vite-plugin-ai-auto-i18n 0.4.2 → 0.5.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 (2) hide show
  1. package/dist/index.js +3 -3
  2. package/package.json +3 -7
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import{a as e,c as t,d as n,f as r,h as i,i as a,l as o,m as s,n as c,o as l,p as u,r as d,s as f,u as p}from"./registry-Cj5gJsxW.js";import{n as m,t as h}from"./resolve-ELDMKdoA.js";import{glob as g}from"tinyglobby";import{readFile as _,rm as v}from"node:fs/promises";import y from"node:path";import{createHash as b}from"node:crypto";import{parse as x}from"@babel/parser";import S from"@babel/traverse";import*as C from"@babel/types";import w from"@babel/generator";async function T(e,t,n){let r=Array(e.length),i=0;return await Promise.all(Array.from({length:Math.min(Math.max(1,t),e.length)},async()=>{for(;i<e.length;){let t=i++;try{r[t]={status:`fulfilled`,value:await n(e[t])}}catch(e){r[t]={status:`rejected`,reason:e}}}})),r}const E=`\\{([^{}]+)\\}`,D=RegExp(E,`g`);function O(e){return[...e.matchAll(D)].map(e=>e[1])}function k(e,t){let n=new Set(e),r=new Set(t);return n.size===r.size&&[...n].every(e=>r.has(e))}function A(e,t){return e.trim()!==``&&k(O(e),t)}var j=class extends Error{partial;failed;constructor(e,t,n){super(e),this.partial=t,this.failed=n,this.name=`PartialTranslationError`}};async function M(e){let{provider:n,sourceLocale:r,locale:a,requests:o,previous:s,debug:c}=e,l=new Set(o.map(e=>e.id)),u=t(s.messages,l).catalog,d=t(s.sources,l).catalog,f=o.filter(e=>u[e.id]===void 0||d[e.id]!==e.source),p={},m=0,h;if(f.length&&n){if(c)for(let e of f)i(`sent ${r} -> ${a} ${e.id}: ${JSON.stringify(e.source)} (context: ${e.context})`);try{p=await n.translate({sourceLocale:r,targetLocale:a,messages:f})}catch(e){if(!(e instanceof j))throw e;p=e.partial,m=e.failed,h=e.message}if(c)for(let e of f){let t=p[e.id];i(`received ${r} -> ${a} ${e.id}: ${typeof t==`string`?JSON.stringify(t):`(no translation)`}`)}}let g={...u},_={...d},v=0;for(let e of f){delete g[e.id],delete _[e.id];let t=p[e.id];typeof t==`string`&&t.trim()&&(e.kind===`mixed`&&!A(t,e.placeholders??[])?v++:(g[e.id]=t,_[e.id]=e.source))}let y=o.filter(e=>g[e.id]===void 0).length;return{file:{messages:g,sources:_},untranslated:y,rejected:v,requested:f.length,failed:m,failure:h}}async function N(e){let t=structuredClone(e.registry),{ambiguous:n,messages:r}=a(t,e.files.flatMap(e=>e.messages)),i=d(t,e.orphanRetentionMinutes),o={};for(let e of r)o[e.id]=e.source;let s=r.map(e=>({id:e.id,source:e.source,context:`${e.component} > ${e.context}`,kind:e.kind,placeholders:e.placeholders})),c=await T(e.locales,e.localeConcurrency,t=>M({provider:e.provider,sourceLocale:e.sourceLocale,locale:t,requests:s,previous:e.previous.get(t)??l(),debug:e.debug})),u=/* @__PURE__ */ new Map,f=/* @__PURE__ */ new Map;return c.forEach((t,n)=>{let r=e.locales[n];t.status===`fulfilled`?u.set(r,t.value):f.set(r,t.reason)}),{registry:t,ambiguous:n,pruned:i,messages:r,sourceFile:{messages:o,sources:{}},locales:u,failures:f}}function P(e){return e.replace(/\s+/g,` `).trim()}function F(e){let t=[P(e.source),e.kind,e.tag.toLowerCase(),e.attribute??``,e.context].join(``);return b(`sha256`).update(t).digest(`hex`).slice(0,24)}const I=S.default??S,ee=/^[A-Z]/,L=/* @__PURE__ */ new Set([`script`,`style`,`code`,`pre`]),R=/* @__PURE__ */ new Set([`alt`,`title`,`placeholder`,`label`,`summary`,`aria-label`,`aria-description`,`aria-placeholder`,`aria-roledescription`,`aria-valuetext`]);function z(e){return e.attributes.some(e=>C.isJSXAttribute(e)&&C.isJSXIdentifier(e.name,{name:`translate`})&&C.isStringLiteral(e.value,{value:`no`}))}function B(e){return C.isJSXIdentifier(e)&&!ee.test(e.name)&&!L.has(e.name)}function V(e){if(C.isIdentifier(e))return e.name;if(C.isMemberExpression(e)&&!e.computed&&C.isIdentifier(e.property)){let t=V(e.object);return t?`${t}.${e.property.name}`:void 0}}function H(e,t){let n=x(e,{sourceType:`unambiguous`,sourceFilename:t,plugins:[`jsx`,`typescript`,`decorators-legacy`]}),r=[];function i(e){let t=e.findParent(e=>e.isFunctionDeclaration()||e.isFunctionExpression()||e.isArrowFunctionExpression());if(!t)return`<module>`;let n=t.parentPath;return n?.isVariableDeclarator()&&C.isIdentifier(n.node.id)?n.node.id.name:t.isFunctionDeclaration()&&t.node.id?t.node.id.name:`<anonymous>`}function a(e,t,n){let r=C.isJSXElement(e)?e.openingElement:e,i=r.attributes.filter(e=>C.isJSXAttribute(e)&&C.isJSXIdentifier(e.name)&&[`aria-label`,`title`,`name`,`type`,`role`].includes(e.name.name)).map(e=>`${e.name.name}=${C.isStringLiteral(e.value)?e.value.value:`{expr}`}`).sort().join(`;`),a=r.attributes.filter(e=>C.isJSXAttribute(e)&&C.isJSXIdentifier(e.name)&&/^on[A-Z]/.test(e.name.name)).map(e=>{let t=C.isJSXExpressionContainer(e.value)?e.value.expression:null,n=t&&C.isIdentifier(t)?t.name:t?.type??`handler`;return`${e.name.name}=${n}`}).sort().join(`,`);return[t,n??``,i,a].filter(Boolean).join(` | `)}function o(e){for(let t=e;t;t=t.parentPath){let e=t.isJSXOpeningElement()?t.node:t.isJSXElement()?t.node.openingElement:void 0;if(e&&z(e))return!0}return!1}return I(n,{JSXElement(e){if(o(e))return;let n=e.node.children,s=n.filter(e=>C.isJSXExpressionContainer(e));if(!s.length||n.some(e=>!C.isJSXText(e)&&!C.isJSXExpressionContainer(e))||!s.every(e=>V(e.expression)!==void 0)||!n.some(e=>C.isJSXText(e)&&/[A-Za-z]/.test(e.value)))return;let c=e.node.openingElement.name;if(!B(c))return;let l=[];for(let e of s){let t=V(e.expression),n=t;for(let e=2;l.includes(n);e++)n=`${t}_${e}`;l.push(n)}let u=``,d=0;for(let e of n)u+=C.isJSXText(e)?e.value:`{${l[d++]}}`;let f=P(u);if(!f)return;let p=c.name,m={source:f,prefix:u.match(/^\s*/)?.[0]??``,suffix:u.match(/\s*$/)?.[0]??``,kind:`mixed`,placeholders:l,file:t,start:e.node.start??0,end:e.node.end??0,tag:p,component:i(e),context:a(e.node,p),fingerprint:``};m.fingerprint=F(m),r.push(m)},JSXText(e){if(o(e))return;let n=e.node.value,s=P(n);if(!s)return;let c=e.findParent(e=>e.isJSXElement());if(!c?.isJSXElement()||c.node.children.some(e=>C.isJSXExpressionContainer(e)))return;let l=c.node.openingElement.name;if(!B(l))return;let u=l.name,d=i(c),f=a(c.node,u),p={source:s,prefix:n.match(/^\s*/)?.[0]??``,suffix:n.match(/\s*$/)?.[0]??``,kind:`text`,file:t,start:e.node.start??0,end:e.node.end??0,tag:u,component:d,context:f,fingerprint:``};p.fingerprint=F(p),r.push(p)},JSXAttribute(e){let n=e.node;if(!C.isJSXIdentifier(n.name)||!R.has(n.name.name)||o(e)||!C.isStringLiteral(n.value))return;let s=P(n.value.value);if(!s||!/[A-Za-z]/.test(s))return;let c=e.parentPath;if(!c.isJSXOpeningElement()||!B(c.node.name))return;let l=c.node.name.name,u=e.findParent(e=>e.isJSXElement());if(!u?.isJSXElement())return;let d=i(u),f=a(u.node,l,n.name.name),p={source:s,kind:`attribute`,file:t,start:n.value.start??0,end:n.value.end??0,tag:l,component:d,attribute:n.name.name,context:f,fingerprint:``};p.fingerprint=F(p),r.push(p)},StringLiteral(e){if(e.parentPath.isJSXAttribute()||!e.node.leadingComments?.some(e=>e.type===`CommentBlock`&&e.value.trim()===`i18n`))return;let n=P(e.node.value);if(!n||!/[A-Za-z]/.test(n))return;let a={source:n,kind:`string`,file:t,start:e.node.start??0,end:e.node.end??0,tag:``,component:i(e),context:``,fingerprint:``};a.fingerprint=F(a),r.push(a)}}),r.sort((e,t)=>e.start-t.start)}const U=S.default??S,W=w.default??w,G=`virtual:autoi18n`,K=`__autoI18nT`,q=`__autoI18nFormat`;function J(e,t,n,r,i,a=!1,o=`en`){let s=x(e,{sourceType:`unambiguous`,sourceFilename:t,plugins:[`jsx`,`typescript`,`decorators-legacy`]}),c=new Map(n.map(e=>[e.start,e])),l=!1,u=!1,d=e=>r===o?e.source:i[e.id]??e.source,f=e=>a?(l=!0,C.callExpression(C.identifier(K),[C.stringLiteral(e.id),C.stringLiteral(e.source)])):C.stringLiteral(d(e));U(s,{JSXElement(e){let t=c.get(e.node.start??-1);if(t?.kind!==`mixed`)return;let n=t.placeholders??[],r=e.node.children.filter(e=>C.isJSXExpressionContainer(e)).map(e=>e.expression),i=t.prefix??``,o=t.suffix??``;if(a){u=!0;let a=C.objectExpression(n.map((e,t)=>C.objectProperty(C.stringLiteral(e),C.cloneNode(r[t])))),s=[i&&C.stringLiteral(i),f(t),o&&C.stringLiteral(o)].filter(Boolean).reduce((e,t)=>C.binaryExpression(`+`,e,t));e.node.children=[C.jsxExpressionContainer(C.callExpression(C.identifier(q),[s,a]))];return}let s=d(t),l=A(s,n)?s:t.source,p=[],m=0,h=e=>{e&&p.push(C.jsxExpressionContainer(C.stringLiteral(e)))};h(i);for(let e of l.matchAll(D))h(l.slice(m,e.index)),p.push(C.jsxExpressionContainer(C.cloneNode(r[n.indexOf(e[1])]))),m=e.index+e[0].length;h(l.slice(m)+o),e.node.children=p},JSXText(e){let t=c.get(e.node.start??-1);if(!t)return;let n=[];a?(t.prefix&&n.push(C.stringLiteral(t.prefix)),n.push(f(t)),t.suffix&&n.push(C.stringLiteral(t.suffix))):n.push(C.stringLiteral(`${t.prefix??``}${d(t)}${t.suffix??``}`));let r=n.reduce((e,t)=>C.binaryExpression(`+`,e,t));e.replaceWith(C.jsxExpressionContainer(r))},JSXAttribute(e){let t=e.node.value;if(!C.isStringLiteral(t))return;let n=c.get(t.start??-1);n&&(e.node.value=a?C.jsxExpressionContainer(f(n)):f(n))},StringLiteral(e){let t=c.get(e.node.start??-1);t?.kind===`string`&&e.replaceWith(f(t))}});let p=[...l?[C.importSpecifier(C.identifier(K),C.identifier(`t`))]:[],...u?[C.importSpecifier(C.identifier(q),C.identifier(`format`))]:[]];p.length&&s.program.body.unshift(C.importDeclaration(p,C.stringLiteral(G)));let m=W(s,{sourceMaps:!0,sourceFileName:t},e);return{code:m.code,map:m.map}}function te(e,t,n){let r=[],i=0;for(let a of e.matchAll(n)){if(!Object.hasOwn(t,a[1]))continue;let n=a.index??0;n>i&&r.push(e.slice(i,n)),r.push(t[a[1]]),i=n+a[0].length}return i<e.length&&r.push(e.slice(i)),r}function ne(e,t){return[`const loaders = {\n${Object.entries(e).map(([e,t])=>` ${JSON.stringify(e)}: () => import(${JSON.stringify(t)}).then(m => (m.default ?? m).messages)`).join(`,
2
- `)}\n};`,`const sourceLocale = ${JSON.stringify(t)};`,`const resolveLocale = ${h.toString()};`,`const createLocaleLoader = ${m.toString()};`,`const formatPlaceholders = ${te.toString()};`,`const PLACEHOLDER = new RegExp(${JSON.stringify(E)}, "g");`,`const loadLocale = createLocaleLoader(loaders, sourceLocale);`,`const listeners = new Set();`,`let currentLocale = sourceLocale;`,`let messages = {};`,`let version = 0;`,`let latestRequest = 0;`,`export const locales = Object.keys(loaders);`,`export function getLocale() { return currentLocale; }`,`export function getVersion() { return version; }`,`export function resolveSupported(preferred) { return resolveLocale(preferred, locales, sourceLocale); }`,`export async function setLocale(locale) {`,` const request = ++latestRequest;`,` let selected = loaders[locale] ? locale : sourceLocale;`,` let catalog;`,` try {`,` catalog = await loadLocale(selected);`,` } catch (error) {`,` if (selected === sourceLocale) throw error;`,` console.warn('autoi18n: could not load "' + selected + '", falling back to "' + sourceLocale + '".', error);`,` selected = sourceLocale;`,` catalog = await loadLocale(selected);`,` }`,` // A slower earlier request must not overwrite the locale the user picked last.`,` if (request !== latestRequest) return;`,` messages = catalog;`,` currentLocale = selected;`,` notify();`,`}`,`function notify() {`,` version++;`,` listeners.forEach(fn => fn(currentLocale));`,`}`,`export function subscribe(fn) { listeners.add(fn); return () => { listeners.delete(fn); }; }`,`export function t(id, source) { return messages[id] ?? source; }`,`export function format(text, values) { return formatPlaceholders(text, values, PLACEHOLDER); }`,`// Dev server pushes fresh catalogues after a source change; no page reload is needed.`,`if (import.meta.hot) {`,` import.meta.hot.on("autoi18n:update", data => {`,` for (const [locale, catalog] of Object.entries(data.catalogs)) loadLocale.prime(locale, catalog);`,` if (data.catalogs[currentLocale]) messages = data.catalogs[currentLocale];`,` notify();`,` });`,`}`].join(`
1
+ import{a as e,c as t,d as n,f as r,h as i,i as a,l as o,m as s,n as c,o as l,p as u,r as d,s as f,u as p}from"./registry-Cj5gJsxW.js";import{n as m,t as h}from"./resolve-ELDMKdoA.js";import{glob as g}from"tinyglobby";import{readFile as _,rm as v}from"node:fs/promises";import y from"node:path";import{createHash as b}from"node:crypto";import{parseSync as x}from"oxc-parser";import S from"magic-string";async function C(e,t,n){let r=Array(e.length),i=0;return await Promise.all(Array.from({length:Math.min(Math.max(1,t),e.length)},async()=>{for(;i<e.length;){let t=i++;try{r[t]={status:`fulfilled`,value:await n(e[t])}}catch(e){r[t]={status:`rejected`,reason:e}}}})),r}const w=`\\{([^{}]+)\\}`,T=RegExp(w,`g`);function E(e){return[...e.matchAll(T)].map(e=>e[1])}function D(e,t){let n=new Set(e),r=new Set(t);return n.size===r.size&&[...n].every(e=>r.has(e))}function O(e,t){return e.trim()!==``&&D(E(e),t)}var k=class extends Error{partial;failed;constructor(e,t,n){super(e),this.partial=t,this.failed=n,this.name=`PartialTranslationError`}};async function A(e){let{provider:n,sourceLocale:r,locale:a,requests:o,previous:s,debug:c}=e,l=new Set(o.map(e=>e.id)),u=t(s.messages,l).catalog,d=t(s.sources,l).catalog,f=o.filter(e=>u[e.id]===void 0||d[e.id]!==e.source),p={},m=0,h;if(f.length&&n){if(c)for(let e of f)i(`sent ${r} -> ${a} ${e.id}: ${JSON.stringify(e.source)} (context: ${e.context})`);try{p=await n.translate({sourceLocale:r,targetLocale:a,messages:f})}catch(e){if(!(e instanceof k))throw e;p=e.partial,m=e.failed,h=e.message}if(c)for(let e of f){let t=p[e.id];i(`received ${r} -> ${a} ${e.id}: ${typeof t==`string`?JSON.stringify(t):`(no translation)`}`)}}let g={...u},_={...d},v=0;for(let e of f){delete g[e.id],delete _[e.id];let t=p[e.id];typeof t==`string`&&t.trim()&&(e.kind===`mixed`&&!O(t,e.placeholders??[])?v++:(g[e.id]=t,_[e.id]=e.source))}let y=o.filter(e=>g[e.id]===void 0).length;return{file:{messages:g,sources:_},untranslated:y,rejected:v,requested:f.length,failed:m,failure:h}}async function ee(e){let t=structuredClone(e.registry),{ambiguous:n,messages:r}=a(t,e.files.flatMap(e=>e.messages)),i=d(t,e.orphanRetentionMinutes),o={};for(let e of r)o[e.id]=e.source;let s=r.map(e=>({id:e.id,source:e.source,context:`${e.component} > ${e.context}`,kind:e.kind,placeholders:e.placeholders})),c=await C(e.locales,e.localeConcurrency,t=>A({provider:e.provider,sourceLocale:e.sourceLocale,locale:t,requests:s,previous:e.previous.get(t)??l(),debug:e.debug})),u=/* @__PURE__ */ new Map,f=/* @__PURE__ */ new Map;return c.forEach((t,n)=>{let r=e.locales[n];t.status===`fulfilled`?u.set(r,t.value):f.set(r,t.reason)}),{registry:t,ambiguous:n,pruned:i,messages:r,sourceFile:{messages:o,sources:{}},locales:u,failures:f}}function j(e){return e.replace(/\s+/g,` `).trim()}function M(e){let t=[j(e.source),e.kind,e.tag.toLowerCase(),e.attribute??``,e.context].join(``);return b(`sha256`).update(t).digest(`hex`).slice(0,24)}function N(e,t){let n=x(t,e,{lang:`tsx`,sourceType:`unambiguous`});if(n.errors.length)throw SyntaxError(`${t}: ${n.errors[0].message}`);return{program:n.program,commentsByEnd:new Map(n.comments.map(e=>[e.end,e]))}}function P(e,t){let n=[],r=e=>{t(e,n),n.push(e);for(let t of Object.keys(e)){if(t===`parent`)continue;let n=e[t];Array.isArray(n)?n.forEach(e=>F(e)&&r(e)):F(n)&&r(n)}n.pop()};r(e)}function F(e){return typeof e==`object`&&!!e&&typeof e.type==`string`}function I(e){return F(e)&&e.type===`Literal`&&typeof e.value==`string`}function te(e,t,n,r){let i=n;for(;;){let n=i;for(;n>0&&/\s/.test(e[n-1]);)n--;let a=t.get(n);if(!a)return!1;if(a.type===`Block`&&a.value.trim()===r)return!0;i=a.start}}const ne=new Map(`quot:0022 amp:0026 apos:0027 lt:003C gt:003E nbsp:00A0 iexcl:00A1 cent:00A2 pound:00A3 curren:00A4 yen:00A5 brvbar:00A6 sect:00A7 uml:00A8 copy:00A9 ordf:00AA laquo:00AB not:00AC shy:00AD reg:00AE macr:00AF deg:00B0 plusmn:00B1 sup2:00B2 sup3:00B3 acute:00B4 micro:00B5 para:00B6 middot:00B7 cedil:00B8 sup1:00B9 ordm:00BA raquo:00BB frac14:00BC frac12:00BD frac34:00BE iquest:00BF Agrave:00C0 Aacute:00C1 Acirc:00C2 Atilde:00C3 Auml:00C4 Aring:00C5 AElig:00C6 Ccedil:00C7 Egrave:00C8 Eacute:00C9 Ecirc:00CA Euml:00CB Igrave:00CC Iacute:00CD Icirc:00CE Iuml:00CF ETH:00D0 Ntilde:00D1 Ograve:00D2 Oacute:00D3 Ocirc:00D4 Otilde:00D5 Ouml:00D6 times:00D7 Oslash:00D8 Ugrave:00D9 Uacute:00DA Ucirc:00DB Uuml:00DC Yacute:00DD THORN:00DE szlig:00DF agrave:00E0 aacute:00E1 acirc:00E2 atilde:00E3 auml:00E4 aring:00E5 aelig:00E6 ccedil:00E7 egrave:00E8 eacute:00E9 ecirc:00EA euml:00EB igrave:00EC iacute:00ED icirc:00EE iuml:00EF eth:00F0 ntilde:00F1 ograve:00F2 oacute:00F3 ocirc:00F4 otilde:00F5 ouml:00F6 divide:00F7 oslash:00F8 ugrave:00F9 uacute:00FA ucirc:00FB uuml:00FC yacute:00FD thorn:00FE yuml:00FF OElig:0152 oelig:0153 Scaron:0160 scaron:0161 Yuml:0178 fnof:0192 circ:02C6 tilde:02DC Alpha:0391 Beta:0392 Gamma:0393 Delta:0394 Epsilon:0395 Zeta:0396 Eta:0397 Theta:0398 Iota:0399 Kappa:039A Lambda:039B Mu:039C Nu:039D Xi:039E Omicron:039F Pi:03A0 Rho:03A1 Sigma:03A3 Tau:03A4 Upsilon:03A5 Phi:03A6 Chi:03A7 Psi:03A8 Omega:03A9 alpha:03B1 beta:03B2 gamma:03B3 delta:03B4 epsilon:03B5 zeta:03B6 eta:03B7 theta:03B8 iota:03B9 kappa:03BA lambda:03BB mu:03BC nu:03BD xi:03BE omicron:03BF pi:03C0 rho:03C1 sigmaf:03C2 sigma:03C3 tau:03C4 upsilon:03C5 phi:03C6 chi:03C7 psi:03C8 omega:03C9 thetasym:03D1 upsih:03D2 piv:03D6 ensp:2002 emsp:2003 thinsp:2009 zwnj:200C zwj:200D lrm:200E rlm:200F ndash:2013 mdash:2014 lsquo:2018 rsquo:2019 sbquo:201A ldquo:201C rdquo:201D bdquo:201E dagger:2020 Dagger:2021 bull:2022 hellip:2026 permil:2030 prime:2032 Prime:2033 lsaquo:2039 rsaquo:203A oline:203E frasl:2044 euro:20AC image:2111 weierp:2118 real:211C trade:2122 alefsym:2135 larr:2190 uarr:2191 rarr:2192 darr:2193 harr:2194 crarr:21B5 lArr:21D0 uArr:21D1 rArr:21D2 dArr:21D3 hArr:21D4 forall:2200 part:2202 exist:2203 empty:2205 nabla:2207 isin:2208 notin:2209 ni:220B prod:220F sum:2211 minus:2212 lowast:2217 radic:221A prop:221D infin:221E ang:2220 and:2227 or:2228 cap:2229 cup:222A int:222B there4:2234 sim:223C cong:2245 asymp:2248 ne:2260 equiv:2261 le:2264 ge:2265 sub:2282 sup:2283 nsub:2284 sube:2286 supe:2287 oplus:2295 otimes:2297 perp:22A5 sdot:22C5 lceil:2308 rceil:2309 lfloor:230A rfloor:230B lang:2329 rang:232A loz:25CA spades:2660 clubs:2663 hearts:2665 diams:2666`.split(` `).map(e=>{let[t,n]=e.split(`:`);return[t,String.fromCharCode(parseInt(n,16))]})),re=/&(?:#(x[0-9a-fA-F]+|[0-9]+)|([A-Za-z0-9]+));/g;function L(e){return e.includes(`&`)?e.replace(re,(e,t,n)=>{if(n!==void 0)return ne.get(n)??e;let r=t.startsWith(`x`)?parseInt(t.slice(1),16):parseInt(t,10);return r<=1114111?String.fromCodePoint(r):e}):e}const ie=/^[A-Z]/,ae=/* @__PURE__ */ new Set([`script`,`style`,`code`,`pre`]),oe=/* @__PURE__ */ new Set([`alt`,`title`,`placeholder`,`label`,`summary`,`aria-label`,`aria-description`,`aria-placeholder`,`aria-roledescription`,`aria-valuetext`]);function R(e){return I(e)?L(e.value):void 0}function z(e){return L(e.value)}function se(e){return e.attributes.some(e=>e.type===`JSXAttribute`&&e.name.type===`JSXIdentifier`&&e.name.name===`translate`&&R(e.value)===`no`)}function B(e){return e.type===`JSXIdentifier`&&!ie.test(e.name)&&!ae.has(e.name)}function V(e){if(e.type===`Identifier`)return e.name;if(e.type===`MemberExpression`&&!e.computed&&e.property.type===`Identifier`){let t=V(e.object);return t?`${t}.${e.property.name}`:void 0}}const ce=(e,t)=>e.type===`FunctionExpression`?!(t?.type===`MethodDefinition`||t?.type===`Property`&&(t.method||t.kind!==`init`)):e.type===`FunctionDeclaration`||e.type===`ArrowFunctionExpression`;function H(e,t){for(let n=e.length-1;n>=0;n--)if(t(e[n]))return n;return-1}function U(e){return e.some(e=>{let t=e.type===`JSXOpeningElement`?e:e.type===`JSXElement`?e.openingElement:void 0;return t!==void 0&&se(t)})}function W(e,t,n){let r=e.attributes.filter(e=>e.type===`JSXAttribute`&&e.name.type===`JSXIdentifier`&&[`aria-label`,`title`,`name`,`type`,`role`].includes(e.name.name)).map(e=>`${e.name.name}=${R(e.value)??`{expr}`}`).sort().join(`;`),i=e.attributes.filter(e=>e.type===`JSXAttribute`&&e.name.type===`JSXIdentifier`&&/^on[A-Z]/.test(e.name.name)).map(e=>{let t=e.value?.type===`JSXExpressionContainer`?e.value.expression:null,n=t&&t.type===`Identifier`?t.name:t?.type??`handler`;return`${e.name.name}=${n}`}).sort().join(`,`);return[t,n??``,r,i].filter(Boolean).join(` | `)}function le(e,t){let{program:n,commentsByEnd:r}=N(e,t),i=[];function a(e){let t=e.length-1;for(;t>=0&&!ce(e[t],e[t-1]);)t--;if(t<0)return`<module>`;let n=e[t],r=e[t-1];return r?.type===`VariableDeclarator`&&r.id.type===`Identifier`?r.id.name:n.type===`FunctionDeclaration`&&n.id?n.id.name:`<anonymous>`}function o(e,n){if(U([...n,e]))return;let r=e.children,o=r.filter(e=>e.type===`JSXExpressionContainer`);if(!o.length||r.some(e=>e.type!==`JSXText`&&e.type!==`JSXExpressionContainer`)||!o.every(e=>V(e.expression)!==void 0)||!r.some(e=>e.type===`JSXText`&&/[A-Za-z]/.test(z(e))))return;let s=e.openingElement.name;if(!B(s))return;let c=[];for(let e of o){let t=V(e.expression),n=t;for(let e=2;c.includes(n);e++)n=`${t}_${e}`;c.push(n)}let l=``,u=0;for(let e of r)l+=e.type===`JSXText`?z(e):`{${c[u++]}}`;let d=j(l);if(!d)return;let f=s.name,p={source:d,prefix:l.match(/^\s*/)?.[0]??``,suffix:l.match(/\s*$/)?.[0]??``,kind:`mixed`,placeholders:c,file:t,start:e.start,end:e.end,tag:f,component:a(n),context:W(e.openingElement,f),fingerprint:``};p.fingerprint=M(p),i.push(p)}function s(e,n){if(U([...n,e]))return;let r=z(e),o=j(r);if(!o)return;let s=H(n,e=>e.type===`JSXElement`);if(s<0)return;let c=n[s];if(c.children.some(e=>e.type===`JSXExpressionContainer`))return;let l=c.openingElement.name;if(!B(l))return;let u=l.name,d={source:o,prefix:r.match(/^\s*/)?.[0]??``,suffix:r.match(/\s*$/)?.[0]??``,kind:`text`,file:t,start:e.start,end:e.end,tag:u,component:a(n.slice(0,s)),context:W(c.openingElement,u),fingerprint:``};d.fingerprint=M(d),i.push(d)}function c(e,n){if(e.name.type!==`JSXIdentifier`||!oe.has(e.name.name)||U([...n,e])||!I(e.value))return;let r=j(L(e.value.value));if(!r||!/[A-Za-z]/.test(r))return;let o=n[n.length-1];if(o?.type!==`JSXOpeningElement`||!B(o.name))return;let s=o.name.name,c=H(n,e=>e.type===`JSXElement`);if(c<0)return;let l=n[c],u=e.name.name,d={source:r,kind:`attribute`,file:t,start:e.value.start,end:e.value.end,tag:s,component:a(n.slice(0,c)),attribute:u,context:W(l.openingElement,s,u),fingerprint:``};d.fingerprint=M(d),i.push(d)}function l(n,o){if(!I(n)||o[o.length-1]?.type===`JSXAttribute`||o.some(e=>e.start===n.start)||!te(e,r,n.start,`i18n`))return;let s=j(n.value);if(!s||!/[A-Za-z]/.test(s))return;let c={source:s,kind:`string`,file:t,start:n.start,end:n.end,tag:``,component:a(o),context:``,fingerprint:``};c.fingerprint=M(c),i.push(c)}return P(n,(e,t)=>{switch(e.type){case`JSXElement`:return o(e,t);case`JSXText`:return s(e,t);case`JSXAttribute`:return c(e,t);case`Literal`:return l(e,t)}}),i.sort((e,t)=>e.start-t.start)}const G=`virtual:autoi18n`,K=`__autoI18nT`,q=`__autoI18nFormat`;function ue(e,t,n,r,i,a=!1,o=`en`){let{program:s}=N(e,t),c={mixed:/* @__PURE__ */ new Map,text:/* @__PURE__ */ new Map,attribute:/* @__PURE__ */ new Map,string:/* @__PURE__ */ new Map};for(let e of n)c[e.kind]?.set(e.start,e);let l=[];P(s,e=>{if(e.type===`JSXElement`){let t=c.mixed.get(e.start);t&&l.push({kind:`mixed`,node:e,message:t})}else if(e.type===`JSXText`){let t=c.text.get(e.start);t&&l.push({kind:`text`,node:e,message:t})}else if(e.type===`JSXAttribute`&&e.value?.type===`Literal`){let t=c.attribute.get(e.value.start);t&&l.push({kind:`attribute`,node:e.value,message:t})}else if(e.type===`Literal`&&typeof e.value==`string`){let t=c.string.get(e.start);t&&l.push({kind:`string`,node:e,message:t})}});let u=new S(e),d=!1,f=!1,p=e=>r===o?e.source:i[e.id]??e.source,m=e=>a?(d=!0,`${K}(${JSON.stringify(e.id)}, ${JSON.stringify(e.source)})`):JSON.stringify(p(e)),h=e=>{let t=e.prefix??``,n=e.suffix??``;return a?[t&&JSON.stringify(t),m(e),n&&JSON.stringify(n)].filter(Boolean).join(` + `):JSON.stringify(`${t}${p(e)}${n}`)};for(let e of l.reverse()){let{message:t}=e;if(e.kind===`mixed`){let n=e.node;if(!n.closingElement)continue;let r=t.placeholders??[],i=n.children.flatMap(e=>e.type===`JSXExpressionContainer`?[e.expression]:[]),o=e=>u.slice(i[e].start,i[e].end),s=n.openingElement.end,c=n.closingElement.start;if(a){f=!0;let e=r.map((e,t)=>`${JSON.stringify(e)}: ${o(t)}`).join(`, `);u.overwrite(s,c,`{${q}(${h(t)}, {${e}})}`);continue}let l=p(t),d=O(l,r)?l:t.source,m=[],g=0,_=e=>{e&&m.push(`{${JSON.stringify(e)}}`)};_(t.prefix??``);for(let e of d.matchAll(T))_(d.slice(g,e.index)),m.push(`{${o(r.indexOf(e[1]))}}`),g=e.index+e[0].length;_(d.slice(g)+(t.suffix??``)),u.overwrite(s,c,m.join(``))}else e.kind===`text`?u.overwrite(e.node.start,e.node.end,`{${h(t)}}`):e.kind===`attribute`?u.overwrite(e.node.start,e.node.end,a?`{${m(t)}}`:m(t)):u.overwrite(e.node.start,e.node.end,m(t))}let g=[...d?[`t as ${K}`]:[],...f?[`format as ${q}`]:[]];return g.length&&u.prepend(`import { ${g.join(`, `)} } from "${G}";\n`),{code:u.toString(),map:u.generateMap({source:t,hires:!0,includeContent:!0})}}function de(e,t,n){let r=[],i=0;for(let a of e.matchAll(n)){if(!Object.hasOwn(t,a[1]))continue;let n=a.index??0;n>i&&r.push(e.slice(i,n)),r.push(t[a[1]]),i=n+a[0].length}return i<e.length&&r.push(e.slice(i)),r}function fe(e,t){return[`const loaders = {\n${Object.entries(e).map(([e,t])=>` ${JSON.stringify(e)}: () => import(${JSON.stringify(t)}).then(m => (m.default ?? m).messages)`).join(`,
2
+ `)}\n};`,`const sourceLocale = ${JSON.stringify(t)};`,`const resolveLocale = ${h.toString()};`,`const createLocaleLoader = ${m.toString()};`,`const formatPlaceholders = ${de.toString()};`,`const PLACEHOLDER = new RegExp(${JSON.stringify(w)}, "g");`,`const loadLocale = createLocaleLoader(loaders, sourceLocale);`,`const listeners = new Set();`,`let currentLocale = sourceLocale;`,`let messages = {};`,`let version = 0;`,`let latestRequest = 0;`,`export const locales = Object.keys(loaders);`,`export function getLocale() { return currentLocale; }`,`export function getVersion() { return version; }`,`export function resolveSupported(preferred) { return resolveLocale(preferred, locales, sourceLocale); }`,`export async function setLocale(locale) {`,` const request = ++latestRequest;`,` let selected = loaders[locale] ? locale : sourceLocale;`,` let catalog;`,` try {`,` catalog = await loadLocale(selected);`,` } catch (error) {`,` if (selected === sourceLocale) throw error;`,` console.warn('autoi18n: could not load "' + selected + '", falling back to "' + sourceLocale + '".', error);`,` selected = sourceLocale;`,` catalog = await loadLocale(selected);`,` }`,` // A slower earlier request must not overwrite the locale the user picked last.`,` if (request !== latestRequest) return;`,` messages = catalog;`,` currentLocale = selected;`,` notify();`,`}`,`function notify() {`,` version++;`,` listeners.forEach(fn => fn(currentLocale));`,`}`,`export function subscribe(fn) { listeners.add(fn); return () => { listeners.delete(fn); }; }`,`export function t(id, source) { return messages[id] ?? source; }`,`export function format(text, values) { return formatPlaceholders(text, values, PLACEHOLDER); }`,`// Dev server pushes fresh catalogues after a source change; no page reload is needed.`,`if (import.meta.hot) {`,` import.meta.hot.on("autoi18n:update", data => {`,` for (const [locale, catalog] of Object.entries(data.catalogs)) loadLocale.prime(locale, catalog);`,` if (data.catalogs[currentLocale]) messages = data.catalogs[currentLocale];`,` notify();`,` });`,`}`].join(`
3
3
  `)+`
4
- `}const Y=6e4;var X=class extends Error{retryable;retryAfterMs;constructor(e,t,n){super(e),this.retryable=t,this.retryAfterMs=n}};function re(e,t=Date.now()){if(!e)return;let n=Number(e);if(Number.isFinite(n))return Math.min(Math.max(n,0)*1e3,Y);let r=Date.parse(e);if(!Number.isNaN(r))return Math.min(Math.max(r-t,0),Y)}const ie=e=>new Promise(t=>setTimeout(t,e));var ae=class{options;constructor(e){this.options=e}async translate(e){let t=Math.max(1,this.options.batchSize??40),n=[];for(let r=0;r<e.messages.length;r+=t)n.push(e.messages.slice(r,r+t));let r=await T(n,this.options.concurrency??4,t=>this.translateBatch({...e,messages:t})),i={},a=[],o=0,s=0;if(r.forEach((e,t)=>{e.status===`fulfilled`?(s++,Object.assign(i,e.value)):(a.push(e.reason),o+=n[t].length)}),!a.length)return i;throw s?new j(`${o} messages failed to translate: ${a[0].message}`,i,o):a[0]}async translateBatch(e){let t=this.options.maxRetries??2,n=this.options.retryDelayMs??500;for(let r=0;;r++)try{return await this.request(e)}catch(e){if(e instanceof X&&!e.retryable||r>=t)throw e;let i=e instanceof X?e.retryAfterMs:void 0;await ie(i??n*2**r*(.5+Math.random()/2))}}async request(e){let t=await fetch(`${this.options.baseURL??`https://api.openai.com/v1`}/chat/completions`,{method:`POST`,signal:AbortSignal.timeout(this.options.timeoutMs??6e4),headers:{Authorization:`Bearer ${this.options.apiKey}`,"Content-Type":`application/json`},body:JSON.stringify({model:this.options.model,temperature:0,response_format:{type:`json_object`},messages:[{role:`system`,content:`You are a professional software localization engine. Translate UI messages from ${e.sourceLocale} to ${e.targetLocale}. Preserve placeholders exactly. Respect context and UI conventions. Return ONLY a JSON object mapping message IDs to translated strings. Do not translate product names or code.`},{role:`user`,content:JSON.stringify(e.messages.map(e=>({id:e.id,text:e.source,context:e.context,kind:e.kind})))}]})});if(!t.ok){let e=t.status===408||t.status===409||t.status===429||t.status>=500;throw new X(`Translation API failed (${t.status}): ${await t.text()}`,e,re(t.headers.get(`retry-after`)))}let r=n.safeParse(await t.json()),i=r.success?r.data.choices[0].message.content:void 0;if(!i)throw new X(`Translation provider returned no content`,!0);let a;try{a=JSON.parse(i)}catch{throw new X(`Translation provider returned invalid JSON`,!0)}let o=u.safeParse(a);if(!o.success)throw new X(`Translation provider returned a non-object`,!0);let s=new Set(e.messages.map(e=>e.id)),c={};for(let[e,t]of Object.entries(o.data))s.has(e)&&typeof t==`string`&&t.trim()&&(c[e]=t);return c}};const Z=[`src/**/*.{tsx,jsx,ts,js}`],Q=[`**/*.test.*`,`**/node_modules/**`];function oe(e){let t=r.safeParse(e);if(t.success)return;let n=t.error.issues.map(e=>`${e.path.join(`.`)||`options`}: ${e.message}`).join(`; `);throw Error(`autoi18n: invalid options (${n}).`)}const $=e=>({info:t=>e.info(t),warn:t=>e.warn(t),error:t=>e.error(t)});async function se(e,t){await Promise.all(t.map(t=>v(y.join(e,`${t}.sources.json`),{force:!0})))}function ce(t){oe(t);let n=t.sourceLocale??`en`,r=t.directory??`.autoi18n`,a=t.delivery??`build`,l=t.debug??!1,u=t.orphanRetentionMinutes??43200,d,m=``,h={},v=/* @__PURE__ */ new Map,b=/* @__PURE__ */ new Map,x=/* @__PURE__ */ new Map,S=/* @__PURE__ */ new Map,C=/* @__PURE__ */ new Set,w,T=Promise.resolve(),E,D=()=>t.locale??process.env.AUTOI18N_LOCALE??n;function O(){let e=t.locales.filter(e=>e!==n),r=t.locale??process.env.AUTOI18N_LOCALE;return a===`build`&&r&&d.command!==`serve`?e.filter(e=>e===r):e}async function k(a){let C=await g(t.include??Z,{cwd:d.root,ignore:t.exclude??Q,absolute:!0}),w=/* @__PURE__ */ new Map,T=[];for(let e of C){let t=await _(e,`utf8`),n=s(t),r=v.get(e),i=r?.hash===n?r:{hash:n,messages:H(t,e)};w.set(e,i),T.push({file:e,messages:i.messages})}let E=y.resolve(d.root,r,`locales`),D=O(),k=/* @__PURE__ */ new Map;for(let e of D)k.set(e,await o(f(E,e),a.warn));let A=await N({files:T,registry:await c(m,a.warn),orphanRetentionMinutes:u,sourceLocale:n,locales:D,localeConcurrency:Math.max(1,Math.floor(t.localeConcurrency??2)),previous:k,provider:t.provider,debug:l});if(l)for(let e of A.pruned)i(`removed ${e.id} ${JSON.stringify(e.source)} (last seen ${e.lastSeen})`);if(A.pruned.length&&a.info(`autoi18n: removed ${A.pruned.length} registry entries no longer in the source.`),await e(m,A.registry),A.ambiguous.length){let e=`autoi18n: ${A.ambiguous.length} duplicated texts changed occurrence count, so their IDs may have moved (e.g. "${A.ambiguous[0]}").`;t.onAmbiguous===`error`?a.error(e):a.warn(e)}await p(f(E,n),A.sourceFile),await se(E,[n,...t.locales]);let j=/* @__PURE__ */ new Map([[n,A.sourceFile.messages]]);for(let[e,t]of A.locales)await p(f(E,e),t.file),j.set(e,t.file.messages);for(let e of A.failures.keys())j.set(e,k.get(e)?.messages??{});let M=0;b=/* @__PURE__ */ new Map;for(let{file:e,messages:t}of T)b.set(e,A.messages.slice(M,M+t.length)),M+=t.length;x=new Map([...w].map(([e,t])=>[e,t.hash])),v=w,S=j,h=Object.fromEntries(t.locales.map(e=>[e,f(E,e)]));for(let[e,n]of A.locales)n.requested&&!t.provider&&t.failOnMissingProvider&&a.error(`Missing ${n.requested} ${e} translations and no provider is configured.`),n.rejected&&a.info(`autoi18n: rejected ${n.rejected} ${e} translations with changed placeholders.`),n.untranslated&&(t.provider?a.warn:a.info)(`autoi18n: ${n.untranslated} ${e} messages have no translation and fall back to the source text.`),n.failed&&a.warn(`autoi18n: ${n.failed} ${e} translation batches failed (${n.failure}); they will be requested again on the next build.`);A.messages.length&&a.info(`autoi18n: indexed ${A.messages.length} messages across ${C.length} files.`);let P=[...A.failures];for(let[e,t]of P.slice(1))a.warn(`autoi18n: ${e} translation failed: ${t.message}`);if(P.length)throw P[0][1]}function A(e){let t=T.then(()=>k(e));return T=t.catch(()=>void 0),t}function j(){w?.ws.send({type:`custom`,event:`autoi18n:update`,data:{catalogs:Object.fromEntries(S)}})}async function M(){try{await A($(d.logger)),j()}catch(e){d.logger.error(`autoi18n: re-translation failed: ${e.message}`)}}function P(){clearTimeout(E),E=setTimeout(()=>void M(),150)}function F(e){if(!/\.[jt]sx?$/.test(e))return!1;let n=y.relative(d.root,e).split(y.sep).join(`/`);return(t.include??Z).some(e=>y.matchesGlob(n,e))&&!(t.exclude??Q).some(e=>y.matchesGlob(n,e))}return{name:`vite-plugin-autoi18n`,enforce:`pre`,configResolved(e){d=e,m=y.resolve(d.root,r,`registry.json`);let i=D();if(i!==n&&!t.locales.includes(i))throw Error(`autoi18n: locale "${i}" is not one of the configured locales (${t.locales.join(`, `)}).`)},resolveId(e){if(e===`virtual:autoi18n`)return`\0${G}`},load(e){if(e===`\0virtual:autoi18n`)return ne(h,n)},configureServer(e){w=e,e.watcher.on(`add`,e=>{F(e)&&P()}),e.watcher.on(`unlink`,e=>{b.has(e)&&P()})},closeBundle(){clearTimeout(E)},async buildStart(){await k({info:e=>this.info(e),warn:e=>this.warn(e),error:e=>this.error(e)})},async transform(e,t){let r=t.split(`?`)[0];if(!b.has(r))return null;s(e)!==x.get(r)&&await A($(d.logger));let i=b.get(r);if(!i||s(e)!==x.get(r))return C.has(r)||(C.add(r),this.warn(`autoi18n: ${r} changed while it was being indexed; its messages are left untranslated.`)),null;let o=d.command===`serve`?n:D(),c=J(e,r,i,o,S.get(o)??{},a===`runtime`,n);return{code:c.code,map:c.map}},async handleHotUpdate({file:e}){if(e.startsWith(y.resolve(d.root,r,`locales`)+y.sep))return[];b.has(e)&&await M()}}}export{ae as OpenAICompatibleProvider,j as PartialTranslationError,ce as default};
4
+ `}const J=6e4;var Y=class extends Error{retryable;retryAfterMs;constructor(e,t,n){super(e),this.retryable=t,this.retryAfterMs=n}};function pe(e,t=Date.now()){if(!e)return;let n=Number(e);if(Number.isFinite(n))return Math.min(Math.max(n,0)*1e3,J);let r=Date.parse(e);if(!Number.isNaN(r))return Math.min(Math.max(r-t,0),J)}const me=e=>new Promise(t=>setTimeout(t,e));var he=class{options;constructor(e){this.options=e}async translate(e){let t=Math.max(1,this.options.batchSize??40),n=[];for(let r=0;r<e.messages.length;r+=t)n.push(e.messages.slice(r,r+t));let r=await C(n,this.options.concurrency??4,t=>this.translateBatch({...e,messages:t})),i={},a=[],o=0,s=0;if(r.forEach((e,t)=>{e.status===`fulfilled`?(s++,Object.assign(i,e.value)):(a.push(e.reason),o+=n[t].length)}),!a.length)return i;throw s?new k(`${o} messages failed to translate: ${a[0].message}`,i,o):a[0]}async translateBatch(e){let t=this.options.maxRetries??2,n=this.options.retryDelayMs??500;for(let r=0;;r++)try{return await this.request(e)}catch(e){if(e instanceof Y&&!e.retryable||r>=t)throw e;let i=e instanceof Y?e.retryAfterMs:void 0;await me(i??n*2**r*(.5+Math.random()/2))}}async request(e){let t=await fetch(`${this.options.baseURL??`https://api.openai.com/v1`}/chat/completions`,{method:`POST`,signal:AbortSignal.timeout(this.options.timeoutMs??6e4),headers:{Authorization:`Bearer ${this.options.apiKey}`,"Content-Type":`application/json`},body:JSON.stringify({model:this.options.model,temperature:0,response_format:{type:`json_object`},messages:[{role:`system`,content:`You are a professional software localization engine. Translate UI messages from ${e.sourceLocale} to ${e.targetLocale}. Preserve placeholders exactly. Respect context and UI conventions. Return ONLY a JSON object mapping message IDs to translated strings. Do not translate product names or code.`},{role:`user`,content:JSON.stringify(e.messages.map(e=>({id:e.id,text:e.source,context:e.context,kind:e.kind})))}]})});if(!t.ok){let e=t.status===408||t.status===409||t.status===429||t.status>=500;throw new Y(`Translation API failed (${t.status}): ${await t.text()}`,e,pe(t.headers.get(`retry-after`)))}let r=n.safeParse(await t.json()),i=r.success?r.data.choices[0].message.content:void 0;if(!i)throw new Y(`Translation provider returned no content`,!0);let a;try{a=JSON.parse(i)}catch{throw new Y(`Translation provider returned invalid JSON`,!0)}let o=u.safeParse(a);if(!o.success)throw new Y(`Translation provider returned a non-object`,!0);let s=new Set(e.messages.map(e=>e.id)),c={};for(let[e,t]of Object.entries(o.data))s.has(e)&&typeof t==`string`&&t.trim()&&(c[e]=t);return c}};const X=[`src/**/*.{tsx,jsx,ts,js}`],Z=[`**/*.test.*`,`**/node_modules/**`];function ge(e){let t=r.safeParse(e);if(t.success)return;let n=t.error.issues.map(e=>`${e.path.join(`.`)||`options`}: ${e.message}`).join(`; `);throw Error(`autoi18n: invalid options (${n}).`)}const Q=e=>({info:t=>e.info(t),warn:t=>e.warn(t),error:t=>e.error(t)});async function $(e,t){await Promise.all(t.map(t=>v(y.join(e,`${t}.sources.json`),{force:!0})))}function _e(t){ge(t);let n=t.sourceLocale??`en`,r=t.directory??`.autoi18n`,a=t.delivery??`build`,l=t.debug??!1,u=t.orphanRetentionMinutes??43200,d,m=``,h={},v=/* @__PURE__ */ new Map,b=/* @__PURE__ */ new Map,x=/* @__PURE__ */ new Map,S=/* @__PURE__ */ new Map,C=/* @__PURE__ */ new Set,w,T=Promise.resolve(),E,D=()=>t.locale??process.env.AUTOI18N_LOCALE??n;function O(){let e=t.locales.filter(e=>e!==n),r=t.locale??process.env.AUTOI18N_LOCALE;return a===`build`&&r&&d.command!==`serve`?e.filter(e=>e===r):e}async function k(a){let C=await g(t.include??X,{cwd:d.root,ignore:t.exclude??Z,absolute:!0}),w=/* @__PURE__ */ new Map,T=[];for(let e of C){let t=await _(e,`utf8`),n=s(t),r=v.get(e),i=r?.hash===n?r:{hash:n,messages:le(t,e)};w.set(e,i),T.push({file:e,messages:i.messages})}let E=y.resolve(d.root,r,`locales`),D=O(),k=/* @__PURE__ */ new Map;for(let e of D)k.set(e,await o(f(E,e),a.warn));let A=await ee({files:T,registry:await c(m,a.warn),orphanRetentionMinutes:u,sourceLocale:n,locales:D,localeConcurrency:Math.max(1,Math.floor(t.localeConcurrency??2)),previous:k,provider:t.provider,debug:l});if(l)for(let e of A.pruned)i(`removed ${e.id} ${JSON.stringify(e.source)} (last seen ${e.lastSeen})`);if(A.pruned.length&&a.info(`autoi18n: removed ${A.pruned.length} registry entries no longer in the source.`),await e(m,A.registry),A.ambiguous.length){let e=`autoi18n: ${A.ambiguous.length} duplicated texts changed occurrence count, so their IDs may have moved (e.g. "${A.ambiguous[0]}").`;t.onAmbiguous===`error`?a.error(e):a.warn(e)}await p(f(E,n),A.sourceFile),await $(E,[n,...t.locales]);let j=/* @__PURE__ */ new Map([[n,A.sourceFile.messages]]);for(let[e,t]of A.locales)await p(f(E,e),t.file),j.set(e,t.file.messages);for(let e of A.failures.keys())j.set(e,k.get(e)?.messages??{});let M=0;b=/* @__PURE__ */ new Map;for(let{file:e,messages:t}of T)b.set(e,A.messages.slice(M,M+t.length)),M+=t.length;x=new Map([...w].map(([e,t])=>[e,t.hash])),v=w,S=j,h=Object.fromEntries(t.locales.map(e=>[e,f(E,e)]));for(let[e,n]of A.locales)n.requested&&!t.provider&&t.failOnMissingProvider&&a.error(`Missing ${n.requested} ${e} translations and no provider is configured.`),n.rejected&&a.info(`autoi18n: rejected ${n.rejected} ${e} translations with changed placeholders.`),n.untranslated&&(t.provider?a.warn:a.info)(`autoi18n: ${n.untranslated} ${e} messages have no translation and fall back to the source text.`),n.failed&&a.warn(`autoi18n: ${n.failed} ${e} translation batches failed (${n.failure}); they will be requested again on the next build.`);A.messages.length&&a.info(`autoi18n: indexed ${A.messages.length} messages across ${C.length} files.`);let N=[...A.failures];for(let[e,t]of N.slice(1))a.warn(`autoi18n: ${e} translation failed: ${t.message}`);if(N.length)throw N[0][1]}function A(e){let t=T.then(()=>k(e));return T=t.catch(()=>void 0),t}function j(){w?.ws.send({type:`custom`,event:`autoi18n:update`,data:{catalogs:Object.fromEntries(S)}})}async function M(){try{await A(Q(d.logger)),j()}catch(e){d.logger.error(`autoi18n: re-translation failed: ${e.message}`)}}function N(){clearTimeout(E),E=setTimeout(()=>void M(),150)}function P(e){if(!/\.[jt]sx?$/.test(e))return!1;let n=y.relative(d.root,e).split(y.sep).join(`/`);return(t.include??X).some(e=>y.matchesGlob(n,e))&&!(t.exclude??Z).some(e=>y.matchesGlob(n,e))}return{name:`vite-plugin-autoi18n`,enforce:`pre`,configResolved(e){d=e,m=y.resolve(d.root,r,`registry.json`);let i=D();if(i!==n&&!t.locales.includes(i))throw Error(`autoi18n: locale "${i}" is not one of the configured locales (${t.locales.join(`, `)}).`)},resolveId(e){if(e===`virtual:autoi18n`)return`\0${G}`},load(e){if(e===`\0virtual:autoi18n`)return fe(h,n)},configureServer(e){w=e,e.watcher.on(`add`,e=>{P(e)&&N()}),e.watcher.on(`unlink`,e=>{b.has(e)&&N()})},closeBundle(){clearTimeout(E)},async buildStart(){await k({info:e=>this.info(e),warn:e=>this.warn(e),error:e=>this.error(e)})},async transform(e,t){let r=t.split(`?`)[0];if(!b.has(r))return null;s(e)!==x.get(r)&&await A(Q(d.logger));let i=b.get(r);if(!i||s(e)!==x.get(r))return C.has(r)||(C.add(r),this.warn(`autoi18n: ${r} changed while it was being indexed; its messages are left untranslated.`)),null;let o=d.command===`serve`?n:D(),c=ue(e,r,i,o,S.get(o)??{},a===`runtime`,n);return{code:c.code,map:c.map}},async handleHotUpdate({file:e}){if(e.startsWith(y.resolve(d.root,r,`locales`)+y.sep))return[];b.has(e)&&await M()}}}export{he as OpenAICompatibleProvider,k as PartialTranslationError,_e as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-ai-auto-i18n",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "description": "Implicit, build-time AI localization for JSX applications",
6
6
  "license": "ISC",
@@ -39,16 +39,12 @@
39
39
  "vite": "^8.3.7"
40
40
  },
41
41
  "dependencies": {
42
- "@babel/generator": "^8.1.0",
43
- "@babel/parser": "^8.1.0",
44
- "@babel/traverse": "^8.1.0",
45
- "@babel/types": "^8.1.0",
42
+ "magic-string": "^1.4.5",
43
+ "oxc-parser": "^0.158.0",
46
44
  "tinyglobby": "^0.2.17",
47
45
  "zod": "^4.6.7"
48
46
  },
49
47
  "devDependencies": {
50
- "@types/babel__generator": "^7.27.0",
51
- "@types/babel__traverse": "^7.28.0",
52
48
  "@types/node": "^26.6.6",
53
49
  "@vitejs/plugin-react": "^6.3.0",
54
50
  "@vitest/coverage-v8": "^5.1.0",