Multilíngue

O suporte a multilíngue utiliza o componente symfony/translation.

Instalação

composer require symfony/translation

Criando pacotes de idioma

O Webman, por padrão, coloca os pacotes de idioma no diretório resource/translations (se não existir, crie você mesmo). Se precisar alterar o diretório, configure em config/translation.php.
Cada idioma corresponde a uma subpasta nele, e as definições de idioma são normalmente colocadas em messages.php. O exemplo é o seguinte:

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

Todos os arquivos de idioma retornam um array, por exemplo:

// resource/translations/en/messages.php

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

Configuração

config/translation.php

return [
    // Idioma padrão
    'locale' => 'zh_CN',
    // Idioma de fallback, quando não conseguir encontrar a tradução no idioma atual, tentará usar a tradução do idioma de fallback
    'fallback_locale' => ['zh_CN', 'en'],
    // Pasta onde os arquivos de idioma estão armazenados
    'path' => base_path() . '/resource/translations',
];

Tradução

As traduções são feitas usando o método trans().

Crie o arquivo de idioma resource/translations/zh_CN/messages.php da seguinte forma:

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

Crie o arquivo app/controller/UserController.php

<?php
namespace app\controller;

use support\Request;

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

Acesse http://127.0.0.1:8787/user/get e será retornado "你好 世界!"

Alterar o idioma padrão

Para mudar o idioma, utilize o método locale().

Adicione um novo arquivo de idioma resource/translations/en/messages.php da seguinte forma:

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

use support\Request;

class UserController
{
    public function get(Request $request)
    {
        // Mudar idioma
        locale('en');
        $hello = trans('hello'); // hello world!
        return response($hello);
    }
}

Acesse http://127.0.0.1:8787/user/get e será retornado "hello world!"

Você também pode usar o quarto parâmetro da função trans() para mudar temporariamente o idioma, por exemplo, o exemplo acima é equivalente a este abaixo:

<?php
namespace app\controller;

use support\Request;

class UserController
{
    public function get(Request $request)
    {
        // Quarto parâmetro para mudar idioma
        $hello = trans('hello', [], null, 'en'); // hello world!
        return response($hello);
    }
}

Definindo o idioma de forma explícita para cada requisição

A tradução é um singleton, o que significa que todas as requisições compartilham essa instância. Se uma requisição usar locale() para definir o idioma padrão, isso afetará todas as requisições subsequentes neste processo. Portanto, devemos definir o idioma explicitamente para cada requisição. Por exemplo, usando o seguinte middleware:

Crie o arquivo app/middleware/Lang.php (se o diretório não existir, crie você mesmo) da seguinte forma:

<?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);
    }
}

Adicione o middleware global em config/middleware.php da seguinte forma:

return [
    // Middlewares globais
    '' => [
        // ... outros middlewares omitidos aqui
        app\middleware\Lang::class,
    ]
];

Usando placeholders

Às vezes, uma mensagem contém variáveis a serem traduzidas. Por exemplo:

trans('hello ' . $name);

Em tais casos, usamos placeholders para lidar com isso.

Altere resource/translations/zh_CN/messages.php da seguinte forma:

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

Durante a tradução, as dados correspondentes aos placeholders são passados como segundo parâmetro

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

Lidando com o plural

Algumas línguas apresentam diferentes construções dependendo da quantidade de itens, por exemplo There is %count% apple. Quando %count% é 1, a frase está correta; quando é maior que 1, a frase está errada.

Nesses casos, utilizamos pipes (|) para listar as formas plurais.

No arquivo de idioma resource/translations/en/messages.php, adicione apple_count da seguinte forma:

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

Podemos até especificar intervalos numéricos e criar regras de pluralidade mais complexas:

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

Especificando arquivos de idiomas

Os arquivos de idiomas têm o nome padrão messages.php, mas na verdade você pode criar arquivos de idiomas com outros nomes.

Crie o arquivo de idioma resource/translations/zh_CN/admin.php da seguinte forma:

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

Use o terceiro parâmetro de trans() para especificar o arquivo de idioma (omitindo a extensão .php).

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

Mais informações

Consulte o manual do symfony/translation