2
0
Adam 1 сар өмнө
parent
commit
6ef3af73df
65 өөрчлөгдсөн 1096 нэмэгдсэн , 71 устгасан
  1. 6 4
      packages/app/src/components/dialog-release-notes.tsx
  2. 1 1
      packages/app/src/components/dialog-select-file.tsx
  3. 1 1
      packages/app/src/components/session/session-header.tsx
  4. 5 3
      packages/app/src/components/settings-providers.tsx
  5. 9 1
      packages/app/src/context/global-sync.tsx
  6. 14 3
      packages/app/src/context/global-sync/bootstrap.ts
  7. 14 0
      packages/app/src/i18n/ar.ts
  8. 14 0
      packages/app/src/i18n/br.ts
  9. 14 0
      packages/app/src/i18n/bs.ts
  10. 14 0
      packages/app/src/i18n/da.ts
  11. 14 0
      packages/app/src/i18n/de.ts
  12. 16 0
      packages/app/src/i18n/en.ts
  13. 14 0
      packages/app/src/i18n/es.ts
  14. 14 0
      packages/app/src/i18n/fr.ts
  15. 14 0
      packages/app/src/i18n/ja.ts
  16. 14 0
      packages/app/src/i18n/ko.ts
  17. 14 0
      packages/app/src/i18n/no.ts
  18. 14 0
      packages/app/src/i18n/pl.ts
  19. 14 0
      packages/app/src/i18n/ru.ts
  20. 14 0
      packages/app/src/i18n/th.ts
  21. 14 0
      packages/app/src/i18n/tr.ts
  22. 14 0
      packages/app/src/i18n/zh.ts
  23. 14 0
      packages/app/src/i18n/zht.ts
  24. 22 5
      packages/app/src/utils/server-errors.ts
  25. 13 5
      packages/app/src/utils/time.ts
  26. 29 1
      packages/desktop/src/cli.ts
  27. 33 0
      packages/desktop/src/i18n/ar.ts
  28. 34 0
      packages/desktop/src/i18n/br.ts
  29. 34 0
      packages/desktop/src/i18n/bs.ts
  30. 33 0
      packages/desktop/src/i18n/da.ts
  31. 34 0
      packages/desktop/src/i18n/de.ts
  32. 34 0
      packages/desktop/src/i18n/en.ts
  33. 34 0
      packages/desktop/src/i18n/es.ts
  34. 34 0
      packages/desktop/src/i18n/fr.ts
  35. 34 0
      packages/desktop/src/i18n/ja.ts
  36. 33 0
      packages/desktop/src/i18n/ko.ts
  37. 33 0
      packages/desktop/src/i18n/no.ts
  38. 34 0
      packages/desktop/src/i18n/pl.ts
  39. 34 0
      packages/desktop/src/i18n/ru.ts
  40. 33 0
      packages/desktop/src/i18n/zh.ts
  41. 33 0
      packages/desktop/src/i18n/zht.ts
  42. 1 1
      packages/desktop/src/index.tsx
  43. 11 4
      packages/desktop/src/loading.tsx
  44. 18 18
      packages/desktop/src/menu.ts
  45. 2 1
      packages/enterprise/src/app.tsx
  46. 14 6
      packages/ui/src/components/message-part.tsx
  47. 3 1
      packages/ui/src/components/scroll-view.tsx
  48. 15 15
      packages/ui/src/components/session-review.tsx
  49. 11 0
      packages/ui/src/i18n/ar.ts
  50. 11 0
      packages/ui/src/i18n/br.ts
  51. 11 0
      packages/ui/src/i18n/bs.ts
  52. 11 0
      packages/ui/src/i18n/da.ts
  53. 11 0
      packages/ui/src/i18n/de.ts
  54. 12 1
      packages/ui/src/i18n/en.ts
  55. 11 0
      packages/ui/src/i18n/es.ts
  56. 11 0
      packages/ui/src/i18n/fr.ts
  57. 11 0
      packages/ui/src/i18n/ja.ts
  58. 11 0
      packages/ui/src/i18n/ko.ts
  59. 11 0
      packages/ui/src/i18n/no.ts
  60. 11 0
      packages/ui/src/i18n/pl.ts
  61. 11 0
      packages/ui/src/i18n/ru.ts
  62. 11 0
      packages/ui/src/i18n/th.ts
  63. 11 0
      packages/ui/src/i18n/tr.ts
  64. 11 0
      packages/ui/src/i18n/zh.ts
  65. 11 0
      packages/ui/src/i18n/zht.ts

+ 6 - 4
packages/app/src/components/dialog-release-notes.tsx

@@ -2,6 +2,7 @@ import { createSignal } from "solid-js"
 import { Dialog } from "@opencode-ai/ui/dialog"
 import { Button } from "@opencode-ai/ui/button"
 import { useDialog } from "@opencode-ai/ui/context/dialog"
