Moodle1.6の日付表示で文字化け

Moodle1.6の日付表示で文字化け

- Yoshiaki Wada の投稿
返信数: 9
はじめて投稿させていただきます、
和田@NTTデータエンジニアリングシステムズと申します。

Moodle 1.6 を Windows の IIS 上で実行した際、
カレンダー等の日付表示部分に文字化けを確認しましたので、
報告させていただきます。

(1) 現象
    カレンダーの年月表示の "年" や "月" に文字化けが発生する。

(2) 実行環境
    Windows XP, 2000
    PHP 5.1.4
    Moodle 1.6(ja_utf8 言語パッケージ使用)

(3) 原因
    lib/moodlelib.php ファイル userdate 関数の return 直前の if 文の処理で、
    元が UTF-8 の文字列を Shift_JIS から UTF-8 へ変換するためと考えています。

(4) 回避策
    lib/moodlelib.php ファイルの 951行目から 956行目までを
    下記のようにコメントアウトする事で文字化けが 発生しなくなります。

    /*
   if (!empty($CFG->unicodedb) && $CFG->ostype == 'WINDOWS') {
       if ($localewincharset = get_string('localewincharset')) {
           $textlib = textlib_get_instance();
           $datestring = $textlib->convert($datestring, $localewincharset, current_charset());
       }
   }
   */
評点平均: お役立ち度: ★★★★★☆☆ (1)
Yoshiaki Wada への返信

Re: Moodle1.6の日付表示で文字化け

- Mitsuhiro Yoshida の投稿
画像 Developers 画像 Particularly helpful Moodlers 画像 Translators
和田様

貴重な情報ありがとうございます。 smile

ご都合がよろしければ、Moodle Bug Trackerへの投稿もお願い致します。

Mitsuhiro Yoshida への返信

Re: Moodle1.6の日付表示で文字化け

- Yoshiaki Wada の投稿
すみません、英文を記述するのが苦手なもので。

Bug Tracker への投稿は、
代わりにお願いできないでしょうか?
Yoshiaki Wada への返信

Re: Moodle1.6の日付表示で文字化け

- Mitsuhiro Yoshida の投稿
画像 Developers 画像 Particularly helpful Moodlers 画像 Translators
中国語でも同じような現象が発生しています。
http://moodle.org/mod/forum/discuss.php?d=44779

Moodle Bug Trackerにも同じ内容が報告されているようですので、投稿は不要でした。
大変失礼しました。 blush
http://moodle.org/bugs/bug.php?op=show&bugid=5447&pos=20


lang/ja_utf8/langconfig.phpの10行目を下記のように変更してもカレンダーの文字化け解消はOKだと思います。

[ 変更後 ]
$string['localewincharset'] = 'UTF-8';

[ 変更前 ]
$string['localewincharset'] = 'CP932';
Mitsuhiro Yoshida への返信

Re: Moodle1.6の日付表示で文字化け

- Yoshiaki Wada の投稿
ありがとうございます。

ja_utf8/langconfig.php の $string['localewincharset'] に UTF-8 を設定して
カレンダーの文字化けが解消できる事を確認しました。

解決策としては、
こちらの方がスマートですね。

ちなみに、以下のように空白にしても文字化けが解消されました。
$string['localewincharset'] = '';
Yoshiaki Wada への返信

Re: Moodle1.6の日付表示で文字化け

- Haruhiko Okumura の投稿
get_string('localewincharset') は空('')なはずなのに変ですね。

lang/en_utf8/langconfig.php
$string['localewincharset'] = '';

lang/ja_utf8/ に該当のファイルは見当たりません(2月6日付,古い?)。
Haruhiko Okumura への返信

Re: Moodle1.6の日付表示で文字化け

- Mitsuhiro Yoshida の投稿
画像 Developers 画像 Particularly helpful Moodlers 画像 Translators
3月25日にEloyさんが、$string['localewincharset'] = 'CP932'; を入れたようです。

Mitsuhiro Yoshida への返信

Re: Moodle1.6の日付表示で文字化け

- Haruhiko Okumura の投稿
ごめんなさい。^^;; 古いのを見ていました。2006-06-29が最新でした。
なんでCP932なんでしょう?
Yoshiaki Wada への返信

Re: Moodle1.6の日付表示で文字化け

- Yoshiaki Wada の投稿
和田@NTTデータエンジニアリングシステムズです。

