Translating project

I had been working this up on and off (mostly off) for a few months. This works with XML exports of the Translation Manager, and will handle multiple locales at once. You will need a Microsoft Azure account, but the free version is, as of this writing, 2 million characters per month.

  1. Export XMLs from Translation Manager

  2. Run the script in whatever fashion you choose.

  3. Resultant files will be in the same directory.

  4. Import the translated files back into the Translation Manager.
    NOTE: Currently, the locales are not being correncly parsed when importing back in. (see this post). But, manually selecting the locale dropdown will let you work around it. :slight_smile:

import javax.xml.parsers
import javax.xml.transform
import java.io.FileOutputStream as FOS
import httplib, urllib, uuid, codecs, os, glob

# **********************************************
# *** Update or verify the following values. ***
# **********************************************

# Replace the subscriptionKey string value with your valid subscription key.
subscriptionKey = 'put_your_own_key_here'

host = 'api.cognitive.microsofttranslator.com'
path = '/translate?api-version=3.0'

#*************************************************

filepath = system.file.openFile()
# Flag to tell it we are processing all of the files are just the selected one.
allFiles = True

if filepath != None:
  # Base file name without locale
  baseName = filepath[:-7]
  # Extension of the file
  extension = filepath[-4:]
  if allFiles == True:
    fileFilter = baseName + '*' + extension
  else:
    fileFilter = filepath

  # create file list 
  fileList = glob.glob(fileFilter)

  # create list of locales
  langList =  [f.replace(baseName,'').replace(extension, '')[1:] for f in fileList]

  # create language parameters to use with Microsoft Translate
  params = '&to='+'&to='.join(langList)
  
  # open the selected file and extract keys to be translated
  dbf = javax.xml.parsers.DocumentBuilderFactory.newInstance()
  db = dbf.newDocumentBuilder()
  dom = db.parse(filepath)
  doc = dom.getDocumentElement()
  entries = doc.getElementsByTagName('entry')
  keyList =[]
  for i in range(entries.getLength()):
    node = entries.item(i)
    keyList.append(node.getAttribute('key'))
	
  # header for Microsoft Translate API call
  headers = {
        'Ocp-Apim-Subscription-Key': subscriptionKey,
        'Content-type': 'application/json',
        'X-ClientTraceId': str(uuid.uuid4())
    }
  # serialize dictionary for use in Microsoft Translate API call
  requestBody = []
  for key in keyList:
    requestBody.append({'Text' : key})
  content = system.util.jsonEncode(requestBody)
  
  # send request to Microsoft Translate  
  conn = httplib.HTTPSConnection(host)
  conn.request ("POST", path + params, content, headers)
  # get response
  response = conn.getresponse()
  data = response.read()
  translatedData = system.util.jsonDecode(data)

  # create dictionary with all translated data
  dictOut = dict((key,{}) for key in keyList)
  for key, t in zip(keyList, translatedData):
    for language, translation in zip(langList, t['translations']):
      dictOut[key][language]=translation['text']

  # create output XML files      
  for lang in langList:
    fileName = baseName + '_' + lang + '_output' + extension
    

    dbf = javax.xml.parsers.DocumentBuilderFactory.newInstance()
    db = dbf.newDocumentBuilder()
    dom = db.newDocument()
	# XML root
    root = dom.createElement('properties')
	#create 'comment' element with locale
    e = dom.createElement('comment')
    e.appendChild(dom.createTextNode('Locale: '+lang))
	# add 'comment' element to root
    root.appendChild(e)
	# add translations
    for key in keyList:
	  # create entry element
      e = dom.createElement('entry')
	  # add 'key' attibute with original text
      e.setAttribute('key', key)
	  # add translated data for the key entry
      e.appendChild(dom.createTextNode(dictOut[key][lang].decode('utf-8')))
	  # add 'entry' element to root
      root.appendChild(e)
	#close root
    dom.appendChild(root)
    
	# prepare xml file properties
    tr = javax.xml.transform.TransformerFactory.newInstance().newTransformer()
    tr.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, 'yes')
    tr.setOutputProperty(javax.xml.transform.OutputKeys.METHOD, 'xml')
    tr.setOutputProperty(javax.xml.transform.OutputKeys.ENCODING, 'UTF-8')
    tr.setOutputProperty(javax.xml.transform.OutputKeys.DOCTYPE_SYSTEM, 'http://java.sun.com/dtd/properties.dtd')
    tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "0")
	# convert XML data to a DOM source for writing to a file
    domSource = javax.xml.transform.dom.DOMSource(dom)
	# prepare FileOutputStream
    streamFile = FOS(fileName)
	# create StreamResult from FileOutputStream
    streamOut = javax.xml.transform.stream.StreamResult(streamFile)
	# write the DOM source to a file
    tr.transform(domSource, streamOut)
	# close the file
    streamOut.getOutputStream().close()

Disclaimer below, but here’s the TLDR version: It works for me, YMMV. Consider yourself warned.

Disclimer: While Jordan has made every attempt to ensure that the information contained in this post has been obtained from reliable sources, Jordan is not responsible for any errors or omissions, or for the results obtained from the use of this information. All information in this post is provided “as is”, with no guarantee of completeness, accuracy, timeliness or of the results obtained from the use of this information, and without warranty of any kind, express or implied, including, but not limited to warranties of performance, merchantability and fitness for a particular purpose. In no event will Jordan, his related partnerships or corporations, or the partners, agents or employees thereof be liable to you or anyone else for any decision made or action taken in reliance on the information in this post or for any consequential, special or similar damages, even if advised of the possibility of such damages.

4 Likes