i18n-jsautotranslate 1.0.0

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.
Files changed (3) hide show
  1. package/index.js +671 -0
  2. package/package.json +16 -0
  3. package/readme.md +381 -0
package/index.js ADDED
@@ -0,0 +1,671 @@
1
+ /* Open source code锛歨ttps://gitee.com/mail_osc/translate */
2
+ const translate = {
3
+ version: "2.2.3.20230217",
4
+ useVersion: "v1",
5
+ setUseVersion2: function () {
6
+ translate.useVersion = "v2"
7
+ },
8
+ translate: null,
9
+ includedLanguages: "zh-CN,zh-TW,en",
10
+ resourcesUrl: "//res.zvo.cn/translate",
11
+ selectLanguageTag: {
12
+ show: !0,
13
+ languages: "",
14
+ alreadyRender: !1,
15
+ selectOnChange: function (e) {
16
+ var t = e.target.value;
17
+ translate.changeLanguage(t)
18
+ },
19
+ render: function () {
20
+ if (!translate.selectLanguageTag.alreadyRender && (translate.selectLanguageTag.alreadyRender = !0,
21
+ translate.selectLanguageTag.show)) {
22
+ if (null == document.getElementById("translate")) {
23
+ var e = document.getElementsByTagName("body")[0],
24
+ t = document.createElement("div");
25
+ t.id = "translate", e.appendChild(t)
26
+ } else if (null != document.getElementById("translateSelectLanguage")) return;
27
+ translate.request.post(translate.request.api.host + translate.request.api.language + "?v=" +
28
+ translate.version, {},
29
+ function (e) {
30
+ if (0 != e.result) {
31
+ var t = function (e) {
32
+ translate.selectLanguageTag.selectOnChange(e)
33
+ },
34
+ a = document.createElement("select");
35
+ a.id = "translateSelectLanguage", a.className = "translateSelectLanguage";
36
+ for (var n = 0; n < e.list.length; n++) {
37
+ var l = document.createElement("option");
38
+ if (l.setAttribute("value", e.list[n].id), translate.selectLanguageTag.languages
39
+ .length > 0) {
40
+ var r = ("," + translate.selectLanguageTag.languages + ",").toLowerCase();
41
+ if (console.log(r), r.indexOf("," + e.list[n].id.toLowerCase() + ",") <
42
+ 0) continue
43
+ }
44
+ null != translate.to && void 0 !== translate.to && translate.to.length > 0 ?
45
+ translate.to == e.list[n].id && l.setAttribute("selected", "selected") :
46
+ e.list[n].id == translate.language.getLocal() && l.setAttribute(
47
+ "selected", "selected"), l.appendChild(document.createTextNode(e.list[
48
+ n].name)), a.appendChild(l)
49
+ }
50
+ window.addEventListener ? a.addEventListener("change", t, !1) : a.attachEvent(
51
+ "onchange", t), document.getElementById("translate").appendChild(a)
52
+ } else console.log("load language list error : " + e.info)
53
+ })
54
+ }
55
+ }
56
+ },
57
+ localLanguage: "zh-CN",
58
+ googleTranslateElementInit: function () {
59
+ var e = "";
60
+ null != document.getElementById("translate") && (e = "translate"), translate.translate = new google.translate
61
+ .TranslateElement({
62
+ pageLanguage: "zh-CN",
63
+ includedLanguages: translate.selectLanguageTag.languages,
64
+ layout: 0
65
+ }, e)
66
+ },
67
+ init: function () {
68
+ var e = window.location.protocol;
69
+ "file:" == window.location.protocol && (e = "http:"), -1 == this.resourcesUrl.indexOf("://") && (this.resourcesUrl =
70
+ e + this.resourcesUrl)
71
+ },
72
+ execute_v1: function () {
73
+ if (null == document.getElementById("translate") && translate.selectLanguageTag.show) {
74
+ var e = document.getElementsByTagName("body")[0],
75
+ t = document.createElement("div");
76
+ t.id = "translate", e.appendChild(t)
77
+ }
78
+ "" == translate.includedLanguages && (translate.selectLanguageTag.languages = translate.includedLanguages),
79
+ console.log(
80
+ "translate.js tip: translate.includedLanguages obsolete, please use the translate.selectLanguageTag.languages are set"
81
+ );
82
+ var a = document.getElementsByTagName("head")[0],
83
+ n = document.createElement("script");
84
+ n.type = "text/javascript", n.src = this.resourcesUrl + "/js/element.js", a.appendChild(n)
85
+ },
86
+ setCookie: function (e, t) {
87
+ var a = e + "=" + escape(t);
88
+ document.cookie = a
89
+ },
90
+ getCookie: function (e) {
91
+ for (var t = document.cookie.split("; "), a = 0; a < t.length; a++) {
92
+ var n = t[a].split("=");
93
+ if (n[0] == e) return unescape(n[1])
94
+ }
95
+ return ""
96
+ },
97
+ currentLanguage: function () {
98
+ translate.check();
99
+ var e = translate.getCookie("googtrans");
100
+ return e.length > 0 ? e.substr(e.lastIndexOf("/") + 1, e.length - 1) : translate.localLanguage
101
+ },
102
+ changeLanguage: function (e) {
103
+ if (
104
+ ",en,de,hi,lt,hr,lv,ht,hu,zh-CN,hy,uk,mg,id,ur,mk,ml,mn,af,mr,uz,ms,el,mt,is,it,my,es,et,eu,ar,pt-PT,ja,ne,az,fa,ro,nl,en-GB,no,be,fi,ru,bg,fr,bs,sd,se,si,sk,sl,ga,sn,so,gd,ca,sq,sr,kk,st,km,kn,sv,ko,sw,gl,zh-TW,pt-BR,co,ta,gu,ky,cs,pa,te,tg,th,la,cy,pl,da,tr,"
105
+ .indexOf("," + e + ",") > -1) {
106
+ translate.check();
107
+ var t = "/" + translate.localLanguage + "/" + e,
108
+ a = document.location.host.split(".");
109
+ if (a.length > 2) {
110
+ var n = a[a.length - 2] + "." + a[a.length - 1];
111
+ document.cookie = "googtrans=;expires=" + new Date(1) + ";domain=" + n + ";path=/", document.cookie =
112
+ "googtrans=" + t + ";domain=" + n + ";path=/"
113
+ }
114
+ return translate.setCookie("googtrans", "" + t), void location.reload()
115
+ }
116
+ if (translate.setUseVersion2(), null != translate.to && translate.to.length > 0 && translate.to !=
117
+ translate.language.getLocal()) var l = !0;
118
+ translate.to = e, translate.storage.set("to", e), l ? location.reload() : translate.execute()
119
+ },
120
+ check: function () {
121
+ "file:" == window.location.protocol && console.log(
122
+ "\r\n---WARNING----\r\ntranslate.js 涓诲姩缈昏瘧缁勪欢鑷寮傚父锛屽綋鍓嶅崗璁槸file鍗忚锛岀炕璇戠粍浠惰鍦ㄦ甯哥殑绾夸笂http銆乭ttps鍗忚涓嬫墠鑳芥甯镐娇鐢ㄧ炕璇戝姛鑳絓r\n------------"
123
+ )
124
+ },
125
+ to: "",
126
+ autoDiscriminateLocalLanguage: !1,
127
+ documents: [],
128
+ ignore: {
129
+ tag: ["style", "script", "img", "link", "i", "pre", "code"],
130
+ class: ["ignore", "translateSelectLanguage"],
131
+ id: [],
132
+ isIgnore: function (e) {
133
+ if (null == e || void 0 === e) return !1;
134
+ for (var t = e, a = 100; a-- > 0;) {
135
+ if (null == t || void 0 === t) return !1;
136
+ var n = translate.element.getNodeName(t).toLowerCase();
137
+ if (n.length > 0) {
138
+ if ("body" == n || "html" == n || "#document" == n) return !1;
139
+ if (translate.ignore.tag.indexOf(n) > -1) return !0
140
+ }
141
+ if (null != t.className) {
142
+ var l = t.className;
143
+ if (null == l || "string" != typeof l) continue;
144
+ l = l.trim().split(" ");
145
+ for (var r = 0; r < l.length; r++)
146
+ if (null != l[r] && l[r].trim().length > 0 && translate.ignore.class.indexOf(l[r]) > -1)
147
+ return !0
148
+ }
149
+ if (null != t.id && void 0 !== t.id && translate.ignore.id.indexOf(t.id) > -1) return !0;
150
+ t = t.parentNode
151
+ }
152
+ return !1
153
+ }
154
+ },
155
+ nomenclature: {
156
+ data: new Array,
157
+ old_Data: [],
158
+ set: function (e) {
159
+ alert(
160
+ "璇峰皢 translate.nomenclature.set 鏇存崲涓� append锛屽叿浣撲娇鐢ㄥ彲鍙傝€冿細 https://github.com/xnx3/translate "
161
+ )
162
+ },
163
+ append: function (e, t, a) {
164
+ void 0 === translate.nomenclature.data[e] && (translate.nomenclature.data[e] = new Array), void 0 ===
165
+ translate.nomenclature.data[e][t] && (translate.nomenclature.data[e][t] = new Array);
166
+ for (var n = a.split("\n"), l = 0; l < n.length; l++) {
167
+ var r = n[l].trim();
168
+ if (!(r.length < 1)) {
169
+ var s = r.split("=");
170
+ if (2 == s.length) {
171
+ var o = s[0].trim(),
172
+ u = s[1].trim();
173
+ 0 != o.length && 0 != u.length && (translate.nomenclature.data[e][t][o] = u)
174
+ }
175
+ }
176
+ }
177
+ },
178
+ get: function () {
179
+ return translate.nomenclature.data
180
+ },
181
+ dispose: function (e) {
182
+ if (null == e || 0 == e.length) return e;
183
+ if (void 0 === translate.nomenclature.data[translate.language.getLocal()] || void 0 === translate.nomenclature
184
+ .data[translate.language.getLocal()][translate.to]) return e;
185
+ for (var t in translate.nomenclature.data[translate.language.getLocal()][translate.to]) {
186
+ var a = translate.nomenclature.data[translate.language.getLocal()][translate.to][t];
187
+ if ("function" != typeof a) {
188
+ var n = e.indexOf(t);
189
+ if (n > -1)
190
+ if ("english" == translate.language.getLocal()) {
191
+ var l = "";
192
+ if (0 == n);
193
+ else if (l = e.substr(n - 1, 1), "english" == translate.language.getCharLanguage(l))
194
+ continue;
195
+ var r = "";
196
+ if (n + t.length == e.length);
197
+ else if (r = e.substr(n + t.length, 1), "english" == translate.language.getCharLanguage(
198
+ r)) continue;
199
+ e = e.replace(new RegExp(l + t + r, "g"), l + a + r)
200
+ } else e = e.replace(new RegExp(t, "g"), a)
201
+ }
202
+ }
203
+ return e
204
+ }
205
+ },
206
+ setAutoDiscriminateLocalLanguage: function () {
207
+ translate.autoDiscriminateLocalLanguage = !0
208
+ },
209
+ nodeQueue: {},
210
+ setDocuments: function (e) {
211
+ null != e && void 0 !== e && (void 0 === e.length ? translate.documents[0] = e : translate.documents =
212
+ e, translate.nodeQueue = {}, console.log("set documents , clear translate.nodeQueue"))
213
+ },
214
+ getDocuments: function () {
215
+ return null != translate.documents && void 0 !== translate.documents && translate.documents.length > 0 ?
216
+ translate.documents : document.all
217
+ },
218
+ listener: {
219
+ isExecuteFinish: !1,
220
+ isStart: !1,
221
+ start: function () {
222
+ translate.temp_linstenerStartInterval = setInterval(function () {
223
+ "complete" == document.readyState && (clearInterval(translate.temp_linstenerStartInterval),
224
+ translate.listener.addListener())
225
+ }, 50)
226
+ },
227
+ addListener: function () {
228
+ translate.listener.isStart = !0;
229
+ const e = {
230
+ attributes: !0,
231
+ childList: !0,
232
+ subtree: !0
233
+ },
234
+ t = new MutationObserver(function (e, t) {
235
+ var a = [];
236
+ for (let t of e) "childList" === t.type && t.addedNodes.length > 0 && a.push.apply(a, t
237
+ .addedNodes);
238
+ a.length > 0 && translate.execute(a)
239
+ });
240
+ for (var a = translate.getDocuments(), n = 0; n < a.length; n++) {
241
+ var l = a[n];
242
+ null != l && t.observe(l, e)
243
+ }
244
+ },
245
+ renderTaskFinish: function (e) { }
246
+ },
247
+ renderTask: class {
248
+ constructor() {
249
+ this.taskQueue = [], this.nodes = []
250
+ }
251
+ add(e, t, a) {
252
+ var n = translate.element.nodeAnalyse.get(e),
253
+ l = translate.util.hash(n.text);
254
+ void 0 === this.nodes[l] && (this.nodes[l] = new Array), this.nodes[l].push(e);
255
+ var r = this.taskQueue[l];
256
+ null != r && void 0 !== r || (r = new Array);
257
+ var s = new Array;
258
+ s.originalText = t, s.resultText = a, r.push(s), this.taskQueue[l] = r
259
+ }
260
+ execute() {
261
+ for (var e in this.taskQueue) {
262
+ "function" != typeof (t = this.taskQueue[e]) && (this.taskQueue[e] = t)
263
+ }
264
+ for (var e in this.nodes)
265
+ for (var t = this.taskQueue[e], a = 0; a < this.nodes[e].length; a++)
266
+ for (var n = 0; n < t.length; n++) {
267
+ var l = t[n];
268
+ "function" != typeof t && translate.element.nodeAnalyse.set(this.nodes[e][n], l.originalText,
269
+ l.resultText)
270
+ }
271
+ void 0 !== this.taskQueue && this.taskQueue.length > 0 && translate.listener.renderTaskFinish(
272
+ this)
273
+ }
274
+ },
275
+ execute: function (e) {
276
+ if ("undefined" != typeof doc && (translate.useVersion = "v2"), "v1" != translate.useVersion) {
277
+ var t = translate.util.uuid();
278
+ if (translate.nodeQueue[t] = new Array, translate.nodeQueue[t].expireTime = Date.now() + 12e4,
279
+ translate.nodeQueue[t].list = new Array, null == translate.to || "" == translate.to) {
280
+ var a = translate.storage.get("to");
281
+ null != a && void 0 !== a && a.length > 0 && (translate.to = a)
282
+ }
283
+ try {
284
+ translate.selectLanguageTag.render()
285
+ } catch (e) {
286
+ console.log(e)
287
+ }
288
+ if (null != translate.to && void 0 !== translate.to && 0 != translate.to.length) {
289
+ if (translate.to != translate.language.getLocal()) {
290
+ var n;
291
+ if (void 0 !== e) {
292
+ if (null == e) return void cnosole.log(
293
+ "translate.execute(...) 涓紶鍏ョ殑瑕佺炕璇戠殑鐩爣鍖哄煙涓嶅瓨鍦ㄣ€�");
294
+ void 0 === e.length ? (n = new Array)[0] = e : n = e
295
+ } else n = translate.getDocuments();
296
+ for (var l = 0; l < n.length & l < 20; l++) {
297
+ var r = n[l];
298
+ translate.element.whileNodes(t, r)
299
+ }
300
+ var s = {},
301
+ o = {};
302
+ for (var u in translate.nodeQueue[t].list) {
303
+ if (null == u || void 0 === u || 0 == u.length || "undefined" == u) continue;
304
+ s[u] = [], o[u] = [];
305
+ let e = new translate.renderTask;
306
+ for (var i in translate.nodeQueue[t].list[u])
307
+ if ("function" != typeof translate.nodeQueue[t].list[u][i]) {
308
+ var g = translate.nodeQueue[t].list[u][i].original,
309
+ c = translate.nodeQueue[t].list[u][i].translateText,
310
+ d = g == c ? i : translate.util.hash(c);
311
+ translate.nodeQueue[t].list[u][i].cacheHash = d;
312
+ var f = translate.storage.get("hash_" + translate.to + "_" + d);
313
+ if (null != f && f.length > 0)
314
+ for (var h = 0; h < translate.nodeQueue[t].list[u][i].nodes.length; h++) e.add(
315
+ translate.nodeQueue[t].list[u][i].nodes[h], g, translate.nodeQueue[
316
+ t].list[u][i].beforeText + f + translate.nodeQueue[t].list[u][i]
317
+ .afterText);
318
+ else s[u].push(c), o[u].push(i)
319
+ } e.execute()
320
+ }
321
+ var v = [];
322
+ for (var u in translate.nodeQueue[t].list) s[u].length < 1 || v.push(u);
323
+ if (translate.listener.isExecuteFinish || (translate.temp_executeFinishNumber = 0,
324
+ translate.temp_executeFinishInterval = setInterval(function () {
325
+ translate.temp_executeFinishNumber == v.length && (translate.listener.isExecuteFinish = !
326
+ 0, clearInterval(translate.temp_executeFinishInterval))
327
+ }, 50)), 0 != v.length)
328
+ for (var p in v) {
329
+ u = v[p];
330
+ if (void 0 === s[u] || s[u].length < 1) return;
331
+ var m = translate.request.api.host + translate.request.api.translate + "?v=" +
332
+ translate.version,
333
+ x = {
334
+ from: u,
335
+ to: translate.to,
336
+ text: encodeURIComponent(JSON.stringify(s[u]))
337
+ };
338
+ translate.request.post(m, x, function (e) {
339
+ if (0 == e.result) return console.log("=======ERROR START======="),
340
+ console.log(s[e.from]), console.log("response : " + e.info),
341
+ console.log("=======ERROR END ======="), void translate.temp_executeFinishNumber++;
342
+ let a = new translate.renderTask;
343
+ for (var n = 0; n < o[e.from].length; n++) {
344
+ var l = e.from,
345
+ r = e.text[n],
346
+ u = o[e.from][n],
347
+ i = translate.nodeQueue[t].list[l][u].cacheHash,
348
+ g = "";
349
+ try {
350
+ g = translate.nodeQueue[t].list[l][u].original
351
+ } catch (e) {
352
+ console.log("uuid:" + t + ", originalWord:" + g + ", lang:" + l +
353
+ ", hash:" + u + ", text:" + r + ", queue:" + translate.nodeQueue[
354
+ t]), console.log(e);
355
+ continue
356
+ }
357
+ for (var c = 0; c < translate.nodeQueue[t].list[l][u].nodes.length; c++)
358
+ a.add(translate.nodeQueue[t].list[l][u].nodes[c], g, translate.nodeQueue[
359
+ t].list[l][u].beforeText + r + translate.nodeQueue[t].list[
360
+ l][u].afterText);
361
+ translate.storage.set("hash_" + e.to + "_" + i, r)
362
+ }
363
+ a.execute(), translate.temp_executeFinishNumber++
364
+ })
365
+ }
366
+ }
367
+ } else translate.autoDiscriminateLocalLanguage && translate.executeByLocalLanguage()
368
+ } else translate.execute_v1()
369
+ },
370
+ element: {
371
+ nodeAnalyse: {
372
+ get: function (e) {
373
+ return translate.element.nodeAnalyse.analyse(e, "", "")
374
+ },
375
+ set: function (e, t, a) {
376
+ translate.element.nodeAnalyse.analyse(e, t, a)
377
+ },
378
+ analyse: function (e, t, a) {
379
+ var n = new Array;
380
+ n.node = e, n.text = "";
381
+ var l = translate.element.getNodeName(e);
382
+ "#text" == l && (void 0 !== e.parentNode && "TEXTAREA" == translate.element.getNodeName(e.parentNode) &&
383
+ (l = "TEXTAREA", e = e.parentNode));
384
+ if ("INPUT" == l || "TEXTAREA" == l) {
385
+ if (null == e.attributes || void 0 === e.attributes) return n.text = "", n;
386
+ if ("INPUT" == l && void 0 !== e.attributes.type && null != typeof e.attributes.type.nodeValue &&
387
+ ("button" == e.attributes.type.nodeValue.toLowerCase() || "submit" == e.attributes.type
388
+ .nodeValue.toLowerCase())) {
389
+ var r = e.attributes.value;
390
+ if (null != r && void 0 !== r && void 0 !== r.nodeValue && r.nodeValue.length > 0)
391
+ return void 0 !== t && t.length > 0 && (r.nodeValue = r.nodeValue.replace(new RegExp(
392
+ translate.util.regExp.pattern(t), "g"), translate.util.regExp.resultText(
393
+ a))), n.text = r.nodeValue, n.node = r, n
394
+ }
395
+ return void 0 !== e.attributes.placeholder ? (void 0 !== t && t.length > 0 && (e.attributes
396
+ .placeholder.nodeValue = e.attributes.placeholder.nodeValue.replace(new RegExp(
397
+ translate.util.regExp.pattern(t), "g"), translate.util.regExp.resultText(
398
+ a))), n.text = e.attributes.placeholder.nodeValue, n.node = e.attributes.placeholder,
399
+ n) : (n.text = "", n)
400
+ }
401
+ if ("META" == l) {
402
+ if (void 0 !== e.name && null != e.name) {
403
+ var s = e.name.toLowerCase();
404
+ if ("keywords" == s || "description" == s) return void 0 !== t && t.length > 0 && (e.content =
405
+ e.content.replace(new RegExp(translate.util.regExp.pattern(t), "g"),
406
+ translate.util.regExp.resultText(a))), n.text = e.content, n
407
+ }
408
+ return n.text = "", n
409
+ }
410
+ return "IMG" == l ? void 0 === e.alt || null == e.alt ? (n.text = "", n) : (void 0 !== t && t.length >
411
+ 0 && (e.alt = e.alt.replace(new RegExp(translate.util.regExp.pattern(t), "g"),
412
+ translate.util.regExp.resultText(a))), n.text = e.alt, n) : (null == e.nodeValue ||
413
+ void 0 === e.nodeValue ? n.text = "" : 0 == e.nodeValue.trim().length ? n.text = "" : (
414
+ void 0 !== t && t.length > 0 && (e.nodeValue = e.nodeValue.replace(new RegExp(
415
+ translate.util.regExp.pattern(t), "g"), translate.util.regExp.resultText(
416
+ a))), n.text = e.nodeValue), n)
417
+ }
418
+ },
419
+ getNodeName: function (e) {
420
+ return null == e || void 0 === e ? "" : null == e.nodeName || void 0 === e.nodeName ? "" : e.nodeName
421
+ },
422
+ whileNodes: function (e, t) {
423
+ if (null != t && void 0 !== t) {
424
+ var a = t.childNodes;
425
+ if (a.length > 0)
426
+ for (var n = 0; n < a.length; n++) translate.element.whileNodes(e, a[n]);
427
+ else translate.element.findNode(e, t)
428
+ }
429
+ },
430
+ findNode: function (e, t) {
431
+ if (null != t && void 0 !== t && null != t.parentNode) {
432
+ var a = translate.element.getNodeName(t.parentNode);
433
+ if ("" != a && !(translate.ignore.tag.indexOf(a.toLowerCase()) > -1)) {
434
+ for (var n = !1, l = t.parentNode; t != l && null != l;) null != l.className && translate.ignore
435
+ .class.indexOf(l.className) > -1 && (n = !0), l = l.parentNode;
436
+ if (!n && !translate.ignore.isIgnore(t)) {
437
+ var r = translate.element.nodeAnalyse.get(t);
438
+ r.text.length > 0 && translate.addNodeToQueue(e, r.node, r.text)
439
+ }
440
+ }
441
+ }
442
+ }
443
+ },
444
+ addNodeToQueue: function (e, t, a) {
445
+ if (null != t && null != a && 0 != a.length && "#comment" != translate.element.getNodeName(t).toLowerCase()) {
446
+ translate.util.hash(a);
447
+ if (translate.util.findTag(a)) {
448
+ if (null == t.parentNode) return;
449
+ var n = translate.element.getNodeName(t.parentNode);
450
+ if ("SCRIPT" == n || "STYLE" == n) return
451
+ }
452
+ var l = translate.language.get(a);
453
+ for (var r in void 0 !== l[translate.to] && delete l[translate.to], l) {
454
+ null != translate.nodeQueue[e].list[r] && void 0 !== translate.nodeQueue[e].list[r] || (
455
+ translate.nodeQueue[e].list[r] = new Array);
456
+ for (var s = 0; s < l[r].length; s++)
457
+ if (void 0 !== l[r][s] && void 0 !== l[r][s].text) {
458
+ var o = l[r][s].text,
459
+ u = l[r][s].beforeText,
460
+ i = l[r][s].afterText,
461
+ g = translate.util.hash(o);
462
+ if (null != translate.nodeQueue[e].list[r][g] && void 0 !== translate.nodeQueue[e].list[
463
+ r][g] || (translate.nodeQueue[e].list[r][g] = new Array, translate.nodeQueue[e]
464
+ .list[r][g].nodes = new Array, translate.nodeQueue[e].list[r][g].original = o,
465
+ translate.nodeQueue[e].list[r][g].translateText = translate.nomenclature.dispose(
466
+ o), translate.nodeQueue[e].list[r][g].beforeText = u, translate.nodeQueue[e]
467
+ .list[r][g].afterText = i), void 0 !== t.isSameNode)
468
+ for (var c = 0; c < translate.nodeQueue[e].list[r][g].nodes.length; c++)
469
+ if (t.isSameNode(translate.nodeQueue[e].list[r][g].nodes[c])) return;
470
+ translate.nodeQueue[e].list[r][g].nodes[translate.nodeQueue[e].list[r][g].nodes.length] =
471
+ t
472
+ }
473
+ }
474
+ }
475
+ },
476
+ language: {
477
+ local: "",
478
+ setLocal: function (e) {
479
+ translate.setUseVersion2(), translate.language.local = e
480
+ },
481
+ getLocal: function () {
482
+ return (null == translate.language.local || translate.language.local.length < 1) && translate.language
483
+ .autoRecognitionLocalLanguage(), translate.language.local
484
+ },
485
+ autoRecognitionLocalLanguage: function () {
486
+ if (!(null != translate.language.local && translate.language.local.length > 2)) {
487
+ var e = document.body.outerText;
488
+ if (null == e || void 0 === e || e.length < 1) translate.language.local = "chinese_simplified";
489
+ else {
490
+ e = e.replace(/\n|\t|\r/g, "");
491
+ for (var t = new Array, a = 0; a < e.length; a++) {
492
+ var n = e.charAt(a),
493
+ l = translate.language.getCharLanguage(n);
494
+ "" == l && (l = "unidentification"), t.push(l)
495
+ }
496
+ var r = translate.util.arrayFindMaxNumber(t),
497
+ s = r.indexOf("specialCharacter");
498
+ s > -1 && r.splice(s, 1), r.length > 0 ? translate.language.local = r[0] : translate.language
499
+ .local = "chinese_simplified"
500
+ }
501
+ }
502
+ },
503
+ get: function (e) {
504
+ for (var t = new Array, a = new Array, n = [], l = [], r = 0; r < e.length; r++) {
505
+ var s = e.charAt(r),
506
+ o = translate.language.getCharLanguage(s);
507
+ "" == o && (o = "unidentification");
508
+ var u = translate.language.analyse(o, a, n, l, s);
509
+ a = u.langStrs, void 0 !== n.language && (l.language = n.language, l.charstr = n.charstr, l.storage_language =
510
+ n.storage_language), n.language = u.storage_language, n.charstr = s, n.storage_language =
511
+ u.storage_language, t.push(o)
512
+ }
513
+ return void 0 !== a.unidentification && delete a.unidentification, void 0 !== a.specialCharacter &&
514
+ delete a.specialCharacter, void 0 !== a.number && delete a.number, a
515
+ },
516
+ getCharLanguage: function (e) {
517
+ return null == e || void 0 === e ? "" : this.english(e) ? "english" : this.specialCharacter(e) ?
518
+ "specialCharacter" : this.number(e) ? "number" : this.chinese_simplified(e) ?
519
+ "chinese_simplified" : this.japanese(e) ? "japanese" : this.korean(e) ? "korean" : (console.log(
520
+ "not find is language , char : " + e + ", unicode: " + e.charCodeAt(0).toString(16)),
521
+ "")
522
+ },
523
+ analyse: function (e, t, a, n, l) {
524
+ void 0 === t[e] && (t[e] = new Array);
525
+ var r = 0;
526
+ void 0 === a.storage_language || (translate.language.connector(l) && (e = a.storage_language), r =
527
+ a.storage_language == e ? t[e].length - 1 : t[e].length), void 0 === t[e][r] && (t[e][r] =
528
+ new Array, t[e][r].beforeText = "", t[e][r].afterText = "", t[e][r].text = ""), t[e][r].text =
529
+ t[e][r].text + l, "english" != translate.language.getLocal() && "english" == translate.to &&
530
+ null != a.storage_language && void 0 !== a.storage_language && a.storage_language.length > 0 &&
531
+ "specialCharacter" != a.storage_language && ("english" != a.storage_language && "english" == e ?
532
+ t[a.storage_language][t[a.storage_language].length - 1].afterText = " " : "english" == a.storage_language &&
533
+ "english" != e && (t[e][r].beforeText = " "));
534
+ var s = new Array;
535
+ return s.langStrs = t, s.storage_language = e, s
536
+ },
537
+ connector: function (e) {
538
+ return !!/.*[\u0020\u00A0\u202F\u205F\u3000]+.*$/.test(e) || (!!/.*[\u0030-\u0039]+.*$/.test(e) ||
539
+ (!!
540
+ /.*[\u0021\u0022\u0023\u0024\u0025\u0026\u0027\u002C\u002D\u002E\u003A\u003B\u003F\u0040]+.*$/
541
+ .test(e) || !!
542
+ /.*[\u3002\uFF1F\uFF01\uFF0C\u3001\uFF1B\uFF1A\u300C\u300D\u300E\u300F\u2018\u2019\u201C\u201D\uFF08\uFF09\u3014\u3015\u3010\u3011\u2014\u2026\u2013\uFF0E\u300A\u300B\u3008\u3009\u00b7]+.*$/
543
+ .test(e)))
544
+ },
545
+ chinese_simplified: function (e) {
546
+ return !!/.*[\u4e00-\u9fa5]+.*$/.test(e)
547
+ },
548
+ english: function (e) {
549
+ return !!/.*[\u0041-\u005a]+.*$/.test(e) || !!/.*[\u0061-\u007a]+.*$/.test(e)
550
+ },
551
+ japanese: function (e) {
552
+ return !!/.*[\u0800-\u4e00]+.*$/.test(e)
553
+ },
554
+ korean: function (e) {
555
+ return !!/.*[\uAC00-\uD7AF]+.*$/.test(e)
556
+ },
557
+ number: function (e) {
558
+ return !!/.*[\u0030-\u0039]+.*$/.test(e)
559
+ },
560
+ specialCharacter: function (e) {
561
+ return !!/.*[\u2460-\u24E9]+.*$/.test(e) || (!!/.*[\u2500-\u25FF]+.*$/.test(e) || (!!
562
+ /.*[\u3200-\u33FF]+.*$/.test(e) || (!!/.*[\uFF00-\uFF5E]+.*$/.test(e) || (!!
563
+ /.*[\u2000-\u22FF]+.*$/.test(e) || (!!/.*[\u3001-\u3036]+.*$/.test(e) || (!!
564
+ /.*[\u0020-\u002F]+.*$/.test(e) || (!!/.*[\u003A-\u007E]+.*$/.test(e) ||
565
+ (!!
566
+ /.*[\u0009\u000a\u0020\u00A0\u1680\u180E\u202F\u205F\u3000\uFEFF]+.*$/
567
+ .test(e) || (!!/.*[\u2000-\u200B]+.*$/.test(e) || (!!
568
+ /.*[\u00A1-\u0105]+.*$/.test(e) || !!
569
+ /.*[\u2C60-\u2C77]+.*$/.test(e)))))))))))
570
+ }
571
+ },
572
+ executeByLocalLanguage: function () {
573
+ translate.request.post(translate.request.api.host + translate.request.api.ip + "?v=" + translate.version, {},
574
+ function (e) {
575
+ 0 == e.result ? (console.log("==== ERROR 鑾峰彇褰撳墠鐢ㄦ埛鎵€鍦ㄥ尯鍩熷紓甯� ===="), console.log(e.info),
576
+ console.log("==== ERROR END ====")) : (translate.setUseVersion2(), translate.storage
577
+ .set("to", e.language), translate.to = e.language, translate.selectLanguageTag,
578
+ translate.execute())
579
+ })
580
+ },
581
+ util: {
582
+ uuid: function () {
583
+ var e = (new Date).getTime();
584
+ return window.performance && "function" == typeof window.performance.now && (e += performance.now()),
585
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".replace(/[xy]/g, function (t) {
586
+ var a = (e + 16 * Math.random()) % 16 | 0;
587
+ return e = Math.floor(e / 16), ("x" == t ? a : 3 & a | 8).toString(16)
588
+ })
589
+ },
590
+ findTag: function (e) {
591
+ return /<[^>]+>/g.test(e)
592
+ },
593
+ arrayFindMaxNumber: function (e) {
594
+ for (var t = {}, a = [], n = 0, l = 0, r = e.length; l < r; l++) t[e[l]] ? t[e[l]]++ : t[e[l]] = 1,
595
+ t[e[l]] > n && (n = t[e[l]]);
596
+ for (var s in t) t[s] === n && a.push(s);
597
+ return a
598
+ },
599
+ hash: function (e) {
600
+ if (null == e || void 0 === e) return e;
601
+ var t, a = 0;
602
+ if (0 === e.length) return a;
603
+ for (t = 0; t < e.length; t++) a = (a << 5) - a + e.charCodeAt(t), a |= 0;
604
+ return a + ""
605
+ },
606
+ charReplace: function (e) {
607
+ return null == e ? "" : e = (e = e.trim()).replace(/\t|\n|\v|\r|\f/g, "")
608
+ },
609
+ regExp: {
610
+ pattern: function (e) {
611
+ return e = (e = e.replace(/\"/g, '\\"')).replace(/\?/g, "\\?")
612
+ },
613
+ resultText: function (e) {
614
+ return e
615
+ }
616
+ }
617
+ },
618
+ request: {
619
+ api: {
620
+ host: "https://api.translate.zvo.cn/",
621
+ language: "language.json",
622
+ translate: "translate.json",
623
+ ip: "ip.json"
624
+ },
625
+ post: function (e, t, a) {
626
+ this.send(e, t, a, "post", !0, {
627
+ "content-type": "application/x-www-form-urlencoded"
628
+ }, null)
629
+ },
630
+ send: function (e, t, a, n, l, r, s) {
631
+ var o = "";
632
+ if (null != t)
633
+ for (var u in t) o.length > 0 && (o += "&"), o = o + u + "=" + t[u];
634
+ var i = null;
635
+ try {
636
+ i = new XMLHttpRequest
637
+ } catch (e) {
638
+ i = new ActiveXObject("Microsoft.XMLHTTP")
639
+ }
640
+ if (i.open(n, e, l), null != r)
641
+ for (var u in r) i.setRequestHeader(u, r[u]);
642
+ i.send(o), i.onreadystatechange = function () {
643
+ if (4 == i.readyState)
644
+ if (200 == i.status) {
645
+ var e = null;
646
+ try {
647
+ e = JSON.parse(i.responseText)
648
+ } catch (e) {
649
+ console.log(e)
650
+ }
651
+ a(null == e ? i.responseText : e)
652
+ } else null != s && s(i)
653
+ }
654
+ }
655
+ },
656
+ storage: {
657
+ set: function (e, t) {
658
+ localStorage.setItem(e, t)
659
+ },
660
+ get: function (e) {
661
+ return localStorage.getItem(e)
662
+ }
663
+ }
664
+ };
665
+ try {
666
+ translate.init()
667
+ } catch (e) {
668
+ console.log(e)
669
+ }
670
+
671
+ export default translate
package/package.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "i18n-jsautotranslate",
3
+ "version": "1.0.0",
4
+ "description": "两行js实现html全自动翻译。无需改动页面、无语言配置文件、无API Key、对SEO友好!",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "keywords": [
10
+ "i18n",
11
+ "translatejs",
12
+ "i18n-translatejs"
13
+ ],
14
+ "author": "管雷鸣",
15
+ "license": "ISC"
16
+ }
package/readme.md ADDED
@@ -0,0 +1,381 @@
1
+
2
+ <h1 align="center">
3
+ translate.js
4
+ </h1>
5
+ <h4 align="center">
6
+ 两行js实现html全自动翻译。 <br/>
7
+ 无需改动页面、无语言配置文件、无API Key、对SEO友好!
8
+ </h4>
9
+ <h4 align="center">
10
+ 当前为中文文档 | <a href="../README.md">See English Documents</a>
11
+ </h4>
12
+
13
+
14
+ # 特性
15
+ * **使用极其简单。** 无需任何前期准备,直接加入几行代码即可拥有多种语言全自动切换能力。
16
+ * **不增加工作量。** 无需另行改造页面本身,也没有各种语言都要单独配置的语言文件,更不需要你对页面本身要显示的文字区域进行代码调用,我认为那样对技术人员实在是太不友好了。而且它也不需要你到某某网站申请什么key,它本身就是开放的,拿来即用。
17
+ * **极其灵活扩展。** 您可指定它只翻译某些指定区域、切换语言时显示下拉框还是通过摆放多个切换语言按钮进行、可指定某些特定的元素不进行翻译忽略……
18
+ * **自动匹配语种。** 自动根据用户所在的国家切换其国家所使用的语种
19
+ * **瞬间翻译能力。** 内置缓存预加载机制,只要翻译过的网页,再次看时会达到瞬间翻译的效果,给用户的感觉就是,这个页面本来就是这种语言的,而不是经过第三方翻译的。
20
+ * **永久免费使用。** 采用Apache-2.0开源协议,您可永久免费使用。
21
+ * **搜索引擎友好。** 完全不影响你本身网站搜索引擎的收录。爬虫所爬取的网页源代码,它不会对其进行任何改动,你可完全放心。
22
+ * **后端翻译开源。** 在某些政府机关及大集团内部项目中,对数据隐私及安全保密有强要求场景、或您对自有客户希望提供自建高可靠翻译服务场景时,您可将后端翻译接口进行私有化部署,不走我们公开开放的翻译接口,以做到安全保密及后端服务全部自行掌控。
23
+
24
+
25
+ # 在线体验
26
+ http://res.zvo.cn/translate/demo.html
27
+
28
+
29
+ # 先拿别人的网站动手试试
30
+ ![效果](http://cdn.weiunity.com/site/341/news/9a7228aaae28475996da9026b93356c8.gif "")
31
+
32
+ 1. 随便打开一个网页
33
+ 2. 右键 - 审查元素
34
+ 3. 粘贴入以下代码:
35
+ ```` var head= document.getElementsByTagName('head')[0]; var script= document.createElement('script'); script.type= 'text/javascript'; script.src= 'https://res.zvo.cn/translate/inspector_v2.js'; head.appendChild(script); ````
36
+ 4. Enter 回车键 , 执行
37
+ 5. 在当前网页的左上角,就出现了一个大大的切换语言,切换试试看。
38
+
39
+ # 快速使用
40
+ 在网页最末尾, ````</html>```` 之前,加入以下代码,一般在页面的最底部就出现了选择语言的 select 切换标签。 其实就这么简单:
41
+
42
+ ````
43
+ <script src="https://res.zvo.cn/translate/translate.js"></script>
44
+ <script>
45
+ translate.setUseVersion2(); //设置使用v2.x 版本
46
+ translate.language.setLocal('chinese_simplified'); //设置本地语种(当前网页的语种)。如果不设置,默认自动识别当前网页显示文字的语种。 可填写如 'english'、'chinese_simplified' 等,具体参见文档下方关于此的说明。
47
+ translate.execute();//进行翻译
48
+ </script>
49
+ ````
50
+
51
+ # 更多扩展用法
52
+
53
+ ### 指定切换语言的select选择框的位置
54
+ 你想在你页面什么地方显示,就吧下面这个放到哪即可。
55
+
56
+ ````
57
+ <div id="translate"></div>
58
+ ````
59
+
60
+ 主要是这个 id="translate" 切换语言的按钮会自动赋予这个id里面。当然你也不一定非要是div的,也可以这样
61
+
62
+ ````
63
+ <span id="translate"></span>
64
+ ````
65
+
66
+ ### CSS美化切换语言按钮
67
+ 可使用css来控制切换语言选择的显示位置及美观。如:
68
+
69
+ ````
70
+ <style>
71
+ .translateSelectLanguage{
72
+ position: absolute;
73
+ top:100px;
74
+ right:100px;
75
+ }
76
+ </style>
77
+ ````
78
+ 这就是控制切换语言的 ``<select>`` 标签
79
+
80
+ ### 设定是否自动出现 select 切换语言
81
+
82
+ ````
83
+ /*
84
+ * 是否显示 select选择语言的选择框,true显示; false不显示。默认为true
85
+ * 注意,这行要放到 translate.execute(); 上面
86
+ */
87
+ translate.selectLanguageTag.show = false;
88
+ translate.execute();
89
+ ````
90
+
91
+ 使用场景是,如果使用了:
92
+
93
+ ````
94
+ <a href="javascript:translate.changeLanguage('en');">切换为英语</a>
95
+ ````
96
+
97
+ 这种切换方式,那么 select下拉选择的就用不到了,就可以用此方式来不显示。
98
+ 当然你也可以使用css的方式来控制其不显示。比如:
99
+
100
+ ````
101
+ <style>
102
+ #translate{
103
+ display:none;
104
+ }
105
+ </style>
106
+ ````
107
+
108
+ ### 自定义出现的 select 切换语言所支持的语种
109
+
110
+ ````
111
+ translate.selectLanguageTag.languages = 'english,chinese_simplified,korean'; //每个语种之间用英文,分割。比如这里设置的是支持英语、简体中文、韩语 的切换。根据后端翻译服务不同,支持的语言也不同。具体支持哪些,可通过 http://api.translate.zvo.cn/doc/language.json.html 获取 (如果您私有部署的,将请求域名换为您自己私有部署的域名)
112
+ ````
113
+ 每个语种之间用英文,分割。比如这里设置的是支持英语、简体中文、韩语 的切换。根据后端翻译服务不同,支持的语言也不同。
114
+ 具体支持哪些,可通过 http://api.translate.zvo.cn/doc/language.json.html 获取 (如果您私有部署的,将请求域名换为您自己私有部署的域名)
115
+ **注意,这行要放到 translate.execute(); 上面**
116
+
117
+ ### 翻译时忽略指定的tag标签
118
+
119
+ ````
120
+ translate.ignore.tag.push('span'); //翻译时追加上自己想忽略不进行翻译的tag标签,凡是在这里面的,都不进行翻译。
121
+ ````
122
+ 翻译时追加上自己想忽略不进行翻译的tag标签,凡是在这里面的,都不进行翻译。
123
+ 如果你想查看当前忽略哪些tag标签,可直接执行 ```` console.log(translate.ignore.tag); ```` 进行查看
124
+ **注意,这行要放到 translate.execute(); 上面**
125
+
126
+ ### 翻译时忽略指定的class值
127
+
128
+ ````
129
+ translate.ignore.class.push('test'); //翻译时追加上自己想忽略不进行翻译的class name的值,凡是在这里面的,都不进行翻译。
130
+ ````
131
+ 翻译时追加上自己想忽略不进行翻译的class标签,凡是在这里面的,都不进行翻译。
132
+ 如果你想查看当前忽略哪些class,可直接执行 ```` console.log(translate.ignore.class); ```` 进行查看
133
+ **注意,这行要放到 translate.execute(); 上面**
134
+
135
+ ### 翻译时忽略指定的id值
136
+
137
+ ````
138
+ translate.ignore.id.push('test'); //翻译时追加上自己想忽略不进行翻译的id的值,凡是在这里面的,都不进行翻译。
139
+ ````
140
+ 翻译时追加上自己想忽略不进行翻译的id的值,凡是在这里面的,都不进行翻译。
141
+ 如果你想查看当前忽略哪些id,可直接执行 ```` console.log(translate.ignore.id); ```` 进行查看
142
+ **注意,这行要放到 translate.execute(); 上面**
143
+
144
+
145
+ ### 翻译指定的区域
146
+
147
+ ````
148
+ var documents = [];
149
+ documents.push(document.getElementById('test1'));
150
+ documents.push(document.getElementById('test2'));
151
+ documents.push(document.getElementById('test3'));
152
+ translate.setDocuments(documents); //指定要翻译的元素的集合,可传入一个或多个元素。如果不设置,默认翻译整个网页
153
+ ````
154
+
155
+ 可使用 translate.setDocuments(...) 指定要翻译的元素的集合,可传入一个或多个元素。如果不设置此,默认翻译整个网页。
156
+ **注意,这行要放到 translate.execute(); 上面**
157
+
158
+ ### js主动切换语言
159
+ 比如点击某个链接显示英文界面
160
+
161
+ ````
162
+ <a href="javascript:translate.changeLanguage('english');" class="ignore">切换为英语</a>
163
+ ````
164
+
165
+ 只需传入翻译的目标语言,即可快速切换到指定语种。具体有哪些语言,可查阅: [http://api.translate.zvo.cn/doc/language.json.html](http://api.translate.zvo.cn/doc/language.json.html)
166
+ 其中 ````class="ignore"```` 加了这个class,代表这个a标签将不会被翻译
167
+
168
+ ### 自动根据用户所在的国家切换其语种
169
+
170
+ 用户第一次打开网页时,自动判断当前用户所在国家使用的是哪种语言,来自动进行切换为用户所在国家的语种。
171
+ 如果用户手动切换了别的语种,再使用时,那就优先以用户所选择的为主,这个就不管用了。
172
+
173
+ ````
174
+ translate.setAutoDiscriminateLocalLanguage(); //设置用户第一次用时,自动识别其所在国家的语种进行切换
175
+ ````
176
+
177
+ ### 设置本地语种(当前网页的语种)
178
+
179
+ ````
180
+ translate.language.setLocal('chinese_simplified'); //设置本地语种(当前网页的语种)。如果不设置,默认就是 chinese_simplified 简体中文
181
+ ````
182
+ 当前支持的本地语种有:
183
+ * **chinese_simplified** 简体中文
184
+ * **chinese_traditional** 繁体中文
185
+ * **english** 英语
186
+ 如果不设置,默认会自动识别当前网页的文本,取当前网页文本中,出现频率最高的语种为默认语种。
187
+ 这个会在出现 select 选择语言时,默认选中的语种。
188
+
189
+ **注意,这行要放到 translate.execute(); 上面**
190
+
191
+ ### 对页面动态渲染的文本进行自动翻译
192
+
193
+ 正常情况下,极大可能会有这种需求:
194
+ 1. 页面中需要通过ajax请求后端服务器获取数据,然后再将数据渲染展示出来。
195
+ 2. 页面中的弹出提示 (就比如 [msg.js](https://gitee.com/mail_osc/msg) 的 ````msg.info('你好');```` ) 这个提示是js加载出来的,提示文字也需要一并进行翻译的情况
196
+ 您可加入下面一行代码,来实现以上需求。
197
+
198
+ ````
199
+ translate.listener.start(); //开启html页面变化的监控,对变化部分会进行自动翻译。注意,这里变化区域,是指使用 translate.setDocuments(...) 设置的区域。如果未设置,那么为监控整个网页的变化
200
+ ````
201
+ 建议放在 translate.execute() 这行之前。
202
+ ##### 注意事项
203
+ 如果你手动设置了 ````translate.setDocuments(...)```` ,那么监听的就不是整个页面了,而是单纯只监听 ````setDocuments(...)```` 所设置的区域的改动。
204
+
205
+ ### 私有化部署翻译服务接口
206
+ 在某些政府机关及大集团内部项目中,对数据隐私及安全保密有强要求场景、以及您对自有客户希望提供高可靠翻译服务场景时,您可将翻译服务接口进行私有化部署,不走我们公开开放的翻译接口,以做到安全保密及后端服务全部自行掌控。
207
+ 实际部署方式,可参考:[https://github.com/xnx3/translate_service](https://github.com/xnx3/translate_service)
208
+ 部署好后,在 ````translate.execute();```` 之前,加入一行代码,如下所示:
209
+
210
+ ````
211
+ translate.request.api.host='http://121.121.121.121/'; //将这里面的ip地址换成你服务器的ip,注意开头,及结尾还有个 / 别拉下
212
+ translate.execute();
213
+ ````
214
+
215
+ 如此,翻译请求接口就会走您自己服务器了。
216
+
217
+ ### 翻译完后自动执行
218
+ 当翻译完成后会自动触发执行某个方法,以便您来做自定义扩展。比如 [layui的翻译组件](https://gitee.com/mail_osc/translate_layui) 便是使用了此能力在翻译完成后重新绘制 select 选中项。
219
+
220
+ ````
221
+ translate.listener.renderTaskFinish = function(task){
222
+ console.log('执行完一次');
223
+ }
224
+ ````
225
+
226
+ 进行翻译时每当执行完一次渲染任务(翻译)时会触发此。注意页面一次翻译会触发多个渲染任务。普通情况下,一次页面的翻译可能会触发两三次渲染任务。(因为一个网页上可能有多种语言,每种语言都是一次翻译任务。)
227
+ 另外如果页面中有ajax交互方面的信息时,每次ajax信息刷新后,也会进行翻译,也是一次翻译任务。
228
+ 当然,这里的翻译任务是确实有进行了翻译的前提下,执行完才会触发此。
229
+
230
+ ### 自定义翻译术语
231
+ 如果你感觉某些翻译不准确,可进行针对性的定义某些词的翻译结果,进行自定义术语库。使用的方法为:
232
+
233
+ ````
234
+ translate.nomenclature.append(from, to, properties);
235
+ ````
236
+ 传入参数解释:
237
+ * **from** 要转换的语种,传入如 chinese_simplified
238
+ * **to** 翻译至的目标语种,传入如 english
239
+ * **properties** 配置表,格式便是properties的格式,每行一个规则,每个前后用等号分割,等号前是要翻译的词或句子,等号后是自定义的翻译结果。传入如:
240
+
241
+ ````
242
+ 你好=Hello
243
+ 世界=ShiJie
244
+ ````
245
+
246
+ 比如,要自定义 “网市场云建站系统” 、 “国际化” 这两个词有简体中文翻译为英文的结果,可以这么写:
247
+
248
+ ````
249
+ translate.nomenclature.append('chinese_simplified','english',`
250
+ 网市场云建站系统=wangmarket CMS
251
+ 国际化=GuoJiHua
252
+ `);
253
+ ````
254
+
255
+ 这个自定义术语库的可以单独用一个js文件来定义,如此定义一次,在类似的项目中有使用,可直接将之前定义的js术语库文件复制来引入即可方便使用。
256
+ 当前正在优化中,如果原语种是中文、韩文还可以,像是英语结果会不准,如果您项目中用到了,发现异常时,可联系我,免费帮您调试好的同时还能完善本项目。
257
+ **注意,这行要放到 translate.execute(); 上面**
258
+
259
+ ##### 示例
260
+ 这里给出一个示例用于参考,链接地址: [https://res.zvo.cn/translate/doc/demo_nomenclature.html](https://res.zvo.cn/translate/doc/demo_nomenclature.html)
261
+ 您可打开后查看页面源代码,即可看到它是如何设置的。
262
+
263
+ # 实际使用场景示例
264
+ ### 普通网站中点击某个语言进行切换
265
+ 如下图所示,网站中的某个位置要有几种语言切换
266
+ ![](http://cdn.weiunity.com/site/341/news/43b838ea6ad041898037eaaaf5802776.png)
267
+ 直接在其html代码末尾的位置加入以下代码:
268
+
269
+ ````
270
+ <!-- 增加某种语言切换的按钮。注意 ul上加了一个 class="ignore" 代表这块代码不会被翻译到 -->
271
+ <ul class="ignore">
272
+ <li><a href="javascript:translate.changeLanguage('english');">English</a></li>|
273
+ <li><a href="javascript:translate.changeLanguage('chinese_simplified');">简体中文</a></li>|
274
+ <li><a href="javascript:translate.changeLanguage('chinese_traditional');">繁體中文</a></li>
275
+ </ul>
276
+
277
+ <!-- 引入多语言切换的js -->
278
+ <script src="https://res.zvo.cn/translate/translate.js"></script>
279
+ <script>
280
+ translate.setUseVersion2(); //设置使用v2.x 版本
281
+ translate.selectLanguageTag.show = false; //不出现的select的选择语言
282
+ translate.execute();
283
+ </script>
284
+ ````
285
+
286
+ # 参与
287
+ 您可直接 fork 本项目,注意,是github仓库 [https://github.com/xnx3/translate](https://github.com/xnx3/translate) ,非 gitee 的仓库
288
+ 如果您改动了哪些代码,请在其中备注上自己的姓名、以及自己的个人主页,是您参与付出的留名。比如,陈某人参与了日语翻译的字符判断,那可以这样:
289
+
290
+ ````
291
+ /*
292
+ 是否包含日语,返回true:包含
293
+ 参与完善者:陈某人 https://www.chenmouren.com/xxxxx.html
294
+ */
295
+ japanese:function(str){
296
+ if(/.*[\u0800-\u4e00]+.*$/.test(str)){
297
+ return true
298
+ } else {
299
+ return false;
300
+ }
301
+ },
302
+
303
+ ````
304
+
305
+ # 版本
306
+ 注意,v1.x 跟 v2.x 使用上略有差别,可使用 ````console.log(translate.version);```` 查看当前使用的版本。
307
+ 另外 v1.x 版本的相关说明参见: [使用说明](v1.md) | [在线demo](https://res.zvo.cn/translate/demo_v1.html)
308
+
309
+ ### v1.0
310
+ 2022.2月发布,提供多语言支持能力,使网页无需改动快速具备多语言切换能力。
311
+
312
+ ### v2.0
313
+ 2022.12月发布,增加更多的扩展方法。
314
+ 1. 可自定义忽略的Tag标签,进行翻译时会忽略之
315
+ 2. 可自定义忽略的class,进行翻译时会忽略之
316
+ 3. 默认内置 class="ignore" 为忽略的class,可在某个标签上增加此属性,即可使其跳过不进行翻译。
317
+ 4. 增加缓存机制,翻译一次后会将结果进行缓存,翻译过后,再查看,会达到秒翻译的结果,极大提高体验度。
318
+ 5. 增加局部翻译的能力,可支持自定义翻译的区域。
319
+ 6. 优化 input 输入框的 placeholder 的内容不翻译的问题
320
+ 7. 优化本地使用(file协议)时无法测试的问题。现在本地也能正常使用及测试了。
321
+ 8. 修复翻译时会莫名其妙多了无数层font标签的问题
322
+ 9. 修复翻译时,像是中文翻译为韩语,鼠标多经过几次会将其翻译的韩语重复翻译导致翻译结果不准确的问题。
323
+ 10. 开放翻译云服务平台接口 http://api.translate.zvo.cn/doc/index.html
324
+
325
+ ### v2.1
326
+ 1. 本地语种时默认赋予使用v2版本翻译
327
+ 1. 增加 ````translate.language.connector()```` 对句子的连接符单独进行适配
328
+ 1. 增加如果是被 ````<!-- -->```` 注释的区域,不进行翻译
329
+ 1. 增加英文 README 文档
330
+ 1. 增加对图片alt、meta关键词及描述的翻译
331
+ 1. 优化判断本地语种跟要翻译的目标语种是否一样,如果是一样,那就不需要进行任何翻译
332
+ 1. 增加 ````translate.listener.start()```` 可对当前页面变化的区域进行自动翻译,比如ajax加载数据后进行渲染
333
+ 1. ````translate.execute(...)```` 增加可传入翻译区域,传入的区域只是单纯做一次性翻译,不会影响 ````setDocuments(...)```` 的值
334
+ 1. 加入任务队列机制,彻底解决翻译时非常小概率有文字遗漏不翻译的问题。
335
+ 1. 增加 ````translate.setAutoDiscriminateLocalLanguage();```` 用户第一次用时,可自动识别其所在国家的语种进行切换
336
+
337
+ ### v2.2
338
+ 1. 开放后端翻译服务接口的私有化一键部署,并开源。
339
+ 2. 大幅优化句子翻译的准确性,达到百度翻译、谷歌翻译的程度
340
+ 3. 增加可配置对某个元素指定id忽略其不进行翻译
341
+ 4. 增加单独针对连接符识别判断,以提高翻译准确度
342
+ 5. 增加可针对 translate.request.api.host 单独配置,以私有化部署
343
+ 6. 增加 inspector_v2.js ,用于v2版本的快速转换体验,并将readme中的快速体验默认便是使用此v2版本。
344
+ 8. 增加 translate.language.autoRecognitionLocalLanguage(); 如果未手动设置当前网页的语种,会自动识别语种
345
+ 9. 增加 translate.language.getLocal() 用户获取当前网页的语种(如果未设置,自动根据网页当前显示的文字进行识别语种)
346
+ 10. 增加 translate.selectLanguageTag.selectOnChange 用于提供重写select onchange 事件,以便更好扩展
347
+ 11. 优化中英文混合时翻译的一些意外问题
348
+ 12. 优化meta - keywords 替换的问题
349
+ 13. 优化转英文时如果英文有',比如 let's 这种的情况
350
+ 14. 优化 ignore 对忽略class name有多情况下的判断
351
+ 15. 开放后端翻译服务接口文档,以便更好自有扩展及使用
352
+ 16. 修复tag有时失效的问题,比如监听状态下局部翻译情况
353
+
354
+ # 这些开源项目正在使用
355
+ 如下开源项目中已置入自动化翻译的能力:
356
+ [kefu.js](https://gitee.com/mail_osc/kefu.js) H5在线客服,引入一行js代码拿来即用!支持手机、电脑、APP、小程序。可一键部署自己私有SAAS云客服平台
357
+ [Pear Admin Layui](https://gitee.com/pear-admin/Pear-Admin-Layui) Pear Admin 是一款开箱即用的前端开发模板,扩展Layui原生UI样式,整合第三方开源组件,提供便捷快速的开发方式,延续LayuiAdmin
358
+ [Layui](https://gitee.com/mail_osc/translate_layui) 翻译组件
359
+ ...
360
+
361
+ # 优秀开源项目及社区推荐
362
+ [Featbit](https://github.com/featbit/featbit) 一个100%开源的 Feature flags / Feature Management 平台工具
363
+ [LinkWeChat](https://gitee.com/LinkWeChat/link-wechat) LinkWeChat 是基于企业微信的开源 SCRM 系统,是企业私域流量管理与营销的综合解决方案。
364
+ [IoTSharp](https://gitee.com/IoTSharp) IoTSharp 是一个 基于.Net Core 开源的物联网基础平台, 支持 HTTP、MQTT 、CoAp 协议
365
+ [流之云](https://gitee.com/ntdgg) 信息化、数字化服务提供商
366
+
367
+
368
+ # 其他
369
+ 当前v2.0版本还处于优化期,并非完美稳定版本,当前只测试了大部分网站能完美适配,但肯定会有遗漏,随着使用的网站不断增加,会逐步修复发现的bug。稳定版本预计将会再之后的三到四个月后发布。当前您使用v2版本时,可直接用我们的js源即可,如果您有本地化的需求,可再后面稳定版本发布后再进行本地化放置。
370
+ 本人热爱开源这件事,如果您是某款开源框架的作者,想要在您开源项目中加入此多语言切换能力,但接入时遇到了困难,欢迎加入下面的QQ群,说明您是哪个开源软件的作者,我必将全力协助。愿意开源的朋友,都是值得尊敬且支持的。
371
+ 本云服务器平台可私有化部署,如果您有这方面需求,也可以联系我,但这个部署耗时几小时到半天,我们也需要给同事发工资,疫情三年都比较艰难,所以部署这块没法无偿帮助了,提供有偿部署,收个几百的人工费,还望能理解。
372
+
373
+ # 交流
374
+ 如果您在使用过程中遇到任何异常情况,请详细说一下您遇到的问题。如果可以,请写下您的网站,以便我们可以更全面地测试,以便快速找到问题所在
375
+ 作者微信:xnx3com
376
+ 交流QQ群:181781514
377
+ github: [https://github.com/xnx3/translate](https://github.com/xnx3/translate)
378
+ gitee: [https://gitee.com/mail_osc/translate](https://gitee.com/mail_osc/translate)
379
+
380
+ # 高级服务
381
+ [当前translate.js是基于js来对当前html进行翻译,绝大多数场景足够使用。但如果你查看页面源代码,会发现源代码并不会变,处于未翻译状态。如果你想针对页面源代码本身直接进行翻译,可以点此查阅我们这个扩展版本](README_SERVICE.md)