Translate and test application output
Translate components, server output, and semantic Markdown while preserving hydration and cache boundaries, then test each runtime.
Translate components
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:
translate("general.points").replace("{points}", formatPoints(points));
Server code awaits the request translator:
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:
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:
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 and 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:
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.
Test each runtime
Route tests can provide dictionaries without invoking production loading:
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 and Storybook. React applications use the matching bindings documented in React.