Yii i18n国际化,消息翻译

来源:互联网 发布:约翰 巴丁 知乎 编辑:程序博客网 时间:2024/04/30 23:46

实现国际化有两种方式,基于文件实现和基于数据库实现。基于文件实现的方式很简单,网上有很多,请自行查询使用。这里主要说一下基于数据库实现的方式。

前提
待翻译的消息使用Yii::t()方法显示,方法参数,第一个是模式,比如常用的app,符合这种模式的消息,都会被初始化到表中,第二个是要显示的消息内容(这里的模式app在source_message表中对应category字段)。

数据库实现是基于DbMessageSource类实现的。
首先需要两张表:source_message表和message表,前者是存储要被翻译的语言,后者是存储被翻译后的语言,实现映射。

一、生成source_message 和 message表

#source_message表CREATE TABLE source_message (    id INTEGER PRIMARY KEY AUTO_INCREMENT,    category VARCHAR(32),    message TEXT);#message表CREATE TABLE message (    id INTEGER,    language VARCHAR(16),    translation TEXT,    PRIMARY KEY (id, language),    CONSTRAINT fk_message_source_message FOREIGN KEY (id)        REFERENCES source_message (id) ON DELETE CASCADE ON UPDATE RESTRICT);

当然,两张表的创建还有一种更便捷的方式,即yii自带的命令:

yii migrate --migrationPath=@yii/i18n/migrations/

这个命令会执行框架下的两张表的创建文件,如下:

vendor/yiisoft/yii2/i18n/migrations/m150207_210500_i18n_init.php

两种方式任一 一种执行后,数据库里都会生成这两张表。两张表的表名是可以改的,但是需要在配置文件中指定:

$sourceMessageTable $messageTable

二、配置i18n组件

'components' => [  'i18n' => [    'translations' => [       'app' => [#对应source_message表中的category字段           'class' => 'yii\i18n\DbMessageSource',           // 'forceTranslation'=>true,#是否强制翻译          'enableCaching' => false,#是否开启缓存          //'cachingDuration' => 1 #缓存时间          //......其他配置信息          ]      ],  ],

三、创建配置文件

在需要翻译的目录,比如(frontend或者backend)目录下手动创建messages目录,执行命令:

yii message/config frontend/messages/config.php

在messages目录下生成config.php文件,内容大致如下:

return [    'color' => null,    'interactive' => true,    'sourcePath' => __DIR__ . DIRECTORY_SEPARATOR . '..',#修改为待翻译目录//    'sourcePath' => '@yii',    'messagePath' => '@yii/messages',    'languages' => ['zh-CN'],    'translator' => 'Yii::t',#这里是关键,默认即可    'sort' => false,    'overwrite' => true,    'removeUnused' => false,    'markUnused' => true,    'except' => [        '.svn',        '.git',        '.gitignore',        '.gitkeep',        '.hgignore',        '.hgkeep',        '/messages',        '/BaseYii.php',    ],    'only' => [        '*.php',    ],    'format' => 'db',//默认生成时,是基于文件翻译,设置为db,默认是php    'db' => 'db',//设置    'sourceMessageTable' => '{{%source_message}}',//待翻译消息表    'messageTable' => '{{%message}}',//翻译后消息表    'catalog' => 'messages',    'ignoreCategories' => [],];

然后重新执行命令:

yii message frontend/messages/config.php

这样,两张表就会被初始化完成。最后是实现以下逻辑即可实现翻译功能。

  1. 翻译前和翻译后的文本显示逻辑
  2. 翻译后的文本存储逻辑

这样视图中基于t()方法显示的消息就会按照设置的文本显示。

最后看看Yii::t()方法到底做了什么:

1.Yii::t()是在BaseYii类中,中间调用了translate()方法

public static function t($category, $message, $params = [], $language = null)    {        if (static::$app !== null) {            return static::$app->getI18n()->translate($category, $message, $params, $language ?: static::$app->language);        } else {          ...                  }    }

2.translate()方法

public function translate($category, $message, $params, $language){    #返回模式为app的原消息    $messageSource = $this->getMessageSource($category);    #调用父类MessageSource的translate()方法    $translation = $messageSource->translate($category, $message, $language);    if ($translation === false) {        return $this->format($message, $params, $messageSource->sourceLanguage);    } else {        return $this->format($translation, $params, $language);    }}

3.MessageSource的translate()方法

public function translate($category, $message, $language){    if ($this->forceTranslation || $language !== $this->sourceLanguage) {        #翻译消息,调用DbMessageSource类的loadMessages()方法        return $this->translateMessage($category, $message, $language);    } else {        return false;    }}

4.loadMessages()方法,根据key,以及缓冲设置进行加载

protected function loadMessages($category, $language){    if ($this->enableCaching) {        $key = [            __CLASS__,            $category,            $language,        ];        $messages = $this->cache->get($key);        if ($messages === false) {            $messages = $this->loadMessagesFromDb($category, $language);            $this->cache->set($key, $messages, $this->cachingDuration);        }        return $messages;    } else {        return $this->loadMessagesFromDb($category, $language);    }}

另外还有消息格式化等,请自行查阅文档使用。

参考资料
http://www.yiichina.com/doc/guide/2.0/tutorial-i18n
http://www.yiiframework.com/doc-2.0/yii-i18n-dbmessagesource.html

0 0