PageSourceSearch

https://rickvanderzwet.nl/trac/briareus/chrome/common/js/babel.js

js rickvanderzwet.nl collected 2026-09-25 20:42:14 UTC 6,923 bytes, 229 lines download raw bytes

1/**
2 * Babel JavaScript Support
3 *
4 * Copyright (C) 2008 Edgewall Software
5 * All rights reserved.
6 *
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.
10 *
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/.
14 */
15
16/**
17 * A simple module that provides a gettext like translation interface.
18 * The catalog passed to load() must be a object conforming to this
19 * interface::
20 *
21 *    {
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.
28 *    }
29 *
30 * Missing elements in the object are ignored.
31 *
32 * Typical usage::
33 *
34 *    var translations = babel.Translations.load(...).install();
35 */
36var babel = new function() {
37
38  var defaultPluralExpr = function(n) { return n == 1 ? 0 : 1; };
39  var formatRegex = /%(?:(?:\(([^\)]+)\))?([disr])|%)/g;
40  var translations = {};
41  var merged;
42
43  /**
44   * A translations object implementing the gettext interface
45   */
46  var Translations = this.Translations = function(locale, domain) {
47    this.messages = {};
48    this.locale = locale || 'unknown';
49    this.domain = domain || 'messages';
50    this.pluralexpr = defaultPluralExpr;
51  };
52
53  /**
54   * Create a new translations object from the catalog and return it.
55   * See the babel-module comment for more details.
56   */
57  Translations.load = function(catalog) {
58    var rv = new Translations();
59    rv.load(catalog);
60    translations[rv.domain] = rv;
61    merged.load(catalog);
62    return rv;
63  };
64
65  /**
66   * Get a Translations instance from the loaded translations. If the
67   * specified domain doesn't exist, returns a dummy Translations
68   * instance.
69   */
70  Translations.get = function(domain) {
71    return translations[domain] || (new Translations({domain: domain}));
72  };
73
74  Translations.prototype = {
75    /**
76     * translate a single string
77     *
78     * If extra parameters are given, use them to fill the format
79     * specified by the string.
80     */
81    gettext: function(string) {
82      var translated = this.messages[string];
83      if (typeof translated == 'undefined')
84        translated = string;
85      else if (typeof translated != 'string')
86        translated = translated[0];
87      if (arguments.length > 1) {
88        arguments[0] = translated;
89        return babel.format.apply(this, arguments);
90      }
91      return translated;
92    },
93
94    /**
95     * translate a pluralizable string
96     *
97     * If extra parameters are given, use them to fill the format
98     * specified by the string.
99     */
100    ngettext: function(singular, plural, n) {
101      var translated = this.messages[singular];
102      if (typeof translated == 'undefined')
103        translated = (n == 1) ? singular : plural;
104      else
105        translated = translated[this.pluralexpr(n)];
106      if (arguments.length > 3) {
107        var format_args = Array.prototype.slice.call(arguments, 3);
108        format_args.unshift(translated);
109        return babel.format.apply(this, format_args)
110      }
111      return translated;
112    },
113
114    /**
115     * Install this translation document wide.  After this call, there are
116     * three new methods on the window object: _, gettext and ngettext
117     */
118    install: function() {
119      window._ = window.gettext = function() {
120        return merged.gettext.apply(merged, arguments);
121      };
122      window.ngettext = function(singular, plural, n) {
123        return merged.ngettext.apply(merged, arguments);
124      };
125      return this;
126    },
127
128    /**
129     * Works like Translations.load but updates the instance rather
130     * then creating a new one.
131     */
132    load: function(catalog) {
133      if (catalog.messages)
134        this.update(catalog.messages)
135      if (catalog.plural_expr)
136        this.setPluralExpr(catalog.plural_expr);
137      if (catalog.locale)
138        this.locale = catalog.locale;
139      if (catalog.domain)
140        this.domain = catalog.domain;
141      return this;
142    },
143
144    /**
145     * Updates the translations with the object of messages.
146     */
147    update: function(mapping) {
148      for (var key in mapping)
149        if (mapping.hasOwnProperty(key))
150          this.messages[key] = mapping[key];
151      return this;
152    },
153
154    /**
155     * Sets the plural expression
156     */
157    setPluralExpr: function(expr) {
158      this.pluralexpr = new Function('n', 'return +(' + expr + ')');
159      return this;
160    }
161  };
162
163  merged = new Translations({});
164
165  /**
166   * Translate a single string in the specified domain.
167   *
168   * If extra parameters are given, use them to fill the format
169   * specified by the string.
170   */
171  window.dgettext = this.dgettext = function(domain, string) {
172    var rv = translations[domain];
173    var args = Array.prototype.slice.call(arguments, 1);
174    if (typeof rv != 'undefined')
175      return rv.gettext.apply(rv, args);
176    if (arguments.length > 1)
177      return babel.format.apply(this, args);
178    return string;
179  };
180
181  /**
182   * Translate a pluralizable string in the specified domain.
183   *
184   * If extra parameters are given, use them to fill the format
185   * specified by the string.
186   */
187  window.dngettext = this.dngettext = function(domain, singular, plural, n) {
188    var rv = translations[domain];
189    if (typeof rv != 'undefined') {
190      var args = Array.prototype.slice.call(arguments, 1);
191      return rv.ngettext.apply(rv, args);
192    }
193    if (arguments.length > 4) {
194      var args = Array.prototype.slice.call(arguments, 4);
195      args.unshift(singular);
196      return babel.format.apply(this, format_args)
197    }
198    return (n == 1) ? singular : plural;
199  };
200
201  /**
202   * A python inspired string formatting function.  Supports named and
203   * positional placeholders and "s", "d" and "i" as type characters
204   * without any formatting specifications.
205   *
206   * Examples::
207   *
208   *    babel.format(_('Hello %s'), name)
209   *    babel.format(_('Progress: %(percent)s%%'), {percent: 100})
210   */
211  this.format = function() {
212    var arg, string = arguments[0], idx = 0;
213    if (arguments.length == 1)
214      return string;
215    else if (arguments.length == 2 && typeof arguments[1] == 'object')
216      arg = arguments[1];
217    else {
218      arg = [];
219      for (var i = 1, n = arguments.length; i != n; ++i)
220        arg[i - 1] = arguments[i];
221    }
222    return string.replace(formatRegex, function(all, name, type) {
223      if (all == '%%') return '%';
224      var value = arg[name || idx++];
225      return (type == 'i' || type == 'd') ? +value : value;
226    });
227  }
228
229};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.