i18n-check

repository·main·Indexed 41 days ago

https://github.com/lingualdev/i18n-check

A tool for validating internationalization (i18n) translation files in JSON or YAML formats. It ensures consistency with a source locale by detecting missing keys, invalid syntax, and unused or undefined keys within application source code. It supports common i18n frameworks including i18next, react-intl, and next-intl, and provides a CLI with customizable reporting styles and check types.

Tokens
4.7K
Snippets
16
Records
20
Agent score
51%

What's inside i18n-check

  1. Configure check types with --only

    main

    By default, i18n-check validates against missingKeys and invalidKeys. You can restrict the execution to specific checks using the --only (or -o) flag.

    Available check types:

    • invalidKeys: Finds translations that are syntactically incorrect (e.g., invalid ICU messages).
    • missingKeys: Finds keys present in the source locale but missing in target locales.
    • unused: Finds keys present in translation files that are not used in the source code.
    • undefined: Finds keys present in translation files that are not used in the source code (often used interchangeably with unused depending on context).

    Note: The --check flag is deprecated; use --only instead.

  2. Understand the CheckResult data structure

    main

    A CheckResult represents the outcome of the i18n validation process. It is a record where keys are the identifiers (such as translation keys or file paths) and values are arrays of error messages associated with those keys.

    // Example structure of a CheckResult
    const result: CheckResult = {
      'common.welcome': ['Missing translation in es.json'],
      'errors.not_found': ['Invalid ICU pattern']
    };
  3. Configure key ignoring with glob patterns

    main

    When using Options, you can provide an ignore array to skip specific keys during validation. The library supports exact matches and simple suffix-based globbing.

    • Exact match: 'my_key' will ignore only my_key.
    • Suffix glob: 'prefix_*' will ignore any key that starts with prefix_ (e.g., prefix_button, prefix_label).
  4. Understand the InvalidTranslationsResult data structure

    main

    When identifying specific invalid entries within translations, the tool uses InvalidTranslationsResult. This maps a context (like a file or language) to an array of InvalidTranslationEntry objects, which contain the specific key that failed and the error msg.

    // Example structure of InvalidTranslationsResult
    const invalidResults: InvalidTranslationsResult = {
      'en.json': [
        { key: 'auth.login', msg: 'Expected string, got number' }
      ]
    };
  5. Find unused and undefined keys in source code

    main

    To detect keys that are defined in your translation files but never actually called in your application code, use the --unused flag followed by the paths to your source files (e.g., .js, .jsx, .ts, .tsx).

    When performing this check, you can provide additional context to the parser:

    • --parser-component-functions <components...>: A list of component names to parse when scanning for usage.
    • --next-intl-translation-fn-type-alias <nextIntlTranslationFnTypeAliases...>: Specific type aliases for next-intl translation functions.

    Example:

    i18n-check -l locales/ -s en -u src/ --only unused
  6. Configure reporting styles with --reporter

    main

    You can control how the results are displayed using the --reporter flag:

    • standard (default): Displays detailed tables for each type of error found (e.g., formatCheckResultTable, formatInvalidTranslationsResultTable).
    • summary: Displays a condensed summary of the findings using formatSummaryTable.
  7. Configure ESLint for @lingual/i18n-check

    main

    The project uses a flat configuration format for ESLint via eslint.config.mjs. It applies recommended JavaScript and TypeScript rules, specifically configuring TypeScript-related linting to allow JSON imports and to ignore unused variables that follow a specific naming pattern (prefixed with an underscore). It also sets the global environment to browser and ignores the translations/ directory.

    import js from '@eslint/js';
    import globals from 'globals';
    import tseslint from 'typescript-eslint';
    import { globalIgnores, defineConfig } from 'eslint/config';
    
    export default defineConfig([
      {
        files: ['**/*.{js,mjs,cjs,ts}'],
        plugins: { js },
        extends: ['js/recommended'],
        rules: {
          '@typescript-eslint/no-require-imports': [
            'error',
            { allow: ['\\.json$'] },
          ],
          '@typescript-eslint/no-unused-vars': [
            'error',
            {
              argsIgnorePattern: '^_',
              varsIgnorePattern: '^_',
              caughtErrorsIgnorePattern: '^_',
            },
          ],
        },
      },
      {
        files: ['**/*.{js,mjs,cjs,ts}'],
        languageOptions: { globals: globals.browser },
      },
      globalIgnores(['translations/**/*']),
      tseslint.configs.recommended,
    ]);
  8. Configure Vitest for i18n-check

    main

    The vitest.bin.config.ts file extends a base Vitest configuration to set up the testing environment specifically for the binary/CLI components of i18n-check. It inherits all settings from ./vitest.config and applies specific exclusions for the test runner to prevent scanning dependency or build directories.

    import { defineConfig } from 'vitest/config';
    import baseConfig from './vitest.config';
    
    export default defineConfig({
      ...baseConfig,
      test: {
        exclude: ['node_modules', 'dist'],
      },
    });
  9. Find unused translation keys with checkUnusedKeys()

    main

    Use checkUnusedKeys to identify keys present in your translation files that are not actually being used in your source code.

    Parameters:

    • translationFiles: An array of TranslationFile objects.
    • filesToParse: An array of file paths (strings) to scan for key usage.
    • options: Options object. Must include 'unused' in the checks array and specify a supported format ('react-intl', 'i18next', or 'next-intl').
    • componentFunctions: (Optional) An array of strings representing custom component functions used for key extraction (primarily for i18next).

    Returns: A Promise resolving to a CheckResult (a mapping of file names to arrays of unused keys) or undefined if checks are not applicable.

    import { checkUnusedKeys } from '@lingual/i18n-check';
    
    const unused = await checkUnusedKeys(
      translationFiles,
      ['src/components/MyComponent.tsx', 'src/pages/Home.tsx'],
      {
        format: 'react-intl',
        checks: ['unused']
      }
    );
  10. Configure i18n-check options

    main

    The Options type defines the configuration for the i18n-check process. You can specify the translation format, custom checks, files to ignore, and type aliases for next-intl translation functions.

    Available format values:

    • 'icu'
    • 'i18next'
    • 'react-intl'
    • 'next-intl'
    const options: Options = {
      format: 'i18next',
      ignore: ['**/node_modules/**'],
      checks: [], // Array of Context objects
      nextIntlTranslationFnTypeAlias: ['TFunction']
    };
  11. Find undefined keys in code with checkUndefinedKeys()

    main

    Use checkUndefinedKeys to find keys that are being called in your source code but do not exist in any of your translation files.

    Parameters:

    • source: An array of TranslationFile objects.
    • filesToParse: An array of file paths (strings) to scan for key usage.
    • options: Options object. Must include 'undefined' in the checks array and specify a supported format ('react-intl', 'i18next', or 'next-intl').
    • componentFunctions: (Optional) An array of strings representing custom component functions used for key extraction (primarily for i18next).

    Returns: A Promise resolving to a CheckResult (a mapping of file paths to arrays of undefined keys) or undefined if checks are not applicable.

    import { checkUndefinedKeys } from '@lingual/i18n-check';
    
    const undefinedKeys = await checkUndefinedKeys(
      translationFiles,
      ['src/**/*.tsx'],
      {
        format: 'i18next',
        checks: ['undefined']
      }
    );
  12. Format check results as a detailed table

    main

    Use formatCheckResultTable to generate a detailed visual table showing exactly which files and keys contain issues. It takes a CheckResult object and returns a formatted string with 'file' and 'key' columns.

    import { formatCheckResultTable } from './errorReporters.js';
    
    const result = {
      'locales/en.json': ['auth.login.error', 'auth.logout.success']
    };
    
    const table = formatCheckResultTable(result);
    console.log(table);