@inline-i18n-multi/cli 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -136,6 +136,75 @@ The CLI commands (`extract`, `validate`, `typegen`) recognize contextual transla
136
136
 
137
137
  Validation checks context variants for completeness across locales. Type generation includes context-aware overloads for `t()`.
138
138
 
139
+ ### Diff Command (v0.10.0)
140
+
141
+ Compare translations between two locales to find missing, extra, or differing keys:
142
+
143
+ ```bash
144
+ npx inline-i18n diff en ko
145
+ npx inline-i18n diff en ko --all
146
+ ```
147
+
148
+ By default, `diff` shows keys that exist in one locale but not the other. Use the `--all` flag to also show shared keys for a complete comparison.
149
+
150
+ Example output:
151
+
152
+ ```
153
+ Comparing en ↔ ko
154
+
155
+ Only in en:
156
+ - settings.theme
157
+ - settings.notifications
158
+
159
+ Only in ko:
160
+ - onboarding.welcome
161
+
162
+ Shared: 45 keys (use --all to show)
163
+ ```
164
+
165
+ ### Stats Command (v0.10.0)
166
+
167
+ Display a translation statistics dashboard with an overview of your project's translation coverage:
168
+
169
+ ```bash
170
+ npx inline-i18n stats
171
+ ```
172
+
173
+ Shows:
174
+ - **Overview** — Total keys, locales, and namespaces
175
+ - **Locale breakdown** — Per-locale key count and coverage percentage
176
+ - **Namespaces** — Key distribution across namespaces
177
+ - **Top files** — Files with the most translation calls
178
+ - **ICU usage** — Breakdown of ICU message types used (plural, select, date, number, etc.)
179
+
180
+ Example output:
181
+
182
+ ```
183
+ Translation Statistics
184
+ ======================
185
+
186
+ Overview
187
+ Total keys: 128
188
+ Locales: 3 (en, ko, ja)
189
+ Namespaces: 2 (default, common)
190
+
191
+ Locale Breakdown
192
+ en 128/128 100%
193
+ ko 120/128 94%
194
+ ja 115/128 90%
195
+
196
+ Top Files
197
+ src/components/Header.tsx 18 keys
198
+ src/pages/Dashboard.tsx 15 keys
199
+ src/pages/Settings.tsx 12 keys
200
+
201
+ ICU Usage
202
+ plural 23 occurrences
203
+ select 8 occurrences
204
+ date 5 occurrences
205
+ number 4 occurrences
206
+ ```
207
+
139
208
  ## Options
140
209
 
141
210
  ```
@@ -146,6 +215,7 @@ Validation checks context variants for completeness across locales. Type generat
146
215
  --strict Enable strict mode (ICU type consistency check)
147
216
  --unused Detect unused translation keys (validate command)
148
217
  --watch, -w Watch mode for validate/typegen (re-run on file changes)
218
+ --all Show shared keys in diff output (diff command)
149
219
  ```
150
220
 
151
221
  ## Documentation
package/dist/bin.js CHANGED
@@ -719,15 +719,145 @@ function buildNestedObject(flat) {
719
719
  return result;
720
720
  }
721
721
 
722
+ // src/commands/diff.ts
723
+ var import_chalk7 = __toESM(require("chalk"));
724
+ async function diff(options) {
725
+ const { locale1, locale2, cwd, all } = options;
726
+ const basePath = cwd || process.cwd();
727
+ console.log(import_chalk7.default.blue(`
728
+ Comparing ${locale1} vs ${locale2}...
729
+ `));
730
+ const entries = await parseProject({ cwd });
731
+ if (entries.length === 0) {
732
+ console.log(import_chalk7.default.yellow("No translations found."));
733
+ return;
734
+ }
735
+ const onlyIn1 = [];
736
+ const onlyIn2 = [];
737
+ const shared = [];
738
+ for (const entry of entries) {
739
+ const has1 = !!entry.translations[locale1];
740
+ const has2 = !!entry.translations[locale2];
741
+ if (has1 && has2) shared.push(entry);
742
+ else if (has1 && !has2) onlyIn1.push(entry);
743
+ else if (!has1 && has2) onlyIn2.push(entry);
744
+ }
745
+ if (onlyIn1.length > 0) {
746
+ console.log(import_chalk7.default.red(`Only in ${locale1} (${onlyIn1.length}):
747
+ `));
748
+ for (const entry of onlyIn1) {
749
+ const relativePath = entry.file.replace(basePath + "/", "");
750
+ console.log(import_chalk7.default.gray(` ${relativePath}:${entry.line}`));
751
+ console.log(` ${import_chalk7.default.cyan(locale1)}: ${entry.translations[locale1]}`);
752
+ console.log();
753
+ }
754
+ }
755
+ if (onlyIn2.length > 0) {
756
+ console.log(import_chalk7.default.red(`Only in ${locale2} (${onlyIn2.length}):
757
+ `));
758
+ for (const entry of onlyIn2) {
759
+ const relativePath = entry.file.replace(basePath + "/", "");
760
+ console.log(import_chalk7.default.gray(` ${relativePath}:${entry.line}`));
761
+ console.log(` ${import_chalk7.default.cyan(locale2)}: ${entry.translations[locale2]}`);
762
+ console.log();
763
+ }
764
+ }
765
+ if (all && shared.length > 0) {
766
+ console.log(import_chalk7.default.green(`Shared (${shared.length}):
767
+ `));
768
+ for (const entry of shared) {
769
+ const relativePath = entry.file.replace(basePath + "/", "");
770
+ console.log(import_chalk7.default.gray(` ${relativePath}:${entry.line}`));
771
+ console.log(` ${import_chalk7.default.cyan(locale1)}: ${entry.translations[locale1]}`);
772
+ console.log(` ${import_chalk7.default.cyan(locale2)}: ${entry.translations[locale2]}`);
773
+ console.log();
774
+ }
775
+ }
776
+ console.log(import_chalk7.default.bold("Summary:"));
777
+ console.log(import_chalk7.default.green(` Shared: ${shared.length}`));
778
+ console.log(onlyIn1.length > 0 ? import_chalk7.default.red(` Only in ${locale1}: ${onlyIn1.length}`) : import_chalk7.default.gray(` Only in ${locale1}: 0`));
779
+ console.log(onlyIn2.length > 0 ? import_chalk7.default.red(` Only in ${locale2}: ${onlyIn2.length}`) : import_chalk7.default.gray(` Only in ${locale2}: 0`));
780
+ console.log();
781
+ }
782
+
783
+ // src/commands/stats.ts
784
+ var import_chalk8 = __toESM(require("chalk"));
785
+ async function stats(options = {}) {
786
+ const { cwd } = options;
787
+ const basePath = cwd || process.cwd();
788
+ console.log(import_chalk8.default.blue("\nGathering translation statistics...\n"));
789
+ const entries = await parseProject({ cwd });
790
+ const dictEntries = await extractProjectDictionaryKeys({ cwd });
791
+ const tCalls = await extractProjectTCalls({ cwd });
792
+ const totalDictKeys = dictEntries.reduce((sum, e) => sum + e.keys.length, 0);
793
+ console.log(import_chalk8.default.bold("Overview:\n"));
794
+ console.log(` Inline translations (it): ${import_chalk8.default.cyan(String(entries.length))}`);
795
+ console.log(` Dictionary keys: ${import_chalk8.default.cyan(String(totalDictKeys))}`);
796
+ console.log(` t() call sites: ${import_chalk8.default.cyan(String(tCalls.length))}`);
797
+ console.log();
798
+ const localeCounts = {};
799
+ for (const entry of entries) {
800
+ for (const locale of Object.keys(entry.translations)) {
801
+ localeCounts[locale] = (localeCounts[locale] || 0) + 1;
802
+ }
803
+ }
804
+ if (Object.keys(localeCounts).length > 0) {
805
+ console.log(import_chalk8.default.bold("Locale Breakdown (inline):\n"));
806
+ const sortedLocales = Object.entries(localeCounts).sort((a, b) => b[1] - a[1]);
807
+ for (const [locale, count] of sortedLocales) {
808
+ console.log(` ${import_chalk8.default.cyan(locale.padEnd(10))} ${count} translations`);
809
+ }
810
+ console.log();
811
+ }
812
+ const namespaces = new Set(dictEntries.map((e) => e.namespace));
813
+ if (namespaces.size > 0) {
814
+ console.log(import_chalk8.default.bold("Namespaces:\n"));
815
+ for (const entry of dictEntries) {
816
+ console.log(` ${import_chalk8.default.yellow(entry.namespace.padEnd(15))} ${entry.keys.length} keys`);
817
+ }
818
+ console.log();
819
+ }
820
+ const fileCounts = {};
821
+ for (const entry of entries) {
822
+ const relativePath = entry.file.replace(basePath + "/", "");
823
+ fileCounts[relativePath] = (fileCounts[relativePath] || 0) + 1;
824
+ }
825
+ if (Object.keys(fileCounts).length > 0) {
826
+ console.log(import_chalk8.default.bold("Top Files:\n"));
827
+ const sortedFiles = Object.entries(fileCounts).sort((a, b) => b[1] - a[1]).slice(0, 10);
828
+ for (const [file, count] of sortedFiles) {
829
+ console.log(` ${import_chalk8.default.gray(file.padEnd(50))} ${import_chalk8.default.cyan(String(count))}`);
830
+ }
831
+ console.log();
832
+ }
833
+ const icuUsage = {};
834
+ for (const entry of entries) {
835
+ if (!entry.icuTypes) continue;
836
+ for (const types of Object.values(entry.icuTypes)) {
837
+ for (const info of types) {
838
+ icuUsage[info.type] = (icuUsage[info.type] || 0) + 1;
839
+ }
840
+ }
841
+ }
842
+ if (Object.keys(icuUsage).length > 0) {
843
+ console.log(import_chalk8.default.bold("ICU Pattern Usage:\n"));
844
+ const sortedICU = Object.entries(icuUsage).sort((a, b) => b[1] - a[1]);
845
+ for (const [type, count] of sortedICU) {
846
+ console.log(` ${import_chalk8.default.yellow(type.padEnd(20))} ${count} usage(s)`);
847
+ }
848
+ console.log();
849
+ }
850
+ }
851
+
722
852
  // src/watch.ts
723
853
  var import_chokidar = require("chokidar");
