Stashed / app / localization / translateMissing.js
translateMissing.js
Raw
const fs = require("fs");
const {
  readdirSync,
  statSync
} = require("fs");
const {
  join
} = require("path")
const {
  Translate
} = require("@google-cloud/translate").v2;

// READ THIS NOTICE
/*
  In order to run this file, you must do the following steps:

  1. Select or create a Cloud Platform project
  2. Enable billing for your project
  3. Enable the Cloud Translation API
  4. Set up authentication with a service account [so you can access the API from your local workstation]
  (These steps are found with more details here: https://www.npmjs.com/package/@google-cloud/translate)

  Once this is done, update 'projectId' below with your GCP project id, and remove the return statement below this comment.

  ----

  BASIC WORKFLOW

  In order to use this file effectively, which is run with the command 'npm run translate', you would
  create translated strings like in menu.js or localization.jsx. You would then run the app and change
  languages in order that the keys for these translated strings are populated in the various other 
  languages' missing.json files. Once this is done for all languages you'd like to create translations for, you may run `npm run translate` in order that the missing translation files be translated with
  the Google Translate API.

  Note - it is important that 'fromLanguage' be updated to the language that the keys are in the various
  translation[.missing].json files. It is this variable that's used by Google to determine the source 
  language from which to translate.
*/
console.log("The translateMissing.js file must be updated before it can be ran.");
return;

const projectId = "YOUR_PROJECT_ID";

// Instantiates a client
const translate = new Translate({
  projectId
});

async function updateTranslations() {

  try {
    const root = "./app/localization/locales";
    const fromLanguage = "en";
    
    // Get valid languages from Google Translate API
    let [googleLanguages] = await translate.getLanguages(); // ie. { code: "en", name: "English" }
    googleLanguages = googleLanguages.map(gl => gl.code.replace("-", "_"))

    // Uncomment me to view the various languages Google can translate to/from
    //console.log(googleLanguages);

    // Get all language directories;
    // https://stackoverflow.com/a/35759360/1837080
    const getDirectories = p => readdirSync(p).filter(f => statSync(join(p, f)).isDirectory());
    const languageDirectories = getDirectories(root).filter(d => googleLanguages.includes(d));    

    // For each language, read in any missing translations
    // and translate
    for (const languageDirectory of languageDirectories) {

      // Check to make sure each language has the proper files
      try {
        const languageRoot = `${root}/${languageDirectory}`;
        const translationFile = `${languageRoot}/translation.json`;
        const missingTranslationFile = `${languageRoot}/translation.missing.json`;

        const translationExists = fs.existsSync(translationFile);
        const translationMissingExists = fs.existsSync(missingTranslationFile);

        if (translationExists && translationMissingExists) {

          // Read in contents of files
          const translations = JSON.parse(fs.readFileSync(translationFile, {
            encoding: "utf8"
          }));
          const missing = JSON.parse(fs.readFileSync(missingTranslationFile, {
            encoding: "utf8"
          }));

          // Only translate files with actual values
          const missingKeys = Object.keys(missing);        
          if (missingKeys.length > 0){

            // Translate each of the missing keys to the target language
            for (const missingKey of missingKeys){
              const googleTranslation = await translate.translate(missingKey, {
                from: fromLanguage,
                to: languageDirectory
              });

              // Only set if a value is returned
              if (googleTranslation.length > 0){
                translations[missingKey] = googleTranslation[0];
              }              
            }
  
            // Write output back to file
            fs.writeFileSync(translationFile, JSON.stringify(translations, null, 2));
            fs.writeFileSync(missingTranslationFile, JSON.stringify({}, null, 2));
  
            console.log(`Successfully updated translations for ${languageDirectory}`);
          } else {
            console.log(`Skipped creating translations for ${languageDirectory}; none found!`);
          }          
        } else {

          // Log if we failed
          if (!translationExists) {
            console.error(`Could not generate translations for language '${languageDirectory}' because ${translationFile} does not exist, skipping!`);
          } else if (!translationMissingExists) {
            console.error(`Could not generate translations for language '${languageDirectory}' because ${missingTranslationFile} does not exist, skipping!`);
          }
        }
      } catch (error) {
        console.error("Failed due to fatal error");
        console.error(error);
      }
    }
  } catch (e) {
    console.error("Failed due to fatal error");
    console.error(error);
  }
}

updateTranslations();