gpt-po 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +55 -0
- package/lib/package.json +58 -0
- package/lib/src/dictionary.json +3 -0
- package/lib/src/index.d.ts +2 -0
- package/lib/src/index.js +83 -0
- package/lib/src/index.js.map +1 -0
- package/lib/src/sync.d.ts +1 -0
- package/lib/src/sync.js +33 -0
- package/lib/src/sync.js.map +1 -0
- package/lib/src/systemprompt.txt +1 -0
- package/lib/src/translate.d.ts +4 -0
- package/lib/src/translate.js +134 -0
- package/lib/src/translate.js.map +1 -0
- package/lib/src/utils.d.ts +6 -0
- package/lib/src/utils.js +60 -0
- package/lib/src/utils.js.map +1 -0
- package/package.json +58 -0
package/README.md
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# PO File Translation Tool for ChatGPT
|
2
|
+
|
3
|
+
Translation tool for gettext (po) files that supports custom system prompts and user dictionaries. It also supports translating specified po files to a designated target language and updating po files based on pot files.
|
4
|
+
|
5
|
+
Read in other languages: English | [简体中文](./Readme_zh-CN.md)
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
```
|
10
|
+
npm install openai
|
11
|
+
```
|
12
|
+
|
13
|
+
Set `OPENAI_API_KEY` before using this tool.
|
14
|
+
|
15
|
+
**It is recommended to use the paid OpenAI API to improve translation speed, as the free OpenAI API is slower (only 3 translations per minute) and has usage restrictions.**
|
16
|
+
|
17
|
+
## Usage Scenarios
|
18
|
+
|
19
|
+
- `gpt-po sync --po <file> --pot <file>` to update po files based on pot files. First update the po file and then translate it.
|
20
|
+
- `gpt-po --po <file>` to translate specified po files to a designated target language. By default, the target language is Simplified Chinese.
|
21
|
+
- `gpt-po userdict` to modify or view user dictionaries
|
22
|
+
- `gpt-po systemprompt` to modify or view system prompts, if you are not sure how to use it, you can leave it alone
|
23
|
+
|
24
|
+
```
|
25
|
+
Usage: gpt-po [command] [options]
|
26
|
+
|
27
|
+
command tool for translate po files by gpt
|
28
|
+
|
29
|
+
Options:
|
30
|
+
-V, --version output the version number
|
31
|
+
-h, --help display help for command
|
32
|
+
|
33
|
+
Commands:
|
34
|
+
translate [options] translate po file (default command)
|
35
|
+
sync [options] update po from pot file
|
36
|
+
systemprompt open/edit system prompt
|
37
|
+
userdict open/edit user dictionary
|
38
|
+
help [command] display help for command
|
39
|
+
```
|
40
|
+
|
41
|
+
```
|
42
|
+
Usage: gpt-po [options]
|
43
|
+
|
44
|
+
translate po file (default command)
|
45
|
+
|
46
|
+
Options:
|
47
|
+
-k, --key <key> openai api key (env: OPENAI_API_KEY)
|
48
|
+
--host <host> openai api host (env: OPENAI_API_HOST)
|
49
|
+
--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",
|
50
|
+
default: "gpt-3.5-turbo")
|
51
|
+
--po <file> po file path
|
52
|
+
-l, --lang <lang> target language (default: "simplified chinese")
|
53
|
+
-o, --output <file> output file path, overwirte po file by default
|
54
|
+
-h, --help display help for command
|
55
|
+
```
|
package/lib/package.json
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
{
|
2
|
+
"name": "gpt-po",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"description": "command tool for translate po files by gpt",
|
5
|
+
"main": "lib/src/index.js",
|
6
|
+
"bin": {
|
7
|
+
"gpt-po": "lib/src/index.js"
|
8
|
+
},
|
9
|
+
"scripts": {
|
10
|
+
"start": "node lib/src/index.js",
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
12
|
+
"prebuild": "rimraf ./lib",
|
13
|
+
"build": "tsc",
|
14
|
+
"postbuild": "ncp ./src/ ./lib/src/ \"--filter=^(?!.*\\.ts$).*$\"",
|
15
|
+
"format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"",
|
16
|
+
"lint": "tslint -p tsconfig.json"
|
17
|
+
},
|
18
|
+
"repository": {
|
19
|
+
"type": "git",
|
20
|
+
"url": "git+https://github.com/ryanhex53/gpt-po.git"
|
21
|
+
},
|
22
|
+
"author": "Ryan",
|
23
|
+
"license": "MIT",
|
24
|
+
"bugs": {
|
25
|
+
"url": "https://github.com/ryanhex53/gpt-po/issues"
|
26
|
+
},
|
27
|
+
"files": [
|
28
|
+
"lib/**/*"
|
29
|
+
],
|
30
|
+
"homepage": "https://github.com/ryanhex53/gpt-po#readme",
|
31
|
+
"keywords": [
|
32
|
+
"gettext",
|
33
|
+
"po",
|
34
|
+
"pot",
|
35
|
+
"chatgpt",
|
36
|
+
"openai"
|
37
|
+
],
|
38
|
+
"devDependencies": {
|
39
|
+
"@types/gettext-parser": "^4.0.2",
|
40
|
+
"@types/jest": "^29.5.1",
|
41
|
+
"jest": "^29.5.0",
|
42
|
+
"ncp": "^2.0.0",
|
43
|
+
"prettier": "^3.0.0-alpha.7-for-vscode",
|
44
|
+
"rimraf": "^5.0.0",
|
45
|
+
"ts-jest": "^29.1.0",
|
46
|
+
"tslint": "^6.1.3",
|
47
|
+
"tslint-config-prettier": "^1.18.0",
|
48
|
+
"typescript": "^5.0.4"
|
49
|
+
},
|
50
|
+
"dependencies": {
|
51
|
+
"commander": "^10.0.1",
|
52
|
+
"gettext-parser": "^6.0.0",
|
53
|
+
"openai": "^3.2.1"
|
54
|
+
},
|
55
|
+
"engines": {
|
56
|
+
"node": ">=12.0.0"
|
57
|
+
}
|
58
|
+
}
|
package/lib/src/index.js
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
"use strict";
|
3
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
4
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
5
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
6
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
7
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
8
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
9
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
10
|
+
});
|
11
|
+
};
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
13
|
+
const commander_1 = require("commander");
|
14
|
+
const os_1 = require("os");
|
15
|
+
const path_1 = require("path");
|
16
|
+
const pkg = require("../package.json");
|
17
|
+
const sync_1 = require("./sync");
|
18
|
+
const translate_1 = require("./translate");
|
19
|
+
const utils_1 = require("./utils");
|
20
|
+
const program = new commander_1.Command();
|
21
|
+
program.name(pkg.name).version(pkg.version).description(pkg.description);
|
22
|
+
program
|
23
|
+
.command("translate", { isDefault: true })
|
24
|
+
.description("translate po file (default command)")
|
25
|
+
.addOption(new commander_1.Option("-k, --key <key>", "openai api key").env("OPENAI_API_KEY"))
|
26
|
+
.addOption(new commander_1.Option("--host <host>", "openai api host").env("OPENAI_API_HOST"))
|
27
|
+
.addOption(new commander_1.Option("--model <model>", "openai model")
|
28
|
+
.default("gpt-3.5-turbo")
|
29
|
+
.choices([
|
30
|
+
"gpt-4",
|
31
|
+
"gpt-4-0314",
|
32
|
+
"gpt-4-32k",
|
33
|
+
"gpt-4-32k-0314",
|
34
|
+
"gpt-3.5-turbo",
|
35
|
+
"gpt-3.5-turbo-0301",
|
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* () {
|
42
|
+
if (host) {
|
43
|
+
process.env.OPENAI_API_HOST = host;
|
44
|
+
}
|
45
|
+
if (key) {
|
46
|
+
process.env.OPENAI_API_KEY = key;
|
47
|
+
}
|
48
|
+
yield (0, translate_1.translatePo)(model, po, source, lang, output);
|
49
|
+
}));
|
50
|
+
program
|
51
|
+
.command("sync")
|
52
|
+
.description("update po from pot file")
|
53
|
+
.requiredOption("--po <file>", "po file path")
|
54
|
+
.requiredOption("--pot <file>", "pot file path")
|
55
|
+
.action(({ po, pot }) => __awaiter(void 0, void 0, void 0, function* () {
|
56
|
+
yield (0, sync_1.sync)(po, pot);
|
57
|
+
}));
|
58
|
+
// program command `systemprompt` with help text `open/edit system prompt`
|
59
|
+
program
|
60
|
+
.command("systemprompt")
|
61
|
+
.description("open/edit system prompt")
|
62
|
+
.action(() => {
|
63
|
+
// open `systemprompt.txt` file by system text default editor
|
64
|
+
const copyFile = __dirname + "/systemprompt.txt";
|
65
|
+
// user home path
|
66
|
+
const promptHome = (0, path_1.join)((0, os_1.homedir)(), "systemprompt.txt");
|
67
|
+
(0, utils_1.copyFileIfNotExists)(promptHome, copyFile);
|
68
|
+
(0, utils_1.openFileByDefault)(promptHome);
|
69
|
+
});
|
70
|
+
// program command `userdict` with help text `open/edit user dictionary`
|
71
|
+
program
|
72
|
+
.command("userdict")
|
73
|
+
.description("open/edit user dictionary")
|
74
|
+
.action(() => {
|
75
|
+
// open `dictionary.json` file by system text default editor
|
76
|
+
const copyFile = __dirname + "/dictionary.json";
|
77
|
+
// user home path
|
78
|
+
const dictHome = (0, path_1.join)((0, os_1.homedir)(), "dictionary.json");
|
79
|
+
(0, utils_1.copyFileIfNotExists)(dictHome, copyFile);
|
80
|
+
(0, utils_1.openFileByDefault)(dictHome);
|
81
|
+
});
|
82
|
+
program.parse(process.argv);
|
83
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare function sync(po: string, pot: string): Promise<void>;
|
package/lib/src/sync.js
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9
|
+
});
|
10
|
+
};
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
12
|
+
exports.sync = void 0;
|
13
|
+
const utils_1 = require("./utils");
|
14
|
+
function sync(po, pot) {
|
15
|
+
return __awaiter(this, void 0, void 0, function* () {
|
16
|
+
const potrans = yield (0, utils_1.parsePo)(po);
|
17
|
+
const potrans2 = yield (0, utils_1.parsePo)(pot);
|
18
|
+
for (const [ctx, entries] of Object.entries(potrans2.translations)) {
|
19
|
+
// copy msgstr from potrans to potrans2
|
20
|
+
for (const [msgid, _] of Object.entries(entries)) {
|
21
|
+
if (potrans.translations[ctx] &&
|
22
|
+
potrans.translations[ctx][msgid] &&
|
23
|
+
potrans.translations[ctx][msgid].msgstr[0]) {
|
24
|
+
potrans2.translations[ctx][msgid] = potrans.translations[ctx][msgid];
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
potrans.translations = potrans2.translations;
|
29
|
+
yield (0, utils_1.compilePo)(potrans, po);
|
30
|
+
});
|
31
|
+
}
|
32
|
+
exports.sync = sync;
|
33
|
+
//# sourceMappingURL=sync.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/sync.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,mCAA6C;AAE7C,SAAsB,IAAI,CAAC,EAAU,EAAE,GAAW;;QAChD,MAAM,OAAO,GAAG,MAAM,IAAA,eAAO,EAAC,EAAE,CAAC,CAAC;QAClC,MAAM,QAAQ,GAAG,MAAM,IAAA,eAAO,EAAC,GAAG,CAAC,CAAC;QAEpC,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE;YAClE,uCAAuC;YACvC,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;gBAChD,IACE,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC;oBACzB,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;oBAChC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAC1C;oBACA,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;iBACtE;aACF;SACF;QACD,OAAO,CAAC,YAAY,GAAG,QAAQ,CAAC,YAAY,CAAC;QAC7C,MAAM,IAAA,iBAAS,EAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC/B,CAAC;CAAA;AAlBD,oBAkBC"}
|
@@ -0,0 +1 @@
|
|
1
|
+
You are a translation expert, follow the user's instructions carefully, translate the text in a colloquial, professional and elegant manner without sounding like a machine translation. Remember to only translate the text and not further interpret it.
|
@@ -0,0 +1,4 @@
|
|
1
|
+
import { OpenAIApi } from "openai";
|
2
|
+
export declare function init(force?: boolean): OpenAIApi;
|
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>;
|
@@ -0,0 +1,134 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9
|
+
});
|
10
|
+
};
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
12
|
+
exports.translatePo = exports.translate = exports.init = void 0;
|
13
|
+
const fs = require("fs");
|
14
|
+
const openai_1 = require("openai");
|
15
|
+
const os_1 = require("os");
|
16
|
+
const path_1 = require("path");
|
17
|
+
const pkg = require("../package.json");
|
18
|
+
const utils_1 = require("./utils");
|
19
|
+
let _openai;
|
20
|
+
let _systemprompt;
|
21
|
+
let _userdict;
|
22
|
+
function init(force) {
|
23
|
+
if (!_openai || force) {
|
24
|
+
const configuration = new openai_1.Configuration({
|
25
|
+
apiKey: process.env.OPENAI_API_KEY,
|
26
|
+
});
|
27
|
+
if (process.env.OPENAI_API_HOST) {
|
28
|
+
configuration.basePath = process.env.OPENAI_API_HOST.replace(/\/+$/, "") + "/v1";
|
29
|
+
}
|
30
|
+
_openai = new openai_1.OpenAIApi(configuration);
|
31
|
+
}
|
32
|
+
// load systemprompt.txt from homedir
|
33
|
+
if (!_systemprompt || force) {
|
34
|
+
const systemprompt = (0, path_1.join)((0, os_1.homedir)(), "systemprompt.txt");
|
35
|
+
(0, utils_1.copyFileIfNotExists)(systemprompt, (0, path_1.join)(__dirname, "systemprompt.txt"));
|
36
|
+
_systemprompt = fs.readFileSync(systemprompt, "utf-8");
|
37
|
+
}
|
38
|
+
// load dictionary.json from homedir
|
39
|
+
if (!_userdict || force) {
|
40
|
+
const userdict = (0, path_1.join)((0, os_1.homedir)(), "dictionary.json");
|
41
|
+
(0, utils_1.copyFileIfNotExists)(userdict, (0, path_1.join)(__dirname, "dictionary.json"));
|
42
|
+
_userdict = JSON.parse(fs.readFileSync(userdict, "utf-8"));
|
43
|
+
}
|
44
|
+
return _openai;
|
45
|
+
}
|
46
|
+
exports.init = init;
|
47
|
+
function translate(text, src, lang, model = "gpt-3.5-turbo") {
|
48
|
+
const openai = init();
|
49
|
+
const dicts = Object.entries(_userdict)
|
50
|
+
.map(([k, v]) => [
|
51
|
+
{ role: "user", content: k },
|
52
|
+
{ role: "assistant", content: v },
|
53
|
+
])
|
54
|
+
.flat();
|
55
|
+
return openai.createChatCompletion({
|
56
|
+
model,
|
57
|
+
temperature: 0.5,
|
58
|
+
n: 1,
|
59
|
+
messages: [
|
60
|
+
{ role: "system", content: _systemprompt },
|
61
|
+
{
|
62
|
+
role: "user",
|
63
|
+
content: `Translate incoming ${src} content into ${lang}, only the translated content can be returned, don't ask question.`,
|
64
|
+
},
|
65
|
+
{
|
66
|
+
role: "assistant",
|
67
|
+
content: "Sure, Please send me the content that needs to be translated.",
|
68
|
+
},
|
69
|
+
// add userdict here
|
70
|
+
...dicts,
|
71
|
+
{ role: "user", content: text },
|
72
|
+
],
|
73
|
+
}, {
|
74
|
+
timeout: 20000,
|
75
|
+
});
|
76
|
+
}
|
77
|
+
exports.translate = translate;
|
78
|
+
function translatePo(model = "gpt-3.5-turbo", po, source, lang, output) {
|
79
|
+
var _a;
|
80
|
+
return __awaiter(this, void 0, void 0, function* () {
|
81
|
+
const potrans = yield (0, utils_1.parsePo)(po);
|
82
|
+
const list = [];
|
83
|
+
for (const [ctx, entries] of Object.entries(potrans.translations)) {
|
84
|
+
for (const [msgid, trans] of Object.entries(entries)) {
|
85
|
+
if (!trans.msgstr[0]) {
|
86
|
+
list.push(trans);
|
87
|
+
}
|
88
|
+
}
|
89
|
+
}
|
90
|
+
if (list.length == 0) {
|
91
|
+
console.log("nothing needs translate");
|
92
|
+
return;
|
93
|
+
}
|
94
|
+
let err429 = false;
|
95
|
+
let modified = false;
|
96
|
+
for (let i = 0; i < list.length; i++) {
|
97
|
+
if (i == 0)
|
98
|
+
(0, utils_1.printProgress)(i, list.length);
|
99
|
+
if (err429) {
|
100
|
+
// sleep for 20 seconds.
|
101
|
+
yield new Promise((resolve) => setTimeout(resolve, 20000));
|
102
|
+
}
|
103
|
+
const trans = list[i];
|
104
|
+
try {
|
105
|
+
const res = yield translate(trans.msgid, source, lang, model);
|
106
|
+
trans.msgstr[0] = ((_a = res.data.choices[0].message) === null || _a === void 0 ? void 0 : _a.content) || trans.msgstr[0];
|
107
|
+
modified = true;
|
108
|
+
(0, utils_1.printProgress)(i + 1, list.length);
|
109
|
+
}
|
110
|
+
catch (error) {
|
111
|
+
if (error.response) {
|
112
|
+
if (error.response.status == 429) {
|
113
|
+
// caused by rate limit exceeded, should sleep for 20 seconds.
|
114
|
+
err429 = true;
|
115
|
+
--i;
|
116
|
+
}
|
117
|
+
else {
|
118
|
+
console.error(error.response.status);
|
119
|
+
// console.log(error.response.data);
|
120
|
+
}
|
121
|
+
}
|
122
|
+
else {
|
123
|
+
console.error(error.message);
|
124
|
+
}
|
125
|
+
}
|
126
|
+
}
|
127
|
+
if (modified) {
|
128
|
+
potrans.headers["Last-Translator"] = `gpt-po v${pkg.version}`;
|
129
|
+
yield (0, utils_1.compilePo)(potrans, output || po);
|
130
|
+
}
|
131
|
+
});
|
132
|
+
}
|
133
|
+
exports.translatePo = translatePo;
|
134
|
+
//# sourceMappingURL=translate.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/translate.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
import { GetTextTranslations } from "gettext-parser";
|
2
|
+
export declare function copyFileIfNotExists(file: string, copyFile: string): void;
|
3
|
+
export declare function openFileByDefault(filePath: string): void;
|
4
|
+
export declare function parsePo(poFile: string, defaultCharset?: string): Promise<GetTextTranslations>;
|
5
|
+
export declare function compilePo(data: GetTextTranslations, poFile: string): Promise<void>;
|
6
|
+
export declare function printProgress(progress: number, total: number, extra?: string): void;
|
package/lib/src/utils.js
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
"use strict";
|
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");
|
5
|
+
const child_process_1 = require("child_process");
|
6
|
+
const gettext_parser_1 = require("gettext-parser");
|
7
|
+
function copyFileIfNotExists(file, copyFile) {
|
8
|
+
// check if file exists else create it
|
9
|
+
try {
|
10
|
+
fs.accessSync(file, fs.constants.F_OK);
|
11
|
+
// check if the file is empty else copy the file
|
12
|
+
fs.statSync(file).size === 0 && fs.copyFileSync(copyFile, file);
|
13
|
+
}
|
14
|
+
catch (err) {
|
15
|
+
fs.copyFileSync(copyFile, file);
|
16
|
+
}
|
17
|
+
}
|
18
|
+
exports.copyFileIfNotExists = copyFileIfNotExists;
|
19
|
+
function openFileByDefault(filePath) {
|
20
|
+
// Use the 'open' command on macOS or 'start' command on Windows to open the file with the default system editor
|
21
|
+
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
22
|
+
// Spawn a new process for the default editor and pass the file name as an argument
|
23
|
+
(0, child_process_1.spawn)(command, [filePath], { shell: true });
|
24
|
+
}
|
25
|
+
exports.openFileByDefault = openFileByDefault;
|
26
|
+
function parsePo(poFile, defaultCharset) {
|
27
|
+
// read poFile as buffer, then parse it
|
28
|
+
return new Promise((resolve, reject) => {
|
29
|
+
fs.readFile(poFile, (err, buffer) => {
|
30
|
+
if (err)
|
31
|
+
reject(err);
|
32
|
+
var result = gettext_parser_1.po.parse(buffer, defaultCharset !== null && defaultCharset !== void 0 ? defaultCharset : "utf-8");
|
33
|
+
resolve(result);
|
34
|
+
});
|
35
|
+
});
|
36
|
+
}
|
37
|
+
exports.parsePo = parsePo;
|
38
|
+
function compilePo(data, poFile) {
|
39
|
+
const buffer = gettext_parser_1.po.compile(data);
|
40
|
+
return new Promise((resolve, reject) => {
|
41
|
+
fs.writeFile(poFile, buffer, (err) => {
|
42
|
+
if (err)
|
43
|
+
reject(err);
|
44
|
+
resolve();
|
45
|
+
});
|
46
|
+
});
|
47
|
+
}
|
48
|
+
exports.compilePo = compilePo;
|
49
|
+
function printProgress(progress, total, extra) {
|
50
|
+
const percent = Math.floor((progress / total) * 100);
|
51
|
+
const bar = Array(Math.floor(percent / 5))
|
52
|
+
.fill("█")
|
53
|
+
.join("");
|
54
|
+
const dots = Array(20 - Math.floor(percent / 5))
|
55
|
+
.fill("░")
|
56
|
+
.join("");
|
57
|
+
process.stdout.write(`\r${bar}${dots} ${percent}% ${extra || ""}`);
|
58
|
+
}
|
59
|
+
exports.printProgress = printProgress;
|
60
|
+
//# sourceMappingURL=utils.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":";;;AAAA,yBAAyB;AAEzB,iDAAsC;AACtC,mDAAyD;AAEzD,SAAgB,mBAAmB,CAAC,IAAY,EAAE,QAAgB;IAChE,sCAAsC;IACtC,IAAI;QACF,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACvC,gDAAgD;QAChD,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;KACjE;IAAC,OAAO,GAAG,EAAE;QACZ,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;KACjC;AACH,CAAC;AATD,kDASC;AAED,SAAgB,iBAAiB,CAAC,QAAgB;IAChD,gHAAgH;IAChH,MAAM,OAAO,GACX,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;IAC/F,mFAAmF;IACnF,IAAA,qBAAK,EAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAC9C,CAAC;AAND,8CAMC;AAED,SAAgB,OAAO,CAAC,MAAc,EAAE,cAAuB;IAC7D,uCAAuC;IACvC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;YAClC,IAAI,GAAG;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAC;YACrB,IAAI,MAAM,GAAG,mBAAE,CAAC,KAAK,CAAC,MAAM,EAAE,cAAc,aAAd,cAAc,cAAd,cAAc,GAAI,OAAO,CAAC,CAAC;YACzD,OAAO,CAAC,MAAM,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AATD,0BASC;AAED,SAAgB,SAAS,CAAC,IAAyB,EAAE,MAAc;IACjE,MAAM,MAAM,GAAG,mBAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;YACnC,IAAI,GAAG;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAC;YACrB,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AARD,8BAQC;AAED,SAAgB,aAAa,CAAC,QAAgB,EAAE,KAAa,EAAE,KAAc;IAC3E,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;IACrD,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;SACvC,IAAI,CAAC,GAAG,CAAC;SACT,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,MAAM,IAAI,GAAG,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;SAC7C,IAAI,CAAC,GAAG,CAAC;SACT,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,IAAI,IAAI,OAAO,KAAK,KAAK,IAAI,EAAE,EAAE,CAAC,CAAC;AACrE,CAAC;AATD,sCASC"}
|
package/package.json
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
{
|
2
|
+
"name": "gpt-po",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"description": "command tool for translate po files by gpt",
|
5
|
+
"main": "lib/src/index.js",
|
6
|
+
"bin": {
|
7
|
+
"gpt-po": "lib/src/index.js"
|
8
|
+
},
|
9
|
+
"scripts": {
|
10
|
+
"start": "node lib/src/index.js",
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
12
|
+
"prebuild": "rimraf ./lib",
|
13
|
+
"build": "tsc",
|
14
|
+
"postbuild": "ncp ./src/ ./lib/src/ \"--filter=^(?!.*\\.ts$).*$\"",
|
15
|
+
"format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"",
|
16
|
+
"lint": "tslint -p tsconfig.json"
|
17
|
+
},
|
18
|
+
"repository": {
|
19
|
+
"type": "git",
|
20
|
+
"url": "git+https://github.com/ryanhex53/gpt-po.git"
|
21
|
+
},
|
22
|
+
"author": "Ryan",
|
23
|
+
"license": "MIT",
|
24
|
+
"bugs": {
|
25
|
+
"url": "https://github.com/ryanhex53/gpt-po/issues"
|
26
|
+
},
|
27
|
+
"files": [
|
28
|
+
"lib/**/*"
|
29
|
+
],
|
30
|
+
"homepage": "https://github.com/ryanhex53/gpt-po#readme",
|
31
|
+
"keywords": [
|
32
|
+
"gettext",
|
33
|
+
"po",
|
34
|
+
"pot",
|
35
|
+
"chatgpt",
|
36
|
+
"openai"
|
37
|
+
],
|
38
|
+
"devDependencies": {
|
39
|
+
"@types/gettext-parser": "^4.0.2",
|
40
|
+
"@types/jest": "^29.5.1",
|
41
|
+
"jest": "^29.5.0",
|
42
|
+
"ncp": "^2.0.0",
|
43
|
+
"prettier": "^3.0.0-alpha.7-for-vscode",
|
44
|
+
"rimraf": "^5.0.0",
|
45
|
+
"ts-jest": "^29.1.0",
|
46
|
+
"tslint": "^6.1.3",
|
47
|
+
"tslint-config-prettier": "^1.18.0",
|
48
|
+
"typescript": "^5.0.4"
|
49
|
+
},
|
50
|
+
"dependencies": {
|
51
|
+
"commander": "^10.0.1",
|
52
|
+
"gettext-parser": "^6.0.0",
|
53
|
+
"openai": "^3.2.1"
|
54
|
+
},
|
55
|
+
"engines": {
|
56
|
+
"node": ">=12.0.0"
|
57
|
+
}
|
58
|
+
}
|