创建一个多语言应用

每一天,我们会见越来越多的国际公司、软件产品和信息资源,他们发布的内容都是多语言的。Yii2提供内置i18n支持,用于制作多语言应用。

在本小节中,我们翻译应用接口到不同的语言上。

准备

按照官方指南http://www.yiiframework.com/doc-2.0/guide-start-installation.html的描述,使用Composer包管理器创建一个新的yii2-app-basic应用。

如何做…

  1. views/layouts/main.php文件修改主菜单标签,使用Yii::t('app/nav', '...')方法:
  1. echo Nav::widget([
  2. 'options' => ['class' => 'navbar-nav navbar-right'],
  3. 'items' => [
  4. ['label' => Yii::t('app/nav', 'Home'), 'url' => ['/site/index']],
  5. ['label' => Yii::t('app/nav', 'About'), 'url' => ['/site/about']],
  6. ['label' => Yii::t('app/nav', 'Contact'), 'url' => ['/site/contact']],
  7. //...
  8. ],
  9. ]);
  1. 修改所有的标题和面包屑,使用Yii::t('app, '...')方法:
  1. $this->title = Yii::t('app', 'Contact');
  2. $this->params['breadcrumbs'][] = $this->title;
  1. 此外,修改你所有按钮的标签:
  1. <div class="form-group">
  2. <?= Html::submitButton(Yii::t('app', 'Submit'), ['class' => 'btn btn-primary'']) ?>
  3. </div>

修改其它硬编码的信息:

  1. <p>
  2. <?= Yii::t('app', 'The above error occurred while the Web server was processing your request.') ?>
  3. </p>
  1. 修改你的LoginForm表单的属性标签:
  1. class LoginForm extends Model
  2. {
  3. ...
  4. public function attributeLabels()
  5. {
  6. return [
  7. 'username' => Yii::t('app/user', 'Username'),
  8. 'password' => Yii::t('app/user', 'Password'),
  9. 'rememberMe' => Yii::t('app/user', 'Remember Me'),
  10. ];
  11. }
  12. }

此外,修改ContactForm模型的属性标签:

  1. class ContactForm extends Model
  2. {
  3. ...
  4. public function attributeLabels()
  5. {
  6. return [
  7. 'name' => Yii::t('app/contact', 'Name'),
  8. 'email' => Yii::t('app/contact', 'Email'),
  9. 'subject' => Yii::t('app/contact', 'Subject'),
  10. 'body' => Yii::t('app/contact', 'Body'),
  11. 'verifyCode' => Yii::t('app', 'Verification Code'),
  12. ];
  13. }
  14. }

它会输出翻译后的标签。

  1. 为了准备翻译,创建messages目录。马上,我们可以为所有需要的语言创建翻译文件。我们可以手动制作,但是有一个很有用的爬虫,它会扫描所有的项目文件,并为所有的消息构建Yii::t()构造。我们来使用它。
  2. 为消息扫描器生成配置文件:
  1. ./yii message/config-template config/messages.php
  1. 打开配置文件,设置如下值:
  1. <?php
  2. return [
  3. 'sourcePath' => '@app',
  4. 'languages' => ['de', 'fr'],
  5. 'translator' => 'Yii::t',
  6. 'sort' => false,
  7. 'removeUnused' => false,
  8. 'markUnused' => true,
  9. 'only' => ['*.php'],
  10. 'except' => [
  11. '.svn',
  12. '.git',
  13. '.gitignore',
  14. '.gitkeep',
  15. '.hgignore',
  16. '.hgkeep',
  17. '/messages',
  18. '/vendor',
  19. ],
  20. 'format' => 'php',
  21. 'messagePath' => '@app/messages',
  22. 'overwrite' => true,
  23. 'ignoreCategories' => [
  24. 'yii',
  25. ],
  26. ];
  1. 运行爬虫,并将这个配置文件传递给它:
  1. ./yii message config/messages.php
  1. 在处理过以后,我们能得到如下文件夹结构:
  1. messages
  2. ├── de
  3. ├── app
  4. ├── contact.php
  5. ├── nav.php
  6. └── user.php
  7. └── app.php
  8. └── fr
  9. ├── app
  10. ├── contact.php
  11. ├── nav.php
  12. └── user.php
  13. └── app.php
  1. 例如,messages/de/app/contact包含如下内容:
  1. <?php
  2. ...
  3. return [
  4. 'Body' => '',
  5. 'Email' => '',
  6. 'Name' => '',
  7. 'Subject' => '',
  8. ];
  1. 它是一个纯PHP数组,原始的句子会放在keys的的位置,翻译后的消息会放在values的位置上。
  2. 只需要将翻译成德语的内容放在值的位置上:
  1. <?php
  2. ...
  3. return [
  4. 'Password' => 'Passwort',
  5. 'Remember Me' => 'Erinnere dich an mich',
  6. 'Username' => 'Benutzername',
  7. ];
  1. config/web.php文件中附加这些翻译到应用的i18n组件上:
  1. $config = [
  2. 'id' => 'basic',
  3. 'basePath' => dirname(__DIR__),
  4. 'bootstrap' => ['log'],
  5. 'components' => [
  6. //…
  7. 'i18n' => [
  8. 'translations' => [
  9. 'app*' => [
  10. 'class' => 'yii\i18n\PhpMessageSource',
  11. 'sourceLanguage' => 'en-US',
  12. ],
  13. ],
  14. ],
  15. 'db' => require(__DIR__ . '/db.php'),
  16. ],
  17. 'params' => $params,
  18. ];
  1. 打开登录页面,会有默认语言:

创建一个多语言应用 - 图1

  1. 修改应用语言为de
  1. $config = [
  2. 'id' => 'basic',
  3. 'language' => 'de',
  4. 'basePath' => dirname(__DIR__),
  5. 'bootstrap' => ['log'],
  6. ...
  7. ];

然后刷新登录页面:

创建一个多语言应用 - 图2

  1. 内置的框架消息和默认校验错误也会被自动翻译。

工作原理…

Yii2提供Yii::t()方法,用于通过i18n组件翻译接口消息,它支持不用的源类型。在本小节中,我们使用的是yii\i18n\hpMessageSource,它用纯PHP文件存储了翻译后的消息。

这个框架没有人工智能,不支持自己翻译消息。你必须在文件或者在数据库中放好准备好的翻译,框架会从消息源中获取需要的信息。

你可以手动设置当前语言:

  1. $config = [
  2. 'id' => 'basic',
  3. 'language' => 'de',
  4. ...
  5. ];

如果不在配置文件中设置语言的话,你可以在运行时设置应用语言:

  1. Yii::$app->language = 'fr';

例如,如果你存放用户语言在User模型的lang字段上,你可以创建语言加载器:

  1. <?php
  2. namespace app\bootstrap;
  3. use yii\base\BootstrapInterface;
  4. class LanguageBootstrap implements BootstrapInterface
  5. {
  6. public function bootstrap($app)
  7. {
  8. if (!$app->user->isGuest) {
  9. $app->language = $app->user->identity->lang;
  10. }
  11. }
  12. }

在bootstraping列表中注册这个类:

  1. $config = [
  2. 'id' => 'basic',
  3. 'basePath' => dirname(__DIR__),
  4. 'bootstrap' => ['log', 'app'bootstrap\LanguageBoostrap'],
  5. ...
  6. ];

现在,每一个认证的用户将会看到他们自己语言的界面。

此外,你可以复写yii\web\UrlManager,用于将当前语言作为GET参数传递,或者是一个URL的前缀方式传递。此外,作为备选项,你可以在浏览器的cookie中存放选择的语言。

当你使用Gii生成模型或者其它代码时,你可以检查如下选项:

创建一个多语言应用 - 图3

在生成的代码中,所有的标签都被嵌入到Yii::t()中。

注意:本小节中我们没有讨论模型内容的翻译。但是,例如,你可以在数据库中独立的表中存放翻译后的文本(例如post_lang表存放帖子模型表),并使用Yii::$app->language属性,获取当前语言,并为你的模型提取需要的内容。

参考

欲了解Yii2中更多关于国际化的信息,参考http://www.yiiframework.com/doc-2.0/guide-tutorial-i18n.html