i18n: replace hardcoded strings in all editor components

Fix 36 hardcoded UI strings across 7 editor files:
- ReJsonEditor.vue: add useI18n import (was entirely missing i18n)
- StringEditor.vue: Edit/Save/Cancel/Saved buttons
- HashEditor.vue: delete confirm dialog, Deleted/Added toasts
- SetEditor.vue: remove confirm dialog, Added/Removed toasts
- ZsetEditor.vue: same pattern as SetEditor
- ListEditor.vue: Prev/Next pagination, Saved/Added/Removed toasts
- StreamEditor.vue: 8 strings (group destroy, entry delete, trim,
  add field warning, entries count)

New i18n keys added to all 5 locales (en, zh-CN, ja, ko, de):
- common.prev, common.next
- editor.deleted, deleteFieldConfirm, removeElementConfirm,
  removeMemberConfirm, destroyGroupConfirm, deleteEntryConfirm,
  trimConfirmDetail, trimmed, entries, addFieldWarning
This commit is contained in:
2026-07-12 10:27:29 +08:00
parent d2c1f50f87
commit 8340630dd4
12 changed files with 93 additions and 31 deletions
@@ -99,10 +99,10 @@ async function saveField(item: HashField) {
async function deleteField(item: HashField) {
if (!connStore.activeId || !keyStore.selectedKey) return
try {
await ElMessageBox.confirm(`Delete field "${item.field}"?`, 'Confirm')
await ElMessageBox.confirm(t('editor.deleteFieldConfirm', { field: item.field }), t('common.confirm'))
await window.electronAPI.redis.hashDel(connStore.activeId, keyStore.selectedKey, item.field)
fields.value = fields.value.filter(f => f.field !== item.field)
ElMessage.success('Deleted')
ElMessage.success(t('editor.deleted'))
} catch (err: any) {
if (err !== 'cancel') ElMessage.error(err.message)
}
@@ -116,7 +116,7 @@ async function addField() {
showAddDialog.value = false
newFieldName.value = ''
newFieldValue.value = ''
ElMessage.success('Added')
ElMessage.success(t('editor.added'))
} catch (err: any) {
ElMessage.error(err.message)
}
@@ -47,7 +47,7 @@ async function addItem() {
showAddDialog.value = false
newItemValue.value = ''
await loadList()
ElMessage.success('Added')
ElMessage.success(t('editor.added'))
} catch (err: any) {
ElMessage.error(err.message)
}
@@ -64,7 +64,7 @@ async function saveEdit() {
await window.electronAPI.redis.listSet(connStore.activeId, keyStore.selectedKey, editingIndex.value, editingValue.value)
items.value[editingIndex.value] = editingValue.value
editingIndex.value = null
ElMessage.success('Saved')
ElMessage.success(t('editor.saved'))
} catch (err: any) {
ElMessage.error(err.message)
}
@@ -73,10 +73,10 @@ async function saveEdit() {
async function removeItem(item: string) {
if (!connStore.activeId || !keyStore.selectedKey) return
try {
await ElMessageBox.confirm(`Remove this element?`, 'Confirm')
await ElMessageBox.confirm(t('editor.removeElementConfirm'), t('common.confirm'))
await window.electronAPI.redis.listRemove(connStore.activeId, keyStore.selectedKey, 1, item)
await loadList()
ElMessage.success('Removed')
ElMessage.success(t('editor.removed'))
} catch (err: any) {
if (err !== 'cancel') ElMessage.error(err.message)
}
@@ -124,9 +124,9 @@ function nextPage() {
</div>
<div class="list-pagination" v-if="totalCount > pageSize">
<el-button size="small" :disabled="pageStart === 0" @click="prevPage">Prev</el-button>
<el-button size="small" :disabled="pageStart === 0" @click="prevPage">{{ t('common.prev') }}</el-button>
<span class="page-info">{{ pageStart + 1 }}-{{ Math.min(pageStart + pageSize, totalCount) }} / {{ totalCount }}</span>
<el-button size="small" :disabled="pageStart + pageSize >= totalCount" @click="nextPage">Next</el-button>
<el-button size="small" :disabled="pageStart + pageSize >= totalCount" @click="nextPage">{{ t('common.next') }}</el-button>
</div>
<el-dialog v-model="showAddDialog" :title="t('editor.push')" width="400px">
@@ -4,11 +4,13 @@ import { VueMonacoEditor } from '@guolao/vue-monaco-editor'
import { useKeyStore } from '@renderer/stores/key'
import { useConnectionStore } from '@renderer/stores/connection'
import { useAppStore } from '@renderer/stores/app'
import { useI18n } from '@renderer/i18n'
import { ElMessage } from 'element-plus'
const keyStore = useKeyStore()
const connStore = useConnectionStore()
const appStore = useAppStore()
const { t } = useI18n()
const editedValue = ref('')
const isEditing = ref(false)
@@ -50,7 +52,7 @@ async function save() {
try {
await window.electronAPI.redis.rejsonSet(connStore.activeId, keyStore.selectedKey, '.', editedValue.value)
isEditing.value = false
ElMessage.success('Saved')
ElMessage.success(t('editor.saved'))
} catch (err: any) {
ElMessage.error(err.message)
}
@@ -62,10 +64,10 @@ async function save() {
<div class="editor-toolbar">
<span class="type-badge">ReJSON</span>
<span class="spacer" />
<el-button v-if="!isEditing" size="small" type="primary" @click="isEditing = true">Edit</el-button>
<el-button v-if="!isEditing" size="small" type="primary" @click="isEditing = true">{{ t('editor.edit') }}</el-button>
<template v-else>
<el-button size="small" type="primary" @click="save">Save</el-button>
<el-button size="small" @click="isEditing = false; loadValue()">Cancel</el-button>
<el-button size="small" type="primary" @click="save">{{ t('editor.save') }}</el-button>
<el-button size="small" @click="isEditing = false; loadValue()">{{ t('editor.cancel') }}</el-button>
</template>
</div>
<div class="editor-content">
@@ -42,7 +42,7 @@ async function addMember() {
}
showAddDialog.value = false
newMember.value = ''
ElMessage.success('Added')
ElMessage.success(t('editor.added'))
} catch (err: any) {
ElMessage.error(err.message)
}
@@ -51,10 +51,10 @@ async function addMember() {
async function removeMember(member: string) {
if (!connStore.activeId || !keyStore.selectedKey) return
try {
await ElMessageBox.confirm(`Remove member "${member}"?`, 'Confirm')
await ElMessageBox.confirm(t('editor.removeMemberConfirm', { member }), t('common.confirm'))
await window.electronAPI.redis.setRemove(connStore.activeId, keyStore.selectedKey, [member])
members.value = members.value.filter(m => m !== member)
ElMessage.success('Removed')
ElMessage.success(t('editor.removed'))
} catch (err: any) {
if (err !== 'cancel') ElMessage.error(err.message)
}
@@ -147,7 +147,7 @@ async function destroyGroup(groupName: string) {
if (!connStore.activeId || !keyStore.selectedKey) return
try {
await ElMessageBox.confirm(
`Destroy consumer group "${groupName}"?`, 'Confirm',
t('editor.destroyGroupConfirm', { name: groupName }), t('common.confirm'),
{ type: 'warning' }
)
await window.electronAPI.redis.streamGroupDestroy(
@@ -193,7 +193,7 @@ async function addEntry() {
}
}
if (fieldValues.length === 0) {
ElMessage.warning('Add at least one field')
ElMessage.warning(t('editor.addFieldWarning'))
return
}
@@ -207,7 +207,7 @@ async function addEntry() {
})
showAddDialog.value = false
newFields.value = [{ key: '', value: '' }]
ElMessage.success('Added')
ElMessage.success(t('editor.added'))
} catch (err: any) {
ElMessage.error(err.message)
}
@@ -216,10 +216,10 @@ async function addEntry() {
async function deleteEntry(entry: StreamEntry) {
if (!connStore.activeId || !keyStore.selectedKey) return
try {
await ElMessageBox.confirm(`Delete entry "${entry.id}"?`, 'Confirm')
await ElMessageBox.confirm(t('editor.deleteEntryConfirm', { id: entry.id }), t('common.confirm'))
await window.electronAPI.redis.streamDel(connStore.activeId, keyStore.selectedKey, [entry.id])
entries.value = entries.value.filter(e => e.id !== entry.id)
ElMessage.success('Deleted')
ElMessage.success(t('editor.deleted'))
} catch (err: any) {
if (err !== 'cancel') ElMessage.error(err.message)
}
@@ -228,12 +228,12 @@ async function deleteEntry(entry: StreamEntry) {
async function trimStream() {
if (!connStore.activeId || !keyStore.selectedKey) return
try {
await ElMessageBox.confirm(`Trim stream to max ${trimMaxLen.value} entries?`, 'Confirm')
await ElMessageBox.confirm(t('editor.trimConfirmDetail', { n: trimMaxLen.value }), t('common.confirm'))
trimming.value = true
const removed = await window.electronAPI.redis.streamTrim(
connStore.activeId, keyStore.selectedKey, trimMaxLen.value
)
ElMessage.success(`Removed ${removed} entries`)
ElMessage.success(t('editor.trimmed', { n: removed }))
await loadEntries()
} catch (err: any) {
if (err !== 'cancel') ElMessage.error(err.message)
@@ -247,7 +247,7 @@ async function trimStream() {
<div class="stream-editor">
<div class="editor-toolbar">
<span class="type-badge">STREAM</span>
<span class="item-count">{{ entries.length }} entries</span>
<span class="item-count">{{ t('editor.entries', { n: entries.length }) }}</span>
<el-button size="small" type="primary" @click="showAddDialog = true">{{ t('common.add') }}</el-button>
<el-popconfirm :title="t('editor.trimConfirm')">
<template #reference>
@@ -137,7 +137,7 @@ async function save() {
await window.electronAPI.redis.setString(connStore.activeId, keyStore.selectedKey, editedValue.value)
keyStore.keyData = editedValue.value
isEditing.value = false
ElMessage.success('Saved')
ElMessage.success(t('editor.saved'))
} catch (err: any) {
ElMessage.error(err.message)
}
@@ -180,10 +180,10 @@ onUnmounted(() => {
{{ t('editor.format') }}: {{ detectedFormat }}
</span>
<span class="spacer" />
<el-button v-if="!isEditing" size="small" type="primary" @click="isEditing = true">Edit</el-button>
<el-button v-if="!isEditing" size="small" type="primary" @click="isEditing = true">{{ t('editor.edit') }}</el-button>
<template v-else>
<el-button size="small" type="primary" @click="save">Save</el-button>
<el-button size="small" @click="isEditing = false; decodeAndDisplay(editedValue)">Cancel</el-button>
<el-button size="small" type="primary" @click="save">{{ t('editor.save') }}</el-button>
<el-button size="small" @click="isEditing = false; decodeAndDisplay(editedValue)">{{ t('editor.cancel') }}</el-button>
</template>
</div>
<div class="editor-content">
@@ -52,7 +52,7 @@ async function addMember() {
showAddDialog.value = false
newMember.value = ''
newScore.value = 0
ElMessage.success('Added')
ElMessage.success(t('editor.added'))
} catch (err: any) {
ElMessage.error(err.message)
}
@@ -61,10 +61,10 @@ async function addMember() {
async function removeMember(member: string) {
if (!connStore.activeId || !keyStore.selectedKey) return
try {
await ElMessageBox.confirm(`Remove member "${member}"?`, 'Confirm')
await ElMessageBox.confirm(t('editor.removeMemberConfirm', { member }), t('common.confirm'))
await window.electronAPI.redis.zsetRemove(connStore.activeId, keyStore.selectedKey, [member])
items.value = items.value.filter(i => i.member !== member)
ElMessage.success('Removed')
ElMessage.success(t('editor.removed'))
} catch (err: any) {
if (err !== 'cancel') ElMessage.error(err.message)
}
+12
View File
@@ -13,6 +13,8 @@ export default {
error: 'Fehler',
loading: 'Laden...',
noData: 'Keine Daten',
prev: 'Zurück',
next: 'Weiter',
},
app: {
title: 'JRedisDesktop',
@@ -202,6 +204,16 @@ export default {
sortDesc: 'Absteigend',
filteredCount: '{n} gefiltert',
fieldCount: '{n} Felder',
deleted: 'Gelöscht',
deleteFieldConfirm: 'Feld "{field}" löschen?',
removeElementConfirm: 'Dieses Element entfernen?',
removeMemberConfirm: 'Mitglied "{member}" entfernen?',
destroyGroupConfirm: 'Consumer-Gruppe "{name}" zerstören?',
deleteEntryConfirm: 'Eintrag "{id}" löschen?',
trimConfirmDetail: 'Stream auf maximal {n} Einträge kürzen?',
trimmed: '{n} Einträge entfernt',
entries: '{n} Einträge',
addFieldWarning: 'Mindestens ein Feld hinzufügen',
},
cli: {
title: 'CLI',
+12
View File
@@ -13,6 +13,8 @@ export default {
error: 'Error',
loading: 'Loading...',
noData: 'No data',
prev: 'Prev',
next: 'Next',
},
app: {
title: 'JRedisDesktop',
@@ -202,6 +204,16 @@ export default {
sortDesc: 'Descending',
filteredCount: '{n} filtered',
fieldCount: '{n} fields',
deleted: 'Deleted',
deleteFieldConfirm: 'Delete field "{field}"?',
removeElementConfirm: 'Remove this element?',
removeMemberConfirm: 'Remove member "{member}"?',
destroyGroupConfirm: 'Destroy consumer group "{name}"?',
deleteEntryConfirm: 'Delete entry "{id}"?',
trimConfirmDetail: 'Trim stream to max {n} entries?',
trimmed: 'Removed {n} entries',
entries: '{n} entries',
addFieldWarning: 'Add at least one field',
},
cli: {
title: 'CLI',
+12
View File
@@ -13,6 +13,8 @@ export default {
error: 'エラー',
loading: '読み込み中...',
noData: 'データなし',
prev: '前へ',
next: '次へ',
},
app: {
title: 'JRedisDesktop',
@@ -202,6 +204,16 @@ export default {
sortDesc: '降順',
filteredCount: '{n} 個フィルター済み',
fieldCount: '{n} 個のフィールド',
deleted: '削除済み',
deleteFieldConfirm: 'フィールド "{field}" を削除しますか?',
removeElementConfirm: 'この要素を削除しますか?',
removeMemberConfirm: 'メンバー "{member}" を削除しますか?',
destroyGroupConfirm: 'コンシューマーグループ "{name}" を破棄しますか?',
deleteEntryConfirm: 'エントリー "{id}" を削除しますか?',
trimConfirmDetail: 'ストリームを最大 {n} 件にトリムしますか?',
trimmed: '{n} 件削除しました',
entries: '{n} 件',
addFieldWarning: '少なくとも1つのフィールドを追加してください',
},
cli: {
title: 'CLI',
+12
View File
@@ -13,6 +13,8 @@ export default {
error: '오류',
loading: '로딩 중...',
noData: '데이터 없음',
prev: '이전',
next: '다음',
},
app: {
title: 'JRedisDesktop',
@@ -202,6 +204,16 @@ export default {
sortDesc: '내림차순',
filteredCount: '{n}개 필터링됨',
fieldCount: '{n}개 필드',
deleted: '삭제됨',
deleteFieldConfirm: '필드 "{field}"를 삭제하시겠습니까?',
removeElementConfirm: '이 요소를 제거하시겠습니까?',
removeMemberConfirm: '멤버 "{member}"를 제거하시겠습니까?',
destroyGroupConfirm: '컨슈머 그룹 "{name}"를 파기하시겠습니까?',
deleteEntryConfirm: '엔트리 "{id}"를 삭제하시겠습니까?',
trimConfirmDetail: '스트림을 최대 {n}개로 트림하시겠습니까?',
trimmed: '{n}개 제거됨',
entries: '{n}개',
addFieldWarning: '최소 하나의 필드를 추가하세요',
},
cli: {
title: 'CLI',
+12
View File
@@ -13,6 +13,8 @@ export default {
error: '错误',
loading: '加载中...',
noData: '暂无数据',
prev: '上一页',
next: '下一页',
},
app: {
title: 'JRedis客户端',
@@ -202,6 +204,16 @@ export default {
sortDesc: '降序',
filteredCount: '已过滤 {n} 项',
fieldCount: '{n} 个字段',
deleted: '已删除',
deleteFieldConfirm: '确认删除字段 "{field}"',
removeElementConfirm: '确认移除此元素?',
removeMemberConfirm: '确认移除成员 "{member}"',
destroyGroupConfirm: '确认销毁消费组 "{name}"',
deleteEntryConfirm: '确认删除条目 "{id}"',
trimConfirmDetail: '将流裁剪至最多 {n} 条?',
trimmed: '已移除 {n} 条',
entries: '{n} 条',
addFieldWarning: '请至少添加一个字段',
},
cli: {
title: '命令行',