2024-04-24 23:01:20 +01:00
|
|
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
|
|
|
|
|
|
|
|
const axios = require('axios');
|
|
|
|
|
const dotenv = require('dotenv');
|
|
|
|
|
const fs = require('fs');
|
|
|
|
|
const path = require('path');
|
|
|
|
|
const keys = require('all-object-keys');
|
|
|
|
|
const jessy = require('jessy');
|
|
|
|
|
const set = require('lodash/set');
|
|
|
|
|
|
|
|
|
|
const englishTranslations = require('../src/lib/utils/translations/en.json');
|
|
|
|
|
|
|
|
|
|
// Load env variables
|
|
|
|
|
dotenv.config();
|
|
|
|
|
|
|
|
|
|
const SCRIPT_WAIT_TIME = 2000;
|
2026-03-09 11:18:22 +01:00
|
|
|
const requestedLanguages = process.argv
|
|
|
|
|
.slice(2)
|
|
|
|
|
.map((language) => language.toLowerCase())
|
|
|
|
|
.filter((language) => language && language !== '--');
|
2024-04-24 23:01:20 +01:00
|
|
|
|
|
|
|
|
// Define file paths for each language
|
|
|
|
|
const languageFiles = {
|
|
|
|
|
de: path.resolve(__dirname, '../src/lib/utils/translations/de.json'),
|
2025-08-08 04:53:38 +01:00
|
|
|
es: path.resolve(__dirname, '../src/lib/utils/translations/es.json'),
|
|
|
|
|
fr: path.resolve(__dirname, '../src/lib/utils/translations/fr.json'),
|
|
|
|
|
hi: path.resolve(__dirname, '../src/lib/utils/translations/hi.json'),
|
|
|
|
|
pl: path.resolve(__dirname, '../src/lib/utils/translations/pl.json'),
|
|
|
|
|
pt: path.resolve(__dirname, '../src/lib/utils/translations/pt.json'),
|
2024-04-26 17:54:11 +01:00
|
|
|
ru: path.resolve(__dirname, '../src/lib/utils/translations/ru.json'),
|
2025-10-13 18:07:46 +01:00
|
|
|
vi: path.resolve(__dirname, '../src/lib/utils/translations/vi.json'),
|
|
|
|
|
da: path.resolve(__dirname, '../src/lib/utils/translations/da.json')
|
2024-04-24 23:01:20 +01:00
|
|
|
};
|
|
|
|
|
|
2026-03-09 11:18:22 +01:00
|
|
|
const selectedLanguageFiles = requestedLanguages.length
|
|
|
|
|
? Object.fromEntries(Object.entries(languageFiles).filter(([language]) => requestedLanguages.includes(language)))
|
|
|
|
|
: languageFiles;
|
|
|
|
|
|
2024-04-24 23:01:20 +01:00
|
|
|
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
|
|
|
|
|
|
|
const getMissingTranslations = async (toLanguage, outputFilePath) => {
|
|
|
|
|
const englishKeys = keys(englishTranslations);
|
|
|
|
|
const targetTranslations = require(outputFilePath); // Load target language translations
|
|
|
|
|
const targetKeys = keys(targetTranslations);
|
|
|
|
|
|
|
|
|
|
const missingKeys = englishKeys.filter((key) => !targetKeys.includes(key));
|
|
|
|
|
|
|
|
|
|
const missingKeysWithDetails = {};
|
|
|
|
|
missingKeys.forEach((key) => {
|
|
|
|
|
const value = jessy(key, englishTranslations);
|
|
|
|
|
if (value !== undefined) {
|
|
|
|
|
missingKeysWithDetails[key] = value;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
console.log(`Details of missing keys in ${toLanguage.toUpperCase()}:`);
|
|
|
|
|
console.log(missingKeysWithDetails, 'missingKeysWithDetails');
|
|
|
|
|
|
|
|
|
|
// Check if there are missing translations, if not, stop the process
|
|
|
|
|
if (!missingKeysWithDetails) {
|
2025-11-01 15:49:29 +01:00
|
|
|
console.log(`No missing translations for ${toLanguage.toUpperCase()}. Stopping translation process.`);
|
2024-04-24 23:01:20 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return missingKeysWithDetails;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const translateLanguage = async (fromLanguage, toLanguage, outputFilePath) => {
|
|
|
|
|
// Check if there are missing translations
|
|
|
|
|
const missingTranslations = await getMissingTranslations(toLanguage, outputFilePath);
|
|
|
|
|
console.log('Missing translations', missingTranslations);
|
|
|
|
|
|
|
|
|
|
if (!Object.keys(missingTranslations).length) {
|
|
|
|
|
console.log('No missing translation skip');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const targetTranslations = require(outputFilePath); // Load target language translations
|
|
|
|
|
|
|
|
|
|
const flattenedEnglish = flattenJSON(missingTranslations);
|
|
|
|
|
const jsonString = JSON.stringify(flattenedEnglish);
|
|
|
|
|
|
|
|
|
|
const encodedParams = new URLSearchParams();
|
|
|
|
|
encodedParams.set('from', fromLanguage);
|
|
|
|
|
encodedParams.set('to', toLanguage);
|
|
|
|
|
encodedParams.set('json', jsonString);
|
|
|
|
|
|
|
|
|
|
const options = {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
url: 'https://google-translate113.p.rapidapi.com/api/v1/translator/json',
|
|
|
|
|
headers: {
|
|
|
|
|
'content-type': 'application/x-www-form-urlencoded',
|
|
|
|
|
'X-RapidAPI-Key': process.env.RAPID_API_KEY,
|
|
|
|
|
'X-RapidAPI-Host': 'google-translate113.p.rapidapi.com'
|
|
|
|
|
},
|
|
|
|
|
data: encodedParams
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
console.log('Calling API');
|
|
|
|
|
const response = await axios.request(options);
|
|
|
|
|
const { trans } = response.data;
|
|
|
|
|
|
|
|
|
|
console.log('Translation gotten', trans);
|
|
|
|
|
|
|
|
|
|
if (trans) {
|
|
|
|
|
for (const key in trans) {
|
|
|
|
|
const value = trans[key];
|
|
|
|
|
set(targetTranslations, key, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fs.writeFileSync(outputFilePath, JSON.stringify(targetTranslations, null, 2));
|
|
|
|
|
console.log(`${toLanguage.toUpperCase()} translations updated successfully.`);
|
|
|
|
|
} else {
|
|
|
|
|
console.log(`Failed to update ${toLanguage.toUpperCase()} translations.`);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(`Error translating to ${toLanguage.toUpperCase()}:`, error);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Function to flatten the JSON object
|
|
|
|
|
const flattenJSON = (obj, prefix = '') => {
|
|
|
|
|
let flattened = {};
|
|
|
|
|
for (const key in obj) {
|
|
|
|
|
if (typeof obj[key] === 'object') {
|
|
|
|
|
const nested = flattenJSON(obj[key], `${prefix}${key}.`);
|
|
|
|
|
flattened = { ...flattened, ...nested };
|
|
|
|
|
} else {
|
|
|
|
|
flattened[`${prefix}${key}`] = obj[key];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return flattened;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Loop through each language and translate the English text with a delay
|
|
|
|
|
const translate = async () => {
|
2026-03-09 11:18:22 +01:00
|
|
|
if (!Object.keys(selectedLanguageFiles).length) {
|
|
|
|
|
console.error(`No matching languages for: ${requestedLanguages.join(', ')}`);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const [language, filePath] of Object.entries(selectedLanguageFiles)) {
|
2024-04-24 23:01:20 +01:00
|
|
|
console.log(`============FROM: EN================`);
|
|
|
|
|
console.log(`============TO: ${language.toUpperCase()}================`);
|
|
|
|
|
|
|
|
|
|
await wait(SCRIPT_WAIT_TIME);
|
|
|
|
|
await translateLanguage('en', language, filePath);
|
|
|
|
|
|
|
|
|
|
console.log(`============COMPLETE================\n\n`);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
translate();
|