diff options
| author | Adam <[email protected]> | 2026-02-27 15:50:50 -0600 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-02-27 15:50:50 -0600 |
| commit | 7f851da15ecde7db6535aae1f13009d3d6068daf (patch) | |
| tree | e8978e858c09a6507dfe0ad40b32b008d634b82e | |
| parent | a3bdb974b36714ace5e2a41e76da8aa6682eb4c8 (diff) | |
| download | opencode-7f851da15ecde7db6535aae1f13009d3d6068daf.tar.gz opencode-7f851da15ecde7db6535aae1f13009d3d6068daf.zip | |
chore(console): i18n sync (#15360)
32 files changed, 664 insertions, 56 deletions
diff --git a/packages/console/app/src/app.tsx b/packages/console/app/src/app.tsx index 3eb70606a..1f1d0066e 100644 --- a/packages/console/app/src/app.tsx +++ b/packages/console/app/src/app.tsx @@ -7,9 +7,21 @@ 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" +import { I18nProvider, useI18n } from "~/context/i18n" import { strip } from "~/lib/language" +function AppMeta() { + const i18n = useI18n() + return ( + <> + <Title>opencode</Title> + <Meta name="description" content={i18n.t("app.meta.description")} /> + <Favicon /> + <Font /> + </> + ) +} + export default function App() { return ( <Router @@ -19,10 +31,7 @@ export default function App() { <LanguageProvider> <I18nProvider> <MetaProvider> - <Title>opencode</Title> - <Meta name="description" content="OpenCode - The open source coding agent." /> - <Favicon /> - <Font /> + <AppMeta /> <Suspense>{props.children}</Suspense> </MetaProvider> </I18nProvider> diff --git a/packages/console/app/src/component/header.tsx b/packages/console/app/src/component/header.tsx index 6fa0f43ad..6ab5ce2f5 100644 --- a/packages/console/app/src/component/header.tsx +++ b/packages/console/app/src/component/header.tsx @@ -124,8 +124,8 @@ export function Header(props: { zen?: boolean; hideGetStarted?: boolean }) { <section data-component="top"> <div onContextMenu={handleLogoContextMenu}> <A href={language.route("/")}> - <img data-slot="logo light" src={logoLight} alt="OpenCode" width="189" height="34" /> - <img data-slot="logo dark" src={logoDark} alt="OpenCode" width="189" height="34" /> + <img data-slot="logo light" src={logoLight} alt={i18n.t("nav.logoAlt")} width="189" height="34" /> + <img data-slot="logo dark" src={logoDark} alt={i18n.t("nav.logoAlt")} width="189" height="34" /> </A> </div> diff --git a/packages/console/app/src/i18n/ar.ts b/packages/console/app/src/i18n/ar.ts index cda1e2a36..0155baf03 100644 --- a/packages/console/app/src/i18n/ar.ts +++ b/packages/console/app/src/i18n/ar.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "الرئيسية", "nav.openMenu": "فتح القائمة", "nav.getStartedFree": "ابدأ مجانا", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "نسخ الشعار كـ SVG", "nav.context.copyWordmark": "نسخ اسم العلامة كـ SVG", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "الوثائق", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "شعار opencode الفاتح", + "notFound.logoDarkAlt": "شعار opencode الداكن", "user.logout": "تسجيل الخروج", + "auth.callback.error.codeMissing": "لم يتم العثور على رمز التفويض.", + "workspace.select": "اختر مساحة العمل", "workspace.createNew": "+ إنشاء مساحة عمل جديدة", "workspace.modal.title": "إنشاء مساحة عمل جديدة", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "يجب أن يكون مبلغ الشحن ${{amount}} على الأقل", "error.reloadTriggerMin": "يجب أن يكون حد الرصيد ${{amount}} على الأقل", + "app.meta.description": "OpenCode - وكيل البرمجة مفتوح المصدر.", + "home.title": "OpenCode | وكيل برمجة بالذكاء الاصطناعي مفتوح المصدر", "temp.title": "opencode | وكيل برمجة بالذكاء الاصطناعي مبني للطرفية", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": "، بما في ذلك النماذج المحلية", "temp.screenshot.caption": "واجهة OpenCode الطرفية مع سمة tokyonight", "temp.screenshot.alt": "واجهة OpenCode الطرفية بسمة tokyonight", + "temp.logoLightAlt": "شعار opencode الفاتح", + "temp.logoDarkAlt": "شعار opencode الداكن", "home.banner.badge": "جديد", "home.banner.text": "تطبيق سطح المكتب متاح بنسخة تجريبية", @@ -238,6 +247,24 @@ export const dict = { "تتم استضافة جميع نماذج Zen في الولايات المتحدة. يتبع المزودون سياسة عدم الاحتفاظ بالبيانات ولا يستخدمون بياناتك لتدريب النماذج، مع", "zen.privacy.exceptionsLink": "الاستثناءات التالية", + "zen.api.error.rateLimitExceeded": "تم تجاوز حد الطلبات. يرجى المحاولة مرة أخرى لاحقًا.", + "zen.api.error.modelNotSupported": "النموذج {{model}} غير مدعوم", + "zen.api.error.modelFormatNotSupported": "النموذج {{model}} غير مدعوم للتنسيق {{format}}", + "zen.api.error.noProviderAvailable": "لا يوجد مزود متاح", + "zen.api.error.providerNotSupported": "المزود {{provider}} غير مدعوم", + "zen.api.error.missingApiKey": "مفتاح API مفقود.", + "zen.api.error.invalidApiKey": "مفتاح API غير صالح.", + "zen.api.error.subscriptionQuotaExceeded": "تم تجاوز حصة الاشتراك. أعد المحاولة خلال {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "تم تجاوز حصة الاشتراك. يمكنك الاستمرار في استخدام النماذج المجانية.", + "zen.api.error.noPaymentMethod": "لا توجد طريقة دفع. أضف طريقة دفع هنا: {{billingUrl}}", + "zen.api.error.insufficientBalance": "رصيد غير كاف. إدارة فواتيرك هنا: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "وصلت مساحة العمل الخاصة بك إلى حد الإنفاق الشهري البالغ ${{amount}}. إدارة حدودك هنا: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "لقد وصلت إلى حد الإنفاق الشهري البالغ ${{amount}}. إدارة حدودك هنا: {{membersUrl}}", + "zen.api.error.modelDisabled": "النموذج معطل", + "black.meta.title": "OpenCode Black | الوصول إلى أفضل نماذج البرمجة في العالم", "black.meta.description": "احصل على وصول إلى Claude، GPT، Gemini والمزيد مع خطط اشتراك OpenCode Black.", "black.hero.title": "الوصول إلى أفضل نماذج البرمجة في العالم", @@ -446,6 +473,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "يرجى تحديث طريقة الدفع والمحاولة مرة أخرى.", "workspace.reload.retrying": "جارٍ إعادة المحاولة...", "workspace.reload.retry": "أعد المحاولة", + "workspace.reload.error.paymentFailed": "فشلت عملية الدفع.", "workspace.payments.title": "سجل المدفوعات", "workspace.payments.subtitle": "معاملات الدفع الأخيرة.", @@ -563,6 +591,10 @@ export const dict = { "enterprise.form.send": "إرسال", "enterprise.form.sending": "جارٍ الإرسال...", "enterprise.form.success": "تم إرسال الرسالة، سنتواصل معك قريبًا.", + "enterprise.form.success.submitted": "تم إرسال النموذج بنجاح.", + "enterprise.form.error.allFieldsRequired": "جميع الحقول مطلوبة.", + "enterprise.form.error.invalidEmailFormat": "تنسيق البريد الإلكتروني غير صالح.", + "enterprise.form.error.internalServer": "خطأ داخلي في الخادم.", "enterprise.faq.title": "الأسئلة الشائعة", "enterprise.faq.q1": "ما هو OpenCode Enterprise؟", "enterprise.faq.a1": @@ -595,6 +627,7 @@ export const dict = { "bench.list.table.agent": "الوكيل", "bench.list.table.model": "النموذج", "bench.list.table.score": "الدرجة", + "bench.submission.error.allFieldsRequired": "جميع الحقول مطلوبة.", "bench.detail.title": "المعيار - {{task}}", "bench.detail.notFound": "المهمة غير موجودة", diff --git a/packages/console/app/src/i18n/br.ts b/packages/console/app/src/i18n/br.ts index ddeb0c10a..b28c5f45a 100644 --- a/packages/console/app/src/i18n/br.ts +++ b/packages/console/app/src/i18n/br.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "Início", "nav.openMenu": "Abrir menu", "nav.getStartedFree": "Começar grátis", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Copiar logo como SVG", "nav.context.copyWordmark": "Copiar marca como SVG", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "Documentação", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "logo opencode claro", + "notFound.logoDarkAlt": "logo opencode escuro", "user.logout": "Sair", + "auth.callback.error.codeMissing": "Nenhum código de autorização encontrado.", + "workspace.select": "Selecionar workspace", "workspace.createNew": "+ Criar novo workspace", "workspace.modal.title": "Criar novo workspace", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "O valor de recarga deve ser de pelo menos ${{amount}}", "error.reloadTriggerMin": "O gatilho de saldo deve ser de pelo menos ${{amount}}", + "app.meta.description": "OpenCode - O agente de codificação de código aberto.", + "home.title": "OpenCode | O agente de codificação de código aberto com IA", "temp.title": "opencode | Agente de codificação com IA feito para o terminal", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": ", incluindo modelos locais", "temp.screenshot.caption": "OpenCode TUI com o tema tokyonight", "temp.screenshot.alt": "OpenCode TUI com tema tokyonight", + "temp.logoLightAlt": "logo opencode claro", + "temp.logoDarkAlt": "logo opencode escuro", "home.banner.badge": "Novo", "home.banner.text": "App desktop disponível em beta", @@ -242,6 +251,24 @@ export const dict = { "Todos os modelos Zen são hospedados nos EUA. Os provedores seguem uma política de retenção zero e não usam seus dados para treinamento de modelo, com as", "zen.privacy.exceptionsLink": "seguintes exceções", + "zen.api.error.rateLimitExceeded": "Limite de taxa excedido. Por favor, tente novamente mais tarde.", + "zen.api.error.modelNotSupported": "Modelo {{model}} não suportado", + "zen.api.error.modelFormatNotSupported": "Modelo {{model}} não suportado para o formato {{format}}", + "zen.api.error.noProviderAvailable": "Nenhum provedor disponível", + "zen.api.error.providerNotSupported": "Provedor {{provider}} não suportado", + "zen.api.error.missingApiKey": "Chave de API ausente.", + "zen.api.error.invalidApiKey": "Chave de API inválida.", + "zen.api.error.subscriptionQuotaExceeded": "Cota de assinatura excedida. Tente novamente em {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Cota de assinatura excedida. Você pode continuar usando modelos gratuitos.", + "zen.api.error.noPaymentMethod": "Nenhuma forma de pagamento. Adicione uma forma de pagamento aqui: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Saldo insuficiente. Gerencie seu faturamento aqui: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Seu workspace atingiu o limite de gastos mensais de ${{amount}}. Gerencie seus limites aqui: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Você atingiu seu limite de gastos mensais de ${{amount}}. Gerencie seus limites aqui: {{membersUrl}}", + "zen.api.error.modelDisabled": "O modelo está desabilitado", + "black.meta.title": "OpenCode Black | Acesse os melhores modelos de codificação do mundo", "black.meta.description": "Tenha acesso ao Claude, GPT, Gemini e mais com os planos de assinatura OpenCode Black.", "black.hero.title": "Acesse os melhores modelos de codificação do mundo", @@ -451,6 +478,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Por favor, atualize sua forma de pagamento e tente novamente.", "workspace.reload.retrying": "Tentando novamente...", "workspace.reload.retry": "Tentar novamente", + "workspace.reload.error.paymentFailed": "Pagamento falhou.", "workspace.payments.title": "Histórico de Pagamentos", "workspace.payments.subtitle": "Transações de pagamento recentes.", @@ -571,6 +599,10 @@ export const dict = { "enterprise.form.send": "Enviar", "enterprise.form.sending": "Enviando...", "enterprise.form.success": "Mensagem enviada, entraremos em contato em breve.", + "enterprise.form.success.submitted": "Formulário enviado com sucesso.", + "enterprise.form.error.allFieldsRequired": "Todos os campos são obrigatórios.", + "enterprise.form.error.invalidEmailFormat": "Formato de e-mail inválido.", + "enterprise.form.error.internalServer": "Erro interno do servidor.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "O que é OpenCode Enterprise?", "enterprise.faq.a1": @@ -603,6 +635,7 @@ export const dict = { "bench.list.table.agent": "Agente", "bench.list.table.model": "Modelo", "bench.list.table.score": "Pontuação", + "bench.submission.error.allFieldsRequired": "Todos os campos são obrigatórios.", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "Tarefa não encontrada", diff --git a/packages/console/app/src/i18n/da.ts b/packages/console/app/src/i18n/da.ts index 18b2b89ff..dfcefc5b9 100644 --- a/packages/console/app/src/i18n/da.ts +++ b/packages/console/app/src/i18n/da.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "Hjem", "nav.openMenu": "Åbn menu", "nav.getStartedFree": "Kom i gang gratis", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Kopier logo som SVG", "nav.context.copyWordmark": "Kopier wordmark som SVG", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "Dokumentation", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencode logo light", + "notFound.logoDarkAlt": "opencode logo dark", "user.logout": "Log ud", + "auth.callback.error.codeMissing": "Ingen autorisationskode fundet.", + "workspace.select": "Vælg workspace", "workspace.createNew": "+ Opret nyt workspace", "workspace.modal.title": "Opret nyt workspace", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "Genopfyldningsbeløb skal være mindst ${{amount}}", "error.reloadTriggerMin": "Saldogrænse skal være mindst ${{amount}}", + "app.meta.description": "OpenCode - Den open source kodningsagent.", + "home.title": "OpenCode | Den open source AI-kodningsagent", "temp.title": "opencode | AI-kodningsagent bygget til terminalen", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": ", inklusive lokale modeller", "temp.screenshot.caption": "opencode TUI med tokyonight-temaet", "temp.screenshot.alt": "opencode TUI med tokyonight-temaet", + "temp.logoLightAlt": "opencode logo light", + "temp.logoDarkAlt": "opencode logo dark", "home.banner.badge": "Ny", "home.banner.text": "Desktop-app tilgængelig i beta", @@ -240,6 +249,24 @@ export const dict = { "Alle Zen-modeller er hostet i USA. Udbydere følger en nulopbevaringspolitik og bruger ikke dine data til modeltræning med", "zen.privacy.exceptionsLink": "følgende undtagelser", + "zen.api.error.rateLimitExceeded": "Hastighedsgrænse overskredet. Prøv venligst igen senere.", + "zen.api.error.modelNotSupported": "Model {{model}} understøttes ikke", + "zen.api.error.modelFormatNotSupported": "Model {{model}} understøttes ikke for format {{format}}", + "zen.api.error.noProviderAvailable": "Ingen udbyder tilgængelig", + "zen.api.error.providerNotSupported": "Udbyder {{provider}} understøttes ikke", + "zen.api.error.missingApiKey": "Manglende API-nøgle.", + "zen.api.error.invalidApiKey": "Ugyldig API-nøgle.", + "zen.api.error.subscriptionQuotaExceeded": "Abonnementskvote overskredet. Prøv igen om {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Abonnementskvote overskredet. Du kan fortsætte med at bruge gratis modeller.", + "zen.api.error.noPaymentMethod": "Ingen betalingsmetode. Tilføj en betalingsmetode her: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Utilstrækkelig saldo. Administrer din fakturering her: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Dit workspace har nået sin månedlige forbrugsgrænse på ${{amount}}. Administrer dine grænser her: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Du har nået din månedlige forbrugsgrænse på ${{amount}}. Administrer dine grænser her: {{membersUrl}}", + "zen.api.error.modelDisabled": "Modellen er deaktiveret", + "black.meta.title": "OpenCode Black | Få adgang til verdens bedste kodningsmodeller", "black.meta.description": "Få adgang til Claude, GPT, Gemini og mere med OpenCode Black-abonnementer.", "black.hero.title": "Få adgang til verdens bedste kodningsmodeller", @@ -449,6 +476,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Opdater din betalingsmetode, og prøv igen.", "workspace.reload.retrying": "Prøver igen...", "workspace.reload.retry": "Prøv igen", + "workspace.reload.error.paymentFailed": "Betaling mislykkedes.", "workspace.payments.title": "Betalingshistorik", "workspace.payments.subtitle": "Seneste betalingstransaktioner.", @@ -567,6 +595,10 @@ export const dict = { "enterprise.form.send": "Send", "enterprise.form.sending": "Sender...", "enterprise.form.success": "Besked sendt, vi vender tilbage snart.", + "enterprise.form.success.submitted": "Formular indsendt med succes.", + "enterprise.form.error.allFieldsRequired": "Alle felter er påkrævet.", + "enterprise.form.error.invalidEmailFormat": "Ugyldigt e-mailformat.", + "enterprise.form.error.internalServer": "Intern serverfejl.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "Hvad er OpenCode Enterprise?", "enterprise.faq.a1": @@ -599,6 +631,7 @@ export const dict = { "bench.list.table.agent": "Agent", "bench.list.table.model": "Model", "bench.list.table.score": "Score", + "bench.submission.error.allFieldsRequired": "Alle felter er påkrævet.", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "Opgave ikke fundet", diff --git a/packages/console/app/src/i18n/de.ts b/packages/console/app/src/i18n/de.ts index 5bee74aed..b5d8070ae 100644 --- a/packages/console/app/src/i18n/de.ts +++ b/packages/console/app/src/i18n/de.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "Startseite", "nav.openMenu": "Menü öffnen", "nav.getStartedFree": "Kostenlos starten", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Logo als SVG kopieren", "nav.context.copyWordmark": "Wortmarke als SVG kopieren", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "Dokumentation", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "OpenCode Logo hell", + "notFound.logoDarkAlt": "OpenCode Logo dunkel", "user.logout": "Abmelden", + "auth.callback.error.codeMissing": "Kein Autorisierungscode gefunden.", + "workspace.select": "Workspace auswählen", "workspace.createNew": "+ Neuen Workspace erstellen", "workspace.modal.title": "Neuen Workspace erstellen", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "Aufladebetrag muss mindestens ${{amount}} betragen", "error.reloadTriggerMin": "Guthaben-Auslöser muss mindestens ${{amount}} betragen", + "app.meta.description": "OpenCode - Der Open-Source Coding-Agent.", + "home.title": "OpenCode | Der Open-Source AI-Coding-Agent", "temp.title": "OpenCode | Für das Terminal gebauter AI-Coding-Agent", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": ", einschließlich lokaler Modelle", "temp.screenshot.caption": "OpenCode TUI mit dem Tokyonight-Theme", "temp.screenshot.alt": "OpenCode TUI mit Tokyonight-Theme", + "temp.logoLightAlt": "OpenCode Logo hell", + "temp.logoDarkAlt": "OpenCode Logo dunkel", "home.banner.badge": "Neu", "home.banner.text": "Desktop-App in der Beta verfügbar", @@ -242,6 +251,24 @@ export const dict = { "Alle Zen-Modelle werden in den USA gehostet. Anbieter folgen einer Zero-Retention-Policy und nutzen deine Daten nicht für Modelltraining, mit den", "zen.privacy.exceptionsLink": "folgenden Ausnahmen", + "zen.api.error.rateLimitExceeded": "Ratenlimit überschritten. Bitte versuche es später erneut.", + "zen.api.error.modelNotSupported": "Modell {{model}} wird nicht unterstützt", + "zen.api.error.modelFormatNotSupported": "Modell {{model}} wird für das Format {{format}} nicht unterstützt", + "zen.api.error.noProviderAvailable": "Kein Anbieter verfügbar", + "zen.api.error.providerNotSupported": "Anbieter {{provider}} wird nicht unterstützt", + "zen.api.error.missingApiKey": "Fehlender API-Key.", + "zen.api.error.invalidApiKey": "Ungültiger API-Key.", + "zen.api.error.subscriptionQuotaExceeded": "Abonnement-Quote überschritten. Erneuter Versuch in {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Abonnement-Quote überschritten. Du kannst weiterhin kostenlose Modelle nutzen.", + "zen.api.error.noPaymentMethod": "Keine Zahlungsmethode. Füge hier eine Zahlungsmethode hinzu: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Unzureichendes Guthaben. Verwalte deine Abrechnung hier: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Dein Workspace hat sein monatliches Ausgabenlimit von ${{amount}} erreicht. Verwalte deine Limits hier: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Du hast dein monatliches Ausgabenlimit von ${{amount}} erreicht. Verwalte deine Limits hier: {{membersUrl}}", + "zen.api.error.modelDisabled": "Modell ist deaktiviert", + "black.meta.title": "OpenCode Black | Zugriff auf die weltweit besten Coding-Modelle", "black.meta.description": "Erhalte Zugriff auf Claude, GPT, Gemini und mehr mit OpenCode Black Abos.", "black.hero.title": "Zugriff auf die weltweit besten Coding-Modelle", @@ -451,6 +478,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Bitte aktualisiere deine Zahlungsmethode und versuche es erneut.", "workspace.reload.retrying": "Versuche erneut...", "workspace.reload.retry": "Erneut versuchen", + "workspace.reload.error.paymentFailed": "Zahlung fehlgeschlagen.", "workspace.payments.title": "Zahlungshistorie", "workspace.payments.subtitle": "Kürzliche Zahlungstransaktionen.", @@ -571,6 +599,10 @@ export const dict = { "enterprise.form.send": "Senden", "enterprise.form.sending": "Sende...", "enterprise.form.success": "Nachricht gesendet, wir melden uns bald.", + "enterprise.form.success.submitted": "Formular erfolgreich gesendet.", + "enterprise.form.error.allFieldsRequired": "Alle Felder sind erforderlich.", + "enterprise.form.error.invalidEmailFormat": "Ungültiges E-Mail-Format.", + "enterprise.form.error.internalServer": "Interner Serverfehler.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "Was ist OpenCode Enterprise?", "enterprise.faq.a1": @@ -603,6 +635,7 @@ export const dict = { "bench.list.table.agent": "Agent", "bench.list.table.model": "Modell", "bench.list.table.score": "Score", + "bench.submission.error.allFieldsRequired": "Alle Felder sind erforderlich.", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "Task nicht gefunden", diff --git a/packages/console/app/src/i18n/en.ts b/packages/console/app/src/i18n/en.ts index d6db2e7f8..07a4ddb4c 100644 --- a/packages/console/app/src/i18n/en.ts +++ b/packages/console/app/src/i18n/en.ts @@ -11,6 +11,7 @@ export const dict = { "nav.home": "Home", "nav.openMenu": "Open menu", "nav.getStartedFree": "Get started for free", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Copy logo as SVG", "nav.context.copyWordmark": "Copy wordmark as SVG", @@ -38,9 +39,13 @@ export const dict = { "notFound.docs": "Docs", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencode logo light", + "notFound.logoDarkAlt": "opencode logo dark", "user.logout": "Logout", + "auth.callback.error.codeMissing": "No authorization code found.", + "workspace.select": "Select workspace", "workspace.createNew": "+ Create New Workspace", "workspace.modal.title": "Create New Workspace", @@ -72,6 +77,8 @@ export const dict = { "error.reloadAmountMin": "Reload amount must be at least ${{amount}}", "error.reloadTriggerMin": "Balance trigger must be at least ${{amount}}", + "app.meta.description": "OpenCode - The open source coding agent.", + "home.title": "OpenCode | The open source AI coding agent", "temp.title": "opencode | AI coding agent built for the terminal", @@ -87,6 +94,8 @@ export const dict = { "temp.feature.models.afterLink": ", including local models", "temp.screenshot.caption": "opencode TUI with the tokyonight theme", "temp.screenshot.alt": "opencode TUI with tokyonight theme", + "temp.logoLightAlt": "opencode logo light", + "temp.logoDarkAlt": "opencode logo dark", "home.banner.badge": "New", "home.banner.text": "Desktop app available in beta", @@ -234,6 +243,24 @@ export const dict = { "All Zen models are hosted in the US. Providers follow a zero-retention policy and do not use your data for model training, with the", "zen.privacy.exceptionsLink": "following exceptions", + "zen.api.error.rateLimitExceeded": "Rate limit exceeded. Please try again later.", + "zen.api.error.modelNotSupported": "Model {{model}} not supported", + "zen.api.error.modelFormatNotSupported": "Model {{model}} not supported for format {{format}}", + "zen.api.error.noProviderAvailable": "No provider available", + "zen.api.error.providerNotSupported": "Provider {{provider}} not supported", + "zen.api.error.missingApiKey": "Missing API key.", + "zen.api.error.invalidApiKey": "Invalid API key.", + "zen.api.error.subscriptionQuotaExceeded": "Subscription quota exceeded. Retry in {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Subscription quota exceeded. You can continue using free models.", + "zen.api.error.noPaymentMethod": "No payment method. Add a payment method here: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Insufficient balance. Manage your billing here: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Your workspace has reached its monthly spending limit of ${{amount}}. Manage your limits here: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "You have reached your monthly spending limit of ${{amount}}. Manage your limits here: {{membersUrl}}", + "zen.api.error.modelDisabled": "Model is disabled", + "black.meta.title": "OpenCode Black | Access all the world's best coding models", "black.meta.description": "Get access to Claude, GPT, Gemini and more with OpenCode Black subscription plans.", "black.hero.title": "Access all the world's best coding models", @@ -443,6 +470,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Please update your payment method and try again.", "workspace.reload.retrying": "Retrying...", "workspace.reload.retry": "Retry", + "workspace.reload.error.paymentFailed": "Payment failed.", "workspace.payments.title": "Payments History", "workspace.payments.subtitle": "Recent payment transactions.", @@ -561,6 +589,10 @@ export const dict = { "enterprise.form.send": "Send", "enterprise.form.sending": "Sending...", "enterprise.form.success": "Message sent, we'll be in touch soon.", + "enterprise.form.success.submitted": "Form submitted successfully.", + "enterprise.form.error.allFieldsRequired": "All fields are required.", + "enterprise.form.error.invalidEmailFormat": "Invalid email format.", + "enterprise.form.error.internalServer": "Internal server error.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "What is OpenCode Enterprise?", "enterprise.faq.a1": @@ -593,6 +625,7 @@ export const dict = { "bench.list.table.agent": "Agent", "bench.list.table.model": "Model", "bench.list.table.score": "Score", + "bench.submission.error.allFieldsRequired": "All fields are required.", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "Task not found", diff --git a/packages/console/app/src/i18n/es.ts b/packages/console/app/src/i18n/es.ts index c4676fe6e..65c81648b 100644 --- a/packages/console/app/src/i18n/es.ts +++ b/packages/console/app/src/i18n/es.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "Inicio", "nav.openMenu": "Abrir menú", "nav.getStartedFree": "Empezar gratis", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Copiar logo como SVG", "nav.context.copyWordmark": "Copiar marca como SVG", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "Documentación", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencode logo claro", + "notFound.logoDarkAlt": "opencode logo oscuro", "user.logout": "Cerrar sesión", + "auth.callback.error.codeMissing": "No se encontró código de autorización.", + "workspace.select": "Seleccionar espacio de trabajo", "workspace.createNew": "+ Crear nuevo espacio de trabajo", "workspace.modal.title": "Crear nuevo espacio de trabajo", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "La cantidad de recarga debe ser al menos ${{amount}}", "error.reloadTriggerMin": "El disparador de saldo debe ser al menos ${{amount}}", + "app.meta.description": "OpenCode - El agente de codificación de código abierto.", + "home.title": "OpenCode | El agente de codificación IA de código abierto", "temp.title": "opencode | Agente de codificación IA creado para la terminal", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": ", incluyendo modelos locales", "temp.screenshot.caption": "opencode TUI con el tema tokyonight", "temp.screenshot.alt": "opencode TUI con tema tokyonight", + "temp.logoLightAlt": "logo de opencode claro", + "temp.logoDarkAlt": "logo de opencode oscuro", "home.banner.badge": "Nuevo", "home.banner.text": "Aplicación de escritorio disponible en beta", @@ -243,6 +252,24 @@ export const dict = { "Todos los modelos Zen están alojados en EE. UU. Los proveedores siguen una política de cero retención y no usan tus datos para entrenamiento de modelos, con las", "zen.privacy.exceptionsLink": "siguientes excepciones", + "zen.api.error.rateLimitExceeded": "Límite de tasa excedido. Por favor, inténtalo de nuevo más tarde.", + "zen.api.error.modelNotSupported": "Modelo {{model}} no soportado", + "zen.api.error.modelFormatNotSupported": "Modelo {{model}} no soportado para el formato {{format}}", + "zen.api.error.noProviderAvailable": "Ningún proveedor disponible", + "zen.api.error.providerNotSupported": "Proveedor {{provider}} no soportado", + "zen.api.error.missingApiKey": "Falta la clave API.", + "zen.api.error.invalidApiKey": "Clave API inválida.", + "zen.api.error.subscriptionQuotaExceeded": "Cuota de suscripción excedida. Reintenta en {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Cuota de suscripción excedida. Puedes continuar usando modelos gratuitos.", + "zen.api.error.noPaymentMethod": "Sin método de pago. Añade un método de pago aquí: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Saldo insuficiente. Gestiona tu facturación aquí: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Tu espacio de trabajo ha alcanzado su límite de gasto mensual de ${{amount}}. Gestiona tus límites aquí: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Has alcanzado tu límite de gasto mensual de ${{amount}}. Gestiona tus límites aquí: {{membersUrl}}", + "zen.api.error.modelDisabled": "El modelo está deshabilitado", + "black.meta.title": "OpenCode Black | Accede a los mejores modelos de codificación del mundo", "black.meta.description": "Obtén acceso a Claude, GPT, Gemini y más con los planes de suscripción de OpenCode Black.", "black.hero.title": "Accede a los mejores modelos de codificación del mundo", @@ -452,6 +479,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Por favor actualiza tu método de pago e intenta de nuevo.", "workspace.reload.retrying": "Reintentando...", "workspace.reload.retry": "Reintentar", + "workspace.reload.error.paymentFailed": "El pago falló.", "workspace.payments.title": "Historial de Pagos", "workspace.payments.subtitle": "Transacciones de pago recientes.", @@ -571,6 +599,10 @@ export const dict = { "enterprise.form.send": "Enviar", "enterprise.form.sending": "Enviando...", "enterprise.form.success": "Mensaje enviado, estaremos en contacto pronto.", + "enterprise.form.success.submitted": "Formulario enviado con éxito.", + "enterprise.form.error.allFieldsRequired": "Todos los campos son obligatorios.", + "enterprise.form.error.invalidEmailFormat": "Formato de correo inválido.", + "enterprise.form.error.internalServer": "Error interno del servidor.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "¿Qué es OpenCode Enterprise?", "enterprise.faq.a1": @@ -603,6 +635,7 @@ export const dict = { "bench.list.table.agent": "Agente", "bench.list.table.model": "Modelo", "bench.list.table.score": "Puntuación", + "bench.submission.error.allFieldsRequired": "Todos los campos son obligatorios.", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "Tarea no encontrada", diff --git a/packages/console/app/src/i18n/fr.ts b/packages/console/app/src/i18n/fr.ts index 7b2306bc2..bf741aa9d 100644 --- a/packages/console/app/src/i18n/fr.ts +++ b/packages/console/app/src/i18n/fr.ts @@ -3,6 +3,7 @@ import { dict as en } from "./en" export const dict = { ...en, + "app.meta.description": "OpenCode - L'agent de code open source.", "nav.github": "GitHub", "nav.docs": "Documentation", "nav.changelog": "Changelog", @@ -15,6 +16,7 @@ export const dict = { "nav.home": "Accueil", "nav.openMenu": "Ouvrir le menu", "nav.getStartedFree": "Commencer gratuitement", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Copier le logo en SVG", "nav.context.copyWordmark": "Copier le logotype en SVG", @@ -42,6 +44,8 @@ export const dict = { "notFound.docs": "Documentation", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencode logo light", + "notFound.logoDarkAlt": "opencode logo dark", "user.logout": "Se déconnecter", @@ -75,6 +79,7 @@ export const dict = { "error.modelRequired": "Le modèle est requis", "error.reloadAmountMin": "Le montant de recharge doit être d'au moins {{amount}} $", "error.reloadTriggerMin": "Le seuil de déclenchement doit être d'au moins {{amount}} $", + "auth.callback.error.codeMissing": "Aucun code d'autorisation trouvé.", "home.title": "OpenCode | L'agent de code IA open source", @@ -91,6 +96,8 @@ export const dict = { "temp.feature.models.afterLink": ", y compris les modèles locaux", "temp.screenshot.caption": "OpenCode TUI avec le thème tokyonight", "temp.screenshot.alt": "OpenCode TUI avec le thème tokyonight", + "temp.logoLightAlt": "opencode logo light", + "temp.logoDarkAlt": "opencode logo dark", "home.banner.badge": "Nouveau", "home.banner.text": "Application desktop disponible en bêta", @@ -246,6 +253,24 @@ export const dict = { "Tous les modèles Zen sont hébergés aux États-Unis. Les fournisseurs suivent une politique de rétention zéro et n'utilisent pas vos données pour l'entraînement des modèles, avec les", "zen.privacy.exceptionsLink": "exceptions suivantes", + "zen.api.error.rateLimitExceeded": "Limite de débit dépassée. Veuillez réessayer plus tard.", + "zen.api.error.modelNotSupported": "Modèle {{model}} non pris en charge", + "zen.api.error.modelFormatNotSupported": "Modèle {{model}} non pris en charge pour le format {{format}}", + "zen.api.error.noProviderAvailable": "Aucun fournisseur disponible", + "zen.api.error.providerNotSupported": "Fournisseur {{provider}} non pris en charge", + "zen.api.error.missingApiKey": "Clé API manquante.", + "zen.api.error.invalidApiKey": "Clé API invalide.", + "zen.api.error.subscriptionQuotaExceeded": "Quota d'abonnement dépassé. Réessayez dans {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Quota d'abonnement dépassé. Vous pouvez continuer à utiliser les modèles gratuits.", + "zen.api.error.noPaymentMethod": "Aucune méthode de paiement. Ajoutez une méthode de paiement ici : {{billingUrl}}", + "zen.api.error.insufficientBalance": "Solde insuffisant. Gérez votre facturation ici : {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Votre espace de travail a atteint sa limite de dépense mensuelle de {{amount}} $. Gérez vos limites ici : {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Vous avez atteint votre limite de dépense mensuelle de {{amount}} $. Gérez vos limites ici : {{membersUrl}}", + "zen.api.error.modelDisabled": "Le modèle est désactivé", + "black.meta.title": "OpenCode Black | Accédez aux meilleurs modèles de code au monde", "black.meta.description": "Accédez à Claude, GPT, Gemini et plus avec les forfaits d'abonnement OpenCode Black.", "black.hero.title": "Accédez aux meilleurs modèles de code au monde", @@ -457,6 +482,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Veuillez mettre à jour votre méthode de paiement et réessayer.", "workspace.reload.retrying": "Nouvelle tentative...", "workspace.reload.retry": "Réessayer", + "workspace.reload.error.paymentFailed": "Échec du paiement.", "workspace.payments.title": "Historique des paiements", "workspace.payments.subtitle": "Transactions de paiement récentes.", @@ -581,6 +607,10 @@ export const dict = { "enterprise.form.send": "Envoyer", "enterprise.form.sending": "Envoi...", "enterprise.form.success": "Message envoyé, nous vous contacterons bientôt.", + "enterprise.form.success.submitted": "Formulaire soumis avec succès.", + "enterprise.form.error.allFieldsRequired": "Tous les champs sont requis.", + "enterprise.form.error.invalidEmailFormat": "Format d'e-mail invalide.", + "enterprise.form.error.internalServer": "Erreur interne du serveur.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "Qu'est-ce que OpenCode Enterprise ?", "enterprise.faq.a1": @@ -640,4 +670,5 @@ export const dict = { "bench.detail.table.duration": "Durée", "bench.detail.run.title": "Exécution {{n}}", "bench.detail.rawJson": "JSON brut", + "bench.submission.error.allFieldsRequired": "Tous les champs sont requis.", } satisfies Dict diff --git a/packages/console/app/src/i18n/it.ts b/packages/console/app/src/i18n/it.ts index 81dd29305..0a9e4f959 100644 --- a/packages/console/app/src/i18n/it.ts +++ b/packages/console/app/src/i18n/it.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "Home", "nav.openMenu": "Apri menu", "nav.getStartedFree": "Inizia gratis", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Copia il logo come SVG", "nav.context.copyWordmark": "Copia il wordmark come SVG", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "Documentazione", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "logo chiaro di opencode", + "notFound.logoDarkAlt": "logo scuro di opencode", "user.logout": "Esci", + "auth.callback.error.codeMissing": "Nessun codice di autorizzazione trovato.", + "workspace.select": "Seleziona workspace", "workspace.createNew": "+ Crea nuovo workspace", "workspace.modal.title": "Crea nuovo workspace", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "L'importo della ricarica deve essere almeno ${{amount}}", "error.reloadTriggerMin": "La soglia del saldo deve essere almeno ${{amount}}", + "app.meta.description": "OpenCode - L'agente di programmazione open source.", + "home.title": "OpenCode | L'agente di coding IA open source", "temp.title": "opencode | Agente di coding IA costruito per il terminale", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": ", inclusi modelli locali", "temp.screenshot.caption": "OpenCode TUI con il tema tokyonight", "temp.screenshot.alt": "OpenCode TUI con tema tokyonight", + "temp.logoLightAlt": "logo chiaro di opencode", + "temp.logoDarkAlt": "logo scuro di opencode", "home.banner.badge": "Nuovo", "home.banner.text": "App desktop disponibile in beta", @@ -240,6 +249,24 @@ export const dict = { "Tutti i modelli Zen sono ospitati negli Stati Uniti. I provider seguono una policy di zero-retention e non usano i tuoi dati per l'addestramento dei modelli, con le", "zen.privacy.exceptionsLink": "seguenti eccezioni", + "zen.api.error.rateLimitExceeded": "Limite di richieste superato. Riprova più tardi.", + "zen.api.error.modelNotSupported": "Modello {{model}} non supportato", + "zen.api.error.modelFormatNotSupported": "Modello {{model}} non supportato per il formato {{format}}", + "zen.api.error.noProviderAvailable": "Nessun provider disponibile", + "zen.api.error.providerNotSupported": "Provider {{provider}} non supportato", + "zen.api.error.missingApiKey": "Chiave API mancante.", + "zen.api.error.invalidApiKey": "Chiave API non valida.", + "zen.api.error.subscriptionQuotaExceeded": "Quota dell'abbonamento superata. Riprova tra {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Quota dell'abbonamento superata. Puoi continuare a utilizzare modelli gratuiti.", + "zen.api.error.noPaymentMethod": "Nessun metodo di pagamento. Aggiungi un metodo di pagamento qui: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Saldo insufficiente. Gestisci la tua fatturazione qui: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "La tua area di lavoro ha raggiunto il limite di spesa mensile di ${{amount}}. Gestisci i tuoi limiti qui: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Hai raggiunto il tuo limite di spesa mensile di ${{amount}}. Gestisci i tuoi limiti qui: {{membersUrl}}", + "zen.api.error.modelDisabled": "Il modello è disabilitato", + "black.meta.title": "OpenCode Black | Accedi ai migliori modelli di coding al mondo", "black.meta.description": "Ottieni l'accesso a Claude, GPT, Gemini e altri con i piani di abbonamento OpenCode Black.", @@ -451,6 +478,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Aggiorna il tuo metodo di pagamento e riprova.", "workspace.reload.retrying": "Riprovo...", "workspace.reload.retry": "Riprova", + "workspace.reload.error.paymentFailed": "Pagamento fallito.", "workspace.payments.title": "Cronologia Pagamenti", "workspace.payments.subtitle": "Transazioni di pagamento recenti.", @@ -569,6 +597,10 @@ export const dict = { "enterprise.form.send": "Invia", "enterprise.form.sending": "Invio...", "enterprise.form.success": "Messaggio inviato, ti contatteremo presto.", + "enterprise.form.success.submitted": "Modulo inviato con successo.", + "enterprise.form.error.allFieldsRequired": "Tutti i campi sono obbligatori.", + "enterprise.form.error.invalidEmailFormat": "Formato email non valido.", + "enterprise.form.error.internalServer": "Errore interno del server.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "Cos'è OpenCode Enterprise?", "enterprise.faq.a1": @@ -601,6 +633,7 @@ export const dict = { "bench.list.table.agent": "Agente", "bench.list.table.model": "Modello", "bench.list.table.score": "Punteggio", + "bench.submission.error.allFieldsRequired": "Tutti i campi sono obbligatori.", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "Task non trovato", diff --git a/packages/console/app/src/i18n/ja.ts b/packages/console/app/src/i18n/ja.ts index afcf6aeb9..ee7b5f928 100644 --- a/packages/console/app/src/i18n/ja.ts +++ b/packages/console/app/src/i18n/ja.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "ホーム", "nav.openMenu": "メニューを開く", "nav.getStartedFree": "無料ではじめる", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "ロゴをSVGでコピー", "nav.context.copyWordmark": "ワードマークをSVGでコピー", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "ドキュメント", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencodeのロゴ(ライト)", + "notFound.logoDarkAlt": "opencodeのロゴ(ダーク)", "user.logout": "ログアウト", + "auth.callback.error.codeMissing": "認証コードが見つかりません。", + "workspace.select": "ワークスペースを選択", "workspace.createNew": "+ 新しいワークスペースを作成", "workspace.modal.title": "新しいワークスペースを作成", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "リロード額は少なくとも ${{amount}} である必要があります", "error.reloadTriggerMin": "残高トリガーは少なくとも ${{amount}} である必要があります", + "app.meta.description": "OpenCode - オープンソースのコーディングエージェント。", + "home.title": "OpenCode | オープンソースのAIコーディングエージェント", "temp.title": "OpenCode | ターミナル向けに構築されたAIコーディングエージェント", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": "を通じて75以上のLLMプロバイダーをサポート", "temp.screenshot.caption": "tokyonight テーマを使用した OpenCode TUI", "temp.screenshot.alt": "tokyonight テーマの OpenCode TUI", + "temp.logoLightAlt": "opencodeのロゴ(ライト)", + "temp.logoDarkAlt": "opencodeのロゴ(ダーク)", "home.banner.badge": "新着", "home.banner.text": "デスクトップアプリのベータ版が利用可能", @@ -239,6 +248,25 @@ export const dict = { "すべてのZenモデルは米国でホストされています。プロバイダーはゼロ保持ポリシーに従い、モデルのトレーニングにデータを使用しません(", "zen.privacy.exceptionsLink": "以下の例外", + "zen.api.error.rateLimitExceeded": "レート制限を超えました。後でもう一度お試しください。", + "zen.api.error.modelNotSupported": "モデル {{model}} はサポートされていません", + "zen.api.error.modelFormatNotSupported": "フォーマット {{format}} ではモデル {{model}} はサポートされていません", + "zen.api.error.noProviderAvailable": "利用可能なプロバイダーがありません", + "zen.api.error.providerNotSupported": "プロバイダー {{provider}} はサポートされていません", + "zen.api.error.missingApiKey": "APIキーがありません。", + "zen.api.error.invalidApiKey": "無効なAPIキーです。", + "zen.api.error.subscriptionQuotaExceeded": + "サブスクリプションの制限を超えました。{{retryIn}} 後に再試行してください。", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "サブスクリプションの制限を超えました。無料モデルは引き続きご利用いただけます。", + "zen.api.error.noPaymentMethod": "お支払い方法がありません。こちらからお支払い方法を追加してください: {{billingUrl}}", + "zen.api.error.insufficientBalance": "残高が不足しています。こちらから請求を管理してください: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "ワークスペースが月額の利用上限 ${{amount}} に達しました。こちらから上限を管理してください: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "月額の利用上限 ${{amount}} に達しました。こちらから上限を管理してください: {{membersUrl}}", + "zen.api.error.modelDisabled": "モデルが無効です", + "black.meta.title": "OpenCode Black | 世界最高峰のコーディングモデルすべてにアクセス", "black.meta.description": "OpenCode Black サブスクリプションプランで、Claude、GPT、Gemini などにアクセス。", "black.hero.title": "世界最高峰のコーディングモデルすべてにアクセス", @@ -448,6 +476,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "支払い方法を更新して、もう一度お試しください。", "workspace.reload.retrying": "再試行中...", "workspace.reload.retry": "再試行", + "workspace.reload.error.paymentFailed": "支払いに失敗しました。", "workspace.payments.title": "支払い履歴", "workspace.payments.subtitle": "最近の支払い取引。", @@ -568,6 +597,10 @@ export const dict = { "enterprise.form.send": "送信", "enterprise.form.sending": "送信中...", "enterprise.form.success": "送信しました。まもなくご連絡いたします。", + "enterprise.form.success.submitted": "フォームが正常に送信されました。", + "enterprise.form.error.allFieldsRequired": "すべての項目は必須です。", + "enterprise.form.error.invalidEmailFormat": "無効なメール形式です。", + "enterprise.form.error.internalServer": "内部サーバーエラー。", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "OpenCode Enterpriseとは?", "enterprise.faq.a1": @@ -600,6 +633,7 @@ export const dict = { "bench.list.table.agent": "エージェント", "bench.list.table.model": "モデル", "bench.list.table.score": "スコア", + "bench.submission.error.allFieldsRequired": "すべての項目は必須です。", "bench.detail.title": "ベンチマーク - {{task}}", "bench.detail.notFound": "タスクが見つかりません", diff --git a/packages/console/app/src/i18n/ko.ts b/packages/console/app/src/i18n/ko.ts index b2375c3f7..2dc3f9466 100644 --- a/packages/console/app/src/i18n/ko.ts +++ b/packages/console/app/src/i18n/ko.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "홈", "nav.openMenu": "메뉴 열기", "nav.getStartedFree": "무료로 시작하기", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "로고를 SVG로 복사", "nav.context.copyWordmark": "워드마크를 SVG로 복사", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "문서", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencode 밝은 로고", + "notFound.logoDarkAlt": "opencode 어두운 로고", "user.logout": "로그아웃", + "auth.callback.error.codeMissing": "인증 코드를 찾을 수 없습니다.", + "workspace.select": "워크스페이스 선택", "workspace.createNew": "+ 새 워크스페이스 만들기", "workspace.modal.title": "새 워크스페이스 만들기", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "충전 금액은 최소 ${{amount}}이어야 합니다", "error.reloadTriggerMin": "잔액 트리거는 최소 ${{amount}}이어야 합니다", + "app.meta.description": "OpenCode - 오픈 소스 코딩 에이전트.", + "home.title": "OpenCode | 오픈 소스 AI 코딩 에이전트", "temp.title": "OpenCode | 터미널을 위해 만들어진 AI 코딩 에이전트", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": "를 통해 75개 이상의 LLM 제공자 지원", "temp.screenshot.caption": "tokyonight 테마가 적용된 OpenCode TUI", "temp.screenshot.alt": "tokyonight 테마가 적용된 OpenCode TUI", + "temp.logoLightAlt": "opencode 밝은 로고", + "temp.logoDarkAlt": "opencode 어두운 로고", "home.banner.badge": "신규", "home.banner.text": "데스크톱 앱 베타 버전 출시", @@ -236,6 +245,24 @@ export const dict = { "모든 Zen 모델은 미국에서 호스팅됩니다. 제공자들은 데이터 보존 금지 정책을 따르며 모델 학습에 데이터를 사용하지 않습니다. 단,", "zen.privacy.exceptionsLink": "다음 예외", + "zen.api.error.rateLimitExceeded": "속도 제한을 초과했습니다. 나중에 다시 시도해 주세요.", + "zen.api.error.modelNotSupported": "{{model}} 모델은 지원되지 않습니다", + "zen.api.error.modelFormatNotSupported": "{{model}} 모델은 {{format}} 형식에 대해 지원되지 않습니다", + "zen.api.error.noProviderAvailable": "사용 가능한 제공자가 없습니다", + "zen.api.error.providerNotSupported": "{{provider}} 제공자는 지원되지 않습니다", + "zen.api.error.missingApiKey": "API 키가 누락되었습니다.", + "zen.api.error.invalidApiKey": "유효하지 않은 API 키입니다.", + "zen.api.error.subscriptionQuotaExceeded": "구독 할당량을 초과했습니다. {{retryIn}} 후 다시 시도해 주세요.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "구독 할당량을 초과했습니다. 무료 모델은 계속 사용할 수 있습니다.", + "zen.api.error.noPaymentMethod": "결제 수단이 없습니다. 결제 수단을 추가하세요: {{billingUrl}}", + "zen.api.error.insufficientBalance": "잔액이 부족합니다. 결제 관리를 여기서 하세요: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "워크스페이스의 월간 지출 한도인 ${{amount}}에 도달했습니다. 한도 관리를 여기서 하세요: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "월간 지출 한도인 ${{amount}}에 도달했습니다. 한도 관리를 여기서 하세요: {{membersUrl}}", + "zen.api.error.modelDisabled": "모델이 비활성화되었습니다", + "black.meta.title": "OpenCode Black | 세계 최고의 코딩 모델에 액세스하세요", "black.meta.description": "OpenCode Black 구독 플랜으로 Claude, GPT, Gemini 등에 액세스하세요.", "black.hero.title": "세계 최고의 코딩 모델에 액세스하세요", @@ -445,6 +472,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "결제 수단을 업데이트하고 다시 시도해 주세요.", "workspace.reload.retrying": "재시도 중...", "workspace.reload.retry": "재시도", + "workspace.reload.error.paymentFailed": "결제에 실패했습니다.", "workspace.payments.title": "결제 내역", "workspace.payments.subtitle": "최근 결제 거래 내역입니다.", @@ -562,6 +590,10 @@ export const dict = { "enterprise.form.send": "전송", "enterprise.form.sending": "전송 중...", "enterprise.form.success": "메시지가 전송되었습니다. 곧 연락드리겠습니다.", + "enterprise.form.success.submitted": "양식이 성공적으로 제출되었습니다.", + "enterprise.form.error.allFieldsRequired": "모든 필드는 필수 항목입니다.", + "enterprise.form.error.invalidEmailFormat": "유효하지 않은 이메일 형식입니다.", + "enterprise.form.error.internalServer": "내부 서버 오류입니다.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "OpenCode 엔터프라이즈란 무엇인가요?", "enterprise.faq.a1": @@ -594,6 +626,7 @@ export const dict = { "bench.list.table.agent": "에이전트", "bench.list.table.model": "모델", "bench.list.table.score": "점수", + "bench.submission.error.allFieldsRequired": "모든 필드는 필수 항목입니다.", "bench.detail.title": "벤치마크 - {{task}}", "bench.detail.notFound": "태스크를 찾을 수 없음", diff --git a/packages/console/app/src/i18n/no.ts b/packages/console/app/src/i18n/no.ts index 41bacfb05..35c4bbb6a 100644 --- a/packages/console/app/src/i18n/no.ts +++ b/packages/console/app/src/i18n/no.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "Hjem", "nav.openMenu": "Åpne meny", "nav.getStartedFree": "Kom i gang gratis", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Kopier logo som SVG", "nav.context.copyWordmark": "Kopier wordmark som SVG", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "Dokumentasjon", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencode logo lys", + "notFound.logoDarkAlt": "opencode logo mørk", "user.logout": "Logg ut", + "auth.callback.error.codeMissing": "Ingen autorisasjonskode funnet.", + "workspace.select": "Velg arbeidsområde", "workspace.createNew": "+ Opprett nytt arbeidsområde", "workspace.modal.title": "Opprett nytt arbeidsområde", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "Påfyllingsbeløp må være minst ${{amount}}", "error.reloadTriggerMin": "Saldo-trigger må være minst ${{amount}}", + "app.meta.description": "OpenCode - Den åpne kildekode kodingsagenten.", + "home.title": "OpenCode | Den åpne kildekode AI-kodingsagenten", "temp.title": "opencode | AI-kodingsagent bygget for terminalen", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": ", inkludert lokale modeller", "temp.screenshot.caption": "opencode TUI med tokyonight-tema", "temp.screenshot.alt": "opencode TUI med tokyonight-tema", + "temp.logoLightAlt": "opencode logo lys", + "temp.logoDarkAlt": "opencode logo mørk", "home.banner.badge": "Ny", "home.banner.text": "Desktop-app tilgjengelig i beta", @@ -240,6 +249,24 @@ export const dict = { "Alle Zen-modeller hostes i USA. Leverandører følger en policy om null oppbevaring og bruker ikke dataene dine til modelltrening, med", "zen.privacy.exceptionsLink": "følgende unntak", + "zen.api.error.rateLimitExceeded": "Rate limit overskredet. Vennligst prøv igjen senere.", + "zen.api.error.modelNotSupported": "Modell {{model}} støttes ikke", + "zen.api.error.modelFormatNotSupported": "Modell {{model}} støttes ikke for format {{format}}", + "zen.api.error.noProviderAvailable": "Ingen leverandør tilgjengelig", + "zen.api.error.providerNotSupported": "Leverandør {{provider}} støttes ikke", + "zen.api.error.missingApiKey": "Mangler API-nøkkel.", + "zen.api.error.invalidApiKey": "Ugyldig API-nøkkel.", + "zen.api.error.subscriptionQuotaExceeded": "Abonnementskvote overskredet. Prøv igjen om {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Abonnementskvote overskredet. Du kan fortsette å bruke gratis modeller.", + "zen.api.error.noPaymentMethod": "Ingen betalingsmetode. Legg til en betalingsmetode her: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Utilstrekkelig saldo. Administrer faktureringen din her: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Arbeidsområdet ditt har nådd sin månedlige utgiftsgrense på ${{amount}}. Administrer grensene dine her: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Du har nådd din månedlige utgiftsgrense på ${{amount}}. Administrer grensene dine her: {{membersUrl}}", + "zen.api.error.modelDisabled": "Modellen er deaktivert", + "black.meta.title": "OpenCode Black | Få tilgang til verdens beste kodemodeller", "black.meta.description": "Få tilgang til Claude, GPT, Gemini og mer med OpenCode Black-abonnementer.", "black.hero.title": "Få tilgang til verdens beste kodemodeller", @@ -449,6 +476,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Vennligst oppdater betalingsmetoden din og prøv på nytt.", "workspace.reload.retrying": "Prøver på nytt...", "workspace.reload.retry": "Prøv på nytt", + "workspace.reload.error.paymentFailed": "Betaling mislyktes.", "workspace.payments.title": "Betalingshistorikk", "workspace.payments.subtitle": "Nylige betalingstransaksjoner.", @@ -567,6 +595,10 @@ export const dict = { "enterprise.form.send": "Send", "enterprise.form.sending": "Sender...", "enterprise.form.success": "Melding sendt, vi tar kontakt snart.", + "enterprise.form.success.submitted": "Skjemaet ble sendt inn.", + "enterprise.form.error.allFieldsRequired": "Alle felt er obligatoriske.", + "enterprise.form.error.invalidEmailFormat": "Ugyldig e-postformat.", + "enterprise.form.error.internalServer": "Intern serverfeil.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "Hva er OpenCode Enterprise?", "enterprise.faq.a1": @@ -599,6 +631,7 @@ export const dict = { "bench.list.table.agent": "Agent", "bench.list.table.model": "Modell", "bench.list.table.score": "Poengsum", + "bench.submission.error.allFieldsRequired": "Alle felt er obligatoriske.", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "Oppgave ikke funnet", diff --git a/packages/console/app/src/i18n/pl.ts b/packages/console/app/src/i18n/pl.ts index dc3c59196..0ff5388be 100644 --- a/packages/console/app/src/i18n/pl.ts +++ b/packages/console/app/src/i18n/pl.ts @@ -14,6 +14,7 @@ export const dict = { "nav.home": "Strona główna", "nav.openMenu": "Otwórz menu", "nav.getStartedFree": "Zacznij za darmo", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Skopiuj logo jako SVG", "nav.context.copyWordmark": "Skopiuj logotyp jako SVG", @@ -41,9 +42,13 @@ export const dict = { "notFound.docs": "Dokumentacja", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "jasne logo opencode", + "notFound.logoDarkAlt": "ciemne logo opencode", "user.logout": "Wyloguj się", + "auth.callback.error.codeMissing": "Nie znaleziono kodu autoryzacji.", + "workspace.select": "Wybierz obszar roboczy", "workspace.createNew": "+ Utwórz nowy obszar roboczy", "workspace.modal.title": "Utwórz nowy obszar roboczy", @@ -75,6 +80,8 @@ export const dict = { "error.reloadAmountMin": "Kwota doładowania musi wynosić co najmniej ${{amount}}", "error.reloadTriggerMin": "Próg salda musi wynosić co najmniej ${{amount}}", + "app.meta.description": "OpenCode - Otwartoźródłowy agent programistyczny.", + "home.title": "OpenCode | Open source'owy agent AI do kodowania", "temp.title": "opencode | Agent AI do kodowania zbudowany dla terminala", @@ -90,6 +97,8 @@ export const dict = { "temp.feature.models.afterLink": ", w tym modele lokalne", "temp.screenshot.caption": "OpenCode TUI z motywem tokyonight", "temp.screenshot.alt": "OpenCode TUI z motywem tokyonight", + "temp.logoLightAlt": "jasne logo opencode", + "temp.logoDarkAlt": "ciemne logo opencode", "home.banner.badge": "Nowość", "home.banner.text": "Aplikacja desktopowa dostępna w wersji beta", @@ -241,6 +250,24 @@ export const dict = { "Wszystkie modele Zen są hostowane w USA. Dostawcy stosują politykę zerowej retencji i nie wykorzystują Twoich danych do trenowania modeli, z", "zen.privacy.exceptionsLink": "następującymi wyjątkami", + "zen.api.error.rateLimitExceeded": "Przekroczono limit zapytań. Spróbuj ponownie później.", + "zen.api.error.modelNotSupported": "Model {{model}} nie jest obsługiwany", + "zen.api.error.modelFormatNotSupported": "Model {{model}} nie jest obsługiwany dla formatu {{format}}", + "zen.api.error.noProviderAvailable": "Brak dostępnego dostawcy", + "zen.api.error.providerNotSupported": "Dostawca {{provider}} nie jest obsługiwany", + "zen.api.error.missingApiKey": "Brak klucza API.", + "zen.api.error.invalidApiKey": "Nieprawidłowy klucz API.", + "zen.api.error.subscriptionQuotaExceeded": "Przekroczono limit subskrypcji. Spróbuj ponownie za {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Przekroczono limit subskrypcji. Możesz kontynuować korzystanie z darmowych modeli.", + "zen.api.error.noPaymentMethod": "Brak metody płatności. Dodaj metodę płatności tutaj: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Niewystarczające saldo. Zarządzaj swoimi płatnościami tutaj: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Twoja przestrzeń robocza osiągnęła miesięczny limit wydatków w wysokości ${{amount}}. Zarządzaj swoimi limitami tutaj: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Osiągnąłeś swój miesięczny limit wydatków w wysokości ${{amount}}. Zarządzaj swoimi limitami tutaj: {{membersUrl}}", + "zen.api.error.modelDisabled": "Model jest wyłączony", + "black.meta.title": "OpenCode Black | Dostęp do najlepszych na świecie modeli kodujących", "black.meta.description": "Uzyskaj dostęp do Claude, GPT, Gemini i innych dzięki planom subskrypcji OpenCode Black.", "black.hero.title": "Dostęp do najlepszych na świecie modeli kodujących", @@ -450,6 +477,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Zaktualizuj metodę płatności i spróbuj ponownie.", "workspace.reload.retrying": "Ponawianie...", "workspace.reload.retry": "Spróbuj ponownie", + "workspace.reload.error.paymentFailed": "Płatność nie powiodła się.", "workspace.payments.title": "Historia płatności", "workspace.payments.subtitle": "Ostatnie transakcje płatnicze.", @@ -570,6 +598,10 @@ export const dict = { "enterprise.form.send": "Wyślij", "enterprise.form.sending": "Wysyłanie...", "enterprise.form.success": "Wiadomość wysłana, skontaktujemy się wkrótce.", + "enterprise.form.success.submitted": "Formularz został pomyślnie wysłany.", + "enterprise.form.error.allFieldsRequired": "Wszystkie pola są wymagane.", + "enterprise.form.error.invalidEmailFormat": "Nieprawidłowy format adresu e-mail.", + "enterprise.form.error.internalServer": "Wewnętrzny błąd serwera.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "Czym jest OpenCode Enterprise?", "enterprise.faq.a1": @@ -602,6 +634,7 @@ export const dict = { "bench.list.table.agent": "Agent", "bench.list.table.model": "Model", "bench.list.table.score": "Wynik", + "bench.submission.error.allFieldsRequired": "Wszystkie pola są wymagane.", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "Nie znaleziono zadania", diff --git a/packages/console/app/src/i18n/ru.ts b/packages/console/app/src/i18n/ru.ts index 21b89dc94..d0db17d29 100644 --- a/packages/console/app/src/i18n/ru.ts +++ b/packages/console/app/src/i18n/ru.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "Главная", "nav.openMenu": "Открыть меню", "nav.getStartedFree": "Начать бесплатно", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Скопировать логотип как SVG", "nav.context.copyWordmark": "Скопировать название как SVG", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "Документация", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "светлый логотип opencode", + "notFound.logoDarkAlt": "темный логотип opencode", "user.logout": "Выйти", + "auth.callback.error.codeMissing": "Код авторизации не найден.", + "workspace.select": "Выбрать рабочее пространство", "workspace.createNew": "+ Создать рабочее пространство", "workspace.modal.title": "Создать рабочее пространство", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "Сумма пополнения должна быть не менее ${{amount}}", "error.reloadTriggerMin": "Порог баланса должен быть не менее ${{amount}}", + "app.meta.description": "OpenCode - AI-агент с открытым кодом для программирования.", + "home.title": "OpenCode | AI-агент с открытым кодом для программирования", "temp.title": "opencode | AI-агент для программирования в терминале", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": ", включая локальные модели", "temp.screenshot.caption": "OpenCode TUI с темой tokyonight", "temp.screenshot.alt": "OpenCode TUI с темой tokyonight", + "temp.logoLightAlt": "светлый логотип opencode", + "temp.logoDarkAlt": "темный логотип opencode", "home.banner.badge": "Новое", "home.banner.text": "Доступно десктопное приложение (бета)", @@ -244,6 +253,24 @@ export const dict = { "Все модели Zen размещены в США. Провайдеры следуют политике нулевого хранения и не используют ваши данные для обучения моделей, за", "zen.privacy.exceptionsLink": "следующими исключениями", + "zen.api.error.rateLimitExceeded": "Превышен лимит запросов. Пожалуйста, попробуйте позже.", + "zen.api.error.modelNotSupported": "Модель {{model}} не поддерживается", + "zen.api.error.modelFormatNotSupported": "Модель {{model}} не поддерживается для формата {{format}}", + "zen.api.error.noProviderAvailable": "Нет доступных провайдеров", + "zen.api.error.providerNotSupported": "Провайдер {{provider}} не поддерживается", + "zen.api.error.missingApiKey": "Отсутствует API ключ.", + "zen.api.error.invalidApiKey": "Неверный API ключ.", + "zen.api.error.subscriptionQuotaExceeded": "Квота подписки превышена. Повторите попытку через {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Квота подписки превышена. Вы можете продолжить использовать бесплатные модели.", + "zen.api.error.noPaymentMethod": "Нет способа оплаты. Добавьте способ оплаты здесь: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Недостаточно средств. Управляйте оплатой здесь: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Ваше рабочее пространство достигло ежемесячного лимита расходов в ${{amount}}. Управляйте лимитами здесь: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Вы достигли ежемесячного лимита расходов в ${{amount}}. Управляйте лимитами здесь: {{membersUrl}}", + "zen.api.error.modelDisabled": "Модель отключена", + "black.meta.title": "OpenCode Black | Доступ к лучшим моделям для кодинга в мире", "black.meta.description": "Получите доступ к Claude, GPT, Gemini и другим моделям с подпиской OpenCode Black.", "black.hero.title": "Доступ к лучшим моделям для кодинга в мире", @@ -455,6 +482,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Пожалуйста, обновите способ оплаты и попробуйте снова.", "workspace.reload.retrying": "Повторная попытка...", "workspace.reload.retry": "Повторить", + "workspace.reload.error.paymentFailed": "Ошибка оплаты.", "workspace.payments.title": "История платежей", "workspace.payments.subtitle": "Недавние транзакции.", @@ -574,6 +602,10 @@ export const dict = { "enterprise.form.send": "Отправить", "enterprise.form.sending": "Отправка...", "enterprise.form.success": "Сообщение отправлено, мы скоро свяжемся с вами.", + "enterprise.form.success.submitted": "Форма успешно отправлена.", + "enterprise.form.error.allFieldsRequired": "Все поля обязательны.", + "enterprise.form.error.invalidEmailFormat": "Неверный формат email.", + "enterprise.form.error.internalServer": "Внутренняя ошибка сервера.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "Что такое OpenCode Enterprise?", "enterprise.faq.a1": @@ -606,6 +638,7 @@ export const dict = { "bench.list.table.agent": "Агент", "bench.list.table.model": "Модель", "bench.list.table.score": "Оценка", + "bench.submission.error.allFieldsRequired": "Все поля обязательны.", "bench.detail.title": "Бенчмарк - {{task}}", "bench.detail.notFound": "Задача не найдена", diff --git a/packages/console/app/src/i18n/th.ts b/packages/console/app/src/i18n/th.ts index 064648354..129b789c9 100644 --- a/packages/console/app/src/i18n/th.ts +++ b/packages/console/app/src/i18n/th.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "หน้าหลัก", "nav.openMenu": "เปิดเมนู", "nav.getStartedFree": "เริ่มต้นฟรี", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "คัดลอกโลโก้เป็น SVG", "nav.context.copyWordmark": "คัดลอกตัวอักษรแบรนด์เป็น SVG", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "เอกสาร", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "โลโก้ opencode แบบสว่าง", + "notFound.logoDarkAlt": "โลโก้ opencode แบบมืด", "user.logout": "ออกจากระบบ", + "auth.callback.error.codeMissing": "ไม่พบ authorization code", + "workspace.select": "เลือก Workspace", "workspace.createNew": "+ สร้าง Workspace ใหม่", "workspace.modal.title": "สร้าง Workspace ใหม่", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "จำนวนเงินที่โหลดซ้ำต้องมีอย่างน้อย ${{amount}}", "error.reloadTriggerMin": "ยอดคงเหลือที่กระตุ้นต้องมีอย่างน้อย ${{amount}}", + "app.meta.description": "OpenCode - เอเจนต์เขียนโค้ดแบบโอเพนซอร์ส", + "home.title": "OpenCode | เอเจนต์เขียนโค้ดด้วย AI แบบโอเพนซอร์ส", "temp.title": "OpenCode | เอเจนต์เขียนโค้ด AI ที่สร้างมาเพื่อเทอร์มินัล", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": "รวมถึงโมเดล Local", "temp.screenshot.caption": "OpenCode TUI พร้อมธีม tokyonight", "temp.screenshot.alt": "OpenCode TUI พร้อมธีม tokyonight", + "temp.logoLightAlt": "โลโก้ opencode แบบสว่าง", + "temp.logoDarkAlt": "โลโก้ opencode แบบมืด", "home.banner.badge": "ใหม่", "home.banner.text": "แอปเดสก์ท็อปพร้อมใช้งานในเวอร์ชันเบต้า", @@ -239,6 +248,24 @@ export const dict = { "โมเดล Zen ทั้งหมดโฮสต์ในสหรัฐอเมริกา ผู้ให้บริการปฏิบัติตามนโยบายไม่เก็บรักษาข้อมูล (zero-retention policy) และไม่ใช้ข้อมูลของคุณสำหรับการฝึกโมเดล โดยมี", "zen.privacy.exceptionsLink": "ข้อยกเว้นดังนี้", + "zen.api.error.rateLimitExceeded": "เกินขีดจำกัดอัตราการใช้งาน กรุณาลองใหม่ในภายหลัง", + "zen.api.error.modelNotSupported": "ไม่รองรับโมเดล {{model}}", + "zen.api.error.modelFormatNotSupported": "ไม่รองรับโมเดล {{model}} สำหรับรูปแบบ {{format}}", + "zen.api.error.noProviderAvailable": "ไม่มีผู้ให้บริการที่พร้อมใช้งาน", + "zen.api.error.providerNotSupported": "ไม่รองรับผู้ให้บริการ {{provider}}", + "zen.api.error.missingApiKey": "ไม่มี API key", + "zen.api.error.invalidApiKey": "API key ไม่ถูกต้อง", + "zen.api.error.subscriptionQuotaExceeded": "โควต้าการสมัครสมาชิกเกินขีดจำกัด ลองใหม่ในอีก {{retryIn}}", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "โควต้าการสมัครสมาชิกเกินขีดจำกัด คุณสามารถดำเนินการต่อโดยใช้โมเดลฟรี", + "zen.api.error.noPaymentMethod": "ไม่มีวิธีการชำระเงิน เพิ่มวิธีการชำระเงินที่นี่: {{billingUrl}}", + "zen.api.error.insufficientBalance": "ยอดเงินคงเหลือไม่เพียงพอ จัดการการเรียกเก็บเงินของคุณที่นี่: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Workspace ของคุณถึงขีดจำกัดการใช้จ่ายรายเดือนที่ ${{amount}} แล้ว จัดการขีดจำกัดของคุณที่นี่: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "คุณถึงขีดจำกัดการใช้จ่ายรายเดือนที่ ${{amount}} แล้ว จัดการขีดจำกัดของคุณที่นี่: {{membersUrl}}", + "zen.api.error.modelDisabled": "โมเดลถูกปิดใช้งาน", + "black.meta.title": "OpenCode Black | เข้าถึงโมเดลเขียนโค้ดที่ดีที่สุดในโลก", "black.meta.description": "เข้าถึง Claude, GPT, Gemini และอื่นๆ ด้วยแผนสมาชิก OpenCode Black", "black.hero.title": "เข้าถึงโมเดลเขียนโค้ดที่ดีที่สุดในโลก", @@ -448,6 +475,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "โปรดอัปเดตวิธีการชำระเงินของคุณแล้วลองอีกครั้ง", "workspace.reload.retrying": "กำลังลองอีกครั้ง...", "workspace.reload.retry": "ลองอีกครั้ง", + "workspace.reload.error.paymentFailed": "การชำระเงินล้มเหลว", "workspace.payments.title": "ประวัติการชำระเงิน", "workspace.payments.subtitle": "รายการธุรกรรมการชำระเงินล่าสุด", @@ -566,6 +594,10 @@ export const dict = { "enterprise.form.send": "ส่ง", "enterprise.form.sending": "กำลังส่ง...", "enterprise.form.success": "ส่งข้อความแล้ว เราจะติดต่อกลับเร็วๆ นี้", + "enterprise.form.success.submitted": "ส่งแบบฟอร์มสำเร็จแล้ว", + "enterprise.form.error.allFieldsRequired": "จำเป็นต้องกรอกทุกช่อง", + "enterprise.form.error.invalidEmailFormat": "รูปแบบอีเมลไม่ถูกต้อง", + "enterprise.form.error.internalServer": "เกิดข้อผิดพลาดภายในเซิร์ฟเวอร์", "enterprise.faq.title": "คำถามที่พบบ่อย", "enterprise.faq.q1": "OpenCode Enterprise คืออะไร?", "enterprise.faq.a1": @@ -598,6 +630,7 @@ export const dict = { "bench.list.table.agent": "เอเจนต์", "bench.list.table.model": "โมเดล", "bench.list.table.score": "คะแนน", + "bench.submission.error.allFieldsRequired": "จำเป็นต้องกรอกทุกช่อง", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "ไม่พบงาน", diff --git a/packages/console/app/src/i18n/tr.ts b/packages/console/app/src/i18n/tr.ts index d94dd15d0..11e6ed58d 100644 --- a/packages/console/app/src/i18n/tr.ts +++ b/packages/console/app/src/i18n/tr.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "Ana sayfa", "nav.openMenu": "Menüyü aç", "nav.getStartedFree": "Ücretsiz başla", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Logoyu SVG olarak kopyala", "nav.context.copyWordmark": "Wordmark'ı SVG olarak kopyala", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "Dokümantasyon", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencode açık logo", + "notFound.logoDarkAlt": "opencode koyu logo", "user.logout": "Çıkış", + "auth.callback.error.codeMissing": "Yetkilendirme kodu bulunamadı.", + "workspace.select": "Çalışma alanı seç", "workspace.createNew": "+ Yeni çalışma alanı oluştur", "workspace.modal.title": "Yeni çalışma alanı oluştur", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "Yükleme tutarı en az ${{amount}} olmalıdır", "error.reloadTriggerMin": "Bakiye tetikleyicisi en az ${{amount}} olmalıdır", + "app.meta.description": "OpenCode - Açık kaynaklı kodlama ajanı.", + "home.title": "OpenCode | Açık kaynaklı yapay zeka kodlama ajanı", "temp.title": "opencode | Terminal için geliştirilmiş yapay zeka kodlama ajanı", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": " üzerinden destekler", "temp.screenshot.caption": "opencode TUI ve tokyonight teması", "temp.screenshot.alt": "tokyonight temalı opencode TUI", + "temp.logoLightAlt": "opencode açık logo", + "temp.logoDarkAlt": "opencode koyu logo", "home.banner.badge": "Yeni", "home.banner.text": "Masaüstü uygulaması beta olarak kullanılabilir", @@ -242,6 +251,24 @@ export const dict = { "Tüm Zen modelleri ABD'de barındırılmaktadır. Sağlayıcılar sıfır saklama politikası izler ve verilerinizi model eğitimi için kullanmaz; şu", "zen.privacy.exceptionsLink": "aşağıdaki istisnalar", + "zen.api.error.rateLimitExceeded": "İstek limiti aşıldı. Lütfen daha sonra tekrar deneyin.", + "zen.api.error.modelNotSupported": "{{model}} modeli desteklenmiyor", + "zen.api.error.modelFormatNotSupported": "{{model}} modeli {{format}} formatı için desteklenmiyor", + "zen.api.error.noProviderAvailable": "Kullanılabilir sağlayıcı yok", + "zen.api.error.providerNotSupported": "{{provider}} sağlayıcısı desteklenmiyor", + "zen.api.error.missingApiKey": "API anahtarı eksik.", + "zen.api.error.invalidApiKey": "Geçersiz API anahtarı.", + "zen.api.error.subscriptionQuotaExceeded": "Abonelik kotası aşıldı. {{retryIn}} içinde tekrar deneyin.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Abonelik kotası aşıldı. Ücretsiz modelleri kullanmaya devam edebilirsiniz.", + "zen.api.error.noPaymentMethod": "Ödeme yöntemi bulunamadı. Buradan bir ödeme yöntemi ekleyin: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Yetersiz bakiye. Faturalandırmanızı buradan yönetin: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Çalışma alanınız aylık ${{amount}} harcama limitine ulaştı. Limitlerinizi buradan yönetin: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Aylık ${{amount}} harcama limitinize ulaştınız. Limitlerinizi buradan yönetin: {{membersUrl}}", + "zen.api.error.modelDisabled": "Model devre dışı", + "black.meta.title": "OpenCode Black | Dünyanın en iyi kodlama modellerine erişin", "black.meta.description": "OpenCode Black abonelik planlarıyla Claude, GPT, Gemini ve daha fazlasına erişin.", "black.hero.title": "Dünyanın en iyi kodlama modellerine erişin", @@ -451,6 +478,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Lütfen ödeme yönteminizi güncelleyin ve tekrar deneyin.", "workspace.reload.retrying": "Yeniden deneniyor...", "workspace.reload.retry": "Yeniden dene", + "workspace.reload.error.paymentFailed": "Ödeme başarısız.", "workspace.payments.title": "Ödeme Geçmişi", "workspace.payments.subtitle": "Son ödeme işlemleri.", @@ -571,6 +599,10 @@ export const dict = { "enterprise.form.send": "Gönder", "enterprise.form.sending": "Gönderiliyor...", "enterprise.form.success": "Mesaj gönderildi, yakında size dönüş yapacağız.", + "enterprise.form.success.submitted": "Form başarıyla gönderildi.", + "enterprise.form.error.allFieldsRequired": "Tüm alanlar gereklidir.", + "enterprise.form.error.invalidEmailFormat": "Geçersiz e-posta formatı.", + "enterprise.form.error.internalServer": "İç sunucu hatası.", "enterprise.faq.title": "SSS", "enterprise.faq.q1": "OpenCode Enterprise nedir?", "enterprise.faq.a1": @@ -603,6 +635,7 @@ export const dict = { "bench.list.table.agent": "Ajan", "bench.list.table.model": "Model", "bench.list.table.score": "Puan", + "bench.submission.error.allFieldsRequired": "Tüm alanlar gereklidir.", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "Görev bulunamadı", diff --git a/packages/console/app/src/i18n/zh.ts b/packages/console/app/src/i18n/zh.ts index bf21073ce..74c8de434 100644 --- a/packages/console/app/src/i18n/zh.ts +++ b/packages/console/app/src/i18n/zh.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "首页", "nav.openMenu": "打开菜单", "nav.getStartedFree": "免费开始", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "复制 Logo (SVG)", "nav.context.copyWordmark": "复制商标 (SVG)", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "文档", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencode logo 亮色", + "notFound.logoDarkAlt": "opencode logo 暗色", "user.logout": "退出登录", + "auth.callback.error.codeMissing": "未找到授权码。", + "workspace.select": "选择工作区", "workspace.createNew": "+ 新建工作区", "workspace.modal.title": "新建工作区", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "充值金额必须至少为 ${{amount}}", "error.reloadTriggerMin": "余额触发阈值必须至少为 ${{amount}}", + "app.meta.description": "OpenCode - 开源编程代理。", + "home.title": "OpenCode | 开源 AI 编程代理", "temp.title": "OpenCode | 专为终端打造的 AI 编程代理", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": ",包括本地模型", "temp.screenshot.caption": "使用 Tokyonight 主题的 OpenCode TUI", "temp.screenshot.alt": "使用 Tokyonight 主题的 OpenCode TUI", + "temp.logoLightAlt": "opencode logo 亮色", + "temp.logoDarkAlt": "opencode logo 暗色", "home.banner.badge": "新", "home.banner.text": "桌面应用 Beta 版现已推出", @@ -229,6 +238,22 @@ export const dict = { "zen.privacy.beforeExceptions": "所有 Zen 模型均托管在美国。提供商遵循零留存政策,不使用您的数据进行模型训练,", "zen.privacy.exceptionsLink": "以下例外情况除外", + "zen.api.error.rateLimitExceeded": "超出速率限制。请稍后重试。", + "zen.api.error.modelNotSupported": "不支持模型 {{model}}", + "zen.api.error.modelFormatNotSupported": "格式 {{format}} 不支持模型 {{model}}", + "zen.api.error.noProviderAvailable": "没有可用的提供商", + "zen.api.error.providerNotSupported": "不支持提供商 {{provider}}", + "zen.api.error.missingApiKey": "缺少 API 密钥。", + "zen.api.error.invalidApiKey": "无效的 API 密钥。", + "zen.api.error.subscriptionQuotaExceeded": "超出订阅配额。请在 {{retryIn}} 后重试。", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": "超出订阅配额。您可以继续使用免费模型。", + "zen.api.error.noPaymentMethod": "没有付款方式。请在此处添加付款方式:{{billingUrl}}", + "zen.api.error.insufficientBalance": "余额不足。请在此处管理您的计费:{{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "您的工作区已达到每月支出限额 ${{amount}}。请在此处管理您的限额:{{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": "您已达到每月支出限额 ${{amount}}。请在此处管理您的限额:{{membersUrl}}", + "zen.api.error.modelDisabled": "模型已禁用", + "black.meta.title": "OpenCode Black | 访问全球顶尖编程模型", "black.meta.description": "通过 OpenCode Black 订阅计划使用 Claude, GPT, Gemini 等模型。", "black.hero.title": "访问全球顶尖编程模型", @@ -436,6 +461,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "请更新您的付款方式并重试。", "workspace.reload.retrying": "正在重试...", "workspace.reload.retry": "重试", + "workspace.reload.error.paymentFailed": "支付失败。", "workspace.payments.title": "支付历史", "workspace.payments.subtitle": "近期支付交易。", @@ -552,6 +578,10 @@ export const dict = { "enterprise.form.send": "发送", "enterprise.form.sending": "正在发送...", "enterprise.form.success": "消息已发送,我们会尽快与您联系。", + "enterprise.form.success.submitted": "表单提交成功。", + "enterprise.form.error.allFieldsRequired": "所有字段均为必填项。", + "enterprise.form.error.invalidEmailFormat": "邮箱格式无效。", + "enterprise.form.error.internalServer": "内部服务器错误。", "enterprise.faq.title": "常见问题", "enterprise.faq.q1": "什么是 OpenCode 企业版?", "enterprise.faq.a1": @@ -584,6 +614,7 @@ export const dict = { "bench.list.table.agent": "代理", "bench.list.table.model": "模型", "bench.list.table.score": "分数", + "bench.submission.error.allFieldsRequired": "所有字段均为必填项。", "bench.detail.title": "基准测试 - {{task}}", "bench.detail.notFound": "未找到任务", diff --git a/packages/console/app/src/i18n/zht.ts b/packages/console/app/src/i18n/zht.ts index 8ac69596c..db06860ee 100644 --- a/packages/console/app/src/i18n/zht.ts +++ b/packages/console/app/src/i18n/zht.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "首頁", "nav.openMenu": "開啟選單", "nav.getStartedFree": "免費開始使用", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "複製標誌(SVG)", "nav.context.copyWordmark": "複製字標(SVG)", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "文件", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencode 淺色標誌", + "notFound.logoDarkAlt": "opencode 深色標誌", "user.logout": "登出", + "auth.callback.error.codeMissing": "找不到授權碼。", + "workspace.select": "選取工作區", "workspace.createNew": "+ 建立新工作區", "workspace.modal.title": "建立新工作區", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "儲值金額必須至少為 ${{amount}}", "error.reloadTriggerMin": "餘額觸發門檻必須至少為 ${{amount}}", + "app.meta.description": "OpenCode - 開源編碼代理。", + "home.title": "OpenCode | 開源 AI 編碼代理", "temp.title": "OpenCode | 專為終端打造的 AI 編碼代理", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": "支援 75+ 家 LLM 供應商,包括本地模型", "temp.screenshot.caption": "使用 tokyonight 主題的 OpenCode TUI", "temp.screenshot.alt": "使用 tokyonight 主題的 OpenCode TUI", + "temp.logoLightAlt": "opencode 淺色標誌", + "temp.logoDarkAlt": "opencode 深色標誌", "home.banner.badge": "新", "home.banner.text": "桌面應用已推出 Beta", @@ -229,6 +238,22 @@ export const dict = { "zen.privacy.beforeExceptions": "所有 Zen 模型均在美國託管。供應商遵循零留存政策,不會將你的資料用於模型訓練,並且有", "zen.privacy.exceptionsLink": "以下例外情況", + "zen.api.error.rateLimitExceeded": "超出頻率限制。請稍後再試。", + "zen.api.error.modelNotSupported": "不支援模型 {{model}}", + "zen.api.error.modelFormatNotSupported": "模型 {{model}} 不支援格式 {{format}}", + "zen.api.error.noProviderAvailable": "無可用的供應商", + "zen.api.error.providerNotSupported": "不支援供應商 {{provider}}", + "zen.api.error.missingApiKey": "缺少 API 金鑰。", + "zen.api.error.invalidApiKey": "無效的 API 金鑰。", + "zen.api.error.subscriptionQuotaExceeded": "超出訂閱配額。請在 {{retryIn}} 後重試。", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": "超出訂閱配額。你可以繼續使用免費模型。", + "zen.api.error.noPaymentMethod": "無付款方式。請在此處新增付款方式:{{billingUrl}}", + "zen.api.error.insufficientBalance": "餘額不足。請在此處管理你的帳務:{{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "你的工作區已達到每月支出限額 ${{amount}}。請在此處管理你的限額:{{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": "你已達到每月支出限額 ${{amount}}。請在此處管理你的限額:{{membersUrl}}", + "zen.api.error.modelDisabled": "模型已停用", + "black.meta.title": "OpenCode Black | 存取全球最佳編碼模型", "black.meta.description": "透過 OpenCode Black 訂閱方案存取 Claude、GPT、Gemini 等模型。", "black.hero.title": "存取全球最佳編碼模型", @@ -436,6 +461,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "請更新你的付款方式並重試。", "workspace.reload.retrying": "重試中...", "workspace.reload.retry": "重試", + "workspace.reload.error.paymentFailed": "付款失敗。", "workspace.payments.title": "付款紀錄", "workspace.payments.subtitle": "最近的付款交易。", @@ -551,6 +577,10 @@ export const dict = { "enterprise.form.send": "傳送", "enterprise.form.sending": "傳送中...", "enterprise.form.success": "訊息已傳送,我們會盡快與你聯絡。", + "enterprise.form.success.submitted": "表單已成功送出。", + "enterprise.form.error.allFieldsRequired": "所有欄位均為必填。", + "enterprise.form.error.invalidEmailFormat": "無效的電子郵件格式。", + "enterprise.form.error.internalServer": "內部伺服器錯誤。", "enterprise.faq.title": "常見問題", "enterprise.faq.q1": "什麼是 OpenCode Enterprise?", "enterprise.faq.a1": @@ -583,6 +613,7 @@ export const dict = { "bench.list.table.agent": "代理", "bench.list.table.model": "模型", "bench.list.table.score": "分數", + "bench.submission.error.allFieldsRequired": "所有欄位均為必填。", "bench.detail.title": "評測 - {{task}}", "bench.detail.notFound": "找不到任務", diff --git a/packages/console/app/src/lib/form-error.ts b/packages/console/app/src/lib/form-error.ts index 1f6e2ea1e..d643a98f1 100644 --- a/packages/console/app/src/lib/form-error.ts +++ b/packages/console/app/src/lib/form-error.ts @@ -48,6 +48,9 @@ const map = { "Provider is required": "error.providerRequired", "API key is required": "error.apiKeyRequired", "Model is required": "error.modelRequired", + "workspace.reload.error.paymentFailed": "workspace.reload.error.paymentFailed", + "Payment failed": "workspace.reload.error.paymentFailed", + "Payment failed.": "workspace.reload.error.paymentFailed", } as const satisfies Record<string, Key> export function formErrorReloadAmountMin(amount: number) { diff --git a/packages/console/app/src/routes/[...404].tsx b/packages/console/app/src/routes/[...404].tsx index 414491f9d..e20ec36fd 100644 --- a/packages/console/app/src/routes/[...404].tsx +++ b/packages/console/app/src/routes/[...404].tsx @@ -16,8 +16,8 @@ export default function NotFound() { <div data-component="content"> <section data-component="top"> <a href={language.route("/")} data-slot="logo-link"> - <img data-slot="logo light" src={logoLight} alt="opencode logo light" /> - <img data-slot="logo dark" src={logoDark} alt="opencode logo dark" /> + <img data-slot="logo light" src={logoLight} alt={i18n.t("notFound.logoLightAlt")} /> + <img data-slot="logo dark" src={logoDark} alt={i18n.t("notFound.logoDarkAlt")} /> </a> <h1 data-slot="title">{i18n.t("notFound.heading")}</h1> </section> diff --git a/packages/console/app/src/routes/api/enterprise.ts b/packages/console/app/src/routes/api/enterprise.ts index 6776a7b3c..27e2dc493 100644 --- a/packages/console/app/src/routes/api/enterprise.ts +++ b/packages/console/app/src/routes/api/enterprise.ts @@ -1,5 +1,7 @@ import type { APIEvent } from "@solidjs/start/server" import { AWS } from "@opencode-ai/console-core/aws.js" +import { i18n } from "~/i18n" +import { localeFromRequest } from "~/lib/language" interface EnterpriseFormData { name: string @@ -9,18 +11,19 @@ interface EnterpriseFormData { } export async function POST(event: APIEvent) { + const dict = i18n(localeFromRequest(event.request)) try { const body = (await event.request.json()) as EnterpriseFormData // Validate required fields if (!body.name || !body.role || !body.email || !body.message) { - return Response.json({ error: "All fields are required" }, { status: 400 }) + return Response.json({ error: dict["enterprise.form.error.allFieldsRequired"] }, { status: 400 }) } // Validate email format const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ if (!emailRegex.test(body.email)) { - return Response.json({ error: "Invalid email format" }, { status: 400 }) + return Response.json({ error: dict["enterprise.form.error.invalidEmailFormat"] }, { status: 400 }) } // Create email content @@ -39,9 +42,9 @@ ${body.email}`.trim() replyTo: body.email, }) - return Response.json({ success: true, message: "Form submitted successfully" }, { status: 200 }) + return Response.json({ success: true, message: dict["enterprise.form.success.submitted"] }, { status: 200 }) } catch (error) { console.error("Error processing enterprise form:", error) - return Response.json({ error: "Internal server error" }, { status: 500 }) + return Response.json({ error: dict["enterprise.form.error.internalServer"] }, { status: 500 }) } } diff --git a/packages/console/app/src/routes/auth/[...callback].ts b/packages/console/app/src/routes/auth/[...callback].ts index 664f6cc6d..00bb89406 100644 --- a/packages/console/app/src/routes/auth/[...callback].ts +++ b/packages/console/app/src/routes/auth/[...callback].ts @@ -2,15 +2,17 @@ import { redirect } from "@solidjs/router" import type { APIEvent } from "@solidjs/start/server" import { AuthClient } from "~/context/auth" import { useAuthSession } from "~/context/auth" +import { i18n } from "~/i18n" import { localeFromRequest, route } from "~/lib/language" export async function GET(input: APIEvent) { const url = new URL(input.request.url) const locale = localeFromRequest(input.request) + const dict = i18n(locale) try { const code = url.searchParams.get("code") - if (!code) throw new Error("No code found") + if (!code) throw new Error(dict["auth.callback.error.codeMissing"]) const result = await AuthClient.exchange(code, `${url.origin}${url.pathname}`) if (result.err) throw new Error(result.err.message) const decoded = AuthClient.decode(result.tokens.access, {} as any) diff --git a/packages/console/app/src/routes/bench/submission.ts b/packages/console/app/src/routes/bench/submission.ts index 94639439b..969ff1659 100644 --- a/packages/console/app/src/routes/bench/submission.ts +++ b/packages/console/app/src/routes/bench/submission.ts @@ -2,6 +2,8 @@ import type { APIEvent } from "@solidjs/start/server" import { Database } from "@opencode-ai/console-core/drizzle/index.js" import { BenchmarkTable } from "@opencode-ai/console-core/schema/benchmark.sql.js" import { Identifier } from "@opencode-ai/console-core/identifier.js" +import { i18n } from "~/i18n" +import { localeFromRequest } from "~/lib/language" interface SubmissionBody { model: string @@ -10,10 +12,11 @@ interface SubmissionBody { } export async function POST(event: APIEvent) { + const dict = i18n(localeFromRequest(event.request)) const body = (await event.request.json()) as SubmissionBody if (!body.model || !body.agent || !body.result) { - return Response.json({ error: "All fields are required" }, { status: 400 }) + return Response.json({ error: dict["bench.submission.error.allFieldsRequired"] }, { status: 400 }) } await Database.use((tx) => diff --git a/packages/console/app/src/routes/brand/index.tsx b/packages/console/app/src/routes/brand/index.tsx index 9140462c7..af89f4985 100644 --- a/packages/console/app/src/routes/brand/index.tsx +++ b/packages/console/app/src/routes/brand/index.tsx @@ -33,6 +33,7 @@ const brandAssets = "/opencode-brand-assets.zip" export default function Brand() { const i18n = useI18n() + const alt = i18n.t("brand.meta.description") const downloadFile = async (url: string, filename: string) => { try { const response = await fetch(url) @@ -88,7 +89,7 @@ export default function Brand() { <div data-component="brand-grid"> <div> - <img src={previewLogoLight} alt="OpenCode brand guidelines" /> + <img src={previewLogoLight} alt={alt} /> <div data-component="actions"> <button onClick={() => downloadFile(logoLightPng, "opencode-logo-light.png")}> PNG @@ -115,7 +116,7 @@ export default function Brand() { </div> </div> <div> - <img src={previewLogoDark} alt="OpenCode brand guidelines" /> + <img src={previewLogoDark} alt={alt} /> <div data-component="actions"> <button onClick={() => downloadFile(logoDarkPng, "opencode-logo-dark.png")}> PNG @@ -142,7 +143,7 @@ export default function Brand() { </div> </div> <div> - <img src={previewLogoLightSquare} alt="OpenCode brand guidelines" /> + <img src={previewLogoLightSquare} alt={alt} /> <div data-component="actions"> <button onClick={() => downloadFile(logoLightSquarePng, "opencode-logo-light-square.png")}> PNG @@ -169,7 +170,7 @@ export default function Brand() { </div> </div> <div> - <img src={previewLogoDarkSquare} alt="OpenCode brand guidelines" /> + <img src={previewLogoDarkSquare} alt={alt} /> <div data-component="actions"> <button onClick={() => downloadFile(logoDarkSquarePng, "opencode-logo-dark-square.png")}> PNG @@ -196,7 +197,7 @@ export default function Brand() { </div> </div> <div> - <img src={previewWordmarkLight} alt="OpenCode brand guidelines" /> + <img src={previewWordmarkLight} alt={alt} /> <div data-component="actions"> <button onClick={() => downloadFile(wordmarkLightPng, "opencode-wordmark-light.png")}> PNG @@ -223,7 +224,7 @@ export default function Brand() { </div> </div> <div> - <img src={previewWordmarkDark} alt="OpenCode brand guidelines" /> + <img src={previewWordmarkDark} alt={alt} /> <div data-component="actions"> <button onClick={() => downloadFile(wordmarkDarkPng, "opencode-wordmark-dark.png")}> PNG @@ -250,7 +251,7 @@ export default function Brand() { </div> </div> <div> - <img src={previewWordmarkSimpleLight} alt="OpenCode brand guidelines" /> + <img src={previewWordmarkSimpleLight} alt={alt} /> <div data-component="actions"> <button onClick={() => downloadFile(wordmarkSimpleLightPng, "opencode-wordmark-simple-light.png")}> PNG @@ -277,7 +278,7 @@ export default function Brand() { </div> </div> <div> - <img src={previewWordmarkSimpleDark} alt="OpenCode brand guidelines" /> + <img src={previewWordmarkSimpleDark} alt={alt} /> <div data-component="actions"> <button onClick={() => downloadFile(wordmarkSimpleDarkPng, "opencode-wordmark-simple-dark.png")}> PNG diff --git a/packages/console/app/src/routes/download/[channel]/[platform].ts b/packages/console/app/src/routes/download/[channel]/[platform].ts index 9a5284263..e9b3f23e7 100644 --- a/packages/console/app/src/routes/download/[channel]/[platform].ts +++ b/packages/console/app/src/routes/download/[channel]/[platform].ts @@ -19,7 +19,7 @@ const downloadNames: Record<string, string> = { export async function GET({ params: { platform, channel } }: APIEvent) { const assetName = assetNames[platform] - if (!assetName) return new Response("Not Found", { status: 404 }) + if (!assetName) return new Response(null, { status: 404 }) const resp = await fetch( `https://github.com/anomalyco/${channel === "stable" ? "opencode" : "opencode-beta"}/releases/latest/download/${assetName}`, diff --git a/packages/console/app/src/routes/stripe/webhook.ts b/packages/console/app/src/routes/stripe/webhook.ts index 47ca442ec..95cd9da21 100644 --- a/packages/console/app/src/routes/stripe/webhook.ts +++ b/packages/console/app/src/routes/stripe/webhook.ts @@ -306,7 +306,7 @@ export async function POST(input: APIEvent) { .update(BillingTable) .set({ reload: false, - reloadError: errorMessage ?? "Payment failed.", + reloadError: errorMessage ?? "workspace.reload.error.paymentFailed", timeReloadError: sql`now()`, }) .where(eq(BillingTable.workspaceID, Actor.workspace())), diff --git a/packages/console/app/src/routes/temp.tsx b/packages/console/app/src/routes/temp.tsx index ac506928e..4eed47857 100644 --- a/packages/console/app/src/routes/temp.tsx +++ b/packages/console/app/src/routes/temp.tsx @@ -47,8 +47,8 @@ export default function Home() { <div data-component="content"> <section data-component="top"> - <img data-slot="logo light" src={logoLight} alt="opencode logo light" /> - <img data-slot="logo dark" src={logoDark} alt="opencode logo dark" /> + <img data-slot="logo light" src={logoLight} alt={i18n.t("temp.logoLightAlt")} /> + <img data-slot="logo dark" src={logoDark} alt={i18n.t("temp.logoDarkAlt")} /> <h1 data-slot="title">{i18n.t("temp.hero.title")}</h1> <div data-slot="login"> <a href="/auth">{i18n.t("temp.zen")}</a> diff --git a/packages/console/app/src/routes/workspace/[id]/billing/lite-section.tsx b/packages/console/app/src/routes/workspace/[id]/billing/lite-section.tsx index 395d008e1..f67775d79 100644 --- a/packages/console/app/src/routes/workspace/[id]/billing/lite-section.tsx +++ b/packages/console/app/src/routes/workspace/[id]/billing/lite-section.tsx @@ -12,6 +12,7 @@ import { queryBillingInfo } from "../../common" import styles from "./lite-section.module.css" import { useI18n } from "~/context/i18n" import { useLanguage } from "~/context/language" +import { formError } from "~/lib/form-error" const queryLiteSubscription = query(async (workspaceID: string) => { "use server" @@ -114,7 +115,7 @@ const createSessionUrl = action(async (workspaceID: string, returnUrl: string) = const setLiteUseBalance = action(async (form: FormData) => { "use server" const workspaceID = form.get("workspaceID")?.toString() - if (!workspaceID) return { error: "Workspace ID is required" } + if (!workspaceID) return { error: formError.workspaceRequired } const useBalance = form.get("useBalance")?.toString() === "true" return json( diff --git a/packages/console/app/src/routes/workspace/[id]/billing/reload-section.tsx b/packages/console/app/src/routes/workspace/[id]/billing/reload-section.tsx index 7084be133..90c9d7a2e 100644 --- a/packages/console/app/src/routes/workspace/[id]/billing/reload-section.tsx +++ b/packages/console/app/src/routes/workspace/[id]/billing/reload-section.tsx @@ -202,7 +202,8 @@ export function ReloadSection() { minute: "2-digit", second: "2-digit", })} - . {i18n.t("workspace.reload.reason")} {billingInfo()?.reloadError?.replace(/\.$/, "")}.{" "} + . {i18n.t("workspace.reload.reason")}{" "} + {localizeError(i18n.t, billingInfo()?.reloadError ?? undefined).replace(/\.$/, "")}.{" "} {i18n.t("workspace.reload.updatePaymentMethod")} </p> <form action={reload} method="post" data-slot="create-form"> diff --git a/packages/console/app/src/routes/zen/util/handler.ts b/packages/console/app/src/routes/zen/util/handler.ts index 3f6d69bf2..d3a25c5f6 100644 --- a/packages/console/app/src/routes/zen/util/handler.ts +++ b/packages/console/app/src/routes/zen/util/handler.ts @@ -35,6 +35,8 @@ import { createTrialLimiter } from "./trialLimiter" import { createStickyTracker } from "./stickyProviderTracker" import { LiteData } from "@opencode-ai/console-core/lite.js" import { Resource } from "@opencode-ai/console-resource" +import { i18n, type Key } from "~/i18n" +import { localeFromRequest } from "~/lib/language" type ZenData = Awaited<ReturnType<typeof ZenData.list>> type RetryOptions = { @@ -43,6 +45,15 @@ type RetryOptions = { } type BillingSource = "anonymous" | "free" | "byok" | "subscription" | "lite" | "balance" +function resolve(text: string, params?: Record<string, string | number>) { + if (!params) return text + return text.replace(/\{\{(\w+)\}\}/g, (raw, key) => { + const value = params[key] + if (value === undefined || value === null) return raw + return String(value) + }) +} + export async function handler( input: APIEvent, opts: { @@ -60,6 +71,8 @@ export async function handler( const MAX_FAILOVER_RETRIES = 3 const MAX_429_RETRIES = 3 + const dict = i18n(localeFromRequest(input.request)) + const t = (key: Key, params?: Record<string, string | number>) => resolve(dict[key], params) const ADMIN_WORKSPACES = [ "wrk_01K46JDFR0E75SG2Q8K172KF3Y", // frank "wrk_01K6W1A3VE0KMNVSCQT43BG2SX", // opencode bench @@ -86,7 +99,7 @@ export async function handler( const dataDumper = createDataDumper(sessionId, requestId, projectId) const trialLimiter = createTrialLimiter(modelInfo.trial, ip, ocClient) const isTrial = await trialLimiter?.isTrial() - const rateLimiter = createRateLimiter(modelInfo.rateLimit, ip, input.request.headers) + const rateLimiter = createRateLimiter(modelInfo.rateLimit, ip, input.request) await rateLimiter?.check() const stickyTracker = createStickyTracker(modelInfo.stickyProvider, sessionId) const stickyProvider = await stickyTracker?.get() @@ -359,14 +372,20 @@ export async function handler( } function validateModel(zenData: ZenData, reqModel: string) { - if (!(reqModel in zenData.models)) throw new ModelError(`Model ${reqModel} not supported`) + if (!(reqModel in zenData.models)) throw new ModelError(t("zen.api.error.modelNotSupported", { model: reqModel })) const modelId = reqModel as keyof typeof zenData.models const modelData = Array.isArray(zenData.models[modelId]) ? zenData.models[modelId].find((model) => opts.format === model.formatFilter) : zenData.models[modelId] - if (!modelData) throw new ModelError(`Model ${reqModel} not supported for format ${opts.format}`) + if (!modelData) + throw new ModelError( + t("zen.api.error.modelFormatNotSupported", { + model: reqModel, + format: opts.format, + }), + ) logger.metric({ model: modelId }) @@ -418,8 +437,9 @@ export async function handler( return modelInfo.providers.find((provider) => provider.id === modelInfo.fallbackProvider) })() - if (!modelProvider) throw new ModelError("No provider available") - if (!(modelProvider.id in zenData.providers)) throw new ModelError(`Provider ${modelProvider.id} not supported`) + if (!modelProvider) throw new ModelError(t("zen.api.error.noProviderAvailable")) + if (!(modelProvider.id in zenData.providers)) + throw new ModelError(t("zen.api.error.providerNotSupported", { provider: modelProvider.id })) return { ...modelProvider, @@ -439,7 +459,7 @@ export async function handler( const apiKey = opts.parseApiKey(input.request.headers) if (!apiKey || apiKey === "public") { if (modelInfo.allowAnonymous) return - throw new AuthError("Missing API key.") + throw new AuthError(t("zen.api.error.missingApiKey")) } const data = await Database.use((tx) => @@ -520,13 +540,13 @@ export async function handler( .then((rows) => rows[0]), ) - if (!data) throw new AuthError("Invalid API key.") + if (!data) throw new AuthError(t("zen.api.error.invalidApiKey")) if ( modelInfo.id.startsWith("alpha-") && Resource.App.stage === "production" && !ADMIN_WORKSPACES.includes(data.workspaceID) ) - throw new AuthError(`Model ${modelInfo.id} not supported`) + throw new AuthError(t("zen.api.error.modelNotSupported", { model: modelInfo.id })) logger.metric({ api_key: data.apiKey, @@ -590,7 +610,9 @@ export async function handler( }) if (result.status === "rate-limited") throw new SubscriptionUsageLimitError( - `Subscription quota exceeded. Retry in ${formatRetryTime(result.resetInSec)}.`, + t("zen.api.error.subscriptionQuotaExceeded", { + retryIn: formatRetryTime(result.resetInSec), + }), result.resetInSec, ) } @@ -606,7 +628,9 @@ export async function handler( }) if (result.status === "rate-limited") throw new SubscriptionUsageLimitError( - `Subscription quota exceeded. Retry in ${formatRetryTime(result.resetInSec)}.`, + t("zen.api.error.subscriptionQuotaExceeded", { + retryIn: formatRetryTime(result.resetInSec), + }), result.resetInSec, ) } @@ -632,7 +656,7 @@ export async function handler( }) if (result.status === "rate-limited") throw new SubscriptionUsageLimitError( - `Subscription quota exceeded. You can continue using free models.`, + t("zen.api.error.subscriptionQuotaExceededUseFreeModels"), result.resetInSec, ) } @@ -647,7 +671,7 @@ export async function handler( }) if (result.status === "rate-limited") throw new SubscriptionUsageLimitError( - `Subscription quota exceeded. You can continue using free models.`, + t("zen.api.error.subscriptionQuotaExceededUseFreeModels"), result.resetInSec, ) } @@ -662,7 +686,7 @@ export async function handler( }) if (result.status === "rate-limited") throw new SubscriptionUsageLimitError( - `Subscription quota exceeded. You can continue using free models.`, + t("zen.api.error.subscriptionQuotaExceededUseFreeModels"), result.resetInSec, ) } @@ -675,14 +699,10 @@ export async function handler( // Validate pay as you go billing const billing = authInfo.billing - if (!billing.paymentMethodID) - throw new CreditsError( - `No payment method. Add a payment method here: https://opencode.ai/workspace/${authInfo.workspaceID}/billing`, - ) - if (billing.balance <= 0) - throw new CreditsError( - `Insufficient balance. Manage your billing here: https://opencode.ai/workspace/${authInfo.workspaceID}/billing`, - ) + const billingUrl = `https://opencode.ai/workspace/${authInfo.workspaceID}/billing` + const membersUrl = `https://opencode.ai/workspace/${authInfo.workspaceID}/members` + if (!billing.paymentMethodID) throw new CreditsError(t("zen.api.error.noPaymentMethod", { billingUrl })) + if (billing.balance <= 0) throw new CreditsError(t("zen.api.error.insufficientBalance", { billingUrl })) const now = new Date() const currentYear = now.getUTCFullYear() @@ -696,7 +716,10 @@ export async function handler( currentMonth === billing.timeMonthlyUsageUpdated.getUTCMonth() ) throw new MonthlyLimitError( - `Your workspace has reached its monthly spending limit of $${billing.monthlyLimit}. Manage your limits here: https://opencode.ai/workspace/${authInfo.workspaceID}/billing`, + t("zen.api.error.workspaceMonthlyLimitReached", { + amount: billing.monthlyLimit, + billingUrl, + }), ) if ( @@ -708,7 +731,10 @@ export async function handler( currentMonth === authInfo.user.timeMonthlyUsageUpdated.getUTCMonth() ) throw new UserLimitError( - `You have reached your monthly spending limit of $${authInfo.user.monthlyLimit}. Manage your limits here: https://opencode.ai/workspace/${authInfo.workspaceID}/members`, + t("zen.api.error.userMonthlyLimitReached", { + amount: authInfo.user.monthlyLimit, + membersUrl, + }), ) return "balance" @@ -716,7 +742,7 @@ export async function handler( function validateModelSettings(authInfo: AuthInfo) { if (!authInfo) return - if (authInfo.isDisabled) throw new ModelError("Model is disabled") + if (authInfo.isDisabled) throw new ModelError(t("zen.api.error.modelDisabled")) } function updateProviderKey(authInfo: AuthInfo, providerInfo: ProviderInfo) { diff --git a/packages/console/app/src/routes/zen/util/rateLimiter.ts b/packages/console/app/src/routes/zen/util/rateLimiter.ts index 5e4f31e67..6325a7b4d 100644 --- a/packages/console/app/src/routes/zen/util/rateLimiter.ts +++ b/packages/console/app/src/routes/zen/util/rateLimiter.ts @@ -3,11 +3,14 @@ import { IpRateLimitTable } from "@opencode-ai/console-core/schema/ip.sql.js" import { FreeUsageLimitError } from "./error" import { logger } from "./logger" import { ZenData } from "@opencode-ai/console-core/model.js" +import { i18n } from "~/i18n" +import { localeFromRequest } from "~/lib/language" -export function createRateLimiter(limit: ZenData.RateLimit | undefined, rawIp: string, headers: Headers) { +export function createRateLimiter(limit: ZenData.RateLimit | undefined, rawIp: string, request: Request) { if (!limit) return + const dict = i18n(localeFromRequest(request)) - const limitValue = limit.checkHeader && !headers.get(limit.checkHeader) ? limit.fallbackValue! : limit.value + const limitValue = limit.checkHeader && !request.headers.get(limit.checkHeader) ? limit.fallbackValue! : limit.value const ip = !rawIp.length ? "unknown" : rawIp const now = Date.now() @@ -36,7 +39,7 @@ export function createRateLimiter(limit: ZenData.RateLimit | undefined, rawIp: s logger.debug(`rate limit total: ${total}`) if (total >= limitValue) throw new FreeUsageLimitError( - `Rate limit exceeded. Please try again later.`, + dict["zen.api.error.rateLimitExceeded"], limit.period === "day" ? getRetryAfterDay(now) : getRetryAfterHour(rows, intervals, limitValue, now), ) }, |
