typescript 41 lines · 8 steps

Locale-aware bootstrapping in Angular

Detect the user's locale at startup and wire Angular's currency and locale providers to match.

Explained by highlit
1import { registerLocaleData } from '@angular/common';
2import localeFr from '@angular/common/locales/fr';
3import localeFrExtra from '@angular/common/locales/extra/fr';
4import localeDe from '@angular/common/locales/de';
5import { LOCALE_ID, importProvidersFrom } from '@angular/core';
6import { bootstrapApplication } from '@angular/platform-browser';
7import { DEFAULT_CURRENCY_CODE } from '@angular/core';
8import { AppComponent } from './app/app.component';
9import { provideRouter } from '@angular/router';
10import { appRoutes } from './app/app.routes';
11 
12registerLocaleData(localeFr, 'fr-FR', localeFrExtra);
13registerLocaleData(localeDe, 'de-DE');
14 
15function resolveLocale(): string {
16 const stored = localStorage.getItem('preferredLocale');
17 if (stored) {
18 return stored;
19 }
20 const supported = ['fr-FR', 'de-DE', 'en-US'];
21 return supported.find((l) => navigator.languages.includes(l)) ?? 'en-US';
22}
23 
24const currencyByLocale: Record<string, string> = {
25 'fr-FR': 'EUR',
26 'de-DE': 'EUR',
27 'en-US': 'USD',
28};
29 
30const activeLocale = resolveLocale();
31 
32bootstrapApplication(AppComponent, {
33 providers: [
34 provideRouter(appRoutes),
35 { provide: LOCALE_ID, useValue: activeLocale },
36 {
37 provide: DEFAULT_CURRENCY_CODE,
38 useValue: currencyByLocale[activeLocale] ?? 'USD',
39 },
40 ],
41}).catch((err) => console.error(err));
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Angular's locale data must be explicitly registered before it can format dates, numbers, or currency for that region.
  2. 2Resolving the active locale from storage or the browser lets the app adapt without rebuilding per market.
  3. 3Injecting LOCALE_ID and DEFAULT_CURRENCY_CODE as providers makes formatting decisions consistent app-wide.

Related explainers

typescript
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import * as Joi from 'joi';
 

Validating env config at boot in NestJS

configuration schema-validation environment-variables
Intermediate 8 steps
java
@Component
@Converter
public class EncryptedStringConverter implements AttributeConverter<String, String> {
 

Transparent column encryption in Spring & JPA

encryption aes-gcm jpa-converter
Advanced 10 steps
typescript
import { Inject, Injectable, Logger } from '@nestjs/common';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';
import { InjectRepository } from '@nestjs/typeorm';

A cache-aside country lookup in NestJS

cache-aside dependency-injection batch-lookup
Intermediate 8 steps
java
package com.acme.billing.config;
 
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;

Feature-flagged beans with Spring @ConditionalOnProperty

feature-flags conditional-beans strategy-pattern
Intermediate 5 steps
typescript
import { Injectable, effect, signal, computed } from '@angular/core';
 
interface Preferences {
  theme: 'light' | 'dark';

A signal-based preferences store in Angular

signals state-management persistence
Intermediate 7 steps
typescript
import { useEffect, useState } from "react";
 
interface Section {
  id: string;

Building a scroll-spy hook in React

custom-hooks intersectionobserver dom-observation
Intermediate 8 steps

Share this explainer

Here's the card — post it anywhere.

Locale-aware bootstrapping in Angular — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code