auto-translated hash-links fail to route correctly
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.
- [ ] I have tried the
npm run clearoryarn clearcommand. - [ ] I have tried
rm -rf node_modules yarn.lock package-lock.jsonand re-installing packages. - [ ] I have tried creating a repro with https://new.docusaurus.io.
- [x] I have read the console error message carefully (if applicable).
Description
When auto-translating a Docusaurus generated page, the left hand side bar links work correctly but the right hand Table of Contents fail to route and translation ceases. This also applies to hash-link anchors at the ends of contents titles and to hash-links in the text body. The link route may also route back to a completely different but previously viewed page.
See attached file. The first tab shows a page working correctly in English then moves on to several tabs each with different failure examples.
https://github.com/user-attachments/assets/971f2c38-c012-41b4-820e-742a29d1277c
Reproducible demo
No response
Steps to reproduce
Go to this page in any browser
This page has the latest build code and reflects the fixes made with #11360 for issue #11358
Expected behavior
The links should route correctly and the translation should be maintained.
Other documenting systems are able to demonstrate correct behaviour with hash-links eg. Qemu
There is an npm module called react-router-hash-link which shows how this should work. This may also hold a possible solution?
See demo of this module at work:
https://github.com/user-attachments/assets/bf5e539d-78e3-4d58-959d-c8bb12c5d441
Actual behavior
The actual behaviour is fully documented in the initial video.
This shows, for example, the auto-translated Docusaurus blog for release 3.7, in French, routing to the 3.8 blog in English, when the ToC link for 'Souligner' is clicked.
Your environment
The reproducible example links all have the latest Docusaurus builds and the behaviour is the same in all browsers and across different Operating systems.
Self-service
- [ ] I'd be willing to fix this bug myself.
AFAIK, this happens because we applied translate="no" to the <a>, but in fact we do want Google Translate to process the <a> element so it can replace href="#..." with href="https://docusaurus-io.translate.goog/...#..., correct? In this case I believe the correct markup should be <a ...><span translate="no">#</span></a>.
Thanks for looking at this.
Would we also need to apply the translate="no" idea to in-body-text hash links?
In the main, initial video, the last tab shows how this also happens on in-body text links. I have attached the built output html for the page start given. The last line shows the hash-link and translate="no" is not present at all.
<!doctype html>
<html lang="en" dir="ltr" class="docs-wrapper plugin-docs plugin-id-default docs-version-current docs-doc-page docs-doc-id-Guides/Mac-OS" data-has-hydrated="false">
<head>
<meta charset="UTF-8">
<meta name="generator" content="Docusaurus v3.8.1">
<title data-rh="true">Mac OS Machines | qqX</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:image" content="https://qqxproject.org/img/qqX.social.card.jpeg"><meta data-rh="true" name="twitter:image" content="https://qqxproject.org/img/qqX.social.card.jpeg"><meta data-rh="true" property="og:url" content="https://qqxproject.org/docs/Guides/Mac-OS"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="qqX -Virtual Machine Manager"><meta data-rh="true" name="keywords" content="qemu, quickemu, quickget, quickgui, virtual machine, fixes, workarounds, easy"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Mac OS Machines | qqX"><meta data-rh="true" name="description" content="Guest Installation"><meta data-rh="true" property="og:description" content="Guest Installation"><link data-rh="true" rel="icon" href="/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://qqxproject.org/docs/Guides/Mac-OS"><link data-rh="true" rel="alternate" href="https://qqxproject.org/docs/Guides/Mac-OS" hreflang="en"><link data-rh="true" rel="alternate" href="https://qqxproject.org/docs/Guides/Mac-OS" hreflang="x-default"><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Mac OS Machines","item":"https://qqxproject.org/docs/Guides/Mac-OS"}]}</script><link rel="stylesheet" href="/assets/css/styles.7b869b1f.css">
<script src="/assets/js/runtime~main.36395134.js" defer="defer"></script>
<script src="/assets/js/main.f1bbdeb0.js" defer="defer"></script>
</head>
<body class="navigation-with-keyboard">
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><defs>
<symbol id="theme-svg-external-link" viewBox="0 0 24 24"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"/></symbol>
</defs></svg>
<script>!function(){var t=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return window.localStorage.getItem("theme")}catch(t){}}();document.documentElement.setAttribute("data-theme",t||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light")),document.documentElement.setAttribute("data-theme-choice",t||"system")}(),function(){try{const c=new URLSearchParams(window.location.search).entries();for(var[t,e]of c)if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id="__docusaurus"><link rel="preload" as="image" href="/img/favicon.ico"><div role="region" aria-label="Skip to main content"><a class="skipToContent_fXgn" href="#__docusaurus_skipToContent_fallback">Skip to main content</a></div><nav aria-label="Main" class="theme-layout-navbar navbar navbar--fixed-top"><div class="navbar__inner"><div class="theme-layout-navbar-left navbar__items"><button aria-label="Toggle navigation bar" aria-expanded="false" class="navbar__toggle clean-btn" type="button"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/"><div class="navbar__logo"><img src="/img/favicon.ico" alt="qqX Logo" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="/img/favicon.ico" alt="qqX Logo" class="themedComponent_mlkZ themedComponent--dark_xIcU"></div><b class="navbar__title text--truncate">qqX Virtual Machine Manager</b></a><a class="navbar__item navbar__link" href="/docs/Installation">Docs</a><a class="navbar__item navbar__link" href="/docs/Translation">Translation</a><a aria-current="page" class="navbar__item navbar__link navbar__link--active" href="/docs/Guides/Windows-OS">Guides for Windows and Mac</a><a class="navbar__item navbar__link" href="/docs/Advanced/Custom-Menus">Advanced Docs</a></div><div class="theme-layout-navbar-right navbar__items navbar__items--right"><a href="https://qqxproject-org.translate.goog/?_x_tr_sl=auto&_x_tr_tl=it&_x_tr_hl=en&_x_tr_pto=wapp" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Google Translate<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a><a href="https://github.com/qqxproject/qqX" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Source Code and Downloads<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a><div class="toggle_vylO colorModeToggle_DEke"><button class="clean-btn toggleButton_gllP toggleButtonDisabled_aARS" type="button" disabled="" title="system mode" aria-label="Switch between dark and light mode (currently system mode)"><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_g3eP lightToggleIcon_pyhR"><path fill="currentColor" d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"></path></svg><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_g3eP darkToggleIcon_wfgR"><path fill="currentColor" d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"></path></svg><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_g3eP systemToggleIcon_QzmC"><path fill="currentColor" d="m12 21c4.971 0 9-4.029 9-9s-4.029-9-9-9-9 4.029-9 9 4.029 9 9 9zm4.95-13.95c1.313 1.313 2.05 3.093 2.05 4.95s-0.738 3.637-2.05 4.95c-1.313 1.313-3.093 2.05-4.95 2.05v-14c1.857 0 3.637 0.737 4.95 2.05z"></path></svg></button></div><div class="navbarSearchContainer_Bca1"></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div id="__docusaurus_skipToContent_fallback" class="theme-layout-main main-wrapper mainWrapper_z2l0"><div class="docsWrapper_hBAB"><button aria-label="Scroll back to top" class="clean-btn theme-back-to-top-button backToTopButton_sjWU" type="button"></button><div class="docRoot_UBD9"><aside class="theme-doc-sidebar-container docSidebarContainer_YfHR"><div class="sidebarViewport_aRkj"><div class="sidebar_njMd"><nav aria-label="Docs sidebar" class="menu thin-scrollbar menu_SIkG"><ul class="theme-doc-sidebar-menu menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/docs/Guides/Windows-OS">Windows Machines</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link menu__link--active" aria-current="page" href="/docs/Guides/Mac-OS">Mac OS Machines</a></li></ul></nav></div></div></aside><main class="docMainContainer_TBSr"><div class="container padding-top--md padding-bottom--lg"><div class="row"><div class="col docItemCol_VOVn"><div class="docItemContainer_Djhp"><article><nav class="theme-doc-breadcrumbs breadcrumbsContainer_Z_bl" aria-label="Breadcrumbs"><ul class="breadcrumbs"><li class="breadcrumbs__item"><a aria-label="Home page" class="breadcrumbs__link" href="/"><svg viewBox="0 0 24 24" class="breadcrumbHomeIcon_YNFT"><path d="M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z" fill="currentColor"></path></svg></a></li><li class="breadcrumbs__item breadcrumbs__item--active"><span class="breadcrumbs__link">Mac OS Machines</span></li></ul></nav><div class="tocCollapsible_ETCw theme-doc-toc-mobile tocMobile_ITEo"><button type="button" class="clean-btn tocCollapsibleButton_TO0P">On this page</button></div><div class="theme-doc-markdown markdown"><header><h1>Mac OS Machines</h1></header><h2 class="anchor anchorWithStickyNavbar_LWe7" id="guest-installation">Guest Installation<a href="#guest-installation" class="hash-link" aria-label="Direct link to Guest Installation" title="Direct link to Guest Installation"></a></h2>
<p>During 2024, using qqX's iMacPro 2017 (Skylake Xeon) virtual CPU formula, <strong>the latest Sonoma 14.5 <a href="https://developer.apple.com/documentation/macos-release-notes" target="_blank" rel="noopener noreferrer">release</a> ran and still continues to run without problems.</strong></p>
<p>At the beginning of 2025, new Quickget updates allowed direct installation of 15.3 Sequoia. However, since then and since the release of 15.4 there have been issues which now, @ 06/2025, make this a non-recommended installation. See <a href="https://github.com/qqxproject/qqX/issues/9" target="_blank" rel="noopener noreferrer">https://github.com/qqxproject/qqX/issues/9</a></p>
<p>Installation routines are not completely perfect and tests show a repeat download/setup to be needed on occasion to get the Sonoma boot to work, but it does function ...</p>
<p>See the <a href="#installation-walk-through"><em>full</em> walk-thru</a></p>
I used this example as I couldn't find an example in the blog pages to use .....
AFAIK, this happens because we applied
translate="no"to the<a>, but in fact we do want Google Translate to process the<a>element so it can replacehref="#..."withhref="https://docusaurus-io.translate.goog/...#..., correct? In this case I believe the correct markup should be<a ...><span translate="no">#</span></a>.
Does it really need to translate the href?
If we have <a href="#anchor">, it should work with original/auto-translated content even if we are on a different domain.
If I disable JS on the translated page, I see the correct native behavior, so I guess we have some JS that diverges from the native behavior, maybe coming from React Router or our Link component.
Perhaps it does have something to do with our JS logic instead of translate="no", but if you check the DOM, with JS disabled, the <a> links get processed and the href becomes absolute (but the site is untranslated altogether), like https://docusaurus-io.translate.goog/blog/releases/3.8?_x_tr_sl=auto&_x_tr_tl=it&_x_tr_hl=en&_x_tr_pto=wapp#persistent-cache. With JS enabled, the <a> links remain as relative hash links, like #persistent-cache. Then, because of the <base href="https://docusaurus.io/blog/releases/3.8"> element they injected in the <head>, relative links redirect to the main site.
My current guess is that our link component somehow rewrites the href after Google Translate has already transformed the DOM? It probably has nothing to do with hydration because then the text content would be reverted as well...
Not sure what is going on, this needs to be investigated 😅
Is this worth a try?
Not having any idea if people are working on this behind the scenes and still finding my feet with React and with Docusaurus.....
I asked Co-Pilot the following:
Given the following issue:
@facebook/docusaurus/issues/11386
How easy would it be to add this module and method
https://www.npmjs.com/package/react-router-hash-link#custom-link?
Would a simple swizzle work?
And the reply was:
Docusaurus uses React Router under the hood, so
react-router-hash-linkis compatible. The module provides a<HashLink>component that fixes hash-link scrolling/routing issues, especially with SPA navigation and translated URLs.
Simple Swizzle?
-
For basic hash-links in text or TOC: Yes, a simple swizzle of the link component (e.g., @theme/Link) could be enough. You would customize it to use <HashLink> when a to prop contains a hash fragment.
-
For more advanced usage: If Docusaurus generates anchor links in multiple locations or if hash-links are deeply integrated (e.g., in Markdown rendering), you may need to swizzle additional components or patch how anchors are rendered.
// src/theme/Link/index.js
import React from 'react';
import { HashLink } from 'react-router-hash-link';
export default function Link(props) {
const { to, ...rest } = props;
if (to && to.includes('#')) {
return <HashLink to={to} {...rest} />;
}
// fallback to default
return <a href={to} {...rest} />;
}
- Caveats: If hash-links are rendered in complex ways (e.g., via Markdown or custom logic), you may need broader changes.
I have no real idea if this is right or wrong.
Maybe there's someone out there, or paid by Meta even, who understands the under-the-hood complexities, who might want to give this a go?
Or maybe Claude?
This worked for me this morning. Probably more of a partial workaround than a true fix. But for the in-body hash link problem, at least, and for the hash-linked page , cited in earlier comments
Changing this:
See the [full walk-thru](#installation-walk-through)
To this:
See the [full walk-thru](Mac-OS#installation-walk-through)
in the Markdown ...
<!-- changes this: -->
<p>See the <a href="#installation-walk-through"><em>full</em> walk-thru</a></p>
<!-- to this: -->
<p>See the <a href="/docs/Guides/Mac-OS#installation-walk-through"><em>full</em> walk-thru</a></p>
<!-- and in-vivo generates this:
https://qqxproject.org/docs/Guides/Mac-OS#installation-walk-through
which auto-translate can handle -->
For this one of the three sub-issues, it could be the best that we will be able to get, so I thought that I ought to share ....
Fixing the TOC will probably fix the titles issue too, I am guessing, but (caveat) whether it will fix this bit or whether it will break the workarounds, of course remains to be seen.
@Alex-Genovese I'm sorry but it's not reasonable for us to install a library that has not been maintained over the last 4 years and was initially created to solve a different issue opened in 2016. Even more so when we plan to update React Router to a newer version soon.
If you want to help with shipping this feature, you should understand why the problem happens in the first place and provide a tailor-made solution. You can take inspiration from the library, but in all cases, you should understand how the solution you propose works to solve this problem 😅
It looks like you are trying random AI/npm solutions to a problem you don't even understand. That's not going to help. Feel free to use whatever solution you want on your own site, at your own risk, but if we add this to Docusaurus core, we must understand the why and how.
@Alex-Genovese I'm sorry but it's not reasonable for us to install a library that has not been maintained over the last 4 years
@slorber Yes, I am still on learning curve here ...
However, when I took a close look at the lib it seemed very simple and straightforward. Nothing much to it really.
So, probably not much in the need of maintenance. Or something that could yield a few of the key code lines or ideas.
This is probably what I had in mind.