docusaurus
docusaurus copied to clipboard
Labels do not have unique translation keys
Have you read the Contributing Guidelines on issues?
- [x] I have read the Contributing Guidelines on issues.
Prerequisites
- [x] I'm using the latest version of Docusaurus.
- [x] I have tried the
npm run clearoryarn clearcommand. - [x] I have tried
rm -rf node_modules yarn.lock package-lock.jsonand re-installing packages. - [x] I have tried creating a repro with https://new.docusaurus.io.
- [x] I have read the console error message carefully (if applicable).
Description
In the sidebars.ts file, if you give multiple objects the same label (e.g., "How-to guides"), they will not generate unique translation keys. This means that the description field on those objects will not work as one of the objects will clobber all of the other ones.
As an example, let's say I want my site to look like this:
Topic A
Getting Started
...
How to guides
...
References
...
Topic B
Getting Started
...
How to guides
...
References
...
In my sidebars.ts file, I figured I could do something like this:
type: 'category',
label: 'References',
link: {
type: 'generated-index',
title: 'References',
description: 'Moderne DX reference docs.',
slug: '/administrator-documentation/moderne-dx/references',
keywords: ['reference'],
},
and
type: 'category',
label: 'References',
link: {
type: 'generated-index',
title: 'References',
description: 'Moderne Platform reference docs.',
slug: '/administrator-documentation/moderne-platform/references',
keywords: ['reference'],
},
However, that will result in one of the categories not having the correct description:
Related information here: https://github.com/facebook/docusaurus/discussions/10906#discussioncomment-12079496
Reproducible demo
https://github.com/mike-solomon/docusaurus-testing/tree/main/website
Steps to reproduce
- Launch the side.
- Navigate to
foo/how-to. - Notice that it has the description for the
bar/how-topage.
Expected behavior
I would expect the descriptions on the category pages to match what I wrote in the sidebars.ts file.
Actual behavior
One or more of my pages descriptions gets clobbered with the incorrect description.
Your environment
- Public source code: https://github.com/moderneinc/moderne-docs
- Public site URL: https://docs.moderne.io/
- Docusaurus version used: 3.7.0
- Operating system and version (e.g. Ubuntu 20.04.2 LTS): Mac OS 15.3
Self-service
- [ ] I'd be willing to fix this bug myself.
Hi! I ran into the same issue with the sidebar translation generation when working with duplicate labels, I'd like to share the details and a possible solution.
In the getTranslationsFiles method, an object is constructed using sidebar data. The problem arises when two sidebar categories share the same label for example, both labeled "Guides". In such cases, the generated object keys become identical. Since JavaScript objects cannot have duplicate keys within the same level, this leads to conflicts.
Here's an example of the issue
{
path: "current",
content: {
"sidebar.docs.category.Guides.link.generated-index.description": {
message: "Let's learn about the most important Docusaurus concepts!",
description: "First Description",
},
"sidebar.docs.category.Guides.link.generated-index.description": {
message: "Docusaurus Guides",
description: "Second Description",
}
}
}
As you can see, the key "sidebar.docs.category.Guides.link.generated-index.description" appears twice, which is not valid in JavaScript.
This object is constructed in packages/docusaurus-plugin-content-docs/src/translations.ts specifically between line 63 - 72, as shown in the screenshot below:
Proposed Solution
To address this, I initially modified the structure to use an array of objects instead of a single object. Here’s the new format I propose
{
path: "current",
content: [
{
"sidebar.docs.category.Guides.link.generated-index.description": {
message: "Let's learn about the most important Docusaurus concepts!",
description: "First Description",
}
},
{
"sidebar.docs.category.Guides.link.generated-index.description": {
message: "Docusaurus Guides",
description: "Second Description",
}
}
]
}
This avoids the duplicate key issue, but it does introduce some side effects in the docusaurus-plugin-content-docs logic. Fortunately, the impact is limited since the methods in that file are mostly self contained and don't affect each other directly.
My next idea was to adjust the logic that assigns the description key by comparing both the key and the value. For example, in the same file translations.ts, line 137 is where the description is assigned:
packages/docusaurus-plugin-content-docs/src/translations.ts 137 is where the description assignment happens refer to the screenshot below
When mapping the descriptions from the JSON back to the sidebar structure, we have access to the current category’s description via category.link.description. So with the array-based format, we could update the transformation logic accordingly to handle it properly.
However, I later discovered that this change would interfere with the writeTranslations method, which is responsible for handling localizations. Unfortunately, this means my proposed format could lead to further side effects and may not be a viable solution without deeper refactoring.
I'm exploring how we could fix those issues in https://github.com/facebook/docusaurus/pull/11228
The problem is that the fix is likely to be a breaking change, and we need to figure out how to roll it out, possibly using v4 future flags.
Do not localize for the default locale?
One way to mitigate this easily is to disable the localization process for the current locale. For unlocalized sites, it's not really useful to try to localize strings.
Most sites with a single locale don't use the i18n folder to override the labels we provide, so making it opt-in would help mitigate the problem.
It's unusual to have conclifts, and it's also unusual to have localized sites, so having both at the same time is even more unusual, which saves us time to design and fix the underlying issue.
Keep translation keys short, but report conflicts?
We have conflicts because it's difficult to generate unique translation keys.
At the same time, we want the translation keys to be relatively short, easy to understand, and do not to change whenever we refactor the sidebar.
We could add the parent/breadcrumb labels, sidebar position index or other fancy things, but this is likely to be annoying in practice since this will lead to the keys to change whenever you change anything in the sidebar.
Instead of using more complex labels, my solution would rather to fail fast (or warn) when such conflict happen, and for the rare cases where this happen, let the user provide explicit translation keys (for example, using a dedicated sidebar item attribute).
Does it make sense?
The idea for me would be that:
- Common case: unlocalized sites should be allowed to have label conflicts without any visual glitch
- Edge case: localized sites with label conflicts would have to provide explicit translation keys for conflicting items
Docusaurus v3.9 will throw a clear error when it encounters i18n translation key conflicts: https://github.com/facebook/docusaurus/pull/11228
And you can resolve those conflicts by adding a unique key attribute to sidebar items that share the same label.
Now I'll try to follow up and see if we can avoid all this for sites that do not even use i18n: https://github.com/facebook/docusaurus/pull/11304
In v3.9, unlocalized sites shouldn't need to worry about translation key conflicts anymore: https://github.com/facebook/docusaurus/pull/11304
For Docusaurus v3.9.2 we are also fixing/completing the support with the sidebar_key front matter: https://github.com/facebook/docusaurus/pull/11490
If you have Feature1/API/index.md, you can pass a unique key such as feature1.api instead of having to create a _category_.json with a "key": "feature1.api" attribute.