Angular’s internationalization (i18n) capabilities are comprehensive, enabling developers to build multilingual applications that adapt content dynamically. One of the key features of Angular i18n is alternative expressions, which allow developers to manage conditional content in templates based on logical conditions or numeric values.
This article explores Angular i18n’s support for alternative expressions, such as select
and selectordinal
, detailing how they work, their use cases, and best practices.
What are Alternative Expressions?
Alternative expressions provide a way to handle conditional content dynamically in Angular i18n templates. Angular supports the following types:
select
: Used for conditional text based on predefined keys or values.selectordinal
: Used for ordinal numbers (e.g., “1st”, “2nd”, “3rd”).
These expressions follow the ICU (International Components for Unicode) syntax, allowing developers to define content variations based on logical conditions.
1. Using select
for Conditional Content
The select
expression is useful for managing content that varies based on a condition, such as gender, roles, or status.
Syntax
htmlCopy code{variable, select,
key1 {Text for key1}
key2 {Text for key2}
other {Default text}
}
Example: Greeting Based on Gender
Template:
htmlCopy code<p i18n>
{gender, select,
male {Hello, Mr. {{ name }}!}
female {Hello, Ms. {{ name }}!}
other {Hello, {{ name }}!}
}
</p>
Component:
typescriptCopy code@Component({
selector: 'app-greeting',
templateUrl: './greeting.component.html',
})
export class GreetingComponent {
gender: 'male' | 'female' | 'other' = 'male';
name = 'John';
}
Output:
- If
gender = 'male'
:Hello, Mr. John!
- If
gender = 'female'
:Hello, Ms. John!
- If
gender = 'other'
:Hello, John!
2. Using selectordinal
for Ordinal Numbers
The selectordinal
expression is used to handle ordinal content, such as “1st”, “2nd”, “3rd”, etc., with localization for different languages.
Syntax
htmlCopy code{variable, selectordinal,
=0 {No items}
one {1st item}
two {2nd item}
few {3rd item}
other {#th item}
}
Example: Ranking Items
Template:
htmlCopy code<p i18n>
{rank, selectordinal,
one {You are in 1st place.}
two {You are in 2nd place.}
few {You are in 3rd place.}
other {You are in #th place.}
}
</p>
Component:
typescriptCopy code@Component({
selector: 'app-ranking',
templateUrl: './ranking.component.html',
})
export class RankingComponent {
rank = 4;
}
Output:
- If
rank = 1
:You are in 1st place.
- If
rank = 2
:You are in 2nd place.
- If
rank = 3
:You are in 3rd place.
- If
rank = 4
:You are in 4th place.
Adding Alternative Expressions to Translation Files
When you extract messages using ng extract-i18n
, Angular generates ICU expressions in the translation file.
Example Generated File:
xmlCopy code<trans-unit id="greeting_message" datatype="html">
<source>{gender, select, male {Hello, Mr. {{ name }}!} female {Hello, Ms. {{ name }}!} other {Hello, {{ name }}!}}</source>
</trans-unit>
<trans-unit id="ranking_message" datatype="html">
<source>{rank, selectordinal, one {1st place} two {2nd place} few {3rd place} other {#th place}}</source>
</trans-unit>
Best Practices for Using Alternative Expressions
- Use Meaningful Context
- Provide clear descriptions for translators to understand the context of each expression.
- Keep Expressions Simple
- Avoid overly complex logic inside ICU expressions for readability and maintainability.
- Test Localization
- Test alternative expressions thoroughly in different locales to ensure they display correctly.
- Fallback for Missing Keys
- Always define a default (
other
) case to handle unexpected values.
- Always define a default (
- Combine with Pluralization
- Use
select
andselectordinal
in combination with pluralization for more dynamic content.
- Use
Real-World Example: Combining Pluralization and Select
Template:
htmlCopy code<p i18n>
{gender, select,
male {{count, plural, =0 {Mr. {{name}} has no messages.} =1 {Mr. {{name}} has one message.} other {Mr. {{name}} has # messages.}}}
female {{count, plural, =0 {Ms. {{name}} has no messages.} =1 {Ms. {{name}} has one message.} other {Ms. {{name}} has # messages.}}}
other {{count, plural, =0 {{name}} has no messages.} =1 {{name}} has one message.} other {{name}} has # messages.}}
}
</p>
Component:
typescriptCopy code@Component({
selector: 'app-messages',
templateUrl: './messages.component.html',
})
export class MessagesComponent {
gender: 'male' | 'female' | 'other' = 'female';
name = 'Jane';
count = 3;
}
Output:
- If
gender = 'female'
andcount = 3
:Ms. Jane has 3 messages.
Common Pitfalls and How to Avoid Them
- Missing
other
Case- Without an
other
case, undefined values will cause errors. Solution: Always include a fallbackother
case.
- Without an
- Misplaced Braces
- ICU syntax can be sensitive to formatting errors. Solution: Use proper indentation and structure.
- Context Confusion
- Translators may misinterpret expressions without clear notes. Solution: Add context descriptions in the
i18n
attribute.
- Translators may misinterpret expressions without clear notes. Solution: Add context descriptions in the
Conclusion
Angular i18n’s support for alternative expressions like select
and selectordinal
empowers developers to create dynamic and localized content easily. By combining these expressions with pluralization and ICU syntax, you can build applications that adapt seamlessly to diverse linguistic and cultural contexts.