Frameworks
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#
Copy the shared datafile loader beside this helper, using its CommonJS variant. It checks HTTP status, retries initial failures, and retains the last known good datafiles during refresh failures.
const { createMessagevisorLoader } = require("./messagevisor-loader");const loader = createMessagevisorLoader();const getMessagevisor = loader.get;const refreshMessagevisor = loader.refresh;module.exports = { getMessagevisor, refreshMessagevisor };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#
Call await refreshMessagevisor() from a deployment hook or revision poller. Handle rejection and keep using getMessagevisor() for the last known good snapshot. See explicit refresh for cache age, request lifetime, and snapshot replacement.