AGROSICA/node-localize

语言: JavaScript

git: https://github.com/AGROSICA/node-localize

GNU gettext启发(但不符合)Node.js的本地化库
GNU gettext-inspired (but not conformant) localization library for Node.js
README.md (中文)

node-localize库

为Node.js提供GNU gettext启发(但不符合)的转换实用程序,试图避免sprintf绑定gettext的某些限制(例如翻译字符串参数在所有翻译结果中按固定顺序排列)和“适合”在“比一个直的港口更好。

安装

如果你有npm,只需输入:

npm install localize

用法

node-localize返回一个对象构造函数,因此可以同时使用多个同时的本地化对象(尽管大多数情况下可能是单例实例化)。初始化时唯一需要的参数是翻译对象,使用以下结构:

var Localize = require('localize');

var myLocalize = new Localize({
    "Testing...": {
        "es": "Pruebas...",
        "sr": "тестирање..."
    },
    "Substitution: $[1]": {
        "es": "Sustitución: $[1]",
        "sr": "замена: $[1]"
    }
});

console.log(myLocalize.translate("Testing...")); // Testing...
console.log(myLocalize.translate("Substitution: $[1]", 5)); // Substitution: 5

myLocalize.setLocale("es");
console.log(myLocalize.translate("Testing...")); // Pruebas...

myLocalize.setLocale("sr");
console.log(myLocalize.translate("Substitution: $[1]", 5)); // замена: 5

node-localize对象也可以传递一个字符串,指示可以找到translations.json文件的目录。对所有子目录中的所有translations.json文件递归搜索此目录,并将它们的内容组合在一起,以便您可以根据需要组织翻译。

还会针对名为translate的目录递归搜索该目录。检查这些目录是否有varname.txt,varname.es.txt,varname.sr.txt等形式的特殊文本文件.varname.txt中的文本被视为应用程序和varname.xx的默认语言。 txt被视为文本的翻译。创建一个特殊的字符串对象,其中varname成为该对象的属性,默认语言文本是属性的值。所以你也可以做以下事情:

var Localize = require('localize');

var myLocalize = new Localize('./path/to/text/files/');

