diff --git a/packages/console/app/src/lib/language.ts b/packages/console/app/src/lib/language.ts index b7165ed6c..a13692476 100644 --- a/packages/console/app/src/lib/language.ts +++ b/packages/console/app/src/lib/language.ts @@ -68,6 +68,80 @@ const TAG = { tr: "tr", } satisfies Record +const DOCS = { + en: "root", + zh: "zh-cn", + zht: "zh-tw", + ko: "ko", + de: "de", + es: "es", + fr: "fr", + it: "it", + da: "da", + ja: "ja", + pl: "pl", + ru: "ru", + ar: "ar", + no: "nb", + br: "pt-br", + th: "th", + tr: "tr", +} satisfies Record + +const DOCS_SEGMENT = new Set([ + "ar", + "bs", + "da", + "de", + "es", + "fr", + "it", + "ja", + "ko", + "nb", + "pl", + "pt-br", + "ru", + "th", + "tr", + "zh-cn", + "zh-tw", +]) + +function suffix(pathname: string) { + const index = pathname.search(/[?#]/) + if (index === -1) { + return { + path: fix(pathname), + suffix: "", + } + } + + return { + path: fix(pathname.slice(0, index)), + suffix: pathname.slice(index), + } +} + +export function docs(locale: Locale, pathname: string) { + const value = DOCS[locale] + const next = suffix(pathname) + if (next.path !== "/docs" && next.path !== "/docs/" && !next.path.startsWith("/docs/")) { + return `${next.path}${next.suffix}` + } + + if (value === "root") return `${next.path}${next.suffix}` + + const hit = /^\/docs\/([^/]+)(\/.*)?$/.exec(next.path) + if (hit && DOCS_SEGMENT.has(hit[1] ?? "")) { + return `${next.path}${next.suffix}` + } + + if (next.path === "/docs") return `/docs/${value}${next.suffix}` + if (next.path === "/docs/") return `/docs/${value}/${next.suffix}` + return `/docs/${value}${next.path.slice("/docs".length)}${next.suffix}` +} + export function parseLocale(value: unknown): Locale | null { if (typeof value !== "string") return null if ((LOCALES as readonly string[]).includes(value)) return value as Locale @@ -90,7 +164,7 @@ export function strip(pathname: string) { export function route(locale: Locale, pathname: string) { const next = strip(pathname) - if (next.startsWith("/docs")) return next + if (next.startsWith("/docs")) return docs(locale, next) if (next.startsWith("/auth")) return next if (next.startsWith("/workspace")) return next if (locale === "en") return next diff --git a/packages/console/app/src/routes/docs/[...path].ts b/packages/console/app/src/routes/docs/[...path].ts index 81c4fc3e9..c4baebbfb 100644 --- a/packages/console/app/src/routes/docs/[...path].ts +++ b/packages/console/app/src/routes/docs/[...path].ts @@ -1,13 +1,14 @@ import type { APIEvent } from "@solidjs/start/server" -import { localeFromRequest, tag } from "~/lib/language" +import { docs, localeFromRequest, tag } from "~/lib/language" async function handler(evt: APIEvent) { const req = evt.request.clone() const url = new URL(req.url) - const targetUrl = `https://docs.opencode.ai${url.pathname}${url.search}` + const locale = localeFromRequest(req) + const targetUrl = `https://docs.opencode.ai${docs(locale, url.pathname)}${url.search}` const headers = new Headers(req.headers) - headers.set("accept-language", tag(localeFromRequest(req))) + headers.set("accept-language", tag(locale)) const response = await fetch(targetUrl, { method: req.method, diff --git a/packages/console/app/src/routes/docs/index.ts b/packages/console/app/src/routes/docs/index.ts index 81c4fc3e9..c4baebbfb 100644 --- a/packages/console/app/src/routes/docs/index.ts +++ b/packages/console/app/src/routes/docs/index.ts @@ -1,13 +1,14 @@ import type { APIEvent } from "@solidjs/start/server" -import { localeFromRequest, tag } from "~/lib/language" +import { docs, localeFromRequest, tag } from "~/lib/language" async function handler(evt: APIEvent) { const req = evt.request.clone() const url = new URL(req.url) - const targetUrl = `https://docs.opencode.ai${url.pathname}${url.search}` + const locale = localeFromRequest(req) + const targetUrl = `https://docs.opencode.ai${docs(locale, url.pathname)}${url.search}` const headers = new Headers(req.headers) - headers.set("accept-language", tag(localeFromRequest(req))) + headers.set("accept-language", tag(locale)) const response = await fetch(targetUrl, { method: req.method, diff --git a/packages/console/app/src/routes/download/index.tsx b/packages/console/app/src/routes/download/index.tsx index 04c3ab0d0..e5e4e9750 100644 --- a/packages/console/app/src/routes/download/index.tsx +++ b/packages/console/app/src/routes/download/index.tsx @@ -294,7 +294,7 @@ export default function Download() { VS Code - + {i18n.t("download.action.install")} @@ -318,7 +318,7 @@ export default function Download() { Cursor - + {i18n.t("download.action.install")} @@ -335,7 +335,7 @@ export default function Download() { Zed - + {i18n.t("download.action.install")} @@ -352,7 +352,7 @@ export default function Download() { Windsurf - + {i18n.t("download.action.install")} @@ -369,7 +369,7 @@ export default function Download() { VSCodium - + {i18n.t("download.action.install")} @@ -393,7 +393,7 @@ export default function Download() { GitHub - + {i18n.t("download.action.install")} @@ -410,7 +410,7 @@ export default function Download() { GitLab - + {i18n.t("download.action.install")} diff --git a/packages/console/app/src/routes/s/[id].ts b/packages/console/app/src/routes/s/[id].ts index eaf89328c..7f32c7d9d 100644 --- a/packages/console/app/src/routes/s/[id].ts +++ b/packages/console/app/src/routes/s/[id].ts @@ -1,13 +1,14 @@ import type { APIEvent } from "@solidjs/start/server" -import { localeFromRequest, tag } from "~/lib/language" +import { docs, localeFromRequest, tag } from "~/lib/language" async function handler(evt: APIEvent) { const req = evt.request.clone() const url = new URL(req.url) - const targetUrl = `https://docs.opencode.ai/docs${url.pathname}${url.search}` + const locale = localeFromRequest(req) + const targetUrl = `https://docs.opencode.ai${docs(locale, `/docs${url.pathname}`)}${url.search}` const headers = new Headers(req.headers) - headers.set("accept-language", tag(localeFromRequest(req))) + headers.set("accept-language", tag(locale)) const response = await fetch(targetUrl, { method: req.method, diff --git a/packages/console/app/src/routes/workspace/[id]/index.tsx b/packages/console/app/src/routes/workspace/[id]/index.tsx index 408f6a113..c91cfd2bc 100644 --- a/packages/console/app/src/routes/workspace/[id]/index.tsx +++ b/packages/console/app/src/routes/workspace/[id]/index.tsx @@ -9,10 +9,12 @@ import { GraphSection } from "./graph-section" import { IconLogo } from "~/component/icon" import { querySessionInfo, queryBillingInfo, createCheckoutUrl, formatBalance } from "../common" import { useI18n } from "~/context/i18n" +import { useLanguage } from "~/context/language" export default function () { const params = useParams() const i18n = useI18n() + const language = useLanguage() const userInfo = createAsync(() => querySessionInfo(params.id!)) const billingInfo = createAsync(() => queryBillingInfo(params.id!)) const checkoutAction = useAction(createCheckoutUrl) @@ -38,7 +40,7 @@ export default function () {

{i18n.t("workspace.home.banner.beforeLink")}{" "} - + {i18n.t("common.learnMore")} .