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 🙏

© 2025 – Pkg Stats / Ryan Hefner

aidiomix

v2.2.32

Published

AI powered translation tool

Downloads

3,253

Readme

Documentation for the aidiomix library

Introduction

aidiomix is an AI-driven translation tool designed to facilitate the management and generation of translations for your projects. It offers integration with multiple AI services to automate the translation of textual content found in your source files.

Before starting

aidiomix suppose that you already have installed a translation library like i18next or react-i18n.

When you are coding a new page or component, instead of having to choose a translation key that fits the string you want to translate, and go manualy update all your translation files, you just have to write the string in your component in the language you want,

...and let aidiomix do the work.

Example:


const MyComponent = () => {

  return <div>Bonjour tout le monde</div>;
};

aidiomix will choose a key for you and update your translation files and your code.


const MyComponent = () => {

  return <div>{t('hello_world')}</div>;
};

In this case, you need to add the useTranslation hook to your component to use the translations.

Installation

Install aidiomix using npm:

npm install aidiomix

Configuration

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', // 'full-path' | 'filename' | 'x-first-parent' | 'x-last-parent' | 'global' | 'content-hash'
  
  // Optional: Namespace file organization strategy (default: 'single-file')
  // 'single-file': All namespaces in one file per language (e.g., locales/en/translation.json)
  // 'separate-files': One file per namespace per language (e.g., locales/en/translation.common.json, locales/en/translation.buttons.json)
  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')}")
    // $key will be replaced with the translation key
    replacementPattern: "{t('$key')}", // Examples: "t('$key')", "{formatMessage({ id: '$key' })}"
    
    // Functions to detect (defaults based on translationFormat)
    translationFunctions: ['t', 'i18n.t'], // Optional: override defaults
    
    // Rich text components to detect (defaults based on translationFormat)
    richTextComponents: ['Trans'], // Optional: override defaults
    
    // Enable detection of untranslated JSX text (default: true)
    detectUntranslatedJSX: true,
    
    // Custom detection rules for specific patterns
    customRules: [
      {
        // Regex pattern to match
        pattern: /STATUS_LABELS\[(\w+)\]\s*=\s*"([^"]+)"/g,
        
        // Optional: Custom processor function
        processor: (detectedString, match) => {
          return {
            stringToResolve: match[2], // The text to translate
            variables: [] // Optional: list of variables
          };
        },
        
        // Priority (higher = processed first, default: 0)
        priority: 10
      }
    ]
  },
  
  // Deprecated: Use textDetection.translationFormat instead
  translationFormat: 'i18next',
  
  // Deprecated: Use textDetection.replacementPattern instead
  translationFunction: 't'
};

Configuration Options

Required Options

  • languages (string[]): Array of language codes to translate to (e.g., ['en', 'fr', 'es'])
  • localesPath (string): Path pattern for locale files. Use {lang} as placeholder (e.g., './locales/{lang}/translation.json')
  • sourceDirectories (string[]): Array of directories to scan for source files (e.g., ['./app', './components'])
  • apiKey (string): Your Aidiomix API key from the dashboard

Optional Options

  • namespaceStrategy (string): Namespace generation strategy (default: 'full-path')

  • namespaceFileStrategy (string): How to organize namespace files (default: 'single-file')

    • 'single-file': All namespaces are stored in one file per language
      • Example: locales/en/translation.json contains all namespaces
      • Structure: { "namespace1": {...}, "namespace2": {...} }
    • 'separate-files': Each namespace gets its own file per language
      • Example: locales/en/translation.common.json, locales/en/translation.buttons.json
      • Each file contains only the translations for that namespace
      • Namespace dots (.) are replaced with dashes (-) in filenames
      • Example: namespace common.buttons → file translation.common-buttons.json

Text Detection Configuration (textDetection)

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

  • translationFormat (string): Translation library format

    • 'i18next' (default): For i18next/react-i18next
    • 'react-intl': For react-intl
    • 'next-intl': For next-intl
  • replacementPattern (string): Pattern for replacing detected JSX text

    • Default: "{t('$key')}"
    • $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 (string[]): 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 (string[]): Rich text components to detect

    • Defaults based on translationFormat:
      • i18next: ['Trans']
      • react-intl: ['FormattedMessage', 'FormattedNumber', 'FormattedDate']
      • next-intl: []
  • detectUntranslatedJSX (boolean): Enable detection of untranslated JSX text (default: true)

  • customRules (TextDetectionRule[]): 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)

