Next.js
Next.js applications can use Messagevisor on the server, in route handlers, and in client components through the React provider.
Install#
$ npm install @messagevisor/sdk @messagevisor/react @messagevisor/module-icuServer helper#
Create a small server-only helper that loads all supported locale datafiles into one SDK instance:
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`, { next: { revalidate: 60 }, }).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;}Server components, route handlers, and Pages Router methods pass locale per call. Do not call setLocale() or setContext() while handling requests.
App Router#
Server components can await the helper directly:
import { getMessagevisor } from "../../messagevisor";export default async function Page({ params }: { params: Promise<{ locale: string }> }) { const { locale } = await params; const m = await getMessagevisor(); const title = m.translate( "dashboard.welcome", { name: "Ada" }, { locale, context: { platform: "web", plan: "pro" } } ); return <h1>{title}</h1>;}Route handlers#
Route handlers can render translated JSON or text:
import { NextResponse } from "next/server";import { getMessagevisor } from "../../messagevisor";export async function GET(request: Request) { const locale = new URL(request.url).searchParams.get("locale") || "en-US"; const m = await getMessagevisor(); return NextResponse.json({ message: m.translate("dashboard.welcome", { name: "Ada" }, { locale }), });}Client provider hydration#
For client-side hooks, pass a loaded datafile into MessagevisorProvider:
"use client";import { useMemo } from "react";import { createMessagevisor } from "@messagevisor/sdk";import { createICUModule } from "@messagevisor/module-icu";import { MessagevisorProvider } from "@messagevisor/react";export function MessagevisorClientProvider(props: { datafile: any; children: React.ReactNode;}) { const m = useMemo( () => createMessagevisor({ datafile: props.datafile, modules: [createICUModule({ ignoreTags: false })], }), [props.datafile] ); return <MessagevisorProvider instance={m}>{props.children}</MessagevisorProvider>;}Then client components can use React SDK hooks.
Client components do not need to pass locale per call. They receive one datafile for the current user-facing locale, and the provider instance keeps that locale as its active locale. If the user switches language in the browser, load the new datafile, call setDatafile(), then call setLocale().
Pages Router#
For Pages Router, load the datafile in getServerSideProps:
import type { GetServerSideProps } from "next";import { getMessagevisor } from "../../messagevisor";export const getServerSideProps: GetServerSideProps = async ({ params }) => { const locale = String(params?.locale || "en-US"); const m = await getMessagevisor(); return { props: { title: m.translate("dashboard.welcome", { name: "Ada" }, { locale }), }, };};export default function Page(props: { title: string }) { return <h1>{props.title}</h1>;}Loading from a CDN#
If datafiles are published under a different path, update the CDN URL in your server helper:
const datafile = await fetch( `https://cdn.yoursite.com/datafiles/messagevisor-web-${locale}.json`, { next: { revalidate: 60 } }).then((response) => response.json());
