yh-i18n 1.1.0 → 1.2.1

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.
package/excelTool.ts ADDED
@@ -0,0 +1,201 @@
1
+ import * as ExcelJS from "exceljs";
2
+ import Config from "@/config";
3
+ import { ElMessage, ElLoading } from "element-plus";
4
+ import http from "@/libs/api.request";
5
+
6
+ const verificationCode = "lkyhtranslateexcel";
7
+ export async function exportExcel(dataList) {
8
+ const loading = ElLoading.service({
9
+ lock: true,
10
+ text: "正在导出当前页面的翻译字段",
11
+ background: "rgba(255, 255, 255, 0.2)",
12
+ });
13
+ const workbook = new ExcelJS.Workbook();
14
+ workbook.creator = "力控远海";
15
+ workbook.lastModifiedBy = "力控远海技术中心前端";
16
+ workbook.keywords = verificationCode;
17
+ workbook.created = new Date();
18
+ workbook.modified = new Date();
19
+ const sheet = workbook.addWorksheet(`${Config.title}-系统待翻译文字`);
20
+
21
+ let columns: any[] = [
22
+ { width: 0, hidden: true },
23
+ { width: 0, hidden: true },
24
+ ];
25
+ let title: string[] = ["", ""];
26
+ let titleObj = {
27
+ zh_CN: "中文",
28
+ en_US: "英语",
29
+ th: "泰语",
30
+ vi: "越南语",
31
+ tr: "土耳其语",
32
+ };
33
+ Config.i18nList.forEach((item) => {
34
+ columns.push({
35
+ width: 30,
36
+ alignment: { vertical: "middle", horizontal: "center", wrapText: true },
37
+ value: item,
38
+ });
39
+ title.push(titleObj[item]);
40
+ });
41
+
42
+ sheet.columns = columns;
43
+ sheet.addRow(title);
44
+ sheet.addRows(
45
+ dataList.map((item) => {
46
+ let { adTranslateId, key } = item;
47
+ let row = [adTranslateId, key];
48
+ Config.i18nList.forEach((valKey) => {
49
+ row.push(item[valKey]);
50
+ });
51
+ return row;
52
+ })
53
+ );
54
+ sheet.getRows(1, 1)?.forEach((row, index) => {
55
+ row.height = 25;
56
+ row.eachCell({ includeEmpty: true }, (cell, cellIndex) => {
57
+ cell.font = { bold: true };
58
+ cell.alignment = {
59
+ vertical: "middle",
60
+ horizontal: "center",
61
+ wrapText: true,
62
+ };
63
+ cell.border = {
64
+ top: { style: "thin" },
65
+ left: { style: "thin" },
66
+ bottom: { style: "thin" },
67
+ right: { style: "thin" },
68
+ };
69
+ });
70
+ });
71
+ sheet.getRows(2, dataList.length)?.forEach((row, index) => {
72
+ row.height = 25;
73
+ row.eachCell({ includeEmpty: true }, (cell, cellIndex) => {
74
+ cell.alignment = {
75
+ vertical: "middle",
76
+ horizontal: "left",
77
+ wrapText: true,
78
+ };
79
+ cell.border = {
80
+ top: { style: "thin" },
81
+ left: { style: "thin" },
82
+ bottom: { style: "thin" },
83
+ right: { style: "thin" },
84
+ };
85
+ });
86
+ });
87
+ sheet.views = [{ state: "frozen", xSplit: 0, ySplit: 1, activeCell: "C2" }];
88
+ workbook.xlsx.writeBuffer().then((data) => {
89
+ const blob = new Blob([data], {
90
+ type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8",
91
+ });
92
+ let downloadA = document.createElement("a");
93
+ downloadA.download = `${Config.title}-系统待翻译文字.xlsx`;
94
+ downloadA.href = window.URL.createObjectURL(blob);
95
+ downloadA.click();
96
+ loading.close();
97
+ ElMessage.success("导出成功,请到下载目录查看");
98
+ });
99
+ }
100
+
101
+ async function getFile() {
102
+ // @ts-ignore
103
+ let fileHandle = await window.showOpenFilePicker({
104
+ id: "importTranslateExcel",
105
+ types: [
106
+ {
107
+ description: "请选择之前导出并已经翻译好了的Excel文件",
108
+ accept: {
109
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": [
110
+ ".xlsx",
111
+ ".xls",
112
+ ],
113
+ },
114
+ },
115
+ ],
116
+ });
117
+ if (Array.isArray(fileHandle)) {
118
+ fileHandle = fileHandle[0];
119
+ }
120
+ let state = await fileHandle.queryPermission({ mode: "read" });
121
+ if (state === "denied") {
122
+ return false;
123
+ } else {
124
+ if (state === "prompt") {
125
+ fileHandle.requestPermission({
126
+ mode: "read",
127
+ });
128
+ }
129
+ return await fileHandle.getFile();
130
+ }
131
+ }
132
+
133
+ export async function importExcel(getDataList) {
134
+ if (!window["showOpenFilePicker"]) {
135
+ ElMessage({
136
+ message: "请使用Chrome(Edge) 102 及以上版本的浏览器",
137
+ type: "warning",
138
+ });
139
+ return false;
140
+ }
141
+ let file = await getFile();
142
+ if (file === false) {
143
+ ElMessage({
144
+ message: "请授权浏览器读取文件",
145
+ type: "warning",
146
+ });
147
+ return false;
148
+ } else {
149
+ const workbook = new ExcelJS.Workbook();
150
+ await workbook.xlsx.load(file);
151
+ if (workbook.keywords !== verificationCode) {
152
+ ElMessage({
153
+ message: "您选择的文件不是系统导出的文件",
154
+ type: "warning",
155
+ });
156
+ return false;
157
+ }
158
+ const loading = ElLoading.service({
159
+ lock: true,
160
+ text: "开始读取已翻译的字段",
161
+ background: "rgba(255, 255, 255, 0.2)",
162
+ });
163
+ let sheet = workbook.worksheets[0];
164
+ let len = sheet._rows.length - 1;
165
+ let dataList: any[] = [];
166
+ sheet.getRows(2, len)?.forEach((row) => {
167
+ let id = row.getCell(1).value;
168
+ let key = row.getCell(2).value;
169
+ let content: any = {};
170
+ Config.i18nList.forEach((item, index) => {
171
+ content[item] = row.getCell(index + 3).value;
172
+ });
173
+ dataList.push({
174
+ id,
175
+ key,
176
+ content: JSON.stringify(content),
177
+ });
178
+ });
179
+ loading.setText("读取完成,正在更新");
180
+
181
+ http
182
+ .request({
183
+ url: "/translate/save",
184
+ type: "json",
185
+ method: "POST",
186
+ data: dataList,
187
+ })
188
+ .then((res) => {
189
+ loading.close();
190
+ if (res?.data?.status === 200) {
191
+ ElMessage.success("导入成功!");
192
+ getDataList();
193
+ } else {
194
+ ElMessage.error(res.data.msg);
195
+ }
196
+ })
197
+ .finally((err) => {
198
+ loading.close();
199
+ });
200
+ }
201
+ }
package/index.d.ts CHANGED
@@ -1,3 +1,6 @@
1
+ import { I18n } from "vue-i18n";
2
+ import { StoreDefinition } from "pinia";
3
+
1
4
  /**
2
5
  * zh_CN 简体中文
3
6
  * en_US 英语(美国)
@@ -6,3 +9,18 @@
6
9
  * tr 土耳其语(土耳其)
7
10
  */
