yh-i18n 1.0.3 → 1.2.0
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 +201 -0
- package/index.d.ts +18 -0
- package/index.js +22 -12
- package/lang/baseEnUS.js +26 -0
- package/lang/baseTh.js +26 -0
- package/lang/baseTr.js +26 -0
- package/lang/baseVi.js +26 -0
- package/lang/baseZhCn.js +26 -0
- package/language.vue +21 -3
- package/list.vue +115 -24
- package/package.json +2 -2
package/excelTool.ts
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import 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
|
@@ -3,6 +3,12 @@ import { defineStore } from "pinia";
|
|
|
3
3
|
import { createI18n } from "vue-i18n";
|
|
4
4
|
import axios from "@/libs/api.request";
|
|
5
5
|
|
|
6
|
+
// base
|
|
7
|
+
import zhCNBase from "./lang/baseZhCn.js";
|
|
8
|
+
import enUSBase from "./lang/baseEnUS.js";
|
|
9
|
+
import thBase from "./lang/baseTh.js";
|
|
10
|
+
import viBase from "./lang/baseVi.js";
|
|
11
|
+
import trBase from "./lang/baseTr.js";
|
|
6
12
|
// vxe table
|
|
7
13
|
import zhCNVXETable from "vxe-table/lib/locale/lang/zh-CN";
|
|
8
14
|
import enUSVXETable from "vxe-table/lib/locale/lang/en-US";
|
|
@@ -24,8 +30,7 @@ const initlang = localStorage.local || localLang || "zh_CN";
|
|
|
24
30
|
|
|
25
31
|
export let i18n = null;
|
|
26
32
|
const isDev = import.meta.env.DEV;
|
|
27
|
-
|
|
28
|
-
window.translateReady = translateReady;
|
|
33
|
+
window.translateReady = !!localStorage.translateReady || false;
|
|
29
34
|
function addTranslate(key) {
|
|
30
35
|
if (key.indexOf("vxe") === -1) {
|
|
31
36
|
try {
|
|
@@ -43,9 +48,13 @@ function addTranslate(key) {
|
|
|
43
48
|
}
|
|
44
49
|
}
|
|
45
50
|
const keySet = new Set();
|
|
51
|
+
Object.keys(zhCNBase).forEach((key) => {
|
|
52
|
+
keySet.add(key);
|
|
53
|
+
});
|
|
54
|
+
|
|
46
55
|
export const ct = (key, args) => {
|
|
47
56
|
if (isDev) {
|
|
48
|
-
if (!keySet.has(key) && translateReady) {
|
|
57
|
+
if (!keySet.has(key) && window.translateReady) {
|
|
49
58
|
keySet.add(key);
|
|
50
59
|
addTranslate(key);
|
|
51
60
|
}
|
|
@@ -114,6 +123,7 @@ export const useI18nStore = defineStore("i18nStore", () => {
|
|
|
114
123
|
}
|
|
115
124
|
});
|
|
116
125
|
}
|
|
126
|
+
|
|
117
127
|
const title = computed(() => {
|
|
118
128
|
return langList[lang.value];
|
|
119
129
|
});
|
|
@@ -150,21 +160,21 @@ async function createMessage(list) {
|
|
|
150
160
|
list.forEach((item) => {
|
|
151
161
|
switch (item) {
|
|
152
162
|
case "zh_CN":
|
|
153
|
-
messages["zh_CN"] = Object.assign(
|
|
163
|
+
messages["zh_CN"] = Object.assign(zhCNBase, zhCNVXETable);
|
|
154
164
|
break;
|
|
155
165
|
case "en_US":
|
|
156
|
-
messages["en_US"] = Object.assign(
|
|
166
|
+
messages["en_US"] = Object.assign(enUSBase, enUSVXETable);
|
|
157
167
|
break;
|
|
158
168
|
case "th":
|
|
159
|
-
messages["th"] = Object.assign(
|
|
169
|
+
messages["th"] = Object.assign(thBase, thVXETable);
|
|
160
170
|
break;
|
|
161
171
|
|
|
162
172
|
case "vi":
|
|
163
|
-
messages["vi"] = Object.assign(
|
|
173
|
+
messages["vi"] = Object.assign(viBase, viVXETable);
|
|
164
174
|
break;
|
|
165
175
|
|
|
166
176
|
case "tr":
|
|
167
|
-
messages["tr"] = Object.assign(
|
|
177
|
+
messages["tr"] = Object.assign(trBase, trVXETable);
|
|
168
178
|
break;
|
|
169
179
|
|
|
170
180
|
default:
|
|
@@ -191,16 +201,16 @@ async function createMessage(list) {
|
|
|
191
201
|
}
|
|
192
202
|
Object.entries(itemObj).forEach(([key, val]) => {
|
|
193
203
|
if (list.includes(key)) {
|
|
194
|
-
messages[key][mKey]
|
|
204
|
+
if (!messages[key][mKey]) {
|
|
205
|
+
messages[key][mKey] = val;
|
|
206
|
+
}
|
|
195
207
|
}
|
|
196
208
|
});
|
|
197
209
|
} catch (err) {
|
|
198
210
|
console.error(err);
|
|
199
211
|
}
|
|
200
212
|
});
|
|
201
|
-
} catch (error) {
|
|
202
|
-
translateReady = false;
|
|
203
|
-
}
|
|
213
|
+
} catch (error) {}
|
|
204
214
|
return messages;
|
|
205
215
|
}
|
|
206
216
|
|
package/lang/baseEnUS.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
翻译键名: "Translate key names",
|
|
3
|
+
翻译管理: "Translation management",
|
|
4
|
+
键入以筛选键名: "Filter key names",
|
|
5
|
+
搜索: "Search",
|
|
6
|
+
新增: "New addition",
|
|
7
|
+
批量删除: "Batch deletion",
|
|
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",
|
|
21
|
+
中文简体: "Simplified Chinese",
|
|
22
|
+
English: "English",
|
|
23
|
+
ไทย: "Thailand.",
|
|
24
|
+
"Việt nam": "Vietnamese",
|
|
25
|
+
Türkçe: "Turkish",
|
|
26
|
+
};
|
package/lang/baseTh.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
翻译键名: "ชื่อคีย์การแปล",
|
|
3
|
+
翻译管理: "การจัดการการแปล",
|
|
4
|
+
键入以筛选键名: "พิมพ์เพื่อกรองชื่อคีย์",
|
|
5
|
+
搜索: "ค้นหา",
|
|
6
|
+
新增: "เพิ่มใหม่",
|
|
7
|
+
批量删除: "ลบแบทช์",
|
|
8
|
+
重置: "รีเซ็ต",
|
|
9
|
+
编辑: "บรรณาธิการ",
|
|
10
|
+
删除: "ลบ",
|
|
11
|
+
操作: "การดำเนินงาน",
|
|
12
|
+
导出当前页: "ส่งออกหน้าปัจจุบัน",
|
|
13
|
+
导入: "นำเข้า",
|
|
14
|
+
翻译键值: "แปลค่ากุญแจ",
|
|
15
|
+
新增翻译: "เพิ่มการแปล",
|
|
16
|
+
编辑翻译: "แก้ไขการแปล",
|
|
17
|
+
请输入翻译键值: "โปรดป้อนค่ากุญแจการแปล",
|
|
18
|
+
上一个: "ก่อนหน้า",
|
|
19
|
+
下一个: "ถัดไป",
|
|
20
|
+
取消: "การยกเลิก",
|
|
21
|
+
中文简体: "ภาษาจีนตัวย่อ",
|
|
22
|
+
English: "ภาษาอังกฤษ",
|
|
23
|
+
ไทย: "ไทย",
|
|
24
|
+
"Việt nam": "เวียดนาม",
|
|
25
|
+
Türkçe: "ตุรกี",
|
|
26
|
+
};
|
package/lang/baseTr.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
翻译键名: "Anahtar isimlerini çevir",
|
|
3
|
+
翻译管理: "Çeviri Yönetimi",
|
|
4
|
+
键入以筛选键名: "Anahtar isimlerini silmek için yazın",
|
|
5
|
+
搜索: "arama",
|
|
6
|
+
新增: "Yeni ekleme",
|
|
7
|
+
批量删除: "Toplu silme",
|
|
8
|
+
重置: "Sıfırla",
|
|
9
|
+
编辑: "edit",
|
|
10
|
+
删除: "Sil",
|
|
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",
|
|
21
|
+
中文简体: "Basitleştirilmiş Çince",
|
|
22
|
+
English: "İngilizce",
|
|
23
|
+
ไทย: "Tayland.",
|
|
24
|
+
"Việt nam": "Vietnamca",
|
|
25
|
+
Türkçe: "Türkçe",
|
|
26
|
+
};
|
package/lang/baseVi.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
翻译键名: "Tên khóa dịch",
|
|
3
|
+
翻译管理: "Quản lý phiên dịch",
|
|
4
|
+
键入以筛选键名: "Nhập để lọc các tên khóa",
|
|
5
|
+
搜索: "Tìm kiếm",
|
|
6
|
+
新增: "Mới",
|
|
7
|
+
批量删除: "Xóa hàng loạt",
|
|
8
|
+
重置: "Đặt lại",
|
|
9
|
+
编辑: "Chỉnh sửa",
|
|
10
|
+
删除: "Xoá",
|
|
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ỏ",
|
|
21
|
+
中文简体: "Trung Quốc",
|
|
22
|
+
English: "Tiếng Việt",
|
|
23
|
+
ไทย: "Thái Lan.",
|
|
24
|
+
"Việt nam": "Việt nam",
|
|
25
|
+
Türkçe: "Thổ Nhĩ Kỳ",
|
|
26
|
+
};
|
package/lang/baseZhCn.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
翻译键名: "翻译键名",
|
|
3
|
+
翻译管理: "翻译管理",
|
|
4
|
+
键入以筛选键名: "键入以筛选键名",
|
|
5
|
+
搜索: "搜索",
|
|
6
|
+
新增: "新增",
|
|
7
|
+
批量删除: "批量删除",
|
|
8
|
+
重置: "重置",
|
|
9
|
+
编辑: "编辑",
|
|
10
|
+
删除: "删除",
|
|
11
|
+
操作: "操作",
|
|
12
|
+
导出当前页: "导出当前页",
|
|
13
|
+
导入: "导入",
|
|
14
|
+
翻译键值: "翻译键值",
|
|
15
|
+
新增翻译: "新增翻译",
|
|
16
|
+
编辑翻译: "编辑翻译",
|
|
17
|
+
请输入翻译键值: "请输入翻译键值",
|
|
18
|
+
上一个: "上一个",
|
|
19
|
+
下一个: "下一个",
|
|
20
|
+
取消: "取消",
|
|
21
|
+
中文简体: "中文简体",
|
|
22
|
+
English: "英语",
|
|
23
|
+
ไทย: "泰语",
|
|
24
|
+
"Việt nam": "越南语",
|
|
25
|
+
Türkçe: "土耳其语",
|
|
26
|
+
};
|
package/language.vue
CHANGED
|
@@ -14,17 +14,35 @@
|
|
|
14
14
|
</el-dropdown-menu>
|
|
15
15
|
</template>
|
|
16
16
|
</el-dropdown>
|
|
17
|
-
|
|
17
|
+
|
|
18
|
+
<el-link v-if="isDev" type="warning" href="/#/translate">{{
|
|
19
|
+
ct("翻译管理")
|
|
20
|
+
}}</el-link>
|
|
21
|
+
|
|
22
|
+
<el-switch
|
|
23
|
+
active-text="收集"
|
|
24
|
+
inactive-text="不收集"
|
|
25
|
+
inline-prompt
|
|
26
|
+
v-if="isDev"
|
|
27
|
+
v-model="isCollect"
|
|
28
|
+
></el-switch>
|
|
18
29
|
</template>
|
|
19
30
|
|
|
20
31
|
<script setup>
|
|
21
|
-
import { useI18nStore } from "yh-i18n";
|
|
32
|
+
import { useI18nStore, ct } from "yh-i18n";
|
|
22
33
|
import { storeToRefs } from "pinia";
|
|
23
|
-
import { ref } from "vue";
|
|
34
|
+
import { ref, watch } from "vue";
|
|
24
35
|
|
|
25
36
|
const isDev = ref(import.meta.env.DEV);
|
|
26
37
|
|
|
27
38
|
const i18nStore = useI18nStore();
|
|
39
|
+
const isCollect = ref(window.translateReady);
|
|
40
|
+
watch(
|
|
41
|
+
() => isCollect.value,
|
|
42
|
+
(val) => {
|
|
43
|
+
window.translateReady = val;
|
|
44
|
+
}
|
|
45
|
+
);
|
|
28
46
|
|
|
29
47
|
const { localList, title } = storeToRefs(i18nStore);
|
|
30
48
|
|
package/list.vue
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
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
4
|
<div class="yh-i18n-list-conditions">
|
|
9
5
|
<el-form inline>
|
|
10
6
|
<el-form-item :label="ct('翻译键名')">
|
|
11
7
|
<el-input
|
|
12
8
|
v-model="listForm.key"
|
|
9
|
+
@keyup.enter.stop.prevent="getDataList(true)"
|
|
13
10
|
:placeholder="ct('键入以筛选键名')"
|
|
14
11
|
></el-input>
|
|
15
12
|
</el-form-item>
|
|
@@ -20,7 +17,35 @@
|
|
|
20
17
|
}}</el-button>
|
|
21
18
|
<el-button @click="resetList">{{ ct("重置") }}</el-button>
|
|
22
19
|
</div>
|
|
23
|
-
<
|
|
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>
|
|
36
|
+
<el-table
|
|
37
|
+
ref="i18nList"
|
|
38
|
+
stripe
|
|
39
|
+
:data="dataList"
|
|
40
|
+
row-key="adTranslateId"
|
|
41
|
+
@row-click="rowClickHandler"
|
|
42
|
+
>
|
|
43
|
+
<el-table-column
|
|
44
|
+
type="selection"
|
|
45
|
+
width="50"
|
|
46
|
+
align="center"
|
|
47
|
+
fixed="left"
|
|
48
|
+
></el-table-column>
|
|
24
49
|
<el-table-column
|
|
25
50
|
type="index"
|
|
26
51
|
label="#"
|
|
@@ -43,7 +68,12 @@
|
|
|
43
68
|
}}</el-button>
|
|
44
69
|
</template>
|
|
45
70
|
</el-table-column>
|
|
46
|
-
<el-table-column
|
|
71
|
+
<el-table-column
|
|
72
|
+
prop="key"
|
|
73
|
+
min-width="140"
|
|
74
|
+
fixed="left"
|
|
75
|
+
:label="ct('翻译键名')"
|
|
76
|
+
></el-table-column>
|
|
47
77
|
<el-table-column
|
|
48
78
|
v-for="column in listColumns"
|
|
49
79
|
:prop="column.field"
|
|
@@ -53,12 +83,12 @@
|
|
|
53
83
|
></el-table-column>
|
|
54
84
|
</el-table>
|
|
55
85
|
<el-pagination
|
|
56
|
-
small
|
|
57
86
|
background
|
|
58
|
-
:page-
|
|
87
|
+
:page-sizes="[100, 200, 1000, 100000]"
|
|
88
|
+
v-model:page-size="listForm.pageSize"
|
|
59
89
|
:total="listForm.total"
|
|
60
90
|
v-model:current-page="listForm.pageNum"
|
|
61
|
-
layout="prev,pager,next,total"
|
|
91
|
+
layout="sizes,prev,pager,next,total"
|
|
62
92
|
></el-pagination>
|
|
63
93
|
</div>
|
|
64
94
|
<el-dialog
|
|
@@ -105,12 +135,11 @@
|
|
|
105
135
|
</template>
|
|
106
136
|
<script setup lang="ts">
|
|
107
137
|
import { reactive, ref, onMounted, watch } from "vue";
|
|
108
|
-
import { ElMessage, ElMessageBox } from "element-plus";
|
|
138
|
+
import { ElLoadingService, ElMessage, ElMessageBox } from "element-plus";
|
|
109
139
|
import { useI18nStore, ct } from "yh-i18n";
|
|
110
140
|
import http from "@/libs/api.request";
|
|
111
141
|
import { VxeFormInstance, VxeFormPropTypes } from "vxe-table";
|
|
112
|
-
import {
|
|
113
|
-
|
|
142
|
+
import { exportExcel, importExcel } from "./excelTool";
|
|
114
143
|
const i18nStore = useI18nStore();
|
|
115
144
|
const vxeFormRef = ref<VxeFormInstance>();
|
|
116
145
|
|
|
@@ -118,16 +147,20 @@ const insertUrl = "/translate/insert";
|
|
|
118
147
|
const updateUrl = "/translate/edit";
|
|
119
148
|
const deleteUrl = "/translate/deleteTranslate";
|
|
120
149
|
|
|
150
|
+
const i18nList = ref();
|
|
121
151
|
const listForm = reactive({
|
|
122
152
|
key: "",
|
|
123
153
|
pageNum: 1,
|
|
124
|
-
pageSize:
|
|
154
|
+
pageSize: 200,
|
|
125
155
|
total: 0,
|
|
126
156
|
});
|
|
127
157
|
const listColumns = reactive<any>([]);
|
|
128
158
|
const dataList = ref<any>([]);
|
|
129
|
-
function getDataList() {
|
|
159
|
+
function getDataList(isReset = false) {
|
|
130
160
|
let { key, pageNum, pageSize } = listForm;
|
|
161
|
+
if (isReset) {
|
|
162
|
+
pageNum = 1;
|
|
163
|
+
}
|
|
131
164
|
http
|
|
132
165
|
.request({
|
|
133
166
|
url: "/translate/select",
|
|
@@ -162,6 +195,24 @@ function getDataList() {
|
|
|
162
195
|
listForm.total = total;
|
|
163
196
|
});
|
|
164
197
|
}
|
|
198
|
+
|
|
199
|
+
watch(
|
|
200
|
+
() => listForm.pageNum,
|
|
201
|
+
() => {
|
|
202
|
+
getDataList();
|
|
203
|
+
}
|
|
204
|
+
);
|
|
205
|
+
watch(
|
|
206
|
+
() => listForm.pageSize,
|
|
207
|
+
() => {
|
|
208
|
+
getDataList();
|
|
209
|
+
}
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
function rowClickHandler(row) {
|
|
213
|
+
i18nList.value?.toggleRowSelection(row);
|
|
214
|
+
}
|
|
215
|
+
|
|
165
216
|
function resetList() {
|
|
166
217
|
listForm.key = "";
|
|
167
218
|
listForm.pageNum = 1;
|
|
@@ -181,9 +232,11 @@ function cancelForm() {
|
|
|
181
232
|
formData.id = null;
|
|
182
233
|
formShow.value = false;
|
|
183
234
|
}
|
|
235
|
+
|
|
184
236
|
function addOne() {
|
|
185
237
|
formShow.value = true;
|
|
186
238
|
}
|
|
239
|
+
|
|
187
240
|
function prevOne() {
|
|
188
241
|
if (formDataIndex.value > 0) {
|
|
189
242
|
let index = formDataIndex.value - 1;
|
|
@@ -191,6 +244,7 @@ function prevOne() {
|
|
|
191
244
|
editOne(item, index);
|
|
192
245
|
}
|
|
193
246
|
}
|
|
247
|
+
|
|
194
248
|
function editOne(item, index) {
|
|
195
249
|
formDataIndex.value = index;
|
|
196
250
|
for (const key in item) {
|
|
@@ -207,6 +261,7 @@ function editOne(item, index) {
|
|
|
207
261
|
inputs = Array.from(document.querySelectorAll(".i18n-form-item input"));
|
|
208
262
|
}, 500);
|
|
209
263
|
}
|
|
264
|
+
|
|
210
265
|
function nextOne() {
|
|
211
266
|
if (formDataIndex.value < dataList.value.length - 1) {
|
|
212
267
|
let index = formDataIndex.value + 1;
|
|
@@ -214,15 +269,21 @@ function nextOne() {
|
|
|
214
269
|
editOne(item, index);
|
|
215
270
|
}
|
|
216
271
|
}
|
|
272
|
+
|
|
217
273
|
function saveOne() {
|
|
274
|
+
let isAdd = !!formData.adTranslateId;
|
|
218
275
|
let url = updateUrl;
|
|
219
276
|
vxeFormRef?.value?.validate().then((errMap) => {
|
|
220
277
|
if (!errMap) {
|
|
221
|
-
let data = {
|
|
222
|
-
id: formData.adTranslateId,
|
|
278
|
+
let data: any = {
|
|
223
279
|
key: formData.key,
|
|
224
280
|
content: {},
|
|
225
281
|
};
|
|
282
|
+
if (isAdd) {
|
|
283
|
+
url = insertUrl;
|
|
284
|
+
} else {
|
|
285
|
+
data.id = formData.adTranslateId;
|
|
286
|
+
}
|
|
226
287
|
for (const key in formData) {
|
|
227
288
|
if (key !== "key" && langList.includes(key)) {
|
|
228
289
|
const val = formData[key];
|
|
@@ -239,10 +300,14 @@ function saveOne() {
|
|
|
239
300
|
.then((res) => {
|
|
240
301
|
if (res?.data?.status === 200) {
|
|
241
302
|
ElMessage.success(res.data.msg);
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
303
|
+
if (!isAdd) {
|
|
304
|
+
dataList.value[formDataIndex.value] = {
|
|
305
|
+
...formData,
|
|
306
|
+
};
|
|
307
|
+
nextOne();
|
|
308
|
+
} else {
|
|
309
|
+
cancelForm();
|
|
310
|
+
}
|
|
246
311
|
} else {
|
|
247
312
|
ElMessage.error(res.data.msg);
|
|
248
313
|
}
|
|
@@ -250,6 +315,7 @@ function saveOne() {
|
|
|
250
315
|
}
|
|
251
316
|
});
|
|
252
317
|
}
|
|
318
|
+
|
|
253
319
|
function delOne(id) {
|
|
254
320
|
ElMessageBox.confirm("确认删除这条翻译记录吗?").then(() => {
|
|
255
321
|
http
|
|
@@ -263,7 +329,7 @@ function delOne(id) {
|
|
|
263
329
|
.then((res) => {
|
|
264
330
|
if (res?.data?.status === 200) {
|
|
265
331
|
ElMessage.success(res.data.msg);
|
|
266
|
-
|
|
332
|
+
getDataList();
|
|
267
333
|
} else {
|
|
268
334
|
ElMessage.error(res.data.msg);
|
|
269
335
|
}
|
|
@@ -271,6 +337,33 @@ function delOne(id) {
|
|
|
271
337
|
});
|
|
272
338
|
}
|
|
273
339
|
|
|
340
|
+
function delMore() {
|
|
341
|
+
ElMessageBox.confirm("确认删除选中的翻译记录吗?").then(async () => {
|
|
342
|
+
let ids = i18nList.value
|
|
343
|
+
?.getSelectionRows()
|
|
344
|
+
.map((row) => row.adTranslateId);
|
|
345
|
+
if (ids && ids.length) {
|
|
346
|
+
let len = ids.length;
|
|
347
|
+
let loading = ElLoadingService({
|
|
348
|
+
text: "正在删除选中的翻译……",
|
|
349
|
+
});
|
|
350
|
+
for (let i = 0; i < ids.length; i++) {
|
|
351
|
+
const id = ids[i];
|
|
352
|
+
loading.setText(`正在删除... ${i + 1}/${len}`);
|
|
353
|
+
await http.request({
|
|
354
|
+
url: deleteUrl,
|
|
355
|
+
method: "POST",
|
|
356
|
+
data: {
|
|
357
|
+
id,
|
|
358
|
+
},
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
loading.close();
|
|
362
|
+
getDataList();
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
|
|
274
367
|
const formItems = reactive<VxeFormPropTypes.Items>([
|
|
275
368
|
{
|
|
276
369
|
field: "key",
|
|
@@ -282,6 +375,7 @@ const formItems = reactive<VxeFormPropTypes.Items>([
|
|
|
282
375
|
},
|
|
283
376
|
},
|
|
284
377
|
]);
|
|
378
|
+
|
|
285
379
|
const fromRules = reactive<VxeFormPropTypes.Rules>({
|
|
286
380
|
key: [{ required: true, type: "string", message: "请输入翻译键值" }],
|
|
287
381
|
});
|
|
@@ -307,9 +401,6 @@ watch(
|
|
|
307
401
|
props: { class: "i18n-form-item", id: `i18nFormItem${index + 2}` },
|
|
308
402
|
},
|
|
309
403
|
});
|
|
310
|
-
fromRules[item.value] = [
|
|
311
|
-
{ required: true, type: "string", message: `请输入${item.label}` },
|
|
312
|
-
];
|
|
313
404
|
});
|
|
314
405
|
}
|
|
315
406
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yh-i18n",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "对于国际化的封装",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -8,11 +8,11 @@
|
|
|
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": {
|
|
14
15
|
"vue": "3.2.47",
|
|
15
|
-
"pinia": "2.0.35",
|
|
16
16
|
"vxe-table": "4.3.10",
|
|
17
17
|
"element-plus": "2.4.4"
|
|
18
18
|
},
|