@liujitcn/kratos-admin-system 0.0.20 → 0.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +51 -50
  2. package/dist/package/declarations/src/api/system/base_language.d.ts +51 -0
  3. package/dist/package/declarations/src/api/system/base_translation.d.ts +7 -0
  4. package/dist/package/declarations/src/api/system/code_gen_i18n.d.ts +8 -0
  5. package/dist/package/declarations/src/components/DynamicTranslationCell.vue.d.ts +39 -0
  6. package/dist/package/declarations/src/components/DynamicTranslationEditor.vue.d.ts +23 -0
  7. package/dist/package/declarations/src/components/dynamicTranslation.d.ts +44 -0
  8. package/dist/package/declarations/src/rpc/system/admin/v1/base_config.d.ts +5 -0
  9. package/dist/package/declarations/src/rpc/system/admin/v1/base_dict.d.ts +79 -0
  10. package/dist/package/declarations/src/rpc/system/admin/v1/base_language.d.ts +114 -0
  11. package/dist/package/declarations/src/rpc/system/admin/v1/base_menu.d.ts +40 -0
  12. package/dist/package/declarations/src/rpc/system/admin/v1/base_translation.d.ts +102 -0
  13. package/dist/package/declarations/src/rpc/system/admin/v1/code_gen.d.ts +2 -0
  14. package/dist/package/declarations/src/rpc/system/admin/v1/code_gen_column.d.ts +7 -0
  15. package/dist/package/declarations/src/rpc/system/admin/v1/code_gen_table.d.ts +13 -0
  16. package/dist/package/declarations/src/views/tool/code-gen/components/CodeGenLocaleEditor.vue.d.ts +23 -0
  17. package/dist/package/declarations/src/views/tool/code-gen/config.d.ts +7 -7
  18. package/dist/package/declarations/src/views/tool/language/index.vue.d.ts +3 -0
  19. package/dist/package/src/api/base/ai_message.ts +7 -12
  20. package/dist/package/src/api/base/sse.ts +3 -1
  21. package/dist/package/src/api/system/base_language.ts +137 -0
  22. package/dist/package/src/api/system/base_translation.ts +22 -0
  23. package/dist/package/src/api/system/code_gen_column.ts +17 -3
  24. package/dist/package/src/api/system/code_gen_i18n.ts +18 -0
  25. package/dist/package/src/api/system/code_gen_table.ts +12 -4
  26. package/dist/package/src/components/DynamicTranslationCell.vue +176 -0
  27. package/dist/package/src/components/DynamicTranslationEditor.vue +166 -0
  28. package/dist/package/src/components/dynamicTranslation.ts +86 -0
  29. package/dist/package/src/locales/README.md +28 -0
  30. package/dist/package/src/locales/en-US.json +929 -0
  31. package/dist/package/src/locales/es-ES.json +928 -0
  32. package/dist/package/src/locales/fr-FR.json +928 -0
  33. package/dist/package/src/locales/ja-JP.json +929 -0
  34. package/dist/package/src/locales/ko-KR.json +928 -0
  35. package/dist/package/src/locales/zh-CN.json +929 -0
  36. package/dist/package/src/locales/zh-TW.json +928 -0
  37. package/dist/package/src/module.ts +19 -1
  38. package/dist/package/src/rpc/system/admin/v1/base_config.ts +5 -0
  39. package/dist/package/src/rpc/system/admin/v1/base_dict.ts +81 -0
  40. package/dist/package/src/rpc/system/admin/v1/base_language.ts +135 -0
  41. package/dist/package/src/rpc/system/admin/v1/base_menu.ts +41 -0
  42. package/dist/package/src/rpc/system/admin/v1/base_translation.ts +117 -0
  43. package/dist/package/src/rpc/system/admin/v1/code_gen.ts +5 -1
  44. package/dist/package/src/rpc/system/admin/v1/code_gen_column.ts +8 -0
  45. package/dist/package/src/rpc/system/admin/v1/code_gen_table.ts +15 -0
  46. package/dist/package/src/views/ai/chat/components/AiMarkdown.vue +1 -6
  47. package/dist/package/src/views/ai/chat/components/ChatPanel.vue +70 -53
  48. package/dist/package/src/views/ai/chat/components/SessionPanel.vue +20 -9
  49. package/dist/package/src/views/ai/chat/components/XSender.vue +36 -23
  50. package/dist/package/src/views/ai/chat/index.vue +55 -39
  51. package/dist/package/src/views/ai/chat/message.ts +18 -17
  52. package/dist/package/src/views/base/api/index.vue +121 -83
  53. package/dist/package/src/views/base/area/index.vue +81 -31
  54. package/dist/package/src/views/base/config/index.vue +272 -78
  55. package/dist/package/src/views/base/dept/index.vue +110 -61
  56. package/dist/package/src/views/base/dict/index.vue +137 -58
  57. package/dist/package/src/views/base/dict/item.vue +147 -61
  58. package/dist/package/src/views/base/job/index.vue +134 -81
  59. package/dist/package/src/views/base/job/log.vue +21 -22
  60. package/dist/package/src/views/base/log/index.vue +68 -46
  61. package/dist/package/src/views/base/menu/index.vue +257 -156
  62. package/dist/package/src/views/base/migration/index.vue +49 -29
  63. package/dist/package/src/views/base/post/index.vue +128 -59
  64. package/dist/package/src/views/base/role/index.vue +145 -78
  65. package/dist/package/src/views/base/tenant/index.vue +132 -63
  66. package/dist/package/src/views/base/user/components/dept-tree.vue +2 -1
  67. package/dist/package/src/views/base/user/index.vue +192 -112
  68. package/dist/package/src/views/profile/components/base.vue +44 -27
  69. package/dist/package/src/views/profile/components/password.vue +43 -27
  70. package/dist/package/src/views/profile/components/security.vue +89 -53
  71. package/dist/package/src/views/profile/index.vue +10 -9
  72. package/dist/package/src/views/tool/api-doc/index.vue +6 -2
  73. package/dist/package/src/views/tool/code-gen/code-preview/index.vue +30 -14
  74. package/dist/package/src/views/tool/code-gen/columns/index.vue +382 -273
  75. package/dist/package/src/views/tool/code-gen/columns/option-copy.ts +1 -6
  76. package/dist/package/src/views/tool/code-gen/components/CodeGenLocaleEditor.vue +118 -0
  77. package/dist/package/src/views/tool/code-gen/components/CodeGenProgressDialog.vue +65 -36
  78. package/dist/package/src/views/tool/code-gen/components/CodePreviewPane.vue +8 -5
  79. package/dist/package/src/views/tool/code-gen/config.ts +114 -77
  80. package/dist/package/src/views/tool/code-gen/preview/data.ts +19 -17
  81. package/dist/package/src/views/tool/code-gen/preview/index.vue +96 -58
  82. package/dist/package/src/views/tool/code-gen/proto/index.vue +110 -62
  83. package/dist/package/src/views/tool/code-gen/table/index.vue +197 -117
  84. package/dist/package/src/views/tool/language/index.vue +256 -0
  85. package/dist/package/src/views/tool/project-doc/index.vue +17 -15
  86. package/package.json +6 -2
@@ -5,233 +5,273 @@
5
5
  <div v-if="formData.id" class="code-gen-column-pane">
6
6
  <div class="code-gen-toolbar code-gen-column-toolbar">
7
7
  <div class="code-gen-column-toolbar__meta">
8
- <strong>数据库字段</strong>
8
+ <strong>{{ t("system.codegen.column.title.databaseFields") }}</strong>
9
9
  <!-- 展示当前字段配置对应的业务表。 -->
10
- <span class="code-gen-column-toolbar__table-name" :title="formData.name">表名:{{ formData.name }}</span>
10
+ <span class="code-gen-column-toolbar__table-name" :title="formData.name">
11
+ {{ t("system.codegen.column.value.tableName", { name: formData.name }) }}
12
+ </span>
11
13
  <span class="code-gen-column-toolbar__table-comment" :title="formData.comment || '--'">
12
- 表注释:{{ formData.comment || "--" }}
14
+ {{ t("system.codegen.column.value.tableComment", { comment: formData.comment || "--" }) }}
13
15
  </span>
14
- <span>查询 {{ enabledSummary.query }} 项</span>
15
- <span>列表 {{ enabledSummary.list }} 项</span>
16
- <span>表单 {{ enabledSummary.form }} 项</span>
16
+ <span>{{ t("system.codegen.column.value.queryCount", { count: enabledSummary.query }) }}</span>
17
+ <span>{{ t("system.codegen.column.value.listCount", { count: enabledSummary.list }) }}</span>
18
+ <span>{{ t("system.codegen.column.value.formCount", { count: enabledSummary.form }) }}</span>
17
19
  </div>
18
20
  <div class="code-gen-column-toolbar__actions">
19
- <el-button type="primary" :icon="Document" :disabled="!canEdit" @click="handleSaveColumns()">保存</el-button>
21
+ <el-button type="primary" :icon="Document" :disabled="!canEdit" @click="handleSaveColumns()">
22
+ {{ t("common.action.save") }}
23
+ </el-button>
20
24
  </div>
21
25
  </div>
22
26
 
23
27
  <div ref="columnTableRef" class="code-gen-column-table">
24
- <el-table :data="columns" row-key="name" border stripe table-layout="fixed" empty-text="暂无字段配置">
25
- <el-table-column label="数据库字段" min-width="320" fixed="left">
26
- <template #default="{ row, $index }">
27
- <div class="code-gen-field-cell">
28
- <el-popover trigger="hover" placement="right-start" :width="320" :show-after="250">
29
- <template #reference>
30
- <div class="code-gen-field-trigger">
31
- <span class="code-gen-field-trigger__name">{{ row.name }}</span>
32
- </div>
33
- </template>
34
- <div class="code-gen-field-popover">
35
- <div class="code-gen-field-popover__header">
36
- <strong>{{ row.name }}</strong>
37
- <span>{{ row.comment || row.name }}</span>
38
- </div>
39
- <div class="code-gen-field-popover__types">
40
- <div>
41
- <span>数据库</span><b>{{ row.db_type || "--" }}</b>
28
+ <el-table
29
+ :data="columns"
30
+ row-key="name"
31
+ border
32
+ stripe
33
+ table-layout="fixed"
34
+ :empty-text="t('system.codegen.column.message.empty')"
35
+ >
36
+ <el-table-column :label="t('system.codegen.column.field.databaseColumn')" min-width="320" fixed="left">
37
+ <template #default="{ row, $index }">
38
+ <div class="code-gen-field-cell">
39
+ <el-popover trigger="hover" placement="right-start" :width="320" :show-after="250">
40
+ <template #reference>
41
+ <div class="code-gen-field-trigger">
42
+ <span class="code-gen-field-trigger__name">{{ row.name }}</span>
42
43
  </div>
43
- <div>
44
- <span>Go</span><b>{{ row.go_type || "--" }}</b>
44
+ </template>
45
+ <div class="code-gen-field-popover">
46
+ <div class="code-gen-field-popover__header">
47
+ <strong>{{ row.name }}</strong>
48
+ <span>{{ row.comment || row.name }}</span>
45
49
  </div>
46
- <div>
47
- <span>Proto</span><b>{{ row.proto_type || "--" }}</b>
50
+ <div class="code-gen-field-popover__types">
51
+ <div>
52
+ <span>{{ t("system.codegen.column.value.database") }}</span
53
+ ><b>{{ row.db_type || "--" }}</b>
54
+ </div>
55
+ <div>
56
+ <span>Go</span><b>{{ row.go_type || "--" }}</b>
57
+ </div>
58
+ <div>
59
+ <span>Proto</span><b>{{ row.proto_type || "--" }}</b>
60
+ </div>
61
+ <div>
62
+ <span>TS</span><b>{{ row.ts_type || "--" }}</b>
63
+ </div>
48
64
  </div>
49
- <div>
50
- <span>TS</span><b>{{ row.ts_type || "--" }}</b>
65
+ <div class="code-gen-field-popover__flags">
66
+ <el-tag v-if="row.is_primary" size="small" type="danger" effect="plain">
67
+ {{ t("system.codegen.column.value.primaryKey") }}
68
+ </el-tag>
69
+ <el-tag v-if="row.is_auto_increment" size="small" type="warning" effect="plain">
70
+ {{ t("system.codegen.column.value.autoIncrement") }}
71
+ </el-tag>
72
+ <el-tag size="small" :type="row.is_nullable ? 'info' : 'success'" effect="plain">
73
+ {{
74
+ t(row.is_nullable ? "system.codegen.column.value.nullable" : "system.codegen.column.value.notNull")
75
+ }}
76
+ </el-tag>
51
77
  </div>
52
78
  </div>
53
- <div class="code-gen-field-popover__flags">
54
- <el-tag v-if="row.is_primary" size="small" type="danger" effect="plain">主键</el-tag>
55
- <el-tag v-if="row.is_auto_increment" size="small" type="warning" effect="plain">自增</el-tag>
56
- <el-tag size="small" :type="row.is_nullable ? 'info' : 'success'" effect="plain">
57
- {{ row.is_nullable ? "可空" : "必填" }}
58
- </el-tag>
59
- </div>
79
+ </el-popover>
80
+ <div class="code-gen-field-order">
81
+ <span class="code-gen-field-order__index">{{ $index + 1 }}</span>
82
+ <el-tooltip :content="t('system.codegen.column.tooltip.drag')" placement="top">
83
+ <el-button
84
+ text
85
+ size="small"
86
+ :icon="List"
87
+ :disabled="!canEdit"
88
+ class="code-gen-field-order__drag"
89
+ :aria-label="t('system.codegen.column.tooltip.dragAria')"
90
+ />
91
+ </el-tooltip>
60
92
  </div>
