多言語サポート(多言語切り替え機能)で、マルチリンガルサイトになります。Geeklog-1.4.1で、本体機能として実装されました。
Geeklogの言語ファイルは40以上の言語に翻訳されましたが、それらの言語の1つでユーザーインタフェースを持つことができるにすぎません。実際のサイトのコンテンツ(記事、静的ページなど)に関しては、複数の言語を切り替えて表示する機能は全くありませんでした。つまり、1つの言語ですべてのコンテンツを作成するか、複数の言語で作成された記事などのコンテンツを同時にすべてのユーザに対して表示するかのどちらかでした。
Euan McKayが最初の多言語ハック[*26] を行いました。後にLWCがそれを基にして一般化を行いました([1][*27] 。
このように、Geeklogの多言語サポートはEuanとLWCの業績に基づいています。
多言語サポートの背景となっている考えは、オブジェクトを記述している言語をそのオブジェクトのID中にコード化するというものです。たとえば、記事のIDの中にコード化するには、
http://www.example.com/article.php/introduction_en -- 英語バージョン http://www.example.com/article.php/introduction_de -- ドイツ語バージョン
とします。
現在では、オブジェクト(記事、話題、静的ページなど)の言語を識別する方法があります、ユーザの言語設定に基づいて表示をOn/Offできます。データベースに格納されているオブジェクトの複数の言語の間で切り替えることもできます。
1.5.0以降,config.phpファイルは管理画面ブロックのメニュー「コンフィギュレーション」で,WEBベースで設定できるようになりました。"言語とロケール" を選びます。
この2つは$_CONF['language_files']
と $_CONF['languages']
の配列です。多言語モードに設定するためには 両方を設定して可能にしなければなりません。この2つの配列がペアになって動作します。
Geeklog 1.5.0では, 多言語サポートを再度不可にはできませんでした( 参照[*28] ). Geeklog 1.5.1からは, there is a litte (X) next to the options (once they're enabled). Click on the (X) 不可に戻せるようになりました。 (この2つ両方を不可にしなければなりません).
サポートしたい言語それぞれに対して、上記で説明したように、多言語指向オブジェクトで使用される言語IDを定義しなければなりません。言語IDは自由に定義することができますが、IDに対応する言語と何らかの関係のあるように設定するのが賢明でしょう。とはいえ、Geeklogシステムの側からすれば、英語に対応する言語IDが'en'だろうと'peter'だろうと構いません。
注意:
$_CONF['language_files']は、どの言語ファイルがどの言語に対応するかを定義します。また、Geeklogは(ユーザ設定の中で)ユーザが使用する言語の設定にも言語ファイル名を使用しています。
他の言語ファイル、つまり、コンテンツの表示に使う予定のない言語ファイルはすべて削除することが推奨されています。
注意: 複数の文字コードを使用する言語(たとえば、日本語とロシア語)を混在させるときには注意してください(文字化けします)。そのような用途では、すべてのの言語ファイルをUTF-8に切り替える必要があるでしょう。
$_CONF['languages']では、サポートされている言語の表示用テキストを定義します。これらのテキストは、サポートされている言語の間でユーザが(ドロップダウンリストを使って)切り替えを行うときに使用されます。
たいていの場合、言語の本来の名前、たとえば、ドイツ語なら'German'ではなく'Deutsch'、日本語なら'Japanese'ではなく'日本語'を使う必要があるでしょうが、これはただの慣例でしかありません。
ユーザが多言語切り替えサイトを訪問すると、登録ユーザであれば、Geeklogはまずユーザ設定をチェックし、次に言語データを格納しているクッキーを探します。見つからなければ、Webブラウザの設定('Accept-Language'ヘッダ)から言語を取得しようとします(ただし、うまくいくのは、上述のように言語名にISOの省略名を使うようにしている場合だけです)。それも失敗したら、サイトのデフォルト言語、つまり、$_CONF['language']でコンテンツは表示されます。
プラグインおよび他のアドオン開発者は、多言語サポートを行うためにすべきことはあまりありません。主な点としては、プラグインの管理下にあるオブジェクトには(Geeklogの記事IDのような)編集可能で数値ではないIDを持たせなければならないでしょう。そうすれば、そのIDに言語IDを付加することができるようになるからです。
プラグインの管理下にあるオブジェクトのリストを持っており、現在の言語でオブジェクトを表示したいだけであれば、SQLリクエストを構築する際にCOM_getLangSQL()関数を使えばよいでしょう。この関数は現在の言語で記述されているオブジェクトを返すためのSQLリクエストの一部を提供してくれます(詳しくは、lib-common.php中にある該当関数の記述を参照してください)。
多言語サポートが無効の場合、COM_getLangSQL()関数は空文字列を返すので、コーディングの際に自分で確認する必要はありません。
たいていの場合、それだけ知っていれば、プラグインで多言語サポートが可能になるはずです。場合によっては、以下に紹介する関数が役に立つかもしれません。
英語・日本語だけでなく、多種多様な言語であらかじめ記事を用意しておき、言語を切り替えると、記事の言語とGeeklogの言語設定が同時に切り替わります。
記事は、記事のIDで言語判別させます。それぞれの記事は、あらかじめ作成した言語ID付きの話題IDの話題に属させる必要があります。
たとえば,次のようにIDを設定して記事を作成します。
日本語の記事 … story_ja イタリア語の記事 … story_it 英語の記事 … story_en
静的ページも同様に、話題IDを追加して作成します。
※ブロックやカスタムメニュープラグインは別のルールがありますので下部参照
多言語ブロックは Geeklog 1.5.1以後でサポートされます。その設定方法は,記事や静的ページとは少し異なるので注意が必要です。
日本語と英語の多言語サイトを作る場合には,以下のように,言語idを追加しないブロックもかならず作成してください。
最初の2つのブロックはそれぞれ多言語切り替えの際に表示するブロックをセットしますが,有効にチェックをいれないで,無効にしておきます。最後のブロックは,有効にしておきます。これで,多言語モードになったら,ブロックaboutに,英語に切りかわったらabout_enのタイトルとコンテンツが, 日本語に切り替わったらabout_jaのタイトルとコンテンツが表示されることになります。
aboutは、何か適当なものをコンテンツに入力して保存しておいてください。多言語に対応したブロックが優先して表示されます。
カスタムメニュープラグインもおなじルールです。
ふつう、言語を切り替えると、日付・時刻などのロケールの設定も変えなければなりません。そのためには、サイトのに記述されている言語ごとに代わりとなる設定を定義することできます。
たとえば、Geeklogで日付のデフォルトの設定は、
$_CONF['datetime'] = '%A, %B %d %Y @ %I:%M %p %Z';
ですが、とりわけ問題になるのが、am/pmを使う時刻のフォーマットが含まれていることです。サイトを英語と日本語で切り替えるとしたら、日本語ユーザは次のように24時間制が使われていると期待するでしょう。
$_CONF['daytime'] = '%a %d %b %Y %T %Z';
日本の言語IDとしてISOの省略形である'ja'を使っていれば、次の設定をサイトのsiteconfig.phpに記入しておけばよいのです。
$_CONF['daytime'] = '%a %d %b %Y %T %Z'; $_CONF['daytime_ja'] = '%Y/%m/%d %H:%M:%S';
この2行を使って、Geeklogは日本語でコンテンツを表示するときには$_CONF['date_ja']のフォーマットを使い、その他の言語で表示するときには$_CONF['date]のフォーマットを使用します。
実際には、上記のことがきちんと機能するには、$_CONF['locale']
と$_CONF['locale_ja']
もそれに合わせて設定しなければなりません。日付のフォーマット(ローカライズされた曜日と月の名前)を行う際に、正しいロケールが設定されている必要があるからです。
$_CONF['locale'] = 'en_GB'; $_CONF['locale_ja'] = 'ja_JP';
上述したように、以下のロケールの設定[*29] はすべて切り替えることができます。多言語用の追加は、siteconfig.phpに追加すると良いでしょう。
$_CONF['locale']
$_CONF['date']
$_CONF['daytime']
$_CONF['shortdate']
$_CONF['dateonly']
$_CONF['timeonly']
$_CONF['week_start']
$_CONF['hour_mode']
$_CONF['thousand_separator']
$_CONF['decimal_separator']
メタタグをロケールに応じて切り替えます。
ロケールで切り替えたい要素はlib-common.phpに追加することでいくらでも設定できます。 meta_description, meta_keywords, site_name, owner_name, site_sloganなど、必要な要素を上記のようにsiteconfig,phpに言語分追記してlib-common.phpのCOM_switchLocaleSettings() に、要素を追加します。
例)
$overridables = array ( 'locale', 'date', 'daytime', 'shortdate', 'dateonly', 'timeonly', 'week_start', 'hour_mode', 'thousand_separator', 'decimal_separator', 'meta_description','meta_keywords', 'site_name', 'owner_name', 'site_slogan' );
$_CONF['site_name_en'] = 'English title'; $_CONF['site_slogan_en'] = 'Slogan'; $_CONF['meta_description_en'] = 'Description'; $_CONF['meta_keywords_en'] = 'Description';
Googleは、多言語のそれぞれのTOPページのURLを変えることを強く推奨しています。
その対策として、多言語のそれぞれの言語用に、話題home_(言語id) たとえばhome_ja, home_en等を作成し、それを多言語サイトのそれぞれのTOPページとします。
ログインした人はいつでもユーザ設定で言語を切り替えられます。
もっと簡単にするには(そしてゲストユーザにも言語の切り替えを行わせるには)、サイトにPHPブロックを設置します。
PHPブロックで, phpblock_switch_language を指定して利用できます。
Geeklogには、利用可能なすべての言語を網羅するドロップダウンリスト(2言語しかない場合はもう一方の言語へ切り替えるためのリンク)を表示するphpblock_switch_language()関数を提供しています。
この関数はheader.thtml(ヘッダのテンプレートファイル)から呼び出すこともできるので、サイトのグローバルメニューに追加することもできます。
<?php print phpblock_switch_language(); ?>
技術的には、切り替えた言語はクッキーに保存され、ログインユーザの場合、言語設定が更新されます。
切り替えるためのアプリケーションとして、switchlang.phpが用意されています。
Formによってプルダウンで切り替えるのではなく、サイトのトップに、それぞれの言語のトップページへのリンクを追加したい場合は、以下のリンクを記述してください。
/switchlang.php/言語ID
を実行して切り替えることができます。
のように指定します。
以下の切り替えのswitchlang.phpは本体に同梱されています。正常に切り替わらない場合があること、同一コンテンツで切り替えるので、用意されていなければ、404エラーになるという欠点があります。
<ul> <li><a href="{site_url}/switchlang.php/ja">日本語</a></li> <li><a href="{site_url}/switchlang.php/en">English</a></li> <li><a href="{site_url}/switchlang.php/zh">中国語・簡体</a></li> <li><a href="{site_url}/switchlang.php/ko">韓国語</a></li> </li>
langselプラグインをあらかじめインストールして、以下のようにヘッダーのテンプレートheader.thtmlに記述してください。 日本語版で提供しているカスタム関数 currenturl をlib-custom.phpから呼んでください。 さらにAutotagsプラグインでcurrenturlをPHP関数として追加してください。
<ul> <li> <form action="{site_url}/langsel/index.php" method="post" class="uk-margin-left uk-text-primary"> <input type="hidden" name="target" value="{!!autotag currenturl:ja topicid:home !!}"> <button type="submit" name="langsel" value="english_utf-8">日本語</button> </form> </li> <li> <form action="{site_url}/langsel/index.php" method="post" class="uk-margin-left uk-text-primary"> <input type="hidden" name="target" value="{!!autotag currenturl:en topicid:home !!}"> <button type="submit" name="langsel" value="english_utf-8">English</button> </form> <</li> </ul> =記事に多言語記事が存在すればリンクを作成するハック for Geeklog 1.7.0 = 表示記事に対応する多言語での記事が存在する場合は、その多言語記事へのリンクを作成するカスタム関数は便利です。 * download: http://hiroron.com/downloads/index.php/227 =言語IDのテーマ変数を追加する= 言語IDを返すテーマ変数{switchlang}をすべてのテンプレートで利用可能にします。 [[言語IDのテーマ変数を追加する]] =テンプレート内に、PHPで、多言語コンテンツを切り替えて表示する= フッタやヘッダテンプレートなどすべてのテンプレートでPHPを利用できます。言語IDを以下のように取得して、assistプラグインのstaticpage_content自動タグによって、以下の例では、トップページのみに、対応した言語のコンテンツ-content_XXを表示します。 <?php echo PLG_replaceTags('[staticpage_content:_footer_contents_'.COM_getLanguageId().']'); ?> == Assistプラグインを活用する場合 == <?php echo PLG_replaceTags('[assist:staticpage_content id:-content_'.COM_getLanguageId().' mode:home]'); ?> == Assist プラグインと{switchlang}が用意された場合 == 上記の{switchlang}が利用できるハックが追加された場合は、以下の記述になります。 {!!autotag assist:staticpage_content id:-content_'.{switchlang}.' mode:home !!} = テンプレートに記述する事例 = 多言語ページ(-menu_ja, -menu_en等)をテンプレートに埋め込んで表示する事例 <pre> <?php echo PLG_replaceTags('[staticpage_content:-menu_'.COM_getLanguageId().']'); ?>
header.thtml には、Geeklog 2.1.3から、テーマ変数が用意されています。
{lang_id}
COM_getLanguageId() は、多言語IDを取得するCOM関数です。これは大変便利な関数です。
Geeklog-1.7.0 では,公開領域/admin/story.phpの748行目付近
修正前:
$story_templates->set_var('story_id', $story->getSid()); $story_templates->set_var('old_story_id', $story->EditElements('originalSid'));
修正後:
$story_templates->set_var('story_id', $story->getSid()); if ( isset( $_CONF['language_files'] ) && isset( $_CONF['languages'] ) ) { $A['sid'] .= '_' . COM_getLanguageId(); } $story_templates->set_var('old_story_id', $story->EditElements('originalSid'));