@hkonda/loco-translate 1.1.1 → 1.1.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/dist-server/routes/export.d.ts.map +1 -1
- package/dist-server/routes/export.js +42 -1
- package/dist-server/routes/export.js.map +1 -1
- package/package.json +1 -1
- package/public/loco.js +133 -18
- package/public/loco.min.js +2 -2
- package/versions.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../server/routes/export.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAG1C,wBAA8B,YAAY,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE;IAAE,OAAO,EAAE,GAAG,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../server/routes/export.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAG1C,wBAA8B,YAAY,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE;IAAE,OAAO,EAAE,GAAG,CAAA;CAAE,iBAoEtF"}
|
|
@@ -11,6 +11,17 @@ export default async function exportRoutes(app, opts) {
|
|
|
11
11
|
languages: { type: 'array', items: { type: 'string' } },
|
|
12
12
|
languageNames: { type: 'object', additionalProperties: { type: 'string' } },
|
|
13
13
|
translations: { type: 'object', additionalProperties: true },
|
|
14
|
+
aria: {
|
|
15
|
+
type: 'array',
|
|
16
|
+
items: {
|
|
17
|
+
type: 'object',
|
|
18
|
+
properties: {
|
|
19
|
+
key: { type: 'string' },
|
|
20
|
+
context: { type: 'string' },
|
|
21
|
+
attributes: { type: 'object', additionalProperties: { type: 'string' } },
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
14
25
|
timestamp: { type: 'number' },
|
|
15
26
|
},
|
|
16
27
|
},
|
|
@@ -35,6 +46,17 @@ export default async function exportRoutes(app, opts) {
|
|
|
35
46
|
languages: { type: 'array', items: { type: 'string' } },
|
|
36
47
|
languageNames: { type: 'object', additionalProperties: { type: 'string' } },
|
|
37
48
|
translations: { type: 'object', additionalProperties: true },
|
|
49
|
+
aria: {
|
|
50
|
+
type: 'array',
|
|
51
|
+
items: {
|
|
52
|
+
type: 'object',
|
|
53
|
+
properties: {
|
|
54
|
+
key: { type: 'string' },
|
|
55
|
+
context: { type: 'string' },
|
|
56
|
+
attributes: { type: 'object', additionalProperties: { type: 'string' } },
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
38
60
|
timestamp: { type: 'number' },
|
|
39
61
|
},
|
|
40
62
|
},
|
|
@@ -74,7 +96,16 @@ function buildExport(project) {
|
|
|
74
96
|
const rows = stmt.all(project.id, lang);
|
|
75
97
|
translations[lang] = rows.map(r => ({ key: r.key, context: r.context || '', value: r.value }));
|
|
76
98
|
}
|
|
77
|
-
|
|
99
|
+
const ariaRows = rawDb.prepare('SELECT key, context, attributes FROM aria_rules WHERE project_id = ? ORDER BY updated_at DESC').all(project.id);
|
|
100
|
+
const aria = ariaRows.map((r) => {
|
|
101
|
+
let attrs = {};
|
|
102
|
+
try {
|
|
103
|
+
attrs = JSON.parse(r.attributes || '{}');
|
|
104
|
+
}
|
|
105
|
+
catch { /* ignore malformed rows */ }
|
|
106
|
+
return { key: r.key, context: r.context || '', attributes: attrs };
|
|
107
|
+
});
|
|
108
|
+
return { languages, languageNames, translations, aria, timestamp: Date.now() };
|
|
78
109
|
}
|
|
79
110
|
function buildExportSingleLang(project, lang) {
|
|
80
111
|
const languageNames = getLanguageNames(project);
|
|
@@ -85,10 +116,20 @@ function buildExportSingleLang(project, lang) {
|
|
|
85
116
|
`).all(project.id, lang);
|
|
86
117
|
const translations = {};
|
|
87
118
|
translations[lang] = rows.map(r => ({ key: r.key, context: r.context || '', value: r.value }));
|
|
119
|
+
const ariaRows = rawDb.prepare('SELECT key, context, attributes FROM aria_rules WHERE project_id = ? ORDER BY updated_at DESC').all(project.id);
|
|
120
|
+
const aria = ariaRows.map((r) => {
|
|
121
|
+
let attrs = {};
|
|
122
|
+
try {
|
|
123
|
+
attrs = JSON.parse(r.attributes || '{}');
|
|
124
|
+
}
|
|
125
|
+
catch { /* ignore malformed rows */ }
|
|
126
|
+
return { key: r.key, context: r.context || '', attributes: attrs };
|
|
127
|
+
});
|
|
88
128
|
return {
|
|
89
129
|
languages: [lang],
|
|
90
130
|
languageNames,
|
|
91
131
|
translations,
|
|
132
|
+
aria,
|
|
92
133
|
timestamp: Date.now(),
|
|
93
134
|
};
|
|
94
135
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"export.js","sourceRoot":"","sources":["../../server/routes/export.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"export.js","sourceRoot":"","sources":["../../server/routes/export.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/public/loco.js
CHANGED
|
@@ -1326,6 +1326,33 @@ var Loco = function() {
|
|
|
1326
1326
|
"title"
|
|
1327
1327
|
];
|
|
1328
1328
|
var SEP = "\0";
|
|
1329
|
+
function sanitizeAriaAttrs(input) {
|
|
1330
|
+
var out = {};
|
|
1331
|
+
if (!input || typeof input !== "object") return out;
|
|
1332
|
+
ARIA_ATTRS.forEach(function(name) {
|
|
1333
|
+
if (!Object.prototype.hasOwnProperty.call(input, name)) return;
|
|
1334
|
+
var value = input[name];
|
|
1335
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
1336
|
+
out[name] = value.trim();
|
|
1337
|
+
}
|
|
1338
|
+
});
|
|
1339
|
+
return out;
|
|
1340
|
+
}
|
|
1341
|
+
function buildAriaRulesMap(rows) {
|
|
1342
|
+
var map = {};
|
|
1343
|
+
if (!Array.isArray(rows)) return map;
|
|
1344
|
+
rows.forEach(function(r) {
|
|
1345
|
+
if (!r || typeof r.key !== "string") return;
|
|
1346
|
+
var context = typeof r.context === "string" ? r.context : "";
|
|
1347
|
+
var attrs = sanitizeAriaAttrs(r.attributes);
|
|
1348
|
+
if (Object.keys(attrs).length === 0) return;
|
|
1349
|
+
map[r.key + SEP + context] = attrs;
|
|
1350
|
+
if (!Object.prototype.hasOwnProperty.call(map, r.key)) {
|
|
1351
|
+
map[r.key] = attrs;
|
|
1352
|
+
}
|
|
1353
|
+
});
|
|
1354
|
+
return map;
|
|
1355
|
+
}
|
|
1329
1356
|
function resolveElement(p) {
|
|
1330
1357
|
if (p.element) return p.element;
|
|
1331
1358
|
if (p.textNode && p.textNode.parentElement) return p.textNode.parentElement;
|
|
@@ -1338,17 +1365,7 @@ var Loco = function() {
|
|
|
1338
1365
|
}).then(function(r) {
|
|
1339
1366
|
return r.json();
|
|
1340
1367
|
}).then(function(data) {
|
|
1341
|
-
|
|
1342
|
-
if (Array.isArray(data)) {
|
|
1343
|
-
data.forEach(function(r) {
|
|
1344
|
-
var attrs = r.attributes || {};
|
|
1345
|
-
map[r.key + SEP + (r.context || "")] = attrs;
|
|
1346
|
-
if (!Object.prototype.hasOwnProperty.call(map, r.key)) {
|
|
1347
|
-
map[r.key] = attrs;
|
|
1348
|
-
}
|
|
1349
|
-
});
|
|
1350
|
-
}
|
|
1351
|
-
return map;
|
|
1368
|
+
return buildAriaRulesMap(data);
|
|
1352
1369
|
}).catch(function(e) {
|
|
1353
1370
|
console.warn("[loco] Failed to fetch ARIA rules:", e);
|
|
1354
1371
|
return {};
|
|
@@ -1497,11 +1514,23 @@ var Loco = function() {
|
|
|
1497
1514
|
}
|
|
1498
1515
|
var translations = {};
|
|
1499
1516
|
translations[lang] = row.data;
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1517
|
+
var ariaReq = tx.objectStore("meta").get("aria");
|
|
1518
|
+
ariaReq.onsuccess = function() {
|
|
1519
|
+
resolve({
|
|
1520
|
+
languages: registry.languages,
|
|
1521
|
+
languageNames: registry.languageNames || {},
|
|
1522
|
+
translations,
|
|
1523
|
+
aria: Array.isArray(ariaReq.result && ariaReq.result.rules) ? ariaReq.result.rules : []
|
|
1524
|
+
});
|
|
1525
|
+
};
|
|
1526
|
+
ariaReq.onerror = function() {
|
|
1527
|
+
resolve({
|
|
1528
|
+
languages: registry.languages,
|
|
1529
|
+
languageNames: registry.languageNames || {},
|
|
1530
|
+
translations,
|
|
1531
|
+
aria: []
|
|
1532
|
+
});
|
|
1533
|
+
};
|
|
1505
1534
|
};
|
|
1506
1535
|
langReq.onerror = function() {
|
|
1507
1536
|
db.close();
|
|
@@ -1519,6 +1548,7 @@ var Loco = function() {
|
|
|
1519
1548
|
var languages = data.languages || [];
|
|
1520
1549
|
var languageNames = data.languageNames || {};
|
|
1521
1550
|
var tMap = data.translations || {};
|
|
1551
|
+
var incomingAria = Array.isArray(data.aria) ? data.aria : [];
|
|
1522
1552
|
var timestamp = data.timestamp || 0;
|
|
1523
1553
|
return openLocoDB().then(function(db) {
|
|
1524
1554
|
return new Promise(function(resolve, reject) {
|
|
@@ -1552,6 +1582,37 @@ var Loco = function() {
|
|
|
1552
1582
|
}
|
|
1553
1583
|
metaStore.put({ key: "registry", languages: newLangs, languageNames: newNames });
|
|
1554
1584
|
metaStore.put({ key: "source:" + url, url, timestamp, storedAt: Date.now() });
|
|
1585
|
+
var ariaGetReq = metaStore.get("aria");
|
|
1586
|
+
ariaGetReq.onsuccess = function() {
|
|
1587
|
+
var nextRules = incomingAria;
|
|
1588
|
+
if (merge && ariaGetReq.result && Array.isArray(ariaGetReq.result.rules)) {
|
|
1589
|
+
var SEP2 = "\0";
|
|
1590
|
+
var map = {};
|
|
1591
|
+
var order = [];
|
|
1592
|
+
var existingRules = ariaGetReq.result.rules;
|
|
1593
|
+
for (var ei = 0; ei < existingRules.length; ei++) {
|
|
1594
|
+
var er = existingRules[ei];
|
|
1595
|
+
if (!er || typeof er.key !== "string") continue;
|
|
1596
|
+
var ek = er.key + SEP2 + (er.context || "");
|
|
1597
|
+
if (!map.hasOwnProperty(ek)) order.push(ek);
|
|
1598
|
+
map[ek] = er;
|
|
1599
|
+
}
|
|
1600
|
+
for (var ni = 0; ni < incomingAria.length; ni++) {
|
|
1601
|
+
var nr = incomingAria[ni];
|
|
1602
|
+
if (!nr || typeof nr.key !== "string") continue;
|
|
1603
|
+
var nk = nr.key + SEP2 + (nr.context || "");
|
|
1604
|
+
if (!map.hasOwnProperty(nk)) order.push(nk);
|
|
1605
|
+
map[nk] = nr;
|
|
1606
|
+
}
|
|
1607
|
+
nextRules = order.map(function(k2) {
|
|
1608
|
+
return map[k2];
|
|
1609
|
+
});
|
|
1610
|
+
}
|
|
1611
|
+
metaStore.put({ key: "aria", rules: nextRules });
|
|
1612
|
+
};
|
|
1613
|
+
ariaGetReq.onerror = function() {
|
|
1614
|
+
metaStore.put({ key: "aria", rules: incomingAria });
|
|
1615
|
+
};
|
|
1555
1616
|
for (var j = 0; j < languages.length; j++) {
|
|
1556
1617
|
if (!tMap[languages[j]]) continue;
|
|
1557
1618
|
if (merge && Array.isArray(tMap[languages[j]])) {
|
|
@@ -1800,6 +1861,19 @@ var Loco = function() {
|
|
|
1800
1861
|
}
|
|
1801
1862
|
}
|
|
1802
1863
|
}
|
|
1864
|
+
result.aria = [];
|
|
1865
|
+
if (Array.isArray(data.aria)) {
|
|
1866
|
+
for (var ai = 0; ai < data.aria.length; ai++) {
|
|
1867
|
+
var row = data.aria[ai];
|
|
1868
|
+
if (!row || typeof row !== "object") continue;
|
|
1869
|
+
if (typeof row.key !== "string" || row.key.length > MAX_STRING_LENGTH) continue;
|
|
1870
|
+
if (DANGEROUS_KEYS[row.key]) continue;
|
|
1871
|
+
var context = typeof row.context === "string" ? row.context : "";
|
|
1872
|
+
var attrs = row.attributes;
|
|
1873
|
+
if (!attrs || typeof attrs !== "object" || Array.isArray(attrs)) continue;
|
|
1874
|
+
result.aria.push({ key: row.key, context, attributes: attrs });
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1803
1877
|
return result;
|
|
1804
1878
|
}
|
|
1805
1879
|
async function init() {
|
|
@@ -1885,6 +1959,10 @@ var Loco = function() {
|
|
|
1885
1959
|
return p.key + "\0" + (p.context || "");
|
|
1886
1960
|
}), {});
|
|
1887
1961
|
}
|
|
1962
|
+
state.ariaRules = buildAriaRulesMap(state.fileData.aria || []);
|
|
1963
|
+
if (Object.keys(state.ariaRules).length > 0) {
|
|
1964
|
+
applyAria(state.phrases, state.ariaRules);
|
|
1965
|
+
}
|
|
1888
1966
|
}
|
|
1889
1967
|
async function initFileMode(urls) {
|
|
1890
1968
|
try {
|
|
@@ -1918,7 +1996,13 @@ var Loco = function() {
|
|
|
1918
1996
|
} catch (e) {
|
|
1919
1997
|
}
|
|
1920
1998
|
if (cached && cached.translations) {
|
|
1921
|
-
state.fileData = {
|
|
1999
|
+
state.fileData = {
|
|
2000
|
+
languages: cached.languages,
|
|
2001
|
+
languageNames: cached.languageNames || {},
|
|
2002
|
+
translations: cached.translations,
|
|
2003
|
+
aria: cached.aria || [],
|
|
2004
|
+
timestamp: 0
|
|
2005
|
+
};
|
|
1922
2006
|
state.loadedFromCache = true;
|
|
1923
2007
|
await applyFileData("cache");
|
|
1924
2008
|
if (state.fileReadyResolve) {
|
|
@@ -1981,8 +2065,33 @@ var Loco = function() {
|
|
|
1981
2065
|
languages: (data.languages || []).slice(),
|
|
1982
2066
|
languageNames: Object.assign({}, data.languageNames || {}),
|
|
1983
2067
|
translations: Object.assign({}, data.translations || {}),
|
|
2068
|
+
aria: (data.aria || []).slice(),
|
|
1984
2069
|
timestamp: data.timestamp || 0
|
|
1985
2070
|
};
|
|
2071
|
+
if (!state.fileData.aria) state.fileData.aria = [];
|
|
2072
|
+
var incomingAria = data.aria || [];
|
|
2073
|
+
if (incomingAria.length > 0) {
|
|
2074
|
+
var SEP2 = "\0";
|
|
2075
|
+
var aMap = {};
|
|
2076
|
+
var aOrder = [];
|
|
2077
|
+
for (var ai = 0; ai < state.fileData.aria.length; ai++) {
|
|
2078
|
+
var ex = state.fileData.aria[ai];
|
|
2079
|
+
if (!ex || typeof ex.key !== "string") continue;
|
|
2080
|
+
var exKey = ex.key + SEP2 + (ex.context || "");
|
|
2081
|
+
if (!aMap.hasOwnProperty(exKey)) aOrder.push(exKey);
|
|
2082
|
+
aMap[exKey] = ex;
|
|
2083
|
+
}
|
|
2084
|
+
for (var bi = 0; bi < incomingAria.length; bi++) {
|
|
2085
|
+
var inc = incomingAria[bi];
|
|
2086
|
+
if (!inc || typeof inc.key !== "string") continue;
|
|
2087
|
+
var inKey = inc.key + SEP2 + (inc.context || "");
|
|
2088
|
+
if (!aMap.hasOwnProperty(inKey)) aOrder.push(inKey);
|
|
2089
|
+
aMap[inKey] = inc;
|
|
2090
|
+
}
|
|
2091
|
+
state.fileData.aria = aOrder.map(function(k2) {
|
|
2092
|
+
return aMap[k2];
|
|
2093
|
+
});
|
|
2094
|
+
}
|
|
1986
2095
|
return;
|
|
1987
2096
|
}
|
|
1988
2097
|
var langs = data.languages || [];
|
|
@@ -2106,7 +2215,7 @@ var Loco = function() {
|
|
|
2106
2215
|
var Loco2 = {
|
|
2107
2216
|
// Version is injected by Vite at build time from versions.json.
|
|
2108
2217
|
// In-browser: Loco.version → e.g. "1.0.8"
|
|
2109
|
-
version: "1.1.
|
|
2218
|
+
version: "1.1.2",
|
|
2110
2219
|
init: function(config) {
|
|
2111
2220
|
if (!config) {
|
|
2112
2221
|
console.warn("[loco] Loco.init() requires a config object");
|
|
@@ -2213,6 +2322,9 @@ var Loco = function() {
|
|
|
2213
2322
|
performance.measure("loco-dom-write-time", "loco-dom-start", "loco-dom-end");
|
|
2214
2323
|
performance.measure("loco-apply-total", "loco-apply-start", "loco-dom-end");
|
|
2215
2324
|
}
|
|
2325
|
+
if (state.ariaRules && Object.keys(state.ariaRules).length > 0) {
|
|
2326
|
+
applyAria(state.phrases, state.ariaRules);
|
|
2327
|
+
}
|
|
2216
2328
|
state.observer = watchAndTranslate(state.phrases.map(function(p) {
|
|
2217
2329
|
return p.key + "\0" + (p.context || "");
|
|
2218
2330
|
}), state.translations);
|
|
@@ -2257,6 +2369,9 @@ var Loco = function() {
|
|
|
2257
2369
|
performance.measure("loco-dom-write-time", "loco-dom-start", "loco-dom-end");
|
|
2258
2370
|
performance.measure("loco-apply-total", "loco-apply-start", "loco-dom-end");
|
|
2259
2371
|
}
|
|
2372
|
+
if (state.ariaRules && Object.keys(state.ariaRules).length > 0) {
|
|
2373
|
+
applyAria(state.phrases, state.ariaRules);
|
|
2374
|
+
}
|
|
2260
2375
|
state.observer = watchAndTranslate(state.phrases.map(function(p) {
|
|
2261
2376
|
return p.key + "\0" + (p.context || "");
|
|
2262
2377
|
}), state.translations);
|
package/public/loco.min.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var Loco=function(){"use strict";var o={apiKey:null,apiBase:null,phrases:[],currentLang:null,translations:{},observer:null,fileMode:!1,fileData:null,fileReadyResolve:null,fileReady:null,fileUrl:null,fileUrls:[],scanStopped:!1,loadedFromCache:!1,screenshotsEnabled:!0,widgetPosition:null,ariaRules:{}},Se=["SCRIPT","STYLE","NOSCRIPT","IFRAME","CODE","SVG","AUDIO","VIDEO","LINK"],Fe=["VAR","STRONG","EM","B","I","SPAN","A","ABBR","MARK","SMALL","SUB","SUP","U","S","TIME"],Ce=["h1","h2","h3","h4","h5","h6","label","legend","caption","figcaption","nav","header","footer","main","section","article","form"],S=new Set(Se),I=new Set(Fe),ge=[].concat(Ce),ve=0,ye=!0,C=1e3,Y=1e4,xe="loco-lang";function j(){try{return localStorage.getItem(xe)}catch{return null}}function ee(e){try{e?localStorage.setItem(xe,e):localStorage.removeItem(xe)}catch{}}function $e(e){if(e.blockedTags){var n=e.blockedTags.disabled||[],t=e.blockedTags.custom||[];S=new Set(Se.filter(function(r){return n.indexOf(r)<0})),t.forEach(function(r){S.add(r.toUpperCase())})}if(e.inlineTags){var n=e.inlineTags.disabled||[],t=e.inlineTags.custom||[];I=new Set(Fe.filter(function(i){return n.indexOf(i)<0})),t.forEach(function(i){I.add(i.toUpperCase())})}if(e.domContextSelectors){var n=e.domContextSelectors.disabled||[],t=e.domContextSelectors.custom||[];ge=Ce.filter(function(i){return n.indexOf(i)<0}).concat(t)}e.screenshotsEnabled===!1&&(o.screenshotsEnabled=!1),typeof e.contextDepth=="number"&&(ve=e.contextDepth),e.domContextEnabled===!1&&(ye=!1)}function N(e){return e.trim().replace(/\s+/g," ")}function b(e){return!/[a-zA-Z\u00C0-\u024F\u0900-\u097F\u0600-\u06FF]/.test(e)}function te(e){var n=e.replace(/\{\{(?:text|number|decimal|date):\d+\}\}/g,"");return!n.trim()||b(n)}function Oe(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function X(e){var t;if(!e||e.nodeType!==1)return!1;const n=(t=e.tagName)==null?void 0:t.toUpperCase();return S.has(n)||e.hasAttribute("notranslate")||e.hasAttribute("data-notranslate")||e.hasAttribute("data-loco-translated")||e.getAttribute("translate")==="no"||e.isContentEditable}var D=new WeakMap;function Pe(e){let n=e.parentElement;for(;n&&n!==document.body;){if(D.has(n))return D.get(n);if(X(n))return D.set(n,!0),!0;n=n.parentElement}for(n=e.parentElement;n&&n!==document.body&&!D.has(n);)D.set(n,!1),n=n.parentElement;return!1}function Ve(){D=new WeakMap}const Re=new Set(["H1","H2","H3","H4","H5","H6"]),qe=new Set(["SCRIPT","STYLE","NOSCRIPT","CODE"]);let _=new WeakMap,M=new WeakMap,K=null;function Ee(){if(ye){K=new Set;var e=ge.slice();try{var n=e.join(",");document.querySelectorAll(n).forEach(function(t){K.add(t)})}catch{e.forEach(function(r){try{document.querySelectorAll(r).forEach(function(a){K.add(a)})}catch{}})}K.forEach(function(t){M.has(t)||Q(t)})}}function W(e){return K?K.has(e):Re.has(e.tagName)?!0:ge.some(function(n){try{return e.matches(n)}catch{return!1}})}function Ge(e){let n="";for(const t of e.childNodes)if(t.nodeType===Node.TEXT_NODE){const r=t.textContent.trim();r&&(n+=(n?" ":"")+r)}return n}function Je(e,n){for(var t="",r=document.createTreeWalker(e,NodeFilter.SHOW_ALL,{acceptNode:function(i){return i.nodeType===Node.ELEMENT_NODE?qe.has(i.tagName)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_SKIP:NodeFilter.FILTER_ACCEPT}}),a;(a=r.nextNode())&&!(a.nodeType===Node.TEXT_NODE&&(t+=a.textContent,t.length>=n)););return t.trim()}function Q(e){if(M.has(e))return M.get(e);let n=null;const t=Ge(e);if(t)return n=t.substring(0,60),M.set(e,n),n;if(Re.has(e.tagName)){const a=(e.textContent||"").trim().replace(/\s+/g," ");if(a)return n=a.substring(0,60),M.set(e,n),n}var r=Je(e,200);if(r){const a=r.split(/\n/)[0].trim().replace(/\s+/g," ");a.length>=2&&!b(a)&&(n=a.substring(0,60))}return M.set(e,n),n}function A(e){if(!e||!ye)return"";if(_.has(e))return _.get(e);var n=e.parentElement;if(n&&n!==document.body&&_.has(n)&&!W(e)){var t=_.get(n);return _.set(e,t),t}const r=[],a=new Set;let i=e,l=0;if(e&&e.tagName==="TD"){var p=e.closest("table");if(p){var m=p.querySelector("thead tr th:nth-child("+(e.cellIndex+1)+")");if(m){var c=Q(m);c&&(a.add(c),r.push(c))}}}for(;i&&i!==document.body&&!(ve>0&&l>=ve);){l++;let f=i.previousElementSibling;for(;f;){var u=f.tagName.toUpperCase();if(S.has(u)){f=f.previousElementSibling;continue}if(u==="ARTICLE"||u==="MAIN"){f=f.previousElementSibling;continue}if(W(f)){const d=Q(f);d&&!a.has(d)&&(a.add(d),r.unshift(d));break}let s=null;for(const d of f.children)if(W(d)){s=d;break}if(!s)for(const d of f.children){for(const v of d.children)if(W(v)){s=v;break}if(s)break}if(s){const d=Q(s);d&&!a.has(d)&&(a.add(d),r.unshift(d));break}f=f.previousElementSibling}if(W(i)){const s=Q(i);s&&!a.has(s)&&(a.add(s),r.unshift(s))}var h=i.tagName;if(h==="ARTICLE"||h==="MAIN")break;i=i.parentElement}const g=r.join(" > ");return _.set(e,g),g}function Ze(e){return/^\d+$/.test(e)?"number":/^\d+\.\d+$/.test(e)?"decimal":"text"}function ze(e,n){for(var t=n.split(/(\{\{(?:text|number|decimal|date):\d+\}\})/),r=[],a=e,i=0;i<t.length;i++){var l=t[i],p=l.match(/^\{\{(text|number|decimal|date):(\d+)\}\}$/);if(p)if(a.indexOf(l)===0)r.push({type:p[1],index:parseInt(p[2]),originalText:l}),a=a.substring(l.length);else{for(var m="",c=i+1;c<t.length;c++){var u=t[c];if(/^\{\{(?:text|number|decimal|date):\d+\}\}$/.test(u)){if(a.indexOf(u)>=0){m=u;break}}else if(u!==""){m=u;break}}var h;if(m==="")h=a,a="";else{var g=a.indexOf(m);g>=0?(h=a.substring(0,g),a=a.substring(g)):(h=a,a="")}r.push({type:p[1],index:parseInt(p[2]),originalText:h})}else a.indexOf(l)===0&&(a=a.substring(l.length))}return r}function ne(e,n){e.forEach(function(t){if(!(t.varSlots&&t.varSlots.length>0)){var r=n[t.key];r&&(t.varSlots=ze(t.key,r),t.key=r)}})}function Ye(e,n){for(var t=n.split(/\{\{(?:text|number|decimal|date):\d+\}\}/g),r=e,a=[],i=0;i<t.length;i++)if(i===0)r.indexOf(t[i])===0&&(r=r.substring(t[i].length));else if(t[i]===""&&i===t.length-1)a.push(r),r="";else{var l=r.indexOf(t[i]);l>=0&&(a.push(r.substring(0,l)),r=r.substring(l+t[i].length))}return a.length>0&&a.every(function(p){return/^[a-zA-Z\s]+$/.test(p.trim())})}function et(e){for(var n=0,t=/\{\{(text|number|decimal|date):\d+\}\}/g,r;(r=t.exec(e))!==null;)switch(r[1]){case"number":n+=3;break;case"decimal":n+=3;break;case"date":n+=2;break;default:n+=1;break}return n}function B(e,n){for(var t=[],r=0;r<n.length;r++){var a=n[r];if(!(a.indexOf("{{text:")<0&&a.indexOf("{{number:")<0&&a.indexOf("{{decimal:")<0&&a.indexOf("{{date:")<0)){for(var i=[],l=[],p=0,m=/\{\{(text|number|decimal|date):\d+\}\}/g,c;(c=m.exec(a))!==null;)i.push(a.substring(p,c.index)),l.push(c[1]),p=m.lastIndex;i.push(a.substring(p));for(var u="",h=0;h<i.length;h++)if(u+=i[h].replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),h<l.length)switch(l[h]){case"number":u+="\\d+";break;case"decimal":u+="\\d+\\.\\d+";break;default:u+=".+";break}t.push({pattern:a,regex:new RegExp("^"+u+"$"),specificity:et(a)})}}if(t.length!==0){t.sort(function(s,d){return d.specificity-s.specificity});for(var g={},f={},r=0;r<n.length;r++)f[n[r]]=!0;return e.forEach(function(s){if(!f[s.key]&&!(s.key.length>C)){for(var d=0;d<t.length;d++)if(t[d].regex.test(s.key)&&!Ye(s.key,t[d].pattern)){g[s.key]=t[d].pattern;break}}}),ne(e,g),g}}var $=new WeakMap;function F(e){if($.has(e))return $.get(e);let n=!1,t=!1;for(const a of e.childNodes)if(a.nodeType===Node.TEXT_NODE&&a.textContent.trim()&&(n=!0),a.nodeType===Node.ELEMENT_NODE){const i=a.tagName.toUpperCase();if(i==="BR")return $.set(e,!1),!1;(i==="VAR"||i==="TIME"&&a.hasAttribute("datetime")||I.has(i))&&(t=!0)}var r=n&&t;return $.set(e,r),r}function tt(){$=new WeakMap}function re(e){let n="";const t=[];for(const r of e.childNodes){if(r.nodeType===Node.TEXT_NODE){const a=N(r.textContent);a&&(n+=a);continue}if(r.nodeType===Node.ELEMENT_NODE){const a=r.tagName.toUpperCase();if(a==="TIME"&&r.hasAttribute("datetime")){const i=t.length;t.push({type:"date",index:i,raw:r.getAttribute("datetime"),display:r.textContent,node:r}),n+=`{{date:${i}}}`;continue}if(a==="VAR"||I.has(a)){const i=N(r.textContent);if(i){const l=t.length,p=Ze(i);t.push({type:p,index:l,tag:a,value:i,node:r}),n+=`{{${p}:${l}}}`}continue}}}return{key:N(n),slots:t}}var ae=["title","placeholder","aria-label"];function Ie(e){const n=[],t=new Set;if(e.nodeType===Node.ELEMENT_NODE&&!X(e)&&F(e)){const{key:c,slots:u}=re(e);if(c&&c.length<=C)if(te(c))u.forEach(function(h){if(h.type==="text"&&h.value&&h.value.length>=2&&!b(h.value)){var g=A(h.node||e),f=h.value+"\0"+g;t.has(f)||(t.add(f),n.push({type:"text",key:h.value,slots:[],textNode:h.node?h.node.firstChild:null,element:h.node||e,context:g,original:h.value}))}});else{var r=A(e),a=c+"\0"+r;t.has(a)||t.add(a);const h=u.some(g=>g.type==="date")?"mixed-date":u.some(g=>g.type==="text")?"mixed-text":"mixed";n.push({type:h,key:c,slots:u,element:e,context:r,original:c,originalHTML:e.innerHTML})}}const i=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT,{acceptNode(c){var v,x,y;if(c.nodeType===Node.TEXT_NODE){const E=N(c.textContent);if(!E||E.length<2||E.length>C||b(E)||/\{\{(?:text|number|decimal|date):\d+\}\}/.test(E)||Pe(c))return NodeFilter.FILTER_SKIP;const w=(x=(v=c.parentElement)==null?void 0:v.tagName)==null?void 0:x.toUpperCase();if(S.has(w)||F(c.parentElement))return NodeFilter.FILTER_SKIP;for(var u=c.parentElement,h=0;u&&h<3;){var g=(y=u.tagName)==null?void 0:y.toUpperCase();if((g==="VAR"||g==="TIME"||I.has(g))&&u.parentElement&&F(u.parentElement))return NodeFilter.FILTER_SKIP;u=u.parentElement,h++}return NodeFilter.FILTER_ACCEPT}if(c.nodeType===Node.ELEMENT_NODE){const E=c.tagName.toUpperCase();if(S.has(E)||X(c))return NodeFilter.FILTER_REJECT;if(E==="INPUT"){var f=(c.getAttribute("type")||"").toLowerCase();if(f==="button"||f==="submit"||f==="reset"){var s=N(c.value);if(s&&s.length>=2&&!b(s))return NodeFilter.FILTER_ACCEPT}var d=ae.some(function(w){var T=N(c.getAttribute(w)||"");return T&&T.length>=2&&!b(T)});return d?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}return F(c)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}return NodeFilter.FILTER_SKIP}});let l;for(;l=i.nextNode();){if(l.nodeType===Node.TEXT_NODE){const c=N(l.textContent);if(!c)continue;var r=A(l.parentElement),a=c+"\0"+r;t.has(a)||t.add(a),n.push({type:"text",key:c,slots:[],textNode:l,element:l.parentElement,context:r,original:c});continue}if(l.nodeType===Node.ELEMENT_NODE&&l.tagName.toUpperCase()==="INPUT"){var p=(l.getAttribute("type")||"").toLowerCase(),r=A(l);if(p==="button"||p==="submit"||p==="reset"){var m=N(l.value);if(m&&m.length>=2&&!b(m)){var a=m+"\0"+r;t.has(a)||t.add(a),n.push({type:"input-value",key:m,slots:[],element:l,context:r,original:m})}}ae.forEach(function(u){var h=N(l.getAttribute(u)||"");if(!(!h||h.length<2||b(h))){var g=h+"\0"+r+"\0"+u;t.has(g)||(t.add(g),n.push({type:"input-attr",key:h,attr:u,slots:[],element:l,context:r,original:h}))}});continue}if(l.nodeType===Node.ELEMENT_NODE){const{key:c,slots:u}=re(l);if(!c||c.length>C)continue;if(te(c)){u.forEach(function(s){if(s.type==="text"&&s.value&&s.value.length>=2&&!b(s.value)){var d=A(s.node||l),v=s.value+"\0"+d;t.has(v)||(t.add(v),n.push({type:"text",key:s.value,slots:[],textNode:s.node?s.node.firstChild:null,element:s.node||l,context:d,original:s.value}))}});continue}var r=A(l),a=c+"\0"+r;t.has(a)||t.add(a);const f=u.some(s=>s.type==="date")?"mixed-date":u.some(s=>s.type==="text")?"mixed-text":"mixed";n.push({type:f,key:c,slots:u,element:l,context:r,original:c,originalHTML:l.innerHTML})}}return n}async function V(e,n){n||(n=100);const t=[],r=new Set;if(Ve(),tt(),Ee(),e.nodeType===Node.ELEMENT_NODE&&!X(e)&&F(e)){const{key:f,slots:s}=re(e);if(f&&f.length<=C)if(te(f))s.forEach(function(d){if(d.type==="text"&&d.value&&d.value.length>=2&&!b(d.value)){var v=A(d.node||e),x=d.value+"\0"+v;r.has(x)||(r.add(x),t.push({type:"text",key:d.value,slots:[],textNode:d.node?d.node.firstChild:null,element:d.node||e,context:v,original:d.value}))}});else{var a=A(e),i=f+"\0"+a;r.has(i)||r.add(i);const d=s.some(v=>v.type==="date")?"mixed-date":s.some(v=>v.type==="text")?"mixed-text":"mixed";t.push({type:d,key:f,slots:s,element:e,context:a,original:f,originalHTML:e.innerHTML})}}const l=[],p=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT,{acceptNode(f){var w,T,P;if(f.nodeType===Node.TEXT_NODE){const L=N(f.textContent);if(!L||L.length<2||L.length>C||b(L)||/\{\{(?:text|number|decimal|date):\d+\}\}/.test(L)||Pe(f))return NodeFilter.FILTER_SKIP;const R=(T=(w=f.parentElement)==null?void 0:w.tagName)==null?void 0:T.toUpperCase();if(S.has(R)||F(f.parentElement))return NodeFilter.FILTER_SKIP;for(var s=f.parentElement,d=0;s&&d<3;){var v=(P=s.tagName)==null?void 0:P.toUpperCase();if((v==="VAR"||v==="TIME"||I.has(v))&&s.parentElement&&F(s.parentElement))return NodeFilter.FILTER_SKIP;s=s.parentElement,d++}return NodeFilter.FILTER_ACCEPT}if(f.nodeType===Node.ELEMENT_NODE){const L=f.tagName.toUpperCase();if(S.has(L)||X(f))return NodeFilter.FILTER_REJECT;if(L==="INPUT"){var x=(f.getAttribute("type")||"").toLowerCase();if(x==="button"||x==="submit"||x==="reset"){var y=N(f.value);if(y&&y.length>=2&&!b(y))return NodeFilter.FILTER_ACCEPT}var E=ae.some(function(R){var k=N(f.getAttribute(R)||"");return k&&k.length>=2&&!b(k)});return E?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}return F(f)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}return NodeFilter.FILTER_SKIP}});for(var m;m=p.nextNode();)l.push(m);for(var c=0;c<l.length;c++){c>0&&c%n===0&&await new Promise(function(f){setTimeout(f,0)});var u=l[c];if(u.nodeType===Node.TEXT_NODE){const f=N(u.textContent);if(!f)continue;var a=A(u.parentElement),i=f+"\0"+a;r.has(i)||r.add(i),t.push({type:"text",key:f,slots:[],textNode:u,element:u.parentElement,context:a,original:f});continue}if(u.nodeType===Node.ELEMENT_NODE&&u.tagName.toUpperCase()==="INPUT"){var h=(u.getAttribute("type")||"").toLowerCase(),a=A(u);if(h==="button"||h==="submit"||h==="reset"){var g=N(u.value);if(g&&g.length>=2&&!b(g)){var i=g+"\0"+a;r.has(i)||r.add(i),t.push({type:"input-value",key:g,slots:[],element:u,context:a,original:g})}}ae.forEach(function(s){var d=N(u.getAttribute(s)||"");if(!(!d||d.length<2||b(d))){var v=d+"\0"+a+"\0"+s;r.has(v)||(r.add(v),t.push({type:"input-attr",key:d,attr:s,slots:[],element:u,context:a,original:d}))}});continue}if(u.nodeType===Node.ELEMENT_NODE){const{key:f,slots:s}=re(u);if(!f||f.length>C)continue;if(te(f)){s.forEach(function(y){if(y.type==="text"&&y.value&&y.value.length>=2&&!b(y.value)){var E=A(y.node||u),w=y.value+"\0"+E;r.has(w)||(r.add(w),t.push({type:"text",key:y.value,slots:[],textNode:y.node?y.node.firstChild:null,element:y.node||u,context:E,original:y.value}))}});continue}var a=A(u),i=f+"\0"+a;r.has(i)||r.add(i);const x=s.some(y=>y.type==="date")?"mixed-date":s.some(y=>y.type==="text")?"mixed-text":"mixed";t.push({type:x,key:f,slots:s,element:u,context:a,original:f,originalHTML:u.innerHTML})}}return t}function oe(e){if(o.scanStopped)return Promise.resolve({ok:!0,registered:0,keyMap:{}});var n=new Set,t=[];return e.forEach(function(r){var a=r.key+"\0"+(r.context||"");n.has(a)||r.varSlots&&r.varSlots.length>0&&/\{\{(?:text|number|decimal|date):\d+\}\}/.test(r.key)||(n.add(a),t.push({key:r.key,context:r.context||""}),r.slots&&r.slots.length>0&&r.slots.forEach(function(i){if(i.type==="text"&&i.value&&!b(i.value)){var l=i.value+"\0";n.has(l)||(n.add(l),t.push({key:i.value,context:""}))}}))}),fetch(o.apiBase+"/api/textnodes",{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":o.apiKey},body:JSON.stringify({keys:t,url:window.location.href})}).then(function(r){return r.json()})}function nt(e){var n=o.apiBase+"/api/translations?lang="+encodeURIComponent(e);return fetch(n,{headers:{"X-API-Key":o.apiKey}}).then(function(t){return t.json()}).then(function(t){var r={};return Array.isArray(t)?t.forEach(function(a){r[a.key+"\0"+(a.context||"")]=a.value,r.hasOwnProperty(a.key)||(r[a.key]=a.value)}):r=t,r})}function rt(){if(!(o.fileMode||!o.screenshotsEnabled)){var e=document.createElement("script");e.src=o.apiBase+"/cdn/html2canvas.min.js",e.onload=function(){typeof html2canvas=="function"&&html2canvas(document.body,{scale:.35,logging:!1,useCORS:!0,allowTaint:!0,width:window.innerWidth,height:window.innerHeight,windowWidth:window.innerWidth,windowHeight:window.innerHeight}).then(function(n){var t=n.toDataURL("image/jpeg",.5),r=t.split(",")[1];!r||r.length>5e5||fetch(o.apiBase+"/api/screenshots",{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":o.apiKey},body:JSON.stringify({url:window.location.href,screenshot:r})}).catch(function(){})}).catch(function(){})},e.onerror=function(){},document.head.appendChild(e)}}function at(e,n){return e.replace(/\{\{(text|number|decimal|date):(\d+)\}\}/g,(t,r,a)=>{const i=n[parseInt(a)];return i?r==="date"?i.display:i.value:t})}function De(e){if(!Array.isArray(e))return e;var n={};return e.forEach(function(t){n[t.key+"\0"+(t.context||"")]=t.value,n.hasOwnProperty(t.key)||(n[t.key]=t.value)}),n}function be(e,n){let t=0,r=0;return e.forEach(a=>{const i=a.key+"\0"+(a.context||"");var l=n[i]||n[a.key];if(!l&&a.slots&&a.slots.length>0){var p=a.slots.some(function(h){if(h.type!=="text"||!h.value)return!1;var g=h.value+"\0"+(a.context||""),f=h.value+"\0";return n.hasOwnProperty(g)||n.hasOwnProperty(f)||n.hasOwnProperty(h.value)});p&&(l=a.key)}if(!l){r++;return}if(a.type==="input-value"&&a.element)try{a.element.value=l,a.element.setAttribute("data-loco-translated",""),t++;return}catch(h){console.warn("[translate] Could not write to input value",h),r++;return}if(a.type==="input-attr"&&a.element&&a.attr)try{a.element.setAttribute(a.attr,l),a.element.setAttribute("data-loco-translated",""),t++;return}catch(h){console.warn("[translate] Could not write to input attr",h),r++;return}if(a.type==="text"&&a.textNode)try{var m=l;a.varSlots&&a.varSlots.length>0&&(m=m.replace(/\{\{(text|number|decimal|date):(\d+)\}\}/g,function(h,g,f){var s=a.varSlots.find(function(d){return(d.type||"text")===g&&d.index===+f});return s||(s=a.varSlots[+f]),s?s.originalText:h})),m=m.replace(/\{\{(?:text|number|decimal|date):\d+\}\}/g,""),a.textNode.nodeValue=m,a.textNode.parentElement&&a.textNode.parentElement.setAttribute("data-loco-translated",""),t++;return}catch(h){console.warn("[translate] Could not write to text node",h),r++;return}if(a.element){try{const h=at(l,a.slots);let g=l;var c={};a.slots.forEach(f=>{const s=`{{${f.type}:${f.index}}}`;if(f.type==="date"&&f.node)f.node.textContent=f.display,c[s]=f.node.outerHTML;else if(f.node){if(f.type==="text"&&f.value){var d=f.value+"\0"+(a.context||""),v=f.value+"\0",x=n[d]||n[v]||n[f.value];x&&(f.node.textContent=x)}c[s]=f.node.outerHTML}}),a.varSlots&&a.varSlots.length>0&&a.varSlots.forEach(function(f){var s="{{"+f.type+":"+f.index+"}}";c.hasOwnProperty(s)||(c[s]=Oe(f.originalText))});var u=g.split(/(\{\{(?:text|number|decimal|date):\d+\}\})/g);g=u.map(function(f){return c.hasOwnProperty(f)?c[f]:/^\{\{(?:text|number|decimal|date):\d+\}\}$/.test(f)?"":Oe(f)}).join(""),a.element.innerHTML=g,a.element.setAttribute("data-loco-translated",""),t++}catch(h){console.warn("[translate] Could not apply mixed translation",h),r++}return}r++}),{applied:t,skipped:r}}async function ie(e,n,t){t||(t=100);for(var r=0,a=0,i=performance.now(),l=0;l<e.length;l+=t){l>0&&performance.now()-i>16&&(await new Promise(function(c){requestAnimationFrame(c)}),i=performance.now());var p=e.slice(l,l+t),m=be(p,n);r+=m.applied,a+=m.skipped}return{applied:r,skipped:a}}function O(e){let n=0;e.forEach(t=>{try{t.type==="input-value"&&t.element?(t.element.value=t.original,t.element.removeAttribute("data-loco-translated"),n++):t.type==="input-attr"&&t.element&&t.attr?(t.element.setAttribute(t.attr,t.original),t.element.removeAttribute("data-loco-translated"),n++):t.type==="text"&&t.textNode&&(t.textNode.nodeValue=t.original,t.textNode.parentElement&&t.textNode.parentElement.removeAttribute("data-loco-translated"),n++)}catch(r){console.warn("[translate] Could not restore text node",r)}}),e.forEach(t=>{if(t.type!=="text")try{t.element&&t.originalHTML!==void 0&&(t.element.innerHTML=t.originalHTML,t.element.removeAttribute("data-loco-translated"),n++)}catch(r){console.warn("[translate] Could not restore node",r)}}),console.log("[loco] untranslated "+n+" phrase(s)")}function le(e,n){const t=new Set(e),r=[];Object.values(n).forEach(function(s){if(s&&(t.add(s),/\{\{(text|number|decimal|date):\d+\}\}/.test(s))){var d=s.split(/\{\{(?:text|number|decimal|date):\d+\}\}/g),v=d.map(function(x){return x.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")});r.push(new RegExp("^"+v.join(".+")+"$"))}});function a(s){if(t.has(s))return!0;for(var d=0;d<r.length;d++)if(r[d].test(s))return!0;return!1}let i=[],l=null,p=null,m=new Set,c=null,u=!1;function h(){if(i.length!==0){var s=i.splice(0);o.fileMode||oe(s).then(function(d){d&&d.keyMap&&(ne(s,d.keyMap),u=!0,be(s,n),c&&c.takeRecords(),u=!1)}).catch(function(){})}}function g(s){const d=Ie(s);d.forEach(v=>{var x=v.key+"\0"+(v.context||"");a(v.key)||t.has(x)||(t.add(x),t.add(v.key),i.push(v),o.phrases.push(v))}),B(d,Object.keys(n)),u=!0,be(d,n),c&&c.takeRecords(),u=!1,o.fileMode||(clearTimeout(l),l=setTimeout(h,500))}function f(s){m.add(s),p||(p=requestAnimationFrame(function(){p=null;var d=Array.from(m);m.clear(),d.forEach(function(v){v.isConnected&&g(v)})}))}return c=new MutationObserver(s=>{if(!u){var d=[],v=new Set;for(const y of s)for(const E of y.addedNodes)if(E.nodeType===Node.ELEMENT_NODE)d.push(E);else if(E.nodeType===Node.TEXT_NODE){var x=E.parentElement;x&&x.isConnected&&v.add(x)}d.forEach(function(y){g(y)}),v.forEach(function(y){f(y)})}}),c.observe(document.body,{childList:!0,subtree:!0}),c}var ot=["aria-labelledby","aria-label","aria-describedby","role","aria-hidden","alt","title"],_e="\0";function it(e){return e.element?e.element:e.textNode&&e.textNode.parentElement?e.textNode.parentElement:null}function Me(){return!o.apiKey||!o.apiBase?Promise.resolve({}):fetch(o.apiBase+"/api/aria",{headers:{"X-API-Key":o.apiKey}}).then(function(e){return e.json()}).then(function(e){var n={};return Array.isArray(e)&&e.forEach(function(t){var r=t.attributes||{};n[t.key+_e+(t.context||"")]=r,Object.prototype.hasOwnProperty.call(n,t.key)||(n[t.key]=r)}),n}).catch(function(e){return console.warn("[loco] Failed to fetch ARIA rules:",e),{}})}function lt(e,n){if(!e||!n)return!1;var t=e.__locoAriaPrev||{},r=!1;return ot.forEach(function(a){if(Object.prototype.hasOwnProperty.call(n,a)){var i=n[a];if(!(typeof i!="string"||i.trim()==="")){Object.prototype.hasOwnProperty.call(t,a)||(t[a]=e.hasAttribute(a)?e.getAttribute(a):null);try{e.setAttribute(a,i.trim()),r=!0}catch(l){console.warn("[loco] Could not set "+a,l)}}}}),r&&(e.__locoAriaPrev=t,e.setAttribute("data-loco-aria","")),r}function we(e,n){if(!n)return{applied:0};var t=0;return e.forEach(function(r){var a=r.key+_e+(r.context||""),i=n[a]||n[r.key];if(i){var l=it(r);l&<(l,i)&&t++}}),{applied:t}}var Ke="loco",st=2;function q(){return new Promise(function(e,n){try{var t=indexedDB.open(Ke,st);t.onupgradeneeded=function(r){var a=r.target.result;a.objectStoreNames.contains("meta")&&r.oldVersion<2&&a.deleteObjectStore("meta"),a.objectStoreNames.contains("meta")||a.createObjectStore("meta",{keyPath:"key"}),a.objectStoreNames.contains("translations")||a.createObjectStore("translations",{keyPath:"lang"})},t.onsuccess=function(r){e(r.target.result)},t.onerror=function(){n(t.error)}}catch(r){n(r)}})}function se(){return q().then(function(e){return new Promise(function(n,t){var r=e.transaction("meta","readonly"),a=r.objectStore("meta").get("registry");a.onsuccess=function(){e.close();var i=a.result;n(i?{languages:i.languages||[],languageNames:i.languageNames||{}}:null)},a.onerror=function(){e.close(),t(a.error)}})})}function Be(e){var n="source:"+e;return q().then(function(t){return new Promise(function(r,a){var i=t.transaction("meta","readonly"),l=i.objectStore("meta").get(n);l.onsuccess=function(){t.close();var p=l.result;r(p?{url:p.url,timestamp:p.timestamp,storedAt:p.storedAt}:null)},l.onerror=function(){t.close(),a(l.error)}})})}function ct(e){return q().then(function(n){return new Promise(function(t,r){var a=n.transaction("translations","readonly"),i=a.objectStore("translations").get(e);i.onsuccess=function(){n.close();var l=i.result;t(l?l.data:null)},i.onerror=function(){n.close(),r(i.error)}})})}function ut(){return q().then(function(e){return new Promise(function(n,t){var r=e.transaction(["meta","translations"],"readonly"),a=r.objectStore("meta"),i=a.get("registry");i.onsuccess=function(){var l=i.result;if(!l||!l.languages||l.languages.length===0){e.close(),n(null);return}var p=j(),m=p||l.languages[0],c=r.objectStore("translations").get(m);c.onsuccess=function(){e.close();var u=c.result;if(!u||!u.data){n(null);return}var h={};h[m]=u.data,n({languages:l.languages,languageNames:l.languageNames||{},translations:h})},c.onerror=function(){e.close(),t(c.error)}},i.onerror=function(){e.close(),t(i.error)}})})}function ce(e,n,t){var r=n.languages||[],a=n.languageNames||{},i=n.translations||{},l=n.timestamp||0;return q().then(function(p){return new Promise(function(m,c){var u=p.transaction(["meta","translations"],"readwrite"),h=u.objectStore("meta"),g=u.objectStore("translations"),f=h.get("registry");f.onsuccess=function(){var s=f.result,d,v;if(t&&s){var x=s.languages||[];d=x.slice();for(var y=0;y<r.length;y++)d.indexOf(r[y])===-1&&d.push(r[y]);v={};var E=s.languageNames||{},w;for(w in E)v[w]=E[w];for(w in a)v[w]=a[w]}else d=r,v=a;h.put({key:"registry",languages:d,languageNames:v}),h.put({key:"source:"+e,url:e,timestamp:l,storedAt:Date.now()});for(var T=0;T<r.length;T++)i[r[T]]&&(t&&Array.isArray(i[r[T]])?function(P){var L=g.get(P);L.onsuccess=function(){var R=L.result,k=R&&Array.isArray(R.data)?R.data:null,G=i[P];if(k){for(var We="\0",J={},me=[],Z=0;Z<k.length;Z++){var Ae=k[Z].key+We+(k[Z].context||"");J.hasOwnProperty(Ae)||me.push(Ae),J[Ae]=k[Z]}for(var z=0;z<G.length;z++){var Le=G[z].key+We+(G[z].context||"");J.hasOwnProperty(Le)||me.push(Le),J[Le]=G[z]}for(var Qe=[],ke=0;ke<me.length;ke++)Qe.push(J[me[ke]]);g.put({lang:P,data:Qe})}else g.put({lang:P,data:G})}}(r[T]):g.put({lang:r[T],data:i[r[T]]}))},u.oncomplete=function(){p.close(),m()},u.onerror=function(){p.close(),c(u.error)}})})}function ft(){return new Promise(function(e){var n=indexedDB.deleteDatabase(Ke);n.onsuccess=function(){e()},n.onerror=function(){e()},n.onblocked=function(){e()}})}var dt='<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" width="32" height="32"><defs><clipPath id="loco-wc"><circle cx="100" cy="100" r="90"/></clipPath></defs><circle cx="100" cy="100" r="90" fill="#1a1f2e"/><g clip-path="url(#loco-wc)"><g transform="translate(100,108) scale(0.72) translate(-334,-198)"><ellipse cx="310" cy="318" rx="10" ry="38" fill="#2ECC88" transform="rotate(-18 310 318)"/><ellipse cx="326" cy="326" rx="9" ry="42" fill="#34D99A" transform="rotate(-6 326 326)"/><ellipse cx="342" cy="328" rx="9" ry="42" fill="#7BC74A" transform="rotate(6 342 328)"/><ellipse cx="357" cy="320" rx="9" ry="36" fill="#F07040" transform="rotate(18 357 320)"/><ellipse cx="334" cy="240" rx="62" ry="80" fill="#2ECC88"/><ellipse cx="334" cy="252" rx="36" ry="52" fill="#D4F4B0"/><path d="M275 220 Q228 190 232 265 Q248 295 280 285 Q268 255 275 220Z" fill="#3A8FE0"/><path d="M277 225 Q238 208 240 262 Q252 285 278 277 Q268 252 277 225Z" fill="#6BB3FF" opacity="0.7"/><path d="M393 220 Q440 190 436 265 Q420 295 388 285 Q400 255 393 220Z" fill="#3A8FE0"/><path d="M391 225 Q430 208 428 262 Q416 285 390 277 Q400 252 391 225Z" fill="#6BB3FF" opacity="0.7"/><ellipse cx="334" cy="172" rx="38" ry="30" fill="#2ECC88"/><circle cx="334" cy="148" r="52" fill="#2ECC88"/><ellipse cx="334" cy="118" rx="30" ry="18" fill="#FFB833"/><circle cx="312" cy="138" r="14" fill="white"/><circle cx="315" cy="140" r="9" fill="#2C2C2A"/><circle cx="315" cy="140" r="4" fill="#04342C"/><circle cx="319" cy="136" r="3.5" fill="white"/><circle cx="356" cy="138" r="14" fill="white"/><circle cx="353" cy="140" r="9" fill="#2C2C2A"/><circle cx="353" cy="140" r="4" fill="#04342C"/><circle cx="357" cy="136" r="3.5" fill="white"/><path d="M326 155 Q334 144 342 155 Q342 170 334 173 Q326 170 326 155Z" fill="#E8A020"/><path d="M328 165 Q334 158 340 165 Q340 174 334 176 Q328 174 328 165Z" fill="#A06010"/><ellipse cx="302" cy="152" rx="12" ry="8" fill="#F07040" opacity="0.8"/><ellipse cx="366" cy="152" rx="12" ry="8" fill="#F07040" opacity="0.8"/><path d="M320 100 Q316 68 308 52" stroke="#FFB833" stroke-width="6" fill="none" stroke-linecap="round"/><path d="M334 97 Q334 64 334 46" stroke="#7BC74A" stroke-width="6" fill="none" stroke-linecap="round"/><path d="M348 100 Q352 68 360 52" stroke="#F07040" stroke-width="6" fill="none" stroke-linecap="round"/><circle cx="308" cy="50" r="8" fill="#FFB833"/><circle cx="334" cy="44" r="8" fill="#7BC74A"/><circle cx="360" cy="50" r="8" fill="#F07040"/><rect x="260" y="330" width="168" height="10" rx="5" fill="#8B5E20"/><path d="M310 330 L300 350 M310 330 L315 352 M310 330 L325 348" stroke="#A07030" stroke-width="4" fill="none" stroke-linecap="round"/><path d="M360 330 L350 350 M360 330 L365 352 M360 330 L375 348" stroke="#A07030" stroke-width="4" fill="none" stroke-linecap="round"/></g></g></svg>',Ne=null;function ue(e,n){Ne=n;var t=document.getElementById("loco-lang-widget");t&&t.remove();var r={},a=e.map(function(s){return typeof s=="object"&&s.code?(s.name&&(r[s.code]=s.name),s.code):s});function i(s){return r[s]||s}var l=j()||null,p=document.createElement("div");p.id="loco-lang-widget",p.setAttribute("data-notranslate","");var m={"bottom-right":"bottom:20px;right:20px;","bottom-left":"bottom:20px;left:20px;","top-right":"top:20px;right:20px;","top-left":"top:20px;left:20px;"};p.style.cssText='position:fixed;z-index:2147483647;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;font-size:14px;'+(m[n]||m["bottom-right"]);var c=document.createElement("button");c.innerHTML=dt,c.style.cssText="width:52px;height:52px;border-radius:50%;border:none;background:#1a1f2e;color:#fff;font-size:22px;cursor:pointer;box-shadow:0 4px 14px rgba(0,0,0,0.25);display:flex;align-items:center;justify-content:center;transition:transform 0.2s,box-shadow 0.2s;overflow:hidden;padding:0;",c.onmouseenter=function(){c.style.transform="scale(1.1)",c.style.boxShadow="0 6px 20px rgba(0,0,0,0.35)"},c.onmouseleave=function(){c.style.transform="scale(1)",c.style.boxShadow="0 4px 14px rgba(0,0,0,0.25)"};var u=document.createElement("div");u.style.cssText="display:none;position:absolute;"+(n.indexOf("bottom")===0?"bottom:56px;":"top:56px;")+(n.indexOf("right")>=0?"right:0;":"left:0;")+"background:#fff;border-radius:12px;box-shadow:0 8px 30px rgba(0,0,0,0.18);min-width:200px;max-height:320px;overflow-y:auto;padding:6px 0;";var h=document.createElement("div");h.textContent="Original",h.style.cssText="padding:10px 16px;cursor:pointer;color:#333;transition:background 0.15s;font-weight:600;border-bottom:1px solid #eee;",h.onmouseenter=function(){h.style.background="#f5f5f5"},h.onmouseleave=function(){h.style.background="transparent"},h.onclick=function(){l=null,window.Loco.restore(),f(),u.style.display="none"},u.appendChild(h);var g=[];a.forEach(function(s){var d=document.createElement("div");d.textContent=i(s),d.setAttribute("data-lang",s),d.style.cssText="padding:10px 16px;cursor:pointer;color:#333;transition:background 0.15s;",d.onmouseenter=function(){d.style.background="#f5f5f5"},d.onmouseleave=function(){d.style.background=l===s?"#e8f0fe":"transparent"},d.onclick=function(){l=s,window.Loco.apply(s),f(),u.style.display="none"},u.appendChild(d),g.push({el:d,code:s})});function f(){h.style.background=l===null?"#e8f0fe":"transparent",h.style.fontWeight=l===null?"600":"400",g.forEach(function(s){s.el.style.background=l===s.code?"#e8f0fe":"transparent",s.el.style.fontWeight=l===s.code?"600":"400"})}c.onclick=function(s){s.stopPropagation(),u.style.display=u.style.display==="none"?"block":"none"},document.addEventListener("click",function(s){p.contains(s.target)||(u.style.display="none")}),f(),p.appendChild(u),p.appendChild(c),document.body.appendChild(p)}function ht(e){Ne&&(!e||e.length===0||ue(e,Ne))}var U={__proto__:1,constructor:1,prototype:1};function Ue(e){if(!e||typeof e!="string")return!1;if(e.charAt(0)==="/"||e.charAt(0)===".")return!0;try{var n=new URL(e,window.location.origin);return n.protocol==="http:"||n.protocol==="https:"}catch{return!1}}function fe(e){if(!e||typeof e!="object"||Array.isArray(e))return null;if(Array.isArray(e._raw)){for(var n={},t={},r=0;r<e._raw.length;r++){var a=e._raw[r];!a||typeof a.l!="string"||typeof a.k!="string"||typeof a.v!="string"||(n[a.l]||(n[a.l]=!0,t[a.l]=[]),t[a.l].push({key:a.k,context:typeof a.c=="string"?a.c:"",value:a.v}))}e={languages:Object.keys(n).sort(),languageNames:{},translations:t,timestamp:0}}var i={};if(!Array.isArray(e.languages))return null;i.languages=[];for(var l=0;l<e.languages.length;l++){if(typeof e.languages[l]!="string"||e.languages[l].length>20)return null;i.languages.push(e.languages[l])}if(i.timestamp=typeof e.timestamp=="number"&&isFinite(e.timestamp)?e.timestamp:0,i.languageNames={},e.languageNames&&typeof e.languageNames=="object"&&!Array.isArray(e.languageNames))for(var p in e.languageNames)!e.languageNames.hasOwnProperty(p)||U[p]||typeof e.languageNames[p]=="string"&&e.languageNames[p].length<=100&&(i.languageNames[p]=e.languageNames[p]);if(i.translations={},e.translations&&typeof e.translations=="object"&&!Array.isArray(e.translations)){for(var m in e.translations)if(!(!e.translations.hasOwnProperty(m)||U[m])&&i.languages.indexOf(m)!==-1){var c=e.translations[m];if(Array.isArray(c)){for(var u=[],h=0;h<c.length;h++){var g=c[h];!g||typeof g!="object"||typeof g.key!="string"||typeof g.value!="string"||g.key.length>Y||g.value.length>Y||U[g.key]||u.push({key:g.key,value:g.value,context:typeof g.context=="string"?g.context:""})}i.translations[m]=u}else if(typeof c=="object"){var f={};for(var s in c)!c.hasOwnProperty(s)||U[s]||typeof c[s]=="string"&&(s.length>Y||c[s].length>Y||(f[s]=c[s]));i.translations[m]=f}}}return i}async function He(){try{var e=await fetch(o.apiBase+"/api/project/crawler-config",{headers:{"X-API-Key":o.apiKey}});e.ok&&$e(await e.json())}catch{}Ee(),o.phrases=await V(document.body),oe(o.phrases).then(function(t){t&&t.keyMap&&ne(o.phrases,t.keyMap)}).catch(function(t){console.warn("[loco] Failed to register keys:",t)}),Me().then(function(t){o.ariaRules=t||{};var r=we(o.phrases,o.ariaRules);r.applied>0&&console.log("[loco] applied ARIA rules to "+r.applied+" element(s)")}).catch(function(){}),!o.scanStopped&&o.screenshotsEnabled&&setTimeout(rt,3e3),console.log("[loco] "+o.phrases.length+" text nodes discovered"),console.log(` Loco.textnodes() — list all discovered text nodes
|
|
1
|
+
var Loco=function(){"use strict";var o={apiKey:null,apiBase:null,phrases:[],currentLang:null,translations:{},observer:null,fileMode:!1,fileData:null,fileReadyResolve:null,fileReady:null,fileUrl:null,fileUrls:[],scanStopped:!1,loadedFromCache:!1,screenshotsEnabled:!0,widgetPosition:null,ariaRules:{}},Re=["SCRIPT","STYLE","NOSCRIPT","IFRAME","CODE","SVG","AUDIO","VIDEO","LINK"],Ce=["VAR","STRONG","EM","B","I","SPAN","A","ABBR","MARK","SMALL","SUB","SUP","U","S","TIME"],Pe=["h1","h2","h3","h4","h5","h6","label","legend","caption","figcaption","nav","header","footer","main","section","article","form"],I=new Set(Re),X=new Set(Ce),we=[].concat(Pe),Ne=0,Te=!0,U=1e3,Z=1e4,Ae="loco-lang";function Y(){try{return localStorage.getItem(Ae)}catch{return null}}function le(e){try{e?localStorage.setItem(Ae,e):localStorage.removeItem(Ae)}catch{}}function Je(e){if(e.blockedTags){var n=e.blockedTags.disabled||[],t=e.blockedTags.custom||[];I=new Set(Re.filter(function(a){return n.indexOf(a)<0})),t.forEach(function(a){I.add(a.toUpperCase())})}if(e.inlineTags){var n=e.inlineTags.disabled||[],t=e.inlineTags.custom||[];X=new Set(Ce.filter(function(i){return n.indexOf(i)<0})),t.forEach(function(i){X.add(i.toUpperCase())})}if(e.domContextSelectors){var n=e.domContextSelectors.disabled||[],t=e.domContextSelectors.custom||[];we=Pe.filter(function(i){return n.indexOf(i)<0}).concat(t)}e.screenshotsEnabled===!1&&(o.screenshotsEnabled=!1),typeof e.contextDepth=="number"&&(Ne=e.contextDepth),e.domContextEnabled===!1&&(Te=!1)}function N(e){return e.trim().replace(/\s+/g," ")}function b(e){return!/[a-zA-Z\u00C0-\u024F\u0900-\u097F\u0600-\u06FF]/.test(e)}function se(e){var n=e.replace(/\{\{(?:text|number|decimal|date):\d+\}\}/g,"");return!n.trim()||b(n)}function De(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function ee(e){var t;if(!e||e.nodeType!==1)return!1;const n=(t=e.tagName)==null?void 0:t.toUpperCase();return I.has(n)||e.hasAttribute("notranslate")||e.hasAttribute("data-notranslate")||e.hasAttribute("data-loco-translated")||e.getAttribute("translate")==="no"||e.isContentEditable}var W=new WeakMap;function Ie(e){let n=e.parentElement;for(;n&&n!==document.body;){if(W.has(n))return W.get(n);if(ee(n))return W.set(n,!0),!0;n=n.parentElement}for(n=e.parentElement;n&&n!==document.body&&!W.has(n);)W.set(n,!1),n=n.parentElement;return!1}function ze(){W=new WeakMap}const _e=new Set(["H1","H2","H3","H4","H5","H6"]),Ze=new Set(["SCRIPT","STYLE","NOSCRIPT","CODE"]);let Q=new WeakMap,$=new WeakMap,q=null;function ke(){if(Te){q=new Set;var e=we.slice();try{var n=e.join(",");document.querySelectorAll(n).forEach(function(t){q.add(t)})}catch{e.forEach(function(a){try{document.querySelectorAll(a).forEach(function(r){q.add(r)})}catch{}})}q.forEach(function(t){$.has(t)||ne(t)})}}function te(e){return q?q.has(e):_e.has(e.tagName)?!0:we.some(function(n){try{return e.matches(n)}catch{return!1}})}function Ye(e){let n="";for(const t of e.childNodes)if(t.nodeType===Node.TEXT_NODE){const a=t.textContent.trim();a&&(n+=(n?" ":"")+a)}return n}function et(e,n){for(var t="",a=document.createTreeWalker(e,NodeFilter.SHOW_ALL,{acceptNode:function(i){return i.nodeType===Node.ELEMENT_NODE?Ze.has(i.tagName)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_SKIP:NodeFilter.FILTER_ACCEPT}}),r;(r=a.nextNode())&&!(r.nodeType===Node.TEXT_NODE&&(t+=r.textContent,t.length>=n)););return t.trim()}function ne(e){if($.has(e))return $.get(e);let n=null;const t=Ye(e);if(t)return n=t.substring(0,60),$.set(e,n),n;if(_e.has(e.tagName)){const r=(e.textContent||"").trim().replace(/\s+/g," ");if(r)return n=r.substring(0,60),$.set(e,n),n}var a=et(e,200);if(a){const r=a.split(/\n/)[0].trim().replace(/\s+/g," ");r.length>=2&&!b(r)&&(n=r.substring(0,60))}return $.set(e,n),n}function k(e){if(!e||!Te)return"";if(Q.has(e))return Q.get(e);var n=e.parentElement;if(n&&n!==document.body&&Q.has(n)&&!te(e)){var t=Q.get(n);return Q.set(e,t),t}const a=[],r=new Set;let i=e,l=0;if(e&&e.tagName==="TD"){var g=e.closest("table");if(g){var p=g.querySelector("thead tr th:nth-child("+(e.cellIndex+1)+")");if(p){var c=ne(p);c&&(r.add(c),a.push(c))}}}for(;i&&i!==document.body&&!(Ne>0&&l>=Ne);){l++;let f=i.previousElementSibling;for(;f;){var u=f.tagName.toUpperCase();if(I.has(u)){f=f.previousElementSibling;continue}if(u==="ARTICLE"||u==="MAIN"){f=f.previousElementSibling;continue}if(te(f)){const d=ne(f);d&&!r.has(d)&&(r.add(d),a.unshift(d));break}let s=null;for(const d of f.children)if(te(d)){s=d;break}if(!s)for(const d of f.children){for(const v of d.children)if(te(v)){s=v;break}if(s)break}if(s){const d=ne(s);d&&!r.has(d)&&(r.add(d),a.unshift(d));break}f=f.previousElementSibling}if(te(i)){const s=ne(i);s&&!r.has(s)&&(r.add(s),a.unshift(s))}var h=i.tagName;if(h==="ARTICLE"||h==="MAIN")break;i=i.parentElement}const m=a.join(" > ");return Q.set(e,m),m}function tt(e){return/^\d+$/.test(e)?"number":/^\d+\.\d+$/.test(e)?"decimal":"text"}function nt(e,n){for(var t=n.split(/(\{\{(?:text|number|decimal|date):\d+\}\})/),a=[],r=e,i=0;i<t.length;i++){var l=t[i],g=l.match(/^\{\{(text|number|decimal|date):(\d+)\}\}$/);if(g)if(r.indexOf(l)===0)a.push({type:g[1],index:parseInt(g[2]),originalText:l}),r=r.substring(l.length);else{for(var p="",c=i+1;c<t.length;c++){var u=t[c];if(/^\{\{(?:text|number|decimal|date):\d+\}\}$/.test(u)){if(r.indexOf(u)>=0){p=u;break}}else if(u!==""){p=u;break}}var h;if(p==="")h=r,r="";else{var m=r.indexOf(p);m>=0?(h=r.substring(0,m),r=r.substring(m)):(h=r,r="")}a.push({type:g[1],index:parseInt(g[2]),originalText:h})}else r.indexOf(l)===0&&(r=r.substring(l.length))}return a}function ce(e,n){e.forEach(function(t){if(!(t.varSlots&&t.varSlots.length>0)){var a=n[t.key];a&&(t.varSlots=nt(t.key,a),t.key=a)}})}function rt(e,n){for(var t=n.split(/\{\{(?:text|number|decimal|date):\d+\}\}/g),a=e,r=[],i=0;i<t.length;i++)if(i===0)a.indexOf(t[i])===0&&(a=a.substring(t[i].length));else if(t[i]===""&&i===t.length-1)r.push(a),a="";else{var l=a.indexOf(t[i]);l>=0&&(r.push(a.substring(0,l)),a=a.substring(l+t[i].length))}return r.length>0&&r.every(function(g){return/^[a-zA-Z\s]+$/.test(g.trim())})}function at(e){for(var n=0,t=/\{\{(text|number|decimal|date):\d+\}\}/g,a;(a=t.exec(e))!==null;)switch(a[1]){case"number":n+=3;break;case"decimal":n+=3;break;case"date":n+=2;break;default:n+=1;break}return n}function V(e,n){for(var t=[],a=0;a<n.length;a++){var r=n[a];if(!(r.indexOf("{{text:")<0&&r.indexOf("{{number:")<0&&r.indexOf("{{decimal:")<0&&r.indexOf("{{date:")<0)){for(var i=[],l=[],g=0,p=/\{\{(text|number|decimal|date):\d+\}\}/g,c;(c=p.exec(r))!==null;)i.push(r.substring(g,c.index)),l.push(c[1]),g=p.lastIndex;i.push(r.substring(g));for(var u="",h=0;h<i.length;h++)if(u+=i[h].replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),h<l.length)switch(l[h]){case"number":u+="\\d+";break;case"decimal":u+="\\d+\\.\\d+";break;default:u+=".+";break}t.push({pattern:r,regex:new RegExp("^"+u+"$"),specificity:at(r)})}}if(t.length!==0){t.sort(function(s,d){return d.specificity-s.specificity});for(var m={},f={},a=0;a<n.length;a++)f[n[a]]=!0;return e.forEach(function(s){if(!f[s.key]&&!(s.key.length>U)){for(var d=0;d<t.length;d++)if(t[d].regex.test(s.key)&&!rt(s.key,t[d].pattern)){m[s.key]=t[d].pattern;break}}}),ce(e,m),m}}var re=new WeakMap;function _(e){if(re.has(e))return re.get(e);let n=!1,t=!1;for(const r of e.childNodes)if(r.nodeType===Node.TEXT_NODE&&r.textContent.trim()&&(n=!0),r.nodeType===Node.ELEMENT_NODE){const i=r.tagName.toUpperCase();if(i==="BR")return re.set(e,!1),!1;(i==="VAR"||i==="TIME"&&r.hasAttribute("datetime")||X.has(i))&&(t=!0)}var a=n&&t;return re.set(e,a),a}function ot(){re=new WeakMap}function ue(e){let n="";const t=[];for(const a of e.childNodes){if(a.nodeType===Node.TEXT_NODE){const r=N(a.textContent);r&&(n+=r);continue}if(a.nodeType===Node.ELEMENT_NODE){const r=a.tagName.toUpperCase();if(r==="TIME"&&a.hasAttribute("datetime")){const i=t.length;t.push({type:"date",index:i,raw:a.getAttribute("datetime"),display:a.textContent,node:a}),n+=`{{date:${i}}}`;continue}if(r==="VAR"||X.has(r)){const i=N(a.textContent);if(i){const l=t.length,g=tt(i);t.push({type:g,index:l,tag:r,value:i,node:a}),n+=`{{${g}:${l}}}`}continue}}}return{key:N(n),slots:t}}var fe=["title","placeholder","aria-label"];function Me(e){const n=[],t=new Set;if(e.nodeType===Node.ELEMENT_NODE&&!ee(e)&&_(e)){const{key:c,slots:u}=ue(e);if(c&&c.length<=U)if(se(c))u.forEach(function(h){if(h.type==="text"&&h.value&&h.value.length>=2&&!b(h.value)){var m=k(h.node||e),f=h.value+"\0"+m;t.has(f)||(t.add(f),n.push({type:"text",key:h.value,slots:[],textNode:h.node?h.node.firstChild:null,element:h.node||e,context:m,original:h.value}))}});else{var a=k(e),r=c+"\0"+a;t.has(r)||t.add(r);const h=u.some(m=>m.type==="date")?"mixed-date":u.some(m=>m.type==="text")?"mixed-text":"mixed";n.push({type:h,key:c,slots:u,element:e,context:a,original:c,originalHTML:e.innerHTML})}}const i=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT,{acceptNode(c){var v,y,x;if(c.nodeType===Node.TEXT_NODE){const E=N(c.textContent);if(!E||E.length<2||E.length>U||b(E)||/\{\{(?:text|number|decimal|date):\d+\}\}/.test(E)||Ie(c))return NodeFilter.FILTER_SKIP;const T=(y=(v=c.parentElement)==null?void 0:v.tagName)==null?void 0:y.toUpperCase();if(I.has(T)||_(c.parentElement))return NodeFilter.FILTER_SKIP;for(var u=c.parentElement,h=0;u&&h<3;){var m=(x=u.tagName)==null?void 0:x.toUpperCase();if((m==="VAR"||m==="TIME"||X.has(m))&&u.parentElement&&_(u.parentElement))return NodeFilter.FILTER_SKIP;u=u.parentElement,h++}return NodeFilter.FILTER_ACCEPT}if(c.nodeType===Node.ELEMENT_NODE){const E=c.tagName.toUpperCase();if(I.has(E)||ee(c))return NodeFilter.FILTER_REJECT;if(E==="INPUT"){var f=(c.getAttribute("type")||"").toLowerCase();if(f==="button"||f==="submit"||f==="reset"){var s=N(c.value);if(s&&s.length>=2&&!b(s))return NodeFilter.FILTER_ACCEPT}var d=fe.some(function(T){var A=N(c.getAttribute(T)||"");return A&&A.length>=2&&!b(A)});return d?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}return _(c)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}return NodeFilter.FILTER_SKIP}});let l;for(;l=i.nextNode();){if(l.nodeType===Node.TEXT_NODE){const c=N(l.textContent);if(!c)continue;var a=k(l.parentElement),r=c+"\0"+a;t.has(r)||t.add(r),n.push({type:"text",key:c,slots:[],textNode:l,element:l.parentElement,context:a,original:c});continue}if(l.nodeType===Node.ELEMENT_NODE&&l.tagName.toUpperCase()==="INPUT"){var g=(l.getAttribute("type")||"").toLowerCase(),a=k(l);if(g==="button"||g==="submit"||g==="reset"){var p=N(l.value);if(p&&p.length>=2&&!b(p)){var r=p+"\0"+a;t.has(r)||t.add(r),n.push({type:"input-value",key:p,slots:[],element:l,context:a,original:p})}}fe.forEach(function(u){var h=N(l.getAttribute(u)||"");if(!(!h||h.length<2||b(h))){var m=h+"\0"+a+"\0"+u;t.has(m)||(t.add(m),n.push({type:"input-attr",key:h,attr:u,slots:[],element:l,context:a,original:h}))}});continue}if(l.nodeType===Node.ELEMENT_NODE){const{key:c,slots:u}=ue(l);if(!c||c.length>U)continue;if(se(c)){u.forEach(function(s){if(s.type==="text"&&s.value&&s.value.length>=2&&!b(s.value)){var d=k(s.node||l),v=s.value+"\0"+d;t.has(v)||(t.add(v),n.push({type:"text",key:s.value,slots:[],textNode:s.node?s.node.firstChild:null,element:s.node||l,context:d,original:s.value}))}});continue}var a=k(l),r=c+"\0"+a;t.has(r)||t.add(r);const f=u.some(s=>s.type==="date")?"mixed-date":u.some(s=>s.type==="text")?"mixed-text":"mixed";n.push({type:f,key:c,slots:u,element:l,context:a,original:c,originalHTML:l.innerHTML})}}return n}async function ae(e,n){n||(n=100);const t=[],a=new Set;if(ze(),ot(),ke(),e.nodeType===Node.ELEMENT_NODE&&!ee(e)&&_(e)){const{key:f,slots:s}=ue(e);if(f&&f.length<=U)if(se(f))s.forEach(function(d){if(d.type==="text"&&d.value&&d.value.length>=2&&!b(d.value)){var v=k(d.node||e),y=d.value+"\0"+v;a.has(y)||(a.add(y),t.push({type:"text",key:d.value,slots:[],textNode:d.node?d.node.firstChild:null,element:d.node||e,context:v,original:d.value}))}});else{var r=k(e),i=f+"\0"+r;a.has(i)||a.add(i);const d=s.some(v=>v.type==="date")?"mixed-date":s.some(v=>v.type==="text")?"mixed-text":"mixed";t.push({type:d,key:f,slots:s,element:e,context:r,original:f,originalHTML:e.innerHTML})}}const l=[],g=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT,{acceptNode(f){var T,A,M;if(f.nodeType===Node.TEXT_NODE){const w=N(f.textContent);if(!w||w.length<2||w.length>U||b(w)||/\{\{(?:text|number|decimal|date):\d+\}\}/.test(w)||Ie(f))return NodeFilter.FILTER_SKIP;const L=(A=(T=f.parentElement)==null?void 0:T.tagName)==null?void 0:A.toUpperCase();if(I.has(L)||_(f.parentElement))return NodeFilter.FILTER_SKIP;for(var s=f.parentElement,d=0;s&&d<3;){var v=(M=s.tagName)==null?void 0:M.toUpperCase();if((v==="VAR"||v==="TIME"||X.has(v))&&s.parentElement&&_(s.parentElement))return NodeFilter.FILTER_SKIP;s=s.parentElement,d++}return NodeFilter.FILTER_ACCEPT}if(f.nodeType===Node.ELEMENT_NODE){const w=f.tagName.toUpperCase();if(I.has(w)||ee(f))return NodeFilter.FILTER_REJECT;if(w==="INPUT"){var y=(f.getAttribute("type")||"").toLowerCase();if(y==="button"||y==="submit"||y==="reset"){var x=N(f.value);if(x&&x.length>=2&&!b(x))return NodeFilter.FILTER_ACCEPT}var E=fe.some(function(L){var O=N(f.getAttribute(L)||"");return O&&O.length>=2&&!b(O)});return E?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}return _(f)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}return NodeFilter.FILTER_SKIP}});for(var p;p=g.nextNode();)l.push(p);for(var c=0;c<l.length;c++){c>0&&c%n===0&&await new Promise(function(f){setTimeout(f,0)});var u=l[c];if(u.nodeType===Node.TEXT_NODE){const f=N(u.textContent);if(!f)continue;var r=k(u.parentElement),i=f+"\0"+r;a.has(i)||a.add(i),t.push({type:"text",key:f,slots:[],textNode:u,element:u.parentElement,context:r,original:f});continue}if(u.nodeType===Node.ELEMENT_NODE&&u.tagName.toUpperCase()==="INPUT"){var h=(u.getAttribute("type")||"").toLowerCase(),r=k(u);if(h==="button"||h==="submit"||h==="reset"){var m=N(u.value);if(m&&m.length>=2&&!b(m)){var i=m+"\0"+r;a.has(i)||a.add(i),t.push({type:"input-value",key:m,slots:[],element:u,context:r,original:m})}}fe.forEach(function(s){var d=N(u.getAttribute(s)||"");if(!(!d||d.length<2||b(d))){var v=d+"\0"+r+"\0"+s;a.has(v)||(a.add(v),t.push({type:"input-attr",key:d,attr:s,slots:[],element:u,context:r,original:d}))}});continue}if(u.nodeType===Node.ELEMENT_NODE){const{key:f,slots:s}=ue(u);if(!f||f.length>U)continue;if(se(f)){s.forEach(function(x){if(x.type==="text"&&x.value&&x.value.length>=2&&!b(x.value)){var E=k(x.node||u),T=x.value+"\0"+E;a.has(T)||(a.add(T),t.push({type:"text",key:x.value,slots:[],textNode:x.node?x.node.firstChild:null,element:x.node||u,context:E,original:x.value}))}});continue}var r=k(u),i=f+"\0"+r;a.has(i)||a.add(i);const y=s.some(x=>x.type==="date")?"mixed-date":s.some(x=>x.type==="text")?"mixed-text":"mixed";t.push({type:y,key:f,slots:s,element:u,context:r,original:f,originalHTML:u.innerHTML})}}return t}function de(e){if(o.scanStopped)return Promise.resolve({ok:!0,registered:0,keyMap:{}});var n=new Set,t=[];return e.forEach(function(a){var r=a.key+"\0"+(a.context||"");n.has(r)||a.varSlots&&a.varSlots.length>0&&/\{\{(?:text|number|decimal|date):\d+\}\}/.test(a.key)||(n.add(r),t.push({key:a.key,context:a.context||""}),a.slots&&a.slots.length>0&&a.slots.forEach(function(i){if(i.type==="text"&&i.value&&!b(i.value)){var l=i.value+"\0";n.has(l)||(n.add(l),t.push({key:i.value,context:""}))}}))}),fetch(o.apiBase+"/api/textnodes",{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":o.apiKey},body:JSON.stringify({keys:t,url:window.location.href})}).then(function(a){return a.json()})}function it(e){var n=o.apiBase+"/api/translations?lang="+encodeURIComponent(e);return fetch(n,{headers:{"X-API-Key":o.apiKey}}).then(function(t){return t.json()}).then(function(t){var a={};return Array.isArray(t)?t.forEach(function(r){a[r.key+"\0"+(r.context||"")]=r.value,a.hasOwnProperty(r.key)||(a[r.key]=r.value)}):a=t,a})}function lt(){if(!(o.fileMode||!o.screenshotsEnabled)){var e=document.createElement("script");e.src=o.apiBase+"/cdn/html2canvas.min.js",e.onload=function(){typeof html2canvas=="function"&&html2canvas(document.body,{scale:.35,logging:!1,useCORS:!0,allowTaint:!0,width:window.innerWidth,height:window.innerHeight,windowWidth:window.innerWidth,windowHeight:window.innerHeight}).then(function(n){var t=n.toDataURL("image/jpeg",.5),a=t.split(",")[1];!a||a.length>5e5||fetch(o.apiBase+"/api/screenshots",{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":o.apiKey},body:JSON.stringify({url:window.location.href,screenshot:a})}).catch(function(){})}).catch(function(){})},e.onerror=function(){},document.head.appendChild(e)}}function st(e,n){return e.replace(/\{\{(text|number|decimal|date):(\d+)\}\}/g,(t,a,r)=>{const i=n[parseInt(r)];return i?a==="date"?i.display:i.value:t})}function Ke(e){if(!Array.isArray(e))return e;var n={};return e.forEach(function(t){n[t.key+"\0"+(t.context||"")]=t.value,n.hasOwnProperty(t.key)||(n[t.key]=t.value)}),n}function Le(e,n){let t=0,a=0;return e.forEach(r=>{const i=r.key+"\0"+(r.context||"");var l=n[i]||n[r.key];if(!l&&r.slots&&r.slots.length>0){var g=r.slots.some(function(h){if(h.type!=="text"||!h.value)return!1;var m=h.value+"\0"+(r.context||""),f=h.value+"\0";return n.hasOwnProperty(m)||n.hasOwnProperty(f)||n.hasOwnProperty(h.value)});g&&(l=r.key)}if(!l){a++;return}if(r.type==="input-value"&&r.element)try{r.element.value=l,r.element.setAttribute("data-loco-translated",""),t++;return}catch(h){console.warn("[translate] Could not write to input value",h),a++;return}if(r.type==="input-attr"&&r.element&&r.attr)try{r.element.setAttribute(r.attr,l),r.element.setAttribute("data-loco-translated",""),t++;return}catch(h){console.warn("[translate] Could not write to input attr",h),a++;return}if(r.type==="text"&&r.textNode)try{var p=l;r.varSlots&&r.varSlots.length>0&&(p=p.replace(/\{\{(text|number|decimal|date):(\d+)\}\}/g,function(h,m,f){var s=r.varSlots.find(function(d){return(d.type||"text")===m&&d.index===+f});return s||(s=r.varSlots[+f]),s?s.originalText:h})),p=p.replace(/\{\{(?:text|number|decimal|date):\d+\}\}/g,""),r.textNode.nodeValue=p,r.textNode.parentElement&&r.textNode.parentElement.setAttribute("data-loco-translated",""),t++;return}catch(h){console.warn("[translate] Could not write to text node",h),a++;return}if(r.element){try{const h=st(l,r.slots);let m=l;var c={};r.slots.forEach(f=>{const s=`{{${f.type}:${f.index}}}`;if(f.type==="date"&&f.node)f.node.textContent=f.display,c[s]=f.node.outerHTML;else if(f.node){if(f.type==="text"&&f.value){var d=f.value+"\0"+(r.context||""),v=f.value+"\0",y=n[d]||n[v]||n[f.value];y&&(f.node.textContent=y)}c[s]=f.node.outerHTML}}),r.varSlots&&r.varSlots.length>0&&r.varSlots.forEach(function(f){var s="{{"+f.type+":"+f.index+"}}";c.hasOwnProperty(s)||(c[s]=De(f.originalText))});var u=m.split(/(\{\{(?:text|number|decimal|date):\d+\}\})/g);m=u.map(function(f){return c.hasOwnProperty(f)?c[f]:/^\{\{(?:text|number|decimal|date):\d+\}\}$/.test(f)?"":De(f)}).join(""),r.element.innerHTML=m,r.element.setAttribute("data-loco-translated",""),t++}catch(h){console.warn("[translate] Could not apply mixed translation",h),a++}return}a++}),{applied:t,skipped:a}}async function he(e,n,t){t||(t=100);for(var a=0,r=0,i=performance.now(),l=0;l<e.length;l+=t){l>0&&performance.now()-i>16&&(await new Promise(function(c){requestAnimationFrame(c)}),i=performance.now());var g=e.slice(l,l+t),p=Le(g,n);a+=p.applied,r+=p.skipped}return{applied:a,skipped:r}}function j(e){let n=0;e.forEach(t=>{try{t.type==="input-value"&&t.element?(t.element.value=t.original,t.element.removeAttribute("data-loco-translated"),n++):t.type==="input-attr"&&t.element&&t.attr?(t.element.setAttribute(t.attr,t.original),t.element.removeAttribute("data-loco-translated"),n++):t.type==="text"&&t.textNode&&(t.textNode.nodeValue=t.original,t.textNode.parentElement&&t.textNode.parentElement.removeAttribute("data-loco-translated"),n++)}catch(a){console.warn("[translate] Could not restore text node",a)}}),e.forEach(t=>{if(t.type!=="text")try{t.element&&t.originalHTML!==void 0&&(t.element.innerHTML=t.originalHTML,t.element.removeAttribute("data-loco-translated"),n++)}catch(a){console.warn("[translate] Could not restore node",a)}}),console.log("[loco] untranslated "+n+" phrase(s)")}function pe(e,n){const t=new Set(e),a=[];Object.values(n).forEach(function(s){if(s&&(t.add(s),/\{\{(text|number|decimal|date):\d+\}\}/.test(s))){var d=s.split(/\{\{(?:text|number|decimal|date):\d+\}\}/g),v=d.map(function(y){return y.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")});a.push(new RegExp("^"+v.join(".+")+"$"))}});function r(s){if(t.has(s))return!0;for(var d=0;d<a.length;d++)if(a[d].test(s))return!0;return!1}let i=[],l=null,g=null,p=new Set,c=null,u=!1;function h(){if(i.length!==0){var s=i.splice(0);o.fileMode||de(s).then(function(d){d&&d.keyMap&&(ce(s,d.keyMap),u=!0,Le(s,n),c&&c.takeRecords(),u=!1)}).catch(function(){})}}function m(s){const d=Me(s);d.forEach(v=>{var y=v.key+"\0"+(v.context||"");r(v.key)||t.has(y)||(t.add(y),t.add(v.key),i.push(v),o.phrases.push(v))}),V(d,Object.keys(n)),u=!0,Le(d,n),c&&c.takeRecords(),u=!1,o.fileMode||(clearTimeout(l),l=setTimeout(h,500))}function f(s){p.add(s),g||(g=requestAnimationFrame(function(){g=null;var d=Array.from(p);p.clear(),d.forEach(function(v){v.isConnected&&m(v)})}))}return c=new MutationObserver(s=>{if(!u){var d=[],v=new Set;for(const x of s)for(const E of x.addedNodes)if(E.nodeType===Node.ELEMENT_NODE)d.push(E);else if(E.nodeType===Node.TEXT_NODE){var y=E.parentElement;y&&y.isConnected&&v.add(y)}d.forEach(function(x){m(x)}),v.forEach(function(x){f(x)})}}),c.observe(document.body,{childList:!0,subtree:!0}),c}var Be=["aria-labelledby","aria-label","aria-describedby","role","aria-hidden","alt","title"],Ue="\0";function ct(e){var n={};return!e||typeof e!="object"||Be.forEach(function(t){if(Object.prototype.hasOwnProperty.call(e,t)){var a=e[t];typeof a=="string"&&a.trim()!==""&&(n[t]=a.trim())}}),n}function je(e){var n={};return Array.isArray(e)&&e.forEach(function(t){if(!(!t||typeof t.key!="string")){var a=typeof t.context=="string"?t.context:"",r=ct(t.attributes);Object.keys(r).length!==0&&(n[t.key+Ue+a]=r,Object.prototype.hasOwnProperty.call(n,t.key)||(n[t.key]=r))}}),n}function ut(e){return e.element?e.element:e.textNode&&e.textNode.parentElement?e.textNode.parentElement:null}function He(){return!o.apiKey||!o.apiBase?Promise.resolve({}):fetch(o.apiBase+"/api/aria",{headers:{"X-API-Key":o.apiKey}}).then(function(e){return e.json()}).then(function(e){return je(e)}).catch(function(e){return console.warn("[loco] Failed to fetch ARIA rules:",e),{}})}function ft(e,n){if(!e||!n)return!1;var t=e.__locoAriaPrev||{},a=!1;return Be.forEach(function(r){if(Object.prototype.hasOwnProperty.call(n,r)){var i=n[r];if(!(typeof i!="string"||i.trim()==="")){Object.prototype.hasOwnProperty.call(t,r)||(t[r]=e.hasAttribute(r)?e.getAttribute(r):null);try{e.setAttribute(r,i.trim()),a=!0}catch(l){console.warn("[loco] Could not set "+r,l)}}}}),a&&(e.__locoAriaPrev=t,e.setAttribute("data-loco-aria","")),a}function G(e,n){if(!n)return{applied:0};var t=0;return e.forEach(function(a){var r=a.key+Ue+(a.context||""),i=n[r]||n[a.key];if(i){var l=ut(a);l&&ft(l,i)&&t++}}),{applied:t}}var Xe="loco",dt=2;function oe(){return new Promise(function(e,n){try{var t=indexedDB.open(Xe,dt);t.onupgradeneeded=function(a){var r=a.target.result;r.objectStoreNames.contains("meta")&&a.oldVersion<2&&r.deleteObjectStore("meta"),r.objectStoreNames.contains("meta")||r.createObjectStore("meta",{keyPath:"key"}),r.objectStoreNames.contains("translations")||r.createObjectStore("translations",{keyPath:"lang"})},t.onsuccess=function(a){e(a.target.result)},t.onerror=function(){n(t.error)}}catch(a){n(a)}})}function ge(){return oe().then(function(e){return new Promise(function(n,t){var a=e.transaction("meta","readonly"),r=a.objectStore("meta").get("registry");r.onsuccess=function(){e.close();var i=r.result;n(i?{languages:i.languages||[],languageNames:i.languageNames||{}}:null)},r.onerror=function(){e.close(),t(r.error)}})})}function We(e){var n="source:"+e;return oe().then(function(t){return new Promise(function(a,r){var i=t.transaction("meta","readonly"),l=i.objectStore("meta").get(n);l.onsuccess=function(){t.close();var g=l.result;a(g?{url:g.url,timestamp:g.timestamp,storedAt:g.storedAt}:null)},l.onerror=function(){t.close(),r(l.error)}})})}function ht(e){return oe().then(function(n){return new Promise(function(t,a){var r=n.transaction("translations","readonly"),i=r.objectStore("translations").get(e);i.onsuccess=function(){n.close();var l=i.result;t(l?l.data:null)},i.onerror=function(){n.close(),a(i.error)}})})}function pt(){return oe().then(function(e){return new Promise(function(n,t){var a=e.transaction(["meta","translations"],"readonly"),r=a.objectStore("meta"),i=r.get("registry");i.onsuccess=function(){var l=i.result;if(!l||!l.languages||l.languages.length===0){e.close(),n(null);return}var g=Y(),p=g||l.languages[0],c=a.objectStore("translations").get(p);c.onsuccess=function(){e.close();var u=c.result;if(!u||!u.data){n(null);return}var h={};h[p]=u.data;var m=a.objectStore("meta").get("aria");m.onsuccess=function(){n({languages:l.languages,languageNames:l.languageNames||{},translations:h,aria:Array.isArray(m.result&&m.result.rules)?m.result.rules:[]})},m.onerror=function(){n({languages:l.languages,languageNames:l.languageNames||{},translations:h,aria:[]})}},c.onerror=function(){e.close(),t(c.error)}},i.onerror=function(){e.close(),t(i.error)}})})}function me(e,n,t){var a=n.languages||[],r=n.languageNames||{},i=n.translations||{},l=Array.isArray(n.aria)?n.aria:[],g=n.timestamp||0;return oe().then(function(p){return new Promise(function(c,u){var h=p.transaction(["meta","translations"],"readwrite"),m=h.objectStore("meta"),f=h.objectStore("translations"),s=m.get("registry");s.onsuccess=function(){var d=s.result,v,y;if(t&&d){var x=d.languages||[];v=x.slice();for(var E=0;E<a.length;E++)v.indexOf(a[E])===-1&&v.push(a[E]);y={};var T=d.languageNames||{},A;for(A in T)y[A]=T[A];for(A in r)y[A]=r[A]}else v=a,y=r;m.put({key:"registry",languages:v,languageNames:y}),m.put({key:"source:"+e,url:e,timestamp:g,storedAt:Date.now()});var M=m.get("aria");M.onsuccess=function(){var L=l;if(t&&M.result&&Array.isArray(M.result.rules)){for(var O="\0",F={},R=[],K=M.result.rules,z=0;z<K.length;z++){var S=K[z];if(!(!S||typeof S.key!="string")){var B=S.key+O+(S.context||"");F.hasOwnProperty(B)||R.push(B),F[B]=S}}for(var C=0;C<l.length;C++){var P=l[C];if(!(!P||typeof P.key!="string")){var D=P.key+O+(P.context||"");F.hasOwnProperty(D)||R.push(D),F[D]=P}}L=R.map(function(ie){return F[ie]})}m.put({key:"aria",rules:L})},M.onerror=function(){m.put({key:"aria",rules:l})};for(var w=0;w<a.length;w++)i[a[w]]&&(t&&Array.isArray(i[a[w]])?function(L){var O=f.get(L);O.onsuccess=function(){var F=O.result,R=F&&Array.isArray(F.data)?F.data:null,K=i[L];if(R){for(var z="\0",S={},B=[],C=0;C<R.length;C++){var P=R[C].key+z+(R[C].context||"");S.hasOwnProperty(P)||B.push(P),S[P]=R[C]}for(var D=0;D<K.length;D++){var ie=K[D].key+z+(K[D].context||"");S.hasOwnProperty(ie)||B.push(ie),S[ie]=K[D]}for(var Ge=[],Fe=0;Fe<B.length;Fe++)Ge.push(S[B[Fe]]);f.put({lang:L,data:Ge})}else f.put({lang:L,data:K})}}(a[w]):f.put({lang:a[w],data:i[a[w]]}))},h.oncomplete=function(){p.close(),c()},h.onerror=function(){p.close(),u(h.error)}})})}function gt(){return new Promise(function(e){var n=indexedDB.deleteDatabase(Xe);n.onsuccess=function(){e()},n.onerror=function(){e()},n.onblocked=function(){e()}})}var mt='<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" width="32" height="32"><defs><clipPath id="loco-wc"><circle cx="100" cy="100" r="90"/></clipPath></defs><circle cx="100" cy="100" r="90" fill="#1a1f2e"/><g clip-path="url(#loco-wc)"><g transform="translate(100,108) scale(0.72) translate(-334,-198)"><ellipse cx="310" cy="318" rx="10" ry="38" fill="#2ECC88" transform="rotate(-18 310 318)"/><ellipse cx="326" cy="326" rx="9" ry="42" fill="#34D99A" transform="rotate(-6 326 326)"/><ellipse cx="342" cy="328" rx="9" ry="42" fill="#7BC74A" transform="rotate(6 342 328)"/><ellipse cx="357" cy="320" rx="9" ry="36" fill="#F07040" transform="rotate(18 357 320)"/><ellipse cx="334" cy="240" rx="62" ry="80" fill="#2ECC88"/><ellipse cx="334" cy="252" rx="36" ry="52" fill="#D4F4B0"/><path d="M275 220 Q228 190 232 265 Q248 295 280 285 Q268 255 275 220Z" fill="#3A8FE0"/><path d="M277 225 Q238 208 240 262 Q252 285 278 277 Q268 252 277 225Z" fill="#6BB3FF" opacity="0.7"/><path d="M393 220 Q440 190 436 265 Q420 295 388 285 Q400 255 393 220Z" fill="#3A8FE0"/><path d="M391 225 Q430 208 428 262 Q416 285 390 277 Q400 252 391 225Z" fill="#6BB3FF" opacity="0.7"/><ellipse cx="334" cy="172" rx="38" ry="30" fill="#2ECC88"/><circle cx="334" cy="148" r="52" fill="#2ECC88"/><ellipse cx="334" cy="118" rx="30" ry="18" fill="#FFB833"/><circle cx="312" cy="138" r="14" fill="white"/><circle cx="315" cy="140" r="9" fill="#2C2C2A"/><circle cx="315" cy="140" r="4" fill="#04342C"/><circle cx="319" cy="136" r="3.5" fill="white"/><circle cx="356" cy="138" r="14" fill="white"/><circle cx="353" cy="140" r="9" fill="#2C2C2A"/><circle cx="353" cy="140" r="4" fill="#04342C"/><circle cx="357" cy="136" r="3.5" fill="white"/><path d="M326 155 Q334 144 342 155 Q342 170 334 173 Q326 170 326 155Z" fill="#E8A020"/><path d="M328 165 Q334 158 340 165 Q340 174 334 176 Q328 174 328 165Z" fill="#A06010"/><ellipse cx="302" cy="152" rx="12" ry="8" fill="#F07040" opacity="0.8"/><ellipse cx="366" cy="152" rx="12" ry="8" fill="#F07040" opacity="0.8"/><path d="M320 100 Q316 68 308 52" stroke="#FFB833" stroke-width="6" fill="none" stroke-linecap="round"/><path d="M334 97 Q334 64 334 46" stroke="#7BC74A" stroke-width="6" fill="none" stroke-linecap="round"/><path d="M348 100 Q352 68 360 52" stroke="#F07040" stroke-width="6" fill="none" stroke-linecap="round"/><circle cx="308" cy="50" r="8" fill="#FFB833"/><circle cx="334" cy="44" r="8" fill="#7BC74A"/><circle cx="360" cy="50" r="8" fill="#F07040"/><rect x="260" y="330" width="168" height="10" rx="5" fill="#8B5E20"/><path d="M310 330 L300 350 M310 330 L315 352 M310 330 L325 348" stroke="#A07030" stroke-width="4" fill="none" stroke-linecap="round"/><path d="M360 330 L350 350 M360 330 L365 352 M360 330 L375 348" stroke="#A07030" stroke-width="4" fill="none" stroke-linecap="round"/></g></g></svg>',Se=null;function ve(e,n){Se=n;var t=document.getElementById("loco-lang-widget");t&&t.remove();var a={},r=e.map(function(s){return typeof s=="object"&&s.code?(s.name&&(a[s.code]=s.name),s.code):s});function i(s){return a[s]||s}var l=Y()||null,g=document.createElement("div");g.id="loco-lang-widget",g.setAttribute("data-notranslate","");var p={"bottom-right":"bottom:20px;right:20px;","bottom-left":"bottom:20px;left:20px;","top-right":"top:20px;right:20px;","top-left":"top:20px;left:20px;"};g.style.cssText='position:fixed;z-index:2147483647;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;font-size:14px;'+(p[n]||p["bottom-right"]);var c=document.createElement("button");c.innerHTML=mt,c.style.cssText="width:52px;height:52px;border-radius:50%;border:none;background:#1a1f2e;color:#fff;font-size:22px;cursor:pointer;box-shadow:0 4px 14px rgba(0,0,0,0.25);display:flex;align-items:center;justify-content:center;transition:transform 0.2s,box-shadow 0.2s;overflow:hidden;padding:0;",c.onmouseenter=function(){c.style.transform="scale(1.1)",c.style.boxShadow="0 6px 20px rgba(0,0,0,0.35)"},c.onmouseleave=function(){c.style.transform="scale(1)",c.style.boxShadow="0 4px 14px rgba(0,0,0,0.25)"};var u=document.createElement("div");u.style.cssText="display:none;position:absolute;"+(n.indexOf("bottom")===0?"bottom:56px;":"top:56px;")+(n.indexOf("right")>=0?"right:0;":"left:0;")+"background:#fff;border-radius:12px;box-shadow:0 8px 30px rgba(0,0,0,0.18);min-width:200px;max-height:320px;overflow-y:auto;padding:6px 0;";var h=document.createElement("div");h.textContent="Original",h.style.cssText="padding:10px 16px;cursor:pointer;color:#333;transition:background 0.15s;font-weight:600;border-bottom:1px solid #eee;",h.onmouseenter=function(){h.style.background="#f5f5f5"},h.onmouseleave=function(){h.style.background="transparent"},h.onclick=function(){l=null,window.Loco.restore(),f(),u.style.display="none"},u.appendChild(h);var m=[];r.forEach(function(s){var d=document.createElement("div");d.textContent=i(s),d.setAttribute("data-lang",s),d.style.cssText="padding:10px 16px;cursor:pointer;color:#333;transition:background 0.15s;",d.onmouseenter=function(){d.style.background="#f5f5f5"},d.onmouseleave=function(){d.style.background=l===s?"#e8f0fe":"transparent"},d.onclick=function(){l=s,window.Loco.apply(s),f(),u.style.display="none"},u.appendChild(d),m.push({el:d,code:s})});function f(){h.style.background=l===null?"#e8f0fe":"transparent",h.style.fontWeight=l===null?"600":"400",m.forEach(function(s){s.el.style.background=l===s.code?"#e8f0fe":"transparent",s.el.style.fontWeight=l===s.code?"600":"400"})}c.onclick=function(s){s.stopPropagation(),u.style.display=u.style.display==="none"?"block":"none"},document.addEventListener("click",function(s){g.contains(s.target)||(u.style.display="none")}),f(),g.appendChild(u),g.appendChild(c),document.body.appendChild(g)}function vt(e){Se&&(!e||e.length===0||ve(e,Se))}var H={__proto__:1,constructor:1,prototype:1};function Qe(e){if(!e||typeof e!="string")return!1;if(e.charAt(0)==="/"||e.charAt(0)===".")return!0;try{var n=new URL(e,window.location.origin);return n.protocol==="http:"||n.protocol==="https:"}catch{return!1}}function ye(e){if(!e||typeof e!="object"||Array.isArray(e))return null;if(Array.isArray(e._raw)){for(var n={},t={},a=0;a<e._raw.length;a++){var r=e._raw[a];!r||typeof r.l!="string"||typeof r.k!="string"||typeof r.v!="string"||(n[r.l]||(n[r.l]=!0,t[r.l]=[]),t[r.l].push({key:r.k,context:typeof r.c=="string"?r.c:"",value:r.v}))}e={languages:Object.keys(n).sort(),languageNames:{},translations:t,timestamp:0}}var i={};if(!Array.isArray(e.languages))return null;i.languages=[];for(var l=0;l<e.languages.length;l++){if(typeof e.languages[l]!="string"||e.languages[l].length>20)return null;i.languages.push(e.languages[l])}if(i.timestamp=typeof e.timestamp=="number"&&isFinite(e.timestamp)?e.timestamp:0,i.languageNames={},e.languageNames&&typeof e.languageNames=="object"&&!Array.isArray(e.languageNames))for(var g in e.languageNames)!e.languageNames.hasOwnProperty(g)||H[g]||typeof e.languageNames[g]=="string"&&e.languageNames[g].length<=100&&(i.languageNames[g]=e.languageNames[g]);if(i.translations={},e.translations&&typeof e.translations=="object"&&!Array.isArray(e.translations)){for(var p in e.translations)if(!(!e.translations.hasOwnProperty(p)||H[p])&&i.languages.indexOf(p)!==-1){var c=e.translations[p];if(Array.isArray(c)){for(var u=[],h=0;h<c.length;h++){var m=c[h];!m||typeof m!="object"||typeof m.key!="string"||typeof m.value!="string"||m.key.length>Z||m.value.length>Z||H[m.key]||u.push({key:m.key,value:m.value,context:typeof m.context=="string"?m.context:""})}i.translations[p]=u}else if(typeof c=="object"){var f={};for(var s in c)!c.hasOwnProperty(s)||H[s]||typeof c[s]=="string"&&(s.length>Z||c[s].length>Z||(f[s]=c[s]));i.translations[p]=f}}}if(i.aria=[],Array.isArray(e.aria))for(var d=0;d<e.aria.length;d++){var r=e.aria[d];if(!(!r||typeof r!="object")&&!(typeof r.key!="string"||r.key.length>Z)&&!H[r.key]){var v=typeof r.context=="string"?r.context:"",y=r.attributes;!y||typeof y!="object"||Array.isArray(y)||i.aria.push({key:r.key,context:v,attributes:y})}}return i}async function $e(){try{var e=await fetch(o.apiBase+"/api/project/crawler-config",{headers:{"X-API-Key":o.apiKey}});e.ok&&Je(await e.json())}catch{}ke(),o.phrases=await ae(document.body),de(o.phrases).then(function(t){t&&t.keyMap&&ce(o.phrases,t.keyMap)}).catch(function(t){console.warn("[loco] Failed to register keys:",t)}),He().then(function(t){o.ariaRules=t||{};var a=G(o.phrases,o.ariaRules);a.applied>0&&console.log("[loco] applied ARIA rules to "+a.applied+" element(s)")}).catch(function(){}),!o.scanStopped&&o.screenshotsEnabled&&setTimeout(lt,3e3),console.log("[loco] "+o.phrases.length+" text nodes discovered"),console.log(` Loco.textnodes() — list all discovered text nodes
|
|
2
2
|
Loco.apply("zh-Hans") — apply translations for a language
|
|
3
3
|
Loco.restore() — revert to original text
|
|
4
|
-
Loco.rescan() — re-scan DOM for new nodes`);var n=j();n?H.apply(n):o.observer=le(o.phrases.map(function(t){return t.key+"\0"+(t.context||"")}),{})}function pt(e,n){for(var t="\0",r={},a=[],i=0;i<e.length;i++){var l=e[i],p=l.key+t+(l.context||"");r.hasOwnProperty(p)||a.push(p),r[p]=l}for(var m=0;m<n.length;m++){var c=n[m],u=c.key+t+(c.context||"");r.hasOwnProperty(u)||a.push(u),r[u]=c}for(var h=[],g=0;g<a.length;g++)h.push(r[a[g]]);return h}async function de(e){o.screenshotsEnabled=!1,Ee(),o.phrases=await V(document.body);var n=[],t=o.fileData.translations||{},r=(o.fileData.languages||[])[0];r&&t[r]&&(t[r]=De(t[r]),n=Object.keys(t[r]));var a=B(o.phrases,n),i=a?Object.keys(a).length:0,l=(o.fileData.languages||[]).length;console.log("[loco] (file mode) "+o.phrases.length+" text nodes discovered, "+l+" language(s) available"+(i?", "+i+" var-remapped":"")+" ["+e+"]"),console.log(" Languages: "+(o.fileData.languages||[]).join(", "));var p=j();p?H.apply(p):o.observer=le(o.phrases.map(function(m){return m.key+"\0"+(m.context||"")}),{})}async function je(e){try{indexedDB.deleteDatabase("loco-translations")}catch{}try{indexedDB.deleteDatabase("loco-meta")}catch{}try{indexedDB.databases&&indexedDB.databases().then(function(t){t.forEach(function(r){if(r.name&&r.name.indexOf("loco-tr-")===0)try{indexedDB.deleteDatabase(r.name)}catch{}})}).catch(function(){})}catch{}o.fileUrls=e;var n=null;try{n=await ut()}catch{}n&&n.translations?(o.fileData={languages:n.languages,languageNames:n.languageNames||{},translations:n.translations,timestamp:0},o.loadedFromCache=!0,await de("cache"),o.fileReadyResolve&&(o.fileReadyResolve(),o.fileReadyResolve=null),gt(e)):(await mt(e),await de("network"),o.fileReadyResolve&&(o.fileReadyResolve(),o.fileReadyResolve=null))}async function mt(e){for(var n=e.map(function(m){return fetch(m).then(function(c){if(!c.ok)throw new Error("HTTP "+c.status+" for "+m);return c.text()}).then(function(c){if(!c||!c.trim())return null;var u;try{u=JSON.parse(c)}catch{return null}var h=fe(u);return h?{url:m,data:h}:(console.warn("[loco] File rejected (invalid schema): "+m),null)}).catch(function(c){return console.warn("[loco] Failed to load "+m+":",c),null})}),t=await Promise.all(n),r=!0,a=0;a<t.length;a++)if(t[a]){var i=t[a].url,l=t[a].data,p=!r||(l.languages||[]).length===1;he(l,r),r=!1;try{await ce(i,l,p)}catch{}}o.loadedFromCache=!1}function he(e,n){if(!o.fileData||n){o.fileData={languages:(e.languages||[]).slice(),languageNames:Object.assign({},e.languageNames||{}),translations:Object.assign({},e.translations||{}),timestamp:e.timestamp||0};return}for(var t=e.languages||[],r=0;r<t.length;r++)o.fileData.languages.indexOf(t[r])===-1&&o.fileData.languages.push(t[r]);var a=e.languageNames||{};o.fileData.languageNames||(o.fileData.languageNames={});for(var i in a)!a.hasOwnProperty(i)||U[i]||(o.fileData.languageNames[i]=a[i]);var l=e.translations||{};o.fileData.translations||(o.fileData.translations={});for(var p in l)if(!(!l.hasOwnProperty(p)||U[p])){var m=o.fileData.translations[p],c=l[p];!m||!Array.isArray(m)||!Array.isArray(c)?o.fileData.translations[p]=c:o.fileData.translations[p]=pt(m,c)}e.timestamp&&e.timestamp>o.fileData.timestamp&&(o.fileData.timestamp=e.timestamp)}function gt(e){var n=e.map(function(t){return Promise.all([Be(t).catch(function(){return null}),fetch(t).then(function(r){return r.ok?r.text():null}).catch(function(){return null})]).then(function(r){var a=r[0],i=r[1];if(!i||!i.trim())return null;var l;try{l=JSON.parse(i)}catch{return null}if(l=fe(l),!l)return null;var p=l.timestamp||0,m=a&&a.timestamp||0;if(p!==m){var c=e.length>1||(l.languages||[]).length===1;return ce(t,l,c).catch(function(){}),l}return null})});Promise.all(n).then(function(t){for(var r=!1,a=0;a<t.length;a++)t[a]&&(he(t[a],!1),r=!0);r&&(o.loadedFromCache=!1,o.observer&&(o.observer.disconnect(),o.observer=null),O(o.phrases),de("network — updated").then(function(){Te()}),console.log("[loco] translations refreshed from file(s) (timestamp changed)"))}).catch(function(){console.log("[loco] using cached translations (network unavailable)")})}function Te(){o.widgetPosition&&se().then(function(e){if(e){var n=pe(e.languages,e.languageNames);ht(n)}}).catch(function(){})}function pe(e,n){return e=e||[],n=n||{},e.map(function(t){return n[t]?{code:t,name:n[t]}:t})}function vt(e){return e?e.type==="text"?!!(e.textNode&&e.textNode.parentElement&&e.textNode.isConnected):!!(e.element&&e.element.isConnected):!1}function Xe(){if(!Array.isArray(o.phrases)||o.phrases.length===0)return[];var e=o.phrases.filter(vt);return e.length!==o.phrases.length&&(o.phrases=e),o.phrases}var H={version:"1.1.1",init:function(e){if(!e){console.warn("[loco] Loco.init() requires a config object");return}if(e.file||e.files){o.fileMode=!0,o.fileReady=new Promise(function(r){o.fileReadyResolve=r});for(var n=e.files?e.files.slice():[e.file],t=0;t<n.length;t++)if(!Ue(n[t])){console.warn("[loco] Blocked unsafe URL: "+n[t]);return}o.fileUrl=n[0],document.readyState==="loading"?document.addEventListener("DOMContentLoaded",function(){je(n)}):je(n);return}if(!e.apiKey){console.warn("[loco] Loco.init() requires { apiKey } or { file }");return}if(!e.apiUrl){console.warn("[loco] Loco.init() requires { apiUrl }");return}o.apiKey=e.apiKey,o.apiBase=e.apiUrl.replace(/\/+$/,""),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",He):He()},apply:async function(e){var n=typeof window<"u"&&window.__locoPerfMode;if(n&&(performance.clearMarks(),performance.clearMeasures(),performance.mark("loco-apply-start")),!e){console.warn('[loco] Loco.apply() requires a language code, e.g. Loco.apply("zh-Hans")');return}if(typeof e!="string"||e.length>20||!/^[a-zA-Z0-9\-_]+$/.test(e)){console.warn("[loco] Invalid language code: "+e);return}if(o.fileMode){if(!o.fileData){console.warn("[loco] File not loaded yet. Call Loco.init({ file }) first.");return}if(!o.fileData.translations||!o.fileData.translations[e])try{var t=await ct(e);if(!t||Object.keys(t).length===0){console.warn('[loco] No translations for "'+e+'" in file data or cache');return}return o.fileData.translations||(o.fileData.translations={}),o.fileData.translations[e]=t,o.fileData.languages.indexOf(e)===-1&&o.fileData.languages.push(e),H.apply(e)}catch(m){console.warn('[loco] Failed to load translations for "'+e+'" from cache:',m);return}o.observer&&(o.observer.disconnect(),o.observer=null),O(o.phrases),o.translations=De(o.fileData.translations[e]),o.fileData.translations[e]=o.translations,n&&performance.mark("loco-collect-start");var r=Xe();r.length===0&&(o.phrases=await V(document.body)),n&&(performance.mark("loco-collect-end"),performance.measure("loco-collection-time","loco-collect-start","loco-collect-end"));var a=Object.keys(o.translations);B(o.phrases,a),n&&performance.mark("loco-dom-start");var i=await ie(o.phrases,o.translations);return n&&(performance.mark("loco-dom-end"),performance.measure("loco-dom-write-time","loco-dom-start","loco-dom-end"),performance.measure("loco-apply-total","loco-apply-start","loco-dom-end")),o.observer=le(o.phrases.map(function(m){return m.key+"\0"+(m.context||"")}),o.translations),o.currentLang=e,ee(e),console.log("[loco] (file) applied "+i.applied+" translation(s), "+i.skipped+" pending"),i}if(!o.apiKey||!o.apiBase){console.warn("[loco] Call Loco.init() first");return}o.observer&&(o.observer.disconnect(),o.observer=null),O(o.phrases);try{var l=await nt(e);o.translations=l||{},n&&performance.mark("loco-collect-start");var p=Xe();p.length===0&&(o.phrases=await V(document.body)),n&&(performance.mark("loco-collect-end"),performance.measure("loco-collection-time","loco-collect-start","loco-collect-end")),B(o.phrases,Object.keys(o.translations)),oe(o.phrases).then(function(c){c&&c.keyMap&&(ne(o.phrases,c.keyMap),ie(o.phrases,o.translations))}).catch(function(){}),n&&performance.mark("loco-dom-start");var i=await ie(o.phrases,o.translations);return n&&(performance.mark("loco-dom-end"),performance.measure("loco-dom-write-time","loco-dom-start","loco-dom-end"),performance.measure("loco-apply-total","loco-apply-start","loco-dom-end")),o.observer=le(o.phrases.map(function(c){return c.key+"\0"+(c.context||"")}),o.translations),o.currentLang=e,ee(e),console.log("[loco] applied "+i.applied+" translation(s), "+i.skipped+" pending"),i}catch(m){console.warn("[loco] Failed to fetch translations:",m)}},restore:function(){O(o.phrases),o.observer&&o.observer.disconnect(),o.currentLang=null,ee(null)},rescan:async function(){var e=Object.keys(o.translations).length>0;e&&O(o.phrases),o.currentLang=null,o.phrases=await V(document.body),o.fileMode||oe(o.phrases).catch(function(){}),o.ariaRules&&Object.keys(o.ariaRules).length>0&&we(o.phrases,o.ariaRules),e&&(B(o.phrases,Object.keys(o.translations)),await ie(o.phrases,o.translations))},textnodes:function(){return o.phrases.map(function(e){return{key:e.key,context:e.context||"",element:e.element}})},aria:async function(){var e=await Me();o.ariaRules=e||{};var n=we(o.phrases,o.ariaRules);return console.log("[loco] applied ARIA rules to "+n.applied+" element(s)"),n},stopScan:function(){o.scanStopped=!0,o.observer&&(o.observer.disconnect(),o.observer=null),console.log("[loco] scanning stopped, no further nodes will be sent to dashboard")},startScan:function(){o.scanStopped=!1,console.log("[loco] scanning resumed")},isFileMode:function(){return o.fileMode},languages:function(){if(o.fileMode){var e=function(){var n=o.fileData?o.fileData.languages||[]:[],t=o.fileData&&o.fileData.languageNames||{};return n.map(function(r){return{code:r,name:t[r]||r}})};return!o.fileData&&o.fileReady?o.fileReady.then(function(){return se().then(function(n){return n&&n.languages&&n.languages.length>0?pe(n.languages,n.languageNames):e()}).catch(function(){return e()})}):se().then(function(n){return n&&n.languages&&n.languages.length>0?pe(n.languages,n.languageNames):e()}).catch(function(){return e()})}return!o.apiKey||!o.apiBase?Promise.resolve([]):fetch(o.apiBase+"/api/languages",{headers:{"X-API-Key":o.apiKey}}).then(function(n){return n.json()}).then(function(n){return Array.isArray(n)?n:[]}).catch(function(){return[]})},widget:function(e){e=e||{};var n=e.position||"bottom-right";if(o.widgetPosition=n,o.fileMode){let t=function(){se().then(function(a){var i;if(a&&a.languages&&a.languages.length>0?i=pe(a.languages,a.languageNames):i=r(),i.length===0){console.warn("[loco] No languages found in translation file or cache");return}ue(i,n)}).catch(function(){var a=r();if(a.length===0){console.warn("[loco] No languages found in translation file");return}ue(a,n)})},r=function(){var a=o.fileData?o.fileData.languages||[]:[],i=o.fileData&&o.fileData.languageNames||{};return a.map(function(l){return i[l]?{code:l,name:i[l]}:l})};if(!o.fileData&&o.fileReady){o.fileReady.then(t);return}t();return}if(!o.apiKey||!o.apiBase){console.warn("[loco] Call Loco.init() first");return}fetch(o.apiBase+"/api/languages",{headers:{"X-API-Key":o.apiKey}}).then(function(t){return t.json()}).then(function(t){if(!Array.isArray(t)||t.length===0){console.warn("[loco] No languages found — add translations in the dashboard first");return}ue(t,n)}).catch(function(t){console.warn("[loco] Failed to fetch languages:",t)})},clearCache:function(){return o.fileMode?ft().then(function(){o.fileData&&(o.fileData.translations={},o.fileData.timestamp=0),o.currentLang=null,o.loadedFromCache=!1,ee(null),O(o.phrases),o.observer&&(o.observer.disconnect(),o.observer=null),console.log("[loco] IndexedDB cache cleared — call pullLatest() to re-fetch")}).catch(function(e){console.warn("[loco] Failed to clear cache:",e)}):(console.warn("[loco] clearCache() is only available in file mode"),Promise.resolve())},addFile:function(e){return o.fileMode?e?Ue(e)?(o.fileUrls.indexOf(e)===-1&&o.fileUrls.push(e),fetch(e).then(function(n){if(!n.ok)throw new Error("HTTP "+n.status);return n.text()}).then(function(n){if(!n||!n.trim())throw new Error("Empty file");var t;try{t=JSON.parse(n)}catch{throw new Error("Invalid JSON")}if(t=fe(t),!t)throw new Error("Invalid file schema");var r=!o.fileData||!o.fileData.languages||o.fileData.languages.length===0,a=!r||(t.languages||[]).length===1;return he(t,r),ce(e,t,a).catch(function(){}),Te(),console.log("[loco] added file: "+e+" ("+(t.languages||[]).join(", ")+")"),{status:"added",languages:t.languages||[]}}).catch(function(n){return console.warn("[loco] addFile() failed:",n),{status:"error",reason:n.message}})):(console.warn("[loco] Blocked unsafe URL: "+e),Promise.resolve({status:"error",reason:"unsafe URL"})):Promise.resolve({status:"error",reason:"no URL provided"}):(console.warn("[loco] addFile() is only available in file mode"),Promise.resolve({status:"error",reason:"not in file mode"}))},pullLatest:function(){if(!o.fileMode)return console.warn("[loco] pullLatest() is only available in file mode"),Promise.resolve({status:"skipped",reason:"not in file mode"});var e=o.fileUrls.length>0?o.fileUrls:o.fileUrl?[o.fileUrl]:[];if(e.length===0)return console.warn("[loco] No file URL(s) configured. Call Loco.init({ file }) first."),Promise.resolve({status:"error",reason:"no file URLs"});var n=e.map(function(t){return Promise.all([Be(t).catch(function(){return null}),fetch(t).then(function(r){if(!r.ok)throw new Error("HTTP "+r.status);return r.text()})]).then(function(r){var a=r[0],i=r[1];if(!i||!i.trim())return{url:t,status:"current",reason:"empty"};var l;try{l=JSON.parse(i)}catch{throw new Error("Invalid JSON in "+t)}if(l=fe(l),!l)throw new Error("Invalid file schema in "+t);var p=l.timestamp||0,m=a&&a.timestamp||0;if(p===m&&m!==0){var c=o.fileData&&o.fileData.translations,u=l.languages||[],h=!c||u.some(function(s){return!o.fileData.translations[s]});if(!h)return{url:t,status:"current",timestamp:m}}var g=!o.fileData||!o.fileData.languages||o.fileData.languages.length===0,f=!g||(l.languages||[]).length===1;return he(l,g),ce(t,l,f).catch(function(){}),{url:t,status:"updated",timestamp:p,previousTimestamp:m}}).catch(function(r){return{url:t,status:"error",reason:r.message}})});return Promise.all(n).then(async function(t){var r=t.some(function(u){return u.status==="updated"});if(r){o.loadedFromCache=!1,o.currentLang=null;var a=j();if(a)o.observer&&(o.observer.disconnect(),o.observer=null),O(o.phrases),await de("pullLatest");else{o.phrases=Ie(document.body);var i=o.fileData.translations||{},l=(o.fileData.languages||[])[0];l&&i[l]&&B(o.phrases,Object.keys(i[l]))}Te()}if(t.length===1){var p=t[0];return console.log("[loco] pullLatest: "+p.status+(p.timestamp?" (timestamp: "+p.timestamp+")":"")),p}var m=t.filter(function(u){return u.status==="updated"}).map(function(u){return u.url}),c=t.filter(function(u){return u.status==="current"}).map(function(u){return u.url});return console.log("[loco] pullLatest: "+m.length+" updated, "+c.length+" current"),{status:r?"updated":"current",results:t}}).catch(function(t){return console.warn("[loco] pullLatest() failed:",t),{status:"error",reason:t.message}})}};return window.Loco=H,Object.defineProperty(H,"_state",{value:o,writable:!1,enumerable:!1,configurable:!1}),H}();
|
|
4
|
+
Loco.rescan() — re-scan DOM for new nodes`);var n=Y();n?J.apply(n):o.observer=pe(o.phrases.map(function(t){return t.key+"\0"+(t.context||"")}),{})}function yt(e,n){for(var t="\0",a={},r=[],i=0;i<e.length;i++){var l=e[i],g=l.key+t+(l.context||"");a.hasOwnProperty(g)||r.push(g),a[g]=l}for(var p=0;p<n.length;p++){var c=n[p],u=c.key+t+(c.context||"");a.hasOwnProperty(u)||r.push(u),a[u]=c}for(var h=[],m=0;m<r.length;m++)h.push(a[r[m]]);return h}async function xe(e){o.screenshotsEnabled=!1,ke(),o.phrases=await ae(document.body);var n=[],t=o.fileData.translations||{},a=(o.fileData.languages||[])[0];a&&t[a]&&(t[a]=Ke(t[a]),n=Object.keys(t[a]));var r=V(o.phrases,n),i=r?Object.keys(r).length:0,l=(o.fileData.languages||[]).length;console.log("[loco] (file mode) "+o.phrases.length+" text nodes discovered, "+l+" language(s) available"+(i?", "+i+" var-remapped":"")+" ["+e+"]"),console.log(" Languages: "+(o.fileData.languages||[]).join(", "));var g=Y();g?J.apply(g):o.observer=pe(o.phrases.map(function(p){return p.key+"\0"+(p.context||"")}),{}),o.ariaRules=je(o.fileData.aria||[]),Object.keys(o.ariaRules).length>0&&G(o.phrases,o.ariaRules)}async function qe(e){try{indexedDB.deleteDatabase("loco-translations")}catch{}try{indexedDB.deleteDatabase("loco-meta")}catch{}try{indexedDB.databases&&indexedDB.databases().then(function(t){t.forEach(function(a){if(a.name&&a.name.indexOf("loco-tr-")===0)try{indexedDB.deleteDatabase(a.name)}catch{}})}).catch(function(){})}catch{}o.fileUrls=e;var n=null;try{n=await pt()}catch{}n&&n.translations?(o.fileData={languages:n.languages,languageNames:n.languageNames||{},translations:n.translations,aria:n.aria||[],timestamp:0},o.loadedFromCache=!0,await xe("cache"),o.fileReadyResolve&&(o.fileReadyResolve(),o.fileReadyResolve=null),Et(e)):(await xt(e),await xe("network"),o.fileReadyResolve&&(o.fileReadyResolve(),o.fileReadyResolve=null))}async function xt(e){for(var n=e.map(function(p){return fetch(p).then(function(c){if(!c.ok)throw new Error("HTTP "+c.status+" for "+p);return c.text()}).then(function(c){if(!c||!c.trim())return null;var u;try{u=JSON.parse(c)}catch{return null}var h=ye(u);return h?{url:p,data:h}:(console.warn("[loco] File rejected (invalid schema): "+p),null)}).catch(function(c){return console.warn("[loco] Failed to load "+p+":",c),null})}),t=await Promise.all(n),a=!0,r=0;r<t.length;r++)if(t[r]){var i=t[r].url,l=t[r].data,g=!a||(l.languages||[]).length===1;Ee(l,a),a=!1;try{await me(i,l,g)}catch{}}o.loadedFromCache=!1}function Ee(e,n){if(!o.fileData||n){o.fileData={languages:(e.languages||[]).slice(),languageNames:Object.assign({},e.languageNames||{}),translations:Object.assign({},e.translations||{}),aria:(e.aria||[]).slice(),timestamp:e.timestamp||0},o.fileData.aria||(o.fileData.aria=[]);var t=e.aria||[];if(t.length>0){for(var a="\0",r={},i=[],l=0;l<o.fileData.aria.length;l++){var g=o.fileData.aria[l];if(!(!g||typeof g.key!="string")){var p=g.key+a+(g.context||"");r.hasOwnProperty(p)||i.push(p),r[p]=g}}for(var c=0;c<t.length;c++){var u=t[c];if(!(!u||typeof u.key!="string")){var h=u.key+a+(u.context||"");r.hasOwnProperty(h)||i.push(h),r[h]=u}}o.fileData.aria=i.map(function(T){return r[T]})}return}for(var m=e.languages||[],f=0;f<m.length;f++)o.fileData.languages.indexOf(m[f])===-1&&o.fileData.languages.push(m[f]);var s=e.languageNames||{};o.fileData.languageNames||(o.fileData.languageNames={});for(var d in s)!s.hasOwnProperty(d)||H[d]||(o.fileData.languageNames[d]=s[d]);var v=e.translations||{};o.fileData.translations||(o.fileData.translations={});for(var y in v)if(!(!v.hasOwnProperty(y)||H[y])){var x=o.fileData.translations[y],E=v[y];!x||!Array.isArray(x)||!Array.isArray(E)?o.fileData.translations[y]=E:o.fileData.translations[y]=yt(x,E)}e.timestamp&&e.timestamp>o.fileData.timestamp&&(o.fileData.timestamp=e.timestamp)}function Et(e){var n=e.map(function(t){return Promise.all([We(t).catch(function(){return null}),fetch(t).then(function(a){return a.ok?a.text():null}).catch(function(){return null})]).then(function(a){var r=a[0],i=a[1];if(!i||!i.trim())return null;var l;try{l=JSON.parse(i)}catch{return null}if(l=ye(l),!l)return null;var g=l.timestamp||0,p=r&&r.timestamp||0;if(g!==p){var c=e.length>1||(l.languages||[]).length===1;return me(t,l,c).catch(function(){}),l}return null})});Promise.all(n).then(function(t){for(var a=!1,r=0;r<t.length;r++)t[r]&&(Ee(t[r],!1),a=!0);a&&(o.loadedFromCache=!1,o.observer&&(o.observer.disconnect(),o.observer=null),j(o.phrases),xe("network — updated").then(function(){Oe()}),console.log("[loco] translations refreshed from file(s) (timestamp changed)"))}).catch(function(){console.log("[loco] using cached translations (network unavailable)")})}function Oe(){o.widgetPosition&&ge().then(function(e){if(e){var n=be(e.languages,e.languageNames);vt(n)}}).catch(function(){})}function be(e,n){return e=e||[],n=n||{},e.map(function(t){return n[t]?{code:t,name:n[t]}:t})}function bt(e){return e?e.type==="text"?!!(e.textNode&&e.textNode.parentElement&&e.textNode.isConnected):!!(e.element&&e.element.isConnected):!1}function Ve(){if(!Array.isArray(o.phrases)||o.phrases.length===0)return[];var e=o.phrases.filter(bt);return e.length!==o.phrases.length&&(o.phrases=e),o.phrases}var J={version:"1.1.2",init:function(e){if(!e){console.warn("[loco] Loco.init() requires a config object");return}if(e.file||e.files){o.fileMode=!0,o.fileReady=new Promise(function(a){o.fileReadyResolve=a});for(var n=e.files?e.files.slice():[e.file],t=0;t<n.length;t++)if(!Qe(n[t])){console.warn("[loco] Blocked unsafe URL: "+n[t]);return}o.fileUrl=n[0],document.readyState==="loading"?document.addEventListener("DOMContentLoaded",function(){qe(n)}):qe(n);return}if(!e.apiKey){console.warn("[loco] Loco.init() requires { apiKey } or { file }");return}if(!e.apiUrl){console.warn("[loco] Loco.init() requires { apiUrl }");return}o.apiKey=e.apiKey,o.apiBase=e.apiUrl.replace(/\/+$/,""),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",$e):$e()},apply:async function(e){var n=typeof window<"u"&&window.__locoPerfMode;if(n&&(performance.clearMarks(),performance.clearMeasures(),performance.mark("loco-apply-start")),!e){console.warn('[loco] Loco.apply() requires a language code, e.g. Loco.apply("zh-Hans")');return}if(typeof e!="string"||e.length>20||!/^[a-zA-Z0-9\-_]+$/.test(e)){console.warn("[loco] Invalid language code: "+e);return}if(o.fileMode){if(!o.fileData){console.warn("[loco] File not loaded yet. Call Loco.init({ file }) first.");return}if(!o.fileData.translations||!o.fileData.translations[e])try{var t=await ht(e);if(!t||Object.keys(t).length===0){console.warn('[loco] No translations for "'+e+'" in file data or cache');return}return o.fileData.translations||(o.fileData.translations={}),o.fileData.translations[e]=t,o.fileData.languages.indexOf(e)===-1&&o.fileData.languages.push(e),J.apply(e)}catch(p){console.warn('[loco] Failed to load translations for "'+e+'" from cache:',p);return}o.observer&&(o.observer.disconnect(),o.observer=null),j(o.phrases),o.translations=Ke(o.fileData.translations[e]),o.fileData.translations[e]=o.translations,n&&performance.mark("loco-collect-start");var a=Ve();a.length===0&&(o.phrases=await ae(document.body)),n&&(performance.mark("loco-collect-end"),performance.measure("loco-collection-time","loco-collect-start","loco-collect-end"));var r=Object.keys(o.translations);V(o.phrases,r),n&&performance.mark("loco-dom-start");var i=await he(o.phrases,o.translations);return n&&(performance.mark("loco-dom-end"),performance.measure("loco-dom-write-time","loco-dom-start","loco-dom-end"),performance.measure("loco-apply-total","loco-apply-start","loco-dom-end")),o.ariaRules&&Object.keys(o.ariaRules).length>0&&G(o.phrases,o.ariaRules),o.observer=pe(o.phrases.map(function(p){return p.key+"\0"+(p.context||"")}),o.translations),o.currentLang=e,le(e),console.log("[loco] (file) applied "+i.applied+" translation(s), "+i.skipped+" pending"),i}if(!o.apiKey||!o.apiBase){console.warn("[loco] Call Loco.init() first");return}o.observer&&(o.observer.disconnect(),o.observer=null),j(o.phrases);try{var l=await it(e);o.translations=l||{},n&&performance.mark("loco-collect-start");var g=Ve();g.length===0&&(o.phrases=await ae(document.body)),n&&(performance.mark("loco-collect-end"),performance.measure("loco-collection-time","loco-collect-start","loco-collect-end")),V(o.phrases,Object.keys(o.translations)),de(o.phrases).then(function(c){c&&c.keyMap&&(ce(o.phrases,c.keyMap),he(o.phrases,o.translations))}).catch(function(){}),n&&performance.mark("loco-dom-start");var i=await he(o.phrases,o.translations);return n&&(performance.mark("loco-dom-end"),performance.measure("loco-dom-write-time","loco-dom-start","loco-dom-end"),performance.measure("loco-apply-total","loco-apply-start","loco-dom-end")),o.ariaRules&&Object.keys(o.ariaRules).length>0&&G(o.phrases,o.ariaRules),o.observer=pe(o.phrases.map(function(c){return c.key+"\0"+(c.context||"")}),o.translations),o.currentLang=e,le(e),console.log("[loco] applied "+i.applied+" translation(s), "+i.skipped+" pending"),i}catch(p){console.warn("[loco] Failed to fetch translations:",p)}},restore:function(){j(o.phrases),o.observer&&o.observer.disconnect(),o.currentLang=null,le(null)},rescan:async function(){var e=Object.keys(o.translations).length>0;e&&j(o.phrases),o.currentLang=null,o.phrases=await ae(document.body),o.fileMode||de(o.phrases).catch(function(){}),o.ariaRules&&Object.keys(o.ariaRules).length>0&&G(o.phrases,o.ariaRules),e&&(V(o.phrases,Object.keys(o.translations)),await he(o.phrases,o.translations))},textnodes:function(){return o.phrases.map(function(e){return{key:e.key,context:e.context||"",element:e.element}})},aria:async function(){var e=await He();o.ariaRules=e||{};var n=G(o.phrases,o.ariaRules);return console.log("[loco] applied ARIA rules to "+n.applied+" element(s)"),n},stopScan:function(){o.scanStopped=!0,o.observer&&(o.observer.disconnect(),o.observer=null),console.log("[loco] scanning stopped, no further nodes will be sent to dashboard")},startScan:function(){o.scanStopped=!1,console.log("[loco] scanning resumed")},isFileMode:function(){return o.fileMode},languages:function(){if(o.fileMode){var e=function(){var n=o.fileData?o.fileData.languages||[]:[],t=o.fileData&&o.fileData.languageNames||{};return n.map(function(a){return{code:a,name:t[a]||a}})};return!o.fileData&&o.fileReady?o.fileReady.then(function(){return ge().then(function(n){return n&&n.languages&&n.languages.length>0?be(n.languages,n.languageNames):e()}).catch(function(){return e()})}):ge().then(function(n){return n&&n.languages&&n.languages.length>0?be(n.languages,n.languageNames):e()}).catch(function(){return e()})}return!o.apiKey||!o.apiBase?Promise.resolve([]):fetch(o.apiBase+"/api/languages",{headers:{"X-API-Key":o.apiKey}}).then(function(n){return n.json()}).then(function(n){return Array.isArray(n)?n:[]}).catch(function(){return[]})},widget:function(e){e=e||{};var n=e.position||"bottom-right";if(o.widgetPosition=n,o.fileMode){let t=function(){ge().then(function(r){var i;if(r&&r.languages&&r.languages.length>0?i=be(r.languages,r.languageNames):i=a(),i.length===0){console.warn("[loco] No languages found in translation file or cache");return}ve(i,n)}).catch(function(){var r=a();if(r.length===0){console.warn("[loco] No languages found in translation file");return}ve(r,n)})},a=function(){var r=o.fileData?o.fileData.languages||[]:[],i=o.fileData&&o.fileData.languageNames||{};return r.map(function(l){return i[l]?{code:l,name:i[l]}:l})};if(!o.fileData&&o.fileReady){o.fileReady.then(t);return}t();return}if(!o.apiKey||!o.apiBase){console.warn("[loco] Call Loco.init() first");return}fetch(o.apiBase+"/api/languages",{headers:{"X-API-Key":o.apiKey}}).then(function(t){return t.json()}).then(function(t){if(!Array.isArray(t)||t.length===0){console.warn("[loco] No languages found — add translations in the dashboard first");return}ve(t,n)}).catch(function(t){console.warn("[loco] Failed to fetch languages:",t)})},clearCache:function(){return o.fileMode?gt().then(function(){o.fileData&&(o.fileData.translations={},o.fileData.timestamp=0),o.currentLang=null,o.loadedFromCache=!1,le(null),j(o.phrases),o.observer&&(o.observer.disconnect(),o.observer=null),console.log("[loco] IndexedDB cache cleared — call pullLatest() to re-fetch")}).catch(function(e){console.warn("[loco] Failed to clear cache:",e)}):(console.warn("[loco] clearCache() is only available in file mode"),Promise.resolve())},addFile:function(e){return o.fileMode?e?Qe(e)?(o.fileUrls.indexOf(e)===-1&&o.fileUrls.push(e),fetch(e).then(function(n){if(!n.ok)throw new Error("HTTP "+n.status);return n.text()}).then(function(n){if(!n||!n.trim())throw new Error("Empty file");var t;try{t=JSON.parse(n)}catch{throw new Error("Invalid JSON")}if(t=ye(t),!t)throw new Error("Invalid file schema");var a=!o.fileData||!o.fileData.languages||o.fileData.languages.length===0,r=!a||(t.languages||[]).length===1;return Ee(t,a),me(e,t,r).catch(function(){}),Oe(),console.log("[loco] added file: "+e+" ("+(t.languages||[]).join(", ")+")"),{status:"added",languages:t.languages||[]}}).catch(function(n){return console.warn("[loco] addFile() failed:",n),{status:"error",reason:n.message}})):(console.warn("[loco] Blocked unsafe URL: "+e),Promise.resolve({status:"error",reason:"unsafe URL"})):Promise.resolve({status:"error",reason:"no URL provided"}):(console.warn("[loco] addFile() is only available in file mode"),Promise.resolve({status:"error",reason:"not in file mode"}))},pullLatest:function(){if(!o.fileMode)return console.warn("[loco] pullLatest() is only available in file mode"),Promise.resolve({status:"skipped",reason:"not in file mode"});var e=o.fileUrls.length>0?o.fileUrls:o.fileUrl?[o.fileUrl]:[];if(e.length===0)return console.warn("[loco] No file URL(s) configured. Call Loco.init({ file }) first."),Promise.resolve({status:"error",reason:"no file URLs"});var n=e.map(function(t){return Promise.all([We(t).catch(function(){return null}),fetch(t).then(function(a){if(!a.ok)throw new Error("HTTP "+a.status);return a.text()})]).then(function(a){var r=a[0],i=a[1];if(!i||!i.trim())return{url:t,status:"current",reason:"empty"};var l;try{l=JSON.parse(i)}catch{throw new Error("Invalid JSON in "+t)}if(l=ye(l),!l)throw new Error("Invalid file schema in "+t);var g=l.timestamp||0,p=r&&r.timestamp||0;if(g===p&&p!==0){var c=o.fileData&&o.fileData.translations,u=l.languages||[],h=!c||u.some(function(s){return!o.fileData.translations[s]});if(!h)return{url:t,status:"current",timestamp:p}}var m=!o.fileData||!o.fileData.languages||o.fileData.languages.length===0,f=!m||(l.languages||[]).length===1;return Ee(l,m),me(t,l,f).catch(function(){}),{url:t,status:"updated",timestamp:g,previousTimestamp:p}}).catch(function(a){return{url:t,status:"error",reason:a.message}})});return Promise.all(n).then(async function(t){var a=t.some(function(u){return u.status==="updated"});if(a){o.loadedFromCache=!1,o.currentLang=null;var r=Y();if(r)o.observer&&(o.observer.disconnect(),o.observer=null),j(o.phrases),await xe("pullLatest");else{o.phrases=Me(document.body);var i=o.fileData.translations||{},l=(o.fileData.languages||[])[0];l&&i[l]&&V(o.phrases,Object.keys(i[l]))}Oe()}if(t.length===1){var g=t[0];return console.log("[loco] pullLatest: "+g.status+(g.timestamp?" (timestamp: "+g.timestamp+")":"")),g}var p=t.filter(function(u){return u.status==="updated"}).map(function(u){return u.url}),c=t.filter(function(u){return u.status==="current"}).map(function(u){return u.url});return console.log("[loco] pullLatest: "+p.length+" updated, "+c.length+" current"),{status:a?"updated":"current",results:t}}).catch(function(t){return console.warn("[loco] pullLatest() failed:",t),{status:"error",reason:t.message}})}};return window.Loco=J,Object.defineProperty(J,"_state",{value:o,writable:!1,enumerable:!1,configurable:!1}),J}();
|
package/versions.json
CHANGED