Installation
Install Transloco using the Angular CLI schematic:
ng add @ngneat/transloco
This command will:
- Install the necessary packages
- Set up the basic configuration
- Create translation files
- Configure your app module
Alternatively, install manually:
npm install @ngneat/transloco
Module Configuration
If you installed manually, configure Transloco in your app module:
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { TranslocoModule } from '@ngneat/transloco';
import { AppComponent } from './app.component';
import { translocoConfig } from './transloco-config';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule,
TranslocoModule
],
providers: [
translocoConfig
],
bootstrap: [AppComponent]
})
export class AppModule { }
Transloco Configuration
Create the Transloco configuration:
// src/app/transloco-config.ts
import { HttpClient } from '@angular/common/http';
import { Injectable, isDevMode } from '@angular/core';
import {
Translation,
TranslocoLoader,
TranslocoConfig,
TRANSLOCO_CONFIG,
TRANSLOCO_LOADER
} from '@ngneat/transloco';
@Injectable({ providedIn: 'root' })
export class TranslocoHttpLoader implements TranslocoLoader {
constructor(private http: HttpClient) {}
getTranslation(lang: string) {
return this.http.get<Translation>(`/assets/i18n/${lang}.json`);
}
}
export const translocoConfig = [
{
provide: TRANSLOCO_CONFIG,
useValue: {
availableLangs: ['en', 'pl', 'es', 'fr'],
defaultLang: 'en',
fallbackLang: 'en',
reRenderOnLangChange: true,
prodMode: !isDevMode(),
} as TranslocoConfig
},
{
provide: TRANSLOCO_LOADER,
useClass: TranslocoHttpLoader
}
];
Translation File Structure
Create translation files in the src/assets/i18n/
directory:
// src/assets/i18n/en.json
{
"homepage": {
"title": "Welcome to our website",
"description": "This is a multilingual Angular application",
"subtitle": "Built with Transloco"
},
"navigation": {
"home": "Home",
"about": "About",
"contact": "Contact",
"products": "Products"
},
"product": {
"name": "Product Name",
"price": "Price: {{price}}",
"available": "Available since: {{date}}",
"addToCart": "Add to Cart",
"removeFromCart": "Remove from Cart"
},
"cart": {
"title": "Shopping Cart",
"empty": "Your cart is empty",
"itemCount": "{{count}} item",
"itemCount_other": "{{count}} items",
"total": "Total: {{amount}}"
},
"user": {
"welcome": "Welcome, {{name}}!",
"profile": "Profile",
"logout": "Logout"
},
"forms": {
"email": "Email",
"password": "Password",
"submit": "Submit",
"cancel": "Cancel",
"save": "Save"
},
"messages": {
"loading": "Loading...",
"error": "Something went wrong",
"success": "Operation completed successfully",
"confirm": "Are you sure?"
}
}
// src/assets/i18n/pl.json
{
"homepage": {
"title": "Witamy na naszej stronie",
"description": "To jest wielojęzyczna aplikacja Angular",
"subtitle": "Zbudowana z Transloco"
},
"navigation": {
"home": "Strona główna",
"about": "O nas",
"contact": "Kontakt",
"products": "Produkty"
},
"product": {
"name": "Nazwa produktu",
"price": "Cena: {{price}}",
"available": "Dostępne od: {{date}}",
"addToCart": "Dodaj do koszyka",
"removeFromCart": "Usuń z koszyka"
},
"cart": {
"title": "Koszyk",
"empty": "Twój koszyk jest pusty",
"itemCount": "{{count}} przedmiot",
"itemCount_other": "{{count}} przedmiotów",
"total": "Razem: {{amount}}"
},
"user": {
"welcome": "Witaj, {{name}}!",
"profile": "Profil",
"logout": "Wyloguj"
},
"forms": {
"email": "Email",
"password": "Hasło",
"submit": "Wyślij",
"cancel": "Anuluj",
"save": "Zapisz"
},
"messages": {
"loading": "Ładowanie...",
"error": "Coś poszło nie tak",
"success": "Operacja zakończona pomyślnie",
"confirm": "Czy jesteś pewny?"
}
}
// src/assets/i18n/es.json
{
"homepage": {
"title": "Bienvenido a nuestro sitio web",
"description": "Esta es una aplicación Angular multiidioma",
"subtitle": "Construida con Transloco"
},
"navigation": {
"home": "Inicio",
"about": "Acerca de",
"contact": "Contacto",
"products": "Productos"
},
"product": {
"name": "Nombre del producto",
"price": "Precio: {{price}}",
"available": "Disponible desde: {{date}}",
"addToCart": "Añadir al carrito",
"removeFromCart": "Quitar del carrito"
},
"cart": {
"title": "Carrito de compras",
"empty": "Tu carrito está vacío",
"itemCount": "{{count}} artículo",
"itemCount_other": "{{count}} artículos",
"total": "Total: {{amount}}"
},
"user": {
"welcome": "¡Bienvenido, {{name}}!",
"profile": "Perfil",
"logout": "Cerrar sesión"
},
"forms": {
"email": "Correo electrónico",
"password": "Contraseña",
"submit": "Enviar",
"cancel": "Cancelar",
"save": "Guardar"
},
"messages": {
"loading": "Cargando...",
"error": "Algo salió mal",
"success": "Operación completada exitosamente",
"confirm": "¿Estás seguro?"
}
}
// src/assets/i18n/fr.json
{
"homepage": {
"title": "Bienvenue sur notre site web",
"description": "Ceci est une application Angular multilingue",
"subtitle": "Construite avec Transloco"
},
"navigation": {
"home": "Accueil",
"about": "À propos",
"contact": "Contact",
"products": "Produits"
},
"product": {
"name": "Nom du produit",
"price": "Prix: {{price}}",
"available": "Disponible depuis: {{date}}",
"addToCart": "Ajouter au panier",
"removeFromCart": "Retirer du panier"
},
"cart": {
"title": "Panier",
"empty": "Votre panier est vide",
"itemCount": "{{count}} article",
"itemCount_other": "{{count}} articles",
"total": "Total: {{amount}}"
},
"user": {
"welcome": "Bienvenue, {{name}} !",
"profile": "Profil",
"logout": "Déconnexion"
},
"forms": {
"email": "Email",
"password": "Mot de passe",
"submit": "Soumettre",
"cancel": "Annuler",
"save": "Sauvegarder"
},
"messages": {
"loading": "Chargement...",
"error": "Quelque chose s'est mal passé",
"success": "Opération terminée avec succès",
"confirm": "Êtes-vous sûr ?"
}
}
Usage Examples
Basic Component Usage
// app.component.ts
import { Component, OnInit } from '@angular/core';
import { TranslocoService } from '@ngneat/transloco';
@Component({
selector: 'app-root',
template: `
<div class="app-container">
<app-language-switcher></app-language-switcher>
<header>
<h1>{{ 'homepage.title' | transloco }}</h1>
<p>{{ 'homepage.description' | transloco }}</p>
<small>{{ 'homepage.subtitle' | transloco }}</small>
</header>
<main>
<app-navigation></app-navigation>
<app-product-list></app-product-list>
<app-shopping-cart></app-shopping-cart>
</main>
</div>
`
})
export class AppComponent implements OnInit {
constructor(private translocoService: TranslocoService) {}
ngOnInit(): void {
// Set initial language
const savedLang = localStorage.getItem('selectedLanguage');
const browserLang = this.translocoService.getBrowserLang();
const defaultLang = savedLang || browserLang || 'en';
this.translocoService.setActiveLang(defaultLang);
}
}
Language Switcher Component
// language-switcher.component.ts
import { Component } from '@angular/core';
import { TranslocoService } from '@ngneat/transloco';
@Component({
selector: 'app-language-switcher',
template: `
<div class="language-switcher">
<select
[value]="translocoService.getActiveLang()"
(change)="changeLanguage($event)">
<option *ngFor="let lang of availableLanguages" [value]="lang.code">
{{ lang.name }}
</option>
</select>
</div>
`
})
export class LanguageSwitcherComponent {
availableLanguages = [
{ code: 'en', name: 'English' },
{ code: 'pl', name: 'Polski' },
{ code: 'es', name: 'Español' },
{ code: 'fr', name: 'Français' }
];
constructor(public translocoService: TranslocoService) {}
changeLanguage(event: Event): void {
const target = event.target as HTMLSelectElement;
const language = target.value;
this.translocoService.setActiveLang(language);
localStorage.setItem('selectedLanguage', language);
}
}
Navigation Component
// navigation.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-navigation',
template: `
<nav class="main-navigation">
<a routerLink="/" class="nav-link">
{{ 'navigation.home' | transloco }}
</a>
<a routerLink="/about" class="nav-link">
{{ 'navigation.about' | transloco }}
</a>
<a routerLink="/products" class="nav-link">
{{ 'navigation.products' | transloco }}
</a>
<a routerLink="/contact" class="nav-link">
{{ 'navigation.contact' | transloco }}
</a>
</nav>
`
})
export class NavigationComponent {}
Product Component with Parameters
// product.component.ts
import { Component, Input } from '@angular/core';
import { TranslocoService } from '@ngneat/transloco';
@Component({
selector: 'app-product',
template: `
<div class="product-card">
<h3>{{ product.name }}</h3>
<p>{{ 'product.price' | transloco:{ price: product.price | currency } }}</p>
<p>{{ 'product.available' | transloco:{ date: product.availableDate | date } }}</p>
<div class="product-actions">
<button
class="btn btn-primary"
(click)="addToCart()"
[disabled]="isInCart">
{{ (isInCart ? 'product.removeFromCart' : 'product.addToCart') | transloco }}
</button>
</div>
</div>
`
})
export class ProductComponent {
@Input() product: any;
@Input() isInCart: boolean = false;
constructor(private translocoService: TranslocoService) {}
addToCart(): void {
// Cart logic here
console.log('Product added to cart');
}
}
Service with Transloco
// notification.service.ts
import { Injectable } from '@angular/core';
import { TranslocoService } from '@ngneat/transloco';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class NotificationService {
constructor(private translocoService: TranslocoService) {}
showWelcomeMessage(userName: string): Observable<string> {
return this.translocoService.selectTranslate('user.welcome', { name: userName });
}
getLoadingMessage(): string {
return this.translocoService.translate('messages.loading');
}
getSuccessMessage(): Observable<string> {
return this.translocoService.selectTranslate('messages.success');
}
getErrorMessage(): Observable<string> {
return this.translocoService.selectTranslate('messages.error');
}
getConfirmationMessage(): Observable<string> {
return this.translocoService.selectTranslate('messages.confirm');
}
}
Shopping Cart with Pluralization
// shopping-cart.component.ts
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-shopping-cart',
template: `
<div class="shopping-cart">
<h2>{{ 'cart.title' | transloco }}</h2>
<div *ngIf="items.length === 0" class="empty-cart">
{{ 'cart.empty' | transloco }}
</div>
<div *ngIf="items.length > 0" class="cart-content">
<div class="cart-summary">
{{ 'cart.itemCount' | transloco:{ count: items.length } }}
</div>
<div class="cart-items">
<div *ngFor="let item of items" class="cart-item">
<span>{{ item.name }}</span>
<span>{{ item.price | currency }}</span>
</div>
</div>
<div class="cart-total">
{{ 'cart.total' | transloco:{ amount: getTotal() | currency } }}
</div>
</div>
</div>
`
})
export class ShoppingCartComponent {
@Input() items: any[] = [];
getTotal(): number {
return this.items.reduce((total, item) => total + item.price, 0);
}
}
Structural Directive Usage
// conditional-content.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-conditional-content',
template: `
<div>
<!-- Using structural directive -->
<div *transloco="let t">
<h1>{{ t('homepage.title') }}</h1>
<p>{{ t('homepage.description') }}</p>
<!-- Nested translations -->
<div *transloco="let nav; read: 'navigation'">
<a>{{ nav('home') }}</a>
<a>{{ nav('about') }}</a>
<a>{{ nav('contact') }}</a>
</div>
</div>
</div>
`
})
export class ConditionalContentComponent {}
Advanced Features
Lazy Loading Scoped Translations
// feature.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TranslocoModule, TRANSLOCO_SCOPE } from '@ngneat/transloco';
@NgModule({
declarations: [],
imports: [
CommonModule,
TranslocoModule
],
providers: [
{
provide: TRANSLOCO_SCOPE,
useValue: 'feature'
}
]
})
export class FeatureModule {}
Custom Pluralization Rules
// transloco-config.ts (enhanced)
import { TranslocoConfig } from '@ngneat/transloco';
export const translocoConfig: TranslocoConfig = {
availableLangs: ['en', 'pl', 'es', 'fr'],
defaultLang: 'en',
fallbackLang: 'en',
reRenderOnLangChange: true,
prodMode: !isDevMode(),
missingHandler: {
useFallbackTranslation: true,
allowEmpty: false
},
interpolation: {
marker: ['{{', '}}']
}
};
SimpleLocalize Configuration
To manage translations with SimpleLocalize, you need to set up the CLI tool.
# macOS / Linux / Windows (WSL)
curl -s https://get.simplelocalize.io/2.9/install | bash
# Windows (PowerShell)
. { iwr -useb https://get.simplelocalize.io/2.9/install-windows } | iex;
# npm
npm install @simplelocalize/cli
# macOS / Linux / Windows (WSL)
curl -s https://get.simplelocalize.io/2.9/install | bash
# Windows (PowerShell)
. { iwr -useb https://get.simplelocalize.io/2.9/install-windows } | iex;
# npm
npm install @simplelocalize/cli
Create simplelocalize.yml
in your project root:
apiKey: YOUR_PROJECT_API_KEY
uploadFormat: single-language-json
uploadPath: ./src/assets/i18n/{lang}.json
uploadLanguageKey: en
uploadOptions:
- REPLACE_TRANSLATION_IF_FOUND
downloadPath: ./src/assets/i18n/{lang}.json
downloadLanguageKeys: ['en', 'pl', 'es', 'fr']
downloadFormat: single-language-json
Work with the CLI to manage your translations:
# Upload translations to SimpleLocalize
simplelocalize upload
# Download translations for all languages
simplelocalize download
# Build your Angular application
ng build
Key Features
- Modern Architecture: Built for modern Angular with RxJS
- Tree-shakable: Only load the translations you need
- Type Safety: Full TypeScript support with strict typing
- Lazy Loading: Load translations on demand with scoped modules
- Hot Reload: Real-time translation updates in development
- ICU Message Format: Advanced pluralization and formatting
- Structural Directive: Powerful template syntax for complex translations
- SSR Support: Full server-side rendering compatibility
Performance Benefits
- Small Bundle Size: Optimized for minimal impact on bundle size
- Lazy Loading: Load translations only when needed
- Caching: Built-in translation caching
- Change Detection: Optimized change detection strategy
- Memory Management: Efficient memory usage with proper cleanup
Resources
Was this helpful?