facebook/docusaurus · error · Error
Docusaurus translation declarations must have at least a tra
Error message
Docusaurus translation declarations must have at least a translation id or a default translation message
What it means
The imperative translate({message, id}) function calls getLocalizedMessage, which requires at least one of id or message. If both are undefined it throws 'Docusaurus translation declarations must have at least a translation id or a default translation message'. This catches incomplete translation calls early so untranslated content never silently ships.
Source
Thrown at packages/docusaurus/src/client/exports/Translate.tsx:22
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import React, {type ReactNode} from 'react';
import {interpolate, type InterpolateValues} from '@docusaurus/Interpolate';
// Can't read it from context, due to exposing imperative API
import codeTranslations from '@generated/codeTranslations';
import type {TranslateParam, TranslateProps} from '@docusaurus/Translate';
function getLocalizedMessage({
id,
message,
}: {
message?: string;
id?: string;
}): string {
if (typeof id === 'undefined' && typeof message === 'undefined') {
throw new Error(
'Docusaurus translation declarations must have at least a translation id or a default translation message',
);
}
return codeTranslations[(id ?? message)!] ?? message ?? id!;
}
// Imperative translation API is useful for some edge-cases:
// - translating page titles (meta)
// - translating string props (input placeholders, image alt, aria labels...)
export function translate<Str extends string>(
{message, id}: TranslateParam<Str>,
values?: InterpolateValues<Str, string | number>,
): string {
const localizedMessage = getLocalizedMessage({message, id});
return interpolate(localizedMessage, values);
}
View on GitHub (pinned to 3f483e80e3)
Solutions
- Always pass a message (the default/fallback English string) and optionally an id.
- If params are dynamic, validate before calling: if (!id && !message) throw or supply a fallback.
- Use a wrapper that requires at least one of the two keys at the type level.
Example fix
// before
translate({});
// after
translate({message: 'Hello, {name}', id: 'greeting'}, {name}); Defensive patterns
Strategy: validation
Validate before calling
function safeTranslate(
p: {id?: string; message?: string},
values?: Record<string, string | number>,
) {
if (p.id === undefined && p.message === undefined) {
throw new Error('translate() needs at least id or message');
}
return translate(p as {message: string}, values);
} Type guard
const hasIdOrMessage = (
p: {id?: unknown; message?: unknown},
): p is {id?: string; message?: string} =>
p.id !== undefined || p.message !== undefined; Prevention
- Always include a message string (English fallback) on every translate call.
- When building params dynamically, default message to a literal before calling.
- Add a type-level helper requiring one of the two keys.
When it happens
Trigger: Call translate({}) or translate({id: undefined, message: undefined}); build the param object dynamically and both keys end up undefined; refactor that drops the message literal.
Common situations: Generating translate params from a map where a key is missing; conditional that omits both id and message; copy-paste leaving an empty object.
Related errors
- The Docusaurus <Translate> component only accept simple stri
- The Docusaurus <Interpolate> component only accept simple st
- Error while attempting to extract Docusaurus translations fr
- Multiple docs sidebar items produce the same translation key
- Please make sure all theme translations are static! Some war
AI-assisted analysis of facebook/docusaurus@3f483e80e3 (2026-08-12).
Data as JSON: /api/errors/4f96e456ea8d4684.
Report an issue: GitHub.