You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Browse filesBrowse the repository at this point in the historyBrowse files
authored
fix(docs): reject non-locale [lang] segments instead of serving the homepage (#12258)
`apps/docs/app/[lang]/` matches ANY single path segment, and `proxy.ts`'s
matcher deliberately excludes dotted paths from locale rewriting (static
assets must not be rewritten). So every dotted single-segment URL skipped the
proxy, landed on `[lang]` with `lang` set to that literal segment, and rendered
the full homepage under a 200 -- an unbounded set of duplicate homepages at
exactly the URLs crawlers probe by default, including `/robots.txt` and
`/sitemap.xml`.
Measured before the fix on the dev server: `/foo.txt`, `/ads.txt`,
`/security.txt`, `/anything.html`, `/sitemap_index.xml`, `/robots.txt` and
`/sitemap.xml` all returned 200 with the homepage, while `/this-page-does-not-exist`
correctly returned 404. A temporary probe in the layout printed
`lang="foo.txt"`, `lang="ads.txt"`, `lang="robots.txt"`, `lang="sitemap.xml"`
against `lang="en"` for `/docs`, `/blog` and `/`.
The declared locales are the contract, so enforce them where they are violated:
`lib/i18n.ts` gains `isSupportedLanguage()` derived from `i18n.languages`, and
the `[lang]` layout calls `notFound()` before it renders anything when the
segment is not a declared locale.
`scripts/check-docs-locale-catch-all.mjs` pins it. The guard is three lines in
a layout that is otherwise pure presentation, and deleting it breaks nothing
any other check can see -- every page still renders, every type still checks,
every link still resolves; the only symptom is a 200 where a 404 belongs, on
URLs no test requests. The gate checks the two halves as one conditional
invariant (if dotted paths bypass the proxy, then every top-level dynamic
segment must reject a non-locale parameter before rendering), so it reasons
rather than pattern-matches and covers the class rather than the file.
Co-authored-by: Jack Zhuang <zhuangjianguo@gmail.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
0 commit comments