61
- </el-popover>
62
- <div class="code-gen-field-order">
63
- <span class="code-gen-field-order__index">{{ $index + 1 }}</span>
64
- <el-tooltip content="拖拽排序" placement="top">
93
+ </div>
94
+ </template>
95
+ </el-table-column>
96
+
97
+ <el-table-column :label="t('system.codegen.column.field.comment')" min-width="360">
98
+ <template #default="{ row }">
99
+ <div class="code-gen-comment-editor">
100
+ <el-input
101
+ v-model="row.comment"
102
+ :disabled="!canEdit"
103
+ maxlength="255"
104
+ :placeholder="t('system.codegen.column.placeholder.comment')"
105
+ />
106
+ <el-popover placement="right-start" :width="400" trigger="click">
107
+ <template #reference>
108
+ <el-button
109
+ :icon="ChatLineSquare"
110
+ circle
111
+ :type="hasMissingColumnLocales(row) ? 'warning' : 'success'"
112
+ :aria-label="t('system.codegen.i18n.action.editColumn')"
113
+ />
114
+ </template>
115
+ <CodeGenLocaleEditor
116
+ :model-value="row.i18n_config"
117
+ :source-comment="row.comment"
118
+ @update:model-value="value => (row.i18n_config = value)"
119
+ />
120
+ </el-popover>
121
+ </div>
122
+ </template>
123
+ </el-table-column>
124
+
125
+ <el-table-column :label="t('system.codegen.column.field.query')" min-width="440">
126
+ <template #default="{ row }">
127
+ <div class="code-gen-config-cell">
128
+ <el-switch
129
+ v-model="row.query_config.enabled"
130
+ :disabled="!canEdit"
131
+ inline-prompt
132
+ :active-text="t('system.codegen.value.on')"
133
+ :inactive-text="t('system.codegen.value.off')"
134
+ />
135
+ <el-select
136
+ v-model="row.query_config.operator"
137
+ :disabled="!canEdit || !row.query_config.enabled"
138
+ :placeholder="t('system.codegen.column.placeholder.queryOperator')"
139
+ >
140
+ <el-option
141
+ v-for="item in queryOperatorOptions"
142
+ :key="String(item.value)"
143
+ :label="item.label"
144
+ :value="item.value"
145
+ />
146
+ </el-select>
147
+ <el-select
148
+ v-model="row.query_config.component"
149
+ :disabled="!canEdit || !row.query_config.enabled"
150
+ :placeholder="t('system.codegen.column.placeholder.queryComponent')"
151
+ @change="handleComponentChange(row, 'query')"
152
+ >
153
+ <el-option
154
+ v-for="item in queryComponentOptions"
155
+ :key="String(item.value)"
156
+ :label="item.label"
157
+ :value="item.value"
158
+ />
159
+ </el-select>
160
+ <el-tooltip
161
+ v-if="shouldShowOptionEntry(row.query_config, 'query')"
162
+ :content="optionEntryTip(row.query_config.option)"
163
+ placement="top"
164
+ >
65
165
  <el-button
66
- text
67
166
  size="small"
68
- :icon="List"
167
+ :type="hasOptionConfig(row.query_config.option) ? 'primary' : 'default'"
168
+ :icon="Setting"
69
169
  :disabled="!canEdit"
70
- class="code-gen-field-order__drag"
71
- aria-label="拖拽调整字段顺序"
72
- />
170
+ @click="openOptionDialog(row, 'query')"
171
+ >
172
+ {{ t("system.codegen.column.action.options") }}
173
+ </el-button>
73
174
  </el-tooltip>
74
175
  </div>
75
- </div>
76
- </template>
77
- </el-table-column>
78
-
79
- <el-table-column label="字段描述" min-width="280">
80
- <template #default="{ row }">
81
- <el-input v-model="row.comment" :disabled="!canEdit" maxlength="255" placeholder="请输入字段描述" />
82
- </template>
83
- </el-table-column>
84
-
85
- <el-table-column label="查询" min-width="440">
86
- <template #default="{ row }">
87
- <div class="code-gen-config-cell">
88
- <el-switch
89
- v-model="row.query_config.enabled"
90
- :disabled="!canEdit"
91
- inline-prompt
92
- active-text="开"
93
- inactive-text="关"
94
- />
95
- <el-select
96
- v-model="row.query_config.operator"
97
- :disabled="!canEdit || !row.query_config.enabled"
98
- placeholder="查询方式"
99
- >
100
- <el-option
101
- v-for="item in queryOperatorOptions"
102
- :key="String(item.value)"
103
- :label="item.label"
104
- :value="item.value"
105
- />
106
- </el-select>
107
- <el-select
108
- v-model="row.query_config.component"
109
- :disabled="!canEdit || !row.query_config.enabled"
110
- placeholder="查询组件"
111
- @change="handleComponentChange(row, 'query')"
112
- >
113
- <el-option
114
- v-for="item in queryComponentOptions"
115
- :key="String(item.value)"
116
- :label="item.label"
117
- :value="item.value"
118
- />
119
- </el-select>
120
- <el-tooltip
121
- v-if="shouldShowOptionEntry(row.query_config, 'query')"
122
- :content="optionEntryTip(row.query_config.option)"
123
- placement="top"
124
- >
125
- <el-button
126
- size="small"
127
- :type="hasOptionConfig(row.query_config.option) ? 'primary' : 'default'"
128
- :icon="Setting"
176
+ </template>
177
+ </el-table-column>
178
+
179
+ <el-table-column :label="t('system.codegen.column.field.list')" min-width="420">
180
+ <template #default="{ row }">
181
+ <div class="code-gen-config-cell">
182
+ <el-switch
183
+ v-model="row.list_config.enabled"
129
184
  :disabled="!canEdit"
130
- @click="openOptionDialog(row, 'query')"
131
- >
132
- 选项
133
- </el-button>
134
- </el-tooltip>
135
- </div>
136
- </template>
137
- </el-table-column>
138
-
139
- <el-table-column label="列表" min-width="420">
140
- <template #default="{ row }">
141
- <div class="code-gen-config-cell">
142
- <el-switch
143
- v-model="row.list_config.enabled"
144
- :disabled="!canEdit"
145
- inline-prompt
146
- active-text="开"
147
- inactive-text="关"
148
- />
149
- <el-select
150
- v-model="row.list_config.component"
151
- :disabled="!canEdit || !row.list_config.enabled"
152
- placeholder="展示组件"
153
- @change="handleComponentChange(row, 'list')"
154
- >
155
- <el-option
156
- v-for="item in listComponentOptions"
157
- :key="String(item.value)"
158
- :label="item.label"
159
- :value="item.value"
185
+ inline-prompt
186
+ :active-text="t('system.codegen.value.on')"
187
+ :inactive-text="t('system.codegen.value.off')"
160
188
  />
161
- </el-select>
162
- <el-tooltip
163
- v-if="shouldShowOptionEntry(row.list_config, 'list')"
164
- :content="optionEntryTip(row.list_config.option)"
165
- placement="top"
166
- >
167
- <el-button
168
- size="small"
169
- :type="hasOptionConfig(row.list_config.option) ? 'primary' : 'default'"
170
- :icon="Setting"
171
- :disabled="!canEdit"
172
- @click="openOptionDialog(row, 'list')"
189
+ <el-select
190
+ v-model="row.list_config.component"
191
+ :disabled="!canEdit || !row.list_config.enabled"
192
+ :placeholder="t('system.codegen.column.placeholder.listComponent')"
193
+ @change="handleComponentChange(row, 'list')"
173
194
  >
