Lab 24: Internationalization (i18n)
📖 Resources
Section titled “📖 Resources”🚀 Starter Code
Section titled “🚀 Starter Code”album-wholesale-v17-signal-pre-jest
In this lab you will add multi-language support to the album wholesale app using Angular’s built-in i18n system. You will mark strings for translation, extract an XLIFF message file, provide a French translation, and build a localized bundle.
📝 Instructions
Section titled “📝 Instructions”Step 1: Mark Strings in Templates
Section titled “Step 1: Mark Strings in Templates”Add the i18n attribute to text elements:
<!-- Simple text --><h1 i18n="@@app.title">Album Store</h1>
<!-- With description for translators --><p i18n="Album count|Shows the number of albums@@album.count"> Available albums</p>
<!-- Attribute translation --><input type="search" i18n-placeholder="@@search.placeholder" placeholder="Search albums…"/>
<!-- Button --><button i18n="@@cart.add">Add to cart</button>Mark at least 5 strings across the app.
Step 2: Configure the Source Locale
Section titled “Step 2: Configure the Source Locale”In angular.json, add i18n configuration:
{ "projects": { "album-wholesale": { "i18n": { "sourceLocale": "en-US", "locales": { "fr": { "translation": "src/locale/messages.fr.xlf" } } } } }}Step 3: Extract the Message File
Section titled “Step 3: Extract the Message File”ng extract-i18n --format xlf2 --output-path src/localeThis generates src/locale/messages.xlf. Open the file — you will see each marked string as a <trans-unit>.
Step 4: Create the French Translation
Section titled “Step 4: Create the French Translation”Copy the source file and rename it:
cp src/locale/messages.xlf src/locale/messages.fr.xlfOpen messages.fr.xlf and add <target> elements for each unit:
<trans-unit id="app.title" datatype="html"> <source>Album Store</source> <target>Boutique d'Albums</target></trans-unit>
<trans-unit id="cart.add" datatype="html"> <source>Add to cart</source> <target>Ajouter au panier</target></trans-unit>
<trans-unit id="search.placeholder" datatype="html"> <source>Search albums…</source> <target>Rechercher des albums…</target></trans-unit>Translate all extracted units.
Step 5: Use Plural and Select Expressions
Section titled “Step 5: Use Plural and Select Expressions”<!-- Plural --><p i18n="@@cart.items"> {itemCount, plural, =0 {No items in cart} =1 {1 item in cart} other {{{itemCount}} items in cart} }</p>
<!-- Select (gender or category) --><span i18n="@@album.type"> {albumType, select, vinyl {Vinyl record} cd {Compact disc} other {Digital} }</span>Add French translations for these expressions in messages.fr.xlf:
<trans-unit id="cart.items" datatype="html"> <source> {itemCount, plural, =0 {No items in cart} =1 {1 item in cart} other {{{itemCount}} items in cart} } </source> <target> {itemCount, plural, =0 {Aucun article} =1 {1 article} other {{{itemCount}} articles} } </target></trans-unit>Step 6: Build with Localization
Section titled “Step 6: Build with Localization”Configure the build target in angular.json:
"build": { "configurations": { "fr": { "localize": ["fr"] }, "production": { "localize": true } }}Build all locales:
ng build --localizeInspect the dist/ folder — you should see browser/en-US/ and browser/fr/ subdirectories.
Step 7: Serve and Verify
Section titled “Step 7: Serve and Verify”Serve the French build locally:
cd dist/album-wholesale/browser/frnpx http-server -p 8080Open http://localhost:8080 and verify all marked strings appear in French.

