fix(i18n): support hyphenated locale codes - #1434
Open
yeeway0609 wants to merge 1 commit into
Open
Conversation
|
@yeeway0609 is attempting to deploy a commit to the NuxtLabs Team on Vercel. A member of the Team first needs to authorize it. |
commit: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves #1233, resolves #1280.
Any locale whose code contains a hyphen —
zh-CN,zh-TW,pt-BR,en-GB,de-CH— 404s on every route, and the build still exits 0. Docus shipszh-CN.json,zh-TW.jsonandpt-BR.json, so those locales look supported but have never worked.Why it happens
The collection is created, but it is empty:
One locale code is used for four things with conflicting constraints:
zh-CNresolveCollection()rejects-and drops the collectiondocs_zh_cnincludeglobcontent/zh-CN/lower: true/zh-cn/...html lang,hreflangzh-CN#1246 addressed only the first row. One code, four call sites, four spellings:
Before #1246 the collection name was invalid and Nuxt Content warned about it; after #1246 the name is valid and the failure is silent. Both states 404.
Reproduction on
main(v5.13.0)pnpx create-docus i18n-test -t i18n cd i18n-testIn
nuxt.config.ts, replacefrwith any hyphenated code:mv content/fr content/zh-CN pnpm build && node .output/server/index.mjsThe build exits 0, but:
/enreturns 200, every/zh-CNroute returns 404. Prerender 404s are non-fatal, which is why CI (lint+typecheck+build) stays green on a completely broken locale.How people work around it today
Every workaround avoids the hyphen, at the cost of a non-standard locale code.
Rename the bundled locale file — suggested in #1280 ("it no longer conforms to geographic identifier codes such as
zh-cn,zh-tw,zh-hk"):Use a bare language code. This is what we ship today. It routes, but
@nuxt/ui/localehas nozhexport, so component strings stay English and<html lang>is wrong — and it needs a hook to undo Docus's own locale filter:zhcannot distinguish Simplified from Traditional, so sites needing both end up dropping one.The fix
Derive the two forms the code actually needs instead of overloading one variable — the same layering the rest of the ecosystem uses, where
@nuxt/uikeepscode: "zh-TW"in its data and normalizes only its export names:modules/config.ts, since Nuxt Content always generates lowercase page paths. The original tag is kept as the locale'slanguage, so<html lang>andhreflangstill emitzh-TW.defaultLocaleis normalized the same way.content/zh-TW/andcontent/zh-tw/both resolve andincludegets the real folder name — which is what Fix i18n collection name strategy #1246 broke.getLocaleKey()— incontent.config.tsand the nine runtime call sites that build one.@nuxt/uilocale lookup, which used the raw code and silently fell back to English.zh-TW.jsonserves thezh-twlocale, in both the i18n registration and the single-language plugin.One part is less obvious:
@nuxtjs/i18ncollects its locales from each layer's raw config, not from the mergednuxt.options.i18n. Normalizing only the merged options registers a second, empty locale, somodules/config.tsnormalizes the layer configs too.Users keep writing standard BCP 47 codes, and name the content folder however they like:
What is accepted, before and after
codeinnuxt.configen,fr,ja/en/en— unchangedzh-TW,zh-CN,pt-BR,en-GB/zh-tw,/zh-cn,/pt-br,/en-gbzh-tw(already lowercase)/zh-twcode: 'zh-TW'content/zh-TW/content/zh-tw/<html lang>en—@nuxt/uilookup missed and fell backzh-TW— the locale'slanguagehreflangzh-tw, matching the URLBreaking changes
None in practice.
en,fr,ja, …) — every transform is a no-op. Verified by rebuilding theen+frdocs site: identical routes, no 404s.content/zh-CN/folders keep working; the folder is matched case-insensitively rather than renamed.Verification
A project with three locales (
en,zh-CN,zh-TW), built onmainand on this branch:pnpm build— onmainthe prerender log shows[404] Page not foundfor/zh-CNand/zh-TW; on this branch it does not.node .output/server/index.mjs, then open the locale routes:main/en,/en/getting-started/introduction/zh-cn,/zh-cn/getting-started/introduction/zh-tw,/zh-tw/getting-started/introductionView source on a
zh-TWpage —<html lang="zh-TW" dir="ltr">, the canonical tag, not the lowercased URL code.Docus UI strings come from the bundled
zh-CN.json/zh-TW.json, and the Nuxt UI component strings from@nuxt/ui/locale'szh_cn/zh_tw.The language switcher lists all three locales, and its links, the sidebar and
sitemap.xmlall point at/zh-cn/...and/zh-tw/....Rebuilding the
en+frdocs site gives identical routes and no 404s.A locale with no bundled locale file still warns and is skipped, as before.
Content folders work in either case —
content/zh-TW/andcontent/zh-tw/both resolve, on case-sensitive filesystems too.pnpm lint,pnpm typecheckandpnpm docs:buildall pass.Related
enpitsuLin/docus-i18n-code— the minimal reproduction published with The language code with hyphens can't generate the collection correctly #1233 (pt-BR).Everything above is a proposal, let me know if you would rather solve this differently. 😊