diff options
| author | Adam <[email protected]> | 2026-02-09 11:34:35 -0600 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-02-09 11:34:35 -0600 |
| commit | dc53086c1e73d43d3a28fc4cdf161e83d09b1877 (patch) | |
| tree | 45a1d0e38de958d0886a5120b2806b21db74145b /packages/web/src/pages | |
| parent | f74c0339cc6315f7e7743e26b7eab47ce026c239 (diff) | |
| download | opencode-dc53086c1e73d43d3a28fc4cdf161e83d09b1877.tar.gz opencode-dc53086c1e73d43d3a28fc4cdf161e83d09b1877.zip | |
wip(docs): i18n (#12681)
Diffstat (limited to 'packages/web/src/pages')
| -rw-r--r-- | packages/web/src/pages/[...slug].md.ts | 20 | ||||
| -rw-r--r-- | packages/web/src/pages/s/[id].astro | 135 |
2 files changed, 111 insertions, 44 deletions
diff --git a/packages/web/src/pages/[...slug].md.ts b/packages/web/src/pages/[...slug].md.ts index 51c63b5a6..dbc11d78e 100644 --- a/packages/web/src/pages/[...slug].md.ts +++ b/packages/web/src/pages/[...slug].md.ts @@ -1,13 +1,29 @@ import type { APIRoute } from "astro" import { getCollection } from "astro:content" -export const GET: APIRoute = async ({ params }) => { +function notFoundText(locals: unknown) { + if (typeof locals !== "object" || locals === null || !("t" in locals)) { + return "share.not_found" + } + const t = (locals as { t?: unknown }).t + if (typeof t !== "function") { + return "share.not_found" + } + const text = t("share.not_found") + if (typeof text === "string" && text.length > 0) { + return text + } + return "share.not_found" +} + +export const GET: APIRoute = async ({ params, locals }) => { const slug = params.slug || "index" const docs = await getCollection("docs") const doc = docs.find((d) => d.id === slug) + const notFound = notFoundText(locals) if (!doc) { - return new Response("Not found", { status: 404 }) + return new Response(notFound, { status: 404, statusText: notFound }) } return new Response(doc.body, { diff --git a/packages/web/src/pages/s/[id].astro b/packages/web/src/pages/s/[id].astro index df39f0070..7ea42f691 100644 --- a/packages/web/src/pages/s/[id].astro +++ b/packages/web/src/pages/s/[id].astro @@ -1,55 +1,112 @@ --- -import { Base64 } from "js-base64"; +import { Base64 } from "js-base64" +import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro" +import type { Session } from "opencode/session/index" +import config from "../../../config.mjs" +import Share from "../../components/Share.tsx" -import config from '../../../config.mjs' -import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; -import Share from "../../components/Share.tsx"; +const apiUrl = import.meta.env.VITE_API_URL || "" +const ta = Astro.locals.t as ((key: string) => string) & { + all?: () => Record<string, string> +} +const all = typeof ta.all === "function" ? ta.all() : {} +const locale = Astro.currentLocale || Astro.locals.starlightRoute.locale || "root" +const formatLocale = locale === "root" ? "en" : locale +const t = ta -const apiUrl = import.meta.env.VITE_API_URL; +function tx(key: string) { + const value = all[key] + if (typeof value === "string") return value + return t(key) +} -const { id } = Astro.params; -const res = await fetch(`${apiUrl}/share_data?id=${id}`); -const data = await res.json(); +const messages = { + locale: formatLocale, + link_to_message: tx("share.link_to_message"), + copied: tx("share.copied"), + copy: tx("share.copy"), + show_more: tx("share.show_more"), + show_less: tx("share.show_less"), + show_results: tx("share.show_results"), + hide_results: tx("share.hide_results"), + show_details: tx("share.show_details"), + hide_details: tx("share.hide_details"), + show_preview: tx("share.show_preview"), + hide_preview: tx("share.hide_preview"), + show_contents: tx("share.show_contents"), + hide_contents: tx("share.hide_contents"), + show_output: tx("share.show_output"), + hide_output: tx("share.hide_output"), + error: tx("share.error"), + waiting_for_messages: tx("share.waiting_for_messages"), + status_connected_waiting: tx("share.status_connected_waiting"), + status_connecting: tx("share.status_connecting"), + status_disconnected: tx("share.status_disconnected"), + status_reconnecting: tx("share.status_reconnecting"), + status_error: tx("share.status_error"), + status_unknown: tx("share.status_unknown"), + error_id_not_found: tx("share.error_id_not_found"), + error_api_url_not_found: tx("share.error_api_url_not_found"), + error_connection_failed: tx("share.error_connection_failed"), + opencode_version: tx("share.opencode_version"), + opencode_name: tx("share.opencode_name"), + models: tx("share.models"), + cost: tx("share.cost"), + input_tokens: tx("share.input_tokens"), + output_tokens: tx("share.output_tokens"), + reasoning_tokens: tx("share.reasoning_tokens"), + scroll_to_bottom: tx("share.scroll_to_bottom"), + attachment: tx("share.attachment"), + thinking: tx("share.thinking"), + thinking_pending: tx("share.thinking_pending"), + creating_plan: tx("share.creating_plan"), + completing_plan: tx("share.completing_plan"), + updating_plan: tx("share.updating_plan"), + match_one: tx("share.match_one"), + match_other: tx("share.match_other"), + result_one: tx("share.result_one"), + result_other: tx("share.result_other"), + debug_key: tx("share.debug_key"), +} + +const id = Astro.params.id || "" +const res = await fetch(`${apiUrl}/share_data?id=${id}`) +const data = (await res.json()) as { + info?: Session.Info + messages: Record<string, { role?: string; modelID?: string }> +} if (!data.info) { return new Response(null, { status: 404, - statusText: 'Not found' - }); + statusText: tx("share.not_found"), + }) } -const models: Set<string> = new Set(); -const version = data.info.version ? `v${data.info.version}` : "v0.0.1"; +const models: Set<string> = new Set() +const version = data.info.version ? `v${data.info.version}` : "v0.0.1" -Object.values(data.messages).forEach((d) => { +for (const d of Object.values(data.messages)) { if (d.role === "assistant" && d.modelID) { - models.add(d.modelID); + models.add(d.modelID) } -}); +} const encodedTitle = encodeURIComponent( Base64.encode( - // Convert to ASCII - encodeURIComponent( - // Truncate to fit S3's max key size - data.info.title.substring(0, 700), - ) - ) -); + encodeURIComponent(data.info.title.substring(0, 700)), + ), +) -const modelsArray = Array.from(models); -let modelParam; -if (modelsArray.length === 1) { - modelParam = modelsArray[0]; -} -else if (modelsArray.length === 2) { - modelParam = encodeURIComponent(`${modelsArray[0]} & ${modelsArray[1]}`); -} -else { - modelParam = encodeURIComponent(`${modelsArray[0]} & ${modelsArray.length - 1} others`); -} +const modelsArray = Array.from(models) +const modelParam = + modelsArray.length === 1 + ? modelsArray[0] + : modelsArray.length === 2 + ? encodeURIComponent(`${modelsArray[0]} & ${modelsArray[1]}`) + : encodeURIComponent(`${modelsArray[0]} & ${modelsArray.length - 1} others`) -const ogImage = `${config.socialCard}/opencode-share/${encodedTitle}.png?model=${modelParam}&version=${version}&id=${id}`; +const ogImage = `${config.socialCard}/opencode-share/${encodedTitle}.png?model=${modelParam}&version=${version}&id=${id}` --- <StarlightPage hasSidebar={false} @@ -63,7 +120,7 @@ const ogImage = `${config.socialCard}/opencode-share/${encodedTitle}.png?model=$ tag: "meta", attrs: { name: "description", - content: "opencode - The AI coding agent built for the terminal.", + content: tx("share.meta_description"), }, }, { @@ -90,13 +147,7 @@ const ogImage = `${config.socialCard}/opencode-share/${encodedTitle}.png?model=$ ], }} > - <Share - id={id} - api={apiUrl} - info={data.info} - messages={data.messages} - client:only="solid" - /> + <Share id={id} api={apiUrl} info={data.info} messages={messages} client:only="solid" /> </StarlightPage> <style is:global> |
