ローカリゼーション

ロケールとの連携

CodeIgniterは、アプリケーションを様々な言語にローカライズするのに役立ついくつかのツールを提供しています。アプリケーションの完全なローカライズは複雑なテーマですが、アプリケーション内の文字列を異なるサポート言語で簡単に置き換えることができます。

言語文字列は**app/Language**ディレクトリに格納され、サポートされている各言語ごとにサブディレクトリが作成されます。

app/
    Language/
        en/
            App.php
        fr/
            App.php

重要

ロケールの検出は、IncomingRequestクラスを使用するウェブベースのリクエストでのみ機能します。コマンドラインリクエストではこれらの機能は使用できません。

ロケールの設定

デフォルトロケールの設定

すべてのサイトには、運用するデフォルトの言語/ロケールがあります。これは**app/Config/App.php**で設定できます。

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class App extends BaseConfig
{
    // ...

    public string $defaultLocale = 'en';

    // ...
}

値は、アプリケーションが文字列やその他の形式を管理するために使用する任意の文字列です。BCP 47言語コードを使用することをお勧めします。これにより、アメリカ英語の場合はen-US、フランス語/フランスの場合はfr-FRなどの言語コードが生成されます。これに関するより分かりやすい説明は、W3Cのサイトにあります。

正確な一致が見つからない場合、システムはより一般的な言語コードにフォールバックします。ロケールコードがen-USに設定されていて、enの言語ファイルしか設定されていない場合、より具体的なen-USに対して何も存在しないため、それらが使用されます。ただし、**app/Language/en-US**ディレクトリに言語ディレクトリが存在する場合は、まずそれが使用されます。

ロケールの検出

リクエスト中に正しいロケールを検出するために、2つの方法がサポートされています。最初の方法は、「設定して忘れる」方法で、使用する正しいロケールを自動的に決定するためにコンテンツネゴシエーションを自動的に実行します。2番目の方法は、ロケールを設定するために使用するセグメントをルートに指定できるようにする方法です。

ロケールを直接設定する必要がある場合は、「現在のロケールの設定」を参照してください。

v4.4.0以降、IncomingRequest::setValidLocales()が追加され、Config\App::$supportedLocales設定から設定された有効なロケールを設定(およびリセット)できます。

コンテンツネゴシエーション

**app/Config/App.php**でさらに2つの設定を行うことで、コンテンツネゴシエーションを自動的に実行するように設定できます。最初の値は、ロケールのネゴシエーションを行うことをRequestクラスに伝えるため、単純にtrueに設定します。

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class App extends BaseConfig
{
    // ...

    public bool $negotiateLocale = true;

    // ...
}

これが有効になると、システムは$supportLocalesで定義したロケールの配列に基づいて、正しい言語を自動的にネゴシエートします。サポートする言語と要求された言語の間に一致が見つからない場合、$supportedLocalesの最初のアイテムが使用されます。次の例では、一致が見つからない場合、enロケールが使用されます。

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class App extends BaseConfig
{
    // ...

    public array $supportedLocales = ['en', 'es', 'fr-FR'];

    // ...
}

ルート内

2番目の方法は、目的のロケールを検出してRequestに設定するカスタムプレースホルダーを使用する方法です。プレースホルダー{locale}は、ルートのセグメントとして配置できます。存在する場合、一致するセグメントの内容がロケールになります。

<?php

$routes->get('{locale}/books', 'App\Books::index');

この例では、ユーザーが**http://example.com/fr/books**にアクセスしようとすると、有効なロケールとして設定されていると仮定して、ロケールはfrに設定されます。

**app/Config/App.php**の$supportedLocalesで定義されている有効なロケールと値が一致しない場合、App設定ファイルでサポートされているロケールのみを使用するように設定していない限り、代わりにデフォルトのロケールが使用されます。

<?php

$routes->useSupportedLocalesOnly(true);

注記

v4.3.0以降、useSupportedLocalesOnly()メソッドを使用できます。

現在のロケールの設定

ロケールを直接設定する場合は、IncomingRequest::setLocale(string $locale)を使用できます。**app/Config/App.php**でサポートされているロケールを設定する必要があります。

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class App extends BaseConfig
{
    // ...

    public array $supportedLocales = ['en', 'es', 'fr-FR'];

    // ...
}

