javascriptjsonangularjspowershellangular-translate

Is there a way I can automate the creation of .json files used for language translations?


I have files such as this that have translation keys and values:

locale-en.json
{
    "CHANGE_PASSWORD": "Change Password",
    "CONFIRM_PASSWORD":  "Confirm Password",
    "NEW_PASSWORD": "New Password"
}

locale-jp.json
{
    "CHANGE_PASSWORD": "パスワードを変更します",
    "CONFIRM_PASSWORD":  "パスワードを認証します",
    "NEW_PASSWORD": "新しいパスワード"
}

When I add a new translation key to the JSON file containing the English translations for example, I must remember to add that key and the associated translation to all the other JSON files. All the JSON files are also edited separately. The process is laborious and error prone.

Has anyone found a way to reduce the errors and to automate the process.

Ideally I would like to be able to run a script from Windows PowerShell that would change the files to this if an additional key was added to locale-en.json :

locale-en.json
{
    "CHANGE_PASSWORD": "Change Password",
    "CONFIRM_PASSWORD":  "Confirm Password",
    "NEW_PASSWORD": "New Password",
    "NEW_KEY": "New Key"
}

locale-jp.json
{
    "CHANGE_PASSWORD": "パスワードを変更します",
    "CONFIRM_PASSWORD":  "パスワードを認証します",
    "NEW_PASSWORD": "新しいパスワード",
    >>>"NEW_KEY": "New Key"
}

Solution

  • You could write something like this in powershell:

    $masterFile = "locale-en.json"
    
    function Get-LocaleMap($file){
    
        $map = @{}
    
        $localeJson = ConvertFrom-Json (gc $file -Raw)
        $localeJson | gm -MemberType NoteProperty | % {
            $map.Add($_.Name, ($localeJson | select -ExpandProperty $_.Name))
        }
    
        return $map
    }
    
    $masterLocale = Get-LocaleMap $masterFile
    
    ls | ? { $_.Name -like "locale-*.json" -and $_.Name -ne $masterFile } | % {
        $locale = Get-LocaleMap $_.FullName
        $masterLocale.GetEnumerator() | % {
            if(!$locale.ContainsKey($_.Key)){
                $locale.Add($_.Key, $_.Value)
            }
        }
    
        ConvertTo-Json $locale | Out-File -FilePath $_.FullName -Force -Encoding utf8
    }
    

    It created a dictionary from your English json file. Then it looks up all other locale files and checks them for keys which are present in the English file but missing from them. Then it adds the missing keys and values and saves the locale files in Unicode.

    Let me show you how you can do the same with old school Windows Scripting since you seem to prefer JavaScript:

    var masterFile = "locale-en.json"
    var fso = new ActiveXObject("Scripting.FileSystemObject");
    var scriptPath = fso.GetParentFolderName(WScript.ScriptFullName);
    var charSet = 'utf-8';
    var f = fso.GetFolder(scriptPath);
    var fc = new Enumerator(f.files);
    
    function getLocaleMap(fileName){
        var path = scriptPath + '\\' + fileName;
        var stream = new ActiveXObject("ADODB.Stream"); // you cannot use fso for utf-8
    
        try{
            stream.CharSet = charSet;
            stream.Open();
            stream.LoadFromFile(path);
            var text = stream.ReadText();
            var json = {};
            eval('json = ' + text); // JSON.parse is not available in all versions
            return json;
        }
        finally{
            stream.Close();
        }
    }
    
    function saveAsUtf8(fileName, text){
        var path = scriptPath + '\\' + fileName;
        var stream = new ActiveXObject("ADODB.Stream"); 
    
        try{
            stream.CharSet = charSet;
            stream.Open();
            stream.Position = 0;
            stream.WriteText(text);
            stream.SaveToFile(path, 2); // overwrite
        }
        finally{
            stream.Close();
        }
    }
    
    var locales = [];
    var masterMap = getLocaleMap(masterFile);
    
    for (; !fc.atEnd(); fc.moveNext())
    {
        var file = fc.item();
        var extension = file.Name.split('.').pop();
        if(extension != "json" || file.Name == masterFile){
           continue;
        }
    
        var map = getLocaleMap(file.Name);
        var newLocaleText = '{\r\n';
        var i = 0;
    
        for(var name in masterMap){
            var value = '';
    
            if(map[name]){
                value = map[name];
            }
            else{
                value = masterMap[name];
            }
    
            if(i > 0){
                newLocaleText += ",\r\n";
            }
    
            newLocaleText += "\t'" + name + "': '" + value + "'";
            i++;
        }
    
        newLocaleText += '\r\n}'
    
        saveAsUtf8(file.Name, newLocaleText);
    }
    

    You can run the javascript from command line like this:

    Cscript.exe "C:\yourscript.js"
    

    I hope it helps.