2016-02-28 83 views

回答

0

项目结构

首先,我创建了一个项目的结构,这将让我的文件separatedly,通过他们的目的分组:

. 
+-- app.js 
+-- piblic 
| +-- locales 
|  +-- app.ru.l20n 
|  +-- app.en.l20n 
| 
+-- node_models 
| +-- l20n 
| 
+-- bower_components 
| +-- Polymer libraries 
| 
+-- app_modules 
| +-- app-l20n-node 
|  +-- index.js 
| 
+-- app_components 
    +-- app-l20n 
     +-- app-l20n.html 
    +-- app-custom-component 
     +-- app-custom-component.html 

的想法很简单:app-l20n-node作为模块本地化所有服务器-side作业,app-l20n是用于用户界面l10n的聚合物组件。

安装

运行npm install l20n --save
当前版本是3.5.1,它有一个小bug。 l20n的主文件是./dist/compat/node/l20n.js,它有两个必需的变量,它们不会在代码中的任何位置使用,但可以在启动时压制应用程序,因为它们仅在库的Devdependencies中提到。为了避免它,我只是评论他们对进入库代码:

//var string_prototype_startswith = require('string.prototype.startswith'); 
//var string_prototype_endswith = require('string.prototype.endswith'); 

翻译文件

我在/public/locales/文件夹,命名为喜欢app.ru.l20napp.en.l20n创建翻译文件。据L20n规则,文件的内容是这样的:

<foo "Foo translation"> 
<bar "Bar translation"> 
<register[$variant] { 
    infinitive: "Register now!" 
}> 

的Node.js + L20n

现在是时候创建一个L20n节点模块。 在我的情况下app_modules\app-l20n-node\index.js代码如下:

'use strict'; 
const L20n = require('l20n'); 
var path = require('path'); 

module.exports = function(keys, lang){ 

    const env = new L20n.Env(L20n.fetchResource); 

    // Don't forget nice debug feature of L20n library 
    env.addEventListener('*', e => console.log(e)); 

    // I suppose that I'll always provide locale code for translation, 
    // but if it would not happen, module should use preset 
    var langs = []; 
    if(!lang) { 
     // you should define locales here 
     langs = [{code: 'ru'}, {code: 'en'}] 
    } else { 
     langs = [{code: lang}] 
    } 

    // set context, using path to locale files 
    const ctx = env.createContext(langs, 
        [path.join(__dirname, '../../public/locales/app.{locale}.l20n')]); 

    const fv = ctx.formatValues; 

    return fv.apply(ctx, keys); 
}; 

现在我们可以在我们的Node.js代码中使用此模块,并得到翻译,通过按键和语言环境要求。我使用express-sessions而不是硬编码的区域设置,并将用户定义的区域设置存储为会话属性req.session.locale。但这一切都取决于项目。

var l20n = require('../../app_modules/app-l20n-node'); 

l20n(['foo','bar'], 'en') 
    .then((t)=>{ 
     console.log(t); // ["Foo translation", "Bar translation"] 
    }); 

聚合物+ L20n

现在我们应该创建L20n聚合物组分。
首先,添加库,并链接到翻译文件到您的HTML <head>

<script src="/node_modules/l20n/dist/compat/web/l20n.js"></script> 
<link rel="localization" href="/locales/app.{locale}.l20n"> 

现在是时候创建的聚合物组分app-l20n.html用新的行为。

<script> 

    /** 
    * Create namespace for custom behavior or use existing one. 
    */ 
    window.MB = window.MB || {}; 

    MB.i18n = { 

     /** 
     * Use l20n.js to translate certain strings 
     * @param component A Polymer component, usually "this.translate(this, props);" 
     * @param props An array of keys to translate: strings or arrays. 
     */ 
     translate: function(component, props) { 
      var view = document.l10n; 
      var promise = view.formatValues.apply(view, props); 
      promise.then(function(args){ 
       for (var i in args){ 

        var prop = props[i]; 

        // strings with parameters represented by arrays: 
        // ["string", {param: value}] 
        if (Array.isArray(prop)) { 

         // get property name - usually the same, as translation key 
         // so the object would have properties obj.Foo and obj.Bar 
         var propName = prop[0]; 

         // if it is needed to create multiple translations of the same 
         // string in one component, but with different parameters, 
         // the best way is to use suffix: 
         // ["string", {param: value}, "_suffix"] 
         if (prop.length == 3) propName = propName + prop[2]; 

         component.set(propName, args[i]); 
        } 

        // common strings 
        else component.set(prop, args[i]); 

       } 
      }); 
     } 
    }; 
</script> 

不,作为新的行为准备就绪,我们可以在我们的自定义聚合物组件中实现它。您可以通过Polymer Behavior或使用L20n自定义标签属性功能以编程方式获得翻译。

<link rel="import" href="/bower_components/polymer/polymer.html"> 
<link rel="import" href="/bower_components/gold-email-input/gold-email-input.html"> 
<link rel="import" href="/bower_components/paper-button/paper-button.html"> 

<link rel="import" href="/app_components/app-l20n/app-l20n.html"> 

<dom-module id="app-custom-component"> 
    <template> 
     <gold-email-input 
      auto-validate 
      required 
      name="email" 
      value="{{Foo}}" 
      label="{{Bar}}"> 
     </gold-email-input> 

     <paper-button onclick="regFormSubmit(event)"> 
      <iron-icon icon="perm-identity"></iron-icon> 
      <span data-l10n-id="Register" data-l10n-args='{"variant": "infinitive"}'></span> 
     </paper-button> 
    </template> 
    <script> 
     function regFormSubmit(event){} 
     Polymer({ 
      is: 'app-custom-component', 
      behaviors: [ 
       MB.i18n 
      ], 
      ready: function(){ 
       this.$.passwordValidator.validate = this._validatePasswords.bind(this); 

       // add your component properties to array. They can be simple like in this example, or 
       // more complex, with parameters: ["Some_key", {param: "xxx"}]. 
       // you can even translate the same string in different properties, using custom suffix: 
       // ["Some_key", {param: "yyy"}, "_suffix"] and place it in template with shortcut: {{Some_key_suffix}} 
       var translateProps = ["Foo", "Bar"]; 

       // now translate, using behavior 
       this.translate(this, translateProps); 
      } 
     }); 
    </script> 
</dom-module> 

希望这个小教程会有所帮助。