注記

この配列に含まれていないロケールを設定しようとすると、「デフォルトのロケール」が設定されます。

現在のロケールの取得

現在のロケールは、常にgetLocale()メソッドを使用してIncomingRequestオブジェクトから取得できます。コントローラーがCodeIgniter\Controllerを拡張している場合、これは$this->requestを通じて使用できます。

<?php

namespace App\Controllers;

class UserController extends BaseController
{
    public function index()
    {
        $locale = $this->request->getLocale();
    }
}

あるいは、Servicesクラスを使用して、現在のリクエストを取得することもできます。

<?php

$locale = service('request')->getLocale();

言語ローカリゼーション

言語ファイルの作成

注記

言語ファイルには名前空間がありません。

言語には、必須の特定の命名規則はありません。ファイルは、保持するコンテンツの種類を論理的に記述するように命名する必要があります。たとえば、エラーメッセージを含むファイルを作成する場合、単純に**Errors.php**という名前を付けることができます。

ファイル内では、配列を返し、配列内の各要素には言語キーがあり、返す文字列を持つことができます。

<?php

return [
    'languageKey' => 'The actual message to be shown.',
];

ネストされた定義もサポートしています。

<?php

return [
    'languageKey' => [
        'nested' => [
            'key' => 'The actual message to be shown.',
        ],
    ],
];
<?php

return [
    'errorEmailMissing'    => 'You must submit an email address',
    'errorURLMissing'      => 'You must submit a URL',
    'errorUsernameMissing' => 'You must submit a username',
    'nested'               => [
        'error' => [
            'message' => 'A specific error message',
        ],
    ],
];

基本的な使用方法

lang()ヘルパー関数を使用して、ファイル名と言語キーを最初の引数としてピリオド(.)で区切って渡すことで、任意の言語ファイルからテキストを取得できます。たとえば、**Errors.php**言語ファイルからerrorEmailMissing文字列を読み込むには、次の手順を実行します。

<?php

echo lang('Errors.errorEmailMissing');

ネストされた定義の場合、次の手順を実行します。

<?php

echo lang('Errors.nested.error.message');

要求された言語キーが現在のロケールのファイルに存在しない場合、文字列は変更されずに返されます。この例では、存在しない場合、「Errors.errorEmailMissing」または「Errors.nested.error.message」が返されます。

パラメーターの置換

注記

以下の関数はすべて、動作するためにシステムにintl拡張機能がロードされている必要があります。拡張機能がロードされていない場合、置換は試行されません。Sitepointに優れた概要があります。

lang()関数の2番目のパラメーターとして、言語文字列のプレースホルダーを置換する値の配列を渡すことができます。これにより、非常に簡単な数値の翻訳とフォーマットが可能になります。

<?php

// The language file, Tests.php:
return [
    'apples'      => 'I have {0, number} apples.',
    'men'         => 'The top {1, number} men out-performed the remaining {0, number}',
    'namedApples' => 'I have {number_apples, number, integer} apples.',
];

// Displays "I have 3 apples."
echo lang('Tests.apples', [3]);

プレースホルダーの最初の項目は、数値の場合、配列内の項目のインデックスに対応します。

<?php

// Displays "The top 23 men out-performed the remaining 20"
echo lang('Tests.men', [20, 23]);

必要に応じて、名前付きキーを使用して整理しやすくすることもできます。

<?php

// Displays "I have 3 apples."
echo lang('Tests.namedApples', ['number_apples' => 3]);

もちろん、数値の置換以外にも多くのことができます。基となるライブラリの公式ICUドキュメントによると、以下の種類のデータが置換できます。

  • 数値 - 整数、通貨、パーセント

  • 日付 - 短縮形、中程度、詳細、完全

  • 時刻 - 短縮形、中程度、詳細、完全

  • spellout - 数値を綴ります(例:34はthirty-fourになります)

  • 序数

  • 期間

いくつかの例を以下に示します。

<?php

