Мультиязычность

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

Установка

composer require symfony/translation

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

По умолчанию webman размещает языковые пакеты в каталоге 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!".

Также можно использовать четвертый аргумент функции trans() для временного изменения языка. Например, пример выше эквивалентен следующему:

<?php
namespace app\controller;

use support\Request;

class UserController
{
    public function get(Request $request)
    {
        // Изменение языка через четвертый аргумент
        $hello = trans('hello', [], null, 'en'); // hello world!
        return response($hello);
    }
}

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

Translation - синглтон, что означает, что все запросы используют один и тот же экземпляр. Если какой-то запрос устанавливает язык по умолчанию с помощью 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():

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.