Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 72 additions & 26 deletions shared-helpers/src/scripts/get-machine-translations.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
/* eslint-disable @typescript-eslint/no-var-requires, import/no-unresolved */

// Takes in a CSV file with two columns (t_key,t_value) with the key being the translation file key and the value being the associated English string, and prints out in the JSON translation file format the "key": "translated string"
// CSV format:
// t_key,t_value
// "key.here","Translation here"
//
// example from within this directory, first argument is one of LanguagesEnum and second argument is the formatted CSV filename with keys and english strings, piped to a new file: `ts-node get-machine-translations es english-keys.csv > any-filename-here.json`
import fs from "node:fs"
import { parse } from "csv-parse/sync"

// Finds missing translations and automatically translates them using Google Translate API
// Prints out translations in the JSON translation file format: "key": "translated string"
// You will need to add the environment variables for Google Translate API access from the api env file, but ensure you do not commit them!
// Example: `ts-node get-machine-translations.ts > any-filename-here.json`
import { Translate } from "@google-cloud/translate/build/src/v2"

async function main(argv: string[]) {
async function main() {
enum LanguagesEnum {
"en" = "en",
"es" = "es",
Expand All @@ -22,9 +16,10 @@ async function main(argv: string[]) {
"bn" = "bn",
}

const GOOGLE_API_EMAIL = "SECRET_VALUE"
const GOOGLE_API_ID = "SECRET_VALUE"
const GOOGLE_API_KEY = "SECRET_VALUE"
// DO NOT COMMIT THESE VALUES! REMOVE BEFORE COMMITTING
const GOOGLE_API_EMAIL = ``
const GOOGLE_API_ID = ``
const GOOGLE_API_KEY = ``

const makeTranslateService = () => {
return new Translate({
Expand All @@ -40,26 +35,77 @@ async function main(argv: string[]) {
return await makeTranslateService().translate(values, {
from: LanguagesEnum.en,
to: language,
format: "html",
})
}

type TranslationsType = {
[key: string]: string
}

const findMissingStrings = (
baseTranslations: TranslationsType,
checkedTranslations: TranslationsType
) => {
const baseKeys = Object.keys(baseTranslations)
const checkedKeys = Object.keys(checkedTranslations)
const missingKeys: string[] = []
baseKeys.forEach((key) => {
if (checkedKeys.indexOf(key) < 0) {
missingKeys.push(key)
}
})
return missingKeys
}

const [language, englishStringsCsv] = argv.slice(2)
// Load translations
const englishTranslations = require("../locales/general.json")
const spanishTranslations = require("../locales/es.json")
const chineseTranslations = require("../locales/zh.json")
const vietnameseTranslations = require("../locales/vi.json")
const tagalogTranslations = require("../locales/tl.json")
const arabicTranslations = require("../locales/ar.json")
const bengaliTranslations = require("../locales/bn.json")

const allTranslations = [
{ translationKeys: spanishTranslations, language: "Spanish", code: LanguagesEnum.es },
{ translationKeys: chineseTranslations, language: "Chinese", code: LanguagesEnum.zh },
{ translationKeys: vietnameseTranslations, language: "Vietnamese", code: LanguagesEnum.vi },
{ translationKeys: tagalogTranslations, language: "Tagalog", code: LanguagesEnum.tl },
{ translationKeys: arabicTranslations, language: "Arabic", code: LanguagesEnum.ar },
{ translationKeys: bengaliTranslations, language: "Bengali", code: LanguagesEnum.bn },
]

console.log(
"Note that Google Translate does not preserve markdown well, and you may need to adjust some translations manually to add back in new lines and other missing formatting if there is any markdown.\n"
)
console.log(
"You can paste these lines directly into each translation file, and then be sure to sort ascending! In VSCode, you can Command + Shift + P --> Sort Ascending.\n"
)

const csvFile = fs.readFileSync(englishStringsCsv)
// Process each language
for (const foreignTranslations of allTranslations) {
console.log("\n--------------------")
console.log(`${foreignTranslations.language} Missing Translations:`)
console.log("--------------------")

const csvData = parse(csvFile, {
columns: true,
skip_empty_lines: true,
})
const missingKeys = findMissingStrings(englishTranslations, foreignTranslations.translationKeys)

for (const row of csvData) {
const tKey = row["t_key"].trim()
const tValue = row["t_value"].trim()
const translatedValue = await fetch([tValue], language as LanguagesEnum)
console.log(`"${tKey}": "${translatedValue[0][0]}",`)
if (missingKeys.length === 0) {
console.log(`No missing translations for ${foreignTranslations.language}`)
continue
}

const englishStrings = missingKeys.map((key) => englishTranslations[key])
const translatedValues = await fetch(englishStrings, foreignTranslations.code)

missingKeys.forEach((key, index) => {
const translatedString = translatedValues[0][index]
console.log(`"${key}": "${translatedString}",`)
})
}
}

void main(process.argv)
void main()

export {}
Loading