+import { useLanguage } from "@/context/language"
 import { useSettings } from "@/context/settings"
 
 export type Highlight = {
@@ -16,6 +17,7 @@ export type Highlight = {
 
 export function DialogReleaseNotes(props: { highlights: Highlight[] }) {
   const dialog = useDialog()
+  const language = useLanguage()
   const settings = useSettings()
   const [index, setIndex] = createSignal(0)
 
@@ -83,16 +85,16 @@ export function DialogReleaseNotes(props: { highlights: Highlight[] }) {
             <div class="flex flex-col items-start gap-3">
               {isLast() ? (
                 <Button variant="primary" size="large" onClick={handleClose}>
-                  Get started
+                  {language.t("dialog.releaseNotes.action.getStarted")}
                 </Button>
               ) : (
                 <Button variant="secondary" size="large" onClick={handleNext}>
-                  Next
+                  {language.t("dialog.releaseNotes.action.next")}
                 </Button>
               )}
 
               <Button variant="ghost" size="small" onClick={handleDisable}>
-                Don't show these in the future
+                {language.t("dialog.releaseNotes.action.hideFuture")}
               </Button>
             </div>
 
@@ -128,7 +130,7 @@ export function DialogReleaseNotes(props: { highlights: Highlight[] }) {
             {feature()!.media!.type === "image" ? (
               <img
                 src={feature()!.media!.src}
-                alt={feature()!.media!.alt ?? feature()?.title ?? "Release preview"}
+                alt={feature()!.media!.alt ?? feature()?.title ?? language.t("dialog.releaseNotes.media.alt")}
                 class="w-full h-full object-cover"
               />
             ) : (

+ 1 - 1
packages/app/src/components/dialog-select-file.tsx

@@ -449,7 +449,7 @@ export function DialogSelectFile(props: { mode?: DialogSelectFileMode; onOpenFil
                 </div>
                 <Show when={item.updated}>
                   <span class="text-12-regular text-text-weak whitespace-nowrap ml-2">
-                    {getRelativeTime(new Date(item.updated!).toISOString())}
+                    {getRelativeTime(new Date(item.updated!).toISOString(), language.t)}
                   </span>
                 </Show>
               </div>

+ 1 - 1
packages/app/src/components/session/session-header.tsx

@@ -430,7 +430,7 @@ export function SessionHeader() {
                               <Spinner class="size-3.5 text-icon-base" />
                             </Show>
                           </div>
-                          <span class="text-12-regular text-text-strong">Open</span>
+                          <span class="text-12-regular text-text-strong">{language.t("common.open")}</span>
                         </Button>
                         <div class="self-stretch w-px bg-border-weak-base" />
                         <DropdownMenu

+ 5 - 3
packages/app/src/components/settings-providers.tsx

@@ -162,7 +162,7 @@ export const SettingsProviders: Component = () => {
                       when={canDisconnect(item)}
                       fallback={
                         <span class="text-14-regular text-text-base opacity-0 group-hover:opacity-100 transition-opacity duration-200 pr-3 cursor-default">
-                          Connected from your environment variables
+                          {language.t("settings.providers.connected.environmentDescription")}
                         </span>
                       }
                     >
@@ -229,10 +229,12 @@ export const SettingsProviders: Component = () => {
               <div class="flex flex-col min-w-0">
                 <div class="flex flex-wrap items-center gap-x-3 gap-y-1">
                   <ProviderIcon id={icon("synthetic")} class="size-5 shrink-0 icon-strong-base" />
-                  <span class="text-14-medium text-text-strong">Custom provider</span>
+                  <span class="text-14-medium text-text-strong">{language.t("provider.custom.title")}</span>
                   <Tag>{language.t("settings.providers.tag.custom")}</Tag>
                 </div>
-                <span class="text-12-regular text-text-weak pl-8">Add an OpenAI-compatible provider by base URL.</span>
+                <span class="text-12-regular text-text-weak pl-8">
+                  {language.t("settings.providers.custom.description")}
+                </span>
               </div>
               <Button
                 size="large"

+ 9 - 1
packages/app/src/context/global-sync.tsx

@@ -204,7 +204,10 @@ function createGlobalSync() {
         showToast({
           variant: "error",
           title: language.t("toast.session.listFailed.title", { project }),
-          description: formatServerError(err),
+          description: formatServerError(err, {
+            unknown: language.t("error.chain.unknown"),
+            invalidConfiguration: language.t("error.server.invalidConfiguration"),
+          }),
         })
       })
 
@@ -234,6 +237,8 @@ function createGlobalSync() {
         setStore: child[1],
         vcsCache: cache,
         loadSessions,
+        unknownError: language.t("error.chain.unknown"),
+        invalidConfigurationError: language.t("error.server.invalidConfiguration"),
       })
     })()
 
@@ -308,6 +313,9 @@ function createGlobalSync() {
         url: globalSDK.url,
       }),
       requestFailedTitle: language.t("common.requestFailed"),
+      unknownError: language.t("error.chain.unknown"),
+      invalidConfigurationError: language.t("error.server.invalidConfiguration"),
+      formatMoreCount: (count) => language.t("common.moreCountSuffix", { count }),
       setGlobalStore,
     })
   }

+ 14 - 3
packages/app/src/context/global-sync/bootstrap.ts

@@ -36,6 +36,9 @@ export async function bootstrapGlobal(input: {
   connectErrorTitle: string
   connectErrorDescription: string
   requestFailedTitle: string
+  unknownError: string
+  invalidConfigurationError: string
+  formatMoreCount: (count: number) => string
   setGlobalStore: SetStoreFunction<GlobalStore>
 }) {
   const health = await input.globalSDK.global
@@ -88,8 +91,11 @@ export async function bootstrapGlobal(input: {
   const results = await Promise.allSettled(tasks)
   const errors = results.filter((r): r is PromiseRejectedResult => r.status === "rejected").map((r) => r.reason)
   if (errors.length) {
-    const message = errors[0] instanceof Error ? errors[0].message : String(errors[0])
-    const more = errors.length > 1 ? ` (+${errors.length - 1} more)` : ""
+    const message = formatServerError(errors[0], {
+      unknown: input.unknownError,
+      invalidConfiguration: input.invalidConfigurationError,
+    })
+    const more = errors.length > 1 ? input.formatMoreCount(errors.length - 1) : ""
     showToast({
       variant: "error",
       title: input.requestFailedTitle,
@@ -116,6 +122,8 @@ export async function bootstrapDirectory(input: {
   setStore: SetStoreFunction<State>
   vcsCache: VcsCache
   loadSessions: (directory: string) => Promise<void> | void
+  unknownError: string
+  invalidConfigurationError: string
 }) {
   if (input.store.status !== "complete") input.setStore("status", "loading")
 
@@ -137,7 +145,10 @@ export async function bootstrapDirectory(input: {
     showToast({
       variant: "error",
       title: `Failed to reload ${project}`,
-      description: formatServerError(err),
+      description: formatServerError(err, {
+        unknown: input.unknownError,
+        invalidConfiguration: input.invalidConfigurationError,
+      }),
     })
     input.setStore("status", "partial")
     return

+ 14 - 0
packages/app/src/i18n/ar.ts

@@ -734,4 +734,18 @@ export const dict = {
   "workspace.reset.archived.one": "ستتم أرشفة جلسة واحدة.",
   "workspace.reset.archived.many": "ستتم أرشفة {{count}} جلسات.",
   "workspace.reset.note": "سيؤدي هذا إلى إعادة تعيين مساحة العمل لتتطابق مع الفرع الافتراضي.",
+  "common.open": "فتح",
+  "dialog.releaseNotes.action.getStarted": "البدء",
+  "dialog.releaseNotes.action.next": "التالي",
+  "dialog.releaseNotes.action.hideFuture": "عدم إظهار هذا في المستقبل",
+  "dialog.releaseNotes.media.alt": "معاينة الإصدار",
+  "toast.project.reloadFailed.title": "فشل في إعادة تحميل {{project}}",
+  "error.server.invalidConfiguration": "تكوين غير صالح",
+  "common.moreCountSuffix": " (+{{count}} إضافي)",
+  "common.time.justNow": "الآن",
+  "common.time.minutesAgo.short": "قبل {{count}} د",
+  "common.time.hoursAgo.short": "قبل {{count}} س",
+  "common.time.daysAgo.short": "قبل {{count}} ي",
+  "settings.providers.connected.environmentDescription": "متصل من متغيرات البيئة الخاصة بك",
+  "settings.providers.custom.description": "أضف مزود متوافق مع OpenAI بواسطة عنوان URL الأساسي.",
 }

+ 14 - 0
packages/app/src/i18n/br.ts

@@ -742,4 +742,18 @@ export const dict = {
   "workspace.reset.archived.one": "1 sessão será arquivada.",
   "workspace.reset.archived.many": "{{count}} sessões serão arquivadas.",
   "workspace.reset.note": "Isso redefinirá o espaço de trabalho para corresponder ao branch padrão.",
+  "common.open": "Abrir",
+  "dialog.releaseNotes.action.getStarted": "Começar",
+  "dialog.releaseNotes.action.next": "Próximo",
+  "dialog.releaseNotes.action.hideFuture": "Não mostrar isso no futuro",
+  "dialog.releaseNotes.media.alt": "Prévia do lançamento",
+  "toast.project.reloadFailed.title": "Falha ao recarregar {{project}}",
+  "error.server.invalidConfiguration": "Configuração inválida",
+  "common.moreCountSuffix": " (+{{count}} mais)",
+  "common.time.justNow": "Agora mesmo",
+  "common.time.minutesAgo.short": "{{count}}m atrás",
+  "common.time.hoursAgo.short": "{{count}}h atrás",
+  "common.time.daysAgo.short": "{{count}}d atrás",
+  "settings.providers.connected.environmentDescription": "Conectado a partir de suas variáveis de ambiente",
+  "settings.providers.custom.description": "Adicionar um provedor compatível com a OpenAI através do URL base.",
 }

+ 14 - 0
packages/app/src/i18n/bs.ts

@@ -819,4 +819,18 @@ export const dict = {
   "workspace.reset.archived.one": "1 sesija će biti arhivirana.",
   "workspace.reset.archived.many": "Biće arhivirano {{count}} sesija.",
   "workspace.reset.note": "Ovo će resetovati radni prostor da odgovara podrazumijevanoj grani.",
+  "common.open": "Otvori",
+  "dialog.releaseNotes.action.getStarted": "Započni",
+  "dialog.releaseNotes.action.next": "Sljedeće",
+  "dialog.releaseNotes.action.hideFuture": "Ne prikazuj ovo u budućnosti",
+  "dialog.releaseNotes.media.alt": "Pregled izdanja",
+  "toast.project.reloadFailed.title": "Nije uspjelo ponovno učitavanje {{project}}",
+  "error.server.invalidConfiguration": "Nevažeća konfiguracija",
+  "common.moreCountSuffix": " (+{{count}} više)",
+  "common.time.justNow": "Upravo sada",
+  "common.time.minutesAgo.short": "prije {{count}} min",
+  "common.time.hoursAgo.short": "prije {{count}} h",
+  "common.time.daysAgo.short": "prije {{count}} d",
+  "settings.providers.connected.environmentDescription": "Povezano sa vašim varijablama okruženja",
+  "settings.providers.custom.description": "Dodajte provajdera kompatibilnog s OpenAI putem osnovnog URL-a.",
 }

+ 14 - 0
packages/app/src/i18n/da.ts

@@ -813,4 +813,18 @@ export const dict = {
   "workspace.reset.archived.one": "1 session vil blive arkiveret.",
   "workspace.reset.archived.many": "{{count}} sessioner vil blive arkiveret.",
   "workspace.reset.note": "Dette vil nulstille arbejdsområdet til at matche hovedgrenen.",
+  "common.open": "Åbn",
+  "dialog.releaseNotes.action.getStarted": "Kom i gang",
+  "dialog.releaseNotes.action.next": "Næste",
+  "dialog.releaseNotes.action.hideFuture": "Vis ikke disse i fremtiden",
+  "dialog.releaseNotes.media.alt": "Forhåndsvisning af udgivelse",
+  "toast.project.reloadFailed.title": "Kunne ikke genindlæse {{project}}",
+  "error.server.invalidConfiguration": "Ugyldig konfiguration",
+  "common.moreCountSuffix": " (+{{count}} mere)",
+  "common.time.justNow": "Lige nu",
+  "common.time.minutesAgo.short": "{{count}}m siden",
+  "common.time.hoursAgo.short": "{{count}}t siden",
+  "common.time.daysAgo.short": "{{count}}d siden",
+  "settings.providers.connected.environmentDescription": "Tilsluttet fra dine miljøvariabler",
+  "settings.providers.custom.description": "Tilføj en OpenAI-kompatibel udbyder via basis-URL.",
 }

+ 14 - 0
packages/app/src/i18n/de.ts

@@ -751,4 +751,18 @@ export const dict = {
   "workspace.reset.archived.one": "1 Sitzung wird archiviert.",
   "workspace.reset.archived.many": "{{count}} Sitzungen werden archiviert.",
   "workspace.reset.note": "Dadurch wird der Arbeitsbereich auf den Standard-Branch zurückgesetzt.",
+  "common.open": "Öffnen",
+  "dialog.releaseNotes.action.getStarted": "Loslegen",
+  "dialog.releaseNotes.action.next": "Weiter",
+  "dialog.releaseNotes.action.hideFuture": "In Zukunft nicht mehr anzeigen",
+  "dialog.releaseNotes.media.alt": "Vorschau auf die Version",
+  "toast.project.reloadFailed.title": "Fehler beim Neuladen von {{project}}",
+  "error.server.invalidConfiguration": "Ungültige Konfiguration",
+  "common.moreCountSuffix": " (+{{count}} weitere)",
+  "common.time.justNow": "Gerade eben",
+  "common.time.minutesAgo.short": "vor {{count}} Min",
+  "common.time.hoursAgo.short": "vor {{count}} Std",
+  "common.time.daysAgo.short": "vor {{count}} Tg",
+  "settings.providers.connected.environmentDescription": "Verbunden aus Ihren Umgebungsvariablen",
+  "settings.providers.custom.description": "Fügen Sie einen OpenAI-kompatiblen Anbieter per Basis-URL hinzu.",
 } satisfies Partial<Record<Keys, string>>

+ 16 - 0
packages/app/src/i18n/en.ts

@@ -218,6 +218,7 @@ export const dict = {
   "common.loading": "Loading",
   "common.loading.ellipsis": "...",
   "common.cancel": "Cancel",
+  "common.open": "Open",
   "common.connect": "Connect",
   "common.disconnect": "Disconnect",
   "common.submit": "Submit",
@@ -347,6 +348,11 @@ export const dict = {
   "dialog.project.edit.worktree.startup.description": "Runs after creating a new workspace (worktree).",
   "dialog.project.edit.worktree.startup.placeholder": "e.g. bun install",
 
+  "dialog.releaseNotes.action.getStarted": "Get started",
+  "dialog.releaseNotes.action.next": "Next",
+  "dialog.releaseNotes.action.hideFuture": "Don't show these in the future",
+  "dialog.releaseNotes.media.alt": "Release preview",
+
   "context.breakdown.title": "Context Breakdown",
   "context.breakdown.note": 'Approximate breakdown of input tokens. "Other" includes tool definitions and overhead.',
   "context.breakdown.system": "System",
@@ -436,6 +442,7 @@ export const dict = {
   "toast.session.unshare.failed.description": "An error occurred while unsharing the session",
 
   "toast.session.listFailed.title": "Failed to load sessions for {{project}}",
+  "toast.project.reloadFailed.title": "Failed to reload {{project}}",
 
   "toast.update.title": "Update available",
   "toast.update.description": "A new version of OpenCode ({{version}}) is now available to install.",
@@ -460,6 +467,7 @@ export const dict = {
   "directory.error.invalidUrl": "Invalid directory in URL.",
 
   "error.chain.unknown": "Unknown error",
+  "error.server.invalidConfiguration": "Invalid configuration",
   "error.chain.causedBy": "Caused by:",
   "error.chain.apiError": "API error",
   "error.chain.status": "Status: {{status}}",
@@ -570,6 +578,7 @@ export const dict = {
 
   "common.closeTab": "Close tab",
   "common.dismiss": "Dismiss",
+  "common.moreCountSuffix": " (+{{count}} more)",
   "common.requestFailed": "Request failed",
   "common.moreOptions": "More options",
   "common.learnMore": "Learn more",
@@ -582,6 +591,11 @@ export const dict = {
   "common.loadMore": "Load more",
   "common.key.esc": "ESC",
 
+  "common.time.justNow": "Just now",
+  "common.time.minutesAgo.short": "{{count}}m ago",
+  "common.time.hoursAgo.short": "{{count}}h ago",
+  "common.time.daysAgo.short": "{{count}}d ago",
+
   "sidebar.menu.toggle": "Toggle menu",
   "sidebar.nav.projectsAndSessions": "Projects and sessions",
   "sidebar.settings": "Settings",
@@ -742,7 +756,9 @@ export const dict = {
   "settings.providers.description": "Provider settings will be configurable here.",
   "settings.providers.section.connected": "Connected providers",
   "settings.providers.connected.empty": "No connected providers",
+  "settings.providers.connected.environmentDescription": "Connected from your environment variables",
   "settings.providers.section.popular": "Popular providers",
+  "settings.providers.custom.description": "Add an OpenAI-compatible provider by base URL.",
   "settings.providers.tag.environment": "Environment",
   "settings.providers.tag.config": "Config",
   "settings.providers.tag.custom": "Custom",

+ 14 - 0
packages/app/src/i18n/es.ts

@@ -825,4 +825,18 @@ export const dict = {
   "workspace.reset.archived.one": "1 sesión será archivada.",
   "workspace.reset.archived.many": "{{count}} sesiones serán archivadas.",
   "workspace.reset.note": "Esto restablecerá el espacio de trabajo para coincidir con la rama predeterminada.",
+  "common.open": "Abrir",
+  "dialog.releaseNotes.action.getStarted": "Comenzar",
+  "dialog.releaseNotes.action.next": "Siguiente",
+  "dialog.releaseNotes.action.hideFuture": "No mostrar esto en el futuro",
+  "dialog.releaseNotes.media.alt": "Vista previa de la versión",
+  "toast.project.reloadFailed.title": "Error al recargar {{project}}",
+  "error.server.invalidConfiguration": "Configuración inválida",
+  "common.moreCountSuffix": " (+{{count}} más)",
+  "common.time.justNow": "Justo ahora",
+  "common.time.minutesAgo.short": "hace {{count}} min",
+  "common.time.hoursAgo.short": "hace {{count}} h",
+  "common.time.daysAgo.short": "hace {{count}} d",
+  "settings.providers.connected.environmentDescription": "Conectado desde tus variables de entorno",
+  "settings.providers.custom.description": "Añade un proveedor compatible con OpenAI por su URL base.",
 }

+ 14 - 0
packages/app/src/i18n/fr.ts

@@ -749,4 +749,18 @@ export const dict = {
   "workspace.reset.archived.one": "1 session sera archivée.",
   "workspace.reset.archived.many": "{{count}} sessions seront archivées.",
   "workspace.reset.note": "Cela réinitialisera l'espace de travail pour correspondre à la branche par défaut.",
+  "common.open": "Ouvrir",
+  "dialog.releaseNotes.action.getStarted": "Commencer",
+  "dialog.releaseNotes.action.next": "Suivant",
+  "dialog.releaseNotes.action.hideFuture": "Ne plus afficher à l'avenir",
+  "dialog.releaseNotes.media.alt": "Aperçu de la version",
+  "toast.project.reloadFailed.title": "Échec du rechargement de {{project}}",
+  "error.server.invalidConfiguration": "Configuration invalide",
+  "common.moreCountSuffix": " (+{{count}} de plus)",
+  "common.time.justNow": "À l'instant",
+  "common.time.minutesAgo.short": "il y a {{count}}m",
+  "common.time.hoursAgo.short": "il y a {{count}}h",
+  "common.time.daysAgo.short": "il y a {{count}}j",
+  "settings.providers.connected.environmentDescription": "Connecté à partir de vos variables d'environnement",
+  "settings.providers.custom.description": "Ajouter un fournisseur compatible avec OpenAI via l'URL de base.",
 }

+ 14 - 0
packages/app/src/i18n/ja.ts

@@ -738,4 +738,18 @@ export const dict = {
   "workspace.reset.archived.one": "1つのセッションがアーカイブされます。",
   "workspace.reset.archived.many": "{{count}}個のセッションがアーカイブされます。",
   "workspace.reset.note": "これにより、ワークスペースはデフォルトブランチと一致するようにリセットされます。",
+  "common.open": "開く",
+  "dialog.releaseNotes.action.getStarted": "始める",
+  "dialog.releaseNotes.action.next": "次へ",
+  "dialog.releaseNotes.action.hideFuture": "今後表示しない",
+  "dialog.releaseNotes.media.alt": "リリースのプレビュー",
+  "toast.project.reloadFailed.title": "{{project}} の再読み込みに失敗しました",
+  "error.server.invalidConfiguration": "無効な設定",
+  "common.moreCountSuffix": " (他 {{count}} 件)",
+  "common.time.justNow": "たった今",
+  "common.time.minutesAgo.short": "{{count}} 分前",
+  "common.time.hoursAgo.short": "{{count}} 時間前",
+  "common.time.daysAgo.short": "{{count}} 日前",
+  "settings.providers.connected.environmentDescription": "環境変数から接続されました",
+  "settings.providers.custom.description": "ベース URL を指定して OpenAI 互換のプロバイダーを追加します。",
 }

+ 14 - 0
packages/app/src/i18n/ko.ts

@@ -738,4 +738,18 @@ export const dict = {
   "workspace.reset.archived.one": "1개의 세션이 보관됩니다.",
   "workspace.reset.archived.many": "{{count}}개의 세션이 보관됩니다.",
   "workspace.reset.note": "이 작업은 작업 공간을 기본 브랜치와 일치하도록 재설정합니다.",
+  "common.open": "열기",
+  "dialog.releaseNotes.action.getStarted": "시작하기",
+  "dialog.releaseNotes.action.next": "다음",
+  "dialog.releaseNotes.action.hideFuture": "다시 보지 않기",
+  "dialog.releaseNotes.media.alt": "릴리스 미리보기",
+  "toast.project.reloadFailed.title": "{{project}} 다시 불러오기 실패",
+  "error.server.invalidConfiguration": "잘못된 구성",
+  "common.moreCountSuffix": " (외 {{count}}개)",
+  "common.time.justNow": "방금 전",
+  "common.time.minutesAgo.short": "{{count}}분 전",
+  "common.time.hoursAgo.short": "{{count}}시간 전",
+  "common.time.daysAgo.short": "{{count}}일 전",
+  "settings.providers.connected.environmentDescription": "환경 변수에서 연결됨",
+  "settings.providers.custom.description": "기본 URL로 OpenAI 호환 공급자를 추가합니다.",
 }

+ 14 - 0
packages/app/src/i18n/no.ts

@@ -821,4 +821,18 @@ export const dict = {
   "workspace.reset.archived.one": "1 sesjon vil bli arkivert.",
   "workspace.reset.archived.many": "{{count}} sesjoner vil bli arkivert.",
   "workspace.reset.note": "Dette vil tilbakestille arbeidsområdet til å samsvare med standardgrenen.",
+  "common.open": "Åpne",
+  "dialog.releaseNotes.action.getStarted": "Kom i gang",
+  "dialog.releaseNotes.action.next": "Neste",
+  "dialog.releaseNotes.action.hideFuture": "Ikke vis disse igjen",
+  "dialog.releaseNotes.media.alt": "Forhåndsvisning av utgivelse",
+  "toast.project.reloadFailed.title": "Kunne ikke laste inn {{project}} på nytt",
+  "error.server.invalidConfiguration": "Ugyldig konfigurasjon",
+  "common.moreCountSuffix": " (+{{count}} mer)",
+  "common.time.justNow": "Akkurat nå",
+  "common.time.minutesAgo.short": "{{count}} m siden",
+  "common.time.hoursAgo.short": "{{count}} t siden",
+  "common.time.daysAgo.short": "{{count}} d siden",
+  "settings.providers.connected.environmentDescription": "Koblet til fra miljøvariablene dine",
+  "settings.providers.custom.description": "Legg til en OpenAI-kompatibel leverandør via basis-URL.",
 } satisfies Partial<Record<Keys, string>>

+ 14 - 0
packages/app/src/i18n/pl.ts

@@ -740,4 +740,18 @@ export const dict = {
   "workspace.reset.archived.one": "1 sesja zostanie zarchiwizowana.",
   "workspace.reset.archived.many": "{{count}} sesji zostanie zarchiwizowanych.",
   "workspace.reset.note": "To zresetuje przestrzeń roboczą, aby odpowiadała domyślnej gałęzi.",
+  "common.open": "Otwórz",
+  "dialog.releaseNotes.action.getStarted": "Rozpocznij",
+  "dialog.releaseNotes.action.next": "Dalej",
+  "dialog.releaseNotes.action.hideFuture": "Nie pokazuj tego w przyszłości",
+  "dialog.releaseNotes.media.alt": "Podgląd wydania",
+  "toast.project.reloadFailed.title": "Nie udało się ponownie wczytać {{project}}",
+  "error.server.invalidConfiguration": "Nieprawidłowa konfiguracja",
+  "common.moreCountSuffix": " (jeszcze {{count}})",
+  "common.time.justNow": "Przed chwilą",
+  "common.time.minutesAgo.short": "{{count}} min temu",
+  "common.time.hoursAgo.short": "{{count}} godz. temu",
+  "common.time.daysAgo.short": "{{count}} dni temu",
+  "settings.providers.connected.environmentDescription": "Połączono ze zmiennymi środowiskowymi",
+  "settings.providers.custom.description": "Dodaj dostawcę zgodnego z OpenAI poprzez podstawowy URL.",
 }

+ 14 - 0
packages/app/src/i18n/ru.ts

@@ -821,4 +821,18 @@ export const dict = {
   "workspace.reset.archived.one": "1 сессия будет архивирована.",
   "workspace.reset.archived.many": "{{count}} сессий будет архивировано.",
   "workspace.reset.note": "Рабочее пространство будет сброшено в соответствие с веткой по умолчанию.",
+  "common.open": "Открыть",
+  "dialog.releaseNotes.action.getStarted": "Начать",
+  "dialog.releaseNotes.action.next": "Далее",
+  "dialog.releaseNotes.action.hideFuture": "Больше не показывать",
+  "dialog.releaseNotes.media.alt": "Превью релиза",
+  "toast.project.reloadFailed.title": "Не удалось перезагрузить {{project}}",
+  "error.server.invalidConfiguration": "Недопустимая конфигурация",
+  "common.moreCountSuffix": " (ещё {{count}})",
+  "common.time.justNow": "Только что",
+  "common.time.minutesAgo.short": "{{count}} мин назад",
+  "common.time.hoursAgo.short": "{{count}} ч назад",
+  "common.time.daysAgo.short": "{{count}} д назад",
+  "settings.providers.connected.environmentDescription": "Подключено из ваших переменных окружения",
+  "settings.providers.custom.description": "Добавить провайдера, совместимого с OpenAI, по базовому URL.",
 }

+ 14 - 0
packages/app/src/i18n/th.ts

@@ -811,4 +811,18 @@ export const dict = {
   "workspace.reset.archived.one": "1 เซสชันจะถูกจัดเก็บ",
   "workspace.reset.archived.many": "{{count}} เซสชันจะถูกจัดเก็บ",
   "workspace.reset.note": "สิ่งนี้จะรีเซ็ตพื้นที่ทำงานให้ตรงกับสาขาเริ่มต้น",
+  "common.open": "เปิด",
+  "dialog.releaseNotes.action.getStarted": "เริ่มต้น",
+  "dialog.releaseNotes.action.next": "ถัดไป",
+  "dialog.releaseNotes.action.hideFuture": "ไม่ต้องแสดงสิ่งนี้อีกในอนาคต",
+  "dialog.releaseNotes.media.alt": "ตัวอย่างรุ่น",
+  "toast.project.reloadFailed.title": "ไม่สามารถโหลด {{project}} ใหม่ได้",
+  "error.server.invalidConfiguration": "การกำหนดค่าไม่ถูกต้อง",
+  "common.moreCountSuffix": " (เพิ่มอีก {{count}})",
+  "common.time.justNow": "เมื่อสักครู่นี้",
+  "common.time.minutesAgo.short": "{{count}} นาทีที่แล้ว",
+  "common.time.hoursAgo.short": "{{count}} ชม. ที่แล้ว",
+  "common.time.daysAgo.short": "{{count}} วันที่แล้ว",
+  "settings.providers.connected.environmentDescription": "เชื่อมต่อจากตัวแปรสภาพแวดล้อมของคุณ",
+  "settings.providers.custom.description": "เพิ่มผู้ให้บริการที่รองรับ OpenAI ด้วย URL หลัก",
 }

+ 14 - 0
packages/app/src/i18n/tr.ts

@@ -832,4 +832,18 @@ export const dict = {
   "workspace.reset.archived.one": "1 oturum arşivlenecek.",
   "workspace.reset.archived.many": "{{count}} oturum arşivlenecek.",
   "workspace.reset.note": "Bu işlem çalışma alanını varsayılan dalla eşleşecek şekilde sıfırlayacak.",
+  "common.open": "Aç",
+  "dialog.releaseNotes.action.getStarted": "Başla",
+  "dialog.releaseNotes.action.next": "İleri",
+  "dialog.releaseNotes.action.hideFuture": "Bunu gelecekte bir daha gösterme",
+  "dialog.releaseNotes.media.alt": "Sürüm önizlemesi",
+  "toast.project.reloadFailed.title": "{{project}} yeniden yüklenemedi",
+  "error.server.invalidConfiguration": "Geçersiz yapılandırma",
+  "common.moreCountSuffix": " (+{{count}} daha)",
+  "common.time.justNow": "Şimdi",
+  "common.time.minutesAgo.short": "{{count}}dk önce",
+  "common.time.hoursAgo.short": "{{count}}sa önce",
+  "common.time.daysAgo.short": "{{count}}g önce",
+  "settings.providers.connected.environmentDescription": "Ortam değişkenlerinizden bağlandı",
+  "settings.providers.custom.description": "Temel URL üzerinden OpenAI uyumlu bir sağlayıcı ekleyin.",
 } satisfies Partial<Record<Keys, string>>

+ 14 - 0
packages/app/src/i18n/zh.ts

@@ -809,4 +809,18 @@ export const dict = {
   "workspace.reset.archived.one": "将归档 1 个会话。",
   "workspace.reset.archived.many": "将归档 {{count}} 个会话。",
   "workspace.reset.note": "这将把工作区重置为与默认分支一致。",
+  "common.open": "打开",
+  "dialog.releaseNotes.action.getStarted": "开始",
+  "dialog.releaseNotes.action.next": "下一步",
+  "dialog.releaseNotes.action.hideFuture": "不再显示",
+  "dialog.releaseNotes.media.alt": "发布预览",
+  "toast.project.reloadFailed.title": "无法重新加载 {{project}}",
+  "error.server.invalidConfiguration": "配置无效",
+  "common.moreCountSuffix": " (还有 {{count}} 个)",
+  "common.time.justNow": "刚刚",
+  "common.time.minutesAgo.short": "{{count}}分钟前",
+  "common.time.hoursAgo.short": "{{count}}小时前",
+  "common.time.daysAgo.short": "{{count}}天前",
+  "settings.providers.connected.environmentDescription": "已通过环境变量连接",
+  "settings.providers.custom.description": "通过基础 URL 添加与 OpenAI 兼容的提供商。",
 } satisfies Partial<Record<Keys, string>>

+ 14 - 0
packages/app/src/i18n/zht.ts

@@ -804,4 +804,18 @@ export const dict = {
   "workspace.reset.archived.one": "將封存 1 個工作階段。",
   "workspace.reset.archived.many": "將封存 {{count}} 個工作階段。",
   "workspace.reset.note": "這將把工作區重設為與預設分支一致。",
+  "common.open": "打開",
+  "dialog.releaseNotes.action.getStarted": "開始",
+  "dialog.releaseNotes.action.next": "下一步",
+  "dialog.releaseNotes.action.hideFuture": "不再顯示",
+  "dialog.releaseNotes.media.alt": "發佈預覽",
+  "toast.project.reloadFailed.title": "無法重新載入 {{project}}",
+  "error.server.invalidConfiguration": "無效的設定",
+  "common.moreCountSuffix": " (還有 {{count}} 個)",
+  "common.time.justNow": "剛剛",
+  "common.time.minutesAgo.short": "{{count}}分鐘前",
+  "common.time.hoursAgo.short": "{{count}}小時前",
+  "common.time.daysAgo.short": "{{count}}天前",
+  "settings.providers.connected.environmentDescription": "已從環境變數連線",
+  "settings.providers.custom.description": "透過基本 URL 新增與 OpenAI 相容的提供者。",
 } satisfies Partial<Record<Keys, string>>

+ 22 - 5
packages/app/src/utils/server-errors.ts

@@ -7,11 +7,28 @@ export type ConfigInvalidError = {
   }
 }
 
-export function formatServerError(error: unknown) {
-  if (isConfigInvalidErrorLike(error)) return parseReabaleConfigInvalidError(error)
+type Label = {
+  unknown: string
+  invalidConfiguration: string
+}
+
+const fallback: Label = {
+  unknown: "Unknown error",
+  invalidConfiguration: "Invalid configuration",
+}
+
+function resolveLabel(labels: Partial<Label> | undefined): Label {
+  return {
+    unknown: labels?.unknown ?? fallback.unknown,
+    invalidConfiguration: labels?.invalidConfiguration ?? fallback.invalidConfiguration,
+  }
+}
+
+export function formatServerError(error: unknown, labels?: Partial<Label>) {
+  if (isConfigInvalidErrorLike(error)) return parseReabaleConfigInvalidError(error, labels)
   if (error instanceof Error && error.message) return error.message
   if (typeof error === "string" && error) return error
-  return "Unknown error"
+  return resolveLabel(labels).unknown
 }
 
 function isConfigInvalidErrorLike(error: unknown): error is ConfigInvalidError {
@@ -20,8 +37,8 @@ function isConfigInvalidErrorLike(error: unknown): error is ConfigInvalidError {
   return o.name === "ConfigInvalidError" && typeof o.data === "object" && o.data !== null
 }
 
-export function parseReabaleConfigInvalidError(errorInput: ConfigInvalidError) {
-  const head = "Invalid configuration"
+export function parseReabaleConfigInvalidError(errorInput: ConfigInvalidError, labels?: Partial<Label>) {
+  const head = resolveLabel(labels).invalidConfiguration
   const file = errorInput.data.path && errorInput.data.path !== "config" ? errorInput.data.path : ""
   const detail = errorInput.data.message?.trim() ?? ""
   const issues = (errorInput.data.issues ?? []).map((issue) => {

+ 13 - 5
packages/app/src/utils/time.ts

@@ -1,4 +1,12 @@
-export function getRelativeTime(dateString: string): string {
+type TimeKey =
+  | "common.time.justNow"
+  | "common.time.minutesAgo.short"
+  | "common.time.hoursAgo.short"
+  | "common.time.daysAgo.short"
+
+type Translate = (key: TimeKey, params?: Record<string, string | number>) => string
+
+export function getRelativeTime(dateString: string, t: Translate): string {
   const date = new Date(dateString)
   const now = new Date()
   const diffMs = now.getTime() - date.getTime()
@@ -7,8 +15,8 @@ export function getRelativeTime(dateString: string): string {
   const diffHours = Math.floor(diffMinutes / 60)
   const diffDays = Math.floor(diffHours / 24)
 
-  if (diffSeconds < 60) return "Just now"
-  if (diffMinutes < 60) return `${diffMinutes}m ago`
-  if (diffHours < 24) return `${diffHours}h ago`
-  return `${diffDays}d ago`
+  if (diffSeconds < 60) return t("common.time.justNow")
+  if (diffMinutes < 60) return t("common.time.minutesAgo.short", { count: diffMinutes })
+  if (diffHours < 24) return t("common.time.hoursAgo.short", { count: diffHours })
+  return t("common.time.daysAgo.short", { count: diffDays })
 }

+ 29 - 1
packages/desktop/src/cli.ts

@@ -3,6 +3,32 @@ import { message } from "@tauri-apps/plugin-dialog"
 import { initI18n, t } from "./i18n"
 import { commands } from "./bindings"
 
+function installError(error: unknown) {
+  const text = String(error)
+  if (text.includes("CLI installation is only supported on macOS & Linux")) {
+    return t("desktop.cli.error.unsupportedPlatform")
+  }
+  if (text.includes("Sidecar binary not found")) {
+    return t("desktop.cli.error.sidecarMissing")
+  }
+  if (text.includes("Failed to write install script")) {
+    return t("desktop.cli.error.scriptWriteFailed")
+  }
+  if (text.includes("Failed to set script permissions")) {
+    return t("desktop.cli.error.scriptPermissionFailed")
+  }
+  if (text.includes("Failed to run install script")) {
+    return t("desktop.cli.error.scriptRunFailed")
+  }
+  if (text.includes("Install script failed")) {
+    return t("desktop.cli.error.scriptFailed")
+  }
+  if (text.includes("Could not determine install path")) {
+    return t("desktop.cli.error.installPathUnknown")
+  }
+  return text || t("desktop.cli.error.unknown")
+}
+
 export async function installCli(): Promise<void> {
   await initI18n()
 
@@ -10,6 +36,8 @@ export async function installCli(): Promise<void> {
     const path = await commands.installCli()
     await message(t("desktop.cli.installed.message", { path }), { title: t("desktop.cli.installed.title") })
   } catch (e) {
-    await message(t("desktop.cli.failed.message", { error: String(e) }), { title: t("desktop.cli.failed.title") })
+    await message(t("desktop.cli.failed.message", { error: installError(e) }), {
+      title: t("desktop.cli.failed.title"),
+    })
   }
 }

+ 33 - 0
packages/desktop/src/i18n/ar.ts

@@ -23,4 +23,37 @@ export const dict = {
   "desktop.cli.installed.message": "تم تثبيت CLI في {{path}}\n\nأعد تشغيل الطرفية لاستخدام الأمر 'opencode'.",
   "desktop.cli.failed.title": "فشل التثبيت",
   "desktop.cli.failed.message": "فشل تثبيت CLI: {{error}}",
+
+  "desktop.menu.app": "OpenCode",
+  "desktop.menu.file": "ملف",
+  "desktop.menu.edit": "تعديل",
+  "desktop.menu.view": "عرض",
+  "desktop.menu.help": "مساعدة",
+  "desktop.menu.file.newSession": "جلسة جديدة",
+  "desktop.menu.file.openProject": "فتح مشروع...",
+  "desktop.menu.view.toggleSidebar": "تبديل الشريط الجانبي",
+  "desktop.menu.view.toggleTerminal": "تبديل الطرفية",
+  "desktop.menu.view.toggleFileTree": "تبديل شجرة الملفات",
+  "desktop.menu.view.back": "رجوع",
+  "desktop.menu.view.forward": "تقدم",
+  "desktop.menu.view.previousSession": "الجلسة السابقة",
+  "desktop.menu.view.nextSession": "الجلسة التالية",
+  "desktop.menu.help.documentation": "وثائق OpenCode",
+  "desktop.menu.help.supportForum": "منتدى الدعم",
+  "desktop.menu.help.shareFeedback": "مشاركة التعليقات",
+  "desktop.menu.help.reportBug": "الإبلاغ عن خطأ",
+  "desktop.cli.error.unsupportedPlatform": "تثبيت CLI مدعوم فقط على macOS و Linux.",
+  "desktop.cli.error.sidecarMissing": "ملف OpenCode CLI الثنائي مفقود. حاول إعادة تثبيت تطبيق سطح المكتب.",
+  "desktop.cli.error.scriptWriteFailed": "فشل تحضير برنامج تثبيت CLI.",
+  "desktop.cli.error.scriptPermissionFailed": "فشل جعل برنامج تثبيت CLI قابلاً للتنفيذ.",
+  "desktop.cli.error.scriptRunFailed": "فشل تشغيل برنامج تثبيت CLI.",
+  "desktop.cli.error.scriptFailed": "فشل برنامج تثبيت CLI.",
+  "desktop.cli.error.installPathUnknown": "تعذر تحديد مكان تثبيت CLI.",
+  "desktop.cli.error.unknown": "خطأ تثبيت غير معروف",
+  "desktop.loading.status.initial": "لحظة من فضلك...",
+  "desktop.loading.status.done": "تم الانتهاء",
+  "desktop.loading.status.migrating": "جارٍ ترحيل قاعدة البيانات الخاصة بك",
+  "desktop.loading.status.waiting": "قد يستغرق هذا بضع دقائق",
+  "desktop.loading.progressAria": "تقدم ترحيل قاعدة البيانات",
+  "desktop.server.local": "خادم محلي",
 }

+ 34 - 0
packages/desktop/src/i18n/br.ts

@@ -24,4 +24,38 @@ export const dict = {
   "desktop.cli.installed.message": "CLI instalada em {{path}}\n\nReinicie seu terminal para usar o comando 'opencode'.",
   "desktop.cli.failed.title": "Falha na instalação",
   "desktop.cli.failed.message": "Falha ao instalar a CLI: {{error}}",
+
+  "desktop.menu.app": "OpenCode",
+  "desktop.menu.file": "Arquivo",
+  "desktop.menu.edit": "Editar",
+  "desktop.menu.view": "Visualizar",
+  "desktop.menu.help": "Ajuda",
+  "desktop.menu.file.newSession": "Nova Sessão",
+  "desktop.menu.file.openProject": "Abrir Projeto...",
+  "desktop.menu.view.toggleSidebar": "Alternar Barra Lateral",
+  "desktop.menu.view.toggleTerminal": "Alternar Terminal",
+  "desktop.menu.view.toggleFileTree": "Alternar Árvore de Arquivos",
+  "desktop.menu.view.back": "Voltar",
+  "desktop.menu.view.forward": "Avançar",
+  "desktop.menu.view.previousSession": "Sessão Anterior",
+  "desktop.menu.view.nextSession": "Próxima Sessão",
+  "desktop.menu.help.documentation": "Documentação do OpenCode",
+  "desktop.menu.help.supportForum": "Fórum de Suporte",
+  "desktop.menu.help.shareFeedback": "Compartilhar Feedback",
+  "desktop.menu.help.reportBug": "Relatar um Bug",
+  "desktop.cli.error.unsupportedPlatform": "A instalação da CLI é suportada apenas no macOS e Linux.",
+  "desktop.cli.error.sidecarMissing":
+    "O binário da CLI do OpenCode está ausente. Tente reinstalar o aplicativo de desktop.",
+  "desktop.cli.error.scriptWriteFailed": "Falha ao preparar o script de instalação da CLI.",
+  "desktop.cli.error.scriptPermissionFailed": "Falha ao tornar o script de instalação da CLI executável.",
+  "desktop.cli.error.scriptRunFailed": "Falha ao executar o script de instalação da CLI.",
+  "desktop.cli.error.scriptFailed": "O instalador da CLI falhou.",
+  "desktop.cli.error.installPathUnknown": "Não foi possível determinar onde a CLI foi instalada.",
+  "desktop.cli.error.unknown": "Erro de instalação desconhecido",
+  "desktop.loading.status.initial": "Só um momento...",
+  "desktop.loading.status.done": "Tudo pronto",
+  "desktop.loading.status.migrating": "Migrando seu banco de dados",
+  "desktop.loading.status.waiting": "Isso pode levar alguns minutos",
+  "desktop.loading.progressAria": "Progresso da migração do banco de dados",
+  "desktop.server.local": "Servidor Local",
 }

+ 34 - 0
packages/desktop/src/i18n/bs.ts

@@ -25,4 +25,38 @@ export const dict = {
     "CLI je instaliran u {{path}}\n\nRestartuj terminal da bi koristio komandu 'opencode'.",
   "desktop.cli.failed.title": "Instalacija nije uspjela",
   "desktop.cli.failed.message": "Neuspjela instalacija CLI-a: {{error}}",
+
+  "desktop.menu.app": "OpenCode",
+  "desktop.menu.file": "Datoteka",
+  "desktop.menu.edit": "Uredi",
+  "desktop.menu.view": "Prikaz",
+  "desktop.menu.help": "Pomoć",
+  "desktop.menu.file.newSession": "Nova sesija",
+  "desktop.menu.file.openProject": "Otvori projekat...",
+  "desktop.menu.view.toggleSidebar": "Prebaci bočnu traku",
+  "desktop.menu.view.toggleTerminal": "Prebaci terminal",
+  "desktop.menu.view.toggleFileTree": "Prebaci stablo datoteka",
+  "desktop.menu.view.back": "Nazad",
+  "desktop.menu.view.forward": "Naprijed",
+  "desktop.menu.view.previousSession": "Prethodna sesija",
+  "desktop.menu.view.nextSession": "Sljedeća sesija",
+  "desktop.menu.help.documentation": "OpenCode Dokumentacija",
+  "desktop.menu.help.supportForum": "Forum za podršku",
+  "desktop.menu.help.shareFeedback": "Podijeli povratne informacije",
+  "desktop.menu.help.reportBug": "Prijavi grešku",
+  "desktop.cli.error.unsupportedPlatform": "Instalacija CLI-a je podržana samo na macOS-u i Linux-u.",
+  "desktop.cli.error.sidecarMissing":
+    "Nedostaje binarna datoteka OpenCode CLI-a. Pokušaj ponovo instalirati desktop aplikaciju.",
+  "desktop.cli.error.scriptWriteFailed": "Nije uspjela priprema skripte za instalaciju CLI-a.",
+  "desktop.cli.error.scriptPermissionFailed": "Nije uspjelo postavljanje izvršnih dozvola za instalaciju CLI-a.",
+  "desktop.cli.error.scriptRunFailed": "Nije uspjelo pokretanje skripte za instalaciju CLI-a.",
+  "desktop.cli.error.scriptFailed": "Instalacija CLI-a nije uspjela.",
+  "desktop.cli.error.installPathUnknown": "Nije bilo moguće utvrditi gdje je instaliran CLI.",
+  "desktop.cli.error.unknown": "Nepoznata greška pri instalaciji",
+  "desktop.loading.status.initial": "Samo trenutak...",
+  "desktop.loading.status.done": "Sve je gotovo",
+  "desktop.loading.status.migrating": "Migracija baze podataka u toku",
+  "desktop.loading.status.waiting": "Ovo može potrajati nekoliko minuta",
+  "desktop.loading.progressAria": "Napredak migracije baze podataka",
+  "desktop.server.local": "Lokalni server",
 }

+ 33 - 0
packages/desktop/src/i18n/da.ts

@@ -25,4 +25,37 @@ export const dict = {
     "CLI installeret i {{path}}\n\nGenstart din terminal for at bruge 'opencode'-kommandoen.",
   "desktop.cli.failed.title": "Installation mislykkedes",
   "desktop.cli.failed.message": "Kunne ikke installere CLI: {{error}}",
+
+  "desktop.menu.app": "OpenCode",
+  "desktop.menu.file": "Filer",
+  "desktop.menu.edit": "Rediger",
+  "desktop.menu.view": "Vis",
+  "desktop.menu.help": "Hjælp",
+  "desktop.menu.file.newSession": "Ny session",
+  "desktop.menu.file.openProject": "Åbn projekt...",
+  "desktop.menu.view.toggleSidebar": "Slå sidepanel til/fra",
+  "desktop.menu.view.toggleTerminal": "Slå terminal til/fra",
+  "desktop.menu.view.toggleFileTree": "Slå filoversigt til/fra",
+  "desktop.menu.view.back": "Tilbage",
+  "desktop.menu.view.forward": "Fremad",
+  "desktop.menu.view.previousSession": "Forrige session",
+  "desktop.menu.view.nextSession": "Næste session",
+  "desktop.menu.help.documentation": "OpenCode Dokumentation",
+  "desktop.menu.help.supportForum": "Supportforum",
+  "desktop.menu.help.shareFeedback": "Del feedback",
+  "desktop.menu.help.reportBug": "Rapporter en fejl",
+  "desktop.cli.error.unsupportedPlatform": "CLI-installation understøttes kun på macOS og Linux.",
+  "desktop.cli.error.sidecarMissing": "OpenCode CLI-binærfil mangler. Prøv at geninstallere desktop-appen.",
+  "desktop.cli.error.scriptWriteFailed": "Kunne ikke forberede CLI-installationsscriptet.",
+  "desktop.cli.error.scriptPermissionFailed": "Kunne ikke gøre CLI-installationsscriptet eksekverbart.",
+  "desktop.cli.error.scriptRunFailed": "Kunne ikke køre CLI-installationsscriptet.",
+  "desktop.cli.error.scriptFailed": "CLI-installationsprogrammet mislykkedes.",
+  "desktop.cli.error.installPathUnknown": "Kunne ikke fastslå, hvor CLI'en blev installeret.",
+  "desktop.cli.error.unknown": "Ukendt installationsfejl",
+  "desktop.loading.status.initial": "Lige et øjeblik...",
+  "desktop.loading.status.done": "Helt færdig",
+  "desktop.loading.status.migrating": "Migrerer din database",
+  "desktop.loading.status.waiting": "Dette kan tage et par minutter",
+  "desktop.loading.progressAria": "Status for databasemigrering",
+  "desktop.server.local": "Lokal server",
 }

+ 34 - 0
packages/desktop/src/i18n/de.ts

@@ -25,4 +25,38 @@ export const dict = {
     "CLI wurde in {{path}} installiert\n\nStarten Sie Ihr Terminal neu, um den Befehl 'opencode' zu verwenden.",
   "desktop.cli.failed.title": "Installation fehlgeschlagen",
   "desktop.cli.failed.message": "CLI konnte nicht installiert werden: {{error}}",
+
+  "desktop.menu.app": "OpenCode",
+  "desktop.menu.file": "Datei",
+  "desktop.menu.edit": "Bearbeiten",
+  "desktop.menu.view": "Ansicht",
+  "desktop.menu.help": "Hilfe",
+  "desktop.menu.file.newSession": "Neue Sitzung",
+  "desktop.menu.file.openProject": "Projekt öffnen...",
+  "desktop.menu.view.toggleSidebar": "Seitenleiste umschalten",
+  "desktop.menu.view.toggleTerminal": "Terminal umschalten",
+  "desktop.menu.view.toggleFileTree": "Dateibaum umschalten",
+  "desktop.menu.view.back": "Zurück",
+  "desktop.menu.view.forward": "Vorwärts",
+  "desktop.menu.view.previousSession": "Vorherige Sitzung",
+  "desktop.menu.view.nextSession": "Nächste Sitzung",
+  "desktop.menu.help.documentation": "OpenCode-Dokumentation",
+  "desktop.menu.help.supportForum": "Support-Forum",
+  "desktop.menu.help.shareFeedback": "Feedback teilen",
+  "desktop.menu.help.reportBug": "Einen Fehler melden",
+  "desktop.cli.error.unsupportedPlatform": "Die CLI-Installation wird nur unter macOS und Linux unterstützt.",
+  "desktop.cli.error.sidecarMissing":
+    "Das OpenCode CLI-Binary fehlt. Versuchen Sie, die Desktop-App neu zu installieren.",
+  "desktop.cli.error.scriptWriteFailed": "Das CLI-Installationsskript konnte nicht vorbereitet werden.",
+  "desktop.cli.error.scriptPermissionFailed": "Das CLI-Installationsskript konnte nicht ausführbar gemacht werden.",
+  "desktop.cli.error.scriptRunFailed": "Das CLI-Installationsskript konnte nicht ausgeführt werden.",
+  "desktop.cli.error.scriptFailed": "Das CLI-Installationsprogramm ist fehlgeschlagen.",
+  "desktop.cli.error.installPathUnknown": "Es konnte nicht ermittelt werden, wo die CLI installiert wurde.",
+  "desktop.cli.error.unknown": "Unbekannter Installationsfehler",
+  "desktop.loading.status.initial": "Einen Moment bitte...",
+  "desktop.loading.status.done": "Alles erledigt",
+  "desktop.loading.status.migrating": "Ihre Datenbank wird migriert",
+  "desktop.loading.status.waiting": "Dies kann einige Minuten dauern",
+  "desktop.loading.progressAria": "Fortschritt der Datenbankmigration",
+  "desktop.server.local": "Lokaler Server",
 }

+ 34 - 0
packages/desktop/src/i18n/en.ts

@@ -3,6 +3,24 @@ export const dict = {
   "desktop.menu.installCli": "Install CLI...",
   "desktop.menu.reloadWebview": "Reload Webview",
   "desktop.menu.restart": "Restart",
+  "desktop.menu.app": "OpenCode",
+  "desktop.menu.file": "File",
+  "desktop.menu.edit": "Edit",
+  "desktop.menu.view": "View",
+  "desktop.menu.help": "Help",
+  "desktop.menu.file.newSession": "New Session",
+  "desktop.menu.file.openProject": "Open Project...",
+  "desktop.menu.view.toggleSidebar": "Toggle Sidebar",
+  "desktop.menu.view.toggleTerminal": "Toggle Terminal",
+  "desktop.menu.view.toggleFileTree": "Toggle File Tree",
+  "desktop.menu.view.back": "Back",
+  "desktop.menu.view.forward": "Forward",
+  "desktop.menu.view.previousSession": "Previous Session",
+  "desktop.menu.view.nextSession": "Next Session",
+  "desktop.menu.help.documentation": "OpenCode Documentation",
+  "desktop.menu.help.supportForum": "Support Forum",
+  "desktop.menu.help.shareFeedback": "Share Feedback",
+  "desktop.menu.help.reportBug": "Report a Bug",
 
   "desktop.dialog.chooseFolder": "Choose a folder",
   "desktop.dialog.chooseFile": "Choose a file",
@@ -24,4 +42,20 @@ export const dict = {
   "desktop.cli.installed.message": "CLI installed to {{path}}\n\nRestart your terminal to use the 'opencode' command.",
   "desktop.cli.failed.title": "Installation Failed",
   "desktop.cli.failed.message": "Failed to install CLI: {{error}}",
+  "desktop.cli.error.unsupportedPlatform": "CLI installation is only supported on macOS and Linux.",
+  "desktop.cli.error.sidecarMissing": "OpenCode CLI binary is missing. Try reinstalling the desktop app.",
+  "desktop.cli.error.scriptWriteFailed": "Failed to prepare CLI installer script.",
+  "desktop.cli.error.scriptPermissionFailed": "Failed to make CLI installer executable.",
+  "desktop.cli.error.scriptRunFailed": "Failed to run CLI installer script.",
+  "desktop.cli.error.scriptFailed": "CLI installer failed.",
+  "desktop.cli.error.installPathUnknown": "Could not determine where the CLI was installed.",
+  "desktop.cli.error.unknown": "Unknown installation error",
+
+  "desktop.loading.status.initial": "Just a moment...",
+  "desktop.loading.status.done": "All done",
+  "desktop.loading.status.migrating": "Migrating your database",
+  "desktop.loading.status.waiting": "This may take a couple of minutes",
+  "desktop.loading.progressAria": "Database migration progress",
+
+  "desktop.server.local": "Local Server",
 }

+ 34 - 0
packages/desktop/src/i18n/es.ts

@@ -24,4 +24,38 @@ export const dict = {
   "desktop.cli.installed.message": "CLI instalada en {{path}}\n\nReinicia tu terminal para usar el comando 'opencode'.",
   "desktop.cli.failed.title": "Instalación fallida",
   "desktop.cli.failed.message": "No se pudo instalar la CLI: {{error}}",
+
+  "desktop.menu.app": "OpenCode",
+  "desktop.menu.file": "Archivo",
+  "desktop.menu.edit": "Editar",
+  "desktop.menu.view": "Ver",
+  "desktop.menu.help": "Ayuda",
+  "desktop.menu.file.newSession": "Nueva sesión",
+  "desktop.menu.file.openProject": "Abrir proyecto...",
+  "desktop.menu.view.toggleSidebar": "Alternar barra lateral",
+  "desktop.menu.view.toggleTerminal": "Alternar terminal",
+  "desktop.menu.view.toggleFileTree": "Alternar árbol de archivos",
+  "desktop.menu.view.back": "Atrás",
+  "desktop.menu.view.forward": "Adelante",
+  "desktop.menu.view.previousSession": "Sesión anterior",
+  "desktop.menu.view.nextSession": "Siguiente sesión",
+  "desktop.menu.help.documentation": "Documentación de OpenCode",
+  "desktop.menu.help.supportForum": "Foro de soporte",
+  "desktop.menu.help.shareFeedback": "Compartir comentarios",
+  "desktop.menu.help.reportBug": "Informar de un error",
+  "desktop.cli.error.unsupportedPlatform": "La instalación de la CLI solo es compatible con macOS y Linux.",
+  "desktop.cli.error.sidecarMissing":
+    "Falta el binario de la CLI de OpenCode. Intenta reinstalar la aplicación de escritorio.",
+  "desktop.cli.error.scriptWriteFailed": "No se pudo preparar el script del instalador de la CLI.",
+  "desktop.cli.error.scriptPermissionFailed": "No se pudo hacer ejecutable el script del instalador de la CLI.",
+  "desktop.cli.error.scriptRunFailed": "No se pudo ejecutar el script del instalador de la CLI.",
+  "desktop.cli.error.scriptFailed": "El instalador de la CLI falló.",
+  "desktop.cli.error.installPathUnknown": "No se pudo determinar dónde se instaló la CLI.",
+  "desktop.cli.error.unknown": "Error de instalación desconocido",
+  "desktop.loading.status.initial": "Un momento...",
+  "desktop.loading.status.done": "Todo listo",
+  "desktop.loading.status.migrating": "Migrando tu base de datos",
+  "desktop.loading.status.waiting": "Esto puede tardar unos minutos",
+  "desktop.loading.progressAria": "Progreso de migración de la base de datos",
+  "desktop.server.local": "Servidor local",
 }

+ 34 - 0
packages/desktop/src/i18n/fr.ts

@@ -25,4 +25,38 @@ export const dict = {
     "CLI installée dans {{path}}\n\nRedémarrez votre terminal pour utiliser la commande 'opencode'.",
   "desktop.cli.failed.title": "Échec de l'installation",
   "desktop.cli.failed.message": "Impossible d'installer la CLI : {{error}}",
+
+  "desktop.menu.app": "OpenCode",
+  "desktop.menu.file": "Fichier",
+  "desktop.menu.edit": "Édition",
+  "desktop.menu.view": "Affichage",
+  "desktop.menu.help": "Aide",
+  "desktop.menu.file.newSession": "Nouvelle session",
+  "desktop.menu.file.openProject": "Ouvrir un projet...",
+  "desktop.menu.view.toggleSidebar": "Basculer la barre latérale",
+  "desktop.menu.view.toggleTerminal": "Basculer le terminal",
+  "desktop.menu.view.toggleFileTree": "Basculer l'arborescence des fichiers",
+  "desktop.menu.view.back": "Retour",
+  "desktop.menu.view.forward": "Suivant",
+  "desktop.menu.view.previousSession": "Session précédente",
+  "desktop.menu.view.nextSession": "Session suivante",
+  "desktop.menu.help.documentation": "Documentation d'OpenCode",
+  "desktop.menu.help.supportForum": "Forum d'assistance",
+  "desktop.menu.help.shareFeedback": "Partager des commentaires",
+  "desktop.menu.help.reportBug": "Signaler un bug",
+  "desktop.cli.error.unsupportedPlatform": "L'installation de la CLI n'est prise en charge que sur macOS et Linux.",
+  "desktop.cli.error.sidecarMissing":
+    "Le binaire de la CLI OpenCode est manquant. Essayez de réinstaller l'application de bureau.",
+  "desktop.cli.error.scriptWriteFailed": "Impossible de préparer le script d'installation de la CLI.",
+  "desktop.cli.error.scriptPermissionFailed": "Impossible de rendre le script d'installation de la CLI exécutable.",
+  "desktop.cli.error.scriptRunFailed": "Impossible d'exécuter le script d'installation de la CLI.",
+  "desktop.cli.error.scriptFailed": "L'installateur de la CLI a échoué.",
+  "desktop.cli.error.installPathUnknown": "Impossible de déterminer où la CLI a été installée.",
+  "desktop.cli.error.unknown": "Erreur d'installation inconnue",
+  "desktop.loading.status.initial": "Un instant...",
+  "desktop.loading.status.done": "Terminé",
+  "desktop.loading.status.migrating": "Migration de votre base de données",
+  "desktop.loading.status.waiting": "Cela peut prendre quelques minutes",
+  "desktop.loading.progressAria": "Progression de la migration de la base de données",
+  "desktop.server.local": "Serveur local",
 }

+ 34 - 0
packages/desktop/src/i18n/ja.ts

@@ -25,4 +25,38 @@ export const dict = {
     "CLI を {{path}} にインストールしました\n\nターミナルを再起動して 'opencode' コマンドを使用してください。",
   "desktop.cli.failed.title": "インストールに失敗しました",
   "desktop.cli.failed.message": "CLI のインストールに失敗しました: {{error}}",
+
+  "desktop.menu.app": "OpenCode",
+  "desktop.menu.file": "ファイル",
+  "desktop.menu.edit": "編集",
+  "desktop.menu.view": "表示",
+  "desktop.menu.help": "ヘルプ",
+  "desktop.menu.file.newSession": "新しいセッション",
+  "desktop.menu.file.openProject": "プロジェクトを開く...",
+  "desktop.menu.view.toggleSidebar": "サイドバーの切り替え",
+  "desktop.menu.view.toggleTerminal": "ターミナルの切り替え",
+  "desktop.menu.view.toggleFileTree": "ファイルツリーの切り替え",
+  "desktop.menu.view.back": "戻る",
+  "desktop.menu.view.forward": "進む",
+  "desktop.menu.view.previousSession": "前のセッション",
+  "desktop.menu.view.nextSession": "次のセッション",
+  "desktop.menu.help.documentation": "OpenCode ドキュメント",
+  "desktop.menu.help.supportForum": "サポートフォーラム",
+  "desktop.menu.help.shareFeedback": "フィードバックを共有",
+  "desktop.menu.help.reportBug": "バグを報告",
+  "desktop.cli.error.unsupportedPlatform": "CLI のインストールは macOS と Linux のみでサポートされています。",
+  "desktop.cli.error.sidecarMissing":
+    "OpenCode CLI のバイナリが見つかりません。デスクトップアプリを再インストールしてみてください。",
+  "desktop.cli.error.scriptWriteFailed": "CLI インストーラースクリプトの準備に失敗しました。",
+  "desktop.cli.error.scriptPermissionFailed": "CLI インストーラースクリプトに実行権限を付与できませんでした。",
+  "desktop.cli.error.scriptRunFailed": "CLI インストーラースクリプトの実行に失敗しました。",
+  "desktop.cli.error.scriptFailed": "CLI インストーラーが失敗しました。",
+  "desktop.cli.error.installPathUnknown": "CLI がどこにインストールされたか特定できませんでした。",
+  "desktop.cli.error.unknown": "不明なインストールエラー",
+  "desktop.loading.status.initial": "少々お待ちください...",
+  "desktop.loading.status.done": "完了しました",
+  "desktop.loading.status.migrating": "データベースを移行しています",
+  "desktop.loading.status.waiting": "これには数分かかる場合があります",
+  "desktop.loading.progressAria": "データベース移行の進行状況",
+  "desktop.server.local": "ローカルサーバー",
 }

+ 33 - 0
packages/desktop/src/i18n/ko.ts

@@ -24,4 +24,37 @@ export const dict = {
     "CLI가 {{path}}에 설치되었습니다\n\n터미널을 다시 시작하여 'opencode' 명령을 사용하세요.",
   "desktop.cli.failed.title": "설치 실패",
   "desktop.cli.failed.message": "CLI 설치 실패: {{error}}",
+
+  "desktop.menu.app": "OpenCode",
+  "desktop.menu.file": "파일",
+  "desktop.menu.edit": "편집",
+  "desktop.menu.view": "보기",
+  "desktop.menu.help": "도움말",
+  "desktop.menu.file.newSession": "새 세션",
+  "desktop.menu.file.openProject": "프로젝트 열기...",
+  "desktop.menu.view.toggleSidebar": "사이드바 전환",
+  "desktop.menu.view.toggleTerminal": "터미널 전환",
+  "desktop.menu.view.toggleFileTree": "파일 트리 전환",
+  "desktop.menu.view.back": "뒤로",
+  "desktop.menu.view.forward": "앞으로",
+  "desktop.menu.view.previousSession": "이전 세션",
+  "desktop.menu.view.nextSession": "다음 세션",
+  "desktop.menu.help.documentation": "OpenCode 문서",
+  "desktop.menu.help.supportForum": "지원 포럼",
+  "desktop.menu.help.shareFeedback": "피드백 공유",
+  "desktop.menu.help.reportBug": "버그 신고",
+  "desktop.cli.error.unsupportedPlatform": "CLI 설치는 macOS 및 Linux에서만 지원됩니다.",
+  "desktop.cli.error.sidecarMissing": "OpenCode CLI 바이너리가 누락되었습니다. 데스크톱 앱을 다시 설치해 보세요.",
+  "desktop.cli.error.scriptWriteFailed": "CLI 설치 스크립트를 준비하지 못했습니다.",
+  "desktop.cli.error.scriptPermissionFailed": "CLI 설치 스크립트를 실행 가능하게 만들지 못했습니다.",
+  "desktop.cli.error.scriptRunFailed": "CLI 설치 스크립트를 실행하지 못했습니다.",
+  "desktop.cli.error.scriptFailed": "CLI 설치 프로그램이 실패했습니다.",
+  "desktop.cli.error.installPathUnknown": "CLI가 어디에 설치되었는지 확인할 수 없습니다.",
+  "desktop.cli.error.unknown": "알 수 없는 설치 오류",
+  "desktop.loading.status.initial": "잠시만 기다려 주세요...",
+  "desktop.loading.status.done": "모두 완료되었습니다",
+  "desktop.loading.status.migrating": "데이터베이스 마이그레이션 중",
+  "desktop.loading.status.waiting": "이 작업은 몇 분 정도 걸릴 수 있습니다",
+  "desktop.loading.progressAria": "데이터베이스 마이그레이션 진행률",
+  "desktop.server.local": "로컬 서버",
 }

+ 33 - 0
packages/desktop/src/i18n/no.ts

@@ -25,4 +25,37 @@ export const dict = {
     "CLI installert til {{path}}\n\nStart terminalen på nytt for å bruke 'opencode'-kommandoen.",
   "desktop.cli.failed.title": "Installasjon mislyktes",
   "desktop.cli.failed.message": "Kunne ikke installere CLI: {{error}}",
+
+  "desktop.menu.app": "OpenCode",
+  "desktop.menu.file": "Fil",
+  "desktop.menu.edit": "Rediger",
+  "desktop.menu.view": "Vis",
+  "desktop.menu.help": "Hjelp",
+  "desktop.menu.file.newSession": "Ny sesjon",
+  "desktop.menu.file.openProject": "Åpne prosjekt...",
+  "desktop.menu.view.toggleSidebar": "Vis/skjul sidefelt",
+  "desktop.menu.view.toggleTerminal": "Vis/skjul terminal",
+  "desktop.menu.view.toggleFileTree": "Vis/skjul filtre",
+  "desktop.menu.view.back": "Tilbake",
+  "desktop.menu.view.forward": "Frem",
+  "desktop.menu.view.previousSession": "Forrige sesjon",
+  "desktop.menu.view.nextSession": "Neste sesjon",
+  "desktop.menu.help.documentation": "OpenCode Dokumentasjon",
+  "desktop.menu.help.supportForum": "Støtteforum",
+  "desktop.menu.help.shareFeedback": "Del tilbakemelding",
+  "desktop.menu.help.reportBug": "Rapporter en feil",
+  "desktop.cli.error.unsupportedPlatform": "CLI-installasjon støttes kun på macOS og Linux.",
+  "desktop.cli.error.sidecarMissing": "OpenCode CLI-binærfil mangler. Prøv å installere skrivebordsappen på nytt.",
+  "desktop.cli.error.scriptWriteFailed": "Kunne ikke klargjøre CLI-installasjonsskriptet.",
+  "desktop.cli.error.scriptPermissionFailed": "Kunne ikke gjøre CLI-installasjonsskriptet kjørbart.",
+  "desktop.cli.error.scriptRunFailed": "Kunne ikke kjøre CLI-installasjonsskriptet.",
+  "desktop.cli.error.scriptFailed": "CLI-installasjonsprogrammet mislyktes.",
+  "desktop.cli.error.installPathUnknown": "Kunne ikke avgjøre hvor CLI ble installert.",
+  "desktop.cli.error.unknown": "Ukjent installasjonsfeil",
+  "desktop.loading.status.initial": "Et øyeblikk...",
+  "desktop.loading.status.done": "Alt ferdig",
+  "desktop.loading.status.migrating": "Migrerer databasen din",
+  "desktop.loading.status.waiting": "Dette kan ta et par minutter",
+  "desktop.loading.progressAria": "Fremdrift for databasemigrering",
+  "desktop.server.local": "Lokal server",
 }

+ 34 - 0
packages/desktop/src/i18n/pl.ts

@@ -25,4 +25,38 @@ export const dict = {
     "CLI zainstalowane w {{path}}\n\nUruchom ponownie terminal, aby użyć polecenia 'opencode'.",
   "desktop.cli.failed.title": "Instalacja nie powiodła się",
   "desktop.cli.failed.message": "Nie udało się zainstalować CLI: {{error}}",
+
+  "desktop.menu.app": "OpenCode",
+  "desktop.menu.file": "Plik",
+  "desktop.menu.edit": "Edycja",
+  "desktop.menu.view": "Widok",
+  "desktop.menu.help": "Pomoc",
+  "desktop.menu.file.newSession": "Nowa sesja",
+  "desktop.menu.file.openProject": "Otwórz projekt...",
+  "desktop.menu.view.toggleSidebar": "Przełącz pasek boczny",
+  "desktop.menu.view.toggleTerminal": "Przełącz terminal",
+  "desktop.menu.view.toggleFileTree": "Przełącz drzewo plików",
+  "desktop.menu.view.back": "Wstecz",
+  "desktop.menu.view.forward": "Dalej",
+  "desktop.menu.view.previousSession": "Poprzednia sesja",
+  "desktop.menu.view.nextSession": "Następna sesja",
+  "desktop.menu.help.documentation": "Dokumentacja OpenCode",
+  "desktop.menu.help.supportForum": "Forum wsparcia",
+  "desktop.menu.help.shareFeedback": "Prześlij opinię",
+  "desktop.menu.help.reportBug": "Zgłoś błąd",
+  "desktop.cli.error.unsupportedPlatform": "Instalacja CLI jest obsługiwana tylko na macOS i Linux.",
+  "desktop.cli.error.sidecarMissing":
+    "Brakuje pliku binarnego OpenCode CLI. Spróbuj ponownie zainstalować aplikację na komputer.",
+  "desktop.cli.error.scriptWriteFailed": "Nie udało się przygotować skryptu instalatora CLI.",
+  "desktop.cli.error.scriptPermissionFailed": "Nie udało się nadać uprawnień do wykonania skryptu instalatora CLI.",
+  "desktop.cli.error.scriptRunFailed": "Nie udało się uruchomić skryptu instalatora CLI.",
+  "desktop.cli.error.scriptFailed": "Instalator CLI nie powiódł się.",
+  "desktop.cli.error.installPathUnknown": "Nie udało się ustalić, gdzie zostało zainstalowane CLI.",
+  "desktop.cli.error.unknown": "Nieznany błąd instalacji",
+  "desktop.loading.status.initial": "Chwileczkę...",
+  "desktop.loading.status.done": "Gotowe",
+  "desktop.loading.status.migrating": "Migrowanie bazy danych",
+  "desktop.loading.status.waiting": "Może to potrwać kilka minut",
+  "desktop.loading.progressAria": "Postęp migracji bazy danych",
+  "desktop.server.local": "Serwer lokalny",
 }

+ 34 - 0
packages/desktop/src/i18n/ru.ts

@@ -24,4 +24,38 @@ export const dict = {
     "CLI установлен в {{path}}\n\nПерезапустите терминал, чтобы использовать команду 'opencode'.",
   "desktop.cli.failed.title": "Ошибка установки",
   "desktop.cli.failed.message": "Не удалось установить CLI: {{error}}",
+
+  "desktop.menu.app": "OpenCode",
+  "desktop.menu.file": "Файл",
+  "desktop.menu.edit": "Правка",
+  "desktop.menu.view": "Вид",
+  "desktop.menu.help": "Справка",
+  "desktop.menu.file.newSession": "Новая сессия",
+  "desktop.menu.file.openProject": "Открыть проект...",
+  "desktop.menu.view.toggleSidebar": "Переключить боковую панель",
+  "desktop.menu.view.toggleTerminal": "Переключить терминал",
+  "desktop.menu.view.toggleFileTree": "Переключить дерево файлов",
+  "desktop.menu.view.back": "Назад",
+  "desktop.menu.view.forward": "Вперед",
+  "desktop.menu.view.previousSession": "Предыдущая сессия",
+  "desktop.menu.view.nextSession": "Следующая сессия",
+  "desktop.menu.help.documentation": "Документация OpenCode",
+  "desktop.menu.help.supportForum": "Форум поддержки",
+  "desktop.menu.help.shareFeedback": "Поделиться отзывом",
+  "desktop.menu.help.reportBug": "Сообщить об ошибке",
+  "desktop.cli.error.unsupportedPlatform": "Установка CLI поддерживается только в macOS и Linux.",
+  "desktop.cli.error.sidecarMissing":
+    "Отсутствует бинарный файл OpenCode CLI. Попробуйте переустановить настольное приложение.",
+  "desktop.cli.error.scriptWriteFailed": "Не удалось подготовить скрипт установщика CLI.",
+  "desktop.cli.error.scriptPermissionFailed": "Не удалось сделать скрипт установщика CLI исполняемым.",
+  "desktop.cli.error.scriptRunFailed": "Не удалось запустить скрипт установщика CLI.",
+  "desktop.cli.error.scriptFailed": "Ошибка установщика CLI.",
+  "desktop.cli.error.installPathUnknown": "Не удалось определить, куда был установлен CLI.",
+  "desktop.cli.error.unknown": "Неизвестная ошибка установки",
+  "desktop.loading.status.initial": "Минуточку...",
+  "desktop.loading.status.done": "Всё готово",
+  "desktop.loading.status.migrating": "Миграция вашей базы данных",
+  "desktop.loading.status.waiting": "Это может занять пару минут",
+  "desktop.loading.progressAria": "Прогресс миграции базы данных",
+  "desktop.server.local": "Локальный сервер",
 }

+ 33 - 0
packages/desktop/src/i18n/zh.ts

@@ -23,4 +23,37 @@ export const dict = {
   "desktop.cli.installed.message": "CLI 已安装到 {{path}}\n\n重启终端以使用 'opencode' 命令。",
   "desktop.cli.failed.title": "安装失败",
   "desktop.cli.failed.message": "无法安装 CLI: {{error}}",
+
+  "desktop.menu.app": "OpenCode",
+  "desktop.menu.file": "文件",
+  "desktop.menu.edit": "编辑",
+  "desktop.menu.view": "查看",
+  "desktop.menu.help": "帮助",
+  "desktop.menu.file.newSession": "新会话",
+  "desktop.menu.file.openProject": "打开项目...",
+  "desktop.menu.view.toggleSidebar": "切换侧边栏",
+  "desktop.menu.view.toggleTerminal": "切换终端",
+  "desktop.menu.view.toggleFileTree": "切换文件树",
+  "desktop.menu.view.back": "后退",
+  "desktop.menu.view.forward": "前进",
+  "desktop.menu.view.previousSession": "上一个会话",
+  "desktop.menu.view.nextSession": "下一个会话",
+  "desktop.menu.help.documentation": "OpenCode 文档",
+  "desktop.menu.help.supportForum": "支持论坛",
+  "desktop.menu.help.shareFeedback": "分享反馈",
+  "desktop.menu.help.reportBug": "报告错误",
+  "desktop.cli.error.unsupportedPlatform": "CLI 安装仅在 macOS 和 Linux 上受支持。",
+  "desktop.cli.error.sidecarMissing": "OpenCode CLI 二进制文件缺失。请尝试重新安装桌面应用程序。",
+  "desktop.cli.error.scriptWriteFailed": "无法准备 CLI 安装脚本。",
+  "desktop.cli.error.scriptPermissionFailed": "无法使 CLI 安装脚本可执行。",
+  "desktop.cli.error.scriptRunFailed": "无法运行 CLI 安装脚本。",
+  "desktop.cli.error.scriptFailed": "CLI 安装程序失败。",
+  "desktop.cli.error.installPathUnknown": "无法确定 CLI 的安装位置。",
+  "desktop.cli.error.unknown": "未知的安装错误",
+  "desktop.loading.status.initial": "稍等片刻...",
+  "desktop.loading.status.done": "全部完成",
+  "desktop.loading.status.migrating": "正在迁移您的数据库",
+  "desktop.loading.status.waiting": "这可能需要几分钟",
+  "desktop.loading.progressAria": "数据库迁移进度",
+  "desktop.server.local": "本地服务器",
 }

+ 33 - 0
packages/desktop/src/i18n/zht.ts

@@ -23,4 +23,37 @@ export const dict = {
   "desktop.cli.installed.message": "CLI 已安裝到 {{path}}\n\n重新啟動終端機以使用 'opencode' 命令。",
   "desktop.cli.failed.title": "安裝失敗",
   "desktop.cli.failed.message": "無法安裝 CLI: {{error}}",
+
+  "desktop.menu.app": "OpenCode",
+  "desktop.menu.file": "檔案",
+  "desktop.menu.edit": "編輯",
+  "desktop.menu.view": "檢視",
+  "desktop.menu.help": "說明",
+  "desktop.menu.file.newSession": "新工作階段",
+  "desktop.menu.file.openProject": "開啟專案...",
+  "desktop.menu.view.toggleSidebar": "切換側邊欄",
+  "desktop.menu.view.toggleTerminal": "切換終端機",
+  "desktop.menu.view.toggleFileTree": "切換檔案樹",
+  "desktop.menu.view.back": "上一步",
+  "desktop.menu.view.forward": "下一步",
+  "desktop.menu.view.previousSession": "上一個工作階段",
+  "desktop.menu.view.nextSession": "下一個工作階段",
+  "desktop.menu.help.documentation": "OpenCode 文件",
+  "desktop.menu.help.supportForum": "支援論壇",
+  "desktop.menu.help.shareFeedback": "分享意見回饋",
+  "desktop.menu.help.reportBug": "回報錯誤",
+  "desktop.cli.error.unsupportedPlatform": "CLI 安裝僅支援 macOS 與 Linux。",
+  "desktop.cli.error.sidecarMissing": "OpenCode CLI 執行檔遺失。請嘗試重新安裝桌面應用程式。",
+  "desktop.cli.error.scriptWriteFailed": "無法準備 CLI 安裝指令碼。",
+  "desktop.cli.error.scriptPermissionFailed": "無法將 CLI 安裝指令碼設為可執行。",
+  "desktop.cli.error.scriptRunFailed": "無法執行 CLI 安裝指令碼。",
+  "desktop.cli.error.scriptFailed": "CLI 安裝程式失敗。",
+  "desktop.cli.error.installPathUnknown": "無法確定 CLI 的安裝位置。",
+  "desktop.cli.error.unknown": "未知的安裝錯誤",
+  "desktop.loading.status.initial": "稍等片刻...",
+  "desktop.loading.status.done": "全部完成",
+  "desktop.loading.status.migrating": "正在移轉您的資料庫",
+  "desktop.loading.status.waiting": "這可能需要幾分鐘",
+  "desktop.loading.progressAria": "資料庫移轉進度",
+  "desktop.server.local": "本機伺服器",
 }

+ 1 - 1
packages/desktop/src/index.tsx

@@ -445,7 +445,7 @@ render(() => {
             }
             const server: ServerConnection.Any = data.is_sidecar
               ? {
-                  displayName: "Local Server",
+                  displayName: t("desktop.server.local"),
                   type: "sidecar",
                   variant: "base",
                   http,

+ 11 - 4
packages/desktop/src/loading.tsx

@@ -8,11 +8,18 @@ import "./styles.css"
 import { createEffect, createMemo, createSignal, onCleanup, onMount } from "solid-js"
 import { commands, events, InitStep } from "./bindings"
 import { Channel } from "@tauri-apps/api/core"
+import { initI18n, t } from "./i18n"
 
 const root = document.getElementById("root")!
-const lines = ["Just a moment...", "Migrating your database", "This may take a couple of minutes"]
+const lines = [
+  t("desktop.loading.status.initial"),
+  t("desktop.loading.status.migrating"),
+  t("desktop.loading.status.waiting"),
+]
 const delays = [3000, 9000]
 
+void initI18n()
+
 render(() => {
   const [step, setStep] = createSignal<InitStep | null>(null)
   const [line, setLine] = createSignal(0)
@@ -54,9 +61,9 @@ render(() => {
   })
 
   const status = createMemo(() => {
-    if (phase() === "done") return "All done"
+    if (phase() === "done") return t("desktop.loading.status.done")
     if (phase() === "sqlite_waiting") return lines[line()]
-    return "Just a moment..."
+    return t("desktop.loading.status.initial")
   })
 
   return (
@@ -72,7 +79,7 @@ render(() => {
             <Progress
               value={value()}
               class="w-20 [&_[data-slot='progress-track']]:h-1 [&_[data-slot='progress-track']]:border-0 [&_[data-slot='progress-track']]:rounded-none [&_[data-slot='progress-track']]:bg-surface-weak [&_[data-slot='progress-fill']]:rounded-none [&_[data-slot='progress-fill']]:bg-icon-warning-base"
-              aria-label="Database migration progress"
+              aria-label={t("desktop.loading.progressAria")}
               getValueLabel={({ value }) => `${Math.round(value)}%`}
             />
           </div>

+ 18 - 18
packages/desktop/src/menu.ts

@@ -16,7 +16,7 @@ export async function createMenu(trigger: (id: string) => void) {
   const menu = await Menu.new({
     items: [
       await Submenu.new({
-        text: "OpenCode",
+        text: t("desktop.menu.app"),
         items: [
           await PredefinedMenuItem.new({
             item: { About: null },
@@ -62,15 +62,15 @@ export async function createMenu(trigger: (id: string) => void) {
         ].filter(Boolean),
       }),
       await Submenu.new({
-        text: "File",
+        text: t("desktop.menu.file"),
         items: [
           await MenuItem.new({
-            text: "New Session",
+            text: t("desktop.menu.file.newSession"),
             accelerator: "Shift+Cmd+S",
             action: () => trigger("session.new"),
           }),
           await MenuItem.new({
-            text: "Open Project...",
+            text: t("desktop.menu.file.openProject"),
             accelerator: "Cmd+O",
             action: () => trigger("project.open"),
           }),
@@ -83,7 +83,7 @@ export async function createMenu(trigger: (id: string) => void) {
         ],
       }),
       await Submenu.new({
-        text: "Edit",
+        text: t("desktop.menu.edit"),
         items: [
           await PredefinedMenuItem.new({
             item: "Undo",
@@ -109,44 +109,44 @@ export async function createMenu(trigger: (id: string) => void) {
         ],
       }),
       await Submenu.new({
-        text: "View",
+        text: t("desktop.menu.view"),
         items: [
           await MenuItem.new({
             action: () => trigger("sidebar.toggle"),
-            text: "Toggle Sidebar",
+            text: t("desktop.menu.view.toggleSidebar"),
             accelerator: "Cmd+B",
           }),
           await MenuItem.new({
             action: () => trigger("terminal.toggle"),
-            text: "Toggle Terminal",
+            text: t("desktop.menu.view.toggleTerminal"),
             accelerator: "Ctrl+`",
           }),
           await MenuItem.new({
             action: () => trigger("fileTree.toggle"),
-            text: "Toggle File Tree",
+            text: t("desktop.menu.view.toggleFileTree"),
           }),
           await PredefinedMenuItem.new({
             item: "Separator",
           }),
           await MenuItem.new({
             action: () => trigger("common.goBack"),
-            text: "Back",
+            text: t("desktop.menu.view.back"),
           }),
           await MenuItem.new({
             action: () => trigger("common.goForward"),
-            text: "Forward",
+            text: t("desktop.menu.view.forward"),
           }),
           await PredefinedMenuItem.new({
             item: "Separator",
           }),
           await MenuItem.new({
             action: () => trigger("session.previous"),
-            text: "Previous Session",
+            text: t("desktop.menu.view.previousSession"),
             accelerator: "Option+ArrowUp",
           }),
           await MenuItem.new({
             action: () => trigger("session.next"),
-            text: "Next Session",
+            text: t("desktop.menu.view.nextSession"),
             accelerator: "Option+ArrowDown",
           }),
           await PredefinedMenuItem.new({
@@ -155,16 +155,16 @@ export async function createMenu(trigger: (id: string) => void) {
         ],
       }),
       await Submenu.new({
-        text: "Help",
+        text: t("desktop.menu.help"),
         items: [
           // missing native macos search
           await MenuItem.new({
             action: () => openUrl("https://opencode.ai/docs"),
-            text: "OpenCode Documentation",
+            text: t("desktop.menu.help.documentation"),
           }),
           await MenuItem.new({
             action: () => openUrl("https://discord.com/invite/opencode"),
-            text: "Support Forum",
+            text: t("desktop.menu.help.supportForum"),
           }),
           await PredefinedMenuItem.new({
             item: "Separator",
@@ -177,11 +177,11 @@ export async function createMenu(trigger: (id: string) => void) {
           }),
           await MenuItem.new({
             action: () => openUrl("https://github.com/anomalyco/opencode/issues/new?template=feature_request.yml"),
-            text: "Share Feedback",
+            text: t("desktop.menu.help.shareFeedback"),
           }),
           await MenuItem.new({
             action: () => openUrl("https://github.com/anomalyco/opencode/issues/new?template=bug_report.yml"),
-            text: "Report a Bug",
+            text: t("desktop.menu.help.reportBug"),
           }),
         ],
       }),

+ 2 - 1
packages/enterprise/src/app.tsx

@@ -56,8 +56,9 @@ function detectLocale() {
 
 function UiI18nBridge(props: ParentProps) {
   const locale = createMemo(() => detectLocale())
+  const zh = uiZh as Partial<Record<string, string>>
   const t = (key: keyof typeof uiEn, params?: UiI18nParams) => {
-    const value = locale() === "zh" ? (uiZh[key] ?? uiEn[key]) : uiEn[key]
+    const value = locale() === "zh" ? (zh[key] ?? uiEn[key]) : uiEn[key]
     const text = value ?? String(key)
     return resolveTemplate(text, params)
   }

+ 14 - 6
packages/ui/src/components/message-part.tsx

@@ -463,14 +463,22 @@ function contextToolTrigger(part: ToolPart, i18n: ReturnType<typeof useI18n>) {
   }
 }
 
-function contextToolSummary(parts: ToolPart[]) {
+function contextToolSummary(parts: ToolPart[], i18n: ReturnType<typeof useI18n>) {
   const read = parts.filter((part) => part.tool === "read").length
   const search = parts.filter((part) => part.tool === "glob" || part.tool === "grep").length
   const list = parts.filter((part) => part.tool === "list").length
   return [
-    read ? `${read} ${read === 1 ? "read" : "reads"}` : undefined,
-    search ? `${search} ${search === 1 ? "search" : "searches"}` : undefined,
-    list ? `${list} ${list === 1 ? "list" : "lists"}` : undefined,
+    read
+      ? i18n.t(read === 1 ? "ui.messagePart.context.read.one" : "ui.messagePart.context.read.other", { count: read })
+      : undefined,
+    search
+      ? i18n.t(search === 1 ? "ui.messagePart.context.search.one" : "ui.messagePart.context.search.other", {
+          count: search,
+        })
+      : undefined,
+    list
+      ? i18n.t(list === 1 ? "ui.messagePart.context.list.one" : "ui.messagePart.context.list.other", { count: list })
+      : undefined,
   ].filter((value): value is string => !!value)
 }
 
@@ -595,7 +603,7 @@ function ContextToolGroup(props: { parts: ToolPart[]; busy?: boolean }) {
     () =>
       !!props.busy || props.parts.some((part) => part.state.status === "pending" || part.state.status === "running"),
   )
-  const summary = createMemo(() => contextToolSummary(props.parts))
+  const summary = createMemo(() => contextToolSummary(props.parts, i18n))
   const details = createMemo(() => summary().join(", "))
 
   return (
@@ -979,7 +987,7 @@ PART_MAPPING["tool"] = function ToolPartDisplay(props) {
                 return (
                   <div style="width: 100%; display: flex; justify-content: flex-end;">
                     <span class="text-13-regular text-text-weak cursor-default">
-                      {i18n.t("ui.tool.questions")} dismissed
+                      {i18n.t("ui.messagePart.questions.dismissed")}
                     </span>
                   </div>
                 )

+ 3 - 1
packages/ui/src/components/scroll-view.tsx

@@ -1,4 +1,5 @@
 import { createSignal, onCleanup, onMount, splitProps, type ComponentProps, Show, mergeProps } from "solid-js"
+import { useI18n } from "../context/i18n"
 
 export interface ScrollViewProps extends ComponentProps<"div"> {
   viewportRef?: (el: HTMLDivElement) => void
@@ -6,6 +7,7 @@ export interface ScrollViewProps extends ComponentProps<"div"> {
 }
 
 export function ScrollView(props: ScrollViewProps) {
+  const i18n = useI18n()
   const merged = mergeProps({ orientation: "vertical" }, props)
   const [local, events, rest] = splitProps(
     merged,
@@ -188,7 +190,7 @@ export function ScrollView(props: ScrollViewProps) {
         onClick={events.onClick as any}
         tabIndex={0}
         role="region"
-        aria-label="scrollable content"
+        aria-label={i18n.t("ui.scrollView.ariaLabel")}
         onKeyDown={(e) => {
           onKeyDown(e)
           if (typeof events.onKeyDown === "function") events.onKeyDown(e as any)

+ 15 - 15
packages/ui/src/components/session-review.tsx

@@ -16,18 +16,8 @@ import { useFileComponent } from "../context/file"
 import { useI18n } from "../context/i18n"
 import { getDirectory, getFilename } from "@opencode-ai/util/path"
 import { checksum } from "@opencode-ai/util/encode"
-import {
-  createEffect,
-  createMemo,
-  createSignal,
-  For,
-  Match,
-  onCleanup,
-  Show,
-  Switch,
-  untrack,
-  type JSX,
-} from "solid-js"
+import { createEffect, createMemo, createSignal, For, Match, Show, Switch, untrack, type JSX } from "solid-js"
+import { onCleanup } from "solid-js"
 import { createStore } from "solid-js/store"
 import { type FileContent, type FileDiff } from "@opencode-ai/sdk/v2"
 import { PreloadMultiFileDiffResult } from "@pierre/diffs/ssr"
@@ -191,6 +181,15 @@ export const SessionReview = (props: SessionReviewProps) => {
     highlightedFile = undefined
   }
 
+  const openFileLabel = () => i18n.t("ui.sessionReview.openFile")
+
+  const selectionLabel = (range: SelectedLineRange) => {
+    const start = Math.min(range.start, range.end)
+    const end = Math.max(range.start, range.end)
+    if (start === end) return i18n.t("ui.sessionReview.selection.line", { line: start })
+    return i18n.t("ui.sessionReview.selection.lines", { start, end })
+  }
+
   const focusSearch = () => {
     if (!hasDiffs()) return
     setSearchOpen(true)
@@ -475,7 +474,8 @@ export const SessionReview = (props: SessionReviewProps) => {
 
         const wrapper = anchors.get(focus.file)
         const anchor = wrapper?.querySelector(`[data-comment-id="${focus.id}"]`)
-        const ready = anchor instanceof HTMLElement
+        const ready =
+          anchor instanceof HTMLElement && anchor.style.pointerEvents !== "none" && anchor.style.opacity !== "0"
 
         const target = ready ? anchor : wrapper
         if (!target) {
@@ -751,11 +751,11 @@ export const SessionReview = (props: SessionReviewProps) => {
                               </Show>
                               <span data-slot="session-review-filename">{getFilename(file)}</span>
                               <Show when={props.onViewFile}>
-                                <Tooltip value="Open file" placement="top" gutter={4}>
+                                <Tooltip value={openFileLabel()} placement="top" gutter={4}>
                                   <button
                                     data-slot="session-review-view-button"
                                     type="button"
-                                    aria-label="Open file"
+                                    aria-label={openFileLabel()}
                                     onClick={(e) => {
                                       e.stopPropagation()
                                       props.onViewFile?.(file)

+ 11 - 0
packages/ui/src/i18n/ar.ts

@@ -3,6 +3,9 @@ export const dict = {
   "ui.sessionReview.title.lastTurn": "تغييرات آخر دور",
   "ui.sessionReview.diffStyle.unified": "موحد",
   "ui.sessionReview.diffStyle.split": "منقسم",
+  "ui.sessionReview.openFile": "فتح ملف",
+  "ui.sessionReview.selection.line": "سطر {{line}}",
+  "ui.sessionReview.selection.lines": "الأسطر {{start}}-{{end}}",
   "ui.sessionReview.expandAll": "توسيع الكل",
   "ui.sessionReview.collapseAll": "طي الكل",
   "ui.sessionReview.change.added": "مضاف",
@@ -53,6 +56,13 @@ export const dict = {
   "ui.sessionTurn.status.gatheringThoughts": "جمع الأفكار",
   "ui.sessionTurn.status.consideringNextSteps": "النظر في الخطوات التالية",
 
+  "ui.messagePart.questions.dismissed": "تم رفض الأسئلة",
+  "ui.messagePart.context.read.one": "{{count}} قراءة",
+  "ui.messagePart.context.read.other": "{{count}} قراءات",
+  "ui.messagePart.context.search.one": "{{count}} بحث",
+  "ui.messagePart.context.search.other": "{{count}} عمليات بحث",
+  "ui.messagePart.context.list.one": "{{count}} قائمة",
+  "ui.messagePart.context.list.other": "{{count}} قوائم",
   "ui.messagePart.diagnostic.error": "خطأ",
   "ui.messagePart.title.edit": "تحرير",
   "ui.messagePart.title.write": "كتابة",
@@ -72,6 +82,7 @@ export const dict = {
   "ui.textField.copied": "تم النسخ",
 
   "ui.imagePreview.alt": "معاينة الصورة",
+  "ui.scrollView.ariaLabel": "محتوى قابل للتمرير",
 
   "ui.tool.read": "قراءة",
   "ui.tool.loaded": "تم التحميل",

+ 11 - 0
packages/ui/src/i18n/br.ts

@@ -3,6 +3,9 @@ export const dict = {
   "ui.sessionReview.title.lastTurn": "Alterações do último turno",
   "ui.sessionReview.diffStyle.unified": "Unificado",
   "ui.sessionReview.diffStyle.split": "Dividido",
+  "ui.sessionReview.openFile": "Abrir arquivo",
+  "ui.sessionReview.selection.line": "linha {{line}}",
+  "ui.sessionReview.selection.lines": "linhas {{start}}-{{end}}",
   "ui.sessionReview.expandAll": "Expandir tudo",
   "ui.sessionReview.collapseAll": "Recolher tudo",
   "ui.sessionReview.change.added": "Adicionado",
@@ -53,6 +56,13 @@ export const dict = {
   "ui.sessionTurn.status.gatheringThoughts": "Organizando pensamentos",
   "ui.sessionTurn.status.consideringNextSteps": "Considerando próximos passos",
 
+  "ui.messagePart.questions.dismissed": "Perguntas descartadas",
+  "ui.messagePart.context.read.one": "{{count}} leitura",
+  "ui.messagePart.context.read.other": "{{count}} leituras",
+  "ui.messagePart.context.search.one": "{{count}} pesquisa",
+  "ui.messagePart.context.search.other": "{{count}} pesquisas",
+  "ui.messagePart.context.list.one": "{{count}} lista",
+  "ui.messagePart.context.list.other": "{{count}} listas",
   "ui.messagePart.diagnostic.error": "Erro",
   "ui.messagePart.title.edit": "Editar",
   "ui.messagePart.title.write": "Escrever",
@@ -72,6 +82,7 @@ export const dict = {
   "ui.textField.copied": "Copiado",
 
   "ui.imagePreview.alt": "Visualização de imagem",
+  "ui.scrollView.ariaLabel": "conteúdo rolável",
 
   "ui.tool.read": "Ler",
   "ui.tool.loaded": "Carregado",

+ 11 - 0
packages/ui/src/i18n/bs.ts

@@ -7,6 +7,9 @@ export const dict = {
   "ui.sessionReview.title.lastTurn": "Promjene u posljednjem potezu",
   "ui.sessionReview.diffStyle.unified": "Ujedinjeno",
   "ui.sessionReview.diffStyle.split": "Podijeljeno",
+  "ui.sessionReview.openFile": "Otvori fajl",
+  "ui.sessionReview.selection.line": "linija {{line}}",
+  "ui.sessionReview.selection.lines": "linije {{start}}-{{end}}",
   "ui.sessionReview.expandAll": "Proširi sve",
   "ui.sessionReview.collapseAll": "Sažmi sve",
   "ui.sessionReview.change.added": "Dodano",
@@ -57,6 +60,13 @@ export const dict = {
   "ui.sessionTurn.status.gatheringThoughts": "Sređivanje misli",
   "ui.sessionTurn.status.consideringNextSteps": "Razmatranje sljedećih koraka",
 
+  "ui.messagePart.questions.dismissed": "Pitanja odbačena",
+  "ui.messagePart.context.read.one": "{{count}} čitanje",
+  "ui.messagePart.context.read.other": "{{count}} čitanja",
+  "ui.messagePart.context.search.one": "{{count}} pretraga",
+  "ui.messagePart.context.search.other": "{{count}} pretrage",
+  "ui.messagePart.context.list.one": "{{count}} lista",
+  "ui.messagePart.context.list.other": "{{count}} liste",
   "ui.messagePart.diagnostic.error": "Greška",
   "ui.messagePart.title.edit": "Uredi",
   "ui.messagePart.title.write": "Napiši",
@@ -76,6 +86,7 @@ export const dict = {
   "ui.textField.copied": "Kopirano",
 
   "ui.imagePreview.alt": "Pregled slike",
+  "ui.scrollView.ariaLabel": "sadržaj za pomjeranje",
 
   "ui.tool.read": "Čitanje",
   "ui.tool.loaded": "Učitano",

+ 11 - 0
packages/ui/src/i18n/da.ts

@@ -3,6 +3,9 @@ export const dict = {
   "ui.sessionReview.title.lastTurn": "Ændringer fra sidste tur",
   "ui.sessionReview.diffStyle.unified": "Samlet",
   "ui.sessionReview.diffStyle.split": "Opdelt",
+  "ui.sessionReview.openFile": "Åbn fil",
+  "ui.sessionReview.selection.line": "linje {{line}}",
+  "ui.sessionReview.selection.lines": "linjer {{start}}-{{end}}",
   "ui.sessionReview.expandAll": "Udvid alle",
   "ui.sessionReview.collapseAll": "Skjul alle",
 
@@ -52,6 +55,13 @@ export const dict = {
   "ui.sessionTurn.status.gatheringThoughts": "Samler tanker",
   "ui.sessionTurn.status.consideringNextSteps": "Overvejer næste skridt",
 
+  "ui.messagePart.questions.dismissed": "Spørgsmål afvist",
+  "ui.messagePart.context.read.one": "{{count}} læsning",
+  "ui.messagePart.context.read.other": "{{count}} læsninger",
+  "ui.messagePart.context.search.one": "{{count}} søgning",
+  "ui.messagePart.context.search.other": "{{count}} søgninger",
+  "ui.messagePart.context.list.one": "{{count}} liste",
+  "ui.messagePart.context.list.other": "{{count}} lister",
   "ui.messagePart.diagnostic.error": "Fejl",
   "ui.messagePart.title.edit": "Rediger",
   "ui.messagePart.title.write": "Skriv",
@@ -71,6 +81,7 @@ export const dict = {
   "ui.textField.copied": "Kopieret",
 
   "ui.imagePreview.alt": "Billedforhåndsvisning",
+  "ui.scrollView.ariaLabel": "rulbart indhold",
 
   "ui.tool.read": "Læs",
   "ui.tool.loaded": "Indlæst",

+ 11 - 0
packages/ui/src/i18n/de.ts

@@ -7,6 +7,9 @@ export const dict = {
   "ui.sessionReview.title.lastTurn": "Änderungen der letzten Runde",
   "ui.sessionReview.diffStyle.unified": "Vereinheitlicht",
   "ui.sessionReview.diffStyle.split": "Geteilt",
+  "ui.sessionReview.openFile": "Datei öffnen",
+  "ui.sessionReview.selection.line": "Zeile {{line}}",
+  "ui.sessionReview.selection.lines": "Zeilen {{start}}-{{end}}",
   "ui.sessionReview.expandAll": "Alle erweitern",
   "ui.sessionReview.collapseAll": "Alle reduzieren",
 
@@ -58,6 +61,13 @@ export const dict = {
   "ui.sessionTurn.status.gatheringThoughts": "Gedanken sammeln",
   "ui.sessionTurn.status.consideringNextSteps": "Nächste Schritte erwägen",
 
+  "ui.messagePart.questions.dismissed": "Fragen verworfen",
+  "ui.messagePart.context.read.one": "{{count}} Lesevorgang",
+  "ui.messagePart.context.read.other": "{{count}} Lesevorgänge",
+  "ui.messagePart.context.search.one": "{{count}} Suche",
+  "ui.messagePart.context.search.other": "{{count}} Suchen",
+  "ui.messagePart.context.list.one": "{{count}} Liste",
+  "ui.messagePart.context.list.other": "{{count}} Listen",
   "ui.messagePart.diagnostic.error": "Fehler",
   "ui.messagePart.title.edit": "Bearbeiten",
   "ui.messagePart.title.write": "Schreiben",
@@ -77,6 +87,7 @@ export const dict = {
   "ui.textField.copied": "Kopiert",
 
   "ui.imagePreview.alt": "Bildvorschau",
+  "ui.scrollView.ariaLabel": "scrollbarer Inhalt",
 
   "ui.tool.read": "Lesen",
   "ui.tool.loaded": "Geladen",

+ 12 - 1
packages/ui/src/i18n/en.ts

@@ -1,4 +1,4 @@
-export const dict = {
+export const dict: Record<string, string> = {
   "ui.sessionReview.title": "Session changes",
   "ui.sessionReview.title.lastTurn": "Last turn changes",
   "ui.sessionReview.diffStyle.unified": "Unified",
@@ -13,6 +13,9 @@ export const dict = {
   "ui.sessionReview.largeDiff.title": "Diff too large to render",
   "ui.sessionReview.largeDiff.meta": "Limit: {{limit}} changed lines. Current: {{current}} changed lines.",
   "ui.sessionReview.largeDiff.renderAnyway": "Render anyway",
+  "ui.sessionReview.openFile": "Open file",
+  "ui.sessionReview.selection.line": "line {{line}}",
+  "ui.sessionReview.selection.lines": "lines {{start}}-{{end}}",
 
   "ui.fileMedia.kind.image": "image",
   "ui.fileMedia.kind.audio": "audio",
@@ -59,6 +62,13 @@ export const dict = {
   "ui.messagePart.title.write": "Write",
   "ui.messagePart.option.typeOwnAnswer": "Type your own answer",
   "ui.messagePart.review.title": "Review your answers",
+  "ui.messagePart.questions.dismissed": "Questions dismissed",
+  "ui.messagePart.context.read.one": "{{count}} read",
+  "ui.messagePart.context.read.other": "{{count}} reads",
+  "ui.messagePart.context.search.one": "{{count}} search",
+  "ui.messagePart.context.search.other": "{{count}} searches",
+  "ui.messagePart.context.list.one": "{{count}} list",
+  "ui.messagePart.context.list.other": "{{count}} lists",
 
   "ui.list.loading": "Loading",
   "ui.list.empty": "No results",
@@ -73,6 +83,7 @@ export const dict = {
   "ui.textField.copied": "Copied",
 
   "ui.imagePreview.alt": "Image preview",
+  "ui.scrollView.ariaLabel": "scrollable content",
 
   "ui.tool.read": "Read",
   "ui.tool.loaded": "Loaded",

+ 11 - 0
packages/ui/src/i18n/es.ts

@@ -3,6 +3,9 @@ export const dict = {
   "ui.sessionReview.title.lastTurn": "Cambios del último turno",
   "ui.sessionReview.diffStyle.unified": "Unificado",
   "ui.sessionReview.diffStyle.split": "Dividido",
+  "ui.sessionReview.openFile": "Abrir archivo",
+  "ui.sessionReview.selection.line": "línea {{line}}",
+  "ui.sessionReview.selection.lines": "líneas {{start}}-{{end}}",
   "ui.sessionReview.expandAll": "Expandir todo",
   "ui.sessionReview.collapseAll": "Colapsar todo",
   "ui.sessionReview.change.added": "Añadido",
@@ -53,6 +56,13 @@ export const dict = {
   "ui.sessionTurn.status.gatheringThoughts": "Recopilando pensamientos",
   "ui.sessionTurn.status.consideringNextSteps": "Considerando siguientes pasos",
 
+  "ui.messagePart.questions.dismissed": "Preguntas descartadas",
+  "ui.messagePart.context.read.one": "{{count}} lectura",
+  "ui.messagePart.context.read.other": "{{count}} lecturas",
+  "ui.messagePart.context.search.one": "{{count}} búsqueda",
+  "ui.messagePart.context.search.other": "{{count}} búsquedas",
+  "ui.messagePart.context.list.one": "{{count}} lista",
+  "ui.messagePart.context.list.other": "{{count}} listas",
   "ui.messagePart.diagnostic.error": "Error",
   "ui.messagePart.title.edit": "Editar",
   "ui.messagePart.title.write": "Escribir",
@@ -72,6 +82,7 @@ export const dict = {
   "ui.textField.copied": "Copiado",
 
   "ui.imagePreview.alt": "Vista previa de imagen",
+  "ui.scrollView.ariaLabel": "contenido desplazable",
 
   "ui.tool.read": "Leer",
   "ui.tool.loaded": "Cargado",

+ 11 - 0
packages/ui/src/i18n/fr.ts

@@ -3,6 +3,9 @@ export const dict = {
   "ui.sessionReview.title.lastTurn": "Modifications du dernier tour",
   "ui.sessionReview.diffStyle.unified": "Unifié",
   "ui.sessionReview.diffStyle.split": "Divisé",
+  "ui.sessionReview.openFile": "Ouvrir le fichier",
+  "ui.sessionReview.selection.line": "ligne {{line}}",
+  "ui.sessionReview.selection.lines": "lignes {{start}}-{{end}}",
   "ui.sessionReview.expandAll": "Tout développer",
   "ui.sessionReview.collapseAll": "Tout réduire",
   "ui.sessionReview.change.added": "Ajouté",
@@ -53,6 +56,13 @@ export const dict = {
   "ui.sessionTurn.status.gatheringThoughts": "Rassemblement des idées",
   "ui.sessionTurn.status.consideringNextSteps": "Examen des prochaines étapes",
 
+  "ui.messagePart.questions.dismissed": "Questions ignorées",
+  "ui.messagePart.context.read.one": "{{count}} lecture",
+  "ui.messagePart.context.read.other": "{{count}} lectures",
+  "ui.messagePart.context.search.one": "{{count}} recherche",
+  "ui.messagePart.context.search.other": "{{count}} recherches",
+  "ui.messagePart.context.list.one": "{{count}} liste",
+  "ui.messagePart.context.list.other": "{{count}} listes",
   "ui.messagePart.diagnostic.error": "Erreur",
   "ui.messagePart.title.edit": "Modifier",
   "ui.messagePart.title.write": "Écrire",
@@ -72,6 +82,7 @@ export const dict = {
   "ui.textField.copied": "Copié",
 
   "ui.imagePreview.alt": "Aperçu de l'image",
+  "ui.scrollView.ariaLabel": "contenu défilable",
 
   "ui.tool.read": "Lire",
   "ui.tool.loaded": "Chargé",

+ 11 - 0
packages/ui/src/i18n/ja.ts

@@ -3,6 +3,9 @@ export const dict = {
   "ui.sessionReview.title.lastTurn": "前回ターンの変更",
   "ui.sessionReview.diffStyle.unified": "Unified",
   "ui.sessionReview.diffStyle.split": "Split",
+  "ui.sessionReview.openFile": "ファイルを開く",
+  "ui.sessionReview.selection.line": "{{line}} 行目",
+  "ui.sessionReview.selection.lines": "{{start}}-{{end}} 行目",
   "ui.sessionReview.expandAll": "すべて展開",
   "ui.sessionReview.collapseAll": "すべて折りたたむ",
 
@@ -52,6 +55,13 @@ export const dict = {
   "ui.sessionTurn.status.gatheringThoughts": "考えをまとめています",
   "ui.sessionTurn.status.consideringNextSteps": "次のステップを検討中",
 
+  "ui.messagePart.questions.dismissed": "質問をスキップしました",
+  "ui.messagePart.context.read.one": "{{count}} 件の読み取り",
+  "ui.messagePart.context.read.other": "{{count}} 件の読み取り",
+  "ui.messagePart.context.search.one": "{{count}} 件の検索",
+  "ui.messagePart.context.search.other": "{{count}} 件の検索",
+  "ui.messagePart.context.list.one": "{{count}} 件のリスト",
+  "ui.messagePart.context.list.other": "{{count}} 件のリスト",
   "ui.messagePart.diagnostic.error": "エラー",
   "ui.messagePart.title.edit": "編集",
   "ui.messagePart.title.write": "作成",
@@ -71,6 +81,7 @@ export const dict = {
   "ui.textField.copied": "コピーしました",
 
   "ui.imagePreview.alt": "画像プレビュー",
+  "ui.scrollView.ariaLabel": "スクロール可能なコンテンツ",
 
   "ui.tool.read": "読み込み",
   "ui.tool.loaded": "読み込み済み",

+ 11 - 0
packages/ui/src/i18n/ko.ts

@@ -3,6 +3,9 @@ export const dict = {
   "ui.sessionReview.title.lastTurn": "마지막 턴 변경 사항",
   "ui.sessionReview.diffStyle.unified": "통합 보기",
   "ui.sessionReview.diffStyle.split": "분할 보기",
+  "ui.sessionReview.openFile": "파일 열기",
+  "ui.sessionReview.selection.line": "{{line}}번 줄",
+  "ui.sessionReview.selection.lines": "{{start}}-{{end}}번 줄",
   "ui.sessionReview.expandAll": "모두 펼치기",
   "ui.sessionReview.collapseAll": "모두 접기",
   "ui.sessionReview.change.added": "추가됨",
@@ -53,6 +56,13 @@ export const dict = {
   "ui.sessionTurn.status.gatheringThoughts": "생각 정리 중",
   "ui.sessionTurn.status.consideringNextSteps": "다음 단계 고려 중",
 
+  "ui.messagePart.questions.dismissed": "질문 무시됨",
+  "ui.messagePart.context.read.one": "{{count}}개 읽음",
+  "ui.messagePart.context.read.other": "{{count}}개 읽음",
+  "ui.messagePart.context.search.one": "{{count}}개 검색",
+  "ui.messagePart.context.search.other": "{{count}}개 검색",
+  "ui.messagePart.context.list.one": "{{count}}개 목록",
+  "ui.messagePart.context.list.other": "{{count}}개 목록",
   "ui.messagePart.diagnostic.error": "오류",
   "ui.messagePart.title.edit": "편집",
   "ui.messagePart.title.write": "작성",
@@ -72,6 +82,7 @@ export const dict = {
   "ui.textField.copied": "복사됨",
 
   "ui.imagePreview.alt": "이미지 미리보기",
+  "ui.scrollView.ariaLabel": "스크롤 가능한 콘텐츠",
 
   "ui.tool.read": "읽기",
   "ui.tool.loaded": "로드됨",

+ 11 - 0
packages/ui/src/i18n/no.ts

@@ -6,6 +6,9 @@ export const dict: Record<Keys, string> = {
   "ui.sessionReview.title.lastTurn": "Endringer i siste tur",
   "ui.sessionReview.diffStyle.unified": "Samlet",
   "ui.sessionReview.diffStyle.split": "Delt",
+  "ui.sessionReview.openFile": "Åpne fil",
+  "ui.sessionReview.selection.line": "linje {{line}}",
+  "ui.sessionReview.selection.lines": "linjer {{start}}-{{end}}",
   "ui.sessionReview.expandAll": "Utvid alle",
   "ui.sessionReview.collapseAll": "Fold sammen alle",
   "ui.sessionReview.change.added": "Lagt til",
@@ -56,6 +59,13 @@ export const dict: Record<Keys, string> = {
   "ui.sessionTurn.status.gatheringThoughts": "Samler tanker",
   "ui.sessionTurn.status.consideringNextSteps": "Vurderer neste trinn",
 
+  "ui.messagePart.questions.dismissed": "Spørsmål avvist",
+  "ui.messagePart.context.read.one": "{{count}} lest",
+  "ui.messagePart.context.read.other": "{{count}} lest",
+  "ui.messagePart.context.search.one": "{{count}} søk",
+  "ui.messagePart.context.search.other": "{{count}} søk",
+  "ui.messagePart.context.list.one": "{{count}} liste",
+  "ui.messagePart.context.list.other": "{{count}} lister",
   "ui.messagePart.diagnostic.error": "Feil",
   "ui.messagePart.title.edit": "Rediger",
   "ui.messagePart.title.write": "Skriv",
@@ -75,6 +85,7 @@ export const dict: Record<Keys, string> = {
   "ui.textField.copied": "Kopiert",
 
   "ui.imagePreview.alt": "Bildeforhåndsvisning",
+  "ui.scrollView.ariaLabel": "rullbart innhold",
 
   "ui.tool.read": "Les",
   "ui.tool.loaded": "Lastet",

+ 11 - 0
packages/ui/src/i18n/pl.ts

@@ -3,6 +3,9 @@ export const dict = {
   "ui.sessionReview.title.lastTurn": "Zmiany z ostatniej tury",
   "ui.sessionReview.diffStyle.unified": "Ujednolicony",
   "ui.sessionReview.diffStyle.split": "Podzielony",
+  "ui.sessionReview.openFile": "Otwórz plik",
+  "ui.sessionReview.selection.line": "linia {{line}}",
+  "ui.sessionReview.selection.lines": "linie {{start}}-{{end}}",
   "ui.sessionReview.expandAll": "Rozwiń wszystko",
   "ui.sessionReview.collapseAll": "Zwiń wszystko",
 
@@ -52,6 +55,13 @@ export const dict = {
   "ui.sessionTurn.status.gatheringThoughts": "Zbieranie myśli",
   "ui.sessionTurn.status.consideringNextSteps": "Rozważanie kolejnych kroków",
 
+  "ui.messagePart.questions.dismissed": "Pytania odrzucone",
+  "ui.messagePart.context.read.one": "{{count}} odczyt",
+  "ui.messagePart.context.read.other": "{{count}} odczyty",
+  "ui.messagePart.context.search.one": "{{count}} wyszukiwanie",
+  "ui.messagePart.context.search.other": "{{count}} wyszukiwania",
+  "ui.messagePart.context.list.one": "{{count}} lista",
+  "ui.messagePart.context.list.other": "{{count}} listy",
   "ui.messagePart.diagnostic.error": "Błąd",
   "ui.messagePart.title.edit": "Edycja",
   "ui.messagePart.title.write": "Pisanie",
@@ -71,6 +81,7 @@ export const dict = {
   "ui.textField.copied": "Skopiowano",
 
   "ui.imagePreview.alt": "Podgląd obrazu",
+  "ui.scrollView.ariaLabel": "treść przewijana",
 
   "ui.tool.read": "Odczyt",
   "ui.tool.loaded": "Załadowano",

+ 11 - 0
packages/ui/src/i18n/ru.ts

@@ -3,6 +3,9 @@ export const dict = {
   "ui.sessionReview.title.lastTurn": "Изменения последнего хода",
   "ui.sessionReview.diffStyle.unified": "Объединённый",
   "ui.sessionReview.diffStyle.split": "Разделённый",
+  "ui.sessionReview.openFile": "Открыть файл",
+  "ui.sessionReview.selection.line": "строка {{line}}",
+  "ui.sessionReview.selection.lines": "строки {{start}}-{{end}}",
   "ui.sessionReview.expandAll": "Развернуть всё",
   "ui.sessionReview.collapseAll": "Свернуть всё",
 
@@ -52,6 +55,13 @@ export const dict = {
   "ui.sessionTurn.status.gatheringThoughts": "Сбор мыслей",
   "ui.sessionTurn.status.consideringNextSteps": "Рассмотрение следующих шагов",
 
+  "ui.messagePart.questions.dismissed": "Вопросы отклонены",
+  "ui.messagePart.context.read.one": "{{count}} чтение",
+  "ui.messagePart.context.read.other": "{{count}} чтений",
+  "ui.messagePart.context.search.one": "{{count}} поиск",
+  "ui.messagePart.context.search.other": "{{count}} поисков",
+  "ui.messagePart.context.list.one": "{{count}} список",
+  "ui.messagePart.context.list.other": "{{count}} списков",
   "ui.messagePart.diagnostic.error": "Ошибка",
   "ui.messagePart.title.edit": "Редактировать",
   "ui.messagePart.title.write": "Написать",
@@ -71,6 +81,7 @@ export const dict = {
   "ui.textField.copied": "Скопировано",
 
   "ui.imagePreview.alt": "Предпросмотр изображения",
+  "ui.scrollView.ariaLabel": "прокручиваемый контент",
 
   "ui.tool.read": "Чтение",
   "ui.tool.loaded": "Загружено",

+ 11 - 0
packages/ui/src/i18n/th.ts

@@ -3,6 +3,9 @@ export const dict = {
   "ui.sessionReview.title.lastTurn": "การเปลี่ยนแปลงของเทิร์นล่าสุด",
   "ui.sessionReview.diffStyle.unified": "แบบรวม",
   "ui.sessionReview.diffStyle.split": "แบบแยก",
+  "ui.sessionReview.openFile": "เปิดไฟล์",
+  "ui.sessionReview.selection.line": "บรรทัดที่ {{line}}",
+  "ui.sessionReview.selection.lines": "บรรทัดที่ {{start}}-{{end}}",
   "ui.sessionReview.expandAll": "ขยายทั้งหมด",
   "ui.sessionReview.collapseAll": "ย่อทั้งหมด",
   "ui.sessionReview.change.added": "เพิ่ม",
@@ -54,6 +57,13 @@ export const dict = {
   "ui.sessionTurn.status.gatheringThoughts": "รวบรวมความคิด",
   "ui.sessionTurn.status.consideringNextSteps": "พิจารณาขั้นตอนถัดไป",
 
+  "ui.messagePart.questions.dismissed": "ละทิ้งคำถามแล้ว",
+  "ui.messagePart.context.read.one": "อ่าน {{count}} รายการ",
+  "ui.messagePart.context.read.other": "อ่าน {{count}} รายการ",
+  "ui.messagePart.context.search.one": "ค้นหา {{count}} รายการ",
+  "ui.messagePart.context.search.other": "ค้นหา {{count}} รายการ",
+  "ui.messagePart.context.list.one": "รายการ {{count}} รายการ",
+  "ui.messagePart.context.list.other": "รายการ {{count}} รายการ",
   "ui.messagePart.diagnostic.error": "ข้อผิดพลาด",
   "ui.messagePart.title.edit": "แก้ไข",
   "ui.messagePart.title.write": "เขียน",
@@ -73,6 +83,7 @@ export const dict = {
   "ui.textField.copied": "คัดลอกแล้ว",
 
   "ui.imagePreview.alt": "ตัวอย่างรูปภาพ",
+  "ui.scrollView.ariaLabel": "เนื้อหาที่เลื่อนได้",
 
   "ui.tool.read": "อ่าน",
   "ui.tool.loaded": "โหลดแล้ว",

+ 11 - 0
packages/ui/src/i18n/tr.ts

@@ -7,6 +7,9 @@ export const dict = {
   "ui.sessionReview.title.lastTurn": "Son tur değişiklikleri",
   "ui.sessionReview.diffStyle.unified": "Birleşik",
   "ui.sessionReview.diffStyle.split": "Bölünmüş",
+  "ui.sessionReview.openFile": "Dosyayı aç",
+  "ui.sessionReview.selection.line": "satır {{line}}",
+  "ui.sessionReview.selection.lines": "satırlar {{start}}-{{end}}",
   "ui.sessionReview.expandAll": "Tümünü genişlet",
   "ui.sessionReview.collapseAll": "Tümünü daralt",
 
@@ -49,6 +52,13 @@ export const dict = {
   "ui.sessionTurn.status.gatheringThoughts": "Düşünceler toplanıyor",
   "ui.sessionTurn.status.consideringNextSteps": "Sonraki adımlar değerlendiriliyor",
 
+  "ui.messagePart.questions.dismissed": "Sorular reddedildi",
+  "ui.messagePart.context.read.one": "{{count}} okuma",
+  "ui.messagePart.context.read.other": "{{count}} okuma",
+  "ui.messagePart.context.search.one": "{{count}} arama",
+  "ui.messagePart.context.search.other": "{{count}} arama",
+  "ui.messagePart.context.list.one": "{{count}} liste",
+  "ui.messagePart.context.list.other": "{{count}} liste",
   "ui.messagePart.diagnostic.error": "Hata",
   "ui.messagePart.title.edit": "Düzenle",
   "ui.messagePart.title.write": "Yaz",
@@ -68,6 +78,7 @@ export const dict = {
   "ui.textField.copied": "Kopyalandı",
 
   "ui.imagePreview.alt": "Görsel önizleme",
+  "ui.scrollView.ariaLabel": "kaydırılabilir içerik",
 
   "ui.tool.read": "Oku",
   "ui.tool.loaded": "Yüklendi",

+ 11 - 0
packages/ui/src/i18n/zh.ts

@@ -7,6 +7,9 @@ export const dict = {
   "ui.sessionReview.title.lastTurn": "上一轮变更",
   "ui.sessionReview.diffStyle.unified": "统一",
   "ui.sessionReview.diffStyle.split": "拆分",
+  "ui.sessionReview.openFile": "打开文件",
+  "ui.sessionReview.selection.line": "第 {{line}} 行",
+  "ui.sessionReview.selection.lines": "第 {{start}}-{{end}} 行",
   "ui.sessionReview.expandAll": "全部展开",
   "ui.sessionReview.collapseAll": "全部收起",
   "ui.sessionReview.change.added": "已添加",
@@ -57,6 +60,13 @@ export const dict = {
   "ui.sessionTurn.status.gatheringThoughts": "正在整理思路",
   "ui.sessionTurn.status.consideringNextSteps": "正在考虑下一步",
 
+  "ui.messagePart.questions.dismissed": "问题已忽略",
+  "ui.messagePart.context.read.one": "{{count}} 次读取",
+  "ui.messagePart.context.read.other": "{{count}} 次读取",
+  "ui.messagePart.context.search.one": "{{count}} 次搜索",
+  "ui.messagePart.context.search.other": "{{count}} 次搜索",
+  "ui.messagePart.context.list.one": "{{count}} 个列表",
+  "ui.messagePart.context.list.other": "{{count}} 个列表",
   "ui.messagePart.diagnostic.error": "错误",
   "ui.messagePart.title.edit": "编辑",
   "ui.messagePart.title.write": "写入",
@@ -76,6 +86,7 @@ export const dict = {
   "ui.textField.copied": "已复制",
 
   "ui.imagePreview.alt": "图片预览",
+  "ui.scrollView.ariaLabel": "可滚动内容",
 
   "ui.tool.read": "读取",
   "ui.tool.loaded": "已加载",

+ 11 - 0
packages/ui/src/i18n/zht.ts

@@ -7,6 +7,9 @@ export const dict = {
   "ui.sessionReview.title.lastTurn": "上一輪變更",
   "ui.sessionReview.diffStyle.unified": "整合",
   "ui.sessionReview.diffStyle.split": "拆分",
+  "ui.sessionReview.openFile": "開啟檔案",
+  "ui.sessionReview.selection.line": "第 {{line}} 行",
+  "ui.sessionReview.selection.lines": "第 {{start}}-{{end}} 行",
   "ui.sessionReview.expandAll": "全部展開",
   "ui.sessionReview.collapseAll": "全部收合",
   "ui.sessionReview.change.added": "已新增",
@@ -57,6 +60,13 @@ export const dict = {
   "ui.sessionTurn.status.gatheringThoughts": "正在整理思緒",
   "ui.sessionTurn.status.consideringNextSteps": "正在考慮下一步",
 
+  "ui.messagePart.questions.dismissed": "問題已略過",
+  "ui.messagePart.context.read.one": "{{count}} 次讀取",
+  "ui.messagePart.context.read.other": "{{count}} 次讀取",
+  "ui.messagePart.context.search.one": "{{count}} 次搜尋",
+  "ui.messagePart.context.search.other": "{{count}} 次搜尋",
+  "ui.messagePart.context.list.one": "{{count}} 個清單",
+  "ui.messagePart.context.list.other": "{{count}} 個清單",
   "ui.messagePart.diagnostic.error": "錯誤",
   "ui.messagePart.title.edit": "編輯",
   "ui.messagePart.title.write": "寫入",
@@ -76,6 +86,7 @@ export const dict = {
   "ui.textField.copied": "已複製",
 
   "ui.imagePreview.alt": "圖片預覽",
+  "ui.scrollView.ariaLabel": "可捲動內容",
 
   "ui.tool.read": "讀取",
   "ui.tool.loaded": "已載入",