网站国际化(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/

相关文章
相关标签/搜索