-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
feat: localize session management group & interval method texts #6471
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -108,6 +108,25 @@ | |
| "ttsProvider": "TTS-модель", | ||
| "apply": "Применить" | ||
| }, | ||
| "groups": { | ||
| "title": "Управление группами", | ||
| "count": "групп: {count}", | ||
| "addToGroup": "Добавить в группу", | ||
| "create": "Создать группу", | ||
| "edit": "Изменить группу", | ||
| "name": "Имя группы", | ||
| "sessionsCount": "сессий: {count}", | ||
| "empty": "Пока нет групп. Нажмите «Создать группу», чтобы добавить.", | ||
| "availableSessions": "Доступные сессии ({count})", | ||
| "selectedSessions": "Выбранные сессии ({count})", | ||
| "searchPlaceholder": "Поиск...", | ||
| "noMatch": "Нет совпадений", | ||
| "noMembers": "Нет участников", | ||
| "customGroupDivider": "── Пользовательские группы ──", | ||
| "customGroupOption": "📁 {name} ({count})", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| "groupOption": "{name} (сессий: {count})", | ||
| "deleteConfirm": "Вы уверены, что хотите удалить группу \"{name}\"?" | ||
| }, | ||
| "status": { | ||
| "enabled": "Включено", | ||
| "disabled": "Выключено" | ||
|
|
@@ -124,7 +143,16 @@ | |
| "noChanges": "Изменений не обнаружено", | ||
| "batchDeleteSuccess": "Массовое удаление выполнено", | ||
| "batchDeleteError": "Ошибка массового удаления", | ||
| "selectSessionsFirst": "Пожалуйста, сначала выберите сессии", | ||
| "selectAtLeastOneConfig": "Пожалуйста, выберите хотя бы одну настройку для изменения", | ||
| "batchUpdateSuccess": "Пакетное обновление успешно выполнено", | ||
| "partialUpdateFailed": "Некоторые обновления не выполнены", | ||
| "batchUpdateError": "Ошибка пакетного обновления", | ||
| "batchUpdateSuccess": "Пакетное обновление успешно выполнено" | ||
| "groupNameRequired": "Имя группы не может быть пустым", | ||
| "saveGroupError": "Ошибка сохранения группы", | ||
| "deleteGroupError": "Ошибка удаления группы", | ||
| "selectSessionsToAddFirst": "Пожалуйста, сначала выберите сессии для добавления", | ||
| "addToGroupSuccess": "Добавлено сессий в группу: {count}", | ||
| "addToGroupError": "Ошибка добавления в группу" | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -108,6 +108,25 @@ | |
| "ttsProvider": "TTS 模型", | ||
| "apply": "应用更改" | ||
| }, | ||
| "groups": { | ||
| "title": "分组管理", | ||
| "count": "{count} 个分组", | ||
| "addToGroup": "添加到分组", | ||
| "create": "新建分组", | ||
| "edit": "编辑分组", | ||
| "name": "分组名称", | ||
| "sessionsCount": "{count} 个会话", | ||
| "empty": "暂无分组,点击「新建分组」创建", | ||
| "availableSessions": "可选会话 ({count})", | ||
| "selectedSessions": "已选会话 ({count})", | ||
| "searchPlaceholder": "搜索...", | ||
| "noMatch": "无匹配项", | ||
| "noMembers": "暂无成员", | ||
| "customGroupDivider": "── 自定义分组 ──", | ||
| "customGroupOption": "📁 {name} ({count})", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| "groupOption": "{name} ({count} 个会话)", | ||
| "deleteConfirm": "确定要删除分组 \"{name}\" 吗?" | ||
| }, | ||
| "status": { | ||
| "enabled": "启用", | ||
| "disabled": "禁用" | ||
|
|
@@ -123,6 +142,17 @@ | |
| "deleteError": "删除失败", | ||
| "noChanges": "没有需要保存的更改", | ||
| "batchDeleteSuccess": "批量删除成功", | ||
| "batchDeleteError": "批量删除失败" | ||
| "batchDeleteError": "批量删除失败", | ||
| "selectSessionsFirst": "请先选择要操作的会话", | ||
| "selectAtLeastOneConfig": "请至少选择一项要修改的配置", | ||
| "batchUpdateSuccess": "批量更新成功", | ||
| "partialUpdateFailed": "部分更新失败", | ||
| "batchUpdateError": "批量更新失败", | ||
| "groupNameRequired": "分组名称不能为空", | ||
| "saveGroupError": "保存分组失败", | ||
| "deleteGroupError": "删除分组失败", | ||
| "selectSessionsToAddFirst": "请先选择要添加的会话", | ||
| "addToGroupSuccess": "已添加 {count} 个会话到分组", | ||
| "addToGroupError": "添加失败" | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -156,24 +156,24 @@ | |||||||||||||||||||
| <!-- 分组管理面板 --> | ||||||||||||||||||||
| <v-card flat class="mt-4"> | ||||||||||||||||||||
| <v-card-title class="d-flex align-center py-3 px-4"> | ||||||||||||||||||||
| <span class="text-h6">分组管理</span> | ||||||||||||||||||||
| <span class="text-h6">{{ tm('groups.title') }}</span> | ||||||||||||||||||||
| <v-chip size="small" class="ml-2" color="secondary" variant="outlined"> | ||||||||||||||||||||
| {{ groups.length }} 个分组 | ||||||||||||||||||||
| {{ tm('groups.count', { count: groups.length }) }} | ||||||||||||||||||||
| </v-chip> | ||||||||||||||||||||
| <v-spacer></v-spacer> | ||||||||||||||||||||
| <v-btn v-if="selectedItems.length > 0 && groups.length > 0" color="info" variant="tonal" size="small" class="mr-2"> | ||||||||||||||||||||
| <v-icon start>mdi-folder-plus</v-icon> | ||||||||||||||||||||
| 添加到分组 | ||||||||||||||||||||
| {{ tm('groups.addToGroup') }} | ||||||||||||||||||||
| <v-menu activator="parent"> | ||||||||||||||||||||
| <v-list density="compact"> | ||||||||||||||||||||
| <v-list-item v-for="g in groups" :key="g.id" @click="addSelectedToGroup(g.id)"> | ||||||||||||||||||||
| <v-list-item-title>{{ g.name }} ({{ g.umo_count }})</v-list-item-title> | ||||||||||||||||||||
| <v-list-item-title>{{ tm('groups.customGroupOption', { name: g.name, count: g.umo_count }) }}</v-list-item-title> | ||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To separate the icon from the translation string, please add the '📁' icon here in the template. This should be done in conjunction with removing it from the |
||||||||||||||||||||
| </v-list-item> | ||||||||||||||||||||
| </v-list> | ||||||||||||||||||||
| </v-menu> | ||||||||||||||||||||
| </v-btn> | ||||||||||||||||||||
| <v-btn color="success" variant="tonal" size="small" @click="openCreateGroupDialog" prepend-icon="mdi-folder-plus"> | ||||||||||||||||||||
| 新建分组 | ||||||||||||||||||||
| {{ tm('groups.create') }} | ||||||||||||||||||||
| </v-btn> | ||||||||||||||||||||
| </v-card-title> | ||||||||||||||||||||
| <v-card-text v-if="groups.length > 0"> | ||||||||||||||||||||
|
|
@@ -183,7 +183,7 @@ | |||||||||||||||||||
| <div class="d-flex align-center justify-space-between"> | ||||||||||||||||||||
| <div> | ||||||||||||||||||||
| <div class="font-weight-bold">{{ group.name }}</div> | ||||||||||||||||||||
| <div class="text-caption text-grey">{{ group.umo_count }} 个会话</div> | ||||||||||||||||||||
| <div class="text-caption text-grey">{{ tm('groups.sessionsCount', { count: group.umo_count }) }}</div> | ||||||||||||||||||||
| </div> | ||||||||||||||||||||
| <div> | ||||||||||||||||||||
| <v-btn icon size="small" variant="text" @click="openEditGroupDialog(group)"> | ||||||||||||||||||||
|
|
@@ -199,23 +199,23 @@ | |||||||||||||||||||
| </v-row> | ||||||||||||||||||||
| </v-card-text> | ||||||||||||||||||||
| <v-card-text v-else class="text-center text-grey py-6"> | ||||||||||||||||||||
| 暂无分组,点击「新建分组」创建 | ||||||||||||||||||||
| {{ tm('groups.empty') }} | ||||||||||||||||||||
| </v-card-text> | ||||||||||||||||||||
| </v-card> | ||||||||||||||||||||
|
|
||||||||||||||||||||
| <!-- 分组编辑对话框 --> | ||||||||||||||||||||
| <v-dialog v-model="groupDialog" max-width="800" @after-enter="loadAvailableUmos"> | ||||||||||||||||||||
| <v-card> | ||||||||||||||||||||
| <v-card-title class="py-3 px-4"> | ||||||||||||||||||||
| {{ groupDialogMode === 'create' ? '新建分组' : '编辑分组' }} | ||||||||||||||||||||
| {{ groupDialogMode === 'create' ? tm('groups.create') : tm('groups.edit') }} | ||||||||||||||||||||
| </v-card-title> | ||||||||||||||||||||
| <v-card-text> | ||||||||||||||||||||
| <v-text-field v-model="editingGroup.name" label="分组名称" variant="outlined" hide-details class="mb-4"></v-text-field> | ||||||||||||||||||||
| <v-text-field v-model="editingGroup.name" :label="tm('groups.name')" variant="outlined" hide-details class="mb-4"></v-text-field> | ||||||||||||||||||||
| <v-row dense> | ||||||||||||||||||||
| <!-- 左侧:可选会话 --> | ||||||||||||||||||||
| <v-col cols="5"> | ||||||||||||||||||||
| <div class="text-subtitle-2 mb-2">可选会话 ({{ unselectedUmos.length }})</div> | ||||||||||||||||||||
| <v-text-field v-model="groupMemberSearch" placeholder="搜索..." variant="outlined" density="compact" hide-details class="mb-2" clearable prepend-inner-icon="mdi-magnify"></v-text-field> | ||||||||||||||||||||
| <div class="text-subtitle-2 mb-2">{{ tm('groups.availableSessions', { count: unselectedUmos.length }) }}</div> | ||||||||||||||||||||
| <v-text-field v-model="groupMemberSearch" :placeholder="tm('groups.searchPlaceholder')" variant="outlined" density="compact" hide-details class="mb-2" clearable prepend-inner-icon="mdi-magnify"></v-text-field> | ||||||||||||||||||||
| <v-list density="compact" class="transfer-list" lines="one"> | ||||||||||||||||||||
| <v-list-item v-for="umo in filteredUnselectedUmos" :key="umo" @click="addToGroup(umo)" class="transfer-item"> | ||||||||||||||||||||
| <template v-slot:prepend> | ||||||||||||||||||||
|
|
@@ -224,7 +224,7 @@ | |||||||||||||||||||
| <v-list-item-title class="text-caption">{{ formatUmoShort(umo) }}</v-list-item-title> | ||||||||||||||||||||
| </v-list-item> | ||||||||||||||||||||
| <v-list-item v-if="filteredUnselectedUmos.length === 0 && !loadingUmos"> | ||||||||||||||||||||
| <v-list-item-title class="text-caption text-grey text-center">无匹配项</v-list-item-title> | ||||||||||||||||||||
| <v-list-item-title class="text-caption text-grey text-center">{{ tm('groups.noMatch') }}</v-list-item-title> | ||||||||||||||||||||
| </v-list-item> | ||||||||||||||||||||
| <v-list-item v-if="loadingUmos"> | ||||||||||||||||||||
| <v-list-item-title class="text-center"><v-progress-circular indeterminate size="20"></v-progress-circular></v-list-item-title> | ||||||||||||||||||||
|
|
@@ -242,8 +242,8 @@ | |||||||||||||||||||
| </v-col> | ||||||||||||||||||||
| <!-- 右侧:已选会话 --> | ||||||||||||||||||||
| <v-col cols="5"> | ||||||||||||||||||||
| <div class="text-subtitle-2 mb-2">已选会话 ({{ editingGroup.umos.length }})</div> | ||||||||||||||||||||
| <v-text-field v-model="groupSelectedSearch" placeholder="搜索..." variant="outlined" density="compact" hide-details class="mb-2" clearable prepend-inner-icon="mdi-magnify"></v-text-field> | ||||||||||||||||||||
| <div class="text-subtitle-2 mb-2">{{ tm('groups.selectedSessions', { count: editingGroup.umos.length }) }}</div> | ||||||||||||||||||||
| <v-text-field v-model="groupSelectedSearch" :placeholder="tm('groups.searchPlaceholder')" variant="outlined" density="compact" hide-details class="mb-2" clearable prepend-inner-icon="mdi-magnify"></v-text-field> | ||||||||||||||||||||
| <v-list density="compact" class="transfer-list" lines="one"> | ||||||||||||||||||||
| <v-list-item v-for="umo in filteredSelectedUmos" :key="umo" @click="removeFromGroup(umo)" class="transfer-item"> | ||||||||||||||||||||
| <template v-slot:prepend> | ||||||||||||||||||||
|
|
@@ -252,16 +252,16 @@ | |||||||||||||||||||
| <v-list-item-title class="text-caption">{{ formatUmoShort(umo) }}</v-list-item-title> | ||||||||||||||||||||
| </v-list-item> | ||||||||||||||||||||
| <v-list-item v-if="editingGroup.umos.length === 0"> | ||||||||||||||||||||
| <v-list-item-title class="text-caption text-grey text-center">暂无成员</v-list-item-title> | ||||||||||||||||||||
| <v-list-item-title class="text-caption text-grey text-center">{{ tm('groups.noMembers') }}</v-list-item-title> | ||||||||||||||||||||
| </v-list-item> | ||||||||||||||||||||
| </v-list> | ||||||||||||||||||||
| </v-col> | ||||||||||||||||||||
| </v-row> | ||||||||||||||||||||
| </v-card-text> | ||||||||||||||||||||
| <v-card-actions class="px-4 pb-4"> | ||||||||||||||||||||
| <v-spacer></v-spacer> | ||||||||||||||||||||
| <v-btn variant="text" @click="groupDialog = false">取消</v-btn> | ||||||||||||||||||||
| <v-btn color="primary" variant="tonal" @click="saveGroup">保存</v-btn> | ||||||||||||||||||||
| <v-btn variant="text" @click="groupDialog = false">{{ tm('buttons.cancel') }}</v-btn> | ||||||||||||||||||||
| <v-btn color="primary" variant="tonal" @click="saveGroup">{{ tm('buttons.save') }}</v-btn> | ||||||||||||||||||||
| </v-card-actions> | ||||||||||||||||||||
| </v-card> | ||||||||||||||||||||
| </v-dialog> | ||||||||||||||||||||
|
|
@@ -721,17 +721,20 @@ export default { | |||||||||||||||||||
| ] | ||||||||||||||||||||
| // 添加自定义分组选项 | ||||||||||||||||||||
| if (this.groups.length > 0) { | ||||||||||||||||||||
| options.push({ label: '── 自定义分组 ──', value: '_divider', disabled: true }) | ||||||||||||||||||||
| options.push({ label: this.tm('groups.customGroupDivider'), value: '_divider', disabled: true }) | ||||||||||||||||||||
| this.groups.forEach(g => { | ||||||||||||||||||||
|
Comment on lines
722
to
725
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: Preserving the visual divider formatting in translations could avoid inconsistent UX across locales. Previously, the hard-coded label (
Suggested change
|
||||||||||||||||||||
| options.push({ label: `📁 ${g.name} (${g.umo_count})`, value: `custom_group:${g.id}` }) | ||||||||||||||||||||
| options.push({ | ||||||||||||||||||||
| label: this.tm('groups.customGroupOption', { name: g.name, count: g.umo_count }), | ||||||||||||||||||||
| value: `custom_group:${g.id}` | ||||||||||||||||||||
| }) | ||||||||||||||||||||
|
Comment on lines
+726
to
+729
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To separate the icon from the translation string, please prepend the '📁' icon to the label here. This change corresponds to the suggested removal of the icon from the |
||||||||||||||||||||
| }) | ||||||||||||||||||||
| } | ||||||||||||||||||||
| return options | ||||||||||||||||||||
| }, | ||||||||||||||||||||
|
|
||||||||||||||||||||
| groupOptions() { | ||||||||||||||||||||
| return this.groups.map(g => ({ | ||||||||||||||||||||
| label: `${g.name} (${g.umo_count} 个会话)`, | ||||||||||||||||||||
| label: this.tm('groups.groupOption', { name: g.name, count: g.umo_count }), | ||||||||||||||||||||
| value: g.id | ||||||||||||||||||||
| })) | ||||||||||||||||||||
| }, | ||||||||||||||||||||
|
|
@@ -1331,7 +1334,7 @@ export default { | |||||||||||||||||||
| if (scope === 'selected') { | ||||||||||||||||||||
| umos = this.selectedItems.map(item => item.umo) | ||||||||||||||||||||
| if (umos.length === 0) { | ||||||||||||||||||||
| this.showError('请先选择要操作的会话') | ||||||||||||||||||||
| this.showError(this.tm('messages.selectSessionsFirst')) | ||||||||||||||||||||
| this.batchUpdating = false | ||||||||||||||||||||
| return | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
@@ -1371,7 +1374,7 @@ export default { | |||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| if (tasks.length === 0) { | ||||||||||||||||||||
| this.showError('请至少选择一项要修改的配置') | ||||||||||||||||||||
| this.showError(this.tm('messages.selectAtLeastOneConfig')) | ||||||||||||||||||||
| this.batchUpdating = false | ||||||||||||||||||||
| return | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
@@ -1380,17 +1383,17 @@ export default { | |||||||||||||||||||
| const allOk = results.every(r => r.data.status === 'ok') | ||||||||||||||||||||
|
|
||||||||||||||||||||
| if (allOk) { | ||||||||||||||||||||
| this.showSuccess('批量更新成功') | ||||||||||||||||||||
| this.showSuccess(this.tm('messages.batchUpdateSuccess')) | ||||||||||||||||||||
| this.batchLlmStatus = null | ||||||||||||||||||||
| this.batchTtsStatus = null | ||||||||||||||||||||
| this.batchChatProvider = null | ||||||||||||||||||||
| this.batchTtsProvider = null | ||||||||||||||||||||
| await this.loadData() | ||||||||||||||||||||
| } else { | ||||||||||||||||||||
| this.showError('部分更新失败') | ||||||||||||||||||||
| this.showError(this.tm('messages.partialUpdateFailed')) | ||||||||||||||||||||
| } | ||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||
| this.showError(error.response?.data?.message || '批量更新失败') | ||||||||||||||||||||
| this.showError(error.response?.data?.message || this.tm('messages.batchUpdateError')) | ||||||||||||||||||||
| } | ||||||||||||||||||||
| this.batchUpdating = false | ||||||||||||||||||||
| }, | ||||||||||||||||||||
|
|
@@ -1477,7 +1480,7 @@ export default { | |||||||||||||||||||
|
|
||||||||||||||||||||
| async saveGroup() { | ||||||||||||||||||||
| if (!this.editingGroup.name.trim()) { | ||||||||||||||||||||
| this.showError('分组名称不能为空') | ||||||||||||||||||||
| this.showError(this.tm('messages.groupNameRequired')) | ||||||||||||||||||||
| return | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
@@ -1504,12 +1507,12 @@ export default { | |||||||||||||||||||
| this.showError(response.data.message) | ||||||||||||||||||||
| } | ||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||
| this.showError(error.response?.data?.message || '保存分组失败') | ||||||||||||||||||||
| this.showError(error.response?.data?.message || this.tm('messages.saveGroupError')) | ||||||||||||||||||||
| } | ||||||||||||||||||||
| }, | ||||||||||||||||||||
|
|
||||||||||||||||||||
| async deleteGroup(group) { | ||||||||||||||||||||
| const message = `确定要删除分组 "${group.name}" 吗?` | ||||||||||||||||||||
| const message = this.tm('groups.deleteConfirm', { name: group.name }) | ||||||||||||||||||||
| if (!(await askForConfirmationDialog(message, this.confirmDialog))) return | ||||||||||||||||||||
|
|
||||||||||||||||||||
| try { | ||||||||||||||||||||
|
|
@@ -1521,7 +1524,7 @@ export default { | |||||||||||||||||||
| this.showError(response.data.message) | ||||||||||||||||||||
| } | ||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||
| this.showError(error.response?.data?.message || '删除分组失败') | ||||||||||||||||||||
| this.showError(error.response?.data?.message || this.tm('messages.deleteGroupError')) | ||||||||||||||||||||
| } | ||||||||||||||||||||
| }, | ||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
@@ -1532,7 +1535,7 @@ export default { | |||||||||||||||||||
|
|
||||||||||||||||||||
| async addSelectedToGroup(groupId) { | ||||||||||||||||||||
| if (this.selectedItems.length === 0) { | ||||||||||||||||||||
| this.showError('请先选择要添加的会话') | ||||||||||||||||||||
| this.showError(this.tm('messages.selectSessionsToAddFirst')) | ||||||||||||||||||||
| return | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
@@ -1542,13 +1545,13 @@ export default { | |||||||||||||||||||
| add_umos: this.selectedItems.map(item => item.umo) | ||||||||||||||||||||
| }) | ||||||||||||||||||||
| if (response.data.status === 'ok') { | ||||||||||||||||||||
| this.showSuccess(`已添加 ${this.selectedItems.length} 个会话到分组`) | ||||||||||||||||||||
| this.showSuccess(this.tm('messages.addToGroupSuccess', { count: this.selectedItems.length })) | ||||||||||||||||||||
| await this.loadGroups() | ||||||||||||||||||||
| } else { | ||||||||||||||||||||
| this.showError(response.data.message) | ||||||||||||||||||||
| } | ||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||
| this.showError(error.response?.data?.message || '添加失败') | ||||||||||||||||||||
| this.showError(error.response?.data?.message || this.tm('messages.addToGroupError')) | ||||||||||||||||||||
| } | ||||||||||||||||||||
| }, | ||||||||||||||||||||
| }, | ||||||||||||||||||||
|
|
||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a good practice to separate presentational elements like icons from translation strings. This improves maintainability, as changing the icon won't require updating all translation files. Please remove the '📁' icon from this translation key.