Internationalization (i18n)
Make your app work in multiple languages. Angular has a built-in i18n pipeline for extraction and translation, or you can build a simpler runtime service with signals.
i18n (internationalization) is the process of making your app work in multiple languages and locales. The name comes from "i" + 18 letters + "n" in the word "internationalization."
"i18n = multi-language support — Hyderabadi, English, Hindi, Telugu."
Two approaches:
- Angular i18n — built-in, extract-and-build pipeline, separate builds per language
- Simple runtime service — custom translation service with signals, single build, runtime switching
Angular's i18n is powerful but requires separate builds per language (5 languages = 5 builds). The simple service approach swaps translations at runtime with signals — great for small-to-medium apps.
Angular's i18n uses a 4-step pipeline:
Step 1: Mark text in templates
<h1 i18n>Welcome to Biryani Hub</h1>
<p i18n>Order the best biryani in Hyderabad!</p>
Step 2: Extract translatable text
# Terminal:
ng extract-i18n --output-path src/locale
# Generates: src/locale/messages.xlf
Step 3: Translate
<!-- messages.hi.xlf (Hindi) -->
<trans-unit id="123">
<source>Welcome to Biryani Hub</source>
<target>बिरयानी हब में आपका स्वागत है</target>
</trans-unit>
Step 4: Build for each language
# Terminal:
ng build --localize
# Builds separate output for each language
# dist/en/, dist/hi/, dist/te/
"Mark → Extract → Translate → Build — 4 step process."
Configure languages in angular.json:
"i18n": {
"sourceLocale": "en",
"locales": {
"hi": "src/locale/messages.hi.xlf",
"te": "src/locale/messages.te.xlf"
}
}Angular provides several i18n directives for templates:
Simple text:
<h1 i18n>Welcome to Biryani Shop</h1>
With meaning and description (for translators):
<h1 i18n="main.title|Main page heading@@mainTitle">Welcome</h1>
<!-- @@mainTitle = unique ID -->
<!-- main.title = meaning -->
<!-- |Main page heading = description for translators -->
Pluralization:
<span i18n>{count, plural,
=0 {no biryanis available}
=1 {one biryani available}
other {{{count}} biryanis available}
}</span>
Gender/selection:
<span i18n>{gender, select,
male {He ordered biryani}
female {She ordered biryani}
other {They ordered biryani}
}</span>
"i18n attribute = translatable mark — Angular isko extract karega." Meaning aur description translators ko context dete hain. Pluralization alag languages mein alag plural rules handle karta hai.
Not just text — element attributes can also be translated:
<!-- Attribute i18n -->
<input i18n-placeholder placeholder="Enter your name" />
<img i18n-alt alt="A plate of Hyderabadi Biryani" />
<button i18n-title title="Click to place your order">Order</button>
<a i18n-aria-label aria-label="Back to home page" href="/">Back</a>
<!-- Dynamic attributes -->
<input [placeholder] i18n-placeholder placeholder="Search biryanis..." />
"Attributes bhi translate karo — placeholder, alt, title, aria-label sab."
Important: The attribute-name follows the pattern i18n-{attributeName}. For dynamic values, use [placeholder] i18n-placeholder together — the i18n- prefix marks it for extraction, while [placeholder] binds the value.
For small-to-medium apps (10-50 strings), Angular's full i18n pipeline with separate builds may be overkill. Here's a simple translation service with signals:
import { Injectable, signal, computed } from '@angular/core';
type Lang = 'en' | 'hi' | 'te' | 'ur';
const TRANSLATIONS: Record<Lang, Record<string, string>> = {
en: {
welcome: 'Welcome to Biryani Hub',
order: 'Order Now',
biryaniCount: (count: number) => `${count} biryani(s)`
},
hi: {
welcome: 'बिरयानी हब में आपका स्वागत है',
order: 'अभी ऑर्डर करें',
biryaniCount: (count: number) => `${count} बिरयानी`
},
te: {
welcome: 'బిర్యానీ హబ్కు స్వాగతం',
order: 'ఇప్పుడే ఆర్డర్ చేయండి',
biryaniCount: (count: number) => `${count} బిర్యానీ`
}
};
@Injectable({ providedIn: 'root' })
export class TranslateService {
private currentLang = signal<Lang>('en');
readonly lang = this.currentLang.asReadonly();
setLang(lang: Lang) { this.currentLang.set(lang); }
t(key: string, params?: Record<string, any>): string {
const translation = TRANSLATIONS[this.currentLang()][key];
if (!translation) return key;
if (typeof translation === 'function') return translation(params);
return translation;
}
}
// In component:
// <h1>{{ translate.t('welcome') }}</h1>
// <button (click)="translate.setLang('hi')">हिन्दी</button>
"Simple approach = apna chhota translator — bada system ki zaroorat nahi for 10-20 strings."
When to use which: Angular i18n for large apps with professional translation teams. Simple service for small apps, MVPs, or when you need runtime language switching.
Key Takeaways
- ✅ i18n = internationalization — making your app work in multiple languages
- ✅ Angular i18n: mark with i18n attribute, extract, translate, build --localize
- ✅ Support: text, plurals, gender/select, attributes (placeholder, alt, title)
- ✅ Angular i18n creates separate builds per language
- ✅ Simple alternative: TranslateService with signals for runtime switching
- ✅ For small apps: use simple service. For large apps: use Angular i18n
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login