1 | var gettext = function(translations, pluralfunction) { |
---|
2 | this.catalog = translations; |
---|
3 | this.gettext = function(msgid) { |
---|
4 | var msgstr = this.catalog[msgid]; |
---|
5 | if ('undefined' == typeof(msgstr)) { |
---|
6 | return msgid; |
---|
7 | } |
---|
8 | return msgstr; |
---|
9 | } |
---|
10 | this.ngettext = function(singular, plural, count) { |
---|
11 | /* nobody will have a \0 in their strings (hopefully) */ |
---|
12 | var msgstr = this.catalog[singular+'\0'+plural]; |
---|
13 | if ('undefined' == typeof(msgstr)) { |
---|
14 | if (1 == count) { |
---|
15 | return singular; |
---|
16 | } else { |
---|
17 | return plural; |
---|
18 | } |
---|
19 | } else { |
---|
20 | return msgstr[this.pluralfunction(count)]; |
---|
21 | } |
---|
22 | } |
---|
23 | this.simplepluralfunction = function(count) { |
---|
24 | if (1 == count) { |
---|
25 | return 0; |
---|
26 | } else { |
---|
27 | return 1; |
---|
28 | } |
---|
29 | } |
---|
30 | this.pluralfunction = ('function' == typeof(pluralfunction))? pluralfunction : this.simplepluralfunction; |
---|
31 | this.add = function(additional) { |
---|
32 | for (key in additional) { |
---|
33 | this.catalog[key] = additional[key]; |
---|
34 | } |
---|
35 | } |
---|
36 | } |
---|
37 | |
---|
38 | /** |
---|
39 | * Makes a template subtitute function f(fmt, values), which |
---|
40 | * replaces all indices of values, surrounded by PREFIX and SUFFIX |
---|
41 | * with the corresponding value from VALUES. |
---|
42 | * |
---|
43 | * In FMT, any unwanted placeholders can be escaped by doubling the SUFFIX. |
---|
44 | * |
---|
45 | * NOTE: prefix and suffix should be different! |
---|
46 | * |
---|
47 | * TODO: escape special regex characters from prefix and suffix |
---|
48 | */ |
---|
49 | gettext.formatterBuilder = function(prefix, suffix) { |
---|
50 | var re = new RegExp('(?:'+prefix+'([^'+(prefix==suffix?prefix:prefix+suffix)+']+)'+suffix+')(?!'+suffix+')', 'g'); |
---|
51 | var format = function(fmt, values) { |
---|
52 | var convert = function(whole, name) { |
---|
53 | var sub = values[name]; |
---|
54 | return ('undefined' == typeof(sub))? whole : sub; |
---|
55 | } |
---|
56 | return fmt.replace(re, convert); |
---|
57 | } |
---|
58 | return format; |
---|
59 | } |
---|
60 | gettext.format = gettext.formatterBuilder('{', '}'); |
---|
61 | |
---|
62 | gettext.boundmethod = function(obj, meth) { |
---|
63 | return function() { |
---|
64 | return meth.apply(obj, arguments); |
---|
65 | } |
---|
66 | } |
---|
67 | |
---|
68 | gettext.attribute_escape = function(s) { |
---|
69 | s = s.replace(/&&/g, '&&'); |
---|
70 | s = s.replace(/&&/g, '&&'); |
---|
71 | s = s.replace(/&(?:$|([^#])(?![a-z1-4]{1,8};))/g, '&$1'); |
---|
72 | s = s.replace(/</g, '<'); |
---|
73 | s = s.replace(/>/g, '>'); |
---|
74 | s = s.replace(/"/g, '"'); |
---|
75 | s = s.replace(/'/g, '''); |
---|
76 | return s; |
---|
77 | } |
---|
78 | |
---|
79 | |
---|
80 | String.prototype.format = function(values) { return gettext.format(this, values); } |
---|
81 | String.prototype.attribute_escape = function() { return gettext.attribute_escape(this); } |
---|