Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add translation string support #10995

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ file(GLOB_RECURSE yaml_config_files ${PX4_SOURCE_DIR}/src/modules/*.yaml
${PX4_SOURCE_DIR}/src/drivers/*.yaml ${PX4_SOURCE_DIR}/src/lib/*.yaml)
add_custom_target(metadata_parameters
COMMAND ${CMAKE_COMMAND} -E make_directory ${PX4_BINARY_DIR}/docs
COMMAND ${CMAKE_COMMAND} -E make_directory ${PX4_SOURCE_DIR}/translations
COMMAND ${PYTHON_EXECUTABLE}
${PX4_SOURCE_DIR}/Tools/serial/generate_config.py --all-ports --params-file ${PX4_SOURCE_DIR}/src/generated_serial_params.c --config-files ${yaml_config_files}
COMMAND ${PYTHON_EXECUTABLE} ${PX4_SOURCE_DIR}/src/lib/parameters/px_process_params.py
Expand All @@ -494,6 +495,10 @@ add_custom_target(metadata_parameters
--src-path `find ${PX4_SOURCE_DIR}/src -maxdepth 4 -type d`
--inject-xml ${PX4_SOURCE_DIR}/src/lib/parameters/parameters_injected.xml
--xml ${PX4_BINARY_DIR}/docs/parameters.xml
COMMAND ${PYTHON_EXECUTABLE} ${PX4_SOURCE_DIR}/src/lib/parameters/px_process_params.py
--src-path `find ${PX4_SOURCE_DIR}/src -maxdepth 4 -type d`
--inject-xml ${PX4_SOURCE_DIR}/src/lib/parameters/parameters_injected.xml
--translation_xml ${PX4_SOURCE_DIR}/src/lib/parameters/translations/parameter_strings.xml
COMMENT "Generating full parameter metadata (markdown and xml)"
USES_TERMINAL
)
Expand Down
50 changes: 50 additions & 0 deletions src/lib/parameters/px4params/translationscanner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import xml.etree.ElementTree as ET
#import os
from os import listdir
from os.path import isfile, join, dirname, realpath, exists


def GetTranslations(filename=''):
lang_translations = dict()
# Get path to translation path

dir_path = dirname(realpath(__file__))
translation_path = dir_path.rsplit('/',1)[0]+'/translations/'
if not exists(translation_path):
#print("DEBUG: Translation direcory not found: %s" % translation_path)
return None
translation_files = [f for f in listdir(translation_path) if isfile(join(translation_path, f))]

# Get english dict
for filename in translation_files:
if filename=='parameter_strings.xml':
english_root = ET.parse(translation_path+filename)
lang_dict = dict()
for entry in english_root.findall("./entry"):
lang_dict[entry.attrib['key']]=entry.text
#print("DEBUG: %s " % entry.attrib['key'])
#print("DEBUG: %s " % entry.text)
lang_translations['en'] = lang_dict
break

# Return if no English version found (need for keys)
if len(lang_translations)==0:
return None

for filename in translation_files:
#print("DEBUG: %s" % filename)
if filename=='parameter_strings.xml':
continue
else:
root = ET.parse(translation_path+filename)
lang_dict = dict()
lang_key=filename.rsplit('-',1)[-1].rsplit('.',1)[0]
#print('DEBUG:lang_key: %s' % lang_key)
for entry in root.findall("./entry"):
key = entry.attrib['key']
entry_text = entry.text
# Only add string if it has changed from English
if key in lang_translations['en'] and not lang_translations['en'][key] == entry_text:
lang_dict[key]=entry_text
lang_translations[lang_key] = lang_dict
return lang_translations
18 changes: 17 additions & 1 deletion src/lib/parameters/px4params/xmlout.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def indent(elem, level=0):

class XMLOutput():

def __init__(self, groups, board, inject_xml_file_name):
def __init__(self, groups, board, inject_xml_file_name, translation_dict=None):
xml_parameters = ET.Element("parameters")
xml_version = ET.SubElement(xml_parameters, "version")
xml_version.text = "3"
Expand Down Expand Up @@ -75,8 +75,24 @@ def __init__(self, groups, board, inject_xml_file_name):
xml_value.attrib["index"] = index;
xml_value.text = param.GetBitmaskBit(index)

#Append translations - passed in to init as translation_dict
if translation_dict and len(translation_dict)>1: #At least English and one translation
xml_localization = ET.SubElement(xml_parameters, "localization")
for key, entries in translation_dict.items():
if not key == 'en':
#print('DEBUG:key: %s' % key)
locale = ET.SubElement(xml_localization, "locale")
locale.attrib["name"] = key
for string_key in entries:
string_element = ET.SubElement(locale, "strings")
string_element.attrib["original"] = translation_dict['en'][string_key]
string_element.attrib["translated"] = translation_dict[key][string_key]
else:
print('Warn: No parameter translations found')

indent(xml_parameters)
self.xml_document = ET.ElementTree(xml_parameters)


def Save(self, filename):
self.xml_document.write(filename, encoding="UTF-8")
129 changes: 129 additions & 0 deletions src/lib/parameters/px4params/xmlstringsout.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#
# Export all parameter strings for translation into key/value file.
#

import xml.etree.ElementTree as ET
import codecs
import os

def indent(elem, level=0):
i = "\n" + level*" "
if len(elem):
if not elem.text or not elem.text.strip():
elem.text = i + " "
if not elem.tail or not elem.tail.strip():
elem.tail = i
for elem in elem:
indent(elem, level+1)
if not elem.tail or not elem.tail.strip():
elem.tail = i
else:
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i

class XMLOutput():

def __init__(self, groups, board, inject_xml_file_name):
unique_strings = set()
xml_parameters = ET.Element("properties")

for group in groups:
group_name=group.GetName()
if group_name not in unique_strings:
Copy link
Contributor

@bys1123 bys1123 Dec 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, looks like it is

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed :-)

This is waiting on @dagar - he will review and merge (if appropriate) when it gets near the top of his priority list.

xml_entry = ET.SubElement(xml_parameters, "entry")
xml_entry.attrib["key"] = 'group_%s' % group_name
#xml_entry.attrib["type"] = 'group'
xml_entry.text = group_name
unique_strings.add(group_name)
else:
pass

for param in group.GetParams():
param_name = param.GetName()
param_default = param.GetDefault()
param_type = param.GetType()
param_volatile = param.GetVolatile()
param_category = param.GetCategory()
#print("DEBUG: param_name: %s" % param_name)
#print("DEBUG: param_default: %s" % param_default)
#print("DEBUG: param type: %s" % param_type)
#print("DEBUG: param_volatile: %s" % param_volatile)
#print("DEBUG: param_category: %s" % param_category)

#Add param_category (if exists)
if param_category not in unique_strings and param_category:
xml_entry = ET.SubElement(xml_parameters, "entry")
xml_entry.attrib["key"] = 'category_%s' % param_category
#xml_entry.attrib["type"] = 'param_category'
#xml_entry.attrib["param"] = 'param_name'
xml_entry.text = param_category
unique_strings.add(param_category)
else:
pass

for code in param.GetFieldCodes():
value = param.GetFieldValue(code)
#print('DEBUG: code: %s, value: %s' % (code, value))
if code in ['short_desc','long_desc']: #Other fields are not translateable
if value not in unique_strings and value:
xml_entry = ET.SubElement(xml_parameters, "entry")
xml_entry.attrib["key"] = 'param_%s_%s' % (param_name,code)
#xml_entry.attrib["type"] = code
#xml_entry.attrib["param"] = param_name
xml_entry.text = value
unique_strings.add(value)
else:
pass



if len(param.GetEnumCodes()) > 0:
for code in param.GetEnumCodes():
value = param.GetEnumValue(code)
#print('DEBUG: code: %s, value: %s' % (code, value))
if value not in unique_strings and value:
xml_entry = ET.SubElement(xml_parameters, "entry")
xml_entry.attrib["key"] = 'enum_%s_val_%s' % (param_name,code)
#xml_entry.attrib["type"] = 'enumvalue'
#xml_entry.attrib["value"] = code
#xml_entry.attrib["param"] = param_name
xml_entry.text = value
unique_strings.add(value)
else:
pass

if len(param.GetBitmaskList()) > 0:
for index in param.GetBitmaskList():
value = param.GetBitmaskBit(index)
#print('DEBUG: index: %s, value: %s' % (index, value))
if value not in unique_strings and value:
xml_entry = ET.SubElement(xml_parameters, "entry")
xml_entry.attrib["key"] = 'bitmask_%s_index_%s' % (param_name,index)
#xml_entry.attrib["type"] = 'bit'
#xml_entry.attrib["value"] = index
#xml_entry.attrib["param"] = param_name
xml_entry.text = value
unique_strings.add(value)
else:
pass



indent(xml_parameters)
self.xml_document = ET.ElementTree(xml_parameters)

def Save(self, filename):
# Create target directory & all intermediate directories if don't exists
dirname=filename.rsplit('/',1)[0]
if not os.path.exists(dirname):
os.makedirs(dirname)

self.xml_document.write(filename, encoding="UTF-8")
# Add doctype (Clunky, but not possible to avoid in ElementTree)
f=open(filename, "r")
filetext=f.read()
f.close
filetext=filetext.replace('<properties>','<!DOCTYPE properties SYSTEM "[http://java.sun.com/dtd/properties.dtd](http://java.sun.com/dtd/properties.dtd)">\n<properties>')
with open(filename, "w") as f:
f.write(filetext)

34 changes: 28 additions & 6 deletions src/lib/parameters/px_process_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
import sys
import os
import argparse
from px4params import srcscanner, srcparser, xmlout, markdownout
from px4params import srcscanner, srcparser, xmlout, xmlstringsout, markdownout, translationscanner

import re
import json
Expand Down Expand Up @@ -84,6 +84,12 @@ def main():
metavar="FILENAME",
help="Create Markdown file"
" (default FILENAME: parameters.md)")
parser.add_argument("-t", "--translation_xml",
nargs='?',
const="parameter_strings.xml",
metavar="FILENAME",
help="Create translation string file"
" (default FILENAME: parameter_strings.xml)")
parser.add_argument('-v', '--verbose',
action='store_true',
help="verbose output")
Expand All @@ -95,7 +101,7 @@ def main():
args = parser.parse_args()

# Check for valid command
if not (args.xml or args.markdown):
if not (args.xml or args.markdown or args.translation_xml):
print("Error: You need to specify at least one output method!\n")
parser.print_usage()
sys.exit(1)
Expand Down Expand Up @@ -128,21 +134,37 @@ def main():
param.default = val
print("OVERRIDING {:s} to {:s}!!!!!".format(name, val))



# Load current translation info from Firmware/translations
lang_translations = translationscanner.GetTranslations()

# Output to XML file
if args.xml:
if args.verbose:
print("Creating XML file " + args.xml)
cur_dir = os.path.dirname(os.path.realpath(__file__))
out = xmlout.XMLOutput(param_groups, args.board,
os.path.join(cur_dir, args.inject_xml))
os.path.join(cur_dir, args.inject_xml),
lang_translations)
out.Save(args.xml)

# Output to XML translation string file
if args.translation_xml:
if args.verbose:
print("Creating translation string XML file " + args.translation_xml)
cur_dir = os.path.dirname(os.path.realpath(__file__))
out = xmlstringsout.XMLOutput(param_groups, args.board,
os.path.join(cur_dir, args.inject_xml))
#print("DEBUG:translation_xml: %s" % args.translation_xml)
out.Save(args.translation_xml)

# Output to Markdown/HTML tables
if args.markdown:
out = markdownout.MarkdownTablesOutput(param_groups)
if args.markdown:
if args.verbose:
print("Creating markdown file " + args.markdown)
out.Save(args.markdown)
out = markdownout.MarkdownTablesOutput(param_groups)
out.Save(args.markdown)

#print("All done!")

Expand Down