174
- 选项
175
- </el-button>
176
- </el-tooltip>
177
- </div>
178
- </template>
179
- </el-table-column>
180
-
181
- <el-table-column label="表单" min-width="440">
182
- <template #default="{ row }">
183
- <div class="code-gen-config-cell">
184
- <el-switch
185
- v-model="row.form_config.enabled"
186
- :disabled="!canEdit"
187
- inline-prompt
188
- active-text="开"
189
- inactive-text="关"
190
- @change="handleFormEnabledChange(row)"
191
- />
192
- <el-select
193
- v-model="row.form_config.component"
194
- :disabled="!canEdit || !row.form_config.enabled"
195
- placeholder="录入组件"
196
- @change="handleComponentChange(row, 'form')"
197
- >
198
- <el-option
199
- v-for="item in formComponentOptions"
200
- :key="String(item.value)"
201
- :label="item.label"
202
- :value="item.value"
203
- />
204
- </el-select>
205
- <el-checkbox v-model="row.form_config.required" :disabled="!canEdit || !row.form_config.enabled"
206
- >必填</el-checkbox
207
- >
208
- <el-tooltip
209
- v-if="shouldShowOptionEntry(row.form_config, 'form')"
210
- :content="optionEntryTip(row.form_config.option)"
211
- placement="top"
212
- >
213
- <el-button
214
- size="small"
215
- :type="hasOptionConfig(row.form_config.option) ? 'primary' : 'default'"
216
- :icon="Setting"
195
+ <el-option
196
+ v-for="item in listComponentOptions"
197
+ :key="String(item.value)"
198
+ :label="item.label"
199
+ :value="item.value"
200
+ />
201
+ </el-select>
202
+ <el-tooltip
203
+ v-if="shouldShowOptionEntry(row.list_config, 'list')"
204
+ :content="optionEntryTip(row.list_config.option)"
205
+ placement="top"
206
+ >
207
+ <el-button
208
+ size="small"
209
+ :type="hasOptionConfig(row.list_config.option) ? 'primary' : 'default'"
210
+ :icon="Setting"
211
+ :disabled="!canEdit"
212
+ @click="openOptionDialog(row, 'list')"
213
+ >
214
+ {{ t("system.codegen.column.action.options") }}
215
+ </el-button>
216
+ </el-tooltip>
217
+ </div>
218
+ </template>
219
+ </el-table-column>
220
+
221
+ <el-table-column :label="t('system.codegen.column.field.form')" min-width="440">
222
+ <template #default="{ row }">
223
+ <div class="code-gen-config-cell">
224
+ <el-switch
225
+ v-model="row.form_config.enabled"
217
226
  :disabled="!canEdit"
218
- @click="openOptionDialog(row, 'form')"
227
+ inline-prompt
228
+ :active-text="t('system.codegen.value.on')"
229
+ :inactive-text="t('system.codegen.value.off')"
230
+ @change="handleFormEnabledChange(row)"
231
+ />
232
+ <el-select
233
+ v-model="row.form_config.component"
234
+ :disabled="!canEdit || !row.form_config.enabled"
235
+ :placeholder="t('system.codegen.column.placeholder.formComponent')"
236
+ @change="handleComponentChange(row, 'form')"
237
+ >
238
+ <el-option
239
+ v-for="item in formComponentOptions"
240
+ :key="String(item.value)"
241
+ :label="item.label"
242
+ :value="item.value"
243
+ />
244
+ </el-select>
245
+ <el-checkbox v-model="row.form_config.required" :disabled="!canEdit || !row.form_config.enabled">{{
246
+ t("system.codegen.column.value.required")
247
+ }}</el-checkbox>
248
+ <el-tooltip
249
+ v-if="shouldShowOptionEntry(row.form_config, 'form')"
250
+ :content="optionEntryTip(row.form_config.option)"
251
+ placement="top"
219
252
  >
220
- 选项
221
- </el-button>
222
- </el-tooltip>
223
- </div>
224
- </template>
225
- </el-table-column>
253
+ <el-button
254
+ size="small"
255
+ :type="hasOptionConfig(row.form_config.option) ? 'primary' : 'default'"
256
+ :icon="Setting"
257
+ :disabled="!canEdit"
258
+ @click="openOptionDialog(row, 'form')"
259
+ >
260
+ {{ t("system.codegen.column.action.options") }}
261
+ </el-button>
262
+ </el-tooltip>
263
+ </div>
264
+ </template>
265
+ </el-table-column>
226
266
  </el-table>
227
267
  </div>
228
268
  </div>
229
- <el-empty v-else description="请先选择生成记录" />
269
+ <el-empty v-else :description="t('system.codegen.column.message.selectRecord')" />
230
270
  </el-card>
231
271
 
232
272
  <ProDialog
233
273
  v-model="optionDialog.visible"
234
- :title="`${optionDialog.scopeLabel}选项 - ${optionDialog.columnName}`"
274
+ :title="optionDialogTitle"
235
275
  width="min(560px, calc(100vw - 32px))"
236
276
  destroy-on-close
237
277
  :show-close="false"
@@ -242,26 +282,32 @@
242
282
  >
243
283
  <template #header="{ titleId, titleClass }">
244
284
  <div class="code-gen-config-dialog__header">
245
- <span :id="titleId" :class="titleClass">{{ `${optionDialog.scopeLabel}选项 - ${optionDialog.columnName}` }}</span>
285
+ <span :id="titleId" :class="titleClass">{{ optionDialogTitle }}</span>
246
286
  <el-button
247
287
  type="primary"
248
288
  :icon="Document"
249
289
  :disabled="!canEdit"
250
- aria-label="保存并关闭"
290
+ :aria-label="t('system.codegen.column.action.saveAndClose')"
251
291
  @click="handleSaveOptionDialog"
252
292
  >
253
- 保存
293
+ {{ t("common.action.save") }}
254
294
  </el-button>
255
295
  </div>
256
296
  </template>
257
297
 
258
298
  <div v-if="optionDialog.option" class="code-gen-option-dialog">
259
299
  <div v-if="optionDialog.formConfig" class="code-gen-popover-form__row">
260
- <span class="code-gen-popover-form__label">选择模式</span>
300
+ <span class="code-gen-popover-form__label">{{ t("system.codegen.column.field.selectionMode") }}</span>
261
301
  <el-radio-group v-model="optionDialog.formConfig.multiple" :disabled="!canEdit">
