or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

cli.mdindex.mdparser.mdstream.md
tile.json

cli.mddocs/

CLI Usage

Command-line interface for scanning files and extracting translation keys. The CLI tool supports glob patterns, configuration files, and flexible output options for batch processing of translation key extraction.

Capabilities

Command Syntax

i18next-scanner [options] <file ...>

Options:
  --config <config>  Path to the config file (default: i18next-scanner.config.js)
  --output <path>    Path to the output directory (default: .)
  -V, --version      output the version number
  -h, --help         output usage information

Basic Usage

Usage Examples:

# Scan single file
i18next-scanner src/app.js

# Scan multiple files
i18next-scanner src/app.js src/utils.js public/index.html

# Scan with glob patterns (use quotes)
i18next-scanner 'src/**/*.{js,jsx}'

# Scan with custom config
i18next-scanner --config my-scanner.config.js 'src/**/*.js'

# Scan with custom output directory
i18next-scanner --output ./translations 'src/**/*.js'

# Combined options
i18next-scanner --config custom.config.js --output ./i18n 'src/**/*.{js,jsx,ts,tsx}'

Configuration File

The CLI uses a JavaScript configuration file that exports an object with input files, output directory, and parser options.

// i18next-scanner.config.js structure
module.exports = {
  input: string | string[];           // Input file patterns
  output: string;                     // Output directory path
  options: ParserOptions;             // Parser configuration
  transform?: CustomTransform;        // Optional custom transform function
  flush?: CustomFlush;               // Optional custom flush function
}

Usage Examples:

// i18next-scanner.config.js
const fs = require('fs');
const chalk = require('chalk');

module.exports = {
  input: [
    'src/**/*.{js,jsx,ts,tsx}',
    'public/**/*.html',
    // Exclude test files and node_modules
    '!src/**/*.spec.{js,jsx,ts,tsx}',
    '!src/**/*.test.{js,jsx,ts,tsx}',
    '!**/node_modules/**'
  ],
  output: './locales',
  options: {
    debug: true,
    sort: true,
    func: {
      list: ['i18next.t', 'i18n.t', 't', '__', '_t'],
      extensions: ['.js', '.jsx', '.ts', '.tsx']
    },
    trans: {
      component: 'Trans',
      i18nKey: 'i18nKey',
      defaultsKey: 'defaults',
      extensions: ['.jsx', '.tsx'],
      fallbackKey: function(ns, value) {
        // Use the default value as fallback key
        return value;
      },
      supportBasicHtmlNodes: true,
      keepBasicHtmlNodesFor: ['br', 'strong', 'i', 'p']
    },
    attr: {
      list: ['data-i18n'],
      extensions: ['.html', '.htm']
    },
    lngs: ['en', 'de', 'fr', 'es'],
    ns: ['common', 'validation', 'navigation', 'errors'],
    defaultLng: 'en',
    defaultNs: 'common',
    defaultValue: '__STRING_NOT_TRANSLATED__',
    resource: {
      loadPath: 'locales/{{lng}}/{{ns}}.json',
      savePath: 'locales/{{lng}}/{{ns}}.json',
      jsonIndent: 2,
      lineEnding: '\\n'
    },
    nsSeparator: ':',
    keySeparator: '.',
    interpolation: {
      prefix: '{{',
      suffix: '}}'
    },
    allowDynamicKeys: false
  },
  
  // Custom transform function
  transform: function customTransform(file, enc, done) {
    const parser = this.parser;
    const content = fs.readFileSync(file.path, enc);
    let count = 0;

    // Parse custom translation functions
    parser.parseFuncFromString(content, { 
      list: ['i18next._', 'i18next.__'] 
    }, (key, options) => {
      parser.set(key, Object.assign({}, options, {
        nsSeparator: false,
        keySeparator: false
      }));
      ++count;
    });

    if (count > 0) {
      console.log(`i18next-scanner: count=${chalk.cyan(count)}, file=${chalk.yellow(JSON.stringify(file.relative))}`);
    }

    done();
  }
};

Glob Pattern Support

