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
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
You'll probably need to manually write a script.
Here's a post about iterating through all the components on a perspective view -
Heres a way to do it in vision -
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.
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
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
@Remco_Thijssen Ignore my approach, @victordcq would be much easier to use and implement and much more thorough.
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
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
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
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)
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')
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
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?
Edit: i just copied the code in the scriptconsole (apart from the modify translate) and it works for me...
Did you copy everything?
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?
seems like it is indeed a version thing
what version do you use
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
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?
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?
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.
try this: component.getPropertyValue('text1')
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
hasattr
wont work but you might still want to check for component.name != None
tho
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:
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,
i dont know, i did not make the one for vision. i dont rly work with vision often. ive heard some people having problemes with other versions, maybe this only works in client on the older version.
what error does it give?
still this i suppose?
well seems the context functions might have changed
in here somewhere
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