Multilingual
Multilingual uses the symfony/translation component.
Installation
composer require symfony/translation
Establishing Language Packs
Webman defaults to placing language packs in the resource/translations directory (please create it if it does not exist). To change the directory, please set it in config/translation.php.
Each language corresponds to a subfolder within it, and language definitions are defaulted to be placed in messages.php. An example is as follows:
resource/
└── translations
├── en
│ └── messages.php
└── zh_CN
└── messages.php
All language files return an array, for example:
// resource/translations/en/messages.php
return [
'hello' => 'Hello webman',
];
Configuration
config/translation.php
return [
// Default language
'locale' => 'zh_CN',
// Fallback language, which attempts to use translations from this language when the current language cannot find a translation
'fallback_locale' => ['zh_CN', 'en'],
// Folder where language files are stored
'path' => base_path() . '/resource/translations',
];
Translation
Translations use the trans() method.
Create the language file resource/translations/zh_CN/messages.php as follows:
return [
'hello' => '你好 世界!',
];
Create the file app/controller/UserController.php
<?php
namespace app\controller;
use support\Request;
class UserController
{
public function get(Request $request)
{
$hello = trans('hello'); // 你好 世界!
return response($hello);
}
}
Visiting http://127.0.0.1:8787/user/get will return "你好 世界!"
Changing Default Language
Switch languages using the locale() method.
Create a new language file resource/translations/en/messages.php as follows:
return [
'hello' => 'hello world!',
];
<?php
namespace app\controller;
use support\Request;
class UserController
{
public function get(Request $request)
{
// Switch language
locale('en');
$hello = trans('hello'); // hello world!
return response($hello);
}
}
Visiting http://127.0.0.1:8787/user/get will return "hello world!"
You can also use the fourth parameter of the trans() function to temporarily switch languages, for example, this case and the one above are equivalent:
<?php
namespace app\controller;
use support\Request;
class UserController
{
public function get(Request $request)
{
// Fourth parameter switches language
$hello = trans('hello', [], null, 'en'); // hello world!
return response($hello);
}
}
Setting Language for Each Request Explicitly
Translation is a singleton, which means all requests share this instance. If a request uses locale() to set the default language, it will affect all subsequent requests in this process. Therefore, we should explicitly set the language for each request. For example, using the following middleware.
Create the file app/middleware/Lang.php (please create the directory if it doesn't exist) as follows:
<?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);
}
}
In config/middleware.php, add the global middleware as follows:
return [
// Global middleware
'' => [
// ... Other middleware omitted here
app\middleware\Lang::class,
]
];
Using Placeholders
Sometimes, a message contains variables that need to be translated, for example:
trans('hello ' . $name);
In such cases, we handle it using placeholders.
Change resource/translations/zh_CN/messages.php as follows:
return [
'hello' => '你好 %name%!',
];
When translating, pass the values corresponding to the placeholders through the second parameter:
trans('hello', ['%name%' => 'webman']); // 你好 webman!
Handling Plurals
Some languages present different sentence structures based on the quantity of items, for example, There is %count% apple. The sentence is correct when %count% is 1, and incorrect when greater than 1.
In such cases, we use a pipe (|) to list out plural forms.
Add apple_count to the language file resource/translations/en/messages.php as follows:
return [
// ...
'apple_count' => 'There is one apple|There are %count% apples',
];
trans('apple_count', ['%count%' => 10]); // There are 10 apples
We can even specify numeric ranges and create more complex plural rules:
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
Specifying Language Files
The default name for language files is messages.php, but you can actually create language files with other names.
Create the language file resource/translations/zh_CN/admin.php as follows:
return [
'hello_admin' => '你好 管理员!',
];
Use the third parameter of trans() to specify the language file (omit the .php suffix):
trans('hello', [], 'admin', 'zh_CN'); // 你好 管理员!
More Information
Refer to the symfony/translation documentation