Fastify
Fastify applications can expose one shared Messagevisor instance through decorators while keeping request-specific locale and context in evaluation calls.
Install#
$ npm install fastify @messagevisor/sdk @messagevisor/module-icuLoad one server SDK instance#
const { createMessagevisor } = require("@messagevisor/sdk");const { createICUModule } = require("@messagevisor/module-icu");const supportedLocales = ["en-US", "nl-NL"];let instancePromise;async function getMessagevisor() { if (instancePromise) return instancePromise; instancePromise = Promise.all( 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 instancePromise;}module.exports = { getMessagevisor };The server instance contains all supported locales. Request handlers pass locale per evaluation instead of calling setLocale().
Decorate Fastify#
const fastify = require("fastify")({ logger: true });const { getMessagevisor } = require("./messagevisor");async function start() { fastify.decorate("getMessagevisor", getMessagevisor); fastify.get("/", async (request) => { const locale = request.query.locale || "en-US"; const m = await fastify.getMessagevisor(); return { title: m.translate( "dashboard.welcome", { name: "Ada" }, { context: { platform: "web", plan: request.query.plan, }, locale, } ), }; }); await fastify.listen({ port: 3000 });}start();JSON routes#
Fastify routes can also return translated API responses:
fastify.get("/api/welcome", async (request) => { const locale = request.query.locale || "en-US"; const m = await fastify.getMessagevisor(); return { message: m.translate("dashboard.welcome", { name: "Ada" }, { locale }), };});TypeScript decorator type#
import type { Messagevisor } from "@messagevisor/sdk";declare module "fastify" { interface FastifyInstance { getMessagevisor(): Promise<Messagevisor>; }}Request context#
Fastify servers are long-lived. Keep request-specific values out of shared SDK state:
const locale = request.query.locale || "en-US";const m = await request.server.getMessagevisor();m.translate("billing.upgrade", undefined, { locale, context: { plan: request.user?.plan, platform: "web", },});Do not call setContext() or setLocale() in route handlers. Those mutate the shared instance; per-call options keep concurrent requests isolated.
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.

