Configuration Guide

Quick Start

Step 1: Create an account and project

  1. Go to https://aidiomix.io and create an account
  2. Create a new project in the dashboard
  3. Copy your API key from the project settings

Step 2: Initialize configuration

Run the init command to create the configuration file:

npx aidiomix init

This will create a aidiomix.config.cjs file in the root of your project.

Step 3: Configure your project

Here's a complete example configuration:

module.exports = {
  // Required: Languages to translate to
  languages: ['en', 'fr', 'es', 'de', 'it'],
  
  // Required: Path pattern for locale files (use {lang} as placeholder)
  localesPath: './locales/{lang}/translation.json',
  
  // Required: Directories to scan for source files
  sourceDirectories: ['./app', './components'],
  
  // Required: Your Aidiomix API key (get it from the dashboard)
  apiKey: 'YOUR_API_KEY',
  
  // Optional: Namespace generation strategy (default: 'full-path')
  namespaceStrategy: 'full-path',
  
  // Optional: Namespace file organization strategy (default: 'single-file')
  // 'single-file': All namespaces in one file per language
  // 'separate-files': One file per namespace per language
  namespaceFileStrategy: 'single-file', // 'single-file' | 'separate-files'
  
  // Optional: Text detection configuration (recommended)
  textDetection: {
    // Translation format (determines defaults)
    translationFormat: 'i18next', // 'i18next' | 'react-intl' | 'next-intl'
    
    // Pattern for replacing detected JSX text (default: "{t('$key')}")
    replacementPattern: "{t('$key')}",
    
    // Functions to detect (defaults based on translationFormat)
    translationFunctions: ['t', 'i18n.t'],
    
    // Rich text components to detect (defaults based on translationFormat)
    richTextComponents: ['Trans'],
    
    // Enable detection of untranslated JSX text (default: true)
    detectUntranslatedJSX: true,
    
    // Custom detection rules for specific patterns
    customRules: [
      {
        pattern: /STATUS_LABELS\[(\w+)\]\s*=\s*"([^"]+)"/g,
        processor: (detectedString, match) => {
          return {
            stringToResolve: match[2],
            variables: []
          };
        },
        priority: 10
      }
    ]
  }
};

Configuration Options

Required Options

  • languages (string[]): Array of language codes to translate to
  • localesPath (string): Path pattern for locale files. Use {lang} as placeholder
  • sourceDirectories (string[]): Array of directories to scan for source files
  • apiKey (string): Your Aidiomix API key from the dashboard

Optional Options

  • namespaceStrategy: See Namespace Strategy for details
  • namespaceFileStrategy: How to organize namespace files
    • 'single-file' (default): All namespaces are stored in one file per language (e.g., locales/en/translation.json)
    • 'separate-files': Each namespace gets its own file per language (e.g., locales/en/translation.common.json, locales/en/translation.buttons.json)

Text Detection Configuration

The textDetection object allows you to customize how aidiomix detects and processes translatable text.

translationFormat

Translation library format:

  • 'i18next' (default): For i18next/react-i18next
  • 'react-intl': For react-intl
  • 'next-intl': For next-intl

replacementPattern

Pattern for replacing detected JSX text. $key will be replaced with the translation key.

Examples:

  • "{t('$key')}" for i18next
  • "{formatMessage({ id: '$key' })}" for react-intl
  • "{t('$key')}" for next-intl

translationFunctions

Functions to detect as translation calls. Defaults based on translationFormat:

  • i18next: ['t', 'i18n.t', 'i18next.t']
  • react-intl: ['formatMessage', 't', 'intl.formatMessage']
  • next-intl: ['t', 'useTranslations().t']

richTextComponents

Rich text components to detect. Defaults based on translationFormat:

  • i18next: ['Trans']
  • react-intl: ['FormattedMessage', 'FormattedNumber', 'FormattedDate']
  • next-intl: []

detectUntranslatedJSX

Enable detection of untranslated JSX text (default: true)

customRules

Custom detection rules for specific patterns. Each rule has:

  • pattern: RegExp or string pattern to match
  • processor (optional): Function to process the match and extract the text to translate
  • priority (optional): Priority number (higher = processed first)

Framework-Specific Examples

i18next

module.exports = {
  languages: ['en', 'fr', 'es'],
  localesPath: './locales/{lang}/translation.json',
  sourceDirectories: ['./app', './components'],
  apiKey: 'YOUR_API_KEY',
  textDetection: {
    translationFormat: 'i18next',
    replacementPattern: "{t('$key')}",
  }
};

react-intl

module.exports = {
  languages: ['en', 'fr', 'es'],
  localesPath: './locales/{lang}/translation.json',
  sourceDirectories: ['./app', './components'],
  apiKey: 'YOUR_API_KEY',
  textDetection: {
    translationFormat: 'react-intl',
    replacementPattern: "{formatMessage({ id: '$key' })}",
  }
};

next-intl

module.exports = {
  languages: ['en', 'fr', 'es'],
  localesPath: './locales/{lang}/translation.json',
  sourceDirectories: ['./app', './components'],
  apiKey: 'YOUR_API_KEY',
  textDetection: {
    translationFormat: 'next-intl',
    replacementPattern: "{t('$key')}",
  }
};

Best Practices

Avoid Variables in Translation Functions

For optimal parser performance, avoid using variables directly in translation functions. The parser cannot detect translation keys when they are stored in variables.

❌ Bad - Don't do this:

const label = 'button.label';
return t(label);  // Parser cannot detect this key

✅ Good - Use string literals:

return t('button.label');  // Parser can detect this key

Why this matters:

  • The parser scans your code statically and looks for string literals in translation functions
  • When you use variables, the parser cannot determine the actual translation key at parse time
  • This prevents the parser from:
    • Detecting unused translation keys
    • Tracking which keys are used in your codebase
    • Providing accurate translation management

Alternative approaches:

If you need dynamic keys, always pass them directly to the t() function. This ensures the clean command can properly detect and track all used keys:

// ❌ Bad - Parser and clean command cannot detect this
const statusKey = `status.${status}`;
return t(statusKey);

// ✅ Good - Pass template literal directly to t()
return t(`status.${status}`);  // Parser can detect the pattern

// ✅ Better - Use explicit keys with direct function calls
const statusKeys = {
  active: 'status.active',
  inactive: 'status.inactive',
  pending: 'status.pending'
};
return t(statusKeys[status]);  // More explicit, but clean may miss some keys

// ✅ Best - Pass keys directly to t() function
return status === 'active' 
  ? t('status.active')
  : status === 'inactive'
  ? t('status.inactive')
  : t('status.pending');

Important: The clean command scans your codebase to find unused translation keys. It can only detect keys that are passed directly as string literals or template literals to the t() function. Using intermediate variables or object lookups may cause the clean command to incorrectly mark keys as unused.

Use Explicit Translation Keys

Always prefer explicit, readable translation keys over dynamic generation:

❌ Bad:

const getKey = (type: string) => `common.${type}.label`;
return t(getKey('button'));

✅ Good:

return t('common.button.label');

Organize Translations by Feature

Group related translations using namespaces to keep your translation files organized:

✅ Good:

// In a button component
return t('components.Button.click_me');

// In a form component
return t('components.Form.submit');

Use Comments for Context

Add comments to provide context for translators:

// Submit button in the checkout form
const submitLabel = "Submit Order"; // @translate

Keep Translation Keys Descriptive

Use descriptive keys that clearly indicate the context:

❌ Bad:

t('key1')
t('text')
t('msg')

✅ Good:

t('checkout.submit_button')
t('user.profile.edit_button')
t('error.invalid_email')