随分、間が開いてしまいましたが、
前回報告させていただいた回避策では、
別の問題を発生させる事を確認しましたので、
改めて回避策を報告させていただきます。

具体的には、
Windows の Moodle 1.6(ja_utf8使用) でカレンダーの日付文字化け回避のために
lib/moodlelib.php ファイルの951行目から956行目をコメントアウトしたり、
ja_utf8 の langconfig.php の localewincharset の設定値を空にしますと、
日付の曜日部分等に英語表記もしくは文字化けが発生する事になります。


(1) 現象
    ・カレンダーの日付(年と月)が文字化けする
    ・日付の曜日の部分だけが英語表記か文字化けする
    ・月をドロップダウンで選択する箇所で英語表記か文字化けする

(2) 実行環境
    ・Windows XP, 2000
    ・PHP 5.1.6
    ・Moodle 1.6.2+(ja_utf8 言語パッケージ使用)

(3) 原因

    根本的な原因は、lib/moodlelib.php ファイル内 userdate 関数の
    実装不備と考えています。

    以下の処理(lib/moodlelib.php 951行目から956行目)は
    Windows の PHP で strftime 関数で取得した曜日等の文字エンコードが
    SJIS(CP932)になる事への回避措置として用意されているものと考えられます。

       if (!empty($CFG->unicodedb) && $CFG->ostype == 'WINDOWS') {
           if ($localewincharset = get_string('localewincharset')) {
               $textlib = textlib_get_instance();
               $datestring = $textlib->convert($datestring, $localewincharset, current_charset());
           }
       }

    しかし、この処理だけでは、
    日付フォーマットに ja_utf8 パッケージ langconfig.php の
    '%%Y年 %%m月 %%d日(%%A)' 等が使われた場合のように、
    strftime 関数の結果が格納される $datestring に
    UTF-8(年、月、日) と SJIS(曜日)が混在するケースに対応できず、
    一部文字の文字化けの発生原因となります。

    そのため、この問題を回避する適切な方法として、
    上記処理に加えて、strftime や gmstrftime 関数に渡される
    日付フォーマットの文字エンコードを事前に変換(UTF-8 から SJIS)する
    処理の追加が考えられます。

(4) 回避策

    回避策は、
    lib/moodlelib.php の userdate 関数内の
    strftime 関数実行前に $format の文字エンコードを
    Windows 用の文字エンコードに変換する処理を加える事です。

    一応、後述の [変更例] のように lib/moodlelib.php を編集して、
    日付の文字化け・英語表記の問題が解決する事を確認しました。

    ただし、この場合、
    ja_utf8 の langconfig.php の localewincharset の設定値は
    デフォルト値の 'CP932' を使用する必要があります。

    ただ、元の moodlelib.php がそうなっているので従いましたが、
    個人的に、Windows 固有の処理をこのような関数内に直接挿入してしまうのは
    好ましい実装だとは思っていません。


    [変更例]

        function userdate($date, $format='', $timezone=99, $fixday = true) {

            ・・・

            if ($format == '') {
                if (empty($strftimedaydatetime)) {
                    $strftimedaydatetime = get_string('strftimedaydatetime');
                }
                $format = $strftimedaydatetime;
            }

            //新規追加する処理
            //カレントの文字エンコードから Windows 用の文字エンコードに変換
            $localewincharset = null;
            $textlib = null;

            if (!empty($CFG->unicodedb) && $CFG->ostype == 'WINDOWS') {
                if ($localewincharset = get_string('localewincharset')) {
                    $textlib = textlib_get_instance();
                    $format = $textlib->convert($format, current_charset(), $localewincharset);
                }
            }

            ・・・

            } else {
                $date += (int)($timezone * 3600);
                if ($fixday) {
                    $datestring = gmstrftime($formatnoday, $date);
                    $daystring  = str_replace(' 0', '', gmstrftime(' %d', $date));
                    $datestring = str_replace('DD', $daystring, $datestring);
                } else {
                    $datestring = gmstrftime($format, $date);
                }
            }

        /// If we are running under Windows and unicode is enabled, try to convert the datestring
        /// to current_charset() (because it's impossible to specify UTF-8 to fetch locale info in Win32)

            //Windows 用の文字エンコードからカレントの文字エンコードに変換
            //この処理は元の実装のままでも良いが、
            //新規追加した処理と重複する部分を削除した
            if ($localewincharset) {
                $datestring = $textlib->convert($datestring, $localewincharset, current_charset());
            }

            return $datestring;
        }