Better Translation

Runtime translator

Build a translator from a loaded message map for SSR, titles, and metadata.

For server-side rendering, document titles, or metadata, build a translator from the loaded Runtime bundle with createT. It has the same call signature as useT but takes the messages directly.

Loading messages

Load the active Locale's messages in route data before rendering the provider.

src/routes/__root.tsx
import { createRootRoute } from "@tanstack/react-router"
import { createServerFn } from "@tanstack/react-start"
import z from "zod"

import { loadMessages } from "better-translation/messages"
import { TranslateProvider } from "better-translation/react"

import { getLocale } from "./-locale"

const getMessagesFn = createServerFn({ method: "GET" })
  .validator(z.object({ locale: z.string() }))
  .handler(async ({ data }) => {
    return await loadMessages(data.locale)
  })

export const Route = createRootRoute({
  beforeLoad: async () => {
    const locale = await getLocale()
    const messages = await getMessagesFn({ data: { locale } })

    return { locale, messages }
  },
  component: RootComponent,
})

function RootComponent() {
  const { locale, messages } = Route.useRouteContext()

  return (
    <TranslateProvider locale={locale} messages={messages}>
      {/* app */}
    </TranslateProvider>
  )
}

createT

Once messages are in route context, child routes can translate metadata without rendering a component.

src/routes/projects.$projectId.tsx
import { createFileRoute } from "@tanstack/react-router"

import { createT } from "better-translation/runtime"

export const Route = createFileRoute("/projects/$projectId")({
  loader: async ({ params }) => {
    const project = await getProject(params.projectId)

    return { project }
  },
  head: ({ match }) => {
    const t = createT(match.context.messages)
    const { project } = match.loaderData

    return {
      meta: [
        { title: t("{name} settings", { name: project.name }, { context: "Page title" }) },
        {
          name: "description",
          content: t("Manage Locale values for {name}", { name: project.name }, { context: "Meta description" }),
        },
      ],
    }
  },
})

Options

The runtime translator accepts the same id and context options as useT. Use context to give translation tools more information about server-rendered copy, metadata, and titles; it also disambiguates generated lookup ids.

Prop

Type

Pass options as the second argument when there are no variables, or as the third argument when there are variables.

usage.ts
t("Archive", { context: "Verb, archives the current Branch" })
t("{count} Messages need review", { count }, { context: "SEO description" })
t("Pay now", { id: "billing.checkout.submit" })

On this page