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.
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
}
]
}
};
languages (string[]): Array of language codes to translate tolocalesPath (string): Path pattern for locale files. Use {lang} as placeholdersourceDirectories (string[]): Array of directories to scan for source filesapiKey (string): Your Aidiomix API key from the dashboardnamespaceStrategy: See Namespace Strategy for detailsnamespaceFileStrategy: 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)The textDetection object allows you to customize how aidiomix detects and processes translatable text.
Translation library format:
'i18next' (default): For i18next/react-i18next'react-intl': For react-intl'next-intl': For next-intlPattern 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-intlFunctions to detect as translation calls. Defaults based on translationFormat:
['t', 'i18n.t', 'i18next.t']['formatMessage', 't', 'intl.formatMessage']['t', 'useTranslations().t']Rich text components to detect. Defaults based on translationFormat:
['Trans']['FormattedMessage', 'FormattedNumber', 'FormattedDate'][]Enable detection of untranslated JSX text (default: true)
Custom detection rules for specific patterns. Each rule has:
pattern: RegExp or string pattern to matchprocessor (optional): Function to process the match and extract the text to translatepriority (optional): Priority number (higher = processed first)module.exports = {
languages: ['en', 'fr', 'es'],
localesPath: './locales/{lang}/translation.json',
sourceDirectories: ['./app', './components'],
apiKey: 'YOUR_API_KEY',
textDetection: {
translationFormat: 'i18next',
replacementPattern: "{t('$key')}",
}
};
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' })}",
}
};
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')}",
}
};
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:
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.
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');
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');
Add comments to provide context for translators:
// Submit button in the checkout form
const submitLabel = "Submit Order"; // @translate
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')