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 (
devsd’) - Returns the full localized string
- Determines the correct article (
- 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.