From 812597bb8b101896a8988493d37261ff851ae502 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Fri, 6 Feb 2026 08:54:51 -0600 Subject: [PATCH] feat(web): i18n (#12471) --- packages/console/app/src/app.tsx | 20 +- .../app/src/component/email-signup.tsx | 14 +- packages/console/app/src/component/footer.tsx | 16 +- packages/console/app/src/component/header.tsx | 66 +- .../app/src/component/language-picker.css | 135 ++++ .../app/src/component/language-picker.tsx | 34 + packages/console/app/src/component/legal.tsx | 12 +- packages/console/app/src/context/i18n.tsx | 27 + packages/console/app/src/context/language.tsx | 68 ++ packages/console/app/src/entry-server.tsx | 39 +- packages/console/app/src/i18n/ar.ts | 531 ++++++++++++++++ packages/console/app/src/i18n/br.ts | 466 ++++++++++++++ packages/console/app/src/i18n/da.ts | 463 ++++++++++++++ packages/console/app/src/i18n/de.ts | 468 ++++++++++++++ packages/console/app/src/i18n/en.ts | 591 ++++++++++++++++++ packages/console/app/src/i18n/es.ts | 465 ++++++++++++++ packages/console/app/src/i18n/fr.ts | 471 ++++++++++++++ packages/console/app/src/i18n/index.ts | 43 ++ packages/console/app/src/i18n/it.ts | 464 ++++++++++++++ packages/console/app/src/i18n/ja.ts | 502 +++++++++++++++ packages/console/app/src/i18n/ko.ts | 494 +++++++++++++++ packages/console/app/src/i18n/no.ts | 462 ++++++++++++++ packages/console/app/src/i18n/pl.ts | 466 ++++++++++++++ packages/console/app/src/i18n/ru.ts | 539 ++++++++++++++++ packages/console/app/src/i18n/th.ts | 541 ++++++++++++++++ packages/console/app/src/i18n/tr.ts | 467 ++++++++++++++ packages/console/app/src/i18n/zh.ts | 473 ++++++++++++++ packages/console/app/src/i18n/zht.ts | 473 ++++++++++++++ packages/console/app/src/lib/form-error.ts | 83 +++ packages/console/app/src/lib/language.ts | 175 ++++++ packages/console/app/src/routes/[...404].tsx | 14 +- .../console/app/src/routes/bench/[id].tsx | 74 ++- .../console/app/src/routes/bench/index.tsx | 12 +- packages/console/app/src/routes/black.tsx | 41 +- .../console/app/src/routes/black/common.tsx | 13 +- .../console/app/src/routes/black/index.tsx | 34 +- .../app/src/routes/black/subscribe/[plan].tsx | 80 ++- .../app/src/routes/black/workspace.tsx | 41 +- .../console/app/src/routes/brand/index.css | 1 + .../console/app/src/routes/brand/index.tsx | 12 +- .../app/src/routes/changelog/index.css | 1 + .../app/src/routes/changelog/index.tsx | 20 +- .../console/app/src/routes/docs/[...path].ts | 8 +- packages/console/app/src/routes/docs/index.ts | 8 +- .../console/app/src/routes/download/index.css | 1 + .../console/app/src/routes/download/index.tsx | 116 ++-- .../app/src/routes/enterprise/index.css | 1 + .../app/src/routes/enterprise/index.tsx | 61 +- packages/console/app/src/routes/index.css | 1 + packages/console/app/src/routes/index.tsx | 151 +++-- packages/console/app/src/routes/s/[id].ts | 8 +- .../console/app/src/routes/t/[...path].tsx | 8 +- packages/console/app/src/routes/temp.tsx | 45 +- packages/console/app/src/routes/user-menu.tsx | 4 +- .../app/src/routes/workspace-picker.tsx | 14 +- .../console/app/src/routes/workspace/[id].css | 29 + .../console/app/src/routes/workspace/[id].tsx | 28 +- .../[id]/billing/billing-section.tsx | 35 +- .../workspace/[id]/billing/black-section.tsx | 62 +- .../[id]/billing/monthly-limit-section.tsx | 40 +- .../[id]/billing/payment-section.tsx | 25 +- .../workspace/[id]/billing/reload-section.tsx | 46 +- .../routes/workspace/[id]/graph-section.tsx | 44 +- .../app/src/routes/workspace/[id]/index.tsx | 12 +- .../workspace/[id]/keys/key-section.tsx | 39 +- .../workspace/[id]/members/member-section.tsx | 109 ++-- .../workspace/[id]/members/role-dropdown.tsx | 6 +- .../routes/workspace/[id]/model-section.tsx | 16 +- .../workspace/[id]/new-user-section.tsx | 30 +- .../workspace/[id]/provider-section.tsx | 40 +- .../[id]/settings/settings-section.tsx | 27 +- .../routes/workspace/[id]/usage-section.tsx | 34 +- .../app/src/routes/workspace/common.tsx | 2 +- packages/console/app/src/routes/zen/index.css | 1 + packages/console/app/src/routes/zen/index.tsx | 132 ++-- 75 files changed, 9868 insertions(+), 726 deletions(-) create mode 100644 packages/console/app/src/component/language-picker.css create mode 100644 packages/console/app/src/component/language-picker.tsx create mode 100644 packages/console/app/src/context/i18n.tsx create mode 100644 packages/console/app/src/context/language.tsx create mode 100644 packages/console/app/src/i18n/ar.ts create mode 100644 packages/console/app/src/i18n/br.ts create mode 100644 packages/console/app/src/i18n/da.ts create mode 100644 packages/console/app/src/i18n/de.ts create mode 100644 packages/console/app/src/i18n/en.ts create mode 100644 packages/console/app/src/i18n/es.ts create mode 100644 packages/console/app/src/i18n/fr.ts create mode 100644 packages/console/app/src/i18n/index.ts create mode 100644 packages/console/app/src/i18n/it.ts create mode 100644 packages/console/app/src/i18n/ja.ts create mode 100644 packages/console/app/src/i18n/ko.ts create mode 100644 packages/console/app/src/i18n/no.ts create mode 100644 packages/console/app/src/i18n/pl.ts create mode 100644 packages/console/app/src/i18n/ru.ts create mode 100644 packages/console/app/src/i18n/th.ts create mode 100644 packages/console/app/src/i18n/tr.ts create mode 100644 packages/console/app/src/i18n/zh.ts create mode 100644 packages/console/app/src/i18n/zht.ts create mode 100644 packages/console/app/src/lib/form-error.ts create mode 100644 packages/console/app/src/lib/language.ts diff --git a/packages/console/app/src/app.tsx b/packages/console/app/src/app.tsx index cde2f0187..3d16a64ab 100644 --- a/packages/console/app/src/app.tsx +++ b/packages/console/app/src/app.tsx @@ -6,19 +6,25 @@ import { Favicon } from "@opencode-ai/ui/favicon" import { Font } from "@opencode-ai/ui/font" import "@ibm/plex/css/ibm-plex.css" import "./app.css" +import { LanguageProvider } from "~/context/language" +import { I18nProvider } from "~/context/i18n" export default function App() { return ( ( - - opencode - - - - {props.children} - + + + + opencode + + + + {props.children} + + + )} > diff --git a/packages/console/app/src/component/email-signup.tsx b/packages/console/app/src/component/email-signup.tsx index 65f81b5fc..bd33e9200 100644 --- a/packages/console/app/src/component/email-signup.tsx +++ b/packages/console/app/src/component/email-signup.tsx @@ -2,6 +2,7 @@ import { action, useSubmission } from "@solidjs/router" import dock from "../asset/lander/dock.png" import { Resource } from "@opencode-ai/console-resource" import { Show } from "solid-js" +import { useI18n } from "~/context/i18n" const emailSignup = action(async (formData: FormData) => { "use server" @@ -23,22 +24,21 @@ const emailSignup = action(async (formData: FormData) => { export function EmailSignup() { const submission = useSubmission(emailSignup) + const i18n = useI18n() return (
-

Be the first to know when we release new products

-

Join the waitlist for early access.

+

{i18n.t("email.title")}

+

{i18n.t("email.subtitle")}

- +
-
- Almost done, check your inbox and confirm your email address -
+
{i18n.t("email.success")}
{submission.error}
diff --git a/packages/console/app/src/component/footer.tsx b/packages/console/app/src/component/footer.tsx index 27f8ddd65..45dae87ec 100644 --- a/packages/console/app/src/component/footer.tsx +++ b/packages/console/app/src/component/footer.tsx @@ -2,12 +2,16 @@ import { createAsync } from "@solidjs/router" import { createMemo } from "solid-js" import { github } from "~/lib/github" import { config } from "~/config" +import { useLanguage } from "~/context/language" +import { useI18n } from "~/context/i18n" export function Footer() { + const language = useLanguage() + const i18n = useI18n() const githubData = createAsync(() => github()) const starCount = createMemo(() => githubData()?.stars - ? new Intl.NumberFormat("en-US", { + ? new Intl.NumberFormat(language.tag(language.locale()), { notation: "compact", compactDisplay: "short", }).format(githubData()!.stars!) @@ -18,20 +22,20 @@ export function Footer() { ) diff --git a/packages/console/app/src/component/header.tsx b/packages/console/app/src/component/header.tsx index 72e9d0418..3eca8b88c 100644 --- a/packages/console/app/src/component/header.tsx +++ b/packages/console/app/src/component/header.tsx @@ -19,6 +19,7 @@ import { createStore } from "solid-js/store" import { github } from "~/lib/github" import { createEffect, onCleanup } from "solid-js" import { config } from "~/config" +import { useI18n } from "~/context/i18n" import "./header-context-menu.css" const isDarkMode = () => window.matchMedia("(prefers-color-scheme: dark)").matches @@ -36,12 +37,14 @@ const fetchSvgContent = async (svgPath: string): Promise => { export function Header(props: { zen?: boolean; hideGetStarted?: boolean }) { const navigate = useNavigate() + const i18n = useI18n() const githubData = createAsync(() => github()) const starCount = createMemo(() => githubData()?.stars ? new Intl.NumberFormat("en-US", { notation: "compact", compactDisplay: "short", + maximumFractionDigits: 0, }).format(githubData()?.stars!) : config.github.starsFormatted.compact, ) @@ -119,8 +122,8 @@ export function Header(props: { zen?: boolean; hideGetStarted?: boolean }) {
@@ -130,49 +133,56 @@ export function Header(props: { zen?: boolean; hideGetStarted?: boolean }) { style={`left: ${store.contextMenuPosition.x}px; top: ${store.contextMenuPosition.y}px;`} >