Automatic Pluralization

@lingo.dev/compiler automatically detects plural forms in your text and converts them to ICU MessageFormat for proper pluralization across languages.

What It Does

The compiler uses AI to detect when text contains plural forms (e.g., "1 item" vs "5 items") and converts them to ICU MessageFormat syntax.

Before (your code):

<p>You have {count} items</p>

After (compiled):

<p>{count, plural, one {You have 1 item} other {You have # items}}</p>

Different languages have different plural rules. Arabic has 6 forms, Russian has 4, English has 2. ICU MessageFormat handles all of them correctly.

How It Works

  1. Compiler detects interpolations with numeric values
  2. Sends text to LLM for plural form detection
  3. LLM returns ICU MessageFormat pattern if pluralization detected
  4. Compiler injects plural-aware translation

This happens automatically—no code changes needed.

Configuration

{
  pluralization: {
    enabled: true, // Default: true
    model: "groq:llama-3.1-8b-instant", // Fast model for plural detection
  }
}

Model: Uses a separate (fast) model for plural detection to keep costs low. Default is Groq's fastest model.

Examples

Simple Plurals

<p>You have {count} items in your cart</p>

Becomes:

{count, plural,
  one {You have 1 item in your cart}
  other {You have # items in your cart}
}

Zero Form

<p>You have {unreadCount} unread messages</p>

Becomes:

{unreadCount, plural,
  =0 {You have no unread messages}
  one {You have 1 unread message}
  other {You have # unread messages}
}

Complex Plurals

<p>{days} days and {hours} hours remaining</p>

Becomes:

{days, plural,
  one {1 day}
  other {# days}
} and {hours, plural,
  one {1 hour}
  other {# hours}
} remaining

Language-Specific Rules

ICU MessageFormat handles complex plural rules automatically:

English (2 forms):

  • one: 1 item
  • other: 0 items, 2 items, 100 items

Russian (4 forms):

  • one: 1, 21, 31, 41... (оди́н элеме́нт)
  • few: 2-4, 22-24... (два элеме́нта)
  • many: 0, 5-20, 25-30... (пять элеме́нтов)
  • other: 1.5, 2.5... (1.5 элеме́нта)

Arabic (6 forms):

  • zero: 0
  • one: 1
  • two: 2
  • few: 3-10
  • many: 11-99
  • other: 100+

The compiler generates correct forms for each target locale.

Disabling Pluralization

If your app doesn't use plural forms or you want to handle them manually:

{
  pluralization: {
    enabled: false,
  }
}

This skips plural detection entirely, reducing LLM calls.

Manual Plural Forms

You can write ICU MessageFormat directly in your code:

<p>
  {formatMessage(
    { id: "items", defaultMessage: "{count, plural, one {# item} other {# items}}" },
    { count }
  )}
</p>

The compiler won't try to detect plurals—it uses your exact format.

Performance

Plural detection adds a small overhead:

  • One extra LLM call per unique text with numeric interpolations
  • Uses fast model (default: Groq llama-3.1-8b-instant)
  • Results are cached—subsequent builds reuse detections

Cost: Negligible. Fast models cost fractions of a cent per request.

Common Questions

Does this work for all languages? Yes. ICU MessageFormat supports 200+ languages with proper plural rules.

What if the AI gets it wrong? Use data-lingo-override to specify exact translations with correct plural forms:

<p data-lingo-override={{
  es: "{count, plural, one {1 artículo} other {# artículos}}"
}}>
  {count} items
</p>

Can I customize the plural detection model? Yes. Set pluralization.model to any supported LLM. Default is optimized for speed and cost.

Does this increase bundle size? Slightly. ICU MessageFormat patterns are a bit larger than simple strings. Impact is minimal.

What about nested plurals? Supported. The compiler handles multiple pluralized variables in the same string.

Do I need to mark plural forms? No. The compiler detects them automatically when pluralization.enabled: true.

Debugging

To see detected plural forms, check .lingo/metadata.json:

{
  "translations": {
    "abc123": {
      "source": "You have {count} items",
      "pattern": "{count, plural, one {You have 1 item} other {You have # items}}",
      "locales": {
        "es": "{count, plural, one {Tienes 1 artículo} other {Tienes # artículos}}"
      }
    }
  }
}

The pattern field shows the ICU MessageFormat detected by the compiler.

Next Steps