Angular
Angular applications can load Messagevisor datafiles through an injectable service and render translations from components.
Install#
$ npm install @messagevisor/sdk @messagevisor/module-icuProvide HttpClient#
Configure Angular's HttpClient at the application root:
import { ApplicationConfig } from "@angular/core";import { provideHttpClient, withFetch } from "@angular/common/http";export const appConfig: ApplicationConfig = { providers: [provideHttpClient(withFetch())],};withFetch() is useful when the same application also uses Angular SSR.
Messagevisor service#
Create a client-side service that fetches built datafiles and keeps the active locale in Angular state:
import { Injectable, signal } from "@angular/core";import { HttpClient } from "@angular/common/http";import { firstValueFrom } from "rxjs";import { createMessagevisor, type Messagevisor } from "@messagevisor/sdk";import { createICUModule } from "@messagevisor/module-icu";@Injectable({ providedIn: "root" })export class MessagevisorService { private readonly cache = new Map<string, Messagevisor>(); readonly locale = signal("en-US"); constructor(private readonly http: HttpClient) {} async getInstance(locale = this.locale()) { const cached = this.cache.get(locale); if (cached) return cached; const datafile = await firstValueFrom( this.http.get(`/datafiles/messagevisor-web-${locale}.json`) ); const m = createMessagevisor({ datafile, locale, modules: [createICUModule({ ignoreTags: false })], }); this.cache.set(locale, m); return m; } async setLocale(locale: string) { await this.getInstance(locale); this.locale.set(locale); }}Place generated datafiles under public/datafiles or whatever static asset path your Angular build serves.
Component usage#
Components can await the service and pass user context per evaluation. In the browser, the service tracks one active locale for one user, so translation calls do not need per-call locale:
import { Component, OnInit, signal } from "@angular/core";import { MessagevisorService } from "./messagevisor.service";@Component({ selector: "app-dashboard", standalone: true, template: `<h1>{{ title() }}</h1>`,})export class DashboardComponent implements OnInit { readonly title = signal(""); constructor(private readonly messagevisor: MessagevisorService) {} async ngOnInit() { const m = await this.messagevisor.getInstance(); this.title.set( m.translate( "dashboard.welcome", { name: "Ada" }, { context: { platform: "web", plan: "pro" } } ) ); }}Do not call setContext() on a shared instance for user-specific values. Pass context in evaluation options. For Angular SSR server code that reuses one Messagevisor instance across requests, load all needed locale datafiles into that server instance and pass locale per call. For browser-only components, setLocale() remains the right model for user-driven language switches.
Locale switching#
When the user switches locale, load the new datafile before updating UI state:
await this.messagevisor.setLocale("nl-NL");const m = await this.messagevisor.getInstance("nl-NL");For highly reactive UIs, wrap common translation calls in your own Angular service methods and update signals after setLocale().
Loading from a CDN#
If datafiles are published separately, point the service at your CDN:
this.http.get( `https://cdn.yoursite.com/datafiles/messagevisor-web-${locale}.json`);
