fix(console): take the page language from the URL only (#56564)

This commit is contained in:
Kit Langton
2026-10-17 15:24:09 -07:00
committed by GitHub
Unverified
parent c78b6eea32
commit 3921f777ed
6 changed files with 38 additions and 15 deletions
@@ -11,7 +11,7 @@ import {
dir as localeDir,
label as localeLabel,
localeFromCookieHeader,
localeFromRequest,
pageLocale,
parseLocale,
route as localeRoute,
tag as localeTag,
@@ -19,7 +19,7 @@ import {
function initial() {
const evt = getRequestEvent()
if (evt) return localeFromRequest(evt.request)
if (evt) return pageLocale(evt.request)
if (typeof document === "object") {
const fromDom = parseLocale(document.documentElement.dataset.locale)
+2 -2
View File
@@ -1,7 +1,7 @@
// @refresh reload
import { createHandler, StartServer } from "@solidjs/start/server"
import { getRequestEvent } from "solid-js/web"
import { dir, localeFromRequest, tag } from "~/lib/language"
import { dir, pageLocale, tag } from "~/lib/language"
const criticalCSS = `[data-component="top"]{min-height:80px;display:flex;align-items:center}`
@@ -10,7 +10,7 @@ export default createHandler(
<StartServer
document={({ assets, children, scripts }) => {
const evt = getRequestEvent()
const locale = evt ? localeFromRequest(evt.request) : "en"
const locale = evt ? pageLocale(evt.request) : "en"
return (
<html lang={tag(locale)} dir={dir(locale)} data-locale={locale}>
+11
View File
@@ -325,6 +325,17 @@ export function localeFromRequest(request: Request) {
)
}
// Pages take their language from the URL alone, so one URL serves the same language to people, crawlers and caches.
export function pageLocale(request: Request) {
const pathname = new URL(request.url).pathname
return (
parseLocale(request.headers.get(LOCALE_HEADER)) ??
fromPathname(pathname) ??
fromDocsPathname(pathname) ??
("en" satisfies Locale)
)
}
export function cookie(locale: Locale) {
return `${LOCALE_COOKIE}=${encodeURIComponent(locale)}; Path=/; Max-Age=31536000; SameSite=Lax`
}
@@ -1,6 +1,6 @@
import type { APIEvent } from "@solidjs/start/server"
import { Resource } from "@opencode/console-resource"
import { cookie, docs, localeFromRequest, tag } from "~/lib/language"
import { docs, pageLocale, tag } from "~/lib/language"
async function handler(evt: APIEvent) {
const req = evt.request.clone()
@@ -10,7 +10,7 @@ async function handler(evt: APIEvent) {
return Response.redirect(new URL(moved[1] === "go" ? "/v2/docs/console/go/" : "/v2/docs/console/models/", url), 302)
}
const locale = localeFromRequest(req)
const locale = pageLocale(req)
const host = Resource.App.stage === "production" ? "docs.opencode.ai" : "docs.dev.opencode.ai"
const targetUrl = `https://${host}${docs(locale, url.pathname)}${url.search}`
@@ -22,9 +22,7 @@ async function handler(evt: APIEvent) {
headers,
body: req.body,
})
const next = new Response(response.body, response)
next.headers.append("set-cookie", cookie(locale))
return next
return new Response(response.body, response)
}
export const GET = handler
@@ -1,11 +1,11 @@
import type { APIEvent } from "@solidjs/start/server"
import { Resource } from "@opencode/console-resource"
import { cookie, docs, localeFromRequest, tag } from "~/lib/language"
import { docs, pageLocale, tag } from "~/lib/language"
async function handler(evt: APIEvent) {
const req = evt.request.clone()
const url = new URL(req.url)
const locale = localeFromRequest(req)
const locale = pageLocale(req)
const host = Resource.App.stage === "production" ? "docs.opencode.ai" : "docs.dev.opencode.ai"
const targetUrl = `https://${host}${docs(locale, url.pathname)}${url.search}`
@@ -17,9 +17,7 @@ async function handler(evt: APIEvent) {
headers,
body: req.body,
})
const next = new Response(response.body, response)
next.headers.append("set-cookie", cookie(locale))
return next
return new Response(response.body, response)
}
export const GET = handler
+17 -1
View File
@@ -1,5 +1,5 @@
import { describe, expect, test } from "bun:test"
import { route } from "../src/lib/language"
import { LOCALE_HEADER, pageLocale, route } from "../src/lib/language"
describe("language.route", () => {
test("keeps the changelog unprefixed for every locale", () => {
@@ -11,3 +11,19 @@ describe("language.route", () => {
expect(route("de", "/download")).toBe("/de/download")
})
})
describe("pageLocale", () => {
const request = (path: string, headers: Record<string, string> = {}) =>
new Request(`https://opencode.ai${path}`, { headers })
const german = { "accept-language": "de-DE,de;q=0.9", cookie: "oc_locale=de" }
test("ignores the browser language and cookie on unprefixed pages", () => {
expect(pageLocale(request("/", german))).toBe("en")
expect(pageLocale(request("/docs/agents/", german))).toBe("en")
})
test("uses the locale in the URL", () => {
expect(pageLocale(request("/", { [LOCALE_HEADER]: "de" }))).toBe("de")
expect(pageLocale(request("/docs/de/agents/"))).toBe("de")
})
})