-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathExt.ux.Localizer.js
308 lines (289 loc) · 10.5 KB
/
Ext.ux.Localizer.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
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
/**
* Allow for language change after language change after language change etc.
* Go back to original language using initialConfig
* Localizable grid values through column renderers!
* When components need tooltips, I usually add them as a tip property to the same component. That tooltip can be translated as well.
* Prevention against word wraps after translation that I have seen occuring.
* renamed locale file to js, because IIS for example can't read .json files by default. (just to make it easy to test run this)
* Most of my comments and changes are described in the commits and code. Code is mostly equal to what ssamayoa has posted.
* This is work in progress and needs further optimization. Specially in the area of configurability.
*
* @author Sergio Samayoa (creator) http://www.sencha.com/forum/showthread.php?182631-Different-languages-Translations&p=797073&viewfull=1#post797073
* @author Christiaan Westerbeek (contributor)
* @see http://www.sencha.com/forum/showthread.php?182631-Different-languages-Translations&p=797073&viewfull=1#post797073
*/
Ext.define("Ext.ux.Localizer", {
singleton : true,
baseLocale : "en",
currLocale : "en",
/**
* @private (Object) localizableProps
* Localizable properties for each xtype.
*/
localizableProps : {
// Ext.button
button : ["text", "tooltip"],
// Ext.form.field
checkboxfield : ["fieldLabel", "boxLabel"],
field : ["fieldLabel"],
filefield : ["fieldLabel", "buttonText"],
radiofield : ["fieldLabel", "boxLabel"],
// Ext.form
checkboxgroup : ["fieldLabel"],
fieldcontainer : ["fieldLabel"],
fieldset : ["title"],
label : ["text"],
// Ext.grid
gridcolumn : ["text"],
panel : ["title"],
tooltip: ["html"],
image: ["src"]
},
/**
* @private (Array) localizableColumns
* Localizable grid columns through renderers
*/
localizableColumns: [ //add grid column renderers
"status_description", "bounced"
],
/**
* @private (Array) columnRenderer
* Reusable column renderer function to be applied to every column listed above on translation
*/
columnRenderer: function (value, metaData, record, row, col, store, gridView) {
return Localizer.localeStrings.get(value)||value;
},
/**
* @private (Object) excludeTypes
* XTypes to be excluded by localize() method.
* If whole xtype must be exclude, assign a boolean value of "false".
* If some itemId must be excluded, assign an array of itemId names.
*/
excludeTypes : {
pagingtoolbar : {
itemIds : ["first", "prev", "inputItem", "afterTextItem", "next", "last", "refresh", "displayItem"]
}
},
/**
* Returns the xtypes if comp as array.
* @param (AbstractComponent) comp
* @return (String []) xtypes of the component
*/
getXTypes : function(comp) {
if (!comp) {
return [];
}
try {
return comp.getXTypes().split("/").reverse();
} catch(e) {
return [];
}
},
/**
* @param (String[]) xtypes
* @return (Boolean)
*/
isExcludeByXType: function(xtypes) {
var me = this, exclude = false;
Ext.each(xtypes, function(xtype) {
var e = me.excludeTypes [xtype];
if (Ext.isBoolean(e) && e === true) {
exclude = true;
return false;
}
});
return exclude;
},
/**
* @param (Container) ownertCt
*/
getItemIdsToExclude: function(ownerCt) {
if (!ownerCt) {
return [];
}
var me = this,
xtypes = me.getXTypes(ownerCt),
itemIds = [];
Ext.each(xtypes, function(xtype) {
var e = me.excludeTypes [xtype];
if (Ext.isArray(e)) {
itemIds = e;
return false;
}
});
return itemIds;
},
getLocalizableProps : function(xtypes) {
var me = this,
localizableProps;
Ext.each(xtypes, function(xtype) {
localizableProps = me.localizableProps [xtype];
if (localizableProps) {
return false;
}
});
return localizableProps;
},
/**
* @private
*/
localize2 : function(comp, localizeChildren) {
var me = this, xtypes = me.getXTypes(comp);
// Do we have to exclude by xtype?
if (me.isExcludeByXType(xtypes)) {
return;
}
// If comp has an itemId, do we have to exclude by itemId?
if (comp.itemId) {
var itemsToExclude = me.getItemIdsToExclude(comp.ownerCt);
if (Ext.Array.contains(itemsToExclude, comp.itemId)) {
return;
}
}
// Do we have to localizeChildren?
if (localizeChildren) {
//console.log(comp);
if (comp.items && comp.items.each) { //actioncolumn items is a real array en doesn't have each. For now, I just skip it.
comp.items.each(function(c) {
me.localize2(c, localizeChildren);
});
}
if (comp.dockedItems) {
Ext.each(comp.dockedItems.items, function(c) {
me.localize2(c, localizeChildren);
});
}
if (comp.tip) {
//So, this is me. When components have tips, I add them as a tip property to the same component.
// that tooltip may need translation as well.
me.localize2(comp.tip, false);
}
}
// This component haves localizable propesties?
var localizableProps = me.getLocalizableProps(xtypes);
if (!localizableProps) {
return;
}
// Lets localize this component
Ext.each(localizableProps, function(localizableProp) {
var capitalized = Ext.String.capitalize(localizableProp);
//first, get the original value of the localizable property
var value = comp.initialConfig [localizableProp];
var replace;
if (me.currLocale!=me.baseLocale) {
if (!value) {
value = comp [localizableProp];
}
if (!value) {
var getFunc = comp ["get" + capitalized];
if (getFunc) {
value = getFunc.call(comp);
}
}
if (!value) {
return;
}
replace = me.localeStrings.get(value);
} else if (me.localeStrings.get(value)!==undefined){
//We're translating back to the baseLocale
// and value is the value from the initialConfig
replace = value;
}
if (!replace) {
return;
}
var setFunc = comp ["set" + capitalized];
replace=replace.replace(/ /g, " "); //This replace prevents against word wraps after translation that I have seen occuring
if (!setFunc) {
comp [localizableProp] = replace;
} else {
setFunc.call(comp, replace);
}
});
// Lets localize this grids column renderers
if (comp instanceof Ext.grid.column.Column && this.localizableColumns && this.localizableColumns.indexOf(comp.dataIndex)>-1) {
comp.renderer=(me.currLocale!=me.baseLocale?me.columnRenderer:false);
}
},
localize : function(comp, locale, localizeChildren) {
// Do we recevived an instance?
var me = this;
if (!comp || !locale) {
return;
}
if (!Ext.isDefined(localizeChildren)) {
localizeChildren = true;
}
// Do we have locale strings for received locale?
me.localeStrings = me.getLocaleStrings(locale);
//Instead of passing the variable 'localStrings' around through several functions, I add 'localStrings' as a property to 'me'.
if (!me.localeStrings) {
return;
}
me.currLocale=locale;
me.localize2(comp, localizeChildren);
},
/**
* @private
*/
loadLocaleStrings: function(locale) {
var me = this, localeStrings;
Ext.Ajax.request({
url : "./app/locale/" + locale + ".js",
async : false,
success : function(response) {
var entries = Ext.decode(response.responseText);
localeStrings = new Ext.util.HashMap();
Ext.each(entries, function(entry) {
localeStrings.add(entry.key, entry.value);
});
me.locales.add(locale, localeStrings);
},
failure : function() {
me.locales.add(locale, false);
localeStrings = false;
}
});
return localeStrings;
},
/**
* @private
*/
getLocaleStrings: function(locale) {
var me = this, localeStrings;
if (!me.locales) {
me.locales = new Ext.util.HashMap();
}
if (!me.locales.get(locale)) {
localeStrings = me.loadLocaleStrings(locale);
} else {
localeStrings = me.locales.get(locale);
}
if (Ext.isBoolean(localeStrings) && !localeStrings) {
// If locale key contains "false" we
// tried to load the locale file before
// but failed.
return;
}
return localeStrings;
},
getLocalizedString: function(key, locale) {
var me = this;
if (!key || !locale) {
return key;
}
var localeStrings = me.getLocaleStrings(locale);
if (!localeStrings) {
return key;
}
var localized = localeStrings.get(key);
if (!localized) {
return key;
}
return localized;
}
});
Localizer = Ext.ux.Localizer;
_ = function(key, locale) {
return Localizer.getLocalizedString(key, locale);
}