i18next-cli 0.9.7 → 0.9.8
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 +5 -1
- package/README.md +3 -0
- package/dist/cjs/cli.js +1 -1
- package/dist/cjs/config.js +1 -1
- package/dist/cjs/extractor/core/extractor.js +1 -1
- package/dist/cjs/extractor/core/key-finder.js +1 -1
- package/dist/cjs/extractor/core/translation-manager.js +1 -1
- package/dist/cjs/extractor/parsers/ast-visitors.js +1 -1
- package/dist/cjs/status.js +1 -1
- package/dist/esm/cli.js +1 -1
- package/dist/esm/config.js +1 -1
- package/dist/esm/extractor/core/extractor.js +1 -1
- package/dist/esm/extractor/core/key-finder.js +1 -1
- package/dist/esm/extractor/core/translation-manager.js +1 -1
- package/dist/esm/extractor/parsers/ast-visitors.js +1 -1
- package/dist/esm/status.js +1 -1
- package/package.json +1 -1
- package/src/cli.ts +1 -1
- package/src/config.ts +10 -9
- package/src/extractor/core/extractor.ts +12 -18
- package/src/extractor/core/key-finder.ts +8 -4
- package/src/extractor/core/translation-manager.ts +7 -1
- package/src/extractor/parsers/ast-visitors.ts +41 -15
- package/src/status.ts +1 -1
- package/src/types.ts +2 -2
- package/types/config.d.ts +3 -3
- package/types/config.d.ts.map +1 -1
- package/types/extractor/core/extractor.d.ts +2 -1
- package/types/extractor/core/extractor.d.ts.map +1 -1
- package/types/extractor/core/key-finder.d.ts +4 -1
- package/types/extractor/core/key-finder.d.ts.map +1 -1
- package/types/extractor/core/translation-manager.d.ts +1 -1
- package/types/extractor/core/translation-manager.d.ts.map +1 -1
- package/types/extractor/parsers/ast-visitors.d.ts +1 -0
- package/types/extractor/parsers/ast-visitors.d.ts.map +1 -1
- package/types/types.d.ts +2 -2
- package/types/types.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,10 +5,14 @@ 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.0.0](https://github.com/i18next/i18next-cli/compare/v0.9.
|
|
8
|
+
## [1.0.0](https://github.com/i18next/i18next-cli/compare/v0.9.8...v1.0.0) - 2025-xx-yy
|
|
9
9
|
|
|
10
10
|
- not yet released
|
|
11
11
|
|
|
12
|
+
## [0.9.8] - 2025-09-25
|
|
13
|
+
|
|
14
|
+
- support t returnObjects
|
|
15
|
+
|
|
12
16
|
## [0.9.7] - 2025-09-25
|
|
13
17
|
|
|
14
18
|
- support t key fallbacks
|
package/README.md
CHANGED
|
@@ -482,6 +482,9 @@ t('key', { name: 'John' })
|
|
|
482
482
|
t(['key.primary', 'key.fallback']);
|
|
483
483
|
t(['key.primary', 'key.fallback'], 'The fallback value');
|
|
484
484
|
t(['key.primary', 'key.fallback'], { defaultValue: 'The fallback value' });
|
|
485
|
+
|
|
486
|
+
// With structured content (returnObjects)
|
|
487
|
+
t('countries', { returnObjects: true });
|
|
485
488
|
```
|
|
486
489
|
|
|
487
490
|
### React Components
|
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"),o=require("glob"),n=require("chalk"),i=require("./config.js"),a=require("./heuristic-config.js"),r=require("./extractor/core/extractor.js");require("node:fs/promises"),require("node:path");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("0.9.
|
|
2
|
+
"use strict";var e=require("commander"),t=require("chokidar"),o=require("glob"),n=require("chalk"),i=require("./config.js"),a=require("./heuristic-config.js"),r=require("./extractor/core/extractor.js");require("node:fs/promises"),require("node:path");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("0.9.8"),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.").action(async e=>{const a=await i.ensureConfig(),c=async()=>{const t=await r.runExtractor(a);e.ci&&t&&(console.error(n.red.bold("\n[CI Mode] Error: Translation files were updated. Please commit the changes.")),console.log(n.yellow("💡 Tip: Tired of committing JSON files? locize syncs your team automatically => https://www.locize.com/docs/getting-started")),console.log(` Learn more: ${n.cyan("npx i18next-cli locize-sync")}`),process.exit(1))};if(await c(),e.watch){console.log("\nWatching for changes...");t.watch(await o.glob(a.extract.input),{ignored:/node_modules/,persistent:!0}).on("change",e=>{console.log(`\nFile changed: ${e}`),c()})}}),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 o=await i.loadConfig();if(!o){console.log(n.blue("No config file found. Attempting to detect project structure..."));const e=await a.detectConfig();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!")),o=e}await g.runStatus(o,{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 n=await i.ensureConfig(),a=()=>c.runTypesGenerator(n);if(await a(),e.watch){console.log("\nWatching for changes...");t.watch(await o.glob(n.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").description("Migrate a legacy i18next-parser.config.js to the new format.").action(async()=>{await l.runMigrator()}),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.").action(async()=>{let e=await i.loadConfig();if(!e){console.log(n.blue("No config file found. Attempting to detect project structure..."));const t=await a.detectConfig();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 i1e-toolkit init")}`),process.exit(1)),console.log(n.green("Project structure detected successfully!")),e=t}await d.runLinter(e)}),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);
|
package/dist/cjs/config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("node:path"),r=require("node:url"),n=require("node:fs/promises"),
|
|
1
|
+
"use strict";var e=require("node:path"),r=require("node:url"),n=require("node:fs/promises"),t=require("jiti"),o=require("inquirer"),i=require("chalk"),a=require("./init.js"),c=require("./utils/logger.js"),u="undefined"!=typeof document?document.currentScript:null;const s=["i18next.config.ts","i18next.config.js","i18next.config.mjs","i18next.config.cjs"];async function l(o=new c.ConsoleLogger){const i=await async function(){for(const r of s){const t=e.resolve(process.cwd(),r);try{return await n.access(t),t}catch{}}return null}();if(!i)return null;try{let e;if(i.endsWith(".ts")){const r=t.createJiti("undefined"==typeof document?require("url").pathToFileURL(__filename).href:u&&"SCRIPT"===u.tagName.toUpperCase()&&u.src||new URL("config.js",document.baseURI).href),n=await r.import(i,{default:!0});e=n}else{const n=r.pathToFileURL(i).href,t=await import(`${n}?t=${Date.now()}`);e=t.default}return e?(e.extract||={},e.extract.primaryLanguage||=e.locales[0]||"en",e.extract.secondaryLanguages||=e.locales.filter(r=>r!==e.extract.primaryLanguage),e):(o.error(`Error: No default export found in ${i}`),null)}catch(e){return o.error(`Error loading configuration from ${i}`),o.error(e),null}}exports.defineConfig=function(e){return e},exports.ensureConfig=async function(e=new c.ConsoleLogger){let r=await l();if(r)return r;const{shouldInit:n}=await o.prompt([{type:"confirm",name:"shouldInit",message:i.yellow("Configuration file not found. Would you like to create one now?"),default:!0}]);if(n){if(await a.runInit(),e.info(i.green("Configuration created. Resuming command...")),r=await l(),r)return r;e.error(i.red("Error: Failed to load configuration after creation. Please try running the command again.")),process.exit(1)}else e.info("Operation cancelled. Please create a configuration file to proceed."),process.exit(0)},exports.loadConfig=l;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var e=require("ora"),t=require("chalk"),r=require("@swc/core"),a=require("node:fs/promises"),n=require("node:path"),o=require("./key-finder.js"),s=require("./translation-manager.js"),i=require("../../utils/validation.js"),c=require("../plugin-manager.js"),l=require("../parsers/comment-parser.js"),u=require("../../utils/logger.js");function g(e,t,r,a=new u.ConsoleLogger){if(e&&"object"==typeof e){for(const n of t)try{n.onVisitNode?.(e,r)}catch(e){a.warn(`Plugin ${n.name} onVisitNode failed:`,e)}for(const n of Object.keys(e)){const o=e[n];if(Array.isArray(o))for(const e of o)e&&"object"==typeof e&&g(e,t,r,a);else o&&"object"==typeof o&&g(o,t,r,a)}}}exports.extract=async function(e){e.extract.primaryLanguage||(e.extract.primaryLanguage=e.locales[0]),e.extract.secondaryLanguages||(e.extract.secondaryLanguages=e.locales.filter(t=>t!==e?.extract?.primaryLanguage)),e.extract.functions||(e.extract.functions=["t"]),e.extract.transComponents||(e.extract.transComponents=["Trans"]);const{allKeys:t,objectKeys:r}=await o.findKeys(e);return s.getTranslations(t,r,e)},exports.processFile=async function(e,t,n,o,s=new u.ConsoleLogger){try{let i=await a.readFile(e,"utf-8");for(const r of t.plugins||[])i=await(r.onLoad?.(i,e))??i;const u=await r.parse(i,{syntax:"typescript",tsx:!0,comments:!0}),f=c.createPluginContext(n);l.extractKeysFromComments(i,t.extract.functions||["t"],f,t),o.visit(u),(t.plugins||[]).length>0&&g(u,t.plugins||[],f,s)}catch(t){throw new i.ExtractorError("Failed to process file",e,t)}},exports.runExtractor=async function(r,c=new u.ConsoleLogger){r.extract.primaryLanguage||(r.extract.primaryLanguage=r.locales[0]||"en"),r.extract.secondaryLanguages||(r.extract.secondaryLanguages=r.locales.filter(e=>e!==r?.extract?.primaryLanguage)),i.validateExtractorConfig(r);const l=e("Running i18next key extractor...\n").start();try{const{allKeys:e,objectKeys:i}=await o.findKeys(r,c);l.text=`Found ${e.size} unique keys. Updating translation files...`;const u=await s.getTranslations(e,i,r);let g=!1;for(const e of u)e.updated&&(g=!0,await a.mkdir(n.dirname(e.path),{recursive:!0}),await a.writeFile(e.path,JSON.stringify(e.newTranslations,null,2)),c.info(t.green(`Updated: ${e.path}`)));return l.succeed(t.bold("Extraction complete!")),g}catch(e){throw l.fail(t.red("Extraction failed.")),e}};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("glob"),
|
|
1
|
+
"use strict";var e=require("glob"),r=require("./extractor.js"),s=require("../../utils/logger.js"),i=require("../plugin-manager.js"),t=require("../parsers/ast-visitors.js");exports.findKeys=async function(n,o=new s.ConsoleLogger){const a=await async function(r){return await e.glob(r.extract.input,{ignore:"node_modules/**",cwd:process.cwd()})}(n),u=new Map,c=new t.ASTVisitors(n,i.createPluginContext(u),o);await i.initializePlugins(n.plugins||[]);for(const e of a)await r.processFile(e,n,u,c,o);for(const e of n.plugins||[])await(e.onEnd?.(u));return{allKeys:u,objectKeys:c.objectKeys}};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("node:fs/promises"),t=require("node:path"),
|
|
1
|
+
"use strict";var e=require("node:fs/promises"),t=require("node:path"),s=require("../../utils/nested-object.js"),a=require("../../utils/file-utils.js");function r(e){const t=`^${e.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*")}$`;return new RegExp(t)}exports.getTranslations=async function(n,o,c){const u=c.extract.defaultNS??"translation",l=c.extract.keySeparator??".",i=[...c.extract.preservePatterns||[]];for(const e of o)i.push(`${e}.*`);const p=i.map(r);c.extract.primaryLanguage||(c.extract.primaryLanguage=c.locales[0]||"en"),c.extract.secondaryLanguages||(c.extract.secondaryLanguages=c.locales.filter(e=>e!==c.extract.primaryLanguage));const g=new Map;for(const e of n.values()){const t=e.ns||u;g.has(t)||g.set(t,[]),g.get(t).push(e)}const f=[];for(const r of c.locales)for(const[n,o]of g.entries()){const u=a.getOutputPath(c.extract.output,r,n),i=t.resolve(process.cwd(),u);let g="",d={};try{g=await e.readFile(i,"utf-8"),d=JSON.parse(g)}catch(e){}const x={},y=s.getNestedKeys(d,l);for(const e of y)if(p.some(t=>t.test(e))){const t=s.getNestedValue(d,e,l);s.setNestedValue(x,e,t,l)}const h=!1===c.extract.sort?o:o.sort((e,t)=>e.key.localeCompare(t.key));for(const{key:e,defaultValue:t}of h){const a=s.getNestedValue(d,e,l)??(r===c.extract?.primaryLanguage?t:"");s.setNestedValue(x,e,a,l)}const m=c.extract.indentation??2,N=JSON.stringify(x,null,m);f.push({path:i,updated:N!==g,newTranslations:x,existingTranslations:d})}return f};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("./jsx-parser.js");exports.ASTVisitors=class{pluginContext;config;logger;scopeStack=[];constructor(e,t,n){this.pluginContext=t,this.config=e,this.logger=n}visit(e){this.enterScope(),this.walk(e),this.exitScope()}walk(e){if(!e)return;let t=!1;switch("Function"!==e.type&&"ArrowFunctionExpression"!==e.type&&"FunctionExpression"!==e.type||(this.enterScope(),t=!0),e.type){case"VariableDeclarator":this.handleVariableDeclarator(e);break;case"CallExpression":this.handleCallExpression(e);break;case"JSXElement":this.handleJSXElement(e)}for(const t in e){if("span"===t)continue;const n=e[t];if(Array.isArray(n))for(const e of n)e&&"object"==typeof e&&e.type&&this.walk(e);else n&&n.type&&this.walk(n)}t&&this.exitScope()}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)}handleVariableDeclarator(e){if("CallExpression"!==e.init?.type)return;const t=e.init.callee;"Identifier"===t.type&&(this.config.extract.useTranslationNames||["useTranslation","getT","useT"]).indexOf(t.value)>-1?this.handleUseTranslationDeclarator(e):"MemberExpression"===t.type&&"Identifier"===t.property.type&&"getFixedT"===t.property.value&&this.handleGetFixedTDeclarator(e)}handleUseTranslationDeclarator(e){if(!e.init||"CallExpression"!==e.init.type)return;let t;if("ArrayPattern"===e.id.type){const n=e.id.elements[0];"Identifier"===n?.type&&(t=n.value)}if("ObjectPattern"===e.id.type)for(const n of e.id.properties){if("AssignmentPatternProperty"===n.type&&"Identifier"===n.key.type&&"t"===n.key.value){t="t";break}if("KeyValuePatternProperty"===n.type&&"Identifier"===n.key.type&&"t"===n.key.value&&"Identifier"===n.value.type){t=n.value.value;break}}if(!t)return;const n=e.init.arguments?.[0]?.expression;let i;"StringLiteral"===n?.type?i=n.value:"ArrayExpression"===n?.type&&"StringLiteral"===n.elements[0]?.expression.type&&(i=n.elements[0].expression.value);const r=e.init.arguments?.[1]?.expression;let s;"ObjectExpression"===r?.type
|
|
1
|
+
"use strict";var e=require("./jsx-parser.js");exports.ASTVisitors=class{pluginContext;config;logger;scopeStack=[];objectKeys=new Set;constructor(e,t,n){this.pluginContext=t,this.config=e,this.logger=n}visit(e){this.enterScope(),this.walk(e),this.exitScope()}walk(e){if(!e)return;let t=!1;switch("Function"!==e.type&&"ArrowFunctionExpression"!==e.type&&"FunctionExpression"!==e.type||(this.enterScope(),t=!0),e.type){case"VariableDeclarator":this.handleVariableDeclarator(e);break;case"CallExpression":this.handleCallExpression(e);break;case"JSXElement":this.handleJSXElement(e)}for(const t in e){if("span"===t)continue;const n=e[t];if(Array.isArray(n))for(const e of n)e&&"object"==typeof e&&e.type&&this.walk(e);else n&&n.type&&this.walk(n)}t&&this.exitScope()}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)}handleVariableDeclarator(e){if("CallExpression"!==e.init?.type)return;const t=e.init.callee;"Identifier"===t.type&&(this.config.extract.useTranslationNames||["useTranslation","getT","useT"]).indexOf(t.value)>-1?this.handleUseTranslationDeclarator(e):"MemberExpression"===t.type&&"Identifier"===t.property.type&&"getFixedT"===t.property.value&&this.handleGetFixedTDeclarator(e)}handleUseTranslationDeclarator(e){if(!e.init||"CallExpression"!==e.init.type)return;let t;if("ArrayPattern"===e.id.type){const n=e.id.elements[0];"Identifier"===n?.type&&(t=n.value)}if("ObjectPattern"===e.id.type)for(const n of e.id.properties){if("AssignmentPatternProperty"===n.type&&"Identifier"===n.key.type&&"t"===n.key.value){t="t";break}if("KeyValuePatternProperty"===n.type&&"Identifier"===n.key.type&&"t"===n.key.value&&"Identifier"===n.value.type){t=n.value.value;break}}if(!t)return;const n=e.init.arguments?.[0]?.expression;let i;"StringLiteral"===n?.type?i=n.value:"ArrayExpression"===n?.type&&"StringLiteral"===n.elements[0]?.expression.type&&(i=n.elements[0].expression.value);const r=e.init.arguments?.[1]?.expression;let s;if("ObjectExpression"===r?.type){const e=this.getObjectPropValue(r,"keyPrefix");s="string"==typeof e?e:void 0}this.setVarInScope(t,{defaultNs:i,keyPrefix:s})}handleGetFixedTDeclarator(e){if("Identifier"!==e.id.type||!e.init||"CallExpression"!==e.init.type)return;const t=e.id.value,n=e.init.arguments,i=n[1]?.expression,r=n[2]?.expression,s="StringLiteral"===i?.type?i.value:void 0,a="StringLiteral"===r?.type?r.value:void 0;(s||a)&&this.setVarInScope(t,{defaultNs:s,keyPrefix:a})}handleCallExpression(e){const t=e.callee;if("Identifier"!==t.type)return;const n=this.getVarFromScope(t.value);if(!((this.config.extract.functions||[]).includes(t.value)||void 0!==n)||0===e.arguments.length)return;const i=e.arguments[0].expression,r=[];if("StringLiteral"===i.type)r.push(i.value);else if("ArrowFunctionExpression"===i.type){const e=this.extractKeyFromSelector(i);e&&r.push(e)}else if("ArrayExpression"===i.type)for(const e of i.elements)"StringLiteral"===e?.expression.type&&r.push(e.expression.value);if(0===r.length)return;const s=e.arguments.length>1?e.arguments[1].expression:void 0,a=this.getDefaultValue(e,r[r.length-1]);for(let e=0;e<r.length;e++){let t,i=r[e];if("ObjectExpression"===s?.type){const e=this.getObjectPropValue(s,"ns");"string"==typeof e&&(t=e)}!t&&n?.defaultNs&&(t=n.defaultNs);const o=this.config.extract.nsSeparator??":";if(!t&&o&&i.includes(o)){const e=i.split(o);t=e.shift(),i=e.join(o)}t||(t=this.config.extract.defaultNS);let l=i;if(n?.keyPrefix){const e=this.config.extract.keySeparator??".";l=`${n.keyPrefix}${e}${i}`}const p=e===r.length-1?a:i;let u=!1;if("ObjectExpression"===s?.type){const e=this.getObjectPropValue(s,"context");if("string"==typeof e&&e){const n=this.config.extract.contextSeparator??"_";this.pluginContext.addKey({key:`${l}${n}${e}`,ns:t,defaultValue:p}),u=!0}u||void 0===this.getObjectPropValue(s,"count")||(this.handlePluralKeys(l,p,t),u=!0),u||!0!==this.getObjectPropValue(s,"returnObjects")||this.objectKeys.add(l)}u||this.pluginContext.addKey({key:l,ns:t,defaultValue:p})}}handlePluralKeys(e,t,n){try{const i=new Intl.PluralRules(this.config.extract?.primaryLanguage).resolvedOptions().pluralCategories,r=this.config.extract.pluralSeparator??"_";for(const s of i)this.pluginContext.addKey({key:`${e}${r}${s}`,ns:n,defaultValue:t,hasCount:!0})}catch(i){this.logger.warn(`Could not determine plural rules for language "${this.config.extract?.primaryLanguage}". Falling back to simple key extraction.`),this.pluginContext.addKey({key:e,defaultValue:t,ns:n})}}getDefaultValue(e,t){if(e.arguments.length<=1)return t;const n=e.arguments[1].expression;if("StringLiteral"===n.type)return n.value||t;if("ObjectExpression"===n.type){const e=this.getObjectPropValue(n,"defaultValue");return"string"==typeof e?e||t:"number"==typeof e||"boolean"==typeof e?String(e):t}return t}handleJSXElement(t){const n=this.getElementName(t);if(n&&(this.config.extract.transComponents||["Trans"]).includes(n)){const n=e.extractFromTransComponent(t,this.config);if(n){if(!n.ns){const e=t.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"t"===e.name.value);if("JSXAttribute"===e?.type&&"JSXExpressionContainer"===e.value?.type&&"Identifier"===e.value.expression.type){const t=e.value.expression.value,i=this.getVarFromScope(t);i?.defaultNs&&(n.ns=i.defaultNs)}}n.ns||(n.ns=this.config.extract.defaultNS),n.hasCount?this.handlePluralKeys(n.key,n.defaultValue,n.ns):this.pluginContext.addKey(n)}}}getElementName(e){if("Identifier"===e.opening.name.type)return e.opening.name.value;if("JSXMemberExpression"===e.opening.name.type){let t=e.opening.name;const n=[];for(;"JSXMemberExpression"===t.type;)"Identifier"===t.property.type&&n.unshift(t.property.value),t=t.object;return"Identifier"===t.type&&n.unshift(t.value),n.join(".")}}getObjectPropValue(e,t){const n=e.properties.find(e=>"KeyValueProperty"===e.type&&("Identifier"===e.key?.type&&e.key.value===t||"StringLiteral"===e.key?.type&&e.key.value===t));if("KeyValueProperty"===n?.type){const e=n.value;return"StringLiteral"===e.type||("BooleanLiteral"===e.type||"NumericLiteral"===e.type)?e.value:""}}extractKeyFromSelector(e){let t=e.body;if("BlockStatement"===t.type){const e=t.stmts.find(e=>"ReturnStatement"===e.type);if("ReturnStatement"!==e?.type||!e.argument)return null;t=e.argument}let n=t;const i=[];for(;"MemberExpression"===n.type;){const e=n.property;if("Identifier"===e.type)i.unshift(e.value);else{if("Computed"!==e.type||"StringLiteral"!==e.expression.type)return null;i.unshift(e.expression.value)}n=n.object}if(i.length>0){const e=this.config.extract.keySeparator,t="string"==typeof e?e:".";return i.join(t)}return null}};
|
package/dist/cjs/status.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("chalk"),o=require("ora"),t=require("node:path"),a=require("node:fs/promises"),s=require("./extractor/core/key-finder.js"),n=require("./utils/nested-object.js"),r=require("./utils/file-utils.js");function l(o,t,a){const s=a>0?Math.round(t/a*100):100,n=c(s);console.log(`${e.bold(o)}: ${n} ${s}% (${t}/${a})`)}function c(o){const t=Math.round(o/100*20),a=20-t;return`[${e.green("".padStart(t,"■"))}${"".padStart(a,"□")}]`}function i(){console.log(e.yellow.bold("\n✨ Take your localization to the next level!")),console.log("Manage translations with your team in the cloud with locize => https://www.locize.com/docs/getting-started"),console.log(`Run ${e.cyan("npx i18next-cli locize-migrate")} to get started.`)}exports.runStatus=async function(u,y={}){u.extract.primaryLanguage||(u.extract.primaryLanguage=u.locales[0]||"en"),u.extract.secondaryLanguages||(u.extract.secondaryLanguages=u.locales.filter(e=>e!==u?.extract?.primaryLanguage));const d=o("Analyzing project localization status...\n").start();try{const o=await async function(e){const
|
|
1
|
+
"use strict";var e=require("chalk"),o=require("ora"),t=require("node:path"),a=require("node:fs/promises"),s=require("./extractor/core/key-finder.js"),n=require("./utils/nested-object.js"),r=require("./utils/file-utils.js");function l(o,t,a){const s=a>0?Math.round(t/a*100):100,n=c(s);console.log(`${e.bold(o)}: ${n} ${s}% (${t}/${a})`)}function c(o){const t=Math.round(o/100*20),a=20-t;return`[${e.green("".padStart(t,"■"))}${"".padStart(a,"□")}]`}function i(){console.log(e.yellow.bold("\n✨ Take your localization to the next level!")),console.log("Manage translations with your team in the cloud with locize => https://www.locize.com/docs/getting-started"),console.log(`Run ${e.cyan("npx i18next-cli locize-migrate")} to get started.`)}exports.runStatus=async function(u,y={}){u.extract.primaryLanguage||(u.extract.primaryLanguage=u.locales[0]||"en"),u.extract.secondaryLanguages||(u.extract.secondaryLanguages=u.locales.filter(e=>e!==u?.extract?.primaryLanguage));const d=o("Analyzing project localization status...\n").start();try{const o=await async function(e){const{allKeys:o}=await s.findKeys(e),{primaryLanguage:l,keySeparator:c=".",defaultNS:i="translation"}=e.extract,u=e.locales.filter(e=>e!==l),y=new Map;for(const e of o.values()){const o=e.ns||i;y.has(o)||y.set(o,[]),y.get(o).push(e)}const d={totalKeys:o.size,keysByNs:y,locales:new Map};for(const o of u){let s=0;const l=new Map;for(const[i,u]of y.entries()){const y=r.getOutputPath(e.extract.output,o,i);let d={};try{const e=await a.readFile(t.resolve(process.cwd(),y),"utf-8");d=JSON.parse(e)}catch{}let g=0;const f=u.map(({key:e})=>{const o=!!n.getNestedValue(d,e,c??".");return o&&g++,{key:e,isTranslated:o}});l.set(i,{totalKeys:u.length,translatedKeys:g,keyDetails:f}),s+=g}d.locales.set(o,{totalTranslated:s,namespaces:l})}return d}(u);d.succeed("Analysis complete."),function(o,t,a){a.detail?function(o,t,a,s){if(a===t.extract.primaryLanguage)return void console.log(e.yellow(`Locale "${a}" is the primary language. All keys are considered present.`));if(!t.locales.includes(a))return void console.error(e.red(`Error: Locale "${a}" is not defined in your configuration.`));const n=o.locales.get(a);if(!n)return void console.error(e.red(`Error: Locale "${a}" is not a valid secondary language.`));console.log(e.bold(`\nKey Status for "${e.cyan(a)}":`));const r=Array.from(o.keysByNs.values()).flat().length;l("Overall",n.totalTranslated,r);const c=s?[s]:Array.from(n.namespaces.keys()).sort();for(const o of c){const t=n.namespaces.get(o);t&&(console.log(e.cyan.bold(`\nNamespace: ${o}`)),l("Namespace Progress",t.translatedKeys,t.totalKeys),t.keyDetails.forEach(({key:o,isTranslated:t})=>{const a=t?e.green("✓"):e.red("✗");console.log(` ${a} ${o}`)}))}const u=r-n.totalTranslated;u>0?console.log(e.yellow.bold(`\nSummary: Found ${u} missing translations for "${a}".`)):console.log(e.green.bold(`\nSummary: 🎉 All keys are translated for "${a}".`));i()}(o,t,a.detail,a.namespace):a.namespace?function(o,t,a){const s=o.keysByNs.get(a);if(!s)return void console.error(e.red(`Error: Namespace "${a}" was not found in your source code.`));console.log(e.cyan.bold(`\nStatus for Namespace: "${a}"`)),console.log("------------------------");for(const[e,t]of o.locales.entries()){const o=t.namespaces.get(a);if(o){const t=o.totalKeys>0?Math.round(o.translatedKeys/o.totalKeys*100):100,a=c(t);console.log(`- ${e}: ${a} ${t}% (${o.translatedKeys}/${o.totalKeys} keys)`)}}i()}(o,0,a.namespace):function(o,t){const{primaryLanguage:a}=t.extract;console.log(e.cyan.bold("\ni18next Project Status")),console.log("------------------------"),console.log(`🔑 Keys Found: ${e.bold(o.totalKeys)}`),console.log(`📚 Namespaces Found: ${e.bold(o.keysByNs.size)}`),console.log(`🌍 Locales: ${e.bold(t.locales.join(", "))}`),console.log(`✅ Primary Language: ${e.bold(a)}`),console.log("\nTranslation Progress:");for(const[e,t]of o.locales.entries()){const a=o.totalKeys>0?Math.round(t.totalTranslated/o.totalKeys*100):100,s=c(a);console.log(`- ${e}: ${s} ${a}% (${t.totalTranslated}/${o.totalKeys} keys)`)}i()}(o,t)}(o,u,y)}catch(e){d.fail("Failed to generate status report."),console.error(e)}};
|
package/dist/esm/cli.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Command as o}from"commander";import e from"chokidar";import{glob as t}from"glob";import i from"chalk";import{ensureConfig as n,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:fs/promises";import"node:path";import{runTypesGenerator as s}from"./types-generator.js";import{runSyncer as l}from"./syncer.js";import{runMigrator as m}from"./migrator.js";import{runInit as p}from"./init.js";import{runLinter as d}from"./linter.js";import{runStatus as f}from"./status.js";import{runLocizeSync as g,runLocizeDownload as u,runLocizeMigrate as y}from"./locize.js";const w=new o;w.name("i18next-cli").description("A unified, high-performance i18next CLI.").version("0.9.
|
|
2
|
+
import{Command as o}from"commander";import e from"chokidar";import{glob as t}from"glob";import i from"chalk";import{ensureConfig as n,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:fs/promises";import"node:path";import{runTypesGenerator as s}from"./types-generator.js";import{runSyncer as l}from"./syncer.js";import{runMigrator as m}from"./migrator.js";import{runInit as p}from"./init.js";import{runLinter as d}from"./linter.js";import{runStatus as f}from"./status.js";import{runLocizeSync as g,runLocizeDownload as u,runLocizeMigrate as y}from"./locize.js";const w=new o;w.name("i18next-cli").description("A unified, high-performance i18next CLI.").version("0.9.8"),w.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.").action(async o=>{const a=await n(),c=async()=>{const e=await r(a);o.ci&&e&&(console.error(i.red.bold("\n[CI Mode] Error: Translation files were updated. Please commit the changes.")),console.log(i.yellow("💡 Tip: Tired of committing JSON files? locize syncs your team automatically => https://www.locize.com/docs/getting-started")),console.log(` Learn more: ${i.cyan("npx i18next-cli locize-sync")}`),process.exit(1))};if(await c(),o.watch){console.log("\nWatching for changes...");e.watch(await t(a.extract.input),{ignored:/node_modules/,persistent:!0}).on("change",o=>{console.log(`\nFile changed: ${o}`),c()})}}),w.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(o,e)=>{let t=await a();if(!t){console.log(i.blue("No config file found. Attempting to detect project structure..."));const o=await c();o||(console.error(i.red("Could not automatically detect your project structure.")),console.log(`Please create a config file first by running: ${i.cyan("npx i18next-cli init")}`),process.exit(1)),console.log(i.green("Project structure detected successfully!")),t=o}await f(t,{detail:o,namespace:e.namespace})}),w.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 o=>{const i=await n(),a=()=>s(i);if(await a(),o.watch){console.log("\nWatching for changes...");e.watch(await t(i.types?.input||[]),{persistent:!0}).on("change",o=>{console.log(`\nFile changed: ${o}`),a()})}}),w.command("sync").description("Synchronize secondary language files with the primary language file.").action(async()=>{const o=await n();await l(o)}),w.command("migrate-config").description("Migrate a legacy i18next-parser.config.js to the new format.").action(async()=>{await m()}),w.command("init").description("Create a new i18next.config.ts/js file with an interactive setup wizard.").action(p),w.command("lint").description("Find potential issues like hardcoded strings in your codebase.").action(async()=>{let o=await a();if(!o){console.log(i.blue("No config file found. Attempting to detect project structure..."));const e=await c();e||(console.error(i.red("Could not automatically detect your project structure.")),console.log(`Please create a config file first by running: ${i.cyan("npx i1e-toolkit init")}`),process.exit(1)),console.log(i.green("Project structure detected successfully!")),o=e}await d(o)}),w.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 o=>{const e=await n();await g(e,o)}),w.command("locize-download").description("Download all translations from your locize project.").action(async o=>{const e=await n();await u(e,o)}),w.command("locize-migrate").description("Migrate local translation files to a new locize project.").action(async o=>{const e=await n();await y(e,o)}),w.parse(process.argv);
|
package/dist/esm/config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{resolve as
|
|
1
|
+
import{resolve as r}from"node:path";import{pathToFileURL as t}from"node:url";import{access as o}from"node:fs/promises";import{createJiti as e}from"jiti";import n from"inquirer";import i from"chalk";import{runInit as a}from"./init.js";import{ConsoleLogger as c}from"./utils/logger.js";const f=["i18next.config.ts","i18next.config.js","i18next.config.mjs","i18next.config.cjs"];function l(r){return r}async function s(n=new c){const i=await async function(){for(const t of f){const e=r(process.cwd(),t);try{return await o(e),e}catch{}}return null}();if(!i)return null;try{let r;if(i.endsWith(".ts")){const t=e(import.meta.url),o=await t.import(i,{default:!0});r=o}else{const o=t(i).href,e=await import(`${o}?t=${Date.now()}`);r=e.default}return r?(r.extract||={},r.extract.primaryLanguage||=r.locales[0]||"en",r.extract.secondaryLanguages||=r.locales.filter(t=>t!==r.extract.primaryLanguage),r):(n.error(`Error: No default export found in ${i}`),null)}catch(r){return n.error(`Error loading configuration from ${i}`),n.error(r),null}}async function u(r=new c){let t=await s();if(t)return t;const{shouldInit:o}=await n.prompt([{type:"confirm",name:"shouldInit",message:i.yellow("Configuration file not found. Would you like to create one now?"),default:!0}]);if(o){if(await a(),r.info(i.green("Configuration created. Resuming command...")),t=await s(),t)return t;r.error(i.red("Error: Failed to load configuration after creation. Please try running the command again.")),process.exit(1)}else r.info("Operation cancelled. Please create a configuration file to proceed."),process.exit(0)}export{l as defineConfig,u as ensureConfig,s as loadConfig};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"ora";import a from"chalk";import{parse as
|
|
1
|
+
import t from"ora";import a from"chalk";import{parse as e}from"@swc/core";import{mkdir as r,writeFile as o,readFile as n}from"node:fs/promises";import{dirname as s}from"node:path";import{findKeys as i}from"./key-finder.js";import{getTranslations as c}from"./translation-manager.js";import{validateExtractorConfig as f,ExtractorError as l}from"../../utils/validation.js";import{createPluginContext as p}from"../plugin-manager.js";import{extractKeysFromComments as m}from"../parsers/comment-parser.js";import{ConsoleLogger as u}from"../../utils/logger.js";async function g(e,n=new u){e.extract.primaryLanguage||(e.extract.primaryLanguage=e.locales[0]||"en"),e.extract.secondaryLanguages||(e.extract.secondaryLanguages=e.locales.filter(t=>t!==e?.extract?.primaryLanguage)),f(e);const l=t("Running i18next key extractor...\n").start();try{const{allKeys:t,objectKeys:f}=await i(e,n);l.text=`Found ${t.size} unique keys. Updating translation files...`;const p=await c(t,f,e);let m=!1;for(const t of p)t.updated&&(m=!0,await r(s(t.path),{recursive:!0}),await o(t.path,JSON.stringify(t.newTranslations,null,2)),n.info(a.green(`Updated: ${t.path}`)));return l.succeed(a.bold("Extraction complete!")),m}catch(t){throw l.fail(a.red("Extraction failed.")),t}}async function y(t,a,r,o,s=new u){try{let i=await n(t,"utf-8");for(const e of a.plugins||[])i=await(e.onLoad?.(i,t))??i;const c=await e(i,{syntax:"typescript",tsx:!0,comments:!0}),f=p(r);m(i,a.extract.functions||["t"],f,a),o.visit(c),(a.plugins||[]).length>0&&d(c,a.plugins||[],f,s)}catch(a){throw new l("Failed to process file",t,a)}}function d(t,a,e,r=new u){if(t&&"object"==typeof t){for(const o of a)try{o.onVisitNode?.(t,e)}catch(t){r.warn(`Plugin ${o.name} onVisitNode failed:`,t)}for(const o of Object.keys(t)){const n=t[o];if(Array.isArray(n))for(const t of n)t&&"object"==typeof t&&d(t,a,e,r);else n&&"object"==typeof n&&d(n,a,e,r)}}}async function x(t){t.extract.primaryLanguage||(t.extract.primaryLanguage=t.locales[0]),t.extract.secondaryLanguages||(t.extract.secondaryLanguages=t.locales.filter(a=>a!==t?.extract?.primaryLanguage)),t.extract.functions||(t.extract.functions=["t"]),t.extract.transComponents||(t.extract.transComponents=["Trans"]);const{allKeys:a,objectKeys:e}=await i(t);return c(a,e,t)}export{x as extract,y as processFile,g as runExtractor};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{glob as o}from"glob";import{processFile as t}from"./extractor.js";import{ConsoleLogger as
|
|
1
|
+
import{glob as o}from"glob";import{processFile as t}from"./extractor.js";import{ConsoleLogger as r}from"../../utils/logger.js";import{initializePlugins as n,createPluginContext as s}from"../plugin-manager.js";import{ASTVisitors as a}from"../parsers/ast-visitors.js";async function e(e,i=new r){const c=await async function(t){return await o(t.extract.input,{ignore:"node_modules/**",cwd:process.cwd()})}(e),p=new Map,m=new a(e,s(p),i);await n(e.plugins||[]);for(const o of c)await t(o,e,p,m,i);for(const o of e.plugins||[])await(o.onEnd?.(p));return{allKeys:p,objectKeys:m.objectKeys}}export{e as findKeys};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readFile as t}from"node:fs/promises";import{resolve as e}from"node:path";import{getNestedKeys as a,getNestedValue as
|
|
1
|
+
import{readFile as t}from"node:fs/promises";import{resolve as e}from"node:path";import{getNestedKeys as a,getNestedValue as o,setNestedValue as r}from"../../utils/nested-object.js";import{getOutputPath as s}from"../../utils/file-utils.js";function n(t){const e=`^${t.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*")}$`;return new RegExp(e)}async function c(c,i,p){const f=p.extract.defaultNS??"translation",l=p.extract.keySeparator??".",u=[...p.extract.preservePatterns||[]];for(const t of i)u.push(`${t}.*`);const g=u.map(n);p.extract.primaryLanguage||(p.extract.primaryLanguage=p.locales[0]||"en"),p.extract.secondaryLanguages||(p.extract.secondaryLanguages=p.locales.filter(t=>t!==p.extract.primaryLanguage));const m=new Map;for(const t of c.values()){const e=t.ns||f;m.has(e)||m.set(e,[]),m.get(e).push(t)}const x=[];for(const n of p.locales)for(const[c,i]of m.entries()){const f=s(p.extract.output,n,c),u=e(process.cwd(),f);let m="",y={};try{m=await t(u,"utf-8"),y=JSON.parse(m)}catch(t){}const d={},h=a(y,l);for(const t of h)if(g.some(e=>e.test(t))){const e=o(y,t,l);r(d,t,e,l)}const L=!1===p.extract.sort?i:i.sort((t,e)=>t.key.localeCompare(e.key));for(const{key:t,defaultValue:e}of L){const a=o(y,t,l)??(n===p.extract?.primaryLanguage?e:"");r(d,t,a,l)}const w=p.extract.indentation??2,$=JSON.stringify(d,null,w);x.push({path:u,updated:$!==m,newTranslations:d,existingTranslations:y})}return x}export{c as getTranslations};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{extractFromTransComponent as e}from"./jsx-parser.js";class t{pluginContext;config;logger;scopeStack=[];constructor(e,t,n){this.pluginContext=t,this.config=e,this.logger=n}visit(e){this.enterScope(),this.walk(e),this.exitScope()}walk(e){if(!e)return;let t=!1;switch("Function"!==e.type&&"ArrowFunctionExpression"!==e.type&&"FunctionExpression"!==e.type||(this.enterScope(),t=!0),e.type){case"VariableDeclarator":this.handleVariableDeclarator(e);break;case"CallExpression":this.handleCallExpression(e);break;case"JSXElement":this.handleJSXElement(e)}for(const t in e){if("span"===t)continue;const n=e[t];if(Array.isArray(n))for(const e of n)e&&"object"==typeof e&&e.type&&this.walk(e);else n&&n.type&&this.walk(n)}t&&this.exitScope()}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)}handleVariableDeclarator(e){if("CallExpression"!==e.init?.type)return;const t=e.init.callee;"Identifier"===t.type&&(this.config.extract.useTranslationNames||["useTranslation","getT","useT"]).indexOf(t.value)>-1?this.handleUseTranslationDeclarator(e):"MemberExpression"===t.type&&"Identifier"===t.property.type&&"getFixedT"===t.property.value&&this.handleGetFixedTDeclarator(e)}handleUseTranslationDeclarator(e){if(!e.init||"CallExpression"!==e.init.type)return;let t;if("ArrayPattern"===e.id.type){const n=e.id.elements[0];"Identifier"===n?.type&&(t=n.value)}if("ObjectPattern"===e.id.type)for(const n of e.id.properties){if("AssignmentPatternProperty"===n.type&&"Identifier"===n.key.type&&"t"===n.key.value){t="t";break}if("KeyValuePatternProperty"===n.type&&"Identifier"===n.key.type&&"t"===n.key.value&&"Identifier"===n.value.type){t=n.value.value;break}}if(!t)return;const n=e.init.arguments?.[0]?.expression;let i;"StringLiteral"===n?.type?i=n.value:"ArrayExpression"===n?.type&&"StringLiteral"===n.elements[0]?.expression.type&&(i=n.elements[0].expression.value);const r=e.init.arguments?.[1]?.expression;let s;"ObjectExpression"===r?.type
|
|
1
|
+
import{extractFromTransComponent as e}from"./jsx-parser.js";class t{pluginContext;config;logger;scopeStack=[];objectKeys=new Set;constructor(e,t,n){this.pluginContext=t,this.config=e,this.logger=n}visit(e){this.enterScope(),this.walk(e),this.exitScope()}walk(e){if(!e)return;let t=!1;switch("Function"!==e.type&&"ArrowFunctionExpression"!==e.type&&"FunctionExpression"!==e.type||(this.enterScope(),t=!0),e.type){case"VariableDeclarator":this.handleVariableDeclarator(e);break;case"CallExpression":this.handleCallExpression(e);break;case"JSXElement":this.handleJSXElement(e)}for(const t in e){if("span"===t)continue;const n=e[t];if(Array.isArray(n))for(const e of n)e&&"object"==typeof e&&e.type&&this.walk(e);else n&&n.type&&this.walk(n)}t&&this.exitScope()}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)}handleVariableDeclarator(e){if("CallExpression"!==e.init?.type)return;const t=e.init.callee;"Identifier"===t.type&&(this.config.extract.useTranslationNames||["useTranslation","getT","useT"]).indexOf(t.value)>-1?this.handleUseTranslationDeclarator(e):"MemberExpression"===t.type&&"Identifier"===t.property.type&&"getFixedT"===t.property.value&&this.handleGetFixedTDeclarator(e)}handleUseTranslationDeclarator(e){if(!e.init||"CallExpression"!==e.init.type)return;let t;if("ArrayPattern"===e.id.type){const n=e.id.elements[0];"Identifier"===n?.type&&(t=n.value)}if("ObjectPattern"===e.id.type)for(const n of e.id.properties){if("AssignmentPatternProperty"===n.type&&"Identifier"===n.key.type&&"t"===n.key.value){t="t";break}if("KeyValuePatternProperty"===n.type&&"Identifier"===n.key.type&&"t"===n.key.value&&"Identifier"===n.value.type){t=n.value.value;break}}if(!t)return;const n=e.init.arguments?.[0]?.expression;let i;"StringLiteral"===n?.type?i=n.value:"ArrayExpression"===n?.type&&"StringLiteral"===n.elements[0]?.expression.type&&(i=n.elements[0].expression.value);const r=e.init.arguments?.[1]?.expression;let s;if("ObjectExpression"===r?.type){const e=this.getObjectPropValue(r,"keyPrefix");s="string"==typeof e?e:void 0}this.setVarInScope(t,{defaultNs:i,keyPrefix:s})}handleGetFixedTDeclarator(e){if("Identifier"!==e.id.type||!e.init||"CallExpression"!==e.init.type)return;const t=e.id.value,n=e.init.arguments,i=n[1]?.expression,r=n[2]?.expression,s="StringLiteral"===i?.type?i.value:void 0,a="StringLiteral"===r?.type?r.value:void 0;(s||a)&&this.setVarInScope(t,{defaultNs:s,keyPrefix:a})}handleCallExpression(e){const t=e.callee;if("Identifier"!==t.type)return;const n=this.getVarFromScope(t.value);if(!((this.config.extract.functions||[]).includes(t.value)||void 0!==n)||0===e.arguments.length)return;const i=e.arguments[0].expression,r=[];if("StringLiteral"===i.type)r.push(i.value);else if("ArrowFunctionExpression"===i.type){const e=this.extractKeyFromSelector(i);e&&r.push(e)}else if("ArrayExpression"===i.type)for(const e of i.elements)"StringLiteral"===e?.expression.type&&r.push(e.expression.value);if(0===r.length)return;const s=e.arguments.length>1?e.arguments[1].expression:void 0,a=this.getDefaultValue(e,r[r.length-1]);for(let e=0;e<r.length;e++){let t,i=r[e];if("ObjectExpression"===s?.type){const e=this.getObjectPropValue(s,"ns");"string"==typeof e&&(t=e)}!t&&n?.defaultNs&&(t=n.defaultNs);const o=this.config.extract.nsSeparator??":";if(!t&&o&&i.includes(o)){const e=i.split(o);t=e.shift(),i=e.join(o)}t||(t=this.config.extract.defaultNS);let l=i;if(n?.keyPrefix){const e=this.config.extract.keySeparator??".";l=`${n.keyPrefix}${e}${i}`}const p=e===r.length-1?a:i;let u=!1;if("ObjectExpression"===s?.type){const e=this.getObjectPropValue(s,"context");if("string"==typeof e&&e){const n=this.config.extract.contextSeparator??"_";this.pluginContext.addKey({key:`${l}${n}${e}`,ns:t,defaultValue:p}),u=!0}u||void 0===this.getObjectPropValue(s,"count")||(this.handlePluralKeys(l,p,t),u=!0),u||!0!==this.getObjectPropValue(s,"returnObjects")||this.objectKeys.add(l)}u||this.pluginContext.addKey({key:l,ns:t,defaultValue:p})}}handlePluralKeys(e,t,n){try{const i=new Intl.PluralRules(this.config.extract?.primaryLanguage).resolvedOptions().pluralCategories,r=this.config.extract.pluralSeparator??"_";for(const s of i)this.pluginContext.addKey({key:`${e}${r}${s}`,ns:n,defaultValue:t,hasCount:!0})}catch(i){this.logger.warn(`Could not determine plural rules for language "${this.config.extract?.primaryLanguage}". Falling back to simple key extraction.`),this.pluginContext.addKey({key:e,defaultValue:t,ns:n})}}getDefaultValue(e,t){if(e.arguments.length<=1)return t;const n=e.arguments[1].expression;if("StringLiteral"===n.type)return n.value||t;if("ObjectExpression"===n.type){const e=this.getObjectPropValue(n,"defaultValue");return"string"==typeof e?e||t:"number"==typeof e||"boolean"==typeof e?String(e):t}return t}handleJSXElement(t){const n=this.getElementName(t);if(n&&(this.config.extract.transComponents||["Trans"]).includes(n)){const n=e(t,this.config);if(n){if(!n.ns){const e=t.opening.attributes?.find(e=>"JSXAttribute"===e.type&&"Identifier"===e.name.type&&"t"===e.name.value);if("JSXAttribute"===e?.type&&"JSXExpressionContainer"===e.value?.type&&"Identifier"===e.value.expression.type){const t=e.value.expression.value,i=this.getVarFromScope(t);i?.defaultNs&&(n.ns=i.defaultNs)}}n.ns||(n.ns=this.config.extract.defaultNS),n.hasCount?this.handlePluralKeys(n.key,n.defaultValue,n.ns):this.pluginContext.addKey(n)}}}getElementName(e){if("Identifier"===e.opening.name.type)return e.opening.name.value;if("JSXMemberExpression"===e.opening.name.type){let t=e.opening.name;const n=[];for(;"JSXMemberExpression"===t.type;)"Identifier"===t.property.type&&n.unshift(t.property.value),t=t.object;return"Identifier"===t.type&&n.unshift(t.value),n.join(".")}}getObjectPropValue(e,t){const n=e.properties.find(e=>"KeyValueProperty"===e.type&&("Identifier"===e.key?.type&&e.key.value===t||"StringLiteral"===e.key?.type&&e.key.value===t));if("KeyValueProperty"===n?.type){const e=n.value;return"StringLiteral"===e.type||("BooleanLiteral"===e.type||"NumericLiteral"===e.type)?e.value:""}}extractKeyFromSelector(e){let t=e.body;if("BlockStatement"===t.type){const e=t.stmts.find(e=>"ReturnStatement"===e.type);if("ReturnStatement"!==e?.type||!e.argument)return null;t=e.argument}let n=t;const i=[];for(;"MemberExpression"===n.type;){const e=n.property;if("Identifier"===e.type)i.unshift(e.value);else{if("Computed"!==e.type||"StringLiteral"!==e.expression.type)return null;i.unshift(e.expression.value)}n=n.object}if(i.length>0){const e=this.config.extract.keySeparator,t="string"==typeof e?e:".";return i.join(t)}return null}}export{t as ASTVisitors};
|
package/dist/esm/status.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import o from"chalk";import e from"ora";import{resolve as t}from"node:path";import{readFile as a}from"node:fs/promises";import{findKeys as s}from"./extractor/core/key-finder.js";import{getNestedValue as n}from"./utils/nested-object.js";import{getOutputPath as r}from"./utils/file-utils.js";async function l(l,d={}){l.extract.primaryLanguage||(l.extract.primaryLanguage=l.locales[0]||"en"),l.extract.secondaryLanguages||(l.extract.secondaryLanguages=l.locales.filter(o=>o!==l?.extract?.primaryLanguage));const g=e("Analyzing project localization status...\n").start();try{const e=await async function(o){const
|
|
1
|
+
import o from"chalk";import e from"ora";import{resolve as t}from"node:path";import{readFile as a}from"node:fs/promises";import{findKeys as s}from"./extractor/core/key-finder.js";import{getNestedValue as n}from"./utils/nested-object.js";import{getOutputPath as r}from"./utils/file-utils.js";async function l(l,d={}){l.extract.primaryLanguage||(l.extract.primaryLanguage=l.locales[0]||"en"),l.extract.secondaryLanguages||(l.extract.secondaryLanguages=l.locales.filter(o=>o!==l?.extract?.primaryLanguage));const g=e("Analyzing project localization status...\n").start();try{const e=await async function(o){const{allKeys:e}=await s(o),{primaryLanguage:l,keySeparator:c=".",defaultNS:i="translation"}=o.extract,y=o.locales.filter(o=>o!==l),d=new Map;for(const o of e.values()){const e=o.ns||i;d.has(e)||d.set(e,[]),d.get(e).push(o)}const g={totalKeys:e.size,keysByNs:d,locales:new Map};for(const e of y){let s=0;const l=new Map;for(const[i,y]of d.entries()){const d=r(o.extract.output,e,i);let g={};try{const o=await a(t(process.cwd(),d),"utf-8");g=JSON.parse(o)}catch{}let u=0;const f=y.map(({key:o})=>{const e=!!n(g,o,c??".");return e&&u++,{key:o,isTranslated:e}});l.set(i,{totalKeys:y.length,translatedKeys:u,keyDetails:f}),s+=u}g.locales.set(e,{totalTranslated:s,namespaces:l})}return g}(l);g.succeed("Analysis complete."),function(e,t,a){a.detail?function(e,t,a,s){if(a===t.extract.primaryLanguage)return void console.log(o.yellow(`Locale "${a}" is the primary language. All keys are considered present.`));if(!t.locales.includes(a))return void console.error(o.red(`Error: Locale "${a}" is not defined in your configuration.`));const n=e.locales.get(a);if(!n)return void console.error(o.red(`Error: Locale "${a}" is not a valid secondary language.`));console.log(o.bold(`\nKey Status for "${o.cyan(a)}":`));const r=Array.from(e.keysByNs.values()).flat().length;c("Overall",n.totalTranslated,r);const l=s?[s]:Array.from(n.namespaces.keys()).sort();for(const e of l){const t=n.namespaces.get(e);t&&(console.log(o.cyan.bold(`\nNamespace: ${e}`)),c("Namespace Progress",t.translatedKeys,t.totalKeys),t.keyDetails.forEach(({key:e,isTranslated:t})=>{const a=t?o.green("✓"):o.red("✗");console.log(` ${a} ${e}`)}))}const i=r-n.totalTranslated;i>0?console.log(o.yellow.bold(`\nSummary: Found ${i} missing translations for "${a}".`)):console.log(o.green.bold(`\nSummary: 🎉 All keys are translated for "${a}".`));y()}(e,t,a.detail,a.namespace):a.namespace?function(e,t,a){const s=e.keysByNs.get(a);if(!s)return void console.error(o.red(`Error: Namespace "${a}" was not found in your source code.`));console.log(o.cyan.bold(`\nStatus for Namespace: "${a}"`)),console.log("------------------------");for(const[o,t]of e.locales.entries()){const e=t.namespaces.get(a);if(e){const t=e.totalKeys>0?Math.round(e.translatedKeys/e.totalKeys*100):100,a=i(t);console.log(`- ${o}: ${a} ${t}% (${e.translatedKeys}/${e.totalKeys} keys)`)}}y()}(e,0,a.namespace):function(e,t){const{primaryLanguage:a}=t.extract;console.log(o.cyan.bold("\ni18next Project Status")),console.log("------------------------"),console.log(`🔑 Keys Found: ${o.bold(e.totalKeys)}`),console.log(`📚 Namespaces Found: ${o.bold(e.keysByNs.size)}`),console.log(`🌍 Locales: ${o.bold(t.locales.join(", "))}`),console.log(`✅ Primary Language: ${o.bold(a)}`),console.log("\nTranslation Progress:");for(const[o,t]of e.locales.entries()){const a=e.totalKeys>0?Math.round(t.totalTranslated/e.totalKeys*100):100,s=i(a);console.log(`- ${o}: ${s} ${a}% (${t.totalTranslated}/${e.totalKeys} keys)`)}y()}(e,t)}(e,l,d)}catch(o){g.fail("Failed to generate status report."),console.error(o)}}function c(e,t,a){const s=a>0?Math.round(t/a*100):100,n=i(s);console.log(`${o.bold(e)}: ${n} ${s}% (${t}/${a})`)}function i(e){const t=Math.round(e/100*20),a=20-t;return`[${o.green("".padStart(t,"■"))}${"".padStart(a,"□")}]`}function y(){console.log(o.yellow.bold("\n✨ Take your localization to the next level!")),console.log("Manage translations with your team in the cloud with locize => https://www.locize.com/docs/getting-started"),console.log(`Run ${o.cyan("npx i18next-cli locize-migrate")} to get started.`)}export{l as runStatus};
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
package/src/config.ts
CHANGED
|
@@ -4,8 +4,9 @@ import { access } from 'node:fs/promises'
|
|
|
4
4
|
import { createJiti } from 'jiti'
|
|
5
5
|
import inquirer from 'inquirer'
|
|
6
6
|
import chalk from 'chalk'
|
|
7
|
-
import type { I18nextToolkitConfig } from './types'
|
|
7
|
+
import type { I18nextToolkitConfig, Logger } from './types'
|
|
8
8
|
import { runInit } from './init'
|
|
9
|
+
import { ConsoleLogger } from './utils/logger'
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* List of supported configuration file names in order of precedence
|
|
@@ -78,7 +79,7 @@ async function findConfigFile (): Promise<string | null> {
|
|
|
78
79
|
* }
|
|
79
80
|
* ```
|
|
80
81
|
*/
|
|
81
|
-
export async function loadConfig (): Promise<I18nextToolkitConfig | null> {
|
|
82
|
+
export async function loadConfig (logger: Logger = new ConsoleLogger()): Promise<I18nextToolkitConfig | null> {
|
|
82
83
|
const configPath = await findConfigFile()
|
|
83
84
|
|
|
84
85
|
if (!configPath) {
|
|
@@ -101,7 +102,7 @@ export async function loadConfig (): Promise<I18nextToolkitConfig | null> {
|
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
if (!config) {
|
|
104
|
-
|
|
105
|
+
logger.error(`Error: No default export found in ${configPath}`)
|
|
105
106
|
return null
|
|
106
107
|
}
|
|
107
108
|
|
|
@@ -112,8 +113,8 @@ export async function loadConfig (): Promise<I18nextToolkitConfig | null> {
|
|
|
112
113
|
|
|
113
114
|
return config
|
|
114
115
|
} catch (error) {
|
|
115
|
-
|
|
116
|
-
|
|
116
|
+
logger.error(`Error loading configuration from ${configPath}`)
|
|
117
|
+
logger.error(error)
|
|
117
118
|
return null
|
|
118
119
|
}
|
|
119
120
|
}
|
|
@@ -125,7 +126,7 @@ export async function loadConfig (): Promise<I18nextToolkitConfig | null> {
|
|
|
125
126
|
* @returns A promise that resolves to a valid configuration object.
|
|
126
127
|
* @throws Exits the process if the user declines to create a config or if loading fails after creation.
|
|
127
128
|
*/
|
|
128
|
-
export async function ensureConfig (): Promise<I18nextToolkitConfig> {
|
|
129
|
+
export async function ensureConfig (logger: Logger = new ConsoleLogger()): Promise<I18nextToolkitConfig> {
|
|
129
130
|
let config = await loadConfig()
|
|
130
131
|
|
|
131
132
|
if (config) {
|
|
@@ -142,17 +143,17 @@ export async function ensureConfig (): Promise<I18nextToolkitConfig> {
|
|
|
142
143
|
|
|
143
144
|
if (shouldInit) {
|
|
144
145
|
await runInit() // Run the interactive setup wizard
|
|
145
|
-
|
|
146
|
+
logger.info(chalk.green('Configuration created. Resuming command...'))
|
|
146
147
|
config = await loadConfig() // Try loading the newly created config
|
|
147
148
|
|
|
148
149
|
if (config) {
|
|
149
150
|
return config
|
|
150
151
|
} else {
|
|
151
|
-
|
|
152
|
+
logger.error(chalk.red('Error: Failed to load configuration after creation. Please try running the command again.'))
|
|
152
153
|
process.exit(1)
|
|
153
154
|
}
|
|
154
155
|
} else {
|
|
155
|
-
|
|
156
|
+
logger.info('Operation cancelled. Please create a configuration file to proceed.')
|
|
156
157
|
process.exit(0)
|
|
157
158
|
}
|
|
158
159
|
}
|
|
@@ -50,10 +50,10 @@ export async function runExtractor (
|
|
|
50
50
|
const spinner = ora('Running i18next key extractor...\n').start()
|
|
51
51
|
|
|
52
52
|
try {
|
|
53
|
-
const allKeys = await findKeys(config, logger)
|
|
53
|
+
const { allKeys, objectKeys } = await findKeys(config, logger)
|
|
54
54
|
spinner.text = `Found ${allKeys.size} unique keys. Updating translation files...`
|
|
55
55
|
|
|
56
|
-
const results = await getTranslations(allKeys, config)
|
|
56
|
+
const results = await getTranslations(allKeys, objectKeys, config)
|
|
57
57
|
|
|
58
58
|
let anyFileUpdated = false
|
|
59
59
|
for (const result of results) {
|
|
@@ -97,8 +97,9 @@ export async function runExtractor (
|
|
|
97
97
|
export async function processFile (
|
|
98
98
|
file: string,
|
|
99
99
|
config: I18nextToolkitConfig,
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
allKeys: Map<string, ExtractedKey>,
|
|
101
|
+
astVisitors: ASTVisitors,
|
|
102
|
+
logger: Logger = new ConsoleLogger()
|
|
102
103
|
): Promise<void> {
|
|
103
104
|
try {
|
|
104
105
|
let code = await readFile(file, 'utf-8')
|
|
@@ -119,18 +120,11 @@ export async function processFile (
|
|
|
119
120
|
// Extract keys from comments
|
|
120
121
|
extractKeysFromComments(code, config.extract.functions || ['t'], pluginContext, config)
|
|
121
122
|
|
|
122
|
-
// Extract keys from AST using visitors
|
|
123
|
-
const astVisitors = new ASTVisitors(
|
|
124
|
-
config,
|
|
125
|
-
pluginContext,
|
|
126
|
-
logger
|
|
127
|
-
)
|
|
128
|
-
|
|
129
123
|
astVisitors.visit(ast)
|
|
130
124
|
|
|
131
125
|
// Run plugin visitors
|
|
132
126
|
if ((config.plugins || []).length > 0) {
|
|
133
|
-
traverseEveryNode(ast, (config.plugins || []), pluginContext)
|
|
127
|
+
traverseEveryNode(ast, (config.plugins || []), pluginContext, logger)
|
|
134
128
|
}
|
|
135
129
|
} catch (error) {
|
|
136
130
|
throw new ExtractorError('Failed to process file', file, error as Error)
|
|
@@ -146,7 +140,7 @@ export async function processFile (
|
|
|
146
140
|
*
|
|
147
141
|
* @internal
|
|
148
142
|
*/
|
|
149
|
-
function traverseEveryNode (node: any, plugins: any[], pluginContext: PluginContext): void {
|
|
143
|
+
function traverseEveryNode (node: any, plugins: any[], pluginContext: PluginContext, logger: Logger = new ConsoleLogger()): void {
|
|
150
144
|
if (!node || typeof node !== 'object') return
|
|
151
145
|
|
|
152
146
|
// Call plugins for this node
|
|
@@ -154,7 +148,7 @@ function traverseEveryNode (node: any, plugins: any[], pluginContext: PluginCont
|
|
|
154
148
|
try {
|
|
155
149
|
plugin.onVisitNode?.(node, pluginContext)
|
|
156
150
|
} catch (err) {
|
|
157
|
-
|
|
151
|
+
logger.warn(`Plugin ${plugin.name} onVisitNode failed:`, err)
|
|
158
152
|
}
|
|
159
153
|
}
|
|
160
154
|
|
|
@@ -162,10 +156,10 @@ function traverseEveryNode (node: any, plugins: any[], pluginContext: PluginCont
|
|
|
162
156
|
const child = node[key]
|
|
163
157
|
if (Array.isArray(child)) {
|
|
164
158
|
for (const c of child) {
|
|
165
|
-
if (c && typeof c === 'object') traverseEveryNode(c, plugins, pluginContext)
|
|
159
|
+
if (c && typeof c === 'object') traverseEveryNode(c, plugins, pluginContext, logger)
|
|
166
160
|
}
|
|
167
161
|
} else if (child && typeof child === 'object') {
|
|
168
|
-
traverseEveryNode(child, plugins, pluginContext)
|
|
162
|
+
traverseEveryNode(child, plugins, pluginContext, logger)
|
|
169
163
|
}
|
|
170
164
|
}
|
|
171
165
|
}
|
|
@@ -190,6 +184,6 @@ export async function extract (config: I18nextToolkitConfig) {
|
|
|
190
184
|
if (!config.extract.secondaryLanguages) config.extract.secondaryLanguages = config.locales.filter((l: string) => l !== config?.extract?.primaryLanguage)
|
|
191
185
|
if (!config.extract.functions) config.extract.functions = ['t']
|
|
192
186
|
if (!config.extract.transComponents) config.extract.transComponents = ['Trans']
|
|
193
|
-
const allKeys = await findKeys(config)
|
|
194
|
-
return getTranslations(allKeys, config)
|
|
187
|
+
const { allKeys, objectKeys } = await findKeys(config)
|
|
188
|
+
return getTranslations(allKeys, objectKeys, config)
|
|
195
189
|
}
|
|
@@ -2,7 +2,8 @@ import { glob } from 'glob'
|
|
|
2
2
|
import type { ExtractedKey, Logger, I18nextToolkitConfig } from '../../types'
|
|
3
3
|
import { processFile } from './extractor'
|
|
4
4
|
import { ConsoleLogger } from '../../utils/logger'
|
|
5
|
-
import { initializePlugins } from '../plugin-manager'
|
|
5
|
+
import { initializePlugins, createPluginContext } from '../plugin-manager'
|
|
6
|
+
import { ASTVisitors } from '../parsers/ast-visitors'
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Main function for finding translation keys across all source files in a project.
|
|
@@ -35,14 +36,17 @@ import { initializePlugins } from '../plugin-manager'
|
|
|
35
36
|
export async function findKeys (
|
|
36
37
|
config: I18nextToolkitConfig,
|
|
37
38
|
logger: Logger = new ConsoleLogger()
|
|
38
|
-
): Promise<Map<string, ExtractedKey
|
|
39
|
+
): Promise<{ allKeys: Map<string, ExtractedKey>, objectKeys: Set<string> }> {
|
|
39
40
|
const sourceFiles = await processSourceFiles(config)
|
|
40
41
|
const allKeys = new Map<string, ExtractedKey>()
|
|
41
42
|
|
|
43
|
+
// Create a single visitors instance to accumulate data across all files
|
|
44
|
+
const astVisitors = new ASTVisitors(config, createPluginContext(allKeys), logger)
|
|
45
|
+
|
|
42
46
|
await initializePlugins(config.plugins || [])
|
|
43
47
|
|
|
44
48
|
for (const file of sourceFiles) {
|
|
45
|
-
await processFile(file, config,
|
|
49
|
+
await processFile(file, config, allKeys, astVisitors, logger)
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
// Run onEnd hooks
|
|
@@ -50,7 +54,7 @@ export async function findKeys (
|
|
|
50
54
|
await plugin.onEnd?.(allKeys)
|
|
51
55
|
}
|
|
52
56
|
|
|
53
|
-
return allKeys
|
|
57
|
+
return { allKeys, objectKeys: astVisitors.objectKeys }
|
|
54
58
|
}
|
|
55
59
|
|
|
56
60
|
/**
|
|
@@ -45,11 +45,17 @@ function globToRegex (glob: string): RegExp {
|
|
|
45
45
|
*/
|
|
46
46
|
export async function getTranslations (
|
|
47
47
|
keys: Map<string, ExtractedKey>,
|
|
48
|
+
objectKeys: Set<string>,
|
|
48
49
|
config: I18nextToolkitConfig
|
|
49
50
|
): Promise<TranslationResult[]> {
|
|
50
51
|
const defaultNS = config.extract.defaultNS ?? 'translation'
|
|
51
52
|
const keySeparator = config.extract.keySeparator ?? '.'
|
|
52
|
-
const
|
|
53
|
+
const patternsToPreserve = [...(config.extract.preservePatterns || [])]
|
|
54
|
+
for (const key of objectKeys) {
|
|
55
|
+
// Convert the object key to a glob pattern to preserve all its children
|
|
56
|
+
patternsToPreserve.push(`${key}.*`)
|
|
57
|
+
}
|
|
58
|
+
const preservePatterns = patternsToPreserve.map(globToRegex)
|
|
53
59
|
if (!config.extract.primaryLanguage) config.extract.primaryLanguage = config.locales[0] || 'en'
|
|
54
60
|
if (!config.extract.secondaryLanguages) config.extract.secondaryLanguages = config.locales.filter((l: string) => l !== config.extract.primaryLanguage)
|
|
55
61
|
|
|
@@ -41,6 +41,8 @@ export class ASTVisitors {
|
|
|
41
41
|
private readonly logger: Logger
|
|
42
42
|
private scopeStack: Array<Map<string, ScopeInfo>> = []
|
|
43
43
|
|
|
44
|
+
public objectKeys = new Set<string>()
|
|
45
|
+
|
|
44
46
|
/**
|
|
45
47
|
* Creates a new AST visitor instance.
|
|
46
48
|
*
|
|
@@ -275,7 +277,8 @@ export class ASTVisitors {
|
|
|
275
277
|
const optionsArg = node.init.arguments?.[1]?.expression
|
|
276
278
|
let keyPrefix: string | undefined
|
|
277
279
|
if (optionsArg?.type === 'ObjectExpression') {
|
|
278
|
-
|
|
280
|
+
const kp = this.getObjectPropValue(optionsArg, 'keyPrefix')
|
|
281
|
+
keyPrefix = typeof kp === 'string' ? kp : undefined
|
|
279
282
|
}
|
|
280
283
|
|
|
281
284
|
// Store the scope info for the declared variable
|
|
@@ -340,7 +343,6 @@ export class ASTVisitors {
|
|
|
340
343
|
const firstArg = node.arguments[0].expression
|
|
341
344
|
const keysToProcess: string[] = []
|
|
342
345
|
|
|
343
|
-
// --- NEW: Handle ArrayExpression for key fallbacks ---
|
|
344
346
|
if (firstArg.type === 'StringLiteral') {
|
|
345
347
|
keysToProcess.push(firstArg.value)
|
|
346
348
|
} else if (firstArg.type === 'ArrowFunctionExpression') {
|
|
@@ -366,7 +368,10 @@ export class ASTVisitors {
|
|
|
366
368
|
let ns: string | undefined
|
|
367
369
|
|
|
368
370
|
// Determine namespace (explicit ns > scope ns > ns:key > default)
|
|
369
|
-
if (options?.type === 'ObjectExpression')
|
|
371
|
+
if (options?.type === 'ObjectExpression') {
|
|
372
|
+
const nsVal = this.getObjectPropValue(options, 'ns')
|
|
373
|
+
if (typeof nsVal === 'string') ns = nsVal
|
|
374
|
+
}
|
|
370
375
|
if (!ns && scopeInfo?.defaultNs) ns = scopeInfo.defaultNs
|
|
371
376
|
|
|
372
377
|
const nsSeparator = this.config.extract.nsSeparator ?? ':'
|
|
@@ -388,21 +393,33 @@ export class ASTVisitors {
|
|
|
388
393
|
const isLastKey = i === keysToProcess.length - 1
|
|
389
394
|
const dv = isLastKey ? defaultValue : key
|
|
390
395
|
|
|
391
|
-
// Handle plurals
|
|
396
|
+
// Handle plurals, context, and returnObjects
|
|
397
|
+
let keyHandled = false
|
|
392
398
|
if (options?.type === 'ObjectExpression') {
|
|
399
|
+
// Handle context
|
|
393
400
|
const contextValue = this.getObjectPropValue(options, 'context')
|
|
394
|
-
|
|
395
|
-
|
|
401
|
+
if (typeof contextValue === 'string' && contextValue) {
|
|
402
|
+
const contextSeparator = this.config.extract.contextSeparator ?? '_'
|
|
396
403
|
this.pluginContext.addKey({ key: `${finalKey}${contextSeparator}${contextValue}`, ns, defaultValue: dv })
|
|
397
|
-
|
|
404
|
+
keyHandled = true
|
|
398
405
|
}
|
|
399
|
-
|
|
406
|
+
|
|
407
|
+
// Handle plurals
|
|
408
|
+
if (!keyHandled && this.getObjectPropValue(options, 'count') !== undefined) {
|
|
400
409
|
this.handlePluralKeys(finalKey, dv, ns)
|
|
401
|
-
|
|
410
|
+
keyHandled = true
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// Handle returnObjects
|
|
414
|
+
if (!keyHandled && this.getObjectPropValue(options, 'returnObjects') === true) {
|
|
415
|
+
this.objectKeys.add(finalKey)
|
|
416
|
+
// We still add the base key itself
|
|
402
417
|
}
|
|
403
418
|
}
|
|
404
419
|
|
|
405
|
-
|
|
420
|
+
if (!keyHandled) {
|
|
421
|
+
this.pluginContext.addKey({ key: finalKey, ns, defaultValue: dv })
|
|
422
|
+
}
|
|
406
423
|
}
|
|
407
424
|
}
|
|
408
425
|
|
|
@@ -462,7 +479,10 @@ export class ASTVisitors {
|
|
|
462
479
|
}
|
|
463
480
|
|
|
464
481
|
if (secondArg.type === 'ObjectExpression') {
|
|
465
|
-
|
|
482
|
+
const val = this.getObjectPropValue(secondArg, 'defaultValue')
|
|
483
|
+
if (typeof val === 'string') return val || fallback
|
|
484
|
+
if (typeof val === 'number' || typeof val === 'boolean') return String(val)
|
|
485
|
+
return fallback
|
|
466
486
|
}
|
|
467
487
|
|
|
468
488
|
return fallback
|
|
@@ -564,7 +584,7 @@ export class ASTVisitors {
|
|
|
564
584
|
*
|
|
565
585
|
* @private
|
|
566
586
|
*/
|
|
567
|
-
private getObjectPropValue (object: ObjectExpression, propName: string): string | undefined {
|
|
587
|
+
private getObjectPropValue (object: ObjectExpression, propName: string): string | boolean | number | undefined {
|
|
568
588
|
const prop = (object.properties).find(
|
|
569
589
|
(p) =>
|
|
570
590
|
p.type === 'KeyValueProperty' &&
|
|
@@ -576,12 +596,18 @@ export class ASTVisitors {
|
|
|
576
596
|
|
|
577
597
|
if (prop?.type === 'KeyValueProperty') {
|
|
578
598
|
const val = prop.value
|
|
579
|
-
//
|
|
599
|
+
// Return concrete literal values when possible
|
|
580
600
|
if (val.type === 'StringLiteral') {
|
|
581
601
|
return val.value
|
|
582
602
|
}
|
|
583
|
-
|
|
584
|
-
|
|
603
|
+
if (val.type === 'BooleanLiteral') {
|
|
604
|
+
return val.value
|
|
605
|
+
}
|
|
606
|
+
if (val.type === 'NumericLiteral') {
|
|
607
|
+
return val.value
|
|
608
|
+
}
|
|
609
|
+
// For other expression types (identifier, member expr, etc.) we only care that the prop exists.
|
|
610
|
+
// Return an empty string to indicate presence.
|
|
585
611
|
return ''
|
|
586
612
|
}
|
|
587
613
|
return undefined
|
package/src/status.ts
CHANGED
|
@@ -84,7 +84,7 @@ export async function runStatus (config: I18nextToolkitConfig, options: StatusOp
|
|
|
84
84
|
* @throws {Error} When key extraction fails or configuration is invalid
|
|
85
85
|
*/
|
|
86
86
|
async function generateStatusReport (config: I18nextToolkitConfig): Promise<StatusReport> {
|
|
87
|
-
const allExtractedKeys = await findKeys(config)
|
|
87
|
+
const { allKeys: allExtractedKeys } = await findKeys(config)
|
|
88
88
|
const { primaryLanguage, keySeparator = '.', defaultNS = 'translation' } = config.extract
|
|
89
89
|
const secondaryLanguages = config.locales.filter(l => l !== primaryLanguage)
|
|
90
90
|
|
package/src/types.ts
CHANGED
|
@@ -277,13 +277,13 @@ export interface Logger {
|
|
|
277
277
|
* Logs a warning message.
|
|
278
278
|
* @param message - The warning message to log
|
|
279
279
|
*/
|
|
280
|
-
warn(message: string): void;
|
|
280
|
+
warn(message: string, more?: any): void;
|
|
281
281
|
|
|
282
282
|
/**
|
|
283
283
|
* Logs an error message.
|
|
284
284
|
* @param message - The error message to log
|
|
285
285
|
*/
|
|
286
|
-
error(message: string): void;
|
|
286
|
+
error(message: string | any): void;
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
/**
|
package/types/config.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { I18nextToolkitConfig } from './types';
|
|
1
|
+
import type { I18nextToolkitConfig, Logger } from './types';
|
|
2
2
|
/**
|
|
3
3
|
* A helper function for defining the i18next-cli config with type-safety.
|
|
4
4
|
*
|
|
@@ -38,7 +38,7 @@ export declare function defineConfig(config: I18nextToolkitConfig): I18nextToolk
|
|
|
38
38
|
* }
|
|
39
39
|
* ```
|
|
40
40
|
*/
|
|
41
|
-
export declare function loadConfig(): Promise<I18nextToolkitConfig | null>;
|
|
41
|
+
export declare function loadConfig(logger?: Logger): Promise<I18nextToolkitConfig | null>;
|
|
42
42
|
/**
|
|
43
43
|
* NEW: Ensures a configuration exists, prompting the user to create one if necessary.
|
|
44
44
|
* This function is a wrapper around loadConfig that provides an interactive fallback.
|
|
@@ -46,5 +46,5 @@ export declare function loadConfig(): Promise<I18nextToolkitConfig | null>;
|
|
|
46
46
|
* @returns A promise that resolves to a valid configuration object.
|
|
47
47
|
* @throws Exits the process if the user declines to create a config or if loading fails after creation.
|
|
48
48
|
*/
|
|
49
|
-
export declare function ensureConfig(): Promise<I18nextToolkitConfig>;
|
|
49
|
+
export declare function ensureConfig(logger?: Logger): Promise<I18nextToolkitConfig>;
|
|
50
50
|
//# sourceMappingURL=config.d.ts.map
|
package/types/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAc3D;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAE,MAAM,EAAE,oBAAoB,GAAG,oBAAoB,CAEhF;AAqBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,UAAU,CAAE,MAAM,GAAE,MAA4B,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAsC5G;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAE,MAAM,GAAE,MAA4B,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA8BvG"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Logger, ExtractedKey, I18nextToolkitConfig } from '../../types';
|
|
2
|
+
import { ASTVisitors } from '../parsers/ast-visitors';
|
|
2
3
|
/**
|
|
3
4
|
* Main extractor function that runs the complete key extraction and file generation process.
|
|
4
5
|
*
|
|
@@ -46,7 +47,7 @@ export declare function runExtractor(config: I18nextToolkitConfig, logger?: Logg
|
|
|
46
47
|
*
|
|
47
48
|
* @internal
|
|
48
49
|
*/
|
|
49
|
-
export declare function processFile(file: string, config: I18nextToolkitConfig,
|
|
50
|
+
export declare function processFile(file: string, config: I18nextToolkitConfig, allKeys: Map<string, ExtractedKey>, astVisitors: ASTVisitors, logger?: Logger): Promise<void>;
|
|
50
51
|
/**
|
|
51
52
|
* Simplified extraction function that returns translation results without file writing.
|
|
52
53
|
* Used primarily for testing and programmatic access.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../../src/extractor/core/extractor.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAiB,oBAAoB,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../../src/extractor/core/extractor.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAiB,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAM5F,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAGrD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,oBAAoB,EAC5B,MAAM,GAAE,MAA4B,GACnC,OAAO,CAAC,OAAO,CAAC,CA+BlB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,oBAAoB,EAC5B,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EAClC,WAAW,EAAE,WAAW,EACxB,MAAM,GAAE,MAA4B,GACnC,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAmCD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,OAAO,CAAE,MAAM,EAAE,oBAAoB,sDAO1D"}
|
|
@@ -27,5 +27,8 @@ import type { ExtractedKey, Logger, I18nextToolkitConfig } from '../../types';
|
|
|
27
27
|
* console.log(`Found ${keys.size} unique translation keys`)
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
|
-
export declare function findKeys(config: I18nextToolkitConfig, logger?: Logger): Promise<
|
|
30
|
+
export declare function findKeys(config: I18nextToolkitConfig, logger?: Logger): Promise<{
|
|
31
|
+
allKeys: Map<string, ExtractedKey>;
|
|
32
|
+
objectKeys: Set<string>;
|
|
33
|
+
}>;
|
|
31
34
|
//# sourceMappingURL=key-finder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"key-finder.d.ts","sourceRoot":"","sources":["../../../src/extractor/core/key-finder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"key-finder.d.ts","sourceRoot":"","sources":["../../../src/extractor/core/key-finder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAM7E;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,oBAAoB,EAC5B,MAAM,GAAE,MAA4B,GACnC,OAAO,CAAC;IAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAAC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAAE,CAAC,CAmB1E"}
|
|
@@ -27,5 +27,5 @@ import { TranslationResult, ExtractedKey, I18nextToolkitConfig } from '../../typ
|
|
|
27
27
|
* // Results contain update status and new/existing translations for each locale
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
|
-
export declare function getTranslations(keys: Map<string, ExtractedKey>, config: I18nextToolkitConfig): Promise<TranslationResult[]>;
|
|
30
|
+
export declare function getTranslations(keys: Map<string, ExtractedKey>, objectKeys: Set<string>, config: I18nextToolkitConfig): Promise<TranslationResult[]>;
|
|
31
31
|
//# sourceMappingURL=translation-manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translation-manager.d.ts","sourceRoot":"","sources":["../../../src/extractor/core/translation-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAiBnF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EAC/B,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,iBAAiB,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"translation-manager.d.ts","sourceRoot":"","sources":["../../../src/extractor/core/translation-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAiBnF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EAC/B,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,EACvB,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAuE9B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast-visitors.d.ts","sourceRoot":"","sources":["../../../src/extractor/parsers/ast-visitors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAmG,MAAM,WAAW,CAAA;AACxI,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAc9E;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAC/B,OAAO,CAAC,UAAU,CAAoC;
|
|
1
|
+
{"version":3,"file":"ast-visitors.d.ts","sourceRoot":"","sources":["../../../src/extractor/parsers/ast-visitors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAmG,MAAM,WAAW,CAAA;AACxI,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAc9E;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAC/B,OAAO,CAAC,UAAU,CAAoC;IAE/C,UAAU,cAAoB;IAErC;;;;;;OAMG;gBAED,MAAM,EAAE,oBAAoB,EAC5B,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,MAAM;IAOhB;;;;;OAKG;IACI,KAAK,CAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAMjC;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,IAAI;IAiDZ;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAIlB;;;;;OAKG;IACH,OAAO,CAAC,SAAS;IAIjB;;;;;;;;OAQG;IACH,OAAO,CAAC,aAAa;IAMrB;;;;;;;;OAQG;IACH,OAAO,CAAC,eAAe;IASvB;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,wBAAwB;IAqBhC;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,8BAA8B;IAkDtC;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,yBAAyB;IAoBjC;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,oBAAoB;IA2F5B;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,gBAAgB;IAmBxB;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,eAAe;IAmBvB;;;;;;;;;OASG;IACH,OAAO,CAAC,gBAAgB;IA8CxB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,cAAc;IAgBtB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,kBAAkB;IA6B1B;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,sBAAsB;CA0C/B"}
|
package/types/types.d.ts
CHANGED
|
@@ -233,12 +233,12 @@ export interface Logger {
|
|
|
233
233
|
* Logs a warning message.
|
|
234
234
|
* @param message - The warning message to log
|
|
235
235
|
*/
|
|
236
|
-
warn(message: string): void;
|
|
236
|
+
warn(message: string, more?: any): void;
|
|
237
237
|
/**
|
|
238
238
|
* Logs an error message.
|
|
239
239
|
* @param message - The error message to log
|
|
240
240
|
*/
|
|
241
|
-
error(message: string): void;
|
|
241
|
+
error(message: string | any): void;
|
|
242
242
|
}
|
|
243
243
|
/**
|
|
244
244
|
* Context object provided to plugins during AST traversal.
|
package/types/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|