В текущем мире очень многие сайты имеют поддержку многих языков, в большинстве случаев это происходит с помощью i18n npm пакета. Чаще всего переводы хранятся в .js, .json файлах и очень часто есть языки для которых в компании нет переводчика, либо же он не предполагался в целом, и в таком случае приходит на помощь разработчик с Google Translate. И вот однажды я столкнулся с тем, что на проекте оказалось очень много текстов и все их нужно было переводить вручную, что занимало достаточно много времени и я задумался о том, как это можно автоматизировать.
Моя идея была в том, чтобы написать функцию, в которую можно было бы передать языковой код и json объект с текстом на исходном языке, а на выходе получить переведенный json/js file. С помощью этой функции я мог бы в ci/cd Pipeline переводить все текста на проекте, в исходных текстах которых были изменения, либо же следить за текстами в рантайме и на лету переводить их.
И я нашел два относительно простых метода, для того чтобы это сделать, один из них платный, другой бесплатный.
Способ №1
Я думаю у многих в компании сейчас активно используются всякие ИИ чат-боты в духе chatgpt и тд, и у многих из них есть api, в которых вы можете получить api key и с помощью него отправлять ему запросы. В моем случае я использовал chatgpt от OpenAI и у них есть специальный npm пакет для node js - тык, с помощью которого можно взаимодействовать с chat ботом, вот и тут я подключаю эту библиотеку и отправляю запрос со следующим prompt - translate object values to ${language} ${JSON.stringify(text)}, где language - языковой код нужного вам языка(языковые коды - тык), text - наш объект с переводами.
translate.js
const { Configuration, OpenAIApi } = require('openai');
const fs = require('fs');
const configuration = new Configuration({
apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);
async function getTranslation(languageCode, text) {
try {
const result = await openai.createChatCompletion({
model: 'gpt-3.5-turbo',
messages: [{ role: 'user', content: `translate object values to ${languageCode} ${JSON.stringify(text)}` }],
});
return result.data.choices[0].message.content;
} catch (error) {
console.error(error);
return null;
}
};
getTranslation('zh', {
label: 'Article about translation',
title: 'Easy way to implement i18n',
description: 'Try to translate this description',
}).then((result) => {
fs.writeFileSync('cn.json', result);
});
module.exports = getTranslation;
Как итог мы получаем переведенный json и можем записать его в нужный нам файл.
Способ №2
Абсолютно бесплатный метод, в котором я использую другую библиотеку - тык, совершенно случайно наткнулся на эту библиотеку на GitHub и решил попробовать ее, по мне работает неплохо - она использует Google Translate. Здесь я реализую аналогичную функцию, за исключением того, что тут я не могу передать весь объект для перевода, поэтому здесь перебирается все значения в объекте и по очереди переводятся.
translate.js
const translate = require('node-google-translate-skidz');
const fs = require('fs');
async function getTranslation(languageCode, text) {
const getTranslate = async (value) => {
const t = await translate({
text: value,
source: 'en',
target: languageCode,
});
return t.translation;
};
const processObject = async (obj) => {
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
const value = obj[key];
if (typeof value === 'object') {
await processObject(value);
} else {
try {
const processedValue = value ? await getTranslate(value) : value;
obj[key] = processedValue;
} catch (error) {
console.error(error);
obj[key] = value;
}
}
}
}
};
const copy = JSON.parse(JSON.stringify(text));
await processObject(copy);
return JSON.stringify(copy, null, 2);
};
getTranslation('zh', {
label: 'Article about translation',
title: 'Easy way to implement i18n',
description: 'Try to translate this description',
}).then((result) => {
fs.writeFileSync('cn.json', result);
});
module.exports = getTranslation;
На выходе также получаем переведенный json файл.
Итого
У меня получился вот такой скрипт, в который я могу прокинуть файл откуда прочитать перевод и куда его записать, также здесь я сделал проверку на то, .json файл это или .js и написал парсер для этого:
const fs = require('fs');
const getTranslation = require('./translate.js');
// .js file имеет вид export const ${languageCode} = { ... }, соответственно для того, чтобы получить контент можно взять все в {} и с помощью eval(я знаю что eval это плохо) преобразовать это в js объект
const parseScriptFile = (filePath) => {
const fileData = fs.readFileSync(filePath, 'utf-8');
const jsonStartIndex = fileData.indexOf('{');
const jsonEndIndex = fileData.lastIndexOf('}');
const jsonObjectString = fileData.slice(jsonStartIndex, jsonEndIndex + 1);
const obj = eval(`(${jsonObjectString})`);
return obj;
};
const languageCode = 'zh';
const filePath = './en.js';
const destinationFilePath = './zh.js';
// Проверяю .js это файл или .json и по разному их обрабатываю
const text = filePath.includes('.json') ? require(filePath) : parseScriptFile(filePath);
getTranslation(languageCode, text).then((res) => {
if (filePath.includes('.json')) {
fs.writeFileSync(destinationFilePath, JSON.stringify(res, null, 2));
} else {
fs.writeFileSync(destinationFilePath, `export const ${languageCode} = ${JSON.stringify(res, null, 2)}`);
}
});
Далее вы можете пропатчить эти скрипты в зависимости от ваших потребностей и получить автоматизированные и удобные переводы во Frontend.
Наслаждайтесь :)
Если статья показалась вам интересной, то у меня есть Тг-канал, где я пишу про новые технологии во фронте, делюсь хорошими книжками и интересными статьями других авторов.
Комментарии (6)
ingumsky
31.07.2023 09:46+1Такой способ подойдёт для домашней странички, но всерьёз рассчитывать на то, что с его помощью вы сможете локализовать свой фронтенд/сервис на разные языки, — очень наивно. Это я вам как человек, который десять лет работает в локализации, скажу.
Ну и, разумеется, проверка в духе — «я перевёл это с помощью того же сервиса обратно и получилось то же самое» — это отсутствие проверки. Не говоря уж о том, что в вашем случае даже такая «проверка» даёт результат в «±60% случаев».Dragonek Автор
31.07.2023 09:46Мне кажется этот способ неплох для MVP или стартапов поначалу, потому что не всегда есть возможность нанять переводчика, а иногда очень хочется начать выходить на какой-то рынок и индексироваться, пусть и не с идеально переведенным продуктом.
Согласен, что проверка не является объективной, но к сожалению, оценить как-либо по-другому довольно трудно и не уверен, что возможно)
interhin
31.07.2023 09:46Тогда уж легче не морочиться с этим и просто автоматический перевод в браузере использовать)
saifutdinov_a
31.07.2023 09:46В некоторых случаях важно переводить фразы в контексте, потому что, например с русского языка *загрузить" на английский перевести и как "Upload" и как "Download". Интересно, как оба способа справляются с "двойными смыслами"?
Vorchun
Автоматизировали - это хорошо, способов много разных. А как с качеством? Оцениили / сравнили результат "на адекватность" в первом (ИИ) и втором (онлайн переводчик) случаях?
Dragonek Автор
Я сравнивал все это с Google Translate и при переводе в обратную сторону он выдает то, что и должно быть + примерно в 60% случаев текст переводился точно также как в Google Translate в браузере, применимо для обоих случаев.