多语言

多语言使用的是 symfony/translation 组件。

安装

  1. composer require symfony/translation

建立语言包

webman默认将语言包放在resource/translations目录下(如果没有请自行创建),如需更改目录,请在config/translation.php中设置。 每种语言对应其中的一个子文件夹,语言定义默认放到messages.php里。示例如下:

  1. resource/
  2. └── translations
  3. ├── en
  4. └── messages.php
  5. └── zh_CN
  6. └── messages.php

所有的语言文件都是返回一个数组例如:

  1. // resource/translations/en/messages.php
  2. return [
  3. 'hello' => 'Hello webman',
  4. ];

配置

config/translation.php

  1. return [
  2. // 默认语言
  3. 'locale' => 'zh_CN',
  4. // 回退语言,当前语言中无法找到翻译时则尝试使用回退语言中的翻译
  5. 'fallback_locale' => ['zh_CN', 'en'],
  6. // 语言文件存放的文件夹
  7. 'path' => base_path() . '/resource/translations',
  8. ];

翻译

翻译使用trans()方法。

创建语言文件 resource/translations/zh_CN/messages.php 如下:

  1. return [
  2. 'hello' => '你好 世界!',
  3. ];

创建文件 app/controller/User.php

  1. <?php
  2. namespace app\controller;
  3. use support\Request;
  4. class User
  5. {
  6. public function get(Request $request)
  7. {
  8. $hello = trans('hello'); // 你好 世界!
  9. return response($hello);
  10. }
  11. }

访问 http://127.0.0.1:8787/user/get 将返回 “你好 世界!”

更改默认语言

切换语言使用 locale() 方法。

新增语言文件 resource/translations/en/messages.php 如下:

  1. return [
  2. 'hello' => 'hello world!',
  3. ];
  1. <?php
  2. namespace app\controller;
  3. use support\Request;
  4. class User
  5. {
  6. public function get(Request $request)
  7. {
  8. // 切换语言
  9. locale('en');
  10. $hello = trans('hello'); // hello world!
  11. return response($hello);
  12. }
  13. }

访问 http://127.0.0.1:8787/user/get 将返回 “hello world!”

你也可以使用trans()函数的第4个参数来临时切换语言,例如上面的例子和下面这个是等价的:

  1. <?php
  2. namespace app\controller;
  3. use support\Request;
  4. class User
  5. {
  6. public function get(Request $request)
  7. {
  8. // 第4个参数切换语言
  9. $hello = trans('hello', [], null, 'en'); // hello world!
  10. return response($hello);
  11. }
  12. }

为每个请求明确的设置语言

translation是一个单例,这意味着所有请求共享这个实例,如果某个请求使用locale()设置了默认语言,则它会影响这个进程的后续所有请求。所以我们应该为每个请求明确的设置语言。例如使用以下中间件

创建文件app/middleware/Lang.php (如目录不存在请自行创建) 如下:

  1. <?php
  2. namespace app\middleware;
  3. use Webman\MiddlewareInterface;
  4. use Webman\Http\Response;
  5. use Webman\Http\Request;
  6. class Lang implements MiddlewareInterface
  7. {
  8. public function process(Request $request, callable $handler) : Response
  9. {
  10. locale(session('lang', 'zh_CN'));
  11. return $handler($request);
  12. }
  13. }

config/middleware.php 中添加全局中间件如下:

  1. return [
  2. // 全局中间件
  3. '' => [
  4. // ... 这里省略其它中间件
  5. app\middleware\Lang::class,
  6. ]
  7. ];

使用占位符

有时,一条信息包含着需要被翻译的变量,例如

  1. trans('hello ' . $name);

遇到这种情况时我们采用占位符来处理。

更改 resource/translations/zh_CN/messages.php 如下:

  1. return [
  2. 'hello' => '你好 %name%!',
  3. ];

翻译的时候将数据通过第二个参数将占位符对应的值传递进去

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

处理复数

有些语言由于事物数量不同呈现不同的句式,例如There is %count% apple,当%count%为1时句式正确,当大于1时则错误。

遇到这种情况时我们采用管道(|)来列出来复数形式。

语言文件 resource/translations/en/messages.php 新增apple_count如下:

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

我们甚至可以指定数字范围,创建更加复杂的复数规则:

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

指定语言文件

语言文件默认名字为message.php,实际上你可以创建其它名称的语言文件。

创建语言文件 resource/translations/zh_CN/admin.php 如下:

  1. return [
  2. 'hello_admin' => '你好 管理员!',
  3. ];

通过trans()第三个参数来指定语言文件(省略.php后缀)。

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

更多信息

参考 symfony/translation手册