defineMessages
Declares messages so the extractor can find them, next to the UI that shows them — the English then lives with the code rather than in a catalog edited by hand. Call it by this name: formatjs extract matches the call by name, wherever it was imported from, so a wrapper under another name extracts nothing.
Write the id yourself, as the SDK's own messages do — an app overrides by id, so an id has to survive a reworded English string. Leave it out only where a bundler plugin injects one; with no plugin either the English stands in, so the message still renders as itself. An id missing from a real build is caught by pnpm i18n-extract --check.
The type parameter is const so each written id keeps its literal type, which is what lets a declared id go where a TLUiTranslationKey is expected — a menu item's label, say — instead of widening to string and needing a cast.
For a message rendered as an element, write it inline on the <F> instead; the extractor reads those props directly. This is for the ones that can't be: a label the UI takes as data, and anything translated as a string through useTranslation.
function defineMessages<
const Messages extends Record<string, TLI18nMessageInput>,
>(
msgs: Messages,
): {
[K in keyof Messages]: Messages[K] & TLI18nMessage;
};Example
const messages = defineMessages({
copy: { id: "action.copy", defaultMessage: "Copy" },
});Parameters
| Name | Description |
|---|---|
| |
Returns
{
[K in keyof Messages]: Messages[K] & TLI18nMessage;
};