转载

Yii2语言国际化配置Twig翻译解决方案

我自己在写项目的时候,不喜欢使用php自身的模板,主要是各种PHP标签让我烦,而且对Html的标签兼容也不够友好,所以我后面采用了twig模板,配置之类的也是很方便,写起来也很顺手,但是在Yii2语言国际化翻译这块就遇到了坑,当我们指定文件类型,除了处理php扩展的之外,也处理twig扩展的文件的时候,就不会解析twig中的内容,因为不符合PHP的标签处理逻辑,在PHP中我们使用Yii::t(),但是在twig中使用的是Yii.t()这个函数在translator的配置中,显得很乏力,而且看源码也可以发现,实际上也只处理php文件,网上找了很多针对这个问题的处理方式,似乎也没有几个使用的。现在看下我是如何解决的

第一步 显示修改i18n配置

将twig扩展加入进去,修改后如下:

return ['color' => null,'interactive' => true,'help' => null,'sourcePath' => '@app','messagePath' => '@app/messages','languages' => ['zh-CN', 'ru-RU'],'translator' => 'Yii::t', // 翻译器'sort' => false,'overwrite' => true,'removeUnused' => false,'markUnused' => true,'except' => ['.svn','.git','.gitignore','.gitkeep','.hgignore','.hgkeep','/messages','/BaseYii.php','vendor','tests','runtime','migrations',],'only' => ['*.php','*.twig', // 添加模板扩展],'format' => 'php','db' => 'db','sourceMessageTable' => '{{%source_message}}','messageTable' => '{{%message}}','catalog' => 'messages','ignoreCategories' => [],'phpFileHeader' => '','phpDocBlock' => null,
];

第二步 继承重写

创建文件app/commands/TranslatorController.php,内容如下

