npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

i18n-unused

v0.16.0

Published

The tool for finding, analyzing and removing unused and missed i18n translations in your JavaScript project

Downloads

72,769

Readme

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