The CLI supports powerful glob patterns for flexible file selection.

Glob Pattern Examples:

# Match all JavaScript files recursively
i18next-scanner 'src/**/*.js'

# Match multiple file types
i18next-scanner 'src/**/*.{js,jsx,ts,tsx}'

# Match specific directories
i18next-scanner 'src/components/**/*.jsx' 'src/pages/**/*.jsx'

# Exclude patterns with negation
i18next-scanner 'src/**/*.js' '!src/**/*.test.js' '!src/**/*.spec.js'

# Match files in root directory only
i18next-scanner 'src/*.js'

# Match with single character wildcard
i18next-scanner 'src/page?.js'  # Matches page1.js, pageA.js, etc.

Environment Integration

Package.json Scripts:

{
  "scripts": {
    "i18n:scan": "i18next-scanner",
    "i18n:scan-dev": "i18next-scanner --config i18next-scanner.dev.js",
    "i18n:scan-prod": "i18next-scanner --config i18next-scanner.prod.js --output ./dist/locales",
    "i18n:watch": "nodemon --watch src --ext js,jsx,ts,tsx --exec \"npm run i18n:scan\""
  }
}

CI/CD Integration:

#!/bin/bash
# Extract translation keys
i18next-scanner --config production.config.js 'src/**/*.{js,jsx,ts,tsx}'

# Verify no untranslated keys in production build
if grep -r "__STRING_NOT_TRANSLATED__" locales/; then
  echo "Error: Found untranslated keys"
  exit 1
fi

Multiple Configuration Examples

Development Configuration:

// i18next-scanner.dev.js
module.exports = {
  input: ['src/**/*.{js,jsx}'],
  output: './dev-locales',
  options: {
    debug: true,
    defaultValue: '__DEV_PLACEHOLDER__',
    lngs: ['en'],
    ns: ['translation']
  }
};

Production Configuration:

// i18next-scanner.prod.js
module.exports = {
  input: [
    'src/**/*.{js,jsx,ts,tsx}',
    '!src/**/*.{test,spec}.{js,jsx,ts,tsx}'
  ],
  output: './dist/locales',
  options: {
    debug: false,
    sort: true,
    lngs: ['en', 'de', 'fr', 'es', 'ja'],
    ns: ['common', 'validation', 'navigation'],
    defaultValue: '',
    resource: {
      jsonIndent: 0, // Minified JSON for production
      lineEnding: '\\n'
    }
  }
};

Command Line Override

CLI arguments take precedence over configuration file settings for input files and output directory.

Usage Examples:

# Override input files (ignores config.input)
i18next-scanner --config prod.config.js 'custom/**/*.js'

# Override output directory (ignores config.output)  
i18next-scanner --output ./custom-output

# Use config for options but override input and output
i18next-scanner --config prod.config.js --output ./build/i18n 'src/critical/*.js'

Error Handling

The CLI provides helpful error messages for common issues:

Common Error Scenarios:

# Missing configuration file
$ i18next-scanner --config missing.config.js
# Error: Cannot find module '/path/to/missing.config.js'

# Invalid glob patterns
$ i18next-scanner 'invalid[pattern'
# Error: Invalid glob pattern

# No input files specified and no config
$ i18next-scanner
# Displays help and exits

# Invalid output directory permissions
$ i18next-scanner --output /restricted/path 'src/*.js'
# Error: Permission denied writing to output directory

Output Format

The CLI generates translation resource files in the specified output directory with the configured structure.

Default Output Structure:

output/
├── i18n/
│   ├── en/
│   │   ├── translation.json
│   │   └── validation.json
│   ├── de/
│   │   ├── translation.json
│   │   └── validation.json
│   └── fr/
│       ├── translation.json
│       └── validation.json

Resource File Format:

{
  "welcome": "Welcome!",
  "user": {
    "name": "Name",
    "email": "Email"
  },
  "button": {
    "save": "Save",
    "cancel": "Cancel"
  },
  "validation": {
    "required": "This field is required",
    "email": "Please enter a valid email"
  }
}