-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathjquery.jsperanto.js
167 lines (150 loc) · 6.1 KB
/
jquery.jsperanto.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
//jquery 1.4 dependencies : $.each, $.extend, $.ajax, $.isFunction, $.isPlainObject
// Uses CommonJS, AMD or browser globals to create a jQuery extension.
(function (factory) {
if (typeof exports === 'object') {
// Node/CommonJS
factory(require('jquery'));
} else if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else {
// Browser globals
factory(jQuery);
}
}(function($) {
var o = {};
var dictionary = false; //not yet loaded
var currentLang = false;
var count_of_replacement = 0;
function init(callback,options){
options = $.isPlainObject(options) ? options : callback;
callback = $.isFunction(callback) ? callback : function(){};
$.extend(o,{
//defaults
interpolationPrefix : '__',
interpolationSuffix : '__',
pluralSuffix : '_plural',
getSuffixMethod : function(count){ return ( count > 1 || typeof(count) == "string" ) ? o.pluralSuffix : ""; },
maxRecursion : 50, //used while applying reuse of strings to avoid infinite loop
reusePrefix : "$t(",
reuseSuffix : ")",
fallbackLang : 'en-us', // see Language fallback section
dicoPath : 'locales', // see Dictionary section
async : true, // might be used to force initialization, dictionary loading to be syncronous
keyseparator : ".", // keys passed to $.jsperanttranslate use this separator
setDollarT : true, // $.t aliases $.jsperanttranslate, nice shortcut
dictionary : false, // to supply the dictionary instead of loading it using $.ajax. A (big) javascript object containing your namespaced translations
lang : false, //specify a language to use
suffixNotFound : ["suffix_not_found_", Math.random()].join('') // used internally by translate
},options);
if(!o.lang){o.lang = detectLanguage();}
return loadDictionary(o.lang,function(loadedLang){
currentLang = loadedLang;
if(o.setDollarT){$.t = $.t || translate;} //shortcut
if(callback) callback(translate);
});
}
function applyReplacement(string,replacementHash){
$.each(replacementHash,function(key,value){
string = string.split([o.interpolationPrefix,key,o.interpolationSuffix].join('')).join(value);
});
return string;
}
function applyReuse(translated,options){
while (translated.indexOf(o.reusePrefix) != -1){
count_of_replacement++;
if(count_of_replacement > o.maxRecursion){break;} // safety net for too much recursion
var index_of_opening = translated.indexOf(o.reusePrefix);
var index_of_end_of_closing = translated.indexOf(o.reuseSuffix,index_of_opening) + o.reuseSuffix.length;
var token = translated.substring(index_of_opening,index_of_end_of_closing);
var token_sans_symbols = token.replace(o.reusePrefix,"").replace(o.reuseSuffix,"");
var translated_token = _translate(token_sans_symbols,options);
translated = translated.replace(token,translated_token);
}
return translated;
}
function detectLanguage(){
if(navigator){
return navigator.language && navigator.language.toLocaleLowerCase() || navigator.userLanguage && navigator.userLanguage.toLocaleLowerCase();
}else{
return o.fallbackLang;
}
}
function containsCount(options){
return (typeof options.count == 'number' || typeof options.count == 'string');
}
function getCountSuffix(options) {
var suffix = o.getSuffixMethod(options.count);
return ( typeof(suffix) == "string" ) ? suffix : '';
}
function translate(dottedkey,options){
count_of_replacement = 0;
return _translate(dottedkey,options);
}
/*
options.defaultValue
options.count
*/
function _translate(dottedkey,options){
options = options || {};
var notfound = options.defaultValue || dottedkey;
if(!dictionary){return notfound;} // No dictionary to translate from
if(containsCount(options)){
var optionsSansCount = $.extend({},options);
delete optionsSansCount.count;
optionsSansCount.defaultValue = o.suffixNotFound;
var suffixKey = dottedkey + getCountSuffix(options);
var translated = translate(suffixKey,optionsSansCount);
if(translated != o.suffixNotFound){
return applyReplacement(translated,{count:options.count});//apply replacement for count only
}// else continue translation with original/singular key
}
var keys = dottedkey.split(o.keyseparator);
var i = 0;
var value = dictionary;
while(keys[i]) {
value = value && value[keys[i]];
i++;
}
if(value){
value = applyReplacement(value,options);
value = applyReuse(value,options);
return value;
}else{
return notfound;
}
}
function loadDictionary(lang,doneCallback){
if(o.dictionary){
dictionary = o.dictionary;
doneCallback(lang);
return;
}
return $.ajax({
url: [o.dicoPath,"/", lang, '.json'].join(''),
success: function(data,status,xhr){
dictionary = data;
doneCallback(lang);
},
error : function(xhr,status,error){
if(lang != o.fallbackLang){
loadDictionary(o.fallbackLang,doneCallback);
}else{
doneCallback(false);
}
},
async : o.async,
dataType: "json"
});
}
function lang(){
return currentLang;
}
$.jsperanto = $.jsperanto || {
init:init,
t:translate,
translate:translate,
detectLanguage : detectLanguage,
lang : lang
};
}));