facebook/docusaurus · error · Error
Translation file path at "${translationFilePath}" does not n
Error message
Translation file path at "${translationFilePath}" does not need to end with ".json", we add the extension automatically. What it means
Thrown by `addTranslationFileExtension` when a plugin declares a translation file path that already ends in `.json`. Docusaurus appends the extension itself (the comment explains it reserves room for future formats like yaml/toml), so a user-supplied `.json` suffix would double it. This is a configuration contract enforced for plugin authors.
Source
Thrown at packages/docusaurus/src/server/translations/translations.ts:171
}
export async function writeCodeTranslations(
context: TranslationContext,
content: TranslationFileContent,
options: WriteTranslationsOptions,
): Promise<void> {
return writeTranslationFileContent({
filePath: getCodeTranslationsFilePath(context),
content,
options,
});
}
// We ask users to not provide any extension on purpose:
// maybe some day we'll want to support multiple FS formats?
// (json/yaml/toml/xml...)
function addTranslationFileExtension(translationFilePath: string) {
if (translationFilePath.endsWith('.json')) {
throw new Error(
`Translation file path at "${translationFilePath}" does not need to end with ".json", we add the extension automatically.`,
);
}
return `${translationFilePath}.json`;
}
function getPluginTranslationFilePath({
localizationDir,
plugin,
translationFilePath,
}: TranslationContext & {
plugin: InitializedPlugin;
translationFilePath: string;
}): string {
const dirPath = getPluginI18nPath({
localizationDir,
pluginName: plugin.name,
pluginId: plugin.options.id,View on GitHub (pinned to 3f483e80e3)
Solutions
- Remove the `.json` suffix from the translation file path your plugin returns.
- Use the path without extension consistently in `getTranslationFiles` and `translate`.
- If you control the format and want `.json` literally, you cannot — rely on Docusaurus to append it.
Example fix
// before
getTranslationFiles: () => [{path: 'fr/messages.json', content: {}}],
// after
getTranslationFiles: () => [{path: 'fr/messages', content: {}}], Defensive patterns
Strategy: validation
Validate before calling
function assertNoJsonExt(path: string) {
if (path.endsWith('.json')) throw new Error(`Remove .json from translation path: ${path}`);
} Prevention
- Return translation paths without any extension from plugin i18n hooks.
- Document this contract for any third-party plugin you maintain.
- Add a unit test asserting paths have no `.json` suffix.
When it happens
Trigger: A plugin's `getTranslationFiles` / `translate` hook returns a path like `'i18n/fr/messages.json'`. The check at translations.ts:171-176 fires before the internal `.json` append.
Common situations: Third-party plugin authors copying example code that included the extension; refactoring a plugin and adding `.json` for clarity; migrating content where source files used `.json`.
Related errors
- 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
- No tags file '${relativeFilePath}' could be found in any of
- Can't find locale config for locale ${logger.code(localeToLo
AI-assisted analysis of facebook/docusaurus@3f483e80e3 (2026-08-12).
Data as JSON: /api/errors/0aeeb74cddd95a34.
Report an issue: GitHub.