# Export all component text used in Ignition

**URL:** <https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668>\
**Category:** Ignition\
**Tags:** ignition80\
**Created:** [December 2, 2021, 1:36pm UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668 "2021-12-02T13:36:31Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Remco\_Thijssen](https://avatars.discourse-cdn.com/v4/letter/r/9fc29f/32.png) [@Remco\_Thijssen](https://forum.inductiveautomation.com/u/Remco_Thijssen)\
**Post date:** [December 2, 2021, 1:36pm UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/1 "2021-12-02T13:36:31Z")

</div>

Hii all,

Is there a way to export all used component text for instance label.text, to translate it. Now i have to look for all the names of the component and translate it. But if the SCADA program is very big, it is a lot of work to search for al the used components.

So, is there a way to get a list of all used components with their name text?

Regards, Remco

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [December 2, 2021, 1:40pm UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/2 "2021-12-02T13:40:06Z")

</div>

vison or perspective?

Also its not all perfect as (im guessing) you also have texts that come from a db, tag or expression so that wont rly work on those…  
But its a start i guess ive done it too xd

---

<div class="post-metadata">

**Author:** ![bkarabinchak.psi](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bkarabinchak.psi/32/83567_2.png) [@bkarabinchak.psi](https://forum.inductiveautomation.com/u/bkarabinchak.psi)\
**Post date:** [December 2, 2021, 1:49pm UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/3 "2021-12-02T13:49:25Z")

</div>

You'll probably need to manually write a script.

Here's a post about iterating through all the components on a perspective view -

> [@Iterate through all components programatically in Perspective?](https://forum.inductiveautomation.com/t/iterate-through-all-components-programatically-in-perspective/32938):
>
> I was wondering if there's a way to iterate through all components on screen for a perspective view? I was trying to use getRootContainer and getChildren but it doesn't seem as straight forward as I thought/as it was for Vision. Any know how this is done?

Heres a way to do it in vision -

> [@Elegant Way to Disable All Components in a Window?](https://forum.inductiveautomation.com/t/elegant-way-to-disable-all-components-in-a-window/21451/4):
>
> You can use the getComponents method, BUT the caveat is the limitation. You either get all components in the root container which is equivalent to 1 level, but if you have nested components/templates it gets trickier. rc = system.gui.getParentWindow(event).getRootContainer() for component in rc.getComponents(): component.enabled=False

You'll need to modify these to try and look at `.text` fields of appropriate components (or just try to get the text field of all components and catch the errors when you do it to a non text component.).

However this will just give you the current values of those texts components as of now - not all possible text values for every binding possibility. But it should still help you get a lot of the text you use from the program.

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [December 2, 2021, 1:59pm UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/4 "2021-12-02T13:59:23Z")

</div>

Here is a script i used to automatically add all text values to the translate manager in perspective  
By checking the resource files… warning this may take a while xd

```auto
	import os
	import json
	from com.inductiveautomation.ignition.gateway import IgnitionGateway
	from com.inductiveautomation.ignition.gateway.script import GatewaySystemUtilities
	
	package = IgnitionGateway.get().getLocalizationManager().loadFullPackage()
	oldKeys = package.getAvailableKeys()
	context = IgnitionGateway.get()
	pathToProjectFolder = str(context.systemManager.dataDir.absoluteFile).replace('\\','/') + '/projects'	
	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 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:			
		system.util.modifyTranslation(str(key),str(key),'en')
	

```

i got one for vision too but the gateway isnt on rn you need it? xd

---

<div class="post-metadata">

**Author:** ![bkarabinchak.psi](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bkarabinchak.psi/32/83567_2.png) [@bkarabinchak.psi](https://forum.inductiveautomation.com/u/bkarabinchak.psi)\
**Post date:** [December 2, 2021, 2:13pm UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/5 "2021-12-02T14:13:11Z")

</div>

@Remco_Thijssen Ignore my approach, @victordcq would be much easier to use and implement and much more thorough.

---

<div class="post-metadata">

**Author:** ![Remco\_Thijssen](https://avatars.discourse-cdn.com/v4/letter/r/9fc29f/32.png) [@Remco\_Thijssen](https://forum.inductiveautomation.com/u/Remco_Thijssen)\
**Post date:** [December 2, 2021, 2:23pm UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/6 "2021-12-02T14:23:14Z")

</div>

How does this exactly works, i’m very new with programming but i tried to do my best haha. Is this a custom script or a script behind a button or something like that? And do you import a json file and what kind of json file is it? I need it for Vision and Perspective, what do you mean by gateway?

And what does os mean by import os.

Sorry for all the questions, i feel myself as a very dumb person right now hahaha

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [December 2, 2021, 2:29pm UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/7 "2021-12-02T14:29:41Z")

</div>

You can put this on a button to run it once

No need to import any files, the script finds the json files of the perspective projects which are stored on the gateway

Alright ill need a moment to fetch it

> [@Remco\_Thijssen](#):
>
> what do you mean by gateway?

are you reffering to the script or my saying its not turned on?

os = operating system. its a library which can browse through your files so it can read all the resources

no problem haha this is an advanded script 😛

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [December 2, 2021, 4:01pm UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/8 "2021-12-02T16:01:11Z")

</div>

This should work in a button for vision… pro tip dont try to understand this one xD There is a bucnh of things that dont get used or are not needed but… it works xd  
(again dont do this to often, it may take long xd)

```auto
from com.inductiveautomation.factorypmi.application.binding.action import ActionAdapter

class ProjectResources:
	
	def __init__ (self):

		import system
		from javax.swing import JFrame
		from java.awt.event import WindowEvent
		
		if system.util.getSystemFlags() & system.util.DESIGNER_FLAG:
			try:
				from com.inductiveautomation.ignition.designer import IgnitionDesigner
			except ImportError:
				pass
			try:
				self.context = IgnitionDesigner.getFrame().getContext()
			except AttributeError:
				pass
		else:
			from com.inductiveautomation.factorypmi.application.runtime import ClientPanel
			"""
			Attempt to resolve client context. By creating a frame it prevents the need to traverse the object heirarchy. i.e. parent.parent....
			"""
			projName = system.util.getProjectName()
			frame_name = 'ThrowAway'
			frm = JFrame(frame_name)
			frm.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE)
			windows = frm.getWindows()
			frm.dispose()
			for window in windows:
				try:
					if projName in window.getTitle():
						pane = window.getContentPane()
						if isinstance(pane, ClientPanel):
							if hasattr(pane, 'getClientContext'):
								self.context = pane.getClientContext()
								break
				except AttributeError:
					pass
		if not hasattr(self.context, 'getProject'):
			raise Exception(self.getInvalidContextError(context))	

	def getAllProjectResources(self):
		return self.context.getProject().getResources()
	
	def getProjectResource(self, resourcepaths):
		list = []
		for resource in self.getAllProjectResources():
			if str(resource.getResourcePath().getFolderPath()) in resourcepaths :
				list.append(resource)
		return list	 	

	def getResourceInfo(self, resourcepath):
		for resource in self.getAllProjectResources():
			if str(resource.getResourcePath().getFolderPath()) == resourcepath :
				dresource = self.getDeSerializedResource(resource)
				if dresource != None:
					return {'Name' : dresource.getName(), 'Title' : dresource.getTitle() }
				else:
					return {}					
		return {}	 	

	def getAllComponentsForResource(self,resourcepaths):
		rows = []
		header = ['Project name', 'Resource Name','Resource Type', 'Component Type', 'Attribute', 'Name' ,'Value']
		resources = self.getProjectResource(resourcepaths)
		checkedResource=[]
		
		def resolveData(component):
			
			if component.getClass().getSimpleName() == u'TemplateHolder':
				if component.templatePath not in checkedResource:				
					checkedResource.append(component.templatePath)				
					tempResources = self.getProjectResource(component.templatePath)					
					for tempResource in tempResources:											
						dresource = self.getDeSerializedResource(tempResource)
						if dresource != None:
							rows.extend(resolveData(dresource))
							
							tempComponents = self.getAllComponentsForObject(dresource)
							for tempComponent in tempComponents:
								#print tempComponent.getName(), tempComponent.getClass().getSimpleName()								
								rows.extend(resolveData(tempComponent))
								
			#get resources
			arr = []
			if hasattr(component, 'text') and component.name != None and component.text:
				arr.append([resource.getProjectName(), resource.getResourceName(), resource.getResourceType().getTypeId(), component.getClass().getSimpleName(), 'Text', component.name, component.text])	
			if hasattr(component, 'toolTipText') and component.name != None and component.toolTipText:
				arr.append([resource.getProjectName(), resource.getResourceName(), resource.getResourceType().getTypeId(), component.getClass().getSimpleName(), 'ToolTip', component.name, component.toolTipText])	
			if hasattr(component, 'title') and component.name != None and component.title:
				arr.append([resource.getProjectName(), resource.getResourceName(), resource.getResourceType().getTypeId(), component.getClass().getSimpleName(), 'Title', component.name, component.title])	
			return arr			
		
			
		for resource in resources:
			dresource = self.getDeSerializedResource(resource)
			if dresource != None:
				
				rows.extend(resolveData(dresource))
				components = self.getAllComponentsForObject(dresource)
				for component in components:
					#print component.getName(), component.getClass().getSimpleName()					
					rows.extend(resolveData(component))
					
		return system.dataset.toDataSet(header, rows)		
		
	def getDeSerializedResource(self, resource):
		deserializer = self.context.createDeserializer()
		if not resource.isFolder():
			if str(resource.getResourceType().getTypeId()) == 'windows':
				try:				
					return deserializer.deserialize(resource.getData("window.bin")).getRootObjects()[0]
				except:
					pass
			elif str(resource.getResourceType().getTypeId()) == 'templates':
				try:				
					return deserializer.deserialize(resource.getData("template.bin")).getRootObjects()[0]
				except:
					pass
		return None

	def getAllComponentsForObject(self, object):
		arr = []
		try:
			for component in object.getComponents():
				arr.append(component)
				self.objectSearch(component, arr)
		except AttributeError:
			pass		
		return arr
		
	def objectSearch(self, object, array):
		try:
			for component in object.getComponents():
				array.append(component)
				self.objectSearch(component, array)
		except AttributeError:
			return		

allText = ProjectResources().getAllComponentsForResource(system.gui.getWindowNames())

for r in range(allText .getRowCount()):
	key = allText.getValueAt(r, 'Value')
	value = key 
	system.util.modifyTranslation(str(key), str(value), 'en')

```

---

<div class="post-metadata">

**Author:** ![Roman\_Windischbauer](https://avatars.discourse-cdn.com/v4/letter/r/35a633/32.png) [@Roman\_Windischbauer](https://forum.inductiveautomation.com/u/Roman_Windischbauer)\
**Post date:** [February 28, 2022, 9:06am UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/9 "2022-02-28T09:06:14Z")

</div>

Hi @victordcq victordcq

thanks for sharing this code, but i am not able to execute it in vision.  
I tried to paste it in script console and keep getting this error that im not able to debug:

Traceback (most recent call last):  
File “”, line 142, in   
File “”, line 67, in getAllComponentsForResource  
File “”, line 50, in getProjectResource  
AttributeError: ‘com.inductiveautomation.ignition.common.project.Pr’ object has no attribute ‘getResourcePath’

Can you help me out?  
Thanks

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [February 28, 2022, 9:24am UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/10 "2022-02-28T09:24:58Z")

</div>

idk if it works in the script console, im not sure if the script console has any know of the projects...  
yu might have to put it in a button script.

and for the error it seems you are looping over projects not projectResources  
Are you sure you called getAllProjectResources?

> [@victordcq](#):
>
> ```auto
> for resource in self.getAllProjectResources():
> if str(resource.getResourcePath()
> 
> ```

Edit: i just copied the code in the scriptconsole (apart from the modify translate) and it works for me...  
Did you copy everything?

---

<div class="post-metadata">

**Author:** ![Roman\_Windischbauer](https://avatars.discourse-cdn.com/v4/letter/r/35a633/32.png) [@Roman\_Windischbauer](https://forum.inductiveautomation.com/u/Roman_Windischbauer)\
**Post date:** [February 28, 2022, 9:40am UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/11 "2022-02-28T09:40:40Z")

</div>

im using the code just the way you pasted it above, there are no differences.  
I use ignition 7.9.17 (vision 9.9.17), might that be a problem?

I keep getting the errors i mentioned above, any ideas?

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [February 28, 2022, 9:47am UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/12 "2022-02-28T09:47:49Z")

</div>

seems like it is indeed a version thing

---

<div class="post-metadata">

**Author:** ![Roman\_Windischbauer](https://avatars.discourse-cdn.com/v4/letter/r/35a633/32.png) [@Roman\_Windischbauer](https://forum.inductiveautomation.com/u/Roman_Windischbauer)\
**Post date:** [February 28, 2022, 9:53am UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/13 "2022-02-28T09:53:59Z")

</div>

what version do you use

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [February 28, 2022, 9:54am UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/14 "2022-02-28T09:54:16Z")

</div>

8.1+

you dont really need this part of the code tho, but im not sure if everything else works.

This bit just checks if the resource is the one you want (provided by system.gui.getWindowNames() `allText = ProjectResources().getAllComponentsForResource(system.gui.getWindowNames())`)  
you will have to use a different compare methode or dont compare and pull in all files since thats probably what you want anyways.

maybe try  
printing resource.getName()  
or any of the properties of you find here to make a compare of the list you get of system.gui.getWindowNames()  
(i think this is the link to the correct version, it should be close enough idk how to navigate the docs to your version xd)  
[http://files.inductiveautomation.com/sdk/javadoc/ignition79/794-beta1/com/inductiveautomation/ignition/common/project/ProjectResource.html](http://files.inductiveautomation.com/sdk/javadoc/ignition79/794-beta1/com/inductiveautomation/ignition/common/project/ProjectResource.html)

---

<div class="post-metadata">

**Author:** ![Roman\_Windischbauer](https://avatars.discourse-cdn.com/v4/letter/r/35a633/32.png) [@Roman\_Windischbauer](https://forum.inductiveautomation.com/u/Roman_Windischbauer)\
**Post date:** [February 28, 2022, 11:38am UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/15 "2022-02-28T11:38:11Z")

</div>

Now i converted my project to 8.1 for testing purposes, i was able to execute the code but unfortunately it only exported one text.

can you tell me, where does the text need to be in order to be exported in the translation manager?

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [February 28, 2022, 11:40am UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/16 "2022-02-28T11:40:40Z")

</div>

> [@victordcq](#):
>
> ```auto
> #get resources
> arr = []
> if hasattr(component, 'text') and component.name != None and component.text:
> arr.append([resource.getProjectName(), resource.getResourceName(), resource.getResourceType().getTypeId(), component.getClass().getSimpleName(), 'Text', component.name, component.text])	
> if hasattr(component, 'toolTipText') and component.name != None and component.toolTipText:
> arr.append([resource.getProjectName(), resource.getResourceName(), resource.getResourceType().getTypeId(), component.getClass().getSimpleName(), 'ToolTip', component.name, component.toolTipText])	
> if hasattr(component, 'title') and component.name != None and component.title:
> arr.append([resource.getProjectName(), resource.getResourceName(), resource.getResourceType().getTypeId(), component.getClass().getSimpleName(), 'Title', component.name, component.title])	
> return arr	
> 
> ```

every fixed property of "text, toolTipText and title" should be added. Bindings/expressions do not get added as these do not exist "yet"  
What were you expecting to get?

---

<div class="post-metadata">

**Author:** ![Roman\_Windischbauer](https://avatars.discourse-cdn.com/v4/letter/r/35a633/32.png) [@Roman\_Windischbauer](https://forum.inductiveautomation.com/u/Roman_Windischbauer)\
**Post date:** [February 28, 2022, 1:45pm UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/17 "2022-02-28T13:45:47Z")

</div>

now it works, thank you, for some reason i need to save the screen, then execute the code.

At this point, template parameters, that contain text, cannot be exported by that code?  
I have one custom property, called “text 1”.

I tried to add 2 lines in your code:

```
		if hasattr(component, "text1") and component.name != None and component.text1:
			arr.append([resource.getProjectName(), resource.getResourceName(), resource.getResourceType().getTypeId(), component.getClass().getSimpleName(), 'text1', component.name, component.text1])	

```

but it did not work.

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [February 28, 2022, 2:26pm UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/18 "2022-02-28T14:26:10Z")

</div>

try this: `component.getPropertyValue('text1')`

```auto
if component.name != None and component.getPropertyValue('text1'):
 arr.append([resource.getProjectName(), resource.getResourceName(), resource.getResourceType().getTypeId(), component.getClass().getSimpleName(), 'text1', component.name, component.getPropertyValue('text1')])

```

edit yup should work

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

`hasattr` wont work but you might still want to check for` component.name != None` tho

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [February 28, 2022, 3:21pm UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/19 "2022-02-28T15:21:27Z")

</div>

> [@victordcq](#):
>
> try this: `component.getPropertyValue('text1')`

Pssst! Just install Simulation Aids and the shortcuts will always work (`component.text1`) even for custom properties, and no matter what method you used to get the component reference. See this discussion:

> [@Transaction groups triggered expression item updating when trigger is false](https://forum.inductiveautomation.com/t/transaction-groups-triggered-expression-item-updating-when-trigger-is-false/17196/14):
>
> Ok, so I’ve been down the rabbit hole and found Ignition’s (undocumented) PyComponentWrapper. I haven’t deciphered it enough to be sure, but it seems to be invoked only for particular situations, based on the string constants in the class file (like “getComponent” and “getComponents”). To play with this, I constructed a conversion adapter like so: public class PyComponentAdapter implements PyObjectAdapter { public PyComponentAdapter() {} @Override public boolean canAdapt(Object jObj) { …

---

<div class="post-metadata">

**Author:** ![MUNIYANDI\_D](https://avatars.discourse-cdn.com/v4/letter/m/48db29/32.png) [@MUNIYANDI\_D](https://forum.inductiveautomation.com/u/MUNIYANDI_D)\
**Post date:** [July 19, 2023, 7:38am UTC](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668/20 "2023-07-19T07:38:09Z")

</div>

Hi @victordcq, but this script runs in designer only. Not in Client. But they developed that for both of designer and the client. But idk why this didn't run in client. Can you please clarify this one ?

Thanks,

[Next page](https://forum.inductiveautomation.com/t/export-all-component-text-used-in-ignition/53668.md?page=2)
