8000 fix(nuxt): decode client-side pathname for non-ASCII route aliases by dannote · Pull Request #34043 · nuxt/nuxt · GitHub
[go: up one dir, main page]

Skip to content

fix(nuxt): decode client-side pathname for non-ASCII route aliases#34043

Merged
danielroe merged 1 commit intonuxt:mainfrom
dannote:fix/decode-client-path-for-non-ascii-aliases
Jan 20, 2026
Merged

fix(nuxt): decode client-side pathname for non-ASCII route aliases#34043
danielroe merged 1 commit intonuxt:mainfrom
dannote:fix/decode-client-path-for-non-ascii-aliases

Conversation

@dannote
Copy link
Contributor
@dannote dannote commented Jan 8, 2026

🔗 Linked issue

Fixes #34042

📚 Description

Problem

Non-ASCII characters in route aliases don't work on the client side. Users have to manually encode aliases:

import { encodePath } from 'ufo'
definePageMeta({
  alias: [encodePath('/товары')] // workaround
})

Root cause

The server decodes incoming URLs via decodePath(event.path) in packages/nitro-server/src/runtime/utils/renderer/app.ts, but the client uses window.location.pathname directly without decoding.

For non-ASCII characters, browsers return encoded paths in location.pathname (e.g., /%D1%82%D0%BE%D0%B2%D0%B0%D1%80%D1%8B instead of /товары), causing a mismatch with decoded aliases.

Solution

Apply decodePath from ufo to client-side paths in createCurrentLocation() to match server behavior.

Test plan

  • Added test case for unicode characters in alias paths (/товары, /produits, /製品)
  • All 707 unit tests pass

@dannote dannote requested a review from danielroe as a code owner January 8, 2026 11:40
@bolt-new-by-stackblitz
Copy link

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@pkg-pr-new
Copy link
pkg-pr-new bot commented Jan 8, 2026

Open in StackBlitz

@nuxt/kit

npm i https://pkg.pr.new/@nuxt/kit@34043

@nuxt/nitro-server

npm i https://pkg.pr.new/@nuxt/nitro-server@34043

nuxt

npm i https://pkg.pr.new/nuxt@34043

@nuxt/rspack-builder

npm i https://pkg.pr.new/@nuxt/rspack-builder@34043

@nuxt/schema

npm i https://pkg.pr.new/@nuxt/schema@34043

@nuxt/vite-builder

npm i https://pkg.pr.new/@nuxt/vite-builder@34043

@nuxt/webpack-builder

npm i https://pkg.pr.new/@nuxt/webpack-builder@34043

commit: 3aed7d1

@coderabbitai
Copy link
Contributor
coderabbitai bot commented Jan 8, 2026

Walkthrough

This pull request addresses non-ASCII character handling in route aliases by decoding URL-encoded paths during client-side route matching. The router plugin is updated to import and apply decodePath from 'ufo' to path computations in both hash-based and standard path extraction. Test coverage is expanded to verify alias handling with Unicode characters, and SSR route expectations are updated to reflect the "/products" pattern.

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed) 8000
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: fixing client-side pathname decoding for non-ASCII route aliases, which is the primary objective of this PR.
Description check ✅ Passed The description is well-related to the changeset, clearly explaining the problem, root cause, solution, and test plan for fixing non-ASCII route alias handling on the client side.
Linked Issues check ✅ Passed The code changes fully address issue #34042 by applying decodePath to client-side paths in the router plugin, adding comprehensive test coverage for unicode aliases, and matching the server's decoding behaviour.
Out of Scope Changes check ✅ Passed All code changes are directly related to fixing non-ASCII route alias handling: router plugin decoding, test snapshot updates, and new unicode alias test case are all within scope.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c8b9b81 and 3aed7d1.

