Skip to content

Latest commit

 

History

History
206 lines (163 loc) · 7.25 KB

README.md

File metadata and controls

206 lines (163 loc) · 7.25 KB

i18n-unused

npm npm

The static analyze tool for finding, marking and removing unused and missing i18n translations in your JavaScript project.

Installation

With npm:

npm install --save-dev i18n-unused

With yarn:

yarn add --dev i18n-unused

Configuration

Add config i18n-unused.config.js to your root folder:

/** @type {import('i18n-unused').RunOptions} */
module.exports = {
  localesPath: 'src/locales',
  srcPath: 'src',
};

For ES-Modules (esm) use i18n-unused.config.cjs. You can also use the .json with no support for callbacks.

Configuration options

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) no boolean true
flatTranslations use flat translations, (eg: Flat JSON) no boolean false
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

Usage

Get help:

i18n-unused -h

Display unused translations:

i18n-unused display-unused

Display unused translations for mashpie/i18n-node:

i18n-unused display-unused --translation-key-matcher '/(?:[$ .](__))\(.*?\)/gi'

Mark unused translations via [UNUSED] or marker from config (works only with json for now):

i18n-unused mark-unused

Remove unused translations (works only with json for now):

i18n-unused remove-unused

Sync translations (works only with json for now):

i18n-unused sync <source> <target>

Display missed translations:

i18n-unused display-missed

Usage in code

collectUnusedTranslations

If you use tool in code, you can run async function collectUnusedTranslations:

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
    },
  );
};

It'll return to you follow collect:

{
  translations: [
    {
      localePath: 'locale_file_path',
      keys: ['unused_key'],
      count: 1,
    },
  ],
  totalCount: 1,
}

collectMissedTranslations

If you use tool in code, you can run async function collectMissedTranslations:

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
    },
  );
};

You'll get the following collection:

{
  translations: [
    {
      filePath: 'src_file_path',
      staticKeys: ['missed_key'], // keys without ${} syntax
      dynamicKeys: ['missed_key'], // keys with ${} syntax
      staticCount: 1,
      dynamicCount: 1,
    },
  ],
  totalStaticCount: 1,
  totalDynamicCount: 1,
}

generateFilesPaths

Available as async function generateFilesPaths:

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
    },
  );
};

Action results

Next actions return unusedTranslations:

  • displayUnusedTranslations
  • removeUnusedTranslations
  • markUnusedTranslations

Next actions return missedTranslations:

  • displayMissedTranslations

What else?

If the tool helped you, please rate it on github, thx. I'll be glad to your PRs =)

License

MIT License. Maxim Vishnevsky