8
11
  type I18nList = "zh_CN" | "en_US" | "th" | "vi" | "tr";
12
+
13
+ declare global {
14
+ interface Window {
15
+ /** 国际化翻译组件是否准备好 */
16
+ translateReady: boolean;
17
+ }
18
+ }
19
+ /** 国际化组件实例 */
20
+ export const i18n: I18n;
21
+
22
+ /** 自定义的翻译函数,这个函数包装了 t 函数,在翻译的前提下,可以帮忙手机键 */
23
+ export const ct: (key: string, args: any[]) => void;
24
+
25
+ /** 国际化相关 Pinia Store 实例 */
26
+ export const useI18nStore: StoreDefinition;
package/index.js CHANGED
@@ -30,7 +30,7 @@ const initlang = localStorage.local || localLang || "zh_CN";
30
30
 
31
31
  export let i18n = null;
32
32
  const isDev = import.meta.env.DEV;
33
- window.translateReady = false;
33
+ window.translateReady = !!localStorage.translateReady || false;
34
34
  function addTranslate(key) {
35
35
  if (key.indexOf("vxe") === -1) {
36
36
  try {
package/lang/baseEnUS.js CHANGED
@@ -1,14 +1,23 @@
1
1
  export default {
2
2
  翻译键名: "Translate key names",
3
3
  翻译管理: "Translation management",
4
- 键入以筛选键名: "filter key names",
5
- 搜索: "search",
4
+ 键入以筛选键名: "Filter key names",
5
+ 搜索: "Search",
6
6
  新增: "New addition",
7
7
  批量删除: "Batch deletion",
8
- 重置: "reset",
9
- 编辑: "edit",
10
- 删除: "delete",
11
- 操作: "operation",
8
+ 重置: "Reset",
9
+ 编辑: "Edit",
10
+ 删除: "Delete",
11
+ 操作: "Operation",
12
+ 导出当前页: "Export current page",
13
+ 导入: "Import",
14
+ 翻译键值: "Translation Key Values",
15
+ 新增翻译: "Add translation",
16
+ 编辑翻译: "Edit translation",
17
+ 请输入翻译键值: "Please enter the translation key value",
18
+ 上一个: "Previous",
19
+ 下一个: "Next",
20
+ 取消: "Cancel",
12
21
  中文简体: "Simplified Chinese",
13
22
  English: "English",
14
23
  ไทย: "Thailand.",
package/lang/baseTh.js CHANGED
@@ -9,6 +9,15 @@ export default {
9
9
  编辑: "บรรณาธิการ",
10
10
  删除: "ลบ",
11
11
  操作: "การดำเนินงาน",
12
+ 导出当前页: "ส่งออกหน้าปัจจุบัน",
13
+ 导入: "นำเข้า",
14
+ 翻译键值: "แปลค่ากุญแจ",
15
+ 新增翻译: "เพิ่มการแปล",
16
+ 编辑翻译: "แก้ไขการแปล",
17
+ 请输入翻译键值: "โปรดป้อนค่ากุญแจการแปล",
18
+ 上一个: "ก่อนหน้า",
19
+ 下一个: "ถัดไป",
20
+ 取消: "การยกเลิก",
12
21
  中文简体: "ภาษาจีนตัวย่อ",
13
22
  English: "ภาษาอังกฤษ",
14
23
  ไทย: "ไทย",
package/lang/baseTr.js CHANGED
@@ -9,6 +9,15 @@ export default {
9
9
  编辑: "edit",
10
10
  删除: "Sil",
11
11
  操作: "operasyon",
12
+ 导出当前页: "Ağımdaki sayfanı dışarı aktar",
13
+ 导入: "İçeri",
14
+ 翻译键值: "Çeviri Anahtarı Değerleri",
15
+ 新增翻译: "Çeviri ekle",
16
+ 编辑翻译: "Çeviri düzenle",
17
+ 请输入翻译键值: "Lütfen çevirim anahtarı değerini girin",
18
+ 上一个: "Önceki",
19
+ 下一个: "Sonraki",
20
+ 取消: "iptal et",
12
21
  中文简体: "Basitleştirilmiş Çince",
13
22
  English: "İngilizce",
14
23
  ไทย: "Tayland.",
package/lang/baseVi.js CHANGED
@@ -9,6 +9,15 @@ export default {
9
9
  编辑: "Chỉnh sửa",
10
10
  删除: "Xoá",
11
11
  操作: "Hoạt động",
12
+ 导出当前页: "Xuất trang hiện tại",
13
+ 导入: "Nhập khẩu",
14
+ 翻译键值: "Dịch giá trị khóa",
15
+ 新增翻译: "Thêm bản dịch",
16
+ 编辑翻译: "Biên dịch",
17
+ 请输入翻译键值: "Vui lòng nhập giá trị khóa dịch",
18
+ 上一个: "Trước",
19
+ 下一个: "Tiếp theo",
20
+ 取消: "Hủy bỏ",
12
21
  中文简体: "Trung Quốc",
13
22
  English: "Tiếng Việt",
14
23
  ไทย: "Thái Lan.",
package/lang/baseZhCn.js CHANGED
@@ -9,6 +9,15 @@ export default {
9
9
  编辑: "编辑",
10
10
  删除: "删除",
11
11
  操作: "操作",
12
+ 导出当前页: "导出当前页",
13
+ 导入: "导入",
14
+ 翻译键值: "翻译键值",
15
+ 新增翻译: "新增翻译",
16
+ 编辑翻译: "编辑翻译",
17
+ 请输入翻译键值: "请输入翻译键值",
18
+ 上一个: "上一个",
19
+ 下一个: "下一个",
20
+ 取消: "取消",
12
21
  中文简体: "中文简体",
13
22
  English: "英语",
14
23
  ไทย: "泰语",
package/list.vue CHANGED
@@ -1,14 +1,6 @@
1
1
  <template>
2
2
  <div class="yh-i18n-list-container">
3
3
  <div class="yh-i18n-list-actions">
4
- <el-button type="primary" @click="addOne">
5
- <i class="iconfont icon-add"></i>
6
- {{ ct("新增") }}
7
- </el-button>
8
- <el-button type="danger" @click="delMore">
9
- <i class="iconfont icon-delete"></i>
10
- {{ ct("批量删除") }}
11
- </el-button>
12
4
  <div class="yh-i18n-list-conditions">
13
5
  <el-form inline>
14
6
  <el-form-item :label="ct('翻译键名')">
@@ -25,15 +17,32 @@
25
17
  }}</el-button>
26
18
  <el-button @click="resetList">{{ ct("重置") }}</el-button>
27
19
  </div>
20
+ <div class="yh-i18n-list-actions">
21
+ <el-button type="primary" @click="addOne">
22
+ <i class="iconfont icon-add"></i>
23
+ {{ ct("新增") }}
24
+ </el-button>
25
+ <el-button type="danger" @click="delMore">
26
+ <i class="iconfont icon-delete"></i>
27
+ {{ ct("批量删除") }}
28
+ </el-button>
29
+ <el-button text @click="exportExcel(dataList)">
30
+ {{ ct("导出当前页") }}
31
+ </el-button>
32
+ <el-button text @click="importExcel(getDataList)">
33
+ {{ ct("导入") }}
34
+ </el-button>
35
+ </div>
28
36
  <el-table
29
37
  ref="i18nList"
38
+ stripe
30
39
  :data="dataList"
31
40
  row-key="adTranslateId"
32
41
  @row-click="rowClickHandler"
33
42
  >
34
43
  <el-table-column
35
44
  type="selection"
36
- width="60"
45
+ width="50"
37
46
  align="center"
38
47
  fixed="left"
39
48
  ></el-table-column>
@@ -59,7 +68,12 @@
59
68
  }}</el-button>
60
69
  </template>
61
70
  </el-table-column>
62
- <el-table-column prop="key" :label="ct('翻译键名')"></el-table-column>
71
+ <el-table-column
72
+ prop="key"
73
+ min-width="140"
74
+ fixed="left"
75
+ :label="ct('翻译键名')"
76
+ ></el-table-column>
63
77
  <el-table-column
64
78
  v-for="column in listColumns"
65
79
  :prop="column.field"
@@ -70,7 +84,7 @@
70
84
  </el-table>
71
85
  <el-pagination
72
86
  background
73
- :page-sizes="[100, 200, 1000, 10000]"
87
+ :page-sizes="[100, 200, 1000, 100000]"
74
88
  v-model:page-size="listForm.pageSize"
75
89
  :total="listForm.total"
76
90
  v-model:current-page="listForm.pageNum"
@@ -125,7 +139,7 @@ import { ElLoadingService, ElMessage, ElMessageBox } from "element-plus";
125
139
  import { useI18nStore, ct } from "yh-i18n";
126
140
  import http from "@/libs/api.request";
127
141
  import { VxeFormInstance, VxeFormPropTypes } from "vxe-table";
128
-
142
+ import { exportExcel, importExcel } from "./excelTool";
129
143
  const i18nStore = useI18nStore();
130
144
  const vxeFormRef = ref<VxeFormInstance>();
131
145
 
@@ -188,10 +202,17 @@ watch(
188
202
  getDataList();
189
203
  }
190
204
  );
205
+ watch(
206
+ () => listForm.pageSize,
207
+ () => {
208
+ getDataList();
209
+ }
210
+ );
191
211
 
192
212
  function rowClickHandler(row) {
193
213
  i18nList.value?.toggleRowSelection(row);
194
214
  }
215
+
195
216
  function resetList() {
196
217
  listForm.key = "";
197
218
  listForm.pageNum = 1;
@@ -211,9 +232,11 @@ function cancelForm() {
211
232
  formData.id = null;
212
233
  formShow.value = false;
213
234
  }
235
+
214
236
  function addOne() {
215
237
  formShow.value = true;
216
238
  }
239
+
217
240
  function prevOne() {
218
241
  if (formDataIndex.value > 0) {
219
242
  let index = formDataIndex.value - 1;
@@ -221,6 +244,7 @@ function prevOne() {
221
244
  editOne(item, index);
222
245
  }
223
246
  }
247
+
224
248
  function editOne(item, index) {
225
249
  formDataIndex.value = index;
226
250
  for (const key in item) {
@@ -237,6 +261,7 @@ function editOne(item, index) {
237
261
  inputs = Array.from(document.querySelectorAll(".i18n-form-item input"));
238
262
  }, 500);
239
263
  }
264
+
240
265
  function nextOne() {
241
266
  if (formDataIndex.value < dataList.value.length - 1) {
242
267
  let index = formDataIndex.value + 1;
@@ -244,15 +269,21 @@ function nextOne() {
244
269
  editOne(item, index);
245
270
  }
246
271
  }
272
+
247
273
  function saveOne() {
274
+ let isAdd = !!formData.adTranslateId;
248
275
  let url = updateUrl;
249
276
  vxeFormRef?.value?.validate().then((errMap) => {
250
277
  if (!errMap) {
251
- let data = {
252
- id: formData.adTranslateId,
278
+ let data: any = {
253
279
  key: formData.key,
254
280
  content: {},
255
281
  };
282
+ if (isAdd) {
283
+ url = insertUrl;
284
+ } else {
285
+ data.id = formData.adTranslateId;
286
+ }
256
287
  for (const key in formData) {
257
288
  if (key !== "key" && langList.includes(key)) {
258
289
  const val = formData[key];
@@ -269,10 +300,14 @@ function saveOne() {
269
300
  .then((res) => {
270
301
  if (res?.data?.status === 200) {
271
302
  ElMessage.success(res.data.msg);
272
- dataList.value[formDataIndex.value] = {
273
- ...formData,
274
- };
275
- nextOne();
303
+ if (!isAdd) {
304
+ dataList.value[formDataIndex.value] = {
305
+ ...formData,
306
+ };
307
+ nextOne();
308
+ } else {
309
+ cancelForm();
310
+ }
276
311
  } else {
277
312
  ElMessage.error(res.data.msg);
278
313
  }
@@ -280,6 +315,7 @@ function saveOne() {
280
315
  }
281
316
  });
282
317
  }
318
+
283
319
  function delOne(id) {
284
320
  ElMessageBox.confirm("确认删除这条翻译记录吗?").then(() => {
285
321
  http
@@ -300,6 +336,7 @@ function delOne(id) {
300
336
  });
301
337
  });
302
338
  }
339
+
303
340
  function delMore() {
304
341
  ElMessageBox.confirm("确认删除选中的翻译记录吗?").then(async () => {
305
342
  let ids = i18nList.value
@@ -338,6 +375,7 @@ const formItems = reactive<VxeFormPropTypes.Items>([
338
375
  },
339
376
  },
340
377
  ]);
378
+
341
379
  const fromRules = reactive<VxeFormPropTypes.Rules>({
342
380
  key: [{ required: true, type: "string", message: "请输入翻译键值" }],
343
381
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yh-i18n",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "对于国际化的封装",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -8,6 +8,7 @@
8
8
  "pub:aliyun": "npm publish --registry https://packages.aliyun.com/60765e0161a945067837bb5f/npm/npm-registry/ --no-git-checks"
9
9
  },
10
10
  "dependencies": {
11
+ "exceljs": "4.4.0",
11
12
  "vue-i18n": "9.8.0"
12
13
  },
13
14
  "peerDependencies": {