docusaurus icon indicating copy to clipboard operation
docusaurus copied to clipboard

auto-translated hash-links fail to route correctly

Open Alex-Genovese opened this issue 4 months ago • 9 comments

Have you read the Contributing Guidelines on issues?

Prerequisites

  • [x] I'm using the latest version of Docusaurus.
  • [ ] I have tried the npm run clear or yarn clear command.
  • [ ] I have tried rm -rf node_modules yarn.lock package-lock.json and 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.

Alex-Genovese avatar Aug 27 '25 12:08 Alex-Genovese

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>.

Josh-Cena avatar Aug 28 '25 05:08 Josh-Cena

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&amp;_x_tr_tl=it&amp;_x_tr_hl=en&amp;_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&#x27;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 .....

Alex-Genovese avatar Aug 28 '25 06:08 Alex-Genovese

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>.

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.

slorber avatar Aug 28 '25 12:08 slorber

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...

Josh-Cena avatar Aug 28 '25 15:08 Josh-Cena

Not sure what is going on, this needs to be investigated 😅

slorber avatar Aug 29 '25 17:08 slorber

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-link is 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?

Alex-Genovese avatar Sep 02 '25 12:09 Alex-Genovese

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 avatar Sep 04 '25 08:09 Alex-Genovese

@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.

slorber avatar Sep 04 '25 14:09 slorber

@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.

Alex-Genovese avatar Sep 04 '25 14:09 Alex-Genovese