{"record":{"id":"4f96e456ea8d4684","repo":"facebook/docusaurus","slug":"docusaurus-translation-declarations-must-have-at-l","errorCode":null,"errorMessage":"Docusaurus translation declarations must have at least a translation id or a default translation message","messagePattern":"Docusaurus translation declarations must have at least a translation id or a default translation message","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/docusaurus/src/client/exports/Translate.tsx","lineNumber":22,"sourceCode":" * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport React, {type ReactNode} from 'react';\nimport {interpolate, type InterpolateValues} from '@docusaurus/Interpolate';\n// Can't read it from context, due to exposing imperative API\nimport codeTranslations from '@generated/codeTranslations';\nimport type {TranslateParam, TranslateProps} from '@docusaurus/Translate';\n\nfunction getLocalizedMessage({\n  id,\n  message,\n}: {\n  message?: string;\n  id?: string;\n}): string {\n  if (typeof id === 'undefined' && typeof message === 'undefined') {\n    throw new Error(\n      'Docusaurus translation declarations must have at least a translation id or a default translation message',\n    );\n  }\n\n  return codeTranslations[(id ?? message)!] ?? message ?? id!;\n}\n\n// Imperative translation API is useful for some edge-cases:\n// - translating page titles (meta)\n// - translating string props (input placeholders, image alt, aria labels...)\nexport function translate<Str extends string>(\n  {message, id}: TranslateParam<Str>,\n  values?: InterpolateValues<Str, string | number>,\n): string {\n  const localizedMessage = getLocalizedMessage({message, id});\n  return interpolate(localizedMessage, values);\n}\n","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/facebook/docusaurus/blob/3f483e80e326cc646b54b83d564b3f0c4881b9a6/packages/docusaurus/src/client/exports/Translate.tsx#L4-L40","documentation":"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.","triggerScenarios":"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.","commonSituations":"Generating translate params from a map where a key is missing; conditional that omits both id and message; copy-paste leaving an empty object.","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."],"exampleFix":"// before\ntranslate({});\n// after\ntranslate({message: 'Hello, {name}', id: 'greeting'}, {name});","handlingStrategy":"validation","validationCode":"function safeTranslate(\n  p: {id?: string; message?: string},\n  values?: Record<string, string | number>,\n) {\n  if (p.id === undefined && p.message === undefined) {\n    throw new Error('translate() needs at least id or message');\n  }\n  return translate(p as {message: string}, values);\n}","typeGuard":"const hasIdOrMessage = (\n  p: {id?: unknown; message?: unknown},\n): p is {id?: string; message?: string} =>\n  p.id !== undefined || p.message !== undefined;","tryCatchPattern":null,"preventionTips":["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."],"tags":["i18n","translate","props-validation"],"backgroundTag":null,"analyzedSha":"3f483e80e326cc646b54b83d564b3f0c4881b9a6","analyzedAt":"2026-08-12T13:25:04.382Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}