next-tongue 0.9.10 → 0.9.11

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.
@@ -67,13 +67,25 @@ export function transformCallSites(source, resourcePath, _options = {}) {
67
67
  importLines.push(`import { ${safeExport(key)} as ${ident} } from '${path}';`);
68
68
  loadedCalls.push(`process.env.NODE_ENV !== 'production' && globalThis.__tongueDevLoaded?.(${JSON.stringify(ns || '_root')}, ${JSON.stringify(key)});`);
69
69
  }
70
- const localeVar = '__tongue_locale';
71
- // Inject locale once after the first useT declaration
72
- code = code.replace(/((?:const|let|var)\s+\w+\s*=\s*useT\s*\([^)]*\))/, `$1\n const ${localeVar} = useLocale();`);
70
+ // Inject locale after every useT — one binding per translator var so each
71
+ // component (and multi-useT in one function) has __tongue_locale_* in scope.
72
+ for (const varName of translators.keys()) {
73
+ if (escapes(withoutDirs, varName))
74
+ continue;
75
+ const localeVar = localeVarFor(varName);
76
+ const declRe = new RegExp(`((?:const|let|var)\\s+${escapeRegExp(varName)}\\s*=\\s*useT\\s*\\([^)]*\\))`, 'g');
77
+ code = code.replace(declRe, (full) => {
78
+ // Idempotent if a prior pass already injected.
79
+ if (full.includes(localeVar))
80
+ return full;
81
+ return `${full}\n const ${localeVar} = useLocale();`;
82
+ });
83
+ }
73
84
  // Replace t.dynamic(expr, { from }, values?) — rewrite from the end so indices stay valid
74
85
  for (const [varName, ns] of translators) {
75
86
  if (escapes(withoutDirs, varName))
76
87
  continue;
88
+ const localeVar = localeVarFor(varName);
77
89
  const calls = findDynamicCalls(code, varName).filter((c) => c.keys && c.keys.length > 0);
78
90
  for (let ci = calls.length - 1; ci >= 0; ci--) {
79
91
  const call = calls[ci];
@@ -96,6 +108,7 @@ export function transformCallSites(source, resourcePath, _options = {}) {
96
108
  for (const [varName, ns] of translators) {
97
109
  if (escapes(withoutDirs, varName))
98
110
  continue;
111
+ const localeVar = localeVarFor(varName);
99
112
  for (const { key, ident } of [...imports.values()].filter((i) => i.ns === ns)) {
100
113
  const richRe = new RegExp(`\\b${escapeRegExp(varName)}\\.rich\\s*\\(\\s*(['"])${escapeRegExp(key)}\\1\\s*(,\\s*([^)]*))?\\)`, 'g');
101
114
  code = code.replace(richRe, (_full, _q, _rest, values) => {
@@ -178,6 +191,10 @@ function escapes(source, varName) {
178
191
  function escapeRegExp(s) {
179
192
  return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
180
193
  }
194
+ /** Per-useT locale binding so each component function has its own in-scope var. */
195
+ function localeVarFor(varName) {
196
+ return varName === 't' ? '__tongue_locale' : `__tongue_locale_${varName}`;
197
+ }
181
198
  function safeImportIdent(ns, key) {
182
199
  return `__tongue_${(ns + '_' + key).replace(/[^A-Za-z0-9_]/g, '_')}`;
183
200
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-tongue",
3
- "version": "0.9.10",
3
+ "version": "0.9.11",
4
4
  "description": "Compiler-first, type-safe i18n for the Next.js 16 App Router",
5
5
  "license": "MIT",
6
6
  "type": "module",