How to add conditions to an i18n translation file

Summary

The issue arises because Angular i18n translation files cannot apply conditional grammar rules (like French elision de → d’ before a vowel) directly inside the translation unit. The translation system treats interpolations as opaque values, so it cannot inspect the first letter of {{country}}.

Root Cause

  • ICU expressions cannot evaluate string contents, only discrete values.
  • Angular i18n does not support regex or string‑based conditions inside translation files.
  • Interpolations are treated as atomic placeholders, not analyzable text.
  • French elision rules require runtime logic, which translation files cannot perform.

Why This Happens in Real Systems

  • Translation systems are designed for static text substitution, not linguistic transformations.
  • ICU MessageFormat supports pluralization and selection, but not string inspection.
  • Many languages require contextual grammar (elision, gender, declension), which cannot be expressed with simple key/value translations.
  • Frameworks avoid adding string‑processing features to translation files to prevent runtime complexity and non-deterministic translations.

Real-World Impact

  • Incorrect French output such as:
    • “Photos de Australie” instead of “Photos d’Australie”
  • Hard-to-maintain translation files when developers try to hack around the limitation.
  • Increased risk of inconsistent grammar across the UI.
  • Forces engineers to implement workarounds outside the translation layer.

Example or Code (if necessary and relevant)

A correct solution requires computing the article before passing the value to the translation:

getArticle(country: string): string {
  return /^[aeiouh]/i.test(country) ? "d’" : "de ";
}

Then in the template:

Photos {{ getArticle(country) }}{{ country }}

How Senior Engineers Fix It

  • Move grammar logic to the application layer, not the translation file.
  • Precompute a localized phrase or article before interpolation.
  • Provide translators with complete phrases, not fragments requiring logic.
  • Use custom pipes or helper functions to encapsulate linguistic rules.
  • Avoid mixing translation concerns with grammatical computation.

Typical robust approach:

  • Create a localizeCountryPhrase(country) function that:
    • Determines the correct article (de vs d’)
    • Returns the full localized string
  • Pass the final string into the translation as a single interpolation.

Why Juniors Miss It

  • They assume translation files can perform dynamic logic, similar to templates.
  • They misunderstand ICU as a general-purpose conditional language, not a limited selector.
  • They try to solve grammar problems inside the translation layer, which is not designed for it.
  • They expect translation systems to handle linguistic rules automatically, which is rarely the case.

If you want, I can also show a clean architecture pattern for handling grammar rules across multiple languages.

Leave a Comment