262
- <el-radio-button :value="false">单选</el-radio-button>
263
- <el-tooltip content="多选仅支持 JSON 字段" :disabled="optionDialog.isJSONColumn" placement="top">
264
- <el-radio-button :value="true" :disabled="!optionDialog.isJSONColumn">多选</el-radio-button>
302
+ <el-radio-button :value="false">{{ t("system.codegen.column.value.single") }}</el-radio-button>
303
+ <el-tooltip
304
+ :content="t('system.codegen.column.tooltip.multipleJsonOnly')"
305
+ :disabled="optionDialog.isJSONColumn"
306
+ placement="top"
307
+ >
308
+ <el-radio-button :value="true" :disabled="!optionDialog.isJSONColumn">
309
+ {{ t("system.codegen.column.value.multiple") }}
310
+ </el-radio-button>
265
311
  </el-tooltip>
266
312
  </el-radio-group>
267
313
  </div>
@@ -272,31 +318,26 @@
272
318
  "
273
319
  class="code-gen-popover-form__row"
274
320
  >
275
- <span class="code-gen-popover-form__label">来源</span>
321
+ <span class="code-gen-popover-form__label">{{ t("system.codegen.column.field.source") }}</span>
276
322
  <el-select
277
323
  v-model="optionDialog.option.source_type"
278
324
  :disabled="!canEdit"
279
325
  clearable
280
- placeholder="选择来源"
326
+ :placeholder="t('system.codegen.column.placeholder.source')"
281
327
  @change="handleOptionSourceTypeChange"
282
328
  >
283
- <el-option
284
- v-for="item in sourceTypeOptions"
285
- :key="String(item.value)"
286
- :label="item.label"
287
- :value="item.value"
288
- />
329
+ <el-option v-for="item in sourceTypeOptions" :key="String(item.value)" :label="item.label" :value="item.value" />
289
330
  </el-select>
290
331
  </div>
291
332
  <div v-if="optionDialog.option.source_type === 'dict'" class="code-gen-popover-form__row">
292
- <span class="code-gen-popover-form__label">字典</span>
333
+ <span class="code-gen-popover-form__label">{{ t("system.codegen.column.field.dictionary") }}</span>
293
334
  <el-select
294
335
  v-model="optionDialog.option.source_value"
295
336
  :disabled="!canEdit"
296
337
  :loading="loadingDictionaries"
297
338
  filterable
298
339
  clearable
299
- placeholder="选择字典"
340
+ :placeholder="t('system.codegen.column.placeholder.dictionary')"
300
341
  @change="handleOptionSourceValueChange"
301
342
  >
302
343
  <el-option
@@ -309,12 +350,12 @@
309
350
  </div>
310
351
  <template v-if="optionDialog.option.kind === 'switch' && optionDialog.option.source_value">
311
352
  <div class="code-gen-popover-form__row">
312
- <span class="code-gen-popover-form__label">开启值</span>
353
+ <span class="code-gen-popover-form__label">{{ t("system.codegen.column.field.activeValue") }}</span>
313
354
  <el-select
314
355
  v-model="optionDialog.option.active_value"
315
356
  :disabled="!canEdit"
316
357
  filterable
317
- placeholder="选择开启值"
358
+ :placeholder="t('system.codegen.column.placeholder.activeValue')"
318
359
  >
319
360
  <el-option
320
361
  v-for="item in dictionaryItemsForEditor"
@@ -326,12 +367,12 @@
326
367
  </el-select>
327
368
  </div>
328
369
  <div class="code-gen-popover-form__row">
329
- <span class="code-gen-popover-form__label">关闭值</span>
370
+ <span class="code-gen-popover-form__label">{{ t("system.codegen.column.field.inactiveValue") }}</span>
330
371
  <el-select
331
372
  v-model="optionDialog.option.inactive_value"
332
373
  :disabled="!canEdit"
333
374
  filterable
334
- placeholder="选择关闭值"
375
+ :placeholder="t('system.codegen.column.placeholder.inactiveValue')"
335
376
  >
336
377
  <el-option
337
378
  v-for="item in dictionaryItemsForEditor"
@@ -344,14 +385,14 @@
344
385
  </div>
345
386
  </template>
346
387
  <div v-else-if="optionDialog.option.source_type === 'table'" class="code-gen-popover-form__row">
347
- <span class="code-gen-popover-form__label">数据表</span>
388
+ <span class="code-gen-popover-form__label">{{ t("system.codegen.column.field.dataTable") }}</span>
348
389
  <el-select
349
390
  v-model="optionDialog.option.source_value"
350
391
  :disabled="!canEdit"
351
392
  :loading="loadingDatabaseTables"
352
393
  filterable
353
394
  clearable
354
- placeholder="选择数据表"
395
+ :placeholder="t('system.codegen.column.placeholder.dataTable')"
355
396
  @change="handleOptionSourceValueChange"
356
397
  >
357
398
  <el-option
@@ -364,14 +405,14 @@
364
405
  </div>
365
406
  <template v-if="optionDialog.option.source_type === 'table'">
366
407
  <div v-if="optionDialog.option.kind === 'tree'" class="code-gen-popover-form__row">
367
- <span class="code-gen-popover-form__label">树父字段</span>
408
+ <span class="code-gen-popover-form__label">{{ t("system.codegen.column.field.treeParent") }}</span>
368
409
  <el-select
369
410
  v-model="optionDialog.option.parent_field"
370
411
  :disabled="!canEdit || !optionDialog.option.source_value"
371
412
  :loading="loadingDatabaseColumns.has(optionDialog.option.source_value)"
372
413
  filterable
373
414
  clearable
374
- placeholder="选择树父字段"
415
+ :placeholder="t('system.codegen.column.placeholder.treeParent')"
375
416
  >
376
417
  <el-option
377
418
  v-for="item in databaseColumnsForEditor"
@@ -382,14 +423,20 @@
382
423
  </el-select>
383
424
  </div>
384
425
  <div v-if="optionDialog.option.kind === 'tree'" class="code-gen-popover-form__row">
385
- <span class="code-gen-popover-form__label">加载方式</span>
426
+ <span class="code-gen-popover-form__label">{{ t("system.codegen.column.field.loadMode") }}</span>
386
427
  <el-checkbox v-model="optionDialog.option.lazy" :disabled="!canEdit">
387
- 懒加载子节点
428
+ {{ t("system.codegen.column.value.lazyChildren") }}
388
429
  </el-checkbox>
389
430
  </div>
390
431
  <div class="code-gen-popover-form__row">
391
432
  <span class="code-gen-popover-form__label">
392
- {{ optionDialog.option.kind === "tree" ? "树显示字段" : "Label 字段" }}
433
+ {{
434
+ t(
435
+ optionDialog.option.kind === "tree"
436
+ ? "system.codegen.column.field.treeLabel"
437
+ : "system.codegen.column.field.labelField"
438
+ )
439
+ }}
393
440
  </span>
394
441
  <el-select
395
442
  v-model="optionDialog.option.label_field"
@@ -397,7 +444,13 @@
397
444
  :loading="loadingDatabaseColumns.has(optionDialog.option.source_value)"
398
445
  filterable
399
446
  clearable
400
- :placeholder="optionDialog.option.kind === 'tree' ? '选择树显示字段' : '选择显示字段'"
447
+ :placeholder="
448
+ t(
449
+ optionDialog.option.kind === 'tree'
450
+ ? 'system.codegen.column.placeholder.treeLabel'
451
+ : 'system.codegen.column.placeholder.labelField'
452
+ )
453
+ "
401
454
  >
