i18next-cli 1.11.3 → 1.11.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/cjs/cli.js +1 -1
- package/dist/cjs/extractor/core/ast-visitors.js +1 -1
- package/dist/cjs/extractor/parsers/jsx-parser.js +1 -1
- package/dist/cjs/extractor/parsers/scope-manager.js +1 -1
- package/dist/cjs/locize.js +1 -1
- package/dist/esm/cli.js +1 -1
- package/dist/esm/extractor/core/ast-visitors.js +1 -1
- package/dist/esm/extractor/parsers/jsx-parser.js +1 -1
- package/dist/esm/extractor/parsers/scope-manager.js +1 -1
- package/dist/esm/locize.js +1 -1
- package/package.json +1 -1
- package/src/cli.ts +1 -1
- package/src/extractor/core/ast-visitors.ts +25 -0
- package/src/extractor/parsers/jsx-parser.ts +62 -53
- package/src/extractor/parsers/scope-manager.ts +12 -0
- package/src/locize.ts +10 -2
- package/types/extractor/core/ast-visitors.d.ts.map +1 -1
- package/types/extractor/parsers/scope-manager.d.ts +8 -0
- package/types/extractor/parsers/scope-manager.d.ts.map +1 -1
- package/types/locize.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.11.5](https://github.com/i18next/i18next-cli/compare/v1.11.4...v1.11.5) - 2025-10-17
|
|
9
|
+
|
|
10
|
+
- **Extractor:** ignore formatting-only JSXText nodes when serializing <Trans> children to avoid inflated component placeholder indexes and incorrect keys caused by indentation/newlines — fixes [#66](https://github.com/i18next/i18next-cli/issues/66)
|
|
11
|
+
- **Extractor:** prevent scope leakage and ensure correct namespace resolution for t()/getFixedT() when functions reference `t` declared later in the same file; restores idempotent extraction regardless of input file ordering — fixes [#65](https://github.com/i18next/i18next-cli/issues/65)
|
|
12
|
+
|
|
13
|
+
## [1.11.4](https://github.com/i18next/i18next-cli/compare/v1.11.3...v1.11.4) - 2025-10-15
|
|
14
|
+
|
|
15
|
+
- **Extractor:** Ignore formatting-only JSXText nodes that contain only whitespace/newlines when serializing `<Trans>` children. This prevents inflated component placeholder indexes caused by indentation/newlines while preserving intentional spaces (e.g. `{' '}`). Resulting keys now match react-i18next runtime normalization. See [#63](https://github.com/i18next/i18next-cli/issues/63).
|
|
16
|
+
|
|
8
17
|
## [1.11.3](https://github.com/i18next/i18next-cli/compare/v1.11.2...v1.11.3) - 2025-10-13
|
|
9
18
|
|
|
10
19
|
- **Extractor:** Fixed the `--watch` flag being ignored in the `extract` command. The watch mode now properly monitors source files for changes and re-runs extraction automatically, matching the behavior of other commands like `types` and `lint`. [#62](https://github.com/i18next/i18next-cli/issues/62)
|
package/dist/cjs/cli.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";var e=require("commander"),t=require("chokidar"),n=require("glob"),o=require("chalk"),i=require("./config.js"),a=require("./heuristic-config.js"),r=require("./extractor/core/extractor.js");require("node:path"),require("node:fs/promises"),require("jiti");var c=require("./types-generator.js"),s=require("./syncer.js"),l=require("./migrator.js"),u=require("./init.js"),d=require("./linter.js"),g=require("./status.js"),p=require("./locize.js");const f=new e.Command;f.name("i18next-cli").description("A unified, high-performance i18next CLI.").version("1.11.
|
|
2
|
+
"use strict";var e=require("commander"),t=require("chokidar"),n=require("glob"),o=require("chalk"),i=require("./config.js"),a=require("./heuristic-config.js"),r=require("./extractor/core/extractor.js");require("node:path"),require("node:fs/promises"),require("jiti");var c=require("./types-generator.js"),s=require("./syncer.js"),l=require("./migrator.js"),u=require("./init.js"),d=require("./linter.js"),g=require("./status.js"),p=require("./locize.js");const f=new e.Command;f.name("i18next-cli").description("A unified, high-performance i18next CLI.").version("1.11.5"),f.command("extract").description("Extract translation keys from source files and update resource files.").option("-w, --watch","Watch for file changes and re-run the extractor.").option("--ci","Exit with a non-zero status code if any files are updated.").option("--dry-run","Run the extractor without writing any files to disk.").option("--sync-primary","Sync primary language values with default values from code.").action(async e=>{try{const o=await i.ensureConfig(),a=async()=>{const t=await r.runExtractor(o,{isWatchMode:!!e.watch,isDryRun:!!e.dryRun,syncPrimaryWithDefaults:!!e.syncPrimary});return e.ci&&!t?(console.log("✅ No files were updated."),process.exit(0)):e.ci&&t&&(console.error("❌ Some files were updated. This should not happen in CI mode."),process.exit(1)),t};if(await a(),e.watch){console.log("\nWatching for changes...");t.watch(await n.glob(o.extract.input),{ignored:/node_modules/,persistent:!0}).on("change",e=>{console.log(`\nFile changed: ${e}`),a()})}}catch(e){console.error("Error running extractor:",e),process.exit(1)}}),f.command("status [locale]").description("Display translation status. Provide a locale for a detailed key-by-key view.").option("-n, --namespace <ns>","Filter the status report by a specific namespace").action(async(e,t)=>{let n=await i.loadConfig();if(!n){console.log(o.blue("No config file found. Attempting to detect project structure..."));const e=await a.detectConfig();e||(console.error(o.red("Could not automatically detect your project structure.")),console.log(`Please create a config file first by running: ${o.cyan("npx i18next-cli init")}`),process.exit(1)),console.log(o.green("Project structure detected successfully!")),n=e}await g.runStatus(n,{detail:e,namespace:t.namespace})}),f.command("types").description("Generate TypeScript definitions from translation resource files.").option("-w, --watch","Watch for file changes and re-run the type generator.").action(async e=>{const o=await i.ensureConfig(),a=()=>c.runTypesGenerator(o);if(await a(),e.watch){console.log("\nWatching for changes...");t.watch(await n.glob(o.types?.input||[]),{persistent:!0}).on("change",e=>{console.log(`\nFile changed: ${e}`),a()})}}),f.command("sync").description("Synchronize secondary language files with the primary language file.").action(async()=>{const e=await i.ensureConfig();await s.runSyncer(e)}),f.command("migrate-config [configPath]").description("Migrate a legacy i18next-parser.config.js to the new format.").action(async e=>{await l.runMigrator(e)}),f.command("init").description("Create a new i18next.config.ts/js file with an interactive setup wizard.").action(u.runInit),f.command("lint").description("Find potential issues like hardcoded strings in your codebase.").option("-w, --watch","Watch for file changes and re-run the linter.").action(async e=>{const r=async()=>{let e=await i.loadConfig();if(!e){console.log(o.blue("No config file found. Attempting to detect project structure..."));const t=await a.detectConfig();t||(console.error(o.red("Could not automatically detect your project structure.")),console.log(`Please create a config file first by running: ${o.cyan("npx i18next-cli init")}`),process.exit(1)),console.log(o.green("Project structure detected successfully!")),e=t}await d.runLinter(e)};if(await r(),e.watch){console.log("\nWatching for changes...");const e=await i.loadConfig();if(e?.extract?.input){t.watch(await n.glob(e.extract.input),{ignored:/node_modules/,persistent:!0}).on("change",e=>{console.log(`\nFile changed: ${e}`),r()})}}}),f.command("locize-sync").description("Synchronize local translations with your locize project.").option("--update-values","Update values of existing translations on locize.").option("--src-lng-only","Check for changes in source language only.").option("--compare-mtime","Compare modification times when syncing.").option("--dry-run","Run the command without making any changes.").action(async e=>{const t=await i.ensureConfig();await p.runLocizeSync(t,e)}),f.command("locize-download").description("Download all translations from your locize project.").action(async e=>{const t=await i.ensureConfig();await p.runLocizeDownload(t,e)}),f.command("locize-migrate").description("Migrate local translation files to a new locize project.").action(async e=>{const t=await i.ensureConfig();await p.runLocizeMigrate(t,e)}),f.parse(process.argv);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("../parsers/scope-manager.js"),s=require("../parsers/expression-resolver.js"),r=require("../parsers/call-expression-handler.js"),o=require("../parsers/jsx-handler.js");exports.ASTVisitors=class{pluginContext;config;logger;hooks;get objectKeys(){return this.callExpressionHandler.objectKeys}scopeManager;expressionResolver;callExpressionHandler;jsxHandler;constructor(
|
|
1
|
+
"use strict";var e=require("../parsers/scope-manager.js"),s=require("../parsers/expression-resolver.js"),r=require("../parsers/call-expression-handler.js"),o=require("../parsers/jsx-handler.js");exports.ASTVisitors=class{pluginContext;config;logger;hooks;get objectKeys(){return this.callExpressionHandler.objectKeys}scopeManager;expressionResolver;callExpressionHandler;jsxHandler;constructor(a,t,i,n){this.pluginContext=t,this.config=a,this.logger=i,this.hooks={onBeforeVisitNode:n?.onBeforeVisitNode,onAfterVisitNode:n?.onAfterVisitNode,resolvePossibleKeyStringValues:n?.resolvePossibleKeyStringValues,resolvePossibleContextStringValues:n?.resolvePossibleContextStringValues},this.scopeManager=new e.ScopeManager(a),this.expressionResolver=new s.ExpressionResolver(this.hooks),this.callExpressionHandler=new r.CallExpressionHandler(a,t,i,this.expressionResolver),this.jsxHandler=new o.JSXHandler(a,t,this.expressionResolver)}visit(e){this.scopeManager.reset(),this.scopeManager.enterScope(),this.walk(e),this.scopeManager.exitScope()}walk(e){if(!e)return;let s=!1;switch("Function"!==e.type&&"ArrowFunctionExpression"!==e.type&&"FunctionExpression"!==e.type||(this.scopeManager.enterScope(),s=!0),this.hooks.onBeforeVisitNode?.(e),e.type){case"VariableDeclarator":this.scopeManager.handleVariableDeclarator(e);break;case"CallExpression":this.callExpressionHandler.handleCallExpression(e,this.scopeManager.getVarFromScope.bind(this.scopeManager));break;case"JSXElement":this.jsxHandler.handleJSXElement(e,this.scopeManager.getVarFromScope.bind(this.scopeManager))}this.hooks.onAfterVisitNode?.(e);for(const s in e){if("span"===s)continue;const r=e[s];if(Array.isArray(r)){for(const e of r)if(e&&"object"==typeof e)if("VariableDeclarator"!==e.type){if("VariableDeclaration"===e.type&&Array.isArray(e.declarations))for(const s of e.declarations)s&&"object"==typeof s&&"VariableDeclarator"===s.type&&this.scopeManager.handleVariableDeclarator(s)}else this.scopeManager.handleVariableDeclarator(e);for(const e of r)e&&"object"==typeof e&&this.walk(e)}else r&&"object"==typeof r&&this.walk(r)}s&&this.scopeManager.exitScope()}getVarFromScope(e){return this.scopeManager.getVarFromScope(e)}};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("./ast-utils.js");exports.extractFromTransComponent=function(t,n){const i=t.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"i18nKey"===e.name.value),r=t.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"defaults"===e.name.value),a=t.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"count"===e.name.value),
|
|
1
|
+
"use strict";var e=require("./ast-utils.js");exports.extractFromTransComponent=function(t,n){const i=t.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"i18nKey"===e.name.value),r=t.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"defaults"===e.name.value),a=t.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"count"===e.name.value),p=t.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"values"===e.name.value);let s;a||"JSXAttribute"!==p?.type||"JSXExpressionContainer"!==p.value?.type||"ObjectExpression"!==p.value.expression.type||(s=e.getObjectProperty(p.value.expression,"count"));const o=!!a||!!s,l=t.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"tOptions"===e.name.value),u="JSXAttribute"===l?.type&&"JSXExpressionContainer"===l.value?.type&&"ObjectExpression"===l.value.expression.type?l.value.expression:void 0,y=t.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"ordinal"===e.name.value),f=!!y,v=t.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"context"===e.name.value);let c="JSXAttribute"===v?.type&&"JSXExpressionContainer"===v.value?.type?v.value.expression:"JSXAttribute"===v?.type&&"StringLiteral"===v.value?.type?v.value:void 0;const d=t.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"ns"===e.name.value);let m;if(m="JSXAttribute"===d?.type&&"StringLiteral"===d.value?.type?d.value.value:void 0,u&&(void 0===m&&(m=e.getObjectPropValue(u,"ns")),void 0===c)){const t=e.getObjectProperty(u,"context");t?.value&&(c=t.value)}const S=function(e,t){if(!e||0===e.length)return"";const n=new Set(t.extract.transKeepBasicHtmlNodesFor??["br","strong","i","p"]),i=e=>e&&"JSXText"===e.type&&/^\s*$/.test(e.value)&&e.value.includes("\n"),r={n:0};function a(e){if(!e||!e.length)return"";let t="";for(const p of e)if(p)if("JSXText"!==p.type){if("JSXExpressionContainer"===p.type){const e=p.expression;if(!e)continue;if("StringLiteral"===e.type)t+=e.value;else if("Identifier"===e.type)t+=`{{${e.value}}}`;else if("ObjectExpression"===e.type){const n=e.properties[0];n&&"KeyValueProperty"===n.type&&n.key&&"Identifier"===n.key.type?t+=`{{${n.key.value}}}`:n&&"Identifier"===n.type&&(t+=`{{${n.value}}}`)}else"MemberExpression"===e.type&&e.property&&"Identifier"===e.property.type?t+=`{{${e.property.value}}}`:"CallExpression"===e.type&&"Identifier"===e.callee?.type&&(t+=`{{${e.callee.value}}}`);r.n++;continue}if("JSXElement"===p.type){let e;if(p.opening&&p.opening.name&&"Identifier"===p.opening.name.type&&(e=p.opening.name.value),e&&n.has(e)){t+=`<${e}>${a(p.children||[])}</${e}>`}else{const e=r.n;r.n++;t+=`<${e}>${a(p.children||[])}</${e}>`}continue}"JSXFragment"!==p.type||(t+=a(p.children||[]))}else i(p)||(t+=p.value,r.n++);return t}const p=a(e);return String(p).replace(/\s+/g," ").trim()}(t.children,n);let g,b,x;if("JSXAttribute"===r?.type&&"StringLiteral"===r.value?.type)g=r.value.value;else{const e=n.extract.defaultValue;g="string"==typeof e?e:""}if("JSXAttribute"===i?.type){if("StringLiteral"===i.value?.type){if(b=i.value,x=b.value,!x||""===x.trim())return console.warn("Ignoring Trans component with empty i18nKey"),null;if(m&&"StringLiteral"===b.type){const e=n.extract.nsSeparator??":",t=b.value;if(e&&t.startsWith(`${m}${e}`)){if(x=t.slice(`${m}${e}`.length),!x||""===x.trim())return console.warn("Ignoring Trans component with i18nKey that becomes empty after namespace removal"),null;b={...b,value:x}}}}else"JSXExpressionContainer"===i.value?.type&&"JSXEmptyExpression"!==i.value.expression.type&&(b=i.value.expression);if(!b)return null}return r||!x||S.trim()?!r&&S.trim()&&(g=S):g=x,{keyExpression:b,serializedChildren:S,ns:m,defaultValue:g,hasCount:o,isOrdinal:f,contextExpression:c,optionsNode:u}};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("./ast-utils.js");exports.ScopeManager=class{scopeStack=[];config;scope=new Map;constructor(e){this.config=e}enterScope(){this.scopeStack.push(new Map)}exitScope(){this.scopeStack.pop()}setVarInScope(e,t){this.scopeStack.length>0&&this.scopeStack[this.scopeStack.length-1].set(e,t)}getVarFromScope(e){for(let t=this.scopeStack.length-1;t>=0;t--)if(this.scopeStack[t].has(e)){return this.scopeStack[t].get(e)}const t=this.scope.get(e);if(t)return t}handleVariableDeclarator(e){const t=e.init;if(!t)return;const r="AwaitExpression"===t.type&&"CallExpression"===t.argument.type?t.argument:"CallExpression"===t.type?t:null;if(!r)return;const i=r.callee;if("Identifier"===i.type){const t=this.getUseTranslationConfig(i.value);if(t)return this.handleUseTranslationDeclarator(e,r,t),void this.handleUseTranslationForComments(e,r,t)}"MemberExpression"===i.type&&"Identifier"===i.property.type&&"getFixedT"===i.property.value&&this.handleGetFixedTDeclarator(e,r)}getUseTranslationConfig(e){const t=this.config.extract.useTranslationNames||["useTranslation"];for(const r of t){if("string"==typeof r&&r===e)return{name:e,nsArg:0,keyPrefixArg:1};if("object"==typeof r&&r.name===e)return{name:r.name,nsArg:r.nsArg??0,keyPrefixArg:r.keyPrefixArg??1}}}handleUseTranslationForComments(e,t,r){let i;if("Identifier"===e.id.type&&(i=e.id.value),"ArrayPattern"===e.id.type){const t=e.id.elements[0];"Identifier"===t?.type&&(i=t.value)}if("ObjectPattern"===e.id.type)for(const t of e.id.properties){if("AssignmentPatternProperty"===t.type&&"Identifier"===t.key.type&&"t"===t.key.value){i="t";break}if("KeyValuePatternProperty"===t.type&&"Identifier"===t.key.type&&"t"===t.key.value&&"Identifier"===t.value.type){i=t.value.value;break}}if(!i)return;const
|
|
1
|
+
"use strict";var e=require("./ast-utils.js");exports.ScopeManager=class{scopeStack=[];config;scope=new Map;constructor(e){this.config=e}reset(){this.scopeStack=[],this.scope=new Map}enterScope(){this.scopeStack.push(new Map)}exitScope(){this.scopeStack.pop()}setVarInScope(e,t){this.scopeStack.length>0&&this.scopeStack[this.scopeStack.length-1].set(e,t)}getVarFromScope(e){for(let t=this.scopeStack.length-1;t>=0;t--)if(this.scopeStack[t].has(e)){return this.scopeStack[t].get(e)}const t=this.scope.get(e);if(t)return t}handleVariableDeclarator(e){const t=e.init;if(!t)return;const r="AwaitExpression"===t.type&&"CallExpression"===t.argument.type?t.argument:"CallExpression"===t.type?t:null;if(!r)return;const i=r.callee;if("Identifier"===i.type){const t=this.getUseTranslationConfig(i.value);if(t)return this.handleUseTranslationDeclarator(e,r,t),void this.handleUseTranslationForComments(e,r,t)}"MemberExpression"===i.type&&"Identifier"===i.property.type&&"getFixedT"===i.property.value&&this.handleGetFixedTDeclarator(e,r)}getUseTranslationConfig(e){const t=this.config.extract.useTranslationNames||["useTranslation"];for(const r of t){if("string"==typeof r&&r===e)return{name:e,nsArg:0,keyPrefixArg:1};if("object"==typeof r&&r.name===e)return{name:r.name,nsArg:r.nsArg??0,keyPrefixArg:r.keyPrefixArg??1}}}handleUseTranslationForComments(e,t,r){let i;if("Identifier"===e.id.type&&(i=e.id.value),"ArrayPattern"===e.id.type){const t=e.id.elements[0];"Identifier"===t?.type&&(i=t.value)}if("ObjectPattern"===e.id.type)for(const t of e.id.properties){if("AssignmentPatternProperty"===t.type&&"Identifier"===t.key.type&&"t"===t.key.value){i="t";break}if("KeyValuePatternProperty"===t.type&&"Identifier"===t.key.type&&"t"===t.key.value&&"Identifier"===t.value.type){i=t.value.value;break}}if(!i)return;const s=t.arguments?.[r.nsArg]?.expression,n=t.arguments?.[r.keyPrefixArg]?.expression;let a,o;if("StringLiteral"===s?.type?a=s.value:"ArrayExpression"===s?.type&&"StringLiteral"===s.elements[0]?.expression.type&&(a=s.elements[0].expression.value),"ObjectExpression"===n?.type){const e=n.properties.find(e=>"KeyValueProperty"===e.type&&"Identifier"===e.key.type&&"keyPrefix"===e.key.value);"KeyValueProperty"===e?.type&&"StringLiteral"===e.value.type&&(o=e.value.value)}(a||o)&&this.scope.set(i,{defaultNs:a,keyPrefix:o})}handleUseTranslationDeclarator(t,r,i){let s;if("Identifier"===t.id.type&&(s=t.id.value),"ArrayPattern"===t.id.type){const e=t.id.elements[0];"Identifier"===e?.type&&(s=e.value)}if("ObjectPattern"===t.id.type)for(const e of t.id.properties){if("AssignmentPatternProperty"===e.type&&"Identifier"===e.key.type&&"t"===e.key.value){s="t";break}if("KeyValuePatternProperty"===e.type&&"Identifier"===e.key.type&&"t"===e.key.value&&"Identifier"===e.value.type){s=e.value.value;break}}if(!s)return;const n=r.arguments?.[i.nsArg]?.expression;let a;"StringLiteral"===n?.type?a=n.value:"ArrayExpression"===n?.type&&"StringLiteral"===n.elements[0]?.expression.type&&(a=n.elements[0].expression.value);const o=r.arguments?.[i.keyPrefixArg]?.expression;let p;if("ObjectExpression"===o?.type){const t=e.getObjectPropValue(o,"keyPrefix");p="string"==typeof t?t:void 0}this.setVarInScope(s,{defaultNs:a,keyPrefix:p})}handleGetFixedTDeclarator(e,t){if("Identifier"!==e.id.type||!e.init||"CallExpression"!==e.init.type)return;const r=e.id.value,i=t.arguments,s=i[1]?.expression,n=i[2]?.expression,a="StringLiteral"===s?.type?s.value:void 0,o="StringLiteral"===n?.type?n.value:void 0;(a||o)&&this.setVarInScope(r,{defaultNs:a,keyPrefix:o})}};
|
package/dist/cjs/locize.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("execa"),o=require("chalk"),n=require("ora"),t=require("inquirer"),i=require("node:path");function r(e,o,n){const{locize:t={},extract:r}=o,{projectId:s,apiKey:c,version:a}=t,l=[e];if(s&&l.push("--project-id",s),c&&l.push("--api-key",c),a&&l.push("--ver",a),"sync"===e){(n.updateValues??t.updateValues)&&l.push("--update-values","true");(n.srcLngOnly??t.sourceLanguageOnly)&&l.push("--reference-language-only","true");(n.compareMtime??t.compareModificationTime)&&l.push("--compare-modification-time","true");(n.dryRun??t.dryRun)&&l.push("--dry","true")}const u=
|
|
1
|
+
"use strict";var e=require("execa"),o=require("chalk"),n=require("ora"),t=require("inquirer"),i=require("node:path");function r(e,o,n){const{locize:t={},extract:r}=o,{projectId:s,apiKey:c,version:a}=t,l=[e];if(s&&l.push("--project-id",s),c&&l.push("--api-key",c),a&&l.push("--ver",a),"sync"===e){(n.updateValues??t.updateValues)&&l.push("--update-values","true");(n.srcLngOnly??t.sourceLanguageOnly)&&l.push("--reference-language-only","true");(n.compareMtime??t.compareModificationTime)&&l.push("--compare-modification-time","true");(n.dryRun??t.dryRun)&&l.push("--dry","true")}const u=String(r.output||"").replace(/\\/g,"/"),p=(u.includes("/{{language}}/")?u.split("/{{language}}/")[0]:u.replace("{{language}}","")).split("/").join(i.sep),d=i.resolve(process.cwd(),p);return l.push("--path",d),l}async function s(i,s,c={}){await async function(){try{await e.execa("locize",["--version"])}catch(e){"ENOENT"===e.code&&(console.error(o.red("Error: `locize-cli` command not found.")),console.log(o.yellow("Please install it globally to use the locize integration:")),console.log(o.cyan("npm install -g locize-cli")),process.exit(1))}}();const a=n(`Running 'locize ${i}'...\n`).start();let l=s;try{const n=r(i,l,c);console.log(o.cyan(`\nRunning 'locize ${n.join(" ")}'...`));const t=await e.execa("locize",n,{stdio:"pipe"});a.succeed(o.green(`'locize ${i}' completed successfully.`)),t?.stdout&&console.log(t.stdout)}catch(n){const s=n.stderr||"";if(s.includes("missing required argument")){const n=await async function(){console.log(o.yellow("\nLocize configuration is missing or invalid. Let's set it up!"));const e=await t.prompt([{type:"input",name:"projectId",message:"What is your locize Project ID? (Find this in your project settings on www.locize.app)",validate:e=>!!e||"Project ID cannot be empty."},{type:"password",name:"apiKey",message:'What is your locize API key? (Create or use one in your project settings > "API Keys")',validate:e=>!!e||"API Key cannot be empty."},{type:"input",name:"version",message:"What version do you want to sync with?",default:"latest"}]);if(!e.projectId)return void console.error(o.red("Project ID is required to continue."));const{save:n}=await t.prompt([{type:"confirm",name:"save",message:"Would you like to see how to save these credentials for future use?",default:!0}]);if(n){const n=`\n# Add this to your .env file (and ensure .env is in your .gitignore!)\nLOCIZE_API_KEY=${e.apiKey}\n`,t=`\n // Add this to your i18next.config.ts file\n locize: {\n projectId: '${e.projectId}',\n // For security, apiKey is best set via an environment variable\n apiKey: process.env.LOCIZE_API_KEY,\n version: '${e.version}',\n },`;console.log(o.cyan("\nGreat! For the best security, we recommend using environment variables for your API key.")),console.log(o.bold("\nRecommended approach (.env file):")),console.log(o.green(n)),console.log(o.bold("Then, in your i18next.config.ts:")),console.log(o.green(t))}return{projectId:e.projectId,apiKey:e.apiKey,version:e.version}}();if(n){l={...l,locize:n},a.start("Retrying with new credentials...");try{const n=r(i,l,c);console.log(o.cyan(`\nRunning 'locize ${n.join(" ")}'...`));const t=await e.execa("locize",n,{stdio:"pipe"});a.succeed(o.green("Retry successful!")),t?.stdout&&console.log(t.stdout)}catch(e){a.fail(o.red("Error during retry.")),console.error(e.stderr||e.message),process.exit(1)}}else a.fail("Operation cancelled."),process.exit(1)}else a.fail(o.red(`Error executing 'locize ${i}'.`)),console.error(s||n.message),process.exit(1)}console.log(o.green(`\n✅ 'locize ${i}' completed successfully.`))}exports.runLocizeDownload=(e,o)=>s("download",e,o),exports.runLocizeMigrate=(e,o)=>s("migrate",e,o),exports.runLocizeSync=(e,o)=>s("sync",e,o);
|
package/dist/esm/cli.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Command as t}from"commander";import e from"chokidar";import{glob as o}from"glob";import n from"chalk";import{ensureConfig as i,loadConfig as a}from"./config.js";import{detectConfig as c}from"./heuristic-config.js";import{runExtractor as r}from"./extractor/core/extractor.js";import"node:path";import"node:fs/promises";import"jiti";import{runTypesGenerator as s}from"./types-generator.js";import{runSyncer as l}from"./syncer.js";import{runMigrator as p}from"./migrator.js";import{runInit as m}from"./init.js";import{runLinter as d}from"./linter.js";import{runStatus as u}from"./status.js";import{runLocizeSync as f,runLocizeDownload as g,runLocizeMigrate as h}from"./locize.js";const y=new t;y.name("i18next-cli").description("A unified, high-performance i18next CLI.").version("1.11.
|
|
2
|
+
import{Command as t}from"commander";import e from"chokidar";import{glob as o}from"glob";import n from"chalk";import{ensureConfig as i,loadConfig as a}from"./config.js";import{detectConfig as c}from"./heuristic-config.js";import{runExtractor as r}from"./extractor/core/extractor.js";import"node:path";import"node:fs/promises";import"jiti";import{runTypesGenerator as s}from"./types-generator.js";import{runSyncer as l}from"./syncer.js";import{runMigrator as p}from"./migrator.js";import{runInit as m}from"./init.js";import{runLinter as d}from"./linter.js";import{runStatus as u}from"./status.js";import{runLocizeSync as f,runLocizeDownload as g,runLocizeMigrate as h}from"./locize.js";const y=new t;y.name("i18next-cli").description("A unified, high-performance i18next CLI.").version("1.11.5"),y.command("extract").description("Extract translation keys from source files and update resource files.").option("-w, --watch","Watch for file changes and re-run the extractor.").option("--ci","Exit with a non-zero status code if any files are updated.").option("--dry-run","Run the extractor without writing any files to disk.").option("--sync-primary","Sync primary language values with default values from code.").action(async t=>{try{const n=await i(),a=async()=>{const e=await r(n,{isWatchMode:!!t.watch,isDryRun:!!t.dryRun,syncPrimaryWithDefaults:!!t.syncPrimary});return t.ci&&!e?(console.log("✅ No files were updated."),process.exit(0)):t.ci&&e&&(console.error("❌ Some files were updated. This should not happen in CI mode."),process.exit(1)),e};if(await a(),t.watch){console.log("\nWatching for changes...");e.watch(await o(n.extract.input),{ignored:/node_modules/,persistent:!0}).on("change",t=>{console.log(`\nFile changed: ${t}`),a()})}}catch(t){console.error("Error running extractor:",t),process.exit(1)}}),y.command("status [locale]").description("Display translation status. Provide a locale for a detailed key-by-key view.").option("-n, --namespace <ns>","Filter the status report by a specific namespace").action(async(t,e)=>{let o=await a();if(!o){console.log(n.blue("No config file found. Attempting to detect project structure..."));const t=await c();t||(console.error(n.red("Could not automatically detect your project structure.")),console.log(`Please create a config file first by running: ${n.cyan("npx i18next-cli init")}`),process.exit(1)),console.log(n.green("Project structure detected successfully!")),o=t}await u(o,{detail:t,namespace:e.namespace})}),y.command("types").description("Generate TypeScript definitions from translation resource files.").option("-w, --watch","Watch for file changes and re-run the type generator.").action(async t=>{const n=await i(),a=()=>s(n);if(await a(),t.watch){console.log("\nWatching for changes...");e.watch(await o(n.types?.input||[]),{persistent:!0}).on("change",t=>{console.log(`\nFile changed: ${t}`),a()})}}),y.command("sync").description("Synchronize secondary language files with the primary language file.").action(async()=>{const t=await i();await l(t)}),y.command("migrate-config [configPath]").description("Migrate a legacy i18next-parser.config.js to the new format.").action(async t=>{await p(t)}),y.command("init").description("Create a new i18next.config.ts/js file with an interactive setup wizard.").action(m),y.command("lint").description("Find potential issues like hardcoded strings in your codebase.").option("-w, --watch","Watch for file changes and re-run the linter.").action(async t=>{const i=async()=>{let t=await a();if(!t){console.log(n.blue("No config file found. Attempting to detect project structure..."));const e=await c();e||(console.error(n.red("Could not automatically detect your project structure.")),console.log(`Please create a config file first by running: ${n.cyan("npx i18next-cli init")}`),process.exit(1)),console.log(n.green("Project structure detected successfully!")),t=e}await d(t)};if(await i(),t.watch){console.log("\nWatching for changes...");const t=await a();if(t?.extract?.input){e.watch(await o(t.extract.input),{ignored:/node_modules/,persistent:!0}).on("change",t=>{console.log(`\nFile changed: ${t}`),i()})}}}),y.command("locize-sync").description("Synchronize local translations with your locize project.").option("--update-values","Update values of existing translations on locize.").option("--src-lng-only","Check for changes in source language only.").option("--compare-mtime","Compare modification times when syncing.").option("--dry-run","Run the command without making any changes.").action(async t=>{const e=await i();await f(e,t)}),y.command("locize-download").description("Download all translations from your locize project.").action(async t=>{const e=await i();await g(e,t)}),y.command("locize-migrate").description("Migrate local translation files to a new locize project.").action(async t=>{const e=await i();await h(e,t)}),y.parse(process.argv);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ScopeManager as e}from"../parsers/scope-manager.js";import{ExpressionResolver as s}from"../parsers/expression-resolver.js";import{CallExpressionHandler as o}from"../parsers/call-expression-handler.js";import{JSXHandler as r}from"../parsers/jsx-handler.js";class t{pluginContext;config;logger;hooks;get objectKeys(){return this.callExpressionHandler.objectKeys}scopeManager;expressionResolver;callExpressionHandler;jsxHandler;constructor(t,i,n
|
|
1
|
+
import{ScopeManager as e}from"../parsers/scope-manager.js";import{ExpressionResolver as s}from"../parsers/expression-resolver.js";import{CallExpressionHandler as o}from"../parsers/call-expression-handler.js";import{JSXHandler as r}from"../parsers/jsx-handler.js";class t{pluginContext;config;logger;hooks;get objectKeys(){return this.callExpressionHandler.objectKeys}scopeManager;expressionResolver;callExpressionHandler;jsxHandler;constructor(t,a,i,n){this.pluginContext=a,this.config=t,this.logger=i,this.hooks={onBeforeVisitNode:n?.onBeforeVisitNode,onAfterVisitNode:n?.onAfterVisitNode,resolvePossibleKeyStringValues:n?.resolvePossibleKeyStringValues,resolvePossibleContextStringValues:n?.resolvePossibleContextStringValues},this.scopeManager=new e(t),this.expressionResolver=new s(this.hooks),this.callExpressionHandler=new o(t,a,i,this.expressionResolver),this.jsxHandler=new r(t,a,this.expressionResolver)}visit(e){this.scopeManager.reset(),this.scopeManager.enterScope(),this.walk(e),this.scopeManager.exitScope()}walk(e){if(!e)return;let s=!1;switch("Function"!==e.type&&"ArrowFunctionExpression"!==e.type&&"FunctionExpression"!==e.type||(this.scopeManager.enterScope(),s=!0),this.hooks.onBeforeVisitNode?.(e),e.type){case"VariableDeclarator":this.scopeManager.handleVariableDeclarator(e);break;case"CallExpression":this.callExpressionHandler.handleCallExpression(e,this.scopeManager.getVarFromScope.bind(this.scopeManager));break;case"JSXElement":this.jsxHandler.handleJSXElement(e,this.scopeManager.getVarFromScope.bind(this.scopeManager))}this.hooks.onAfterVisitNode?.(e);for(const s in e){if("span"===s)continue;const o=e[s];if(Array.isArray(o)){for(const e of o)if(e&&"object"==typeof e)if("VariableDeclarator"!==e.type){if("VariableDeclaration"===e.type&&Array.isArray(e.declarations))for(const s of e.declarations)s&&"object"==typeof s&&"VariableDeclarator"===s.type&&this.scopeManager.handleVariableDeclarator(s)}else this.scopeManager.handleVariableDeclarator(e);for(const e of o)e&&"object"==typeof e&&this.walk(e)}else o&&"object"==typeof o&&this.walk(o)}s&&this.scopeManager.exitScope()}getVarFromScope(e){return this.scopeManager.getVarFromScope(e)}}export{t as ASTVisitors};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getObjectProperty as e,getObjectPropValue as t}from"./ast-utils.js";function n(n,i){const r=n.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"i18nKey"===e.name.value),a=n.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"defaults"===e.name.value),
|
|
1
|
+
import{getObjectProperty as e,getObjectPropValue as t}from"./ast-utils.js";function n(n,i){const r=n.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"i18nKey"===e.name.value),a=n.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"defaults"===e.name.value),p=n.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"count"===e.name.value),s=n.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"values"===e.name.value);let l;p||"JSXAttribute"!==s?.type||"JSXExpressionContainer"!==s.value?.type||"ObjectExpression"!==s.value.expression.type||(l=e(s.value.expression,"count"));const o=!!p||!!l,u=n.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"tOptions"===e.name.value),y="JSXAttribute"===u?.type&&"JSXExpressionContainer"===u.value?.type&&"ObjectExpression"===u.value.expression.type?u.value.expression:void 0,f=n.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"ordinal"===e.name.value),v=!!f,c=n.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"context"===e.name.value);let d="JSXAttribute"===c?.type&&"JSXExpressionContainer"===c.value?.type?c.value.expression:"JSXAttribute"===c?.type&&"StringLiteral"===c.value?.type?c.value:void 0;const m=n.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"ns"===e.name.value);let S;if(S="JSXAttribute"===m?.type&&"StringLiteral"===m.value?.type?m.value.value:void 0,y&&(void 0===S&&(S=t(y,"ns")),void 0===d)){const t=e(y,"context");t?.value&&(d=t.value)}const g=function(e,t){if(!e||0===e.length)return"";const n=new Set(t.extract.transKeepBasicHtmlNodesFor??["br","strong","i","p"]),i=e=>e&&"JSXText"===e.type&&/^\s*$/.test(e.value)&&e.value.includes("\n"),r={n:0};function a(e){if(!e||!e.length)return"";let t="";for(const p of e)if(p)if("JSXText"!==p.type){if("JSXExpressionContainer"===p.type){const e=p.expression;if(!e)continue;if("StringLiteral"===e.type)t+=e.value;else if("Identifier"===e.type)t+=`{{${e.value}}}`;else if("ObjectExpression"===e.type){const n=e.properties[0];n&&"KeyValueProperty"===n.type&&n.key&&"Identifier"===n.key.type?t+=`{{${n.key.value}}}`:n&&"Identifier"===n.type&&(t+=`{{${n.value}}}`)}else"MemberExpression"===e.type&&e.property&&"Identifier"===e.property.type?t+=`{{${e.property.value}}}`:"CallExpression"===e.type&&"Identifier"===e.callee?.type&&(t+=`{{${e.callee.value}}}`);r.n++;continue}if("JSXElement"===p.type){let e;if(p.opening&&p.opening.name&&"Identifier"===p.opening.name.type&&(e=p.opening.name.value),e&&n.has(e)){t+=`<${e}>${a(p.children||[])}</${e}>`}else{const e=r.n;r.n++;t+=`<${e}>${a(p.children||[])}</${e}>`}continue}"JSXFragment"!==p.type||(t+=a(p.children||[]))}else i(p)||(t+=p.value,r.n++);return t}const p=a(e);return String(p).replace(/\s+/g," ").trim()}(n.children,i);let x,b,J;if("JSXAttribute"===a?.type&&"StringLiteral"===a.value?.type)x=a.value.value;else{const e=i.extract.defaultValue;x="string"==typeof e?e:""}if("JSXAttribute"===r?.type){if("StringLiteral"===r.value?.type){if(b=r.value,J=b.value,!J||""===J.trim())return console.warn("Ignoring Trans component with empty i18nKey"),null;if(S&&"StringLiteral"===b.type){const e=i.extract.nsSeparator??":",t=b.value;if(e&&t.startsWith(`${S}${e}`)){if(J=t.slice(`${S}${e}`.length),!J||""===J.trim())return console.warn("Ignoring Trans component with i18nKey that becomes empty after namespace removal"),null;b={...b,value:J}}}}else"JSXExpressionContainer"===r.value?.type&&"JSXEmptyExpression"!==r.value.expression.type&&(b=r.value.expression);if(!b)return null}return a||!J||g.trim()?!a&&g.trim()&&(x=g):x=J,{keyExpression:b,serializedChildren:g,ns:S,defaultValue:x,hasCount:o,isOrdinal:v,contextExpression:d,optionsNode:y}}export{n as extractFromTransComponent};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getObjectPropValue as e}from"./ast-utils.js";class t{scopeStack=[];config;scope=new Map;constructor(e){this.config=e}enterScope(){this.scopeStack.push(new Map)}exitScope(){this.scopeStack.pop()}setVarInScope(e,t){this.scopeStack.length>0&&this.scopeStack[this.scopeStack.length-1].set(e,t)}getVarFromScope(e){for(let t=this.scopeStack.length-1;t>=0;t--)if(this.scopeStack[t].has(e)){return this.scopeStack[t].get(e)}const t=this.scope.get(e);if(t)return t}handleVariableDeclarator(e){const t=e.init;if(!t)return;const r="AwaitExpression"===t.type&&"CallExpression"===t.argument.type?t.argument:"CallExpression"===t.type?t:null;if(!r)return;const i=r.callee;if("Identifier"===i.type){const t=this.getUseTranslationConfig(i.value);if(t)return this.handleUseTranslationDeclarator(e,r,t),void this.handleUseTranslationForComments(e,r,t)}"MemberExpression"===i.type&&"Identifier"===i.property.type&&"getFixedT"===i.property.value&&this.handleGetFixedTDeclarator(e,r)}getUseTranslationConfig(e){const t=this.config.extract.useTranslationNames||["useTranslation"];for(const r of t){if("string"==typeof r&&r===e)return{name:e,nsArg:0,keyPrefixArg:1};if("object"==typeof r&&r.name===e)return{name:r.name,nsArg:r.nsArg??0,keyPrefixArg:r.keyPrefixArg??1}}}handleUseTranslationForComments(e,t,r){let i;if("Identifier"===e.id.type&&(i=e.id.value),"ArrayPattern"===e.id.type){const t=e.id.elements[0];"Identifier"===t?.type&&(i=t.value)}if("ObjectPattern"===e.id.type)for(const t of e.id.properties){if("AssignmentPatternProperty"===t.type&&"Identifier"===t.key.type&&"t"===t.key.value){i="t";break}if("KeyValuePatternProperty"===t.type&&"Identifier"===t.key.type&&"t"===t.key.value&&"Identifier"===t.value.type){i=t.value.value;break}}if(!i)return;const
|
|
1
|
+
import{getObjectPropValue as e}from"./ast-utils.js";class t{scopeStack=[];config;scope=new Map;constructor(e){this.config=e}reset(){this.scopeStack=[],this.scope=new Map}enterScope(){this.scopeStack.push(new Map)}exitScope(){this.scopeStack.pop()}setVarInScope(e,t){this.scopeStack.length>0&&this.scopeStack[this.scopeStack.length-1].set(e,t)}getVarFromScope(e){for(let t=this.scopeStack.length-1;t>=0;t--)if(this.scopeStack[t].has(e)){return this.scopeStack[t].get(e)}const t=this.scope.get(e);if(t)return t}handleVariableDeclarator(e){const t=e.init;if(!t)return;const r="AwaitExpression"===t.type&&"CallExpression"===t.argument.type?t.argument:"CallExpression"===t.type?t:null;if(!r)return;const i=r.callee;if("Identifier"===i.type){const t=this.getUseTranslationConfig(i.value);if(t)return this.handleUseTranslationDeclarator(e,r,t),void this.handleUseTranslationForComments(e,r,t)}"MemberExpression"===i.type&&"Identifier"===i.property.type&&"getFixedT"===i.property.value&&this.handleGetFixedTDeclarator(e,r)}getUseTranslationConfig(e){const t=this.config.extract.useTranslationNames||["useTranslation"];for(const r of t){if("string"==typeof r&&r===e)return{name:e,nsArg:0,keyPrefixArg:1};if("object"==typeof r&&r.name===e)return{name:r.name,nsArg:r.nsArg??0,keyPrefixArg:r.keyPrefixArg??1}}}handleUseTranslationForComments(e,t,r){let i;if("Identifier"===e.id.type&&(i=e.id.value),"ArrayPattern"===e.id.type){const t=e.id.elements[0];"Identifier"===t?.type&&(i=t.value)}if("ObjectPattern"===e.id.type)for(const t of e.id.properties){if("AssignmentPatternProperty"===t.type&&"Identifier"===t.key.type&&"t"===t.key.value){i="t";break}if("KeyValuePatternProperty"===t.type&&"Identifier"===t.key.type&&"t"===t.key.value&&"Identifier"===t.value.type){i=t.value.value;break}}if(!i)return;const s=t.arguments?.[r.nsArg]?.expression,n=t.arguments?.[r.keyPrefixArg]?.expression;let a,o;if("StringLiteral"===s?.type?a=s.value:"ArrayExpression"===s?.type&&"StringLiteral"===s.elements[0]?.expression.type&&(a=s.elements[0].expression.value),"ObjectExpression"===n?.type){const e=n.properties.find(e=>"KeyValueProperty"===e.type&&"Identifier"===e.key.type&&"keyPrefix"===e.key.value);"KeyValueProperty"===e?.type&&"StringLiteral"===e.value.type&&(o=e.value.value)}(a||o)&&this.scope.set(i,{defaultNs:a,keyPrefix:o})}handleUseTranslationDeclarator(t,r,i){let s;if("Identifier"===t.id.type&&(s=t.id.value),"ArrayPattern"===t.id.type){const e=t.id.elements[0];"Identifier"===e?.type&&(s=e.value)}if("ObjectPattern"===t.id.type)for(const e of t.id.properties){if("AssignmentPatternProperty"===e.type&&"Identifier"===e.key.type&&"t"===e.key.value){s="t";break}if("KeyValuePatternProperty"===e.type&&"Identifier"===e.key.type&&"t"===e.key.value&&"Identifier"===e.value.type){s=e.value.value;break}}if(!s)return;const n=r.arguments?.[i.nsArg]?.expression;let a;"StringLiteral"===n?.type?a=n.value:"ArrayExpression"===n?.type&&"StringLiteral"===n.elements[0]?.expression.type&&(a=n.elements[0].expression.value);const o=r.arguments?.[i.keyPrefixArg]?.expression;let p;if("ObjectExpression"===o?.type){const t=e(o,"keyPrefix");p="string"==typeof t?t:void 0}this.setVarInScope(s,{defaultNs:a,keyPrefix:p})}handleGetFixedTDeclarator(e,t){if("Identifier"!==e.id.type||!e.init||"CallExpression"!==e.init.type)return;const r=e.id.value,i=t.arguments,s=i[1]?.expression,n=i[2]?.expression,a="StringLiteral"===s?.type?s.value:void 0,o="StringLiteral"===n?.type?n.value:void 0;(a||o)&&this.setVarInScope(r,{defaultNs:a,keyPrefix:o})}}export{t as ScopeManager};
|
package/dist/esm/locize.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{execa as e}from"execa";import o from"chalk";import n from"ora";import t from"inquirer";import{resolve as
|
|
1
|
+
import{execa as e}from"execa";import o from"chalk";import n from"ora";import t from"inquirer";import{sep as i,resolve as s}from"node:path";function r(e,o,n){const{locize:t={},extract:r}=o,{projectId:c,apiKey:a,version:l}=t,u=[e];if(c&&u.push("--project-id",c),a&&u.push("--api-key",a),l&&u.push("--ver",l),"sync"===e){(n.updateValues??t.updateValues)&&u.push("--update-values","true");(n.srcLngOnly??t.sourceLanguageOnly)&&u.push("--reference-language-only","true");(n.compareMtime??t.compareModificationTime)&&u.push("--compare-modification-time","true");(n.dryRun??t.dryRun)&&u.push("--dry","true")}const p=String(r.output||"").replace(/\\/g,"/"),d=(p.includes("/{{language}}/")?p.split("/{{language}}/")[0]:p.replace("{{language}}","")).split("/").join(i),g=s(process.cwd(),d);return u.push("--path",g),u}async function c(i,s,c={}){await async function(){try{await e("locize",["--version"])}catch(e){"ENOENT"===e.code&&(console.error(o.red("Error: `locize-cli` command not found.")),console.log(o.yellow("Please install it globally to use the locize integration:")),console.log(o.cyan("npm install -g locize-cli")),process.exit(1))}}();const a=n(`Running 'locize ${i}'...\n`).start();let l=s;try{const n=r(i,l,c);console.log(o.cyan(`\nRunning 'locize ${n.join(" ")}'...`));const t=await e("locize",n,{stdio:"pipe"});a.succeed(o.green(`'locize ${i}' completed successfully.`)),t?.stdout&&console.log(t.stdout)}catch(n){const s=n.stderr||"";if(s.includes("missing required argument")){const n=await async function(){console.log(o.yellow("\nLocize configuration is missing or invalid. Let's set it up!"));const e=await t.prompt([{type:"input",name:"projectId",message:"What is your locize Project ID? (Find this in your project settings on www.locize.app)",validate:e=>!!e||"Project ID cannot be empty."},{type:"password",name:"apiKey",message:'What is your locize API key? (Create or use one in your project settings > "API Keys")',validate:e=>!!e||"API Key cannot be empty."},{type:"input",name:"version",message:"What version do you want to sync with?",default:"latest"}]);if(!e.projectId)return void console.error(o.red("Project ID is required to continue."));const{save:n}=await t.prompt([{type:"confirm",name:"save",message:"Would you like to see how to save these credentials for future use?",default:!0}]);if(n){const n=`\n# Add this to your .env file (and ensure .env is in your .gitignore!)\nLOCIZE_API_KEY=${e.apiKey}\n`,t=`\n // Add this to your i18next.config.ts file\n locize: {\n projectId: '${e.projectId}',\n // For security, apiKey is best set via an environment variable\n apiKey: process.env.LOCIZE_API_KEY,\n version: '${e.version}',\n },`;console.log(o.cyan("\nGreat! For the best security, we recommend using environment variables for your API key.")),console.log(o.bold("\nRecommended approach (.env file):")),console.log(o.green(n)),console.log(o.bold("Then, in your i18next.config.ts:")),console.log(o.green(t))}return{projectId:e.projectId,apiKey:e.apiKey,version:e.version}}();if(n){l={...l,locize:n},a.start("Retrying with new credentials...");try{const n=r(i,l,c);console.log(o.cyan(`\nRunning 'locize ${n.join(" ")}'...`));const t=await e("locize",n,{stdio:"pipe"});a.succeed(o.green("Retry successful!")),t?.stdout&&console.log(t.stdout)}catch(e){a.fail(o.red("Error during retry.")),console.error(e.stderr||e.message),process.exit(1)}}else a.fail("Operation cancelled."),process.exit(1)}else a.fail(o.red(`Error executing 'locize ${i}'.`)),console.error(s||n.message),process.exit(1)}console.log(o.green(`\n✅ 'locize ${i}' completed successfully.`))}const a=(e,o)=>c("sync",e,o),l=(e,o)=>c("download",e,o),u=(e,o)=>c("migrate",e,o);export{l as runLocizeDownload,u as runLocizeMigrate,a as runLocizeSync};
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -78,6 +78,8 @@ export class ASTVisitors {
|
|
|
78
78
|
* @param node - The root module node to traverse
|
|
79
79
|
*/
|
|
80
80
|
public visit (node: Module): void {
|
|
81
|
+
// Reset any per-file scope state to avoid leaking scopes between files.
|
|
82
|
+
this.scopeManager.reset()
|
|
81
83
|
this.scopeManager.enterScope() // Create the root scope for the file
|
|
82
84
|
this.walk(node)
|
|
83
85
|
this.scopeManager.exitScope() // Clean up the root scope
|
|
@@ -133,6 +135,29 @@ export class ASTVisitors {
|
|
|
133
135
|
|
|
134
136
|
const child = node[key]
|
|
135
137
|
if (Array.isArray(child)) {
|
|
138
|
+
// Pre-scan array children to register VariableDeclarator-based scopes
|
|
139
|
+
// (e.g., `const { t } = useTranslation(...)`) before walking the rest
|
|
140
|
+
// of the items. This ensures that functions/arrow-functions defined
|
|
141
|
+
// earlier in the same block that reference t will resolve to the
|
|
142
|
+
// correct scope even if the `useTranslation` declarator appears later.
|
|
143
|
+
for (const item of child) {
|
|
144
|
+
if (!item || typeof item !== 'object') continue
|
|
145
|
+
|
|
146
|
+
// Direct declarator present in arrays (rare)
|
|
147
|
+
if (item.type === 'VariableDeclarator') {
|
|
148
|
+
this.scopeManager.handleVariableDeclarator(item)
|
|
149
|
+
continue
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Common case: VariableDeclaration which contains .declarations (VariableDeclarator[])
|
|
153
|
+
if (item.type === 'VariableDeclaration' && Array.isArray(item.declarations)) {
|
|
154
|
+
for (const decl of item.declarations) {
|
|
155
|
+
if (decl && typeof decl === 'object' && decl.type === 'VariableDeclarator') {
|
|
156
|
+
this.scopeManager.handleVariableDeclarator(decl)
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
136
161
|
for (const item of child) {
|
|
137
162
|
// Be less strict: if it's a non-null object, walk it.
|
|
138
163
|
// This allows traversal into nodes that might not have a `.type` property
|
|
@@ -239,86 +239,95 @@ export function extractFromTransComponent (node: JSXElement, config: I18nextTool
|
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
/**
|
|
242
|
-
* Serializes JSX children into a string
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
* - Text nodes are preserved as-is
|
|
246
|
-
* - HTML elements are converted to indexed placeholders or preserved if allowed
|
|
247
|
-
* - JSX expressions become interpolation placeholders: `{{variable}}`
|
|
248
|
-
* - Fragments are flattened
|
|
249
|
-
* - Whitespace is normalized
|
|
250
|
-
*
|
|
251
|
-
* The serialization respects the `transKeepBasicHtmlNodesFor` configuration
|
|
252
|
-
* to determine which HTML tags should be preserved vs. converted to indexed placeholders.
|
|
253
|
-
*
|
|
254
|
-
* @param children - Array of JSX child nodes to serialize
|
|
255
|
-
* @param config - Configuration containing HTML preservation settings
|
|
256
|
-
* @returns Serialized string representation
|
|
257
|
-
*
|
|
258
|
-
* @example
|
|
259
|
-
* ```typescript
|
|
260
|
-
* // JSX: Hello <strong>{{name}}</strong>, you have <Link to="/msgs">{{count}} messages</Link>.
|
|
261
|
-
* // With transKeepBasicHtmlNodesFor: ['strong']
|
|
262
|
-
* // Returns: "Hello <strong>{{name}}</strong>, you have <1>{{count}} messages</1>."
|
|
263
|
-
* // (strong preserved, Link becomes indexed placeholder <1>)
|
|
264
|
-
*
|
|
265
|
-
* const serialized = serializeJSXChildren(children, config)
|
|
266
|
-
* ```
|
|
267
|
-
*
|
|
268
|
-
* @internal
|
|
242
|
+
* Serializes JSX children into a string, correctly indexing component placeholders.
|
|
243
|
+
* This version correctly calculates an element's index based on its position
|
|
244
|
+
* among its sibling *elements*, ignoring text nodes for indexing purposes.
|
|
269
245
|
*/
|
|
270
246
|
function serializeJSXChildren (children: any[], config: I18nextToolkitConfig): string {
|
|
247
|
+
if (!children || children.length === 0) return ''
|
|
248
|
+
|
|
271
249
|
const allowedTags = new Set(config.extract.transKeepBasicHtmlNodesFor ?? ['br', 'strong', 'i', 'p'])
|
|
272
250
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
251
|
+
const isFormattingWhitespace = (n: any) =>
|
|
252
|
+
n &&
|
|
253
|
+
n.type === 'JSXText' &&
|
|
254
|
+
/^\s*$/.test(n.value) &&
|
|
255
|
+
n.value.includes('\n')
|
|
256
|
+
|
|
257
|
+
// counter of "indexable" slots (increments for meaningful text, expression containers and non-preserved elements)
|
|
258
|
+
const counter = { n: 0 }
|
|
259
|
+
|
|
260
|
+
function serialize (nodes: any[]): string {
|
|
261
|
+
if (!nodes || !nodes.length) return ''
|
|
280
262
|
let out = ''
|
|
281
|
-
|
|
282
|
-
|
|
263
|
+
|
|
264
|
+
for (const child of nodes) {
|
|
265
|
+
if (!child) continue
|
|
266
|
+
|
|
283
267
|
if (child.type === 'JSXText') {
|
|
284
|
-
|
|
285
|
-
|
|
268
|
+
if (!isFormattingWhitespace(child)) {
|
|
269
|
+
out += child.value
|
|
270
|
+
counter.n++
|
|
271
|
+
}
|
|
272
|
+
continue
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (child.type === 'JSXExpressionContainer') {
|
|
286
276
|
const expr = child.expression
|
|
277
|
+
if (!expr) continue
|
|
278
|
+
|
|
287
279
|
if (expr.type === 'StringLiteral') {
|
|
288
280
|
out += expr.value
|
|
289
281
|
} else if (expr.type === 'Identifier') {
|
|
290
282
|
out += `{{${expr.value}}}`
|
|
291
283
|
} else if (expr.type === 'ObjectExpression') {
|
|
292
|
-
// Handle object expressions like {{bar: 1}} -> {{bar}}
|
|
293
284
|
const prop = expr.properties[0]
|
|
294
285
|
if (prop && prop.type === 'KeyValueProperty' && prop.key && prop.key.type === 'Identifier') {
|
|
295
286
|
out += `{{${prop.key.value}}}`
|
|
296
287
|
} else if (prop && prop.type === 'Identifier') {
|
|
297
|
-
// Handle the case where properties[0] is directly an Identifier
|
|
298
288
|
out += `{{${prop.value}}}`
|
|
299
289
|
}
|
|
290
|
+
} else if (expr.type === 'MemberExpression' && expr.property && expr.property.type === 'Identifier') {
|
|
291
|
+
out += `{{${expr.property.value}}}`
|
|
292
|
+
} else if (expr.type === 'CallExpression' && expr.callee?.type === 'Identifier') {
|
|
293
|
+
out += `{{${expr.callee.value}}}`
|
|
300
294
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
295
|
+
// expression containers (including explicit {' '}) consume a slot
|
|
296
|
+
counter.n++
|
|
297
|
+
continue
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (child.type === 'JSXElement') {
|
|
301
|
+
let tag: string | undefined
|
|
302
|
+
if (child.opening && child.opening.name && child.opening.name.type === 'Identifier') {
|
|
304
303
|
tag = child.opening.name.value
|
|
305
304
|
}
|
|
306
305
|
|
|
307
|
-
const innerContent = serializeChildren(child.children)
|
|
308
|
-
|
|
309
306
|
if (tag && allowedTags.has(tag)) {
|
|
310
|
-
//
|
|
311
|
-
|
|
307
|
+
// preserved HTML tag: do NOT consume a numeric slot for the tag itself
|
|
308
|
+
const inner = serialize(child.children || [])
|
|
309
|
+
out += `<${tag}>${inner}</${tag}>`
|
|
312
310
|
} else {
|
|
313
|
-
//
|
|
314
|
-
|
|
311
|
+
// non-preserved element: use current counter value as numeric index, then consume the slot
|
|
312
|
+
const myIndex = counter.n
|
|
313
|
+
counter.n++
|
|
314
|
+
const inner = serialize(child.children || [])
|
|
315
|
+
out += `<${myIndex}>${inner}</${myIndex}>`
|
|
315
316
|
}
|
|
316
|
-
|
|
317
|
-
|
|
317
|
+
continue
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (child.type === 'JSXFragment') {
|
|
321
|
+
out += serialize(child.children || [])
|
|
322
|
+
continue
|
|
318
323
|
}
|
|
319
|
-
|
|
324
|
+
|
|
325
|
+
// unknown node types: ignore
|
|
326
|
+
}
|
|
327
|
+
|
|
320
328
|
return out
|
|
321
329
|
}
|
|
322
330
|
|
|
323
|
-
|
|
331
|
+
const result = serialize(children)
|
|
332
|
+
return String(result).replace(/\s+/g, ' ').trim()
|
|
324
333
|
}
|
|
@@ -11,6 +11,18 @@ export class ScopeManager {
|
|
|
11
11
|
this.config = config
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Reset per-file scope state.
|
|
16
|
+
*
|
|
17
|
+
* This clears both the scope stack and the legacy scope map. It should be
|
|
18
|
+
* called at the start of processing each file so that scope info does not
|
|
19
|
+
* leak between files.
|
|
20
|
+
*/
|
|
21
|
+
public reset (): void {
|
|
22
|
+
this.scopeStack = []
|
|
23
|
+
this.scope = new Map()
|
|
24
|
+
}
|
|
25
|
+
|
|
14
26
|
/**
|
|
15
27
|
* Enters a new variable scope by pushing a new scope map onto the stack.
|
|
16
28
|
* Used when entering functions to isolate variable declarations.
|
package/src/locize.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { execa } from 'execa'
|
|
|
2
2
|
import chalk from 'chalk'
|
|
3
3
|
import ora from 'ora'
|
|
4
4
|
import inquirer from 'inquirer'
|
|
5
|
-
import { resolve } from 'node:path'
|
|
5
|
+
import { resolve, sep } from 'node:path'
|
|
6
6
|
import type { I18nextToolkitConfig } from './types'
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -143,7 +143,15 @@ function buildArgs (command: string, config: I18nextToolkitConfig, cliOptions: a
|
|
|
143
143
|
if (dryRun) commandArgs.push('--dry', 'true')
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
|
|
146
|
+
// Normalize path separators in the configured output so splitting works on both POSIX and Windows
|
|
147
|
+
const outputNormalized = String(extract.output || '').replace(/\\/g, '/')
|
|
148
|
+
const baseCandidate = outputNormalized.includes('/{{language}}/')
|
|
149
|
+
? outputNormalized.split('/{{language}}/')[0]
|
|
150
|
+
: outputNormalized.replace('{{language}}', '')
|
|
151
|
+
// Convert to OS-specific separators before resolving so the resulting path uses path.sep
|
|
152
|
+
const baseCandidateWithSep = baseCandidate.split('/').join(sep)
|
|
153
|
+
const basePath = resolve(process.cwd(), baseCandidateWithSep)
|
|
154
|
+
|
|
147
155
|
commandArgs.push('--path', basePath)
|
|
148
156
|
|
|
149
157
|
return commandArgs
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast-visitors.d.ts","sourceRoot":"","sources":["../../../src/extractor/core/ast-visitors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAQ,MAAM,WAAW,CAAA;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAM1G;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAC9D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAC/B,OAAO,CAAC,KAAK,CAAiB;IAE9B,IAAW,UAAU,gBAEpB;IAED,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;IAC3C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAoB;IACvD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAuB;IAC7D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IAEvC;;;;;;OAMG;gBAED,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,EAC7C,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,eAAe;IAkBzB;;;;;OAKG;IACI,KAAK,CAAE,IAAI,EAAE,MAAM,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"ast-visitors.d.ts","sourceRoot":"","sources":["../../../src/extractor/core/ast-visitors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAQ,MAAM,WAAW,CAAA;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAM1G;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAC9D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAC/B,OAAO,CAAC,KAAK,CAAiB;IAE9B,IAAW,UAAU,gBAEpB;IAED,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;IAC3C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAoB;IACvD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAuB;IAC7D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IAEvC;;;;;;OAMG;gBAED,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,EAC7C,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,eAAe;IAkBzB;;;;;OAKG;IACI,KAAK,CAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAQjC;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,IAAI;IAkFZ;;;;;;;;OAQG;IACI,eAAe,CAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;CAG7D"}
|
|
@@ -5,6 +5,14 @@ export declare class ScopeManager {
|
|
|
5
5
|
private config;
|
|
6
6
|
private scope;
|
|
7
7
|
constructor(config: Omit<I18nextToolkitConfig, 'plugins'>);
|
|
8
|
+
/**
|
|
9
|
+
* Reset per-file scope state.
|
|
10
|
+
*
|
|
11
|
+
* This clears both the scope stack and the legacy scope map. It should be
|
|
12
|
+
* called at the start of processing each file so that scope info does not
|
|
13
|
+
* leak between files.
|
|
14
|
+
*/
|
|
15
|
+
reset(): void;
|
|
8
16
|
/**
|
|
9
17
|
* Enters a new variable scope by pushing a new scope map onto the stack.
|
|
10
18
|
* Used when entering functions to isolate variable declarations.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope-manager.d.ts","sourceRoot":"","sources":["../../../src/extractor/parsers/scope-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAkB,MAAM,WAAW,CAAA;AACnE,OAAO,KAAK,EAAE,SAAS,EAA4B,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAG5F,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,KAAK,CAAqE;gBAErE,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC;IAI1D;;;OAGG;IACH,UAAU,IAAK,IAAI;IAInB;;;OAGG;IACH,SAAS,IAAK,IAAI;IAIlB;;;;;;OAMG;IACH,aAAa,CAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAMnD;;;;;;OAMG;IACH,eAAe,CAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAkBrD;;;;;;;;;;OAUG;IACH,wBAAwB,CAAE,IAAI,EAAE,kBAAkB,GAAG,IAAI;IAsCzD;;;;;;;;OAQG;IACH,OAAO,CAAC,uBAAuB;IAoB/B;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,+BAA+B;IAmEvC;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,8BAA8B;IAwDtC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,yBAAyB;CAmBlC"}
|
|
1
|
+
{"version":3,"file":"scope-manager.d.ts","sourceRoot":"","sources":["../../../src/extractor/parsers/scope-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAkB,MAAM,WAAW,CAAA;AACnE,OAAO,KAAK,EAAE,SAAS,EAA4B,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAG5F,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,KAAK,CAAqE;gBAErE,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC;IAI1D;;;;;;OAMG;IACI,KAAK,IAAK,IAAI;IAKrB;;;OAGG;IACH,UAAU,IAAK,IAAI;IAInB;;;OAGG;IACH,SAAS,IAAK,IAAI;IAIlB;;;;;;OAMG;IACH,aAAa,CAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAMnD;;;;;;OAMG;IACH,eAAe,CAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAkBrD;;;;;;;;;;OAUG;IACH,wBAAwB,CAAE,IAAI,EAAE,kBAAkB,GAAG,IAAI;IAsCzD;;;;;;;;OAQG;IACH,OAAO,CAAC,uBAAuB;IAoB/B;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,+BAA+B;IAmEvC;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,8BAA8B;IAwDtC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,yBAAyB;CAmBlC"}
|
package/types/locize.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locize.d.ts","sourceRoot":"","sources":["../src/locize.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"locize.d.ts","sourceRoot":"","sources":["../src/locize.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAwOnD,eAAO,MAAM,aAAa,GAAI,QAAQ,oBAAoB,EAAE,aAAa,GAAG,kBAAiD,CAAA;AAC7H,eAAO,MAAM,iBAAiB,GAAI,QAAQ,oBAAoB,EAAE,aAAa,GAAG,kBAAqD,CAAA;AACrI,eAAO,MAAM,gBAAgB,GAAI,QAAQ,oBAAoB,EAAE,aAAa,GAAG,kBAAoD,CAAA"}
|