Frameworks
Hono
Hono applications can use one shared Messagevisor instance in route handlers across Node.js, Bun, Deno, and edge runtimes.
Install#
$ 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:
Copy the shared datafile loader beside this helper. It checks HTTP status, retries initial failures, and retains the last known good datafiles during refresh failures.
import { createMessagevisorLoader } from "./messagevisor-loader.js";const loader = createMessagevisorLoader();export const getMessagevisor = loader.get;export const refreshMessagevisor = loader.refresh;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:
import { Hono } from "hono";import { html } from "hono/html";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(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 Hono HTML helper escapes interpolated strings. Keep translated text inside escaped expressions like ${title}. ICU formatting does not sanitize HTML, so do not use raw() for translations or values supplied by users. For intentional rich text, map supported tags to controlled rendering components instead.
Use the same helper in each edge isolate. Pass request locale and context per evaluation. A warm isolate can reuse its cache, but another isolate loads independently.
Do not rely on background work continuing after a response. Await refreshMessagevisor() in a scheduled handler, or adapt the explicit refresh recipe to the platform's request lifetime mechanism.