feat(registry): add next-intl localized routes#350
Conversation
# Conflicts: # apps/registry/package.json # pnpm-lock.yaml
bntvllnt
left a comment
There was a problem hiding this comment.
@bntvllnt Review verdict: APPROVE recommended for reviewer triage — no source blockers found
Head reviewed: 053e00a11db6b02a688a887b3cf27b41be84bd71
No code blockers found after full changed-file review of the localized registry route/content implementation.
Evidence checked:
- PR body references
Closes #281and names the current head. - CI includes
pnpm -F @vllnt/ui-registry check:translations; localcheck:translationspassed and en/fr message key parity is clean. - Locale routing, canonical/hreflang helpers, localized sitemap entries, machine route redirects, and localized overlay registry handling are internally consistent in the changed files.
STATUS
- GitHub Actions/code checks are green and
Vercel – storybookis SUCCESS. Vercel – ui.vllnt.ai: FAILUREis eligible for the PM stale-Vercel reviewer-triage waiver only; it is not merge/release approval.- Validation gap: local registry TypeScript could not be reproduced because this local workspace lacks
next-intlinnode_modules; live GitHub Quality Gates are green.
|
Preview ready · Updated 2026-06-03T20:04:55Z
Inspect
|
…e loops - Replace useLocale/useTranslations (client hooks) with getLocale/getTranslations from next-intl/server so metadata export can coexist in the same file - Remove functional/no-loop-statements eslint-disable from llms.txt and llms-full.txt routes; refactor for-loops to map+spread and reduce
bntvllnt
left a comment
There was a problem hiding this comment.
Review — 1 blocking finding
BLOCKING
C1 — French 404 still ships English metadata and CTA copy- Evidence:
apps/registry/app/[locale]/not-found.tsx:8-11exports static English metadata (Page not found,We couldn't find...) for every locale, andapps/registry/app/[locale]/not-found.tsx:52-65hardcodesRead the docs/Request a componentinstead of using the existingcommon.readDocs/common.requestComponentmessages. - Why it matters: this PR's core contract is localized registry routes. On
/fr/...misses, the page body partly uses French viagetTranslations, but the route still renders English CTA text and English document metadata while the layout declareshtml lang="fr". That leaves the French localized surface visibly incomplete and contradicts the PR's stated localization remediation. - Fix: replace the hardcoded CTA labels with translated messages and move the 404 metadata behind locale-aware
generateMetadata/translation lookup (or otherwise return locale-specific metadata for[locale]).
- Evidence:
WARN
- None beyond the blocker above.
VERIFIED CLEAN
- Re-fetched the live PR before publication: PR #350 is open/non-draft at
fb51552cf235dd918bc90baf58fb8bda1add1a61, basemain, merge stateCLEAN. - Confirmed current checks are green for issue-link, Quality Gates, CodeQL, react-doctor, registry/storybook build/deploy, and preview deploy.
- Reviewed the localized App Router migration, i18n request/routing/proxy setup, machine-readable
llmsroutes,/r/[name]locale response behavior, sitemap/SEO helpers, content/sidebar loaders, translation messages, registry metadata/scripts, CI/package/lockfile changes, and generated registry artifacts. No additional blocking issue was found in those areas. - PR body includes
Closes #281and references the current head SHA.
VALIDATION
- Ran/read:
gh pr view 350 --repo vllnt/ui --json ...andgh pr checks 350 --repo vllnt/ui --json name,state,bucket,link,workflow. - Inspected diff artifacts from detached worktree
/home/ubuntu/ui/.worktrees/pr-350-review-t43617508atfb51552cf235dd918bc90baf58fb8bda1add1a61againstorigin/main. - Attempted local
pnpm -F @vllnt/ui-registry check:translations; it could not run in the detached worktree because localnode_modules/tsxare missing (spawn ENOENT). I did not treat that environment failure as PR code evidence.
Note: authenticated reviewer appears to be the PR author, so this is a blocking COMMENT review rather than an autonomous approval or merge.
|
Closing in favor of a fresh next-intl implementation on current main. This branch localizes 6 page groups under [locale]/ but predates main's newer pages (/templates, /design, /releases, /changelog) and relies on |
Fresh next-intl i18n implementation (re-done on current main; supersedes closed #350). ## What - next-intl localized routes with `[locale]` segment + **middleware** (`localePrefix: as-needed`), locales en (default) + fr. - All 21 HTML pages moved under `app/[locale]/` — incl. /templates, /design, /releases, /changelog that #350 didn't cover. Route handlers (llms/rss/atom/r/mcp/og) stay English at root. - Header language switcher added alongside pagefind search + What's-new dropdown + GitHubMark. - Locale-aware canonical + hreflang; en/fr message catalogs + localized MDX (home/docs/components/philosophy) reused from #350. ## Validation - `pnpm --filter @vllnt/ui-registry build` green (966 static pages, en+fr cross-product) · `tsc --noEmit` clean. - Lockfile based on main (eslint-plugin-react-hooks held at 7.0.1; only next-intl transitive additions). ## Notes - Landing page content left English literals (routing/metadata localized); deliberate to avoid inventing translations. - Recommend a quick visual pass on /, /fr, and the locale switcher post-merge. Closes #281 Co-authored-by: bntvllnt <bntvllnt@users.noreply.github.com>
Summary
next-intlrouting for English and French registry app pages, with localized metadata, hreflang alternates, sitemap entries, and locale-aware navigation/chrome.content/pages/<slug>/<locale>.mdx, add French pages, and add a CI translation check for required default-locale MDX./r/<name>.<locale>.jsondescription overlays./fr/vsand/fr/vs/shadcnnow have French metadata and visible French body/table copy, so the advertised French canonical, sitemap, and hreflang alternates no longer point at English-only comparison pages.origin/mainafter PR fix(registry): upgrade Next.js to 16.2.6 #357 by preserving the PR's localized-route changes and main's Next.js /@next/mdx16.2.6 update inapps/registry/package.jsonandpnpm-lock.yaml.Dependency tradeoff
next-intlto the registry app only. This bringsnext-intl,use-intl, and@formatjs/*runtime packages, but avoids a bespoke i18n router/message loader and matches the issue request.Validation
Earlier not-found fix validation on
fb51552cf235dd918bc90baf58fb8bda1add1a61before the 2026-05-31 branch refresh:tsc --noEmit --project tsconfig.json(0 errors)app/[locale]/not-found.tsx,app/[locale]/llms.txt/route.ts,app/[locale]/llms-full.txt/route.tsnot-found.tsxconverted from sync client component toasyncserver component;useLocale/useTranslationsreplaced withgetLocale/getTranslationsfromnext-intl/server— resolvesmetadata+ client-hook conflict that caused Next.js build errorfunctional/no-loop-statementseslint-disable removed from both llms route files; loops replaced withmap+spread (llms.txt) andreduce(llms-full.txt)Earlier reconciliation validation on
fb51552cf235dd918bc90baf58fb8bda1add1a61before the 2026-05-31 branch refresh:git diff --checkpnpm -F @vllnt/ui-registry check:translationspnpm -F @vllnt/ui-registry exec tsc --noEmit --project tsconfig.jsonpnpm -F @vllnt/ui-registry registry:buildLatest remediation validation on earlier head
d66a08c69581cfc3ff69cd0213461890be0c4bc9:pnpm -F @vllnt/ui-registry exec tsc --noEmit --project tsconfig.jsonpnpm -F @vllnt/ui-registry exec eslint 'app/[locale]/vs/page.tsx' 'app/[locale]/vs/shadcn/page.tsx'git diff --checkpnpm -F @vllnt/ui-registry lintexited 1 with 221 existing errors outside the edited comparison files, includingapp/manifest.ts,app/mcp/route.ts,app/robots.ts,lib/jsonld.ts, registry scripts, andtypes/registry.ts.Prior branch validation retained from earlier HEAD:
pnpm install --frozen-lockfilepnpm -F @vllnt/ui lintpnpm -F @vllnt/ui exec tsc --noEmit --project tsconfig.build.jsonpnpm -F @vllnt/ui-registry exec tsc --noEmit --project tsconfig.jsonpnpm buildpnpm test:oncepnpm -F @vllnt/ui-registry check:translationspnpm -F @vllnt/ui check:use-clientpnpm -F @vllnt/ui exec tsx scripts/check-story-coverage.tspnpm -F @vllnt/ui exec tsx scripts/verify-stories.tspnpm -F @vllnt/ui build-storybookgit diff --checkRuntime smoke
After the earlier
pnpm build, ranpnpm -F @vllnt/ui-registry exec next start -p 3011and verified:curl -I http://localhost:3011/en/llms.txt->308tohttp://localhost:3011/llms.txtcurl -I http://localhost:3011/en/llms-full.txt->308tohttp://localhost:3011/llms-full.txtcurl -I http://localhost:3011/request-component->200with rewrite to/en/request-componentandNEXT_LOCALE=encurl http://localhost:3011/r/button.fr.json-> localized overlay JSON withlocale: "fr",sourceLocale: "en", and canonical/r/button.jsoncurl http://localhost:3011/fr/llms.txt | head -8-> French llms header/contentBranch freshness
mainon 2026-05-31T15:06:18Z.83f8e60390854a137f65d3af7ca7738bda6be47c.7d14e563f349259d071634e02a8f489fedb6b0bd.UNSTABLE.Closes #281