feat: localize session management group & interval method texts (#6471)

* fix(ui): localize session management group texts

Replace hardcoded Chinese strings in SessionManagementPage with i18n
lookups for group management labels, dialogs, and action feedback.

Add and align translation keys in en-US, ru-RU, and zh-CN for group
management and batch operation messages to ensure consistent multilingual
UI behavior.

* fix(ui): localize interval method hint text
This commit is contained in:
Ruochen Pan
2026-03-17 10:21:55 +08:00
committed by GitHub
parent 1c7c2ee0cd
commit 85cfd62014
5 changed files with 126 additions and 55 deletions
@@ -851,7 +851,7 @@
},
"interval_method": {
"description": "Interval Method",
"hint": "random 为随机时间,log 为根据消息长度计算,$y=log_<log_base>(x)$x为字数,y的单位为秒。"
"hint": "random uses a random delay. log calculates delay by message length: $y=log_{log\\_base}(x)$, where x is word count and y is in seconds."
},
"interval": {
"description": "Random Interval Time",
@@ -93,24 +93,6 @@
"batchDeleteConfirm": {
"title": "Confirm Batch Delete",
"message": "Are you sure you want to delete {count} selected rules? Global settings will be used after deletion."
},
"batchOperations": {
"title": "Batch Operations",
"hint": "Quick batch modify session settings",
"scope": "Apply to",
"scopeSelected": "Selected sessions",
"scopeAll": "All sessions",
"scopeGroup": "All groups",
"scopePrivate": "All private chats",
"llmStatus": "LLM Status",
"ttsStatus": "TTS Status",
"chatProvider": "Chat Model",
"ttsProvider": "TTS Model",
"apply": "Apply Changes"
},
"status": {
"enabled": "Enabled",
"disabled": "Disabled"
},
"batchOperations": {
"title": "Batch Operations",
@@ -126,6 +108,25 @@
"ttsProvider": "TTS Model",
"apply": "Apply Changes"
},
"groups": {
"title": "Group Management",
"count": "{count} groups",
"addToGroup": "Add to Group",
"create": "Create Group",
"edit": "Edit Group",
"name": "Group Name",
"sessionsCount": "{count} sessions",
"empty": "No groups yet. Click 'Create Group' to create one.",
"availableSessions": "Available Sessions ({count})",
"selectedSessions": "Selected Sessions ({count})",
"searchPlaceholder": "Search...",
"noMatch": "No matches",
"noMembers": "No members",
"customGroupDivider": "── Custom Groups ──",
"customGroupOption": "📁 {name} ({count})",
"groupOption": "{name} ({count} sessions)",
"deleteConfirm": "Are you sure you want to delete group \"{name}\"?"
},
"status": {
"enabled": "Enabled",
"disabled": "Disabled"
@@ -142,7 +143,16 @@
"noChanges": "No changes to save",
"batchDeleteSuccess": "Batch delete successful",
"batchDeleteError": "Batch delete failed",
"selectSessionsFirst": "Please select sessions first",
"selectAtLeastOneConfig": "Please select at least one setting to modify",
"batchUpdateSuccess": "Batch update successful",
"partialUpdateFailed": "Some updates failed",
"batchUpdateError": "Batch update failed",
"batchUpdateSuccess": "Batch update success"
"groupNameRequired": "Group name cannot be empty",
"saveGroupError": "Failed to save group",
"deleteGroupError": "Failed to delete group",
"selectSessionsToAddFirst": "Please select sessions to add first",
"addToGroupSuccess": "Added {count} sessions to the group",
"addToGroupError": "Failed to add to group"
}
}
@@ -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})",
"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": "Ошибка добавления в группу"
}
}
@@ -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})",
"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": "添加失败"
}
}
+35 -32
View File
@@ -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>
</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,7 +199,7 @@
</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>
@@ -207,15 +207,15 @@
<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,7 +252,7 @@
<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>
@@ -260,8 +260,8 @@
</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,9 +721,12 @@ 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 => {
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}`
})
})
}
return options
@@ -731,7 +734,7 @@ export default {
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'))
}
},
},