724
- var import_chalk7 = __toESM(require("chalk"));
854
+ var import_chalk9 = __toESM(require("chalk"));
725
855
  function startWatch(options) {
726
856
  const { cwd, patterns, ignore, onChange, label } = options;
727
- console.log(import_chalk7.default.blue(`
857
+ console.log(import_chalk9.default.blue(`
728
858
  Watching for changes (${label})...
729
859
  `));
730
- console.log(import_chalk7.default.gray("Press Ctrl+C to stop\n"));
860
+ console.log(import_chalk9.default.gray("Press Ctrl+C to stop\n"));
731
861
  const watcher = (0, import_chokidar.watch)(patterns, {
732
862
  cwd,
733
863
  ignored: ignore,
@@ -737,14 +867,14 @@ Watching for changes (${label})...
737
867
  const handleChange = (filePath) => {
738
868
  if (debounceTimer) clearTimeout(debounceTimer);
739
869
  debounceTimer = setTimeout(async () => {
740
- console.log(import_chalk7.default.gray(`
870
+ console.log(import_chalk9.default.gray(`
741
871
  Change detected: ${filePath}`));
742
- console.log(import_chalk7.default.gray("-".repeat(40)));
872
+ console.log(import_chalk9.default.gray("-".repeat(40)));
743
873
  try {
744
874
  await onChange();
745
875
  } catch {
746
876
  }
747
- console.log(import_chalk7.default.gray(`
877
+ console.log(import_chalk9.default.gray(`
748
878
  Watching for changes (${label})...`));
749
879
  }, 300);
750
880
  };
@@ -754,7 +884,7 @@ Watching for changes (${label})...`));
754
884
 
755
885
  // src/bin.ts
756
886
  var program = new import_commander.Command();
757
- program.name("inline-i18n").description("CLI tools for inline-i18n-multi").version("0.9.0");
887
+ program.name("inline-i18n").description("CLI tools for inline-i18n-multi").version("0.10.0");
758
888
  program.command("find <query>").description("Find translations containing the query text").option("-c, --cwd <path>", "Working directory").action(async (query, options) => {
759
889
  await find({ query, cwd: options.cwd });
760
890
  });
@@ -790,5 +920,11 @@ program.command("typegen").description("Generate TypeScript types for translatio
790
920
  program.command("extract").description("Extract inline translations to JSON files").option("-c, --cwd <path>", "Working directory").option("-o, --output <path>", "Output directory", "translations").option("-f, --format <format>", "Output format (flat|nested)", "flat").action(async (options) => {
791
921
  await extract(options);
792
922
  });
923
+ program.command("diff <locale1> <locale2>").description("Compare translations between two locales").option("-c, --cwd <path>", "Working directory").option("-a, --all", "Show all entries including shared translations").action(async (locale1, locale2, options) => {
924
+ await diff({ locale1, locale2, cwd: options.cwd, all: options.all });
925
+ });
926
+ program.command("stats").description("Show translation statistics overview").option("-c, --cwd <path>", "Working directory").action(async (options) => {
927
+ await stats(options);
928
+ });
793
929
  program.parse();
794
930
  //# sourceMappingURL=bin.js.map
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bin.ts","../src/commands/find.ts","../src/parser.ts","../src/commands/validate.ts","../src/commands/unused.ts","../src/commands/coverage.ts","../src/commands/typegen.ts","../src/commands/extract.ts","../src/watch.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { find } from './commands/find'\nimport { validate } from './commands/validate'\nimport { coverage } from './commands/coverage'\nimport { typegen } from './commands/typegen'\nimport { extract } from './commands/extract'\nimport { startWatch } from './watch'\n\nconst program = new Command()\n\nprogram\n .name('inline-i18n')\n .description('CLI tools for inline-i18n-multi')\n .version('0.9.0')\n\nprogram\n .command('find <query>')\n .description('Find translations containing the query text')\n .option('-c, --cwd <path>', 'Working directory')\n .action(async (query: string, options: { cwd?: string }) => {\n await find({ query, cwd: options.cwd })\n })\n\nprogram\n .command('validate')\n .description('Validate translation consistency')\n .option('-c, --cwd <path>', 'Working directory')\n .option('-l, --locales <locales...>', 'Required locales to check')\n .option('-s, --strict', 'Enable strict mode (ICU type consistency check)')\n .option('-u, --unused', 'Detect unused dictionary keys')\n .option('-w, --watch', 'Watch mode - re-validate on file changes')\n .action(async (options: { cwd?: string; locales?: string[]; strict?: boolean; unused?: boolean; watch?: boolean }) => {\n await validate(options.watch ? { ...options, noExit: true } : options)\n if (options.watch) {\n const cwd = options.cwd || process.cwd()\n startWatch({\n cwd,\n patterns: ['**/*.{ts,tsx,js,jsx}'],\n ignore: ['**/node_modules/**', '**/dist/**', '**/.next/**'],\n onChange: () => validate({ ...options, noExit: true }),\n label: 'validate',\n })\n }\n })\n\nprogram\n .command('coverage')\n .description('Show translation coverage by locale')\n .option('-c, --cwd <path>', 'Working directory')\n .option('-l, --locales <locales...>', 'Locales to check', ['ko', 'en'])\n .action(async (options: { cwd?: string; locales: string[] }) => {\n await coverage(options)\n })\n\nprogram\n .command('typegen')\n .description('Generate TypeScript types for translation keys')\n .option('-c, --cwd <path>', 'Working directory')\n .option('-o, --output <path>', 'Output file path', 'src/i18n.d.ts')\n .option('-w, --watch', 'Watch mode - regenerate types on file changes')\n .action(async (options: { cwd?: string; output?: string; watch?: boolean }) => {\n await typegen(options)\n if (options.watch) {\n const cwd = options.cwd || process.cwd()\n startWatch({\n cwd,\n patterns: ['**/*.{ts,tsx,js,jsx}'],\n ignore: ['**/node_modules/**', '**/dist/**', '**/.next/**'],\n onChange: () => typegen(options),\n label: 'typegen',\n })\n }\n })\n\nprogram\n .command('extract')\n .description('Extract inline translations to JSON files')\n .option('-c, --cwd <path>', 'Working directory')\n .option('-o, --output <path>', 'Output directory', 'translations')\n .option('-f, --format <format>', 'Output format (flat|nested)', 'flat')\n .action(async (options: { cwd?: string; output?: string; format?: 'flat' | 'nested' }) => {\n await extract(options)\n })\n\nprogram.parse()\n","import chalk from 'chalk'\nimport { parseProject, type TranslationEntry } from '../parser'\n\ninterface FindOptions {\n query: string\n cwd?: string\n}\n\nexport async function find(options: FindOptions): Promise<void> {\n const { query, cwd } = options\n\n console.log(chalk.blue(`\\nSearching for: \"${query}\"\\n`))\n\n const entries = await parseProject({ cwd })\n const results: TranslationEntry[] = []\n\n const lowerQuery = query.toLowerCase()\n\n for (const entry of entries) {\n const values = Object.values(entry.translations)\n const matches = values.some((v) => v.toLowerCase().includes(lowerQuery))\n\n if (matches) {\n results.push(entry)\n }\n }\n\n if (results.length === 0) {\n console.log(chalk.yellow('No results found.'))\n return\n }\n\n console.log(chalk.green(`Found ${results.length} occurrence(s):\\n`))\n\n for (const result of results) {\n const relativePath = result.file.replace(process.cwd() + '/', '')\n console.log(chalk.gray(`${relativePath}:${result.line}:${result.column}`))\n\n for (const [locale, text] of Object.entries(result.translations)) {\n const highlighted = text.replace(\n new RegExp(`(${query})`, 'gi'),\n chalk.yellow('$1')\n )\n console.log(` ${chalk.cyan(locale)}: ${highlighted}`)\n }\n console.log()\n }\n}\n","import { parse } from '@babel/parser'\nimport traverse from '@babel/traverse'\nimport * as fs from 'fs'\nimport fg from 'fast-glob'\n\n// v0.8.0: Dictionary key and t() call extraction\n\nexport interface DictionaryKeyEntry {\n file: string\n line: number\n namespace: string\n keys: string[]\n}\n\nexport interface TCallEntry {\n file: string\n line: number\n key: string\n}\n\nexport interface ICUTypeInfo {\n variable: string\n type: string\n}\n\nexport interface TranslationEntry {\n file: string\n line: number\n column: number\n translations: Record<string, string>\n variables: string[]\n /** ICU type information per locale (v0.7.0) */\n icuTypes?: Record<string, ICUTypeInfo[]>\n}\n\ninterface ParseOptions {\n cwd?: string\n include?: string[]\n exclude?: string[]\n}\n\nconst IT_FUNCTION_NAMES = [\n 'it',\n 'it_ja', 'it_zh', 'it_es', 'it_fr', 'it_de',\n 'en_ja', 'en_zh', 'en_es', 'en_fr', 'en_de',\n 'ja_zh', 'ja_es', 'zh_es',\n]\n\nconst PAIR_MAPPING: Record<string, [string, string]> = {\n it: ['ko', 'en'],\n it_ja: ['ko', 'ja'],\n it_zh: ['ko', 'zh'],\n it_es: ['ko', 'es'],\n it_fr: ['ko', 'fr'],\n it_de: ['ko', 'de'],\n en_ja: ['en', 'ja'],\n en_zh: ['en', 'zh'],\n en_es: ['en', 'es'],\n en_fr: ['en', 'fr'],\n en_de: ['en', 'de'],\n ja_zh: ['ja', 'zh'],\n ja_es: ['ja', 'es'],\n zh_es: ['zh', 'es'],\n}\n\nfunction extractVariables(text: string): string[] {\n const matches = text.match(/\\{(\\w+)\\}/g)\n if (!matches) return []\n return matches.map((m) => m.slice(1, -1))\n}\n\nconst ICU_TYPE_PATTERN = /\\{(\\w+),\\s*(\\w+)/g\n\nfunction extractICUTypes(text: string): ICUTypeInfo[] {\n const types: ICUTypeInfo[] = []\n let match: RegExpExecArray | null\n ICU_TYPE_PATTERN.lastIndex = 0\n while ((match = ICU_TYPE_PATTERN.exec(text)) !== null) {\n types.push({ variable: match[1]!, type: match[2]! })\n }\n return types\n}\n\nfunction parseFile(filePath: string): TranslationEntry[] {\n const entries: TranslationEntry[] = []\n const code = fs.readFileSync(filePath, 'utf-8')\n\n let ast\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n })\n } catch {\n return []\n }\n\n traverse(ast, {\n CallExpression(nodePath) {\n const { node } = nodePath\n const { callee } = node\n\n if (callee.type !== 'Identifier') return\n if (!IT_FUNCTION_NAMES.includes(callee.name)) return\n\n const funcName = callee.name\n const args = node.arguments\n const loc = node.loc\n\n if (!loc) return\n\n const entry: TranslationEntry = {\n file: filePath,\n line: loc.start.line,\n column: loc.start.column,\n translations: {},\n variables: [],\n }\n\n if (args[0]?.type === 'ObjectExpression') {\n const obj = args[0]\n for (const prop of obj.properties) {\n if (\n prop.type === 'ObjectProperty' &&\n prop.key.type === 'Identifier' &&\n prop.value.type === 'StringLiteral'\n ) {\n entry.translations[prop.key.name] = prop.value.value\n entry.variables.push(...extractVariables(prop.value.value))\n // Extract ICU type info (v0.7.0)\n const types = extractICUTypes(prop.value.value)\n if (types.length > 0) {\n if (!entry.icuTypes) entry.icuTypes = {}\n entry.icuTypes[prop.key.name] = types\n }\n }\n }\n } else if (\n args[0]?.type === 'StringLiteral' &&\n args[1]?.type === 'StringLiteral'\n ) {\n const [lang1, lang2] = PAIR_MAPPING[funcName] || ['ko', 'en']\n entry.translations[lang1] = args[0].value\n entry.translations[lang2] = args[1].value\n entry.variables.push(...extractVariables(args[0].value))\n entry.variables.push(...extractVariables(args[1].value))\n // Extract ICU type info (v0.7.0)\n const types1 = extractICUTypes(args[0].value)\n if (types1.length > 0) {\n if (!entry.icuTypes) entry.icuTypes = {}\n entry.icuTypes[lang1] = types1\n }\n const types2 = extractICUTypes(args[1].value)\n if (types2.length > 0) {\n if (!entry.icuTypes) entry.icuTypes = {}\n entry.icuTypes[lang2] = types2\n }\n }\n\n entry.variables = [...new Set(entry.variables)]\n\n if (Object.keys(entry.translations).length > 0) {\n entries.push(entry)\n }\n },\n })\n\n return entries\n}\n\n// v0.8.0: Flatten nested ObjectExpression to dot-notation keys\nfunction flattenObjectKeys(\n node: { type: string; properties?: unknown[] },\n prefix: string = '',\n): string[] {\n const keys: string[] = []\n if (node.type !== 'ObjectExpression' || !node.properties) return keys\n\n for (const prop of node.properties as Array<{\n type: string\n key: { type: string; name?: string; value?: string }\n value: { type: string; properties?: unknown[] }\n }>) {\n if (prop.type !== 'ObjectProperty') continue\n\n let propName: string | undefined\n if (prop.key.type === 'Identifier') propName = prop.key.name\n else if (prop.key.type === 'StringLiteral') propName = prop.key.value\n\n if (!propName) continue\n\n const fullKey = prefix ? `${prefix}.${propName}` : propName\n\n if (prop.value.type === 'StringLiteral') {\n keys.push(fullKey)\n } else if (prop.value.type === 'ObjectExpression') {\n keys.push(...flattenObjectKeys(prop.value, fullKey))\n }\n }\n return keys\n}\n\n// v0.8.0: Extract dictionary keys from loadDictionaries() calls\nexport function parseDictionaryKeys(filePath: string): DictionaryKeyEntry[] {\n const entries: DictionaryKeyEntry[] = []\n const code = fs.readFileSync(filePath, 'utf-8')\n\n let ast\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n })\n } catch {\n return []\n }\n\n traverse(ast, {\n CallExpression(nodePath) {\n const { node } = nodePath\n const { callee } = node\n\n if (callee.type !== 'Identifier' || callee.name !== 'loadDictionaries') return\n\n const args = node.arguments\n const loc = node.loc\n if (!loc || !args[0] || args[0].type !== 'ObjectExpression') return\n\n // Second argument is optional namespace\n let namespace = 'default'\n if (args[1]?.type === 'StringLiteral') {\n namespace = args[1].value\n }\n\n // First argument: { locale: { key: value } }\n // Collect keys from the first locale's dict (all locales should have same keys)\n const dictObj = args[0]\n const allKeys = new Set<string>()\n\n for (const localeProp of dictObj.properties as Array<{\n type: string\n value: { type: string; properties?: unknown[] }\n }>) {\n if (localeProp.type !== 'ObjectProperty') continue\n if (localeProp.value.type !== 'ObjectExpression') continue\n\n const localeKeys = flattenObjectKeys(localeProp.value)\n for (const key of localeKeys) {\n allKeys.add(key)\n }\n }\n\n if (allKeys.size > 0) {\n entries.push({\n file: filePath,\n line: loc.start.line,\n namespace,\n keys: [...allKeys],\n })\n }\n },\n })\n\n return entries\n}\n\n// v0.8.0: Extract t() call sites\nexport function parseTCalls(filePath: string): TCallEntry[] {\n const entries: TCallEntry[] = []\n const code = fs.readFileSync(filePath, 'utf-8')\n\n let ast\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n })\n } catch {\n return []\n }\n\n traverse(ast, {\n CallExpression(nodePath) {\n const { node } = nodePath\n const { callee } = node\n\n if (callee.type !== 'Identifier' || callee.name !== 't') return\n\n const args = node.arguments\n const loc = node.loc\n if (!loc || !args[0] || args[0].type !== 'StringLiteral') return\n\n entries.push({\n file: filePath,\n line: loc.start.line,\n key: args[0].value,\n })\n },\n })\n\n return entries\n}\n\nexport async function extractProjectDictionaryKeys(options: ParseOptions = {}): Promise<DictionaryKeyEntry[]> {\n const {\n cwd = process.cwd(),\n include = ['**/*.{ts,tsx,js,jsx}'],\n exclude = ['**/node_modules/**', '**/dist/**', '**/.next/**'],\n } = options\n\n const files = await fg(include, { cwd, ignore: exclude, absolute: true })\n const allEntries: DictionaryKeyEntry[] = []\n\n for (const file of files) {\n allEntries.push(...parseDictionaryKeys(file))\n }\n\n return allEntries\n}\n\nexport async function extractProjectTCalls(options: ParseOptions = {}): Promise<TCallEntry[]> {\n const {\n cwd = process.cwd(),\n include = ['**/*.{ts,tsx,js,jsx}'],\n exclude = ['**/node_modules/**', '**/dist/**', '**/.next/**'],\n } = options\n\n const files = await fg(include, { cwd, ignore: exclude, absolute: true })\n const allEntries: TCallEntry[] = []\n\n for (const file of files) {\n allEntries.push(...parseTCalls(file))\n }\n\n return allEntries\n}\n\nexport async function parseProject(options: ParseOptions = {}): Promise<TranslationEntry[]> {\n const {\n cwd = process.cwd(),\n include = ['**/*.{ts,tsx,js,jsx}'],\n exclude = ['**/node_modules/**', '**/dist/**', '**/.next/**'],\n } = options\n\n const files = await fg(include, {\n cwd,\n ignore: exclude,\n absolute: true,\n })\n\n const allEntries: TranslationEntry[] = []\n\n for (const file of files) {\n const entries = parseFile(file)\n allEntries.push(...entries)\n }\n\n return allEntries\n}\n","import chalk from 'chalk'\nimport { parseProject, type TranslationEntry } from '../parser'\nimport { unused } from './unused'\n\ninterface ValidateOptions {\n cwd?: string\n locales?: string[]\n strict?: boolean\n unused?: boolean\n noExit?: boolean\n}\n\ninterface Issue {\n type: 'inconsistent' | 'missing' | 'variable_mismatch' | 'icu_type_mismatch'\n message: string\n entries: TranslationEntry[]\n details?: string[]\n}\n\nfunction checkVariableConsistency(entry: TranslationEntry): Issue | null {\n const varsByLocale: { locale: string; vars: string[] }[] = []\n\n for (const [locale, text] of Object.entries(entry.translations)) {\n const matches = text.match(/\\{(\\w+)\\}/g) || []\n const varNames = [...new Set(matches.map((v) => v.slice(1, -1)))].sort()\n varsByLocale.push({ locale, vars: varNames })\n }\n\n if (varsByLocale.length < 2) return null\n\n const reference = varsByLocale[0]!\n const details: string[] = []\n\n for (let i = 1; i < varsByLocale.length; i++) {\n const current = varsByLocale[i]!\n const refSet = new Set(reference.vars)\n const curSet = new Set(current.vars)\n\n const onlyInRef = reference.vars.filter((v) => !curSet.has(v))\n const onlyInCur = current.vars.filter((v) => !refSet.has(v))\n\n if (onlyInRef.length > 0) {\n details.push(\n `${reference.locale} has {${onlyInRef.join('}, {')}} missing in ${current.locale}`,\n )\n }\n if (onlyInCur.length > 0) {\n details.push(\n `${current.locale} has {${onlyInCur.join('}, {')}} missing in ${reference.locale}`,\n )\n }\n }\n\n if (details.length === 0) return null\n\n return {\n type: 'variable_mismatch',\n message: 'Variable mismatch between translations',\n entries: [entry],\n details,\n }\n}\n\nfunction checkICUTypeConsistency(entry: TranslationEntry): Issue | null {\n if (!entry.icuTypes) return null\n\n const locales = Object.keys(entry.icuTypes)\n if (locales.length < 2) return null\n\n const details: string[] = []\n const reference = locales[0]!\n const refTypes = entry.icuTypes[reference]!\n\n for (let i = 1; i < locales.length; i++) {\n const locale = locales[i]!\n const curTypes = entry.icuTypes[locale]!\n\n for (const refType of refTypes) {\n const match = curTypes.find((t: { variable: string; type: string }) => t.variable === refType.variable)\n if (match && match.type !== refType.type) {\n details.push(\n `{${refType.variable}} is \"${refType.type}\" in ${reference} but \"${match.type}\" in ${locale}`,\n )\n }\n }\n }\n\n if (details.length === 0) return null\n\n return {\n type: 'icu_type_mismatch',\n message: 'ICU type mismatch between translations',\n entries: [entry],\n details,\n }\n}\n\nexport async function validate(options: ValidateOptions = {}): Promise<void> {\n const { cwd, locales, strict, unused: checkUnused } = options\n\n console.log(chalk.blue('\\nValidating translations...\\n'))\n\n const entries = await parseProject({ cwd })\n const issues: Issue[] = []\n\n // group by first language text (usually ko)\n const groups = new Map<string, TranslationEntry[]>()\n\n for (const entry of entries) {\n const key = Object.values(entry.translations)[0] || ''\n if (!groups.has(key)) {\n groups.set(key, [])\n }\n groups.get(key)!.push(entry)\n }\n\n // check for inconsistent translations\n for (const [key, group] of groups) {\n if (group.length < 2) continue\n\n const translationSets = group.map((e) => JSON.stringify(e.translations))\n const uniqueSets = [...new Set(translationSets)]\n\n if (uniqueSets.length > 1) {\n issues.push({\n type: 'inconsistent',\n message: `Inconsistent translations for \"${key}\"`,\n entries: group,\n })\n }\n }\n\n // check for missing locales\n if (locales && locales.length > 0) {\n for (const entry of entries) {\n const missing = locales.filter((l) => !entry.translations[l])\n\n if (missing.length > 0) {\n issues.push({\n type: 'missing',\n message: `Missing locales: ${missing.join(', ')}`,\n entries: [entry],\n })\n }\n }\n }\n\n // check for variable name consistency (enhanced in v0.7.0)\n for (const entry of entries) {\n const issue = checkVariableConsistency(entry)\n if (issue) issues.push(issue)\n }\n\n // check for ICU type consistency (strict mode, v0.7.0)\n if (strict) {\n for (const entry of entries) {\n const issue = checkICUTypeConsistency(entry)\n if (issue) issues.push(issue)\n }\n }\n\n // unused key detection (v0.8.0)\n let unusedCount = 0\n if (checkUnused) {\n const result = await unused({ cwd })\n unusedCount = result.unusedKeys.length\n }\n\n // print results\n if (issues.length === 0 && unusedCount === 0) {\n console.log(chalk.green('All translations are valid!\\n'))\n console.log(chalk.gray(`Checked ${entries.length} translation(s)`))\n if (strict) {\n console.log(chalk.gray('(strict mode enabled)'))\n }\n if (checkUnused) {\n console.log(chalk.gray('(unused key detection enabled)'))\n }\n return\n }\n\n console.log(chalk.red(`Found ${issues.length} issue(s):\\n`))\n\n for (const issue of issues) {\n console.log(` ${chalk.yellow(issue.message)}`)\n\n for (const entry of issue.entries) {\n const relativePath = entry.file.replace(process.cwd() + '/', '')\n console.log(chalk.gray(` ${relativePath}:${entry.line}`))\n\n for (const [locale, text] of Object.entries(entry.translations)) {\n console.log(` ${chalk.cyan(locale)}: ${text}`)\n }\n }\n\n if (issue.details && issue.details.length > 0) {\n for (const detail of issue.details) {\n console.log(chalk.gray(` → ${detail}`))\n }\n }\n\n console.log()\n }\n\n if ((issues.length > 0 || unusedCount > 0) && !options.noExit) {\n process.exit(1)\n }\n}\n","import chalk from 'chalk'\nimport { extractProjectDictionaryKeys, extractProjectTCalls } from '../parser'\n\ninterface UnusedKey {\n namespace: string\n key: string\n definedIn: string\n line: number\n}\n\nconst PLURAL_SUFFIXES = ['_zero', '_one', '_two', '_few', '_many', '_other']\n\nexport async function unused(options: { cwd?: string } = {}): Promise<{ unusedKeys: UnusedKey[] }> {\n const { cwd } = options\n\n console.log(chalk.blue('\\nDetecting unused translations...\\n'))\n\n const dictEntries = await extractProjectDictionaryKeys({ cwd })\n const tCalls = await extractProjectTCalls({ cwd })\n\n // Build set of used keys (normalized: namespace:key or key for default)\n const usedKeys = new Set<string>()\n for (const call of tCalls) {\n usedKeys.add(call.key)\n // Also add with default namespace if no namespace prefix\n if (!call.key.includes(':')) {\n usedKeys.add(call.key)\n }\n }\n\n // Check each dictionary key against used keys\n const unusedKeys: UnusedKey[] = []\n\n for (const entry of dictEntries) {\n for (const key of entry.keys) {\n const fullKey = entry.namespace === 'default' ? key : `${entry.namespace}:${key}`\n\n // Check if key is directly used\n if (usedKeys.has(fullKey)) continue\n\n // Check if this is a plural suffix variant (e.g. count_one, count_other)\n // and the base key is used via t('items.count', { count: N })\n let isPluralVariant = false\n for (const suffix of PLURAL_SUFFIXES) {\n if (key.endsWith(suffix)) {\n const baseKey = key.slice(0, -suffix.length)\n const fullBaseKey = entry.namespace === 'default' ? baseKey : `${entry.namespace}:${baseKey}`\n if (usedKeys.has(fullBaseKey)) {\n isPluralVariant = true\n break\n }\n }\n }\n if (isPluralVariant) continue\n\n unusedKeys.push({\n namespace: entry.namespace,\n key: fullKey,\n definedIn: entry.file,\n line: entry.line,\n })\n }\n }\n\n // Report results\n if (unusedKeys.length === 0) {\n const totalKeys = dictEntries.reduce((sum, e) => sum + e.keys.length, 0)\n console.log(chalk.green('No unused translations found!\\n'))\n console.log(chalk.gray(`Checked ${totalKeys} dictionary key(s) against ${tCalls.length} t() call(s)`))\n return { unusedKeys }\n }\n\n console.log(chalk.yellow(`Found ${unusedKeys.length} unused translation key(s):\\n`))\n for (const item of unusedKeys) {\n const relativePath = item.definedIn.replace(process.cwd() + '/', '')\n console.log(` ${chalk.red('-')} ${chalk.cyan(item.key)}`)\n console.log(chalk.gray(` defined in ${relativePath}:${item.line}`))\n }\n\n console.log()\n return { unusedKeys }\n}\n","import chalk from 'chalk'\nimport { parseProject } from '../parser'\n\ninterface CoverageOptions {\n cwd?: string\n locales: string[]\n}\n\ninterface LocaleCoverage {\n locale: string\n total: number\n translated: number\n percentage: number\n}\n\nexport async function coverage(options: CoverageOptions): Promise<void> {\n const { cwd, locales } = options\n\n console.log(chalk.blue('\\nAnalyzing translation coverage...\\n'))\n\n const entries = await parseProject({ cwd })\n\n if (entries.length === 0) {\n console.log(chalk.yellow('No translations found.'))\n return\n }\n\n const coverageData: LocaleCoverage[] = []\n\n for (const locale of locales) {\n let translated = 0\n\n for (const entry of entries) {\n if (entry.translations[locale]) {\n translated++\n }\n }\n\n const percentage = Math.round((translated / entries.length) * 100)\n\n coverageData.push({\n locale,\n total: entries.length,\n translated,\n percentage,\n })\n }\n\n // print coverage table\n console.log(chalk.bold('Translation Coverage:\\n'))\n\n const maxLocaleLen = Math.max(...locales.map((l) => l.length), 6)\n\n console.log(\n chalk.gray(\n `${'Locale'.padEnd(maxLocaleLen)} ${'Coverage'.padStart(10)} ${'Translated'.padStart(12)}`\n )\n )\n console.log(chalk.gray('─'.repeat(maxLocaleLen + 26)))\n\n for (const data of coverageData) {\n const color =\n data.percentage === 100 ? chalk.green :\n data.percentage >= 80 ? chalk.yellow : chalk.red\n\n const bar = createProgressBar(data.percentage, 10)\n const percentStr = `${data.percentage}%`.padStart(4)\n\n console.log(\n `${data.locale.padEnd(maxLocaleLen)} ${color(bar)} ${color(percentStr)} ${chalk.gray(`${data.translated}/${data.total}`)}`\n )\n }\n\n console.log()\n\n // summary\n const fullyCovered = coverageData.filter((d) => d.percentage === 100).length\n const partiallyCovered = coverageData.filter((d) => d.percentage > 0 && d.percentage < 100).length\n const notCovered = coverageData.filter((d) => d.percentage === 0).length\n\n if (fullyCovered === locales.length) {\n console.log(chalk.green('All locales are fully translated!'))\n } else {\n console.log(chalk.gray(`Full: ${fullyCovered}, Partial: ${partiallyCovered}, Empty: ${notCovered}`))\n }\n}\n\nfunction createProgressBar(percentage: number, width: number): string {\n const filled = Math.round((percentage / 100) * width)\n const empty = width - filled\n\n return '█'.repeat(filled) + '░'.repeat(empty)\n}\n","import * as fs from 'fs'\nimport * as path from 'path'\nimport chalk from 'chalk'\nimport { extractProjectDictionaryKeys } from '../parser'\n\ninterface TypegenOptions {\n cwd?: string\n output?: string\n}\n\nconst PLURAL_SUFFIXES = ['_zero', '_one', '_two', '_few', '_many', '_other']\n\nexport async function typegen(options: TypegenOptions = {}): Promise<void> {\n const { cwd, output = 'src/i18n.d.ts' } = options\n\n console.log(chalk.blue('\\nGenerating TypeScript types...\\n'))\n\n const dictEntries = await extractProjectDictionaryKeys({ cwd })\n\n // Collect all unique full keys (namespace:key or key)\n const allKeys = new Set<string>()\n\n for (const entry of dictEntries) {\n for (const key of entry.keys) {\n const fullKey = entry.namespace === 'default' ? key : `${entry.namespace}:${key}`\n allKeys.add(fullKey)\n\n // Also add plural base keys (strip _one, _other, etc.)\n for (const suffix of PLURAL_SUFFIXES) {\n if (key.endsWith(suffix)) {\n const baseKey = key.slice(0, -suffix.length)\n const fullBaseKey = entry.namespace === 'default' ? baseKey : `${entry.namespace}:${baseKey}`\n allKeys.add(fullBaseKey)\n }\n }\n }\n }\n\n if (allKeys.size === 0) {\n console.log(chalk.yellow('No dictionary keys found. Make sure loadDictionaries() calls are present.'))\n return\n }\n\n const sortedKeys = [...allKeys].sort()\n\n // Generate the .d.ts content\n const keyUnion = sortedKeys.map(k => ` | '${k}'`).join('\\n')\n\n const content = `// Auto-generated by inline-i18n typegen\n// Do not edit manually. Re-run: npx inline-i18n typegen\n\nimport 'inline-i18n-multi'\n\ndeclare module 'inline-i18n-multi' {\n export type TranslationKey =\n${keyUnion}\n\n export function t(\n key: TranslationKey,\n vars?: TranslationVars,\n locale?: string\n ): string\n\n export function hasTranslation(\n key: TranslationKey,\n locale?: string\n ): boolean\n}\n`\n\n const outputPath = path.resolve(cwd || process.cwd(), output)\n const outputDir = path.dirname(outputPath)\n\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true })\n }\n\n fs.writeFileSync(outputPath, content, 'utf-8')\n\n console.log(chalk.green(`Generated ${sortedKeys.length} translation key types`))\n console.log(chalk.gray(`Output: ${outputPath}\\n`))\n\n // Show sample\n const sample = sortedKeys.slice(0, 5)\n for (const key of sample) {\n console.log(` ${chalk.cyan(key)}`)\n }\n if (sortedKeys.length > 5) {\n console.log(chalk.gray(` ... and ${sortedKeys.length - 5} more`))\n }\n}\n","import chalk from 'chalk'\nimport * as fs from 'fs'\nimport * as path from 'path'\nimport { parseProject } from '../parser'\n\ninterface ExtractOptions {\n cwd?: string\n output?: string\n format?: 'flat' | 'nested'\n}\n\nexport async function extract(options: ExtractOptions = {}): Promise<void> {\n const { cwd, output = 'translations', format = 'flat' } = options\n\n console.log(chalk.blue('\\nExtracting inline translations...\\n'))\n\n const entries = await parseProject({ cwd })\n\n if (entries.length === 0) {\n console.log(chalk.yellow('No translations found.'))\n return\n }\n\n // Group translations by locale\n const byLocale: Record<string, Record<string, string>> = {}\n const basePath = cwd || process.cwd()\n\n for (const entry of entries) {\n for (const [locale, text] of Object.entries(entry.translations)) {\n if (!byLocale[locale]) byLocale[locale] = {}\n\n const relativePath = entry.file.replace(basePath + '/', '')\n const key = `${relativePath}:${entry.line}`\n byLocale[locale][key] = text\n }\n }\n\n // Write output files\n const outputDir = path.resolve(basePath, output)\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true })\n }\n\n const locales = Object.keys(byLocale).sort()\n for (const locale of locales) {\n const translations = byLocale[locale]!\n let content: string\n\n if (format === 'nested') {\n const nested = buildNestedObject(translations)\n content = JSON.stringify(nested, null, 2) + '\\n'\n } else {\n content = JSON.stringify(translations, null, 2) + '\\n'\n }\n\n const filePath = path.join(outputDir, `${locale}.json`)\n fs.writeFileSync(filePath, content)\n console.log(\n chalk.green(` ${locale}.json`) +\n chalk.gray(` (${Object.keys(translations).length} keys)`)\n )\n }\n\n console.log(chalk.gray(`\\nExtracted ${entries.length} translation(s) to ${output}/`))\n}\n\n/**\n * Build a nested object from flat dot-notation keys\n */\nfunction buildNestedObject(flat: Record<string, string>): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n\n for (const [key, value] of Object.entries(flat)) {\n const parts = key.split('.')\n let current: Record<string, unknown> = result\n\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i]!\n if (!current[part] || typeof current[part] !== 'object') {\n current[part] = {}\n }\n current = current[part] as Record<string, unknown>\n }\n\n current[parts[parts.length - 1]!] = value\n }\n\n return result\n}\n","import { watch } from 'chokidar'\nimport chalk from 'chalk'\n\ninterface WatchOptions {\n cwd: string\n patterns: string[]\n ignore: string[]\n onChange: () => Promise<void>\n label: string\n}\n\nexport function startWatch(options: WatchOptions): void {\n const { cwd, patterns, ignore, onChange, label } = options\n\n console.log(chalk.blue(`\\nWatching for changes (${label})...\\n`))\n console.log(chalk.gray('Press Ctrl+C to stop\\n'))\n\n const watcher = watch(patterns, {\n cwd,\n ignored: ignore,\n ignoreInitial: true,\n })\n\n let debounceTimer: ReturnType<typeof setTimeout> | null = null\n\n const handleChange = (filePath: string) => {\n if (debounceTimer) clearTimeout(debounceTimer)\n debounceTimer = setTimeout(async () => {\n console.log(chalk.gray(`\\nChange detected: ${filePath}`))\n console.log(chalk.gray('-'.repeat(40)))\n try {\n await onChange()\n } catch {\n // Error already printed by the command\n }\n console.log(chalk.gray(`\\nWatching for changes (${label})...`))\n }, 300)\n }\n\n watcher.on('change', handleChange)\n watcher.on('add', handleChange)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uBAAwB;;;ACAxB,mBAAkB;;;ACAlB,oBAAsB;AACtB,sBAAqB;AACrB,SAAoB;AACpB,uBAAe;AAsCf,IAAM,oBAAoB;AAAA,EACxB;AAAA,EACA;AAAA,EAAS;AAAA,EAAS;AAAA,EAAS;AAAA,EAAS;AAAA,EACpC;AAAA,EAAS;AAAA,EAAS;AAAA,EAAS;AAAA,EAAS;AAAA,EACpC;AAAA,EAAS;AAAA,EAAS;AACpB;AAEA,IAAM,eAAiD;AAAA,EACrD,IAAI,CAAC,MAAM,IAAI;AAAA,EACf,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AACpB;AAEA,SAAS,iBAAiB,MAAwB;AAChD,QAAM,UAAU,KAAK,MAAM,YAAY;AACvC,MAAI,CAAC,QAAS,QAAO,CAAC;AACtB,SAAO,QAAQ,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC;AAC1C;AAEA,IAAM,mBAAmB;AAEzB,SAAS,gBAAgB,MAA6B;AACpD,QAAM,QAAuB,CAAC;AAC9B,MAAI;AACJ,mBAAiB,YAAY;AAC7B,UAAQ,QAAQ,iBAAiB,KAAK,IAAI,OAAO,MAAM;AACrD,UAAM,KAAK,EAAE,UAAU,MAAM,CAAC,GAAI,MAAM,MAAM,CAAC,EAAG,CAAC;AAAA,EACrD;AACA,SAAO;AACT;AAEA,SAAS,UAAU,UAAsC;AACvD,QAAM,UAA8B,CAAC;AACrC,QAAM,OAAU,gBAAa,UAAU,OAAO;AAE9C,MAAI;AACJ,MAAI;AACF,cAAM,qBAAM,MAAM;AAAA,MAChB,YAAY;AAAA,MACZ,SAAS,CAAC,cAAc,KAAK;AAAA,IAC/B,CAAC;AAAA,EACH,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AAEA,sBAAAA,SAAS,KAAK;AAAA,IACZ,eAAe,UAAU;AACvB,YAAM,EAAE,KAAK,IAAI;AACjB,YAAM,EAAE,OAAO,IAAI;AAEnB,UAAI,OAAO,SAAS,aAAc;AAClC,UAAI,CAAC,kBAAkB,SAAS,OAAO,IAAI,EAAG;AAE9C,YAAM,WAAW,OAAO;AACxB,YAAM,OAAO,KAAK;AAClB,YAAM,MAAM,KAAK;AAEjB,UAAI,CAAC,IAAK;AAEV,YAAM,QAA0B;AAAA,QAC9B,MAAM;AAAA,QACN,MAAM,IAAI,MAAM;AAAA,QAChB,QAAQ,IAAI,MAAM;AAAA,QAClB,cAAc,CAAC;AAAA,QACf,WAAW,CAAC;AAAA,MACd;AAEA,UAAI,KAAK,CAAC,GAAG,SAAS,oBAAoB;AACxC,cAAM,MAAM,KAAK,CAAC;AAClB,mBAAW,QAAQ,IAAI,YAAY;AACjC,cACE,KAAK,SAAS,oBACd,KAAK,IAAI,SAAS,gBAClB,KAAK,MAAM,SAAS,iBACpB;AACA,kBAAM,aAAa,KAAK,IAAI,IAAI,IAAI,KAAK,MAAM;AAC/C,kBAAM,UAAU,KAAK,GAAG,iBAAiB,KAAK,MAAM,KAAK,CAAC;AAE1D,kBAAM,QAAQ,gBAAgB,KAAK,MAAM,KAAK;AAC9C,gBAAI,MAAM,SAAS,GAAG;AACpB,kBAAI,CAAC,MAAM,SAAU,OAAM,WAAW,CAAC;AACvC,oBAAM,SAAS,KAAK,IAAI,IAAI,IAAI;AAAA,YAClC;AAAA,UACF;AAAA,QACF;AAAA,MACF,WACE,KAAK,CAAC,GAAG,SAAS,mBAClB,KAAK,CAAC,GAAG,SAAS,iBAClB;AACA,cAAM,CAAC,OAAO,KAAK,IAAI,aAAa,QAAQ,KAAK,CAAC,MAAM,IAAI;AAC5D,cAAM,aAAa,KAAK,IAAI,KAAK,CAAC,EAAE;AACpC,cAAM,aAAa,KAAK,IAAI,KAAK,CAAC,EAAE;AACpC,cAAM,UAAU,KAAK,GAAG,iBAAiB,KAAK,CAAC,EAAE,KAAK,CAAC;AACvD,cAAM,UAAU,KAAK,GAAG,iBAAiB,KAAK,CAAC,EAAE,KAAK,CAAC;AAEvD,cAAM,SAAS,gBAAgB,KAAK,CAAC,EAAE,KAAK;AAC5C,YAAI,OAAO,SAAS,GAAG;AACrB,cAAI,CAAC,MAAM,SAAU,OAAM,WAAW,CAAC;AACvC,gBAAM,SAAS,KAAK,IAAI;AAAA,QAC1B;AACA,cAAM,SAAS,gBAAgB,KAAK,CAAC,EAAE,KAAK;AAC5C,YAAI,OAAO,SAAS,GAAG;AACrB,cAAI,CAAC,MAAM,SAAU,OAAM,WAAW,CAAC;AACvC,gBAAM,SAAS,KAAK,IAAI;AAAA,QAC1B;AAAA,MACF;AAEA,YAAM,YAAY,CAAC,GAAG,IAAI,IAAI,MAAM,SAAS,CAAC;AAE9C,UAAI,OAAO,KAAK,MAAM,YAAY,EAAE,SAAS,GAAG;AAC9C,gBAAQ,KAAK,KAAK;AAAA,MACpB;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAGA,SAAS,kBACP,MACA,SAAiB,IACP;AACV,QAAM,OAAiB,CAAC;AACxB,MAAI,KAAK,SAAS,sBAAsB,CAAC,KAAK,WAAY,QAAO;AAEjE,aAAW,QAAQ,KAAK,YAIpB;AACF,QAAI,KAAK,SAAS,iBAAkB;AAEpC,QAAI;AACJ,QAAI,KAAK,IAAI,SAAS,aAAc,YAAW,KAAK,IAAI;AAAA,aAC/C,KAAK,IAAI,SAAS,gBAAiB,YAAW,KAAK,IAAI;AAEhE,QAAI,CAAC,SAAU;AAEf,UAAM,UAAU,SAAS,GAAG,MAAM,IAAI,QAAQ,KAAK;AAEnD,QAAI,KAAK,MAAM,SAAS,iBAAiB;AACvC,WAAK,KAAK,OAAO;AAAA,IACnB,WAAW,KAAK,MAAM,SAAS,oBAAoB;AACjD,WAAK,KAAK,GAAG,kBAAkB,KAAK,OAAO,OAAO,CAAC;AAAA,IACrD;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,oBAAoB,UAAwC;AAC1E,QAAM,UAAgC,CAAC;AACvC,QAAM,OAAU,gBAAa,UAAU,OAAO;AAE9C,MAAI;AACJ,MAAI;AACF,cAAM,qBAAM,MAAM;AAAA,MAChB,YAAY;AAAA,MACZ,SAAS,CAAC,cAAc,KAAK;AAAA,IAC/B,CAAC;AAAA,EACH,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AAEA,sBAAAA,SAAS,KAAK;AAAA,IACZ,eAAe,UAAU;AACvB,YAAM,EAAE,KAAK,IAAI;AACjB,YAAM,EAAE,OAAO,IAAI;AAEnB,UAAI,OAAO,SAAS,gBAAgB,OAAO,SAAS,mBAAoB;AAExE,YAAM,OAAO,KAAK;AAClB,YAAM,MAAM,KAAK;AACjB,UAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,EAAE,SAAS,mBAAoB;AAG7D,UAAI,YAAY;AAChB,UAAI,KAAK,CAAC,GAAG,SAAS,iBAAiB;AACrC,oBAAY,KAAK,CAAC,EAAE;AAAA,MACtB;AAIA,YAAM,UAAU,KAAK,CAAC;AACtB,YAAM,UAAU,oBAAI,IAAY;AAEhC,iBAAW,cAAc,QAAQ,YAG7B;AACF,YAAI,WAAW,SAAS,iBAAkB;AAC1C,YAAI,WAAW,MAAM,SAAS,mBAAoB;AAElD,cAAM,aAAa,kBAAkB,WAAW,KAAK;AACrD,mBAAW,OAAO,YAAY;AAC5B,kBAAQ,IAAI,GAAG;AAAA,QACjB;AAAA,MACF;AAEA,UAAI,QAAQ,OAAO,GAAG;AACpB,gBAAQ,KAAK;AAAA,UACX,MAAM;AAAA,UACN,MAAM,IAAI,MAAM;AAAA,UAChB;AAAA,UACA,MAAM,CAAC,GAAG,OAAO;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAGO,SAAS,YAAY,UAAgC;AAC1D,QAAM,UAAwB,CAAC;AAC/B,QAAM,OAAU,gBAAa,UAAU,OAAO;AAE9C,MAAI;AACJ,MAAI;AACF,cAAM,qBAAM,MAAM;AAAA,MAChB,YAAY;AAAA,MACZ,SAAS,CAAC,cAAc,KAAK;AAAA,IAC/B,CAAC;AAAA,EACH,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AAEA,sBAAAA,SAAS,KAAK;AAAA,IACZ,eAAe,UAAU;AACvB,YAAM,EAAE,KAAK,IAAI;AACjB,YAAM,EAAE,OAAO,IAAI;AAEnB,UAAI,OAAO,SAAS,gBAAgB,OAAO,SAAS,IAAK;AAEzD,YAAM,OAAO,KAAK;AAClB,YAAM,MAAM,KAAK;AACjB,UAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,EAAE,SAAS,gBAAiB;AAE1D,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,MAAM,IAAI,MAAM;AAAA,QAChB,KAAK,KAAK,CAAC,EAAE;AAAA,MACf,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAEA,eAAsB,6BAA6B,UAAwB,CAAC,GAAkC;AAC5G,QAAM;AAAA,IACJ,MAAM,QAAQ,IAAI;AAAA,IAClB,UAAU,CAAC,sBAAsB;AAAA,IACjC,UAAU,CAAC,sBAAsB,cAAc,aAAa;AAAA,EAC9D,IAAI;AAEJ,QAAM,QAAQ,UAAM,iBAAAC,SAAG,SAAS,EAAE,KAAK,QAAQ,SAAS,UAAU,KAAK,CAAC;AACxE,QAAM,aAAmC,CAAC;AAE1C,aAAW,QAAQ,OAAO;AACxB,eAAW,KAAK,GAAG,oBAAoB,IAAI,CAAC;AAAA,EAC9C;AAEA,SAAO;AACT;AAEA,eAAsB,qBAAqB,UAAwB,CAAC,GAA0B;AAC5F,QAAM;AAAA,IACJ,MAAM,QAAQ,IAAI;AAAA,IAClB,UAAU,CAAC,sBAAsB;AAAA,IACjC,UAAU,CAAC,sBAAsB,cAAc,aAAa;AAAA,EAC9D,IAAI;AAEJ,QAAM,QAAQ,UAAM,iBAAAA,SAAG,SAAS,EAAE,KAAK,QAAQ,SAAS,UAAU,KAAK,CAAC;AACxE,QAAM,aAA2B,CAAC;AAElC,aAAW,QAAQ,OAAO;AACxB,eAAW,KAAK,GAAG,YAAY,IAAI,CAAC;AAAA,EACtC;AAEA,SAAO;AACT;AAEA,eAAsB,aAAa,UAAwB,CAAC,GAAgC;AAC1F,QAAM;AAAA,IACJ,MAAM,QAAQ,IAAI;AAAA,IAClB,UAAU,CAAC,sBAAsB;AAAA,IACjC,UAAU,CAAC,sBAAsB,cAAc,aAAa;AAAA,EAC9D,IAAI;AAEJ,QAAM,QAAQ,UAAM,iBAAAA,SAAG,SAAS;AAAA,IAC9B;AAAA,IACA,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ,CAAC;AAED,QAAM,aAAiC,CAAC;AAExC,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAU,UAAU,IAAI;AAC9B,eAAW,KAAK,GAAG,OAAO;AAAA,EAC5B;AAEA,SAAO;AACT;;;AD9VA,eAAsB,KAAK,SAAqC;AAC9D,QAAM,EAAE,OAAO,IAAI,IAAI;AAEvB,UAAQ,IAAI,aAAAC,QAAM,KAAK;AAAA,kBAAqB,KAAK;AAAA,CAAK,CAAC;AAEvD,QAAM,UAAU,MAAM,aAAa,EAAE,IAAI,CAAC;AAC1C,QAAM,UAA8B,CAAC;AAErC,QAAM,aAAa,MAAM,YAAY;AAErC,aAAW,SAAS,SAAS;AAC3B,UAAM,SAAS,OAAO,OAAO,MAAM,YAAY;AAC/C,UAAM,UAAU,OAAO,KAAK,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,UAAU,CAAC;AAEvE,QAAI,SAAS;AACX,cAAQ,KAAK,KAAK;AAAA,IACpB;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,IAAI,aAAAA,QAAM,OAAO,mBAAmB,CAAC;AAC7C;AAAA,EACF;AAEA,UAAQ,IAAI,aAAAA,QAAM,MAAM,SAAS,QAAQ,MAAM;AAAA,CAAmB,CAAC;AAEnE,aAAW,UAAU,SAAS;AAC5B,UAAM,eAAe,OAAO,KAAK,QAAQ,QAAQ,IAAI,IAAI,KAAK,EAAE;AAChE,YAAQ,IAAI,aAAAA,QAAM,KAAK,GAAG,YAAY,IAAI,OAAO,IAAI,IAAI,OAAO,MAAM,EAAE,CAAC;AAEzE,eAAW,CAAC,QAAQ,IAAI,KAAK,OAAO,QAAQ,OAAO,YAAY,GAAG;AAChE,YAAM,cAAc,KAAK;AAAA,QACvB,IAAI,OAAO,IAAI,KAAK,KAAK,IAAI;AAAA,QAC7B,aAAAA,QAAM,OAAO,IAAI;AAAA,MACnB;AACA,cAAQ,IAAI,KAAK,aAAAA,QAAM,KAAK,MAAM,CAAC,KAAK,WAAW,EAAE;AAAA,IACvD;AACA,YAAQ,IAAI;AAAA,EACd;AACF;;;AE/CA,IAAAC,gBAAkB;;;ACAlB,IAAAC,gBAAkB;AAUlB,IAAM,kBAAkB,CAAC,SAAS,QAAQ,QAAQ,QAAQ,SAAS,QAAQ;AAE3E,eAAsB,OAAO,UAA4B,CAAC,GAAyC;AACjG,QAAM,EAAE,IAAI,IAAI;AAEhB,UAAQ,IAAI,cAAAC,QAAM,KAAK,sCAAsC,CAAC;AAE9D,QAAM,cAAc,MAAM,6BAA6B,EAAE,IAAI,CAAC;AAC9D,QAAM,SAAS,MAAM,qBAAqB,EAAE,IAAI,CAAC;AAGjD,QAAM,WAAW,oBAAI,IAAY;AACjC,aAAW,QAAQ,QAAQ;AACzB,aAAS,IAAI,KAAK,GAAG;AAErB,QAAI,CAAC,KAAK,IAAI,SAAS,GAAG,GAAG;AAC3B,eAAS,IAAI,KAAK,GAAG;AAAA,IACvB;AAAA,EACF;AAGA,QAAM,aAA0B,CAAC;AAEjC,aAAW,SAAS,aAAa;AAC/B,eAAW,OAAO,MAAM,MAAM;AAC5B,YAAM,UAAU,MAAM,cAAc,YAAY,MAAM,GAAG,MAAM,SAAS,IAAI,GAAG;AAG/E,UAAI,SAAS,IAAI,OAAO,EAAG;AAI3B,UAAI,kBAAkB;AACtB,iBAAW,UAAU,iBAAiB;AACpC,YAAI,IAAI,SAAS,MAAM,GAAG;AACxB,gBAAM,UAAU,IAAI,MAAM,GAAG,CAAC,OAAO,MAAM;AAC3C,gBAAM,cAAc,MAAM,cAAc,YAAY,UAAU,GAAG,MAAM,SAAS,IAAI,OAAO;AAC3F,cAAI,SAAS,IAAI,WAAW,GAAG;AAC7B,8BAAkB;AAClB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,UAAI,gBAAiB;AAErB,iBAAW,KAAK;AAAA,QACd,WAAW,MAAM;AAAA,QACjB,KAAK;AAAA,QACL,WAAW,MAAM;AAAA,QACjB,MAAM,MAAM;AAAA,MACd,CAAC;AAAA,IACH;AAAA,EACF;AAGA,MAAI,WAAW,WAAW,GAAG;AAC3B,UAAM,YAAY,YAAY,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,KAAK,QAAQ,CAAC;AACvE,YAAQ,IAAI,cAAAA,QAAM,MAAM,iCAAiC,CAAC;AAC1D,YAAQ,IAAI,cAAAA,QAAM,KAAK,WAAW,SAAS,8BAA8B,OAAO,MAAM,cAAc,CAAC;AACrG,WAAO,EAAE,WAAW;AAAA,EACtB;AAEA,UAAQ,IAAI,cAAAA,QAAM,OAAO,SAAS,WAAW,MAAM;AAAA,CAA+B,CAAC;AACnF,aAAW,QAAQ,YAAY;AAC7B,UAAM,eAAe,KAAK,UAAU,QAAQ,QAAQ,IAAI,IAAI,KAAK,EAAE;AACnE,YAAQ,IAAI,KAAK,cAAAA,QAAM,IAAI,GAAG,CAAC,IAAI,cAAAA,QAAM,KAAK,KAAK,GAAG,CAAC,EAAE;AACzD,YAAQ,IAAI,cAAAA,QAAM,KAAK,kBAAkB,YAAY,IAAI,KAAK,IAAI,EAAE,CAAC;AAAA,EACvE;AAEA,UAAQ,IAAI;AACZ,SAAO,EAAE,WAAW;AACtB;;;AD9DA,SAAS,yBAAyB,OAAuC;AACvE,QAAM,eAAqD,CAAC;AAE5D,aAAW,CAAC,QAAQ,IAAI,KAAK,OAAO,QAAQ,MAAM,YAAY,GAAG;AAC/D,UAAM,UAAU,KAAK,MAAM,YAAY,KAAK,CAAC;AAC7C,UAAM,WAAW,CAAC,GAAG,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK;AACvE,iBAAa,KAAK,EAAE,QAAQ,MAAM,SAAS,CAAC;AAAA,EAC9C;AAEA,MAAI,aAAa,SAAS,EAAG,QAAO;AAEpC,QAAM,YAAY,aAAa,CAAC;AAChC,QAAM,UAAoB,CAAC;AAE3B,WAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC5C,UAAM,UAAU,aAAa,CAAC;AAC9B,UAAM,SAAS,IAAI,IAAI,UAAU,IAAI;AACrC,UAAM,SAAS,IAAI,IAAI,QAAQ,IAAI;AAEnC,UAAM,YAAY,UAAU,KAAK,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;AAC7D,UAAM,YAAY,QAAQ,KAAK,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;AAE3D,QAAI,UAAU,SAAS,GAAG;AACxB,cAAQ;AAAA,QACN,GAAG,UAAU,MAAM,SAAS,UAAU,KAAK,MAAM,CAAC,gBAAgB,QAAQ,MAAM;AAAA,MAClF;AAAA,IACF;AACA,QAAI,UAAU,SAAS,GAAG;AACxB,cAAQ;AAAA,QACN,GAAG,QAAQ,MAAM,SAAS,UAAU,KAAK,MAAM,CAAC,gBAAgB,UAAU,MAAM;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS,CAAC,KAAK;AAAA,IACf;AAAA,EACF;AACF;AAEA,SAAS,wBAAwB,OAAuC;AACtE,MAAI,CAAC,MAAM,SAAU,QAAO;AAE5B,QAAM,UAAU,OAAO,KAAK,MAAM,QAAQ;AAC1C,MAAI,QAAQ,SAAS,EAAG,QAAO;AAE/B,QAAM,UAAoB,CAAC;AAC3B,QAAM,YAAY,QAAQ,CAAC;AAC3B,QAAM,WAAW,MAAM,SAAS,SAAS;AAEzC,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,SAAS,QAAQ,CAAC;AACxB,UAAM,WAAW,MAAM,SAAS,MAAM;AAEtC,eAAW,WAAW,UAAU;AAC9B,YAAM,QAAQ,SAAS,KAAK,CAAC,MAA0C,EAAE,aAAa,QAAQ,QAAQ;AACtG,UAAI,SAAS,MAAM,SAAS,QAAQ,MAAM;AACxC,gBAAQ;AAAA,UACN,IAAI,QAAQ,QAAQ,SAAS,QAAQ,IAAI,QAAQ,SAAS,SAAS,MAAM,IAAI,QAAQ,MAAM;AAAA,QAC7F;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS,CAAC,KAAK;AAAA,IACf;AAAA,EACF;AACF;AAEA,eAAsB,SAAS,UAA2B,CAAC,GAAkB;AAC3E,QAAM,EAAE,KAAK,SAAS,QAAQ,QAAQ,YAAY,IAAI;AAEtD,UAAQ,IAAI,cAAAC,QAAM,KAAK,gCAAgC,CAAC;AAExD,QAAM,UAAU,MAAM,aAAa,EAAE,IAAI,CAAC;AAC1C,QAAM,SAAkB,CAAC;AAGzB,QAAM,SAAS,oBAAI,IAAgC;AAEnD,aAAW,SAAS,SAAS;AAC3B,UAAM,MAAM,OAAO,OAAO,MAAM,YAAY,EAAE,CAAC,KAAK;AACpD,QAAI,CAAC,OAAO,IAAI,GAAG,GAAG;AACpB,aAAO,IAAI,KAAK,CAAC,CAAC;AAAA,IACpB;AACA,WAAO,IAAI,GAAG,EAAG,KAAK,KAAK;AAAA,EAC7B;AAGA,aAAW,CAAC,KAAK,KAAK,KAAK,QAAQ;AACjC,QAAI,MAAM,SAAS,EAAG;AAEtB,UAAM,kBAAkB,MAAM,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE,YAAY,CAAC;AACvE,UAAM,aAAa,CAAC,GAAG,IAAI,IAAI,eAAe,CAAC;AAE/C,QAAI,WAAW,SAAS,GAAG;AACzB,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,SAAS,kCAAkC,GAAG;AAAA,QAC9C,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAGA,MAAI,WAAW,QAAQ,SAAS,GAAG;AACjC,eAAW,SAAS,SAAS;AAC3B,YAAM,UAAU,QAAQ,OAAO,CAAC,MAAM,CAAC,MAAM,aAAa,CAAC,CAAC;AAE5D,UAAI,QAAQ,SAAS,GAAG;AACtB,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,SAAS,oBAAoB,QAAQ,KAAK,IAAI,CAAC;AAAA,UAC/C,SAAS,CAAC,KAAK;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,aAAW,SAAS,SAAS;AAC3B,UAAM,QAAQ,yBAAyB,KAAK;AAC5C,QAAI,MAAO,QAAO,KAAK,KAAK;AAAA,EAC9B;AAGA,MAAI,QAAQ;AACV,eAAW,SAAS,SAAS;AAC3B,YAAM,QAAQ,wBAAwB,KAAK;AAC3C,UAAI,MAAO,QAAO,KAAK,KAAK;AAAA,IAC9B;AAAA,EACF;AAGA,MAAI,cAAc;AAClB,MAAI,aAAa;AACf,UAAM,SAAS,MAAM,OAAO,EAAE,IAAI,CAAC;AACnC,kBAAc,OAAO,WAAW;AAAA,EAClC;AAGA,MAAI,OAAO,WAAW,KAAK,gBAAgB,GAAG;AAC5C,YAAQ,IAAI,cAAAA,QAAM,MAAM,+BAA+B,CAAC;AACxD,YAAQ,IAAI,cAAAA,QAAM,KAAK,WAAW,QAAQ,MAAM,iBAAiB,CAAC;AAClE,QAAI,QAAQ;AACV,cAAQ,IAAI,cAAAA,QAAM,KAAK,uBAAuB,CAAC;AAAA,IACjD;AACA,QAAI,aAAa;AACf,cAAQ,IAAI,cAAAA,QAAM,KAAK,gCAAgC,CAAC;AAAA,IAC1D;AACA;AAAA,EACF;AAEA,UAAQ,IAAI,cAAAA,QAAM,IAAI,SAAS,OAAO,MAAM;AAAA,CAAc,CAAC;AAE3D,aAAW,SAAS,QAAQ;AAC1B,YAAQ,IAAI,KAAK,cAAAA,QAAM,OAAO,MAAM,OAAO,CAAC,EAAE;AAE9C,eAAW,SAAS,MAAM,SAAS;AACjC,YAAM,eAAe,MAAM,KAAK,QAAQ,QAAQ,IAAI,IAAI,KAAK,EAAE;AAC/D,cAAQ,IAAI,cAAAA,QAAM,KAAK,MAAM,YAAY,IAAI,MAAM,IAAI,EAAE,CAAC;AAE1D,iBAAW,CAAC,QAAQ,IAAI,KAAK,OAAO,QAAQ,MAAM,YAAY,GAAG;AAC/D,gBAAQ,IAAI,QAAQ,cAAAA,QAAM,KAAK,MAAM,CAAC,KAAK,IAAI,EAAE;AAAA,MACnD;AAAA,IACF;AAEA,QAAI,MAAM,WAAW,MAAM,QAAQ,SAAS,GAAG;AAC7C,iBAAW,UAAU,MAAM,SAAS;AAClC,gBAAQ,IAAI,cAAAA,QAAM,KAAK,eAAU,MAAM,EAAE,CAAC;AAAA,MAC5C;AAAA,IACF;AAEA,YAAQ,IAAI;AAAA,EACd;AAEA,OAAK,OAAO,SAAS,KAAK,cAAc,MAAM,CAAC,QAAQ,QAAQ;AAC7D,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;AE/MA,IAAAC,gBAAkB;AAelB,eAAsB,SAAS,SAAyC;AACtE,QAAM,EAAE,KAAK,QAAQ,IAAI;AAEzB,UAAQ,IAAI,cAAAC,QAAM,KAAK,uCAAuC,CAAC;AAE/D,QAAM,UAAU,MAAM,aAAa,EAAE,IAAI,CAAC;AAE1C,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,IAAI,cAAAA,QAAM,OAAO,wBAAwB,CAAC;AAClD;AAAA,EACF;AAEA,QAAM,eAAiC,CAAC;AAExC,aAAW,UAAU,SAAS;AAC5B,QAAI,aAAa;AAEjB,eAAW,SAAS,SAAS;AAC3B,UAAI,MAAM,aAAa,MAAM,GAAG;AAC9B;AAAA,MACF;AAAA,IACF;AAEA,UAAM,aAAa,KAAK,MAAO,aAAa,QAAQ,SAAU,GAAG;AAEjE,iBAAa,KAAK;AAAA,MAChB;AAAA,MACA,OAAO,QAAQ;AAAA,MACf;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAGA,UAAQ,IAAI,cAAAA,QAAM,KAAK,yBAAyB,CAAC;AAEjD,QAAM,eAAe,KAAK,IAAI,GAAG,QAAQ,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC;AAEhE,UAAQ;AAAA,IACN,cAAAA,QAAM;AAAA,MACJ,GAAG,SAAS,OAAO,YAAY,CAAC,KAAK,WAAW,SAAS,EAAE,CAAC,KAAK,aAAa,SAAS,EAAE,CAAC;AAAA,IAC5F;AAAA,EACF;AACA,UAAQ,IAAI,cAAAA,QAAM,KAAK,SAAI,OAAO,eAAe,EAAE,CAAC,CAAC;AAErD,aAAW,QAAQ,cAAc;AAC/B,UAAM,QACJ,KAAK,eAAe,MAAM,cAAAA,QAAM,QAChC,KAAK,cAAc,KAAK,cAAAA,QAAM,SAAS,cAAAA,QAAM;AAE/C,UAAM,MAAM,kBAAkB,KAAK,YAAY,EAAE;AACjD,UAAM,aAAa,GAAG,KAAK,UAAU,IAAI,SAAS,CAAC;AAEnD,YAAQ;AAAA,MACN,GAAG,KAAK,OAAO,OAAO,YAAY,CAAC,KAAK,MAAM,GAAG,CAAC,IAAI,MAAM,UAAU,CAAC,KAAK,cAAAA,QAAM,KAAK,GAAG,KAAK,UAAU,IAAI,KAAK,KAAK,EAAE,CAAC;AAAA,IAC5H;AAAA,EACF;AAEA,UAAQ,IAAI;AAGZ,QAAM,eAAe,aAAa,OAAO,CAAC,MAAM,EAAE,eAAe,GAAG,EAAE;AACtE,QAAM,mBAAmB,aAAa,OAAO,CAAC,MAAM,EAAE,aAAa,KAAK,EAAE,aAAa,GAAG,EAAE;AAC5F,QAAM,aAAa,aAAa,OAAO,CAAC,MAAM,EAAE,eAAe,CAAC,EAAE;AAElE,MAAI,iBAAiB,QAAQ,QAAQ;AACnC,YAAQ,IAAI,cAAAA,QAAM,MAAM,mCAAmC,CAAC;AAAA,EAC9D,OAAO;AACL,YAAQ,IAAI,cAAAA,QAAM,KAAK,SAAS,YAAY,cAAc,gBAAgB,YAAY,UAAU,EAAE,CAAC;AAAA,EACrG;AACF;AAEA,SAAS,kBAAkB,YAAoB,OAAuB;AACpE,QAAM,SAAS,KAAK,MAAO,aAAa,MAAO,KAAK;AACpD,QAAM,QAAQ,QAAQ;AAEtB,SAAO,SAAI,OAAO,MAAM,IAAI,SAAI,OAAO,KAAK;AAC9C;;;AC5FA,IAAAC,MAAoB;AACpB,WAAsB;AACtB,IAAAC,gBAAkB;AAQlB,IAAMC,mBAAkB,CAAC,SAAS,QAAQ,QAAQ,QAAQ,SAAS,QAAQ;AAE3E,eAAsB,QAAQ,UAA0B,CAAC,GAAkB;AACzE,QAAM,EAAE,KAAK,SAAS,gBAAgB,IAAI;AAE1C,UAAQ,IAAI,cAAAC,QAAM,KAAK,oCAAoC,CAAC;AAE5D,QAAM,cAAc,MAAM,6BAA6B,EAAE,IAAI,CAAC;AAG9D,QAAM,UAAU,oBAAI,IAAY;AAEhC,aAAW,SAAS,aAAa;AAC/B,eAAW,OAAO,MAAM,MAAM;AAC5B,YAAM,UAAU,MAAM,cAAc,YAAY,MAAM,GAAG,MAAM,SAAS,IAAI,GAAG;AAC/E,cAAQ,IAAI,OAAO;AAGnB,iBAAW,UAAUD,kBAAiB;AACpC,YAAI,IAAI,SAAS,MAAM,GAAG;AACxB,gBAAM,UAAU,IAAI,MAAM,GAAG,CAAC,OAAO,MAAM;AAC3C,gBAAM,cAAc,MAAM,cAAc,YAAY,UAAU,GAAG,MAAM,SAAS,IAAI,OAAO;AAC3F,kBAAQ,IAAI,WAAW;AAAA,QACzB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,SAAS,GAAG;AACtB,YAAQ,IAAI,cAAAC,QAAM,OAAO,2EAA2E,CAAC;AACrG;AAAA,EACF;AAEA,QAAM,aAAa,CAAC,GAAG,OAAO,EAAE,KAAK;AAGrC,QAAM,WAAW,WAAW,IAAI,OAAK,UAAU,CAAC,GAAG,EAAE,KAAK,IAAI;AAE9D,QAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhB,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeR,QAAM,aAAkB,aAAQ,OAAO,QAAQ,IAAI,GAAG,MAAM;AAC5D,QAAM,YAAiB,aAAQ,UAAU;AAEzC,MAAI,CAAI,eAAW,SAAS,GAAG;AAC7B,IAAG,cAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,EAC7C;AAEA,EAAG,kBAAc,YAAY,SAAS,OAAO;AAE7C,UAAQ,IAAI,cAAAA,QAAM,MAAM,aAAa,WAAW,MAAM,wBAAwB,CAAC;AAC/E,UAAQ,IAAI,cAAAA,QAAM,KAAK,WAAW,UAAU;AAAA,CAAI,CAAC;AAGjD,QAAM,SAAS,WAAW,MAAM,GAAG,CAAC;AACpC,aAAW,OAAO,QAAQ;AACxB,YAAQ,IAAI,KAAK,cAAAA,QAAM,KAAK,GAAG,CAAC,EAAE;AAAA,EACpC;AACA,MAAI,WAAW,SAAS,GAAG;AACzB,YAAQ,IAAI,cAAAA,QAAM,KAAK,aAAa,WAAW,SAAS,CAAC,OAAO,CAAC;AAAA,EACnE;AACF;;;AC1FA,IAAAC,gBAAkB;AAClB,IAAAC,MAAoB;AACpB,IAAAC,QAAsB;AAStB,eAAsB,QAAQ,UAA0B,CAAC,GAAkB;AACzE,QAAM,EAAE,KAAK,SAAS,gBAAgB,SAAS,OAAO,IAAI;AAE1D,UAAQ,IAAI,cAAAC,QAAM,KAAK,uCAAuC,CAAC;AAE/D,QAAM,UAAU,MAAM,aAAa,EAAE,IAAI,CAAC;AAE1C,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,IAAI,cAAAA,QAAM,OAAO,wBAAwB,CAAC;AAClD;AAAA,EACF;AAGA,QAAM,WAAmD,CAAC;AAC1D,QAAM,WAAW,OAAO,QAAQ,IAAI;AAEpC,aAAW,SAAS,SAAS;AAC3B,eAAW,CAAC,QAAQ,IAAI,KAAK,OAAO,QAAQ,MAAM,YAAY,GAAG;AAC/D,UAAI,CAAC,SAAS,MAAM,EAAG,UAAS,MAAM,IAAI,CAAC;AAE3C,YAAM,eAAe,MAAM,KAAK,QAAQ,WAAW,KAAK,EAAE;AAC1D,YAAM,MAAM,GAAG,YAAY,IAAI,MAAM,IAAI;AACzC,eAAS,MAAM,EAAE,GAAG,IAAI;AAAA,IAC1B;AAAA,EACF;AAGA,QAAM,YAAiB,cAAQ,UAAU,MAAM;AAC/C,MAAI,CAAI,eAAW,SAAS,GAAG;AAC7B,IAAG,cAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,EAC7C;AAEA,QAAM,UAAU,OAAO,KAAK,QAAQ,EAAE,KAAK;AAC3C,aAAW,UAAU,SAAS;AAC5B,UAAM,eAAe,SAAS,MAAM;AACpC,QAAI;AAEJ,QAAI,WAAW,UAAU;AACvB,YAAM,SAAS,kBAAkB,YAAY;AAC7C,gBAAU,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI;AAAA,IAC9C,OAAO;AACL,gBAAU,KAAK,UAAU,cAAc,MAAM,CAAC,IAAI;AAAA,IACpD;AAEA,UAAM,WAAgB,WAAK,WAAW,GAAG,MAAM,OAAO;AACtD,IAAG,kBAAc,UAAU,OAAO;AAClC,YAAQ;AAAA,MACN,cAAAA,QAAM,MAAM,KAAK,MAAM,OAAO,IAC9B,cAAAA,QAAM,KAAK,KAAK,OAAO,KAAK,YAAY,EAAE,MAAM,QAAQ;AAAA,IAC1D;AAAA,EACF;AAEA,UAAQ,IAAI,cAAAA,QAAM,KAAK;AAAA,YAAe,QAAQ,MAAM,sBAAsB,MAAM,GAAG,CAAC;AACtF;AAKA,SAAS,kBAAkB,MAAuD;AAChF,QAAM,SAAkC,CAAC;AAEzC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC/C,UAAM,QAAQ,IAAI,MAAM,GAAG;AAC3B,QAAI,UAAmC;AAEvC,aAAS,IAAI,GAAG,IAAI,MAAM,SAAS,GAAG,KAAK;AACzC,YAAM,OAAO,MAAM,CAAC;AACpB,UAAI,CAAC,QAAQ,IAAI,KAAK,OAAO,QAAQ,IAAI,MAAM,UAAU;AACvD,gBAAQ,IAAI,IAAI,CAAC;AAAA,MACnB;AACA,gBAAU,QAAQ,IAAI;AAAA,IACxB;AAEA,YAAQ,MAAM,MAAM,SAAS,CAAC,CAAE,IAAI;AAAA,EACtC;AAEA,SAAO;AACT;;;ACxFA,sBAAsB;AACtB,IAAAC,gBAAkB;AAUX,SAAS,WAAW,SAA6B;AACtD,QAAM,EAAE,KAAK,UAAU,QAAQ,UAAU,MAAM,IAAI;AAEnD,UAAQ,IAAI,cAAAC,QAAM,KAAK;AAAA,wBAA2B,KAAK;AAAA,CAAQ,CAAC;AAChE,UAAQ,IAAI,cAAAA,QAAM,KAAK,wBAAwB,CAAC;AAEhD,QAAM,cAAU,uBAAM,UAAU;AAAA,IAC9B;AAAA,IACA,SAAS;AAAA,IACT,eAAe;AAAA,EACjB,CAAC;AAED,MAAI,gBAAsD;AAE1D,QAAM,eAAe,CAAC,aAAqB;AACzC,QAAI,cAAe,cAAa,aAAa;AAC7C,oBAAgB,WAAW,YAAY;AACrC,cAAQ,IAAI,cAAAA,QAAM,KAAK;AAAA,mBAAsB,QAAQ,EAAE,CAAC;AACxD,cAAQ,IAAI,cAAAA,QAAM,KAAK,IAAI,OAAO,EAAE,CAAC,CAAC;AACtC,UAAI;AACF,cAAM,SAAS;AAAA,MACjB,QAAQ;AAAA,MAER;AACA,cAAQ,IAAI,cAAAA,QAAM,KAAK;AAAA,wBAA2B,KAAK,MAAM,CAAC;AAAA,IAChE,GAAG,GAAG;AAAA,EACR;AAEA,UAAQ,GAAG,UAAU,YAAY;AACjC,UAAQ,GAAG,OAAO,YAAY;AAChC;;;ARjCA,IAAM,UAAU,IAAI,yBAAQ;AAE5B,QACG,KAAK,aAAa,EAClB,YAAY,iCAAiC,EAC7C,QAAQ,OAAO;AAElB,QACG,QAAQ,cAAc,EACtB,YAAY,6CAA6C,EACzD,OAAO,oBAAoB,mBAAmB,EAC9C,OAAO,OAAO,OAAe,YAA8B;AAC1D,QAAM,KAAK,EAAE,OAAO,KAAK,QAAQ,IAAI,CAAC;AACxC,CAAC;AAEH,QACG,QAAQ,UAAU,EAClB,YAAY,kCAAkC,EAC9C,OAAO,oBAAoB,mBAAmB,EAC9C,OAAO,8BAA8B,2BAA2B,EAChE,OAAO,gBAAgB,iDAAiD,EACxE,OAAO,gBAAgB,+BAA+B,EACtD,OAAO,eAAe,0CAA0C,EAChE,OAAO,OAAO,YAAuG;AACpH,QAAM,SAAS,QAAQ,QAAQ,EAAE,GAAG,SAAS,QAAQ,KAAK,IAAI,OAAO;AACrE,MAAI,QAAQ,OAAO;AACjB,UAAM,MAAM,QAAQ,OAAO,QAAQ,IAAI;AACvC,eAAW;AAAA,MACT;AAAA,MACA,UAAU,CAAC,sBAAsB;AAAA,MACjC,QAAQ,CAAC,sBAAsB,cAAc,aAAa;AAAA,MAC1D,UAAU,MAAM,SAAS,EAAE,GAAG,SAAS,QAAQ,KAAK,CAAC;AAAA,MACrD,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AACF,CAAC;AAEH,QACG,QAAQ,UAAU,EAClB,YAAY,qCAAqC,EACjD,OAAO,oBAAoB,mBAAmB,EAC9C,OAAO,8BAA8B,oBAAoB,CAAC,MAAM,IAAI,CAAC,EACrE,OAAO,OAAO,YAAiD;AAC9D,QAAM,SAAS,OAAO;AACxB,CAAC;AAEH,QACG,QAAQ,SAAS,EACjB,YAAY,gDAAgD,EAC5D,OAAO,oBAAoB,mBAAmB,EAC9C,OAAO,uBAAuB,oBAAoB,eAAe,EACjE,OAAO,eAAe,+CAA+C,EACrE,OAAO,OAAO,YAAgE;AAC7E,QAAM,QAAQ,OAAO;AACrB,MAAI,QAAQ,OAAO;AACjB,UAAM,MAAM,QAAQ,OAAO,QAAQ,IAAI;AACvC,eAAW;AAAA,MACT;AAAA,MACA,UAAU,CAAC,sBAAsB;AAAA,MACjC,QAAQ,CAAC,sBAAsB,cAAc,aAAa;AAAA,MAC1D,UAAU,MAAM,QAAQ,OAAO;AAAA,MAC/B,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AACF,CAAC;AAEH,QACG,QAAQ,SAAS,EACjB,YAAY,2CAA2C,EACvD,OAAO,oBAAoB,mBAAmB,EAC9C,OAAO,uBAAuB,oBAAoB,cAAc,EAChE,OAAO,yBAAyB,+BAA+B,MAAM,EACrE,OAAO,OAAO,YAA2E;AACxF,QAAM,QAAQ,OAAO;AACvB,CAAC;AAEH,QAAQ,MAAM;","names":["traverse","fg","chalk","import_chalk","import_chalk","chalk","chalk","import_chalk","chalk","fs","import_chalk","PLURAL_SUFFIXES","chalk","import_chalk","fs","path","chalk","import_chalk","chalk"]}
1
+ {"version":3,"sources":["../src/bin.ts","../src/commands/find.ts","../src/parser.ts","../src/commands/validate.ts","../src/commands/unused.ts","../src/commands/coverage.ts","../src/commands/typegen.ts","../src/commands/extract.ts","../src/commands/diff.ts","../src/commands/stats.ts","../src/watch.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { find } from './commands/find'\nimport { validate } from './commands/validate'\nimport { coverage } from './commands/coverage'\nimport { typegen } from './commands/typegen'\nimport { extract } from './commands/extract'\nimport { diff } from './commands/diff'\nimport { stats } from './commands/stats'\nimport { startWatch } from './watch'\n\nconst program = new Command()\n\nprogram\n .name('inline-i18n')\n .description('CLI tools for inline-i18n-multi')\n .version('0.10.0')\n\nprogram\n .command('find <query>')\n .description('Find translations containing the query text')\n .option('-c, --cwd <path>', 'Working directory')\n .action(async (query: string, options: { cwd?: string }) => {\n await find({ query, cwd: options.cwd })\n })\n\nprogram\n .command('validate')\n .description('Validate translation consistency')\n .option('-c, --cwd <path>', 'Working directory')\n .option('-l, --locales <locales...>', 'Required locales to check')\n .option('-s, --strict', 'Enable strict mode (ICU type consistency check)')\n .option('-u, --unused', 'Detect unused dictionary keys')\n .option('-w, --watch', 'Watch mode - re-validate on file changes')\n .action(async (options: { cwd?: string; locales?: string[]; strict?: boolean; unused?: boolean; watch?: boolean }) => {\n await validate(options.watch ? { ...options, noExit: true } : options)\n if (options.watch) {\n const cwd = options.cwd || process.cwd()\n startWatch({\n cwd,\n patterns: ['**/*.{ts,tsx,js,jsx}'],\n ignore: ['**/node_modules/**', '**/dist/**', '**/.next/**'],\n onChange: () => validate({ ...options, noExit: true }),\n label: 'validate',\n })\n }\n })\n\nprogram\n .command('coverage')\n .description('Show translation coverage by locale')\n .option('-c, --cwd <path>', 'Working directory')\n .option('-l, --locales <locales...>', 'Locales to check', ['ko', 'en'])\n .action(async (options: { cwd?: string; locales: string[] }) => {\n await coverage(options)\n })\n\nprogram\n .command('typegen')\n .description('Generate TypeScript types for translation keys')\n .option('-c, --cwd <path>', 'Working directory')\n .option('-o, --output <path>', 'Output file path', 'src/i18n.d.ts')\n .option('-w, --watch', 'Watch mode - regenerate types on file changes')\n .action(async (options: { cwd?: string; output?: string; watch?: boolean }) => {\n await typegen(options)\n if (options.watch) {\n const cwd = options.cwd || process.cwd()\n startWatch({\n cwd,\n patterns: ['**/*.{ts,tsx,js,jsx}'],\n ignore: ['**/node_modules/**', '**/dist/**', '**/.next/**'],\n onChange: () => typegen(options),\n label: 'typegen',\n })\n }\n })\n\nprogram\n .command('extract')\n .description('Extract inline translations to JSON files')\n .option('-c, --cwd <path>', 'Working directory')\n .option('-o, --output <path>', 'Output directory', 'translations')\n .option('-f, --format <format>', 'Output format (flat|nested)', 'flat')\n .action(async (options: { cwd?: string; output?: string; format?: 'flat' | 'nested' }) => {\n await extract(options)\n })\n\nprogram\n .command('diff <locale1> <locale2>')\n .description('Compare translations between two locales')\n .option('-c, --cwd <path>', 'Working directory')\n .option('-a, --all', 'Show all entries including shared translations')\n .action(async (locale1: string, locale2: string, options: { cwd?: string; all?: boolean }) => {\n await diff({ locale1, locale2, cwd: options.cwd, all: options.all })\n })\n\nprogram\n .command('stats')\n .description('Show translation statistics overview')\n .option('-c, --cwd <path>', 'Working directory')\n .action(async (options: { cwd?: string }) => {\n await stats(options)\n })\n\nprogram.parse()\n","import chalk from 'chalk'\nimport { parseProject, type TranslationEntry } from '../parser'\n\ninterface FindOptions {\n query: string\n cwd?: string\n}\n\nexport async function find(options: FindOptions): Promise<void> {\n const { query, cwd } = options\n\n console.log(chalk.blue(`\\nSearching for: \"${query}\"\\n`))\n\n const entries = await parseProject({ cwd })\n const results: TranslationEntry[] = []\n\n const lowerQuery = query.toLowerCase()\n\n for (const entry of entries) {\n const values = Object.values(entry.translations)\n const matches = values.some((v) => v.toLowerCase().includes(lowerQuery))\n\n if (matches) {\n results.push(entry)\n }\n }\n\n if (results.length === 0) {\n console.log(chalk.yellow('No results found.'))\n return\n }\n\n console.log(chalk.green(`Found ${results.length} occurrence(s):\\n`))\n\n for (const result of results) {\n const relativePath = result.file.replace(process.cwd() + '/', '')\n console.log(chalk.gray(`${relativePath}:${result.line}:${result.column}`))\n\n for (const [locale, text] of Object.entries(result.translations)) {\n const highlighted = text.replace(\n new RegExp(`(${query})`, 'gi'),\n chalk.yellow('$1')\n )\n console.log(` ${chalk.cyan(locale)}: ${highlighted}`)\n }\n console.log()\n }\n}\n","import { parse } from '@babel/parser'\nimport traverse from '@babel/traverse'\nimport * as fs from 'fs'\nimport fg from 'fast-glob'\n\n// v0.8.0: Dictionary key and t() call extraction\n\nexport interface DictionaryKeyEntry {\n file: string\n line: number\n namespace: string\n keys: string[]\n}\n\nexport interface TCallEntry {\n file: string\n line: number\n key: string\n}\n\nexport interface ICUTypeInfo {\n variable: string\n type: string\n}\n\nexport interface TranslationEntry {\n file: string\n line: number\n column: number\n translations: Record<string, string>\n variables: string[]\n /** ICU type information per locale (v0.7.0) */\n icuTypes?: Record<string, ICUTypeInfo[]>\n}\n\ninterface ParseOptions {\n cwd?: string\n include?: string[]\n exclude?: string[]\n}\n\nconst IT_FUNCTION_NAMES = [\n 'it',\n 'it_ja', 'it_zh', 'it_es', 'it_fr', 'it_de',\n 'en_ja', 'en_zh', 'en_es', 'en_fr', 'en_de',\n 'ja_zh', 'ja_es', 'zh_es',\n]\n\nconst PAIR_MAPPING: Record<string, [string, string]> = {\n it: ['ko', 'en'],\n it_ja: ['ko', 'ja'],\n it_zh: ['ko', 'zh'],\n it_es: ['ko', 'es'],\n it_fr: ['ko', 'fr'],\n it_de: ['ko', 'de'],\n en_ja: ['en', 'ja'],\n en_zh: ['en', 'zh'],\n en_es: ['en', 'es'],\n en_fr: ['en', 'fr'],\n en_de: ['en', 'de'],\n ja_zh: ['ja', 'zh'],\n ja_es: ['ja', 'es'],\n zh_es: ['zh', 'es'],\n}\n\nfunction extractVariables(text: string): string[] {\n const matches = text.match(/\\{(\\w+)\\}/g)\n if (!matches) return []\n return matches.map((m) => m.slice(1, -1))\n}\n\nconst ICU_TYPE_PATTERN = /\\{(\\w+),\\s*(\\w+)/g\n\nfunction extractICUTypes(text: string): ICUTypeInfo[] {\n const types: ICUTypeInfo[] = []\n let match: RegExpExecArray | null\n ICU_TYPE_PATTERN.lastIndex = 0\n while ((match = ICU_TYPE_PATTERN.exec(text)) !== null) {\n types.push({ variable: match[1]!, type: match[2]! })\n }\n return types\n}\n\nfunction parseFile(filePath: string): TranslationEntry[] {\n const entries: TranslationEntry[] = []\n const code = fs.readFileSync(filePath, 'utf-8')\n\n let ast\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n })\n } catch {\n return []\n }\n\n traverse(ast, {\n CallExpression(nodePath) {\n const { node } = nodePath\n const { callee } = node\n\n if (callee.type !== 'Identifier') return\n if (!IT_FUNCTION_NAMES.includes(callee.name)) return\n\n const funcName = callee.name\n const args = node.arguments\n const loc = node.loc\n\n if (!loc) return\n\n const entry: TranslationEntry = {\n file: filePath,\n line: loc.start.line,\n column: loc.start.column,\n translations: {},\n variables: [],\n }\n\n if (args[0]?.type === 'ObjectExpression') {\n const obj = args[0]\n for (const prop of obj.properties) {\n if (\n prop.type === 'ObjectProperty' &&\n prop.key.type === 'Identifier' &&\n prop.value.type === 'StringLiteral'\n ) {\n entry.translations[prop.key.name] = prop.value.value\n entry.variables.push(...extractVariables(prop.value.value))\n // Extract ICU type info (v0.7.0)\n const types = extractICUTypes(prop.value.value)\n if (types.length > 0) {\n if (!entry.icuTypes) entry.icuTypes = {}\n entry.icuTypes[prop.key.name] = types\n }\n }\n }\n } else if (\n args[0]?.type === 'StringLiteral' &&\n args[1]?.type === 'StringLiteral'\n ) {\n const [lang1, lang2] = PAIR_MAPPING[funcName] || ['ko', 'en']\n entry.translations[lang1] = args[0].value\n entry.translations[lang2] = args[1].value\n entry.variables.push(...extractVariables(args[0].value))\n entry.variables.push(...extractVariables(args[1].value))\n // Extract ICU type info (v0.7.0)\n const types1 = extractICUTypes(args[0].value)\n if (types1.length > 0) {\n if (!entry.icuTypes) entry.icuTypes = {}\n entry.icuTypes[lang1] = types1\n }\n const types2 = extractICUTypes(args[1].value)\n if (types2.length > 0) {\n if (!entry.icuTypes) entry.icuTypes = {}\n entry.icuTypes[lang2] = types2\n }\n }\n\n entry.variables = [...new Set(entry.variables)]\n\n if (Object.keys(entry.translations).length > 0) {\n entries.push(entry)\n }\n },\n })\n\n return entries\n}\n\n// v0.8.0: Flatten nested ObjectExpression to dot-notation keys\nfunction flattenObjectKeys(\n node: { type: string; properties?: unknown[] },\n prefix: string = '',\n): string[] {\n const keys: string[] = []\n if (node.type !== 'ObjectExpression' || !node.properties) return keys\n\n for (const prop of node.properties as Array<{\n type: string\n key: { type: string; name?: string; value?: string }\n value: { type: string; properties?: unknown[] }\n }>) {\n if (prop.type !== 'ObjectProperty') continue\n\n let propName: string | undefined\n if (prop.key.type === 'Identifier') propName = prop.key.name\n else if (prop.key.type === 'StringLiteral') propName = prop.key.value\n\n if (!propName) continue\n\n const fullKey = prefix ? `${prefix}.${propName}` : propName\n\n if (prop.value.type === 'StringLiteral') {\n keys.push(fullKey)\n } else if (prop.value.type === 'ObjectExpression') {\n keys.push(...flattenObjectKeys(prop.value, fullKey))\n }\n }\n return keys\n}\n\n// v0.8.0: Extract dictionary keys from loadDictionaries() calls\nexport function parseDictionaryKeys(filePath: string): DictionaryKeyEntry[] {\n const entries: DictionaryKeyEntry[] = []\n const code = fs.readFileSync(filePath, 'utf-8')\n\n let ast\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n })\n } catch {\n return []\n }\n\n traverse(ast, {\n CallExpression(nodePath) {\n const { node } = nodePath\n const { callee } = node\n\n if (callee.type !== 'Identifier' || callee.name !== 'loadDictionaries') return\n\n const args = node.arguments\n const loc = node.loc\n if (!loc || !args[0] || args[0].type !== 'ObjectExpression') return\n\n // Second argument is optional namespace\n let namespace = 'default'\n if (args[1]?.type === 'StringLiteral') {\n namespace = args[1].value\n }\n\n // First argument: { locale: { key: value } }\n // Collect keys from the first locale's dict (all locales should have same keys)\n const dictObj = args[0]\n const allKeys = new Set<string>()\n\n for (const localeProp of dictObj.properties as Array<{\n type: string\n value: { type: string; properties?: unknown[] }\n }>) {\n if (localeProp.type !== 'ObjectProperty') continue\n if (localeProp.value.type !== 'ObjectExpression') continue\n\n const localeKeys = flattenObjectKeys(localeProp.value)\n for (const key of localeKeys) {\n allKeys.add(key)\n }\n }\n\n if (allKeys.size > 0) {\n entries.push({\n file: filePath,\n line: loc.start.line,\n namespace,\n keys: [...allKeys],\n })\n }\n },\n })\n\n return entries\n}\n\n// v0.8.0: Extract t() call sites\nexport function parseTCalls(filePath: string): TCallEntry[] {\n const entries: TCallEntry[] = []\n const code = fs.readFileSync(filePath, 'utf-8')\n\n let ast\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n })\n } catch {\n return []\n }\n\n traverse(ast, {\n CallExpression(nodePath) {\n const { node } = nodePath\n const { callee } = node\n\n if (callee.type !== 'Identifier' || callee.name !== 't') return\n\n const args = node.arguments\n const loc = node.loc\n if (!loc || !args[0] || args[0].type !== 'StringLiteral') return\n\n entries.push({\n file: filePath,\n line: loc.start.line,\n key: args[0].value,\n })\n },\n })\n\n return entries\n}\n\nexport async function extractProjectDictionaryKeys(options: ParseOptions = {}): Promise<DictionaryKeyEntry[]> {\n const {\n cwd = process.cwd(),\n include = ['**/*.{ts,tsx,js,jsx}'],\n exclude = ['**/node_modules/**', '**/dist/**', '**/.next/**'],\n } = options\n\n const files = await fg(include, { cwd, ignore: exclude, absolute: true })\n const allEntries: DictionaryKeyEntry[] = []\n\n for (const file of files) {\n allEntries.push(...parseDictionaryKeys(file))\n }\n\n return allEntries\n}\n\nexport async function extractProjectTCalls(options: ParseOptions = {}): Promise<TCallEntry[]> {\n const {\n cwd = process.cwd(),\n include = ['**/*.{ts,tsx,js,jsx}'],\n exclude = ['**/node_modules/**', '**/dist/**', '**/.next/**'],\n } = options\n\n const files = await fg(include, { cwd, ignore: exclude, absolute: true })\n const allEntries: TCallEntry[] = []\n\n for (const file of files) {\n allEntries.push(...parseTCalls(file))\n }\n\n return allEntries\n}\n\nexport async function parseProject(options: ParseOptions = {}): Promise<TranslationEntry[]> {\n const {\n cwd = process.cwd(),\n include = ['**/*.{ts,tsx,js,jsx}'],\n exclude = ['**/node_modules/**', '**/dist/**', '**/.next/**'],\n } = options\n\n const files = await fg(include, {\n cwd,\n ignore: exclude,\n absolute: true,\n })\n\n const allEntries: TranslationEntry[] = []\n\n for (const file of files) {\n const entries = parseFile(file)\n allEntries.push(...entries)\n }\n\n return allEntries\n}\n","import chalk from 'chalk'\nimport { parseProject, type TranslationEntry } from '../parser'\nimport { unused } from './unused'\n\ninterface ValidateOptions {\n cwd?: string\n locales?: string[]\n strict?: boolean\n unused?: boolean\n noExit?: boolean\n}\n\ninterface Issue {\n type: 'inconsistent' | 'missing' | 'variable_mismatch' | 'icu_type_mismatch'\n message: string\n entries: TranslationEntry[]\n details?: string[]\n}\n\nfunction checkVariableConsistency(entry: TranslationEntry): Issue | null {\n const varsByLocale: { locale: string; vars: string[] }[] = []\n\n for (const [locale, text] of Object.entries(entry.translations)) {\n const matches = text.match(/\\{(\\w+)\\}/g) || []\n const varNames = [...new Set(matches.map((v) => v.slice(1, -1)))].sort()\n varsByLocale.push({ locale, vars: varNames })\n }\n\n if (varsByLocale.length < 2) return null\n\n const reference = varsByLocale[0]!\n const details: string[] = []\n\n for (let i = 1; i < varsByLocale.length; i++) {\n const current = varsByLocale[i]!\n const refSet = new Set(reference.vars)\n const curSet = new Set(current.vars)\n\n const onlyInRef = reference.vars.filter((v) => !curSet.has(v))\n const onlyInCur = current.vars.filter((v) => !refSet.has(v))\n\n if (onlyInRef.length > 0) {\n details.push(\n `${reference.locale} has {${onlyInRef.join('}, {')}} missing in ${current.locale}`,\n )\n }\n if (onlyInCur.length > 0) {\n details.push(\n `${current.locale} has {${onlyInCur.join('}, {')}} missing in ${reference.locale}`,\n )\n }\n }\n\n if (details.length === 0) return null\n\n return {\n type: 'variable_mismatch',\n message: 'Variable mismatch between translations',\n entries: [entry],\n details,\n }\n}\n\nfunction checkICUTypeConsistency(entry: TranslationEntry): Issue | null {\n if (!entry.icuTypes) return null\n\n const locales = Object.keys(entry.icuTypes)\n if (locales.length < 2) return null\n\n const details: string[] = []\n const reference = locales[0]!\n const refTypes = entry.icuTypes[reference]!\n\n for (let i = 1; i < locales.length; i++) {\n const locale = locales[i]!\n const curTypes = entry.icuTypes[locale]!\n\n for (const refType of refTypes) {\n const match = curTypes.find((t: { variable: string; type: string }) => t.variable === refType.variable)\n if (match && match.type !== refType.type) {\n details.push(\n `{${refType.variable}} is \"${refType.type}\" in ${reference} but \"${match.type}\" in ${locale}`,\n )\n }\n }\n }\n\n if (details.length === 0) return null\n\n return {\n type: 'icu_type_mismatch',\n message: 'ICU type mismatch between translations',\n entries: [entry],\n details,\n }\n}\n\nexport async function validate(options: ValidateOptions = {}): Promise<void> {\n const { cwd, locales, strict, unused: checkUnused } = options\n\n console.log(chalk.blue('\\nValidating translations...\\n'))\n\n const entries = await parseProject({ cwd })\n const issues: Issue[] = []\n\n // group by first language text (usually ko)\n const groups = new Map<string, TranslationEntry[]>()\n\n for (const entry of entries) {\n const key = Object.values(entry.translations)[0] || ''\n if (!groups.has(key)) {\n groups.set(key, [])\n }\n groups.get(key)!.push(entry)\n }\n\n // check for inconsistent translations\n for (const [key, group] of groups) {\n if (group.length < 2) continue\n\n const translationSets = group.map((e) => JSON.stringify(e.translations))\n const uniqueSets = [...new Set(translationSets)]\n\n if (uniqueSets.length > 1) {\n issues.push({\n type: 'inconsistent',\n message: `Inconsistent translations for \"${key}\"`,\n entries: group,\n })\n }\n }\n\n // check for missing locales\n if (locales && locales.length > 0) {\n for (const entry of entries) {\n const missing = locales.filter((l) => !entry.translations[l])\n\n if (missing.length > 0) {\n issues.push({\n type: 'missing',\n message: `Missing locales: ${missing.join(', ')}`,\n entries: [entry],\n })\n }\n }\n }\n\n // check for variable name consistency (enhanced in v0.7.0)\n for (const entry of entries) {\n const issue = checkVariableConsistency(entry)\n if (issue) issues.push(issue)\n }\n\n // check for ICU type consistency (strict mode, v0.7.0)\n if (strict) {\n for (const entry of entries) {\n const issue = checkICUTypeConsistency(entry)\n if (issue) issues.push(issue)\n }\n }\n\n // unused key detection (v0.8.0)\n let unusedCount = 0\n if (checkUnused) {\n const result = await unused({ cwd })\n unusedCount = result.unusedKeys.length\n }\n\n // print results\n if (issues.length === 0 && unusedCount === 0) {\n console.log(chalk.green('All translations are valid!\\n'))\n console.log(chalk.gray(`Checked ${entries.length} translation(s)`))\n if (strict) {\n console.log(chalk.gray('(strict mode enabled)'))\n }\n if (checkUnused) {\n console.log(chalk.gray('(unused key detection enabled)'))\n }\n return\n }\n\n console.log(chalk.red(`Found ${issues.length} issue(s):\\n`))\n\n for (const issue of issues) {\n console.log(` ${chalk.yellow(issue.message)}`)\n\n for (const entry of issue.entries) {\n const relativePath = entry.file.replace(process.cwd() + '/', '')\n console.log(chalk.gray(` ${relativePath}:${entry.line}`))\n\n for (const [locale, text] of Object.entries(entry.translations)) {\n console.log(` ${chalk.cyan(locale)}: ${text}`)\n }\n }\n\n if (issue.details && issue.details.length > 0) {\n for (const detail of issue.details) {\n console.log(chalk.gray(` → ${detail}`))\n }\n }\n\n console.log()\n }\n\n if ((issues.length > 0 || unusedCount > 0) && !options.noExit) {\n process.exit(1)\n }\n}\n","import chalk from 'chalk'\nimport { extractProjectDictionaryKeys, extractProjectTCalls } from '../parser'\n\ninterface UnusedKey {\n namespace: string\n key: string\n definedIn: string\n line: number\n}\n\nconst PLURAL_SUFFIXES = ['_zero', '_one', '_two', '_few', '_many', '_other']\n\nexport async function unused(options: { cwd?: string } = {}): Promise<{ unusedKeys: UnusedKey[] }> {\n const { cwd } = options\n\n console.log(chalk.blue('\\nDetecting unused translations...\\n'))\n\n const dictEntries = await extractProjectDictionaryKeys({ cwd })\n const tCalls = await extractProjectTCalls({ cwd })\n\n // Build set of used keys (normalized: namespace:key or key for default)\n const usedKeys = new Set<string>()\n for (const call of tCalls) {\n usedKeys.add(call.key)\n // Also add with default namespace if no namespace prefix\n if (!call.key.includes(':')) {\n usedKeys.add(call.key)\n }\n }\n\n // Check each dictionary key against used keys\n const unusedKeys: UnusedKey[] = []\n\n for (const entry of dictEntries) {\n for (const key of entry.keys) {\n const fullKey = entry.namespace === 'default' ? key : `${entry.namespace}:${key}`\n\n // Check if key is directly used\n if (usedKeys.has(fullKey)) continue\n\n // Check if this is a plural suffix variant (e.g. count_one, count_other)\n // and the base key is used via t('items.count', { count: N })\n let isPluralVariant = false\n for (const suffix of PLURAL_SUFFIXES) {\n if (key.endsWith(suffix)) {\n const baseKey = key.slice(0, -suffix.length)\n const fullBaseKey = entry.namespace === 'default' ? baseKey : `${entry.namespace}:${baseKey}`\n if (usedKeys.has(fullBaseKey)) {\n isPluralVariant = true\n break\n }\n }\n }\n if (isPluralVariant) continue\n\n unusedKeys.push({\n namespace: entry.namespace,\n key: fullKey,\n definedIn: entry.file,\n line: entry.line,\n })\n }\n }\n\n // Report results\n if (unusedKeys.length === 0) {\n const totalKeys = dictEntries.reduce((sum, e) => sum + e.keys.length, 0)\n console.log(chalk.green('No unused translations found!\\n'))\n console.log(chalk.gray(`Checked ${totalKeys} dictionary key(s) against ${tCalls.length} t() call(s)`))\n return { unusedKeys }\n }\n\n console.log(chalk.yellow(`Found ${unusedKeys.length} unused translation key(s):\\n`))\n for (const item of unusedKeys) {\n const relativePath = item.definedIn.replace(process.cwd() + '/', '')\n console.log(` ${chalk.red('-')} ${chalk.cyan(item.key)}`)\n console.log(chalk.gray(` defined in ${relativePath}:${item.line}`))\n }\n\n console.log()\n return { unusedKeys }\n}\n","import chalk from 'chalk'\nimport { parseProject } from '../parser'\n\ninterface CoverageOptions {\n cwd?: string\n locales: string[]\n}\n\ninterface LocaleCoverage {\n locale: string\n total: number\n translated: number\n percentage: number\n}\n\nexport async function coverage(options: CoverageOptions): Promise<void> {\n const { cwd, locales } = options\n\n console.log(chalk.blue('\\nAnalyzing translation coverage...\\n'))\n\n const entries = await parseProject({ cwd })\n\n if (entries.length === 0) {\n console.log(chalk.yellow('No translations found.'))\n return\n }\n\n const coverageData: LocaleCoverage[] = []\n\n for (const locale of locales) {\n let translated = 0\n\n for (const entry of entries) {\n if (entry.translations[locale]) {\n translated++\n }\n }\n\n const percentage = Math.round((translated / entries.length) * 100)\n\n coverageData.push({\n locale,\n total: entries.length,\n translated,\n percentage,\n })\n }\n\n // print coverage table\n console.log(chalk.bold('Translation Coverage:\\n'))\n\n const maxLocaleLen = Math.max(...locales.map((l) => l.length), 6)\n\n console.log(\n chalk.gray(\n `${'Locale'.padEnd(maxLocaleLen)} ${'Coverage'.padStart(10)} ${'Translated'.padStart(12)}`\n )\n )\n console.log(chalk.gray('─'.repeat(maxLocaleLen + 26)))\n\n for (const data of coverageData) {\n const color =\n data.percentage === 100 ? chalk.green :\n data.percentage >= 80 ? chalk.yellow : chalk.red\n\n const bar = createProgressBar(data.percentage, 10)\n const percentStr = `${data.percentage}%`.padStart(4)\n\n console.log(\n `${data.locale.padEnd(maxLocaleLen)} ${color(bar)} ${color(percentStr)} ${chalk.gray(`${data.translated}/${data.total}`)}`\n )\n }\n\n console.log()\n\n // summary\n const fullyCovered = coverageData.filter((d) => d.percentage === 100).length\n const partiallyCovered = coverageData.filter((d) => d.percentage > 0 && d.percentage < 100).length\n const notCovered = coverageData.filter((d) => d.percentage === 0).length\n\n if (fullyCovered === locales.length) {\n console.log(chalk.green('All locales are fully translated!'))\n } else {\n console.log(chalk.gray(`Full: ${fullyCovered}, Partial: ${partiallyCovered}, Empty: ${notCovered}`))\n }\n}\n\nfunction createProgressBar(percentage: number, width: number): string {\n const filled = Math.round((percentage / 100) * width)\n const empty = width - filled\n\n return '█'.repeat(filled) + '░'.repeat(empty)\n}\n","import * as fs from 'fs'\nimport * as path from 'path'\nimport chalk from 'chalk'\nimport { extractProjectDictionaryKeys } from '../parser'\n\ninterface TypegenOptions {\n cwd?: string\n output?: string\n}\n\nconst PLURAL_SUFFIXES = ['_zero', '_one', '_two', '_few', '_many', '_other']\n\nexport async function typegen(options: TypegenOptions = {}): Promise<void> {\n const { cwd, output = 'src/i18n.d.ts' } = options\n\n console.log(chalk.blue('\\nGenerating TypeScript types...\\n'))\n\n const dictEntries = await extractProjectDictionaryKeys({ cwd })\n\n // Collect all unique full keys (namespace:key or key)\n const allKeys = new Set<string>()\n\n for (const entry of dictEntries) {\n for (const key of entry.keys) {\n const fullKey = entry.namespace === 'default' ? key : `${entry.namespace}:${key}`\n allKeys.add(fullKey)\n\n // Also add plural base keys (strip _one, _other, etc.)\n for (const suffix of PLURAL_SUFFIXES) {\n if (key.endsWith(suffix)) {\n const baseKey = key.slice(0, -suffix.length)\n const fullBaseKey = entry.namespace === 'default' ? baseKey : `${entry.namespace}:${baseKey}`\n allKeys.add(fullBaseKey)\n }\n }\n }\n }\n\n if (allKeys.size === 0) {\n console.log(chalk.yellow('No dictionary keys found. Make sure loadDictionaries() calls are present.'))\n return\n }\n\n const sortedKeys = [...allKeys].sort()\n\n // Generate the .d.ts content\n const keyUnion = sortedKeys.map(k => ` | '${k}'`).join('\\n')\n\n const content = `// Auto-generated by inline-i18n typegen\n// Do not edit manually. Re-run: npx inline-i18n typegen\n\nimport 'inline-i18n-multi'\n\ndeclare module 'inline-i18n-multi' {\n export type TranslationKey =\n${keyUnion}\n\n export function t(\n key: TranslationKey,\n vars?: TranslationVars,\n locale?: string\n ): string\n\n export function hasTranslation(\n key: TranslationKey,\n locale?: string\n ): boolean\n}\n`\n\n const outputPath = path.resolve(cwd || process.cwd(), output)\n const outputDir = path.dirname(outputPath)\n\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true })\n }\n\n fs.writeFileSync(outputPath, content, 'utf-8')\n\n console.log(chalk.green(`Generated ${sortedKeys.length} translation key types`))\n console.log(chalk.gray(`Output: ${outputPath}\\n`))\n\n // Show sample\n const sample = sortedKeys.slice(0, 5)\n for (const key of sample) {\n console.log(` ${chalk.cyan(key)}`)\n }\n if (sortedKeys.length > 5) {\n console.log(chalk.gray(` ... and ${sortedKeys.length - 5} more`))\n }\n}\n","import chalk from 'chalk'\nimport * as fs from 'fs'\nimport * as path from 'path'\nimport { parseProject } from '../parser'\n\ninterface ExtractOptions {\n cwd?: string\n output?: string\n format?: 'flat' | 'nested'\n}\n\nexport async function extract(options: ExtractOptions = {}): Promise<void> {\n const { cwd, output = 'translations', format = 'flat' } = options\n\n console.log(chalk.blue('\\nExtracting inline translations...\\n'))\n\n const entries = await parseProject({ cwd })\n\n if (entries.length === 0) {\n console.log(chalk.yellow('No translations found.'))\n return\n }\n\n // Group translations by locale\n const byLocale: Record<string, Record<string, string>> = {}\n const basePath = cwd || process.cwd()\n\n for (const entry of entries) {\n for (const [locale, text] of Object.entries(entry.translations)) {\n if (!byLocale[locale]) byLocale[locale] = {}\n\n const relativePath = entry.file.replace(basePath + '/', '')\n const key = `${relativePath}:${entry.line}`\n byLocale[locale][key] = text\n }\n }\n\n // Write output files\n const outputDir = path.resolve(basePath, output)\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true })\n }\n\n const locales = Object.keys(byLocale).sort()\n for (const locale of locales) {\n const translations = byLocale[locale]!\n let content: string\n\n if (format === 'nested') {\n const nested = buildNestedObject(translations)\n content = JSON.stringify(nested, null, 2) + '\\n'\n } else {\n content = JSON.stringify(translations, null, 2) + '\\n'\n }\n\n const filePath = path.join(outputDir, `${locale}.json`)\n fs.writeFileSync(filePath, content)\n console.log(\n chalk.green(` ${locale}.json`) +\n chalk.gray(` (${Object.keys(translations).length} keys)`)\n )\n }\n\n console.log(chalk.gray(`\\nExtracted ${entries.length} translation(s) to ${output}/`))\n}\n\n/**\n * Build a nested object from flat dot-notation keys\n */\nfunction buildNestedObject(flat: Record<string, string>): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n\n for (const [key, value] of Object.entries(flat)) {\n const parts = key.split('.')\n let current: Record<string, unknown> = result\n\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i]!\n if (!current[part] || typeof current[part] !== 'object') {\n current[part] = {}\n }\n current = current[part] as Record<string, unknown>\n }\n\n current[parts[parts.length - 1]!] = value\n }\n\n return result\n}\n","import chalk from 'chalk'\nimport { parseProject, type TranslationEntry } from '../parser'\n\ninterface DiffOptions {\n locale1: string\n locale2: string\n cwd?: string\n all?: boolean\n}\n\nexport async function diff(options: DiffOptions): Promise<void> {\n const { locale1, locale2, cwd, all } = options\n const basePath = cwd || process.cwd()\n\n console.log(chalk.blue(`\\nComparing ${locale1} vs ${locale2}...\\n`))\n\n const entries = await parseProject({ cwd })\n\n if (entries.length === 0) {\n console.log(chalk.yellow('No translations found.'))\n return\n }\n\n const onlyIn1: TranslationEntry[] = []\n const onlyIn2: TranslationEntry[] = []\n const shared: TranslationEntry[] = []\n\n for (const entry of entries) {\n const has1 = !!entry.translations[locale1]\n const has2 = !!entry.translations[locale2]\n\n if (has1 && has2) shared.push(entry)\n else if (has1 && !has2) onlyIn1.push(entry)\n else if (!has1 && has2) onlyIn2.push(entry)\n }\n\n if (onlyIn1.length > 0) {\n console.log(chalk.red(`Only in ${locale1} (${onlyIn1.length}):\\n`))\n for (const entry of onlyIn1) {\n const relativePath = entry.file.replace(basePath + '/', '')\n console.log(chalk.gray(` ${relativePath}:${entry.line}`))\n console.log(` ${chalk.cyan(locale1)}: ${entry.translations[locale1]}`)\n console.log()\n }\n }\n\n if (onlyIn2.length > 0) {\n console.log(chalk.red(`Only in ${locale2} (${onlyIn2.length}):\\n`))\n for (const entry of onlyIn2) {\n const relativePath = entry.file.replace(basePath + '/', '')\n console.log(chalk.gray(` ${relativePath}:${entry.line}`))\n console.log(` ${chalk.cyan(locale2)}: ${entry.translations[locale2]}`)\n console.log()\n }\n }\n\n if (all && shared.length > 0) {\n console.log(chalk.green(`Shared (${shared.length}):\\n`))\n for (const entry of shared) {\n const relativePath = entry.file.replace(basePath + '/', '')\n console.log(chalk.gray(` ${relativePath}:${entry.line}`))\n console.log(` ${chalk.cyan(locale1)}: ${entry.translations[locale1]}`)\n console.log(` ${chalk.cyan(locale2)}: ${entry.translations[locale2]}`)\n console.log()\n }\n }\n\n console.log(chalk.bold('Summary:'))\n console.log(chalk.green(` Shared: ${shared.length}`))\n console.log(onlyIn1.length > 0\n ? chalk.red(` Only in ${locale1}: ${onlyIn1.length}`)\n : chalk.gray(` Only in ${locale1}: 0`))\n console.log(onlyIn2.length > 0\n ? chalk.red(` Only in ${locale2}: ${onlyIn2.length}`)\n : chalk.gray(` Only in ${locale2}: 0`))\n console.log()\n}\n","import chalk from 'chalk'\nimport { parseProject, extractProjectDictionaryKeys, extractProjectTCalls } from '../parser'\n\ninterface StatsOptions {\n cwd?: string\n}\n\nexport async function stats(options: StatsOptions = {}): Promise<void> {\n const { cwd } = options\n const basePath = cwd || process.cwd()\n\n console.log(chalk.blue('\\nGathering translation statistics...\\n'))\n\n const entries = await parseProject({ cwd })\n const dictEntries = await extractProjectDictionaryKeys({ cwd })\n const tCalls = await extractProjectTCalls({ cwd })\n\n const totalDictKeys = dictEntries.reduce((sum, e) => sum + e.keys.length, 0)\n\n // Overview\n console.log(chalk.bold('Overview:\\n'))\n console.log(` Inline translations (it): ${chalk.cyan(String(entries.length))}`)\n console.log(` Dictionary keys: ${chalk.cyan(String(totalDictKeys))}`)\n console.log(` t() call sites: ${chalk.cyan(String(tCalls.length))}`)\n console.log()\n\n // Locale breakdown\n const localeCounts: Record<string, number> = {}\n for (const entry of entries) {\n for (const locale of Object.keys(entry.translations)) {\n localeCounts[locale] = (localeCounts[locale] || 0) + 1\n }\n }\n\n if (Object.keys(localeCounts).length > 0) {\n console.log(chalk.bold('Locale Breakdown (inline):\\n'))\n const sortedLocales = Object.entries(localeCounts).sort((a, b) => b[1] - a[1])\n for (const [locale, count] of sortedLocales) {\n console.log(` ${chalk.cyan(locale.padEnd(10))} ${count} translations`)\n }\n console.log()\n }\n\n // Namespace summary\n const namespaces = new Set(dictEntries.map(e => e.namespace))\n if (namespaces.size > 0) {\n console.log(chalk.bold('Namespaces:\\n'))\n for (const entry of dictEntries) {\n console.log(` ${chalk.yellow(entry.namespace.padEnd(15))} ${entry.keys.length} keys`)\n }\n console.log()\n }\n\n // Top files\n const fileCounts: Record<string, number> = {}\n for (const entry of entries) {\n const relativePath = entry.file.replace(basePath + '/', '')\n fileCounts[relativePath] = (fileCounts[relativePath] || 0) + 1\n }\n\n if (Object.keys(fileCounts).length > 0) {\n console.log(chalk.bold('Top Files:\\n'))\n const sortedFiles = Object.entries(fileCounts)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 10)\n for (const [file, count] of sortedFiles) {\n console.log(` ${chalk.gray(file.padEnd(50))} ${chalk.cyan(String(count))}`)\n }\n console.log()\n }\n\n // ICU pattern usage\n const icuUsage: Record<string, number> = {}\n for (const entry of entries) {\n if (!entry.icuTypes) continue\n for (const types of Object.values(entry.icuTypes)) {\n for (const info of types) {\n icuUsage[info.type] = (icuUsage[info.type] || 0) + 1\n }\n }\n }\n\n if (Object.keys(icuUsage).length > 0) {\n console.log(chalk.bold('ICU Pattern Usage:\\n'))\n const sortedICU = Object.entries(icuUsage).sort((a, b) => b[1] - a[1])\n for (const [type, count] of sortedICU) {\n console.log(` ${chalk.yellow(type.padEnd(20))} ${count} usage(s)`)\n }\n console.log()\n }\n}\n","import { watch } from 'chokidar'\nimport chalk from 'chalk'\n\ninterface WatchOptions {\n cwd: string\n patterns: string[]\n ignore: string[]\n onChange: () => Promise<void>\n label: string\n}\n\nexport function startWatch(options: WatchOptions): void {\n const { cwd, patterns, ignore, onChange, label } = options\n\n console.log(chalk.blue(`\\nWatching for changes (${label})...\\n`))\n console.log(chalk.gray('Press Ctrl+C to stop\\n'))\n\n const watcher = watch(patterns, {\n cwd,\n ignored: ignore,\n ignoreInitial: true,\n })\n\n let debounceTimer: ReturnType<typeof setTimeout> | null = null\n\n const handleChange = (filePath: string) => {\n if (debounceTimer) clearTimeout(debounceTimer)\n debounceTimer = setTimeout(async () => {\n console.log(chalk.gray(`\\nChange detected: ${filePath}`))\n console.log(chalk.gray('-'.repeat(40)))\n try {\n await onChange()\n } catch {\n // Error already printed by the command\n }\n console.log(chalk.gray(`\\nWatching for changes (${label})...`))\n }, 300)\n }\n\n watcher.on('change', handleChange)\n watcher.on('add', handleChange)\n}\n"],"mappings":"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","names":["traverse","fg","chalk","import_chalk","import_chalk","chalk","chalk","import_chalk","chalk","fs","import_chalk","PLURAL_SUFFIXES","chalk","import_chalk","fs","path","chalk","import_chalk","chalk","import_chalk","chalk","import_chalk","chalk"]}
package/dist/index.d.ts CHANGED
@@ -79,4 +79,17 @@ interface ExtractOptions {
79
79
  }
80
80
  declare function extract(options?: ExtractOptions): Promise<void>;
81
81
 
82
- export { type DictionaryKeyEntry, type TCallEntry, type TranslationEntry, coverage, extract, extractProjectDictionaryKeys, extractProjectTCalls, find, parseDictionaryKeys, parseProject, parseTCalls, typegen, unused, validate };
82
+ interface DiffOptions {
83
+ locale1: string;
84
+ locale2: string;
85
+ cwd?: string;
86
+ all?: boolean;
87
+ }
88
+ declare function diff(options: DiffOptions): Promise<void>;
89
+
90
+ interface StatsOptions {
91
+ cwd?: string;
92
+ }
93
+ declare function stats(options?: StatsOptions): Promise<void>;
94
+
95
+ export { type DictionaryKeyEntry, type TCallEntry, type TranslationEntry, coverage, diff, extract, extractProjectDictionaryKeys, extractProjectTCalls, find, parseDictionaryKeys, parseProject, parseTCalls, stats, typegen, unused, validate };
package/dist/index.js CHANGED
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  coverage: () => coverage,
34
+ diff: () => diff,
34
35
  extract: () => extract,
35
36
  extractProjectDictionaryKeys: () => extractProjectDictionaryKeys,
36
37
  extractProjectTCalls: () => extractProjectTCalls,
@@ -38,6 +39,7 @@ __export(index_exports, {
38
39
  parseDictionaryKeys: () => parseDictionaryKeys,
39
40
  parseProject: () => parseProject,
40
41
  parseTCalls: () => parseTCalls,
42
+ stats: () => stats,
41
43
  typegen: () => typegen,
42
44
  unused: () => unused,
43
45
  validate: () => validate
@@ -734,9 +736,140 @@ function buildNestedObject(flat) {
734
736
  }
735
737
  return result;
736
738
  }
739
+
740
+ // src/commands/diff.ts
741
+ var import_chalk7 = __toESM(require("chalk"));
742
+ async function diff(options) {
743
+ const { locale1, locale2, cwd, all } = options;
744
+ const basePath = cwd || process.cwd();
745
+ console.log(import_chalk7.default.blue(`
746
+ Comparing ${locale1} vs ${locale2}...
747
+ `));
748
+ const entries = await parseProject({ cwd });
749
+ if (entries.length === 0) {
750
+ console.log(import_chalk7.default.yellow("No translations found."));
751
+ return;
752
+ }
753
+ const onlyIn1 = [];
754
+ const onlyIn2 = [];
755
+ const shared = [];
756
+ for (const entry of entries) {
757
+ const has1 = !!entry.translations[locale1];
758
+ const has2 = !!entry.translations[locale2];
759
+ if (has1 && has2) shared.push(entry);
760
+ else if (has1 && !has2) onlyIn1.push(entry);
761
+ else if (!has1 && has2) onlyIn2.push(entry);
762
+ }
763
+ if (onlyIn1.length > 0) {
764
+ console.log(import_chalk7.default.red(`Only in ${locale1} (${onlyIn1.length}):
765
+ `));
766
+ for (const entry of onlyIn1) {
767
+ const relativePath = entry.file.replace(basePath + "/", "");
768
+ console.log(import_chalk7.default.gray(` ${relativePath}:${entry.line}`));
769
+ console.log(` ${import_chalk7.default.cyan(locale1)}: ${entry.translations[locale1]}`);
770
+ console.log();
771
+ }
772
+ }
773
+ if (onlyIn2.length > 0) {
774
+ console.log(import_chalk7.default.red(`Only in ${locale2} (${onlyIn2.length}):
775
+ `));
776
+ for (const entry of onlyIn2) {
777
+ const relativePath = entry.file.replace(basePath + "/", "");
778
+ console.log(import_chalk7.default.gray(` ${relativePath}:${entry.line}`));
779
+ console.log(` ${import_chalk7.default.cyan(locale2)}: ${entry.translations[locale2]}`);
780
+ console.log();
781
+ }
782
+ }
783
+ if (all && shared.length > 0) {
784
+ console.log(import_chalk7.default.green(`Shared (${shared.length}):
785
+ `));
786
+ for (const entry of shared) {
787
+ const relativePath = entry.file.replace(basePath + "/", "");
788
+ console.log(import_chalk7.default.gray(` ${relativePath}:${entry.line}`));
789
+ console.log(` ${import_chalk7.default.cyan(locale1)}: ${entry.translations[locale1]}`);
790
+ console.log(` ${import_chalk7.default.cyan(locale2)}: ${entry.translations[locale2]}`);
791
+ console.log();
792
+ }
793
+ }
794
+ console.log(import_chalk7.default.bold("Summary:"));
795
+ console.log(import_chalk7.default.green(` Shared: ${shared.length}`));
796
+ console.log(onlyIn1.length > 0 ? import_chalk7.default.red(` Only in ${locale1}: ${onlyIn1.length}`) : import_chalk7.default.gray(` Only in ${locale1}: 0`));
797
+ console.log(onlyIn2.length > 0 ? import_chalk7.default.red(` Only in ${locale2}: ${onlyIn2.length}`) : import_chalk7.default.gray(` Only in ${locale2}: 0`));
798
+ console.log();
799
+ }
800
+
801
+ // src/commands/stats.ts
802
+ var import_chalk8 = __toESM(require("chalk"));
803
+ async function stats(options = {}) {
804
+ const { cwd } = options;
805
+ const basePath = cwd || process.cwd();
806
+ console.log(import_chalk8.default.blue("\nGathering translation statistics...\n"));
807
+ const entries = await parseProject({ cwd });
808
+ const dictEntries = await extractProjectDictionaryKeys({ cwd });
809
+ const tCalls = await extractProjectTCalls({ cwd });
810
+ const totalDictKeys = dictEntries.reduce((sum, e) => sum + e.keys.length, 0);
811
+ console.log(import_chalk8.default.bold("Overview:\n"));
812
+ console.log(` Inline translations (it): ${import_chalk8.default.cyan(String(entries.length))}`);
813
+ console.log(` Dictionary keys: ${import_chalk8.default.cyan(String(totalDictKeys))}`);
814
+ console.log(` t() call sites: ${import_chalk8.default.cyan(String(tCalls.length))}`);
815
+ console.log();
816
+ const localeCounts = {};
817
+ for (const entry of entries) {
818
+ for (const locale of Object.keys(entry.translations)) {
819
+ localeCounts[locale] = (localeCounts[locale] || 0) + 1;
820
+ }
821
+ }
822
+ if (Object.keys(localeCounts).length > 0) {
823
+ console.log(import_chalk8.default.bold("Locale Breakdown (inline):\n"));
824
+ const sortedLocales = Object.entries(localeCounts).sort((a, b) => b[1] - a[1]);
825
+ for (const [locale, count] of sortedLocales) {
826
+ console.log(` ${import_chalk8.default.cyan(locale.padEnd(10))} ${count} translations`);
827
+ }
828
+ console.log();
829
+ }
830
+ const namespaces = new Set(dictEntries.map((e) => e.namespace));
831
+ if (namespaces.size > 0) {
832
+ console.log(import_chalk8.default.bold("Namespaces:\n"));
833
+ for (const entry of dictEntries) {
834
+ console.log(` ${import_chalk8.default.yellow(entry.namespace.padEnd(15))} ${entry.keys.length} keys`);
835
+ }
836
+ console.log();
837
+ }
838
+ const fileCounts = {};
839
+ for (const entry of entries) {
840
+ const relativePath = entry.file.replace(basePath + "/", "");
841
+ fileCounts[relativePath] = (fileCounts[relativePath] || 0) + 1;
842
+ }
843
+ if (Object.keys(fileCounts).length > 0) {
844
+ console.log(import_chalk8.default.bold("Top Files:\n"));
845
+ const sortedFiles = Object.entries(fileCounts).sort((a, b) => b[1] - a[1]).slice(0, 10);
846
+ for (const [file, count] of sortedFiles) {
847
+ console.log(` ${import_chalk8.default.gray(file.padEnd(50))} ${import_chalk8.default.cyan(String(count))}`);
848
+ }
849
+ console.log();
850
+ }
851
+ const icuUsage = {};
852
+ for (const entry of entries) {
853
+ if (!entry.icuTypes) continue;
854
+ for (const types of Object.values(entry.icuTypes)) {
855
+ for (const info of types) {
856
+ icuUsage[info.type] = (icuUsage[info.type] || 0) + 1;
857
+ }
858
+ }
859
+ }
860
+ if (Object.keys(icuUsage).length > 0) {
861
+ console.log(import_chalk8.default.bold("ICU Pattern Usage:\n"));
862
+ const sortedICU = Object.entries(icuUsage).sort((a, b) => b[1] - a[1]);
863
+ for (const [type, count] of sortedICU) {
864
+ console.log(` ${import_chalk8.default.yellow(type.padEnd(20))} ${count} usage(s)`);
865
+ }
866
+ console.log();
867
+ }
868
+ }
737
869
  // Annotate the CommonJS export names for ESM import in node:
738
870
  0 && (module.exports = {
739
871
  coverage,
872
+ diff,
740
873
  extract,
741
874
  extractProjectDictionaryKeys,
742
875
  extractProjectTCalls,
@@ -744,6 +877,7 @@ function buildNestedObject(flat) {
744
877
  parseDictionaryKeys,
745
878
  parseProject,
746
879
  parseTCalls,
880
+ stats,
747
881
  typegen,
748
882
  unused,
749
883
  validate
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/parser.ts","../src/commands/find.ts","../src/commands/validate.ts","../src/commands/unused.ts","../src/commands/coverage.ts","../src/commands/typegen.ts","../src/commands/extract.ts"],"sourcesContent":["export {\n parseProject,\n parseDictionaryKeys,\n parseTCalls,\n extractProjectDictionaryKeys,\n extractProjectTCalls,\n type TranslationEntry,\n type DictionaryKeyEntry,\n type TCallEntry,\n} from './parser'\nexport { find } from './commands/find'\nexport { validate } from './commands/validate'\nexport { coverage } from './commands/coverage'\nexport { unused } from './commands/unused'\nexport { typegen } from './commands/typegen'\nexport { extract } from './commands/extract'\n","import { parse } from '@babel/parser'\nimport traverse from '@babel/traverse'\nimport * as fs from 'fs'\nimport fg from 'fast-glob'\n\n// v0.8.0: Dictionary key and t() call extraction\n\nexport interface DictionaryKeyEntry {\n file: string\n line: number\n namespace: string\n keys: string[]\n}\n\nexport interface TCallEntry {\n file: string\n line: number\n key: string\n}\n\nexport interface ICUTypeInfo {\n variable: string\n type: string\n}\n\nexport interface TranslationEntry {\n file: string\n line: number\n column: number\n translations: Record<string, string>\n variables: string[]\n /** ICU type information per locale (v0.7.0) */\n icuTypes?: Record<string, ICUTypeInfo[]>\n}\n\ninterface ParseOptions {\n cwd?: string\n include?: string[]\n exclude?: string[]\n}\n\nconst IT_FUNCTION_NAMES = [\n 'it',\n 'it_ja', 'it_zh', 'it_es', 'it_fr', 'it_de',\n 'en_ja', 'en_zh', 'en_es', 'en_fr', 'en_de',\n 'ja_zh', 'ja_es', 'zh_es',\n]\n\nconst PAIR_MAPPING: Record<string, [string, string]> = {\n it: ['ko', 'en'],\n it_ja: ['ko', 'ja'],\n it_zh: ['ko', 'zh'],\n it_es: ['ko', 'es'],\n it_fr: ['ko', 'fr'],\n it_de: ['ko', 'de'],\n en_ja: ['en', 'ja'],\n en_zh: ['en', 'zh'],\n en_es: ['en', 'es'],\n en_fr: ['en', 'fr'],\n en_de: ['en', 'de'],\n ja_zh: ['ja', 'zh'],\n ja_es: ['ja', 'es'],\n zh_es: ['zh', 'es'],\n}\n\nfunction extractVariables(text: string): string[] {\n const matches = text.match(/\\{(\\w+)\\}/g)\n if (!matches) return []\n return matches.map((m) => m.slice(1, -1))\n}\n\nconst ICU_TYPE_PATTERN = /\\{(\\w+),\\s*(\\w+)/g\n\nfunction extractICUTypes(text: string): ICUTypeInfo[] {\n const types: ICUTypeInfo[] = []\n let match: RegExpExecArray | null\n ICU_TYPE_PATTERN.lastIndex = 0\n while ((match = ICU_TYPE_PATTERN.exec(text)) !== null) {\n types.push({ variable: match[1]!, type: match[2]! })\n }\n return types\n}\n\nfunction parseFile(filePath: string): TranslationEntry[] {\n const entries: TranslationEntry[] = []\n const code = fs.readFileSync(filePath, 'utf-8')\n\n let ast\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n })\n } catch {\n return []\n }\n\n traverse(ast, {\n CallExpression(nodePath) {\n const { node } = nodePath\n const { callee } = node\n\n if (callee.type !== 'Identifier') return\n if (!IT_FUNCTION_NAMES.includes(callee.name)) return\n\n const funcName = callee.name\n const args = node.arguments\n const loc = node.loc\n\n if (!loc) return\n\n const entry: TranslationEntry = {\n file: filePath,\n line: loc.start.line,\n column: loc.start.column,\n translations: {},\n variables: [],\n }\n\n if (args[0]?.type === 'ObjectExpression') {\n const obj = args[0]\n for (const prop of obj.properties) {\n if (\n prop.type === 'ObjectProperty' &&\n prop.key.type === 'Identifier' &&\n prop.value.type === 'StringLiteral'\n ) {\n entry.translations[prop.key.name] = prop.value.value\n entry.variables.push(...extractVariables(prop.value.value))\n // Extract ICU type info (v0.7.0)\n const types = extractICUTypes(prop.value.value)\n if (types.length > 0) {\n if (!entry.icuTypes) entry.icuTypes = {}\n entry.icuTypes[prop.key.name] = types\n }\n }\n }\n } else if (\n args[0]?.type === 'StringLiteral' &&\n args[1]?.type === 'StringLiteral'\n ) {\n const [lang1, lang2] = PAIR_MAPPING[funcName] || ['ko', 'en']\n entry.translations[lang1] = args[0].value\n entry.translations[lang2] = args[1].value\n entry.variables.push(...extractVariables(args[0].value))\n entry.variables.push(...extractVariables(args[1].value))\n // Extract ICU type info (v0.7.0)\n const types1 = extractICUTypes(args[0].value)\n if (types1.length > 0) {\n if (!entry.icuTypes) entry.icuTypes = {}\n entry.icuTypes[lang1] = types1\n }\n const types2 = extractICUTypes(args[1].value)\n if (types2.length > 0) {\n if (!entry.icuTypes) entry.icuTypes = {}\n entry.icuTypes[lang2] = types2\n }\n }\n\n entry.variables = [...new Set(entry.variables)]\n\n if (Object.keys(entry.translations).length > 0) {\n entries.push(entry)\n }\n },\n })\n\n return entries\n}\n\n// v0.8.0: Flatten nested ObjectExpression to dot-notation keys\nfunction flattenObjectKeys(\n node: { type: string; properties?: unknown[] },\n prefix: string = '',\n): string[] {\n const keys: string[] = []\n if (node.type !== 'ObjectExpression' || !node.properties) return keys\n\n for (const prop of node.properties as Array<{\n type: string\n key: { type: string; name?: string; value?: string }\n value: { type: string; properties?: unknown[] }\n }>) {\n if (prop.type !== 'ObjectProperty') continue\n\n let propName: string | undefined\n if (prop.key.type === 'Identifier') propName = prop.key.name\n else if (prop.key.type === 'StringLiteral') propName = prop.key.value\n\n if (!propName) continue\n\n const fullKey = prefix ? `${prefix}.${propName}` : propName\n\n if (prop.value.type === 'StringLiteral') {\n keys.push(fullKey)\n } else if (prop.value.type === 'ObjectExpression') {\n keys.push(...flattenObjectKeys(prop.value, fullKey))\n }\n }\n return keys\n}\n\n// v0.8.0: Extract dictionary keys from loadDictionaries() calls\nexport function parseDictionaryKeys(filePath: string): DictionaryKeyEntry[] {\n const entries: DictionaryKeyEntry[] = []\n const code = fs.readFileSync(filePath, 'utf-8')\n\n let ast\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n })\n } catch {\n return []\n }\n\n traverse(ast, {\n CallExpression(nodePath) {\n const { node } = nodePath\n const { callee } = node\n\n if (callee.type !== 'Identifier' || callee.name !== 'loadDictionaries') return\n\n const args = node.arguments\n const loc = node.loc\n if (!loc || !args[0] || args[0].type !== 'ObjectExpression') return\n\n // Second argument is optional namespace\n let namespace = 'default'\n if (args[1]?.type === 'StringLiteral') {\n namespace = args[1].value\n }\n\n // First argument: { locale: { key: value } }\n // Collect keys from the first locale's dict (all locales should have same keys)\n const dictObj = args[0]\n const allKeys = new Set<string>()\n\n for (const localeProp of dictObj.properties as Array<{\n type: string\n value: { type: string; properties?: unknown[] }\n }>) {\n if (localeProp.type !== 'ObjectProperty') continue\n if (localeProp.value.type !== 'ObjectExpression') continue\n\n const localeKeys = flattenObjectKeys(localeProp.value)\n for (const key of localeKeys) {\n allKeys.add(key)\n }\n }\n\n if (allKeys.size > 0) {\n entries.push({\n file: filePath,\n line: loc.start.line,\n namespace,\n keys: [...allKeys],\n })\n }\n },\n })\n\n return entries\n}\n\n// v0.8.0: Extract t() call sites\nexport function parseTCalls(filePath: string): TCallEntry[] {\n const entries: TCallEntry[] = []\n const code = fs.readFileSync(filePath, 'utf-8')\n\n let ast\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n })\n } catch {\n return []\n }\n\n traverse(ast, {\n CallExpression(nodePath) {\n const { node } = nodePath\n const { callee } = node\n\n if (callee.type !== 'Identifier' || callee.name !== 't') return\n\n const args = node.arguments\n const loc = node.loc\n if (!loc || !args[0] || args[0].type !== 'StringLiteral') return\n\n entries.push({\n file: filePath,\n line: loc.start.line,\n key: args[0].value,\n })\n },\n })\n\n return entries\n}\n\nexport async function extractProjectDictionaryKeys(options: ParseOptions = {}): Promise<DictionaryKeyEntry[]> {\n const {\n cwd = process.cwd(),\n include = ['**/*.{ts,tsx,js,jsx}'],\n exclude = ['**/node_modules/**', '**/dist/**', '**/.next/**'],\n } = options\n\n const files = await fg(include, { cwd, ignore: exclude, absolute: true })\n const allEntries: DictionaryKeyEntry[] = []\n\n for (const file of files) {\n allEntries.push(...parseDictionaryKeys(file))\n }\n\n return allEntries\n}\n\nexport async function extractProjectTCalls(options: ParseOptions = {}): Promise<TCallEntry[]> {\n const {\n cwd = process.cwd(),\n include = ['**/*.{ts,tsx,js,jsx}'],\n exclude = ['**/node_modules/**', '**/dist/**', '**/.next/**'],\n } = options\n\n const files = await fg(include, { cwd, ignore: exclude, absolute: true })\n const allEntries: TCallEntry[] = []\n\n for (const file of files) {\n allEntries.push(...parseTCalls(file))\n }\n\n return allEntries\n}\n\nexport async function parseProject(options: ParseOptions = {}): Promise<TranslationEntry[]> {\n const {\n cwd = process.cwd(),\n include = ['**/*.{ts,tsx,js,jsx}'],\n exclude = ['**/node_modules/**', '**/dist/**', '**/.next/**'],\n } = options\n\n const files = await fg(include, {\n cwd,\n ignore: exclude,\n absolute: true,\n })\n\n const allEntries: TranslationEntry[] = []\n\n for (const file of files) {\n const entries = parseFile(file)\n allEntries.push(...entries)\n }\n\n return allEntries\n}\n","import chalk from 'chalk'\nimport { parseProject, type TranslationEntry } from '../parser'\n\ninterface FindOptions {\n query: string\n cwd?: string\n}\n\nexport async function find(options: FindOptions): Promise<void> {\n const { query, cwd } = options\n\n console.log(chalk.blue(`\\nSearching for: \"${query}\"\\n`))\n\n const entries = await parseProject({ cwd })\n const results: TranslationEntry[] = []\n\n const lowerQuery = query.toLowerCase()\n\n for (const entry of entries) {\n const values = Object.values(entry.translations)\n const matches = values.some((v) => v.toLowerCase().includes(lowerQuery))\n\n if (matches) {\n results.push(entry)\n }\n }\n\n if (results.length === 0) {\n console.log(chalk.yellow('No results found.'))\n return\n }\n\n console.log(chalk.green(`Found ${results.length} occurrence(s):\\n`))\n\n for (const result of results) {\n const relativePath = result.file.replace(process.cwd() + '/', '')\n console.log(chalk.gray(`${relativePath}:${result.line}:${result.column}`))\n\n for (const [locale, text] of Object.entries(result.translations)) {\n const highlighted = text.replace(\n new RegExp(`(${query})`, 'gi'),\n chalk.yellow('$1')\n )\n console.log(` ${chalk.cyan(locale)}: ${highlighted}`)\n }\n console.log()\n }\n}\n","import chalk from 'chalk'\nimport { parseProject, type TranslationEntry } from '../parser'\nimport { unused } from './unused'\n\ninterface ValidateOptions {\n cwd?: string\n locales?: string[]\n strict?: boolean\n unused?: boolean\n noExit?: boolean\n}\n\ninterface Issue {\n type: 'inconsistent' | 'missing' | 'variable_mismatch' | 'icu_type_mismatch'\n message: string\n entries: TranslationEntry[]\n details?: string[]\n}\n\nfunction checkVariableConsistency(entry: TranslationEntry): Issue | null {\n const varsByLocale: { locale: string; vars: string[] }[] = []\n\n for (const [locale, text] of Object.entries(entry.translations)) {\n const matches = text.match(/\\{(\\w+)\\}/g) || []\n const varNames = [...new Set(matches.map((v) => v.slice(1, -1)))].sort()\n varsByLocale.push({ locale, vars: varNames })\n }\n\n if (varsByLocale.length < 2) return null\n\n const reference = varsByLocale[0]!\n const details: string[] = []\n\n for (let i = 1; i < varsByLocale.length; i++) {\n const current = varsByLocale[i]!\n const refSet = new Set(reference.vars)\n const curSet = new Set(current.vars)\n\n const onlyInRef = reference.vars.filter((v) => !curSet.has(v))\n const onlyInCur = current.vars.filter((v) => !refSet.has(v))\n\n if (onlyInRef.length > 0) {\n details.push(\n `${reference.locale} has {${onlyInRef.join('}, {')}} missing in ${current.locale}`,\n )\n }\n if (onlyInCur.length > 0) {\n details.push(\n `${current.locale} has {${onlyInCur.join('}, {')}} missing in ${reference.locale}`,\n )\n }\n }\n\n if (details.length === 0) return null\n\n return {\n type: 'variable_mismatch',\n message: 'Variable mismatch between translations',\n entries: [entry],\n details,\n }\n}\n\nfunction checkICUTypeConsistency(entry: TranslationEntry): Issue | null {\n if (!entry.icuTypes) return null\n\n const locales = Object.keys(entry.icuTypes)\n if (locales.length < 2) return null\n\n const details: string[] = []\n const reference = locales[0]!\n const refTypes = entry.icuTypes[reference]!\n\n for (let i = 1; i < locales.length; i++) {\n const locale = locales[i]!\n const curTypes = entry.icuTypes[locale]!\n\n for (const refType of refTypes) {\n const match = curTypes.find((t: { variable: string; type: string }) => t.variable === refType.variable)\n if (match && match.type !== refType.type) {\n details.push(\n `{${refType.variable}} is \"${refType.type}\" in ${reference} but \"${match.type}\" in ${locale}`,\n )\n }\n }\n }\n\n if (details.length === 0) return null\n\n return {\n type: 'icu_type_mismatch',\n message: 'ICU type mismatch between translations',\n entries: [entry],\n details,\n }\n}\n\nexport async function validate(options: ValidateOptions = {}): Promise<void> {\n const { cwd, locales, strict, unused: checkUnused } = options\n\n console.log(chalk.blue('\\nValidating translations...\\n'))\n\n const entries = await parseProject({ cwd })\n const issues: Issue[] = []\n\n // group by first language text (usually ko)\n const groups = new Map<string, TranslationEntry[]>()\n\n for (const entry of entries) {\n const key = Object.values(entry.translations)[0] || ''\n if (!groups.has(key)) {\n groups.set(key, [])\n }\n groups.get(key)!.push(entry)\n }\n\n // check for inconsistent translations\n for (const [key, group] of groups) {\n if (group.length < 2) continue\n\n const translationSets = group.map((e) => JSON.stringify(e.translations))\n const uniqueSets = [...new Set(translationSets)]\n\n if (uniqueSets.length > 1) {\n issues.push({\n type: 'inconsistent',\n message: `Inconsistent translations for \"${key}\"`,\n entries: group,\n })\n }\n }\n\n // check for missing locales\n if (locales && locales.length > 0) {\n for (const entry of entries) {\n const missing = locales.filter((l) => !entry.translations[l])\n\n if (missing.length > 0) {\n issues.push({\n type: 'missing',\n message: `Missing locales: ${missing.join(', ')}`,\n entries: [entry],\n })\n }\n }\n }\n\n // check for variable name consistency (enhanced in v0.7.0)\n for (const entry of entries) {\n const issue = checkVariableConsistency(entry)\n if (issue) issues.push(issue)\n }\n\n // check for ICU type consistency (strict mode, v0.7.0)\n if (strict) {\n for (const entry of entries) {\n const issue = checkICUTypeConsistency(entry)\n if (issue) issues.push(issue)\n }\n }\n\n // unused key detection (v0.8.0)\n let unusedCount = 0\n if (checkUnused) {\n const result = await unused({ cwd })\n unusedCount = result.unusedKeys.length\n }\n\n // print results\n if (issues.length === 0 && unusedCount === 0) {\n console.log(chalk.green('All translations are valid!\\n'))\n console.log(chalk.gray(`Checked ${entries.length} translation(s)`))\n if (strict) {\n console.log(chalk.gray('(strict mode enabled)'))\n }\n if (checkUnused) {\n console.log(chalk.gray('(unused key detection enabled)'))\n }\n return\n }\n\n console.log(chalk.red(`Found ${issues.length} issue(s):\\n`))\n\n for (const issue of issues) {\n console.log(` ${chalk.yellow(issue.message)}`)\n\n for (const entry of issue.entries) {\n const relativePath = entry.file.replace(process.cwd() + '/', '')\n console.log(chalk.gray(` ${relativePath}:${entry.line}`))\n\n for (const [locale, text] of Object.entries(entry.translations)) {\n console.log(` ${chalk.cyan(locale)}: ${text}`)\n }\n }\n\n if (issue.details && issue.details.length > 0) {\n for (const detail of issue.details) {\n console.log(chalk.gray(` → ${detail}`))\n }\n }\n\n console.log()\n }\n\n if ((issues.length > 0 || unusedCount > 0) && !options.noExit) {\n process.exit(1)\n }\n}\n","import chalk from 'chalk'\nimport { extractProjectDictionaryKeys, extractProjectTCalls } from '../parser'\n\ninterface UnusedKey {\n namespace: string\n key: string\n definedIn: string\n line: number\n}\n\nconst PLURAL_SUFFIXES = ['_zero', '_one', '_two', '_few', '_many', '_other']\n\nexport async function unused(options: { cwd?: string } = {}): Promise<{ unusedKeys: UnusedKey[] }> {\n const { cwd } = options\n\n console.log(chalk.blue('\\nDetecting unused translations...\\n'))\n\n const dictEntries = await extractProjectDictionaryKeys({ cwd })\n const tCalls = await extractProjectTCalls({ cwd })\n\n // Build set of used keys (normalized: namespace:key or key for default)\n const usedKeys = new Set<string>()\n for (const call of tCalls) {\n usedKeys.add(call.key)\n // Also add with default namespace if no namespace prefix\n if (!call.key.includes(':')) {\n usedKeys.add(call.key)\n }\n }\n\n // Check each dictionary key against used keys\n const unusedKeys: UnusedKey[] = []\n\n for (const entry of dictEntries) {\n for (const key of entry.keys) {\n const fullKey = entry.namespace === 'default' ? key : `${entry.namespace}:${key}`\n\n // Check if key is directly used\n if (usedKeys.has(fullKey)) continue\n\n // Check if this is a plural suffix variant (e.g. count_one, count_other)\n // and the base key is used via t('items.count', { count: N })\n let isPluralVariant = false\n for (const suffix of PLURAL_SUFFIXES) {\n if (key.endsWith(suffix)) {\n const baseKey = key.slice(0, -suffix.length)\n const fullBaseKey = entry.namespace === 'default' ? baseKey : `${entry.namespace}:${baseKey}`\n if (usedKeys.has(fullBaseKey)) {\n isPluralVariant = true\n break\n }\n }\n }\n if (isPluralVariant) continue\n\n unusedKeys.push({\n namespace: entry.namespace,\n key: fullKey,\n definedIn: entry.file,\n line: entry.line,\n })\n }\n }\n\n // Report results\n if (unusedKeys.length === 0) {\n const totalKeys = dictEntries.reduce((sum, e) => sum + e.keys.length, 0)\n console.log(chalk.green('No unused translations found!\\n'))\n console.log(chalk.gray(`Checked ${totalKeys} dictionary key(s) against ${tCalls.length} t() call(s)`))\n return { unusedKeys }\n }\n\n console.log(chalk.yellow(`Found ${unusedKeys.length} unused translation key(s):\\n`))\n for (const item of unusedKeys) {\n const relativePath = item.definedIn.replace(process.cwd() + '/', '')\n console.log(` ${chalk.red('-')} ${chalk.cyan(item.key)}`)\n console.log(chalk.gray(` defined in ${relativePath}:${item.line}`))\n }\n\n console.log()\n return { unusedKeys }\n}\n","import chalk from 'chalk'\nimport { parseProject } from '../parser'\n\ninterface CoverageOptions {\n cwd?: string\n locales: string[]\n}\n\ninterface LocaleCoverage {\n locale: string\n total: number\n translated: number\n percentage: number\n}\n\nexport async function coverage(options: CoverageOptions): Promise<void> {\n const { cwd, locales } = options\n\n console.log(chalk.blue('\\nAnalyzing translation coverage...\\n'))\n\n const entries = await parseProject({ cwd })\n\n if (entries.length === 0) {\n console.log(chalk.yellow('No translations found.'))\n return\n }\n\n const coverageData: LocaleCoverage[] = []\n\n for (const locale of locales) {\n let translated = 0\n\n for (const entry of entries) {\n if (entry.translations[locale]) {\n translated++\n }\n }\n\n const percentage = Math.round((translated / entries.length) * 100)\n\n coverageData.push({\n locale,\n total: entries.length,\n translated,\n percentage,\n })\n }\n\n // print coverage table\n console.log(chalk.bold('Translation Coverage:\\n'))\n\n const maxLocaleLen = Math.max(...locales.map((l) => l.length), 6)\n\n console.log(\n chalk.gray(\n `${'Locale'.padEnd(maxLocaleLen)} ${'Coverage'.padStart(10)} ${'Translated'.padStart(12)}`\n )\n )\n console.log(chalk.gray('─'.repeat(maxLocaleLen + 26)))\n\n for (const data of coverageData) {\n const color =\n data.percentage === 100 ? chalk.green :\n data.percentage >= 80 ? chalk.yellow : chalk.red\n\n const bar = createProgressBar(data.percentage, 10)\n const percentStr = `${data.percentage}%`.padStart(4)\n\n console.log(\n `${data.locale.padEnd(maxLocaleLen)} ${color(bar)} ${color(percentStr)} ${chalk.gray(`${data.translated}/${data.total}`)}`\n )\n }\n\n console.log()\n\n // summary\n const fullyCovered = coverageData.filter((d) => d.percentage === 100).length\n const partiallyCovered = coverageData.filter((d) => d.percentage > 0 && d.percentage < 100).length\n const notCovered = coverageData.filter((d) => d.percentage === 0).length\n\n if (fullyCovered === locales.length) {\n console.log(chalk.green('All locales are fully translated!'))\n } else {\n console.log(chalk.gray(`Full: ${fullyCovered}, Partial: ${partiallyCovered}, Empty: ${notCovered}`))\n }\n}\n\nfunction createProgressBar(percentage: number, width: number): string {\n const filled = Math.round((percentage / 100) * width)\n const empty = width - filled\n\n return '█'.repeat(filled) + '░'.repeat(empty)\n}\n","import * as fs from 'fs'\nimport * as path from 'path'\nimport chalk from 'chalk'\nimport { extractProjectDictionaryKeys } from '../parser'\n\ninterface TypegenOptions {\n cwd?: string\n output?: string\n}\n\nconst PLURAL_SUFFIXES = ['_zero', '_one', '_two', '_few', '_many', '_other']\n\nexport async function typegen(options: TypegenOptions = {}): Promise<void> {\n const { cwd, output = 'src/i18n.d.ts' } = options\n\n console.log(chalk.blue('\\nGenerating TypeScript types...\\n'))\n\n const dictEntries = await extractProjectDictionaryKeys({ cwd })\n\n // Collect all unique full keys (namespace:key or key)\n const allKeys = new Set<string>()\n\n for (const entry of dictEntries) {\n for (const key of entry.keys) {\n const fullKey = entry.namespace === 'default' ? key : `${entry.namespace}:${key}`\n allKeys.add(fullKey)\n\n // Also add plural base keys (strip _one, _other, etc.)\n for (const suffix of PLURAL_SUFFIXES) {\n if (key.endsWith(suffix)) {\n const baseKey = key.slice(0, -suffix.length)\n const fullBaseKey = entry.namespace === 'default' ? baseKey : `${entry.namespace}:${baseKey}`\n allKeys.add(fullBaseKey)\n }\n }\n }\n }\n\n if (allKeys.size === 0) {\n console.log(chalk.yellow('No dictionary keys found. Make sure loadDictionaries() calls are present.'))\n return\n }\n\n const sortedKeys = [...allKeys].sort()\n\n // Generate the .d.ts content\n const keyUnion = sortedKeys.map(k => ` | '${k}'`).join('\\n')\n\n const content = `// Auto-generated by inline-i18n typegen\n// Do not edit manually. Re-run: npx inline-i18n typegen\n\nimport 'inline-i18n-multi'\n\ndeclare module 'inline-i18n-multi' {\n export type TranslationKey =\n${keyUnion}\n\n export function t(\n key: TranslationKey,\n vars?: TranslationVars,\n locale?: string\n ): string\n\n export function hasTranslation(\n key: TranslationKey,\n locale?: string\n ): boolean\n}\n`\n\n const outputPath = path.resolve(cwd || process.cwd(), output)\n const outputDir = path.dirname(outputPath)\n\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true })\n }\n\n fs.writeFileSync(outputPath, content, 'utf-8')\n\n console.log(chalk.green(`Generated ${sortedKeys.length} translation key types`))\n console.log(chalk.gray(`Output: ${outputPath}\\n`))\n\n // Show sample\n const sample = sortedKeys.slice(0, 5)\n for (const key of sample) {\n console.log(` ${chalk.cyan(key)}`)\n }\n if (sortedKeys.length > 5) {\n console.log(chalk.gray(` ... and ${sortedKeys.length - 5} more`))\n }\n}\n","import chalk from 'chalk'\nimport * as fs from 'fs'\nimport * as path from 'path'\nimport { parseProject } from '../parser'\n\ninterface ExtractOptions {\n cwd?: string\n output?: string\n format?: 'flat' | 'nested'\n}\n\nexport async function extract(options: ExtractOptions = {}): Promise<void> {\n const { cwd, output = 'translations', format = 'flat' } = options\n\n console.log(chalk.blue('\\nExtracting inline translations...\\n'))\n\n const entries = await parseProject({ cwd })\n\n if (entries.length === 0) {\n console.log(chalk.yellow('No translations found.'))\n return\n }\n\n // Group translations by locale\n const byLocale: Record<string, Record<string, string>> = {}\n const basePath = cwd || process.cwd()\n\n for (const entry of entries) {\n for (const [locale, text] of Object.entries(entry.translations)) {\n if (!byLocale[locale]) byLocale[locale] = {}\n\n const relativePath = entry.file.replace(basePath + '/', '')\n const key = `${relativePath}:${entry.line}`\n byLocale[locale][key] = text\n }\n }\n\n // Write output files\n const outputDir = path.resolve(basePath, output)\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true })\n }\n\n const locales = Object.keys(byLocale).sort()\n for (const locale of locales) {\n const translations = byLocale[locale]!\n let content: string\n\n if (format === 'nested') {\n const nested = buildNestedObject(translations)\n content = JSON.stringify(nested, null, 2) + '\\n'\n } else {\n content = JSON.stringify(translations, null, 2) + '\\n'\n }\n\n const filePath = path.join(outputDir, `${locale}.json`)\n fs.writeFileSync(filePath, content)\n console.log(\n chalk.green(` ${locale}.json`) +\n chalk.gray(` (${Object.keys(translations).length} keys)`)\n )\n }\n\n console.log(chalk.gray(`\\nExtracted ${entries.length} translation(s) to ${output}/`))\n}\n\n/**\n * Build a nested object from flat dot-notation keys\n */\nfunction buildNestedObject(flat: Record<string, string>): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n\n for (const [key, value] of Object.entries(flat)) {\n const parts = key.split('.')\n let current: Record<string, unknown> = result\n\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i]!\n if (!current[part] || typeof current[part] !== 'object') {\n current[part] = {}\n }\n current = current[part] as Record<string, unknown>\n }\n\n current[parts[parts.length - 1]!] = value\n }\n\n return result\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAAsB;AACtB,sBAAqB;AACrB,SAAoB;AACpB,uBAAe;AAsCf,IAAM,oBAAoB;AAAA,EACxB;AAAA,EACA;AAAA,EAAS;AAAA,EAAS;AAAA,EAAS;AAAA,EAAS;AAAA,EACpC;AAAA,EAAS;AAAA,EAAS;AAAA,EAAS;AAAA,EAAS;AAAA,EACpC;AAAA,EAAS;AAAA,EAAS;AACpB;AAEA,IAAM,eAAiD;AAAA,EACrD,IAAI,CAAC,MAAM,IAAI;AAAA,EACf,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AAAA,EAClB,OAAO,CAAC,MAAM,IAAI;AACpB;AAEA,SAAS,iBAAiB,MAAwB;AAChD,QAAM,UAAU,KAAK,MAAM,YAAY;AACvC,MAAI,CAAC,QAAS,QAAO,CAAC;AACtB,SAAO,QAAQ,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC;AAC1C;AAEA,IAAM,mBAAmB;AAEzB,SAAS,gBAAgB,MAA6B;AACpD,QAAM,QAAuB,CAAC;AAC9B,MAAI;AACJ,mBAAiB,YAAY;AAC7B,UAAQ,QAAQ,iBAAiB,KAAK,IAAI,OAAO,MAAM;AACrD,UAAM,KAAK,EAAE,UAAU,MAAM,CAAC,GAAI,MAAM,MAAM,CAAC,EAAG,CAAC;AAAA,EACrD;AACA,SAAO;AACT;AAEA,SAAS,UAAU,UAAsC;AACvD,QAAM,UAA8B,CAAC;AACrC,QAAM,OAAU,gBAAa,UAAU,OAAO;AAE9C,MAAI;AACJ,MAAI;AACF,cAAM,qBAAM,MAAM;AAAA,MAChB,YAAY;AAAA,MACZ,SAAS,CAAC,cAAc,KAAK;AAAA,IAC/B,CAAC;AAAA,EACH,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AAEA,sBAAAA,SAAS,KAAK;AAAA,IACZ,eAAe,UAAU;AACvB,YAAM,EAAE,KAAK,IAAI;AACjB,YAAM,EAAE,OAAO,IAAI;AAEnB,UAAI,OAAO,SAAS,aAAc;AAClC,UAAI,CAAC,kBAAkB,SAAS,OAAO,IAAI,EAAG;AAE9C,YAAM,WAAW,OAAO;AACxB,YAAM,OAAO,KAAK;AAClB,YAAM,MAAM,KAAK;AAEjB,UAAI,CAAC,IAAK;AAEV,YAAM,QAA0B;AAAA,QAC9B,MAAM;AAAA,QACN,MAAM,IAAI,MAAM;AAAA,QAChB,QAAQ,IAAI,MAAM;AAAA,QAClB,cAAc,CAAC;AAAA,QACf,WAAW,CAAC;AAAA,MACd;AAEA,UAAI,KAAK,CAAC,GAAG,SAAS,oBAAoB;AACxC,cAAM,MAAM,KAAK,CAAC;AAClB,mBAAW,QAAQ,IAAI,YAAY;AACjC,cACE,KAAK,SAAS,oBACd,KAAK,IAAI,SAAS,gBAClB,KAAK,MAAM,SAAS,iBACpB;AACA,kBAAM,aAAa,KAAK,IAAI,IAAI,IAAI,KAAK,MAAM;AAC/C,kBAAM,UAAU,KAAK,GAAG,iBAAiB,KAAK,MAAM,KAAK,CAAC;AAE1D,kBAAM,QAAQ,gBAAgB,KAAK,MAAM,KAAK;AAC9C,gBAAI,MAAM,SAAS,GAAG;AACpB,kBAAI,CAAC,MAAM,SAAU,OAAM,WAAW,CAAC;AACvC,oBAAM,SAAS,KAAK,IAAI,IAAI,IAAI;AAAA,YAClC;AAAA,UACF;AAAA,QACF;AAAA,MACF,WACE,KAAK,CAAC,GAAG,SAAS,mBAClB,KAAK,CAAC,GAAG,SAAS,iBAClB;AACA,cAAM,CAAC,OAAO,KAAK,IAAI,aAAa,QAAQ,KAAK,CAAC,MAAM,IAAI;AAC5D,cAAM,aAAa,KAAK,IAAI,KAAK,CAAC,EAAE;AACpC,cAAM,aAAa,KAAK,IAAI,KAAK,CAAC,EAAE;AACpC,cAAM,UAAU,KAAK,GAAG,iBAAiB,KAAK,CAAC,EAAE,KAAK,CAAC;AACvD,cAAM,UAAU,KAAK,GAAG,iBAAiB,KAAK,CAAC,EAAE,KAAK,CAAC;AAEvD,cAAM,SAAS,gBAAgB,KAAK,CAAC,EAAE,KAAK;AAC5C,YAAI,OAAO,SAAS,GAAG;AACrB,cAAI,CAAC,MAAM,SAAU,OAAM,WAAW,CAAC;AACvC,gBAAM,SAAS,KAAK,IAAI;AAAA,QAC1B;AACA,cAAM,SAAS,gBAAgB,KAAK,CAAC,EAAE,KAAK;AAC5C,YAAI,OAAO,SAAS,GAAG;AACrB,cAAI,CAAC,MAAM,SAAU,OAAM,WAAW,CAAC;AACvC,gBAAM,SAAS,KAAK,IAAI;AAAA,QAC1B;AAAA,MACF;AAEA,YAAM,YAAY,CAAC,GAAG,IAAI,IAAI,MAAM,SAAS,CAAC;AAE9C,UAAI,OAAO,KAAK,MAAM,YAAY,EAAE,SAAS,GAAG;AAC9C,gBAAQ,KAAK,KAAK;AAAA,MACpB;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAGA,SAAS,kBACP,MACA,SAAiB,IACP;AACV,QAAM,OAAiB,CAAC;AACxB,MAAI,KAAK,SAAS,sBAAsB,CAAC,KAAK,WAAY,QAAO;AAEjE,aAAW,QAAQ,KAAK,YAIpB;AACF,QAAI,KAAK,SAAS,iBAAkB;AAEpC,QAAI;AACJ,QAAI,KAAK,IAAI,SAAS,aAAc,YAAW,KAAK,IAAI;AAAA,aAC/C,KAAK,IAAI,SAAS,gBAAiB,YAAW,KAAK,IAAI;AAEhE,QAAI,CAAC,SAAU;AAEf,UAAM,UAAU,SAAS,GAAG,MAAM,IAAI,QAAQ,KAAK;AAEnD,QAAI,KAAK,MAAM,SAAS,iBAAiB;AACvC,WAAK,KAAK,OAAO;AAAA,IACnB,WAAW,KAAK,MAAM,SAAS,oBAAoB;AACjD,WAAK,KAAK,GAAG,kBAAkB,KAAK,OAAO,OAAO,CAAC;AAAA,IACrD;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,oBAAoB,UAAwC;AAC1E,QAAM,UAAgC,CAAC;AACvC,QAAM,OAAU,gBAAa,UAAU,OAAO;AAE9C,MAAI;AACJ,MAAI;AACF,cAAM,qBAAM,MAAM;AAAA,MAChB,YAAY;AAAA,MACZ,SAAS,CAAC,cAAc,KAAK;AAAA,IAC/B,CAAC;AAAA,EACH,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AAEA,sBAAAA,SAAS,KAAK;AAAA,IACZ,eAAe,UAAU;AACvB,YAAM,EAAE,KAAK,IAAI;AACjB,YAAM,EAAE,OAAO,IAAI;AAEnB,UAAI,OAAO,SAAS,gBAAgB,OAAO,SAAS,mBAAoB;AAExE,YAAM,OAAO,KAAK;AAClB,YAAM,MAAM,KAAK;AACjB,UAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,EAAE,SAAS,mBAAoB;AAG7D,UAAI,YAAY;AAChB,UAAI,KAAK,CAAC,GAAG,SAAS,iBAAiB;AACrC,oBAAY,KAAK,CAAC,EAAE;AAAA,MACtB;AAIA,YAAM,UAAU,KAAK,CAAC;AACtB,YAAM,UAAU,oBAAI,IAAY;AAEhC,iBAAW,cAAc,QAAQ,YAG7B;AACF,YAAI,WAAW,SAAS,iBAAkB;AAC1C,YAAI,WAAW,MAAM,SAAS,mBAAoB;AAElD,cAAM,aAAa,kBAAkB,WAAW,KAAK;AACrD,mBAAW,OAAO,YAAY;AAC5B,kBAAQ,IAAI,GAAG;AAAA,QACjB;AAAA,MACF;AAEA,UAAI,QAAQ,OAAO,GAAG;AACpB,gBAAQ,KAAK;AAAA,UACX,MAAM;AAAA,UACN,MAAM,IAAI,MAAM;AAAA,UAChB;AAAA,UACA,MAAM,CAAC,GAAG,OAAO;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAGO,SAAS,YAAY,UAAgC;AAC1D,QAAM,UAAwB,CAAC;AAC/B,QAAM,OAAU,gBAAa,UAAU,OAAO;AAE9C,MAAI;AACJ,MAAI;AACF,cAAM,qBAAM,MAAM;AAAA,MAChB,YAAY;AAAA,MACZ,SAAS,CAAC,cAAc,KAAK;AAAA,IAC/B,CAAC;AAAA,EACH,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AAEA,sBAAAA,SAAS,KAAK;AAAA,IACZ,eAAe,UAAU;AACvB,YAAM,EAAE,KAAK,IAAI;AACjB,YAAM,EAAE,OAAO,IAAI;AAEnB,UAAI,OAAO,SAAS,gBAAgB,OAAO,SAAS,IAAK;AAEzD,YAAM,OAAO,KAAK;AAClB,YAAM,MAAM,KAAK;AACjB,UAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,EAAE,SAAS,gBAAiB;AAE1D,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,MAAM,IAAI,MAAM;AAAA,QAChB,KAAK,KAAK,CAAC,EAAE;AAAA,MACf,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAEA,eAAsB,6BAA6B,UAAwB,CAAC,GAAkC;AAC5G,QAAM;AAAA,IACJ,MAAM,QAAQ,IAAI;AAAA,IAClB,UAAU,CAAC,sBAAsB;AAAA,IACjC,UAAU,CAAC,sBAAsB,cAAc,aAAa;AAAA,EAC9D,IAAI;AAEJ,QAAM,QAAQ,UAAM,iBAAAC,SAAG,SAAS,EAAE,KAAK,QAAQ,SAAS,UAAU,KAAK,CAAC;AACxE,QAAM,aAAmC,CAAC;AAE1C,aAAW,QAAQ,OAAO;AACxB,eAAW,KAAK,GAAG,oBAAoB,IAAI,CAAC;AAAA,EAC9C;AAEA,SAAO;AACT;AAEA,eAAsB,qBAAqB,UAAwB,CAAC,GAA0B;AAC5F,QAAM;AAAA,IACJ,MAAM,QAAQ,IAAI;AAAA,IAClB,UAAU,CAAC,sBAAsB;AAAA,IACjC,UAAU,CAAC,sBAAsB,cAAc,aAAa;AAAA,EAC9D,IAAI;AAEJ,QAAM,QAAQ,UAAM,iBAAAA,SAAG,SAAS,EAAE,KAAK,QAAQ,SAAS,UAAU,KAAK,CAAC;AACxE,QAAM,aAA2B,CAAC;AAElC,aAAW,QAAQ,OAAO;AACxB,eAAW,KAAK,GAAG,YAAY,IAAI,CAAC;AAAA,EACtC;AAEA,SAAO;AACT;AAEA,eAAsB,aAAa,UAAwB,CAAC,GAAgC;AAC1F,QAAM;AAAA,IACJ,MAAM,QAAQ,IAAI;AAAA,IAClB,UAAU,CAAC,sBAAsB;AAAA,IACjC,UAAU,CAAC,sBAAsB,cAAc,aAAa;AAAA,EAC9D,IAAI;AAEJ,QAAM,QAAQ,UAAM,iBAAAA,SAAG,SAAS;AAAA,IAC9B;AAAA,IACA,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ,CAAC;AAED,QAAM,aAAiC,CAAC;AAExC,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAU,UAAU,IAAI;AAC9B,eAAW,KAAK,GAAG,OAAO;AAAA,EAC5B;AAEA,SAAO;AACT;;;ACtWA,mBAAkB;AAQlB,eAAsB,KAAK,SAAqC;AAC9D,QAAM,EAAE,OAAO,IAAI,IAAI;AAEvB,UAAQ,IAAI,aAAAC,QAAM,KAAK;AAAA,kBAAqB,KAAK;AAAA,CAAK,CAAC;AAEvD,QAAM,UAAU,MAAM,aAAa,EAAE,IAAI,CAAC;AAC1C,QAAM,UAA8B,CAAC;AAErC,QAAM,aAAa,MAAM,YAAY;AAErC,aAAW,SAAS,SAAS;AAC3B,UAAM,SAAS,OAAO,OAAO,MAAM,YAAY;AAC/C,UAAM,UAAU,OAAO,KAAK,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,UAAU,CAAC;AAEvE,QAAI,SAAS;AACX,cAAQ,KAAK,KAAK;AAAA,IACpB;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,IAAI,aAAAA,QAAM,OAAO,mBAAmB,CAAC;AAC7C;AAAA,EACF;AAEA,UAAQ,IAAI,aAAAA,QAAM,MAAM,SAAS,QAAQ,MAAM;AAAA,CAAmB,CAAC;AAEnE,aAAW,UAAU,SAAS;AAC5B,UAAM,eAAe,OAAO,KAAK,QAAQ,QAAQ,IAAI,IAAI,KAAK,EAAE;AAChE,YAAQ,IAAI,aAAAA,QAAM,KAAK,GAAG,YAAY,IAAI,OAAO,IAAI,IAAI,OAAO,MAAM,EAAE,CAAC;AAEzE,eAAW,CAAC,QAAQ,IAAI,KAAK,OAAO,QAAQ,OAAO,YAAY,GAAG;AAChE,YAAM,cAAc,KAAK;AAAA,QACvB,IAAI,OAAO,IAAI,KAAK,KAAK,IAAI;AAAA,QAC7B,aAAAA,QAAM,OAAO,IAAI;AAAA,MACnB;AACA,cAAQ,IAAI,KAAK,aAAAA,QAAM,KAAK,MAAM,CAAC,KAAK,WAAW,EAAE;AAAA,IACvD;AACA,YAAQ,IAAI;AAAA,EACd;AACF;;;AC/CA,IAAAC,gBAAkB;;;ACAlB,IAAAC,gBAAkB;AAUlB,IAAM,kBAAkB,CAAC,SAAS,QAAQ,QAAQ,QAAQ,SAAS,QAAQ;AAE3E,eAAsB,OAAO,UAA4B,CAAC,GAAyC;AACjG,QAAM,EAAE,IAAI,IAAI;AAEhB,UAAQ,IAAI,cAAAC,QAAM,KAAK,sCAAsC,CAAC;AAE9D,QAAM,cAAc,MAAM,6BAA6B,EAAE,IAAI,CAAC;AAC9D,QAAM,SAAS,MAAM,qBAAqB,EAAE,IAAI,CAAC;AAGjD,QAAM,WAAW,oBAAI,IAAY;AACjC,aAAW,QAAQ,QAAQ;AACzB,aAAS,IAAI,KAAK,GAAG;AAErB,QAAI,CAAC,KAAK,IAAI,SAAS,GAAG,GAAG;AAC3B,eAAS,IAAI,KAAK,GAAG;AAAA,IACvB;AAAA,EACF;AAGA,QAAM,aAA0B,CAAC;AAEjC,aAAW,SAAS,aAAa;AAC/B,eAAW,OAAO,MAAM,MAAM;AAC5B,YAAM,UAAU,MAAM,cAAc,YAAY,MAAM,GAAG,MAAM,SAAS,IAAI,GAAG;AAG/E,UAAI,SAAS,IAAI,OAAO,EAAG;AAI3B,UAAI,kBAAkB;AACtB,iBAAW,UAAU,iBAAiB;AACpC,YAAI,IAAI,SAAS,MAAM,GAAG;AACxB,gBAAM,UAAU,IAAI,MAAM,GAAG,CAAC,OAAO,MAAM;AAC3C,gBAAM,cAAc,MAAM,cAAc,YAAY,UAAU,GAAG,MAAM,SAAS,IAAI,OAAO;AAC3F,cAAI,SAAS,IAAI,WAAW,GAAG;AAC7B,8BAAkB;AAClB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,UAAI,gBAAiB;AAErB,iBAAW,KAAK;AAAA,QACd,WAAW,MAAM;AAAA,QACjB,KAAK;AAAA,QACL,WAAW,MAAM;AAAA,QACjB,MAAM,MAAM;AAAA,MACd,CAAC;AAAA,IACH;AAAA,EACF;AAGA,MAAI,WAAW,WAAW,GAAG;AAC3B,UAAM,YAAY,YAAY,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,KAAK,QAAQ,CAAC;AACvE,YAAQ,IAAI,cAAAA,QAAM,MAAM,iCAAiC,CAAC;AAC1D,YAAQ,IAAI,cAAAA,QAAM,KAAK,WAAW,SAAS,8BAA8B,OAAO,MAAM,cAAc,CAAC;AACrG,WAAO,EAAE,WAAW;AAAA,EACtB;AAEA,UAAQ,IAAI,cAAAA,QAAM,OAAO,SAAS,WAAW,MAAM;AAAA,CAA+B,CAAC;AACnF,aAAW,QAAQ,YAAY;AAC7B,UAAM,eAAe,KAAK,UAAU,QAAQ,QAAQ,IAAI,IAAI,KAAK,EAAE;AACnE,YAAQ,IAAI,KAAK,cAAAA,QAAM,IAAI,GAAG,CAAC,IAAI,cAAAA,QAAM,KAAK,KAAK,GAAG,CAAC,EAAE;AACzD,YAAQ,IAAI,cAAAA,QAAM,KAAK,kBAAkB,YAAY,IAAI,KAAK,IAAI,EAAE,CAAC;AAAA,EACvE;AAEA,UAAQ,IAAI;AACZ,SAAO,EAAE,WAAW;AACtB;;;AD9DA,SAAS,yBAAyB,OAAuC;AACvE,QAAM,eAAqD,CAAC;AAE5D,aAAW,CAAC,QAAQ,IAAI,KAAK,OAAO,QAAQ,MAAM,YAAY,GAAG;AAC/D,UAAM,UAAU,KAAK,MAAM,YAAY,KAAK,CAAC;AAC7C,UAAM,WAAW,CAAC,GAAG,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK;AACvE,iBAAa,KAAK,EAAE,QAAQ,MAAM,SAAS,CAAC;AAAA,EAC9C;AAEA,MAAI,aAAa,SAAS,EAAG,QAAO;AAEpC,QAAM,YAAY,aAAa,CAAC;AAChC,QAAM,UAAoB,CAAC;AAE3B,WAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC5C,UAAM,UAAU,aAAa,CAAC;AAC9B,UAAM,SAAS,IAAI,IAAI,UAAU,IAAI;AACrC,UAAM,SAAS,IAAI,IAAI,QAAQ,IAAI;AAEnC,UAAM,YAAY,UAAU,KAAK,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;AAC7D,UAAM,YAAY,QAAQ,KAAK,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;AAE3D,QAAI,UAAU,SAAS,GAAG;AACxB,cAAQ;AAAA,QACN,GAAG,UAAU,MAAM,SAAS,UAAU,KAAK,MAAM,CAAC,gBAAgB,QAAQ,MAAM;AAAA,MAClF;AAAA,IACF;AACA,QAAI,UAAU,SAAS,GAAG;AACxB,cAAQ;AAAA,QACN,GAAG,QAAQ,MAAM,SAAS,UAAU,KAAK,MAAM,CAAC,gBAAgB,UAAU,MAAM;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS,CAAC,KAAK;AAAA,IACf;AAAA,EACF;AACF;AAEA,SAAS,wBAAwB,OAAuC;AACtE,MAAI,CAAC,MAAM,SAAU,QAAO;AAE5B,QAAM,UAAU,OAAO,KAAK,MAAM,QAAQ;AAC1C,MAAI,QAAQ,SAAS,EAAG,QAAO;AAE/B,QAAM,UAAoB,CAAC;AAC3B,QAAM,YAAY,QAAQ,CAAC;AAC3B,QAAM,WAAW,MAAM,SAAS,SAAS;AAEzC,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,SAAS,QAAQ,CAAC;AACxB,UAAM,WAAW,MAAM,SAAS,MAAM;AAEtC,eAAW,WAAW,UAAU;AAC9B,YAAM,QAAQ,SAAS,KAAK,CAAC,MAA0C,EAAE,aAAa,QAAQ,QAAQ;AACtG,UAAI,SAAS,MAAM,SAAS,QAAQ,MAAM;AACxC,gBAAQ;AAAA,UACN,IAAI,QAAQ,QAAQ,SAAS,QAAQ,IAAI,QAAQ,SAAS,SAAS,MAAM,IAAI,QAAQ,MAAM;AAAA,QAC7F;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS,CAAC,KAAK;AAAA,IACf;AAAA,EACF;AACF;AAEA,eAAsB,SAAS,UAA2B,CAAC,GAAkB;AAC3E,QAAM,EAAE,KAAK,SAAS,QAAQ,QAAQ,YAAY,IAAI;AAEtD,UAAQ,IAAI,cAAAC,QAAM,KAAK,gCAAgC,CAAC;AAExD,QAAM,UAAU,MAAM,aAAa,EAAE,IAAI,CAAC;AAC1C,QAAM,SAAkB,CAAC;AAGzB,QAAM,SAAS,oBAAI,IAAgC;AAEnD,aAAW,SAAS,SAAS;AAC3B,UAAM,MAAM,OAAO,OAAO,MAAM,YAAY,EAAE,CAAC,KAAK;AACpD,QAAI,CAAC,OAAO,IAAI,GAAG,GAAG;AACpB,aAAO,IAAI,KAAK,CAAC,CAAC;AAAA,IACpB;AACA,WAAO,IAAI,GAAG,EAAG,KAAK,KAAK;AAAA,EAC7B;AAGA,aAAW,CAAC,KAAK,KAAK,KAAK,QAAQ;AACjC,QAAI,MAAM,SAAS,EAAG;AAEtB,UAAM,kBAAkB,MAAM,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE,YAAY,CAAC;AACvE,UAAM,aAAa,CAAC,GAAG,IAAI,IAAI,eAAe,CAAC;AAE/C,QAAI,WAAW,SAAS,GAAG;AACzB,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,SAAS,kCAAkC,GAAG;AAAA,QAC9C,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAGA,MAAI,WAAW,QAAQ,SAAS,GAAG;AACjC,eAAW,SAAS,SAAS;AAC3B,YAAM,UAAU,QAAQ,OAAO,CAAC,MAAM,CAAC,MAAM,aAAa,CAAC,CAAC;AAE5D,UAAI,QAAQ,SAAS,GAAG;AACtB,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,SAAS,oBAAoB,QAAQ,KAAK,IAAI,CAAC;AAAA,UAC/C,SAAS,CAAC,KAAK;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,aAAW,SAAS,SAAS;AAC3B,UAAM,QAAQ,yBAAyB,KAAK;AAC5C,QAAI,MAAO,QAAO,KAAK,KAAK;AAAA,EAC9B;AAGA,MAAI,QAAQ;AACV,eAAW,SAAS,SAAS;AAC3B,YAAM,QAAQ,wBAAwB,KAAK;AAC3C,UAAI,MAAO,QAAO,KAAK,KAAK;AAAA,IAC9B;AAAA,EACF;AAGA,MAAI,cAAc;AAClB,MAAI,aAAa;AACf,UAAM,SAAS,MAAM,OAAO,EAAE,IAAI,CAAC;AACnC,kBAAc,OAAO,WAAW;AAAA,EAClC;AAGA,MAAI,OAAO,WAAW,KAAK,gBAAgB,GAAG;AAC5C,YAAQ,IAAI,cAAAA,QAAM,MAAM,+BAA+B,CAAC;AACxD,YAAQ,IAAI,cAAAA,QAAM,KAAK,WAAW,QAAQ,MAAM,iBAAiB,CAAC;AAClE,QAAI,QAAQ;AACV,cAAQ,IAAI,cAAAA,QAAM,KAAK,uBAAuB,CAAC;AAAA,IACjD;AACA,QAAI,aAAa;AACf,cAAQ,IAAI,cAAAA,QAAM,KAAK,gCAAgC,CAAC;AAAA,IAC1D;AACA;AAAA,EACF;AAEA,UAAQ,IAAI,cAAAA,QAAM,IAAI,SAAS,OAAO,MAAM;AAAA,CAAc,CAAC;AAE3D,aAAW,SAAS,QAAQ;AAC1B,YAAQ,IAAI,KAAK,cAAAA,QAAM,OAAO,MAAM,OAAO,CAAC,EAAE;AAE9C,eAAW,SAAS,MAAM,SAAS;AACjC,YAAM,eAAe,MAAM,KAAK,QAAQ,QAAQ,IAAI,IAAI,KAAK,EAAE;AAC/D,cAAQ,IAAI,cAAAA,QAAM,KAAK,MAAM,YAAY,IAAI,MAAM,IAAI,EAAE,CAAC;AAE1D,iBAAW,CAAC,QAAQ,IAAI,KAAK,OAAO,QAAQ,MAAM,YAAY,GAAG;AAC/D,gBAAQ,IAAI,QAAQ,cAAAA,QAAM,KAAK,MAAM,CAAC,KAAK,IAAI,EAAE;AAAA,MACnD;AAAA,IACF;AAEA,QAAI,MAAM,WAAW,MAAM,QAAQ,SAAS,GAAG;AAC7C,iBAAW,UAAU,MAAM,SAAS;AAClC,gBAAQ,IAAI,cAAAA,QAAM,KAAK,eAAU,MAAM,EAAE,CAAC;AAAA,MAC5C;AAAA,IACF;AAEA,YAAQ,IAAI;AAAA,EACd;AAEA,OAAK,OAAO,SAAS,KAAK,cAAc,MAAM,CAAC,QAAQ,QAAQ;AAC7D,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;AE/MA,IAAAC,gBAAkB;AAelB,eAAsB,SAAS,SAAyC;AACtE,QAAM,EAAE,KAAK,QAAQ,IAAI;AAEzB,UAAQ,IAAI,cAAAC,QAAM,KAAK,uCAAuC,CAAC;AAE/D,QAAM,UAAU,MAAM,aAAa,EAAE,IAAI,CAAC;AAE1C,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,IAAI,cAAAA,QAAM,OAAO,wBAAwB,CAAC;AAClD;AAAA,EACF;AAEA,QAAM,eAAiC,CAAC;AAExC,aAAW,UAAU,SAAS;AAC5B,QAAI,aAAa;AAEjB,eAAW,SAAS,SAAS;AAC3B,UAAI,MAAM,aAAa,MAAM,GAAG;AAC9B;AAAA,MACF;AAAA,IACF;AAEA,UAAM,aAAa,KAAK,MAAO,aAAa,QAAQ,SAAU,GAAG;AAEjE,iBAAa,KAAK;AAAA,MAChB;AAAA,MACA,OAAO,QAAQ;AAAA,MACf;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAGA,UAAQ,IAAI,cAAAA,QAAM,KAAK,yBAAyB,CAAC;AAEjD,QAAM,eAAe,KAAK,IAAI,GAAG,QAAQ,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC;AAEhE,UAAQ;AAAA,IACN,cAAAA,QAAM;AAAA,MACJ,GAAG,SAAS,OAAO,YAAY,CAAC,KAAK,WAAW,SAAS,EAAE,CAAC,KAAK,aAAa,SAAS,EAAE,CAAC;AAAA,IAC5F;AAAA,EACF;AACA,UAAQ,IAAI,cAAAA,QAAM,KAAK,SAAI,OAAO,eAAe,EAAE,CAAC,CAAC;AAErD,aAAW,QAAQ,cAAc;AAC/B,UAAM,QACJ,KAAK,eAAe,MAAM,cAAAA,QAAM,QAChC,KAAK,cAAc,KAAK,cAAAA,QAAM,SAAS,cAAAA,QAAM;AAE/C,UAAM,MAAM,kBAAkB,KAAK,YAAY,EAAE;AACjD,UAAM,aAAa,GAAG,KAAK,UAAU,IAAI,SAAS,CAAC;AAEnD,YAAQ;AAAA,MACN,GAAG,KAAK,OAAO,OAAO,YAAY,CAAC,KAAK,MAAM,GAAG,CAAC,IAAI,MAAM,UAAU,CAAC,KAAK,cAAAA,QAAM,KAAK,GAAG,KAAK,UAAU,IAAI,KAAK,KAAK,EAAE,CAAC;AAAA,IAC5H;AAAA,EACF;AAEA,UAAQ,IAAI;AAGZ,QAAM,eAAe,aAAa,OAAO,CAAC,MAAM,EAAE,eAAe,GAAG,EAAE;AACtE,QAAM,mBAAmB,aAAa,OAAO,CAAC,MAAM,EAAE,aAAa,KAAK,EAAE,aAAa,GAAG,EAAE;AAC5F,QAAM,aAAa,aAAa,OAAO,CAAC,MAAM,EAAE,eAAe,CAAC,EAAE;AAElE,MAAI,iBAAiB,QAAQ,QAAQ;AACnC,YAAQ,IAAI,cAAAA,QAAM,MAAM,mCAAmC,CAAC;AAAA,EAC9D,OAAO;AACL,YAAQ,IAAI,cAAAA,QAAM,KAAK,SAAS,YAAY,cAAc,gBAAgB,YAAY,UAAU,EAAE,CAAC;AAAA,EACrG;AACF;AAEA,SAAS,kBAAkB,YAAoB,OAAuB;AACpE,QAAM,SAAS,KAAK,MAAO,aAAa,MAAO,KAAK;AACpD,QAAM,QAAQ,QAAQ;AAEtB,SAAO,SAAI,OAAO,MAAM,IAAI,SAAI,OAAO,KAAK;AAC9C;;;AC5FA,IAAAC,MAAoB;AACpB,WAAsB;AACtB,IAAAC,gBAAkB;AAQlB,IAAMC,mBAAkB,CAAC,SAAS,QAAQ,QAAQ,QAAQ,SAAS,QAAQ;AAE3E,eAAsB,QAAQ,UAA0B,CAAC,GAAkB;AACzE,QAAM,EAAE,KAAK,SAAS,gBAAgB,IAAI;AAE1C,UAAQ,IAAI,cAAAC,QAAM,KAAK,oCAAoC,CAAC;AAE5D,QAAM,cAAc,MAAM,6BAA6B,EAAE,IAAI,CAAC;AAG9D,QAAM,UAAU,oBAAI,IAAY;AAEhC,aAAW,SAAS,aAAa;AAC/B,eAAW,OAAO,MAAM,MAAM;AAC5B,YAAM,UAAU,MAAM,cAAc,YAAY,MAAM,GAAG,MAAM,SAAS,IAAI,GAAG;AAC/E,cAAQ,IAAI,OAAO;AAGnB,iBAAW,UAAUD,kBAAiB;AACpC,YAAI,IAAI,SAAS,MAAM,GAAG;AACxB,gBAAM,UAAU,IAAI,MAAM,GAAG,CAAC,OAAO,MAAM;AAC3C,gBAAM,cAAc,MAAM,cAAc,YAAY,UAAU,GAAG,MAAM,SAAS,IAAI,OAAO;AAC3F,kBAAQ,IAAI,WAAW;AAAA,QACzB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,SAAS,GAAG;AACtB,YAAQ,IAAI,cAAAC,QAAM,OAAO,2EAA2E,CAAC;AACrG;AAAA,EACF;AAEA,QAAM,aAAa,CAAC,GAAG,OAAO,EAAE,KAAK;AAGrC,QAAM,WAAW,WAAW,IAAI,OAAK,UAAU,CAAC,GAAG,EAAE,KAAK,IAAI;AAE9D,QAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhB,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeR,QAAM,aAAkB,aAAQ,OAAO,QAAQ,IAAI,GAAG,MAAM;AAC5D,QAAM,YAAiB,aAAQ,UAAU;AAEzC,MAAI,CAAI,eAAW,SAAS,GAAG;AAC7B,IAAG,cAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,EAC7C;AAEA,EAAG,kBAAc,YAAY,SAAS,OAAO;AAE7C,UAAQ,IAAI,cAAAA,QAAM,MAAM,aAAa,WAAW,MAAM,wBAAwB,CAAC;AAC/E,UAAQ,IAAI,cAAAA,QAAM,KAAK,WAAW,UAAU;AAAA,CAAI,CAAC;AAGjD,QAAM,SAAS,WAAW,MAAM,GAAG,CAAC;AACpC,aAAW,OAAO,QAAQ;AACxB,YAAQ,IAAI,KAAK,cAAAA,QAAM,KAAK,GAAG,CAAC,EAAE;AAAA,EACpC;AACA,MAAI,WAAW,SAAS,GAAG;AACzB,YAAQ,IAAI,cAAAA,QAAM,KAAK,aAAa,WAAW,SAAS,CAAC,OAAO,CAAC;AAAA,EACnE;AACF;;;AC1FA,IAAAC,gBAAkB;AAClB,IAAAC,MAAoB;AACpB,IAAAC,QAAsB;AAStB,eAAsB,QAAQ,UAA0B,CAAC,GAAkB;AACzE,QAAM,EAAE,KAAK,SAAS,gBAAgB,SAAS,OAAO,IAAI;AAE1D,UAAQ,IAAI,cAAAC,QAAM,KAAK,uCAAuC,CAAC;AAE/D,QAAM,UAAU,MAAM,aAAa,EAAE,IAAI,CAAC;AAE1C,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,IAAI,cAAAA,QAAM,OAAO,wBAAwB,CAAC;AAClD;AAAA,EACF;AAGA,QAAM,WAAmD,CAAC;AAC1D,QAAM,WAAW,OAAO,QAAQ,IAAI;AAEpC,aAAW,SAAS,SAAS;AAC3B,eAAW,CAAC,QAAQ,IAAI,KAAK,OAAO,QAAQ,MAAM,YAAY,GAAG;AAC/D,UAAI,CAAC,SAAS,MAAM,EAAG,UAAS,MAAM,IAAI,CAAC;AAE3C,YAAM,eAAe,MAAM,KAAK,QAAQ,WAAW,KAAK,EAAE;AAC1D,YAAM,MAAM,GAAG,YAAY,IAAI,MAAM,IAAI;AACzC,eAAS,MAAM,EAAE,GAAG,IAAI;AAAA,IAC1B;AAAA,EACF;AAGA,QAAM,YAAiB,cAAQ,UAAU,MAAM;AAC/C,MAAI,CAAI,eAAW,SAAS,GAAG;AAC7B,IAAG,cAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,EAC7C;AAEA,QAAM,UAAU,OAAO,KAAK,QAAQ,EAAE,KAAK;AAC3C,aAAW,UAAU,SAAS;AAC5B,UAAM,eAAe,SAAS,MAAM;AACpC,QAAI;AAEJ,QAAI,WAAW,UAAU;AACvB,YAAM,SAAS,kBAAkB,YAAY;AAC7C,gBAAU,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI;AAAA,IAC9C,OAAO;AACL,gBAAU,KAAK,UAAU,cAAc,MAAM,CAAC,IAAI;AAAA,IACpD;AAEA,UAAM,WAAgB,WAAK,WAAW,GAAG,MAAM,OAAO;AACtD,IAAG,kBAAc,UAAU,OAAO;AAClC,YAAQ;AAAA,MACN,cAAAA,QAAM,MAAM,KAAK,MAAM,OAAO,IAC9B,cAAAA,QAAM,KAAK,KAAK,OAAO,KAAK,YAAY,EAAE,MAAM,QAAQ;AAAA,IAC1D;AAAA,EACF;AAEA,UAAQ,IAAI,cAAAA,QAAM,KAAK;AAAA,YAAe,QAAQ,MAAM,sBAAsB,MAAM,GAAG,CAAC;AACtF;AAKA,SAAS,kBAAkB,MAAuD;AAChF,QAAM,SAAkC,CAAC;AAEzC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC/C,UAAM,QAAQ,IAAI,MAAM,GAAG;AAC3B,QAAI,UAAmC;AAEvC,aAAS,IAAI,GAAG,IAAI,MAAM,SAAS,GAAG,KAAK;AACzC,YAAM,OAAO,MAAM,CAAC;AACpB,UAAI,CAAC,QAAQ,IAAI,KAAK,OAAO,QAAQ,IAAI,MAAM,UAAU;AACvD,gBAAQ,IAAI,IAAI,CAAC;AAAA,MACnB;AACA,gBAAU,QAAQ,IAAI;AAAA,IACxB;AAEA,YAAQ,MAAM,MAAM,SAAS,CAAC,CAAE,IAAI;AAAA,EACtC;AAEA,SAAO;AACT;","names":["traverse","fg","chalk","import_chalk","import_chalk","chalk","chalk","import_chalk","chalk","fs","import_chalk","PLURAL_SUFFIXES","chalk","import_chalk","fs","path","chalk"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/parser.ts","../src/commands/find.ts","../src/commands/validate.ts","../src/commands/unused.ts","../src/commands/coverage.ts","../src/commands/typegen.ts","../src/commands/extract.ts","../src/commands/diff.ts","../src/commands/stats.ts"],"sourcesContent":["export {\n parseProject,\n parseDictionaryKeys,\n parseTCalls,\n extractProjectDictionaryKeys,\n extractProjectTCalls,\n type TranslationEntry,\n type DictionaryKeyEntry,\n type TCallEntry,\n} from './parser'\nexport { find } from './commands/find'\nexport { validate } from './commands/validate'\nexport { coverage } from './commands/coverage'\nexport { unused } from './commands/unused'\nexport { typegen } from './commands/typegen'\nexport { extract } from './commands/extract'\nexport { diff } from './commands/diff'\nexport { stats } from './commands/stats'\n","import { parse } from '@babel/parser'\nimport traverse from '@babel/traverse'\nimport * as fs from 'fs'\nimport fg from 'fast-glob'\n\n// v0.8.0: Dictionary key and t() call extraction\n\nexport interface DictionaryKeyEntry {\n file: string\n line: number\n namespace: string\n keys: string[]\n}\n\nexport interface TCallEntry {\n file: string\n line: number\n key: string\n}\n\nexport interface ICUTypeInfo {\n variable: string\n type: string\n}\n\nexport interface TranslationEntry {\n file: string\n line: number\n column: number\n translations: Record<string, string>\n variables: string[]\n /** ICU type information per locale (v0.7.0) */\n icuTypes?: Record<string, ICUTypeInfo[]>\n}\n\ninterface ParseOptions {\n cwd?: string\n include?: string[]\n exclude?: string[]\n}\n\nconst IT_FUNCTION_NAMES = [\n 'it',\n 'it_ja', 'it_zh', 'it_es', 'it_fr', 'it_de',\n 'en_ja', 'en_zh', 'en_es', 'en_fr', 'en_de',\n 'ja_zh', 'ja_es', 'zh_es',\n]\n\nconst PAIR_MAPPING: Record<string, [string, string]> = {\n it: ['ko', 'en'],\n it_ja: ['ko', 'ja'],\n it_zh: ['ko', 'zh'],\n it_es: ['ko', 'es'],\n it_fr: ['ko', 'fr'],\n it_de: ['ko', 'de'],\n en_ja: ['en', 'ja'],\n en_zh: ['en', 'zh'],\n en_es: ['en', 'es'],\n en_fr: ['en', 'fr'],\n en_de: ['en', 'de'],\n ja_zh: ['ja', 'zh'],\n ja_es: ['ja', 'es'],\n zh_es: ['zh', 'es'],\n}\n\nfunction extractVariables(text: string): string[] {\n const matches = text.match(/\\{(\\w+)\\}/g)\n if (!matches) return []\n return matches.map((m) => m.slice(1, -1))\n}\n\nconst ICU_TYPE_PATTERN = /\\{(\\w+),\\s*(\\w+)/g\n\nfunction extractICUTypes(text: string): ICUTypeInfo[] {\n const types: ICUTypeInfo[] = []\n let match: RegExpExecArray | null\n ICU_TYPE_PATTERN.lastIndex = 0\n while ((match = ICU_TYPE_PATTERN.exec(text)) !== null) {\n types.push({ variable: match[1]!, type: match[2]! })\n }\n return types\n}\n\nfunction parseFile(filePath: string): TranslationEntry[] {\n const entries: TranslationEntry[] = []\n const code = fs.readFileSync(filePath, 'utf-8')\n\n let ast\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n })\n } catch {\n return []\n }\n\n traverse(ast, {\n CallExpression(nodePath) {\n const { node } = nodePath\n const { callee } = node\n\n if (callee.type !== 'Identifier') return\n if (!IT_FUNCTION_NAMES.includes(callee.name)) return\n\n const funcName = callee.name\n const args = node.arguments\n const loc = node.loc\n\n if (!loc) return\n\n const entry: TranslationEntry = {\n file: filePath,\n line: loc.start.line,\n column: loc.start.column,\n translations: {},\n variables: [],\n }\n\n if (args[0]?.type === 'ObjectExpression') {\n const obj = args[0]\n for (const prop of obj.properties) {\n if (\n prop.type === 'ObjectProperty' &&\n prop.key.type === 'Identifier' &&\n prop.value.type === 'StringLiteral'\n ) {\n entry.translations[prop.key.name] = prop.value.value\n entry.variables.push(...extractVariables(prop.value.value))\n // Extract ICU type info (v0.7.0)\n const types = extractICUTypes(prop.value.value)\n if (types.length > 0) {\n if (!entry.icuTypes) entry.icuTypes = {}\n entry.icuTypes[prop.key.name] = types\n }\n }\n }\n } else if (\n args[0]?.type === 'StringLiteral' &&\n args[1]?.type === 'StringLiteral'\n ) {\n const [lang1, lang2] = PAIR_MAPPING[funcName] || ['ko', 'en']\n entry.translations[lang1] = args[0].value\n entry.translations[lang2] = args[1].value\n entry.variables.push(...extractVariables(args[0].value))\n entry.variables.push(...extractVariables(args[1].value))\n // Extract ICU type info (v0.7.0)\n const types1 = extractICUTypes(args[0].value)\n if (types1.length > 0) {\n if (!entry.icuTypes) entry.icuTypes = {}\n entry.icuTypes[lang1] = types1\n }\n const types2 = extractICUTypes(args[1].value)\n if (types2.length > 0) {\n if (!entry.icuTypes) entry.icuTypes = {}\n entry.icuTypes[lang2] = types2\n }\n }\n\n entry.variables = [...new Set(entry.variables)]\n\n if (Object.keys(entry.translations).length > 0) {\n entries.push(entry)\n }\n },\n })\n\n return entries\n}\n\n// v0.8.0: Flatten nested ObjectExpression to dot-notation keys\nfunction flattenObjectKeys(\n node: { type: string; properties?: unknown[] },\n prefix: string = '',\n): string[] {\n const keys: string[] = []\n if (node.type !== 'ObjectExpression' || !node.properties) return keys\n\n for (const prop of node.properties as Array<{\n type: string\n key: { type: string; name?: string; value?: string }\n value: { type: string; properties?: unknown[] }\n }>) {\n if (prop.type !== 'ObjectProperty') continue\n\n let propName: string | undefined\n if (prop.key.type === 'Identifier') propName = prop.key.name\n else if (prop.key.type === 'StringLiteral') propName = prop.key.value\n\n if (!propName) continue\n\n const fullKey = prefix ? `${prefix}.${propName}` : propName\n\n if (prop.value.type === 'StringLiteral') {\n keys.push(fullKey)\n } else if (prop.value.type === 'ObjectExpression') {\n keys.push(...flattenObjectKeys(prop.value, fullKey))\n }\n }\n return keys\n}\n\n// v0.8.0: Extract dictionary keys from loadDictionaries() calls\nexport function parseDictionaryKeys(filePath: string): DictionaryKeyEntry[] {\n const entries: DictionaryKeyEntry[] = []\n const code = fs.readFileSync(filePath, 'utf-8')\n\n let ast\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n })\n } catch {\n return []\n }\n\n traverse(ast, {\n CallExpression(nodePath) {\n const { node } = nodePath\n const { callee } = node\n\n if (callee.type !== 'Identifier' || callee.name !== 'loadDictionaries') return\n\n const args = node.arguments\n const loc = node.loc\n if (!loc || !args[0] || args[0].type !== 'ObjectExpression') return\n\n // Second argument is optional namespace\n let namespace = 'default'\n if (args[1]?.type === 'StringLiteral') {\n namespace = args[1].value\n }\n\n // First argument: { locale: { key: value } }\n // Collect keys from the first locale's dict (all locales should have same keys)\n const dictObj = args[0]\n const allKeys = new Set<string>()\n\n for (const localeProp of dictObj.properties as Array<{\n type: string\n value: { type: string; properties?: unknown[] }\n }>) {\n if (localeProp.type !== 'ObjectProperty') continue\n if (localeProp.value.type !== 'ObjectExpression') continue\n\n const localeKeys = flattenObjectKeys(localeProp.value)\n for (const key of localeKeys) {\n allKeys.add(key)\n }\n }\n\n if (allKeys.size > 0) {\n entries.push({\n file: filePath,\n line: loc.start.line,\n namespace,\n keys: [...allKeys],\n })\n }\n },\n })\n\n return entries\n}\n\n// v0.8.0: Extract t() call sites\nexport function parseTCalls(filePath: string): TCallEntry[] {\n const entries: TCallEntry[] = []\n const code = fs.readFileSync(filePath, 'utf-8')\n\n let ast\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n })\n } catch {\n return []\n }\n\n traverse(ast, {\n CallExpression(nodePath) {\n const { node } = nodePath\n const { callee } = node\n\n if (callee.type !== 'Identifier' || callee.name !== 't') return\n\n const args = node.arguments\n const loc = node.loc\n if (!loc || !args[0] || args[0].type !== 'StringLiteral') return\n\n entries.push({\n file: filePath,\n line: loc.start.line,\n key: args[0].value,\n })\n },\n })\n\n return entries\n}\n\nexport async function extractProjectDictionaryKeys(options: ParseOptions = {}): Promise<DictionaryKeyEntry[]> {\n const {\n cwd = process.cwd(),\n include = ['**/*.{ts,tsx,js,jsx}'],\n exclude = ['**/node_modules/**', '**/dist/**', '**/.next/**'],\n } = options\n\n const files = await fg(include, { cwd, ignore: exclude, absolute: true })\n const allEntries: DictionaryKeyEntry[] = []\n\n for (const file of files) {\n allEntries.push(...parseDictionaryKeys(file))\n }\n\n return allEntries\n}\n\nexport async function extractProjectTCalls(options: ParseOptions = {}): Promise<TCallEntry[]> {\n const {\n cwd = process.cwd(),\n include = ['**/*.{ts,tsx,js,jsx}'],\n exclude = ['**/node_modules/**', '**/dist/**', '**/.next/**'],\n } = options\n\n const files = await fg(include, { cwd, ignore: exclude, absolute: true })\n const allEntries: TCallEntry[] = []\n\n for (const file of files) {\n allEntries.push(...parseTCalls(file))\n }\n\n return allEntries\n}\n\nexport async function parseProject(options: ParseOptions = {}): Promise<TranslationEntry[]> {\n const {\n cwd = process.cwd(),\n include = ['**/*.{ts,tsx,js,jsx}'],\n exclude = ['**/node_modules/**', '**/dist/**', '**/.next/**'],\n } = options\n\n const files = await fg(include, {\n cwd,\n ignore: exclude,\n absolute: true,\n })\n\n const allEntries: TranslationEntry[] = []\n\n for (const file of files) {\n const entries = parseFile(file)\n allEntries.push(...entries)\n }\n\n return allEntries\n}\n","import chalk from 'chalk'\nimport { parseProject, type TranslationEntry } from '../parser'\n\ninterface FindOptions {\n query: string\n cwd?: string\n}\n\nexport async function find(options: FindOptions): Promise<void> {\n const { query, cwd } = options\n\n console.log(chalk.blue(`\\nSearching for: \"${query}\"\\n`))\n\n const entries = await parseProject({ cwd })\n const results: TranslationEntry[] = []\n\n const lowerQuery = query.toLowerCase()\n\n for (const entry of entries) {\n const values = Object.values(entry.translations)\n const matches = values.some((v) => v.toLowerCase().includes(lowerQuery))\n\n if (matches) {\n results.push(entry)\n }\n }\n\n if (results.length === 0) {\n console.log(chalk.yellow('No results found.'))\n return\n }\n\n console.log(chalk.green(`Found ${results.length} occurrence(s):\\n`))\n\n for (const result of results) {\n const relativePath = result.file.replace(process.cwd() + '/', '')\n console.log(chalk.gray(`${relativePath}:${result.line}:${result.column}`))\n\n for (const [locale, text] of Object.entries(result.translations)) {\n const highlighted = text.replace(\n new RegExp(`(${query})`, 'gi'),\n chalk.yellow('$1')\n )\n console.log(` ${chalk.cyan(locale)}: ${highlighted}`)\n }\n console.log()\n }\n}\n","import chalk from 'chalk'\nimport { parseProject, type TranslationEntry } from '../parser'\nimport { unused } from './unused'\n\ninterface ValidateOptions {\n cwd?: string\n locales?: string[]\n strict?: boolean\n unused?: boolean\n noExit?: boolean\n}\n\ninterface Issue {\n type: 'inconsistent' | 'missing' | 'variable_mismatch' | 'icu_type_mismatch'\n message: string\n entries: TranslationEntry[]\n details?: string[]\n}\n\nfunction checkVariableConsistency(entry: TranslationEntry): Issue | null {\n const varsByLocale: { locale: string; vars: string[] }[] = []\n\n for (const [locale, text] of Object.entries(entry.translations)) {\n const matches = text.match(/\\{(\\w+)\\}/g) || []\n const varNames = [...new Set(matches.map((v) => v.slice(1, -1)))].sort()\n varsByLocale.push({ locale, vars: varNames })\n }\n\n if (varsByLocale.length < 2) return null\n\n const reference = varsByLocale[0]!\n const details: string[] = []\n\n for (let i = 1; i < varsByLocale.length; i++) {\n const current = varsByLocale[i]!\n const refSet = new Set(reference.vars)\n const curSet = new Set(current.vars)\n\n const onlyInRef = reference.vars.filter((v) => !curSet.has(v))\n const onlyInCur = current.vars.filter((v) => !refSet.has(v))\n\n if (onlyInRef.length > 0) {\n details.push(\n `${reference.locale} has {${onlyInRef.join('}, {')}} missing in ${current.locale}`,\n )\n }\n if (onlyInCur.length > 0) {\n details.push(\n `${current.locale} has {${onlyInCur.join('}, {')}} missing in ${reference.locale}`,\n )\n }\n }\n\n if (details.length === 0) return null\n\n return {\n type: 'variable_mismatch',\n message: 'Variable mismatch between translations',\n entries: [entry],\n details,\n }\n}\n\nfunction checkICUTypeConsistency(entry: TranslationEntry): Issue | null {\n if (!entry.icuTypes) return null\n\n const locales = Object.keys(entry.icuTypes)\n if (locales.length < 2) return null\n\n const details: string[] = []\n const reference = locales[0]!\n const refTypes = entry.icuTypes[reference]!\n\n for (let i = 1; i < locales.length; i++) {\n const locale = locales[i]!\n const curTypes = entry.icuTypes[locale]!\n\n for (const refType of refTypes) {\n const match = curTypes.find((t: { variable: string; type: string }) => t.variable === refType.variable)\n if (match && match.type !== refType.type) {\n details.push(\n `{${refType.variable}} is \"${refType.type}\" in ${reference} but \"${match.type}\" in ${locale}`,\n )\n }\n }\n }\n\n if (details.length === 0) return null\n\n return {\n type: 'icu_type_mismatch',\n message: 'ICU type mismatch between translations',\n entries: [entry],\n details,\n }\n}\n\nexport async function validate(options: ValidateOptions = {}): Promise<void> {\n const { cwd, locales, strict, unused: checkUnused } = options\n\n console.log(chalk.blue('\\nValidating translations...\\n'))\n\n const entries = await parseProject({ cwd })\n const issues: Issue[] = []\n\n // group by first language text (usually ko)\n const groups = new Map<string, TranslationEntry[]>()\n\n for (const entry of entries) {\n const key = Object.values(entry.translations)[0] || ''\n if (!groups.has(key)) {\n groups.set(key, [])\n }\n groups.get(key)!.push(entry)\n }\n\n // check for inconsistent translations\n for (const [key, group] of groups) {\n if (group.length < 2) continue\n\n const translationSets = group.map((e) => JSON.stringify(e.translations))\n const uniqueSets = [...new Set(translationSets)]\n\n if (uniqueSets.length > 1) {\n issues.push({\n type: 'inconsistent',\n message: `Inconsistent translations for \"${key}\"`,\n entries: group,\n })\n }\n }\n\n // check for missing locales\n if (locales && locales.length > 0) {\n for (const entry of entries) {\n const missing = locales.filter((l) => !entry.translations[l])\n\n if (missing.length > 0) {\n issues.push({\n type: 'missing',\n message: `Missing locales: ${missing.join(', ')}`,\n entries: [entry],\n })\n }\n }\n }\n\n // check for variable name consistency (enhanced in v0.7.0)\n for (const entry of entries) {\n const issue = checkVariableConsistency(entry)\n if (issue) issues.push(issue)\n }\n\n // check for ICU type consistency (strict mode, v0.7.0)\n if (strict) {\n for (const entry of entries) {\n const issue = checkICUTypeConsistency(entry)\n if (issue) issues.push(issue)\n }\n }\n\n // unused key detection (v0.8.0)\n let unusedCount = 0\n if (checkUnused) {\n const result = await unused({ cwd })\n unusedCount = result.unusedKeys.length\n }\n\n // print results\n if (issues.length === 0 && unusedCount === 0) {\n console.log(chalk.green('All translations are valid!\\n'))\n console.log(chalk.gray(`Checked ${entries.length} translation(s)`))\n if (strict) {\n console.log(chalk.gray('(strict mode enabled)'))\n }\n if (checkUnused) {\n console.log(chalk.gray('(unused key detection enabled)'))\n }\n return\n }\n\n console.log(chalk.red(`Found ${issues.length} issue(s):\\n`))\n\n for (const issue of issues) {\n console.log(` ${chalk.yellow(issue.message)}`)\n\n for (const entry of issue.entries) {\n const relativePath = entry.file.replace(process.cwd() + '/', '')\n console.log(chalk.gray(` ${relativePath}:${entry.line}`))\n\n for (const [locale, text] of Object.entries(entry.translations)) {\n console.log(` ${chalk.cyan(locale)}: ${text}`)\n }\n }\n\n if (issue.details && issue.details.length > 0) {\n for (const detail of issue.details) {\n console.log(chalk.gray(` → ${detail}`))\n }\n }\n\n console.log()\n }\n\n if ((issues.length > 0 || unusedCount > 0) && !options.noExit) {\n process.exit(1)\n }\n}\n","import chalk from 'chalk'\nimport { extractProjectDictionaryKeys, extractProjectTCalls } from '../parser'\n\ninterface UnusedKey {\n namespace: string\n key: string\n definedIn: string\n line: number\n}\n\nconst PLURAL_SUFFIXES = ['_zero', '_one', '_two', '_few', '_many', '_other']\n\nexport async function unused(options: { cwd?: string } = {}): Promise<{ unusedKeys: UnusedKey[] }> {\n const { cwd } = options\n\n console.log(chalk.blue('\\nDetecting unused translations...\\n'))\n\n const dictEntries = await extractProjectDictionaryKeys({ cwd })\n const tCalls = await extractProjectTCalls({ cwd })\n\n // Build set of used keys (normalized: namespace:key or key for default)\n const usedKeys = new Set<string>()\n for (const call of tCalls) {\n usedKeys.add(call.key)\n // Also add with default namespace if no namespace prefix\n if (!call.key.includes(':')) {\n usedKeys.add(call.key)\n }\n }\n\n // Check each dictionary key against used keys\n const unusedKeys: UnusedKey[] = []\n\n for (const entry of dictEntries) {\n for (const key of entry.keys) {\n const fullKey = entry.namespace === 'default' ? key : `${entry.namespace}:${key}`\n\n // Check if key is directly used\n if (usedKeys.has(fullKey)) continue\n\n // Check if this is a plural suffix variant (e.g. count_one, count_other)\n // and the base key is used via t('items.count', { count: N })\n let isPluralVariant = false\n for (const suffix of PLURAL_SUFFIXES) {\n if (key.endsWith(suffix)) {\n const baseKey = key.slice(0, -suffix.length)\n const fullBaseKey = entry.namespace === 'default' ? baseKey : `${entry.namespace}:${baseKey}`\n if (usedKeys.has(fullBaseKey)) {\n isPluralVariant = true\n break\n }\n }\n }\n if (isPluralVariant) continue\n\n unusedKeys.push({\n namespace: entry.namespace,\n key: fullKey,\n definedIn: entry.file,\n line: entry.line,\n })\n }\n }\n\n // Report results\n if (unusedKeys.length === 0) {\n const totalKeys = dictEntries.reduce((sum, e) => sum + e.keys.length, 0)\n console.log(chalk.green('No unused translations found!\\n'))\n console.log(chalk.gray(`Checked ${totalKeys} dictionary key(s) against ${tCalls.length} t() call(s)`))\n return { unusedKeys }\n }\n\n console.log(chalk.yellow(`Found ${unusedKeys.length} unused translation key(s):\\n`))\n for (const item of unusedKeys) {\n const relativePath = item.definedIn.replace(process.cwd() + '/', '')\n console.log(` ${chalk.red('-')} ${chalk.cyan(item.key)}`)\n console.log(chalk.gray(` defined in ${relativePath}:${item.line}`))\n }\n\n console.log()\n return { unusedKeys }\n}\n","import chalk from 'chalk'\nimport { parseProject } from '../parser'\n\ninterface CoverageOptions {\n cwd?: string\n locales: string[]\n}\n\ninterface LocaleCoverage {\n locale: string\n total: number\n translated: number\n percentage: number\n}\n\nexport async function coverage(options: CoverageOptions): Promise<void> {\n const { cwd, locales } = options\n\n console.log(chalk.blue('\\nAnalyzing translation coverage...\\n'))\n\n const entries = await parseProject({ cwd })\n\n if (entries.length === 0) {\n console.log(chalk.yellow('No translations found.'))\n return\n }\n\n const coverageData: LocaleCoverage[] = []\n\n for (const locale of locales) {\n let translated = 0\n\n for (const entry of entries) {\n if (entry.translations[locale]) {\n translated++\n }\n }\n\n const percentage = Math.round((translated / entries.length) * 100)\n\n coverageData.push({\n locale,\n total: entries.length,\n translated,\n percentage,\n })\n }\n\n // print coverage table\n console.log(chalk.bold('Translation Coverage:\\n'))\n\n const maxLocaleLen = Math.max(...locales.map((l) => l.length), 6)\n\n console.log(\n chalk.gray(\n `${'Locale'.padEnd(maxLocaleLen)} ${'Coverage'.padStart(10)} ${'Translated'.padStart(12)}`\n )\n )\n console.log(chalk.gray('─'.repeat(maxLocaleLen + 26)))\n\n for (const data of coverageData) {\n const color =\n data.percentage === 100 ? chalk.green :\n data.percentage >= 80 ? chalk.yellow : chalk.red\n\n const bar = createProgressBar(data.percentage, 10)\n const percentStr = `${data.percentage}%`.padStart(4)\n\n console.log(\n `${data.locale.padEnd(maxLocaleLen)} ${color(bar)} ${color(percentStr)} ${chalk.gray(`${data.translated}/${data.total}`)}`\n )\n }\n\n console.log()\n\n // summary\n const fullyCovered = coverageData.filter((d) => d.percentage === 100).length\n const partiallyCovered = coverageData.filter((d) => d.percentage > 0 && d.percentage < 100).length\n const notCovered = coverageData.filter((d) => d.percentage === 0).length\n\n if (fullyCovered === locales.length) {\n console.log(chalk.green('All locales are fully translated!'))\n } else {\n console.log(chalk.gray(`Full: ${fullyCovered}, Partial: ${partiallyCovered}, Empty: ${notCovered}`))\n }\n}\n\nfunction createProgressBar(percentage: number, width: number): string {\n const filled = Math.round((percentage / 100) * width)\n const empty = width - filled\n\n return '█'.repeat(filled) + '░'.repeat(empty)\n}\n","import * as fs from 'fs'\nimport * as path from 'path'\nimport chalk from 'chalk'\nimport { extractProjectDictionaryKeys } from '../parser'\n\ninterface TypegenOptions {\n cwd?: string\n output?: string\n}\n\nconst PLURAL_SUFFIXES = ['_zero', '_one', '_two', '_few', '_many', '_other']\n\nexport async function typegen(options: TypegenOptions = {}): Promise<void> {\n const { cwd, output = 'src/i18n.d.ts' } = options\n\n console.log(chalk.blue('\\nGenerating TypeScript types...\\n'))\n\n const dictEntries = await extractProjectDictionaryKeys({ cwd })\n\n // Collect all unique full keys (namespace:key or key)\n const allKeys = new Set<string>()\n\n for (const entry of dictEntries) {\n for (const key of entry.keys) {\n const fullKey = entry.namespace === 'default' ? key : `${entry.namespace}:${key}`\n allKeys.add(fullKey)\n\n // Also add plural base keys (strip _one, _other, etc.)\n for (const suffix of PLURAL_SUFFIXES) {\n if (key.endsWith(suffix)) {\n const baseKey = key.slice(0, -suffix.length)\n const fullBaseKey = entry.namespace === 'default' ? baseKey : `${entry.namespace}:${baseKey}`\n allKeys.add(fullBaseKey)\n }\n }\n }\n }\n\n if (allKeys.size === 0) {\n console.log(chalk.yellow('No dictionary keys found. Make sure loadDictionaries() calls are present.'))\n return\n }\n\n const sortedKeys = [...allKeys].sort()\n\n // Generate the .d.ts content\n const keyUnion = sortedKeys.map(k => ` | '${k}'`).join('\\n')\n\n const content = `// Auto-generated by inline-i18n typegen\n// Do not edit manually. Re-run: npx inline-i18n typegen\n\nimport 'inline-i18n-multi'\n\ndeclare module 'inline-i18n-multi' {\n export type TranslationKey =\n${keyUnion}\n\n export function t(\n key: TranslationKey,\n vars?: TranslationVars,\n locale?: string\n ): string\n\n export function hasTranslation(\n key: TranslationKey,\n locale?: string\n ): boolean\n}\n`\n\n const outputPath = path.resolve(cwd || process.cwd(), output)\n const outputDir = path.dirname(outputPath)\n\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true })\n }\n\n fs.writeFileSync(outputPath, content, 'utf-8')\n\n console.log(chalk.green(`Generated ${sortedKeys.length} translation key types`))\n console.log(chalk.gray(`Output: ${outputPath}\\n`))\n\n // Show sample\n const sample = sortedKeys.slice(0, 5)\n for (const key of sample) {\n console.log(` ${chalk.cyan(key)}`)\n }\n if (sortedKeys.length > 5) {\n console.log(chalk.gray(` ... and ${sortedKeys.length - 5} more`))\n }\n}\n","import chalk from 'chalk'\nimport * as fs from 'fs'\nimport * as path from 'path'\nimport { parseProject } from '../parser'\n\ninterface ExtractOptions {\n cwd?: string\n output?: string\n format?: 'flat' | 'nested'\n}\n\nexport async function extract(options: ExtractOptions = {}): Promise<void> {\n const { cwd, output = 'translations', format = 'flat' } = options\n\n console.log(chalk.blue('\\nExtracting inline translations...\\n'))\n\n const entries = await parseProject({ cwd })\n\n if (entries.length === 0) {\n console.log(chalk.yellow('No translations found.'))\n return\n }\n\n // Group translations by locale\n const byLocale: Record<string, Record<string, string>> = {}\n const basePath = cwd || process.cwd()\n\n for (const entry of entries) {\n for (const [locale, text] of Object.entries(entry.translations)) {\n if (!byLocale[locale]) byLocale[locale] = {}\n\n const relativePath = entry.file.replace(basePath + '/', '')\n const key = `${relativePath}:${entry.line}`\n byLocale[locale][key] = text\n }\n }\n\n // Write output files\n const outputDir = path.resolve(basePath, output)\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true })\n }\n\n const locales = Object.keys(byLocale).sort()\n for (const locale of locales) {\n const translations = byLocale[locale]!\n let content: string\n\n if (format === 'nested') {\n const nested = buildNestedObject(translations)\n content = JSON.stringify(nested, null, 2) + '\\n'\n } else {\n content = JSON.stringify(translations, null, 2) + '\\n'\n }\n\n const filePath = path.join(outputDir, `${locale}.json`)\n fs.writeFileSync(filePath, content)\n console.log(\n chalk.green(` ${locale}.json`) +\n chalk.gray(` (${Object.keys(translations).length} keys)`)\n )\n }\n\n console.log(chalk.gray(`\\nExtracted ${entries.length} translation(s) to ${output}/`))\n}\n\n/**\n * Build a nested object from flat dot-notation keys\n */\nfunction buildNestedObject(flat: Record<string, string>): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n\n for (const [key, value] of Object.entries(flat)) {\n const parts = key.split('.')\n let current: Record<string, unknown> = result\n\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i]!\n if (!current[part] || typeof current[part] !== 'object') {\n current[part] = {}\n }\n current = current[part] as Record<string, unknown>\n }\n\n current[parts[parts.length - 1]!] = value\n }\n\n return result\n}\n","import chalk from 'chalk'\nimport { parseProject, type TranslationEntry } from '../parser'\n\ninterface DiffOptions {\n locale1: string\n locale2: string\n cwd?: string\n all?: boolean\n}\n\nexport async function diff(options: DiffOptions): Promise<void> {\n const { locale1, locale2, cwd, all } = options\n const basePath = cwd || process.cwd()\n\n console.log(chalk.blue(`\\nComparing ${locale1} vs ${locale2}...\\n`))\n\n const entries = await parseProject({ cwd })\n\n if (entries.length === 0) {\n console.log(chalk.yellow('No translations found.'))\n return\n }\n\n const onlyIn1: TranslationEntry[] = []\n const onlyIn2: TranslationEntry[] = []\n const shared: TranslationEntry[] = []\n\n for (const entry of entries) {\n const has1 = !!entry.translations[locale1]\n const has2 = !!entry.translations[locale2]\n\n if (has1 && has2) shared.push(entry)\n else if (has1 && !has2) onlyIn1.push(entry)\n else if (!has1 && has2) onlyIn2.push(entry)\n }\n\n if (onlyIn1.length > 0) {\n console.log(chalk.red(`Only in ${locale1} (${onlyIn1.length}):\\n`))\n for (const entry of onlyIn1) {\n const relativePath = entry.file.replace(basePath + '/', '')\n console.log(chalk.gray(` ${relativePath}:${entry.line}`))\n console.log(` ${chalk.cyan(locale1)}: ${entry.translations[locale1]}`)\n console.log()\n }\n }\n\n if (onlyIn2.length > 0) {\n console.log(chalk.red(`Only in ${locale2} (${onlyIn2.length}):\\n`))\n for (const entry of onlyIn2) {\n const relativePath = entry.file.replace(basePath + '/', '')\n console.log(chalk.gray(` ${relativePath}:${entry.line}`))\n console.log(` ${chalk.cyan(locale2)}: ${entry.translations[locale2]}`)\n console.log()\n }\n }\n\n if (all && shared.length > 0) {\n console.log(chalk.green(`Shared (${shared.length}):\\n`))\n for (const entry of shared) {\n const relativePath = entry.file.replace(basePath + '/', '')\n console.log(chalk.gray(` ${relativePath}:${entry.line}`))\n console.log(` ${chalk.cyan(locale1)}: ${entry.translations[locale1]}`)\n console.log(` ${chalk.cyan(locale2)}: ${entry.translations[locale2]}`)\n console.log()\n }\n }\n\n console.log(chalk.bold('Summary:'))\n console.log(chalk.green(` Shared: ${shared.length}`))\n console.log(onlyIn1.length > 0\n ? chalk.red(` Only in ${locale1}: ${onlyIn1.length}`)\n : chalk.gray(` Only in ${locale1}: 0`))\n console.log(onlyIn2.length > 0\n ? chalk.red(` Only in ${locale2}: ${onlyIn2.length}`)\n : chalk.gray(` Only in ${locale2}: 0`))\n console.log()\n}\n","import chalk from 'chalk'\nimport { parseProject, extractProjectDictionaryKeys, extractProjectTCalls } from '../parser'\n\ninterface StatsOptions {\n cwd?: string\n}\n\nexport async function stats(options: StatsOptions = {}): Promise<void> {\n const { cwd } = options\n const basePath = cwd || process.cwd()\n\n console.log(chalk.blue('\\nGathering translation statistics...\\n'))\n\n const entries = await parseProject({ cwd })\n const dictEntries = await extractProjectDictionaryKeys({ cwd })\n const tCalls = await extractProjectTCalls({ cwd })\n\n const totalDictKeys = dictEntries.reduce((sum, e) => sum + e.keys.length, 0)\n\n // Overview\n console.log(chalk.bold('Overview:\\n'))\n console.log(` Inline translations (it): ${chalk.cyan(String(entries.length))}`)\n console.log(` Dictionary keys: ${chalk.cyan(String(totalDictKeys))}`)\n console.log(` t() call sites: ${chalk.cyan(String(tCalls.length))}`)\n console.log()\n\n // Locale breakdown\n const localeCounts: Record<string, number> = {}\n for (const entry of entries) {\n for (const locale of Object.keys(entry.translations)) {\n localeCounts[locale] = (localeCounts[locale] || 0) + 1\n }\n }\n\n if (Object.keys(localeCounts).length > 0) {\n console.log(chalk.bold('Locale Breakdown (inline):\\n'))\n const sortedLocales = Object.entries(localeCounts).sort((a, b) => b[1] - a[1])\n for (const [locale, count] of sortedLocales) {\n console.log(` ${chalk.cyan(locale.padEnd(10))} ${count} translations`)\n }\n console.log()\n }\n\n // Namespace summary\n const namespaces = new Set(dictEntries.map(e => e.namespace))\n if (namespaces.size > 0) {\n console.log(chalk.bold('Namespaces:\\n'))\n for (const entry of dictEntries) {\n console.log(` ${chalk.yellow(entry.namespace.padEnd(15))} ${entry.keys.length} keys`)\n }\n console.log()\n }\n\n // Top files\n const fileCounts: Record<string, number> = {}\n for (const entry of entries) {\n const relativePath = entry.file.replace(basePath + '/', '')\n fileCounts[relativePath] = (fileCounts[relativePath] || 0) + 1\n }\n\n if (Object.keys(fileCounts).length > 0) {\n console.log(chalk.bold('Top Files:\\n'))\n const sortedFiles = Object.entries(fileCounts)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 10)\n for (const [file, count] of sortedFiles) {\n console.log(` ${chalk.gray(file.padEnd(50))} ${chalk.cyan(String(count))}`)\n }\n console.log()\n }\n\n // ICU pattern usage\n const icuUsage: Record<string, number> = {}\n for (const entry of entries) {\n if (!entry.icuTypes) continue\n for (const types of Object.values(entry.icuTypes)) {\n for (const info of types) {\n icuUsage[info.type] = (icuUsage[info.type] || 0) + 1\n }\n }\n }\n\n if (Object.keys(icuUsage).length > 0) {\n console.log(chalk.bold('ICU Pattern Usage:\\n'))\n const sortedICU = Object.entries(icuUsage).sort((a, b) => b[1] - a[1])\n for (const [type, count] of sortedICU) {\n console.log(` ${chalk.yellow(type.padEnd(20))} ${count} usage(s)`)\n }\n console.log()\n }\n}\n"],"mappings":"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","names":["traverse","fg","chalk","import_chalk","import_chalk","chalk","chalk","import_chalk","chalk","fs","import_chalk","PLURAL_SUFFIXES","chalk","import_chalk","fs","path","chalk","import_chalk","chalk","import_chalk","chalk"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inline-i18n-multi/cli",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "CLI tools for inline-i18n-multi",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",