@hkonda/loco-translate 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README.md +284 -0
  2. package/bin/loco.js +5 -0
  3. package/dist/assets/index-CGo6e-bA.js +59 -0
  4. package/dist/assets/index-DBcQDZ75.css +1 -0
  5. package/dist/index.html +13 -0
  6. package/dist-server/app.d.ts +3 -0
  7. package/dist-server/app.d.ts.map +1 -0
  8. package/dist-server/app.js +154 -0
  9. package/dist-server/app.js.map +1 -0
  10. package/dist-server/config.d.ts +16 -0
  11. package/dist-server/config.d.ts.map +1 -0
  12. package/dist-server/config.js +41 -0
  13. package/dist-server/config.js.map +1 -0
  14. package/dist-server/db/index.d.ts +8 -0
  15. package/dist-server/db/index.d.ts.map +1 -0
  16. package/dist-server/db/index.js +28 -0
  17. package/dist-server/db/index.js.map +1 -0
  18. package/dist-server/db/schema.d.ts +851 -0
  19. package/dist-server/db/schema.d.ts.map +1 -0
  20. package/dist-server/db/schema.js +65 -0
  21. package/dist-server/db/schema.js.map +1 -0
  22. package/dist-server/db/seed.d.ts +14 -0
  23. package/dist-server/db/seed.d.ts.map +1 -0
  24. package/dist-server/db/seed.js +229 -0
  25. package/dist-server/db/seed.js.map +1 -0
  26. package/dist-server/index.d.ts +2 -0
  27. package/dist-server/index.d.ts.map +1 -0
  28. package/dist-server/index.js +31 -0
  29. package/dist-server/index.js.map +1 -0
  30. package/dist-server/routes/ai-jobs.d.ts +5 -0
  31. package/dist-server/routes/ai-jobs.d.ts.map +1 -0
  32. package/dist-server/routes/ai-jobs.js +141 -0
  33. package/dist-server/routes/ai-jobs.js.map +1 -0
  34. package/dist-server/routes/backup.d.ts +5 -0
  35. package/dist-server/routes/backup.d.ts.map +1 -0
  36. package/dist-server/routes/backup.js +125 -0
  37. package/dist-server/routes/backup.js.map +1 -0
  38. package/dist-server/routes/chrome-extension.d.ts +5 -0
  39. package/dist-server/routes/chrome-extension.d.ts.map +1 -0
  40. package/dist-server/routes/chrome-extension.js +140 -0
  41. package/dist-server/routes/chrome-extension.js.map +1 -0
  42. package/dist-server/routes/export.d.ts +5 -0
  43. package/dist-server/routes/export.d.ts.map +1 -0
  44. package/dist-server/routes/export.js +95 -0
  45. package/dist-server/routes/export.js.map +1 -0
  46. package/dist-server/routes/languages.d.ts +5 -0
  47. package/dist-server/routes/languages.d.ts.map +1 -0
  48. package/dist-server/routes/languages.js +36 -0
  49. package/dist-server/routes/languages.js.map +1 -0
  50. package/dist-server/routes/project.d.ts +5 -0
  51. package/dist-server/routes/project.d.ts.map +1 -0
  52. package/dist-server/routes/project.js +151 -0
  53. package/dist-server/routes/project.js.map +1 -0
  54. package/dist-server/routes/prompts.d.ts +5 -0
  55. package/dist-server/routes/prompts.d.ts.map +1 -0
  56. package/dist-server/routes/prompts.js +90 -0
  57. package/dist-server/routes/prompts.js.map +1 -0
  58. package/dist-server/routes/screenshots.d.ts +5 -0
  59. package/dist-server/routes/screenshots.d.ts.map +1 -0
  60. package/dist-server/routes/screenshots.js +71 -0
  61. package/dist-server/routes/screenshots.js.map +1 -0
  62. package/dist-server/routes/textnodes.d.ts +5 -0
  63. package/dist-server/routes/textnodes.d.ts.map +1 -0
  64. package/dist-server/routes/textnodes.js +318 -0
  65. package/dist-server/routes/textnodes.js.map +1 -0
  66. package/dist-server/routes/translations.d.ts +5 -0
  67. package/dist-server/routes/translations.d.ts.map +1 -0
  68. package/dist-server/routes/translations.js +224 -0
  69. package/dist-server/routes/translations.js.map +1 -0
  70. package/dist-server/scripts/backup.d.ts +2 -0
  71. package/dist-server/scripts/backup.d.ts.map +1 -0
  72. package/dist-server/scripts/backup.js +26 -0
  73. package/dist-server/scripts/backup.js.map +1 -0
  74. package/dist-server/services/ai-translation.d.ts +21 -0
  75. package/dist-server/services/ai-translation.d.ts.map +1 -0
  76. package/dist-server/services/ai-translation.js +137 -0
  77. package/dist-server/services/ai-translation.js.map +1 -0
  78. package/dist-server/services/job-manager.d.ts +67 -0
  79. package/dist-server/services/job-manager.d.ts.map +1 -0
  80. package/dist-server/services/job-manager.js +159 -0
  81. package/dist-server/services/job-manager.js.map +1 -0
  82. package/dist-server/services/slot-pattern.d.ts +16 -0
  83. package/dist-server/services/slot-pattern.d.ts.map +1 -0
  84. package/dist-server/services/slot-pattern.js +68 -0
  85. package/dist-server/services/slot-pattern.js.map +1 -0
  86. package/dist-server/utils/network.d.ts +2 -0
  87. package/dist-server/utils/network.d.ts.map +1 -0
  88. package/dist-server/utils/network.js +16 -0
  89. package/dist-server/utils/network.js.map +1 -0
  90. package/package.json +47 -0
  91. package/public/loco.js +2386 -0
  92. package/public/loco.min.js +4 -0
