Text Detection

aidiomix automatically detects translatable text in your codebase using a priority-based system.

Detection Priority

  1. Explicit comments (@aidiomix-translate) - Highest priority
  2. Translation function calls (t('text'), formatMessage(), etc.)
  3. Rich text components (<Trans>, <FormattedMessage>, etc.)
  4. Untranslated JSX text (if enabled)
  5. Custom rules (if configured)

Automatic Detection

JSX Text Content

Text directly inside JSX elements is automatically detected:

<div>Hello World</div>  // ✅ Detected

JSX Attributes

Common attributes that contain user-facing text are automatically detected:

  • 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

Translation Function Calls

Functions configured in translationFunctions are automatically detected:

// i18next
{t('Hello World')}
i18n.t('Welcome')

// react-intl
formatMessage({ id: 'greeting' })
intl.formatMessage({ defaultMessage: 'Hello' })

// next-intl
t('Hello World')

Rich Text Components

Components configured in richTextComponents are automatically detected:

// i18next
<Trans i18nKey="greeting">Hello World</Trans>

// react-intl
<FormattedMessage id="greeting" defaultMessage="Hello World" />

Manual Tagging with Comments

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

Force Translation

Use @aidiomix-translate (or @translate, @t) to mark texts that might not be automatically detected:

// In attributes
<Input 
  value="ACTIVE" // @aidiomix-translate
  placeholder="vous@exemple.com" // @no-translate
/>

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

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

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

Multiple Directives on Same Line

You can combine multiple directives on the same line to specify both translation and namespace:

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. See the Namespace Strategy documentation for more details.

Exclude from Translation

Use @no-translate (or @skip-translation, @notranslate) to prevent automatic detection:

<Input placeholder="https://exemple.com" // @no-translate
<Input placeholder="vous@exemple.com" // @skip-translation

Custom Detection Rules

You can define custom rules for specific patterns in your codebase:

textDetection: {
  customRules: [
    {
      // Detect status labels in Record objects
      pattern: /STATUS_LABELS\[(\w+)\]\s*=\s*"([^"]+)"/g,
      processor: (detectedString, match) => {
        return {
          stringToResolve: match[2] // The label value
        };
      },
      priority: 10
    },
    {
      // Detect error messages
      pattern: /throw\s+new\s+Error\(["']([^"']+)["']\)/g,
      processor: (detectedString, match) => {
        return {
          stringToResolve: match[1]
        };
      },
      priority: 5
    }
  ]
}

Variables in Translations

When detecting text in translation function calls, variables are automatically preserved:

// Before
t('Hello {name}', { name: 'John' })

// After (only the string is replaced)
t('common.greeting', { name: 'John' })

Variables in the second argument are preserved automatically.

Best Practices

  1. Use comments sparingly: Let aidiomix detect automatically when possible
  2. Tag enum values: Use @aidiomix-translate for Record values that should be translated
  3. Exclude technical text: Use @no-translate for URLs, IDs, and technical identifiers
  4. Be explicit with edge cases: When in doubt, use comments to clarify intent
  5. Use custom rules for patterns: Define custom rules for recurring patterns in your codebase