Files
classroomio/apps/dashboard/scripts/translate.cjs
T
Rotimi Best b96d91cd7c feat: setup drizzle (#594)
* chore: migration to SvelteKit 2

* stage 1: migrate to svelte 5 and fix rerendering issues

* stage 2: fix more $: reactivity across dashboard

* fix merge conflicts

* chore: migrate code in main to svelte 5

* chore: update preventDefault

* chore: simplify tsconfig and remove unused mobileMenuRef in MobileMenu.svelte

* chore: enforce .ts across dashboard

* rename from classroomio-com to website

* stage-3: Replace carbon icon svelte with lucide icon

* update lock file

* chore: finish icon replacement

* fix: settings and setup page multiple rerender

* stage 3: More icon and rerendering fixes

* feat: setup drizzle and better auth

* fix: onboarding validation error showing translation key #586 (#593)

* fix: onboarding validation error showing translation key #586

* fix: remove debug log for profile update errors

* chore: add a clean command

* fix: remove message from email verification response
2025-11-01 15:49:29 +01:00

142 lines
4.7 KiB
JavaScript

/* 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;
// Define file paths for each language
const languageFiles = {
de: path.resolve(__dirname, '../src/lib/utils/translations/de.json'),
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'),
ru: path.resolve(__dirname, '../src/lib/utils/translations/ru.json'),
vi: path.resolve(__dirname, '../src/lib/utils/translations/vi.json'),
da: path.resolve(__dirname, '../src/lib/utils/translations/da.json')
};
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) {
console.log(`No missing translations for ${toLanguage.toUpperCase()}. Stopping translation process.`);
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 () => {
for (const [language, filePath] of Object.entries(languageFiles)) {
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();