gpt-po 1.0.4 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -21,6 +21,7 @@ Set `OPENAI_API_KEY` before using this tool.
21
21
 
22
22
  - `gpt-po sync --po <file> --pot <file>` Update the po file based on the pot file, while preserving the original translations.
23
23
  - `gpt-po --po <file>` Translate specified po files to a designated target language. By default, the target language is Simplified Chinese.
24
+ - `gpt-po --dir .` Translate all po files in current directory to a designated target language.
24
25
  - `gpt-po userdict` Modify or view user dictionaries
25
26
  - `gpt-po systemprompt` Modify or view system prompts, if you are not sure how to use it, you can leave it alone
26
27
 
@@ -52,7 +53,9 @@ Options:
52
53
  --model <model> openai model (choices: "gpt-4", "gpt-4-0314", "gpt-4-32k", "gpt-4-32k-0314", "gpt-3.5-turbo", "gpt-3.5-turbo-0301",
53
54
  default: "gpt-3.5-turbo")
54
55
  --po <file> po file path
56
+ --dir <dir> po file directory
55
57
  -src, --source <lang> source language (default: "english")
58
+ --verbose show verbose log
56
59
  -l, --lang <lang> target language (default: "simplified chinese")
57
60
  -o, --output <file> output file path, overwirte po file by default
58
61
  -h, --help display help for command
package/README_zh-CN.md CHANGED
@@ -21,6 +21,7 @@ npm install gpt-po
21
21
 
22
22
  - `gpt-po sync --po <file> --pot <file>` 根据pot文件更新po文件,保留原有翻译
23
23
  - `gpt-po --po <file>` 翻译指定的po文件到指定的目标语言,默认目标语言是简体中文
24
+ - `gpt-po --dir .` 翻译当前目录下的所有po文件到指定的目标语言,默认目标语言是简体中文
24
25
  - `gpt-po userdict` 修改或查看用户字典
25
26
  - `gpt-po systemprompt` 修改或查看系统提示词,如果你不确定如何使用,可以不用修改
26
27
 
@@ -52,7 +53,9 @@ Options:
52
53
  --model <model> openai model (choices: "gpt-4", "gpt-4-0314", "gpt-4-32k", "gpt-4-32k-0314", "gpt-3.5-turbo", "gpt-3.5-turbo-0301",
53
54
  default: "gpt-3.5-turbo")
54
55
  --po <file> po file path
56
+ --dir <dir> po files directory
55
57
  -src, --source <lang> source language (default: "english")
58
+ --verbose show verbose log
56
59
  -l, --lang <lang> target language (default: "simplified chinese")
57
60
  -o, --output <file> output file path, overwirte po file by default
58
61
  -h, --help display help for command
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gpt-po",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "command tool for translate po files by gpt",
5
5
  "main": "lib/src/index.js",
6
6
  "bin": {
package/lib/src/index.js CHANGED
@@ -34,18 +34,31 @@ program
34
34
  "gpt-3.5-turbo",
35
35
  "gpt-3.5-turbo-0301",
36
36
  ]))
