原文地址:https://prinzeugen.net/yet-an...javascript
如今 Blessing Skin Server 的 HTML 模板是使用 Laravel 自帶的本地化來實現多語言支持的,而且使用了 devitek/yaml-translation 這個包把 Laravel 語言文件從默認的 PHP 數組形式改成 YAML 格式的文件。前端
不得不說數組形式的語言文件簡直反人類好嗎,一大堆 =>
看的眼暈。。YAML 大法好!(ゝ∀・)java
回到正題。雖然 HTML 模板裏的國際化是解決了,可是整個應用中須要國際化的地方可不止 HTML 模板,同時還有 JavaScript(一些驗證的提示文本)。可是靜態的腳本文件中總不能內嵌 PHP 吧,因此咱們得搞個單獨的解決方案。laravel
雖說網上現成的 JS 國際化的庫不少,但我總以爲有些看不上眼(多是我沒找到好的),就準備本身實現一下。git
首先咱們須要一個全局變量來保存從語言文件裏讀出來的東西:github
// 保存全部加載的語言文件 $.locales = {}; // 當前選擇的語言翻譯文件 var locale = {};
這裏咱們把 locales
這個字典綁到了 jQuery 定義的全局變量 $
上,這也就意味着要依賴 jQuery 了。固然你不綁在 $
上也是一點關係也沒有的,由於咱們下面並不須要用到 jQuery。數組
如今咱們就能夠在語言文件中這樣寫了:閉包
(function ($) { "use strict"; $.locales['zh-CN'] = { auth: { login: '登陸', validation: { emptyPassword: '密碼要好好填哦' } }, user: { changeNickName: '肯定要將暱稱設置爲 :new_nickname 嗎?' }, general: { confirm: '肯定', cancel: '取消' } }; })(window.jQuery);
若是你不許備依賴於 $
這個變量,就把閉包的做用域和裏面的變量名改一下。總之就是保證它能夠被全局地訪問到就好。less
由於咱們可能會加載多個含有語言文件的 locale.js
文件,因此咱們須要判斷一下當前語言,而後把對應的語言字典加載到上面定義的 locale
變量中:函數
function loadLocales() { for (lang in $.locales) { // 這裏你能夠進行進一步的加載判斷 if (!isEmpty($.locales[lang])) { locale = $.locales[lang] || {}; } } }
上面用到的那個 isEmpty
函數能夠看這裏:@Gist。而後咱們就能夠定義用於把 key
翻譯成具體語言的翻譯函數啦:
function trans(key, parameters) { if (isEmpty(locale)) { // 載入當前所選的語言至全局變量 loadLocales(); } parameters = parameters || {}; var segments = key.split('.'); var temp = locale || {}; for (i in segments) { if (isEmpty(temp[segments[i]])) { // 若是該項不存在,則原樣返回 key return key; } else { temp = temp[segments[i]]; } } for (i in parameters) { if (!isEmpty(parameters[i])) { // 替換語言字符串中的佔位符 temp = temp.replace(':'+i, parameters[i]); } } return temp; }
這裏能夠看到這個函數接受兩個參數,key
和 parameters
。key
就是用於翻譯的鍵值了,而且咱們能夠傳一個 dict
做爲參數來替換語言字符串中的佔位符。
並且在 key
的處理中,咱們解析了相似於 auth.login
這樣的 key
,而且是能夠無限嵌套下去的。是否是感受挺熟悉的?沒錯,就是 Laravel 翻譯器也在使用的「點」語法 ( ゚ 3゚) 我是以爲蠻不錯的就搬過來了(笑
如今咱們在加載完語言文件後就可使用這個函數來實現前端國際化啦:
trans('auth.validation.emptyPassword'); // 返回 "密碼要好好填哦" trans('user.changeNickName', { new_nickname: 'FUCK' }); // 返回 "肯定要將暱稱設置爲 FUCK 嗎?"