⛔ Files ignored due to path filters (2)
  • packages/nuxt/test/__snapshots__/pages-override-meta-disabled.test.ts.snap is excluded by !**/*.snap
  • packages/nuxt/test/__snapshots__/pages-override-meta-enabled.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (3)
  • packages/nuxt/src/pages/runtime/plugins/router.ts
  • packages/nuxt/test/nitro-ssr-routes.test.ts
  • packages/nuxt/test/pages.test.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Follow standard TypeScript conventions and best practices

Files:

  • packages/nuxt/test/nitro-ssr-routes.test.ts
  • packages/nuxt/test/pages.test.ts
  • packages/nuxt/src/pages/runtime/plugins/router.ts
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx,js,jsx,vue}: Use clear, descriptive variable and function names
Add comments only to explain complex logic or non-obvious implementations
Keep functions focused and manageable (generally under 50 lines), and extract complex logic into separate domain-specific files
Remove code that is not used or needed
Use error handling patterns consistently

Files:

  • packages/nuxt/test/nitro-ssr-routes.test.ts
  • packages/nuxt/test/pages.test.ts
  • packages/nuxt/src/pages/runtime/plugins/router.ts
**/*.{test,spec}.{ts,tsx,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Write unit tests for core functionality using vitest

Files:

  • packages/nuxt/test/nitro-ssr-routes.test.ts
  • packages/nuxt/test/pages.test.ts
🧠 Learnings (3)
📚 Learning: 2025-11-25T11:42:16.132Z
Learnt from: CR
Repo: nuxt/nuxt PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-25T11:42:16.132Z
Learning: Applies to **/e2e/**/*.{ts,tsx,js} : Write end-to-end tests using Playwright and `nuxt/test-utils`

Applied to files:

  • packages/nuxt/test/pages.test.ts
📚 Learning: 2024-11-05T15:22:54.759Z
Learnt from: GalacticHypernova
Repo: nuxt/nuxt PR: 26468
File: packages/nuxt/src/components/plugins/loader.ts:24-24
Timestamp: 2024-11-05T15:22:54.759Z
Learning: In `packages/nuxt/src/components/plugins/loader.ts`, the references to `resolve` and `distDir` are legacy code from before Nuxt used the new unplugin VFS and will be removed.

Applied to files:

  • packages/nuxt/src/pages/runtime/plugins/router.ts
📚 Learning: 2024-12-12T12:36:34.871Z
Learnt from: huang-julien
Repo: nuxt/nuxt PR: 29366
File: packages/nuxt/src/app/components/nuxt-root.vue:16-19
Timestamp: 2024-12-12T12:36:34.871Z
Learning: In `packages/nuxt/src/app/components/nuxt-root.vue`, when optimizing bundle size by conditionally importing components based on route metadata, prefer using inline conditional imports like:

```js
const IsolatedPage = route?.meta?.isolate ? defineAsyncComponent(() => import('#build/isolated-page.mjs')) : null
```

instead of wrapping the import in a computed property or importing the component unconditionally.

Applied to files:

  • packages/nuxt/src/pages/runtime/plugins/router.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: test-fixtures (windows-latest, dev, vite-env-api, default, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (windows-latest, built, vite, async, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (windows-latest, dev, vite, default, manifest-off, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, webpack, default, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (windows-latest, built, vite-env-api, async, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, dev, vite, default, manifest-off, json, lts/-1)
  • GitHub Check: test-fixtures (windows-latest, built, vite, async, manifest-off, json, lts/-1)
  • GitHub Check: test-fixtures (windows-latest, dev, vite, async, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (windows-latest, dev, vite, async, manifest-off, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, vite-env-api, default, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, vite, async, manifest-on, js, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, vite, default, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, dev, vite, async, manifest-off, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, dev, vite-env-api, default, manifest-on, json, lts/-1)
  • GitHub Check: test-benchmark
  • GitHub Check: typecheck (ubuntu-latest, bundler)
  • GitHub Check: test-size
  • GitHub Check: release-pkg-pr-new
  • GitHub Check: typecheck (windows-latest, bundler)
  • GitHub Check: code
🔇 Additional comments (4)
packages/nuxt/src/pages/runtime/plugins/router.ts (2)

5-5: LGTM!

The addition of decodePath to the existing ufo imports is correct and necessary for the fix.


38-40: Excellent fix for non-ASCII route alias matching.

The application of decodePath to both hash-based and standard pathname extraction correctly aligns client-side behaviour with the server, which decodes paths using decodePath(event.path). This ensures that non-ASCII characters (e.g., /товары) are properly decoded from their percent-encoded form (/%D1%82%D0%BE%D0%B2%D0%B0%D1%80%D1%8B) before route matching.

The placement is correct—applying decodePath after withoutBase ensures the base is removed first, then the path is decoded.

packages/nuxt/test/pages.test.ts (1)

838-861: LGTM!

The test case properly verifies that route generation handles unicode characters in alias paths. The use of multiple languages (Russian, French, and Japanese) provides good coverage for non-ASCII character handling.

packages/nuxt/test/nitro-ssr-routes.test.ts (1)

69-69: LGTM!

The snapshot update correctly includes the new /products route from the unicode alias test case.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codspeed-hq
Copy link
codspeed-hq bot commented Jan 8, 2026

Merging this PR will improve performance by 14.34%

Summary

⚡ 1 improved benchmark
✅ 9 untouched benchmarks

Performance Changes

Benchmark BASE HEAD Efficiency
writeTypes in the basic-types fixture 94.7 ms 82.8 ms +14.34%

Comparing dannote:fix/decode-client-path-for-non-ascii-aliases (3aed7d1) with main (8f4fbec)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (c8b9b81) during the generation of this report, so 8f4fbec was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@dannote
Copy link
Contributor Author
dannote commented Jan 8, 2026

Yep, @coderabbitai correctly spotted #33990. This PR adds the client-side counterpart (window.location.pathname comes back encoded).

@coderabbitai
Copy link
Contributor
coderabbitai bot commented Jan 8, 2026

Tip

For best results, initiate chat on the files or code changes.

@dannote, thank you for the confirmation! That makes perfect sense—since browsers return window.location.pathname percent-encoded for non-ASCII characters, applying decodePath on the client side ensures the path matching behavior is consistent with how the server handles incoming URLs via decodePath(event.path). This elegantly solves the mismatch for unicode route aliases like /товары, /produits, and /製品.

(ᵔᴥᵔ)


✏️ Learnings added
Learnt from: dannote
URL: https://github.com/nuxt/nuxt/pull/34043

Timestamp: 2026-01-08T12:11:58.919Z
Learning: In Nuxt's router plugin (packages/nuxt/src/pages/runtime/plugins/router.ts), window.location.pathname returns percent-encoded values for non-ASCII characters and needs to be decoded using decodePath from ufo to match server-side path handling behavior.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Client-side route aliases with non-ASCII characters don't match

2 participants

0