Deprecated Options (for backward compatibility)

  • translationFormat: Use textDetection.translationFormat instead
  • translationFunction: Use textDetection.replacementPattern instead

Namespace Strategy

aidiomix automatically organizes translations using namespaces based on the file structure. This helps keep your translations organized and prevents key conflicts.

You can configure the namespace strategy in your aidiomix.config.cjs file using the namespaceStrategy option.

Configuration

Add the namespaceStrategy option to your configuration:

module.exports = {
  languages: ['en', 'fr', 'es'],
  localesPath: './locales/{lang}/translation.json',
  sourceDirectories: ['./app', './components'],
  apiKey: 'YOUR_API_KEY',
  translationFunction: 't',
  namespaceStrategy: 'full-path', // or 'filename', 'first-parent', 'last-parent', 'global', 'content-hash'
};

Available Strategies

1. Full Path (default: 'full-path')

Uses the complete file path relative to sourceDirectories as the namespace.

Example:

  • File: ./app/components/ui/Button.tsx
  • Namespace: components.ui.Button
  • Translation key: components.ui.Button.hello_world

Pros:

  • Automatic organization by file structure
  • No key conflicts between different files
  • Easy to navigate and find translations

Cons:

  • Namespace changes when files are moved
  • Can create long namespaces for deeply nested files

2. Filename Only ('filename')

Uses only the filename (without path or extension) as the namespace.

Example:

  • File: ./app/components/ui/Button.tsx
  • Namespace: Button
  • Translation key: Button.hello_world

Pros:

  • Namespace never changes when moving files
  • Simple and readable

Cons:

  • Risk of key conflicts if multiple files have the same name
  • Less organization for large projects

3. X First Parent Directories ('x-first-parent')

Uses the first X parent directories as the namespace. Replace x with the number of directories you want.

Examples:

  • '1-first-parent': File ./app/components/ui/Button.tsx → Namespace: components (1 parent, filename excluded)
  • '2-first-parent': File ./app/components/ui/Button.tsx → Namespace: components.ui (2 parents, filename excluded)
  • '3-first-parent': File ./app/components/ui/Button.tsx → Namespace: components.ui (only 2 parents available, filename excluded)

Pros:

  • Flexible - choose exactly how many parent directories to include
  • More stable than full path
  • Good for organizing by top-level directories
  • Can include filename by using a higher number

Cons:

  • Still changes if moving between different parent directories
  • Need to choose the right number for your project structure

4. X Last Parent Directories ('x-last-parent')

Uses the last X parent directories (including filename) as the namespace. Replace x with the number of directories you want.

Examples:

  • '1-last-parent': File ./app/components/ui/Button.tsx → Namespace: Button (1 element: filename only)
  • '2-last-parent': File ./app/components/ui/Button.tsx → Namespace: ui.Button (2 elements: 1 parent + filename)
  • '2-last-parent': File ./app/[lang]/client/campaigns/[id]/page.tsx → Namespace: campaigns.id (2 elements: 1 parent + filename, normalized from campaigns.[id])
  • '3-last-parent': File ./app/components/ui/Button.tsx → Namespace: components.ui.Button (3 elements: 2 parents + filename)

Pros:

  • Flexible - choose exactly how many parent directories to include
  • Handles dynamic route segments well (e.g., [lang], [id])
  • More stable than full path
  • Ideal for Next.js App Router projects
  • Always includes the filename as the last part

Cons:

  • Still changes if moving between different parent directories
  • Need to choose the right number for your project structure

Handling Dynamic Route Segments: For files with dynamic route segments like [lang], [id], or [...slug], the brackets are automatically removed:

  • [lang]lang
  • [id]id
  • [...slug]slug

5. Global Namespace ('global')

No namespace prefix - all translations are at the root level.

Example:

  • File: ./app/components/Button.tsx
  • Namespace: `` (empty)
  • Translation key: hello_world (no namespace prefix)

JSON structure:

{
  "hello_world": "Hello World",
  "click_me": "Click me"
}

Pros:

  • Simple, no namespace management
  • Shorter translation keys

Cons:

  • High risk of key conflicts
  • Harder to organize large projects
  • Not recommended for projects with many files

6. Content-Based Hash ('content-hash')

Uses a hash of the file content to create a stable namespace.

Example:

  • File: ./app/components/Button.tsx
  • Namespace: a1b2c3d4 (first 8 characters of MD5 hash)
  • Translation key: a1b2c3d4.hello_world

Pros:

  • Very stable - namespace never changes unless file content changes
  • No conflicts between different files

Cons:

  • Not human-readable
  • Harder to understand and navigate
  • Namespace changes if file content changes significantly

Explicit Namespace Comment

Regardless of the configured strategy, you can override the namespace by adding a comment at the top of your file:

Single-line comment:

// @namespace: common.buttons
// or
// @aidiomix-namespace: common.buttons

Multi-line comment:

/* @namespace: common.buttons */
/* or */
/* @aidiomix-namespace: common.buttons */

Example:

// @namespace: shared.components
const Button = () => {
  return <div>Hello World</div>;
};

The explicit namespace takes precedence over the configured strategy. This is useful when:

  • You want to group translations from multiple files under the same namespace
  • You need a specific namespace that doesn't match the file structure
  • You want to ensure stability regardless of file location

Per-Key Namespace Override

You can also specify a namespace for individual translation keys by combining directives on the same line:

Syntax:

// @aidiomix-translate @aidiomix-namespace: <namespace>
// or
// @translate @namespace: <namespace>

Examples:

// String literals
const message = "Hello"; // @aidiomix-translate @aidiomix-namespace: common
const button = "Click me"; // @translate @namespace: buttons

// JSX text
<div>
  {/* @aidiomix-translate @aidiomix-namespace: common */}
  Hello World
</div>

// JSX attributes
<Input 
  placeholder="Search..." // @aidiomix-translate @aidiomix-namespace: forms
/>

Behavior:

  • The per-key namespace takes precedence over both the file-level namespace comment and the configured strategy
  • If no per-key namespace is specified, the file-level namespace (or strategy) is used
  • Multiple directives can be combined on the same line
  • Useful when you want specific keys to be grouped differently from the rest of the file

Example with mixed namespaces:

// File-level namespace: components.Button (from strategy)
const Button = () => {
  const title = "Welcome"; // Uses file namespace: components.Button.text_xxx
  const commonText = "Hello"; // @aidiomix-translate @aidiomix-namespace: common
  // Uses specific namespace: common.text_xxx
  
  return (
    <div>
      <h1>{title}</h1>
      <p>{commonText}</p>
    </div>
  );
};

Choosing the Right Strategy

Use full-path (default) when:

  • Files are rarely moved
  • You want maximum organization and no conflicts
  • You have a stable project structure

Use filename when:

  • Files are frequently moved
  • You have unique filenames across your project
  • You want simple, readable namespaces

Use x-first-parent when:

  • You organize code by top-level directories (e.g., components/, pages/, features/)
  • You want moderate stability with some organization
  • You want to control exactly how many parent directories to include
  • Example: '1-first-parent' for top-level only, '2-first-parent' for two levels

Use x-last-parent when:

  • You're using Next.js App Router with dynamic routes
  • You want good organization with better stability than full-path
  • You need to handle files with dynamic segments like [id] or [lang]
  • You want to control exactly how many parent directories to include from the end
  • Example: '2-last-parent' is often a good default (includes parent + filename)

Use global when:

  • You have a small project with few files
  • You want the simplest possible setup
  • You're okay managing potential key conflicts manually

Use content-hash when:

  • You need maximum stability regardless of file location
  • You don't need human-readable namespaces
  • You're building a tool or library where namespace readability isn't important

Text Detection Features

Automatic Detection

