@hkonda/loco-translate 1.1.11 → 1.1.12

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.
@@ -6,6 +6,8 @@ export declare const AI_CONFIG: {
6
6
  readonly HOSTNAME: "app.ozwell.ai";
7
7
  readonly PORT: 443;
8
8
  readonly PATH: "/api/v1/completion";
9
+ readonly REQUEST_TIMEOUT_MS: number;
10
+ readonly MAX_RETRIES: number;
9
11
  };
10
12
  export declare const LIMITS: {
11
13
  readonly MAX_URL_LENGTH: 2048;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../server/config.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,YAAY,QAAwB,CAAC;AAalD,eAAO,MAAM,IAAI,QAA2C,CAAC;AAC7D,eAAO,MAAM,SAAS,QAA8B,CAAC;AAUrD,eAAO,MAAM,QAAQ,QAA+C,CAAC;AAErE,eAAO,MAAM,SAAS;;;;CAIZ,CAAC;AAEX,eAAO,MAAM,MAAM;;;;;CAKT,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../server/config.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,YAAY,QAAwB,CAAC;AAalD,eAAO,MAAM,IAAI,QAA2C,CAAC;AAC7D,eAAO,MAAM,SAAS,QAA8B,CAAC;AAiBrD,eAAO,MAAM,QAAQ,QAA+C,CAAC;AAErE,eAAO,MAAM,SAAS;;;;;;CAMZ,CAAC;AAEX,eAAO,MAAM,MAAM;;;;;CAKT,CAAC"}
@@ -18,6 +18,13 @@ if (existsSync(envPath)) {
18
18
  }
19
19
  export const PORT = parseInt(process.env.PORT || '6101', 10);
20
20
  export const BASE_PATH = process.env.BASE_PATH || ''; // e.g. '/loco' for reverse-proxy deployments
21
+ function envInt(name, fallback, min) {
22
+ const raw = process.env[name];
23
+ const parsed = raw ? parseInt(raw, 10) : fallback;
24
+ if (!Number.isFinite(parsed))
25
+ return fallback;
26
+ return Math.max(min, parsed);
27
+ }
21
28
  // Data directory for the SQLite database and backups.
22
29
  // When running from source (dev), use server/data/ inside the repo.
23
30
  // When installed as an npm package, default to .loco/ in the user's cwd.
@@ -31,6 +38,8 @@ export const AI_CONFIG = {
31
38
  HOSTNAME: 'app.ozwell.ai',
32
39
  PORT: 443,
33
40
  PATH: '/api/v1/completion',
41
+ REQUEST_TIMEOUT_MS: envInt('AI_REQUEST_TIMEOUT_MS', 45000, 1000),
42
+ MAX_RETRIES: envInt('AI_MAX_RETRIES', 1, 0),
34
43
  };
35
44
  export const LIMITS = {
36
45
  MAX_URL_LENGTH: 2048,
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../server/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAE9C,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,6EAA6E;AAC7E,0FAA0F;AAC1F,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAElD,qDAAqD;AACrD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;AAC5C,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;IACxB,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC5C,IAAI,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACjD,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;AAC7D,MAAM,CAAC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,6CAA6C;AAEnG,sDAAsD;AACtD,oEAAoE;AACpE,yEAAyE;AACzE,gDAAgD;AAChD,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;AAC1E,MAAM,eAAe,GAAG,YAAY;IAClC,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,MAAM,CAAC;IACtC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;AACjC,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,eAAe,CAAC;AAErE,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,QAAQ,EAAE,eAAe;IACzB,IAAI,EAAE,GAAG;IACT,IAAI,EAAE,oBAAoB;CAClB,CAAC;AAEX,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,cAAc,EAAE,IAAI;IACpB,mBAAmB,EAAE,MAAM;IAC3B,eAAe,EAAE,EAAE;IACnB,cAAc,EAAE,EAAE;CACV,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../server/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAE9C,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,6EAA6E;AAC7E,0FAA0F;AAC1F,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAElD,qDAAqD;AACrD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;AAC5C,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;IACxB,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC5C,IAAI,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACjD,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;AAC7D,MAAM,CAAC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,6CAA6C;AAEnG,SAAS,MAAM,CAAC,IAAY,EAAE,QAAgB,EAAE,GAAW;IACzD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAClD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC9C,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED,sDAAsD;AACtD,oEAAoE;AACpE,yEAAyE;AACzE,gDAAgD;AAChD,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;AAC1E,MAAM,eAAe,GAAG,YAAY;IAClC,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,MAAM,CAAC;IACtC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;AACjC,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,eAAe,CAAC;AAErE,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,QAAQ,EAAE,eAAe;IACzB,IAAI,EAAE,GAAG;IACT,IAAI,EAAE,oBAAoB;IAC1B,kBAAkB,EAAE,MAAM,CAAC,uBAAuB,EAAE,KAAK,EAAE,IAAI,CAAC;IAChE,WAAW,EAAE,MAAM,CAAC,gBAAgB,EAAE,CAAC,EAAE,CAAC,CAAC;CACnC,CAAC;AAEX,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,cAAc,EAAE,IAAI;IACpB,mBAAmB,EAAE,MAAM;IAC3B,eAAe,EAAE,EAAE;IACnB,cAAc,EAAE,EAAE;CACV,CAAC"}
@@ -103,7 +103,7 @@ export default async function aiJobsRoutes(app, opts) {
103
103
  const ensureMaster = rawDb.prepare(`
104
104
  INSERT INTO textnodes (project_id, key, context, status)
105
105
  VALUES (?, ?, '', 'approved')
106
- ON CONFLICT(project_id, key, context) DO NOTHING
106
+ ON CONFLICT(project_id, key, context) DO UPDATE SET status = 'approved'
107
107
  `);
108
108
  rawDb.transaction(() => {
109
109
  for (const it of jobItems)
@@ -1 +1 @@
1
- {"version":3,"file":"ai-translation.d.ts","sourceRoot":"","sources":["../../server/services/ai-translation.ts"],"names":[],"mappings":"AAKA,UAAU,cAAc;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,eAAe;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,cAAc,EAC9B,gBAAgB,EAAE,MAAM,GAAG,IAAI,EAC/B,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,MAAM,CAAC,CAsFjB;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,eAAe,EAAE,EACxB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,cAAc,EAC9B,SAAS,EAAE,MAAM,EACjB,kBAAkB,EAAE,OAAO,EAC3B,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CA+Cf"}
1
+ {"version":3,"file":"ai-translation.d.ts","sourceRoot":"","sources":["../../server/services/ai-translation.ts"],"names":[],"mappings":"AAKA,UAAU,cAAc;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,eAAe;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,cAAc,EAC9B,gBAAgB,EAAE,MAAM,GAAG,IAAI,EAC/B,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,MAAM,CAAC,CAqHjB;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,eAAe,EAAE,EACxB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,cAAc,EAC9B,SAAS,EAAE,MAAM,EACjB,kBAAkB,EAAE,OAAO,EAC3B,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CA+Cf"}
@@ -48,59 +48,84 @@ export async function translateWithAI(text, targetLang, context, promptTemplate,
48
48
  port: AI_CONFIG.PORT,
49
49
  path: AI_CONFIG.PATH,
50
50
  method: 'POST',
51
+ timeout: AI_CONFIG.REQUEST_TIMEOUT_MS,
51
52
  headers: {
52
53
  'Authorization': `Bearer ${API_KEY}`,
53
54
  'Content-Type': 'application/json',
54
55
  'Content-Length': Buffer.byteLength(body),
55
56
  },
56
57
  };
57
- return new Promise((resolve, reject) => {
58
- const req = https.request(options, (res) => {
59
- let data = '';
60
- res.on('data', (chunk) => { data += chunk; });
61
- res.on('end', () => {
62
- if (res.statusCode !== 200) {
63
- reject(new Error(`BlueHive API error: ${res.statusCode} - ${data}`));
64
- }
65
- else {
66
- try {
67
- const json = JSON.parse(data);
68
- let translated = json.choices[0].message.content.trim();
69
- // Restore {{type:N}} placeholders
70
- for (const st of slotTokens) {
71
- translated = translated.replace(st.placeholder, st.original);
58
+ const maxAttempts = AI_CONFIG.MAX_RETRIES + 1;
59
+ let lastError = null;
60
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
61
+ try {
62
+ const translated = await new Promise((resolve, reject) => {
63
+ let settled = false;
64
+ const finish = (fn, value) => {
65
+ if (settled)
66
+ return;
67
+ settled = true;
68
+ fn(value);
69
+ };
70
+ const req = https.request(options, (res) => {
71
+ let data = '';
72
+ res.on('data', (chunk) => { data += chunk; });
73
+ res.on('end', () => {
74
+ if (res.statusCode !== 200) {
75
+ finish(reject, new Error(`BlueHive API error: ${res.statusCode} - ${data}`));
76
+ return;
77
+ }
78
+ try {
79
+ const json = JSON.parse(data);
80
+ let translatedText = json.choices[0].message.content.trim();
81
+ // Restore {{type:N}} placeholders
82
+ for (const st of slotTokens) {
83
+ translatedText = translatedText.replace(st.placeholder, st.original);
84
+ }
85
+ // Strip wrapping quotes the AI sometimes adds
86
+ if (translatedText.length >= 2 &&
87
+ ((translatedText[0] === '"' && translatedText[translatedText.length - 1] === '"') ||
88
+ (translatedText[0] === '\u201c' && translatedText[translatedText.length - 1] === '\u201d'))) {
89
+ translatedText = translatedText.slice(1, -1);
90
+ }
91
+ finish(resolve, translatedText);
72
92
  }
73
- // Strip wrapping quotes the AI sometimes adds
74
- if (translated.length >= 2 &&
75
- ((translated[0] === '"' && translated[translated.length - 1] === '"') ||
76
- (translated[0] === '\u201c' && translated[translated.length - 1] === '\u201d'))) {
77
- translated = translated.slice(1, -1);
93
+ catch {
94
+ finish(reject, new Error('Failed to parse BlueHive response'));
78
95
  }
79
- resolve(translated);
80
- }
81
- catch (e) {
82
- reject(new Error('Failed to parse BlueHive response'));
83
- }
84
- }
96
+ });
97
+ });
98
+ req.on('timeout', () => {
99
+ req.destroy(new Error(`BlueHive API request timed out after ${AI_CONFIG.REQUEST_TIMEOUT_MS}ms`));
100
+ });
101
+ req.on('error', (err) => {
102
+ finish(reject, err instanceof Error ? err : new Error(String(err)));
103
+ });
104
+ req.write(body);
105
+ req.end();
85
106
  });
86
- });
87
- req.on('error', reject);
88
- req.write(body);
89
- req.end();
90
- });
107
+ return translated;
108
+ }
109
+ catch (err) {
110
+ lastError = err instanceof Error ? err : new Error(String(err));
111
+ if (attempt >= maxAttempts)
112
+ break;
113
+ }
114
+ }
115
+ throw (lastError || new Error('BlueHive request failed'));
91
116
  }
92
117
  /**
93
118
  * Process a batch of translations as a background job.
94
119
  */
95
120
  export async function processTranslations(jobId, items, langCode, promptTemplate, projectId, includeScreenshots, projectSettings) {
96
121
  jobManager.startJob(jobId);
97
- rawDb.prepare('UPDATE ai_job_log SET status = ? WHERE job_id = ?').run('running', jobId);
122
+ rawDb.prepare('UPDATE ai_job_log SET status = ? WHERE project_id = ? AND job_id = ?').run('running', projectId, jobId);
98
123
  for (let i = 0; i < items.length; i++) {
99
124
  if (jobManager.isCancelled(jobId)) {
100
125
  jobManager.finalizeCancelled(jobId);
101
126
  const cancelledJob = jobManager.getJob(jobId);
102
- rawDb.prepare("UPDATE ai_job_log SET status = ?, finished_at = datetime('now'), completed = ?, failed = ? WHERE job_id = ?")
103
- .run('cancelled', cancelledJob?.completed || 0, cancelledJob?.failed || 0, jobId);
127
+ rawDb.prepare("UPDATE ai_job_log SET status = ?, finished_at = datetime('now'), completed = ?, failed = ? WHERE project_id = ? AND job_id = ?")
128
+ .run('cancelled', cancelledJob?.completed || 0, cancelledJob?.failed || 0, projectId, jobId);
104
129
  return;
105
130
  }
106
131
  const item = items[i];
@@ -131,7 +156,7 @@ export async function processTranslations(jobId, items, langCode, promptTemplate
131
156
  }
132
157
  jobManager.completeJob(jobId);
133
158
  const finished = jobManager.getJob(jobId);
134
- rawDb.prepare("UPDATE ai_job_log SET status = ?, finished_at = datetime('now'), completed = ?, failed = ? WHERE job_id = ?")
135
- .run(finished?.status || 'completed', finished?.completed || 0, finished?.failed || 0, jobId);
159
+ rawDb.prepare("UPDATE ai_job_log SET status = ?, finished_at = datetime('now'), completed = ?, failed = ? WHERE project_id = ? AND job_id = ?")
160
+ .run(finished?.status || 'completed', finished?.completed || 0, finished?.failed || 0, projectId, jobId);
136
161
  }
137
162
  //# sourceMappingURL=ai-translation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ai-translation.js","sourceRoot":"","sources":["../../server/services/ai-translation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ai-translation.js","sourceRoot":"","sources":["../../server/services/ai-translation.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hkonda/loco-translate",
3
- "version": "1.1.11",
3
+ "version": "1.1.12",
4
4
  "description": "Self-hosted translation manager — auto-discovers text, AI translations, Svelte dashboard, CDN client.",
5
5
  "type": "module",
6
6
  "bin": {
package/public/loco.js CHANGED
@@ -2332,7 +2332,7 @@ var Loco = function() {
2332
2332
  var Loco2 = {
2333
2333
  // Version is injected by Vite at build time from versions.json.
2334
2334
  // In-browser: Loco.version → e.g. "1.0.8"
2335
- version: "1.1.11",
2335
+ version: "1.1.12",
2336
2336
  init: function(config) {
2337
2337
  if (!config) {
2338
2338
  console.warn("[loco] Loco.init() requires a config object");
@@ -1,4 +1,4 @@
1
1
  var Loco=function(){"use strict";var i={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"],Pe=["VAR","STRONG","EM","B","I","SPAN","A","ABBR","MARK","SMALL","SUB","SUP","U","S","TIME"],De=["h1","h2","h3","h4","h5","h6","label","legend","caption","figcaption","nav","header","footer","main","section","article","form"],I=new Set(Re),W=new Set(Pe),we=[].concat(De),Ne=0,Te=!0,B=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 Ye(e){if(e.blockedTags){var n=e.blockedTags.disabled||[],t=e.blockedTags.custom||[];I=new Set(Re.filter(function(r){return n.indexOf(r)<0})),t.forEach(function(r){I.add(r.toUpperCase())})}if(e.inlineTags){var n=e.inlineTags.disabled||[],t=e.inlineTags.custom||[];W=new Set(Pe.filter(function(o){return n.indexOf(o)<0})),t.forEach(function(o){W.add(o.toUpperCase())})}if(e.domContextSelectors){var n=e.domContextSelectors.disabled||[],t=e.domContextSelectors.custom||[];we=De.filter(function(o){return n.indexOf(o)<0}).concat(t)}e.screenshotsEnabled===!1&&(i.screenshotsEnabled=!1),typeof e.contextDepth=="number"&&(Ne=e.contextDepth),e.domContextEnabled===!1&&(Te=!1)}function L(e){return e.trim().replace(/\s+/g," ")}function A(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()||A(n)}function _e(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}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 X=new WeakMap;function Ie(e){let n=e.parentElement;for(;n&&n!==document.body;){if(X.has(n))return X.get(n);if(ee(n))return X.set(n,!0),!0;n=n.parentElement}for(n=e.parentElement;n&&n!==document.body&&!X.has(n);)X.set(n,!1),n=n.parentElement;return!1}function et(){X=new WeakMap}const Me=new Set(["H1","H2","H3","H4","H5","H6"]),tt=new Set(["SCRIPT","STYLE","NOSCRIPT","CODE"]);let Q=new WeakMap,z=new WeakMap,G=null;function Le(){if(Te){G=new Set;var e=we.slice();try{var n=e.join(",");document.querySelectorAll(n).forEach(function(t){G.add(t)})}catch{e.forEach(function(r){try{document.querySelectorAll(r).forEach(function(a){G.add(a)})}catch{}})}G.forEach(function(t){z.has(t)||ne(t)})}}function te(e){return G?G.has(e):Me.has(e.tagName)?!0:we.some(function(n){try{return e.matches(n)}catch{return!1}})}function nt(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 rt(e,n){for(var t="",r=document.createTreeWalker(e,NodeFilter.SHOW_ALL,{acceptNode:function(o){return o.nodeType===Node.ELEMENT_NODE?tt.has(o.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 ne(e){if(z.has(e))return z.get(e);let n=null;const t=nt(e);if(t)return n=t.substring(0,60),z.set(e,n),n;if(Me.has(e.tagName)){const a=(e.textContent||"").trim().replace(/\s+/g," ");if(a)return n=a.substring(0,60),z.set(e,n),n}var r=rt(e,200);if(r){const a=r.split(/\n/)[0].trim().replace(/\s+/g," ");a.length>=2&&!A(a)&&(n=a.substring(0,60))}return z.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 r=[],a=new Set;let o=e,l=0;if(e&&e.tagName==="TD"){var v=e.closest("table");if(v){var h=v.querySelector("thead tr th:nth-child("+(e.cellIndex+1)+")");if(h){var s=ne(h);s&&(a.add(s),r.push(s))}}}for(;o&&o!==document.body&&!(Ne>0&&l>=Ne);){l++;let c=o.previousElementSibling;for(;c;){var f=c.tagName.toUpperCase();if(I.has(f)){c=c.previousElementSibling;continue}if(f==="ARTICLE"||f==="MAIN"){c=c.previousElementSibling;continue}if(te(c)){const d=ne(c);d&&!a.has(d)&&(a.add(d),r.unshift(d));break}let u=null;for(const d of c.children)if(te(d)){u=d;break}if(!u)for(const d of c.children){for(const m of d.children)if(te(m)){u=m;break}if(u)break}if(u){const d=ne(u);d&&!a.has(d)&&(a.add(d),r.unshift(d));break}c=c.previousElementSibling}if(te(o)){const u=ne(o);u&&!a.has(u)&&(a.add(u),r.unshift(u))}var p=o.tagName;if(p==="ARTICLE"||p==="MAIN")break;o=o.parentElement}const g=r.join(" > ");return Q.set(e,g),g}function at(e){return/^\d+$/.test(e)?"number":/^\d+\.\d+$/.test(e)?"decimal":"text"}function it(e,n){for(var t=n.split(/(\{\{(?:text|number|decimal|date):\d+\}\})/),r=[],a=e,o=0;o<t.length;o++){var l=t[o],v=l.match(/^\{\{(text|number|decimal|date):(\d+)\}\}$/);if(v)if(a.indexOf(l)===0)r.push({type:v[1],index:parseInt(v[2]),originalText:l}),a=a.substring(l.length);else{for(var h="",s=o+1;s<t.length;s++){var f=t[s];if(/^\{\{(?:text|number|decimal|date):\d+\}\}$/.test(f)){if(a.indexOf(f)>=0){h=f;break}}else if(f!==""){h=f;break}}var p;if(h==="")p=a,a="";else{var g=a.indexOf(h);g>=0?(p=a.substring(0,g),a=a.substring(g)):(p=a,a="")}r.push({type:v[1],index:parseInt(v[2]),originalText:p})}else a.indexOf(l)===0&&(a=a.substring(l.length))}return r}function ce(e,n){e.forEach(function(t){if(!(t.varSlots&&t.varSlots.length>0)){var r=n[t.key];r&&(t.varSlots=it(t.key,r),t.key=r)}})}function ot(e,n){for(var t=n.split(/\{\{(?:text|number|decimal|date):\d+\}\}/g),r=e,a=[],o=0;o<t.length;o++)if(o===0)r.indexOf(t[o])===0&&(r=r.substring(t[o].length));else if(t[o]===""&&o===t.length-1)a.push(r),r="";else{var l=r.indexOf(t[o]);l>=0&&(a.push(r.substring(0,l)),r=r.substring(l+t[o].length))}return a.length>0&&a.every(function(v){return/^[a-zA-Z\s]+$/.test(v.trim())})}function lt(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 q(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 o=[],l=[],v=0,h=/\{\{(text|number|decimal|date):\d+\}\}/g,s;(s=h.exec(a))!==null;)o.push(a.substring(v,s.index)),l.push(s[1]),v=h.lastIndex;o.push(a.substring(v));for(var f="",p=0;p<o.length;p++)if(f+=o[p].replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),p<l.length)switch(l[p]){case"number":f+="\\d+";break;case"decimal":f+="\\d+\\.\\d+";break;default:f+=".+";break}t.push({pattern:a,regex:new RegExp("^"+f+"$"),specificity:lt(a)})}}if(t.length!==0){t.sort(function(u,d){return d.specificity-u.specificity});for(var g={},c={},r=0;r<n.length;r++)c[n[r]]=!0;return e.forEach(function(u){if(!c[u.key]&&!(u.key.length>B)){for(var d=0;d<t.length;d++)if(t[d].regex.test(u.key)&&!ot(u.key,t[d].pattern)){g[u.key]=t[d].pattern;break}}}),ce(e,g),g}}var re=new WeakMap;function M(e){if(re.has(e))return re.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 o=a.tagName.toUpperCase();if(o==="BR")return re.set(e,!1),!1;(o==="VAR"||o==="TIME"&&a.hasAttribute("datetime")||W.has(o))&&(t=!0)}var r=n&&t;return re.set(e,r),r}function st(){re=new WeakMap}function ue(e){let n="";const t=[];for(const r of e.childNodes){if(r.nodeType===Node.TEXT_NODE){const a=L(r.textContent);a&&(n+=a);continue}if(r.nodeType===Node.ELEMENT_NODE){const a=r.tagName.toUpperCase();if(a==="TIME"&&r.hasAttribute("datetime")){const o=t.length;t.push({type:"date",index:o,raw:r.getAttribute("datetime"),display:r.textContent,node:r}),n+=`{{date:${o}}}`;continue}if(a==="VAR"||W.has(a)){const o=L(r.textContent);if(o){const l=t.length,v=at(o);t.push({type:v,index:l,tag:a,value:o,node:r}),n+=`{{${v}:${l}}}`}continue}}}return{key:L(n),slots:t}}var fe=["title","placeholder","aria-label"];function Ke(e){const n=[],t=new Set;if(e.nodeType===Node.ELEMENT_NODE&&!ee(e)&&M(e)){const{key:s,slots:f}=ue(e);if(s&&s.length<=B)if(se(s))f.forEach(function(p){if(p.type==="text"&&p.value&&p.value.length>=2&&!A(p.value)){var g=k(p.node||e),c=p.value+"\0"+g;t.has(c)||(t.add(c),n.push({type:"text",key:p.value,slots:[],textNode:p.node?p.node.firstChild:null,element:p.node||e,context:g,original:p.value}))}});else{var r=k(e),a=s+"\0"+r;t.has(a)||t.add(a);const p=f.some(g=>g.type==="date")?"mixed-date":f.some(g=>g.type==="text")?"mixed-text":"mixed";n.push({type:p,key:s,slots:f,element:e,context:r,original:s,originalHTML:e.innerHTML})}}const o=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT,{acceptNode(s){var m,x,b;if(s.nodeType===Node.TEXT_NODE){const w=L(s.textContent);if(!w||w.length<2||w.length>B||A(w)||/\{\{(?:text|number|decimal|date):\d+\}\}/.test(w)||Ie(s))return NodeFilter.FILTER_SKIP;const y=(x=(m=s.parentElement)==null?void 0:m.tagName)==null?void 0:x.toUpperCase();if(I.has(y)||M(s.parentElement))return NodeFilter.FILTER_SKIP;for(var f=s.parentElement,p=0;f&&p<3;){var g=(b=f.tagName)==null?void 0:b.toUpperCase();if((g==="VAR"||g==="TIME"||W.has(g))&&f.parentElement&&M(f.parentElement))return NodeFilter.FILTER_SKIP;f=f.parentElement,p++}return NodeFilter.FILTER_ACCEPT}if(s.nodeType===Node.ELEMENT_NODE){const w=s.tagName.toUpperCase();if(I.has(w)||ee(s))return NodeFilter.FILTER_REJECT;if(w==="INPUT"){var c=(s.getAttribute("type")||"").toLowerCase();if(c==="button"||c==="submit"||c==="reset"){var u=L(s.value);if(u&&u.length>=2&&!A(u))return NodeFilter.FILTER_ACCEPT}var d=fe.some(function(y){var E=L(s.getAttribute(y)||"");return E&&E.length>=2&&!A(E)});return d?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}return M(s)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}return NodeFilter.FILTER_SKIP}});let l;for(;l=o.nextNode();){if(l.nodeType===Node.TEXT_NODE){const s=L(l.textContent);if(!s)continue;var r=k(l.parentElement),a=s+"\0"+r;t.has(a)||t.add(a),n.push({type:"text",key:s,slots:[],textNode:l,element:l.parentElement,context:r,original:s});continue}if(l.nodeType===Node.ELEMENT_NODE&&l.tagName.toUpperCase()==="INPUT"){var v=(l.getAttribute("type")||"").toLowerCase(),r=k(l);if(v==="button"||v==="submit"||v==="reset"){var h=L(l.value);if(h&&h.length>=2&&!A(h)){var a=h+"\0"+r;t.has(a)||t.add(a),n.push({type:"input-value",key:h,slots:[],element:l,context:r,original:h})}}fe.forEach(function(f){var p=L(l.getAttribute(f)||"");if(!(!p||p.length<2||A(p))){var g=p+"\0"+r+"\0"+f;t.has(g)||(t.add(g),n.push({type:"input-attr",key:p,attr:f,slots:[],element:l,context:r,original:p}))}});continue}if(l.nodeType===Node.ELEMENT_NODE){const{key:s,slots:f}=ue(l);if(!s||s.length>B)continue;if(se(s)){f.forEach(function(u){if(u.type==="text"&&u.value&&u.value.length>=2&&!A(u.value)){var d=k(u.node||l),m=u.value+"\0"+d;t.has(m)||(t.add(m),n.push({type:"text",key:u.value,slots:[],textNode:u.node?u.node.firstChild:null,element:u.node||l,context:d,original:u.value}))}});continue}var r=k(l),a=s+"\0"+r;t.has(a)||t.add(a);const c=f.some(u=>u.type==="date")?"mixed-date":f.some(u=>u.type==="text")?"mixed-text":"mixed";n.push({type:c,key:s,slots:f,element:l,context:r,original:s,originalHTML:l.innerHTML})}}return n}async function ae(e,n){n||(n=100);const t=[],r=new Set;if(et(),st(),Le(),e.nodeType===Node.ELEMENT_NODE&&!ee(e)&&M(e)){const{key:c,slots:u}=ue(e);if(c&&c.length<=B)if(se(c))u.forEach(function(d){if(d.type==="text"&&d.value&&d.value.length>=2&&!A(d.value)){var m=k(d.node||e),x=d.value+"\0"+m;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:m,original:d.value}))}});else{var a=k(e),o=c+"\0"+a;r.has(o)||r.add(o);const d=u.some(m=>m.type==="date")?"mixed-date":u.some(m=>m.type==="text")?"mixed-text":"mixed";t.push({type:d,key:c,slots:u,element:e,context:a,original:c,originalHTML:e.innerHTML})}}const l=[],v=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT,{acceptNode(c){var y,E,T;if(c.nodeType===Node.TEXT_NODE){const N=L(c.textContent);if(!N||N.length<2||N.length>B||A(N)||/\{\{(?:text|number|decimal|date):\d+\}\}/.test(N)||Ie(c))return NodeFilter.FILTER_SKIP;const C=(E=(y=c.parentElement)==null?void 0:y.tagName)==null?void 0:E.toUpperCase();if(I.has(C)||M(c.parentElement))return NodeFilter.FILTER_SKIP;for(var u=c.parentElement,d=0;u&&d<3;){var m=(T=u.tagName)==null?void 0:T.toUpperCase();if((m==="VAR"||m==="TIME"||W.has(m))&&u.parentElement&&M(u.parentElement))return NodeFilter.FILTER_SKIP;u=u.parentElement,d++}return NodeFilter.FILTER_ACCEPT}if(c.nodeType===Node.ELEMENT_NODE){const N=c.tagName.toUpperCase();if(I.has(N)||ee(c))return NodeFilter.FILTER_REJECT;if(N==="INPUT"){var x=(c.getAttribute("type")||"").toLowerCase();if(x==="button"||x==="submit"||x==="reset"){var b=L(c.value);if(b&&b.length>=2&&!A(b))return NodeFilter.FILTER_ACCEPT}var w=fe.some(function(C){var O=L(c.getAttribute(C)||"");return O&&O.length>=2&&!A(O)});return w?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}return M(c)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}return NodeFilter.FILTER_SKIP}});for(var h;h=v.nextNode();)l.push(h);for(var s=0;s<l.length;s++){s>0&&s%n===0&&await new Promise(function(c){setTimeout(c,0)});var f=l[s];if(f.nodeType===Node.TEXT_NODE){const c=L(f.textContent);if(!c)continue;var a=k(f.parentElement),o=c+"\0"+a;r.has(o)||r.add(o),t.push({type:"text",key:c,slots:[],textNode:f,element:f.parentElement,context:a,original:c});continue}if(f.nodeType===Node.ELEMENT_NODE&&f.tagName.toUpperCase()==="INPUT"){var p=(f.getAttribute("type")||"").toLowerCase(),a=k(f);if(p==="button"||p==="submit"||p==="reset"){var g=L(f.value);if(g&&g.length>=2&&!A(g)){var o=g+"\0"+a;r.has(o)||r.add(o),t.push({type:"input-value",key:g,slots:[],element:f,context:a,original:g})}}fe.forEach(function(u){var d=L(f.getAttribute(u)||"");if(!(!d||d.length<2||A(d))){var m=d+"\0"+a+"\0"+u;r.has(m)||(r.add(m),t.push({type:"input-attr",key:d,attr:u,slots:[],element:f,context:a,original:d}))}});continue}if(f.nodeType===Node.ELEMENT_NODE){const{key:c,slots:u}=ue(f);if(!c||c.length>B)continue;if(se(c)){u.forEach(function(b){if(b.type==="text"&&b.value&&b.value.length>=2&&!A(b.value)){var w=k(b.node||f),y=b.value+"\0"+w;r.has(y)||(r.add(y),t.push({type:"text",key:b.value,slots:[],textNode:b.node?b.node.firstChild:null,element:b.node||f,context:w,original:b.value}))}});continue}var a=k(f),o=c+"\0"+a;r.has(o)||r.add(o);const x=u.some(b=>b.type==="date")?"mixed-date":u.some(b=>b.type==="text")?"mixed-text":"mixed";t.push({type:x,key:c,slots:u,element:f,context:a,original:c,originalHTML:f.innerHTML})}}return t}function de(e){if(i.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(o){if(o.type==="text"&&o.value&&!A(o.value)){var l=o.value+"\0";n.has(l)||(n.add(l),t.push({key:o.value,context:""}))}}))}),fetch(i.apiBase+"/api/textnodes",{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":i.apiKey},body:JSON.stringify({keys:t,url:window.location.href})}).then(function(r){return r.json()})}function ct(e){var n=i.apiBase+"/api/translations?lang="+encodeURIComponent(e);return fetch(n,{headers:{"X-API-Key":i.apiKey}}).then(function(t){return t.json()}).then(function(t){var r={};if(Array.isArray(t)){var a={};t.forEach(function(o){var l=o.context||"";r[o.key+"\0"+l]=o.value,l===""?(r[o.key]=o.value,a[o.key]=!0):!a[o.key]&&!r.hasOwnProperty(o.key)&&(r[o.key]=o.value)})}else r=t;return r})}function ut(){if(!(i.fileMode||!i.screenshotsEnabled)){var e=document.createElement("script");e.src=i.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(i.apiBase+"/api/screenshots",{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":i.apiKey},body:JSON.stringify({url:window.location.href,screenshot:r})}).catch(function(){})}).catch(function(){})},e.onerror=function(){},document.head.appendChild(e)}}function ft(e,n){return e.replace(/\{\{(text|number|decimal|date):(\d+)\}\}/g,(t,r,a)=>{const o=n[parseInt(a)];return o?r==="date"?o.display:o.value:t})}function Ue(e){if(!Array.isArray(e))return e;var n={},t={};return e.forEach(function(r){var a=r.context||"";n[r.key+"\0"+a]=r.value,a===""?(n[r.key]=r.value,t[r.key]=!0):!t[r.key]&&!n.hasOwnProperty(r.key)&&(n[r.key]=r.value)}),n}function ke(e,n){let t=0,r=0;return e.forEach(a=>{const o=a.key+"\0"+(a.context||"");var l=n[o]||n[a.key];if(!l&&a.slots&&a.slots.length>0){var v=a.slots.some(function(p){if(p.type!=="text"||!p.value)return!1;var g=p.value+"\0"+(a.context||""),c=p.value+"\0";return n.hasOwnProperty(g)||n.hasOwnProperty(c)||n.hasOwnProperty(p.value)});v&&(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(p){console.warn("[translate] Could not write to input value",p),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(p){console.warn("[translate] Could not write to input attr",p),r++;return}if(a.type==="text"&&a.textNode)try{var h=l;a.varSlots&&a.varSlots.length>0&&(h=h.replace(/\{\{(text|number|decimal|date):(\d+)\}\}/g,function(p,g,c){var u=a.varSlots.find(function(d){return(d.type||"text")===g&&d.index===+c});return u||(u=a.varSlots[+c]),u?u.originalText:p})),h=h.replace(/\{\{(?:text|number|decimal|date):\d+\}\}/g,""),a.textNode.nodeValue=h,a.textNode.parentElement&&a.textNode.parentElement.setAttribute("data-loco-translated",""),t++;return}catch(p){console.warn("[translate] Could not write to text node",p),r++;return}if(a.element){try{const p=ft(l,a.slots);let g=l;var s={};a.slots.forEach(c=>{if(c.type==="date"&&c.node)c.node.textContent=c.display,s[c.index]=c.node.outerHTML;else if(c.node){if(c.type==="text"&&c.value){var u=c.value+"\0"+(a.context||""),d=c.value+"\0",m=n[u]||n[d]||n[c.value];m&&(c.node.textContent=m)}s[c.index]=c.node.outerHTML}}),a.varSlots&&a.varSlots.length>0&&a.varSlots.forEach(function(c){s.hasOwnProperty(c.index)||(s[c.index]=_e(c.originalText))});var f=g.split(/(\{\{(?:text|number|decimal|date):\d+\}\})/g);g=f.map(function(c){var u=c.match(/^\{\{(?:text|number|decimal|date):(\d+)\}\}$/);if(u){var d=+u[1];return s.hasOwnProperty(d)?s[d]:""}return _e(c)}).join(""),a.element.innerHTML=g,a.element.setAttribute("data-loco-translated",""),t++}catch(p){console.warn("[translate] Could not apply mixed translation",p),r++}return}r++}),{applied:t,skipped:r}}async function pe(e,n,t){t||(t=100);for(var r=0,a=0,o=performance.now(),l=0;l<e.length;l+=t){l>0&&performance.now()-o>16&&(await new Promise(function(s){requestAnimationFrame(s)}),o=performance.now());var v=e.slice(l,l+t),h=ke(v,n);r+=h.applied,a+=h.skipped}return{applied:r,skipped:a}}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(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 he(e,n){const t=new Set(e),r=[];Object.values(n).forEach(function(u){if(u&&(t.add(u),/\{\{(text|number|decimal|date):\d+\}\}/.test(u))){var d=u.split(/\{\{(?:text|number|decimal|date):\d+\}\}/g),m=d.map(function(x){return x.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")});r.push(new RegExp("^"+m.join(".+")+"$"))}});function a(u){if(t.has(u))return!0;for(var d=0;d<r.length;d++)if(r[d].test(u))return!0;return!1}let o=[],l=null,v=null,h=new Set,s=null,f=!1;function p(){if(o.length!==0){var u=o.splice(0);i.fileMode||de(u).then(function(d){d&&d.keyMap&&(ce(u,d.keyMap),f=!0,ke(u,n),s&&s.takeRecords(),f=!1)}).catch(function(){})}}function g(u){const d=Ke(u);d.forEach(m=>{var x=m.key+"\0"+(m.context||"");a(m.key)||t.has(x)||(t.add(x),t.add(m.key),o.push(m),i.phrases.push(m))}),q(d,Object.keys(n)),f=!0,ke(d,n),s&&s.takeRecords(),f=!1,i.fileMode||(clearTimeout(l),l=setTimeout(p,500))}function c(u){h.add(u),v||(v=requestAnimationFrame(function(){v=null;var d=Array.from(h);h.clear(),d.forEach(function(m){m.isConnected&&g(m)})}))}return s=new MutationObserver(u=>{if(!f){var d=[],m=new Set;for(const b of u)for(const w of b.addedNodes)if(w.nodeType===Node.ELEMENT_NODE)d.push(w);else if(w.nodeType===Node.TEXT_NODE){var x=w.parentElement;x&&x.isConnected&&m.add(x)}d.forEach(function(b){g(b)}),m.forEach(function(b){c(b)})}}),s.observe(document.body,{childList:!0,subtree:!0}),s}var Be=["aria-labelledby","aria-label","aria-describedby","role","aria-hidden","alt","title"],je="\0";function dt(e){var n={};return!e||typeof e!="object"||Be.forEach(function(t){if(Object.prototype.hasOwnProperty.call(e,t)){var r=e[t];typeof r=="string"&&r.trim()!==""&&(n[t]=r.trim())}}),n}function He(e){var n={};return Array.isArray(e)&&e.forEach(function(t){if(!(!t||typeof t.key!="string")){var r=typeof t.context=="string"?t.context:"",a=dt(t.attributes);Object.keys(a).length!==0&&(n[t.key+je+r]=a,Object.prototype.hasOwnProperty.call(n,t.key)||(n[t.key]=a))}}),n}function pt(e){return e.element?e.element:e.textNode&&e.textNode.parentElement?e.textNode.parentElement:null}function We(){return!i.apiKey||!i.apiBase?Promise.resolve({}):fetch(i.apiBase+"/api/aria",{headers:{"X-API-Key":i.apiKey}}).then(function(e){return e.json()}).then(function(e){return He(e)}).catch(function(e){return console.warn("[loco] Failed to fetch ARIA rules:",e),{}})}function ht(e,n){if(!e||!n)return!1;var t=e.__locoAriaPrev||{},r=!1;return Be.forEach(function(a){if(Object.prototype.hasOwnProperty.call(n,a)){var o=n[a];if(!(typeof o!="string"||o.trim()==="")){Object.prototype.hasOwnProperty.call(t,a)||(t[a]=e.hasAttribute(a)?e.getAttribute(a):null);try{e.setAttribute(a,o.trim()),r=!0}catch(l){console.warn("[loco] Could not set "+a,l)}}}}),r&&(e.__locoAriaPrev=t,e.setAttribute("data-loco-aria","")),r}function V(e,n){if(!n)return{applied:0};var t=0;return e.forEach(function(r){var a=r.key+je+(r.context||""),o=n[a]||n[r.key];if(o){var l=pt(r);l&&ht(l,o)&&t++}}),{applied:t}}var Xe="loco",gt=2;function ie(){return new Promise(function(e,n){try{var t=indexedDB.open(Xe,gt);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 ge(){return ie().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 o=a.result;n(o?{languages:o.languages||[],languageNames:o.languageNames||{}}:null)},a.onerror=function(){e.close(),t(a.error)}})})}function Qe(e){var n="source:"+e;return ie().then(function(t){return new Promise(function(r,a){var o=t.transaction("meta","readonly"),l=o.objectStore("meta").get(n);l.onsuccess=function(){t.close();var v=l.result;r(v?{url:v.url,timestamp:v.timestamp,storedAt:v.storedAt}:null)},l.onerror=function(){t.close(),a(l.error)}})})}function vt(e){return ie().then(function(n){return new Promise(function(t,r){var a=n.transaction("translations","readonly"),o=a.objectStore("translations").get(e);o.onsuccess=function(){n.close();var l=o.result;t(l?l.data:null)},o.onerror=function(){n.close(),r(o.error)}})})}function mt(){return ie().then(function(e){return new Promise(function(n,t){var r=e.transaction(["meta","translations"],"readonly"),a=r.objectStore("meta"),o=a.get("registry");o.onsuccess=function(){var l=o.result;if(!l||!l.languages||l.languages.length===0){e.close(),n(null);return}var v=Y(),h=v||l.languages[0],s=r.objectStore("translations").get(h);s.onsuccess=function(){e.close();var f=s.result;if(!f||!f.data){n(null);return}var p={};p[h]=f.data;var g=r.objectStore("meta").get("aria");g.onsuccess=function(){n({languages:l.languages,languageNames:l.languageNames||{},translations:p,aria:Array.isArray(g.result&&g.result.rules)?g.result.rules:[]})},g.onerror=function(){n({languages:l.languages,languageNames:l.languageNames||{},translations:p,aria:[]})}},s.onerror=function(){e.close(),t(s.error)}},o.onerror=function(){e.close(),t(o.error)}})})}function ve(e,n,t){var r=n.languages||[],a=n.languageNames||{},o=n.translations||{},l=Array.isArray(n.aria)?n.aria:[],v=n.timestamp||0;return ie().then(function(h){return new Promise(function(s,f){var p=h.transaction(["meta","translations"],"readwrite"),g=p.objectStore("meta"),c=p.objectStore("translations"),u=g.get("registry");u.onsuccess=function(){var d=u.result,m,x;if(t&&d){var b=d.languages||[];m=b.slice();for(var w=0;w<r.length;w++)m.indexOf(r[w])===-1&&m.push(r[w]);x={};var y=d.languageNames||{},E;for(E in y)x[E]=y[E];for(E in a)x[E]=a[E]}else m=r,x=a;g.put({key:"registry",languages:m,languageNames:x}),g.put({key:"source:"+e,url:e,timestamp:v,storedAt:Date.now()});var T=g.get("aria");T.onsuccess=function(){var C=l;if(t&&T.result&&Array.isArray(T.result.rules)){for(var O="\0",F={},R=[],K=T.result.rules,J=0;J<K.length;J++){var S=K[J];if(!(!S||typeof S.key!="string")){var U=S.key+O+(S.context||"");F.hasOwnProperty(U)||R.push(U),F[U]=S}}for(var P=0;P<l.length;P++){var D=l[P];if(!(!D||typeof D.key!="string")){var _=D.key+O+(D.context||"");F.hasOwnProperty(_)||R.push(_),F[_]=D}}C=R.map(function(oe){return F[oe]})}g.put({key:"aria",rules:C})},T.onerror=function(){g.put({key:"aria",rules:l})};for(var N=0;N<r.length;N++)o[r[N]]&&(t&&Array.isArray(o[r[N]])?function(C){var O=c.get(C);O.onsuccess=function(){var F=O.result,R=F&&Array.isArray(F.data)?F.data:null,K=o[C];if(R){for(var J="\0",S={},U=[],P=0;P<R.length;P++){var D=R[P].key+J+(R[P].context||"");S.hasOwnProperty(D)||U.push(D),S[D]=R[P]}for(var _=0;_<K.length;_++){var oe=K[_].key+J+(K[_].context||"");S.hasOwnProperty(oe)||U.push(oe),S[oe]=K[_]}for(var Ze=[],Fe=0;Fe<U.length;Fe++)Ze.push(S[U[Fe]]);c.put({lang:C,data:Ze})}else c.put({lang:C,data:K})}}(r[N]):c.put({lang:r[N],data:o[r[N]]}))},p.oncomplete=function(){h.close(),s()},p.onerror=function(){h.close(),f(p.error)}})})}function yt(){return new Promise(function(e){var n=indexedDB.deleteDatabase(Xe);n.onsuccess=function(){e()},n.onerror=function(){e()},n.onblocked=function(){e()}})}var xt='<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>',Ce=null;function me(e,n){Ce=n;var t=document.getElementById("loco-lang-widget");t&&t.remove();var r={},a=e.map(function(y){return typeof y=="object"&&y.code?(y.name&&(r[y.code]=y.name),y.code):y}),o={"zh-Hans":"Chinese (Simplified)","zh-Hant":"Chinese (Traditional)"};function l(y){return String(y||"").trim().replace(/_/g,"-")}function v(y){return y&&y.charAt(0).toUpperCase()+y.slice(1).toLowerCase()}function h(y){var E=l(y);if(!E)return"";var T=E.split("-").filter(Boolean);if(T.length===0)return"";T[0]=T[0].toLowerCase();for(var N=1;N<T.length;N++)T[N].length===2?T[N]=T[N].toUpperCase():T[N].length===4?T[N]=v(T[N]):T[N]=T[N].toLowerCase();return T.join("-")}function s(y){var E=h(y);if(!E)return"";if(o[E])return o[E];if(E.indexOf("-")===-1)return"";try{if(typeof Intl<"u"&&typeof Intl.DisplayNames=="function"){var T=new Intl.DisplayNames([navigator.language||"en","en"],{type:"language"}),N=T.of(E);if(N&&N!==E)return N}}catch{}return""}function f(y,E){return y?h(y)===h(E):!0}function p(y){var E=r[y]||r[h(y)]||"";if(E&&!f(E,y))return E;var T=h(y);return o[T]?o[T]:s(y)||y}var g=Y()||null,c=document.createElement("div");c.id="loco-lang-widget",c.setAttribute("data-notranslate","");var u={"bottom-right":"bottom:20px;right:20px;","bottom-left":"bottom:20px;left:20px;","top-right":"top:20px;right:20px;","top-left":"top:20px;left:20px;"};c.style.cssText='position:fixed;z-index:2147483647;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;font-size:14px;'+(u[n]||u["bottom-right"]);var d=document.createElement("button");d.innerHTML=xt,d.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;",d.onmouseenter=function(){d.style.transform="scale(1.1)",d.style.boxShadow="0 6px 20px rgba(0,0,0,0.35)"},d.onmouseleave=function(){d.style.transform="scale(1)",d.style.boxShadow="0 4px 14px rgba(0,0,0,0.25)"};var m=document.createElement("div");m.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 x=document.createElement("div");x.textContent="Original",x.style.cssText="padding:10px 16px;cursor:pointer;color:#333;transition:background 0.15s;font-weight:600;border-bottom:1px solid #eee;",x.onmouseenter=function(){x.style.background="#f5f5f5"},x.onmouseleave=function(){x.style.background="transparent"},x.onclick=function(){g=null,window.Loco.restore(),w(),m.style.display="none"},m.appendChild(x);var b=[];a.forEach(function(y){var E=document.createElement("div");E.textContent=p(y),E.setAttribute("data-lang",y),E.style.cssText="padding:10px 16px;cursor:pointer;color:#333;transition:background 0.15s;",E.onmouseenter=function(){E.style.background="#f5f5f5"},E.onmouseleave=function(){E.style.background=g===y?"#e8f0fe":"transparent"},E.onclick=function(){g=y,window.Loco.apply(y),w(),m.style.display="none"},m.appendChild(E),b.push({el:E,code:y})});function w(){x.style.background=g===null?"#e8f0fe":"transparent",x.style.fontWeight=g===null?"600":"400",b.forEach(function(y){y.el.style.background=g===y.code?"#e8f0fe":"transparent",y.el.style.fontWeight=g===y.code?"600":"400"})}d.onclick=function(y){y.stopPropagation(),m.style.display=m.style.display==="none"?"block":"none"},document.addEventListener("click",function(y){c.contains(y.target)||(m.style.display="none")}),w(),c.appendChild(m),c.appendChild(d),document.body.appendChild(c)}function Et(e){Ce&&(!e||e.length===0||me(e,Ce))}var H={__proto__:1,constructor:1,prototype:1};function ze(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={},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 o={};if(!Array.isArray(e.languages))return null;o.languages=[];for(var l=0;l<e.languages.length;l++){if(typeof e.languages[l]!="string"||e.languages[l].length>20)return null;o.languages.push(e.languages[l])}if(o.timestamp=typeof e.timestamp=="number"&&isFinite(e.timestamp)?e.timestamp:0,o.languageNames={},e.languageNames&&typeof e.languageNames=="object"&&!Array.isArray(e.languageNames))for(var v in e.languageNames)!e.languageNames.hasOwnProperty(v)||H[v]||typeof e.languageNames[v]=="string"&&e.languageNames[v].length<=100&&(o.languageNames[v]=e.languageNames[v]);if(o.translations={},e.translations&&typeof e.translations=="object"&&!Array.isArray(e.translations)){for(var h in e.translations)if(!(!e.translations.hasOwnProperty(h)||H[h])&&o.languages.indexOf(h)!==-1){var s=e.translations[h];if(Array.isArray(s)){for(var f=[],p=0;p<s.length;p++){var g=s[p];!g||typeof g!="object"||typeof g.key!="string"||typeof g.value!="string"||g.key.length>Z||g.value.length>Z||H[g.key]||f.push({key:g.key,value:g.value,context:typeof g.context=="string"?g.context:""})}o.translations[h]=f}else if(typeof s=="object"){var c={};for(var u in s)!s.hasOwnProperty(u)||H[u]||typeof s[u]=="string"&&(u.length>Z||s[u].length>Z||(c[u]=s[u]));o.translations[h]=c}}}if(o.aria=[],Array.isArray(e.aria))for(var d=0;d<e.aria.length;d++){var a=e.aria[d];if(!(!a||typeof a!="object")&&!(typeof a.key!="string"||a.key.length>Z)&&!H[a.key]){var m=typeof a.context=="string"?a.context:"",x=a.attributes;!x||typeof x!="object"||Array.isArray(x)||o.aria.push({key:a.key,context:m,attributes:x})}}return o}async function Ge(){try{var e=await fetch(i.apiBase+"/api/project/crawler-config",{headers:{"X-API-Key":i.apiKey}});e.ok&&Ye(await e.json())}catch{}Le(),i.phrases=await ae(document.body),de(i.phrases).then(function(t){t&&t.keyMap&&ce(i.phrases,t.keyMap)}).catch(function(t){console.warn("[loco] Failed to register keys:",t)}),We().then(function(t){i.ariaRules=t||{};var r=V(i.phrases,i.ariaRules);r.applied>0&&console.log("[loco] applied ARIA rules to "+r.applied+" element(s)")}).catch(function(){}),!i.scanStopped&&i.screenshotsEnabled&&setTimeout(ut,3e3),console.log("[loco] "+i.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=Y();n?$.apply(n):i.observer=he(i.phrases.map(function(t){return t.key+"\0"+(t.context||"")}),{})}function bt(e,n){for(var t="\0",r={},a=[],o=0;o<e.length;o++){var l=e[o],v=l.key+t+(l.context||"");r.hasOwnProperty(v)||a.push(v),r[v]=l}for(var h=0;h<n.length;h++){var s=n[h],f=s.key+t+(s.context||"");r.hasOwnProperty(f)||a.push(f),r[f]=s}for(var p=[],g=0;g<a.length;g++)p.push(r[a[g]]);return p}async function xe(e){i.screenshotsEnabled=!1,Le(),i.phrases=await ae(document.body);var n=[],t=i.fileData.translations||{},r=(i.fileData.languages||[])[0];r&&t[r]&&(t[r]=Ue(t[r]),n=Object.keys(t[r]));var a=q(i.phrases,n),o=a?Object.keys(a).length:0,l=(i.fileData.languages||[]).length;console.log("[loco] (file mode) "+i.phrases.length+" text nodes discovered, "+l+" language(s) available"+(o?", "+o+" var-remapped":"")+" ["+e+"]"),console.log(" Languages: "+(i.fileData.languages||[]).join(", "));var v=Y();v?$.apply(v):i.observer=he(i.phrases.map(function(h){return h.key+"\0"+(h.context||"")}),{}),i.ariaRules=He(i.fileData.aria||[]),Object.keys(i.ariaRules).length>0&&V(i.phrases,i.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(r){if(r.name&&r.name.indexOf("loco-tr-")===0)try{indexedDB.deleteDatabase(r.name)}catch{}})}).catch(function(){})}catch{}i.fileUrls=e;var n=null;try{n=await mt()}catch{}n&&n.translations?(i.fileData={languages:n.languages,languageNames:n.languageNames||{},translations:n.translations,aria:n.aria||[],timestamp:0},i.loadedFromCache=!0,await xe("cache"),i.fileReadyResolve&&(i.fileReadyResolve(),i.fileReadyResolve=null),Nt(e)):(await wt(e),await xe("network"),i.fileReadyResolve&&(i.fileReadyResolve(),i.fileReadyResolve=null))}async function wt(e){for(var n=e.map(function(h){return fetch(h).then(function(s){if(!s.ok)throw new Error("HTTP "+s.status+" for "+h);return s.text()}).then(function(s){if(!s||!s.trim())return null;var f;try{f=JSON.parse(s)}catch{return null}var p=ye(f);return p?{url:h,data:p}:(console.warn("[loco] File rejected (invalid schema): "+h),null)}).catch(function(s){return console.warn("[loco] Failed to load "+h+":",s),null})}),t=await Promise.all(n),r=!0,a=0;a<t.length;a++)if(t[a]){var o=t[a].url,l=t[a].data,v=!r||(l.languages||[]).length===1;Ee(l,r),r=!1;try{await ve(o,l,v)}catch{}}i.loadedFromCache=!1}function Ee(e,n){if(!i.fileData||n){i.fileData={languages:(e.languages||[]).slice(),languageNames:Object.assign({},e.languageNames||{}),translations:Object.assign({},e.translations||{}),aria:(e.aria||[]).slice(),timestamp:e.timestamp||0},i.fileData.aria||(i.fileData.aria=[]);var t=e.aria||[];if(t.length>0){for(var r="\0",a={},o=[],l=0;l<i.fileData.aria.length;l++){var v=i.fileData.aria[l];if(!(!v||typeof v.key!="string")){var h=v.key+r+(v.context||"");a.hasOwnProperty(h)||o.push(h),a[h]=v}}for(var s=0;s<t.length;s++){var f=t[s];if(!(!f||typeof f.key!="string")){var p=f.key+r+(f.context||"");a.hasOwnProperty(p)||o.push(p),a[p]=f}}i.fileData.aria=o.map(function(y){return a[y]})}return}for(var g=e.languages||[],c=0;c<g.length;c++)i.fileData.languages.indexOf(g[c])===-1&&i.fileData.languages.push(g[c]);var u=e.languageNames||{};i.fileData.languageNames||(i.fileData.languageNames={});for(var d in u)!u.hasOwnProperty(d)||H[d]||(i.fileData.languageNames[d]=u[d]);var m=e.translations||{};i.fileData.translations||(i.fileData.translations={});for(var x in m)if(!(!m.hasOwnProperty(x)||H[x])){var b=i.fileData.translations[x],w=m[x];!b||!Array.isArray(b)||!Array.isArray(w)?i.fileData.translations[x]=w:i.fileData.translations[x]=bt(b,w)}e.timestamp&&e.timestamp>i.fileData.timestamp&&(i.fileData.timestamp=e.timestamp)}function Nt(e){var n=e.map(function(t){return Promise.all([Qe(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],o=r[1];if(!o||!o.trim())return null;var l;try{l=JSON.parse(o)}catch{return null}if(l=ye(l),!l)return null;var v=l.timestamp||0,h=a&&a.timestamp||0;if(v!==h){var s=e.length>1||(l.languages||[]).length===1;return ve(t,l,s).catch(function(){}),l}return null})});Promise.all(n).then(function(t){for(var r=!1,a=0;a<t.length;a++)t[a]&&(Ee(t[a],!1),r=!0);r&&(i.loadedFromCache=!1,i.observer&&(i.observer.disconnect(),i.observer=null),j(i.phrases),xe("network — updated").then(function(){Se()}),console.log("[loco] translations refreshed from file(s) (timestamp changed)"))}).catch(function(){console.log("[loco] using cached translations (network unavailable)")})}function Se(){i.widgetPosition&&ge().then(function(e){if(e){var n=be(e.languages,e.languageNames);Et(n)}}).catch(function(){})}var Ve={"zh-Hans":"Chinese (Simplified)","zh-Hant":"Chinese (Traditional)"};function Tt(e){var n=String(e||"").trim().replace(/_/g,"-");if(!n)return"";var t=n.split("-").filter(Boolean);if(t.length===0)return"";t[0]=t[0].toLowerCase();for(var r=1;r<t.length;r++)t[r].length===2?t[r]=t[r].toUpperCase():t[r].length===4?t[r]=t[r].charAt(0).toUpperCase()+t[r].slice(1).toLowerCase():t[r]=t[r].toLowerCase();return t.join("-")}function $e(e){var n=Tt(e);if(!n)return"";if(Ve[n])return Ve[n];if(n.indexOf("-")===-1)return"";try{if(typeof Intl<"u"&&typeof Intl.DisplayNames=="function"){var t=new Intl.DisplayNames([typeof navigator<"u"&&navigator.language||"en","en"],{type:"language"}),r=t.of(n);if(r&&r!==n)return r}}catch{}return""}function Oe(e,n){if(!e)return"";n=n||{};var t=n[e];if(t)return t;var r=String(e).replace(/_/g,"-");if(n[r])return n[r];var a=r.toLowerCase();if(n[a])return n[a];var o=a.split("-").map(function(l,v){return v===0?l:l.length===2?l.toUpperCase():l.length===4?l.charAt(0).toUpperCase()+l.slice(1):l}).join("-");return n[o]?n[o]:$e(e)}function be(e,n){return e=e||[],n=n||{},e.map(function(t){var r=Oe(t,n);return r?{code:t,name:r}:t})}function At(e){return e?e.type==="text"?!!(e.textNode&&e.textNode.parentElement&&e.textNode.isConnected):!!(e.element&&e.element.isConnected):!1}function Je(){if(!Array.isArray(i.phrases)||i.phrases.length===0)return[];var e=i.phrases.filter(At);return e.length!==i.phrases.length&&(i.phrases=e),i.phrases}var $={version:"1.1.11",init:function(e){if(!e){console.warn("[loco] Loco.init() requires a config object");return}if(e.file||e.files){i.fileMode=!0,i.fileReady=new Promise(function(r){i.fileReadyResolve=r});for(var n=e.files?e.files.slice():[e.file],t=0;t<n.length;t++)if(!ze(n[t])){console.warn("[loco] Blocked unsafe URL: "+n[t]);return}i.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}i.apiKey=e.apiKey,i.apiBase=e.apiUrl.replace(/\/+$/,""),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",Ge):Ge()},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(i.fileMode){if(!i.fileData){console.warn("[loco] File not loaded yet. Call Loco.init({ file }) first.");return}if(!i.fileData.translations||!i.fileData.translations[e])try{var t=await vt(e);if(!t||Object.keys(t).length===0){console.warn('[loco] No translations for "'+e+'" in file data or cache');return}return i.fileData.translations||(i.fileData.translations={}),i.fileData.translations[e]=t,i.fileData.languages.indexOf(e)===-1&&i.fileData.languages.push(e),$.apply(e)}catch(h){console.warn('[loco] Failed to load translations for "'+e+'" from cache:',h);return}i.observer&&(i.observer.disconnect(),i.observer=null),j(i.phrases),i.translations=Ue(i.fileData.translations[e]),i.fileData.translations[e]=i.translations,n&&performance.mark("loco-collect-start");var r=Je();r.length===0&&(i.phrases=await ae(document.body)),n&&(performance.mark("loco-collect-end"),performance.measure("loco-collection-time","loco-collect-start","loco-collect-end"));var a=Object.keys(i.translations);q(i.phrases,a),n&&performance.mark("loco-dom-start");var o=await pe(i.phrases,i.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")),i.ariaRules&&Object.keys(i.ariaRules).length>0&&V(i.phrases,i.ariaRules),i.observer=he(i.phrases.map(function(h){return h.key+"\0"+(h.context||"")}),i.translations),i.currentLang=e,le(e),console.log("[loco] (file) applied "+o.applied+" translation(s), "+o.skipped+" pending"),o}if(!i.apiKey||!i.apiBase){console.warn("[loco] Call Loco.init() first");return}i.observer&&(i.observer.disconnect(),i.observer=null),j(i.phrases);try{var l=await ct(e);i.translations=l||{},n&&performance.mark("loco-collect-start");var v=Je();v.length===0&&(i.phrases=await ae(document.body)),n&&(performance.mark("loco-collect-end"),performance.measure("loco-collection-time","loco-collect-start","loco-collect-end")),q(i.phrases,Object.keys(i.translations)),de(i.phrases).then(function(s){s&&s.keyMap&&(ce(i.phrases,s.keyMap),pe(i.phrases,i.translations))}).catch(function(){}),n&&performance.mark("loco-dom-start");var o=await pe(i.phrases,i.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")),i.ariaRules&&Object.keys(i.ariaRules).length>0&&V(i.phrases,i.ariaRules),i.observer=he(i.phrases.map(function(s){return s.key+"\0"+(s.context||"")}),i.translations),i.currentLang=e,le(e),console.log("[loco] applied "+o.applied+" translation(s), "+o.skipped+" pending"),o}catch(h){console.warn("[loco] Failed to fetch translations:",h)}},restore:function(){j(i.phrases),i.observer&&i.observer.disconnect(),i.currentLang=null,le(null)},rescan:async function(){var e=Object.keys(i.translations).length>0;e&&j(i.phrases),i.currentLang=null,i.phrases=await ae(document.body),i.fileMode||de(i.phrases).catch(function(){}),i.ariaRules&&Object.keys(i.ariaRules).length>0&&V(i.phrases,i.ariaRules),e&&(q(i.phrases,Object.keys(i.translations)),await pe(i.phrases,i.translations))},textnodes:function(){return i.phrases.map(function(e){return{key:e.key,context:e.context||"",element:e.element}})},aria:async function(){var e=await We();i.ariaRules=e||{};var n=V(i.phrases,i.ariaRules);return console.log("[loco] applied ARIA rules to "+n.applied+" element(s)"),n},stopScan:function(){i.scanStopped=!0,i.observer&&(i.observer.disconnect(),i.observer=null),console.log("[loco] scanning stopped, no further nodes will be sent to dashboard")},startScan:function(){i.scanStopped=!1,console.log("[loco] scanning resumed")},isFileMode:function(){return i.fileMode},languages:function(){if(i.fileMode){var e=function(){var n=i.fileData?i.fileData.languages||[]:[],t=i.fileData&&i.fileData.languageNames||{};return n.map(function(r){return{code:r,name:Oe(r,t)||r}})};return!i.fileData&&i.fileReady?i.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!i.apiKey||!i.apiBase?Promise.resolve([]):fetch(i.apiBase+"/api/languages",{headers:{"X-API-Key":i.apiKey}}).then(function(n){return n.json()}).then(function(n){return Array.isArray(n)?n.map(function(t){if(t&&typeof t=="object"&&t.code){var r=t.name&&t.name!==t.code?t.name:$e(t.code);return{code:t.code,name:r||t.code}}return t}):[]}).catch(function(){return[]})},widget:function(e){e=e||{};var n=e.position||"bottom-right";if(i.widgetPosition=n,i.fileMode){let t=function(){ge().then(function(a){var o;if(a&&a.languages&&a.languages.length>0?o=be(a.languages,a.languageNames):o=r(),o.length===0){console.warn("[loco] No languages found in translation file or cache");return}me(o,n)}).catch(function(){var a=r();if(a.length===0){console.warn("[loco] No languages found in translation file");return}me(a,n)})},r=function(){var a=i.fileData?i.fileData.languages||[]:[],o=i.fileData&&i.fileData.languageNames||{};return a.map(function(l){var v=Oe(l,o);return v?{code:l,name:v}:l})};if(!i.fileData&&i.fileReady){i.fileReady.then(t);return}t();return}if(!i.apiKey||!i.apiBase){console.warn("[loco] Call Loco.init() first");return}fetch(i.apiBase+"/api/languages",{headers:{"X-API-Key":i.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}me(t,n)}).catch(function(t){console.warn("[loco] Failed to fetch languages:",t)})},clearCache:function(){return i.fileMode?yt().then(function(){i.fileData&&(i.fileData.translations={},i.fileData.timestamp=0),i.currentLang=null,i.loadedFromCache=!1,le(null),j(i.phrases),i.observer&&(i.observer.disconnect(),i.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 i.fileMode?e?ze(e)?(i.fileUrls.indexOf(e)===-1&&i.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 r=!i.fileData||!i.fileData.languages||i.fileData.languages.length===0,a=!r||(t.languages||[]).length===1;return Ee(t,r),ve(e,t,a).catch(function(){}),Se(),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(!i.fileMode)return console.warn("[loco] pullLatest() is only available in file mode"),Promise.resolve({status:"skipped",reason:"not in file mode"});var e=i.fileUrls.length>0?i.fileUrls:i.fileUrl?[i.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([Qe(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],o=r[1];if(!o||!o.trim())return{url:t,status:"current",reason:"empty"};var l;try{l=JSON.parse(o)}catch{throw new Error("Invalid JSON in "+t)}if(l=ye(l),!l)throw new Error("Invalid file schema in "+t);var v=l.timestamp||0,h=a&&a.timestamp||0;if(v===h&&h!==0){var s=i.fileData&&i.fileData.translations,f=l.languages||[],p=!s||f.some(function(u){return!i.fileData.translations[u]});if(!p)return{url:t,status:"current",timestamp:h}}var g=!i.fileData||!i.fileData.languages||i.fileData.languages.length===0,c=!g||(l.languages||[]).length===1;return Ee(l,g),ve(t,l,c).catch(function(){}),{url:t,status:"updated",timestamp:v,previousTimestamp:h}}).catch(function(r){return{url:t,status:"error",reason:r.message}})});return Promise.all(n).then(async function(t){var r=t.some(function(f){return f.status==="updated"});if(r){i.loadedFromCache=!1,i.currentLang=null;var a=Y();if(a)i.observer&&(i.observer.disconnect(),i.observer=null),j(i.phrases),await xe("pullLatest");else{i.phrases=Ke(document.body);var o=i.fileData.translations||{},l=(i.fileData.languages||[])[0];l&&o[l]&&q(i.phrases,Object.keys(o[l]))}Se()}if(t.length===1){var v=t[0];return console.log("[loco] pullLatest: "+v.status+(v.timestamp?" (timestamp: "+v.timestamp+")":"")),v}var h=t.filter(function(f){return f.status==="updated"}).map(function(f){return f.url}),s=t.filter(function(f){return f.status==="current"}).map(function(f){return f.url});return console.log("[loco] pullLatest: "+h.length+" updated, "+s.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=$,Object.defineProperty($,"_state",{value:i,writable:!1,enumerable:!1,configurable:!1}),$}();
4
+ Loco.rescan() — re-scan DOM for new nodes`);var n=Y();n?$.apply(n):i.observer=he(i.phrases.map(function(t){return t.key+"\0"+(t.context||"")}),{})}function bt(e,n){for(var t="\0",r={},a=[],o=0;o<e.length;o++){var l=e[o],v=l.key+t+(l.context||"");r.hasOwnProperty(v)||a.push(v),r[v]=l}for(var h=0;h<n.length;h++){var s=n[h],f=s.key+t+(s.context||"");r.hasOwnProperty(f)||a.push(f),r[f]=s}for(var p=[],g=0;g<a.length;g++)p.push(r[a[g]]);return p}async function xe(e){i.screenshotsEnabled=!1,Le(),i.phrases=await ae(document.body);var n=[],t=i.fileData.translations||{},r=(i.fileData.languages||[])[0];r&&t[r]&&(t[r]=Ue(t[r]),n=Object.keys(t[r]));var a=q(i.phrases,n),o=a?Object.keys(a).length:0,l=(i.fileData.languages||[]).length;console.log("[loco] (file mode) "+i.phrases.length+" text nodes discovered, "+l+" language(s) available"+(o?", "+o+" var-remapped":"")+" ["+e+"]"),console.log(" Languages: "+(i.fileData.languages||[]).join(", "));var v=Y();v?$.apply(v):i.observer=he(i.phrases.map(function(h){return h.key+"\0"+(h.context||"")}),{}),i.ariaRules=He(i.fileData.aria||[]),Object.keys(i.ariaRules).length>0&&V(i.phrases,i.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(r){if(r.name&&r.name.indexOf("loco-tr-")===0)try{indexedDB.deleteDatabase(r.name)}catch{}})}).catch(function(){})}catch{}i.fileUrls=e;var n=null;try{n=await mt()}catch{}n&&n.translations?(i.fileData={languages:n.languages,languageNames:n.languageNames||{},translations:n.translations,aria:n.aria||[],timestamp:0},i.loadedFromCache=!0,await xe("cache"),i.fileReadyResolve&&(i.fileReadyResolve(),i.fileReadyResolve=null),Nt(e)):(await wt(e),await xe("network"),i.fileReadyResolve&&(i.fileReadyResolve(),i.fileReadyResolve=null))}async function wt(e){for(var n=e.map(function(h){return fetch(h).then(function(s){if(!s.ok)throw new Error("HTTP "+s.status+" for "+h);return s.text()}).then(function(s){if(!s||!s.trim())return null;var f;try{f=JSON.parse(s)}catch{return null}var p=ye(f);return p?{url:h,data:p}:(console.warn("[loco] File rejected (invalid schema): "+h),null)}).catch(function(s){return console.warn("[loco] Failed to load "+h+":",s),null})}),t=await Promise.all(n),r=!0,a=0;a<t.length;a++)if(t[a]){var o=t[a].url,l=t[a].data,v=!r||(l.languages||[]).length===1;Ee(l,r),r=!1;try{await ve(o,l,v)}catch{}}i.loadedFromCache=!1}function Ee(e,n){if(!i.fileData||n){i.fileData={languages:(e.languages||[]).slice(),languageNames:Object.assign({},e.languageNames||{}),translations:Object.assign({},e.translations||{}),aria:(e.aria||[]).slice(),timestamp:e.timestamp||0},i.fileData.aria||(i.fileData.aria=[]);var t=e.aria||[];if(t.length>0){for(var r="\0",a={},o=[],l=0;l<i.fileData.aria.length;l++){var v=i.fileData.aria[l];if(!(!v||typeof v.key!="string")){var h=v.key+r+(v.context||"");a.hasOwnProperty(h)||o.push(h),a[h]=v}}for(var s=0;s<t.length;s++){var f=t[s];if(!(!f||typeof f.key!="string")){var p=f.key+r+(f.context||"");a.hasOwnProperty(p)||o.push(p),a[p]=f}}i.fileData.aria=o.map(function(y){return a[y]})}return}for(var g=e.languages||[],c=0;c<g.length;c++)i.fileData.languages.indexOf(g[c])===-1&&i.fileData.languages.push(g[c]);var u=e.languageNames||{};i.fileData.languageNames||(i.fileData.languageNames={});for(var d in u)!u.hasOwnProperty(d)||H[d]||(i.fileData.languageNames[d]=u[d]);var m=e.translations||{};i.fileData.translations||(i.fileData.translations={});for(var x in m)if(!(!m.hasOwnProperty(x)||H[x])){var b=i.fileData.translations[x],w=m[x];!b||!Array.isArray(b)||!Array.isArray(w)?i.fileData.translations[x]=w:i.fileData.translations[x]=bt(b,w)}e.timestamp&&e.timestamp>i.fileData.timestamp&&(i.fileData.timestamp=e.timestamp)}function Nt(e){var n=e.map(function(t){return Promise.all([Qe(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],o=r[1];if(!o||!o.trim())return null;var l;try{l=JSON.parse(o)}catch{return null}if(l=ye(l),!l)return null;var v=l.timestamp||0,h=a&&a.timestamp||0;if(v!==h){var s=e.length>1||(l.languages||[]).length===1;return ve(t,l,s).catch(function(){}),l}return null})});Promise.all(n).then(function(t){for(var r=!1,a=0;a<t.length;a++)t[a]&&(Ee(t[a],!1),r=!0);r&&(i.loadedFromCache=!1,i.observer&&(i.observer.disconnect(),i.observer=null),j(i.phrases),xe("network — updated").then(function(){Se()}),console.log("[loco] translations refreshed from file(s) (timestamp changed)"))}).catch(function(){console.log("[loco] using cached translations (network unavailable)")})}function Se(){i.widgetPosition&&ge().then(function(e){if(e){var n=be(e.languages,e.languageNames);Et(n)}}).catch(function(){})}var Ve={"zh-Hans":"Chinese (Simplified)","zh-Hant":"Chinese (Traditional)"};function Tt(e){var n=String(e||"").trim().replace(/_/g,"-");if(!n)return"";var t=n.split("-").filter(Boolean);if(t.length===0)return"";t[0]=t[0].toLowerCase();for(var r=1;r<t.length;r++)t[r].length===2?t[r]=t[r].toUpperCase():t[r].length===4?t[r]=t[r].charAt(0).toUpperCase()+t[r].slice(1).toLowerCase():t[r]=t[r].toLowerCase();return t.join("-")}function $e(e){var n=Tt(e);if(!n)return"";if(Ve[n])return Ve[n];if(n.indexOf("-")===-1)return"";try{if(typeof Intl<"u"&&typeof Intl.DisplayNames=="function"){var t=new Intl.DisplayNames([typeof navigator<"u"&&navigator.language||"en","en"],{type:"language"}),r=t.of(n);if(r&&r!==n)return r}}catch{}return""}function Oe(e,n){if(!e)return"";n=n||{};var t=n[e];if(t)return t;var r=String(e).replace(/_/g,"-");if(n[r])return n[r];var a=r.toLowerCase();if(n[a])return n[a];var o=a.split("-").map(function(l,v){return v===0?l:l.length===2?l.toUpperCase():l.length===4?l.charAt(0).toUpperCase()+l.slice(1):l}).join("-");return n[o]?n[o]:$e(e)}function be(e,n){return e=e||[],n=n||{},e.map(function(t){var r=Oe(t,n);return r?{code:t,name:r}:t})}function At(e){return e?e.type==="text"?!!(e.textNode&&e.textNode.parentElement&&e.textNode.isConnected):!!(e.element&&e.element.isConnected):!1}function Je(){if(!Array.isArray(i.phrases)||i.phrases.length===0)return[];var e=i.phrases.filter(At);return e.length!==i.phrases.length&&(i.phrases=e),i.phrases}var $={version:"1.1.12",init:function(e){if(!e){console.warn("[loco] Loco.init() requires a config object");return}if(e.file||e.files){i.fileMode=!0,i.fileReady=new Promise(function(r){i.fileReadyResolve=r});for(var n=e.files?e.files.slice():[e.file],t=0;t<n.length;t++)if(!ze(n[t])){console.warn("[loco] Blocked unsafe URL: "+n[t]);return}i.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}i.apiKey=e.apiKey,i.apiBase=e.apiUrl.replace(/\/+$/,""),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",Ge):Ge()},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(i.fileMode){if(!i.fileData){console.warn("[loco] File not loaded yet. Call Loco.init({ file }) first.");return}if(!i.fileData.translations||!i.fileData.translations[e])try{var t=await vt(e);if(!t||Object.keys(t).length===0){console.warn('[loco] No translations for "'+e+'" in file data or cache');return}return i.fileData.translations||(i.fileData.translations={}),i.fileData.translations[e]=t,i.fileData.languages.indexOf(e)===-1&&i.fileData.languages.push(e),$.apply(e)}catch(h){console.warn('[loco] Failed to load translations for "'+e+'" from cache:',h);return}i.observer&&(i.observer.disconnect(),i.observer=null),j(i.phrases),i.translations=Ue(i.fileData.translations[e]),i.fileData.translations[e]=i.translations,n&&performance.mark("loco-collect-start");var r=Je();r.length===0&&(i.phrases=await ae(document.body)),n&&(performance.mark("loco-collect-end"),performance.measure("loco-collection-time","loco-collect-start","loco-collect-end"));var a=Object.keys(i.translations);q(i.phrases,a),n&&performance.mark("loco-dom-start");var o=await pe(i.phrases,i.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")),i.ariaRules&&Object.keys(i.ariaRules).length>0&&V(i.phrases,i.ariaRules),i.observer=he(i.phrases.map(function(h){return h.key+"\0"+(h.context||"")}),i.translations),i.currentLang=e,le(e),console.log("[loco] (file) applied "+o.applied+" translation(s), "+o.skipped+" pending"),o}if(!i.apiKey||!i.apiBase){console.warn("[loco] Call Loco.init() first");return}i.observer&&(i.observer.disconnect(),i.observer=null),j(i.phrases);try{var l=await ct(e);i.translations=l||{},n&&performance.mark("loco-collect-start");var v=Je();v.length===0&&(i.phrases=await ae(document.body)),n&&(performance.mark("loco-collect-end"),performance.measure("loco-collection-time","loco-collect-start","loco-collect-end")),q(i.phrases,Object.keys(i.translations)),de(i.phrases).then(function(s){s&&s.keyMap&&(ce(i.phrases,s.keyMap),pe(i.phrases,i.translations))}).catch(function(){}),n&&performance.mark("loco-dom-start");var o=await pe(i.phrases,i.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")),i.ariaRules&&Object.keys(i.ariaRules).length>0&&V(i.phrases,i.ariaRules),i.observer=he(i.phrases.map(function(s){return s.key+"\0"+(s.context||"")}),i.translations),i.currentLang=e,le(e),console.log("[loco] applied "+o.applied+" translation(s), "+o.skipped+" pending"),o}catch(h){console.warn("[loco] Failed to fetch translations:",h)}},restore:function(){j(i.phrases),i.observer&&i.observer.disconnect(),i.currentLang=null,le(null)},rescan:async function(){var e=Object.keys(i.translations).length>0;e&&j(i.phrases),i.currentLang=null,i.phrases=await ae(document.body),i.fileMode||de(i.phrases).catch(function(){}),i.ariaRules&&Object.keys(i.ariaRules).length>0&&V(i.phrases,i.ariaRules),e&&(q(i.phrases,Object.keys(i.translations)),await pe(i.phrases,i.translations))},textnodes:function(){return i.phrases.map(function(e){return{key:e.key,context:e.context||"",element:e.element}})},aria:async function(){var e=await We();i.ariaRules=e||{};var n=V(i.phrases,i.ariaRules);return console.log("[loco] applied ARIA rules to "+n.applied+" element(s)"),n},stopScan:function(){i.scanStopped=!0,i.observer&&(i.observer.disconnect(),i.observer=null),console.log("[loco] scanning stopped, no further nodes will be sent to dashboard")},startScan:function(){i.scanStopped=!1,console.log("[loco] scanning resumed")},isFileMode:function(){return i.fileMode},languages:function(){if(i.fileMode){var e=function(){var n=i.fileData?i.fileData.languages||[]:[],t=i.fileData&&i.fileData.languageNames||{};return n.map(function(r){return{code:r,name:Oe(r,t)||r}})};return!i.fileData&&i.fileReady?i.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!i.apiKey||!i.apiBase?Promise.resolve([]):fetch(i.apiBase+"/api/languages",{headers:{"X-API-Key":i.apiKey}}).then(function(n){return n.json()}).then(function(n){return Array.isArray(n)?n.map(function(t){if(t&&typeof t=="object"&&t.code){var r=t.name&&t.name!==t.code?t.name:$e(t.code);return{code:t.code,name:r||t.code}}return t}):[]}).catch(function(){return[]})},widget:function(e){e=e||{};var n=e.position||"bottom-right";if(i.widgetPosition=n,i.fileMode){let t=function(){ge().then(function(a){var o;if(a&&a.languages&&a.languages.length>0?o=be(a.languages,a.languageNames):o=r(),o.length===0){console.warn("[loco] No languages found in translation file or cache");return}me(o,n)}).catch(function(){var a=r();if(a.length===0){console.warn("[loco] No languages found in translation file");return}me(a,n)})},r=function(){var a=i.fileData?i.fileData.languages||[]:[],o=i.fileData&&i.fileData.languageNames||{};return a.map(function(l){var v=Oe(l,o);return v?{code:l,name:v}:l})};if(!i.fileData&&i.fileReady){i.fileReady.then(t);return}t();return}if(!i.apiKey||!i.apiBase){console.warn("[loco] Call Loco.init() first");return}fetch(i.apiBase+"/api/languages",{headers:{"X-API-Key":i.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}me(t,n)}).catch(function(t){console.warn("[loco] Failed to fetch languages:",t)})},clearCache:function(){return i.fileMode?yt().then(function(){i.fileData&&(i.fileData.translations={},i.fileData.timestamp=0),i.currentLang=null,i.loadedFromCache=!1,le(null),j(i.phrases),i.observer&&(i.observer.disconnect(),i.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 i.fileMode?e?ze(e)?(i.fileUrls.indexOf(e)===-1&&i.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 r=!i.fileData||!i.fileData.languages||i.fileData.languages.length===0,a=!r||(t.languages||[]).length===1;return Ee(t,r),ve(e,t,a).catch(function(){}),Se(),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(!i.fileMode)return console.warn("[loco] pullLatest() is only available in file mode"),Promise.resolve({status:"skipped",reason:"not in file mode"});var e=i.fileUrls.length>0?i.fileUrls:i.fileUrl?[i.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([Qe(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],o=r[1];if(!o||!o.trim())return{url:t,status:"current",reason:"empty"};var l;try{l=JSON.parse(o)}catch{throw new Error("Invalid JSON in "+t)}if(l=ye(l),!l)throw new Error("Invalid file schema in "+t);var v=l.timestamp||0,h=a&&a.timestamp||0;if(v===h&&h!==0){var s=i.fileData&&i.fileData.translations,f=l.languages||[],p=!s||f.some(function(u){return!i.fileData.translations[u]});if(!p)return{url:t,status:"current",timestamp:h}}var g=!i.fileData||!i.fileData.languages||i.fileData.languages.length===0,c=!g||(l.languages||[]).length===1;return Ee(l,g),ve(t,l,c).catch(function(){}),{url:t,status:"updated",timestamp:v,previousTimestamp:h}}).catch(function(r){return{url:t,status:"error",reason:r.message}})});return Promise.all(n).then(async function(t){var r=t.some(function(f){return f.status==="updated"});if(r){i.loadedFromCache=!1,i.currentLang=null;var a=Y();if(a)i.observer&&(i.observer.disconnect(),i.observer=null),j(i.phrases),await xe("pullLatest");else{i.phrases=Ke(document.body);var o=i.fileData.translations||{},l=(i.fileData.languages||[])[0];l&&o[l]&&q(i.phrases,Object.keys(o[l]))}Se()}if(t.length===1){var v=t[0];return console.log("[loco] pullLatest: "+v.status+(v.timestamp?" (timestamp: "+v.timestamp+")":"")),v}var h=t.filter(function(f){return f.status==="updated"}).map(function(f){return f.url}),s=t.filter(function(f){return f.status==="current"}).map(function(f){return f.url});return console.log("[loco] pullLatest: "+h.length+" updated, "+s.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=$,Object.defineProperty($,"_state",{value:i,writable:!1,enumerable:!1,configurable:!1}),$}();
package/versions.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "1.1.11"
2
+ "version": "1.1.12"
3
3
  }