網站國際化(i18n)應該怎麼作?i18n-node + handlebars實現的例子

國際化(i18n)的原理

國際化(Internaltionalization)常常被用i18n簡稱,這是由於從國際化這個詞從i到n之間有18個字母,爲了不打過多字就被簡化爲了i18n。國際化使得任何網站文本不是hard code在代碼之中,所以在往後國際化的過程當中不須要對原先的代碼進行修改而只須要添加對應的文本翻譯便可。node

國際化的實現一種經常使用的方法是根據用戶的語言設置偏好,將網頁模版中的佔位字符串替換成對應的語言翻譯。好比能夠在項目的根目錄下設置/locales這樣一個文件夾,裏面放入以鍵值對形式存儲的json string。若是用戶的語言偏好設置是:zh_CN (中文),那麼遇到模版的welcome佔位符的時候,就替換爲「歡迎」,此外還能夠有其餘不一樣語言的翻譯。git

一個一般的locale json文件格式以下:github

//zh_CN.json:
{
    "welcome": "歡迎!!"
}

基於用戶登陸狀態、系統偏好設置的4層備選(Fallback)結構

剛纔提到了用戶的語言偏好設置爲中文,那麼偏好設置如何獲取呢?假定一個具備用戶帳戶系統的網站,通常來講有如下4個來源,依次做爲上一個層次失效時的備選方案(Fallback):express

  1. 登陸用戶帳戶的設置
  2. 用戶cookie中存儲的locale信息
  3. 用戶瀏覽器的默認語言
  4. 網站的默認語言

在用戶登陸的狀況下提取用戶的語言偏好。若是檢查到用戶沒有登陸,可是cookie中保存了用戶上次訪問時設置的語言偏好,那麼使用cookie中的語言偏好。若是用戶的cookie中並無關於locale的信息(通常來講是用戶第一次訪問或者清除了cookie數據),那麼退一步使用用戶瀏覽器的語言偏好,這一信息能夠從請求頭的Accept-language中提取。最後做爲不得已在用戶未發送任何信息的狀況下,使用網站默認語言做爲用戶的偏好設置。json

其中,使用一、三、4的狀況下,服務器端應在最後一步嘗試設置瀏覽器的Cookie數據,以保證用戶在下一次訪問、或者切換登陸狀態時仍然可以按照以前的偏好設置獲取網站服務。segmentfault

使用i18n-node和handlebars的實現

nodejs的i18n-node提供了很是簡單的i18n中間件,而且支持多種的模版實現。若是你們搜索可能還會看到i18n-node2這個package。它是對於早期i18n-node的一個擴展,由Jquery的John Resig實現,目前的i18n-node已經基本包含了這些內容。瀏覽器

下面的代碼展現瞭如何使用i18n-node module結合handlebars的helper函數來實現基本的i18n。安全

這裏的一個基本假設是,服務器處理i18n是在獲取了用戶登陸信息以後。關於如何使用express-session保存用戶登陸狀態以提供連續的服務,能夠參考《Session原理、安全以及最基本的Express和Redis實現》這篇文章。服務器

//server.js
var express = require('express'),
    session = require('express-session'),
    handlebars = require('express-handlebars'),
    i18n = require('i18n'),
    app = express();

//配置i18n
i18n.configure({
    locales:['en', 'zh-CN'],  //聲明包含的語言
    directory: __dirname + '/locales',  //翻譯json文件的路徑
    defaultLocale: 'en'   //默認的語言,即爲上述標準4
});

// 設置app的模版引擎
app.engine('hbs', handlebars.create({
    layoutsDir: 'templates/layouts',
    partialsDir: 'templates/partials',
    defaultLayout: 'default',
    helpers: new require('helpers')(),
    extname: '.hbs'
}).engine);

// 添加session處理的中間件
app.use(session({
    secret: 'express is powerful'
}));
// 添加setLocale中間件,注意必須在session以後
app.use(setLocale);

// 定義setLocale中間件
function setLocale(req, res, next){
    var locale;
    // 當req進入i18n中間件的時候,已經經過sessionId信息獲取了用戶數據
    // 獲取用戶數據中的locale數據
    if(req.user){
        locale = req.user.locale;
    }
    // 獲取cookie中的locale數據
    else if(req.signedCookies['locale']){
        locale = req.signedCookies['locale'];
    }
    // 獲取瀏覽器第一個偏好語言,這個函數是express提供的
    else if(req.acceptsLanguages()){
        locale = req.acceptsLanguages();
    }
    // 沒有語言偏好的時候網站使用的語言爲中文
    else{
        locale = 'zh_CN';
    }
    // 若是cookie中保存的語言偏好與此處使用的語言偏好不一樣,更新cookie中的語言偏好設置
    if(req.signedCookies['locale'] !== locale){
        res.cookie('locale', locale, { signed: true, httpOnly: true });
    }
    // 設置i18n對這個請求所使用的語言
    req.setLocale(locale);
    next();
};

// 啓動http server...省略部分代碼
//helpers.js
var i18n = require('i18n');
module.exports = function() {

    var _helpers = {};
    // 聲明handlebar中的i18n helper函數
    // __函數不考慮單複數
    _helpers.__ = function () {
        return i18n.__.apply(this, arguments);
    };
    // __n函數考慮單複數
    _helpers.__n = function () {
        return i18n.__n.apply(this, arguments);
    };

    return _helpers;
};
// templates/index.hbs
<h1>{{{__ "welcome"}}}</h1>

這樣就能夠渲染出有「歡迎」兩個字的頁面了。這只是i18n-node最簡單的用法,你們能夠去i18n-node的Github頁面看更多API信息cookie

另外給你們推薦偶爾發現的一個網站Transifex,它使用衆包的方式幫助你的網站作國際化,比起本身找朋友翻譯,這個網站提供的方式是收集世界各地有興趣來翻譯的愛好羣體幫你翻譯,能夠得到的語種和可靠性都還不錯的樣子。

https://www.transifex.com/

相關文章
相關標籤/搜索