@@ -0,0 +1,4 @@
1
+ var Loco=function(){"use strict";var i={apiKey:null,apiBase:null,phrases:[],translations:{},observer:null,fileMode:!1,fileData:null,fileReadyResolve:null,fileReady:null,fileUrl:null,fileUrls:[],scanStopped:!1,loadedFromCache:!1,screenshotsEnabled:!0,widgetPosition:null},we=["SCRIPT","STYLE","NOSCRIPT","IFRAME","CODE","SVG","AUDIO","VIDEO","LINK"],Le=["VAR","STRONG","EM","B","I","SPAN","A","ABBR","MARK","SMALL","SUB","SUP","U","S","TIME"],Se=["h1","h2","h3","h4","h5","h6","label","legend","caption","figcaption","nav","header","footer","main","section","article","form"],F=new Set(we),D=new Set(Le),he=[].concat(Se),pe=0,ge=!0,k=1e3,G=1e4,ve="loco-lang";function U(){try{return localStorage.getItem(ve)}catch{return null}}function J(e){try{e?localStorage.setItem(ve,e):localStorage.removeItem(ve)}catch{}}function Be(e){if(e.blockedTags){var r=e.blockedTags.disabled||[],t=e.blockedTags.custom||[];F=new Set(we.filter(function(n){return r.indexOf(n)<0})),t.forEach(function(n){F.add(n.toUpperCase())})}if(e.inlineTags){var r=e.inlineTags.disabled||[],t=e.inlineTags.custom||[];D=new Set(Le.filter(function(o){return r.indexOf(o)<0})),t.forEach(function(o){D.add(o.toUpperCase())})}if(e.domContextSelectors){var r=e.domContextSelectors.disabled||[],t=e.domContextSelectors.custom||[];he=Se.filter(function(o){return r.indexOf(o)<0}).concat(t)}e.screenshotsEnabled===!1&&(i.screenshotsEnabled=!1),typeof e.contextDepth=="number"&&(pe=e.contextDepth),e.domContextEnabled===!1&&(ge=!1)}function N(e){return e.trim().replace(/\s+/g," ")}function E(e){return!/[a-zA-Z\u00C0-\u024F\u0900-\u097F\u0600-\u06FF]/.test(e)}function Z(e){var r=e.replace(/\{\{(?:text|number|decimal|date):\d+\}\}/g,"");return!r.trim()||E(r)}function Fe(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function B(e){var t;if(!e||e.nodeType!==1)return!1;const r=(t=e.tagName)==null?void 0:t.toUpperCase();return F.has(r)||e.hasAttribute("notranslate")||e.hasAttribute("data-notranslate")||e.getAttribute("translate")==="no"||e.isContentEditable}function Ae(e){let r=e.parentElement;for(;r&&r!==document.body;){if(B(r))return!0;r=r.parentElement}return!1}const ke=new Set(["H1","H2","H3","H4","H5","H6"]),He=new Set(["SCRIPT","STYLE","NOSCRIPT","CODE"]);let me=new WeakMap,P=new WeakMap,I=null;function Ce(){if(ge){I=new Set;var e=he.slice();try{var r=e.join(",");document.querySelectorAll(r).forEach(function(t){I.add(t)})}catch{e.forEach(function(n){try{document.querySelectorAll(n).forEach(function(a){I.add(a)})}catch{}})}I.forEach(function(t){P.has(t)||H(t)})}}function z(e){return I?I.has(e):ke.has(e.tagName)?!0:he.some(function(r){try{return e.matches(r)}catch{return!1}})}function je(e){let r="";for(const t of e.childNodes)if(t.nodeType===Node.TEXT_NODE){const n=t.textContent.trim();n&&(r+=(r?" ":"")+n)}return r}function Xe(e,r){for(var t="",n=document.createTreeWalker(e,NodeFilter.SHOW_ALL,{acceptNode:function(o){return o.nodeType===Node.ELEMENT_NODE?He.has(o.tagName)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_SKIP:NodeFilter.FILTER_ACCEPT}}),a;(a=n.nextNode())&&!(a.nodeType===Node.TEXT_NODE&&(t+=a.textContent,t.length>=r)););return t.trim()}function H(e){if(P.has(e))return P.get(e);let r=null;const t=je(e);if(t)return r=t.substring(0,60),P.set(e,r),r;if(ke.has(e.tagName)){const a=(e.textContent||"").trim().replace(/\s+/g," ");if(a)return r=a.substring(0,60),P.set(e,r),r}var n=Xe(e,200);if(n){const a=n.split(/\n/)[0].trim().replace(/\s+/g," ");a.length>=2&&!E(a)&&(r=a.substring(0,60))}return P.set(e,r),r}function L(e){if(!e||!ge)return"";if(me.has(e))return me.get(e);const r=[],t=new Set;let n=e,a=0;if(e&&e.tagName==="TD"){var o=e.closest("table");if(o){var s=o.querySelector("thead tr th:nth-child("+(e.cellIndex+1)+")");if(s){var h=H(s);h&&(t.add(h),r.push(h))}}}for(;n&&n!==document.body&&!(pe>0&&a>=pe);){a++;let d=n.previousElementSibling;for(;d;){var v=d.tagName.toUpperCase();if(F.has(v)){d=d.previousElementSibling;continue}if(v==="ARTICLE"||v==="MAIN"){d=d.previousElementSibling;continue}if(z(d)){const f=H(d);f&&!t.has(f)&&(t.add(f),r.unshift(f));break}let p=null;for(const f of d.children)if(z(f)){p=f;break}if(!p)for(const f of d.children){for(const l of f.children)if(z(l)){p=l;break}if(p)break}if(p){const f=H(p);f&&!t.has(f)&&(t.add(f),r.unshift(f));break}d=d.previousElementSibling}if(z(n)){const p=H(n);p&&!t.has(p)&&(t.add(p),r.unshift(p))}var c=n.tagName;if(c==="ARTICLE"||c==="MAIN")break;n=n.parentElement}const u=r.join(" > ");return me.set(e,u),u}function Qe(e){return/^\d+$/.test(e)?"number":/^\d+\.\d+$/.test(e)?"decimal":"text"}function We(e,r){for(var t=r.split(/(\{\{(?:text|number|decimal|date):\d+\}\})/),n=[],a=e,o=0;o<t.length;o++){var s=t[o],h=s.match(/^\{\{(text|number|decimal|date):(\d+)\}\}$/);if(h)if(a.indexOf(s)===0)n.push({type:h[1],index:parseInt(h[2]),originalText:s}),a=a.substring(s.length);else{for(var v="",c=o+1;c<t.length;c++){var u=t[c];if(/^\{\{(?:text|number|decimal|date):\d+\}\}$/.test(u)){if(a.indexOf(u)>=0){v=u;break}}else if(u!==""){v=u;break}}var d;if(v==="")d=a,a="";else{var p=a.indexOf(v);p>=0?(d=a.substring(0,p),a=a.substring(p)):(d=a,a="")}n.push({type:h[1],index:parseInt(h[2]),originalText:d})}else a.indexOf(s)===0&&(a=a.substring(s.length))}return n}function Y(e,r){e.forEach(function(t){if(!(t.varSlots&&t.varSlots.length>0)){var n=r[t.key];n&&(t.varSlots=We(t.key,n),t.key=n)}})}function $e(e,r){for(var t=r.split(/\{\{(?:text|number|decimal|date):\d+\}\}/g),n=e,a=[],o=0;o<t.length;o++)if(o===0)n.indexOf(t[o])===0&&(n=n.substring(t[o].length));else if(t[o]===""&&o===t.length-1)a.push(n),n="";else{var s=n.indexOf(t[o]);s>=0&&(a.push(n.substring(0,s)),n=n.substring(s+t[o].length))}return a.length>0&&a.every(function(h){return/^[a-zA-Z\s]+$/.test(h.trim())})}function Ve(e){for(var r=0,t=/\{\{(text|number|decimal|date):\d+\}\}/g,n;(n=t.exec(e))!==null;)switch(n[1]){case"number":r+=3;break;case"decimal":r+=3;break;case"date":r+=2;break;default:r+=1;break}return r}function R(e,r){for(var t=[],n=0;n<r.length;n++){var a=r[n];if(!(a.indexOf("{{text:")<0&&a.indexOf("{{number:")<0&&a.indexOf("{{decimal:")<0&&a.indexOf("{{date:")<0)){for(var o=[],s=[],h=0,v=/\{\{(text|number|decimal|date):\d+\}\}/g,c;(c=v.exec(a))!==null;)o.push(a.substring(h,c.index)),s.push(c[1]),h=v.lastIndex;o.push(a.substring(h));for(var u="",d=0;d<o.length;d++)if(u+=o[d].replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),d<s.length)switch(s[d]){case"number":u+="\\d+";break;case"decimal":u+="\\d+\\.\\d+";break;default:u+=".+";break}t.push({pattern:a,regex:new RegExp("^"+u+"$"),specificity:Ve(a)})}}if(t.length!==0){t.sort(function(l,g){return g.specificity-l.specificity});for(var p={},f={},n=0;n<r.length;n++)f[r[n]]=!0;return e.forEach(function(l){if(!f[l.key]&&!(l.key.length>k)){for(var g=0;g<t.length;g++)if(t[g].regex.test(l.key)&&!$e(l.key,t[g].pattern)){p[l.key]=t[g].pattern;break}}}),Y(e,p),p}}function A(e){let r=!1,t=!1;for(const n of e.childNodes)if(n.nodeType===Node.TEXT_NODE&&n.textContent.trim()&&(r=!0),n.nodeType===Node.ELEMENT_NODE){const a=n.tagName.toUpperCase();if(a==="BR")return!1;(a==="VAR"||a==="TIME"&&n.hasAttribute("datetime")||D.has(a))&&(t=!0)}return r&&t}function ee(e){let r="";const t=[];for(const n of e.childNodes){if(n.nodeType===Node.TEXT_NODE){const a=N(n.textContent);a&&(r+=a);continue}if(n.nodeType===Node.ELEMENT_NODE){const a=n.tagName.toUpperCase();if(a==="TIME"&&n.hasAttribute("datetime")){const o=t.length;t.push({type:"date",index:o,raw:n.getAttribute("datetime"),display:n.textContent,node:n}),r+=`{{date:${o}}}`;continue}if(a==="VAR"||D.has(a)){const o=N(n.textContent);if(o){const s=t.length,h=Qe(o);t.push({type:h,index:s,tag:a,value:o,node:n}),r+=`{{${h}:${s}}}`}continue}}}return{key:N(r),slots:t}}var te=["title","placeholder","aria-label"];function Oe(e){const r=[],t=new Set;if(e.nodeType===Node.ELEMENT_NODE&&!B(e)&&A(e)){const{key:c,slots:u}=ee(e);if(c&&c.length<=k)if(Z(c))u.forEach(function(d){if(d.type==="text"&&d.value&&d.value.length>=2&&!E(d.value)){var p=L(d.node||e),f=d.value+"\0"+p;t.has(f)||(t.add(f),r.push({type:"text",key:d.value,slots:[],textNode:d.node?d.node.firstChild:null,element:d.node||e,context:p,original:d.value}))}});else{var n=L(e),a=c+"\0"+n;t.has(a)||t.add(a);const d=u.some(p=>p.type==="date")?"mixed-date":u.some(p=>p.type==="text")?"mixed-text":"mixed";r.push({type:d,key:c,slots:u,element:e,context:n,original:c,originalHTML:e.innerHTML})}}const o=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT,{acceptNode(c){var g,m,x;if(c.nodeType===Node.TEXT_NODE){const y=N(c.textContent);if(!y||y.length<2||y.length>k||E(y)||/\{\{(?:text|number|decimal|date):\d+\}\}/.test(y)||Ae(c))return NodeFilter.FILTER_SKIP;const b=(m=(g=c.parentElement)==null?void 0:g.tagName)==null?void 0:m.toUpperCase();if(F.has(b)||A(c.parentElement))return NodeFilter.FILTER_SKIP;for(var u=c.parentElement;u;){var d=(x=u.tagName)==null?void 0:x.toUpperCase();if((d==="VAR"||d==="TIME"||D.has(d))&&u.parentElement&&A(u.parentElement))return NodeFilter.FILTER_SKIP;u=u.parentElement}return NodeFilter.FILTER_ACCEPT}if(c.nodeType===Node.ELEMENT_NODE){const y=c.tagName.toUpperCase();if(F.has(y)||B(c))return NodeFilter.FILTER_REJECT;if(y==="INPUT"){var p=(c.getAttribute("type")||"").toLowerCase();if(p==="button"||p==="submit"||p==="reset"){var f=N(c.value);if(f&&f.length>=2&&!E(f))return NodeFilter.FILTER_ACCEPT}var l=te.some(function(b){var T=N(c.getAttribute(b)||"");return T&&T.length>=2&&!E(T)});return l?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}return A(c)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}return NodeFilter.FILTER_SKIP}});let s;for(;s=o.nextNode();){if(s.nodeType===Node.TEXT_NODE){const c=N(s.textContent);if(!c)continue;var n=L(s.parentElement),a=c+"\0"+n;t.has(a)||t.add(a),r.push({type:"text",key:c,slots:[],textNode:s,element:s.parentElement,context:n,original:c});continue}if(s.nodeType===Node.ELEMENT_NODE&&s.tagName.toUpperCase()==="INPUT"){var h=(s.getAttribute("type")||"").toLowerCase(),n=L(s);if(h==="button"||h==="submit"||h==="reset"){var v=N(s.value);if(v&&v.length>=2&&!E(v)){var a=v+"\0"+n;t.has(a)||t.add(a),r.push({type:"input-value",key:v,slots:[],element:s,context:n,original:v})}}te.forEach(function(u){var d=N(s.getAttribute(u)||"");if(!(!d||d.length<2||E(d))){var p=d+"\0"+n+"\0"+u;t.has(p)||(t.add(p),r.push({type:"input-attr",key:d,attr:u,slots:[],element:s,context:n,original:d}))}});continue}if(s.nodeType===Node.ELEMENT_NODE){const{key:c,slots:u}=ee(s);if(!c||c.length>k)continue;if(Z(c)){u.forEach(function(l){if(l.type==="text"&&l.value&&l.value.length>=2&&!E(l.value)){var g=L(l.node||s),m=l.value+"\0"+g;t.has(m)||(t.add(m),r.push({type:"text",key:l.value,slots:[],textNode:l.node?l.node.firstChild:null,element:l.node||s,context:g,original:l.value}))}});continue}var n=L(s),a=c+"\0"+n;t.has(a)||t.add(a);const f=u.some(l=>l.type==="date")?"mixed-date":u.some(l=>l.type==="text")?"mixed-text":"mixed";r.push({type:f,key:c,slots:u,element:s,context:n,original:c,originalHTML:s.innerHTML})}}return r}async function j(e,r){r||(r=100);const t=[],n=new Set;if(e.nodeType===Node.ELEMENT_NODE&&!B(e)&&A(e)){const{key:f,slots:l}=ee(e);if(f&&f.length<=k)if(Z(f))l.forEach(function(g){if(g.type==="text"&&g.value&&g.value.length>=2&&!E(g.value)){var m=L(g.node||e),x=g.value+"\0"+m;n.has(x)||(n.add(x),t.push({type:"text",key:g.value,slots:[],textNode:g.node?g.node.firstChild:null,element:g.node||e,context:m,original:g.value}))}});else{var a=L(e),o=f+"\0"+a;n.has(o)||n.add(o);const g=l.some(m=>m.type==="date")?"mixed-date":l.some(m=>m.type==="text")?"mixed-text":"mixed";t.push({type:g,key:f,slots:l,element:e,context:a,original:f,originalHTML:e.innerHTML})}}const s=[],h=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT,{acceptNode(f){var b,T,S;if(f.nodeType===Node.TEXT_NODE){const w=N(f.textContent);if(!w||w.length<2||w.length>k||E(w)||/\{\{(?:text|number|decimal|date):\d+\}\}/.test(w)||Ae(f))return NodeFilter.FILTER_SKIP;const K=(T=(b=f.parentElement)==null?void 0:b.tagName)==null?void 0:T.toUpperCase();if(F.has(K)||A(f.parentElement))return NodeFilter.FILTER_SKIP;for(var l=f.parentElement;l;){var g=(S=l.tagName)==null?void 0:S.toUpperCase();if((g==="VAR"||g==="TIME"||D.has(g))&&l.parentElement&&A(l.parentElement))return NodeFilter.FILTER_SKIP;l=l.parentElement}return NodeFilter.FILTER_ACCEPT}if(f.nodeType===Node.ELEMENT_NODE){const w=f.tagName.toUpperCase();if(F.has(w)||B(f))return NodeFilter.FILTER_REJECT;if(w==="INPUT"){var m=(f.getAttribute("type")||"").toLowerCase();if(m==="button"||m==="submit"||m==="reset"){var x=N(f.value);if(x&&x.length>=2&&!E(x))return NodeFilter.FILTER_ACCEPT}var y=te.some(function(K){var O=N(f.getAttribute(K)||"");return O&&O.length>=2&&!E(O)});return y?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}return A(f)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}return NodeFilter.FILTER_SKIP}});for(var v;v=h.nextNode();)s.push(v);for(var c=0;c<s.length;c++){c>0&&c%r===0&&await new Promise(function(f){setTimeout(f,0)});var u=s[c];if(u.nodeType===Node.TEXT_NODE){const f=N(u.textContent);if(!f)continue;var a=L(u.parentElement),o=f+"\0"+a;n.has(o)||n.add(o),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 d=(u.getAttribute("type")||"").toLowerCase(),a=L(u);if(d==="button"||d==="submit"||d==="reset"){var p=N(u.value);if(p&&p.length>=2&&!E(p)){var o=p+"\0"+a;n.has(o)||n.add(o),t.push({type:"input-value",key:p,slots:[],element:u,context:a,original:p})}}te.forEach(function(l){var g=N(u.getAttribute(l)||"");if(!(!g||g.length<2||E(g))){var m=g+"\0"+a+"\0"+l;n.has(m)||(n.add(m),t.push({type:"input-attr",key:g,attr:l,slots:[],element:u,context:a,original:g}))}});continue}if(u.nodeType===Node.ELEMENT_NODE){const{key:f,slots:l}=ee(u);if(!f||f.length>k)continue;if(Z(f)){l.forEach(function(y){if(y.type==="text"&&y.value&&y.value.length>=2&&!E(y.value)){var b=L(y.node||u),T=y.value+"\0"+b;n.has(T)||(n.add(T),t.push({type:"text",key:y.value,slots:[],textNode:y.node?y.node.firstChild:null,element:y.node||u,context:b,original:y.value}))}});continue}var a=L(u),o=f+"\0"+a;n.has(o)||n.add(o);const x=l.some(y=>y.type==="date")?"mixed-date":l.some(y=>y.type==="text")?"mixed-text":"mixed";t.push({type:x,key:f,slots:l,element:u,context:a,original:f,originalHTML:u.innerHTML})}}return t}function ne(e){if(i.scanStopped)return Promise.resolve({ok:!0,registered:0,keyMap:{}});var r=new Set,t=[];return e.forEach(function(n){var a=n.key+"\0"+(n.context||"");r.has(a)||n.varSlots&&n.varSlots.length>0&&/\{\{(?:text|number|decimal|date):\d+\}\}/.test(n.key)||(r.add(a),t.push({key:n.key,context:n.context||""}),n.slots&&n.slots.length>0&&n.slots.forEach(function(o){if(o.type==="text"&&o.value&&!E(o.value)){var s=o.value+"\0";r.has(s)||(r.add(s),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(n){return n.json()})}function qe(e){var r=i.apiBase+"/api/translations?lang="+encodeURIComponent(e);return fetch(r,{headers:{"X-API-Key":i.apiKey}}).then(function(t){return t.json()}).then(function(t){var n={};return Array.isArray(t)?t.forEach(function(a){n[a.key+"\0"+(a.context||"")]=a.value,n.hasOwnProperty(a.key)||(n[a.key]=a.value)}):n=t,n})}function Ge(){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(r){var t=r.toDataURL("image/jpeg",.5),n=t.split(",")[1];!n||n.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:n})}).catch(function(){})}).catch(function(){})},e.onerror=function(){},document.head.appendChild(e)}}function Je(e,r){return e.replace(/\{\{(text|number|decimal|date):(\d+)\}\}/g,(t,n,a)=>{const o=r[parseInt(a)];return o?n==="date"?o.display:o.value:t})}function De(e){if(!Array.isArray(e))return e;var r={};return e.forEach(function(t){r[t.key+"\0"+(t.context||"")]=t.value,r.hasOwnProperty(t.key)||(r[t.key]=t.value)}),r}function ye(e,r){let t=0,n=0;return e.forEach(a=>{const o=a.key+"\0"+(a.context||"");var s=r[o]||r[a.key];if(!s&&a.slots&&a.slots.length>0){var h=a.slots.some(function(d){if(d.type!=="text"||!d.value)return!1;var p=d.value+"\0"+(a.context||""),f=d.value+"\0";return r.hasOwnProperty(p)||r.hasOwnProperty(f)||r.hasOwnProperty(d.value)});h&&(s=a.key)}if(!s){n++;return}if(a.type==="input-value"&&a.element)try{a.element.value=s,t++;return}catch(d){console.warn("[translate] Could not write to input value",d),n++;return}if(a.type==="input-attr"&&a.element&&a.attr)try{a.element.setAttribute(a.attr,s),t++;return}catch(d){console.warn("[translate] Could not write to input attr",d),n++;return}if(a.type==="text"&&a.textNode)try{var v=s;a.varSlots&&a.varSlots.length>0&&(v=v.replace(/\{\{(text|number|decimal|date):(\d+)\}\}/g,function(d,p,f){var l=a.varSlots.find(function(g){return(g.type||"text")===p&&g.index===+f});return l||(l=a.varSlots[+f]),l?l.originalText:d})),v=v.replace(/\{\{(?:text|number|decimal|date):\d+\}\}/g,""),a.textNode.nodeValue=v,t++;return}catch(d){console.warn("[translate] Could not write to text node",d),n++;return}if(a.element){try{const d=Je(s,a.slots);let p=s;var c={};a.slots.forEach(f=>{const l=`{{${f.type}:${f.index}}}`;if(f.type==="date"&&f.node)f.node.textContent=f.display,c[l]=f.node.outerHTML;else if(f.node){if(f.type==="text"&&f.value){var g=f.value+"\0"+(a.context||""),m=f.value+"\0",x=r[g]||r[m]||r[f.value];x&&(f.node.textContent=x)}c[l]=f.node.outerHTML}}),a.varSlots&&a.varSlots.length>0&&a.varSlots.forEach(function(f){var l="{{"+f.type+":"+f.index+"}}";c.hasOwnProperty(l)||(c[l]=Fe(f.originalText))});var u=p.split(/(\{\{(?:text|number|decimal|date):\d+\}\})/g);p=u.map(function(f){return c.hasOwnProperty(f)?c[f]:/^\{\{(?:text|number|decimal|date):\d+\}\}$/.test(f)?"":Fe(f)}).join(""),a.element.innerHTML=p,t++}catch(d){console.warn("[translate] Could not apply mixed translation",d),n++}return}n++}),{applied:t,skipped:n}}async function re(e,r,t){t||(t=100);for(var n=0,a=0,o=0;o<e.length;o+=t){o>0&&await new Promise(function(v){setTimeout(v,0)});var s=e.slice(o,o+t),h=ye(s,r);n+=h.applied,a+=h.skipped}return{applied:n,skipped:a}}function C(e){let r=0;e.forEach(t=>{try{t.type==="input-value"&&t.element?(t.element.value=t.original,r++):t.type==="input-attr"&&t.element&&t.attr?(t.element.setAttribute(t.attr,t.original),r++):t.type==="text"&&t.textNode&&(t.textNode.nodeValue=t.original,r++)}catch(n){console.warn("[translate] Could not restore text node",n)}}),e.forEach(t=>{if(t.type!=="text")try{t.element&&t.originalHTML!==void 0&&(t.element.innerHTML=t.originalHTML,r++)}catch(n){console.warn("[translate] Could not restore node",n)}}),console.log("[loco] untranslated "+r+" phrase(s)")}function ae(e,r){const t=new Set(e),n=[];Object.values(r).forEach(function(l){if(l&&(t.add(l),/\{\{(text|number|decimal|date):\d+\}\}/.test(l))){var g=l.split(/\{\{(?:text|number|decimal|date):\d+\}\}/g),m=g.map(function(x){return x.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")});n.push(new RegExp("^"+m.join(".+")+"$"))}});function a(l){if(t.has(l))return!0;for(var g=0;g<n.length;g++)if(n[g].test(l))return!0;return!1}let o=[],s=null,h=null,v=new Set,c=null,u=!1;function d(){if(o.length!==0){var l=o.splice(0);i.fileMode||ne(l).then(function(g){g&&g.keyMap&&(Y(l,g.keyMap),u=!0,ye(l,r),c&&c.takeRecords(),u=!1)}).catch(function(){})}}function p(l){const g=Oe(l);g.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))}),R(g,Object.keys(r)),u=!0,ye(g,r),c&&c.takeRecords(),u=!1,i.fileMode||(clearTimeout(s),s=setTimeout(d,500))}function f(l){v.add(l),h||(h=requestAnimationFrame(function(){h=null;var g=Array.from(v);v.clear(),g.forEach(function(m){m.isConnected&&p(m)})}))}return c=new MutationObserver(l=>{if(!u){var g=[],m=new Set;for(const y of l)for(const b of y.addedNodes)if(b.nodeType===Node.ELEMENT_NODE)g.push(b);else if(b.nodeType===Node.TEXT_NODE){var x=b.parentElement;x&&x.isConnected&&m.add(x)}g.forEach(function(y){p(y)}),m.forEach(function(y){f(y)})}}),c.observe(document.body,{childList:!0,subtree:!0}),c}var Pe="loco",Ze=2;function X(){return new Promise(function(e,r){try{var t=indexedDB.open(Pe,Ze);t.onupgradeneeded=function(n){var a=n.target.result;a.objectStoreNames.contains("meta")&&n.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(n){e(n.target.result)},t.onerror=function(){r(t.error)}}catch(n){r(n)}})}function ie(){return X().then(function(e){return new Promise(function(r,t){var n=e.transaction("meta","readonly"),a=n.objectStore("meta").get("registry");a.onsuccess=function(){e.close();var o=a.result;r(o?{languages:o.languages||[],languageNames:o.languageNames||{}}:null)},a.onerror=function(){e.close(),t(a.error)}})})}function Ie(e){var r="source:"+e;return X().then(function(t){return new Promise(function(n,a){var o=t.transaction("meta","readonly"),s=o.objectStore("meta").get(r);s.onsuccess=function(){t.close();var h=s.result;n(h?{url:h.url,timestamp:h.timestamp,storedAt:h.storedAt}:null)},s.onerror=function(){t.close(),a(s.error)}})})}function ze(e){return X().then(function(r){return new Promise(function(t,n){var a=r.transaction("translations","readonly"),o=a.objectStore("translations").get(e);o.onsuccess=function(){r.close();var s=o.result;t(s?s.data:null)},o.onerror=function(){r.close(),n(o.error)}})})}function Ye(){return X().then(function(e){return new Promise(function(r,t){var n=e.transaction(["meta","translations"],"readonly"),a=n.objectStore("meta"),o=a.get("registry");o.onsuccess=function(){var s=o.result;if(!s||!s.languages||s.languages.length===0){e.close(),r(null);return}var h=U(),v=h||s.languages[0],c=n.objectStore("translations").get(v);c.onsuccess=function(){e.close();var u=c.result;if(!u||!u.data){r(null);return}var d={};d[v]=u.data,r({languages:s.languages,languageNames:s.languageNames||{},translations:d})},c.onerror=function(){e.close(),t(c.error)}},o.onerror=function(){e.close(),t(o.error)}})})}function oe(e,r,t){var n=r.languages||[],a=r.languageNames||{},o=r.translations||{},s=r.timestamp||0;return X().then(function(h){return new Promise(function(v,c){var u=h.transaction(["meta","translations"],"readwrite"),d=u.objectStore("meta"),p=u.objectStore("translations"),f=d.get("registry");f.onsuccess=function(){var l=f.result,g,m;if(t&&l){var x=l.languages||[];g=x.slice();for(var y=0;y<n.length;y++)g.indexOf(n[y])===-1&&g.push(n[y]);m={};var b=l.languageNames||{},T;for(T in b)m[T]=b[T];for(T in a)m[T]=a[T]}else g=n,m=a;d.put({key:"registry",languages:g,languageNames:m}),d.put({key:"source:"+e,url:e,timestamp:s,storedAt:Date.now()});for(var S=0;S<n.length;S++)o[n[S]]&&(t&&Array.isArray(o[n[S]])?function(w){var K=p.get(w);K.onsuccess=function(){var O=K.result,Q=O&&Array.isArray(O.data)?O.data:null,W=o[w];if(Q){for(var Ke="\0",$={},de=[],V=0;V<Q.length;V++){var be=Q[V].key+Ke+(Q[V].context||"");$.hasOwnProperty(be)||de.push(be),$[be]=Q[V]}for(var q=0;q<W.length;q++){var Te=W[q].key+Ke+(W[q].context||"");$.hasOwnProperty(Te)||de.push(Te),$[Te]=W[q]}for(var Ue=[],Ne=0;Ne<de.length;Ne++)Ue.push($[de[Ne]]);p.put({lang:w,data:Ue})}else p.put({lang:w,data:W})}}(n[S]):p.put({lang:n[S],data:o[n[S]]}))},u.oncomplete=function(){h.close(),v()},u.onerror=function(){h.close(),c(u.error)}})})}function et(){return new Promise(function(e){var r=indexedDB.deleteDatabase(Pe);r.onsuccess=function(){e()},r.onerror=function(){e()},r.onblocked=function(){e()}})}var tt='<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>',xe=null;function se(e,r){xe=r;var t=document.getElementById("loco-lang-widget");t&&t.remove();var n={},a=e.map(function(l){return typeof l=="object"&&l.code?(l.name&&(n[l.code]=l.name),l.code):l});function o(l){return n[l]||l}var s=U()||null,h=document.createElement("div");h.id="loco-lang-widget",h.setAttribute("data-notranslate","");var v={"bottom-right":"bottom:20px;right:20px;","bottom-left":"bottom:20px;left:20px;","top-right":"top:20px;right:20px;","top-left":"top:20px;left:20px;"};h.style.cssText='position:fixed;z-index:2147483647;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;font-size:14px;'+(v[r]||v["bottom-right"]);var c=document.createElement("button");c.innerHTML=tt,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;"+(r.indexOf("bottom")===0?"bottom:56px;":"top:56px;")+(r.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 d=document.createElement("div");d.textContent="Original",d.style.cssText="padding:10px 16px;cursor:pointer;color:#333;transition:background 0.15s;font-weight:600;border-bottom:1px solid #eee;",d.onmouseenter=function(){d.style.background="#f5f5f5"},d.onmouseleave=function(){d.style.background="transparent"},d.onclick=function(){s=null,window.Loco.restore(),f(),u.style.display="none"},u.appendChild(d);var p=[];a.forEach(function(l){var g=document.createElement("div");g.textContent=o(l),g.setAttribute("data-lang",l),g.style.cssText="padding:10px 16px;cursor:pointer;color:#333;transition:background 0.15s;",g.onmouseenter=function(){g.style.background="#f5f5f5"},g.onmouseleave=function(){g.style.background=s===l?"#e8f0fe":"transparent"},g.onclick=function(){s=l,window.Loco.apply(l),f(),u.style.display="none"},u.appendChild(g),p.push({el:g,code:l})});function f(){d.style.background=s===null?"#e8f0fe":"transparent",d.style.fontWeight=s===null?"600":"400",p.forEach(function(l){l.el.style.background=s===l.code?"#e8f0fe":"transparent",l.el.style.fontWeight=s===l.code?"600":"400"})}c.onclick=function(l){l.stopPropagation(),u.style.display=u.style.display==="none"?"block":"none"},document.addEventListener("click",function(l){h.contains(l.target)||(u.style.display="none")}),f(),h.appendChild(u),h.appendChild(c),document.body.appendChild(h)}function nt(e){xe&&(!e||e.length===0||se(e,xe))}var _={__proto__:1,constructor:1,prototype:1};function Re(e){if(!e||typeof e!="string")return!1;if(e.charAt(0)==="/"||e.charAt(0)===".")return!0;try{var r=new URL(e,window.location.origin);return r.protocol==="http:"||r.protocol==="https:"}catch{return!1}}function le(e){if(!e||typeof e!="object"||Array.isArray(e))return null;if(Array.isArray(e._raw)){for(var r={},t={},n=0;n<e._raw.length;n++){var a=e._raw[n];!a||typeof a.l!="string"||typeof a.k!="string"||typeof a.v!="string"||(r[a.l]||(r[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(r).sort(),languageNames:{},translations:t,timestamp:0}}var o={};if(!Array.isArray(e.languages))return null;o.languages=[];for(var s=0;s<e.languages.length;s++){if(typeof e.languages[s]!="string"||e.languages[s].length>20)return null;o.languages.push(e.languages[s])}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 h in e.languageNames)!e.languageNames.hasOwnProperty(h)||_[h]||typeof e.languageNames[h]=="string"&&e.languageNames[h].length<=100&&(o.languageNames[h]=e.languageNames[h]);if(o.translations={},e.translations&&typeof e.translations=="object"&&!Array.isArray(e.translations)){for(var v in e.translations)if(!(!e.translations.hasOwnProperty(v)||_[v])&&o.languages.indexOf(v)!==-1){var c=e.translations[v];if(Array.isArray(c)){for(var u=[],d=0;d<c.length;d++){var p=c[d];!p||typeof p!="object"||typeof p.key!="string"||typeof p.value!="string"||p.key.length>G||p.value.length>G||_[p.key]||u.push({key:p.key,value:p.value,context:typeof p.context=="string"?p.context:""})}o.translations[v]=u}else if(typeof c=="object"){var f={};for(var l in c)!c.hasOwnProperty(l)||_[l]||typeof c[l]=="string"&&(l.length>G||c[l].length>G||(f[l]=c[l]));o.translations[v]=f}}}return o}async function _e(){try{var e=await fetch(i.apiBase+"/api/project/crawler-config",{headers:{"X-API-Key":i.apiKey}});e.ok&&Be(await e.json())}catch{}Ce(),i.phrases=await j(document.body),ne(i.phrases).then(function(t){t&&t.keyMap&&Y(i.phrases,t.keyMap)}).catch(function(t){console.warn("[loco] Failed to register keys:",t)}),!i.scanStopped&&i.screenshotsEnabled&&setTimeout(Ge,3e3),console.log("[loco] "+i.phrases.length+" text nodes discovered"),console.log(` Loco.textnodes() — list all discovered text nodes
2
+ Loco.apply("zh-Hans") — apply translations for a language
3
+ Loco.restore() — revert to original text
4
+ Loco.rescan() — re-scan DOM for new nodes`);var r=U();r?M.apply(r):i.observer=ae(i.phrases.map(function(t){return t.key+"\0"+(t.context||"")}),{})}function rt(e,r){for(var t="\0",n={},a=[],o=0;o<e.length;o++){var s=e[o],h=s.key+t+(s.context||"");n.hasOwnProperty(h)||a.push(h),n[h]=s}for(var v=0;v<r.length;v++){var c=r[v],u=c.key+t+(c.context||"");n.hasOwnProperty(u)||a.push(u),n[u]=c}for(var d=[],p=0;p<a.length;p++)d.push(n[a[p]]);return d}async function ce(e){i.screenshotsEnabled=!1,Ce(),i.phrases=await j(document.body);var r=[],t=i.fileData.translations||{},n=(i.fileData.languages||[])[0];n&&t[n]&&(t[n]=De(t[n]),r=Object.keys(t[n]));var a=R(i.phrases,r),o=a?Object.keys(a).length:0,s=(i.fileData.languages||[]).length;console.log("[loco] (file mode) "+i.phrases.length+" text nodes discovered, "+s+" language(s) available"+(o?", "+o+" var-remapped":"")+" ["+e+"]"),console.log(" Languages: "+(i.fileData.languages||[]).join(", "));var h=U();h?M.apply(h):i.observer=ae(i.phrases.map(function(v){return v.key+"\0"+(v.context||"")}),{})}async function Me(e){try{indexedDB.deleteDatabase("loco-translations")}catch{}try{indexedDB.deleteDatabase("loco-meta")}catch{}try{indexedDB.databases&&indexedDB.databases().then(function(t){t.forEach(function(n){if(n.name&&n.name.indexOf("loco-tr-")===0)try{indexedDB.deleteDatabase(n.name)}catch{}})}).catch(function(){})}catch{}i.fileUrls=e;var r=null;try{r=await Ye()}catch{}r&&r.translations?(i.fileData={languages:r.languages,languageNames:r.languageNames||{},translations:r.translations,timestamp:0},i.loadedFromCache=!0,await ce("cache"),i.fileReadyResolve&&(i.fileReadyResolve(),i.fileReadyResolve=null),it(e)):(await at(e),await ce("network"),i.fileReadyResolve&&(i.fileReadyResolve(),i.fileReadyResolve=null))}async function at(e){for(var r=e.map(function(v){return fetch(v).then(function(c){if(!c.ok)throw new Error("HTTP "+c.status+" for "+v);return c.text()}).then(function(c){if(!c||!c.trim())return null;var u;try{u=JSON.parse(c)}catch{return null}var d=le(u);return d?{url:v,data:d}:(console.warn("[loco] File rejected (invalid schema): "+v),null)}).catch(function(c){return console.warn("[loco] Failed to load "+v+":",c),null})}),t=await Promise.all(r),n=!0,a=0;a<t.length;a++)if(t[a]){var o=t[a].url,s=t[a].data,h=!n||(s.languages||[]).length===1;ue(s,n),n=!1;try{await oe(o,s,h)}catch{}}i.loadedFromCache=!1}function ue(e,r){if(!i.fileData||r){i.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||[],n=0;n<t.length;n++)i.fileData.languages.indexOf(t[n])===-1&&i.fileData.languages.push(t[n]);var a=e.languageNames||{};i.fileData.languageNames||(i.fileData.languageNames={});for(var o in a)!a.hasOwnProperty(o)||_[o]||(i.fileData.languageNames[o]=a[o]);var s=e.translations||{};i.fileData.translations||(i.fileData.translations={});for(var h in s)if(!(!s.hasOwnProperty(h)||_[h])){var v=i.fileData.translations[h],c=s[h];!v||!Array.isArray(v)||!Array.isArray(c)?i.fileData.translations[h]=c:i.fileData.translations[h]=rt(v,c)}e.timestamp&&e.timestamp>i.fileData.timestamp&&(i.fileData.timestamp=e.timestamp)}function it(e){var r=e.map(function(t){return Promise.all([Ie(t).catch(function(){return null}),fetch(t).then(function(n){return n.ok?n.text():null}).catch(function(){return null})]).then(function(n){var a=n[0],o=n[1];if(!o||!o.trim())return null;var s;try{s=JSON.parse(o)}catch{return null}if(s=le(s),!s)return null;var h=s.timestamp||0,v=a&&a.timestamp||0;if(h!==v){var c=e.length>1||(s.languages||[]).length===1;return oe(t,s,c).catch(function(){}),s}return null})});Promise.all(r).then(function(t){for(var n=!1,a=0;a<t.length;a++)t[a]&&(ue(t[a],!1),n=!0);n&&(i.loadedFromCache=!1,i.observer&&(i.observer.disconnect(),i.observer=null),C(i.phrases),ce("network — updated").then(function(){Ee()}),console.log("[loco] translations refreshed from file(s) (timestamp changed)"))}).catch(function(){console.log("[loco] using cached translations (network unavailable)")})}function Ee(){i.widgetPosition&&ie().then(function(e){if(e){var r=fe(e.languages,e.languageNames);nt(r)}}).catch(function(){})}function fe(e,r){return e=e||[],r=r||{},e.map(function(t){return r[t]?{code:t,name:r[t]}:t})}var M={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(n){i.fileReadyResolve=n});for(var r=e.files?e.files.slice():[e.file],t=0;t<r.length;t++)if(!Re(r[t])){console.warn("[loco] Blocked unsafe URL: "+r[t]);return}i.fileUrl=r[0],document.readyState==="loading"?document.addEventListener("DOMContentLoaded",function(){Me(r)}):Me(r);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",_e):_e()},apply:async function(e){if(!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 r=await ze(e);if(!r||Object.keys(r).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]=r,i.fileData.languages.indexOf(e)===-1&&i.fileData.languages.push(e),M.apply(e)}catch(o){console.warn('[loco] Failed to load translations for "'+e+'" from cache:',o);return}i.observer&&(i.observer.disconnect(),i.observer=null),C(i.phrases),i.translations=De(i.fileData.translations[e]),i.fileData.translations[e]=i.translations,i.phrases=await j(document.body);var t=Object.keys(i.translations);R(i.phrases,t);var n=await re(i.phrases,i.translations);return i.observer=ae(i.phrases.map(function(o){return o.key+"\0"+(o.context||"")}),i.translations),J(e),console.log("[loco] (file) applied "+n.applied+" translation(s), "+n.skipped+" pending"),n}if(!i.apiKey||!i.apiBase){console.warn("[loco] Call Loco.init() first");return}i.observer&&(i.observer.disconnect(),i.observer=null),C(i.phrases);try{var a=await qe(e);i.translations=a||{},i.phrases=await j(document.body),R(i.phrases,Object.keys(i.translations)),ne(i.phrases).then(function(s){s&&s.keyMap&&(Y(i.phrases,s.keyMap),re(i.phrases,i.translations))}).catch(function(){});var n=await re(i.phrases,i.translations);return i.observer=ae(i.phrases.map(function(s){return s.key+"\0"+(s.context||"")}),i.translations),J(e),console.log("[loco] applied "+n.applied+" translation(s), "+n.skipped+" pending"),n}catch(o){console.warn("[loco] Failed to fetch translations:",o)}},restore:function(){C(i.phrases),i.observer&&i.observer.disconnect(),J(null)},rescan:async function(){var e=Object.keys(i.translations).length>0;e&&C(i.phrases),i.phrases=await j(document.body),i.fileMode||ne(i.phrases).catch(function(){}),e&&(R(i.phrases,Object.keys(i.translations)),await re(i.phrases,i.translations))},textnodes:function(){return i.phrases.map(function(e){return{key:e.key,context:e.context||"",element:e.element}})},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 r=i.fileData?i.fileData.languages||[]:[],t=i.fileData&&i.fileData.languageNames||{};return r.map(function(n){return{code:n,name:t[n]||n}})};return!i.fileData&&i.fileReady?i.fileReady.then(function(){return ie().then(function(r){return r&&r.languages&&r.languages.length>0?fe(r.languages,r.languageNames):e()}).catch(function(){return e()})}):ie().then(function(r){return r&&r.languages&&r.languages.length>0?fe(r.languages,r.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(r){return r.json()}).then(function(r){return Array.isArray(r)?r:[]}).catch(function(){return[]})},widget:function(e){e=e||{};var r=e.position||"bottom-right";if(i.widgetPosition=r,i.fileMode){let t=function(){ie().then(function(a){var o;if(a&&a.languages&&a.languages.length>0?o=fe(a.languages,a.languageNames):o=n(),o.length===0){console.warn("[loco] No languages found in translation file or cache");return}se(o,r)}).catch(function(){var a=n();if(a.length===0){console.warn("[loco] No languages found in translation file");return}se(a,r)})},n=function(){var a=i.fileData?i.fileData.languages||[]:[],o=i.fileData&&i.fileData.languageNames||{};return a.map(function(s){return o[s]?{code:s,name:o[s]}:s})};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}se(t,r)}).catch(function(t){console.warn("[loco] Failed to fetch languages:",t)})},clearCache:function(){return i.fileMode?et().then(function(){i.fileData&&(i.fileData.translations={},i.fileData.timestamp=0),i.loadedFromCache=!1,J(null),C(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?Re(e)?(i.fileUrls.indexOf(e)===-1&&i.fileUrls.push(e),fetch(e).then(function(r){if(!r.ok)throw new Error("HTTP "+r.status);return r.text()}).then(function(r){if(!r||!r.trim())throw new Error("Empty file");var t;try{t=JSON.parse(r)}catch{throw new Error("Invalid JSON")}if(t=le(t),!t)throw new Error("Invalid file schema");var n=!i.fileData||!i.fileData.languages||i.fileData.languages.length===0,a=!n||(t.languages||[]).length===1;return ue(t,n),oe(e,t,a).catch(function(){}),Ee(),console.log("[loco] added file: "+e+" ("+(t.languages||[]).join(", ")+")"),{status:"added",languages:t.languages||[]}}).catch(function(r){return console.warn("[loco] addFile() failed:",r),{status:"error",reason:r.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 r=e.map(function(t){return Promise.all([Ie(t).catch(function(){return null}),fetch(t).then(function(n){if(!n.ok)throw new Error("HTTP "+n.status);return n.text()})]).then(function(n){var a=n[0],o=n[1];if(!o||!o.trim())return{url:t,status:"current",reason:"empty"};var s;try{s=JSON.parse(o)}catch{throw new Error("Invalid JSON in "+t)}if(s=le(s),!s)throw new Error("Invalid file schema in "+t);var h=s.timestamp||0,v=a&&a.timestamp||0;if(h===v&&v!==0){var c=i.fileData&&i.fileData.translations,u=s.languages||[],d=!c||u.some(function(l){return!i.fileData.translations[l]});if(!d)return{url:t,status:"current",timestamp:v}}var p=!i.fileData||!i.fileData.languages||i.fileData.languages.length===0,f=!p||(s.languages||[]).length===1;return ue(s,p),oe(t,s,f).catch(function(){}),{url:t,status:"updated",timestamp:h,previousTimestamp:v}}).catch(function(n){return{url:t,status:"error",reason:n.message}})});return Promise.all(r).then(async function(t){var n=t.some(function(u){return u.status==="updated"});if(n){i.loadedFromCache=!1;var a=U();if(a)i.observer&&(i.observer.disconnect(),i.observer=null),C(i.phrases),await ce("pullLatest");else{i.phrases=Oe(document.body);var o=i.fileData.translations||{},s=(i.fileData.languages||[])[0];s&&o[s]&&R(i.phrases,Object.keys(o[s]))}Ee()}if(t.length===1){var h=t[0];return console.log("[loco] pullLatest: "+h.status+(h.timestamp?" (timestamp: "+h.timestamp+")":"")),h}var v=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: "+v.length+" updated, "+c.length+" current"),{status:n?"updated":"current",results:t}}).catch(function(t){return console.warn("[loco] pullLatest() failed:",t),{status:"error",reason:t.message}})}};return window.Loco=M,Object.defineProperty(M,"_state",{value:i,writable:!1,enumerable:!1,configurable:!1}),M}();