feat: add translation script

This commit is contained in:
Denis Gukov 2024-09-29 12:32:44 +05:00
parent 0a92e7c571
commit 2580c0b2bf
5 changed files with 2464 additions and 94 deletions

1
.gitignore vendored
View File

@ -30,3 +30,4 @@ node_modules/
.vscode .vscode
__debug_bin* __debug_bin*
.task/ .task/
/web/.env

61
web/gulp-gpt-translate.js Normal file
View File

@ -0,0 +1,61 @@
const through = require('through2');
const PluginError = require('plugin-error');
const { OpenAI } = require('openai');
const PLUGIN_NAME = 'gulp-gpt-translate';
function gptTranslate(options) {
if (!options || !options.apiKey) {
throw new PluginError(PLUGIN_NAME, 'An OpenAI API key is required.');
}
if (!options.targetLanguage) {
throw new PluginError(PLUGIN_NAME, 'A target language must be specified.');
}
const openai = new OpenAI();
return through.obj(function (file, enc, cb) {
const self = this;
if (file.isNull()) {
return cb(null, file); // Pass along if no contents
}
if (file.isStream()) {
self.emit('error', new PluginError(PLUGIN_NAME, 'Streaming not supported.'));
return cb();
}
(async () => {
try {
const content = file.contents.toString(enc);
console.log(`****** translating file ${file.path} ******`);
const response = await openai.chat.completions.create({
model: options.model || 'gpt-4o-mini',
temperature: 0,
messages: [
{
role: 'system',
content: `You are a helpful assistant that translates text to ${options.targetLanguage}. `,
},
...(options.messages || []).map((m) => ({ role: 'user', content: m })),
{ role: 'user', content },
],
});
file.contents = Buffer.from(response.choices[0].message.content, enc);
self.push(file);
cb();
} catch (err) {
self.emit('error', new PluginError(PLUGIN_NAME, err.message));
cb(err);
}
})();
});
}
module.exports = gptTranslate;

35
web/gulpfile.js Normal file
View File

@ -0,0 +1,35 @@
const { src, dest } = require('gulp');
const rename = require('gulp-rename');
require('dotenv').config();
const gptTranslate = require('./gulp-gpt-translate');
const LANG_NAMES = {
en: 'English',
ru: 'Russian',
es: 'Spanish',
fr: 'French',
de: 'German',
it: 'Italian',
ja: 'Japanese',
ko: 'Korean',
pt: 'Portuguese',
zh: 'Chinese',
};
function tr() {
return Object.keys(LANG_NAMES).filter((lang) => lang !== 'en').map((lang) => src('src/lang/en.js')
.pipe(gptTranslate({
apiKey: process.env.OPENAI_API_KEY,
targetLanguage: LANG_NAMES[lang],
messages: [
'This content contains Ansible Semaphore strings.',
'Do not wrap result to any formatting tags. Result must be valid json file.',
],
}))
.pipe(rename({ basename: lang }))
.pipe(dest('src/lang')));
}
module.exports = {
tr,
};

2454
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -32,17 +32,24 @@
"@vue/test-utils": "^1.3.0", "@vue/test-utils": "^1.3.0",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",
"chai": "^4.3.6", "chai": "^4.3.6",
"dotenv": "^16.4.5",
"eslint": "^7.32.0", "eslint": "^7.32.0",
"eslint-plugin-import": "^2.26.0", "eslint-plugin-import": "^2.26.0",
"eslint-plugin-vue": "^9.1.1", "eslint-plugin-vue": "^9.1.1",
"eslint-plugin-vuejs-accessibility": "^1.2.0", "eslint-plugin-vuejs-accessibility": "^1.2.0",
"glob-parent": ">=5.1.2", "glob-parent": ">=5.1.2",
"gulp": "^5.0.0",
"gulp-cli": "^3.0.0",
"gulp-rename": "^2.0.0",
"nanoid": ">=3.1.31", "nanoid": ">=3.1.31",
"nyc": "^15.1.0", "nyc": "^15.1.0",
"openai": "^4.65.0",
"plugin-error": "^2.0.1",
"sass": "~1.32.12", "sass": "~1.32.12",
"sass-loader": "^13.0.0", "sass-loader": "^13.0.0",
"stylus": "^0.54.8", "stylus": "^0.54.8",
"stylus-loader": "^3.0.2", "stylus-loader": "^3.0.2",
"through2": "^4.0.2",
"vue-cli-plugin-vuetify": "~2.0.7", "vue-cli-plugin-vuetify": "~2.0.7",
"vue-template-compiler": "^2.6.14", "vue-template-compiler": "^2.6.14",
"vuetify-loader": "^1.8.0" "vuetify-loader": "^1.8.0"