diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/translations.test.ts.snap b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/translations.test.ts.snap index 8d5f668a1b26..51541aadebad 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/translations.test.ts.snap +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/translations.test.ts.snap @@ -168,6 +168,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` "sourceDirName": "", "tags": [], "title": "doc1 title", + "unlisted": false, "version": "any", }, { @@ -188,6 +189,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` "sourceDirName": "", "tags": [], "title": "doc2 title", + "unlisted": false, "version": "any", }, { @@ -208,6 +210,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` "sourceDirName": "", "tags": [], "title": "doc3 title", + "unlisted": false, "version": "any", }, { @@ -228,6 +231,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` "sourceDirName": "", "tags": [], "title": "doc4 title", + "unlisted": false, "version": "any", }, { @@ -248,12 +252,14 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` "sourceDirName": "", "tags": [], "title": "doc5 title", + "unlisted": false, "version": "any", }, ], "drafts": [], "isLast": true, "label": "current label (translated)", + "noIndex": false, "path": "/docs/", "routePriority": undefined, "sidebarFilePath": "any", @@ -354,6 +360,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` "sourceDirName": "", "tags": [], "title": "doc1 title", + "unlisted": false, "version": "any", }, { @@ -374,6 +381,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` "sourceDirName": "", "tags": [], "title": "doc2 title", + "unlisted": false, "version": "any", }, { @@ -394,6 +402,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` "sourceDirName": "", "tags": [], "title": "doc3 title", + "unlisted": false, "version": "any", }, { @@ -414,6 +423,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` "sourceDirName": "", "tags": [], "title": "doc4 title", + "unlisted": false, "version": "any", }, { @@ -434,12 +444,14 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` "sourceDirName": "", "tags": [], "title": "doc5 title", + "unlisted": false, "version": "any", }, ], "drafts": [], "isLast": true, "label": "2.0.0 label (translated)", + "noIndex": false, "path": "/docs/", "routePriority": undefined, "sidebarFilePath": "any", @@ -540,6 +552,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` "sourceDirName": "", "tags": [], "title": "doc1 title", + "unlisted": false, "version": "any", }, { @@ -560,6 +573,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` "sourceDirName": "", "tags": [], "title": "doc2 title", + "unlisted": false, "version": "any", }, { @@ -580,6 +594,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` "sourceDirName": "", "tags": [], "title": "doc3 title", + "unlisted": false, "version": "any", }, { @@ -600,6 +615,7 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` "sourceDirName": "", "tags": [], "title": "doc4 title", + "unlisted": false, "version": "any", }, { @@ -620,12 +636,14 @@ exports[`translateLoadedContent returns translated loaded content 1`] = ` "sourceDirName": "", "tags": [], "title": "doc5 title", + "unlisted": false, "version": "any", }, ], "drafts": [], "isLast": true, "label": "1.0.0 label (translated)", + "noIndex": false, "path": "/docs/", "routePriority": undefined, "sidebarFilePath": "any", diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/translations.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/translations.test.ts index 87485078fad5..7b5eddd68f06 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/translations.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/translations.test.ts @@ -18,10 +18,13 @@ import type { } from '@docusaurus/plugin-content-docs'; import type {Sidebar} from '../sidebars/types'; -function createSampleDoc(doc: Pick): DocMetadata { +function createSampleDoc( + doc: Pick & Partial, +): DocMetadata { return { sourceDirName: '', draft: false, + unlisted: false, tags: [], editUrl: 'any', lastUpdatedAt: 0, @@ -50,6 +53,7 @@ function createSampleVersion( routePriority: undefined, sidebarFilePath: 'any', isLast: true, + noIndex: false, contentPath: 'any', contentPathLocalized: 'any', tagsPath: '/tags/', @@ -331,4 +335,80 @@ describe('translateLoadedContent', () => { translateLoadedContent(SampleLoadedContent, translationFiles), ).toMatchSnapshot(); }); + + it('translates pagination navigation titles for generated-index categories', () => { + const content: LoadedContent = { + loadedVersions: [ + createSampleVersion({ + versionName: CURRENT_VERSION_NAME, + docs: [ + createSampleDoc({ + id: 'doc1', + next: { + title: 'Getting started', + permalink: '/docs/category/getting-started-index-slug', + }, + }), + createSampleDoc({ + id: 'doc2', + previous: { + title: 'Getting started', + permalink: '/docs/category/getting-started-index-slug', + }, + next: { + title: 'doc3 title', + permalink: '/docs/doc3', + }, + }), + createSampleDoc({ + id: 'doc3', + previous: { + title: 'doc2 title', + permalink: '/docs/doc2', + }, + }), + ], + }), + ], + }; + + const translationFiles = getLoadedContentTranslationFiles(content); + const translatedFiles = translationFiles.map((translationFile) => + updateTranslationFileMessages( + translationFile, + (message) => `${message} (translated)`, + ), + ); + + const translated = translateLoadedContent(content, translatedFiles); + const [doc1, doc2, doc3] = translated.loadedVersions[0]!.docs; + + // doc1.next points to a generated-index category + // => title should be translated + expect(doc1!.next).toEqual({ + title: 'Getting started (translated)', + permalink: '/docs/category/getting-started-index-slug', + }); + + // doc2.previous points to a generated-index category + // => title should be translated + expect(doc2!.previous).toEqual({ + title: 'Getting started (translated)', + permalink: '/docs/category/getting-started-index-slug', + }); + + // doc2.next points to a regular doc + // => title should NOT be changed, it's already translated from the i18n MDX + expect(doc2!.next).toEqual({ + title: 'doc3 title', + permalink: '/docs/doc3', + }); + + // doc3.previous points to a regular doc + // => title should NOT be changed, it's already translated from the i18n MDX + expect(doc3!.previous).toEqual({ + title: 'doc2 title', + permalink: '/docs/doc2', + }); + }); }); diff --git a/packages/docusaurus-plugin-content-docs/src/translations.ts b/packages/docusaurus-plugin-content-docs/src/translations.ts index ecea3252d438..3230453a4a21 100644 --- a/packages/docusaurus-plugin-content-docs/src/translations.ts +++ b/packages/docusaurus-plugin-content-docs/src/translations.ts @@ -269,16 +269,64 @@ function getVersionTranslationFiles(version: LoadedVersion): TranslationFile[] { }, ]; } + +// TODO Docusaurus v4 or later +// this temporarily works, but it is not an ideal solution +// The docs navigation can be computed and shouldn't be part of LoadedVersion +// We need to derive the navigation from already translated content +// See https://github.com/facebook/docusaurus/pull/11794 +function translateDocNavigation( + docs: LoadedVersion['docs'], + translatedSidebars: Sidebars, +): LoadedVersion['docs'] { + // Build a map of permalink -> translated label for generated-index categories + const translatedLabelByPermalink = new Map(); + for (const sidebar of Object.values(translatedSidebars)) { + for (const category of collectSidebarCategories(sidebar)) { + if (category.link?.type === 'generated-index') { + translatedLabelByPermalink.set(category.link.permalink, category.label); + } + } + } + + if (translatedLabelByPermalink.size === 0) { + return docs; + } + + return docs.map((doc) => { + const previous = + doc.previous && translatedLabelByPermalink.has(doc.previous.permalink) + ? { + ...doc.previous, + title: translatedLabelByPermalink.get(doc.previous.permalink)!, + } + : doc.previous; + const next = + doc.next && translatedLabelByPermalink.has(doc.next.permalink) + ? { + ...doc.next, + title: translatedLabelByPermalink.get(doc.next.permalink)!, + } + : doc.next; + if (previous === doc.previous && next === doc.next) { + return doc; + } + return {...doc, previous, next}; + }); +} + function translateVersion( version: LoadedVersion, translationFiles: {[fileName: string]: TranslationFile}, ): LoadedVersion { const versionTranslations = translationFiles[getVersionFileName(version.versionName)]!.content; + const translatedSidebars = translateSidebars(version, versionTranslations); return { ...version, label: versionTranslations['version.label']?.message ?? version.label, - sidebars: translateSidebars(version, versionTranslations), + sidebars: translatedSidebars, + docs: translateDocNavigation(version.docs, translatedSidebars), }; }