angularjs国际化多语言,angular-translate教程详解,$translate.instant()为什么不生效
<div align="center"><img src="https://img2020.cnblogs.com/blog/1213309/202004/1213309-20200425181437416-1418762837.png"></div><h1 id="壹--引">壹 ❀ 引</h1>
<p>最近项目要求支持国际化多语言,由于项目用的还是angularjs,那么首当其冲的选择了angularjs封装的I18N插件<code>angular-translate</code>,本文主要会从三个方向展开讨论,一是基本用法,怎么用,代码是什么意思;二是问题解答,比如<code>$translate.instant()</code>为什么没效,怎么在JS程序中使用多语言等;第三便是提供我的解决方案,供大家参考,那么本文开始。</p>
<h1 id="贰--基本用法">贰 ❀ 基本用法</h1>
<p>由于是三方插件,自然要下载才能使用,请大家在项目目录下执行<code>npm i angular-translate</code>命令,下载多语言相关依赖包,OK下载完成后在<code>node_modules</code>文件夹中可以看到如下内容:</p>
<div align="center"><img src="https://img2020.cnblogs.com/blog/1213309/202004/1213309-20200423185210247-842275821.png"></div>
<p>文件虽多,我们需要用到的其实只有<code>angular-translate.min.js</code>与<code>angular-translate-loader-static-files</code>目录下的<code>angular-translate-loader-static-files.min.js</code>。</p>
<p>所以第一步,在HTML文件中引入相关资源,如下:</p>
<pre><code class="language-html"><script src="node_modules/angular/angular.min.js"></script>
<script src="node_modules/angular-translate/dist/angular-translate.js"></script>
<script
src="node_modules/angular-translate/dist/angular-translate-loader-static-files/angular-translate-loader-static-files.min.js"></script>
</code></pre>
<p>在项目目录下新建一个language文件夹,用于存放我们的语言列表,这里我们就建两个,一个中文一个英文,如下:</p>
<div align="center"><img src="https://img2020.cnblogs.com/blog/1213309/202004/1213309-20200423185246751-434500551.png"></div>
<p>我们在<code>en.json</code>中添加如下代码</p>
<pre><code class="language-json">{
"name": "echo",
"age": "twenty-seven"
}
</code></pre>
<p>我们在<code>zh.json</code>中添加如下代码:</p>
<pre><code class="language-json">{
"name": "听风",
"age": "27"
}
</code></pre>
<p>好的,现在我们创建HTML页面主体部分,以及对应的controller,如下:</p>
<pre><code class="language-html"><body ng-controller="myCtrl as vm">
<p>{{"name"|translate}}</p>
<p translate="age"></p>
<select name="" id="" ng-model="vm.language" ng-change="vm.change()">
<option value="en">英文</option>
<option value="zh">中文</option>
</select>
</body>
</code></pre>
<pre><code class="language-javascript">angular.module('myApp', ['pascalprecht.translate'])
.controller('myCtrl', ['$translate', function ($translate) {
var vm = this;
vm.language = "zh";
vm.change = function () {
$translate.use(vm.language);
};
}])
.config(function ($translateProvider) {
// 读取本地JSON文件,prefix代表文件路径前缀,suffix代表文件后续
$translateProvider.useStaticFilesLoader({
prefix: './language/',
suffix: '.json'
});
// 设置默认的语言
$translateProvider.preferredLanguage('zh');
});
</code></pre>
<p>angullarjs其它部分大家执行搭建,做到这一步,利用live-server启动本地服务器(其它本地服务器也行)打开页面,尝试切换select选项,可以发现我们已经实现了一个简单的多语言了。</p>
<div align="center"><img src="https://img2020.cnblogs.com/blog/1213309/202004/1213309-20200423185330919-1687049229.gif"></div>
<p>那么现在我们来解释下上述代码是什么意思,做了什么。</p>
<p>首先在HTML中我用了两种方式来显示多语言,一种是表达式,一种是指令形式,两种皆可,官方推荐使用指令会更好,不过有特殊情况只能用表达式,这点后面我们再说。而在代码中的<code>name</code>与<code>age</code>其实就是对应了JSON文件中数据的key,这点不难理解。</p>
<p>对于JS代码,第一步就是得在module中加入<code>pascalprecht.translate</code>模板,这样我们才能通过config对多语言进行初步配置,比如<code>$translateProvider.preferredLanguage('zh')</code>这一句用来设置多语言的默认语言,例子中默认的就是中文。</p>
<p>而<code>$translateProvider.useStaticFilesLoader</code>这一句其实对应了我们在HTML中引用的<code>angular-translate-loader-static-files</code>文件,它的作用就是用来导入项目中的其它静态文件,毕竟引用了JSON,后程序才有可供查找的语言列表;另外属性<code>prefix</code>用来描述文件路径,<code>suffix</code>用来描述你需要引用文件的后缀。</p>
<p>细心的同学一定想问,那程序怎么知道要去哪个JSON文件中去查呢,在上述代码config与controller分别有这两段,作用都是告诉translate应该用哪个语言表查询:</p>
<pre><code class="language-javascript">$translate.use(vm.language);
$translateProvider.preferredLanguage('zh');
</code></pre>
<p>再看select中option赋予的值,不是正好与我们的JSON文件名相同吗。那么关于translate基础介绍说到了,下面来聊聊使用中会遇到哪些问题。</p>
<h1 id="叁---进阶用法与部分问题解答">叁❀ 进阶用法与部分问题解答</h1>
<h3 id="叁--壹-translate-keyvalue包含变量">叁 ❀ 壹 translate key/value包含变量</h3>
<p>我们在上文的例子中,translate查找所用的key是一个确切的值,其实说到底,所谓translate国际化,就是在不同的语言表中定义相同的key名,再根据用户操作切换不同的表作为查找根据而已。</p>
<p>那么问题来了,假设我们在使用时写在HTML上的key是个变量怎么办呢?不留悬念,直接看下面的例子:</p>
<p>我们在controller中添加如下代码:</p>
<pre><code class="language-javascript">vm.myName = 'name';
</code></pre>
<p>然后在HTML中添加如下两行:</p>
<pre><code class="language-html"><p>{{vm.myName|translate}}</p>
<p translate="{{vm.myName}}"></p>
</code></pre>
<p>刷新页面,可以看到生效了,这里我们就是将key赋予了一个变量,通过上述两种方式能解析key为变量的情况。</p>
<p>对应的,那么假设JSON配置的value中包含变量怎么办呢,直接看下面这个例子:</p>
<p>我们在JSON中英文中分别添加如下代码:</p>
<pre><code class="language-json">// en.json
{
"sayName":"my nam is {{userName}}"
}
// zh.json
{
"sayName":"我的名字是{{userName}}"
}
</code></pre>
<p>在HTML中添加如下代码:</p>
<pre><code class="language-html"><p>{{ 'sayName' | translate:'{ userName: "听风是风" }' }}</p>
<p translate="sayName" translate-values='{ userName: "听风是风"}'></p>
<p translate="sayName" translate-value-user-name='听风是风'></p>
</code></pre>
<div align="center"><img src="https://img2020.cnblogs.com/blog/1213309/202004/1213309-20200425180256436-142953644.gif"></div>
<p>其实说到底就是为过滤器传递罢了,考虑到vaule中包含多个变量的情况,如果全写在HTML上就不太美观了,所以我们可以将值定义成一个对象,我们分别在controller与HTML中添加如下代码:</p>
<pre><code class="language-javascript">vm.userName = {
userName: '听风是风'
};
</code></pre>
<pre><code class="language-html"><p>{{ 'sayName' | translate:vm.userName}}</p>
<p translate="sayName" translate-values='vm.userName'></p>
</code></pre>
<p>其实效果还是一样,看着也舒服了很多,万一存在多个变量,咱们也是为controller中的对象添加属性而已。</p>
<h3 id="叁--贰-在controller中使用国际化">叁 ❀ 贰 在controller中使用国际化</h3>
<p>上面例子举了一大堆,其实都是在HTML上使用过滤器实现语言国际化,那么问题来了,假设我在controller中有一个弹窗,弹窗内容也得支持国际化,这个文本咋整呢?我们使用<code>$translate.instant()</code>方法,看个例子:</p>
<p>请分别在HTML于controller中添加如下代码:</p>
<pre><code class="language-html"><button ng-click="vm.alert()">点我</button>
</code></pre>
<pre><code class="language-javascript">vm.alert = function () {
let msg = $translate.instant('sayName', {
userName: 'echo'
});
alert(msg);
};
</code></pre>
<p>这里大家自行测试,说直白点,<code>$translate.instant</code>接受了两个参数,第一个是你要找的key,第二个参数是传递给JSON文件中变量的值。</p>
<p>问题来了,有的同学说为啥我的<code>$translate.instant</code>无效,就是获取不到,大家直接在controller外层添加如下代码,注意,不要用事件去包裹它,看看控制台打印结果:</p>
<pre><code class="language-javascript">let msg = $translate.instant('sayName', {
userName: 'echo'
});
console.log(msg);//sayName
</code></pre>
<p>可以看到直接输出了key,并没找到我们想要的值,这是因为translate加载JSON并查找的过程是一个异步,大家可以修改加载语言引用的逻辑,比如将config修改成如下代码:</p>
<pre><code class="language-javascript">.config(function ($translateProvider) {
// 注册语言表
$translateProvider
.translations('en', {
"sayName": "my nam is {{userName}}"
})
.translations('zh', {
"sayName": "我的名字是{{userName}}"
});
// 设置默认的语言
$translateProvider.preferredLanguage('zh');
});
</code></pre>
<p>OK,再刷新页面看看控制台,我们发现成功获取到了。</p>
<p>有同学就不乐意了,这样做虽然解决了语言表异步的问题,但是语言表一旦多了,看着就非常不美观了。没事,咱们再将config改回到最初的样式,然后在controller中添加如下代码:</p>
<pre><code class="language-javascript">$translate('sayName', {
userName: 'echo'
}).then(function (resp) {
console.log(resp)
}, function (err) {
console.log(err)
});
</code></pre>
<p><code>$translate(key)</code>方法返回一个promise,也就是说即便文件引用是异步的情况,我们通过这种方式也能成功获取到想要的语言内容,当然缺点也非常明显,每次做查询都得写promise回调,代码看着非常不爽。那么贴上最后的解决方法,给大家做个参考。</p>
<h1 id="肆--仅供参考的方案">肆 ❀ 仅供参考的方案</h1>
<p>HTML中我就不说了,主要说说config,我的写法是这样:</p>
<pre><code class="language-javascript">.config(function ($translateProvider) {
// 获取语言模块
let enLanguage = require("../language/en.js");
let zhLanguage = require("../language/zh.js");
// 注册语言表
$translateProvider
.translations('en', enLanguage.language)
.translations('zh', zhLanguage.language);
// 设置默认的语言
$translateProvider.preferredLanguage('zh');
});
</code></pre>
<p>而语言表就不是放在JSON文件中了,而是放在了两个JS文件中进行管理,这里我借用了mod.js让JS模块化,代码如下:</p>
<pre><code class="language-javascript">//en.js
exports.language = {
"sayName": "my nam is {{userName}}"
}
//zh.js
exports.language = {
"sayName": "我的名字是{{userName}}"
}
</code></pre>
<p>这么做的好处其实就两点,第一语言有独立的文件进行管理,便于后期维护;第二解决了文件加载查询异步问题,在controller中我们获取多语言就非常方便。</p>
<p>最后提一点,假设我们在中文中配置了一个key,因为疏忽导致在英文中忘记配置了这个key,那么用户在切换语言时因为找不到对应的key,这就会加载失败,官方在config中还提供了一个非常棒的方法,直接上代码:</p>
<pre><code class="language-javascript">$translateProvider
.translations('en', enLanguage.language)
.translations('zh', zhLanguage.language)
.fallbackLanguage(['en', 'zh']);
</code></pre>
<p><code>fallbackLanguage</code>的作用就是,假设一个key查找失败,那么<code>angular-translate</code>就会以<code>['en', 'zh']</code>为替补语言进行查找,以此来保证某个key找不到,你的页面至少是有一种候补语言能展示出来。</p>
<p>那么关于<code>angular-translate</code>的使用介绍就说到这里了,本文结束。</p><br><br>
来源:https://www.cnblogs.com/echolun/p/12762839.html
頁:
[1]