angularjs國際化多語言,angular-translate教程詳解,$translate.instant()為什么不生效


壹 ❀ 引

最近項目要求支持國際化多語言,由於項目用的還是angularjs,那么首當其沖的選擇了angularjs封裝的I18N插件angular-translate,本文主要會從三個方向展開討論,一是基本用法,怎么用,代碼是什么意思;二是問題解答,比如$translate.instant()為什么沒效,怎么在JS程序中使用多語言等;第三便是提供我的解決方案,供大家參考,那么本文開始。

貳 ❀ 基本用法

由於是三方插件,自然要下載才能使用,請大家在項目目錄下執行npm i angular-translate命令,下載多語言相關依賴包,OK下載完成后在node_modules文件夾中可以看到如下內容:

文件雖多,我們需要用到的其實只有angular-translate.min.jsangular-translate-loader-static-files目錄下的angular-translate-loader-static-files.min.js

所以第一步,在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>

在項目目錄下新建一個language文件夾,用於存放我們的語言列表,這里我們就建兩個,一個中文一個英文,如下:

我們在en.json中添加如下代碼

{
    "name": "echo",
    "age": "twenty-seven"
}

我們在zh.json中添加如下代碼:

{
    "name": "聽風",
    "age": "27"
}

好的,現在我們創建HTML頁面主體部分,以及對應的controller,如下:

<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>
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');
  });

angullarjs其它部分大家執行搭建,做到這一步,利用live-server啟動本地服務器(其它本地服務器也行)打開頁面,嘗試切換select選項,可以發現我們已經實現了一個簡單的多語言了。

那么現在我們來解釋下上述代碼是什么意思,做了什么。

首先在HTML中我用了兩種方式來顯示多語言,一種是表達式,一種是指令形式,兩種皆可,官方推薦使用指令會更好,不過有特殊情況只能用表達式,這點后面我們再說。而在代碼中的nameage其實就是對應了JSON文件中數據的key,這點不難理解。

對於JS代碼,第一步就是得在module中加入pascalprecht.translate模板,這樣我們才能通過config對多語言進行初步配置,比如$translateProvider.preferredLanguage('zh')這一句用來設置多語言的默認語言,例子中默認的就是中文。

$translateProvider.useStaticFilesLoader這一句其實對應了我們在HTML中引用的angular-translate-loader-static-files文件,它的作用就是用來導入項目中的其它靜態文件,畢竟引用了JSON,后程序才有可供查找的語言列表;另外屬性prefix用來描述文件路徑,suffix用來描述你需要引用文件的后綴。

細心的同學一定想問,那程序怎么知道要去哪個JSON文件中去查呢,在上述代碼config與controller分別有這兩段,作用都是告訴translate應該用哪個語言表查詢:

$translate.use(vm.language);
$translateProvider.preferredLanguage('zh');

再看select中option賦予的值,不是正好與我們的JSON文件名相同嗎。那么關於translate基礎介紹說到了,下面來聊聊使用中會遇到哪些問題。

叄 ❀ 進階用法與部分問題解答

叄 ❀ 壹 translate key/value包含變量

我們在上文的例子中,translate查找所用的key是一個確切的值,其實說到底,所謂translate國際化,就是在不同的語言表中定義相同的key名,再根據用戶操作切換不同的表作為查找根據而已。

那么問題來了,假設我們在使用時寫在HTML上的key是個變量怎么辦呢?不留懸念,直接看下面的例子:

我們在controller中添加如下代碼:

vm.myName = 'name';

然后在HTML中添加如下兩行:

<p>{{vm.myName|translate}}</p>
<p translate="{{vm.myName}}"></p>

刷新頁面,可以看到生效了,這里我們就是將key賦予了一個變量,通過上述兩種方式能解析key為變量的情況。

對應的,那么假設JSON配置的value中包含變量怎么辦呢,直接看下面這個例子:

我們在JSON中英文中分別添加如下代碼:

// en.json
{
    "sayName":"my nam is {{userName}}"
}
// zh.json
{
    "sayName":"我的名字是{{userName}}"
}

在HTML中添加如下代碼:

<p>{{ 'sayName' | translate:'{ userName: "聽風是風" }' }}</p>
<p translate="sayName" translate-values='{ userName: "聽風是風"}'></p>
<p translate="sayName" translate-value-user-name='聽風是風'></p>

