Многоязычность

Многоязычность использует symfony/translation компонент.

Установка

composer require symfony/translation

Создание языкового пакета

По умолчанию вебмен размещает языковой пакет в папке resource/translations (если папка отсутствует, создайте её самостоятельно). Чтобы изменить директорию, настройте это в файле config/translation.php. Каждому языку соответствует одна из поддиректорий, определение языка по умолчанию хранится в файле messages.php. Пример:

resource/
└── translations
    ├── en
    │   └── messages.php
    └── zh_CN
        └── messages.php

Все языковые файлы возвращают массив, например:

// resource/translations/en/messages.php

return [
    'hello' => 'Hello webman',
];

Настройка

config/translation.php

return [
    // Язык по умолчанию
    'locale' => 'zh_CN',
    // Язык для возврата. Если перевод не найден в текущем языке, пробуем использовать перевод из языка для возврата
    'fallback_locale' => ['zh_CN', 'en'],
    // Папка для хранения языковых файлов
    'path' => base_path() . '/resource/translations',
];

Перевод

Перевод осуществляется с помощью метода trans().

Создайте языковой файл resource/translations/zh_CN/messages.php следующим образом:

return [
    'hello' => '你好 世界!',
];

Создайте файл app/controller/UserController.php

<?php
namespace app\controller;

use support\Request;

class UserController
{
    public function get(Request $request)
    {
        $hello = trans('hello'); // 你好 世界!
        return response($hello);
    }
}

Обратившись по адресу http://127.0.0.1:8787/user/get, вы получите "你好 世界!"

Изменение языка по умолчанию

Для смены языка используется метод locale().

Добавьте языковой файл resource/translations/en/messages.php следующим образом:

return [
    'hello' => 'hello world!',
];
<?php
namespace app\controller;

use support\Request;

class UserController
{
    public function get(Request $request)
    {
        // Смена языка
        locale('en');
        $hello = trans('hello'); // hello world!
        return response($hello);
    }
}

Обратившись по адресу http://127.0.0.1:8787/user/get, вы получите "hello world!"

Вы также можете использовать 4-й параметр функции trans() для временной смены языка, например, данный пример эквивалентен предыдущему:

<?php
namespace app\controller;

use support\Request;

class UserController
{
    public function get(Request $request)
    {
        // 4-й параметр смена языка
        $hello = trans('hello', [], null, 'en'); // hello world!
        return response($hello);
    }
}

Явная установка языка для каждого запроса

Перевод является одиночным экземпляром, это означает, что все запросы используют этот экземпляр. Если какой-либо запрос использует locale() для установки языка по умолчанию, это повлияет на все последующие запросы в этом процессе. Поэтому мы должны явным образом устанавливать язык для каждого запроса. Например, используйте следующий миддлвар

Создайте файл app/middleware/Lang.php (если директория не существует, создайте её самостоятельно) следующим образом:

<?php
namespace app\middleware;

use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;

class Lang implements MiddlewareInterface
{
    public function process(Request $request, callable $handler) : Response
    {
        locale(session('lang', 'zh_CN'));
        return $handler($request);
    }
}

В файле config/middleware.php добавьте глобальный миддлвар следующим образом:

return [
    // Глобальные миддлвары
    '' => [
        // ... здесь опущены другие миддлвары
        app\middleware\Lang::class,
    ]
];

Использование плейсхолдеров

Иногда сообщение содержит переменные, которые необходимо перевести, например:

trans('hello ' . $name);

При возникновении такой ситуации мы используем плейсхолдеры для обработки.

Измените resource/translations/zh_CN/messages.php следующим образом:

return [
    'hello' => '你好 %name%!',
];

При переводе передавайте данные через второй параметр, чтобы сопоставить значение плейсхолдера.

trans('hello', ['%name%' => 'webman']); // 你好 webman!

Обработка множественного числа

Некоторые языки используют разные формы в зависимости от количества предметов, например There is %count% apple, когда %count% равно 1, фраза корректна, когда больше 1 — неверна.

В таких случаях мы используем трубку (|), чтобы перечислить формы множественного числа.

В языковом файле resource/translations/en/messages.php добавьте apple_count следующим образом:

return [
    // ...
    'apple_count' => 'There is one apple|There are %count% apples',
];
trans('apple_count', ['%count%' => 10]); // There are 10 apples

Мы даже можем задать диапазон чисел и создать более сложные правила множественного числа:

return [
    // ...
    'apple_count' => '{0} There are no apples|{1} There is one apple|]1,19] There are %count% apples|[20,Inf[ There are many apples'
];
trans('apple_count', ['%count%' => 20]); // There are many apples

Указание языкового файла

По умолчанию имя языкового файла равно messages.php, однако вы можете создать языковые файлы с другими именами.

Создайте языковой файл resource/translations/zh_CN/admin.php следующим образом:

return [
    'hello_admin' => '你好 管理员!',
];

Чрезвычайно важно установить языковой файл через третий параметр trans() (опуская .php суффикс).

trans('hello', [], 'admin', 'zh_CN'); // 你好 管理员!

Дополнительная информация

См. документацию symfony/translation