diff --git a/docs-site/astro.config.mjs b/docs-site/astro.config.mjs index bf301194f..749fe171a 100644 --- a/docs-site/astro.config.mjs +++ b/docs-site/astro.config.mjs @@ -22,7 +22,6 @@ export default defineConfig({ favicon: "/favicon.ico", customCss: [ "@fontsource-variable/geist", - "pretendard/dist/web/variable/pretendardvariable-dynamic-subset.css", "./src/styles/custom.css", ], components: { @@ -42,102 +41,86 @@ export default defineConfig({ baseUrl: "https://github.com/pavelhov/CodexCommander/edit/main/docs-site/", }, lastUpdated: true, - // English at the site root; Korean under /ko, Simplified Chinese under /zh-cn, Russian under /ru, Japanese under /ja. - defaultLocale: "root", - locales: { - root: { label: "English", lang: "en" }, - ko: { label: "한국어", lang: "ko" }, - "zh-cn": { label: "简体中文", lang: "zh-CN" }, - ru: { label: "Русский", lang: "ru" }, - ja: { label: "日本語", lang: "ja" }, - }, sidebar: [ { label: "Getting Started", - translations: { ko: "시작하기", "zh-CN": "开始使用", ru: "Начало работы", ja: "はじめに" }, items: [ - { label: "Installation", translations: { ko: "설치", "zh-CN": "安装", ru: "Установка", ja: "インストール" }, slug: "getting-started/installation" }, - { label: "Quickstart", translations: { ko: "빠른 시작", "zh-CN": "快速开始", ru: "Быстрый старт", ja: "クイックスタート" }, slug: "getting-started/quickstart" }, - { label: "How It Works", translations: { ko: "동작 원리", "zh-CN": "工作原理", ru: "Как это работает", ja: "仕組み" }, slug: "getting-started/how-it-works" }, - { label: "Agent Quickstart", translations: { ko: "에이전트 퀵스타트", "zh-CN": "Agent 快速上手", ru: "Быстрый старт для агентов", ja: "エージェント向けクイックスタート" }, slug: "getting-started/for-agents" }, + { label: "Installation", slug: "getting-started/installation" }, + { label: "Quickstart", slug: "getting-started/quickstart" }, + { label: "How It Works", slug: "getting-started/how-it-works" }, + { label: "Agent Quickstart", slug: "getting-started/for-agents" }, ], }, { label: "Guides", - translations: { ko: "가이드", "zh-CN": "指南", ru: "Руководства", ja: "ガイド" }, items: [ - { label: "Providers", translations: { ko: "프로바이더", "zh-CN": "提供商", ru: "Провайдеры", ja: "プロバイダー" }, slug: "guides/providers" }, - { label: "Model Routing", translations: { ko: "모델 라우팅", "zh-CN": "模型路由", ru: "Маршрутизация моделей", ja: "モデルルーティング" }, slug: "guides/model-routing" }, - { label: "Codex Integration", translations: { ko: "Codex 통합", "zh-CN": "Codex 集成", ru: "Интеграция с Codex", ja: "Codex 連携" }, slug: "guides/codex-integration" }, - { label: "Codex App Model Picker", translations: { ko: "Codex App 모델 선택기", "zh-CN": "Codex App 模型选择器", ru: "Выбор модели в Codex App", ja: "Codex App モデルピッカー" }, slug: "guides/codex-app-models" }, - { label: "Model Ordering", translations: { ko: "모델 정렬에 관하여", "zh-CN": "模型排序", ru: "Сортировка моделей", ja: "モデルの並び順" }, slug: "guides/model-ordering" }, - { label: "Combos", translations: { ko: "콤보", "zh-CN": "组合", ru: "Комбо", ja: "コンボ" }, slug: "guides/combos" }, - { label: "Claude Code", translations: { ko: "Claude Code", "zh-CN": "Claude Code", ru: "Claude Code", ja: "Claude Code" }, slug: "guides/claude-code" }, - { label: "Grok Build", translations: { ko: "Grok Build", "zh-CN": "Grok Build", ru: "Grok Build", ja: "Grok Build" }, slug: "guides/grok-build" }, - { label: "opencode", translations: { ko: "opencode", "zh-CN": "opencode", ru: "opencode", ja: "opencode" }, slug: "guides/opencode" }, - { label: "Pi", translations: { ko: "Pi", "zh-CN": "Pi", ru: "Pi", ja: "Pi" }, slug: "guides/pi" }, - { label: "Integrations", translations: { ko: "연동", "zh-CN": "集成", ru: "Интеграции", ja: "連携" }, slug: "guides/integrations" }, - { label: "Sidecars: Web Search & Vision", translations: { ko: "사이드카: 웹 검색 & 비전", "zh-CN": "边车:网络搜索与视觉", ru: "Сайдкары: веб-поиск и зрение", ja: "サイドカー: ウェブ検索 & ビジョン" }, slug: "guides/sidecars" }, - { label: "Image Bridge", translations: { ko: "이미지 브릿지", "zh-CN": "图像桥接", ru: "Image Bridge", ja: "画像ブリッジ" }, slug: "guides/image-bridge" }, - { label: "Video Bridge", translations: { ko: "비디오 브릿지", "zh-CN": "视频桥接", ru: "Video Bridge", ja: "動画ブリッジ" }, slug: "guides/video-bridge" }, - { label: "Web Dashboard", translations: { ko: "웹 대시보드", "zh-CN": "网页控制台", ru: "Веб-дашборд", ja: "ウェブダッシュボード" }, slug: "guides/web-dashboard" }, - { label: "macOS Menu Bar", translations: { ko: "macOS 메뉴 막대", "zh-CN": "macOS 菜单栏", ru: "Строка меню macOS", ja: "macOS メニューバー" }, slug: "guides/macos-menu-bar" }, - { label: "Sub-agent Surface", translations: { ko: "서브에이전트 서피스", "zh-CN": "子代理界面", ru: "Интерфейс подагентов", ja: "サブエージェントサーフェス" }, slug: "guides/sub-agent-surface" }, + { label: "Providers", slug: "guides/providers" }, + { label: "Model Routing", slug: "guides/model-routing" }, + { label: "Codex Integration", slug: "guides/codex-integration" }, + { label: "Codex App Model Picker", slug: "guides/codex-app-models" }, + { label: "Model Ordering", slug: "guides/model-ordering" }, + { label: "Combos", slug: "guides/combos" }, + { label: "Claude Code", slug: "guides/claude-code" }, + { label: "Grok Build", slug: "guides/grok-build" }, + { label: "opencode", slug: "guides/opencode" }, + { label: "Pi", slug: "guides/pi" }, + { label: "Integrations", slug: "guides/integrations" }, + { label: "Sidecars: Web Search & Vision", slug: "guides/sidecars" }, + { label: "Image Bridge", slug: "guides/image-bridge" }, + { label: "Video Bridge", slug: "guides/video-bridge" }, + { label: "Web Dashboard", slug: "guides/web-dashboard" }, + { label: "macOS Menu Bar", slug: "guides/macos-menu-bar" }, + { label: "Sub-agent Surface", slug: "guides/sub-agent-surface" }, ], }, { label: "Benchmarks", - translations: { ko: "벤치마크", "zh-CN": "基准测试", ru: "Бенчмарки", ja: "ベンチマーク" }, collapsed: true, items: [ - { label: "Overview", translations: { ko: "개요", "zh-CN": "概览", ru: "Обзор", ja: "概要" }, slug: "benchmarks" }, - { label: "Coding", translations: { ko: "코딩", "zh-CN": "编程", ru: "Кодинг", ja: "コーディング" }, slug: "benchmarks/coding" }, - { label: "Frontend", translations: { ko: "프론트엔드", "zh-CN": "前端", ru: "Фронтенд", ja: "フロントエンド" }, slug: "benchmarks/frontend" }, - { label: "Terminal", translations: { ko: "터미널", "zh-CN": "终端", ru: "Терминал", ja: "ターミナル" }, slug: "benchmarks/terminal" }, - { label: "Security", translations: { ko: "보안", "zh-CN": "安全", ru: "Безопасность", ja: "セキュリティ" }, slug: "benchmarks/security" }, - { label: "Intelligence", translations: { ko: "인텔리전스", "zh-CN": "智能", ru: "Интеллект", ja: "インテリジェンス" }, slug: "benchmarks/intelligence" }, + { label: "Overview", slug: "benchmarks" }, + { label: "Coding", slug: "benchmarks/coding" }, + { label: "Frontend", slug: "benchmarks/frontend" }, + { label: "Terminal", slug: "benchmarks/terminal" }, + { label: "Security", slug: "benchmarks/security" }, + { label: "Intelligence", slug: "benchmarks/intelligence" }, ], }, { label: "Reference", - translations: { ko: "레퍼런스", "zh-CN": "参考", ru: "Справочник", ja: "リファレンス" }, items: [ { label: "CLI", - translations: { ko: "CLI", "zh-CN": "命令行", ru: "CLI", ja: "CLI" }, items: [ - { label: "Overview", translations: { ko: "개요", "zh-CN": "概览", ru: "Обзор", ja: "概要" }, slug: "reference/cli" }, - { label: "Lifecycle & Service", translations: { ko: "라이프사이클 & 서비스", "zh-CN": "生命周期与服务", ru: "Жизненный цикл и служба", ja: "ライフサイクル & サービス" }, slug: "reference/cli/lifecycle" }, - { label: "Providers, Accounts & Models", translations: { ko: "프로바이더, 계정 & 모델", "zh-CN": "提供商、账户与模型", ru: "Провайдеры, аккаунты и модели", ja: "プロバイダー・アカウント・モデル" }, slug: "reference/cli/providers-accounts" }, - { label: "Agents, Routing & Integrations", translations: { ko: "에이전트, 라우팅 & 통합", "zh-CN": "代理、路由与集成", ru: "Агенты, маршрутизация и интеграции", ja: "エージェント・ルーティング・連携" }, slug: "reference/cli/agents" }, + { label: "Overview", slug: "reference/cli" }, + { label: "Lifecycle & Service", slug: "reference/cli/lifecycle" }, + { label: "Providers, Accounts & Models", slug: "reference/cli/providers-accounts" }, + { label: "Agents, Routing & Integrations", slug: "reference/cli/agents" }, ], }, { label: "Configuration", - translations: { ko: "설정", "zh-CN": "配置", ru: "Конфигурация", ja: "設定" }, items: [ - { label: "Overview", translations: { ko: "개요", "zh-CN": "概览", ru: "Обзор", ja: "概要" }, slug: "reference/configuration" }, - { label: "Providers", translations: { ko: "프로바이더", "zh-CN": "提供商", ru: "Провайдеры", ja: "プロバイダー" }, slug: "reference/configuration/providers" }, - { label: "Routing", translations: { ko: "라우팅", "zh-CN": "路由", ru: "Маршрутизация", ja: "ルーティング" }, slug: "reference/configuration/routing" }, - { label: "Agents", translations: { ko: "에이전트", "zh-CN": "代理", ru: "Агенты", ja: "エージェント" }, slug: "reference/configuration/agents" }, - { label: "Server & Runtime", translations: { ko: "서버 & 런타임", "zh-CN": "服务器与运行时", ru: "Сервер и рантайм", ja: "サーバー & ランタイム" }, slug: "reference/configuration/server" }, + { label: "Overview", slug: "reference/configuration" }, + { label: "Providers", slug: "reference/configuration/providers" }, + { label: "Routing", slug: "reference/configuration/routing" }, + { label: "Agents", slug: "reference/configuration/agents" }, + { label: "Server & Runtime", slug: "reference/configuration/server" }, ], }, - { label: "Adapters", translations: { ko: "어댑터", "zh-CN": "适配器", ru: "Адаптеры", ja: "アダプター" }, slug: "reference/adapters" }, - { label: "Architecture", translations: { ko: "아키텍처", "zh-CN": "架构", ru: "Архитектура", ja: "アーキテクチャ" }, slug: "reference/architecture" }, - { label: "Proxy API Formats", translations: { ko: "프록시 API 형식", "zh-CN": "代理 API 格式", ru: "Форматы API прокси", ja: "プロキシAPI形式" }, slug: "reference/proxy-formats" }, - { label: "Management API", translations: { ko: "관리 API", "zh-CN": "管理 API", ru: "API управления", ja: "管理API" }, slug: "reference/management-api" }, + { label: "Adapters", slug: "reference/adapters" }, + { label: "Architecture", slug: "reference/architecture" }, + { label: "Proxy API Formats", slug: "reference/proxy-formats" }, + { label: "Management API", slug: "reference/management-api" }, ], }, { label: "Troubleshooting", - translations: { ko: "문제 해결", "zh-CN": "故障排除", ru: "Устранение неполадок", ja: "トラブルシューティング" }, collapsed: true, items: [ - { label: "Windows Memory Growth", translations: { ko: "Windows 메모리 증가", "zh-CN": "Windows 内存增长", ru: "Рост памяти в Windows", ja: "Windows メモリ増加" }, slug: "troubleshooting/windows-memory" }, + { label: "Windows Memory Growth", slug: "troubleshooting/windows-memory" }, ], }, - { label: "Contributing", translations: { ko: "기여하기", "zh-CN": "贡献", ru: "Как внести вклад", ja: "コントリビュート" }, slug: "contributing" }, + { label: "Contributing", slug: "contributing" }, ], }), ], diff --git a/docs-site/src/components/FrontierBoards.astro b/docs-site/src/components/FrontierBoards.astro index 2a2937d86..616004717 100644 --- a/docs-site/src/components/FrontierBoards.astro +++ b/docs-site/src/components/FrontierBoards.astro @@ -10,23 +10,18 @@ import data from "../data/frontier-benchmarks.json"; import { FRONTIER_STRINGS } from "../data/frontier-i18n"; interface Props { - locale?: "en" | "ko" | "zh-cn" | "ru" | "ja"; /** Comma-separated board ids to render; omit for all boards. */ boards?: string; /** Show the page-level subtitle (overview pages only). */ intro?: boolean; } -const { locale = "en", boards: boardsProp, intro = false } = Astro.props; +const { boards: boardsProp, intro = false } = Astro.props; const include = boardsProp ? new Set(boardsProp.split(",").map(s => s.trim()).filter(Boolean)) : null; -const strings = FRONTIER_STRINGS[locale] as Record; -const fallback = FRONTIER_STRINGS.en as Record; -const t = (key: string): string => strings[key] ?? fallback[key] ?? key; +const t = (key: string): string => FRONTIER_STRINGS[key] ?? key; const fill = (key: string, vars: Record): string => Object.entries(vars).reduce((acc, [k, v]) => acc.replace(`{${k}}`, v), t(key)); -// The PR i18n has no column-header key for "score" — keep a tiny local map. -const SCORE_HEADER: Record = { en: "Score", ko: "점수", "zh-cn": "得分", ru: "Балл", ja: "スコア" }; /** Dataset tags are kebab-case; i18n keys are camelCase (cheap-subagent → cheapSubagent). */ const tagKey = (tag: string): string => tag.replace(/-([a-z])/g, (_, c) => c.toUpperCase()); @@ -75,7 +70,7 @@ const boards = data.benchmarks.filter(board => !include || include.has(board.id) {t("frontier.col.model")} {t("frontier.col.effort")} - {SCORE_HEADER[locale] ?? SCORE_HEADER.en} + Score {t("frontier.col.cost")} {board.allMeasured && {t("frontier.col.efficiency")}} {t("frontier.col.tags")} diff --git a/docs-site/src/components/Header.astro b/docs-site/src/components/Header.astro index 6fd845805..e2ba34833 100644 --- a/docs-site/src/components/Header.astro +++ b/docs-site/src/components/Header.astro @@ -8,94 +8,65 @@ import Search from '@astrojs/starlight/components/Search.astro'; import SiteTitle from '@astrojs/starlight/components/SiteTitle.astro'; import SocialIcons from '@astrojs/starlight/components/SocialIcons.astro'; -const { locale } = Astro.locals.starlightRoute; // Splash pages have no Starlight sidebar/hamburger, so the pill carries its own // menu below the desktop-nav breakpoint. const isSplash = Astro.locals.starlightRoute.entry.data.template === 'splash'; -// Root locale is `undefined`; BASE_URL already ends with a slash. +// BASE_URL already ends with a slash. const base = import.meta.env.BASE_URL.replace(/\/?$/, '/'); -const prefix = locale ? `${base}${locale}/` : base; +const prefix = base; type NavLink = { label: string; href: string }; type NavGroup = { label: string; links: NavLink[] }; -const t = (en: string, ko: string, zh: string, ru: string, ja: string) => - locale === 'ko' ? ko : locale === 'zh-cn' ? zh : locale === 'ru' ? ru : locale === 'ja' ? ja : en; - -type LanguageOption = { code: 'root' | 'ko' | 'zh-cn' | 'ru' | 'ja'; label: string }; -const languages: LanguageOption[] = [ - { code: 'root', label: 'English' }, - { code: 'ko', label: '한국어' }, - { code: 'zh-cn', label: '简体中文' }, - { code: 'ru', label: 'Русский' }, - { code: 'ja', label: '日本語' }, -]; -const currentLanguage = languages.find(({ code }) => code === (locale ?? 'root')) ?? languages[0]; - -// Preserve the current document path when switching locale. Starlight's root -// locale has no URL segment, while every translated locale does. -const routePrefix = locale ? `${base}${locale}/` : base; -const routeSuffix = Astro.url.pathname.startsWith(routePrefix) - ? Astro.url.pathname.slice(routePrefix.length) - : ''; -const languageHref = (code: LanguageOption['code']) => - `${code === 'root' ? base : `${base}${code}/`}${routeSuffix}`; - const themeLabels = { - auto: t('Auto', '자동', '自动', 'Авто', '自動'), - light: t('Light', '라이트', '浅色', 'Светлая', 'ライト'), - dark: t('Dark', '다크', '深色', 'Тёмная', 'ダーク'), + auto: 'Auto', + light: 'Light', + dark: 'Dark', }; -const themeName = t('Theme', '테마', '主题', 'Тема', 'テーマ'); -const themeCycleHint = t( - 'Click to use the next theme', - '클릭하여 다음 테마로 전환', - '点击切换到下一个主题', - 'Нажмите, чтобы включить следующую тему', - 'クリックして次のテーマに切り替え', -); +const themeName = 'Theme'; +const themeCycleHint = 'Click to use the next theme'; const groups: NavGroup[] = [ { - label: t('Getting Started', '시작하기', '开始使用', 'Начало работы', 'はじめに'), + label: 'Getting Started', links: [ - { label: t('Installation', '설치', '安装', 'Установка', 'インストール'), href: `${prefix}getting-started/installation/` }, - { label: t('Quickstart', '빠른 시작', '快速开始', 'Быстрый старт', 'クイックスタート'), href: `${prefix}getting-started/quickstart/` }, - { label: t('How It Works', '동작 원리', '工作原理', 'Как это работает', '仕組み'), href: `${prefix}getting-started/how-it-works/` }, - { label: t('Agent Quickstart', '에이전트 퀵스타트', 'Agent 快速上手', 'Быстрый старт для агентов', 'エージェント向けクイックスタート'), href: `${prefix}getting-started/for-agents/` }, + { label: 'Installation', href: `${prefix}getting-started/installation/` }, + { label: 'Quickstart', href: `${prefix}getting-started/quickstart/` }, + { label: 'How It Works', href: `${prefix}getting-started/how-it-works/` }, + { label: 'Agent Quickstart', href: `${prefix}getting-started/for-agents/` }, ], }, { - label: t('Guides', '가이드', '指南', 'Руководства', 'ガイド'), + label: 'Guides', links: [ - { label: t('Providers', '프로바이더', '提供商', 'Провайдеры', 'プロバイダー'), href: `${prefix}guides/providers/` }, - { label: t('Model Routing', '모델 라우팅', '模型路由', 'Маршрутизация моделей', 'モデルルーティング'), href: `${prefix}guides/model-routing/` }, - { label: t('Combos', '콤보', '组合', 'Комбо', 'コンボ'), href: `${prefix}guides/combos/` }, - { label: t('Codex Integration', 'Codex 통합', 'Codex 集成', 'Интеграция с Codex', 'Codex 連携'), href: `${prefix}guides/codex-integration/` }, - { label: t('Codex App Model Picker', 'Codex App 모델 선택기', 'Codex App 模型选择器', 'Селектор моделей Codex App', 'Codex App モデルピッカー'), href: `${prefix}guides/codex-app-models/` }, + { label: 'Providers', href: `${prefix}guides/providers/` }, + { label: 'Model Routing', href: `${prefix}guides/model-routing/` }, + { label: 'Combos', href: `${prefix}guides/combos/` }, + { label: 'Codex Integration', href: `${prefix}guides/codex-integration/` }, + { label: 'Codex App Model Picker', href: `${prefix}guides/codex-app-models/` }, { label: 'Claude Code', href: `${prefix}guides/claude-code/` }, - { label: t('Sidecars: Search & Vision', '사이드카: 검색 & 비전', '边车:搜索与视觉', 'Сайдкары: поиск и зрение', 'サイドカー: 検索 & ビジョン'), href: `${prefix}guides/sidecars/` }, - { label: t('Image Bridge', '이미지 브릿지', '图像桥接', 'Image Bridge', '画像ブリッジ'), href: `${prefix}guides/image-bridge/` }, - { label: t('Video Bridge', '비디오 브릿지', '视频桥接', 'Video Bridge', '動画ブリッジ'), href: `${prefix}guides/video-bridge/` }, - { label: t('Web Dashboard', '웹 대시보드', '网页控制台', 'Веб-дашборд', 'ウェブダッシュボード'), href: `${prefix}guides/web-dashboard/` }, - { label: t('Sub-agent Surface', '서브에이전트 서피스', '子代理界面', 'Интерфейс подагентов', 'サブエージェントサーフェス'), href: `${prefix}guides/sub-agent-surface/` }, + { label: 'Sidecars: Search & Vision', href: `${prefix}guides/sidecars/` }, + { label: 'Image Bridge', href: `${prefix}guides/image-bridge/` }, + { label: 'Video Bridge', href: `${prefix}guides/video-bridge/` }, + { label: 'Web Dashboard', href: `${prefix}guides/web-dashboard/` }, + { label: 'Sub-agent Surface', href: `${prefix}guides/sub-agent-surface/` }, ], }, { - label: t('Reference', '레퍼런스', '参考', 'Справочник', 'リファレンス'), + label: 'Reference', links: [ { label: 'CLI', href: `${prefix}reference/cli/` }, - { label: t('Configuration', '설정', '配置', 'Конфигурация', '設定'), href: `${prefix}reference/configuration/` }, - { label: t('Adapters', '어댑터', '适配器', 'Адаптеры', 'アダプター'), href: `${prefix}reference/adapters/` }, - { label: t('Architecture', '아키텍처', '架构', 'Архитектура', 'アーキテクチャ'), href: `${prefix}reference/architecture/` }, - { label: t('Proxy API Formats', '프록시 API 형식', '代理 API 格式', 'Форматы API прокси', 'プロキシAPI形式'), href: `${prefix}reference/proxy-formats/` }, - { label: t('Management API', '관리 API', '管理 API', 'API управления', '管理API'), href: `${prefix}reference/management-api/` }, + { label: 'Configuration', href: `${prefix}reference/configuration/` }, + { label: 'Adapters', href: `${prefix}reference/adapters/` }, + { label: 'Architecture', href: `${prefix}reference/architecture/` }, + { label: 'Proxy API Formats', href: `${prefix}reference/proxy-formats/` }, + { label: 'Management API', href: `${prefix}reference/management-api/` }, ], }, ]; const contributing: NavLink = { - label: t('Contributing', '기여하기', '贡献', 'Участие в проекте', 'コントリビュート'), + label: 'Contributing', href: `${prefix}contributing/`, }; --- @@ -104,7 +75,7 @@ const contributing: NavLink = {
-