console.log(myLocalize.translate(myLocalize.strings.reallyLongText); // The contents of ./path/to/text/files/translations/reallyLongText.txt, if it exists

myLocalize.setLocale("es");
console.log(myLocalize.translate(myLocalize.strings.reallyLongText); // The contents of ./path/to/text/files/translations/reallyLongText.es.txt, if it exists

日期

由于日期格式在不同语言中差别很大,并且这些差异无法通过简单替换来解决,因此还有一个用于翻译这些值的localDate方法。

var theDate = new Date("4-Jul-1776");
var dateLocalize = new Localize("./translations");
dateLocalize.loadDateFormats({
    "es": {
        dayNames: [
            'Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb',
            'Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'
        ],
        monthNames: [
            'Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic',
            'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'
        ],
        masks: {
            "default": "dddd, d 'de' mmmm yyyy"
        }
    }
});

console.log(dateLocalize.localDate(theDate)); // Thu Jul 04 1776 00:00:00
console.log(dateLocalize.localDate(theDate, "fullDate")); // Thursday, July 4, 1776
console.log(dateLocalize.localDate(theDate, "mm/dd/yyyy")); // 07/04/1776

dateLocalize.setLocale("es");
console.log(dateLocalize.localDate(theDate)); // Jueves, 4 de Julio 1776

日期格式规则和配置取自node-dateformat,已扩展为支持多个同时语言环境并包含在node-localize中。

完整的API

var myLocalize = new Localize(translationsObjOrStr, dateFormatObj, defaultLocaleStr);
// translationsObjOrStr: a conformant translations object or a string indicating
//     the directory where one or more conformant translations.json files are stored
// dateFormatObj: a conformant date format object, containing one or more locales
//     if not specified, will auto-generate an 'en' locale; if initially specified,
//     will *overwrite* this auto-generated locale object
// defaultLocale: the locale of all keys in the translations object. Defaults to 'en'
myLocalize.setLocale(localeStr);
// localeStr: a locale string to switch to
myLocalize.loadTranslations(translationsObjOrStr);
// translationsObjOrStr: a conformant translations object or a string indicating
//     the directory where one or more conformant translations.json files are stored
//     Multiple calls to loadTranslations *appends* the keys to the translations
//     object in memory (overwriting duplicate keys).
myLocalize.getTranslations(translationsArrOrUndef);
// translationsArrOrUndef: an array of untranslated text whose translations you want
// to acquire, or leave it undefined for the entire internal translations object
myLocalize.clearTranslations();
// Wipes out the translations object entirely (if a clean reload is desired)
myLocalize.throwOnMissingTranslation(throwBool);
// throwBool: Boolean indicating whether or not missing translations should
//     throw an error or be silently ignored and the text stay in the default
//     locale. Useful for development to turn off.
myLocalize.translate(translateStr, arg1, arg2, ...);
// translateStr: The string to be translated and optionally perform a
//     substitution of specified args into. Arguments are specified in a RegExp
//     style by number starting with 1 (it is the first argument that can be
//     used and also is the arguments[1] value...), while using a jQuery-style
//     demarcation of $[x], where x is the argument number.
myLocalize.loadDateFormats(dateFormatObj);
// dateFormatObj: a conformant date format object, containing one or more locales
//     Specified locales are appended to the internal object just like
//     loadTranslations.
myLocalize.getDateFormats();
// Returns the internal date formats object.
myLocalize.clearDateFormats();
// Resets the date formats object to just the 'en' locale.
myLocalize.localDate(dateObjOrStr, maskStr, utcBool)
// dateObjOrStr: the date object or string to format as desired in the current
//     locale.
// maskStr: the predefined mask to use, or a custom mask.
// utcBool: a boolean indicating whether the timezone should be local or UTC
myLocalize.strings
// Object of key-value pairs defined by files in ``translations`` directories
// Key is the filename (sans extension) and value is the default language
// text. Useful for translating very large blocks of text that shouldn't really
// exist in code.

xlocalize CLI实用程序

从版本0.2.0开始,node-localize在通过NPM安装时,会向PATH添加一个xlocalize实用程序命令,该命令允许自动构建translations.json文件(并且可以在将来重新运行以更新现有文件而不用破坏现有的任何翻译)。它的命令开关如下:

xlocalize USAGE:

-l  Set the default language for the translations.json file(s) (default: en)
-r  Set xlocalize to generate translations.json files recursively (default)
-R  Set xlocalize to only generate a translations.json file for the current directory
-e  Set the file extensions to include for translation (default: html,js)
-t  Set the languages to translate to (comma separated)
-h  Show this help message.

例如,要在当前目录中创建仅用于HTML和JS文件的英语翻译为西班牙语,葡萄牙语,意大利语和法语的translations.json文件:

xlocalize -R -t es,pt,it,fr

如果要在以后翻译一种新语言(例如塞尔维亚语),您可以使用以下命令:

xlocalize -R -t es,pt,it,fr,sr

快速集成技巧

如果您的网站支持多种语言(可能是您使用此库的原因!),您需要翻译每种支持语言的页面内容。以下代码片段应该可以在Express中轻松使用。

根据请求切换区域设置的中间件

app.configure(function() {
    ...
    app.use(function(request, response, next) {
        var lang = request.session.lang || "en";
        localize.setLocale(lang);
        next();
    });
    ...
});

我假设您在会话中存储了他们的语言偏好,但是可以很容易地调整逻辑,但是您可以检测要显示的语言。

将translate,localDate和字符串导出为静态助手

app.helpers({
    ...
    translate: localize.translate,
    localDate: localize.localDate,
    strings: localize.strings
});

您的控制器甚至不应该意识到任何本地化问题;视图应该这样做,所以这应该是你的app.js文件中的足够配置。

在视图中使用translate,localDate和字符串

<h1>${translate("My Awesome Webpage")}</h1>

<h2>${translate("By: $[1]", webpageAuthor)}</h2>

<h3>${translate("Published: $[1]", localDate(publicationDate))}</h3>

{{if translate(strings.reallyLongPost) == strings.reallyLongPost}}
<strong>${translate("Warning: The following content is in English.")}</strong>
{{/if}}

{{html translate(strings.reallyLongPost)}}

我在这里使用jQuery模板for Express,但它应该很容易翻译成你喜欢的任何模板语言。

轻松将node-localize库导出到客户端,而无需将库复制到自己的源中

由于node-localize也可以在浏览器内部运行,jQuery模板也可以运行,因此能够将库导出到客户端非常有用。但是,不是手动将库代码复制到您的网站(并手动跟踪更新/错误修正),您可以直接从库中获取node-localize的源代码,并为其添加Express路由:

app.get('/js/localize.js', function(req, res) {
    res.send(Localize.source);
});

其中Localize等同于require('localize'),而不是实例化的localize对象。

如果您以这种方式在客户端上使用node-localize,那么将getTranslations和getDateFormats添加到app.helpers对象是明智的,因此视图可以指定客户端需要正常运行的转换和日期格式。

计划功能

  • 对于区域语言差异,可选的国家和地区代码支持(如果缺少特定的国家/地区代码则可以回溯到基线语言翻译)
  • 数字本地化(1,234,567.89对比1.234.567,89对比1 234 567,89对比日本数字[目前还不知道如何处理那个]
  • 货币本地化;不仅仅代表100.00美元兑100,00美元,而且可能还涉及货币转换。
  • 多元化;一个区域gettext仍然节拍node-localize是在给定数字来复数时正确复数单词的能力。

许可证(MIT)

版权所有(C)2011 by Agrosica,Inc.,David Ellis,FelixGeisendörfer,Steven Levithan,Scott Trenda,Kris Kowal,Jerry Jalava,Clint Andrew Hall。

特此授予任何获得副本的人免费许可 这个软件和相关的文档文件(“软件”),来处理 在软件中没有限制,包括但不限于权利 使用,复制,修改,合并,发布,分发,再许可和/或出售 本软件的副本,并允许软件所在的人员 在这样做的情况下,符合以下条件:

上述版权声明和本许可声明应包括在内 本软件的所有副本或重要部分。

本软件按“原样”提供,不提供任何形式的保证,或者 暗示,包括但不限于适销性保证, 适用于特定用途和不侵权的适用性。在任何情况下都不应该 作者或版权所有者对任何索赔,损害或其他责任均有责任 无论是合同,侵权行为还是其他行为,由此产生的责任, 在软件或使用或其他交易中的或与之相关的 软件。

本文使用googletrans自动翻译,仅供参考, 原文来自github.com

en_README.md

The node-localize library

provides a GNU gettext-inspired (but not conformant) translation utility for Node.js that tries to avoid some of the limitations of the sprintf-bound gettext (such as translation string parameters being in a fixed order in all translation results) and "fit in" better than a straight port.

Installation

If you have npm, just type:

npm install localize

Usage

node-localize returns an object constructor so multiple simultaneous localization objects may be in use at once (though most cases will probably be a singleton instantiation). The only required parameter on initialization is a translations object, using the following structure:

var Localize = require('localize');

var myLocalize = new Localize({
    "Testing...": {
        "es": "Pruebas...",
        "sr": "тестирање..."
    },
    "Substitution: $[1]": {
        "es": "Sustitución: $[1]",
        "sr": "замена: $[1]"
    }
});

console.log(myLocalize.translate("Testing...")); // Testing...
console.log(myLocalize.translate("Substitution: $[1]", 5)); // Substitution: 5

myLocalize.setLocale("es");
console.log(myLocalize.translate("Testing...")); // Pruebas...

myLocalize.setLocale("sr");
console.log(myLocalize.translate("Substitution: $[1]", 5)); // замена: 5

node-localize objects can also be passed a string indicating the directory a translations.json file can be found. This directory is searched recursively for all translations.json files in all subdirectories, and their contents combined together, so you can organize your translations as you wish.

The directory is also searched recursively for directories named translations. These directories are checked for special text files of the form varname.txt, varname.es.txt, varname.sr.txt, etc. The text in varname.txt is treated as the default language of the application and the varname.xx.txt are treated as translations of the text. A special strings object is created where the varname becomes a property of that object and the default language text is the value of the property. So you can also do the following:

var Localize = require('localize');

var myLocalize = new Localize('./path/to/text/files/');

console.log(myLocalize.translate(myLocalize.strings.reallyLongText); // The contents of ./path/to/text/files/translations/reallyLongText.txt, if it exists

myLocalize.setLocale("es");
console.log(myLocalize.translate(myLocalize.strings.reallyLongText); // The contents of ./path/to/text/files/translations/reallyLongText.es.txt, if it exists

Dates

Because date formats differ so wildly in different languages and these differences cannot be solved via simple substitution, there is also a localDate method for translating these values.

var theDate = new Date("4-Jul-1776");
var dateLocalize = new Localize("./translations");
dateLocalize.loadDateFormats({
    "es": {
        dayNames: [
            'Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb',
            'Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'
        ],
        monthNames: [
            'Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic',
            'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'
        ],
        masks: {
            "default": "dddd, d 'de' mmmm yyyy"
        }
    }
});

console.log(dateLocalize.localDate(theDate)); // Thu Jul 04 1776 00:00:00
console.log(dateLocalize.localDate(theDate, "fullDate")); // Thursday, July 4, 1776
console.log(dateLocalize.localDate(theDate, "mm/dd/yyyy")); // 07/04/1776

dateLocalize.setLocale("es");
console.log(dateLocalize.localDate(theDate)); // Jueves, 4 de Julio 1776

The date formatting rules and configuration have been taken from node-dateformat, which has been extended to support multiple simultaneous locales and subsumed into node-localize.

Complete API

var myLocalize = new Localize(translationsObjOrStr, dateFormatObj, defaultLocaleStr);
// translationsObjOrStr: a conformant translations object or a string indicating
//     the directory where one or more conformant translations.json files are stored
// dateFormatObj: a conformant date format object, containing one or more locales
//     if not specified, will auto-generate an 'en' locale; if initially specified,
//     will *overwrite* this auto-generated locale object
// defaultLocale: the locale of all keys in the translations object. Defaults to 'en'
myLocalize.setLocale(localeStr);
// localeStr: a locale string to switch to
myLocalize.loadTranslations(translationsObjOrStr);
// translationsObjOrStr: a conformant translations object or a string indicating
//     the directory where one or more conformant translations.json files are stored
//     Multiple calls to loadTranslations *appends* the keys to the translations
//     object in memory (overwriting duplicate keys).
myLocalize.getTranslations(translationsArrOrUndef);
// translationsArrOrUndef: an array of untranslated text whose translations you want
// to acquire, or leave it undefined for the entire internal translations object
myLocalize.clearTranslations();
// Wipes out the translations object entirely (if a clean reload is desired)
myLocalize.throwOnMissingTranslation(throwBool);
// throwBool: Boolean indicating whether or not missing translations should
//     throw an error or be silently ignored and the text stay in the default
//     locale. Useful for development to turn off.
myLocalize.translate(translateStr, arg1, arg2, ...);
// translateStr: The string to be translated and optionally perform a
//     substitution of specified args into. Arguments are specified in a RegExp
//     style by number starting with 1 (it is the first argument that can be
//     used and also is the arguments[1] value...), while using a jQuery-style
//     demarcation of $[x], where x is the argument number.
myLocalize.loadDateFormats(dateFormatObj);
// dateFormatObj: a conformant date format object, containing one or more locales
//     Specified locales are appended to the internal object just like
//     loadTranslations.
myLocalize.getDateFormats();
// Returns the internal date formats object.
myLocalize.clearDateFormats();
// Resets the date formats object to just the 'en' locale.
myLocalize.localDate(dateObjOrStr, maskStr, utcBool)
// dateObjOrStr: the date object or string to format as desired in the current
//     locale.
// maskStr: the predefined mask to use, or a custom mask.
// utcBool: a boolean indicating whether the timezone should be local or UTC
myLocalize.strings
// Object of key-value pairs defined by files in ``translations`` directories
// Key is the filename (sans extension) and value is the default language
// text. Useful for translating very large blocks of text that shouldn't really
// exist in code.

xlocalize CLI Utility

Starting at version 0.2.0, node-localize, when installed via NPM, adds an xlocalize utility command to the PATH, which allows for automatic construction of translations.json files (and can be re-run in the future to update existing files without clobbering any current translations present). It's command switches are as follows:

xlocalize USAGE:

-l  Set the default language for the translations.json file(s) (default: en)
-r  Set xlocalize to generate translations.json files recursively (default)
-R  Set xlocalize to only generate a translations.json file for the current directory
-e  Set the file extensions to include for translation (default: html,js)
-t  Set the languages to translate to (comma separated)
-h  Show this help message.

For example, to create a translations.json file in the current directory only that will translate from English to Spanish, Portuguese, Italian, and French for HTML and JS files:

xlocalize -R -t es,pt,it,fr

And if a new language, such as Serbian, is to be translated at a later time, you can use the command:

xlocalize -R -t es,pt,it,fr,sr

Express Integration Tips

If your website supports multiple languages (probably why you're using this library!), you'll want to translate the page content for each supported language. The following snippets of code should make it easy to use within Express.

Middleware to switch locale on request

app.configure(function() {
    ...
    app.use(function(request, response, next) {
        var lang = request.session.lang || "en";
        localize.setLocale(lang);
        next();
    });
    ...
});

I'm assuming you're storing their language preference inside of a session, but the logic can be easily tweaked for however you detect which language to show.

Export translate, localDate, and strings as static helpers

app.helpers({
    ...
    translate: localize.translate,
    localDate: localize.localDate,
    strings: localize.strings
});

Your controllers shouldn't really even be aware of any localization issues; the views should be doing that, so this ought to be enough configuration within your app.js file.

Using translate, localDate, and strings in your views

<h1>${translate("My Awesome Webpage")}</h1>

<h2>${translate("By: $[1]", webpageAuthor)}</h2>

<h3>${translate("Published: $[1]", localDate(publicationDate))}</h3>

{{if translate(strings.reallyLongPost) == strings.reallyLongPost}}
<strong>${translate("Warning: The following content is in English.")}</strong>
{{/if}}

{{html translate(strings.reallyLongPost)}}

I'm using jQuery Templates for Express here, but it should be easy to translate to whatever templating language you prefer.

Easy exporting of node-localize library to client without copying library into own source

Since node-localize can also run inside of the browser, and so can jQuery Templates, it can be quite useful to be able to export the library to the client. But rather than manually copying the library code into your website (and keeping track of updates/bugfixes manually), you can get the source code of node-localize directly from the library and add an Express route for it:

app.get('/js/localize.js', function(req, res) {
    res.send(Localize.source);
});

Where Localize is equivalent to require('localize'), not an instantiated localize object.

If you're using node-localize on the client in this fashion, it would be wise to add getTranslations and getDateFormats to the app.helpers object, so views can specify which translations and date formatting they need the client to have to function properly.

Planned Features

  • Optional Country Code support (that falls back to baseline language translation if a specific country code is missing) for regional language differences
  • Numeric localization (1,234,567.89 versus 1.234.567,89 versus 1 234 567,89 versus Japanese Numerals [no idea how to handle that one at the moment])
  • Currency localization; not just representing $100.00 versus 100,00$, but perhaps hooking into currency conversion, as well.
  • Pluralization; one area gettext still beats node-localize is the ability to pluralize words correctly when given the number to pluralize against.

License (MIT)

Copyright (C) 2011 by Agrosica, Inc, David Ellis, Felix Geisendörfer, Steven Levithan, Scott Trenda, Kris Kowal, Jerry Jalava, Clint Andrew Hall.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.