The public page in four languages, at four addresses - #127
Merged
suskozaver merged 1 commit intoSep 16, 2026
Merged
suskozaver merged 1 commit into
suskozaver merged 1 commit into
Conversation
Every screen inside the app has been translated for a while. The one page a stranger actually arrives at was still English, and the reason recorded in 05-decisions.md was sound: /landing renders on the server, before any browser has said which language it wants, so useLang has nothing to read. Making it a client component would have translated it and cost the thing it is for, which is arriving instantly on a phone that has never opened the app. So the language comes from the URL instead. English keeps /landing and the rest live at /landing/de, /landing/sl and /landing/pl. English does not move to /landing/en: every link to this page that exists points at /landing, and a second URL holding the same page is a duplicate a search engine has to be told to ignore. All four are prerendered, carry a canonical pointing at themselves, and name each other in hreflang, with x-default on English. The paths are relative because this app is self-hosted by whoever wants it and there is no one absolute origin to write down; a wrong one would be worse than none. Checked by reading the emitted HTML in both build modes, the server build and BUILD_TARGET=static, rather than by trusting the config: /landing/sl/index.html exists, says canonical /landing/sl, and carries all five alternate links. dynamicParams is false, so /landing/fr is a 404 rather than an attempt to render a language the dictionary does not carry. That is also what the static export needs, since a folder of files has no server to render an unknown locale on demand. lang sits on <main> rather than on <html>. The root layout owns <html> and is shared by the whole app, so varying it would mean two root layouts and a route group around every other page. A screen reader switches voice at the element carrying lang, which is what the attribute is for. The page body moved into Landing.tsx, which takes the language as a prop. The two route files are what is left: eight lines and a metadata call each. The app's own metadata in layout.tsx is still English, and that is not an oversight. It titles /, /plan, /stock and the rest, which are client screens whose language lives in a store in the browser. Routing those would mean a locale segment through the whole app for a title nobody links to. Written into 05-decisions.md, along with what the old entry said and why the wait was right. Sixty-eight keys in four languages.
|
Someone is attempting to deploy a commit to the Arun's projects Team on Vercel. A member of the Team first needs to authorize it. |
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.
Every screen inside the app has been translated for a while. The one page a stranger actually arrives at was still English, and the reason recorded in
05-decisions.mdwas sound:/landingrenders on the server, before any browser has said which language it wants, souseLanghas nothing to read. Making it a client component would have translated it and cost the thing it is for, which is arriving instantly on a phone that has never opened the app.So the language comes from the URL instead.
The addresses
English keeps
/landing. The rest live at/landing/de,/landing/sland/landing/pl.English does not move to
/landing/en: every link to this page that exists in the world points at/landing, and a second URL holding the same page is a duplicate a search engine has to be told to ignore.All four are prerendered, carry a canonical pointing at themselves, and name each other in
hreflang, withx-defaulton English. The paths are relative, because this app is self-hosted by whoever wants it and there is no one absolute origin to write down. A wrong one would be worse than none.dynamicParams = false, so/landing/fris a 404 rather than an attempt to render a language the dictionary does not carry. That is also what the static export needs: a folder of files has no server to render an unknown locale on demand.Checked in the output, not in the config
Both build modes were built and the emitted HTML read:
/landing,/landing/de,/landing/sl,/landing/plprerenderedBUILD_TARGET=static:out/landing/sl/index.htmlexists, says<link rel="canonical" href="/landing/sl">, carries all five alternate links, and opens with<main lang="sl">Where
langsitsOn
<main>, not on<html>. The root layout owns<html>and is shared by the whole app, so varying it would mean two root layouts and a route group around every other page. A screen reader switches voice at the element carryinglang, which is what the attribute is for.Shape
The page body moved into
Landing.tsx, which takes the language as a prop. The two route files are what is left: eight lines and a metadata call each.Still English on purpose
The app's own
metadatainlayout.tsx. It titles/,/plan,/stockand the rest, which are client screens whose language lives in a store in the browser. Routing those would mean a locale segment through the entire app, for a title nobody links to. Written up in05-decisions.mdalong with what the old entry said and why the wait was right.Sixty-eight keys in four languages.
Checks
npx tsc --noEmit,npx next lint,npm testandTZ=America/New_York npm test: 63 files, 1643 tests, no warnings. Plus both production builds.