feat(web): Paraglide v2 i18n + locale-prefixed routes #921
No reviewers
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks!921
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "dev/908"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Wires up Paraglide JS v2 in
apps/weband restructures all TanStack Router routes under a/$locale/prefix, satisfying US-A1, US-A2, and US-A3.project.inlang/settings.json+messages/en.json+@inlang/paraglide-viteplugin; HMR works invite dev,bun run buildsucceedssrc/routes/$locale/;$locale.tsxlayout validates the param and redirects invalid locales toen;/resolves locale then redirects to/$locale/planner/boardsrc/lib/locale.tsimplements URL → serverpreferredLocale→localStorage→Accept-Language→enordersrc/components/locale-link.tsx— drop-in replacement for<Link>that auto-injects the current URL locale__root.tsxlogin/post-login navigations are locale-awareTest plan
just qa— 975/975 pass, 0 typecheck errors, 0 lint errorsvite dev: navigate to/app/→ redirects to/app/en/planner/board/app/xx/planner/board(invalid locale) → redirects to/app/en/planner/boardbun run buildsucceeds inapps/webCloses #908
CI still pending at review time (run #1627, sha
2d29444). Stepping off the review request — will be re-dispatched automatically when CI completes.⚠️ Flagging pre-emptively:
@inlang/paraglide-viteis installed in devDependencies but not registered invite.config.ts, andsrc/paraglide/runtime.tsis missing (imported by$locale.tsx). CI will likely fail on the typecheck/build step — these need to be fixed before merge.REQUEST_CHANGES (no
submit_reviewtool available, posting findings inline)behavior
apps/web/vite.config.ts:@inlang/paraglide-viteis installed indevDependenciesbut never added to thepluginsarray. Without this, the Vite plugin never runs, Paraglide codegen never executes, and HMR for message changes doesn't work. Addparaglide({ project: "./project.inlang", outdir: "./src/paraglide" })to the plugins list (afterreact()).behavior
apps/web/src/routes/$locale.tsxline 4:import { setLocale } from "@/paraglide/runtime"—src/paraglide/runtime.tsdoes not exist on this branch (verified via Forge API). It's neither committed nor generated (because the Vite plugin isn't wired up). This import will fail at build time. Fix: add the Vite plugin (above) so codegen produces the file, or commit the generated output.behavior
apps/web/project.inlang/settings.json:"modules": []— the Paraglide message-format plugin is missing. Should be["https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@latest/dist/index.js"](or the local npm path). Without this, inlang has no plugin and won't compile messages.CI status for head SHA
2d294448was returned asunknownwith emptystartedAt— unable to confirm green.REQUEST_CHANGES — two blocking issues:
behavior
apps/web/vite.config.ts:@inlang/paraglide-viteis in devDependencies but never added to thepluginsarray. The Vite plugin must be registered to generate (or serve as a virtual module) the paraglide runtime. Missing:import { paraglide } from "@inlang/paraglide-vite"andparaglide({ project: "./project.inlang", outdir: "./src/paraglide" })in the plugins list — without itbun run buildandvite devwill both fail to resolve@/paraglide/runtime.behavior
apps/web/src/paraglide/runtime(missing file):$locale.tsximportssetLocalefrom"@/paraglide/runtime"but neitherruntime.jsnorruntime.tsexists insrc/paraglide/. This is a direct consequence of the plugin not being wired — typecheck and build both fail with module-not-found. Fix vite.config.ts first; the plugin will generate the file on firstvite dev/vite build.doc-gap
apps/web/project.inlang/settings.json:"modules": []— the message format plugin (@inlang/plugin-message-format) should be listed here so the Inlang CLI / IDE extension can resolve messages. Not blocking build but incomplete setup.The PR added @inlang/paraglide-vite as a dep and introduced a route that imports from the generated `src/paraglide/runtime` module, but two pieces were missing: 1. `vite.config.ts` never wired up the `paraglide()` Vite plugin, so the runtime directory was never generated during dev/build. 2. CI runs `bun x tsc --noEmit` before Vite starts, so even with the plugin in place the generated files wouldn't exist at typecheck time. Fix: - Add `{ paraglide }` plugin from `@inlang/paraglide-vite` to vite.config.ts. - Add a `codegen` recipe to the justfile that runs `paraglide-js compile --emit-ts-declarations` (generates .d.ts stubs so standalone tsc can type-check the generated JS). - Make `typecheck` depend on `codegen` so the files exist before tsc runs. - Exclude `project.inlang/` from Biome checks: the auto-generated `.meta.json` uses spaces and is owned by the inlang CLI, not this project's formatter. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>CI still pending at review time (run #1633, sha
9a80d08). Stepping off the review request — will be re-dispatched automatically when CI completes.REQUEST_CHANGES
behavior
apps/web/src/routes/$locale/login.tsx~line 54 —buildInitHref'sisLoginPathdoesn't match locale-prefixed paths. When the operator is on/app/en/loginthe check evaluates false → OAuth return URL becomes/app/en/logininstead of/. After the callback they land back on the login page (briefly, before__root.tsx'suseEffectrescues them). Fix: add the same pattern used in__root.tsx:doc-gap
apps/web/src/routes/$locale.tsxJSDoc says "Performs the server-preference canonical redirect (one-shot, no split-brain)" butLocaleLayoutonly persists tolocalStorage— no redirect is issued. Either remove that sentence or implement the fetch+redirect that the comment promises.CI still pending at review time (run #3157, sha
15adf96). Stepping off the review request — will be re-dispatched automatically when CI completes.All three ACs met; code is correct.
doc-gapapps/web/src/routes/$locale.tsxline 8–13: JSDoc claims the layout "redirect[s] once to the canonical locale path" if URL locale differs from server preference — the implementation only setslocalStorage, no redirect. The code is correct (URL-first wins per the resolution order), but the comment contradicts itself and the spec. Strip the redirect claim from the JSDoc.