# Translation in Perspective

**URL:** <https://forum.inductiveautomation.com/t/translation-in-perspective/64590>\
**Category:** Ignition\
**Tags:** perspective, ignition81, vision\
**Created:** [September 28, 2022, 12:45pm UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590 "2022-09-28T12:45:17Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![Trevor\_Nelson](https://avatars.discourse-cdn.com/v4/letter/t/dfb087/32.png) [@Trevor\_Nelson](https://forum.inductiveautomation.com/u/Trevor_Nelson)\
**Post date:** [September 28, 2022, 12:45pm UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590/1 "2022-09-28T12:45:17Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![KathyApplebaum](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kathyapplebaum/32/7261_2.png) [@KathyApplebaum](https://forum.inductiveautomation.com/u/KathyApplebaum)\
**Post date:** [September 28, 2022, 2:50pm UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590/2 "2022-09-28T14:50:04Z")

</div>

You can find the supported locale abbreviations at [Java 11 Supported Locales](https://www.oracle.com/java/technologies/javase/jdk11-suported-locales.html)

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

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [September 28, 2022, 2:57pm UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590/3 "2022-09-28T14:57:52Z")

</div>

> [@Trevor\_Nelson](#):
>
> Is there a way to populate the translation terms list in the translation manager window with all translatable terms in a Perspective project?

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.

---

<div class="post-metadata">

**Author:** ![Trevor\_Nelson](https://avatars.discourse-cdn.com/v4/letter/t/dfb087/32.png) [@Trevor\_Nelson](https://forum.inductiveautomation.com/u/Trevor_Nelson)\
**Post date:** [September 28, 2022, 3:05pm UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590/4 "2022-09-28T15:05:39Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Trevor\_Nelson](https://avatars.discourse-cdn.com/v4/letter/t/dfb087/32.png) [@Trevor\_Nelson](https://forum.inductiveautomation.com/u/Trevor_Nelson)\
**Post date:** [September 28, 2022, 3:08pm UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590/5 "2022-09-28T15:08:21Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Trevor\_Nelson](https://avatars.discourse-cdn.com/v4/letter/t/dfb087/32.png) [@Trevor\_Nelson](https://forum.inductiveautomation.com/u/Trevor_Nelson)\
**Post date:** [September 28, 2022, 3:10pm UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590/6 "2022-09-28T15:10:33Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [September 28, 2022, 3:17pm UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590/7 "2022-09-28T15:17:42Z")

</div>

You can put full sentences in there.

---

<div class="post-metadata">

**Author:** ![Trevor\_Nelson](https://avatars.discourse-cdn.com/v4/letter/t/dfb087/32.png) [@Trevor\_Nelson](https://forum.inductiveautomation.com/u/Trevor_Nelson)\
**Post date:** [September 28, 2022, 3:20pm UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590/8 "2022-09-28T15:20:48Z")

</div>

Thanks.

---

<div class="post-metadata">

**Author:** ![KathyApplebaum](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kathyapplebaum/32/7261_2.png) [@KathyApplebaum](https://forum.inductiveautomation.com/u/KathyApplebaum)\
**Post date:** [September 28, 2022, 3:22pm UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590/9 "2022-09-28T15:22:11Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [September 28, 2022, 3:24pm UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590/10 "2022-09-28T15:24:17Z")

</div>

Be aware though that apart from those flexibility settings:

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/a/8/a8ea9ab963234042ead5fa0070bc2a8d756963a0.png)

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

---

<div class="post-metadata">

**Author:** ![Trevor\_Nelson](https://avatars.discourse-cdn.com/v4/letter/t/dfb087/32.png) [@Trevor\_Nelson](https://forum.inductiveautomation.com/u/Trevor_Nelson)\
**Post date:** [September 29, 2022, 12:23pm UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590/11 "2022-09-29T12:23:01Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Amitkumar\_Ravat](https://avatars.discourse-cdn.com/v4/letter/a/3ab097/32.png) [@Amitkumar\_Ravat](https://forum.inductiveautomation.com/u/Amitkumar_Ravat)\
**Post date:** [November 15, 2023, 3:34am UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590/12 "2023-11-15T03:34:12Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Trevor\_Nelson](https://avatars.discourse-cdn.com/v4/letter/t/dfb087/32.png) [@Trevor\_Nelson](https://forum.inductiveautomation.com/u/Trevor_Nelson)\
**Post date:** [November 15, 2023, 12:54pm UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590/13 "2023-11-15T12:54:25Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![DNice](https://avatars.discourse-cdn.com/v4/letter/d/858c86/32.png) [@DNice](https://forum.inductiveautomation.com/u/DNice)\
**Post date:** [November 15, 2023, 2:49pm UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590/14 "2023-11-15T14:49:14Z")

</div>

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.

```auto
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.

---

<div class="post-metadata">

**Author:** ![Trevor\_Nelson](https://avatars.discourse-cdn.com/v4/letter/t/dfb087/32.png) [@Trevor\_Nelson](https://forum.inductiveautomation.com/u/Trevor_Nelson)\
**Post date:** [December 19, 2023, 8:12pm UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590/15 "2023-12-19T20:12:18Z")

</div>

@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.

```auto
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.'

```

---

<div class="post-metadata">

**Author:** ![jmorris](https://avatars.discourse-cdn.com/v4/letter/j/ba8739/32.png) [@jmorris](https://forum.inductiveautomation.com/u/jmorris)\
**Post date:** [June 21, 2024, 5:09pm UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590/16 "2024-06-21T17:09:34Z")

</div>

Guys, we really need a friendly "menu based" way to add all perspective view terms to the translation manager!!  
Even more, from a project standpoint there should a way to select from a list of all perspective views and add the terms from multiple views automatically.

---

<div class="post-metadata">

**Author:** ![Trevor\_Nelson](https://avatars.discourse-cdn.com/v4/letter/t/dfb087/32.png) [@Trevor\_Nelson](https://forum.inductiveautomation.com/u/Trevor_Nelson)\
**Post date:** [June 21, 2024, 5:28pm UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590/17 "2024-06-21T17:28:48Z")

</div>

That would be nice.

---

<div class="post-metadata">

**Author:** ![ARIFRAHUMAN\_A](https://avatars.discourse-cdn.com/v4/letter/a/e19b73/32.png) [@ARIFRAHUMAN\_A](https://forum.inductiveautomation.com/u/ARIFRAHUMAN_A)\
**Post date:** [April 15, 2025, 10:25am UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590/18 "2025-04-15T10:25:23Z")

</div>

Hello @Trevor_Nelson,

I tried running this script from a button, but I encountered an error related to the `obj` field. How can I run this script correctly?

Also, regarding the output — compared to the script shared by @DNice, which gathers all words and sentences across the entire project for the Translation Manager — I only want to collect and translate text from specific **Perspective views** , not the whole project. I saw a similar feature exists for Vision windows, but not for Perspective.

Could anyone please help me with this?

---

<div class="post-metadata">

**Author:** ![DNice](https://avatars.discourse-cdn.com/v4/letter/d/858c86/32.png) [@DNice](https://forum.inductiveautomation.com/u/DNice)\
**Post date:** [April 15, 2025, 5:05pm UTC](https://forum.inductiveautomation.com/t/translation-in-perspective/64590/19 "2025-04-15T17:05:46Z")

</div>

We cannot easily help without seeing the error.  
Why not just translate everything? i f its automated it shouldnt really be much more time?  
But to answer your Q, you could copy paste them into an empty project and run the script or manually enter the "root" variable this section of the code to point to a specific view file path:

```python
...
for root, dirs, files in os.walk(pathToProject):
	try: 
		for x in _json_extract(json.loads(open(root + '/view.json').read()), 'text'):
...

```
