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

# Translate and test application output

Translate components, server output, and semantic Markdown while preserving hydration and cache boundaries, then test each runtime.

## Translate components

```tsx
import { useTranslate } from "#brix";

export function SearchButton() {
  const translate = useTranslate();
  return <button>{translate("general.ctaSearch")}</button>;
}

```

Import application hooks statically from `#brix`, assign `useTranslate()` directly to one local, and call it with string-literal keys. Dynamic imports, aliases, passed translators, variables, templates, and conditional key expressions fail checks. This lets Brix send each hydrated island only statically reachable messages. SSR-only use sends no browser dictionary payload.

Interpolation is explicit application code:

```ts
translate("general.points").replace("{points}", formatPoints(points));

```

Server code awaits the request translator:

```ts
const translate = await getTranslator(c);
const title = translate("search.title");

```

## Translate semantic Markdown

Markdown callbacks are server code. Do not call hooks or derive Markdown from rendered HTML:

```ts
markdown: async (c) => {
  const translate = await getTranslator(c);
  return md.document({
    body: md.heading(1, md.text(translate("search.title"))),
  });
},

```

Canonical negotiated responses and durable `.md` aliases use the same locale and `Content-Language`. Markdown bypasses Preact providers and hydration payloads. Repeated translator calls share request-local active and fallback loads.

## Keep edge caches locale-safe

Localized paths are partitioned by path automatically. If host determines locale and translated pages or fragments use edge caching, configure:

```ts
translations: {
  load,
  localePartition: "host",
},

```

Cookie-, header-, or otherwise opaque locale selection fails closed to uncached responses unless a fragment URL carries a validated explicit locale backed by finite manifest metadata. An edge must be able to observe every value in its cache key.

Fragment hydration carries only that fragment's statically used messages. Independently cached fragments follow the same locale partition rules. See [fragments](/docs/fragments) and [caching](/docs/caching).
Deferred fragment URLs reserve `__brix_locale`, validate exactly one configured locale, and publish
finite locale keys in schema-2 manifests so central edge caches partition explicit locale values.

## Use Contentful as a source

Keep Contentful's model behind the source-neutral loader:

```ts
const { items } = await contentful.getEntries("localizationResource", { locale }).unwrap();

return Object.fromEntries(
  items.flatMap((resource) =>
    Object.entries(resource.fields.resources).map(([key, value]) => [
      `${resource.fields.category}.${key}`,
      value,
    ]),
  ),
);

```

Configure `cache: dataCache.public("1h")` on the Contentful client and use its verified webhook invalidation. Preserve your production flattening and fallback semantics; never expose Contentful entries as component translation APIs. See [Contentful](/docs/contentful).

## Test each runtime

Route tests can provide dictionaries without invoking production loading:

```ts
const response = await testPage(searchPageRoute, {
  locale: "sv",
  representation: "markdown",
  translations: {
    sv: { "search.title": "Sök" },
    "en-GB": { "search.title": "Search" },
  },
});

```

Assert rendered content and `Content-Language`. Browser component tests use `renderWithTranslations`; Storybook previews use the managed translation preview and locale toolbar. See [testing](/docs/testing) and [Storybook](/docs/storybook). React applications use the matching bindings documented in [React](/docs/react).
