cc-translate 0.4.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/README.md ADDED
File without changes
package/index.d.ts ADDED
@@ -0,0 +1,48 @@
1
+ import { OpenAI } from "openai";
2
+ import { ICwalletTranslateParams, IJson, IOpenaiConfig, IOutputLanguageFile, ISingleTranslate, ITranslateChat, ITranslateChatResponse, SupportLanguageType } from "./types";
3
+ export declare class CwalletTranslate {
4
+ private OPENAI_KEY;
5
+ CACHE_ROOT_PATH: string;
6
+ ENTRY_ROOT_PATH: string;
7
+ SOURCE_LANGUAGE: SupportLanguageType;
8
+ OUTPUT_ROOT_PATH: string | undefined;
9
+ languages: SupportLanguageType[];
10
+ client: OpenAI | null;
11
+ openaiConfig: IOpenaiConfig;
12
+ fineTune: string[];
13
+ constructor(params: ICwalletTranslateParams);
14
+ get supportLanguages(): import("./types").ILanguage[];
15
+ get outputPath(): string;
16
+ searchLanguage(code: SupportLanguageType): import("./types").ILanguage | undefined;
17
+ createOpenAIClient: () => void;
18
+ /** 翻译入口文件的所有支持的语言文件夹和其中的文件 */
19
+ translate: () => Promise<void>;
20
+ /**
21
+ * 翻译单个文件
22
+ * @param params
23
+ * @returns
24
+ */
25
+ singleTranslate: (params: ISingleTranslate) => Promise<void>;
26
+ /**
27
+ * 使用open ai 进行翻译
28
+ * @param {string} key
29
+ * @param {string} value
30
+ * @param {OpenAI} client
31
+ * @param {string} language
32
+ * @returns
33
+ */
34
+ translateChat: (params: ITranslateChat) => Promise<ITranslateChatResponse>;
35
+ /**
36
+ * 对比缓存文件 获取需要翻译的内容
37
+ * @param language
38
+ * @param fileName
39
+ * @returns
40
+ */
41
+ getTranslateContent: (language: SupportLanguageType, fileName: string) => Promise<IJson | undefined>;
42
+ /**
43
+ * 输出语言文件
44
+ * @param {Object} jsonMap
45
+ */
46
+ outputLanguageFile: (params: IOutputLanguageFile) => Promise<void>;
47
+ }
48
+ //# sourceMappingURL=index.d.ts.map
package/index.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EACL,uBAAuB,EACvB,KAAK,EACL,aAAa,EACb,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,SAAS,CAAC;AAsBjB,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,UAAU,CAAS;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,mBAAmB,CAAC;IACrC,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,SAAS,EAAE,mBAAmB,EAAE,CAAC;IACjC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC7B,YAAY,EAAE,aAAa,CAAC;IAC5B,QAAQ,EAAE,MAAM,EAAE,CAAC;gBAEP,MAAM,EAAE,uBAAuB;IAc3C,IAAI,gBAAgB,kCAOnB;IAED,IAAI,UAAU,WAEb;IAED,cAAc,CAAC,IAAI,EAAE,mBAAmB;IAIxC,kBAAkB,aAOhB;IACF,8BAA8B;IAC9B,SAAS,sBAyDP;IACF;;;;OAIG;IACH,eAAe,WAAkB,gBAAgB,mBA4D/C;IAEF;;;;;;;OAOG;IACH,aAAa,WAAY,cAAc,KAAG,OAAO,CAAC,sBAAsB,CAAC,CA2DvE;IACF;;;;;OAKG;IACH,mBAAmB,aACP,mBAAmB,YACnB,MAAM,KACf,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CA8B3B;IAEF;;;OAGG;IACH,kBAAkB,WAAkB,mBAAmB,mBAsCrD;CACH"}
package/index.js ADDED
@@ -0,0 +1,274 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import path from "path";
11
+ import fs from "fs";
12
+ import colors from "ansi-colors";
13
+ import { OpenAI } from "openai";
14
+ import cliProgress from "cli-progress";
15
+ import { chunkArray, getRandomNumber, notExistsToCreateFile, readFileOfDirSync, readJsonFileSync, } from "./lib/utils.js";
16
+ import { getCacheFileSync, registerLanguageCacheFile, translateJSONDiffToJson, } from "./lib/cache/index.js";
17
+ import { logErrorToFile } from "./lib/log/index.js";
18
+ import { SUPPORT_LANGUAGE_MAP } from "./lib/support.js";
19
+ const __dirname = process.cwd();
20
+ const DEFAULT_OPENAI_CONFIG = {
21
+ model: "gpt-4o",
22
+ };
23
+ export class CwalletTranslate {
24
+ constructor(params) {
25
+ var _a, _b, _c;
26
+ this.client = null;
27
+ this.createOpenAIClient = () => {
28
+ /** 初始化openAi */
29
+ const client = new OpenAI({
30
+ apiKey: this.OPENAI_KEY,
31
+ });
32
+ this.client = client;
33
+ };
34
+ /** 翻译入口文件的所有支持的语言文件夹和其中的文件 */
35
+ this.translate = () => __awaiter(this, void 0, void 0, function* () {
36
+ console.log("🚀 开始翻译");
37
+ console.log(`🚀 使用的模型: ${this.openaiConfig.model} 🚀`);
38
+ console.log(`🚀 微调: ${this.fineTune} 🚀`);
39
+ const translateFolderPath = path.join(this.ENTRY_ROOT_PATH, this.SOURCE_LANGUAGE);
40
+ // 翻译源语言问价夹下的所有json文件
41
+ const translateFolders = yield readFileOfDirSync(translateFolderPath);
42
+ // 创建进度条
43
+ const multiBar = new cliProgress.MultiBar({
44
+ clearOnComplete: false,
45
+ hideCursor: true,
46
+ format: colors.cyan("{bar}") +
47
+ "| {percentage}% || {filename} {value}/{total} ",
48
+ }, cliProgress.Presets.legacy);
49
+ let promises = [];
50
+ const arr = [];
51
+ for (const item of this.supportLanguages) {
52
+ // 源语言不翻译
53
+ if (item.code === this.SOURCE_LANGUAGE)
54
+ continue;
55
+ for (const fileName of translateFolders) {
56
+ const translateJson = yield this.getTranslateContent(item.code, fileName);
57
+ if (!translateJson) {
58
+ console.log(`${item.code}:${fileName} 没有需要翻译的内容`);
59
+ continue;
60
+ }
61
+ arr.push(() => this.singleTranslate({
62
+ language: item.code,
63
+ fileName,
64
+ multiBar,
65
+ translateJson,
66
+ }));
67
+ }
68
+ }
69
+ promises = chunkArray(arr, 8);
70
+ for (const chunk of promises) {
71
+ yield Promise.all(chunk.map((fn) => fn()));
72
+ }
73
+ multiBar.stop();
74
+ console.log("🚀 翻译完毕");
75
+ });
76
+ /**
77
+ * 翻译单个文件
78
+ * @param params
79
+ * @returns
80
+ */
81
+ this.singleTranslate = (params) => __awaiter(this, void 0, void 0, function* () {
82
+ const {
83
+ /** 待翻译的语言 */
84
+ language,
85
+ /** 待翻译的文件名 */
86
+ fileName, translateJson, multiBar, callback, } = params;
87
+ try {
88
+ /** 待翻译的文件路径 */
89
+ const translateFilePath = path.join(this.ENTRY_ROOT_PATH, language, fileName);
90
+ // 等待翻译的数组
91
+ const jsonMap = {};
92
+ // 生成chat循环代码
93
+ const promiseList = Object.entries(translateJson).map(([key, value], index) => () => this.translateChat({
94
+ key,
95
+ value,
96
+ language,
97
+ index,
98
+ fileName,
99
+ }));
100
+ const progressBar = multiBar.create(promiseList.length, 0);
101
+ for (const fn of promiseList) {
102
+ const result = yield fn();
103
+ jsonMap[result.key] = result.value;
104
+ progressBar.update(result.index + 1, {
105
+ filename: `${language}:${fileName}`,
106
+ });
107
+ }
108
+ this.outputLanguageFile({
109
+ jsonMap,
110
+ folderName: language,
111
+ fileName,
112
+ translateFilePath,
113
+ });
114
+ callback && callback();
115
+ }
116
+ catch (error) {
117
+ logErrorToFile({
118
+ error: error,
119
+ language,
120
+ fileName,
121
+ key: "",
122
+ });
123
+ return;
124
+ }
125
+ });
126
+ /**
127
+ * 使用open ai 进行翻译
128
+ * @param {string} key
129
+ * @param {string} value
130
+ * @param {OpenAI} client
131
+ * @param {string} language
132
+ * @returns
133
+ */
134
+ this.translateChat = (params) => {
135
+ return new Promise((resolve) => {
136
+ const { key, value, language, index, fileName } = params;
137
+ try {
138
+ if (!this.client)
139
+ throw new Error("Connection failed");
140
+ const targetLanguage = this.searchLanguage(language);
141
+ const originLanguage = this.searchLanguage(this.SOURCE_LANGUAGE);
142
+ if (!targetLanguage) {
143
+ throw new Error(`不支持的语言:${language}`);
144
+ }
145
+ if (!originLanguage) {
146
+ throw new Error(`不支持的语言:${this.SOURCE_LANGUAGE}`);
147
+ }
148
+ setTimeout(() => __awaiter(this, void 0, void 0, function* () {
149
+ var _a, _b, _c;
150
+ const chatCompletion = yield this.client.chat.completions.create({
151
+ model: (_a = this.openaiConfig) === null || _a === void 0 ? void 0 : _a.model,
152
+ messages: [
153
+ ...this.fineTune.map((val) => ({
154
+ role: "system",
155
+ content: val,
156
+ })),
157
+ {
158
+ role: "system",
159
+ content: `请将${originLanguage.name}翻译成${targetLanguage.name}`,
160
+ },
161
+ {
162
+ role: "system",
163
+ content: `翻译完成直接输出后对应意思的内容不要携带任何无关内容`,
164
+ },
165
+ {
166
+ role: "user",
167
+ content: value,
168
+ },
169
+ ],
170
+ });
171
+ resolve({
172
+ key,
173
+ value: (_c = (_b = chatCompletion === null || chatCompletion === void 0 ? void 0 : chatCompletion.choices[0]) === null || _b === void 0 ? void 0 : _b.message.content) !== null && _c !== void 0 ? _c : value,
174
+ index,
175
+ });
176
+ }), getRandomNumber(200, 300));
177
+ }
178
+ catch (error) {
179
+ logErrorToFile({ error: error, key, fileName, language });
180
+ resolve({
181
+ key,
182
+ value,
183
+ index,
184
+ error: error,
185
+ });
186
+ }
187
+ });
188
+ };
189
+ /**
190
+ * 对比缓存文件 获取需要翻译的内容
191
+ * @param language
192
+ * @param fileName
193
+ * @returns
194
+ */
195
+ this.getTranslateContent = (language, fileName) => __awaiter(this, void 0, void 0, function* () {
196
+ const translateFilePath = path.join(this.ENTRY_ROOT_PATH, this.SOURCE_LANGUAGE, fileName);
197
+ /** 缓存文件路径 */
198
+ const cacheFilePath = path.join(this.CACHE_ROOT_PATH, language, fileName);
199
+ if (!fs.existsSync(translateFilePath)) {
200
+ console.dir(`File not found: ${translateFilePath}`);
201
+ return;
202
+ }
203
+ const translateFileObject = yield readJsonFileSync(translateFilePath);
204
+ const cacheObject = yield getCacheFileSync(cacheFilePath);
205
+ const diffObject = translateJSONDiffToJson(cacheObject, translateFileObject);
206
+ if (Object.values(diffObject).length === 0) {
207
+ if (Object.keys(translateFileObject).length === 0) {
208
+ this.outputLanguageFile({
209
+ jsonMap: {},
210
+ folderName: language,
211
+ fileName,
212
+ translateFilePath,
213
+ });
214
+ }
215
+ return;
216
+ }
217
+ return diffObject;
218
+ });
219
+ /**
220
+ * 输出语言文件
221
+ * @param {Object} jsonMap
222
+ */
223
+ this.outputLanguageFile = (params) => __awaiter(this, void 0, void 0, function* () {
224
+ const { folderName, fileName, jsonMap, translateFilePath } = params;
225
+ const outputFilePath = path.join(this.outputPath, folderName, fileName);
226
+ //创建输出文件夹
227
+ notExistsToCreateFile(this.outputPath);
228
+ //创建输出的语言文件夹
229
+ notExistsToCreateFile(`${this.outputPath}/${folderName}`);
230
+ let oldJsonData = "";
231
+ // 检查是否存在文件
232
+ if (!fs.existsSync(outputFilePath)) {
233
+ oldJsonData = yield fs.readFileSync(path.join(this.ENTRY_ROOT_PATH, this.SOURCE_LANGUAGE, fileName), "utf8");
234
+ }
235
+ else {
236
+ oldJsonData = yield fs.readFileSync(outputFilePath, "utf8");
237
+ }
238
+ const oldJsonMap = JSON.parse(oldJsonData);
239
+ const newJsonMap = Object.assign(oldJsonMap, jsonMap);
240
+ yield fs.writeFileSync(path.resolve(outputFilePath), JSON.stringify(newJsonMap, null, 2), "utf8");
241
+ // 注册缓存
242
+ registerLanguageCacheFile({
243
+ sourceFilePath: path.join(this.ENTRY_ROOT_PATH, this.SOURCE_LANGUAGE, fileName),
244
+ jsonMap: newJsonMap,
245
+ fileName,
246
+ language: folderName,
247
+ folderName: this.CACHE_ROOT_PATH,
248
+ });
249
+ });
250
+ this.OPENAI_KEY = params.key;
251
+ this.CACHE_ROOT_PATH = path.resolve(__dirname, params.cacheFileRootPath);
252
+ this.ENTRY_ROOT_PATH = path.resolve(__dirname, params.fileRootPath);
253
+ this.openaiConfig = (_a = params.openaiConfig) !== null && _a !== void 0 ? _a : DEFAULT_OPENAI_CONFIG;
254
+ this.SOURCE_LANGUAGE = (_b = params.sourceLanguage) !== null && _b !== void 0 ? _b : "en";
255
+ this.OUTPUT_ROOT_PATH = params.outputRootPath
256
+ ? path.resolve(__dirname, params.outputRootPath)
257
+ : undefined;
258
+ this.fineTune = params.fineTune;
259
+ this.languages = (_c = params.languages) !== null && _c !== void 0 ? _c : [];
260
+ this.createOpenAIClient();
261
+ }
262
+ get supportLanguages() {
263
+ return Object.entries(SUPPORT_LANGUAGE_MAP)
264
+ .map(([key, val]) => val)
265
+ .filter(({ code }) => this.languages.includes(code) || code === this.SOURCE_LANGUAGE);
266
+ }
267
+ get outputPath() {
268
+ var _a;
269
+ return (_a = this.OUTPUT_ROOT_PATH) !== null && _a !== void 0 ? _a : this.ENTRY_ROOT_PATH;
270
+ }
271
+ searchLanguage(code) {
272
+ return this.supportLanguages.find((item) => item.code === code);
273
+ }
274
+ }
@@ -0,0 +1,20 @@
1
+ import { IJson, IRegisterLanguageCacheFile } from "../../types";
2
+ /**
3
+ * 和翻译缓存json文件对比 返回存在更改的json文件
4
+ * @param {object} cacheObject 已经缓存的对象
5
+ * @param {object} translateObject 需要翻译的对象
6
+ * @returns {object} 存在修改的对象
7
+ */
8
+ export declare const translateJSONDiffToJson: (cacheObject: IJson, translateObject: IJson) => IJson;
9
+ /**
10
+ * 获取缓存文件
11
+ * @param {string} filePath 缓存文件路径
12
+ * @returns {Promise<{key:value}>}
13
+ */
14
+ export declare const getCacheFileSync: (filePath: string) => Promise<IJson>;
15
+ /**
16
+ * 注册语言缓存文件
17
+ * @param {string} language
18
+ */
19
+ export declare const registerLanguageCacheFile: (params: IRegisterLanguageCacheFile) => Promise<void>;
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/cache/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,gBACrB,KAAK,mBACD,KAAK,UAiBvB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,aAAoB,MAAM,KAAG,OAAO,CAAC,KAAK,CAMtE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,yBAAyB,WAC5B,0BAA0B,kBAmBnC,CAAC"}
@@ -0,0 +1,66 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import path from "path";
11
+ import fs from "fs";
12
+ import { notExistsToCreateFile, readJsonFileSync } from "../utils.js";
13
+ /**
14
+ * 和翻译缓存json文件对比 返回存在更改的json文件
15
+ * @param {object} cacheObject 已经缓存的对象
16
+ * @param {object} translateObject 需要翻译的对象
17
+ * @returns {object} 存在修改的对象
18
+ */
19
+ export const translateJSONDiffToJson = (cacheObject, translateObject) => {
20
+ if (Object.values(cacheObject).length === 0)
21
+ return translateObject;
22
+ // json文件内容diff
23
+ const pendingTranslateMap = {};
24
+ Object.entries(translateObject).forEach(([key, value]) => {
25
+ //不存在该key 是新增的key
26
+ if (!cacheObject[key]) {
27
+ pendingTranslateMap[key] = value;
28
+ }
29
+ // 存在缓存key但是内容不一样 需要重新翻译
30
+ else if (translateObject[key] !== cacheObject[key]) {
31
+ pendingTranslateMap[key] = value;
32
+ }
33
+ });
34
+ return pendingTranslateMap;
35
+ };
36
+ /**
37
+ * 获取缓存文件
38
+ * @param {string} filePath 缓存文件路径
39
+ * @returns {Promise<{key:value}>}
40
+ */
41
+ export const getCacheFileSync = (filePath) => __awaiter(void 0, void 0, void 0, function* () {
42
+ if (fs.existsSync(filePath)) {
43
+ return yield readJsonFileSync(filePath);
44
+ }
45
+ else {
46
+ return {};
47
+ }
48
+ });
49
+ /**
50
+ * 注册语言缓存文件
51
+ * @param {string} language
52
+ */
53
+ export const registerLanguageCacheFile = (params) => __awaiter(void 0, void 0, void 0, function* () {
54
+ const { jsonMap, sourceFilePath, fileName, language, folderName } = params;
55
+ const cacheFilePath = path.join(folderName, language, fileName);
56
+ const sourceObject = yield readJsonFileSync(sourceFilePath);
57
+ const cacheObject = yield readJsonFileSync(cacheFilePath);
58
+ Object.entries(jsonMap).forEach(([key, value]) => {
59
+ cacheObject[key] = sourceObject[key];
60
+ });
61
+ if (Object.values(jsonMap).length === 0)
62
+ return;
63
+ notExistsToCreateFile(folderName);
64
+ notExistsToCreateFile(`${folderName}/${language}`);
65
+ yield fs.writeFileSync(cacheFilePath, JSON.stringify(cacheObject, null, 2), "utf8");
66
+ });
@@ -0,0 +1,3 @@
1
+ import { ITranslateLogError } from "../../types";
2
+ export declare function logErrorToFile(params: ITranslateLogError): void;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/log/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGjD,wBAAgB,cAAc,CAAC,MAAM,EAAE,kBAAkB,QAexD"}
@@ -0,0 +1,17 @@
1
+ import fs from "fs";
2
+ export function logErrorToFile(params) {
3
+ const { error, key, language, fileName } = params;
4
+ const logMessage = `${new Date().toISOString()} - Error: ${error.message}
5
+ \nLanguage: ${language}
6
+ \nFileName: ${fileName}
7
+ \nkey:${key}
8
+ \nStack: ${error.stack}\n\n`;
9
+ fs.appendFile("error.log", logMessage, (err) => {
10
+ if (err) {
11
+ console.error("无法写入日志文件:", err);
12
+ }
13
+ else {
14
+ console.log("错误日志已写入 error.log 文件");
15
+ }
16
+ });
17
+ }
@@ -0,0 +1,3 @@
1
+ import { SupportLanguageMap } from "../types";
2
+ export declare const SUPPORT_LANGUAGE_MAP: SupportLanguageMap;
3
+ //# sourceMappingURL=support.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"support.d.ts","sourceRoot":"","sources":["../src/lib/support.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE9C,eAAO,MAAM,oBAAoB,EAAE,kBAqGlC,CAAC"}
package/lib/support.js ADDED
@@ -0,0 +1,102 @@
1
+ export const SUPPORT_LANGUAGE_MAP = {
2
+ en: {
3
+ code: "en",
4
+ name: "英语",
5
+ },
6
+ ["zh-CN"]: {
7
+ code: "zh-CN",
8
+ name: "简体中文",
9
+ },
10
+ ["zh-TW"]: {
11
+ code: "zh-TW",
12
+ name: "繁体中文",
13
+ },
14
+ ja: {
15
+ code: "ja",
16
+ name: "日语",
17
+ },
18
+ ar: {
19
+ code: "ar",
20
+ name: "阿拉伯语",
21
+ },
22
+ bn: {
23
+ code: "bn",
24
+ name: "孟加拉语",
25
+ },
26
+ de: {
27
+ code: "de",
28
+ name: "德语",
29
+ },
30
+ ["es-ES"]: {
31
+ code: "es-ES",
32
+ name: "西班牙语",
33
+ },
34
+ fr: {
35
+ code: "fr",
36
+ name: "法语",
37
+ },
38
+ hi: {
39
+ code: "hi",
40
+ name: "印地语",
41
+ },
42
+ id: {
43
+ code: "id",
44
+ name: "印度尼西亚语",
45
+ },
46
+ it: {
47
+ code: "it",
48
+ name: "意大利语",
49
+ },
50
+ ko: {
51
+ code: "ko",
52
+ name: "韩语",
53
+ },
54
+ ms: {
55
+ code: "ms",
56
+ name: "马来语",
57
+ },
58
+ my: {
59
+ code: "my",
60
+ name: "缅甸语",
61
+ },
62
+ ["ne-NP"]: {
63
+ code: "ne-NP",
64
+ name: "尼泊尔语",
65
+ },
66
+ nl: {
67
+ code: "nl",
68
+ name: "荷兰语",
69
+ },
70
+ pl: {
71
+ code: "pl",
72
+ name: "波兰语",
73
+ },
74
+ ["pt-PT"]: {
75
+ code: "pt-PT",
76
+ name: "葡萄牙语",
77
+ },
78
+ ru: {
79
+ code: "ru",
80
+ name: "俄罗斯语",
81
+ },
82
+ tl: {
83
+ code: "tl",
84
+ name: "菲律宾语",
85
+ },
86
+ tr: {
87
+ code: "tr",
88
+ name: "土耳其语",
89
+ },
90
+ vi: {
91
+ code: "vi",
92
+ name: "越南语",
93
+ },
94
+ uk: {
95
+ code: "uk",
96
+ name: "乌克兰语",
97
+ },
98
+ ["ur-PK"]: {
99
+ code: "ur-PK",
100
+ name: "乌尔都语",
101
+ },
102
+ };
package/lib/utils.d.ts ADDED
@@ -0,0 +1,25 @@
1
+ import { ICreateJsonFileParams } from "../types";
2
+ /**
3
+ * 不存在的文件夹则创建
4
+ * @param {string} path
5
+ */
6
+ export declare const notExistsToCreateFile: (path: string) => void;
7
+ /**
8
+ * 获取json文件 并返回 [[key,value],[key,value]...]]
9
+ * @param {*} path
10
+ * @returns
11
+ */
12
+ export declare const readJsonFileSync: (path: string) => Promise<any>;
13
+ /**
14
+ * 创建json文件
15
+ * @param {string} fileName 文件名
16
+ * @param {string} folderName 文件夹名
17
+ * @param {string} language 语言环境
18
+ * @param {object} jsonData 文件数据
19
+ */
20
+ export declare const createJsonFile: (params: ICreateJsonFileParams) => void;
21
+ export declare const getRandomNumber: (min: number, max: number) => number;
22
+ export declare const isDirectoryPath: (path: string) => boolean;
23
+ export declare const readFileOfDirSync: (dirPath: string) => string[];
24
+ export declare function chunkArray<T extends object>(array: T[], chunkSize: number): T[][];
25
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/lib/utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAEjD;;;GAGG;AACH,eAAO,MAAM,qBAAqB,SAAU,MAAM,SAGjD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,SAAgB,MAAM,iBAUlD,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,WAAY,qBAAqB,SAS3D,CAAC;AAEF,eAAO,MAAM,eAAe,QAAS,MAAM,OAAO,MAAM,WAEvD,CAAC;AAEF,eAAO,MAAM,eAAe,SAAU,MAAM,YAG3C,CAAC;AAEF,eAAO,MAAM,iBAAiB,YAAa,MAAM,aAKhD,CAAC;AAEF,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,SASzE"}
package/lib/utils.js ADDED
@@ -0,0 +1,75 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import path from "path";
11
+ import fs from "fs";
12
+ /**
13
+ * 不存在的文件夹则创建
14
+ * @param {string} path
15
+ */
16
+ export const notExistsToCreateFile = (path) => {
17
+ if (fs.existsSync(path))
18
+ return;
19
+ fs.mkdirSync(path);
20
+ };
21
+ /**
22
+ * 获取json文件 并返回 [[key,value],[key,value]...]]
23
+ * @param {*} path
24
+ * @returns
25
+ */
26
+ export const readJsonFileSync = (path) => __awaiter(void 0, void 0, void 0, function* () {
27
+ try {
28
+ if (!fs.existsSync(path))
29
+ return {};
30
+ const jsonStr = yield fs.readFileSync(path, "utf8");
31
+ // 将JSON字符串解析为对象
32
+ return JSON.parse(jsonStr);
33
+ }
34
+ catch (error) {
35
+ console.error("解析JSON时出错:", error);
36
+ return {};
37
+ }
38
+ });
39
+ /**
40
+ * 创建json文件
41
+ * @param {string} fileName 文件名
42
+ * @param {string} folderName 文件夹名
43
+ * @param {string} language 语言环境
44
+ * @param {object} jsonData 文件数据
45
+ */
46
+ export const createJsonFile = (params) => {
47
+ const { fileName, folderName, jsonData, language } = params;
48
+ notExistsToCreateFile(folderName);
49
+ notExistsToCreateFile(path.resolve(`${folderName}/${language}`));
50
+ fs.writeFileSync(path.resolve(`${folderName}/${language}/${fileName}`), JSON.stringify(jsonData, null, 2), "utf8");
51
+ };
52
+ export const getRandomNumber = (min, max) => {
53
+ return Math.floor(Math.random() * (max - min + 1)) + min;
54
+ };
55
+ export const isDirectoryPath = (path) => {
56
+ if (!fs.existsSync(path))
57
+ return false;
58
+ return fs.statSync(path).isDirectory();
59
+ };
60
+ export const readFileOfDirSync = (dirPath) => {
61
+ if (!isDirectoryPath(dirPath))
62
+ return [];
63
+ const files = fs.readdirSync(dirPath);
64
+ // 筛选出所有文件夹
65
+ return files.filter((file) => path.extname(file) === ".json");
66
+ };
67
+ export function chunkArray(array, chunkSize) {
68
+ const result = [];
69
+ let index = 0;
70
+ while (index < array.length) {
71
+ result.push(array.slice(index, index + chunkSize));
72
+ index += chunkSize;
73
+ }
74
+ return result;
75
+ }