Javascript 教程:基于L20n库的node.js/Polymer i18n解决方案

Javascript 教程:基于L20n库的node.js/Polymer i18n解决方案,javascript,node.js,internationalization,polymer,l20n,Javascript,Node.js,Internationalization,Polymer,L20n,在node.jsweb项目中实现i18n有一个相当常见的问题。如果您想: 使用web组件(例如) 对服务器端和客户端文件使用单个翻译文件 按程序翻译某些项目(如动态创建的字符串) 由于Mozilla团队开发了全新的解决方案,这个问题可以很容易地解决。项目结构 首先,我创建了一个项目结构,它将按照文件的用途将文件分开存放: . +-- app.js +-- piblic | +-- locales | +-- app.ru.l20n | +-- app.en.l20n

node.js
web项目中实现i18n有一个相当常见的问题。如果您想:

  • 使用web组件(例如)
  • 对服务器端和客户端文件使用单个翻译文件
  • 按程序翻译某些项目(如动态创建的字符串)
  • 由于Mozilla团队开发了全新的解决方案,这个问题可以很容易地解决。

    项目结构 首先,我创建了一个项目结构,它将按照文件的用途将文件分开存放:

    .
    +-- 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
    被用作所有服务器端作业的本地化模块,
    app-l20n
    是用于用户界面l10n的聚合物组件

    装置 运行npm安装l20n——保存 当前版本是3.5.1,它有一个小错误。l20n的主文件是
    /dist/compat/node/l20n.js
    ,它有两个必需的变量,这些变量在代码中的任何地方都没有使用,但在启动时会压碎你的应用程序,因为它们只在库的devdependences中提到。为了避免这种情况,我只是将它们直接注释到库代码中:

    //var string_prototype_startswith = require('string.prototype.startswith');
    //var string_prototype_endswith = require('string.prototype.endswith');
    
    翻译文件 我在我的
    /public/locales/
    文件夹中创建了翻译文件,名为
    app.ru.l20n
    app.en.l20n
    。根据L20n规则,文件的内容如下所示:

    <foo "Foo translation">
    <bar "Bar translation">
    <register[$variant] {
        infinitive: "Register now!"
    }>
    
    现在,我们可以在node.js代码中使用这个模块,并根据键和区域设置请求获得翻译。我使用
    express sessions
    代替硬编码的区域设置,并将用户定义的区域设置存储为session属性
    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

    不,因为新的行为已经准备好了,我们可以在我们的定制聚合物组件中实现它。您可以通过聚合行为或使用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>
    
    
    函数regFormSubmit(事件){}
    聚合物({
    是:“应用程序自定义组件”,
    行为:[
    MB.i18n
    ],
    就绪:函数(){
    this.$.passwordValidator.validate=this.\u validatePasswords.bind(this);
    //将组件属性添加到数组中。它们可以像本例中那样简单,也可以
    //更复杂,参数:[“Some_key”,{param:“xxx”}]。
    //您甚至可以使用自定义后缀转换不同属性中的相同字符串:
    //[“Some_key”、{param:“yyy”}、“\u suffix”]并使用快捷方式将其放置在模板中:{Some_key_suffix}
    var translateProps=[“Foo”,“Bar”];
    //现在,使用行为进行翻译
    这个,翻译(这个,翻译操作);
    }
    });
    
    希望这个小教程会有帮助

    <script src="/node_modules/l20n/dist/compat/web/l20n.js"></script>
    <link rel="localization" href="/locales/app.{locale}.l20n">
    
    <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>
    
    <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>