Hono
Hono applications can use one shared Messagevisor instance in route handlers across Node.js, Bun, Deno, and edge runtimes.
Install#
Command
$ npm install hono @messagevisor/sdk @messagevisor/module-icuLoad one server SDK instance#
For Node.js-style runtimes, create a small helper that reads all supported locale datafiles into one SDK instance:
src/messagevisor.ts
import { createMessagevisor, type Messagevisor } from "@messagevisor/sdk";import { createICUModule } from "@messagevisor/module-icu";const supportedLocales = ["en-US", "nl-NL"];let instancePromise: Promise<Messagevisor> | undefined;export 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;}Route handlers pass locale per evaluation instead of calling setLocale().
Route handlers#
Use c.req.query() for request inputs and c.json() or c.html() for translated responses:
src/index.ts
import { Hono } from "hono";import { getMessagevisor } from "./messagevisor";const app = new Hono();app.get("/", async (c) => { const locale = c.req.query("locale") || "en-US"; const plan = c.req.query("plan"); const m = await getMessagevisor(); const title = m.translate( "dashboard.welcome", { name: "Ada" }, { locale, context: { platform: "web", plan } } ); return c.html(`<h1>${title}</h1>`);});app.get("/api/welcome", async (c) => { const locale = c.req.query("locale") || "en-US"; const m = await getMessagevisor(); return c.json({ message: m.translate("dashboard.welcome", { name: "Ada" }, { locale }), });});export default app;Do not call setContext() or setLocale() on a shared instance for request-specific values. Pass locale and context in the evaluation options so concurrent requests stay isolated.
Edge runtimes#
The same CDN helper works in edge runtimes:
let instancePromise: Promise<Messagevisor> | undefined;async function getMessagevisor() { if (instancePromise) return instancePromise; instancePromise = Promise.all( ["en-US", "nl-NL"].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;}If the runtime keeps isolates warm, cache the shared SDK instance and keep request locale in the call options:
m.translate("dashboard.welcome", { name: "Ada" }, { locale });