aidiomix automatically detects translatable text in the following contexts:

  1. JSX Text Content: Text directly inside JSX elements

    <div>Hello World</div>  // ✅ Detected
  2. JSX Attributes: Common attributes that contain user-facing text

    • placeholder - Input placeholders
    • title - Tooltips and titles
    • alt - Image alt text
    • aria-label - Accessibility labels
    • aria-describedby - Accessibility descriptions
    • label - Form labels
    <Input placeholder="Search..." />  // ✅ Detected
    <img alt="User avatar" />          // ✅ Detected
    <button title="Click me">          // ✅ Detected
  3. String Literals: String values in your code

    const message = "Welcome";  // ✅ Detected

Manual Tagging with Comments

You can explicitly control which texts should be translated using inline comments:

Force Translation

Use comments to mark texts that might not be automatically detected:

Syntax options:

  • // use translate or // @translate or // @t
  • /* use translate */ or /* @translate */
  • // @aidiomix-translate or /* @aidiomix-translate */

Examples:

// In attributes
<Input 
  value="ACTIVE" // @translate
  placeholder="[email protected]" // @no-translate
/>

// In string literals
const statusLabels = {
  ACTIVE: "Active", // @translate
  INACTIVE: "Inactive", // @translate
};

// In JSX text
<div>
  {/* @translate */}
  Technical term that should be translated
</div>

// In expressions
{status === "ACTIVE" ? (
  "Actif" // @translate
) : (
  "Inactif" // @translate
)}

Multiple Directives on Same Line

You can combine multiple directives on the same line, such as specifying a namespace for a specific key:

Syntax:

// @aidiomix-translate @aidiomix-namespace: <namespace>
// or
// @translate @namespace: <namespace>

Examples:

// String literals with namespace
const message = "Hello"; // @aidiomix-translate @aidiomix-namespace: common
const button = "Click me"; // @translate @namespace: buttons

// JSX text with namespace
<div>
  {/* @aidiomix-translate @aidiomix-namespace: common */}
  Hello World
</div>

// JSX attributes with namespace
<Input 
  placeholder="Search..." // @aidiomix-translate @aidiomix-namespace: forms
/>

This allows you to override the namespace for individual keys, giving you fine-grained control over how translations are organized.

Exclude from Translation

Use comments to prevent automatic detection of technical text:

Syntax options:

  • // @no-translate or // @skip-translation or // @notranslate
  • /* @no-translate */

Examples:

<Input placeholder="https://exemple.com" // @no-translate
<Input placeholder="[email protected]" // @skip-translation

Detection Rules

aidiomix uses intelligent heuristics to distinguish translatable text from technical values:

Automatically excluded:

  • URLs (https://example.com)
  • Email addresses (standalone)
  • Purely numeric values
  • Technical attributes (href, src, className, onClick, etc.)

Automatically included:

  • Text with spaces and letters (natural language)
  • Text with accented characters (likely French, Spanish, etc.)
  • Text with sentence punctuation (. ! ?)
  • Multiple words (more than 2 words)
  • Attributes in the translatable list (see above)

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')

Usage

Parse and translate files

To generate the translation files, run the following command:

npx aidiomix parse

This will parse the files and extract the non-translated strings Then it will translate them into the supported languages Then it will use IA to choose appropriate keys for the translations Then it will update the translation files with the new translations Then it will replace the non-translated strings with the new keys

Parse a single file

To parse and translate a single file, use the parse-file command:

npx aidiomix parse-file <filepath>

For example:

npx aidiomix parse-file src/components/Button.tsx

This command will:

  1. Parse the specified file and extract non-translated strings
  2. Translate them into all configured languages
  3. Generate appropriate translation keys using AI
  4. Update the translation files with the new translations
  5. Replace the non-translated strings in the file with the translation keys

This is useful when you want to process a specific file without parsing all files in your source directories.

Clean unused translation keys

To remove unused translation keys from your language files, run:

npx aidiomix clean

This command will:

  1. Scan all source files in your sourceDirectories to find all used translation keys
  2. Compare them with the keys in your language files
  3. Remove any keys that are not used in your code
  4. Clean up empty namespace objects after key removal

This is useful for keeping your translation files clean and removing keys that are no longer needed after refactoring or removing features.