@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 +70 -0
- package/dist/bin.js +143 -7
- package/dist/bin.js.map +1 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +134 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
854
|
+
var import_chalk9 = __toESM(require("chalk"));
|
|
725
855
|
function startWatch(options) {
|
|
726
856
|
const { cwd, patterns, ignore, onChange, label } = options;
|
|
727
|
-
console.log(
|
|
857
|
+
console.log(import_chalk9.default.blue(`
|
|
728
858
|
Watching for changes (${label})...
|
|
729
859
|
`));
|
|
730
|
-
console.log(
|
|
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(
|
|
870
|
+
console.log(import_chalk9.default.gray(`
|
|
741
871
|
Change detected: ${filePath}`));
|
|
742
|
-
console.log(
|
|
872
|
+
console.log(import_chalk9.default.gray("-".repeat(40)));
|
|
743
873
|
try {
|
|
744
874
|
await onChange();
|
|
745
875
|
} catch {
|
|
746
876
|
}
|
|
747
|
-
console.log(
|
|
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.
|
|
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":"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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"]}
|
|
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
|
-
|
|
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":"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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"]}
|
|
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;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;;;ACxFA,IAAAC,gBAAkB;AAUlB,eAAsB,KAAK,SAAqC;AAC9D,QAAM,EAAE,SAAS,SAAS,KAAK,IAAI,IAAI;AACvC,QAAM,WAAW,OAAO,QAAQ,IAAI;AAEpC,UAAQ,IAAI,cAAAC,QAAM,KAAK;AAAA,YAAe,OAAO,OAAO,OAAO;AAAA,CAAO,CAAC;AAEnE,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,UAA8B,CAAC;AACrC,QAAM,UAA8B,CAAC;AACrC,QAAM,SAA6B,CAAC;AAEpC,aAAW,SAAS,SAAS;AAC3B,UAAM,OAAO,CAAC,CAAC,MAAM,aAAa,OAAO;AACzC,UAAM,OAAO,CAAC,CAAC,MAAM,aAAa,OAAO;AAEzC,QAAI,QAAQ,KAAM,QAAO,KAAK,KAAK;AAAA,aAC1B,QAAQ,CAAC,KAAM,SAAQ,KAAK,KAAK;AAAA,aACjC,CAAC,QAAQ,KAAM,SAAQ,KAAK,KAAK;AAAA,EAC5C;AAEA,MAAI,QAAQ,SAAS,GAAG;AACtB,YAAQ,IAAI,cAAAA,QAAM,IAAI,WAAW,OAAO,KAAK,QAAQ,MAAM;AAAA,CAAM,CAAC;AAClE,eAAW,SAAS,SAAS;AAC3B,YAAM,eAAe,MAAM,KAAK,QAAQ,WAAW,KAAK,EAAE;AAC1D,cAAQ,IAAI,cAAAA,QAAM,KAAK,KAAK,YAAY,IAAI,MAAM,IAAI,EAAE,CAAC;AACzD,cAAQ,IAAI,OAAO,cAAAA,QAAM,KAAK,OAAO,CAAC,KAAK,MAAM,aAAa,OAAO,CAAC,EAAE;AACxE,cAAQ,IAAI;AAAA,IACd;AAAA,EACF;AAEA,MAAI,QAAQ,SAAS,GAAG;AACtB,YAAQ,IAAI,cAAAA,QAAM,IAAI,WAAW,OAAO,KAAK,QAAQ,MAAM;AAAA,CAAM,CAAC;AAClE,eAAW,SAAS,SAAS;AAC3B,YAAM,eAAe,MAAM,KAAK,QAAQ,WAAW,KAAK,EAAE;AAC1D,cAAQ,IAAI,cAAAA,QAAM,KAAK,KAAK,YAAY,IAAI,MAAM,IAAI,EAAE,CAAC;AACzD,cAAQ,IAAI,OAAO,cAAAA,QAAM,KAAK,OAAO,CAAC,KAAK,MAAM,aAAa,OAAO,CAAC,EAAE;AACxE,cAAQ,IAAI;AAAA,IACd;AAAA,EACF;AAEA,MAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,YAAQ,IAAI,cAAAA,QAAM,MAAM,WAAW,OAAO,MAAM;AAAA,CAAM,CAAC;AACvD,eAAW,SAAS,QAAQ;AAC1B,YAAM,eAAe,MAAM,KAAK,QAAQ,WAAW,KAAK,EAAE;AAC1D,cAAQ,IAAI,cAAAA,QAAM,KAAK,KAAK,YAAY,IAAI,MAAM,IAAI,EAAE,CAAC;AACzD,cAAQ,IAAI,OAAO,cAAAA,QAAM,KAAK,OAAO,CAAC,KAAK,MAAM,aAAa,OAAO,CAAC,EAAE;AACxE,cAAQ,IAAI,OAAO,cAAAA,QAAM,KAAK,OAAO,CAAC,KAAK,MAAM,aAAa,OAAO,CAAC,EAAE;AACxE,cAAQ,IAAI;AAAA,IACd;AAAA,EACF;AAEA,UAAQ,IAAI,cAAAA,QAAM,KAAK,UAAU,CAAC;AAClC,UAAQ,IAAI,cAAAA,QAAM,MAAM,aAAa,OAAO,MAAM,EAAE,CAAC;AACrD,UAAQ,IAAI,QAAQ,SAAS,IACzB,cAAAA,QAAM,IAAI,aAAa,OAAO,KAAK,QAAQ,MAAM,EAAE,IACnD,cAAAA,QAAM,KAAK,aAAa,OAAO,KAAK,CAAC;AACzC,UAAQ,IAAI,QAAQ,SAAS,IACzB,cAAAA,QAAM,IAAI,aAAa,OAAO,KAAK,QAAQ,MAAM,EAAE,IACnD,cAAAA,QAAM,KAAK,aAAa,OAAO,KAAK,CAAC;AACzC,UAAQ,IAAI;AACd;;;AC5EA,IAAAC,gBAAkB;AAOlB,eAAsB,MAAM,UAAwB,CAAC,GAAkB;AACrE,QAAM,EAAE,IAAI,IAAI;AAChB,QAAM,WAAW,OAAO,QAAQ,IAAI;AAEpC,UAAQ,IAAI,cAAAC,QAAM,KAAK,yCAAyC,CAAC;AAEjE,QAAM,UAAU,MAAM,aAAa,EAAE,IAAI,CAAC;AAC1C,QAAM,cAAc,MAAM,6BAA6B,EAAE,IAAI,CAAC;AAC9D,QAAM,SAAS,MAAM,qBAAqB,EAAE,IAAI,CAAC;AAEjD,QAAM,gBAAgB,YAAY,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,KAAK,QAAQ,CAAC;AAG3E,UAAQ,IAAI,cAAAA,QAAM,KAAK,aAAa,CAAC;AACrC,UAAQ,IAAI,kCAAkC,cAAAA,QAAM,KAAK,OAAO,QAAQ,MAAM,CAAC,CAAC,EAAE;AAClF,UAAQ,IAAI,kCAAkC,cAAAA,QAAM,KAAK,OAAO,aAAa,CAAC,CAAC,EAAE;AACjF,UAAQ,IAAI,kCAAkC,cAAAA,QAAM,KAAK,OAAO,OAAO,MAAM,CAAC,CAAC,EAAE;AACjF,UAAQ,IAAI;AAGZ,QAAM,eAAuC,CAAC;AAC9C,aAAW,SAAS,SAAS;AAC3B,eAAW,UAAU,OAAO,KAAK,MAAM,YAAY,GAAG;AACpD,mBAAa,MAAM,KAAK,aAAa,MAAM,KAAK,KAAK;AAAA,IACvD;AAAA,EACF;AAEA,MAAI,OAAO,KAAK,YAAY,EAAE,SAAS,GAAG;AACxC,YAAQ,IAAI,cAAAA,QAAM,KAAK,8BAA8B,CAAC;AACtD,UAAM,gBAAgB,OAAO,QAAQ,YAAY,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AAC7E,eAAW,CAAC,QAAQ,KAAK,KAAK,eAAe;AAC3C,cAAQ,IAAI,KAAK,cAAAA,QAAM,KAAK,OAAO,OAAO,EAAE,CAAC,CAAC,IAAI,KAAK,eAAe;AAAA,IACxE;AACA,YAAQ,IAAI;AAAA,EACd;AAGA,QAAM,aAAa,IAAI,IAAI,YAAY,IAAI,OAAK,EAAE,SAAS,CAAC;AAC5D,MAAI,WAAW,OAAO,GAAG;AACvB,YAAQ,IAAI,cAAAA,QAAM,KAAK,eAAe,CAAC;AACvC,eAAW,SAAS,aAAa;AAC/B,cAAQ,IAAI,KAAK,cAAAA,QAAM,OAAO,MAAM,UAAU,OAAO,EAAE,CAAC,CAAC,IAAI,MAAM,KAAK,MAAM,OAAO;AAAA,IACvF;AACA,YAAQ,IAAI;AAAA,EACd;AAGA,QAAM,aAAqC,CAAC;AAC5C,aAAW,SAAS,SAAS;AAC3B,UAAM,eAAe,MAAM,KAAK,QAAQ,WAAW,KAAK,EAAE;AAC1D,eAAW,YAAY,KAAK,WAAW,YAAY,KAAK,KAAK;AAAA,EAC/D;AAEA,MAAI,OAAO,KAAK,UAAU,EAAE,SAAS,GAAG;AACtC,YAAQ,IAAI,cAAAA,QAAM,KAAK,cAAc,CAAC;AACtC,UAAM,cAAc,OAAO,QAAQ,UAAU,EAC1C,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAC1B,MAAM,GAAG,EAAE;AACd,eAAW,CAAC,MAAM,KAAK,KAAK,aAAa;AACvC,cAAQ,IAAI,KAAK,cAAAA,QAAM,KAAK,KAAK,OAAO,EAAE,CAAC,CAAC,IAAI,cAAAA,QAAM,KAAK,OAAO,KAAK,CAAC,CAAC,EAAE;AAAA,IAC7E;AACA,YAAQ,IAAI;AAAA,EACd;AAGA,QAAM,WAAmC,CAAC;AAC1C,aAAW,SAAS,SAAS;AAC3B,QAAI,CAAC,MAAM,SAAU;AACrB,eAAW,SAAS,OAAO,OAAO,MAAM,QAAQ,GAAG;AACjD,iBAAW,QAAQ,OAAO;AACxB,iBAAS,KAAK,IAAI,KAAK,SAAS,KAAK,IAAI,KAAK,KAAK;AAAA,MACrD;AAAA,IACF;AAAA,EACF;AAEA,MAAI,OAAO,KAAK,QAAQ,EAAE,SAAS,GAAG;AACpC,YAAQ,IAAI,cAAAA,QAAM,KAAK,sBAAsB,CAAC;AAC9C,UAAM,YAAY,OAAO,QAAQ,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AACrE,eAAW,CAAC,MAAM,KAAK,KAAK,WAAW;AACrC,cAAQ,IAAI,KAAK,cAAAA,QAAM,OAAO,KAAK,OAAO,EAAE,CAAC,CAAC,IAAI,KAAK,WAAW;AAAA,IACpE;AACA,YAAQ,IAAI;AAAA,EACd;AACF;","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"]}
|