其實說到底就是為過濾器傳遞罷了,考慮到vaule中包含多個變量的情況,如果全寫在HTML上就不太美觀了,所以我們可以將值定義成一個對象,我們分別在controller與HTML中添加如下代碼:

vm.userName = {
    userName: '聽風是風'
};
<p>{{ 'sayName' | translate:vm.userName}}</p>
<p translate="sayName" translate-values='vm.userName'></p>

其實效果還是一樣,看着也舒服了很多,萬一存在多個變量,咱們也是為controller中的對象添加屬性而已。

叄 ❀ 貳 在controller中使用國際化

上面例子舉了一大堆,其實都是在HTML上使用過濾器實現語言國際化,那么問題來了,假設我在controller中有一個彈窗,彈窗內容也得支持國際化,這個文本咋整呢?我們使用$translate.instant()方法,看個例子:

請分別在HTML於controller中添加如下代碼:

<button ng-click="vm.alert()">點我</button>
vm.alert = function () {
    let msg = $translate.instant('sayName', {
        userName: 'echo'
    });
    alert(msg);
};

這里大家自行測試,說直白點,$translate.instant接受了兩個參數,第一個是你要找的key,第二個參數是傳遞給JSON文件中變量的值。

問題來了,有的同學說為啥我的$translate.instant無效,就是獲取不到,大家直接在controller外層添加如下代碼,注意,不要用事件去包裹它,看看控制台打印結果:

let msg = $translate.instant('sayName', {
    userName: 'echo'
});
console.log(msg);//sayName

可以看到直接輸出了key,並沒找到我們想要的值,這是因為translate加載JSON並查找的過程是一個異步,大家可以修改加載語言引用的邏輯,比如將config修改成如下代碼:

.config(function ($translateProvider) {
    // 注冊語言表
    $translateProvider
        .translations('en', {
            "sayName": "my nam is {{userName}}"
        })
        .translations('zh', {
            "sayName": "我的名字是{{userName}}"
        });
    // 設置默認的語言
    $translateProvider.preferredLanguage('zh');
});

OK,再刷新頁面看看控制台,我們發現成功獲取到了。

有同學就不樂意了,這樣做雖然解決了語言表異步的問題,但是語言表一旦多了,看着就非常不美觀了。沒事,咱們再將config改回到最初的樣式,然后在controller中添加如下代碼:

$translate('sayName', {
    userName: 'echo'
}).then(function (resp) {
    console.log(resp)
}, function (err) {
    console.log(err)
});

$translate(key)方法返回一個promise,也就是說即便文件引用是異步的情況,我們通過這種方式也能成功獲取到想要的語言內容,當然缺點也非常明顯,每次做查詢都得寫promise回調,代碼看着非常不爽。那么貼上最后的解決方法,給大家做個參考。

肆 ❀ 僅供參考的方案

HTML中我就不說了,主要說說config,我的寫法是這樣:

.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');
});

而語言表就不是放在JSON文件中了,而是放在了兩個JS文件中進行管理,這里我借用了mod.js讓JS模塊化,代碼如下:

//en.js
exports.language = {
    "sayName": "my nam is {{userName}}"
}

//zh.js
exports.language = {
    "sayName": "我的名字是{{userName}}"
}

這么做的好處其實就兩點,第一語言有獨立的文件進行管理,便於后期維護;第二解決了文件加載查詢異步問題,在controller中我們獲取多語言就非常方便。

最后提一點,假設我們在中文中配置了一個key,因為疏忽導致在英文中忘記配置了這個key,那么用戶在切換語言時因為找不到對應的key,這就會加載失敗,官方在config中還提供了一個非常棒的方法,直接上代碼:

$translateProvider
    .translations('en', enLanguage.language)
    .translations('zh', zhLanguage.language)
    .fallbackLanguage(['en', 'zh']);

fallbackLanguage的作用就是,假設一個key查找失敗,那么angular-translate就會以['en', 'zh']為替補語言進行查找,以此來保證某個key找不到,你的頁面至少是有一種候補語言能展示出來。

那么關於angular-translate的使用介紹就說到這里了,本文結束。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM