Yii 2 —— 基于Mustache的页面多语言解决方案

在Yii 2中,官方的页面多语言解决方案有两个:

方案1,使用Yii::t()函数,在页面中需要输出文字的地方,使用类似如下代码:

<?= Yii::t(‘views/login’, ‘hello’)?>

这样做的后果是页面上大量充斥着类似的代码,导致页面可读性很差,而且对于同一个页面来说,Yii::t()函数的第一个参数基本上都是一样的,看到这些重复代码,也是心塞。我曾经在项目中采用这种方式实现多语言,一个简单的登录页面都能写到心烦的要命。

方案2,为指定语言做一个专门的视图,假设你有个页面是英文的,想再做个中文页面,可是中英文页面布局等相差很大,不是简单的翻译文字,那么在Yii 2中,可以在该页面的目录下,再建立一个zh-CN目录,然后在这个目录下建立一个同名的视图文件,页面内容用中文实现即可。这个我会专门再有文章说明如何实现。

如果中英文页面布局基本一样,只是文字有变化,那么建议还是不要用方案2了,宁可用方案1降低可读性,否则一旦页面内容有修改,两个页面之间的内容同步会搞到你怀疑人生。

总之,不管是方案1还是2,我都不喜欢,想要寻找一种简洁明了的页面多语言方案,页面看起来干净清爽,又不需要为每个语言做单独的页面。

那么怎样才能做到呢,我从Mustache中找到了实现的方案,假设下面是一个视图的代码:

<h3>{{基本信息}}</h3>
<table class="table table-bordered">
    <tbody>
    <tr>
        <td class="base-label active">{{下载队列}}</td>
        <td class="base-label active">{{等待队列}}</td>
    </tr>
    <tr>
        <td class="base-label active">{{已安装}}</td>
        <td class="base-label active">{{当前GameInfo}}</td>
    </tr>
    <tr>
        <td class="base-label active">{{剩余电量}}</td>
        <td class="base-label active">{{是否允许OTA}}</td>
    </tr>
    </tbody>
</table>

如果把想要多语言显示的文字用Mustache的变量符号给括起来,然后假设上面的内容已经存到一个字符串$content里,那么在Action中,可以用Mustache将其输出为英文:

$content = $this->render(‘mypage‘, $params);
$m = new Mustache_Engine();
$content = $m->render($content, [
    ‘基本信息‘ => ‘Base Information‘,
    ‘下载队列‘ => ‘Downloading‘,
    ‘等待队列‘ => ‘Waiting‘,
    ‘已安装‘ => ‘Installed‘,
    ‘当前GameInfo‘ => ‘GameInfo‘,
    ‘剩余电量‘ => ‘Battery Level‘,
    ‘是否允许OTA‘ => ‘Is can OTA‘,
]);

return $content;

这里的要点是先用Yii的render函数,得到要输出页面的字符串,然后使用Mustache,将指定的文字转换为英文,最后通过return输出。

上面这段代码就是使用Mustache实现页面多语言的核心思想,首先看页面的代码,完全没有任何PHP的代码,都是标准的HTML元素,页面看起来非常的干净清爽,前端开发人员可以直接用这个页面做前端的各种效果,完美实现前后端开发的解耦。

当然,上面展示的是核心的思想,但是要实际使用,还是需要进一步的完善。

首先,翻译的文字其实不适合放到Action的代码里,这样不好维护,应该按照Yii 2的设计思想,放到messages目录下,为指定语言建立messages文件,类似如下:

return [
    ‘device/views/deviceLog/mypage => [
        ‘基本信息‘ => ‘Base Information‘,
        ‘下载队列‘ => ‘Downloading‘,
        ‘等待队列‘ => ‘Waiting‘,
        ‘已安装‘ => ‘Installed‘,
        ‘当前GameInfo‘ => ‘GameInfo‘,
        ‘剩余电量‘ => ‘Battery Level‘,
        ‘是否允许OTA‘ => ‘Is can OTA‘,
    ],
];

使用视图的路径作为键值,方便为每个页面确定翻译的内容。

其次,做一个自己的Controller的基类,重载render函数:

public function render($view, $params = [])
{
    $content = parent::render($view, $params);

    $path = $this->getViewPath() . ‘/‘ . $view;
    $list = EonI18nUtils::getMsgs($path);
    if (empty($list)) {
        return $content;
    }
    $m = new Mustache_Engine([
        ‘delimiters‘ => ‘## ##‘,
    ]);
    $content = $m->render($content, $list);

    return $content;
}

这里,先调用父类的render函数,得到正常输出的视图字符串,再调用EonI18nUtils::getMsgs(),根据视图文件的路径,得到该页面的多语言键值对,然后创建Mustache对象,将视图字符串中的指定键值修改为翻译后的文字。

为了保证页面上基于JavaScript的Mustache可以使用,这里将Mustache的键值标签由{{}}改为####,页面代码类似如下:

<h3>##基本信息##</h3>
<table class="table table-bordered">
    <tbody>
    <tr>
        <td class="base-label active">##下载队列##</td>
        <td class="base-val">{{downloading}}</td>
        <td class="base-label active">##等待队列##</td>
        <td class="base-val">{{waitting}}</td>
    </tr>
    <tr>
        <td class="base-label active">##已安装##</td>
        <td class="base-val">{{installed}}</td>
        <td class="base-label active">##当前GameInfo##</td>
        <td class="base-val">{{gameinfo}}</td>
    </tr>
    <tr>
        <td class="base-label active">##剩余电量##</td>
        <td class="base-val">{{battery_level}}%</td>
        <td class="base-label active">##是否允许OTA##</td>
        <td class="base-val">{{allowOTA}}</td>
    </tr>
    </tbody>
</table>

这样,上面代码中用##括起来的文字会被翻译,而用{{}}括起来的,则由页面上的JS代码使用Mustache方案替换文字。

EonI18nUtils::getMsgs()的参考代码如下:

public static function getMsgs($category, $lang = null)
{
    $category = str_replace(‘\\‘, ‘/‘, $category);
    $arr = explode("/", $category);
    $arr = array_slice($arr, count($arr) - 4);
    $category = implode("/", $arr);

    $messageSource = \Yii::$app->getI18n()->getMessageSource(‘messages‘);
    $list = $messageSource->getMsgList($category, $lang);
    return $list;
}

getMsgList()代码类似如下:

public function getMsgList($langPath, $language)
{
    $language = $this->getLanguage($language);
    if (!isset($this->_messages[$language])) {
        $this->_messages[$language] = $this->loadMessages(‘messages‘, $language);
    }
    if (isset($this->_messages[$language][$langPath])) {
        return $this->_messages[$language][$langPath];
    }
    return false;
}

原文地址:https://blog.51cto.com/lancelot/2383607

时间: 2024-10-01 12:01:38

Yii 2 —— 基于Mustache的页面多语言解决方案的相关文章

Yii的缓存机制之页面缓存

