> [Agent navigation index](/llms.txt)

# Set up translations

Configure strict translation keys, locale resolution, server dictionary loading, fallback behavior, and request-local reuse.

## Define the browser-safe contract

```ts
import { defineBrix } from "brix/contracts";
import { createTranslationHooks } from "brix/hooks";
import { defineTranslations } from "brix/translations";
import type { TranslationKey } from "./types/generated/translation-keys.ts";

const translations = defineTranslations<TranslationKey>({ fallbackLocale: "en-GB" });

export const brix = defineBrix({
  locales: ["sv", "en-GB"] as const,
  defaultLocale: "sv",
  translations,
});

export const { useLocale, useTranslate } = createTranslationHooks(translations);
export const { createApiContract, createPageContract, executeApi, getPath } = brix;

```

There is no built-in default locale for translated applications. Keep a strict generated key union; `defineTranslations<string>` is rejected because Brix cannot safely verify or filter arbitrary keys.

## Load dictionaries on the server

```ts
export const brixServer = defineBrixServer(brix, {
  resolveLocale: (c) => localeFromRequest(c.req.raw),
  translations: {
    load: (_c, { locale }) => dictionaries[locale],
    onMissing: (event) => telemetry.translationKeysMissing(event),
  },
});

export const { getLocale, getTranslator } = brixServer;

```

The loader returns a partial string dictionary. Brix validates and freezes it, deduplicates each locale within one request, and shares it across handlers, page rendering, fragments, and Markdown. It does not create an implicit cross-request cache.

For a remote source, use the native data cache in the client call:

```ts
load: (_c, { locale }) =>
  translationClient
    .execute(getDictionaryApiContract, {
      query: { locale },
      cache: dataCache.public({ ttl: "1h", staleIfError: "1d" }),
    })
    .unwrap(),

```

Do not add a translation-specific cache abstraction. Source retry belongs on the API or Contentful client. Invalidate its contract, tag, or Contentful delivery client after updates. Loader failures fail the request unless the configured native cache can provide eligible stale data.

## Resolve locale consistently

`resolveLocale` may return only a configured locale. A uniquely localized page path wins; otherwise Brix uses the callback and then `defaultLocale`. The result drives `getLocale(c)`, `useLocale()`, `<html lang>`, `Content-Language`, SSR, Markdown, and hydration.

Fallback loading is enabled when active locale differs from `fallbackLocale`. Set `fallback: false` or a callback only for a deliberate alternate policy. Missing lookup order is active message, enabled fallback message, optional example behavior, then key. Strings remain unchanged, including braces, Unicode, newlines, and HTML-looking text.

`onMissing` receives request-deduplicated missing keys after handling. Its failure or bounded timeout does not change the response.

Continue with [translate and test application output](/docs/translations-usage).