<?phpnamespace app\commands;use yii\console\controllers\MessageController;
use yii\helpers\Console;/*** Extracts messages to be translated from source files.** @author durban.zhang <durban.zhang@gmail.com>*/
class TranslatorController extends MessageController
{public function init(){parent::init();}/*** This command echoes what you have entered as the message.* @param string $message the message to be echoed.*/protected function extractMessages($fileName, $translator, $ignoreCategories = []){$messages = [];$extInfo = pathinfo($fileName, PATHINFO_EXTENSION);if ('twig' == $extInfo) {$coloredFileName = Console::ansiFormat($fileName, [Console::FG_CYAN]);$this->stdout("Extracting messages from $coloredFileName...\n");$subject = file_get_contents($fileName);$preg = '/\{\{ Yii\.t\(\'(.*?)\', \'(.*?)\'\) \}\}/';$content = preg_replace($preg, "<?php Yii::t('$1', '$2'); ?>", $subject);$tokens = token_get_all($content);foreach ((array) $translator as $currentTranslator) {$translatorTokens = token_get_all('<?php ' . $currentTranslator);array_shift($translatorTokens);$messages = array_merge_recursive($messages,$this->extractMessagesFromTokens($tokens,$translatorTokens,$ignoreCategories));}$this->stdout("\n");} else {$messages = parent::extractMessages($fileName, $translator, $ignoreCategories);}return $messages;}protected function extractMessagesFromTokens(array $tokens, array $translatorTokens, array $ignoreCategories){$messages = [];$translatorTokensCount = count($translatorTokens);$matchedTokensCount = 0;$buffer = [];$pendingParenthesisCount = 0;foreach ($tokens as $token) {// finding out translator callif ($matchedTokensCount < $translatorTokensCount) {if ($this->tokensEqual($token, $translatorTokens[$matchedTokensCount])) {$matchedTokensCount++;} else {$matchedTokensCount = 0;}} elseif ($matchedTokensCount === $translatorTokensCount) {// translator found// end of function callif ($this->tokensEqual(')', $token)) {$pendingParenthesisCount--;if (0 === $pendingParenthesisCount) {// end of translator call or end of something that we can't extractif (isset($buffer[0][0], $buffer[1], $buffer[2][0]) && T_CONSTANT_ENCAPSED_STRING === $buffer[0][0] && ',' === $buffer[1] && T_CONSTANT_ENCAPSED_STRING === $buffer[2][0]) {// is valid call we can extract$category = stripcslashes($buffer[0][1]);$category = mb_substr($category, 1, -1);if (!$this->isCategoryIgnored($category, $ignoreCategories)) {$message = stripcslashes($buffer[2][1]);$message = mb_substr($message, 1, -1);$messages[$category][] = $message;}$nestedTokens = array_slice($buffer, 3);if (count($nestedTokens) > $translatorTokensCount) {// search for possible nested translator calls$messages = array_merge_recursive($messages, $this->extractMessagesFromTokens($nestedTokens, $translatorTokens, $ignoreCategories));}} else {// invalid call or dynamic call we can't extract$line = Console::ansiFormat($this->getLine($buffer), [Console::FG_CYAN]);$skipping = Console::ansiFormat('Skipping line', [Console::FG_YELLOW]);$this->stdout("$skipping $line. Make sure both category and message are static strings.\n");}// prepare for the next match$matchedTokensCount = 0;$pendingParenthesisCount = 0;$buffer = [];} else {$buffer[] = $token;}} elseif ($this->tokensEqual('(', $token)) {// count beginning of function call, skipping translator beginningif ($pendingParenthesisCount > 0) {$buffer[] = $token;}$pendingParenthesisCount++;} elseif (isset($token[0]) && !in_array($token[0], [T_WHITESPACE, T_COMMENT])) {// ignore comments and whitespaces$buffer[] = $token;}}}return $messages;}
}

从上面的代码可以看出,实现了两个方法
extractMessagesextractMessagesFromTokens
本来是不需要实现extractMessagesFromTokens这个方法的,但是父类中的private,试过了实例化类,但是需要传递需要的参数,为了避免出现问题,暂时没用实例化的方式。
最后extractMessagesFromTokens 这个只是父类的copy版本。那么重点就在extractMessages
判断如果文件是twig文件,则进行处理,处理逻辑我写的也很简单,暂时能解决问题

$preg = '/\{\{ Yii\.t\(\'(.*?)\', \'(.*?)\'\) \}\}/';
$content = preg_replace($preg, "<?php Yii::t('$1', '$2'); ?>", $subject);
$tokens = token_get_all($content);

主要是将Yii.t转为了含有PHP标签的字符串,实际上父类也只是针对代码进行字符串的过滤处理,以此类推的话,如果有其他模板的话也可以采用此方法

到这里就处理完了,

但是执行的命令不是下面这个

./yii message/extract @app/config/i18n.php

而是下面这个

./yii translator/extract @app/config/i18n.php

OK,问题解决,如您有其他方案,请指教

Yii2语言国际化配置Twig翻译解决方案相关推荐

  1. Yii2语言国际化配置

    转载 Yii2语言国际化配置 最近想将博客做成支持多语言的,还好Yii2支持这个功能,于是查看了下官方的文档,哎,看了半天不知道干嘛用的,于是各种百度,Google的搜索,最终才明白原来很简单,只是官 ...

  2. Flutter应用名称语言国际化

    本文主要讲解 有关flutter应用名称语言国际化的问题 一.Android 应用名称语言国际化配置 配置中文/英文 新建 values-en如下图 在上面两个文件下各自见一个strings.xml文 ...

  3. SpringBoot RESTful 风格 API 多语言国际化i18n解决方案

    文章目录 1 摘要 2 核心代码 2.1 多语言枚举类 2.2 多语言处理工具类 2.3 多语言的API返回状态码枚举类 2.4 多语言 API 接口返回结果封装 2.5 i18n 国际化多语言配置文 ...

  4. qt 判断路径非英文符号与非英文字符_Qt中,软件多语言国际化翻译的方法与步骤...

    总第23篇 在Qt的项目开发过程中,有时软件要翻译成多语言版本,这就涉及到国际化方面的操作.虽然Qt对这方面集成了很多工具,操作起来比较方便,本文还是总结一下国际化的方法和步骤,用以备忘和参考. 我们 ...

  5. springBoot国际化多语言开发配置,中文OR英文支持一键切换

    springBoot有许多的自动化配置,其中就包括多语言的autoConfiguration,打开org.springframework.boot.autoconfigure.context.Mess ...

  6. Qt中,软件多语言国际化翻译的方法与步骤

    Qt中,软件多语言国际化翻译的方法与步骤 在Qt的项目开发过程中,有时软件要翻译成多语言版本,这就涉及到国际化方面的操作.虽然Qt对这方面集成了很多工具,操作起来比较方便,本文还是总结一下国际化的方法 ...

  7. html多语言国际化,gMIS吉密斯i18n多语言国际化更新

    gMIS吉密斯 部署和使用范围日益扩大,跨国多语言版本成为迫切需要的功能,早在2018年年中就考虑要增加这一功能--在gMIS吉密斯中实现多语言版本的支持. 以期实现gMIS吉密斯的跨行业.跨地区和国 ...

  8. AngularJS国际化配置

    2019独角兽企业重金招聘Python工程师标准>>> AngularJS国际化配置 下载angular-translate 下载zip包:https://github.com/an ...

  9. vue-i18n及ElementUI国际化配置步骤

    1.vue-I18n使用 1.1.下载依赖 注意:vue2.0要用8版本的,使用9版本的会报错 npm install vue-i18n // 默认安装最新版本npm i vue-i18n@8.27. ...

最新文章

  1. 摄像头模组(CCM)与镀膜
  2. ORM单表查询,跨表查询,分组查询
  3. 因为在此系统中禁止执行脚本解决
  4. ubuntu 退出anaconda环境_ubuntu 安装两个Anaconda,并迁移虚拟环境
  5. oracle精简版_使用Entity Framework Core访问数据库(Oracle篇)
  6. Windows与Linux之间海量文件的传输与Linux下大小写敏感问题
  7. 6 redis 编译失败_Centos7.8环境搭建Redis主从复制和哨兵模式
  8. 智能会议系统(9)---流媒体协议学习
  9. 计算机导论答案解析,计算机导论答案解析内容.doc
  10. 纯粹经济学 —— 基本概念
  11. java - 建造者模式
  12. 区块链 以太坊 三元组是什么 state root transaction root receipt root
  13. 下列符合c语言语法的实型常量,以下各项中,符合C语言语法规定的实型常量是()...
  14. jpg怎么转换成png?
  15. 阿里云企业邮箱标准版多域名绑定
  16. 侯捷C++->构造函数
  17. 介绍一款分享真实互联网薪资的小程序
  18. python中1 is True 的结果为False,is判断与==判断的区别
  19. (十二)命令模式详解(故事版) .
  20. 无缝切地图的3D赛车游戏火了,小哥花16个月用JS打造,浏览器免费就能玩

热门文章

  1. 一个有关抽奖的专题项目
  2. TTS技术简单介绍和Ekho(余音)TTS的安装与编程
  3. numpy.random模块常用函数
  4. swoole服务器主动推消息,实现websocket-主动消息推送laravelswoole
  5. bind-html自动换行,如何实现textarea placeholder自动换行?
  6. npkill(安全快速的清理电脑上的 node_modules)
  7. 7-2 图形卡片分组游戏 (60 分)
  8. php报错怎么改,php 怎么设置报错级别 和 控制报错[转]
  9. 部署Java web项目到阿里云服务器
  10. 前端类名优秀命名例子_这是一篇需要花费你15分钟阅读的干货!浅谈前端工程化...