Translation in Perspective

Is there a way to populate the translation terms list in the translation manager window with all translatable terms in a Perspective project? The translation videos show that capability in Vision, but I’m unable to find it in Perspective 8.1.19. Also is there a list of locale abbreviations somewhere? I manually added a couple terms to the translation manager, and I’m able to display the values for all of the languages except simplified Chinese. I tried zh and zh-CN for Chinese. Those didn’t work.

You can find the supported locale abbreviations at Java 11 Supported Locales

zh-CN should have worked for simplified Chinese. I’ll play around with it a bit and see if that’s an oversight.

No built-in way, but I seem to remember @nminchin mentioning he'd made a script for that.
Even if he didn't mention it, he probably has a script for that anyway. Maybe he'll be willing to share.

Thanks, Kathy. Let me know if it’s an oversight or if you can get it to work.

It would be great if there is already a script somewhere so we don’t have to manually add every term in our project.

Kathy, do you know if full sentences can be entered in the terms list, or does Ignition work on individual words?

You can put full sentences in there.

Thanks.

1 Like

It works on exact matches of terms. So if you entered a translation for “red” and the term it’s looking for is “red light”, it won’t match. But your term can be as long as you want, probably limited to 2 billion characters including spaces and punctuation.

We pretty much have to do it this way because so many words are so ambiguous when it comes to translation. Does stop mean halt or does it mean the diameter of a lens (f stop) or does it mean a station (train stop)? Or maybe it’s some acronym specific to your company. We feel it’s much safer to leave that up to you.

1 Like

Be aware though that apart from those flexibility settings:

image

it will only translate EXACT matches. So watch the spelling of everything.

2 Likes

Is there a way to use a script to get a list of the locales you have selected in the Translation Manager in Perspective?

Vision has the ability using system.util.getAvailableLocales(). I have my available locale codes and names hard coded in the properties for the dropdown that I’m using to select different languages for the project. I’d like to have a script get the locales and populate the dropdown properties to avoid having someone edit the component properties if we add new languages in the future.

did you find any script or any document that can help to get the locales and populate the dropdown?

No, I never did. I still have data hardcoded in my application.

Here is the script in my notes that I found on the forums from a while back (likely form nminchin originally). Put this script on a button in a view run it on action performed.

import os
import json
from com.inductiveautomation.ignition.gateway import IgnitionGateway
from com.inductiveautomation.ignition.gateway.script import GatewaySystemUtilities

system.perspective.print('started')
package = IgnitionGateway.get().getLocalizationManager().loadFullPackage()
oldKeys = package.getAvailableKeys()
context = IgnitionGateway.get()
pathToProjectFolder = str(context.systemManager.dataDir.absoluteFile).replace('\\','/') + '/projects'	
system.perspective.print('project path:' + str(pathToProjectFolder))
pathToProject = pathToProjectFolder + "/" + system.perspective.getProjectInfo().name + "/com.inductiveautomation.perspective/views/"


def json_extract(obj, key):
    """Recursively fetch values from nested JSON."""
    arr = []
        
    def extract(obj, arr, key):
        """Recursively search for values of key in JSON tree."""
        if isinstance(obj, dict):
            for k, v in obj.items():
                if isinstance(v, (dict, list)):
                    extract(v, arr, key)
                elif k == key:
                    arr.append(v)
        elif isinstance(obj, list):
            for item in obj:
                extract(item, arr, key)
        return arr

    values = extract(obj, arr, key)
    return values

newKeys = []
for root, dirs, files in os.walk(pathToProject):
        try:
                for textphrase in ['text','label','title']: #NOTE edit these parameters to capture all of the text fields you want to translate
                        for x in json_extract(json.loads(open(root + '/view.json').read()), textphrase):
                                if x not in newKeys and x not in oldKeys and x != "" and type(x) != int and type(x) != float: 
                                        newKeys.append(x)
        except:
                pass

for key in newKeys:
        key = key.strip()
        if key not in ['°F', u'\n','',None,'*',]: # Filter out undesired values
                system.util.modifyTranslation(str(key),str(key),'en')
                system.perspective.print('adding new key:' + str(key))

Running this script will insert all the text found in any parameters named ['text','label','title'] into your translation manager.
Export the translations from the Designer>Tools>Translation Manager tool.
Manually translate the words or automate it using a python Google Translate API script. (I also have a script for this somehwere...)
Finally, import the new translated words back into the designer.

I have 2 projects being used in half a dozen different countries so automating the initial translation is super helpful. Getting feedback from end users is critical though as Google translate is only about 70% accurate for my industry.

2 Likes

@DNice Your code worked, but it threw an error in one of my projects even though it successfully populated my translation lists. I made a few edits that allow the code to run without throwing errors.

Also, the translation list includes some junk terms that I have to delete, but deleting a few terms isn't a big deal.

Thanks for the help.

def _extract(obj, key):
        if isinstance(obj, dict):
            for k, v in obj.items():
                if isinstance(v, (dict, list)):
                    for result in _extract(v, key):
                        yield result
                elif k == key:
                    yield v
        elif isinstance(obj, list):
            for item in obj:
                for result in _extract(item, key):
                    yield result
    
    return (result for result in _extract(obj, key))

def updateTranslationList(logID):	
	package = IgnitionGateway.get().getLocalizationManager().loadFullPackage()
	oldKeys = set(package.getAvailableKeys())
	context = IgnitionGateway.get()
	pathToProjectFolder = str(context.systemManager.dataDir.absoluteFile).replace('\\','/') + '/projects'	
	pathToProject = pathToProjectFolder + "/" + system.perspective.getProjectInfo().name + "/com.inductiveautomation.perspective/views/"
	
	newKeys = []
	for root, dirs, files in os.walk(pathToProject):
		try:
			for x in _json_extract(json.loads(open(root + '/view.json').read()), 'text'):
				if x not in newKeys and x not in oldKeys and x != "":
					newKeys.append(x)
		except:
			pass
	
	for key in newKeys:			
	    if isinstance(key, (str, int)) and re.match(r'^\w+, str(key)):
	        system.util.modifyTranslation(str(key), str(key), 'en')
	return 'Translation list update complete.'