402
455
  <el-option
403
456
  v-for="item in databaseColumnsForEditor"
@@ -409,7 +462,13 @@
409
462
  </div>
410
463
  <div class="code-gen-popover-form__row">
411
464
  <span class="code-gen-popover-form__label">
412
- {{ optionDialog.option.kind === "tree" ? "树值字段" : "Value 字段" }}
465
+ {{
466
+ t(
467
+ optionDialog.option.kind === "tree"
468
+ ? "system.codegen.column.field.treeValue"
469
+ : "system.codegen.column.field.valueField"
470
+ )
471
+ }}
413
472
  </span>
414
473
  <el-select
415
474
  v-model="optionDialog.option.value_field"
@@ -417,7 +476,13 @@
417
476
  :loading="loadingDatabaseColumns.has(optionDialog.option.source_value)"
418
477
  filterable
419
478
  clearable
420
- :placeholder="optionDialog.option.kind === 'tree' ? '选择树值字段' : '选择值字段'"
479
+ :placeholder="
480
+ t(
481
+ optionDialog.option.kind === 'tree'
482
+ ? 'system.codegen.column.placeholder.treeValue'
483
+ : 'system.codegen.column.placeholder.valueField'
484
+ )
485
+ "
421
486
  >
422
487
  <el-option
423
488
  v-for="item in databaseColumnsForEditor"
@@ -430,31 +495,38 @@
430
495
  </template>
431
496
  <div v-if="optionDialog.option.source_type === 'static'" class="code-gen-static-options">
432
497
  <div class="code-gen-static-options__header">
433
- <span class="code-gen-popover-form__label">静态数据</span>
434
- <el-button size="small" :icon="Plus" :disabled="!canEdit" @click="addStaticOption">添加</el-button>
498
+ <span class="code-gen-popover-form__label">{{ t("system.codegen.column.field.staticData") }}</span>
499
+ <el-button size="small" :icon="Plus" :disabled="!canEdit" @click="addStaticOption">
500
+ {{ t("common.action.create") }}
501
+ </el-button>
435
502
  </div>
436
503
  <div v-if="staticOptionsForEditor.length" class="code-gen-static-options__list">
437
504
  <div v-for="(item, index) in staticOptionsForEditor" :key="index" class="code-gen-static-options__item">
438
- <el-input v-model="item.label" :disabled="!canEdit" placeholder="Label" @input="syncStaticOptions" />
505
+ <el-input
506
+ v-model="item.label"
507
+ :disabled="!canEdit"
508
+ :placeholder="t('system.codegen.column.placeholder.optionLabel')"
509
+ @input="syncStaticOptions"
510
+ />
439
511
  <el-input
440
512
  :model-value="String(item.value)"
441
513
  :disabled="!canEdit"
442
- placeholder="Value"
514
+ :placeholder="t('system.codegen.column.placeholder.optionValue')"
443
515
  @update:model-value="updateStaticOptionValue(item, $event)"
444
516
  />
445
- <el-tooltip content="删除静态数据" placement="top">
517
+ <el-tooltip :content="t('system.codegen.column.action.deleteStatic')" placement="top">
446
518
  <el-button
447
519
  :icon="Delete"
448
520
  :disabled="!canEdit"
449
521
  circle
450
522
  text
451
- aria-label="删除静态数据"
523
+ :aria-label="t('system.codegen.column.action.deleteStatic')"
452
524
  @click="removeStaticOption(index)"
453
525
  />
454
526
  </el-tooltip>
455
527
  </div>
456
528
  </div>
457
- <el-empty v-else :image-size="48" description="暂无静态数据" />
529
+ <el-empty v-else :image-size="48" :description="t('system.codegen.column.message.emptyStatic')" />
458
530
  </div>
459
531
  </div>
460
532
  </ProDialog>
@@ -464,12 +536,14 @@
464
536
  <script setup lang="ts">
465
537
  import Sortable from "sortablejs";
466
538
  import { computed, nextTick, onBeforeUnmount, onMounted, reactive, ref, watch } from "vue";
467
- import { Delete, Document, List, Plus, Setting } from "@element-plus/icons-vue";
539
+ import { ChatLineSquare, Delete, Document, List, Plus, Setting } from "@element-plus/icons-vue";
468
540
  import { useRoute, useRouter } from "vue-router";
541
+ import { t } from "@liujitcn/kratos-admin-core";
469
542
  import ProDialog from "@liujitcn/kratos-admin-core/components/Dialog/ProDialog.vue";
470
543
  import { useAuthButtons } from "@liujitcn/kratos-admin-core/auth";
471
544
  import { useTabsStore } from "@liujitcn/kratos-admin-core/stores/runtime";
472
545
  import { defBaseDictService } from "@liujitcn/kratos-admin-system/api/system/base_dict";
546
+ import { loadEnabledBaseLanguages } from "@liujitcn/kratos-admin-system/api/system/base_language";
473
547
  import { defCodeGenColumnService } from "@liujitcn/kratos-admin-system/api/system/code_gen_column";
474
548
  import { defCodeGenTableService } from "@liujitcn/kratos-admin-system/api/system/code_gen_table";
475
549
  import type { OptionBaseDictResponse_BaseDict } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_dict";
@@ -482,6 +556,8 @@ import type {
482
556
  CodeGenDatabaseColumn
483
557
  } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/code_gen_column";
484
558
  import type { CodeGenDatabaseTable, CodeGenTableForm } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/code_gen_table";
