{"_id":"@another-art/i18n-checker","_rev":"2-7f49edcea897d2514adaf425fa194238","name":"@another-art/i18n-checker","dist-tags":{"latest":"0.0.2"},"versions":{"0.0.1":{"name":"@another-art/i18n-checker","version":"0.0.1","keywords":["i18n","internationalization","translation","checker","missing-keys","locale"],"license":"MIT","_id":"@another-art/i18n-checker@0.0.1","maintainers":[{"name":"another-art","email":"ice.post.yandex@gmail.com"}],"bin":{"i18n-checker":"dist/cli.js"},"dist":{"shasum":"edf30d7ea5cfd83a8688075c953abcde75e6d379","tarball":"https://registry.npmjs.org/@another-art/i18n-checker/-/i18n-checker-0.0.1.tgz","fileCount":17,"integrity":"sha512-VTrbkfB0MsFdW0F2M3iil/jqRM3OwKXut/ELv8K5GewUCTwqoZLavp4xqWr55XwLavyxuqLwU9uUoQkLM/0hLA==","signatures":[{"sig":"MEQCIAeKpA10zqw/MS3nj3bt6+GQKmr6CqOu3sCi117UlU8vAiBTN04hvj446aQ6mL+QJ/jucSmUO55smG9uTGp+d+NHCQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":52004},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsc","check":"bun run src/cli.ts","prepublishOnly":"bun run build"},"_npmUser":{"name":"another-art","email":"ice.post.yandex@gmail.com"},"_npmVersion":"11.10.1","description":"Scan i18n translation files for missing keys, extra keys, and placeholder mismatches","directories":{},"_nodeVersion":"25.7.0","_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.9.3","@types/node":"^25.3.3"},"_npmOperationalInternal":{"tmp":"tmp/i18n-checker_0.0.1_1772595847195_0.6550294862536281","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"@another-art/i18n-checker","version":"0.0.2","description":"Scan i18n translation files for missing keys, extra keys, and placeholder mismatches","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"bin":{"i18n-checker":"dist/cli.js"},"scripts":{"build":"tsc","check":"bun run src/cli.ts","prepublishOnly":"bun run build"},"keywords":["i18n","internationalization","translation","checker","missing-keys","locale"],"license":"MIT","engines":{"node":">=20"},"devDependencies":{"@types/node":"^25.3.3","typescript":"^5.9.3"},"_id":"@another-art/i18n-checker@0.0.2","_nodeVersion":"25.7.0","_npmVersion":"11.10.1","dist":{"integrity":"sha512-pCj2qiaEPgj/RlaGqNjwoKs5UA0t2VBXnLezMlf63xQ/WXXe9k9pgzxMb7vx/SDP86SqWpxtL/2yt2OSRyzyoA==","shasum":"bfada6f6d144cf93775c01b41602743e4571cb80","tarball":"https://registry.npmjs.org/@another-art/i18n-checker/-/i18n-checker-0.0.2.tgz","fileCount":18,"unpackedSize":54672,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDbI7fYtwXcvyvEjX7Diy19aqG7jHtfnIEV0KMjase5UgIgaJQj8vMswPH9sY2ykLyr7NUWQkfmxxqWZ5stMNanijg="}]},"_npmUser":{"name":"another-art","email":"ice.post.yandex@gmail.com"},"directories":{},"maintainers":[{"name":"another-art","email":"ice.post.yandex@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/i18n-checker_0.0.2_1772596856204_0.5816856557789079"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-04T03:44:07.071Z","modified":"2026-03-04T04:00:56.514Z","0.0.1":"2026-03-04T03:44:07.354Z","0.0.2":"2026-03-04T04:00:56.390Z"},"license":"MIT","keywords":["i18n","internationalization","translation","checker","missing-keys","locale"],"description":"Scan i18n translation files for missing keys, extra keys, and placeholder mismatches","maintainers":[{"name":"another-art","email":"ice.post.yandex@gmail.com"}],"readme":"# i18n-checker\n\nScan i18n translation files for missing keys, extra keys, and placeholder mismatches. Zero dependencies.\n\n## Install\n\n```bash\nnpm install @another-art/i18n-checker\n```\n\n## CLI\n\n```bash\nnpx @another-art/i18n-checker ./path/to/project\n```\n\nStarts a local server with an interactive UI showing all translation issues.\n\nOptions:\n- `PORT` env variable to set port (default: `3999`, auto-increments if busy)\n\n```bash\nPORT=4000 npx @another-art/i18n-checker .\n```\n\n## Library\n\n```ts\nimport { scan, buildHtml } from '@another-art/i18n-checker';\n\nconst result = await scan('/path/to/project');\n\nconsole.log(result.totalMissing);     // missing keys count\nconsole.log(result.totalExtra);       // extra keys count\nconsole.log(result.totalPlaceholder); // placeholder mismatch count\n\nfor (const dir of result.results) {\n  console.log(dir.i18nPath, dir.issues.length);\n\n  for (const issue of dir.issues) {\n    console.log(`  [${issue.type}] ${issue.locale} — ${issue.key}`);\n  }\n}\n\n// Generate HTML report\nconst html = buildHtml(result);\n```\n\n## Supported formats\n\n**Folder format** — `i18n/<locale>/index.json`:\n\n```\nsrc/\n  i18n/\n    en/\n      index.json    ← { \"greeting\": \"Hello, {name}!\" }\n    ru/\n      index.json    ← { \"greeting\": \"Привет, {name}!\" }\n```\n\n**Flat format** — `<locale>.json` files in the same directory:\n\n```\nlocales/\n  en.json           ← { \"save\": \"Save\", \"cancel\": \"Cancel\" }\n  ru.json           ← { \"save\": \"Сохранить\" }\n```\n\nFlat format is detected when a directory contains 2+ files matching `<locale>.json` (2-3 letter codes).\n\n## Detected issues\n\n| Type | Description |\n|------|-------------|\n| `missing` | Key exists in reference locale but not in target |\n| `extra` | Key exists in target but not in reference locale |\n| `placeholder_mismatch` | Placeholders like `{name}` differ between locales |\n\nReference locale is `en` if present, otherwise the first locale alphabetically.\n\n## Types\n\n```ts\ninterface ScanResult {\n  root: string;\n  results: CheckResult[];\n  totalMissing: number;\n  totalExtra: number;\n  totalPlaceholder: number;\n}\n\ninterface CheckResult {\n  i18nPath: string;\n  referenceLocale: string;\n  allLocales: string[];\n  totalKeys: number;\n  issues: Issue[];\n  translations: Record<string, Record<string, string>>;\n}\n\ninterface Issue {\n  locale: string;\n  key: string;\n  type: 'missing' | 'extra' | 'placeholder_mismatch';\n  detail?: string;\n  referenceValue?: string;\n  localeValue?: string;\n}\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}