Как автоматизировать переводы во Frontend приложении

от автора

В текущем мире очень многие сайты имеют поддержку многих языков, в большинстве случаев это происходит с помощью 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.

Наслаждайтесь 🙂

Если статья показалась вам интересной, то у меня есть Тг-канал, где я пишу про новые технологии во фронте, делюсь хорошими книжками и интересными статьями других авторов.


ссылка на оригинал статьи https://habr.com/ru/articles/751366/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *