gpt-po 1.0.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 +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
|
+
}
|