// The language file, Tests.php
return [
    'shortTime'  => 'The time is now {0, time, short}.',
    'mediumTime' => 'The time is now {0, time, medium}.',
    'longTime'   => 'The time is now {0, time, long}.',
    'fullTime'   => 'The time is now {0, time, full}.',
    'shortDate'  => 'The date is now {0, date, short}.',
    'mediumDate' => 'The date is now {0, date, medium}.',
    'longDate'   => 'The date is now {0, date, long}.',
    'fullDate'   => 'The date is now {0, date, full}.',
    'spelledOut' => '34 is {0, spellout}',
    'ordinal'    => 'The ordinal is {0, ordinal}',
    'duration'   => 'It has been {0, duration}',
];

// Displays "The time is now 11:18 PM"
echo lang('Tests.shortTime', [time()]);
// Displays "The time is now 11:18:50 PM"
echo lang('Tests.mediumTime', [time()]);
// Displays "The time is now 11:19:09 PM CDT"
echo lang('Tests.longTime', [time()]);
// Displays "The time is now 11:19:26 PM Central Daylight Time"
echo lang('Tests.fullTime', [time()]);

// Displays "The date is now 8/14/16"
echo lang('Tests.shortDate', [time()]);
// Displays "The date is now Aug 14, 2016"
echo lang('Tests.mediumDate', [time()]);
// Displays "The date is now August 14, 2016"
echo lang('Tests.longDate', [time()]);
// Displays "The date is now Sunday, August 14, 2016"
echo lang('Tests.fullDate', [time()]);

// Displays "34 is thirty-four"
echo lang('Tests.spelledOut', [34]);

// Displays "It has been 408,676:24:35"
echo lang('Tests.ordinal', [time()]);

条件付き置換、複数形化など、MessageFormatterクラスと基になるICUフォーマットに関する機能をよりよく理解するには、ドキュメントをよく読んでください。先に提供された2つのリンクは、利用可能なオプションについて優れた情報を提供します。

ロケールの指定

パラメーターの置換時に使用するロケールを指定するには、lang()関数の3番目のパラメーターとしてロケールを渡すことができます。

<?php

// Displays "The time is now 23:21:28 GMT-5"
echo lang('Test.longTime', [time()], 'ru-RU');

// Displays "£7.41"
echo lang('{price, number, currency}', ['price' => 7.41], 'en-GB');
// Displays "$7.41"
echo lang('{price, number, currency}', ['price' => 7.41], 'en-US');

ネストされた配列

言語ファイルは、リストなどの処理を容易にするためにネストされた配列も許可しています。

<?php

// Language/en/Fruit.php

return [
    'list' => [
        'Apples',
        'Bananas',
        'Grapes',
        'Lemons',
        'Oranges',
        'Strawberries',
    ],
];

// Displays "Apples, Bananas, Grapes, Lemons, Oranges, Strawberries"
echo implode(', ', lang('Fruit.list'));

言語フォールバック

特定のロケール(例:**Language/en/app.php**)のメッセージセットがある場合、独自のフォルダーにあるそのロケールの言語バリアント(例:**Language/en-US/app.php**)を追加できます。

そのロケールバリアントで異なるローカライズが必要なメッセージの値のみを提供する必要があります。不足しているメッセージ定義は、メインのロケール設定から自動的に取得されます。

さらに良いことに、新しいメッセージがフレームワークに追加され、まだロケールに翻訳する機会がなかった場合でも、ローカライズは英語までフォールバックできます。

そのため、fr-CAロケールを使用している場合、ローカライズされたメッセージは最初に**Language/fr-CA**ディレクトリで検索され、次に**Language/fr**ディレクトリで検索され、最後に**Language/en**ディレクトリで検索されます。

メッセージ翻訳

独自のリポジトリに「公式」翻訳セットがあります。

そのリポジトリをダウンロードし、その**Language**フォルダーを**app**フォルダーにコピーできます。 App名前空間が**app**フォルダーにマップされているため、組み込まれた翻訳は自動的に取得されます。

あるいは、より良い方法は、プロジェクト内で次のコマンドを実行することです。

composer require codeigniter4/translations

翻訳フォルダーが適切にマップされるため、翻訳されたメッセージは自動的に取得されます。