/** * Locale strings for the panel surfaces (zh/en). The client registers the * dictionary through the locale service like the sibling plugins; copy is * deliberately short and technical. * @module dsh-aionui-panel/client/locales */ const zh = { 'explorer.tabs.files': '文件', 'explorer.tabs.changes': '变更', 'explorer.search.placeholder': '按文件名搜索', 'explorer.search.searching': '搜索中…', 'explorer.search.empty': '没有匹配的文件', 'explorer.search.error': '搜索失败', 'explorer.search.truncated': '结果过多,仅显示前 {count} 条', 'explorer.tree.empty': '项目为空', 'explorer.collapse': '收起面板', 'explorer.expand': '展开面板', 'explorer.maximize': '最大化文件面板', 'explorer.restore': '还原面板', 'explorer.openPreview': '打开预览', 'explorer.drag.dropHint': '松手插入文件路径', 'scm.repositories': '存储库', 'scm.changes': '变更', 'scm.staged': '已暂存', 'scm.unstaged': '变更', 'scm.untracked': '未跟踪', 'scm.conflicted': '冲突', 'scm.stage': '暂存', 'scm.unstage': '取消暂存', 'scm.discard': '放弃更改', 'scm.stageAll': '全部暂存', 'scm.discardAll': '全部放弃', 'scm.empty': '没有更改', 'scm.notRepo': '当前目录不是 git 仓库', 'scm.gitMissing': '未检测到 git,请先安装 git 后重试', 'scm.loading': '读取状态中…', 'scm.failed': '操作失败', 'scm.viewList': '列表视图', 'scm.viewTree': '树视图', 'scm.discardConfirmTracked': '放弃对 {count} 个文件的更改?此操作不可恢复。', 'scm.discardConfirmUntracked': '删除 {count} 个未跟踪文件?此操作不可恢复。', 'preview.noTabs': '没有打开的预览', 'preview.newUrlTab': '新建 URL 预览', 'preview.collapsePanel': '收起预览面板', 'preview.maximize': '最大化预览面板', 'preview.restore': '还原面板', 'preview.source': '源码', 'preview.preview': '预览', 'preview.editor': '编辑器', 'preview.split': '分屏', 'preview.refresh': '刷新', 'preview.refresh.updated': '文件已在磁盘更新', 'preview.save': '保存', 'preview.download': '下载', 'preview.copyCode': '复制代码', 'preview.copyCodeDone': '已复制', 'preview.openExternal': '在系统应用中打开', 'preview.dirty': '未保存的更改', 'preview.closeLeft': '关闭左侧', 'preview.closeRight': '关闭右侧', 'preview.closeOthers': '关闭其他', 'preview.closeAll': '关闭全部', 'preview.closeConfirmTitle': '关闭未保存的标签页', 'preview.closeConfirmBody': '{count} 个标签页有未保存的更改,关闭将丢失这些更改。', 'preview.saved': '已保存', 'preview.saveConflict': '文件已在磁盘上被修改,保存冲突:请刷新后重试', 'preview.errorOversized': '文件过大,仅加载前 80,000 字符', 'preview.unsupported': '此格式暂不支持预览', 'preview.downloadHint': '可在系统应用中打开或下载查看', 'preview.url.placeholder': '输入网址,回车打开', 'preview.url.hint': '按 Esc 还原', 'common.cancel': '取消', 'common.confirm': '确定', 'common.close': '关闭', 'common.delete': '删除', 'common.copyPath': '复制路径', 'common.copied': '已复制', 'explorer.menu.copyPath': '复制路径', 'explorer.menu.copyName': '复制名称', 'explorer.menu.reveal': '在文件管理器中显示', 'explorer.menu.openWithDefault': '用默认应用打开', 'explorer.menu.rename': '重命名', 'explorer.menu.newFile': '新建文件', 'explorer.menu.newFolder': '新建文件夹', 'explorer.menu.delete': '删除', 'explorer.rename.title': '重命名', 'explorer.newFile.title': '新建文件', 'explorer.newFolder.title': '新建文件夹', 'explorer.deleteConfirmTitle': '删除确认', 'explorer.deleteConfirmBody': '确定要删除「{name}」吗?此操作不可恢复。', 'explorer.opFailed': '操作失败', 'settings.title': '侧边卡片', 'settings.description': '右侧面板由侧边卡片提供,来自 DSH-better-sidebar(github.com/omdsh-dev/DSH-better-sidebar)。', 'settings.sourcePrefix': '侧边卡片(右侧面板)由外部插件 DSH-better-sidebar 提供,来自 ', 'settings.sourceSuffix': '。以下为常用设置,改动即时生效。', 'settings.generalTitle': '常规', 'settings.openByDefault': '新会话默认打开', 'settings.openByDefaultHint': '新建会话时自动展开侧边卡片;已存在的会话保持各自布局', 'settings.width': '默认宽度占比', 'settings.widthHint': '新建会话时侧边卡片占窗口宽度的百分比 (20–60)', 'settings.openPath': '聊天区文件在侧边栏打开', 'settings.openPathHint': '在聊天里点击文件链接(工具行、产物列表、文件提及)时,在侧边栏编辑器中打开,不再调用系统默认应用', 'settings.titleBar': '位置兼容模式', 'settings.titleBarHint': '为 Windows 右上角的原生标题栏预留空间:侧边栏按钮与侧边栏内容整体下移,避免被标题栏遮挡', 'settings.tabsTitle': '侧边栏内容', 'settings.viewersTitle': '文件预览', 'settings.prefsLoading': '设置加载中…', 'settings.prefsUnavailable': '侧边卡片设置不可用:未安装 dsh-better-sidebar 或其设置路由不可达。', 'settings.overridden': '已覆盖', 'settings.reset': '恢复默认', 'settings.notExposed': '当前 DSH 版本未向设置页暴露本插件的配置命名空间,表单不可用。可编辑 ~/.dsh/settings.yaml 直接配置,或为 dsh-host-apiproxy 的 WEB_SETTINGS_NAMESPACES 白名单补充本命名空间后重启。', 'settings.readOnly': '当前部署的设置只读。', 'settings.inherit': '继承', 'settings.on': '开', 'settings.off': '关', 'settings.expand': '展开设置', 'settings.collapse': '收起设置', 'settings.save': '保存', 'settings.saving': '保存中…', 'settings.discard': '放弃', 'settings.unsaved': '未保存', 'settings.saveFailed': '部署未接受这些值,已保留供你修改。', 'settings.invalidNumber': '请输入数字,留空则使用默认值。', } as const const en: Record = { 'explorer.tabs.files': 'Files', 'explorer.tabs.changes': 'Changes', 'explorer.search.placeholder': 'Search file names', 'explorer.search.searching': 'Searching…', 'explorer.search.empty': 'No matching files', 'explorer.search.error': 'Search failed', 'explorer.search.truncated': 'Too many results, showing first {count}', 'explorer.tree.empty': 'The project is empty', 'explorer.collapse': 'Collapse panel', 'explorer.expand': 'Expand panel', 'explorer.maximize': 'Maximize files panel', 'explorer.restore': 'Restore panel', 'explorer.openPreview': 'Open preview', 'explorer.drag.dropHint': 'Release to insert the file path', 'scm.repositories': 'Repositories', 'scm.changes': 'Changes', 'scm.staged': 'Staged', 'scm.unstaged': 'Changes', 'scm.untracked': 'Untracked', 'scm.conflicted': 'Conflict', 'scm.stage': 'Stage', 'scm.unstage': 'Unstage', 'scm.discard': 'Discard', 'scm.stageAll': 'Stage all', 'scm.discardAll': 'Discard all', 'scm.empty': 'No changes', 'scm.notRepo': 'Not a git repository', 'scm.gitMissing': 'Git is not installed. Install git and reload to use the changes panel', 'scm.loading': 'Loading status…', 'scm.failed': 'Operation failed', 'scm.viewList': 'List view', 'scm.viewTree': 'Tree view', 'scm.discardConfirmTracked': 'Discard changes in {count} files? This cannot be undone.', 'scm.discardConfirmUntracked': 'Delete {count} untracked files? This cannot be undone.', 'preview.noTabs': 'No open previews', 'preview.newUrlTab': 'New URL preview', 'preview.collapsePanel': 'Collapse preview panel', 'preview.maximize': 'Maximize preview panel', 'preview.restore': 'Restore panel', 'preview.source': 'Source', 'preview.preview': 'Preview', 'preview.editor': 'Editor', 'preview.split': 'Split', 'preview.refresh': 'Refresh', 'preview.refresh.updated': 'File updated on disk', 'preview.save': 'Save', 'preview.download': 'Download', 'preview.copyCode': 'Copy code', 'preview.copyCodeDone': 'Copied', 'preview.openExternal': 'Open in system app', 'preview.dirty': 'Unsaved changes', 'preview.closeLeft': 'Close left', 'preview.closeRight': 'Close right', 'preview.closeOthers': 'Close others', 'preview.closeAll': 'Close all', 'preview.closeConfirmTitle': 'Close unsaved tabs', 'preview.closeConfirmBody': '{count} tabs have unsaved changes. Closing will lose them.', 'preview.saved': 'Saved', 'preview.saveConflict': 'File changed on disk. Save conflict: refresh and retry', 'preview.errorOversized': 'File too large, only the first 80,000 characters loaded', 'preview.unsupported': 'Preview not supported for this format', 'preview.downloadHint': 'Open in a system app or download to view', 'preview.url.placeholder': 'Enter a URL and press Enter', 'preview.url.hint': 'Press Esc to revert', 'common.cancel': 'Cancel', 'common.confirm': 'OK', 'common.close': 'Close', 'common.delete': 'Delete', 'common.copyPath': 'Copy path', 'common.copied': 'Copied', 'explorer.menu.copyPath': 'Copy path', 'explorer.menu.copyName': 'Copy name', 'explorer.menu.reveal': 'Reveal in file manager', 'explorer.menu.openWithDefault': 'Open with default app', 'explorer.menu.rename': 'Rename', 'explorer.menu.newFile': 'New file', 'explorer.menu.newFolder': 'New folder', 'explorer.menu.delete': 'Delete', 'explorer.rename.title': 'Rename', 'explorer.newFile.title': 'New file', 'explorer.newFolder.title': 'New folder', 'explorer.deleteConfirmTitle': 'Confirm delete', 'explorer.deleteConfirmBody': 'Delete "{name}"? This cannot be undone.', 'explorer.opFailed': 'Operation failed', 'settings.title': 'Side Card', 'settings.description': 'The right panel is the side card from DSH-better-sidebar (github.com/omdsh-dev/DSH-better-sidebar).', 'settings.sourcePrefix': 'The side card (right panel) is provided by the external DSH-better-sidebar plugin, from ', 'settings.sourceSuffix': '. Its everyday settings follow below and apply immediately.', 'settings.generalTitle': 'General', 'settings.openByDefault': 'Open for new conversations', 'settings.openByDefaultHint': 'New conversations expand the side card automatically; existing conversations keep their own layout', 'settings.width': 'Default width percent', 'settings.widthHint': 'The percentage of the window width the side card occupies in new conversations (20-60)', 'settings.openPath': 'Open chat files in the side card', 'settings.openPathHint': 'File links in chat (tool rows, produced lists, file mentions) open in the side card editor instead of the system default app', 'settings.titleBar': 'Position compatibility mode', 'settings.titleBarHint': 'Reserves space for the native Windows title bar at the top right: the sidebar buttons and content shift down to clear it', 'settings.tabsTitle': 'Sidebar content', 'settings.viewersTitle': 'File previews', 'settings.prefsLoading': 'Loading settings…', 'settings.prefsUnavailable': 'Side card settings unavailable: dsh-better-sidebar is not installed or its settings route is unreachable.', 'settings.overridden': 'Overridden', 'settings.reset': 'Reset', 'settings.notExposed': 'This DSH version does not expose this plugin\'s settings namespace; the form is unavailable. Edit ~/.dsh/settings.yaml directly, or add the namespace to the WEB_SETTINGS_NAMESPACES allowlist of dsh-host-apiproxy and restart.', 'settings.readOnly': 'Settings are read-only in this deployment.', 'settings.inherit': 'Inherit', 'settings.on': 'On', 'settings.off': 'Off', 'settings.expand': 'Expand settings', 'settings.collapse': 'Collapse settings', 'settings.save': 'Save', 'settings.saving': 'Saving…', 'settings.discard': 'Discard', 'settings.unsaved': 'Unsaved', 'settings.saveFailed': 'The deployment rejected these values; your edits are kept.', 'settings.invalidNumber': 'Enter a number, or leave it empty to use the default.', } export type AionUiPanelKey = keyof typeof zh /** The dictionary namespace this plugin owns. */ export const NS = 'aionui-panel' /** Format one copy string with {name} placeholders. */ export function format(template: string, params: Record): string { return template.replace(/\{(\w+)\}/g, (_, key: string) => String(params[key] ?? `{${key}}`)) } /** Simple dictionary access (zh/en by a global flag the client sets). */ export const dictionaries: Record<'zh' | 'en', Record> = { zh, en } let currentLanguage: 'zh' | 'en' = 'zh' /** Set the active language (the client mirrors the locale service). */ export function setLanguage(language: string): void { currentLanguage = language === 'en' ? 'en' : 'zh' } /** Translate one key with optional params. */ export function t(key: AionUiPanelKey, params?: Record): string { const table = dictionaries[currentLanguage] ?? zh const template = table[key] ?? zh[key] return params === undefined ? template : format(template, params) }