-
Notifications
You must be signed in to change notification settings - Fork 821
/
i18n.js
231 lines (201 loc) · 5.96 KB
/
i18n.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
if(typeof(ss) == 'undefined') ss = {};
/*
* Lightweight clientside i18n implementation.
* Caution: Only available after DOM loaded because we need to detect the language
*
* For non-i18n stub implementation, see sapphire/javascript/i18nx.js
*
* Based on jQuery i18n plugin: 1.0.0 Feb-10-2008
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
* Based on 'javascript i18n that almost doesn't suck' by markos
* http://markos.gaivo.net/blog/?p=100
*/
ss.i18n = {
currentLocale: null,
defaultLocale: 'en_US',
lang: {},
inited: false,
init: function() {
if(this.inited) return;
this.currentLocale = this.detectLocale();
this.inited = true;
},
/**
* set_locale()
* Set locale in long format, e.g. "de_AT" for Austrian German.
* @param string locale
*/
setLocale: function(locale) {
this.currentLocale = locale;
},
/**
* getLocale()
* Get locale in long format. Falls back to i18n.defaut_locale.
* @return string
*/
getLocale: function() {
return (this.currentLocale) ? this.currentLocale : this.defaultLocale;
},
/**
* _()
* The actual translation function. Looks the given string up in the
* dictionary and returns the translation if one exists. If a translation
* is not found, returns the original word
*
* @param string entity A "long" locale format, e.g. "de_DE" (Required)
* @param string fallbackString (Required)
* @param int priority (not used)
* @param string context Give translators context for the string
* @return string : Translated word
*
*/
_t: function (entity, fallbackString, priority, context) {
this.init();
if (this.lang && this.lang[this.getLocale()] && this.lang[this.getLocale()][entity]) {
return this.lang[this.getLocale()][entity];
} else if (this.lang && this.lang[this.defaultLocale] && this.lang[this.defaultLocale][entity]) {
return this.lang[this.defaultLocale][entity];
} else if(fallbackString) {
return fallbackString;
} else {
return '';
}
},
/**
* Add entities to a dictionary. If a dictionary doesn't
* exist for this locale, its automatically created.
* Existing entities are overwritten.
*
* @param string locale
* @param Object dict
*/
addDictionary: function(locale, dict) {
if(!this.lang[locale]) this.lang[locale] = {};
for(entity in dict) {
this.lang[locale][entity] = dict[entity];
}
},
/**
* Get dictionary for a specific locale.
*
* @param string locale
*/
getDictionary: function(locale) {
return this.lang[locale];
},
/**
* stripStr()
*
* @param string str : The string to strip
* @return string result : Stripped string
*
*/
stripStr: function(str) {
return str.replace(/^\s*/, "").replace(/\s*$/, "");
},
/**
* stripStrML()
*
* @param string str : The multi-line string to strip
* @return string result : Stripped string
*
*/
stripStrML: function(str) {
// Split because m flag doesn't exist before JS1.5 and we need to
// strip newlines anyway
var parts = str.split('\n');
for (var i=0; i<parts.length; i++)
parts[i] = stripStr(parts[i]);
// Don't join with empty strings, because it "concats" words
// And strip again
return stripStr(parts.join(" "));
},
/*
* printf()
* C-printf like function, which substitutes %s with parameters
* given in list. %%s is used to escape %s.
*
* Doesn't work in IE5.0 (splice)
*
* @param string S : string to perform printf on.
* @param string L : Array of arguments for printf()
*/
sprintf: function(S) {
if (arguments.length == 1) return S;
var nS = "";
var tS = S.split("%s");
var args = [];
for (var i=1, len = arguments.length; i <len; ++i) {
args.push(arguments[i]);
};
for(var i=0; i<args.length; i++) {
if (tS[i].lastIndexOf('%') == tS[i].length-1 && i != args.length-1)
tS[i] += "s"+tS.splice(i+1,1)[0];
nS += tS[i] + args[i];
}
return nS + tS[tS.length-1];
},
/**
* Detect document language settings by looking at <meta> tags.
* If no match is found, returns this.defaultLocale.
*
* @todo get by <html lang=''> - needs modification of SSViewer
*
* @return string Locale in mixed lowercase/uppercase format suitable
* for usage in ss.i18n.lang arrays (e.g. 'en_US').
*/
detectLocale: function() {
var rawLocale;
var detectedLocale;
// get by container tag
rawLocale = jQuery('body').attr('lang');
// get by meta
if(!rawLocale) {
var metas = document.getElementsByTagName('meta');
for(var i=0; i<metas.length; i++) {
if(metas[i].attributes['http-equiv'] && metas[i].attributes['http-equiv'].nodeValue.toLowerCase() == 'content-language') {
rawLocale = metas[i].attributes['content'].nodeValue;
}
}
}
// fallback to default locale
if(!rawLocale) rawLocale = this.defaultLocale;
var rawLocaleParts = rawLocale.match(/([^-|_]*)[-|_](.*)/);
// get locale (e.g. 'en_US') from common name (e.g. 'en')
// by looking at ss.i18n.lang tables
if(rawLocale.length == 2) {
for(compareLocale in ss.i18n.lang) {
if(compareLocale.substr(0,2).toLowerCase() == rawLocale.toLowerCase()) {
detectedLocale = compareLocale;
break;
}
}
} else if(rawLocaleParts) {
detectedLocale = rawLocaleParts[1].toLowerCase() + '_' + rawLocaleParts[2].toUpperCase();
}
return detectedLocale;
},
/**
* Attach an event listener to the given object.
* Modeled after behaviour.js, but externalized
* to keep the i18n library standalone for now.
*/
addEvent: function(obj, evType, fn, useCapture){
if (obj.addEventListener){
obj.addEventListener(evType, fn, useCapture);
return true;
} else if (obj.attachEvent){
var r = obj.attachEvent("on"+evType, fn);
return r;
} else {
alert("Handler could not be attached");
}
}
};
ss.i18n.addEvent(window, "load", function() {
ss.i18n.init();
});