37
- .requiredOption("--po <file>", "po file path")
38
- .option("-src, --source <lang>", "source language", "english")
39
- .requiredOption("-l, --lang <lang>", "target language", "simplified chinese")
40
- .option("-o, --output <file>", "output file path, overwirte po file by default")
41
- .action(({ key, host, model, po, source, lang, output }) => __awaiter(void 0, void 0, void 0, function* () {
37
+ .addOption(new commander_1.Option("--po <file>", "po file path").conflicts("dir"))
38
+ .addOption(new commander_1.Option("--dir <dir>", "po file directory").conflicts("po"))
39
+ .option("-src, --source <lang>", "source language", "English")
40
+ .option("-l, --lang <lang>", "target language", "Simplified Chinese")
41
+ .option("--verbose", "print verbose log")
42
+ .addOption(new commander_1.Option("-o, --output <file>", "output file path, overwirte po file by default").conflicts("dir"))
43
+ .action((args) => __awaiter(void 0, void 0, void 0, function* () {
44
+ const { key, host, model, po, dir, source, lang, verbose, output, checkRegx } = args;
42
45
  if (host) {
43
46
  process.env.OPENAI_API_HOST = host;
44
47
  }
45
48
  if (key) {
46
49
  process.env.OPENAI_API_KEY = key;
47
50
  }
48
- yield (0, translate_1.translatePo)(model, po, source, lang, output);
51
+ (0, translate_1.init)();
52
+ if (po) {
53
+ yield (0, translate_1.translatePo)(model, po, source, lang, verbose, output);
54
+ }
55
+ else if (dir) {
56
+ yield (0, translate_1.translatePoDir)(model, dir, source, lang, verbose);
57
+ }
58
+ else {
59
+ console.error("po file or directory is required");
60
+ process.exit(1);
61
+ }
49
62
  }));
50
63
  program
51
64
  .command("sync")
@@ -1,4 +1,5 @@
1
1
  import { OpenAIApi } from "openai";
2
2
  export declare function init(force?: boolean): OpenAIApi;
3
3
  export declare function translate(text: string, src: string, lang: string, model?: string): Promise<import("axios").AxiosResponse<import("openai").CreateChatCompletionResponse, any>>;
4
- export declare function translatePo(model: string | undefined, po: string, source: string, lang: string, output: string): Promise<void>;
4
+ export declare function translatePo(model: string | undefined, po: string, source: string, lang: string, verbose: boolean, output: string): Promise<void>;
5
+ export declare function translatePoDir(model: string | undefined, dir: string, source: string, lang: string, verbose: boolean): Promise<void>;
@@ -9,10 +9,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.translatePo = exports.translate = exports.init = void 0;
12
+ exports.translatePoDir = exports.translatePo = exports.translate = exports.init = void 0;
13
13
  const fs = require("fs");
14
14
  const openai_1 = require("openai");
15
- const os_1 = require("os");
16
15
  const path_1 = require("path");
17
16
  const pkg = require("../package.json");
18
17
  const utils_1 = require("./utils");
@@ -31,13 +30,13 @@ function init(force) {
31
30
  }
32
31
  // load systemprompt.txt from homedir
33
32
  if (!_systemprompt || force) {
34
- const systemprompt = (0, path_1.join)((0, os_1.homedir)(), "systemprompt.txt");
33
+ const systemprompt = (0, utils_1.findConfig)("systemprompt.txt");
35
34
  (0, utils_1.copyFileIfNotExists)(systemprompt, (0, path_1.join)(__dirname, "systemprompt.txt"));
36
35
  _systemprompt = fs.readFileSync(systemprompt, "utf-8");
37
36
  }
38
37
  // load dictionary.json from homedir
39
38
  if (!_userdict || force) {
40
- const userdict = (0, path_1.join)((0, os_1.homedir)(), "dictionary.json");
39
+ const userdict = (0, utils_1.findConfig)("dictionary.json");
41
40
  (0, utils_1.copyFileIfNotExists)(userdict, (0, path_1.join)(__dirname, "dictionary.json"));
42
41
  _userdict = JSON.parse(fs.readFileSync(userdict, "utf-8"));
43
42
  }
@@ -45,22 +44,20 @@ function init(force) {
45
44
  }
46
45
  exports.init = init;
47
46
  function translate(text, src, lang, model = "gpt-3.5-turbo") {
48
- const openai = init();
49
47
  const dicts = Object.entries(_userdict)
50
48
  .map(([k, v]) => [
51
49
  { role: "user", content: k },
52
50
  { role: "assistant", content: v },
53
51
  ])
54
52
  .flat();
55
- return openai.createChatCompletion({
53
+ return _openai.createChatCompletion({
56
54
  model,
57
- temperature: 0.5,
58
- n: 1,
55
+ temperature: 0.1,
59
56
  messages: [
60
57
  { role: "system", content: _systemprompt },
61
58
  {
62
59
  role: "user",
63
- content: `Translate incoming ${src} content into ${lang}, only the translated content can be returned, don't ask question.`,
60
+ content: `Translate the ${src} content I will post later into ${lang}, and keep the untranslated parts such as symbols in the result.`,
64
61
  },
65
62
  {
66
63
  role: "assistant",
@@ -75,22 +72,35 @@ function translate(text, src, lang, model = "gpt-3.5-turbo") {
75
72
  });
76
73
  }
77
74
  exports.translate = translate;
78
- function translatePo(model = "gpt-3.5-turbo", po, source, lang, output) {
75
+ function translatePo(model = "gpt-3.5-turbo", po, source, lang, verbose, output) {
79
76
  var _a;
80
77
  return __awaiter(this, void 0, void 0, function* () {
81
78
  const potrans = yield (0, utils_1.parsePo)(po);
82
79
  const list = [];
80
+ const trimRegx = /(?:^ )|(?: $)/;
81
+ let trimed = false;
83
82
  for (const [ctx, entries] of Object.entries(potrans.translations)) {
84
83
  for (const [msgid, trans] of Object.entries(entries)) {
84
+ if (msgid == "")
85
+ continue;
85
86
  if (!trans.msgstr[0]) {
86
87
  list.push(trans);
88
+ continue;
89
+ }
90
+ else if (trimRegx.test(trans.msgstr[0])) {
91
+ trimed = true;
92
+ trans.msgstr[0] = trans.msgstr[0].trim();
87
93
  }
88
94
  }
89
95
  }
96
+ if (trimed) {
97
+ yield (0, utils_1.compilePo)(potrans, po);
98
+ }
90
99
  if (list.length == 0) {
91
- console.log("nothing needs translate");
100
+ console.log("done.");
92
101
  return;
93
102
  }
103
+ potrans.headers["Last-Translator"] = `gpt-po v${pkg.version}`;
94
104
  let err429 = false;
95
105
  let modified = false;
96
106
  for (let i = 0; i < list.length; i++) {
@@ -105,7 +115,12 @@ function translatePo(model = "gpt-3.5-turbo", po, source, lang, output) {
105
115
  const res = yield translate(trans.msgid, source, lang, model);
106
116
  trans.msgstr[0] = ((_a = res.data.choices[0].message) === null || _a === void 0 ? void 0 : _a.content) || trans.msgstr[0];
107
117
  modified = true;
118
+ if (verbose) {
119
+ console.log(trans.msgid);
120
+ console.log(trans.msgstr[0]);
121
+ }
108
122
  (0, utils_1.printProgress)(i + 1, list.length);
123
+ yield (0, utils_1.compilePo)(potrans, output || po);
109
124
  }
110
125
  catch (error) {
111
126
  if (error.response) {
@@ -116,7 +131,7 @@ function translatePo(model = "gpt-3.5-turbo", po, source, lang, output) {
116
131
  }
117
132
  else {
118
133
  console.error(error.response.status);
119
- // console.log(error.response.data);
134
+ console.log(error.response.data);
120
135
  }
121
136
  }
122
137
  else {
@@ -124,11 +139,21 @@ function translatePo(model = "gpt-3.5-turbo", po, source, lang, output) {
124
139
  }
125
140
  }
126
141
  }
127
- if (modified) {
128
- potrans.headers["Last-Translator"] = `gpt-po v${pkg.version}`;
129
- yield (0, utils_1.compilePo)(potrans, output || po);
130
- }
142
+ console.log("done.");
131
143
  });
132
144
  }
133
145
  exports.translatePo = translatePo;
146
+ function translatePoDir(model = "gpt-3.5-turbo", dir, source, lang, verbose) {
147
+ return __awaiter(this, void 0, void 0, function* () {
148
+ const files = fs.readdirSync(dir);
149
+ for (const file of files) {
150
+ if (file.endsWith(".po")) {
151
+ const po = (0, path_1.join)(dir, file);
152
+ console.log(`translating ${po}`);
153
+ yield translatePo(model, po, source, lang, verbose, po);
154
+ }
155
+ }
156
+ });
157
+ }
158
+ exports.translatePoDir = translatePoDir;
134
159
  //# sourceMappingURL=translate.js.map
@@ -1,6 +1,13 @@
1
1
  import { GetTextTranslations } from "gettext-parser";
2
+ /**
3
+ * copy source file to destination file if destination file does not exist
4
+ * @param file destination file path
5
+ * @param copyFile source file path
6
+ */
2
7
  export declare function copyFileIfNotExists(file: string, copyFile: string): void;
3
8
  export declare function openFileByDefault(filePath: string): void;
4
9
  export declare function parsePo(poFile: string, defaultCharset?: string): Promise<GetTextTranslations>;
5
10
  export declare function compilePo(data: GetTextTranslations, poFile: string): Promise<void>;
6
11
  export declare function printProgress(progress: number, total: number, extra?: string): void;
12
+ export declare function gitRootDir(dir?: string): string | null;
13
+ export declare function findConfig(fileName: string): string;
package/lib/src/utils.js CHANGED
@@ -1,10 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.printProgress = exports.compilePo = exports.parsePo = exports.openFileByDefault = exports.copyFileIfNotExists = void 0;
4
- const fs = require("fs");
3
+ exports.findConfig = exports.gitRootDir = exports.printProgress = exports.compilePo = exports.parsePo = exports.openFileByDefault = exports.copyFileIfNotExists = void 0;
5
4
  const child_process_1 = require("child_process");
5
+ const fs = require("fs");
6
6
  const gettext_parser_1 = require("gettext-parser");
7
+ const os_1 = require("os");
8
+ const path = require("path");
9
+ /**
10
+ * copy source file to destination file if destination file does not exist
11
+ * @param file destination file path
12
+ * @param copyFile source file path
13
+ */
7
14
  function copyFileIfNotExists(file, copyFile) {
15
+ // make sure the directory exists
16
+ fs.mkdirSync(path.dirname(file), { recursive: true });
8
17
  // check if file exists else create it
9
18
  try {
10
19
  fs.accessSync(file, fs.constants.F_OK);
@@ -57,4 +66,42 @@ function printProgress(progress, total, extra) {
57
66
  process.stdout.write(`\r${bar}${dots} ${percent}% ${progress}/${total} ${extra || ""}`);
58
67
  }
59
68
  exports.printProgress = printProgress;
69
+ function gitRootDir(dir) {
70
+ // if dir is not provided, use current working directory
71
+ dir = dir || process.cwd();
72
+ // check if dir is a git repository
73
+ if (fs.existsSync(path.join(dir, ".git"))) {
74
+ return dir;
75
+ }
76
+ else {
77
+ // if dir is root directory, return null
78
+ if (path.dirname(dir) === dir) {
79
+ return null;
80
+ }
81
+ else {
82
+ // else, check parent directory
83
+ return gitRootDir(path.dirname(dir));
84
+ }
85
+ }
86
+ }
87
+ exports.gitRootDir = gitRootDir;
88
+ function findConfig(fileName) {
89
+ const currentDir = process.cwd();
90
+ const gitDir = gitRootDir() || currentDir;
91
+ const homeDir = (0, os_1.homedir)();
92
+ const filePaths = [
93
+ path.join(currentDir, ".gpt-po", fileName),
94
+ path.join(gitDir, ".gpt-po", fileName),
95
+ path.join(homeDir, ".config", ".gpt-po", fileName)
96
+ ];
97
+ // check if file exists and return the first one
98
+ for (const filePath of filePaths) {
99
+ if (fs.existsSync(filePath)) {
100
+ return filePath;
101
+ }
102
+ }
103
+ // if no file exists, return the default one
104
+ return path.join(homeDir, ".gpt-po", fileName);
105
+ }
106
+ exports.findConfig = findConfig;
60
107
  //# sourceMappingURL=utils.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gpt-po",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "command tool for translate po files by gpt",
5
5
  "main": "lib/src/index.js",
6
6
  "bin": {