页面缓存是不能通过片段缓存来实现的,因为布局和内容不能同时缓存.只能通过过滤器来生成缓存. 实现方法: 在控制器里使用过滤器来实现 function filters (){ return array( array( 'system.web.widgets.COutputCache + detail', //只针对detail有效 'duration' => 3600, //缓存时间 'varyByParam' => array('id'), //缓存依赖(通过不同的id实现不同的缓存) ),

[label][paypal] Paypal 支付页面的语言显示问题

答复 Frank 通过 Email2014-11-12 02:01 上午 您好 感谢您联系PayPal商家技术支持中心. PayPal登陆页面的语言是PayPal服务器根据以下各种因素来自动判断的:1.Buyer浏览器设置中的语言偏好设置.2.Buyer浏览器中和PayPal相关的Cookie. 比如如果曾经用繁体中文账户登陆过PayPal,在浏览器Cookie会有保存,以后在付款时可能显示繁体中文.3.参数LOCALECODE.4.还有,PAYMENTREQUEST_n_SHIPTOCOUNT

基于jQ+CSS3页面滚动内容元素动画特效

今天给大家分享一款基于jQ+CSS3页面滚动内容元素动画特效.这是一款基于jQuery+CSS3实现的页面滚动代码.该实例适用于适用浏览器:360.FireFox.Chrome.Safari.Opera.傲游.搜狗.世界之窗. 不支持IE8及以下浏览器. 在线预览   源码下载 实现的代码. html代码: <div class="htmleaf-container"> <div class="container"> <h2 class

最省力的多语言解决方案

微软的ASP.NET localization(本地化,多语言)的方案,在使用的过程中,碰到许多的问题,这些问题都不是技术实现上的.主要是他浪费了我们许多的时间和精力. 1.在页面上使用许多key来替换页面的汉字文本,导致页面不可读,很难定位,维护困难. 2.要把全部的文本换成key,工作量巨大,繁重枯燥,很容易出错,忘记转换,忘记后很难发现. 3.key很容易发生冗余,因为不同时间加入的文字到底以前加过没有,要查找,挺烦的, 4.key和文本的一致性不好维护, 最近在开发了几天和python

基于QT的换肤整体解决方案(QSkinStyle)(提供Linux的XP风格)

基于QT的换肤整体解决方案(QSkinStyle) 对QT这个成功的跨平台GUI库,本身内置了对换肤功能的实现,比如cleanlooks.plastique等跨平台风格:还有一些是和平台相关的风格,比如WindowsXP.WindowsVista风格只能用在windows平台上,底层也会调用uxtheme.dll来实现windows的风格.    QT内置的风格(qwindowsstyle.qmotifstyle.qcdestyle等),都是针对不同的风格定义(metric.look and f

基于K2的集成供应链流程解决方案

基于K2的集成供应链流程解决方案http://www.k2software.cn/zh-hans/scm-solution 一.详细功能模块 需求管理模块多渠道管理.需求计划.需求感知与传递市场营销及促销规划.新产品导入.订单满足.店面补货 物流模块交通运输规划,负载汇总和优化运输能力规划和管理:运输执行和管理零担,多点收集,多点送货跟踪和追踪,逆向物流,进出口物流 集成的业务计划财务规划,S&OP(销售和运营计划)基线和根本原因分析供应链风险管理与业务连续性 采购生产管理模块主生产计划,材料清

JS中用execCommand(&quot;SaveAs&quot;)保存页面兼容性问题解决方案

开发环境:ASP.NET MVC,其他环境仅供参考. 问题描述:在开发中遇到这样的需求,保存页面,通常使用JavaScript的saveAs进行保存,各浏览器对saveAs支持,见下表. 代码一:初始保存的代码,只有IE6,7,8支持. function CmdSave() { var OW = window.open('', "_blank", ""); var DD = new Date(); OW.document.open(); var content =

基于OpenConnect 构建的SSL VPN解决方案 2017/11/10

本文转载于灵跃云 :原文链接 1.写在前面 VPN(Virtual Private Network),虚拟专用网络,是一种通过公用网络安全地对企业内部专用网络进行远程访问的连接方式,可有效保障通信的机密性.如,出差办公人员可通过VPN通道安全地访问公司内部OA系统.发展至今的VPN同时融合了访问控制.路由选择.传输管理等多种功能,在全球的信息安全体系及各行业的信息系统中已发挥着重要作用. 常见的VPN主要有: ● PPTP VPN ● L2TP VPN ● IPSec VPN ● SSL VPN

基于Shader实现的UGUI描边解决方案

基于Shader实现的UGUI描边解决方案 前言 大扎好,我系狗猥.当大家都以为我鸽了的时候,我又出现了,这也是一种鸽.创业两年失败后归来,今天想给大家分享一个我最近研究出来的好康的,比游戏还刺激,还可以教你登dua郎喔(大误 这次给大家带来的是基于Shader实现的UGUI描边,也支持对Text组件使用. 首先请大家看看最终效果(上面放了一个Image和一个Text): (8102年了怎么还在舰 接下来,我会向大家介绍思路和具体实现过程.如果你想直接代到项目里使用,请自行跳转到本文最后,那里有