559
+ import CodeGenLocaleEditor from "../components/CodeGenLocaleEditor.vue";
560
+ import { getEditableLanguageOptions } from "@liujitcn/kratos-admin-system/components/dynamicTranslation";
485
561
  import {
486
562
  copyCodeGenOptionToEmptyMatches,
487
563
  copyFirstMatchingCodeGenOption,
@@ -491,11 +567,11 @@ import {
491
567
  } from "./option-copy";
492
568
  import type { CodeGenOptionContainer, CodeGenOptionScope } from "./option-copy";
493
569
  import {
494
- codeGenFormComponentOptions as formComponentOptions,
495
- codeGenListComponentOptions as listComponentOptions,
496
- codeGenQueryComponentOptions as queryComponentOptions,
497
- codeGenQueryOperatorOptions as queryOperatorOptions,
498
- codeGenSourceTypeOptions as sourceTypeOptions,
570
+ codeGenFormComponentOptions,
571
+ codeGenListComponentOptions,
572
+ codeGenQueryComponentOptions,
573
+ codeGenQueryOperatorOptions,
574
+ codeGenSourceTypeOptions,
499
575
  createDefaultCodeGenFormConfig,
500
576
  createDefaultCodeGenListConfig,
501
577
  createDefaultCodeGenOptionConfig,
@@ -552,7 +628,6 @@ interface CodeGenStaticOption {
552
628
  interface CodeGenOptionDialog {
553
629
  visible: boolean;
554
630
  scope: CodeGenOptionScope;
555
- scopeLabel: string;
556
631
  columnName: string;
557
632
  component: string;
558
633
  isJSONColumn: boolean;
@@ -577,7 +652,6 @@ interface CodeGenColumnOptionConsistencyIssue {
577
652
  const optionDialog = reactive<CodeGenOptionDialog>({
578
653
  visible: false,
579
654
  scope: "query",
580
- scopeLabel: "查询",
581
655
  columnName: "",
582
656
  component: "",
583
657
  isJSONColumn: false,
@@ -601,6 +675,17 @@ const enabledSummary = computed(() => ({
601
675
  list: columns.value.filter(item => item.list_config.enabled).length,
602
676
  form: columns.value.filter(item => item.form_config.enabled).length
603
677
  }));
678
+ const queryOperatorOptions = computed(() => codeGenQueryOperatorOptions());
679
+ const queryComponentOptions = computed(() => codeGenQueryComponentOptions());
680
+ const listComponentOptions = computed(() => codeGenListComponentOptions());
681
+ const formComponentOptions = computed(() => codeGenFormComponentOptions());
682
+ const sourceTypeOptions = computed(() => codeGenSourceTypeOptions());
683
+ const optionDialogTitle = computed(() =>
684
+ t("system.codegen.column.title.options", {
685
+ scope: codeGenScopeLabel(optionDialog.scope),
686
+ column: optionDialog.columnName
687
+ })
688
+ );
604
689
 
605
690
  /** 当前选项编辑器可用的数据库字段。 */
606
691
  const databaseColumnsForEditor = computed(() => {
@@ -653,7 +738,9 @@ async function handleQuery() {
653
738
  /** 同步当前页签和浏览器标题。 */
654
739
  function syncWorkspaceTitle() {
655
740
  const tableTitle = formData.comment || formData.name;
656
- const title = tableTitle ? `${tableTitle}字段配置` : "字段配置";
741
+ const title = tableTitle
742
+ ? t("system.codegen.column.title.workspaceWithTable", { table: tableTitle })
743
+ : t("system.codegen.column.title.workspace");
657
744
  tabsStore.setTabsTitle(title);
658
745
  document.title = `${title} - ${import.meta.env.VITE_GLOB_APP_TITLE}`;
659
746
  }
@@ -664,7 +751,7 @@ async function handleSaveColumns(showMessage = true) {
664
751
  syncColumnSorts();
665
752
  columns.value.forEach(syncColumnOptionKinds);
666
753
  if (columns.value.some(item => !item.name || !item.db_type)) {
667
- ElMessage.warning("字段名和数据库类型不能为空");
754
+ ElMessage.warning(t("system.codegen.column.message.nameAndTypeRequired"));
668
755
  return false;
669
756
  }
670
757
  const optionIssue = findCodeGenColumnOptionIssue(columns.value);
@@ -677,11 +764,14 @@ async function handleSaveColumns(showMessage = true) {
677
764
  if (consistencyIssue) {
678
765
  try {
679
766
  await ElMessageBox.confirm(
680
- `字段 ${consistencyIssue.columnName} 的${consistencyIssue.scopes}选项来源不一致,是否继续保存?`,
681
- "选项配置警告",
767
+ t("system.codegen.column.dialog.inconsistentSource", {
768
+ column: consistencyIssue.columnName,
769
+ scopes: consistencyIssue.scopes
770
+ }),
771
+ t("system.codegen.column.title.optionWarning"),
682
772
  {
683
- confirmButtonText: "继续保存",
684
- cancelButtonText: "返回修改",
773
+ confirmButtonText: t("system.codegen.column.action.continueSave"),
774
+ cancelButtonText: t("system.codegen.column.action.backToEdit"),
685
775
  type: "warning"
686
776
  }
687
777
  );
@@ -697,7 +787,7 @@ async function handleSaveColumns(showMessage = true) {
697
787
  sort: index + 1
698
788
  }))
699
789
  });
700
- if (showMessage) ElMessage.success("保存成功");
790
+ if (showMessage) ElMessage.success(t("common.message.operationSuccess"));
701
791
  // 路由切换前保留当前页签地址,避免误删目标页签。
702
792
  const currentPath = route.fullPath;
703
793
  await router.push("/code/gen/table");
@@ -788,7 +878,6 @@ async function openOptionDialog(row: CodeGenColumnView, scope: CodeGenOptionScop
788
878
  const config = getCodeGenOptionContainer(row, scope);
789
879
  syncOptionKind(config, scope);
790
880
  optionDialog.scope = scope;
791
- optionDialog.scopeLabel = scope === "query" ? "查询" : scope === "list" ? "列表" : "表单";
792
881
  optionDialog.columnName = row.name;
793
882
  optionDialog.component = config.component;
794
883
  optionDialog.isJSONColumn = row.db_type.trim().toLowerCase() === "json";
@@ -935,9 +1024,7 @@ function applyTableOptionDefaultFields(option: CodeGenColumnOptionConfig, compon
935
1024
  /** 格式化数据表字段选项。 */
936
1025
  function formatDatabaseColumn(column: CodeGenDatabaseColumn) {
937
1026
  const columnType = column.column_type || column.db_type;
938
- return column.comment
939
- ? `${column.name}(${column.comment} / ${columnType})`
940
- : `${column.name}(${columnType})`;
1027
+ return column.comment ? `${column.name}(${column.comment} / ${columnType})` : `${column.name}(${columnType})`;
941
1028
  }
942
1029
 
943
1030
  /** 添加一条空白静态选项。 */
@@ -1011,7 +1098,7 @@ function findCodeGenColumnOptionIssue(items: CodeGenColumnView[]): CodeGenColumn
1011
1098
  ["form", column.form_config.option]
1012
1099
  ];
1013
1100
  for (const [scope, option] of optionConfigs) {
1014
- const scopeLabel = scope === "query" ? "查询" : scope === "list" ? "列表" : "表单";
1101
+ const scopeLabel = codeGenScopeLabel(scope);
1015
1102
  const message = getCodeGenOptionValidationMessage(column.name, scopeLabel, option);
1016
1103
  if (message) return { row: column, scope, message };
1017
1104
  }
@@ -1023,17 +1110,20 @@ function findCodeGenColumnOptionConsistencyIssue(items: CodeGenColumnView[]): Co
1023
1110
  for (const column of items) {
1024
1111
  const entries = (
1025
1112
  [
1026
- ["查询", column.query_config, "query"],
1027
- ["列表", column.list_config, "list"],
1028
- ["表单", column.form_config, "form"]
1113
+ [codeGenScopeLabel("query"), column.query_config, "query"],
1114
+ [codeGenScopeLabel("list"), column.list_config, "list"],
1115
+ [codeGenScopeLabel("form"), column.form_config, "form"]
1029
1116
  ] as const
1030
- ).filter(([, config, scope]) => config.enabled && hasOptionComponent(config.component, scope) && isCompleteCodeGenOptionConfig(config.option));
1117
+ ).filter(
1118
+ ([, config, scope]) =>
1119
+ config.enabled && hasOptionComponent(config.component, scope) && isCompleteCodeGenOptionConfig(config.option)
1120
+ );
1031
1121
  if (entries.length < 2) continue;
1032
1122
  const firstSignature = codeGenOptionSourceSignature(entries[0][1].option);
1033
1123
  if (entries.every(([, config]) => codeGenOptionSourceSignature(config.option) === firstSignature)) continue;
1034
1124
  return {
1035
1125
  columnName: column.name,
1036
- scopes: entries.map(([label]) => label).join("、")
1126
+ scopes: entries.map(([label]) => label).join(t("system.codegen.preview.value.listSeparator"))
1037
1127
  };
1038
1128
  }
1039
1129
  }
@@ -1062,33 +1152,34 @@ function getCodeGenOptionValidationMessage(columnName: string, scope: string, op
1062
1152
  option.inactive_value ||
1063
1153
  option.lazy
1064
1154
  );
1065
- if (!option.kind) return hasSourceFields ? `字段 ${columnName} 的${scope}选项配置无对应组件` : "";
1155
+ const args = { column: columnName, scope };
1156
+ if (!option.kind) return hasSourceFields ? t("system.codegen.column.validation.optionComponentMissing", args) : "";
1066
1157
  if (option.kind === "switch") {
1067
1158
  if (option.source_type !== "dict" || !option.source_value || !option.active_value || !option.inactive_value) {
1068
- return `字段 ${columnName} 的${scope}开关配置不完整`;
1159
+ return t("system.codegen.column.validation.switchIncomplete", args);
1069
1160
  }
1070
- if (option.active_value === option.inactive_value) return `字段 ${columnName} 的${scope}开启值和关闭值不能相同`;
1161
+ if (option.active_value === option.inactive_value) return t("system.codegen.column.validation.switchValuesSame", args);
1071
1162
  return "";
1072
1163
  }
1073
- if (option.active_value || option.inactive_value) return `字段 ${columnName} 的${scope}选项不能配置开关值`;
1074
- if (option.lazy && option.kind !== "tree") return `字段 ${columnName} 的${scope}仅树形选项支持懒加载`;
1164
+ if (option.active_value || option.inactive_value) return t("system.codegen.column.validation.switchValuesUnsupported", args);
1165
+ if (option.lazy && option.kind !== "tree") return t("system.codegen.column.validation.lazyTreeOnly", args);
1075
1166
  if (option.kind === "tree" && option.source_type !== "table") {
1076
- return `字段 ${columnName} 的${scope}树形选项只能使用数据表来源`;
1167
+ return t("system.codegen.column.validation.treeTableOnly", args);
1077
1168
  }
1078
1169
  if (!new Set(["static", "dict", "table"]).has(option.source_type) || !option.source_value) {
1079
- return `字段 ${columnName} 的${scope}选项来源配置不完整`;
1170
+ return t("system.codegen.column.validation.sourceIncomplete", args);
1080
1171
  }
1081
1172
  if (option.source_type === "static") {
1082
1173
  const options = parseCodeGenStaticOptions(option.source_value);
1083
1174
  if (!options.length || options.some(item => item.label === "" || item.value === "")) {
1084
- return `字段 ${columnName} 的${scope}选项至少需要一条完整的静态数据`;
1175
+ return t("system.codegen.column.validation.staticIncomplete", args);
1085
1176
  }
1086
1177
  }
1087
1178
  if (
1088
1179
  option.source_type === "table" &&
1089
1180
  (!option.label_field || !option.value_field || (option.kind === "tree" && !option.parent_field))
1090
1181
  ) {
1091
- return `字段 ${columnName} 的${scope}数据表选项字段配置不完整`;
1182
+ return t("system.codegen.column.validation.tableFieldsIncomplete", args);
1092
1183
  }
1093
1184
  return "";
1094
1185
  }
@@ -1105,7 +1196,19 @@ function hasOptionConfig(option: CodeGenColumnOptionConfig) {
1105
1196
 
1106
1197
  /** 返回选项入口的当前状态提示。 */
1107
1198
  function optionEntryTip(option: CodeGenColumnOptionConfig) {
1108
- return hasOptionConfig(option) ? "已配置,可直接保存;需要覆盖时可打开修改" : "配置选项";
1199
+ return t(
1200
+ hasOptionConfig(option) ? "system.codegen.column.tooltip.optionConfigured" : "system.codegen.column.tooltip.configureOption"
1201
+ );
1202
+ }
1203
+
1204
+ /** 返回配置范围的当前语言名称。 */
1205
+ function codeGenScopeLabel(scope: CodeGenOptionScope) {
1206
+ return t(`system.codegen.column.scope.${scope}`);
1207
+ }
1208
+
1209
+ /** 判断字段是否缺少任一非主语言描述。 */
1210
+ function hasMissingColumnLocales(column: CodeGenColumnView) {
1211
+ return getEditableLanguageOptions().some(item => !column.i18n_config?.get(item.value)?.comment);
1109
1212
  }
1110
1213
 
1111
1214
  /** 判断组件是否依赖选择数据源。 */
@@ -1131,11 +1234,7 @@ function syncOptionKind(config: CodeGenOptionContainer, scope: CodeGenOptionScop
1131
1234
  return;
1132
1235
  }
1133
1236
  const kind =
1134
- config.component === "tree-select"
1135
- ? "tree"
1136
- : scope !== "query" && config.component === "switch"
1137
- ? "switch"
1138
- : "option";
1237
+ config.component === "tree-select" ? "tree" : scope !== "query" && config.component === "switch" ? "switch" : "option";
1139
1238
  if (kind === "tree" && config.option.source_type !== "table") {
1140
1239
  Object.assign(config.option, createDefaultCodeGenOptionConfig());
1141
1240
  config.option.source_type = "table";
@@ -1172,6 +1271,7 @@ function syncOptionKind(config: CodeGenOptionContainer, scope: CodeGenOptionScop
1172
1271
 
1173
1272
  onMounted(() => {
1174
1273
  syncWorkspaceTitle();
1274
+ void loadEnabledBaseLanguages();
1175
1275
  void handleQuery();
1176
1276
  });
1177
1277
 
@@ -1318,6 +1418,7 @@ onBeforeUnmount(() => {
1318
1418
  }
1319
1419
 
1320
1420
  .code-gen-config-cell,
1421
+ .code-gen-comment-editor,
1321
1422
  .code-gen-static-options__header,
1322
1423
  .code-gen-static-options__item {
1323
1424
  display: flex;
@@ -1326,6 +1427,14 @@ onBeforeUnmount(() => {
1326
1427
  align-items: center;
1327
1428
  }
1328
1429
 
1430
+ .code-gen-comment-editor {
1431
+ flex-wrap: nowrap;
1432
+ }
1433
+
1434
+ .code-gen-comment-editor .el-input {
1435
+ min-width: 0;
1436
+ }
1437
+
1329
1438
  .code-gen-field-trigger__name {
1330
1439
  flex-shrink: 0;
1331
1440
  max-width: 135px;