b28-cli 1.7.1 → 1.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +13 -13
- package/README.MD +470 -466
- package/TestFile/output/lang/BRPT.json +24 -0
- package/TestFile/output/lang/CN.json +24 -0
- package/TestFile/output/lang/CS.json +24 -0
- package/TestFile/output/lang/DE.json +24 -0
- package/TestFile/output/lang/EN.json +24 -0
- package/TestFile/output/lang/ES.json +24 -0
- package/TestFile/output/lang/FR.json +24 -0
- package/TestFile/output/lang/HU.json +24 -0
- package/TestFile/output/lang/IT.json +24 -0
- package/TestFile/output/lang/KO.json +24 -0
- package/TestFile/output/lang/LAES.json +24 -0
- package/TestFile/output/lang/NL.json +24 -0
- package/TestFile/output/lang/PL.json +24 -0
- package/TestFile/output/lang/PT.json +24 -0
- package/TestFile/output/lang/RO.json +24 -0
- package/TestFile/output/lang/RU.json +24 -0
- package/TestFile/output/lang/TR.json +24 -0
- package/TestFile/output/lang/UK.json +24 -0
- package/TestFile/output/lang/ZH.json +24 -0
- package/TestFile/output/lang/brpt/translate.json +23 -0
- package/TestFile/output/lang/cn/translate.json +23 -0
- package/TestFile/output/lang/cs/translate.json +23 -0
- package/TestFile/output/lang/de/translate.json +23 -0
- package/TestFile/output/lang/es/translate.json +23 -0
- package/TestFile/output/lang/fr/translate.json +23 -0
- package/TestFile/output/lang/hu/translate.json +23 -0
- package/TestFile/output/lang/it/translate.json +23 -0
- package/TestFile/output/lang/ko/translate.json +23 -0
- package/TestFile/output/lang/laes/translate.json +23 -0
- package/TestFile/output/lang/nl/translate.json +23 -0
- package/TestFile/output/lang/pl/translate.json +23 -0
- package/TestFile/output/lang/pt/translate.json +23 -0
- package/TestFile/output/lang/ro/translate.json +23 -0
- package/TestFile/output/lang/ru/translate.json +23 -0
- package/TestFile/output/lang/tr/translate.json +23 -0
- package/TestFile/output/lang/uk/translate.json +23 -0
- package/TestFile/output/lang/zh/translate.json +23 -0
- package/TestFile/output/lang.json +25 -0
- package/b28n.js +739 -739
- package/b28nPigeonhole/11ac_ecos_b28n.js +677 -677
- package/b28nPigeonhole/11ac_linux_b28n_async.js +709 -709
- package/b28nPigeonhole/4G03_b28n_async.js +708 -708
- package/b28nPigeonhole/G5310P_b28n.js +650 -650
- package/b28nPigeonhole/es5b28n.js +711 -711
- package/b28nPigeonhole/es6b28n.js +857 -857
- package/b28nPigeonhole/readMe.md +20 -20
- package/b28nPigeonhole//345/276/256/344/274/201/350/267/257/347/224/261b28n.js +916 -916
- package/dist/ExtractLangExcel.js +138 -45
- package/dist/cmd.js +14 -9
- package/dist/excel2json.js +215 -54
- package/dist/extract/extract-html.js +2 -2
- package/dist/extract/extract-js.js +2 -2
- package/dist/extract/extract-regexp.js +2 -2
- package/dist/extract/extract-vue.js +9 -9
- package/dist/extract/extract.js +4 -4
- package/dist/extract/extractRegexp/index.js +6 -6
- package/dist/extract/vue/html-parser.js +16 -16
- package/dist/extract/vue/util.js +2 -2
- package/dist/extract/vue/vue-compiler.js +2 -2
- package/dist/extractOrigin/extract.js +2 -2
- package/dist/extractOrigin/extract_html_ori.js +2 -2
- package/dist/extractOrigin/extract_js_ori.js +2 -2
- package/dist/handle.js +57 -7
- package/dist/index.js +36 -7
- package/dist/mergeExcel.js +407 -0
- package/dist/mergeJson.js +423 -2
- package/dist/util/config.js +90 -32
- package/dist/util/index.js +48 -41
- package/index.js +5 -5
- package/package.json +63 -62
- package/result.txt +53 -53
- package/test.js +182 -182
|
@@ -1,857 +1,857 @@
|
|
|
1
|
-
(function (window, document) {
|
|
2
|
-
Array.prototype.indexOf =
|
|
3
|
-
Array.prototype.indexOf ||
|
|
4
|
-
function (item) {
|
|
5
|
-
for (let i = 0, l = this.length; i < l; i++) {
|
|
6
|
-
if (this[i] === item) {
|
|
7
|
-
return i;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
return -1;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
Array.prototype.filter =
|
|
14
|
-
Array.prototype.filter ||
|
|
15
|
-
function (cb) {
|
|
16
|
-
let arr = [];
|
|
17
|
-
if (cb && typeof cb === "function") {
|
|
18
|
-
for (let i = 0, l = this.length; i < l; i++) {
|
|
19
|
-
cb(this[i]) && arr.push(this[i]);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
return arr;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
//翻译配置项
|
|
26
|
-
let b28Cfg = {
|
|
27
|
-
/**
|
|
28
|
-
* 支持的语言项,若设置的语言不在配置项中,则显示默认语言
|
|
29
|
-
*/
|
|
30
|
-
supportLang: ["en", "cn"],
|
|
31
|
-
/**
|
|
32
|
-
* 默认语言,若supportLang中没有设置的默认语言,则自动添加到supportLang中去
|
|
33
|
-
*/
|
|
34
|
-
defaultLang: "en",
|
|
35
|
-
/**
|
|
36
|
-
* 配置语言包文件类型 within ["xml", "json"]
|
|
37
|
-
*/
|
|
38
|
-
fileType: "json",
|
|
39
|
-
/**
|
|
40
|
-
* 用默认语言做id
|
|
41
|
-
*/
|
|
42
|
-
idDefaultLang: true,
|
|
43
|
-
/**
|
|
44
|
-
* 是否对要翻译文字进行trim
|
|
45
|
-
*/
|
|
46
|
-
trimText: true,
|
|
47
|
-
/**
|
|
48
|
-
* 默认替换节点中的文字,将其设为true可插入html
|
|
49
|
-
*/
|
|
50
|
-
insertHTML: true,
|
|
51
|
-
/**
|
|
52
|
-
* 是否初始化下拉框
|
|
53
|
-
*/
|
|
54
|
-
initSelect: true,
|
|
55
|
-
/**
|
|
56
|
-
* 时间戳
|
|
57
|
-
*/
|
|
58
|
-
dateStr: new Date().getTime(),
|
|
59
|
-
|
|
60
|
-
langArr: {
|
|
61
|
-
cn: "简体中文",
|
|
62
|
-
zh: "繁體中文",
|
|
63
|
-
de: "Deutsch", //德语
|
|
64
|
-
en: "English", //英语
|
|
65
|
-
es: "Español", //西班牙
|
|
66
|
-
fr: "Français", //法国
|
|
67
|
-
hu: "Magyar", //匈牙利
|
|
68
|
-
it: "Italiano", //意大利
|
|
69
|
-
pl: "Polski", //波兰
|
|
70
|
-
ro: "Română", //罗马尼亚
|
|
71
|
-
ar: "العربية", //阿拉伯
|
|
72
|
-
tr: "Türkçe", //土耳其
|
|
73
|
-
ru: "Русский", //Russian 俄语
|
|
74
|
-
pt: "Português", //Portugal 葡萄牙语
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
let win = window,
|
|
79
|
-
doc = document,
|
|
80
|
-
core_version = "3.0.0",
|
|
81
|
-
core_trim = core_version.trim,
|
|
82
|
-
//获取语言文件相对路径
|
|
83
|
-
js = document.scripts,
|
|
84
|
-
langJs = js[js.length - 1]["src"],
|
|
85
|
-
langPath = langJs.substring(0, langJs.lastIndexOf("/") + 1);
|
|
86
|
-
|
|
87
|
-
/** 工具函数 start */
|
|
88
|
-
//对象浅拷贝
|
|
89
|
-
function extend(oldObj, newObj) {
|
|
90
|
-
if (typeof newObj !== "object") {
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
for (let key in newObj) {
|
|
95
|
-
if (newObj.hasOwnProperty(key)) {
|
|
96
|
-
oldObj[key] = newObj[key];
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
/** 工具函数 end */
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* 创建ajax
|
|
104
|
-
*/
|
|
105
|
-
function createXHR() {
|
|
106
|
-
try {
|
|
107
|
-
return new XMLHttpRequest();
|
|
108
|
-
} catch (e) {
|
|
109
|
-
try {
|
|
110
|
-
return new window.ActiveXObject("Msxml2.XMLHTTP");
|
|
111
|
-
} catch (e) {
|
|
112
|
-
try {
|
|
113
|
-
return new window.ActiveXObject("Microsoft.XMLHTTP");
|
|
114
|
-
} catch (e) {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* 添加文档加载完成后的事件委托
|
|
123
|
-
*/
|
|
124
|
-
let domReady = (function () {
|
|
125
|
-
let funcs = [],
|
|
126
|
-
already = false,
|
|
127
|
-
len,
|
|
128
|
-
i;
|
|
129
|
-
|
|
130
|
-
function handler(e) {
|
|
131
|
-
e = e || win.event;
|
|
132
|
-
if (already) {
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (e.type === "readystatechange" && doc.readyState !== "complete") {
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
for (i = 0, len = funcs.length; i < len; i++) {
|
|
141
|
-
funcs[i].call(doc);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
already = true;
|
|
145
|
-
funcs = null;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (doc.addEventListener) {
|
|
149
|
-
doc.addEventListener("DOMContentLoaded", handler, false);
|
|
150
|
-
doc.addEventListener("onreadystatechange", handler, false);
|
|
151
|
-
win.addEventListener("load", handler, false);
|
|
152
|
-
} else if (doc.attachEvent) {
|
|
153
|
-
doc.attachEvent("onreadystatechange", handler);
|
|
154
|
-
win.attachEvent("onload", handler);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
return function ready(f) {
|
|
158
|
-
if (already) {
|
|
159
|
-
f.call(doc);
|
|
160
|
-
} else {
|
|
161
|
-
funcs.push(f);
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
})();
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* 加载script
|
|
168
|
-
*/
|
|
169
|
-
let loadScript = (function () {
|
|
170
|
-
let scripts = doc.createElement("script"),
|
|
171
|
-
hasReadyState = scripts.readyState;
|
|
172
|
-
|
|
173
|
-
return hasReadyState
|
|
174
|
-
? function (url, callBack) {
|
|
175
|
-
let scripts = doc.createElement("script");
|
|
176
|
-
|
|
177
|
-
scripts.onreadystatechange = function () {
|
|
178
|
-
if (scripts.readyState === "loaded" || scripts.readyState === "complete") {
|
|
179
|
-
scripts.onreadystatechange = null;
|
|
180
|
-
|
|
181
|
-
if (typeof callBack === "function") {
|
|
182
|
-
callBack();
|
|
183
|
-
callBack = null;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
|
-
scripts.src = url;
|
|
188
|
-
doc.getElementsByTagName("head")[0].appendChild(scripts);
|
|
189
|
-
}
|
|
190
|
-
: function (url, callBack) {
|
|
191
|
-
let scripts = doc.createElement("script");
|
|
192
|
-
|
|
193
|
-
scripts.onload = function () {
|
|
194
|
-
if (typeof callBack === "function") {
|
|
195
|
-
callBack();
|
|
196
|
-
callBack = null;
|
|
197
|
-
}
|
|
198
|
-
};
|
|
199
|
-
scripts.src = url;
|
|
200
|
-
doc.getElementsByTagName("head")[0].appendChild(scripts);
|
|
201
|
-
};
|
|
202
|
-
})();
|
|
203
|
-
|
|
204
|
-
// 获取数据文件 并注入到msg中
|
|
205
|
-
let loadData = {
|
|
206
|
-
reload(type, url, callBack) {
|
|
207
|
-
let parseData = type === "json" ? loadData.parseJson : loadData.parseXML,
|
|
208
|
-
request;
|
|
209
|
-
|
|
210
|
-
request = createXHR();
|
|
211
|
-
request.open("GET", url + "?" + Math.random(), false);
|
|
212
|
-
request.send(null);
|
|
213
|
-
|
|
214
|
-
if ((request.status >= 200 && request.status < 300) || request.status === 304) {
|
|
215
|
-
let langData = parseData(request);
|
|
216
|
-
|
|
217
|
-
if (typeof callBack === "function") {
|
|
218
|
-
callBack(langData);
|
|
219
|
-
langData = null;
|
|
220
|
-
callBack = null;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
},
|
|
224
|
-
parseXML(request) {
|
|
225
|
-
let i,
|
|
226
|
-
pos,
|
|
227
|
-
posLen,
|
|
228
|
-
langData = {};
|
|
229
|
-
|
|
230
|
-
pos = request.responseXML.documentElement.getElementsByTagName("message");
|
|
231
|
-
posLen = pos.length;
|
|
232
|
-
|
|
233
|
-
for (i = 0; i < posLen; i++) {
|
|
234
|
-
langData[pos[i].getAttribute("msgid")] = pos[i].getAttribute("msgstr");
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
return langData;
|
|
238
|
-
},
|
|
239
|
-
parseJson(request) {
|
|
240
|
-
return window.JSON.parse(request.responseText) || request.responseText;
|
|
241
|
-
},
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* 去除lang-xx类名,并添加新的类名
|
|
246
|
-
*/
|
|
247
|
-
function handleClass(classname) {
|
|
248
|
-
let name = document.documentElement.className;
|
|
249
|
-
if (name) {
|
|
250
|
-
name = name.split(" ").filter((item) => {
|
|
251
|
-
return !/^lang-/.test(item);
|
|
252
|
-
});
|
|
253
|
-
name.push(classname);
|
|
254
|
-
|
|
255
|
-
document.documentElement.className = name.join(" ");
|
|
256
|
-
} else {
|
|
257
|
-
document.documentElement.className = classname;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* 获取元素的文本内容 或者设置文本内容
|
|
263
|
-
*/
|
|
264
|
-
let innerText = (function () {
|
|
265
|
-
if (b28Cfg.insertHTML) {
|
|
266
|
-
return function (elem, str) {
|
|
267
|
-
elem.innerHTML = str;
|
|
268
|
-
return elem;
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
let element = doc.createElement("p");
|
|
273
|
-
element.innerHTML = core_version;
|
|
274
|
-
return element.textContent
|
|
275
|
-
? function (elem, str) {
|
|
276
|
-
if (str) {
|
|
277
|
-
elem.textContent = str;
|
|
278
|
-
return elem;
|
|
279
|
-
}
|
|
280
|
-
return elem.textContent;
|
|
281
|
-
}
|
|
282
|
-
: function (elem, str) {
|
|
283
|
-
if (str) {
|
|
284
|
-
elem.innerText = str;
|
|
285
|
-
return elem;
|
|
286
|
-
}
|
|
287
|
-
return elem.innerText;
|
|
288
|
-
};
|
|
289
|
-
})();
|
|
290
|
-
|
|
291
|
-
/**
|
|
292
|
-
* 去除字符串首尾空格全兼容
|
|
293
|
-
*/
|
|
294
|
-
function trim(text) {
|
|
295
|
-
if (text == null) {
|
|
296
|
-
return "";
|
|
297
|
-
}
|
|
298
|
-
if (core_trim && !core_trim.call("\uFEFF\xA0")) {
|
|
299
|
-
return core_trim.call(text);
|
|
300
|
-
} else {
|
|
301
|
-
text += "";
|
|
302
|
-
return text.replace(/(^\s*)|(\s*$)/g, "");
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* 根据配置参数决定是否去除空格
|
|
308
|
-
*/
|
|
309
|
-
function _trim(str) {
|
|
310
|
-
return b28Cfg.trimText ? trim(str) : str;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
/**
|
|
314
|
-
* 是否是html元素
|
|
315
|
-
*/
|
|
316
|
-
function assertElement(elem) {
|
|
317
|
-
//支持HTMLElement
|
|
318
|
-
if (typeof HTMLElement === "object" && elem instanceof HTMLElement) {
|
|
319
|
-
return true;
|
|
320
|
-
}
|
|
321
|
-
//ie等
|
|
322
|
-
if (typeof elem === "object" && (elem.nodeType === 1 || elem.nodeType === 9) && typeof elem.nodeName === "string") {
|
|
323
|
-
return true;
|
|
324
|
-
}
|
|
325
|
-
return false;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
/**
|
|
329
|
-
* 判断是否为null,undefined或者空白字符串
|
|
330
|
-
* @param {值} val
|
|
331
|
-
*/
|
|
332
|
-
function notNull(val) {
|
|
333
|
-
return val && /\S/.test(val);
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
/**
|
|
337
|
-
* 寻找子元素中text
|
|
338
|
-
* @param {元素} elem
|
|
339
|
-
*/
|
|
340
|
-
function getTextChild(elem) {
|
|
341
|
-
if (elem) {
|
|
342
|
-
let first = elem.firstChild;
|
|
343
|
-
if (first) {
|
|
344
|
-
if (first.nodeType === 3) {
|
|
345
|
-
return first.nodeValue;
|
|
346
|
-
}
|
|
347
|
-
return getTextChild(first.nextSibling);
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
function htmlEncode(str) {
|
|
353
|
-
var encodeObj = {
|
|
354
|
-
"&": "&",
|
|
355
|
-
"<": "<",
|
|
356
|
-
">": ">",
|
|
357
|
-
"'": "'",
|
|
358
|
-
'"': """,
|
|
359
|
-
" ": " ",
|
|
360
|
-
};
|
|
361
|
-
if (str.length == 0) {
|
|
362
|
-
return "";
|
|
363
|
-
}
|
|
364
|
-
return str.replace(/(&|\s| |<|>|\'|\")/g, function (a) {
|
|
365
|
-
return encodeObj[a];
|
|
366
|
-
});
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
function htmlDecode(str) {
|
|
370
|
-
var decodeObj = {
|
|
371
|
-
"&": "&",
|
|
372
|
-
"<": "<",
|
|
373
|
-
">": ">",
|
|
374
|
-
"'": "'",
|
|
375
|
-
""": '"',
|
|
376
|
-
" ": " ",
|
|
377
|
-
};
|
|
378
|
-
if (str.length == 0) {
|
|
379
|
-
return "";
|
|
380
|
-
}
|
|
381
|
-
return str.replace(/(&|<|>|'|"| )/g, function (a) {
|
|
382
|
-
return decodeObj[a];
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
/** 文本处理相关函数 end */
|
|
386
|
-
|
|
387
|
-
//翻译对象
|
|
388
|
-
function Butterlation(cfg) {
|
|
389
|
-
extend(b28Cfg, cfg);
|
|
390
|
-
|
|
391
|
-
//若所支持的语言中没有默认语言,则将默认语言添加到支持语言数组中
|
|
392
|
-
if (b28Cfg.idDefaultLang && b28Cfg.supportLang.indexOf(b28Cfg.defaultLang) === -1) {
|
|
393
|
-
b28Cfg.supportLang.push(b28Cfg.defaultLang);
|
|
394
|
-
}
|
|
395
|
-
this.curDomain = 0;
|
|
396
|
-
this.domainArr = [];
|
|
397
|
-
this.options = {
|
|
398
|
-
defaultLang: b28Cfg.defaultLang,
|
|
399
|
-
support: b28Cfg.supportLang,
|
|
400
|
-
fileType: b28Cfg.fileType,
|
|
401
|
-
};
|
|
402
|
-
this.langArr = b28Cfg.langArr;
|
|
403
|
-
/**语言包文件是否加载完成标志 */
|
|
404
|
-
this.b28Loaded = false;
|
|
405
|
-
/**当前语言 */
|
|
406
|
-
this.lang = "";
|
|
407
|
-
/**是否记录当前语言用于无刷新翻译页面 */
|
|
408
|
-
this.saveLang = false;
|
|
409
|
-
/**当前语言包信息 */
|
|
410
|
-
this.langData = {};
|
|
411
|
-
/**记录翻译页面前的数据 */
|
|
412
|
-
this.original = {
|
|
413
|
-
title: doc.title,
|
|
414
|
-
};
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
Butterlation.prototype = {
|
|
418
|
-
/**
|
|
419
|
-
* 翻译title
|
|
420
|
-
*/
|
|
421
|
-
transTitle: function (title) {
|
|
422
|
-
doc.title = this.gettext(_trim(title));
|
|
423
|
-
},
|
|
424
|
-
/**
|
|
425
|
-
* 翻译html元素节点
|
|
426
|
-
* @param {object} element
|
|
427
|
-
*/
|
|
428
|
-
replaceTextNodeValue: function (element) {
|
|
429
|
-
if (!element) {
|
|
430
|
-
return;
|
|
431
|
-
}
|
|
432
|
-
if (/^SCRIPT$/i.test(element.tagName)) {
|
|
433
|
-
if (element.nextSibling) {
|
|
434
|
-
this.replaceTextNodeValue(element.nextSibling);
|
|
435
|
-
}
|
|
436
|
-
return;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
let firstChild = element.firstChild,
|
|
440
|
-
nextSibling = element.nextSibling,
|
|
441
|
-
nodeType = element.nodeType,
|
|
442
|
-
btnStr = "submit,reset,button",
|
|
443
|
-
curValue,
|
|
444
|
-
isInputButton,
|
|
445
|
-
oldValue;
|
|
446
|
-
|
|
447
|
-
//handle element node
|
|
448
|
-
if (nodeType === 1) {
|
|
449
|
-
//alt属性
|
|
450
|
-
this.replaceTextNodeAttr("alt", element, "data-o-alt");
|
|
451
|
-
|
|
452
|
-
//placeholder属性
|
|
453
|
-
this.replaceTextNodeAttr("placeholder", element, "data-o-holder");
|
|
454
|
-
|
|
455
|
-
//title属性
|
|
456
|
-
this.replaceTextNodeAttr("title", element, "data-o-title");
|
|
457
|
-
|
|
458
|
-
isInputButton = element.nodeName.toLowerCase() == "input" && btnStr.indexOf(element.getAttribute("type")) !== -1;
|
|
459
|
-
|
|
460
|
-
if (isInputButton) {
|
|
461
|
-
//data-lang属性具有较高优先级
|
|
462
|
-
curValue = element.getAttribute("data-lang") || element.value;
|
|
463
|
-
} else {
|
|
464
|
-
if (element.getAttribute("data-nowrap") === "1") {
|
|
465
|
-
curValue = element.innerHTML;
|
|
466
|
-
} else {
|
|
467
|
-
curValue = element.getAttribute("data-lang");
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
if (curValue && /\S/.test(curValue)) {
|
|
472
|
-
curValue = htmlEncode(curValue);
|
|
473
|
-
if (this.saveLang) {
|
|
474
|
-
let oldText = element.getAttribute("data-o-text");
|
|
475
|
-
if (oldText === undefined || oldText === null) {
|
|
476
|
-
if (element.getAttribute("data-nowrap") === "1") {
|
|
477
|
-
oldText = curValue;
|
|
478
|
-
} else {
|
|
479
|
-
oldText = getTextChild(element);
|
|
480
|
-
notNull(oldText) && (oldText = htmlEncode(oldText));
|
|
481
|
-
}
|
|
482
|
-
oldText = oldText || " ";
|
|
483
|
-
element.setAttribute("data-o-text", oldText);
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
if (this.options.defaultLang === this.lang) {
|
|
487
|
-
curValue = oldText;
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
curValue = htmlDecode(curValue);
|
|
492
|
-
if (curValue) {
|
|
493
|
-
curValue = _trim(curValue);
|
|
494
|
-
if (isInputButton) {
|
|
495
|
-
element.setAttribute("value", this.gettext(curValue));
|
|
496
|
-
} else {
|
|
497
|
-
innerText(element, this.gettext(curValue));
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
//handle textNode
|
|
502
|
-
} else if (nodeType === 3 && notNull(element.nodeValue)) {
|
|
503
|
-
curValue = _trim(element.nodeValue);
|
|
504
|
-
if (this.saveLang) {
|
|
505
|
-
let parNode = element.parentNode;
|
|
506
|
-
oldValue = parNode.getAttribute("data-o-text");
|
|
507
|
-
if (oldValue) {
|
|
508
|
-
curValue = htmlDecode(oldValue);
|
|
509
|
-
} else {
|
|
510
|
-
parNode.setAttribute("data-o-text", htmlEncode(curValue));
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
element.nodeValue = this.gettext(curValue);
|
|
514
|
-
}
|
|
515
|
-
//translate siblings
|
|
516
|
-
if (nextSibling) {
|
|
517
|
-
this.replaceTextNodeValue(nextSibling);
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
//translate firstChild
|
|
521
|
-
//stop handle elem.child if elem has attr data-lang
|
|
522
|
-
if (firstChild && !element.getAttribute("data-lang")) {
|
|
523
|
-
this.replaceTextNodeValue(firstChild);
|
|
524
|
-
}
|
|
525
|
-
},
|
|
526
|
-
/**
|
|
527
|
-
* 翻译html元素节点的属性
|
|
528
|
-
* @param {object} element
|
|
529
|
-
*/
|
|
530
|
-
|
|
531
|
-
replaceTextNodeAttr: function (attr, element, oldAttr) {
|
|
532
|
-
let curValue = element.getAttribute(attr);
|
|
533
|
-
let oldValue = element.getAttribute(oldAttr);
|
|
534
|
-
if (this.saveLang) {
|
|
535
|
-
if (oldValue) {
|
|
536
|
-
curValue = oldValue;
|
|
537
|
-
} else {
|
|
538
|
-
notNull(curValue) && element.setAttribute(oldAttr, curValue);
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
if (notNull(curValue)) {
|
|
542
|
-
curValue = _trim(curValue);
|
|
543
|
-
element.setAttribute(attr, this.gettext(curValue));
|
|
544
|
-
}
|
|
545
|
-
},
|
|
546
|
-
/**
|
|
547
|
-
* 获取语言包信息
|
|
548
|
-
*/
|
|
549
|
-
getMsg: function () {
|
|
550
|
-
return this.langData;
|
|
551
|
-
},
|
|
552
|
-
/**
|
|
553
|
-
* 是否支持该语言
|
|
554
|
-
* @param {string} lang
|
|
555
|
-
*/
|
|
556
|
-
isSupport: function (lang) {
|
|
557
|
-
let support = this.options.support;
|
|
558
|
-
|
|
559
|
-
if (support.indexOf(lang) === -1) {
|
|
560
|
-
return false;
|
|
561
|
-
}
|
|
562
|
-
return lang;
|
|
563
|
-
},
|
|
564
|
-
|
|
565
|
-
/**
|
|
566
|
-
* 设置语言
|
|
567
|
-
* @param {string} lang
|
|
568
|
-
*/
|
|
569
|
-
setLang: function (lang) {
|
|
570
|
-
if (lang !== undefined) {
|
|
571
|
-
if (!this.isSupport(lang)) {
|
|
572
|
-
lang = this.options.defaultLang;
|
|
573
|
-
}
|
|
574
|
-
doc.cookie = "bLanguage=" + lang + ";";
|
|
575
|
-
}
|
|
576
|
-
return lang;
|
|
577
|
-
},
|
|
578
|
-
|
|
579
|
-
/**
|
|
580
|
-
* 获取当前设置的语言
|
|
581
|
-
*/
|
|
582
|
-
getLang: function () {
|
|
583
|
-
let special = {
|
|
584
|
-
zh: "cn",
|
|
585
|
-
"zh-chs": "cn",
|
|
586
|
-
"zh-cn": "cn",
|
|
587
|
-
"zh-cht": "cn",
|
|
588
|
-
"zh-hk": "zh",
|
|
589
|
-
"zh-mo": "zh",
|
|
590
|
-
"zh-tw": "zh",
|
|
591
|
-
"zh-sg": "zh",
|
|
592
|
-
},
|
|
593
|
-
defLang = this.options.defaultLang,
|
|
594
|
-
local,
|
|
595
|
-
ret,
|
|
596
|
-
start,
|
|
597
|
-
end;
|
|
598
|
-
|
|
599
|
-
if (doc.cookie.indexOf("bLanguage=") === -1) {
|
|
600
|
-
local = (
|
|
601
|
-
win.navigator.language ||
|
|
602
|
-
win.navigator.userLanguage ||
|
|
603
|
-
win.navigator.browserLanguage ||
|
|
604
|
-
win.navigator.systemLanguage ||
|
|
605
|
-
defLang
|
|
606
|
-
).toLowerCase();
|
|
607
|
-
|
|
608
|
-
ret = special[local] || special[local.split("-")[0].toString()] || local.split("-")[0].toString();
|
|
609
|
-
} else {
|
|
610
|
-
if (doc.cookie.indexOf("bLanguage=") === 0) {
|
|
611
|
-
start = 10;
|
|
612
|
-
} else if (doc.cookie.indexOf("; bLanguage=") !== -1) {
|
|
613
|
-
start = doc.cookie.indexOf("; bLanguage=") + 12;
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
if (start !== undefined) {
|
|
617
|
-
end = doc.cookie.indexOf(";", start) !== -1 ? doc.cookie.indexOf(";", start) : doc.cookie.length;
|
|
618
|
-
ret = doc.cookie.substring(start, end);
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
//语言使用优先级 1.浏览器语言是否支持 2 默认语言是否支持 3支持中的语言第一个 4.默认语言
|
|
622
|
-
return this.isSupport(ret) || this.isSupport(defLang) || (this.options.support && this.options.support[0]) || defLang;
|
|
623
|
-
},
|
|
624
|
-
|
|
625
|
-
/**
|
|
626
|
-
* 拼接语言文件的url
|
|
627
|
-
* @param {string} domain 语言文件名称不包含扩展名(如:lang.json -> domain为lang)
|
|
628
|
-
*/
|
|
629
|
-
getURL: function (domain) {
|
|
630
|
-
return langPath + this.lang + "/" + domain + "." + this.options.fileType + "?" + b28Cfg.dateStr;
|
|
631
|
-
},
|
|
632
|
-
|
|
633
|
-
/**
|
|
634
|
-
* 加载所需要的语言文件,并翻译页面
|
|
635
|
-
* @param {string} domain 翻译文件的名称不包含扩展名(如:lang.json -> domain为lang)
|
|
636
|
-
* @param {lang} lang 当前语言
|
|
637
|
-
* @param {function} callBack 回调
|
|
638
|
-
*/
|
|
639
|
-
setTextDomain: function (domain, lang, callBack) {
|
|
640
|
-
let i,
|
|
641
|
-
domainLen,
|
|
642
|
-
htmlElem = doc.documentElement;
|
|
643
|
-
|
|
644
|
-
this.domainArr = [];
|
|
645
|
-
this.lang = lang || this.getLang();
|
|
646
|
-
this.setLang(lang);
|
|
647
|
-
this.curDomain = 0;
|
|
648
|
-
if (typeof callBack === "function") {
|
|
649
|
-
this.success = callBack;
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
htmlElem.style.visibility = "hidden";
|
|
653
|
-
|
|
654
|
-
handleClass("lang-" + this.lang);
|
|
655
|
-
|
|
656
|
-
if (Object.prototype.toString.call(domain) === "[object Array]") {
|
|
657
|
-
domainLen = domain.length;
|
|
658
|
-
this.domainArr = domain;
|
|
659
|
-
|
|
660
|
-
for (i = 0; i < domainLen; i = i + 1) {
|
|
661
|
-
this.loadDomain(this.getURL(domain[i]), i);
|
|
662
|
-
}
|
|
663
|
-
} else if (typeof domain === "string") {
|
|
664
|
-
this.domainArr.push(domain);
|
|
665
|
-
this.loadDomain(this.getURL(domain), 0);
|
|
666
|
-
}
|
|
667
|
-
},
|
|
668
|
-
|
|
669
|
-
/**
|
|
670
|
-
* 加载语言文件
|
|
671
|
-
* @param {string} url 语言包文件地址
|
|
672
|
-
*/
|
|
673
|
-
loadDomain: function (url) {
|
|
674
|
-
//若当前设定语言与默认语言一样,则不加载语言文件
|
|
675
|
-
if (b28Cfg.idDefaultLang && this.lang === b28Cfg.defaultLang) {
|
|
676
|
-
this.b28Loaded = true;
|
|
677
|
-
b28Cfg.initSelect &&
|
|
678
|
-
domReady(() => {
|
|
679
|
-
this.initSelectElem();
|
|
680
|
-
});
|
|
681
|
-
//重置语言对象
|
|
682
|
-
this.langData = {};
|
|
683
|
-
domReady(() => {
|
|
684
|
-
this.translatePage();
|
|
685
|
-
});
|
|
686
|
-
} else {
|
|
687
|
-
//加载对应文件
|
|
688
|
-
loadData.reload(this.options.fileType, url, (data) => {
|
|
689
|
-
this.handLangData(data);
|
|
690
|
-
});
|
|
691
|
-
}
|
|
692
|
-
},
|
|
693
|
-
|
|
694
|
-
/**
|
|
695
|
-
* 处理加载的数据文件
|
|
696
|
-
*/
|
|
697
|
-
handLangData: function (data) {
|
|
698
|
-
extend(this.langData, data);
|
|
699
|
-
this.loadedDict();
|
|
700
|
-
},
|
|
701
|
-
|
|
702
|
-
/**
|
|
703
|
-
* 语言文件加载完成后的回调,界面加载完成后进入翻译工作
|
|
704
|
-
*/
|
|
705
|
-
loadedDict: function () {
|
|
706
|
-
let len = this.domainArr.length;
|
|
707
|
-
if (this.curDomain + 1 === len) {
|
|
708
|
-
this.b28Loaded = true;
|
|
709
|
-
domReady(() => {
|
|
710
|
-
this.translatePage();
|
|
711
|
-
});
|
|
712
|
-
} else {
|
|
713
|
-
this.curDomain += 1;
|
|
714
|
-
}
|
|
715
|
-
},
|
|
716
|
-
|
|
717
|
-
/**
|
|
718
|
-
* 语言包文件是否加载完成
|
|
719
|
-
*/
|
|
720
|
-
isLoaded: function () {
|
|
721
|
-
return this.b28Loaded;
|
|
722
|
-
},
|
|
723
|
-
|
|
724
|
-
/**
|
|
725
|
-
* 翻译纯文本
|
|
726
|
-
* @param {string} key 需要翻译的字段
|
|
727
|
-
*/
|
|
728
|
-
gettext: function (key) {
|
|
729
|
-
if (key === undefined) return;
|
|
730
|
-
if (this.options.defaultLang === this.lang) {
|
|
731
|
-
//处理一对多的翻译时对翻译加上了唯一标识的前缀,故需要把这些前缀去掉
|
|
732
|
-
return key.replace(/^[a-zA-Z]\#[a-zA-Z][a-zA-Z][a-zA-Z]\#/g, "");
|
|
733
|
-
}
|
|
734
|
-
return this.langData[key] !== undefined ? this.langData[key] : key.replace(/^[a-zA-Z]\#[a-zA-Z][a-zA-Z][a-zA-Z]\#/g, "");
|
|
735
|
-
},
|
|
736
|
-
|
|
737
|
-
/**
|
|
738
|
-
* 翻译有%s参数的文本
|
|
739
|
-
* @param {string} key 需要翻译的字段
|
|
740
|
-
* @param {Array} replacements 参数
|
|
741
|
-
*/
|
|
742
|
-
getFormatText: function (key, replacements) {
|
|
743
|
-
let nkey = this.gettext(key);
|
|
744
|
-
|
|
745
|
-
if (replacements === "" || replacements === undefined) {
|
|
746
|
-
return nkey;
|
|
747
|
-
}
|
|
748
|
-
if (Object.prototype.toString.call(replacements) !== "[object Array]") {
|
|
749
|
-
replacements = [replacements];
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
for (let i = 0, l = replacements.length; i < l; i++) {
|
|
753
|
-
nkey = nkey.replace(/%s/, replacements[i]);
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
return nkey;
|
|
757
|
-
},
|
|
758
|
-
|
|
759
|
-
/**
|
|
760
|
-
* 初始化语言选择框
|
|
761
|
-
*/
|
|
762
|
-
initSelectElem: function () {
|
|
763
|
-
let selectElem = doc.getElementById("select-lang"),
|
|
764
|
-
len = b28Cfg.supportLang.length,
|
|
765
|
-
newOption,
|
|
766
|
-
lang,
|
|
767
|
-
i;
|
|
768
|
-
|
|
769
|
-
if (selectElem && selectElem.nodeName.toLowerCase() == "select") {
|
|
770
|
-
for (i = 0; i < len; i++) {
|
|
771
|
-
lang = b28Cfg.supportLang[i];
|
|
772
|
-
newOption = new Option(this.langArr[lang], lang);
|
|
773
|
-
selectElem.add(newOption, undefined);
|
|
774
|
-
}
|
|
775
|
-
selectElem.value = this.lang;
|
|
776
|
-
|
|
777
|
-
if (doc.addEventListener) {
|
|
778
|
-
selectElem.addEventListener(
|
|
779
|
-
"change",
|
|
780
|
-
function () {
|
|
781
|
-
this.setLang(doc.getElementById("select-lang").value);
|
|
782
|
-
setTimeout(function () {
|
|
783
|
-
window.location.reload();
|
|
784
|
-
}, 24);
|
|
785
|
-
},
|
|
786
|
-
false
|
|
787
|
-
);
|
|
788
|
-
} else if (doc.attachEvent) {
|
|
789
|
-
selectElem.attachEvent("onchange", function () {
|
|
790
|
-
this.setLang(doc.getElementById("select-lang").value);
|
|
791
|
-
setTimeout(function () {
|
|
792
|
-
window.location.reload();
|
|
793
|
-
}, 24);
|
|
794
|
-
});
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
},
|
|
798
|
-
|
|
799
|
-
/**
|
|
800
|
-
* 翻译translateTarget及translateTarget里面的内容
|
|
801
|
-
* @param {element} translateTarget 需要翻译的内容的容器
|
|
802
|
-
*/
|
|
803
|
-
translate: function (translateTarget) {
|
|
804
|
-
let translateElem;
|
|
805
|
-
//确定html容器元素
|
|
806
|
-
if (assertElement(translateTarget)) {
|
|
807
|
-
translateElem = translateTarget;
|
|
808
|
-
} else if (translateTarget && typeof translateTarget === "string") {
|
|
809
|
-
translateElem = doc.getElementById(translateTarget);
|
|
810
|
-
}
|
|
811
|
-
translateElem = translateElem || doc.documentElement;
|
|
812
|
-
// 隐藏页面
|
|
813
|
-
doc.documentElement.style.visibility = "hidden";
|
|
814
|
-
// 逐个翻译元素
|
|
815
|
-
this.replaceTextNodeValue(translateElem);
|
|
816
|
-
|
|
817
|
-
this.saveLang = false;
|
|
818
|
-
// 显示页面
|
|
819
|
-
doc.documentElement.style.visibility = "visible";
|
|
820
|
-
// 执行翻译完成后的回调
|
|
821
|
-
if (typeof this.success === "function") {
|
|
822
|
-
this.success();
|
|
823
|
-
}
|
|
824
|
-
},
|
|
825
|
-
|
|
826
|
-
/**
|
|
827
|
-
* 翻译页面
|
|
828
|
-
*/
|
|
829
|
-
translatePage: function () {
|
|
830
|
-
let bodyElem = doc.body || doc.documentElement;
|
|
831
|
-
|
|
832
|
-
// 翻译HTML页面内容
|
|
833
|
-
this.transTitle(this.original.title);
|
|
834
|
-
|
|
835
|
-
// 初始语言选择下拉框
|
|
836
|
-
b28Cfg.initSelect && this.initSelectElem();
|
|
837
|
-
//全局翻译时需要记录所有的信息
|
|
838
|
-
this.saveLang = true;
|
|
839
|
-
this.translate(bodyElem);
|
|
840
|
-
},
|
|
841
|
-
};
|
|
842
|
-
|
|
843
|
-
let Butterlate = new Butterlation(),
|
|
844
|
-
defaultLang;
|
|
845
|
-
|
|
846
|
-
//将翻译对象挂载到window上面
|
|
847
|
-
win.Butterlate = Butterlate;
|
|
848
|
-
win.B = win.B || win.Butterlate;
|
|
849
|
-
win._ = function (key, replacements) {
|
|
850
|
-
return Butterlate.getFormatText(key, replacements);
|
|
851
|
-
};
|
|
852
|
-
win.Butterlate.loadScript = loadScript;
|
|
853
|
-
if (window.beforeTranslate) {
|
|
854
|
-
defaultLang = window.beforeTranslate();
|
|
855
|
-
}
|
|
856
|
-
window.B.setTextDomain("lang", defaultLang);
|
|
857
|
-
})(window, document);
|
|
1
|
+
(function (window, document) {
|
|
2
|
+
Array.prototype.indexOf =
|
|
3
|
+
Array.prototype.indexOf ||
|
|
4
|
+
function (item) {
|
|
5
|
+
for (let i = 0, l = this.length; i < l; i++) {
|
|
6
|
+
if (this[i] === item) {
|
|
7
|
+
return i;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
return -1;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
Array.prototype.filter =
|
|
14
|
+
Array.prototype.filter ||
|
|
15
|
+
function (cb) {
|
|
16
|
+
let arr = [];
|
|
17
|
+
if (cb && typeof cb === "function") {
|
|
18
|
+
for (let i = 0, l = this.length; i < l; i++) {
|
|
19
|
+
cb(this[i]) && arr.push(this[i]);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return arr;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
//翻译配置项
|
|
26
|
+
let b28Cfg = {
|
|
27
|
+
/**
|
|
28
|
+
* 支持的语言项,若设置的语言不在配置项中,则显示默认语言
|
|
29
|
+
*/
|
|
30
|
+
supportLang: ["en", "cn"],
|
|
31
|
+
/**
|
|
32
|
+
* 默认语言,若supportLang中没有设置的默认语言,则自动添加到supportLang中去
|
|
33
|
+
*/
|
|
34
|
+
defaultLang: "en",
|
|
35
|
+
/**
|
|
36
|
+
* 配置语言包文件类型 within ["xml", "json"]
|
|
37
|
+
*/
|
|
38
|
+
fileType: "json",
|
|
39
|
+
/**
|
|
40
|
+
* 用默认语言做id
|
|
41
|
+
*/
|
|
42
|
+
idDefaultLang: true,
|
|
43
|
+
/**
|
|
44
|
+
* 是否对要翻译文字进行trim
|
|
45
|
+
*/
|
|
46
|
+
trimText: true,
|
|
47
|
+
/**
|
|
48
|
+
* 默认替换节点中的文字,将其设为true可插入html
|
|
49
|
+
*/
|
|
50
|
+
insertHTML: true,
|
|
51
|
+
/**
|
|
52
|
+
* 是否初始化下拉框
|
|
53
|
+
*/
|
|
54
|
+
initSelect: true,
|
|
55
|
+
/**
|
|
56
|
+
* 时间戳
|
|
57
|
+
*/
|
|
58
|
+
dateStr: new Date().getTime(),
|
|
59
|
+
|
|
60
|
+
langArr: {
|
|
61
|
+
cn: "简体中文",
|
|
62
|
+
zh: "繁體中文",
|
|
63
|
+
de: "Deutsch", //德语
|
|
64
|
+
en: "English", //英语
|
|
65
|
+
es: "Español", //西班牙
|
|
66
|
+
fr: "Français", //法国
|
|
67
|
+
hu: "Magyar", //匈牙利
|
|
68
|
+
it: "Italiano", //意大利
|
|
69
|
+
pl: "Polski", //波兰
|
|
70
|
+
ro: "Română", //罗马尼亚
|
|
71
|
+
ar: "العربية", //阿拉伯
|
|
72
|
+
tr: "Türkçe", //土耳其
|
|
73
|
+
ru: "Русский", //Russian 俄语
|
|
74
|
+
pt: "Português", //Portugal 葡萄牙语
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
let win = window,
|
|
79
|
+
doc = document,
|
|
80
|
+
core_version = "3.0.0",
|
|
81
|
+
core_trim = core_version.trim,
|
|
82
|
+
//获取语言文件相对路径
|
|
83
|
+
js = document.scripts,
|
|
84
|
+
langJs = js[js.length - 1]["src"],
|
|
85
|
+
langPath = langJs.substring(0, langJs.lastIndexOf("/") + 1);
|
|
86
|
+
|
|
87
|
+
/** 工具函数 start */
|
|
88
|
+
//对象浅拷贝
|
|
89
|
+
function extend(oldObj, newObj) {
|
|
90
|
+
if (typeof newObj !== "object") {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
for (let key in newObj) {
|
|
95
|
+
if (newObj.hasOwnProperty(key)) {
|
|
96
|
+
oldObj[key] = newObj[key];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/** 工具函数 end */
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* 创建ajax
|
|
104
|
+
*/
|
|
105
|
+
function createXHR() {
|
|
106
|
+
try {
|
|
107
|
+
return new XMLHttpRequest();
|
|
108
|
+
} catch (e) {
|
|
109
|
+
try {
|
|
110
|
+
return new window.ActiveXObject("Msxml2.XMLHTTP");
|
|
111
|
+
} catch (e) {
|
|
112
|
+
try {
|
|
113
|
+
return new window.ActiveXObject("Microsoft.XMLHTTP");
|
|
114
|
+
} catch (e) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* 添加文档加载完成后的事件委托
|
|
123
|
+
*/
|
|
124
|
+
let domReady = (function () {
|
|
125
|
+
let funcs = [],
|
|
126
|
+
already = false,
|
|
127
|
+
len,
|
|
128
|
+
i;
|
|
129
|
+
|
|
130
|
+
function handler(e) {
|
|
131
|
+
e = e || win.event;
|
|
132
|
+
if (already) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (e.type === "readystatechange" && doc.readyState !== "complete") {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
for (i = 0, len = funcs.length; i < len; i++) {
|
|
141
|
+
funcs[i].call(doc);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
already = true;
|
|
145
|
+
funcs = null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (doc.addEventListener) {
|
|
149
|
+
doc.addEventListener("DOMContentLoaded", handler, false);
|
|
150
|
+
doc.addEventListener("onreadystatechange", handler, false);
|
|
151
|
+
win.addEventListener("load", handler, false);
|
|
152
|
+
} else if (doc.attachEvent) {
|
|
153
|
+
doc.attachEvent("onreadystatechange", handler);
|
|
154
|
+
win.attachEvent("onload", handler);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return function ready(f) {
|
|
158
|
+
if (already) {
|
|
159
|
+
f.call(doc);
|
|
160
|
+
} else {
|
|
161
|
+
funcs.push(f);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
})();
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* 加载script
|
|
168
|
+
*/
|
|
169
|
+
let loadScript = (function () {
|
|
170
|
+
let scripts = doc.createElement("script"),
|
|
171
|
+
hasReadyState = scripts.readyState;
|
|
172
|
+
|
|
173
|
+
return hasReadyState
|
|
174
|
+
? function (url, callBack) {
|
|
175
|
+
let scripts = doc.createElement("script");
|
|
176
|
+
|
|
177
|
+
scripts.onreadystatechange = function () {
|
|
178
|
+
if (scripts.readyState === "loaded" || scripts.readyState === "complete") {
|
|
179
|
+
scripts.onreadystatechange = null;
|
|
180
|
+
|
|
181
|
+
if (typeof callBack === "function") {
|
|
182
|
+
callBack();
|
|
183
|
+
callBack = null;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
scripts.src = url;
|
|
188
|
+
doc.getElementsByTagName("head")[0].appendChild(scripts);
|
|
189
|
+
}
|
|
190
|
+
: function (url, callBack) {
|
|
191
|
+
let scripts = doc.createElement("script");
|
|
192
|
+
|
|
193
|
+
scripts.onload = function () {
|
|
194
|
+
if (typeof callBack === "function") {
|
|
195
|
+
callBack();
|
|
196
|
+
callBack = null;
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
scripts.src = url;
|
|
200
|
+
doc.getElementsByTagName("head")[0].appendChild(scripts);
|
|
201
|
+
};
|
|
202
|
+
})();
|
|
203
|
+
|
|
204
|
+
// 获取数据文件 并注入到msg中
|
|
205
|
+
let loadData = {
|
|
206
|
+
reload(type, url, callBack) {
|
|
207
|
+
let parseData = type === "json" ? loadData.parseJson : loadData.parseXML,
|
|
208
|
+
request;
|
|
209
|
+
|
|
210
|
+
request = createXHR();
|
|
211
|
+
request.open("GET", url + "?" + Math.random(), false);
|
|
212
|
+
request.send(null);
|
|
213
|
+
|
|
214
|
+
if ((request.status >= 200 && request.status < 300) || request.status === 304) {
|
|
215
|
+
let langData = parseData(request);
|
|
216
|
+
|
|
217
|
+
if (typeof callBack === "function") {
|
|
218
|
+
callBack(langData);
|
|
219
|
+
langData = null;
|
|
220
|
+
callBack = null;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
parseXML(request) {
|
|
225
|
+
let i,
|
|
226
|
+
pos,
|
|
227
|
+
posLen,
|
|
228
|
+
langData = {};
|
|
229
|
+
|
|
230
|
+
pos = request.responseXML.documentElement.getElementsByTagName("message");
|
|
231
|
+
posLen = pos.length;
|
|
232
|
+
|
|
233
|
+
for (i = 0; i < posLen; i++) {
|
|
234
|
+
langData[pos[i].getAttribute("msgid")] = pos[i].getAttribute("msgstr");
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return langData;
|
|
238
|
+
},
|
|
239
|
+
parseJson(request) {
|
|
240
|
+
return window.JSON.parse(request.responseText) || request.responseText;
|
|
241
|
+
},
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* 去除lang-xx类名,并添加新的类名
|
|
246
|
+
*/
|
|
247
|
+
function handleClass(classname) {
|
|
248
|
+
let name = document.documentElement.className;
|
|
249
|
+
if (name) {
|
|
250
|
+
name = name.split(" ").filter((item) => {
|
|
251
|
+
return !/^lang-/.test(item);
|
|
252
|
+
});
|
|
253
|
+
name.push(classname);
|
|
254
|
+
|
|
255
|
+
document.documentElement.className = name.join(" ");
|
|
256
|
+
} else {
|
|
257
|
+
document.documentElement.className = classname;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* 获取元素的文本内容 或者设置文本内容
|
|
263
|
+
*/
|
|
264
|
+
let innerText = (function () {
|
|
265
|
+
if (b28Cfg.insertHTML) {
|
|
266
|
+
return function (elem, str) {
|
|
267
|
+
elem.innerHTML = str;
|
|
268
|
+
return elem;
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
let element = doc.createElement("p");
|
|
273
|
+
element.innerHTML = core_version;
|
|
274
|
+
return element.textContent
|
|
275
|
+
? function (elem, str) {
|
|
276
|
+
if (str) {
|
|
277
|
+
elem.textContent = str;
|
|
278
|
+
return elem;
|
|
279
|
+
}
|
|
280
|
+
return elem.textContent;
|
|
281
|
+
}
|
|
282
|
+
: function (elem, str) {
|
|
283
|
+
if (str) {
|
|
284
|
+
elem.innerText = str;
|
|
285
|
+
return elem;
|
|
286
|
+
}
|
|
287
|
+
return elem.innerText;
|
|
288
|
+
};
|
|
289
|
+
})();
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* 去除字符串首尾空格全兼容
|
|
293
|
+
*/
|
|
294
|
+
function trim(text) {
|
|
295
|
+
if (text == null) {
|
|
296
|
+
return "";
|
|
297
|
+
}
|
|
298
|
+
if (core_trim && !core_trim.call("\uFEFF\xA0")) {
|
|
299
|
+
return core_trim.call(text);
|
|
300
|
+
} else {
|
|
301
|
+
text += "";
|
|
302
|
+
return text.replace(/(^\s*)|(\s*$)/g, "");
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* 根据配置参数决定是否去除空格
|
|
308
|
+
*/
|
|
309
|
+
function _trim(str) {
|
|
310
|
+
return b28Cfg.trimText ? trim(str) : str;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* 是否是html元素
|
|
315
|
+
*/
|
|
316
|
+
function assertElement(elem) {
|
|
317
|
+
//支持HTMLElement
|
|
318
|
+
if (typeof HTMLElement === "object" && elem instanceof HTMLElement) {
|
|
319
|
+
return true;
|
|
320
|
+
}
|
|
321
|
+
//ie等
|
|
322
|
+
if (typeof elem === "object" && (elem.nodeType === 1 || elem.nodeType === 9) && typeof elem.nodeName === "string") {
|
|
323
|
+
return true;
|
|
324
|
+
}
|
|
325
|
+
return false;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* 判断是否为null,undefined或者空白字符串
|
|
330
|
+
* @param {值} val
|
|
331
|
+
*/
|
|
332
|
+
function notNull(val) {
|
|
333
|
+
return val && /\S/.test(val);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* 寻找子元素中text
|
|
338
|
+
* @param {元素} elem
|
|
339
|
+
*/
|
|
340
|
+
function getTextChild(elem) {
|
|
341
|
+
if (elem) {
|
|
342
|
+
let first = elem.firstChild;
|
|
343
|
+
if (first) {
|
|
344
|
+
if (first.nodeType === 3) {
|
|
345
|
+
return first.nodeValue;
|
|
346
|
+
}
|
|
347
|
+
return getTextChild(first.nextSibling);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function htmlEncode(str) {
|
|
353
|
+
var encodeObj = {
|
|
354
|
+
"&": "&",
|
|
355
|
+
"<": "<",
|
|
356
|
+
">": ">",
|
|
357
|
+
"'": "'",
|
|
358
|
+
'"': """,
|
|
359
|
+
" ": " ",
|
|
360
|
+
};
|
|
361
|
+
if (str.length == 0) {
|
|
362
|
+
return "";
|
|
363
|
+
}
|
|
364
|
+
return str.replace(/(&|\s| |<|>|\'|\")/g, function (a) {
|
|
365
|
+
return encodeObj[a];
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function htmlDecode(str) {
|
|
370
|
+
var decodeObj = {
|
|
371
|
+
"&": "&",
|
|
372
|
+
"<": "<",
|
|
373
|
+
">": ">",
|
|
374
|
+
"'": "'",
|
|
375
|
+
""": '"',
|
|
376
|
+
" ": " ",
|
|
377
|
+
};
|
|
378
|
+
if (str.length == 0) {
|
|
379
|
+
return "";
|
|
380
|
+
}
|
|
381
|
+
return str.replace(/(&|<|>|'|"| )/g, function (a) {
|
|
382
|
+
return decodeObj[a];
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
/** 文本处理相关函数 end */
|
|
386
|
+
|
|
387
|
+
//翻译对象
|
|
388
|
+
function Butterlation(cfg) {
|
|
389
|
+
extend(b28Cfg, cfg);
|
|
390
|
+
|
|
391
|
+
//若所支持的语言中没有默认语言,则将默认语言添加到支持语言数组中
|
|
392
|
+
if (b28Cfg.idDefaultLang && b28Cfg.supportLang.indexOf(b28Cfg.defaultLang) === -1) {
|
|
393
|
+
b28Cfg.supportLang.push(b28Cfg.defaultLang);
|
|
394
|
+
}
|
|
395
|
+
this.curDomain = 0;
|
|
396
|
+
this.domainArr = [];
|
|
397
|
+
this.options = {
|
|
398
|
+
defaultLang: b28Cfg.defaultLang,
|
|
399
|
+
support: b28Cfg.supportLang,
|
|
400
|
+
fileType: b28Cfg.fileType,
|
|
401
|
+
};
|
|
402
|
+
this.langArr = b28Cfg.langArr;
|
|
403
|
+
/**语言包文件是否加载完成标志 */
|
|
404
|
+
this.b28Loaded = false;
|
|
405
|
+
/**当前语言 */
|
|
406
|
+
this.lang = "";
|
|
407
|
+
/**是否记录当前语言用于无刷新翻译页面 */
|
|
408
|
+
this.saveLang = false;
|
|
409
|
+
/**当前语言包信息 */
|
|
410
|
+
this.langData = {};
|
|
411
|
+
/**记录翻译页面前的数据 */
|
|
412
|
+
this.original = {
|
|
413
|
+
title: doc.title,
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
Butterlation.prototype = {
|
|
418
|
+
/**
|
|
419
|
+
* 翻译title
|
|
420
|
+
*/
|
|
421
|
+
transTitle: function (title) {
|
|
422
|
+
doc.title = this.gettext(_trim(title));
|
|
423
|
+
},
|
|
424
|
+
/**
|
|
425
|
+
* 翻译html元素节点
|
|
426
|
+
* @param {object} element
|
|
427
|
+
*/
|
|
428
|
+
replaceTextNodeValue: function (element) {
|
|
429
|
+
if (!element) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
if (/^SCRIPT$/i.test(element.tagName)) {
|
|
433
|
+
if (element.nextSibling) {
|
|
434
|
+
this.replaceTextNodeValue(element.nextSibling);
|
|
435
|
+
}
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
let firstChild = element.firstChild,
|
|
440
|
+
nextSibling = element.nextSibling,
|
|
441
|
+
nodeType = element.nodeType,
|
|
442
|
+
btnStr = "submit,reset,button",
|
|
443
|
+
curValue,
|
|
444
|
+
isInputButton,
|
|
445
|
+
oldValue;
|
|
446
|
+
|
|
447
|
+
//handle element node
|
|
448
|
+
if (nodeType === 1) {
|
|
449
|
+
//alt属性
|
|
450
|
+
this.replaceTextNodeAttr("alt", element, "data-o-alt");
|
|
451
|
+
|
|
452
|
+
//placeholder属性
|
|
453
|
+
this.replaceTextNodeAttr("placeholder", element, "data-o-holder");
|
|
454
|
+
|
|
455
|
+
//title属性
|
|
456
|
+
this.replaceTextNodeAttr("title", element, "data-o-title");
|
|
457
|
+
|
|
458
|
+
isInputButton = element.nodeName.toLowerCase() == "input" && btnStr.indexOf(element.getAttribute("type")) !== -1;
|
|
459
|
+
|
|
460
|
+
if (isInputButton) {
|
|
461
|
+
//data-lang属性具有较高优先级
|
|
462
|
+
curValue = element.getAttribute("data-lang") || element.value;
|
|
463
|
+
} else {
|
|
464
|
+
if (element.getAttribute("data-nowrap") === "1") {
|
|
465
|
+
curValue = element.innerHTML;
|
|
466
|
+
} else {
|
|
467
|
+
curValue = element.getAttribute("data-lang");
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (curValue && /\S/.test(curValue)) {
|
|
472
|
+
curValue = htmlEncode(curValue);
|
|
473
|
+
if (this.saveLang) {
|
|
474
|
+
let oldText = element.getAttribute("data-o-text");
|
|
475
|
+
if (oldText === undefined || oldText === null) {
|
|
476
|
+
if (element.getAttribute("data-nowrap") === "1") {
|
|
477
|
+
oldText = curValue;
|
|
478
|
+
} else {
|
|
479
|
+
oldText = getTextChild(element);
|
|
480
|
+
notNull(oldText) && (oldText = htmlEncode(oldText));
|
|
481
|
+
}
|
|
482
|
+
oldText = oldText || " ";
|
|
483
|
+
element.setAttribute("data-o-text", oldText);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (this.options.defaultLang === this.lang) {
|
|
487
|
+
curValue = oldText;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
curValue = htmlDecode(curValue);
|
|
492
|
+
if (curValue) {
|
|
493
|
+
curValue = _trim(curValue);
|
|
494
|
+
if (isInputButton) {
|
|
495
|
+
element.setAttribute("value", this.gettext(curValue));
|
|
496
|
+
} else {
|
|
497
|
+
innerText(element, this.gettext(curValue));
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
//handle textNode
|
|
502
|
+
} else if (nodeType === 3 && notNull(element.nodeValue)) {
|
|
503
|
+
curValue = _trim(element.nodeValue);
|
|
504
|
+
if (this.saveLang) {
|
|
505
|
+
let parNode = element.parentNode;
|
|
506
|
+
oldValue = parNode.getAttribute("data-o-text");
|
|
507
|
+
if (oldValue) {
|
|
508
|
+
curValue = htmlDecode(oldValue);
|
|
509
|
+
} else {
|
|
510
|
+
parNode.setAttribute("data-o-text", htmlEncode(curValue));
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
element.nodeValue = this.gettext(curValue);
|
|
514
|
+
}
|
|
515
|
+
//translate siblings
|
|
516
|
+
if (nextSibling) {
|
|
517
|
+
this.replaceTextNodeValue(nextSibling);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
//translate firstChild
|
|
521
|
+
//stop handle elem.child if elem has attr data-lang
|
|
522
|
+
if (firstChild && !element.getAttribute("data-lang")) {
|
|
523
|
+
this.replaceTextNodeValue(firstChild);
|
|
524
|
+
}
|
|
525
|
+
},
|
|
526
|
+
/**
|
|
527
|
+
* 翻译html元素节点的属性
|
|
528
|
+
* @param {object} element
|
|
529
|
+
*/
|
|
530
|
+
|
|
531
|
+
replaceTextNodeAttr: function (attr, element, oldAttr) {
|
|
532
|
+
let curValue = element.getAttribute(attr);
|
|
533
|
+
let oldValue = element.getAttribute(oldAttr);
|
|
534
|
+
if (this.saveLang) {
|
|
535
|
+
if (oldValue) {
|
|
536
|
+
curValue = oldValue;
|
|
537
|
+
} else {
|
|
538
|
+
notNull(curValue) && element.setAttribute(oldAttr, curValue);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
if (notNull(curValue)) {
|
|
542
|
+
curValue = _trim(curValue);
|
|
543
|
+
element.setAttribute(attr, this.gettext(curValue));
|
|
544
|
+
}
|
|
545
|
+
},
|
|
546
|
+
/**
|
|
547
|
+
* 获取语言包信息
|
|
548
|
+
*/
|
|
549
|
+
getMsg: function () {
|
|
550
|
+
return this.langData;
|
|
551
|
+
},
|
|
552
|
+
/**
|
|
553
|
+
* 是否支持该语言
|
|
554
|
+
* @param {string} lang
|
|
555
|
+
*/
|
|
556
|
+
isSupport: function (lang) {
|
|
557
|
+
let support = this.options.support;
|
|
558
|
+
|
|
559
|
+
if (support.indexOf(lang) === -1) {
|
|
560
|
+
return false;
|
|
561
|
+
}
|
|
562
|
+
return lang;
|
|
563
|
+
},
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* 设置语言
|
|
567
|
+
* @param {string} lang
|
|
568
|
+
*/
|
|
569
|
+
setLang: function (lang) {
|
|
570
|
+
if (lang !== undefined) {
|
|
571
|
+
if (!this.isSupport(lang)) {
|
|
572
|
+
lang = this.options.defaultLang;
|
|
573
|
+
}
|
|
574
|
+
doc.cookie = "bLanguage=" + lang + ";";
|
|
575
|
+
}
|
|
576
|
+
return lang;
|
|
577
|
+
},
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* 获取当前设置的语言
|
|
581
|
+
*/
|
|
582
|
+
getLang: function () {
|
|
583
|
+
let special = {
|
|
584
|
+
zh: "cn",
|
|
585
|
+
"zh-chs": "cn",
|
|
586
|
+
"zh-cn": "cn",
|
|
587
|
+
"zh-cht": "cn",
|
|
588
|
+
"zh-hk": "zh",
|
|
589
|
+
"zh-mo": "zh",
|
|
590
|
+
"zh-tw": "zh",
|
|
591
|
+
"zh-sg": "zh",
|
|
592
|
+
},
|
|
593
|
+
defLang = this.options.defaultLang,
|
|
594
|
+
local,
|
|
595
|
+
ret,
|
|
596
|
+
start,
|
|
597
|
+
end;
|
|
598
|
+
|
|
599
|
+
if (doc.cookie.indexOf("bLanguage=") === -1) {
|
|
600
|
+
local = (
|
|
601
|
+
win.navigator.language ||
|
|
602
|
+
win.navigator.userLanguage ||
|
|
603
|
+
win.navigator.browserLanguage ||
|
|
604
|
+
win.navigator.systemLanguage ||
|
|
605
|
+
defLang
|
|
606
|
+
).toLowerCase();
|
|
607
|
+
|
|
608
|
+
ret = special[local] || special[local.split("-")[0].toString()] || local.split("-")[0].toString();
|
|
609
|
+
} else {
|
|
610
|
+
if (doc.cookie.indexOf("bLanguage=") === 0) {
|
|
611
|
+
start = 10;
|
|
612
|
+
} else if (doc.cookie.indexOf("; bLanguage=") !== -1) {
|
|
613
|
+
start = doc.cookie.indexOf("; bLanguage=") + 12;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
if (start !== undefined) {
|
|
617
|
+
end = doc.cookie.indexOf(";", start) !== -1 ? doc.cookie.indexOf(";", start) : doc.cookie.length;
|
|
618
|
+
ret = doc.cookie.substring(start, end);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
//语言使用优先级 1.浏览器语言是否支持 2 默认语言是否支持 3支持中的语言第一个 4.默认语言
|
|
622
|
+
return this.isSupport(ret) || this.isSupport(defLang) || (this.options.support && this.options.support[0]) || defLang;
|
|
623
|
+
},
|
|
624
|
+
|
|
625
|
+
/**
|
|
626
|
+
* 拼接语言文件的url
|
|
627
|
+
* @param {string} domain 语言文件名称不包含扩展名(如:lang.json -> domain为lang)
|
|
628
|
+
*/
|
|
629
|
+
getURL: function (domain) {
|
|
630
|
+
return langPath + this.lang + "/" + domain + "." + this.options.fileType + "?" + b28Cfg.dateStr;
|
|
631
|
+
},
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* 加载所需要的语言文件,并翻译页面
|
|
635
|
+
* @param {string} domain 翻译文件的名称不包含扩展名(如:lang.json -> domain为lang)
|
|
636
|
+
* @param {lang} lang 当前语言
|
|
637
|
+
* @param {function} callBack 回调
|
|
638
|
+
*/
|
|
639
|
+
setTextDomain: function (domain, lang, callBack) {
|
|
640
|
+
let i,
|
|
641
|
+
domainLen,
|
|
642
|
+
htmlElem = doc.documentElement;
|
|
643
|
+
|
|
644
|
+
this.domainArr = [];
|
|
645
|
+
this.lang = lang || this.getLang();
|
|
646
|
+
this.setLang(lang);
|
|
647
|
+
this.curDomain = 0;
|
|
648
|
+
if (typeof callBack === "function") {
|
|
649
|
+
this.success = callBack;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
htmlElem.style.visibility = "hidden";
|
|
653
|
+
|
|
654
|
+
handleClass("lang-" + this.lang);
|
|
655
|
+
|
|
656
|
+
if (Object.prototype.toString.call(domain) === "[object Array]") {
|
|
657
|
+
domainLen = domain.length;
|
|
658
|
+
this.domainArr = domain;
|
|
659
|
+
|
|
660
|
+
for (i = 0; i < domainLen; i = i + 1) {
|
|
661
|
+
this.loadDomain(this.getURL(domain[i]), i);
|
|
662
|
+
}
|
|
663
|
+
} else if (typeof domain === "string") {
|
|
664
|
+
this.domainArr.push(domain);
|
|
665
|
+
this.loadDomain(this.getURL(domain), 0);
|
|
666
|
+
}
|
|
667
|
+
},
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* 加载语言文件
|
|
671
|
+
* @param {string} url 语言包文件地址
|
|
672
|
+
*/
|
|
673
|
+
loadDomain: function (url) {
|
|
674
|
+
//若当前设定语言与默认语言一样,则不加载语言文件
|
|
675
|
+
if (b28Cfg.idDefaultLang && this.lang === b28Cfg.defaultLang) {
|
|
676
|
+
this.b28Loaded = true;
|
|
677
|
+
b28Cfg.initSelect &&
|
|
678
|
+
domReady(() => {
|
|
679
|
+
this.initSelectElem();
|
|
680
|
+
});
|
|
681
|
+
//重置语言对象
|
|
682
|
+
this.langData = {};
|
|
683
|
+
domReady(() => {
|
|
684
|
+
this.translatePage();
|
|
685
|
+
});
|
|
686
|
+
} else {
|
|
687
|
+
//加载对应文件
|
|
688
|
+
loadData.reload(this.options.fileType, url, (data) => {
|
|
689
|
+
this.handLangData(data);
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
},
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* 处理加载的数据文件
|
|
696
|
+
*/
|
|
697
|
+
handLangData: function (data) {
|
|
698
|
+
extend(this.langData, data);
|
|
699
|
+
this.loadedDict();
|
|
700
|
+
},
|
|
701
|
+
|
|
702
|
+
/**
|
|
703
|
+
* 语言文件加载完成后的回调,界面加载完成后进入翻译工作
|
|
704
|
+
*/
|
|
705
|
+
loadedDict: function () {
|
|
706
|
+
let len = this.domainArr.length;
|
|
707
|
+
if (this.curDomain + 1 === len) {
|
|
708
|
+
this.b28Loaded = true;
|
|
709
|
+
domReady(() => {
|
|
710
|
+
this.translatePage();
|
|
711
|
+
});
|
|
712
|
+
} else {
|
|
713
|
+
this.curDomain += 1;
|
|
714
|
+
}
|
|
715
|
+
},
|
|
716
|
+
|
|
717
|
+
/**
|
|
718
|
+
* 语言包文件是否加载完成
|
|
719
|
+
*/
|
|
720
|
+
isLoaded: function () {
|
|
721
|
+
return this.b28Loaded;
|
|
722
|
+
},
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* 翻译纯文本
|
|
726
|
+
* @param {string} key 需要翻译的字段
|
|
727
|
+
*/
|
|
728
|
+
gettext: function (key) {
|
|
729
|
+
if (key === undefined) return;
|
|
730
|
+
if (this.options.defaultLang === this.lang) {
|
|
731
|
+
//处理一对多的翻译时对翻译加上了唯一标识的前缀,故需要把这些前缀去掉
|
|
732
|
+
return key.replace(/^[a-zA-Z]\#[a-zA-Z][a-zA-Z][a-zA-Z]\#/g, "");
|
|
733
|
+
}
|
|
734
|
+
return this.langData[key] !== undefined ? this.langData[key] : key.replace(/^[a-zA-Z]\#[a-zA-Z][a-zA-Z][a-zA-Z]\#/g, "");
|
|
735
|
+
},
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* 翻译有%s参数的文本
|
|
739
|
+
* @param {string} key 需要翻译的字段
|
|
740
|
+
* @param {Array} replacements 参数
|
|
741
|
+
*/
|
|
742
|
+
getFormatText: function (key, replacements) {
|
|
743
|
+
let nkey = this.gettext(key);
|
|
744
|
+
|
|
745
|
+
if (replacements === "" || replacements === undefined) {
|
|
746
|
+
return nkey;
|
|
747
|
+
}
|
|
748
|
+
if (Object.prototype.toString.call(replacements) !== "[object Array]") {
|
|
749
|
+
replacements = [replacements];
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
for (let i = 0, l = replacements.length; i < l; i++) {
|
|
753
|
+
nkey = nkey.replace(/%s/, replacements[i]);
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
return nkey;
|
|
757
|
+
},
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* 初始化语言选择框
|
|
761
|
+
*/
|
|
762
|
+
initSelectElem: function () {
|
|
763
|
+
let selectElem = doc.getElementById("select-lang"),
|
|
764
|
+
len = b28Cfg.supportLang.length,
|
|
765
|
+
newOption,
|
|
766
|
+
lang,
|
|
767
|
+
i;
|
|
768
|
+
|
|
769
|
+
if (selectElem && selectElem.nodeName.toLowerCase() == "select") {
|
|
770
|
+
for (i = 0; i < len; i++) {
|
|
771
|
+
lang = b28Cfg.supportLang[i];
|
|
772
|
+
newOption = new Option(this.langArr[lang], lang);
|
|
773
|
+
selectElem.add(newOption, undefined);
|
|
774
|
+
}
|
|
775
|
+
selectElem.value = this.lang;
|
|
776
|
+
|
|
777
|
+
if (doc.addEventListener) {
|
|
778
|
+
selectElem.addEventListener(
|
|
779
|
+
"change",
|
|
780
|
+
function () {
|
|
781
|
+
this.setLang(doc.getElementById("select-lang").value);
|
|
782
|
+
setTimeout(function () {
|
|
783
|
+
window.location.reload();
|
|
784
|
+
}, 24);
|
|
785
|
+
},
|
|
786
|
+
false
|
|
787
|
+
);
|
|
788
|
+
} else if (doc.attachEvent) {
|
|
789
|
+
selectElem.attachEvent("onchange", function () {
|
|
790
|
+
this.setLang(doc.getElementById("select-lang").value);
|
|
791
|
+
setTimeout(function () {
|
|
792
|
+
window.location.reload();
|
|
793
|
+
}, 24);
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
},
|
|
798
|
+
|
|
799
|
+
/**
|
|
800
|
+
* 翻译translateTarget及translateTarget里面的内容
|
|
801
|
+
* @param {element} translateTarget 需要翻译的内容的容器
|
|
802
|
+
*/
|
|
803
|
+
translate: function (translateTarget) {
|
|
804
|
+
let translateElem;
|
|
805
|
+
//确定html容器元素
|
|
806
|
+
if (assertElement(translateTarget)) {
|
|
807
|
+
translateElem = translateTarget;
|
|
808
|
+
} else if (translateTarget && typeof translateTarget === "string") {
|
|
809
|
+
translateElem = doc.getElementById(translateTarget);
|
|
810
|
+
}
|
|
811
|
+
translateElem = translateElem || doc.documentElement;
|
|
812
|
+
// 隐藏页面
|
|
813
|
+
doc.documentElement.style.visibility = "hidden";
|
|
814
|
+
// 逐个翻译元素
|
|
815
|
+
this.replaceTextNodeValue(translateElem);
|
|
816
|
+
|
|
817
|
+
this.saveLang = false;
|
|
818
|
+
// 显示页面
|
|
819
|
+
doc.documentElement.style.visibility = "visible";
|
|
820
|
+
// 执行翻译完成后的回调
|
|
821
|
+
if (typeof this.success === "function") {
|
|
822
|
+
this.success();
|
|
823
|
+
}
|
|
824
|
+
},
|
|
825
|
+
|
|
826
|
+
/**
|
|
827
|
+
* 翻译页面
|
|
828
|
+
*/
|
|
829
|
+
translatePage: function () {
|
|
830
|
+
let bodyElem = doc.body || doc.documentElement;
|
|
831
|
+
|
|
832
|
+
// 翻译HTML页面内容
|
|
833
|
+
this.transTitle(this.original.title);
|
|
834
|
+
|
|
835
|
+
// 初始语言选择下拉框
|
|
836
|
+
b28Cfg.initSelect && this.initSelectElem();
|
|
837
|
+
//全局翻译时需要记录所有的信息
|
|
838
|
+
this.saveLang = true;
|
|
839
|
+
this.translate(bodyElem);
|
|
840
|
+
},
|
|
841
|
+
};
|
|
842
|
+
|
|
843
|
+
let Butterlate = new Butterlation(),
|
|
844
|
+
defaultLang;
|
|
845
|
+
|
|
846
|
+
//将翻译对象挂载到window上面
|
|
847
|
+
win.Butterlate = Butterlate;
|
|
848
|
+
win.B = win.B || win.Butterlate;
|
|
849
|
+
win._ = function (key, replacements) {
|
|
850
|
+
return Butterlate.getFormatText(key, replacements);
|
|
851
|
+
};
|
|
852
|
+
win.Butterlate.loadScript = loadScript;
|
|
853
|
+
if (window.beforeTranslate) {
|
|
854
|
+
defaultLang = window.beforeTranslate();
|
|
855
|
+
}
|
|
856
|
+
window.B.setTextDomain("lang", defaultLang);
|
|
857
|
+
})(window, document);
|