2
* Babel JavaScript Support
4
* Copyright (C) 2008 Edgewall Software
7
* This software is licensed as described in the file COPYING, which
8
* you should have received as part of this distribution. The terms
9
* are also available at http://babel.edgewall.org/wiki/License.
11
* This software consists of voluntary contributions made by many
12
* individuals. For the exact contribution history, see the revision
13
* history and logs, available at http://babel.edgewall.org/log/.
17
* A simple module that provides a gettext like translation interface.
18
* The catalog passed to load() must be a object conforming to this
22
* messages: an object of {msgid: translations} items where
23
* translations is an array of messages or a single
24
* string if the message is not pluralizable.
25
* plural_expr: the plural expression for the language.
26
* locale: the identifier for this locale.
27
* domain: the name of the domain.
30
* Missing elements in the object are ignored.
34
* var translations = babel.Translations.load(...).install();
36
var babel = new function() {
38
var defaultPluralExpr = function(n) { return n == 1 ? 0 : 1; };
39
var formatRegex = /%?%(?:\(([^\)]+)\))?([disr])/g;
42
* A translations object implementing the gettext interface
44
var Translations = this.Translations = function(locale, domain) {
46
this.locale = locale || 'unknown';
47
this.domain = domain || 'messages';
48
this.pluralexpr = defaultPluralExpr;
52
* Create a new translations object from the catalog and return it.
53
* See the babel-module comment for more details.
55
Translations.load = function(catalog) {
56
var rv = new Translations();
61
Translations.prototype = {
63
* translate a single string.
65
gettext: function(string) {
66
var translated = this.messages[string];
67
if (typeof translated == 'undefined')
69
return (typeof translated == 'string') ? translated : translated[0];
73
* translate a pluralizable string
75
ngettext: function(singular, plural, n) {
76
var translated = this.messages[singular];
77
if (typeof translated == 'undefined')
78
return (n == 1) ? singular : plural;
79
return translated[this.pluralexpr(n)];
83
* Install this translation document wide. After this call, there are
84
* three new methods on the window object: _, gettext and ngettext
88
window._ = window.gettext = function(string) {
89
return self.gettext(string);
91
window.ngettext = function(singular, plural, n) {
92
return self.ngettext(singular, plural, n);
98
* Works like Translations.load but updates the instance rather
99
* then creating a new one.
101
load: function(catalog) {
102
if (catalog.messages)
103
this.update(catalog.messages)
104
if (catalog.plural_expr)
105
this.setPluralExpr(catalog.plural_expr);
107
this.locale = catalog.locale;
109
this.domain = catalog.domain;
114
* Updates the translations with the object of messages.
116
update: function(mapping) {
117
for (var key in mapping)
118
if (mapping.hasOwnProperty(key))
119
this.messages[key] = mapping[key];
124
* Sets the plural expression
126
setPluralExpr: function(expr) {
127
this.pluralexpr = new Function('n', 'return +(' + expr + ')');
133
* A python inspired string formatting function. Supports named and
134
* positional placeholders and "s", "d" and "i" as type characters
135
* without any formatting specifications.
139
* babel.format(_('Hello %s'), name)
140
* babel.format(_('Progress: %(percent)s%%'), {percent: 100})
142
this.format = function() {
143
var arg, string = arguments[0], idx = 0;
144
if (arguments.length == 1)
146
else if (arguments.length == 2 && typeof arguments[1] == 'object')
150
for (var i = 1, n = arguments.length; i != n; ++i)
151
arg[i - 1] = arguments[i];
153
return string.replace(formatRegex, function(all, name, type) {
154
if (all[0] == all[1]) return all.substring(1);
155
var value = arg[name || idx++];
156
return (type == 'i' || type == 'd') ? +value : value;