NestJS
NestJS applications can expose one shared Messagevisor instance through injectable providers and keep request-specific locale and context in controller method calls.
Install#
$ npm install @messagevisor/sdk @messagevisor/module-icuMessagevisor service#
Create an injectable service that loads all supported locale datafiles into one SDK instance:
import { Injectable } from "@nestjs/common";import { createMessagevisor, type Messagevisor } from "@messagevisor/sdk";import { createICUModule } from "@messagevisor/module-icu";@Injectable()export class MessagevisorService { private readonly supportedLocales = ["en-US", "nl-NL"]; private instancePromise?: Promise<Messagevisor>; async getInstance() { if (this.instancePromise) return this.instancePromise; this.instancePromise = Promise.all( this.supportedLocales.map((locale) => fetch(`https://cdn.yoursite.com/datafiles/messagevisor-web-${locale}.json`).then( (response) => response.json() ) ) ).then((datafiles) => { const m = createMessagevisor({ datafile: datafiles[0], modules: [createICUModule({ ignoreTags: false })], }); datafiles.slice(1).forEach((datafile) => m.setDatafile(datafile)); return m; }); return this.instancePromise; }}Controllers pass locale per call. Do not call setLocale() or setContext() while handling requests.
Module#
Register the service in a module so controllers can inject it:
import { Module } from "@nestjs/common";import { MessagevisorService } from "./messagevisor.service";@Module({ providers: [MessagevisorService], exports: [MessagevisorService],})export class MessagevisorModule {}Then import MessagevisorModule from your app or feature module.
Controller#
Use Nest's @Query() decorator for locale and runtime context values:
import { Controller, Get, Query } from "@nestjs/common";import { MessagevisorService } from "./messagevisor/messagevisor.service";@Controller()export class AppController { constructor(private readonly messagevisor: MessagevisorService) {} @Get() async index(@Query("locale") locale = "en-US", @Query("plan") plan?: string) { const m = await this.messagevisor.getInstance(); return { title: m.translate( "dashboard.welcome", { name: "Ada" }, { locale, context: { platform: "web", plan } } ), }; } @Get("api/welcome") async welcome(@Query("locale") locale = "en-US") { const m = await this.messagevisor.getInstance(); return { message: m.translate("dashboard.welcome", { name: "Ada" }, { locale }), }; }}Nest serializes returned objects as JSON by default. If you render HTML from Nest, resolve the translation in the same way and pass it to your template or response layer.
Refreshing datafiles#
If datafiles are published to a CDN, refresh your cache on a timer, by revision checks, or during deployment. The SDK supports setDatafile() if you need to update the datafile without recreating the instance; pass true as the second argument when you need to fully replace an already-loaded locale.
Loading from a CDN#
If datafiles are published under a different path, update the CDN URL in your service:
const datafile = await fetch( `https://cdn.yoursite.com/datafiles/messagevisor-web-${locale}.json`).then((response) => response.json());
