- Last modified
+ {t().session.lastModified}
{DateTime.fromMillis(project().time.updated ?? project().time.created).toRelative()}
diff --git a/packages/app/src/i18n/context.tsx b/packages/app/src/i18n/context.tsx
new file mode 100644
index 000000000000..4835e3429eb6
--- /dev/null
+++ b/packages/app/src/i18n/context.tsx
@@ -0,0 +1,71 @@
+import { createContext, useContext, Accessor, Setter, createSignal, createRoot } from "solid-js"
+import { useStorage } from "@solid-primitives/storage"
+import { locales, type Locale, type Translation, defaultLocale, supportedLocales } from "./locales"
+
+type I18nContextValue = {
+ locale: Accessor
+ setLocale: Setter
+ t: Accessor
+ locales: typeof supportedLocales
+}
+
+const I18nContext = createContext()
+
+export function I18nProvider(props: { children: any }) {
+ const [locale, setLocale] = createSignal(defaultLocale)
+
+ // Initialize from localStorage or browser language
+ const initializeLocale = () => {
+ const stored = localStorage.getItem("opencode-locale") as Locale | null
+ if (stored && supportedLocales.includes(stored)) {
+ setLocale(stored)
+ return
+ }
+
+ // Detect browser language
+ const browserLang = navigator.language
+ if (browserLang.startsWith("zh")) {
+ setLocale("zh-CN")
+ } else if (browserLang.startsWith("ja")) {
+ setLocale("ja")
+ } else if (browserLang.startsWith("fr")) {
+ setLocale("fr")
+ } else if (browserLang.startsWith("es")) {
+ setLocale("es")
+ }
+ }
+ initializeLocale()
+
+ // Persist locale changes
+ const persistLocale: Setter = (...args) => {
+ const result = setLocale(...args)
+ const newLocale = locale()
+ localStorage.setItem("opencode-locale", newLocale)
+ return result
+ }
+
+ const t = () => locales[locale()]
+
+ const value: I18nContextValue = {
+ locale,
+ setLocale: persistLocale,
+ t,
+ locales: supportedLocales,
+ }
+
+ return {props.children}
+}
+
+export function useI18n() {
+ const context = useContext(I18nContext)
+ if (!context) {
+ throw new Error("useI18n must be used within I18nProvider")
+ }
+ return context
+}
+
+// Helper to get nested translation values
+export function useT() {
+ const { t } = useI18n()
+ return t
+}
diff --git a/packages/app/src/i18n/index.ts b/packages/app/src/i18n/index.ts
new file mode 100644
index 000000000000..580f87100eb4
--- /dev/null
+++ b/packages/app/src/i18n/index.ts
@@ -0,0 +1,2 @@
+export { I18nProvider, useI18n, useT } from "./context"
+export { locales, defaultLocale, supportedLocales, type Locale, type Translation } from "./locales"
diff --git a/packages/app/src/i18n/locales/en.ts b/packages/app/src/i18n/locales/en.ts
new file mode 100644
index 000000000000..8557f8c39037
--- /dev/null
+++ b/packages/app/src/i18n/locales/en.ts
@@ -0,0 +1,108 @@
+export default {
+ common: {
+ loading: "Loading...",
+ save: "Save",
+ cancel: "Cancel",
+ confirm: "Confirm",
+ delete: "Delete",
+ edit: "Edit",
+ search: "Search",
+ back: "Back",
+ next: "Next",
+ close: "Close",
+ },
+ home: {
+ title: "OpenCode AI",
+ subtitle: "AI-powered development tool",
+ start: "Start Coding",
+ recentProjects: "Recent projects",
+ noRecentProjects: "No recent projects",
+ getStarted: "Get started by opening a local project",
+ openProject: "Open project",
+ },
+ session: {
+ new: "New Session",
+ newSession: "New session",
+ mainBranch: "Main branch",
+ mainBranchWithName: "Main branch ({branch})",
+ createWorktree: "Create new worktree",
+ lastModified: "Last modified",
+ backToParent: "Back to parent session",
+ share: "Share session",
+ terminate: "Terminate",
+ archive: "Archive session",
+ filesChanged: "{count} file{plural} changed",
+ },
+ dialog: {
+ selectProvider: {
+ title: "Select Provider",
+ description: "Choose an AI provider to use",
+ },
+ selectModel: {
+ title: "Select Model",
+ description: "Choose a model to use",
+ unpaid: {
+ title: "Model Payment Required",
+ description: "This model requires payment to use",
+ },
+ },
+ selectServer: {
+ title: "Select Server",
+ description: "Choose a server to connect to",
+ },
+ selectDirectory: {
+ title: "Select Directory",
+ description: "Choose a directory to work with",
+ openProject: "Open project",
+ },
+ selectFile: {
+ title: "Select File",
+ description: "Choose a file to work with",
+ },
+ selectMcp: {
+ title: "Select MCP",
+ description: "Choose a Model Context Protocol server",
+ },
+ connectProvider: {
+ title: "Connect Provider",
+ description: "Configure your AI provider credentials",
+ },
+ editProject: {
+ title: "Edit Project",
+ description: "Edit project settings",
+ editProject: "Edit project",
+ closeProject: "Close project",
+ },
+ manageModels: {
+ title: "Manage Models",
+ description: "Manage available models",
+ },
+ },
+ terminal: {
+ tabs: {
+ session: "Session",
+ context: "Context",
+ lsp: "LSP",
+ mcp: "MCP",
+ },
+ },
+ fileTree: {
+ empty: "No files found",
+ refresh: "Refresh",
+ },
+ sidebar: {
+ toggle: "Toggle sidebar",
+ newSession: "New session",
+ loadMore: "Load more",
+ gettingStarted: "Getting started",
+ gettingStartedDesc1: "OpenCode includes free models so you can start immediately.",
+ gettingStartedDesc2: "Connect any provider to use models, inc. Claude, GPT, Gemini etc.",
+ connectProvider: "Connect provider",
+ shareFeedback: "Share feedback",
+ changeLanguage: "Change language",
+ },
+ layout: {
+ editProject: "Edit project",
+ closeProject: "Close project",
+ },
+} as const
diff --git a/packages/app/src/i18n/locales/es.ts b/packages/app/src/i18n/locales/es.ts
new file mode 100644
index 000000000000..207da6fd659d
--- /dev/null
+++ b/packages/app/src/i18n/locales/es.ts
@@ -0,0 +1,108 @@
+export default {
+ common: {
+ loading: "Cargando...",
+ save: "Guardar",
+ cancel: "Cancelar",
+ confirm: "Confirmar",
+ delete: "Eliminar",
+ edit: "Editar",
+ search: "Buscar",
+ back: "Atrás",
+ next: "Siguiente",
+ close: "Cerrar",
+ },
+ home: {
+ title: "OpenCode AI",
+ subtitle: "Herramienta de desarrollo impulsada por IA",
+ start: "Comenzar a codificar",
+ recentProjects: "Proyectos recientes",
+ noRecentProjects: "Sin proyectos recientes",
+ getStarted: "Abre un proyecto local para comenzar",
+ openProject: "Abrir proyecto",
+ },
+ session: {
+ new: "Nueva sesión",
+ newSession: "Nueva sesión",
+ mainBranch: "Rama principal",
+ mainBranchWithName: "Rama principal ({branch})",
+ createWorktree: "Crear nuevo árbol de trabajo",
+ lastModified: "Última modificación",
+ backToParent: "Volver a la sesión principal",
+ share: "Compartir sesión",
+ terminate: "Terminar",
+ archive: "Archivar sesión",
+ filesChanged: "{count} archivo{plural} modificado{plural}",
+ },
+ dialog: {
+ selectProvider: {
+ title: "Seleccionar proveedor",
+ description: "Elige un proveedor de IA para usar",
+ },
+ selectModel: {
+ title: "Seleccionar modelo",
+ description: "Elige un modelo para usar",
+ unpaid: {
+ title: "Pago del modelo requerido",
+ description: "Este modelo requiere pago para usarse",
+ },
+ },
+ selectServer: {
+ title: "Seleccionar servidor",
+ description: "Elige un servidor al cual conectarse",
+ },
+ selectDirectory: {
+ title: "Seleccionar directorio",
+ description: "Elige un directorio con el cual trabajar",
+ openProject: "Abrir proyecto",
+ },
+ selectFile: {
+ title: "Seleccionar archivo",
+ description: "Elige un archivo con el cual trabajar",
+ },
+ selectMcp: {
+ title: "Seleccionar MCP",
+ description: "Elige un servidor Model Context Protocol",
+ },
+ connectProvider: {
+ title: "Conectar proveedor",
+ description: "Configura tus credenciales de proveedor de IA",
+ },
+ editProject: {
+ title: "Editar proyecto",
+ description: "Edita la configuración del proyecto",
+ editProject: "Editar proyecto",
+ closeProject: "Cerrar proyecto",
+ },
+ manageModels: {
+ title: "Administrar modelos",
+ description: "Administra los modelos disponibles",
+ },
+ },
+ terminal: {
+ tabs: {
+ session: "Sesión",
+ context: "Contexto",
+ lsp: "LSP",
+ mcp: "MCP",
+ },
+ },
+ fileTree: {
+ empty: "No se encontraron archivos",
+ refresh: "Actualizar",
+ },
+ sidebar: {
+ toggle: "Alternar barra lateral",
+ newSession: "Nueva sesión",
+ loadMore: "Cargar más",
+ gettingStarted: "Comenzando",
+ gettingStartedDesc1: "OpenCode incluye modelos gratuitos para que puedas comenzar de inmediato.",
+ gettingStartedDesc2: "Conecta cualquier proveedor para usar modelos, incl. Claude, GPT, Gemini, etc.",
+ connectProvider: "Conectar proveedor",
+ shareFeedback: "Comentar comentarios",
+ changeLanguage: "Cambiar idioma",
+ },
+ layout: {
+ editProject: "Editar proyecto",
+ closeProject: "Cerrar proyecto",
+ },
+} as const
diff --git a/packages/app/src/i18n/locales/fr.ts b/packages/app/src/i18n/locales/fr.ts
new file mode 100644
index 000000000000..eb52d3e531a7
--- /dev/null
+++ b/packages/app/src/i18n/locales/fr.ts
@@ -0,0 +1,108 @@
+export default {
+ common: {
+ loading: "Chargement...",
+ save: "Enregistrer",
+ cancel: "Annuler",
+ confirm: "Confirmer",
+ delete: "Supprimer",
+ edit: "Modifier",
+ search: "Rechercher",
+ back: "Retour",
+ next: "Suivant",
+ close: "Fermer",
+ },
+ home: {
+ title: "OpenCode AI",
+ subtitle: "Outil de développement alimenté par l'IA",
+ start: "Commencer à coder",
+ recentProjects: "Projets récents",
+ noRecentProjects: "Aucun projet récent",
+ getStarted: "Ouvrez un projet local pour commencer",
+ openProject: "Ouvrir un projet",
+ },
+ session: {
+ new: "Nouvelle session",
+ newSession: "Nouvelle session",
+ mainBranch: "Branche principale",
+ mainBranchWithName: "Branche principale ({branch})",
+ createWorktree: "Créer un nouvel arbre de travail",
+ lastModified: "Dernière modification",
+ backToParent: "Retour à la session parente",
+ share: "Partager la session",
+ terminate: "Terminer",
+ archive: "Archiver la session",
+ filesChanged: "{count} fichier{plural} modifié{plural}",
+ },
+ dialog: {
+ selectProvider: {
+ title: "Sélectionner un fournisseur",
+ description: "Choisir un fournisseur d'IA à utiliser",
+ },
+ selectModel: {
+ title: "Sélectionner un modèle",
+ description: "Choisir un modèle à utiliser",
+ unpaid: {
+ title: "Paiement du modèle requis",
+ description: "Ce modèle nécessite un paiement pour être utilisé",
+ },
+ },
+ selectServer: {
+ title: "Sélectionner un serveur",
+ description: "Choisir un serveur auquel se connecter",
+ },
+ selectDirectory: {
+ title: "Sélectionner un répertoire",
+ description: "Choisir un répertoire avec lequel travailler",
+ openProject: "Ouvrir un projet",
+ },
+ selectFile: {
+ title: "Sélectionner un fichier",
+ description: "Choisir un fichier avec lequel travailler",
+ },
+ selectMcp: {
+ title: "Sélectionner un MCP",
+ description: "Choisir un serveur Model Context Protocol",
+ },
+ connectProvider: {
+ title: "Connecter un fournisseur",
+ description: "Configurer vos identifiants de fournisseur d'IA",
+ },
+ editProject: {
+ title: "Modifier le projet",
+ description: "Modifier les paramètres du projet",
+ editProject: "Modifier le projet",
+ closeProject: "Fermer le projet",
+ },
+ manageModels: {
+ title: "Gérer les modèles",
+ description: "Gérer les modèles disponibles",
+ },
+ },
+ terminal: {
+ tabs: {
+ session: "Session",
+ context: "Contexte",
+ lsp: "LSP",
+ mcp: "MCP",
+ },
+ },
+ fileTree: {
+ empty: "Aucun fichier trouvé",
+ refresh: "Actualiser",
+ },
+ sidebar: {
+ toggle: "Afficher/Masquer la barre latérale",
+ newSession: "Nouvelle session",
+ loadMore: "Charger plus",
+ gettingStarted: "Premiers pas",
+ gettingStartedDesc1: "OpenCode inclut des modèles gratuits pour que vous puissiez commencer immédiatement.",
+ gettingStartedDesc2: "Connectez n'importe quel fournisseur pour utiliser des modèles, y compris Claude, GPT, Gemini, etc.",
+ connectProvider: "Connecter un fournisseur",
+ shareFeedback: "Partager des commentaires",
+ changeLanguage: "Changer de langue",
+ },
+ layout: {
+ editProject: "Modifier le projet",
+ closeProject: "Fermer le projet",
+ },
+} as const
diff --git a/packages/app/src/i18n/locales/index.ts b/packages/app/src/i18n/locales/index.ts
new file mode 100644
index 000000000000..ddf15d5609c0
--- /dev/null
+++ b/packages/app/src/i18n/locales/index.ts
@@ -0,0 +1,19 @@
+import en from "./en"
+import zhCN from "./zh-CN"
+import ja from "./ja"
+import fr from "./fr"
+import es from "./es"
+
+export const locales = {
+ en,
+ "zh-CN": zhCN,
+ ja,
+ fr,
+ es,
+} as const
+
+export type Locale = keyof typeof locales
+export const defaultLocale: Locale = "en"
+export const supportedLocales: Locale[] = Object.keys(locales) as Locale[]
+
+export type Translation = typeof locales[Locale]
diff --git a/packages/app/src/i18n/locales/ja.ts b/packages/app/src/i18n/locales/ja.ts
new file mode 100644
index 000000000000..cf59d9878ae4
--- /dev/null
+++ b/packages/app/src/i18n/locales/ja.ts
@@ -0,0 +1,108 @@
+export default {
+ common: {
+ loading: "読み込み中...",
+ save: "保存",
+ cancel: "キャンセル",
+ confirm: "確認",
+ delete: "削除",
+ edit: "編集",
+ search: "検索",
+ back: "戻る",
+ next: "次へ",
+ close: "閉じる",
+ },
+ home: {
+ title: "OpenCode AI",
+ subtitle: "AI による開発ツール",
+ start: "コーディングを開始",
+ recentProjects: "最近のプロジェクト",
+ noRecentProjects: "最近のプロジェクトがありません",
+ getStarted: "ローカルプロジェクトを開いて始めましょう",
+ openProject: "プロジェクトを開く",
+ },
+ session: {
+ new: "新しいセッション",
+ newSession: "新しいセッション",
+ mainBranch: "メインブランチ",
+ mainBranchWithName: "メインブランチ ({branch})",
+ createWorktree: "新しいワークツリーを作成",
+ lastModified: "最終更新",
+ backToParent: "親セッションに戻る",
+ share: "セッションを共有",
+ terminate: "終了",
+ archive: "セッションをアーカイブ",
+ filesChanged: "{count} ファイルが変更されました",
+ },
+ dialog: {
+ selectProvider: {
+ title: "プロバイダーを選択",
+ description: "使用する AI プロバイダーを選択してください",
+ },
+ selectModel: {
+ title: "モデルを選択",
+ description: "使用するモデルを選択してください",
+ unpaid: {
+ title: "モデルの支払いが必要",
+ description: "このモデルを使用するには支払いが必要です",
+ },
+ },
+ selectServer: {
+ title: "サーバーを選択",
+ description: "接続するサーバーを選択してください",
+ },
+ selectDirectory: {
+ title: "ディレクトリを選択",
+ description: "使用するディレクトリを選択してください",
+ openProject: "プロジェクトを開く",
+ },
+ selectFile: {
+ title: "ファイルを選択",
+ description: "使用するファイルを選択してください",
+ },
+ selectMcp: {
+ title: "MCP を選択",
+ description: "モデル コンテキスト プロトコル サーバーを選択してください",
+ },
+ connectProvider: {
+ title: "プロバイダーに接続",
+ description: "AI プロバイダーの認証情報を設定してください",
+ },
+ editProject: {
+ title: "プロジェクトを編集",
+ description: "プロジェクト設定を編集してください",
+ editProject: "プロジェクトを編集",
+ closeProject: "プロジェクトを閉じる",
+ },
+ manageModels: {
+ title: "モデルを管理",
+ description: "利用可能なモデルを管理してください",
+ },
+ },
+ terminal: {
+ tabs: {
+ session: "セッション",
+ context: "コンテキスト",
+ lsp: "LSP",
+ mcp: "MCP",
+ },
+ },
+ fileTree: {
+ empty: "ファイルが見つかりません",
+ refresh: "更新",
+ },
+ sidebar: {
+ toggle: "サイドバーを切り替え",
+ newSession: "新しいセッション",
+ loadMore: "もっと見る",
+ gettingStarted: "はじめに",
+ gettingStartedDesc1: "OpenCode には無料モデルが含まれており、すぐに始められます。",
+ gettingStartedDesc2: "プロバイダーを接続してモデルを使用できます(Claude、GPT、Gemini など)。",
+ connectProvider: "プロバイダーに接続",
+ shareFeedback: "フィードバックを共有",
+ changeLanguage: "言語を変更",
+ },
+ layout: {
+ editProject: "プロジェクトを編集",
+ closeProject: "プロジェクトを閉じる",
+ },
+} as const
diff --git a/packages/app/src/i18n/locales/zh-CN.ts b/packages/app/src/i18n/locales/zh-CN.ts
new file mode 100644
index 000000000000..ec32202d07f7
--- /dev/null
+++ b/packages/app/src/i18n/locales/zh-CN.ts
@@ -0,0 +1,108 @@
+export default {
+ common: {
+ loading: "加载中...",
+ save: "保存",
+ cancel: "取消",
+ confirm: "确认",
+ delete: "删除",
+ edit: "编辑",
+ search: "搜索",
+ back: "返回",
+ next: "下一步",
+ close: "关闭",
+ },
+ home: {
+ title: "OpenCode AI",
+ subtitle: "AI 驱动的开发工具",
+ start: "开始编码",
+ recentProjects: "最近的项目",
+ noRecentProjects: "没有最近的项目",
+ getStarted: "打开本地项目开始使用",
+ openProject: "打开项目",
+ },
+ session: {
+ new: "新会话",
+ newSession: "新会话",
+ mainBranch: "主分支",
+ mainBranchWithName: "主分支 ({branch})",
+ createWorktree: "创建新工作树",
+ lastModified: "最后修改",
+ backToParent: "返回父会话",
+ share: "分享会话",
+ terminate: "终止",
+ archive: "归档会话",
+ filesChanged: "{count} 个文件已更改",
+ },
+ dialog: {
+ selectProvider: {
+ title: "选择提供商",
+ description: "选择要使用的 AI 提供商",
+ },
+ selectModel: {
+ title: "选择模型",
+ description: "选择要使用的模型",
+ unpaid: {
+ title: "模型需要付费",
+ description: "此模型需要付费才能使用",
+ },
+ },
+ selectServer: {
+ title: "选择服务器",
+ description: "选择要连接的服务器",
+ },
+ selectDirectory: {
+ title: "选择目录",
+ description: "选择要使用的目录",
+ openProject: "打开项目",
+ },
+ selectFile: {
+ title: "选择文件",
+ description: "选择要使用的文件",
+ },
+ selectMcp: {
+ title: "选择 MCP",
+ description: "选择模型上下文协议服务器",
+ },
+ connectProvider: {
+ title: "连接提供商",
+ description: "配置您的 AI 提供商凭据",
+ },
+ editProject: {
+ title: "编辑项目",
+ description: "编辑项目设置",
+ editProject: "编辑项目",
+ closeProject: "关闭项目",
+ },
+ manageModels: {
+ title: "管理模型",
+ description: "管理可用模型",
+ },
+ },
+ terminal: {
+ tabs: {
+ session: "会话",
+ context: "上下文",
+ lsp: "LSP",
+ mcp: "MCP",
+ },
+ },
+ fileTree: {
+ empty: "未找到文件",
+ refresh: "刷新",
+ },
+ sidebar: {
+ toggle: "切换侧边栏",
+ newSession: "新会话",
+ loadMore: "加载更多",
+ gettingStarted: "入门指南",
+ gettingStartedDesc1: "OpenCode 包含免费模型,您可以立即开始使用。",
+ gettingStartedDesc2: "连接任何提供商以使用模型,包括 Claude、GPT、Gemini 等。",
+ connectProvider: "连接提供商",
+ shareFeedback: "分享反馈",
+ changeLanguage: "切换语言",
+ },
+ layout: {
+ editProject: "编辑项目",
+ closeProject: "关闭项目",
+ },
+} as const
diff --git a/packages/app/src/pages/home.tsx b/packages/app/src/pages/home.tsx
index 275113566ad1..8e3358d0238b 100644
--- a/packages/app/src/pages/home.tsx
+++ b/packages/app/src/pages/home.tsx
@@ -12,6 +12,7 @@ import { useDialog } from "@opencode-ai/ui/context/dialog"
import { DialogSelectDirectory } from "@/components/dialog-select-directory"
import { DialogSelectServer } from "@/components/dialog-select-server"
import { useServer } from "@/context/server"
+import { useI18n } from "@/i18n"
export default function Home() {
const sync = useGlobalSync()
@@ -20,6 +21,7 @@ export default function Home() {
const dialog = useDialog()
const navigate = useNavigate()
const server = useServer()
+ const { t } = useI18n()
const homedir = createMemo(() => sync.data.path.home)
function openProject(directory: string) {
@@ -40,7 +42,7 @@ export default function Home() {
if (platform.openDirectoryPickerDialog && server.isLocal()) {
const result = await platform.openDirectoryPickerDialog?.({
- title: "Open project",
+ title: t().home.openProject,
multiple: true,
})
resolve(result)
@@ -75,9 +77,9 @@ export default function Home() {
0}>
-
Recent projects
+
{t().home.recentProjects}
@@ -107,12 +109,12 @@ export default function Home() {
-
No recent projects
-
Get started by opening a local project
+
{t().home.noRecentProjects}
+
{t().home.getStarted}
diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx
index 85d61d57beb9..c7dd5517d023 100644
--- a/packages/app/src/pages/layout.tsx
+++ b/packages/app/src/pages/layout.tsx
@@ -53,10 +53,12 @@ import { useTheme, type ColorScheme } from "@opencode-ai/ui/theme"
import { DialogSelectProvider } from "@/components/dialog-select-provider"
import { DialogEditProject } from "@/components/dialog-edit-project"
import { DialogSelectServer } from "@/components/dialog-select-server"
+import { DialogSelectLanguage } from "@/components/dialog-select-language"
import { useCommand, type CommandOption } from "@/context/command"
import { ConstrainDragXAxis } from "@/utils/solid-dnd"
import { DialogSelectDirectory } from "@/components/dialog-select-directory"
import { useServer } from "@/context/server"
+import { useI18n } from "@/i18n"
export default function Layout(props: ParentProps) {
const [store, setStore] = createStore({
@@ -91,6 +93,7 @@ export default function Layout(props: ParentProps) {
const dialog = useDialog()
const command = useCommand()
const theme = useTheme()
+ const { t } = useI18n()
const availableThemeEntries = createMemo(() => Object.entries(theme.themes()))
const colorSchemeOrder: ColorScheme[] = ["system", "light", "dark"]
const colorSchemeLabel: Record = {
@@ -176,7 +179,7 @@ export default function Layout(props: ParentProps) {
const session = store.session.find((s) => s.id === perm.sessionID)
const sessionKey = `${directory}:${perm.sessionID}`
- const sessionTitle = session?.title ?? "New session"
+ const sessionTitle = session?.title ?? t().session.newSession
const projectName = getFilename(directory)
const description = `${sessionTitle} in ${projectName} needs permission`
const href = `/${base64Encode(directory)}/session/${perm.sessionID}`
@@ -359,21 +362,21 @@ export default function Layout(props: ParentProps) {
const commands: CommandOption[] = [
{
id: "sidebar.toggle",
- title: "Toggle sidebar",
+ title: t().sidebar.toggle,
category: "View",
keybind: "mod+b",
onSelect: () => layout.sidebar.toggle(),
},
{
id: "project.open",
- title: "Open project",
+ title: t().home.openProject,
category: "Project",
keybind: "mod+o",
onSelect: () => chooseProject(),
},
{
id: "provider.connect",
- title: "Connect provider",
+ title: t().sidebar.connectProvider,
category: "Provider",
onSelect: () => connectProvider(),
},
@@ -397,9 +400,19 @@ export default function Layout(props: ParentProps) {
keybind: "alt+arrowdown",
onSelect: () => navigateSessionByOffset(1),
},
+ {
+ id: "session.new",
+ title: t().session.newSession,
+ category: "Session",
+ keybind: "mod+n",
+ onSelect: () => {
+ const current = params.dir ? base64Decode(params.dir) : undefined
+ if (current) navigate(`/${params.dir}/session`)
+ },
+ },
{
id: "session.archive",
- title: "Archive session",
+ title: t().session.archive,
category: "Session",
keybind: "mod+shift+backspace",
disabled: !params.dir || !params.id,
@@ -732,7 +745,7 @@ export default function Layout(props: ParentProps) {
archiveSession(props.session)} />
@@ -810,15 +823,15 @@ export default function Layout(props: ParentProps) {
dialog.show(() => )}
>
- Edit project
+ {t().layout.editProject}
closeProject(props.project.worktree)}>
- Close project
+ {t().layout.closeProject}
-
+
@@ -842,14 +855,14 @@ export default function Layout(props: ParentProps) {
>
@@ -918,8 +931,7 @@ export default function Layout(props: ParentProps) {
@@ -948,7 +960,7 @@ export default function Layout(props: ParentProps) {
@@ -985,24 +997,24 @@ export default function Layout(props: ParentProps) {
0 && !providers.paid().length && expanded()}>
-
Getting started
-
OpenCode includes free models so you can start immediately.
-
Connect any provider to use models, inc. Claude, GPT, Gemini etc.
+
{t().sidebar.gettingStarted}
+
{t().sidebar.gettingStartedDesc1}
+
{t().sidebar.gettingStartedDesc2}
-
+
0}>
-
+
@@ -1019,7 +1031,7 @@ export default function Layout(props: ParentProps) {
placement="right"
value={
- Open project
+ {t().home.openProject}
{command.keybind("project.open")}
@@ -1034,10 +1046,10 @@ export default function Layout(props: ParentProps) {
icon="folder-add-left"
onClick={chooseProject}
>
- Open project
+ {t().home.openProject}
-
+
+
+
+