From 8a68cf207abe820da21d21586d1d5649cd19e5a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E6=9C=88?= <3600911665@qq.com> Date: Wed, 16 Jul 2025 23:36:47 +0800 Subject: [PATCH] i18n: Refactor translation management tools and add ignore feature for dynamic resources - Updated README.md to reflect changes in translation management tools and added ignore mark feature for dynamic resources. - Created Chinese translation guide for the translation management tools. - Created English translation guide for the translation management tools. - Enhanced translation-cleaner.py to skip keys marked with /*keep*/ during cleanup. - Improved translation-manager.py to create backups only when updating keys interactively. - Updated zh_CN.json with new translations and added ignore marks for dynamic values. --- .config/quickshell/ii/Translation.qml | 9 ++- .../ii/modules/sidebarLeft/AiChat.qml | 6 +- .../sidebarRight/calendar/CalendarWidget.qml | 2 +- .../notifications/NotificationList.qml | 2 +- .config/quickshell/translations/en_US.json | 14 ++++- .../quickshell/translations/tools/README.md | 33 +++++------ .../translation-tools-guide-zh_CN.md} | 33 ++++++----- .../{ => guide}/translation-tools-guide.md | 32 +++++------ .../translations/tools/translation-cleaner.py | 31 ++++++----- .../translations/tools/translation-manager.py | 55 +++++++++++++------ .config/quickshell/translations/zh_CN.json | 26 ++++++--- 11 files changed, 145 insertions(+), 98 deletions(-) rename .config/quickshell/translations/tools/{翻译管理脚本说明.md => guide/translation-tools-guide-zh_CN.md} (89%) rename .config/quickshell/translations/tools/{ => guide}/translation-tools-guide.md (87%) diff --git a/.config/quickshell/ii/Translation.qml b/.config/quickshell/ii/Translation.qml index 97aff7c5c..74a3e6ba8 100644 --- a/.config/quickshell/ii/Translation.qml +++ b/.config/quickshell/ii/Translation.qml @@ -145,12 +145,17 @@ Singleton { if (root.translations.hasOwnProperty(key)) { var translation = root.translations[key] if (translation && translation.toString().trim().length > 0) { - return translation.toString() + var str = translation.toString().trim() + if (str.endsWith("/*keep*/")) { + return str.substring(0, str.length - 8).trim() + } else { + return str + } } else { return translation.toString() } } - + return key // Fallback to key name } diff --git a/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml index afd9f41c7..26f8e5837 100644 --- a/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml @@ -419,7 +419,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) return { name: `${messageInputField.text.trim().split(" ").length == 1 ? (root.commandPrefix + "prompt ") : ""}${file.target}`, displayName: `${FileUtils.trimFileExt(FileUtils.fileNameForPath(file.target))}`, - description: `Load prompt from ${file.target}`, + description: Translation.tr("Load prompt from %1").arg(file.target), } }) } else if (messageInputField.text.startsWith(`${root.commandPrefix}save`)) { @@ -438,7 +438,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) return { name: `${messageInputField.text.trim().split(" ").length == 1 ? (root.commandPrefix + "save ") : ""}${chatName}`, displayName: `${chatName}`, - description: `Save chat from ${chatName}`, + description: Translation.tr("Save chat from %1").arg(chatName), } }) } else if (messageInputField.text.startsWith(`${root.commandPrefix}load`)) { @@ -457,7 +457,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) return { name: `${messageInputField.text.trim().split(" ").length == 1 ? (root.commandPrefix + "load ") : ""}${chatName}`, displayName: `${chatName}`, - description: `Load chat from ${file.target}`, + description: Translation.tr(`Load chat from %1`).arg(file.target), } }) } else if(messageInputField.text.startsWith(root.commandPrefix)) { diff --git a/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml b/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml index 0c79fcef3..3aac36045 100644 --- a/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml +++ b/.config/quickshell/ii/modules/sidebarRight/calendar/CalendarWidget.qml @@ -93,7 +93,7 @@ Item { Repeater { model: CalendarLayout.weekDays delegate: CalendarDayButton { - day: modelData.day + day: Translation.tr(modelData.day) isToday: modelData.today bold: true enabled: false diff --git a/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml b/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml index d26693f7e..4c95b9a5b 100644 --- a/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml +++ b/.config/quickshell/ii/modules/sidebarRight/notifications/NotificationList.qml @@ -85,7 +85,7 @@ Item { anchors.verticalCenter: parent.verticalCenter anchors.leftMargin: 10 horizontalAlignment: Text.AlignHCenter - text: `${Notifications.list.length} ${Translation.tr("notifications")}` + text: Translation.tr("%1 notifications").arg(Notifications.list.length) opacity: Notifications.list.length > 0 ? 1 : 0 visible: opacity > 0 diff --git a/.config/quickshell/translations/en_US.json b/.config/quickshell/translations/en_US.json index 3f4118e17..a9ee4e93e 100644 --- a/.config/quickshell/translations/en_US.json +++ b/.config/quickshell/translations/en_US.json @@ -1,4 +1,11 @@ { + "Mo": "Mo/*keep*/", + "Tu": "Tu/*keep*/", + "We": "We/*keep*/", + "Th": "Th/*keep*/", + "Fr": "Fr/*keep*/", + "Sa": "Sa/*keep*/", + "Su": "Su/*keep*/", "%1 characters": "%1 characters", "**Pricing**: free. Data use policy varies depending on your OpenRouter account settings.\n\n**Instructions**: Log into OpenRouter account, go to Keys on the topright menu, click Create API Key": "**Pricing**: free. Data use policy varies depending on your OpenRouter account settings.\n\n**Instructions**: Log into OpenRouter account, go to Keys on the topright menu, click Create API Key", "**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key": "**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key", @@ -152,7 +159,6 @@ "Set the system prompt for the model.": "Set the system prompt for the model.", "To Do": "To Do", "Calendar": "Calendar", - "notifications": "notifications", "Advanced": "Advanced", "About": "About", "Services": "Services", @@ -306,5 +312,9 @@ "Page %1": "Page %1", "Local Ollama model | %1": "Local Ollama model | %1", "The current system prompt is\n\n---\n\n%1": "The current system prompt is\n\n---\n\n%1", - "Unknown function call: %1": "Unknown function call: %1" + "Unknown function call: %1": "Unknown function call: %1", + "%1 notifications": "%1 notifications", + "Save chat from %1": "Save chat from %1", + "Load chat from %1": "Load chat from %1", + "Load prompt from %1": "Load prompt from %1" } \ No newline at end of file diff --git a/.config/quickshell/translations/tools/README.md b/.config/quickshell/translations/tools/README.md index e41c742e9..94c213631 100644 --- a/.config/quickshell/translations/tools/README.md +++ b/.config/quickshell/translations/tools/README.md @@ -163,7 +163,6 @@ Translation.tr("Say \"Hello\"") // With parameter placeholders Translation.tr("Hello, %1!").arg(name) -Translation.tr("{0} files selected").arg(count) ``` ## Example Output @@ -235,20 +234,15 @@ Original key count: 470, after cleaning: 420 --source-dir /path/to/source ``` -### Batch Processing +### Ignore Mark Feature -```bash -# Create a processing script -cat > update-all-translations.sh << 'EOF' -#!/bin/bash -for lang in zh_CN ja_JP ko_KR; do - echo "Processing $lang..." - ./manage-translations.sh update -l $lang -done -EOF +For dynamic resources or special texts that should not be automatically cleaned, you can add `/*keep*/` at the end of the translation value. The tool will automatically ignore these keys and will not delete them during cleaning or syncing. -chmod +x update-all-translations.sh -./update-all-translations.sh +Example: +```json +{ + "dynamic_key": "Some dynamic value /*keep*/" +} ``` ## Notes @@ -256,7 +250,8 @@ chmod +x update-all-translations.sh 1. **Backup is important**: The tool automatically creates backups before cleaning, but it is recommended to manually back up important files 2. **Text extraction limitations**: - - Only supports static strings, not dynamically constructed strings + - ~~Only supports static strings, not dynamically constructed strings~~ + - Dynamic resources (such as variable concatenation or runtime-generated text) cannot be automatically extracted. You need to manually add them to the translation file and use the `/*keep*/` mark for ignore management. - Must use the `Translation.tr()` format 3. **File encoding**: All files must use UTF-8 encoding @@ -267,13 +262,16 @@ chmod +x update-all-translations.sh ### Common Issues -**Q: The number of extracted texts does not match expectations?** +**Q: Text does not appear after adding Translation.tr?** +A: You need to import the translation feature in your QML file using `import "root:/"`, otherwise the translation text will not be displayed correctly. + +**Q: The number of extracted texts does not match expectations?** A: Check whether all translatable texts use the `Translation.tr()` format and ensure there are no dynamically constructed strings. -**Q: Some translations are missing after syncing?** +**Q: Some translations are missing after syncing?** A: Check whether the source language file contains all necessary keys, and consider using a different source language for syncing. -**Q: The cleaning operation deleted needed keys?** +**Q: The cleaning operation deleted needed keys?** A: Restore from the automatically created backup file and check whether `Translation.tr()` is used correctly in the source code. ### Restore Backup @@ -285,4 +283,3 @@ cp .config/quickshell/translations/zh_CN.json.backup .config/quickshell/translat # Restore all files cp .config/quickshell/translations.backup/* .config/quickshell/translations/ ``` - diff --git a/.config/quickshell/translations/tools/翻译管理脚本说明.md b/.config/quickshell/translations/tools/guide/translation-tools-guide-zh_CN.md similarity index 89% rename from .config/quickshell/translations/tools/翻译管理脚本说明.md rename to .config/quickshell/translations/tools/guide/translation-tools-guide-zh_CN.md index fa9850cf8..821533bea 100644 --- a/.config/quickshell/translations/tools/翻译管理脚本说明.md +++ b/.config/quickshell/translations/tools/guide/translation-tools-guide-zh_CN.md @@ -163,7 +163,6 @@ Translation.tr("Say \"Hello\"") // 带参数占位符 Translation.tr("Hello, %1!").arg(name) -Translation.tr("{0} files selected").arg(count) ``` ## 示例输出 @@ -235,29 +234,25 @@ $ ./manage-translations.sh clean --source-dir /path/to/source ``` -### 批量处理 - -```bash -# 创建处理脚本 -cat > update-all-translations.sh << 'EOF' -#!/bin/bash -for lang in zh_CN ja_JP ko_KR; do - echo "Processing $lang..." - ./manage-translations.sh update -l $lang -done -EOF - -chmod +x update-all-translations.sh -./update-all-translations.sh -``` ## 注意事项 1. **备份重要**:在执行清理操作前,工具会自动创建备份,但建议手动备份重要文件 2. **文本提取限制**: - - 只支持静态字符串,不支持动态构建的字符串 + - ~~只支持静态字符串,不支持动态构建的字符串~~ + - 动态资源(如变量拼接、运行时生成的文本)无法自动提取,需要在翻译文件中手动添加,并使用 `/*keep*/` 标记进行忽略管理。 - 必须使用 `Translation.tr()` 格式 +### 忽略标记功能 + +对于动态资源或特殊文本,如果不希望被自动清理,可在翻译值末尾添加 `/*keep*/`,工具会自动忽略这些键,不会在清理和同步时删除。 + +示例: +```json +{ + "dynamic_key": "Some dynamic value /*keep*/" +} +``` 3. **文件编码**:所有文件必须使用 UTF-8 编码 @@ -267,6 +262,10 @@ chmod +x update-all-translations.sh ### 常见问题 + +**Q: 添加了 Translation.tr 后文字不显示?** +A: 需要在 QML 文件中使用 `import "root:/"` 导入翻译功能,否则无法正常显示翻译文本。 + **Q: 提取的文本数量与预期不符?** A: 检查是否所有可翻译文本都使用了 `Translation.tr()` 格式,确保没有动态构建的字符串。 diff --git a/.config/quickshell/translations/tools/translation-tools-guide.md b/.config/quickshell/translations/tools/guide/translation-tools-guide.md similarity index 87% rename from .config/quickshell/translations/tools/translation-tools-guide.md rename to .config/quickshell/translations/tools/guide/translation-tools-guide.md index 96165b99b..94c213631 100644 --- a/.config/quickshell/translations/tools/translation-tools-guide.md +++ b/.config/quickshell/translations/tools/guide/translation-tools-guide.md @@ -163,7 +163,6 @@ Translation.tr("Say \"Hello\"") // With parameter placeholders Translation.tr("Hello, %1!").arg(name) -Translation.tr("{0} files selected").arg(count) ``` ## Example Output @@ -235,20 +234,15 @@ Original key count: 470, after cleaning: 420 --source-dir /path/to/source ``` -### Batch Processing +### Ignore Mark Feature -```bash -# Create a processing script -cat > update-all-translations.sh << 'EOF' -#!/bin/bash -for lang in zh_CN ja_JP ko_KR; do - echo "Processing $lang..." - ./manage-translations.sh update -l $lang -done -EOF +For dynamic resources or special texts that should not be automatically cleaned, you can add `/*keep*/` at the end of the translation value. The tool will automatically ignore these keys and will not delete them during cleaning or syncing. -chmod +x update-all-translations.sh -./update-all-translations.sh +Example: +```json +{ + "dynamic_key": "Some dynamic value /*keep*/" +} ``` ## Notes @@ -256,7 +250,8 @@ chmod +x update-all-translations.sh 1. **Backup is important**: The tool automatically creates backups before cleaning, but it is recommended to manually back up important files 2. **Text extraction limitations**: - - Only supports static strings, not dynamically constructed strings + - ~~Only supports static strings, not dynamically constructed strings~~ + - Dynamic resources (such as variable concatenation or runtime-generated text) cannot be automatically extracted. You need to manually add them to the translation file and use the `/*keep*/` mark for ignore management. - Must use the `Translation.tr()` format 3. **File encoding**: All files must use UTF-8 encoding @@ -267,13 +262,16 @@ chmod +x update-all-translations.sh ### Common Issues -**Q: The number of extracted texts does not match expectations?** +**Q: Text does not appear after adding Translation.tr?** +A: You need to import the translation feature in your QML file using `import "root:/"`, otherwise the translation text will not be displayed correctly. + +**Q: The number of extracted texts does not match expectations?** A: Check whether all translatable texts use the `Translation.tr()` format and ensure there are no dynamically constructed strings. -**Q: Some translations are missing after syncing?** +**Q: Some translations are missing after syncing?** A: Check whether the source language file contains all necessary keys, and consider using a different source language for syncing. -**Q: The cleaning operation deleted needed keys?** +**Q: The cleaning operation deleted needed keys?** A: Restore from the automatically created backup file and check whether `Translation.tr()` is used correctly in the source code. ### Restore Backup diff --git a/.config/quickshell/translations/tools/translation-cleaner.py b/.config/quickshell/translations/tools/translation-cleaner.py index 642101d15..b26e3fbd9 100755 --- a/.config/quickshell/translations/tools/translation-cleaner.py +++ b/.config/quickshell/translations/tools/translation-cleaner.py @@ -50,29 +50,34 @@ def clean_translation_files(translations_dir: str, source_dir: str, backup: bool translations = manager.load_translation_file(lang) original_count = len(translations) - if backup: - # Create backup - backup_file = Path(translations_dir) / f"{lang}.json.bak" - with open(backup_file, 'w', encoding='utf-8') as f: - json.dump(translations, f, ensure_ascii=False, indent=2) - print(f"Created backup: {backup_file}") - - # Find unused keys - unused_keys = set(translations.keys()) - current_texts - + # Find unused keys, skip those whose value ends with /*keep*/ + unused_keys = set() + for k in translations.keys(): + v = translations[k] + if k not in current_texts: + if isinstance(v, str) and v.strip().endswith('/*keep*/'): + continue + unused_keys.add(k) + if unused_keys: print(f"Found {len(unused_keys)} unused keys:") for i, key in enumerate(sorted(unused_keys)[:10], 1): # Only show first 10 print(f" {i}. \"{key[:50]}{'...' if len(key) > 50 else ''}\"") if len(unused_keys) > 10: print(f" ... and {len(unused_keys) - 10} more keys") - + response = input(f"Delete these {len(unused_keys)} unused keys? (y/n): ") if response.lower().strip() in ['y', 'yes']: + if backup: + # Create backup only when user confirms deletion + backup_file = Path(translations_dir) / f"{lang}.json.bak" + with open(backup_file, 'w', encoding='utf-8') as f: + json.dump(translations, f, ensure_ascii=False, indent=2) + print(f"Created backup: {backup_file}") # Delete unused keys for key in unused_keys: del translations[key] - + # Save cleaned file manager.save_translation_file(lang, translations) removed_count = len(unused_keys) @@ -82,7 +87,7 @@ def clean_translation_files(translations_dir: str, source_dir: str, backup: bool print("Skipped deletion") else: print("No unused keys found") - + new_count = len(translations) print(f"Original key count: {original_count}, after cleanup: {new_count}") diff --git a/.config/quickshell/translations/tools/translation-manager.py b/.config/quickshell/translations/tools/translation-manager.py index 1b1a604ab..a3105446b 100755 --- a/.config/quickshell/translations/tools/translation-manager.py +++ b/.config/quickshell/translations/tools/translation-manager.py @@ -138,35 +138,52 @@ class TranslationManager: return missing_keys, extra_keys def interactive_update(self, lang_code: str, missing_keys: Set[str], extra_keys: Set[str]): - """Interactively update translation file""" + """Interactively update translation file, create backup only if updating""" translations = self.load_translation_file(lang_code) modified = False - + backup_created = False + # Handle missing keys if missing_keys: print(f"\nFound {len(missing_keys)} missing translation keys:") for i, key in enumerate(sorted(missing_keys), 1): print(f"{i}. \"{key}\"") - + if self.ask_yes_no(f"\nAdd these {len(missing_keys)} missing keys?"): + if not backup_created: + backup_file = self.translations_dir / f"{lang_code}.json.bak" + with open(backup_file, 'w', encoding='utf-8') as f: + json.dump(translations, f, ensure_ascii=False, indent=2) + print(f"Created backup: {backup_file}") + backup_created = True for key in missing_keys: translations[key] = key # Default value is the key itself modified = True print(f"Added {len(missing_keys)} keys") - + # Handle extra keys if extra_keys: - print(f"\nFound {len(extra_keys)} extra translation keys:") - for i, key in enumerate(sorted(extra_keys), 1): - print(f"{i}. \"{key}\" -> \"{translations.get(key, '')}\"") - - if self.ask_yes_no(f"\nDelete these {len(extra_keys)} extra keys?"): - for key in extra_keys: - if key in translations: - del translations[key] - modified = True - print(f"Deleted {len(extra_keys)} keys") - + # Only show extra keys that are not marked with /*keep*/ + filtered_extra_keys = [key for key in extra_keys if not (isinstance(translations.get(key, ""), str) and translations.get(key, "").strip().endswith('/*keep*/'))] + if filtered_extra_keys: + print(f"\nFound {len(filtered_extra_keys)} extra translation keys:") + for i, key in enumerate(sorted(filtered_extra_keys), 1): + print(f"{i}. \"{key}\" -> \"{translations.get(key, '')}\"") + if self.ask_yes_no(f"\nDelete these {len(filtered_extra_keys)} extra keys?"): + if not backup_created: + backup_file = self.translations_dir / f"{lang_code}.json.bak" + with open(backup_file, 'w', encoding='utf-8') as f: + json.dump(translations, f, ensure_ascii=False, indent=2) + print(f"Created backup: {backup_file}") + backup_created = True + deleted_count = 0 + for key in filtered_extra_keys: + if key in translations: + del translations[key] + modified = True + deleted_count += 1 + print(f"Deleted {deleted_count} keys") + # Save changes if modified: self.save_translation_file(lang_code, translations) @@ -288,7 +305,13 @@ def main(): print(f"Analysis results:") print(f" Missing keys: {len(missing_keys)}") - print(f" Extra keys: {len(extra_keys)}") + # Load translation file for current lang to get values + current_translations = manager.load_translation_file(lang) + filtered_extra_keys = [key for key in extra_keys if not (isinstance(current_translations.get(key, ""), str) and current_translations.get(key, "").strip().endswith('/*keep*/'))] + ignored_extra_keys = [key for key in extra_keys if (isinstance(current_translations.get(key, ""), str) and current_translations.get(key, "").strip().endswith('/*keep*/'))] + print(f" Extra keys: {len(filtered_extra_keys)}") + if ignored_extra_keys: + print(f" Ignored keys: {len(ignored_extra_keys)} (marked with /*keep*/)") if missing_keys or extra_keys: manager.interactive_update(lang, missing_keys, extra_keys) diff --git a/.config/quickshell/translations/zh_CN.json b/.config/quickshell/translations/zh_CN.json index 71e64d7ea..c3749d2f8 100644 --- a/.config/quickshell/translations/zh_CN.json +++ b/.config/quickshell/translations/zh_CN.json @@ -1,4 +1,11 @@ { + "Mo": "一/*keep*/", + "Tu": "二/*keep*/", + "We": "三/*keep*/", + "Th": "四/*keep*/", + "Fr": "五/*keep*/", + "Sa": "六/*keep*/", + "Su": "日/*keep*/", "%1 characters": "%1 个字符", "**Pricing**: free. Data used for training.\n\n**Instructions**: Log into Google account, allow AI Studio to create Google Cloud project or whatever it asks, go back and click Get API key": "**价格**:免费。数据用于训练。\n\n**说明**:登录 Google 账户,允许 AI Studio 创建 Google Cloud 项目或其他要求,然后返回并点击获取 API 密钥", "**Pricing**: free. Data use policy varies depending on your OpenRouter account settings.\n\n**Instructions**: Log into OpenRouter account, go to Keys on the topright menu, click Create API Key": "**价格**:免费。数据使用政策取决于您的 OpenRouter 账户设置。\n\n**说明**:登录 OpenRouter 账户,在右上角菜单中选择 Keys,点击创建 API 密钥", @@ -96,7 +103,7 @@ "Save": "保存", "Save to Downloads": "保存到下载文件夹", "Search": "搜索", - "Search the web": "搜索网络", + "Search the web": "在网络上搜索", "Search, calculate or run": "搜索、计算或运行", "Select Language": "选择语言", "Session": "会话", @@ -170,7 +177,6 @@ "Set the system prompt for the model.": "为模型设置系统提示。", "To Do": "待办", "Calendar": "日历", - "notifications": "条通知", "Advanced": "高级", "About": "关于", "Services": "服务", @@ -212,7 +218,7 @@ "Policies": "策略", "Weeb": "二次元", "Closet": "隐藏", - "Bar style": "Bar 样式", + "Bar style": "条栏样式", "Show next time": "下次显示", "Usage": "用法", "Plain rectangle": "纯矩形", @@ -281,7 +287,7 @@ "Screen snip": "屏幕截图", "Mic toggle": "麦克风切换", "Hover to reveal": "悬停显示", - "Bar": "Bar", + "Bar": "条栏", "Show background": "显示背景", "Show regions of potential interest": "显示可能感兴趣的区域", "Color picker": "取色器", @@ -303,8 +309,12 @@ "Drag or click a region • LMB: Copy • RMB: Edit": "拖动或点击一个区域 • 鼠标左键:复制 • 鼠标右键:编辑", "Current model: %1\nSet it with %2model MODEL": "当前模型:%1\n使用 %2model MODEL 设置", "Message the model... \"%1\" for commands": "与模型对话... \"%1\" 查看命令", - "The current system prompt is\n\n---\n\n%1": "The current system prompt is\n\n---\n\n%1", - "Model set to %1": "Model set to %1", - "Online models disallowed for %1\n\nControlled by `policies.ai` config option": "Online models disallowed for %1\n\nControlled by `policies.ai` config option", - "Loaded the following system prompt\n\n---\n\n%1": "Loaded the following system prompt\n\n---\n\n%1" + "The current system prompt is\n\n---\n\n%1": "当前系统提示词为\n\n---\n\n%1", + "Model set to %1": "模型已设置为 %1", + "Online models disallowed for %1\n\nControlled by `policies.ai` config option": "%1 禁止使用在线模型\n\n由 `policies.ai` 配置项控制", + "Loaded the following system prompt\n\n---\n\n%1": "已加载以下系统提示词\n\n---\n\n%1", + "%1 notifications": "%1 条通知", + "Save chat from %1": "保存聊天记录到 %1", + "Load chat from %1": "从 %1 加载聊天记录", + "Load prompt from %1": "从 %1 加载提示词" } \ No newline at end of file