yh-i18n 2.2.23 → 2.3.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 CHANGED
@@ -5,33 +5,6 @@ import http from '@/libs/api.request';
5
5
  import {useI18nStore} from './index';
6
6
 
7
7
  const verificationCode = 'lkyhtranslateexcel';
8
-
9
- /**
10
- * 解析翻译内容,将 JSON 字符串解析并合并到 item 对象中
11
- * @param item 翻译项对象
12
- * @param localKeys 本地语言键列表
13
- * @returns 处理后的翻译项对象
14
- */
15
- export function parseTranslateContent(item: any, localKeys: string[]): any {
16
- try {
17
- let content = JSON.parse(item.content);
18
- let keys = Object.keys(content);
19
-
20
- keys.forEach((key) => {
21
- let val = content[key];
22
- item[key] = val;
23
- });
24
-
25
- localKeys.forEach((k) => {
26
- if (!keys.includes(k)) {
27
- item[k] = '';
28
- }
29
- });
30
- } catch (error) {
31
- console.error('解析翻译内容失败:', error);
32
- }
33
- return item;
34
- }
35
8
  export async function exportExcel(total) {
36
9
  const loading = ElLoading.service({
37
10
  lock: true,
@@ -51,7 +24,23 @@ export async function exportExcel(total) {
51
24
  .then((res) => {
52
25
  let localKeys = i18nStore.localList.map((item) => item.value);
53
26
  let {records} = res.data.data;
54
- records = records.map((item) => parseTranslateContent(item, localKeys));
27
+ records = records.map((item) => {
28
+ try {
29
+ let content = JSON.parse(item.content);
30
+ let keys = Object.keys(content);
31
+
32
+ keys.forEach((key) => {
33
+ let val = content[key];
34
+ item[key] = val;
35
+ });
36
+ localKeys.forEach((k) => {
37
+ if (!keys.includes(k)) {
38
+ item[k] = '';
39
+ }
40
+ });
41
+ } catch (error) {}
42
+ return item;
43
+ });
55
44
  return records;
56
45
  });
57
46
  loading.setText('正在序列化表格数据……');
@@ -88,8 +77,8 @@ export async function exportExcel(total) {
88
77
  sheet.addRow(title);
89
78
  sheet.addRows(
90
79
  records.map((item) => {
91
- let {id, name} = item;
92
- let row = [id, name];
80
+ let {adTranslateId, key} = item;
81
+ let row = [adTranslateId, key];
93
82
  Config.i18nList.forEach((valKey) => {
94
83
  row.push(item[valKey]);
95
84
  });
@@ -212,7 +201,6 @@ export async function importExcel(e, getDataList) {
212
201
  message: '您选择的文件不是系统导出的文件',
213
202
  type: 'warning',
214
203
  });
215
- e.target.value = '';
216
204
  return false;
217
205
  }
218
206
  const loading = ElLoading.service({
@@ -227,14 +215,14 @@ export async function importExcel(e, getDataList) {
227
215
  let dataList: any[] = [];
228
216
  sheet.getRows(2, len)?.forEach((row) => {
229
217
  let id = row.getCell(1).value;
230
- let name = row.getCell(2).value;
218
+ let key = row.getCell(2).value;
231
219
  let content: any = {};
232
220
  Config.i18nList.forEach((item, index) => {
233
221
  content[item] = row.getCell(index + 3).value;
234
222
  });
235
223
  dataList.push({
236
224
  id,
237
- name,
225
+ key,
238
226
  content: JSON.stringify(content),
239
227
  });
240
228
  });
@@ -262,8 +250,6 @@ export async function importExcel(e, getDataList) {
262
250
  getDataList();
263
251
  } catch (error) {
264
252
  ElMessage.error('导入保存翻译数据遇到错误:', error.message);
265
- } finally {
266
- e.target.value = '';
267
253
  }
268
254
  }
269
255
  }
package/index.d.ts CHANGED
@@ -21,7 +21,7 @@ declare global {
21
21
  export const i18n: I18n;
22
22
 
23
23
  /** 自定义的翻译函数,这个函数包装了 t 函数,在翻译的前提下,可以帮忙手机键 */
24
- export const ct: (key: string, args?: any[]) => void;
24
+ export const ct: (key: string, args: any[]) => void;
25
25
 
26
26
  /** 国际化相关 Pinia Store 实例 */
27
27
  export const useI18nStore: StoreDefinition;
package/index.js CHANGED
@@ -10,12 +10,14 @@ import enUSBase from "./lang/baseEnUS.js";
10
10
  import thBase from "./lang/baseTh.js";
11
11
  import viBase from "./lang/baseVi.js";
12
12
  import trBase from "./lang/baseTr.js";
13
+ import faBase from "./lang/baseFa.js"
13
14
  // vxe table
14
15
  import zhCNVXETable from "./lang/zh.js";
15
16
  import enUSVXETable from "./lang/en.js";
16
17
  import thVXETable from "./lang/th.js";
17
18
  import viVXETable from "./lang/vi.js";
18
19
  import trVXETable from "./lang/tr.js";
20
+ import faVXETable from "./lang/fa.js"
19
21
 
20
22
  // element-plus
21
23
  import el_zh_CN from "element-plus/dist/locale/zh-cn.mjs";
@@ -23,6 +25,7 @@ import el_en_US from "element-plus/dist/locale/en.mjs";
23
25
  import el_th from "element-plus/dist/locale/th.mjs";
24
26
  import el_vi from "element-plus/dist/locale/vi.mjs";
25
27
  import el_tr from "element-plus/dist/locale/tr.mjs";
28
+ import el_fa from "element-plus/dist/locale/fa.mjs";
26
29
 
27
30
  // 自动根据浏览器系统语言设置语言
28
31
  let navLang = navigator.language.replace("-", "_");
@@ -47,15 +50,15 @@ Object.keys(zhCNBase).forEach((key) => {
47
50
 
48
51
  const unHandle = [];
49
52
 
50
- function addTranslate (name) {
51
- if (name && name.indexOf("vxe") === -1) {
53
+ function addTranslate (key) {
54
+ if (key && key.indexOf("vxe") === -1) {
52
55
  try {
53
56
  axios.request({
54
57
  url: "/translate/insert",
55
58
  method: "POST",
56
59
  data: {
57
- name,
58
- content: `{"zh_CN":"${name}"}`,
60
+ key,
61
+ content: `{"zh_CN":"${key}"}`,
59
62
  },
60
63
  });
61
64
  } catch (error) {
@@ -84,7 +87,7 @@ function recursionAddTranslate () {
84
87
  }
85
88
  }
86
89
 
87
- export const ct = (key, args = []) => {
90
+ export const ct = (key, args) => {
88
91
  if (key && window.translateReady && window.translateCollect) {
89
92
  // 将 键的处理全部放入队列中,避免挤兑正常逻辑的运算资源
90
93
  if (!keySet.has(key) && !unHandle.includes(key)) {
@@ -119,6 +122,7 @@ export const useI18nStore = defineStore("i18nStore", () => {
119
122
  th: "ไทย",
120
123
  vi: "Việt nam",
121
124
  tr: "Türkçe",
125
+ fa_IR: "فارسی",
122
126
  });
123
127
 
124
128
  const localList = reactive([]);
@@ -155,6 +159,12 @@ export const useI18nStore = defineStore("i18nStore", () => {
155
159
  value: "tr",
156
160
  });
157
161
  break;
162
+ case "fa_IR":
163
+ localList.push({
164
+ label: "فارسی",
165
+ value: "fa_IR",
166
+ });
167
+ break;
158
168
  }
159
169
  });
160
170
  }
@@ -175,6 +185,8 @@ export const useI18nStore = defineStore("i18nStore", () => {
175
185
  return el_vi;
176
186
  case "tr":
177
187
  return el_tr;
188
+ case "fa_IR":
189
+ return el_fa;
178
190
  }
179
191
  });
180
192
 
@@ -197,6 +209,7 @@ async function getRemoteMessage (list) {
197
209
  th: {},
198
210
  vi: {},
199
211
  tr: {},
212
+ fa_IR: {},
200
213
  };
201
214
  let {
202
215
  data: { data },
@@ -257,7 +270,9 @@ function createLocalMessage (list) {
257
270
  case "tr":
258
271
  messages["tr"] = Object.assign(trBase, trVXETable);
259
272
  break;
260
-
273
+ case "fa_IR":
274
+ messages["fa_IR"] = Object.assign(faBase, faVXETable);
275
+ break;
261
276
  default:
262
277
  break;
263
278
  }
package/lang/baseEnUS.js CHANGED
@@ -23,4 +23,5 @@ export default {
23
23
  ไทย: "Thailand.",
24
24
  "Việt nam": "Vietnamese",
25
25
  Türkçe: "Turkish",
26
+ "فارسی": "Persian"
26
27
  };
package/lang/baseFa.js ADDED
@@ -0,0 +1,27 @@
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
+ "فارسی": "فارسی",
27
+ };
package/lang/baseTh.js CHANGED
@@ -23,4 +23,5 @@ export default {
23
23
  ไทย: "ไทย",
24
24
  "Việt nam": "เวียดนาม",
25
25
  Türkçe: "ตุรกี",
26
+ "فارسی": "ภาษาเปอร์เซีย"
26
27
  };
package/lang/baseTr.js CHANGED
@@ -23,4 +23,5 @@ export default {
23
23
  ไทย: "Tayland.",
24
24
  "Việt nam": "Vietnamca",
25
25
  Türkçe: "Türkçe",
26
+ "فارسی": "Farsça"
26
27
  };
package/lang/baseVi.js CHANGED
@@ -23,4 +23,5 @@ export default {
23
23
  ไทย: "Thái Lan.",
24
24
  "Việt nam": "Việt nam",
25
25
  Türkçe: "Thổ Nhĩ Kỳ",
26
+ "فارسی": "Tiếng Ba Tư"
26
27
  };
package/lang/baseZhCn.js CHANGED
@@ -23,4 +23,5 @@ export default {
23
23
  ไทย: "泰语",
24
24
  "Việt nam": "越南语",
25
25
  Türkçe: "土耳其语",
26
+ "فارسی": "波斯语",
26
27
  };
package/lang/fa.js ADDED
@@ -0,0 +1,310 @@
1
+ export default {
2
+ vxe: {
3
+ loading: {
4
+ text: "در حال بارگذاری...",
5
+ },
6
+ error: {
7
+ groupFixed: "اگر از سرستون گروهی استفاده می‌شود، ستون ثابت باید به صورت گروهی تنظیم شود",
8
+ groupMouseRange: 'سرستون گروهی نمی‌تواند با "{0}" همزمان استفاده شود، که ممکن است باعث خطا شود',
9
+ groupTag: 'سرستون گروهی باید از "{0}" به جای "{1}" استفاده کند، که ممکن است باعث خطا شود',
10
+ scrollErrProp: 'پس از فعال کردن اسکرول مجازی، پارامتر "{0}" پشتیبانی نمی‌شود',
11
+ errConflicts: 'پارامتر "{0}" با "{1}" تداخل دارد',
12
+ unableInsert: "نمی‌توان در موقعیت مشخصی درج کرد، لطفاً بررسی کنید که آیا پارامترها صحیح هستند",
13
+ useErr: 'هنگام نصب ماژول "{0}" خطایی رخ داد، ممکن است ترتیب نادرست باشد، ماژول‌های وابسته باید قبل از Table نصب شوند',
14
+ barUnableLink: "نوار ابزار نمی‌تواند به جدول متصل شود",
15
+ expandContent: 'اسلات ردیف باز شده باید "content" باشد، لطفاً بررسی کنید که آیا صحیح است',
16
+ reqModule: 'ماژول "{0}" وجود ندارد',
17
+ reqProp: 'پارامتر ضروری "{0}" وجود ندارد، که ممکن است باعث خطا شود',
18
+ emptyProp: 'پارامتر "{0}" نمی‌تواند خالی باشد',
19
+ errProp: 'پارامتر "{0}" پشتیبانی نمی‌شود، ممکن است "{1}" باشد',
20
+ colRepet: 'column.{0}="{1}" تکرار شده است، که ممکن است باعث عدم کارکرد برخی توابع شود',
21
+ notFunc: 'متد "{0}" وجود ندارد',
22
+ notSlot: 'اسلات "{0}" وجود ندارد',
23
+ noTree: 'ساختار درختی "{0}" را پشتیبانی نمی‌کند',
24
+ notProp: 'پارامتر "{0}" پشتیبانی نمی‌شود',
25
+ coverProp: 'پارامتر "{1}" از "{0}" بازنویسی شده است، که ممکن است باعث خطا شود',
26
+ delFunc: 'متد "{0}" منسوخ شده است، لطفاً از "{1}" استفاده کنید',
27
+ delProp: 'پارامتر "{0}" منسوخ شده است، لطفاً از "{1}" استفاده کنید',
28
+ delEvent: 'رویداد "{0}" منسوخ شده است، لطفاً از "{1}" استفاده کنید',
29
+ removeProp: 'پارامتر "{0}" منسوخ شده و توصیه نمی‌شود,这可能会导致出现错误',
30
+ errFormat: 'محتوای قالب‌بندی سراسری باید با "VXETable.formats" تعریف شود، روش اتصال "formatter={0}" دیگر توصیه نمی‌شود',
31
+ notType: 'نوع فایل "{0}" پشتیبانی نمی‌شود',
32
+ notExp: "این مرورگر از قابلیت وارد کردن/صادر کردن پشتیبانی نمی‌کند",
33
+ impFields: "وارد کردن ناموفق بود، لطفاً بررسی کنید که نام فیلدها و فرمت داده صحیح هستند",
34
+ treeNotImp: "جدول درختی از وارد کردن پشتیبانی نمی‌کند",
35
+ },
36
+ renderer: {
37
+ search: "جستجو",
38
+ cases: {
39
+ equal: "مساوی",
40
+ unequal: "نامساوی",
41
+ gt: "بزرگتر از",
42
+ ge: "بزرگتر یا مساوی",
43
+ lt: "کوچکتر از",
44
+ le: "کوچکتر یا مساوی",
45
+ begin: "شروع با",
46
+ notbegin: "شروع نشود با",
47
+ endin: "پایان با",
48
+ notendin: "پایان نشود با",
49
+ include: "شامل",
50
+ exclude: "شامل نشود",
51
+ between: "بین",
52
+ custom: "فیلتر سفارشی",
53
+ insensitive: "بدون حساسیت به حروف",
54
+ isSensitive: "حساس به حروف",
55
+ },
56
+ combination: {
57
+ menus: {
58
+ clearSort: "پاک کردن مرتب‌سازی",
59
+ sortAsc: "صعودی",
60
+ sortDesc: "نزولی",
61
+ fixedColumn: "ستون ثابت",
62
+ fixedGroup: "گروه ثابت",
63
+ cancelFixed: "لغو ثابت",
64
+ fixedLeft: "ثابت چپ",
65
+ fixedRight: "ثابت راست",
66
+ clearFilter: "پاک کردن فیلتر",
67
+ textOption: "فیلتر متنی",
68
+ numberOption: "فیلتر عددی",
69
+ },
70
+ popup: {
71
+ title: "روش فیلتر سفارشی",
72
+ currColumnTitle: "ستون فعلی:",
73
+ and: "و",
74
+ or: "یا",
75
+ describeHtml: "از ? برای نمایندگی یک کاراکتر استفاده کنید<br/>از * برای نمایندگی چندین کاراکتر دلخواه استفاده کنید",
76
+ },
77
+ empty: "(خالی)",
78
+ notData: "موردی یافت نشد",
79
+ },
80
+ },
81
+ pro: {
82
+ area: {
83
+ mergeErr: "نمی‌توان این عملیات را روی سلول ادغام شده انجام داد",
84
+ multiErr: "نمی‌توان این عملیات را روی ناحیه انتخاب چندگانه انجام داد",
85
+ extendErr: "اگر ناحیه گسترش یافته شامل سلول‌های ادغام شده باشد، تمام سلول‌های ادغام شده باید اندازه یکسانی داشته باشند",
86
+ pasteMultiErr: "نمی‌توان چسباند، برای انجام این عملیات ناحیه کپی شده و ناحیه چسبانده شده باید اندازه یکسانی داشته باشند",
87
+ },
88
+ fnr: {
89
+ title: "جستجو و جایگزینی",
90
+ findLabel: "جستجو",
91
+ replaceLabel: "جایگزینی",
92
+ findTitle: "جستجوی محتوا:",
93
+ replaceTitle: "جایگزینی با:",
94
+ tabs: {
95
+ find: "جستجو",
96
+ replace: "جایگزینی",
97
+ },
98
+ filter: {
99
+ re: "عبارت منظم",
100
+ whole: "تطبیق کل کلمه",
101
+ sensitive: "حساس به حروف",
102
+ },
103
+ btns: {
104
+ findNext: "جستجوی بعدی",
105
+ findAll: "جستجوی همه",
106
+ replace: "جایگزینی",
107
+ replaceAll: "جایگزینی همه",
108
+ cancel: "لغو",
109
+ },
110
+ header: {
111
+ seq: "#",
112
+ cell: "سلول",
113
+ value: "مقدار",
114
+ },
115
+ empty: "(تهی)",
116
+ reError: "عبارت منظم نامعتبر",
117
+ recordCount: "{0} سلول یافت شد",
118
+ notCell: "سلول منطبقی یافت نشد",
119
+ replaceSuccess: "با موفقیت {0} سلول جایگزین شد",
120
+ },
121
+ },
122
+ table: {
123
+ emptyText: "داده‌ای موجود نیست",
124
+ allTitle: "انتخاب همه/لغو",
125
+ seqTitle: "#",
126
+ confirmFilter: "فیلتر",
127
+ resetFilter: "بازنشانی",
128
+ allFilter: "همه",
129
+ sortAsc: "صعودی:کمترین به بیشترین",
130
+ sortDesc: "نزولی:بیشترین به کمترین",
131
+ filter: "فعال کردن فیلتر برای ستون انتخاب شده",
132
+ impSuccess: "با موفقیت {0} رکورد وارد شد",
133
+ expLoading: "در حال صدور...",
134
+ expSuccess: "صدور با موفقیت انجام شد",
135
+ expFilename: "صدور_{0}",
136
+ expOriginFilename: "صدور_منبع_{0}",
137
+ customTitle: "تنظیمات ستون",
138
+ customAll: "همه",
139
+ customConfirm: "تایید",
140
+ customRestore: "بازیابی",
141
+ },
142
+ grid: {
143
+ selectOneRecord: "لطفاً حداقل یک رکورد انتخاب کنید!",
144
+ deleteSelectRecord: "آیا مطمئن هستید که می‌خواهید رکوردهای انتخاب شده را حذف کنید؟",
145
+ removeSelectRecord: "آیا مطمئن هستید که می‌خواهید رکوردهای انتخاب شده را جابجا کنید؟",
146
+ dataUnchanged: "داده‌ها تغییر نکرده‌اند!",
147
+ delSuccess: "رکوردهای انتخاب شده با موفقیت حذف شدند!",
148
+ saveSuccess: "ذخیره با موفقیت انجام شد!",
149
+ operError: "خطایی رخ داد، عملیات ناموفق بود!",
150
+ },
151
+ select: {
152
+ search: "جستجو",
153
+ loadingText: "در حال بارگذاری",
154
+ emptyText: "داده‌ای موجود نیست",
155
+ },
156
+ pager: {
157
+ goto: "برو به",
158
+ pagesize: "{0} مورد/صفحه",
159
+ total: "مجموع {0} رکورد",
160
+ pageClassifier: "صفحه",
161
+ prevPage: "صفحه قبل",
162
+ nextPage: "صفحه بعد",
163
+ prevJump: "پرش به بالا",
164
+ nextJump: "پرش به پایین",
165
+ },
166
+ alert: {
167
+ title: "پیام هشدار",
168
+ },
169
+ button: {
170
+ confirm: "تایید",
171
+ cancel: "لغو",
172
+ },
173
+ import: {
174
+ modes: {
175
+ covering: "بازنویسی",
176
+ insert: "درج",
177
+ },
178
+ impTitle: "وارد کردن داده‌ها",
179
+ impFile: "نام فایل",
180
+ impSelect: "انتخاب فایل",
181
+ impType: "نوع فایل",
182
+ impOpts: "تنظیمات پارامتر",
183
+ impConfirm: "وارد کردن",
184
+ impCancel: "لغو",
185
+ },
186
+ export: {
187
+ types: {
188
+ csv: "CSV (جدا شده با کاما)(*.csv)",
189
+ html: "صفحه وب(*.html)",
190
+ xml: "داده XML(*.xml)",
191
+ txt: "فایل متنی (جدا شده با تب)(*.txt)",
192
+ xls: "کتاب کار Excel 97-2003(*.xls)",
193
+ xlsx: "کتاب کار Excel(*.xlsx)",
194
+ pdf: "PDF (*.pdf)",
195
+ },
196
+ modes: {
197
+ current: "داده‌های فعلی (داده‌های صفحه فعلی)",
198
+ selected: "داده‌های انتخاب شده (داده‌های انتخاب شده در صفحه فعلی)",
199
+ all: "تمام داده‌ها (شامل داده‌های تمام صفحات)",
200
+ },
201
+ printTitle: "چاپ داده‌ها",
202
+ expTitle: "صدور داده‌ها",
203
+ expName: "نام فایل",
204
+ expNamePlaceholder: "لطفاً نام فایل را وارد کنید",
205
+ expSheetName: "عنوان",
206
+ expSheetNamePlaceholder: "لطفاً عنوان را وارد کنید",
207
+ expType: "نوع ذخیره",
208
+ expMode: "انتخاب داده‌ها",
209
+ expCurrentColumn: "تمام فیلدها",
210
+ expColumn: "انتخاب فیلدها",
211
+ expOpts: "تنظیمات پارامتر",
212
+ expOptHeader: "سرستون",
213
+ expHeaderTitle: "آیا سرستون نیاز است",
214
+ expOptFooter: "پاصفحه",
215
+ expFooterTitle: "آیا پاصفحه نیاز است",
216
+ expOptColgroup: "سرستون گروهی",
217
+ expColgroupTitle: "در صورت وجود، از سرستون با ساختار گروهی پشتیبانی می‌کند",
218
+ expOptMerge: "ادغام",
219
+ expMergeTitle: "در صورت وجود، از سلول‌های با ساختار ادغام شده پشتیبانی می‌کند",
220
+ expOptAllExpand: "باز کردن سطوح",
221
+ expAllExpandTitle: "در صورت وجود، از باز کردن تمام داده‌های با ساختار سلسله مراتبی پشتیبانی می‌کند",
222
+ expOptUseStyle: "سبک",
223
+ expUseStyleTitle: "در صورت وجود، از سلول‌های دارای سبک پشتیبانی می‌کند",
224
+ expOptOriginal: "داده‌های منبع",
225
+ expOriginalTitle: "اگر داده‌های منبع باشند، از وارد کردن به جدول پشتیبانی می‌کنند",
226
+ expPrint: "چاپ",
227
+ expConfirm: "صدور",
228
+ expCancel: "لغو",
229
+ },
230
+ modal: {
231
+ zoomIn: "بیشینه‌سازی",
232
+ zoomOut: "بازیابی",
233
+ close: "بستن",
234
+ },
235
+ form: {
236
+ folding: "جمع کردن",
237
+ unfolding: "باز کردن",
238
+ },
239
+ toolbar: {
240
+ import: "وارد کردن",
241
+ export: "صدور",
242
+ print: "چاپ",
243
+ refresh: "بازنشانی",
244
+ zoomIn: "تمام صفحه",
245
+ zoomOut: "بازیابی",
246
+ custom: "تنظیمات ستون",
247
+ customAll: "همه",
248
+ customConfirm: "تایید",
249
+ customRestore: "بازیابی",
250
+ },
251
+ input: {
252
+ date: {
253
+ m1: "۰۱ ژانویه",
254
+ m2: "۰۲ فوریه",
255
+ m3: "۰۳ مارس",
256
+ m4: "۰۴ آوریل",
257
+ m5: "۰۵ مه",
258
+ m6: "۰۶ ژوئن",
259
+ m7: "۰۷ ژوئیه",
260
+ m8: "۰۸ اوت",
261
+ m9: "۰۹ سپتامبر",
262
+ m10: "۱۰ اکتبر",
263
+ m11: "۱۱ نوامبر",
264
+ m12: "۱۲ دسامبر",
265
+ quarterLabel: "{0} سال",
266
+ monthLabel: "{0} سال",
267
+ dayLabel: "{0} سال {1}",
268
+ labelFormat: {
269
+ date: "yyyy-MM-dd",
270
+ time: "HH:mm:ss",
271
+ datetime: "yyyy-MM-dd HH:mm:ss",
272
+ week: "هفته WW از سال yyyy",
273
+ month: "yyyy-MM",
274
+ quarter: "فصل q از سال yyyy",
275
+ year: "yyyy",
276
+ },
277
+ weeks: {
278
+ w: "هفته",
279
+ w0: "یکشنبه",
280
+ w1: "دوشنبه",
281
+ w2: "سه‌شنبه",
282
+ w3: "چهارشنبه",
283
+ w4: "پنجشنبه",
284
+ w5: "جمعه",
285
+ w6: "شنبه",
286
+ },
287
+ months: {
288
+ m0: "ژانویه",
289
+ m1: "فوریه",
290
+ m2: "مارس",
291
+ m3: "آوریل",
292
+ m4: "مه",
293
+ m5: "ژوئن",
294
+ m6: "ژوئیه",
295
+ m7: "اوت",
296
+ m8: "سپتامبر",
297
+ m9: "اکتبر",
298
+ m10: "نوامبر",
299
+ m11: "دسامبر",
300
+ },
301
+ quarters: {
302
+ q1: "فصل اول",
303
+ q2: "فصل دوم",
304
+ q3: "فصل سوم",
305
+ q4: "فصل چهارم",
306
+ },
307
+ },
308
+ },
309
+ },
310
+ };
package/list.vue CHANGED
@@ -5,7 +5,7 @@
5
5
  <el-form inline>
6
6
  <el-form-item :label="ct('翻译键名')">
7
7
  <el-input
8
- v-model="listForm.name"
8
+ v-model="listForm.key"
9
9
  @keyup.enter.stop.prevent="getDataList(true)"
10
10
  :placeholder="ct('键入以筛选键名')"></el-input>
11
11
  </el-form-item>
@@ -48,7 +48,7 @@
48
48
  ref="i18nList"
49
49
  stripe
50
50
  :data="dataList"
51
- row-key="id"
51
+ row-key="adTranslateId"
52
52
  @row-click="rowClickHandler">
53
53
  <el-table-column
54
54
  type="selection"
@@ -76,13 +76,13 @@
76
76
  <el-button
77
77
  link
78
78
  type="danger"
79
- @click="delOne(row.id)">
79
+ @click="delOne(row.adTranslateId)">
80
80
  {{ ct('删除') }}
81
81
  </el-button>
82
82
  </template>
83
83
  </el-table-column>
84
84
  <el-table-column
85
- prop="name"
85
+ prop="key"
86
86
  min-width="140"
87
87
  fixed="left"
88
88
  :label="ct('翻译键名')"></el-table-column>
@@ -105,9 +105,8 @@
105
105
  class="form-drawer"
106
106
  v-model="formShow"
107
107
  @close="cancelForm"
108
- :close-on-click-modal="false"
109
108
  draggable
110
- :title="formData.id ? ct('编辑翻译') : ct('新增翻译')">
109
+ :title="formData.adTranslateId ? ct('编辑翻译') : ct('新增翻译')">
111
110
  <vxe-form
112
111
  title-align="right"
113
112
  title-width="100px"
@@ -115,14 +114,14 @@
115
114
  title-colon
116
115
  :data="formData"
117
116
  :items="formItems"
118
- :rules="formRules"></vxe-form>
117
+ :rules="fromRules"></vxe-form>
119
118
  <template #footer>
120
119
  <div class="yh-i18n-form-actions">
121
120
  <el-button
122
121
  @click="prevOne"
123
122
  text
124
123
  :disabled="!isNaN(formDataIndex) && formDataIndex <= 0">
125
- {{ ct('上一个') }} (ctrl/alt + ←)
124
+ {{ ct('上一个') }}(←)
126
125
  </el-button>
127
126
  <el-button
128
127
  type="primary"
@@ -133,44 +132,25 @@
133
132
  <el-button
134
133
  type="primary"
135
134
  @click="saveOne">
136
- {{ ct('保存') }}(ctrl + S)
135
+ {{ ct('保存') }}
137
136
  </el-button>
138
137
  <el-button
139
138
  @click="nextOne"
140
139
  text
141
- :disabled="!isNaN(formDataIndex) && formDataIndex >= dataList.length - 1">
142
- {{ ct('下一个') }}(ctrl/alt + →)
140
+ :disabled="!isNaN(formDataIndex) && formDataIndex >= dataList.leng - 1">
141
+ {{ ct('下一个') }}(→)
143
142
  </el-button>
144
143
  </div>
145
144
  </template>
146
145
  </el-dialog>
147
146
  </template>
148
147
  <script setup lang="ts">
149
- import {reactive, ref, onMounted, onUnmounted, watch} from 'vue';
148
+ import {reactive, ref, onMounted, watch} from 'vue';
150
149
  import {ElLoadingService, ElMessage, ElMessageBox} from 'element-plus';
151
150
  import {useI18nStore, ct} from 'yh-i18n';
152
151
  import http from '@/libs/api.request';
153
152
  import {VxeFormInstance, VxeFormPropTypes} from 'vxe-table';
154
- import {exportExcel, importExcel, parseTranslateContent} from './excelTool';
155
-
156
- interface TranslateItem {
157
- id?: string;
158
- name: string;
159
- content: string;
160
- [key: string]: any;
161
- }
162
-
163
- interface ListColumn {
164
- field: string;
165
- title: string;
166
- minWidth: string;
167
- }
168
-
169
- interface SaveData {
170
- name: string;
171
- content: Record<string, string> | string;
172
- id?: string;
173
- }
153
+ import {exportExcel, importExcel} from './excelTool';
174
154
  const i18nStore = useI18nStore();
175
155
  const vxeFormRef = ref<VxeFormInstance>();
176
156
 
@@ -180,15 +160,15 @@ const deleteUrl = '/translate/deleteTranslate';
180
160
 
181
161
  const i18nList = ref();
182
162
  const listForm = reactive({
183
- name: '',
163
+ key: '',
184
164
  pageNum: 1,
185
165
  pageSize: 10,
186
166
  total: 0,
187
167
  });
188
- const listColumns = reactive<ListColumn[]>([]);
189
- const dataList = ref<TranslateItem[]>([]);
168
+ const listColumns = reactive<any>([]);
169
+ const dataList = ref<any>([]);
190
170
  function getDataList(isReset = false) {
191
- let {name, pageNum, pageSize} = listForm;
171
+ let {key, pageNum, pageSize} = listForm;
192
172
  if (isReset) {
193
173
  pageNum = 1;
194
174
  }
@@ -200,7 +180,7 @@ function getDataList(isReset = false) {
200
180
  url: '/translate/select',
201
181
  method: 'post',
202
182
  data: {
203
- name,
183
+ key,
204
184
  pageNum,
205
185
  pageSize,
206
186
  },
@@ -208,14 +188,26 @@ function getDataList(isReset = false) {
208
188
  .then((res) => {
209
189
  let localKeys = i18nStore.localList.map((item) => item.value);
210
190
  let {records, total} = res.data.data;
211
- records = records.map((item) => parseTranslateContent(item, localKeys));
191
+ records = records.map((item) => {
192
+ try {
193
+ let content = JSON.parse(item.content);
194
+ let keys = Object.keys(content);
195
+
196
+ keys.forEach((key) => {
197
+ let val = content[key];
198
+ item[key] = val;
199
+ });
200
+ localKeys.forEach((k) => {
201
+ if (!keys.includes(k)) {
202
+ item[k] = '';
203
+ }
204
+ });
205
+ } catch (error) {}
206
+ return item;
207
+ });
212
208
  dataList.value = records;
213
209
  listForm.total = total;
214
210
  })
215
- .catch((error) => {
216
- ElMessage.error('获取数据失败');
217
- console.error('获取列表数据失败:', error);
218
- })
219
211
  .finally(() => {
220
212
  loading.close();
221
213
  });
@@ -239,25 +231,22 @@ function rowClickHandler(row) {
239
231
  }
240
232
 
241
233
  function resetList() {
242
- listForm.name = '';
234
+ listForm.key = '';
243
235
  listForm.pageNum = 1;
244
236
  listForm.total = 0;
245
237
  getDataList();
246
238
  }
247
239
 
248
240
  const langList = Object.keys(i18nStore.langList);
249
- const formDataIndex = ref<number>();
250
- const formData = reactive<TranslateItem>({
251
- name: '',
252
- content: '',
253
- });
241
+ const formDataIndex = ref();
242
+ const formData = reactive<any>({});
254
243
  const formShow = ref(false);
255
-
244
+ let inputs: HTMLInputElement[] = [];
256
245
  function cancelForm() {
257
246
  vxeFormRef?.value?.reset();
258
247
  vxeFormRef?.value?.clearValidate();
259
248
  formDataIndex.value = void 0;
260
- formData.id = undefined;
249
+ formData.id = null;
261
250
  formShow.value = false;
262
251
  }
263
252
 
@@ -266,7 +255,7 @@ function addOne() {
266
255
  }
267
256
 
268
257
  function prevOne() {
269
- if (formDataIndex.value !== void 0 && formDataIndex.value > 0) {
258
+ if (formDataIndex.value > 0) {
270
259
  let index = formDataIndex.value - 1;
271
260
  let item = dataList.value[index];
272
261
  editOne(item, index);
@@ -275,13 +264,6 @@ function prevOne() {
275
264
 
276
265
  function editOne(item, index) {
277
266
  formDataIndex.value = index;
278
- // 先清空表单数据,除了 id
279
- for (const key in formData) {
280
- if (key !== 'id') {
281
- delete formData[key];
282
- }
283
- }
284
- // 然后将新项目的数据复制到表单
285
267
  for (const key in item) {
286
268
  if (Object.prototype.hasOwnProperty.call(item, key)) {
287
269
  const val = item[key];
@@ -296,7 +278,7 @@ function editOne(item, index) {
296
278
  }
297
279
 
298
280
  function nextOne() {
299
- if (formDataIndex.value !== void 0 && formDataIndex.value < dataList.value.length - 1) {
281
+ if (formDataIndex.value < dataList.value.length - 1) {
300
282
  let index = formDataIndex.value + 1;
301
283
  let item = dataList.value[index];
302
284
  editOne(item, index);
@@ -304,18 +286,18 @@ function nextOne() {
304
286
  }
305
287
 
306
288
  function saveOne() {
307
- let isAdd = !formData.id;
289
+ let isAdd = !!formData.adTranslateId;
308
290
  let url = updateUrl;
309
291
  vxeFormRef?.value?.validate().then((errMap) => {
310
292
  if (!errMap) {
311
- let data: SaveData = {
312
- name: formData.name,
293
+ let data: any = {
294
+ key: formData.key,
313
295
  content: {},
314
296
  };
315
297
  if (isAdd) {
316
298
  url = insertUrl;
317
299
  } else {
318
- data.id = formData.id;
300
+ data.id = formData.adTranslateId;
319
301
  }
320
302
  for (const key in formData) {
321
303
  if (key !== 'key' && langList.includes(key)) {
@@ -333,16 +315,13 @@ function saveOne() {
333
315
  .then((res) => {
334
316
  if (res?.data?.status === 200) {
335
317
  ElMessage.success(res.data.msg);
336
- if (isAdd) {
337
- getDataList();
338
- cancelForm();
318
+ if (!isAdd) {
319
+ dataList.value[formDataIndex.value] = {
320
+ ...formData,
321
+ };
322
+ nextOne();
339
323
  } else {
340
- if (formDataIndex.value !== undefined && formDataIndex.value !== null) {
341
- dataList.value[formDataIndex.value] = {
342
- ...formData,
343
- };
344
- nextOne();
345
- }
324
+ cancelForm();
346
325
  }
347
326
  } else {
348
327
  ElMessage.error(res.data.msg);
@@ -375,8 +354,7 @@ function delOne(id) {
375
354
 
376
355
  function delMore() {
377
356
  ElMessageBox.confirm('确认删除选中的翻译记录吗?').then(async () => {
378
- const selectedRows = i18nList.value?.getSelectionRows();
379
- const ids = selectedRows?.map((row) => row.id) || [];
357
+ let ids = i18nList.value?.getSelectionRows().map((row) => row.adTranslateId);
380
358
  if (ids && ids.length) {
381
359
  let len = ids.length;
382
360
  let loading = ElLoadingService({
@@ -385,21 +363,15 @@ function delMore() {
385
363
  for (let i = 0; i < ids.length; i++) {
386
364
  const id = ids[i];
387
365
  loading.setText(`正在删除... ${i + 1}/${len}`);
388
- try {
389
- await http.request({
390
- url: deleteUrl,
391
- method: 'POST',
392
- data: {
393
- id,
394
- },
395
- });
396
- } catch (error) {
397
- ElMessage.error(`删除第 ${i + 1} 条记录失败`);
398
- console.error(`删除第 ${i + 1} 条记录失败:`, error);
399
- }
366
+ await http.request({
367
+ url: deleteUrl,
368
+ method: 'POST',
369
+ data: {
370
+ id,
371
+ },
372
+ });
400
373
  }
401
374
  loading.close();
402
- ElMessage.success(`删除完成,共 ${len} 条记录`);
403
375
  getDataList();
404
376
  }
405
377
  });
@@ -407,7 +379,7 @@ function delMore() {
407
379
 
408
380
  const formItems = reactive<VxeFormPropTypes.Items>([
409
381
  {
410
- field: 'name',
382
+ field: 'key',
411
383
  span: 24,
412
384
  title: '翻译键值',
413
385
  itemRender: {
@@ -417,8 +389,8 @@ const formItems = reactive<VxeFormPropTypes.Items>([
417
389
  },
418
390
  ]);
419
391
 
420
- const formRules = reactive<VxeFormPropTypes.Rules>({
421
- name: [{required: true, type: 'string', message: '请输入翻译键值'}],
392
+ const fromRules = reactive<VxeFormPropTypes.Rules>({
393
+ key: [{required: true, type: 'string', message: '请输入翻译键值'}],
422
394
  });
423
395
 
424
396
  let needInit = true;
@@ -451,32 +423,51 @@ watch(
451
423
  }
452
424
  );
453
425
 
454
- const handleKeydown = (e: KeyboardEvent) => {
455
- let {key, ctrlKey, altKey} = e;
456
- if (key === 's' && ctrlKey) {
457
- e.preventDefault();
458
- e.stopPropagation();
459
- saveOne();
460
- }
461
- if (key === 'ArrowRight' && (ctrlKey || altKey)) {
462
- e.preventDefault();
463
- e.stopPropagation();
464
- nextOne();
465
- }
466
- if (key === 'ArrowLeft' && (ctrlKey || altKey)) {
467
- e.preventDefault();
468
- e.stopPropagation();
469
- prevOne();
470
- }
471
- };
472
-
473
426
  onMounted(() => {
474
427
  getDataList();
475
- window.addEventListener('keydown', handleKeydown);
476
- });
428
+ window.addEventListener('keydown', (e) => {
429
+ let {key, ctrlKey, altKey} = e;
430
+ if (key === 's' && ctrlKey) {
431
+ e.preventDefault();
432
+ e.stopPropagation();
433
+ saveOne();
434
+ }
435
+ if (key === 'ArrowRight' && (ctrlKey || altKey)) {
436
+ e.preventDefault();
437
+ e.stopPropagation();
438
+ nextOne();
439
+ }
440
+ if (key === 'ArrowLeft' && (ctrlKey || altKey)) {
441
+ e.preventDefault();
442
+ e.stopPropagation();
443
+ prevOne();
444
+ }
445
+ if (key === 'Tab') {
446
+ e.preventDefault();
447
+ e.stopPropagation();
448
+ if (
449
+ document.activeElement ||
450
+ // @ts-ignore
451
+ inputs.includes(document.activeElement)
452
+ ) {
453
+ // @ts-ignore
454
+ let index = inputs.indexOf(document.activeElement);
477
455
 
478
- onUnmounted(() => {
479
- window.removeEventListener('keydown', handleKeydown);
456
+ if (index === inputs.length) {
457
+ index = 0;
458
+ } else {
459
+ index++;
460
+ }
461
+ inputs[index].focus();
462
+ } else {
463
+ setTimeout(() => {
464
+ if (!document.activeElement || !inputs.includes(document.activeElement as HTMLInputElement)) {
465
+ (document.querySelector('#i18nFormItem1 input') as HTMLInputElement)?.focus();
466
+ }
467
+ }, 100);
468
+ }
469
+ }
470
+ });
480
471
  });
481
472
  </script>
482
473
  <style lang="scss">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yh-i18n",
3
- "version": "2.2.23",
3
+ "version": "2.3.0",
4
4
  "description": "对于国际化的封装",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -18,4 +18,4 @@
18
18
  "element-plus": "^2.3.8"
19
19
  },
20
20
  "author": "Liubin"
21
- }
21
+ }