Install i18n-unused
mainInstall i18n-unused as a development dependency using npm or yarn to start analyzing your project for unused or missing i18n translations.
npm install --save-dev i18n-unused
# or
yarn add --dev i18n-unusedrepository·main·Indexed 41 days ago
https://github.com/mxmvshnvsk/i18n-unusedA static analysis tool for finding, analyzing, and removing unused or missing i18n translations in JavaScript projects. Version 0.20.0 provides a CLI and programmatic API to identify unused keys, mark or remove them from JSON locale files, and synchronize translations between locales.
Install i18n-unused as a development dependency using npm or yarn to start analyzing your project for unused or missing i18n translations.
npm install --save-dev i18n-unused
# or
yarn add --dev i18n-unusedCreate an i18n-unused.config.js file in your project root to define how the tool scans for locales and source files. For ES-Modules, use i18n-unused.config.cjs. You can also use a .json file, though it does not support callbacks.
Example configuration:
/** @type {import('i18n-unused').RunOptions} */
module.exports = {
localesPath: 'src/locales',
srcPath: 'src',
};The library provides specific types to represent the results of its analysis.
When checking for unused keys, the result is returned as UnusedTranslations:
translations: An array of UnusedTranslation objects. Each object contains:localePath: The path to the locale file.keys: An array of the unused keys found.count: The number of unused keys in that file.totalCount: The total number of unused keys across all files.When checking for keys used in code but missing from locales, the result is returned as MissedTranslations:
translations: An array of MissedTranslation objects. Each object contains:filePath: The path to the source file where the key was found.staticKeys: Keys found via static analysis.dynamicKeys: Keys found via dynamic analysis.staticCount: Count of static keys.dynamicCount: Count of dynamic keys.totalStaticCount: Total static keys missed across all files.totalDynamicCount: Total dynamic keys missed across all files.Use the collectMissedTranslations async function to find keys that are used in your source code but are missing from your translation files. It distinguishes between staticKeys (without ${} syntax) and dynamicKeys (with ${} syntax).
Return Shape:
{
"translations": [
{
"filePath": "src_file_path",
"staticKeys": ["missed_key"],
"dynamicKeys": ["missed_key"],
"staticCount": 1,
"dynamicCount": 1
}
],
"totalStaticCount": 1,
"totalDynamicCount": 1
}import { collectMissedTranslations } from 'i18n-unused';
const handleTranslations = async () => {
const missedTranslations = await collectMissedTranslations(
localesPaths, // paths to locale files
srcFilesPaths, // paths to src files
{
localeFileParser: (module) => module, // optional, resolver for module
excludeTranslationKey: ['.props.'], // optional, special string or sting[] to exclude flat translations
translationKeyMatcher: /(?:[$ .](_|t|tc))\(.*?\)/ig, // optional, match translation keys in files
},
);
};Use the collectUnusedTranslations async function to programmatically find unused keys in your application logic. It returns an object containing the list of unused keys per locale file and the total count.
Return Shape:
{
"translations": [
{
"localePath": "locale_file_path",
"keys": ["unused_key"],
"count": 1
}
],
"totalCount": 1
}import { collectUnusedTranslations } from 'i18n-unused';
const handleTranslations = async () => {
const unusedTranslations = await collectUnusedTranslations(
localesPaths, // paths to locale files
srcFilesPaths, // paths to src files
{
localeFileParser: (module) => module, // optional, resolver for module
excludeTranslationKey: ['.props.'], // optional, special string or sting[] to exclude flat translations
},
);
};The generateFilesPaths async function returns an array of full paths to files based on a provided path and configuration options like srcExtensions and fileNameResolver.
import { generateFilesPaths } from 'i18n-unused';
const handleFilesPaths = async () => {
// return array of full paths to files
const filesPaths = await generateFilesPaths(
srcPath, // path where search files, example: 'src/locales'
{
srcExtensions, // allowed file extensions, example: ['js', 'ts']
fileNameResolver, // resolver for file name, see more info about 'localeNameResolver' option
},
);
};The RunOptions interface defines the configuration for running the unused and missed translation checks. You can use these options to customize how locales are loaded, how source files are scanned, and how translation keys are matched.
localesPath: Path to your locales folder.localesExtensions: Allowed file extensions for locales (defaults to ['json'] if localeNameResolver is not set).localeNameResolver: A ModuleNameResolver (RegExp or function) to resolve locale names from filenames.localeFileParser: A ModuleResolver to handle locale imports (defaults to (m) => m.default).localeFileLoader: A CustomFileLoader to manually load locale files.srcPath: Path to search for translations (defaults to process.cwd()).srcExtensions: Allowed file extensions for source files (defaults to ['js', 'jsx', 'ts', 'tsx', 'vue']).ignorePaths: Array of paths to ignore (must start similarly to srcPath).ignoreComments: Whether to ignore code comments in source files (defaults to false).excludeKey: A string or array of strings. If a translation key includes these, it will be ignored (e.g., '.props.' ignores Button.props.value).translationKeyMatcher: A TranslationKeyMatcher (RegExp) to find translation keys in code (defaults to matching $_, $t, t, $tc, tc, and i18nKey).translationSeparator: The separator used for translation keys in code (defaults to '.').missedTranslationParser: A MissedTranslationParser to extract keys from matches (defaults to matching values inside rounded brackets).context: Whether to use i18n context like plurals (defaults to true).translationContextSeparator: Separator for i18n context (defaults to '_').translationContextMatcher: RegExp to match i18n context keys (defaults to matching zero, one, two, few, many, other, male, female, 0, 1, 2, 3, 4, 5, plural, 11, and 100).failOnUnused: Throw an error if unused translations are found (defaults to false).failOnMissed: Throw an error if missed translations are found (defaults to false).marker: Special string used to mark unused translations (defaults to '[UNUSED]').localeJsonStringifyIndent: JSON indentation for writing files (defaults to 2).The following options are available in the i18n-unused.config.js file to customize the analysis behavior.
| Option name | Description | Required | Type | Default value |
| --- | --- | --- | --- | --- |
| localesPath | path to search for locales | yes | string | - |
| localesExtensions | allowed file extensions for locales | no | string[] | if not set `localeNameResolver`: ['json'] |
| localeNameResolver | file name resolver for locales | no | RegExp, (name: string) => boolean | - |
| customChecker | function to check if a key is used, if so the key should be removed from translationsKeys | no | fn, (matchedKeys: Set<string>, translationsKeys: string[] => void) | A defined validations will be applied |
| localeFileParser | resolve locale imports, for example if you use named imports from locales files, just wrap it to your own resolver | no | (module) => module | fn, return `module.default` or `module` |
| localeFileLoader | load the locale file manually (e.g. for using your own parser) | no | (filePath) => object | - |
| srcPath | path to search for translations | no | string | `''` (same as run folder) |
| srcExtensions | allowed file extensions for translations | no | string[] | ['js', 'ts', 'jsx', 'tsx', 'vue'] |
| ignorePaths | ignored paths, eg: `['src/ignored-folder']`, should start similarly `srcPath` | no | string[] | - |
| translationKeyMatcher | matcher to search for translation keys in files | no | RegExp | RegExp, match `$_`, `$t`, `t`, `$tc`, `tc` and `i18nKey` |
| excludeKey | doesn't process translations that include passed key(s), for example if you set `excludeKey: '.props.'`, script will ignore `Button.props.value`. | no | string, string[] | - |
| ignoreComments | Ignore code comments in src files. | no | boolean | false |
| marker | special string to mark unused translations, it'll added via `mark-unused` | no | string | '[UNUSED]' |
| gitCheck | show git state change tree | no | boolean | false |
| context | use i18n context, (eg: [plurals](https://www.i18next.com/translation-function/context)) | no | boolean | true |
| flatTranslations | use flat translations, (eg: [Flat JSON](https://www.codeandweb.com/babeledit/documentation/file-formats#flat-json)) | no | boolean |
| translationSeparator | separator for translations using in code | no | string | '.' |
| translationContextSeparator | separator for i18n context (see `context` option) | no | string | '_' |
| translationContextMatcher | matcher to search for context endings | no | RegExp | RegExp, match `zero`, `one`, `two`, `few`, `many`, `other`, `male`, `female`, `0`, `1`, `2`, `3`, `4`, `5`, `plural`, `11` and `100` |
| missedTranslationParser | parser for ejecting value from `translationKeyMatcher` matches | no | RegExp, (v: string) => string | RegExp, match value inside rounded brackets |
| localeJsonStringifyIndent | json indent value for writing json file, either a number of spaces, or a string to indent with. (i.e. `2`, `4`, `\t`) | no | string , number | `2` |Use the following global options to define how the tool searches for translations and source files:
# Global Options
- `-sExt, --src-extensions [srcExtensions...]`: File extensions to include in the search. Defaults to `js, ts, jsx, tsx, vue`.
- `-lExt, --locales-extensions [localesExtensions...]`: Extensions for locales files. Defaults to `json`.
- `-lExt, --translation-key-matcher <translationKeyMatcher>`: A regex string used to match translation keys in source files. Default: `/(?:[$ .](_|t|tc|i18nKey))\(.*?\)/gi`.
- `-sPath, --src-path <srcPath>`: Path to your source code (e.g., `src`).
- `-lPath, --locales-path <localesPath>`: Path to your locales files (e.g., `src/locales`).
- `-v, --version`: Output the current version.The remove-unused command automatically deletes unused translations from your locale files.
npx i18n-unused remove-unusedRun the following commands from your terminal to manage translations:
i18n-unused -h: Display help.i18n-unused display-unused: List all unused translations.i18n-unused mark-unused: Mark unused translations with the configured marker (works only with .json files).i18n-unused remove-unused: Remove unused translations (works only with .json files).i18n-unused sync <source> <target>: Sync translations between source and target (works only with .json files).i18n-unused display-missed: List all missed translations (keys used in code but missing in locale files).Custom Matcher Example:
To use a custom matcher for i18n-node style translations:
i18n-unused display-unused --translation-key-matcher '/(?:[$ .](__))\(.*?\)/gi'
i18n-unused -h
i18n-unused display-unused
i18n-unused mark-unused
i18n-unused remove-unused
i18n-unused sync <source> <target>
i18n-unused display-missedUse the display-unused command to output a table showing translations that are defined in your locale files but are not being used anywhere in your source code.
npx i18n-unused display-unused --src-path src --locales-path src/locales