Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Fix URL Anchor Hash Inconsistency When Switching Languages #160

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

clicelee
Copy link
Contributor

@clicelee clicelee commented Feb 16, 2025

📝 Key Changes

This PR ensures that anchor hash values remain consistent across different languages. Previously, switching languages would not update the hash, causing incorrect navigation. By implementing a slugify function and using a titleMap based on English headers, it now generates unified anchor values automatically, preventing unwanted page jumps.

Changed file: .vitepress/config.mts

Problem

In the Frontend Fundamentals, when navigating to a specific section, the section title is appended as a hash value in the URL.

For example:
✅ Korean URL:
https://frontend-fundamentals.com/code/examples/submit-button.html#👃-코드-냄새-맡아보기
However, when switching to another language, the hash value does not change, which results in incorrect navigation.

❌ Incorrect behavior when switching languages:
https://frontend-fundamentals.com/ja/code/examples/submit-button.html#👃-코드-냄새-맡아보기
Since the hash remains the same across all languages, the browser does not navigate to the correct section and instead moves to the top of the page.


Solution Written in VitePress

According to VitePress documentation, we can unify the anchor hash values across different languages by explicitly specifying the anchor name in the markdown headers:

## 코드 예시 {#code-example}
## 代码示例 {#code-example}
## Code Example {#code-example}

This ensures that all languages use the same #code-example hash, leading to consistent navigation:
...com/en/#code-example
...com/ko/#code-example

However manually defining {#anchor-name} for every header in a multilingual documentation is tedious and error-prone, I automated the process by using a slugify function.


Solution using slugify and titleMap

  • The anchor values are based on English headers (titleMap follows English headers as the default).
  • If the current header is in another language, it is mapped to its corresponding English anchor using titleMap.
  • If a header is slightly different but should share the same anchor (e.g., Code Example 1: LoginStartPage and Code Example), I explicitly define the mapping in titleMap.
  • Any extra symbols (such as emojis) are removed to ensure clean and consistent anchor values.
const titleMap: Record<string, string> = {
    "Code Example": "code-example",
    "코드 예시": "code-example",
    代码示例: "code-example",
    コード例: "code-example",
  }

Implementation Summary

  • Step 1: Remove emojis and normalize the string.
  • Step 2: Check for an exact match in titleMap.
  • Step 3: If no exact match, find the closest partial match.
  • Step 4: Generate a slug from the header text.
  anchor: {
      slugify: (str) => {
        // 1. Remove emojis
        let cleanedStr = str
          .normalize("NFKC")
          .replace(/[\p{Emoji_Presentation}\p{Extended_Pictographic}]/gu, "")
          .replace(/\uFE0F/g, "")
          .trim();

        // 2. Check for an exact match in titleMap
        if (titleMap[cleanedStr]) {
          return titleMap[cleanedStr];
        }

        // 3. Find the longest partial match in titleMap
        let matchedKey = Object.keys(titleMap)
          .filter((key) => cleanedStr.includes(key))
          .sort((a, b) => b.length - a.length)[0];

        if (matchedKey) {
          return titleMap[matchedKey];
        }
        // 4. Apply general slug conversion
        let slug = cleanedStr
          .trim()
          .toLowerCase()
          .replace(/[^\p{L}\p{N}\s-]/gu, "")
          .replace(/\s+/g, "-");

        return slug;
      }

💡 Additional Notes

  • Future headers should be added to titleMap to maintain consistency.

🖼️ Before and After Comparison

Before
When switching to another language, the hash value does not change, which results in incorrect navigation.
Since the hash remains the same across all languages, the browser does not navigate to the correct section and instead moves to the top of the page.

BEFORE.mov

After
When switching between languages, users can stay on the correct section instead of being sent to the top of the page.

AFTER.mov

Copy link

vercel bot commented Feb 16, 2025

@clicelee is attempting to deploy a commit to the Toss Team on Vercel.

A member of the Team first needs to authorize it.

@clicelee clicelee changed the title Fix: Fix Anchor Hash Inconsistency When Switching Languages Fix: Fix URL Anchor Hash Inconsistency When Switching Languages Feb 16, 2025
Copy link
Collaborator

@milooy milooy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @clicelee, thanks for the PR! I really appreciate you finding and fixing this issue. Sorry for the late comment.

I have a couple of thoughts:

  1. This solution requires adding every possible header text to the titleMap. As our documentation grows and changes, managing that could become a hassle. What do you think about that?
  2. Also, is it really necessary to have anchors work across different languages? The current version keeps the anchor static for a single language, and while the new approach fixes the inconsistency, it relies on a fixed titleMap, which might bring its own challenges.

I'd love to hear your thoughts on these trade-offs. Thanks again for your work on this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants