From 3698db62fdc8e4d4e938d66b1f243a80b79d13aa Mon Sep 17 00:00:00 2001 From: Jean-Christophe Fillion-Robin Date: Fri, 1 Feb 2019 07:48:55 -0500 Subject: [PATCH 1/5] ENH: Support for scripted module internationalization This commit adds CMake function "SlicerFunctionAddPythonScriptTrFilesTargets" used to ensure input expected by lupdate/lrelease translation tools are generated. The CMake function associates custom commands with each python scripts and also adds a convenience target called "AddPythonScriptTrFiles" to explicitly regenerate the .py.tr files. The custom commands generate the .py.tr files by invoking a python cli (CMake/Rewrite.py) replacing calls to "slicer.util.tr" with "QT_TRANSLATE_NOOP". The python cli "CMake/Rewrite.py" internally uses the astor python package. Updates SlicerConfig to set Slicer_BUILD_I18N_SUPPORT, Slicer_UPDATE_TRANSLATION and Slicer_LANGUAGES. Co-authored-by: Carlos Luque --- Base/Python/CMakeLists.txt | 1 + Base/Python/slicer/i18n.py | 4 ++ CMake/RewriteTr.py | 82 ++++++++++++++++++++++ CMake/SlicerConfig.cmake.in | 9 ++- CMake/SlicerMacroBuildScriptedModule.cmake | 66 +++++++++++++++++ CMakeLists.txt | 11 ++- Modules/Scripted/Endoscopy/Endoscopy.py | 12 ++-- SuperBuild.cmake | 4 ++ SuperBuild/External_python-astor.cmake | 45 ++++++++++++ 9 files changed, 226 insertions(+), 8 deletions(-) create mode 100644 Base/Python/slicer/i18n.py create mode 100644 CMake/RewriteTr.py create mode 100644 SuperBuild/External_python-astor.cmake diff --git a/Base/Python/CMakeLists.txt b/Base/Python/CMakeLists.txt index 9331ad9c957..25264b03b67 100644 --- a/Base/Python/CMakeLists.txt +++ b/Base/Python/CMakeLists.txt @@ -6,6 +6,7 @@ set(Slicer_PYTHON_SCRIPTS slicer/slicerqt slicer/testing slicer/util + slicer/i18n freesurfer mrml vtkAddon diff --git a/Base/Python/slicer/i18n.py b/Base/Python/slicer/i18n.py new file mode 100644 index 00000000000..a453a3a3e25 --- /dev/null +++ b/Base/Python/slicer/i18n.py @@ -0,0 +1,4 @@ + +def tr(context, text): + from slicer import app + return app.translate(context, text) diff --git a/CMake/RewriteTr.py b/CMake/RewriteTr.py new file mode 100644 index 00000000000..58b919eb72d --- /dev/null +++ b/CMake/RewriteTr.py @@ -0,0 +1,82 @@ +import ast +import errno +import getopt +import os +import sys + +import astor + + +class RewriteTr(ast.NodeTransformer): + """Replace tr to QT_TRANSLATE_NOOP + """ + def visit_Call(self, node): + self.generic_visit(node) + # Transform 'tr' into 'QT_TRANSLATE_NOOP' """ + if (isinstance(node.func, ast.Name) and \ + ("tr" == node.func.id) and \ + len(node.args) == 2): + call = ast.Call(func=ast.Name(id='QT_TRANSLATE_NOOP', ctx=ast.Load()), + args=node.args, + keywords=[]) + ast.copy_location(call, node) + # Add lineno & col_offset to the nodes we created + ast.fix_missing_locations(call) + return call + + # Return the original node if we don't want to change it. + return node + + +def mkdir_p(path): + """Ensure directory ``path`` exists. If needed, parent directories + are created. + Adapted from http://stackoverflow.com/a/600612/1539918 + """ + try: + os.makedirs(path) + except OSError as exc: # Python >2.5 + if exc.errno == errno.EEXIST and os.path.isdir(path): + pass + else: # pragma: no cover + raise + + +def main(argv): + + input_file = '' + output_file = '' + try: + opts, args = getopt.getopt(argv, "hi:o:", ["ifile=","ofile="]) + except getopt.GetoptError: + print('RewriteTr.py -i -o ') + sys.exit(2) + for opt, arg in opts: + if opt == '-h': + print('RewriteTr.py -i -o ') + sys.exit() + elif opt in ("-i", "--ifile"): + input_file = arg + elif opt in ("-o", "--ofile"): + output_file = arg + + with open(input_file, "r") as source: + tree = ast.parse(source.read()) + + tree_new = RewriteTr().visit(tree) + all_lines = astor.to_source(tree_new) + + # if needed, create output directory + output_dir = os.path.dirname(output_file) + #print("output_dir [%s]" % output_dir) + mkdir_p(output_dir) + + # replace the single quotation marks to double quotation marks. It is necessary for lupdate + with open(output_file, "w") as destination: + for line in all_lines: + linenew = line.replace('\'', "\"") + destination.write(linenew) + + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/CMake/SlicerConfig.cmake.in b/CMake/SlicerConfig.cmake.in index 585f1791930..1423695fbf2 100644 --- a/CMake/SlicerConfig.cmake.in +++ b/CMake/SlicerConfig.cmake.in @@ -126,6 +126,12 @@ set(Slicer_BUILD_EXTENSIONMANAGER_SUPPORT "@Slicer_BUILD_EXTENSIONMANAGER_SUPPOR set(Slicer_BUILD_PARAMETERSERIALIZER_SUPPORT "@Slicer_BUILD_PARAMETERSERIALIZER_SUPPORT@") set(Slicer_BUILD_TESTING "@BUILD_TESTING@") set(Slicer_BUILD_WEBENGINE_SUPPORT "@Slicer_BUILD_WEBENGINE_SUPPORT@") +set(Slicer_BUILD_I18N_SUPPORT "@Slicer_BUILD_I18N_SUPPORT@") +set(Slicer_UPDATE_TRANSLATION "@Slicer_UPDATE_TRANSLATION@") + +if(Slicer_BUILD_I18N_SUPPORT) + set(Slicer_LANGUAGES "@Slicer_LANGUAGES@") +endif() set(Slicer_REQUIRED_QT_VERSION "@Slicer_REQUIRED_QT_VERSION@") set(Slicer_REQUIRED_QT_MODULES "@Slicer_REQUIRED_QT_MODULES@") @@ -348,6 +354,8 @@ if(Slicer_USE_PYTHONQT) set(Slicer_INSTALL_QTSCRIPTEDMODULES_SHARE_DIR "@Slicer_INSTALL_QTSCRIPTEDMODULES_SHARE_DIR@") endif() +set(Slicer_INSTALL_QM_DIR "@Slicer_INSTALL_QM_DIR@") + set(Slicer_INSTALL_THIRDPARTY_BIN_DIR "${Slicer_INSTALL_ROOT}${Slicer_BUNDLE_EXTENSIONS_LOCATION}${Slicer_THIRDPARTY_BIN_DIR}") set(Slicer_INSTALL_THIRDPARTY_LIB_DIR "${Slicer_INSTALL_ROOT}${Slicer_BUNDLE_EXTENSIONS_LOCATION}${Slicer_THIRDPARTY_LIB_DIR}") set(Slicer_INSTALL_THIRDPARTY_SHARE_DIR "${Slicer_INSTALL_ROOT}${Slicer_BUNDLE_EXTENSIONS_LOCATION}${Slicer_THIRDPARTY_SHARE_DIR}") @@ -355,7 +363,6 @@ set(Slicer_INSTALL_THIRDPARTY_SHARE_DIR "${Slicer_INSTALL_ROOT}${Slicer_BUNDLE_E # The Slicer install prefix (*not* defined in the install tree) set(Slicer_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@") - # -------------------------------------------------------------------------- # Testing # -------------------------------------------------------------------------- diff --git a/CMake/SlicerMacroBuildScriptedModule.cmake b/CMake/SlicerMacroBuildScriptedModule.cmake index 3cf67d4653a..dbd035fc3e1 100644 --- a/CMake/SlicerMacroBuildScriptedModule.cmake +++ b/CMake/SlicerMacroBuildScriptedModule.cmake @@ -97,6 +97,9 @@ macro(slicerMacroBuildScriptedModule) set(_no_install_subdir_option "") endif() + # -------------------------------------------------------------------------- + # Copy and/or compile scripts and associated resources + # -------------------------------------------------------------------------- ctkMacroCompilePythonScript( TARGET_NAME ${MY_SLICER_NAME} SCRIPTS "${MY_SLICER_SCRIPTS}" @@ -106,6 +109,16 @@ macro(slicerMacroBuildScriptedModule) ${_no_install_subdir_option} ) + # -------------------------------------------------------------------------- + # Translations + # -------------------------------------------------------------------------- + if("${CTK_COMPILE_PYTHON_SCRIPTS_GLOBAL_TARGET_NAME}" STREQUAL "") + SlicerFunctionAddPythonScriptTrFilesTargets(${MY_SLICER_NAME}) + endif() + + # -------------------------------------------------------------------------- + # Tests + # -------------------------------------------------------------------------- if(BUILD_TESTING AND MY_SLICER_WITH_GENERIC_TESTS) set(_generic_unitest_scripts) SlicerMacroConfigureGenericPythonModuleTests("${MY_SLICER_NAME}" _generic_unitest_scripts) @@ -122,3 +135,56 @@ macro(slicerMacroBuildScriptedModule) endmacro() +function(SlicerFunctionAddPythonScriptTrFilesTargets target) + + set(rewrite_script "${Slicer_CMAKE_DIR}/RewriteTr.py") + if(NOT EXISTS ${rewrite_script}) + message(FATAL_ERROR "Rewrite script does not exist [${rewrite_script}]") + endif() + + set(TS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Resources/Translations/") + + #get_property(Slicer_LANGUAGES GLOBAL PROPERTY Slicer_LANGUAGES) + + get_property(_CTK_${target}_PYTHON_SCRIPTS GLOBAL PROPERTY _CTK_${target}_PYTHON_SCRIPTS) + + set(rewritten_srcs) + foreach(entry IN LISTS _CTK_${target}_PYTHON_SCRIPTS) + string(REPLACE "|" ";" tuple "${entry}") + list(GET tuple 0 src) + list(GET tuple 1 tgt_file) + list(GET tuple 2 dest_dir) + + set(rewritten_src_file "${tgt_file}.tr") + set(rewritten_src "${dest_dir}/${rewritten_src_file}") + + add_custom_command(DEPENDS ${src} + COMMAND ${PYTHON_EXECUTABLE} + ${rewrite_script} -i ${src} -o ${rewritten_src} + OUTPUT ${rewritten_src} + COMMENT "Generating .py.tr file into binary directory: ${rewritten_src_file}") + + list(APPEND rewritten_srcs ${rewritten_src}) + endforeach() + + include(SlicerMacroTranslation) + SlicerMacroTranslation( + SRCS ${rewritten_srcs} + TS_DIR ${TS_DIR} + TS_BASEFILENAME ${target} + TS_LANGUAGES ${Slicer_LANGUAGES} + QM_OUTPUT_DIR_VAR QM_OUTPUT_DIR + QM_OUTPUT_FILES_VAR QM_OUTPUT_FILES + ) + + # store the paths where the qm files are located + set_property(GLOBAL APPEND PROPERTY Slicer_QM_OUTPUT_DIRS ${QM_OUTPUT_DIR}) + + # store the qm files associated with scripted modules + set_property(GLOBAL APPEND PROPERTY QM_SCRIPTED_MODULE_FILES ${QM_OUTPUT_FILES}) + + set(target_name Add${target}PythonScriptTrFiles) + if(NOT TARGET ${target_name}) + add_custom_target(${target_name} DEPENDS ${rewritten_srcs} ${ARGN}) + endif() +endfunction() diff --git a/CMakeLists.txt b/CMakeLists.txt index fbc16a5210d..3b25f4d6a4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -417,7 +417,8 @@ include(SlicerFunctionAddPythonQtResources) #----------------------------------------------------------------------------- if(Slicer_BUILD_I18N_SUPPORT) set(Slicer_LANGUAGES - "fr" + "es_Es" + "fr_FR" ) set_property(GLOBAL PROPERTY Slicer_LANGUAGES ${Slicer_LANGUAGES}) endif() @@ -1151,10 +1152,16 @@ ExternalData_Add_Target(${Slicer_ExternalData_DATA_MANAGEMENT_TARGET}) #----------------------------------------------------------------------------- # Create targets CopySlicerPython{Resource, Script}Files, CompileSlicerPythonFiles if(Slicer_USE_PYTHONQT) + slicerFunctionAddPythonQtResourcesTargets(SlicerPythonResources) ctkFunctionAddCompilePythonScriptTargets( ${CTK_COMPILE_PYTHON_SCRIPTS_GLOBAL_TARGET_NAME} - DEPENDS SlicerPythonResources + DEPENDS + SlicerPythonResources + ) + + SlicerFunctionAddPythonScriptTrFilesTargets( + ${CTK_COMPILE_PYTHON_SCRIPTS_GLOBAL_TARGET_NAME} ) endif() diff --git a/Modules/Scripted/Endoscopy/Endoscopy.py b/Modules/Scripted/Endoscopy/Endoscopy.py index 73a4c9819f1..461f2916a79 100644 --- a/Modules/Scripted/Endoscopy/Endoscopy.py +++ b/Modules/Scripted/Endoscopy/Endoscopy.py @@ -5,6 +5,8 @@ from slicer.ScriptedLoadableModule import * import logging +from slicer.i18n import tr + # # Endoscopy # @@ -64,7 +66,7 @@ def setup(self): # Path collapsible button pathCollapsibleButton = ctk.ctkCollapsibleButton() - pathCollapsibleButton.text = "Path" + pathCollapsibleButton.text = tr("EndoscopyWidget", "Path") self.layout.addWidget(pathCollapsibleButton) # Layout within the path collapsible button @@ -80,7 +82,7 @@ def setup(self): cameraNodeSelector.removeEnabled = False cameraNodeSelector.connect('currentNodeChanged(bool)', self.enableOrDisableCreateButton) cameraNodeSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.setCameraNode) - pathFormLayout.addRow("Camera:", cameraNodeSelector) + pathFormLayout.addRow(tr("EndoscopyWidget", "Camera:"), cameraNodeSelector) self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)', cameraNodeSelector, 'setMRMLScene(vtkMRMLScene*)') @@ -94,12 +96,12 @@ def setup(self): inputFiducialsNodeSelector.addEnabled = False inputFiducialsNodeSelector.removeEnabled = False inputFiducialsNodeSelector.connect('currentNodeChanged(bool)', self.enableOrDisableCreateButton) - pathFormLayout.addRow("Input Fiducials:", inputFiducialsNodeSelector) + pathFormLayout.addRow(tr("EndoscopyWidget", "Input Fiducials:"), inputFiducialsNodeSelector) self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)', inputFiducialsNodeSelector, 'setMRMLScene(vtkMRMLScene*)') # CreatePath button - createPathButton = qt.QPushButton("Create path") + createPathButton = qt.QPushButton(tr("EndoscopyWidget", "Create path")) createPathButton.toolTip = "Create the path." createPathButton.enabled = False pathFormLayout.addRow(createPathButton) @@ -108,7 +110,7 @@ def setup(self): # Flythrough collapsible button flythroughCollapsibleButton = ctk.ctkCollapsibleButton() - flythroughCollapsibleButton.text = "Flythrough" + flythroughCollapsibleButton.text = tr("EndoscopyWidget", "Flythrough") flythroughCollapsibleButton.enabled = False self.layout.addWidget(flythroughCollapsibleButton) diff --git a/SuperBuild.cmake b/SuperBuild.cmake index 3e8c4ea481a..2fde0f738f8 100644 --- a/SuperBuild.cmake +++ b/SuperBuild.cmake @@ -155,6 +155,10 @@ if(Slicer_USE_PYTHONQT) endif() endif() +if(Slicer_BUILD_I18N_SUPPORT AND Slicer_USE_PYTHONQT) + list(APPEND Slicer_DEPENDENCIES python-astor) +endif() + if(Slicer_USE_TBB) list(APPEND Slicer_DEPENDENCIES tbb) endif() diff --git a/SuperBuild/External_python-astor.cmake b/SuperBuild/External_python-astor.cmake new file mode 100644 index 00000000000..37e36e8514c --- /dev/null +++ b/SuperBuild/External_python-astor.cmake @@ -0,0 +1,45 @@ +set(proj python-astor) + +# Set dependency list +set(${proj}_DEPENDENCIES python python-setuptools) + +if(NOT DEFINED Slicer_USE_SYSTEM_${proj}) + set(Slicer_USE_SYSTEM_${proj} ${Slicer_USE_SYSTEM_python}) +endif() + +# Include dependent projects if any +ExternalProject_Include_Dependencies(${proj} PROJECT_VAR proj DEPENDS_VAR ${proj}_DEPENDENCIES) + +if(Slicer_USE_SYSTEM_${proj}) + ExternalProject_FindPythonPackage( + MODULE_NAME "astor" + REQUIRED + ) +endif() + +if(NOT Slicer_USE_SYSTEM_${proj}) + + set(_version "0.7.1") + + ExternalProject_Add(${proj} + ${${proj}_EP_ARGS} + URL "https://files.pythonhosted.org/packages/99/80/f9482277c919d28bebd85813c0a70117214149a96b08981b72b63240b84c/astor-${_version}.tar.gz" + URL_HASH "SHA256=95c30d87a6c2cf89aa628b87398466840f0ad8652f88eb173125a6df8533fb8d" + DOWNLOAD_DIR ${CMAKE_BINARY_DIR} + SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj} + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND ${PYTHON_EXECUTABLE} setup.py install + LOG_INSTALL 1 + DEPENDS + ${${proj}_DEPENDENCIES} + ) + + ExternalProject_GenerateProjectDescription_Step(${proj} + VERSION ${_version} + ) + +else() + ExternalProject_Add_Empty(${proj} DEPENDS ${${proj}_DEPENDENCIES}) +endif() From 53f379c1ac068d66276511d878a496e4ac8e07b2 Mon Sep 17 00:00:00 2001 From: Jean-Christophe Fillion-Robin Date: Wed, 26 Jun 2019 05:07:28 -0400 Subject: [PATCH 2/5] ENH: i18n: Add GenerateSlicerTranslationQMFiles target Removes the dependency of library to *.qm files and instead add the target GenerateSlicerTranslationQMFiles allowing to explicitly re-generate the '*.qm" files.. --- CMake/SlicerMacroBuildApplication.cmake | 11 +- CMake/SlicerMacroBuildBaseQtLibrary.cmake | 11 +- CMake/SlicerMacroBuildLoadableModule.cmake | 9 +- CMake/SlicerMacroBuildModuleWidgets.cmake | 10 +- CMake/SlicerMacroBuildScriptedModule.cmake | 80 ++++-------- CMake/SlicerMacroTranslation.cmake | 138 ++++++++++++++++----- CMakeLists.txt | 42 ++++--- Libs/MRML/Widgets/CMakeLists.txt | 11 +- 8 files changed, 158 insertions(+), 154 deletions(-) diff --git a/CMake/SlicerMacroBuildApplication.cmake b/CMake/SlicerMacroBuildApplication.cmake index af90539c4d8..30d40f9f67e 100644 --- a/CMake/SlicerMacroBuildApplication.cmake +++ b/CMake/SlicerMacroBuildApplication.cmake @@ -175,9 +175,7 @@ macro(slicerMacroBuildAppLibrary) # Translation # -------------------------------------------------------------------------- if(Slicer_BUILD_I18N_SUPPORT) - set(TS_DIR - "${CMAKE_CURRENT_SOURCE_DIR}/Resources/Translations/" - ) + set(TS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Resources/Translations") get_property(Slicer_LANGUAGES GLOBAL PROPERTY Slicer_LANGUAGES) include(SlicerMacroTranslation) @@ -187,13 +185,7 @@ macro(slicerMacroBuildAppLibrary) TS_DIR ${TS_DIR} TS_BASEFILENAME ${SLICERAPPLIB_NAME} TS_LANGUAGES ${Slicer_LANGUAGES} - QM_OUTPUT_DIR_VAR QM_OUTPUT_DIR - QM_OUTPUT_FILES_VAR QM_OUTPUT_FILES ) - - set_property(GLOBAL APPEND PROPERTY Slicer_QM_OUTPUT_DIRS ${QM_OUTPUT_DIR}) - else() - set(QM_OUTPUT_FILES ) endif() # -------------------------------------------------------------------------- @@ -204,7 +196,6 @@ macro(slicerMacroBuildAppLibrary) ${SLICERAPPLIB_MOC_OUTPUT} ${SLICERAPPLIB_UI_CXX} ${SLICERAPPLIB_QRC_SRCS} - ${QM_OUTPUT_FILES} ) set_target_properties(${lib_name} PROPERTIES LABELS ${lib_name}) diff --git a/CMake/SlicerMacroBuildBaseQtLibrary.cmake b/CMake/SlicerMacroBuildBaseQtLibrary.cmake index e7ba64316d0..2eca91d7bf2 100644 --- a/CMake/SlicerMacroBuildBaseQtLibrary.cmake +++ b/CMake/SlicerMacroBuildBaseQtLibrary.cmake @@ -174,9 +174,7 @@ macro(SlicerMacroBuildBaseQtLibrary) # Translation # -------------------------------------------------------------------------- if(Slicer_BUILD_I18N_SUPPORT) - set(TS_DIR - "${CMAKE_CURRENT_SOURCE_DIR}/Resources/Translations/" - ) + set(TS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Resources/Translations") get_property(Slicer_LANGUAGES GLOBAL PROPERTY Slicer_LANGUAGES) include(SlicerMacroTranslation) @@ -186,13 +184,7 @@ macro(SlicerMacroBuildBaseQtLibrary) TS_DIR ${TS_DIR} TS_BASEFILENAME ${SLICERQTBASELIB_NAME} TS_LANGUAGES ${Slicer_LANGUAGES} - QM_OUTPUT_DIR_VAR QM_OUTPUT_DIR - QM_OUTPUT_FILES_VAR QM_OUTPUT_FILES ) - - set_property(GLOBAL APPEND PROPERTY Slicer_QM_OUTPUT_DIRS ${QM_OUTPUT_DIR}) - else() - set(QM_OUTPUT_FILES ) endif() # -------------------------------------------------------------------------- @@ -203,7 +195,6 @@ macro(SlicerMacroBuildBaseQtLibrary) ${SLICERQTBASELIB_MOC_OUTPUT} ${SLICERQTBASELIB_UI_CXX} ${SLICERQTBASELIB_QRC_SRCS} - ${QM_OUTPUT_FILES} ) set_target_properties(${lib_name} PROPERTIES LABELS ${lib_name}) diff --git a/CMake/SlicerMacroBuildLoadableModule.cmake b/CMake/SlicerMacroBuildLoadableModule.cmake index 197d485a4b3..e3e5b1646ca 100644 --- a/CMake/SlicerMacroBuildLoadableModule.cmake +++ b/CMake/SlicerMacroBuildLoadableModule.cmake @@ -167,7 +167,7 @@ macro(slicerMacroBuildLoadableModule) # Translation # -------------------------------------------------------------------------- if(Slicer_BUILD_I18N_SUPPORT) - set(TS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Resources/Translations/") + set(TS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Resources/Translations") get_property(Slicer_LANGUAGES GLOBAL PROPERTY Slicer_LANGUAGES) include(SlicerMacroTranslation) @@ -177,13 +177,7 @@ macro(slicerMacroBuildLoadableModule) TS_DIR ${TS_DIR} TS_BASEFILENAME ${LOADABLEMODULE_NAME} TS_LANGUAGES ${Slicer_LANGUAGES} - QM_OUTPUT_DIR_VAR QM_OUTPUT_DIR - QM_OUTPUT_FILES_VAR QM_OUTPUT_FILES ) - set_property(GLOBAL APPEND PROPERTY Slicer_QM_OUTPUT_DIRS ${QM_OUTPUT_DIR}) - - else() - set(QM_OUTPUT_FILES ) endif() # -------------------------------------------------------------------------- @@ -194,7 +188,6 @@ macro(slicerMacroBuildLoadableModule) ${LOADABLEMODULE_MOC_OUTPUT} ${LOADABLEMODULE_UI_CXX} ${LOADABLEMODULE_QRC_SRCS} - ${QM_OUTPUT_FILES} ) # Set loadable modules output path diff --git a/CMake/SlicerMacroBuildModuleWidgets.cmake b/CMake/SlicerMacroBuildModuleWidgets.cmake index e67d93242f2..e274ff2b9c9 100644 --- a/CMake/SlicerMacroBuildModuleWidgets.cmake +++ b/CMake/SlicerMacroBuildModuleWidgets.cmake @@ -83,7 +83,7 @@ macro(SlicerMacroBuildModuleWidgets) # Translation #----------------------------------------------------------------------------- if(Slicer_BUILD_I18N_SUPPORT) - set(TS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Resources/Translations/") + set(TS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Resources/Translations") get_property(Slicer_LANGUAGES GLOBAL PROPERTY Slicer_LANGUAGES) include(SlicerMacroTranslation) @@ -93,13 +93,7 @@ macro(SlicerMacroBuildModuleWidgets) TS_DIR ${TS_DIR} TS_BASEFILENAME ${MODULEWIDGETS_NAME} TS_LANGUAGES ${Slicer_LANGUAGES} - QM_OUTPUT_DIR_VAR QM_OUTPUT_DIR - QM_OUTPUT_FILES_VAR QM_OUTPUT_FILES ) - set_property(GLOBAL APPEND PROPERTY Slicer_QM_OUTPUT_DIRS ${QM_OUTPUT_DIR}) - - else() - set(QM_OUTPUT_FILES ) endif() # -------------------------------------------------------------------------- @@ -110,7 +104,7 @@ macro(SlicerMacroBuildModuleWidgets) EXPORT_DIRECTIVE ${MODULEWIDGETS_EXPORT_DIRECTIVE} FOLDER ${MODULEWIDGETS_FOLDER} INCLUDE_DIRECTORIES ${MODULEWIDGETS_INCLUDE_DIRECTORIES} - SRCS ${MODULEWIDGETS_SRCS} ${QM_OUTPUT_FILES} + SRCS ${MODULEWIDGETS_SRCS} MOC_SRCS ${MODULEWIDGETS_MOC_SRCS} UI_SRCS ${MODULEWIDGETS_UI_SRCS} TARGET_LIBRARIES ${MODULEWIDGETS_TARGET_LIBRARIES} diff --git a/CMake/SlicerMacroBuildScriptedModule.cmake b/CMake/SlicerMacroBuildScriptedModule.cmake index dbd035fc3e1..d75c2a6a21d 100644 --- a/CMake/SlicerMacroBuildScriptedModule.cmake +++ b/CMake/SlicerMacroBuildScriptedModule.cmake @@ -112,9 +112,29 @@ macro(slicerMacroBuildScriptedModule) # -------------------------------------------------------------------------- # Translations # -------------------------------------------------------------------------- - if("${CTK_COMPILE_PYTHON_SCRIPTS_GLOBAL_TARGET_NAME}" STREQUAL "") - SlicerFunctionAddPythonScriptTrFilesTargets(${MY_SLICER_NAME}) - endif() + + set(scripts ) + foreach(file IN ITEMS ${MY_SLICER_SCRIPTS}) + # Append "py" extension if needed + get_filename_component(file_ext ${file} EXT) + if(NOT "${file_ext}" MATCHES "py") + set(file "${file}.py") + endif() + list(APPEND scripts ${file}) + endforeach() + + set(TS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Resources/Translations") + include(SlicerMacroTranslation) + SlicerMacroTranslation( + SRCS ${scripts} + TS_DIR ${TS_DIR} + TS_BASEFILENAME ${MY_SLICER_NAME} + TS_LANGUAGES ${Slicer_LANGUAGES} + ) + + #if("${CTK_COMPILE_PYTHON_SCRIPTS_GLOBAL_TARGET_NAME}" STREQUAL "") + # SlicerFunctionAddPythonScriptTrFilesTargets(${MY_SLICER_NAME}) + #endif() # -------------------------------------------------------------------------- # Tests @@ -134,57 +154,3 @@ macro(slicerMacroBuildScriptedModule) endif() endmacro() - -function(SlicerFunctionAddPythonScriptTrFilesTargets target) - - set(rewrite_script "${Slicer_CMAKE_DIR}/RewriteTr.py") - if(NOT EXISTS ${rewrite_script}) - message(FATAL_ERROR "Rewrite script does not exist [${rewrite_script}]") - endif() - - set(TS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Resources/Translations/") - - #get_property(Slicer_LANGUAGES GLOBAL PROPERTY Slicer_LANGUAGES) - - get_property(_CTK_${target}_PYTHON_SCRIPTS GLOBAL PROPERTY _CTK_${target}_PYTHON_SCRIPTS) - - set(rewritten_srcs) - foreach(entry IN LISTS _CTK_${target}_PYTHON_SCRIPTS) - string(REPLACE "|" ";" tuple "${entry}") - list(GET tuple 0 src) - list(GET tuple 1 tgt_file) - list(GET tuple 2 dest_dir) - - set(rewritten_src_file "${tgt_file}.tr") - set(rewritten_src "${dest_dir}/${rewritten_src_file}") - - add_custom_command(DEPENDS ${src} - COMMAND ${PYTHON_EXECUTABLE} - ${rewrite_script} -i ${src} -o ${rewritten_src} - OUTPUT ${rewritten_src} - COMMENT "Generating .py.tr file into binary directory: ${rewritten_src_file}") - - list(APPEND rewritten_srcs ${rewritten_src}) - endforeach() - - include(SlicerMacroTranslation) - SlicerMacroTranslation( - SRCS ${rewritten_srcs} - TS_DIR ${TS_DIR} - TS_BASEFILENAME ${target} - TS_LANGUAGES ${Slicer_LANGUAGES} - QM_OUTPUT_DIR_VAR QM_OUTPUT_DIR - QM_OUTPUT_FILES_VAR QM_OUTPUT_FILES - ) - - # store the paths where the qm files are located - set_property(GLOBAL APPEND PROPERTY Slicer_QM_OUTPUT_DIRS ${QM_OUTPUT_DIR}) - - # store the qm files associated with scripted modules - set_property(GLOBAL APPEND PROPERTY QM_SCRIPTED_MODULE_FILES ${QM_OUTPUT_FILES}) - - set(target_name Add${target}PythonScriptTrFiles) - if(NOT TARGET ${target_name}) - add_custom_target(${target_name} DEPENDS ${rewritten_srcs} ${ARGN}) - endif() -endfunction() diff --git a/CMake/SlicerMacroTranslation.cmake b/CMake/SlicerMacroTranslation.cmake index 72bf849e305..f5f0d312af2 100644 --- a/CMake/SlicerMacroTranslation.cmake +++ b/CMake/SlicerMacroTranslation.cmake @@ -32,22 +32,16 @@ # # TS_LANGUAGES...........: Variable with all the languages # -# QM_OUTPUT_DIR_VAR .....: Translation's dirs generated by the macro -# -# QM_OUTPUT_FILES_VAR....: Translation's files generated by the macro -# function(SlicerMacroTranslation) set(options) - set(oneValueArgs QM_OUTPUT_DIR_VAR TS_DIR TS_BASEFILENAME) - set(multiValueArgs SRCS UI_SRCS TS_LANGUAGES QM_OUTPUT_FILES_VAR) + set(oneValueArgs TS_DIR TS_BASEFILENAME) + set(multiValueArgs SRCS UI_SRCS TS_LANGUAGES) cmake_parse_arguments(MY "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) # --------------------------------------------------------------------------------- # Sanity Checks # --------------------------------------------------------------------------------- - #set(expected_nonempty_vars SRCS UI_SRCS TS_INPUT) -#add TS_LANGUAGES also set(expected_nonempty_vars SRCS TS_DIR TS_BASEFILENAME ) foreach(var ${expected_nonempty_vars}) if("${MY_${var}}" STREQUAL "") @@ -56,20 +50,22 @@ function(SlicerMacroTranslation) endforeach() # --------------------------------------------------------------------------------- - # Set File to translate + # Set FILES_TO_TRANSLATE # --------------------------------------------------------------------------------- - - set(FILES_TO_TRANSLATE - ${MY_SRCS} - ${MY_UI_SRCS} - ) + set(FILES_TO_TRANSLATE ) + foreach(file IN LISTS MY_SRCS MY_UI_SRCS) + if(NOT IS_ABSOLUTE ${file}) + set(file ${CMAKE_CURRENT_SOURCE_DIR}/${file}) + endif() + list(APPEND FILES_TO_TRANSLATE ${file}) + endforeach() # --------------------------------------------------------------------------------- # Set TS_FILES # --------------------------------------------------------------------------------- set(TS_FILES) foreach(language ${MY_TS_LANGUAGES}) - set(ts_file "${MY_TS_DIR}${MY_TS_BASEFILENAME}_${language}.ts") + set(ts_file "${MY_TS_DIR}/${MY_TS_BASEFILENAME}_${language}.ts") if(NOT Slicer_UPDATE_TRANSLATION AND NOT EXISTS ${ts_file}) continue() @@ -78,24 +74,110 @@ function(SlicerMacroTranslation) list(APPEND TS_FILES ${ts_file}) endforeach() + # --------------------------------------------------------------------------------- + # Set properties used in SlicerFunctionAddGenerateSlicerTranslationQMFilesTarget + # --------------------------------------------------------------------------------- + set_property(GLOBAL APPEND PROPERTY Slicer_TS_BASEFILENAMES ${MY_TS_BASEFILENAME}) + set_property(GLOBAL PROPERTY Slicer_${MY_TS_BASEFILENAME}_FILES_TO_TRANSLATE "${FILES_TO_TRANSLATE}") + set_property(GLOBAL PROPERTY Slicer_${MY_TS_BASEFILENAME}_TS_FILES "${TS_FILES}") + set_property(GLOBAL PROPERTY Slicer_${MY_TS_BASEFILENAME}_QM_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") + +endfunction() + + +function(SlicerFunctionAddGenerateSlicerTranslationQMFilesTarget) + set(options) + set(oneValueArgs ) + set(multiValueArgs QM_OUTPUT_DIRS_VAR) + cmake_parse_arguments(MY "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + # --------------------------------------------------------------------------------- + # Sanity Checks + # --------------------------------------------------------------------------------- + set(expected_nonempty_vars QM_OUTPUT_DIRS_VAR) + foreach(var ${expected_nonempty_vars}) + if("${MY_${var}}" STREQUAL "") + message(FATAL_ERROR "error: CMake variable ${var} is empty !") + endif() + endforeach() + + set(rewrite_script "${Slicer_CMAKE_DIR}/RewriteTr.py") + if(NOT EXISTS ${rewrite_script}) + message(FATAL_ERROR "Rewrite script does not exist [${rewrite_script}]") + endif() + + # --------------------------------------------------------------------------------- + set(qm_output_dirs) + set(rewritten_scripts_to_translate) + # --------------------------------------------------------------------------------- # UPDATE or ADD translation # --------------------------------------------------------------------------------- + get_property(ts_basefilenames GLOBAL PROPERTY Slicer_TS_BASEFILENAMES) + foreach(ts_basefilename IN LISTS ts_basefilenames) + get_property(files_to_translate GLOBAL PROPERTY Slicer_${ts_basefilename}_FILES_TO_TRANSLATE) + get_property(ts_files GLOBAL PROPERTY Slicer_${ts_basefilename}_TS_FILES) + get_property(qm_output_dir GLOBAL PROPERTY Slicer_${ts_basefilename}_QM_OUTPUT_DIR) + + # Keep track of cpp source files and python scripts independently + set(srcs_to_translate) + set(scripts_to_translate) + foreach(file IN LISTS files_to_translate) + get_filename_component(file_ext ${file} EXT) + if("${file_ext}" MATCHES "py") + list(APPEND scripts_to_translate ${file}) + else() + list(APPEND srcs_to_translate ${file}) + endif() + endforeach() + + # Add custom commands for rewriting python scripts + set(rewritten_scripts_to_translate_for_context) + if(Slicer_USE_PYTHONQT) + foreach(script IN LISTS scripts_to_translate) + set(rewritten_src_file "${script}.tr") + set(rewritten_src "${qm_output_dir}/${rewritten_src_file}") + + add_custom_command(DEPENDS ${script} + COMMAND ${PYTHON_EXECUTABLE} + ${rewrite_script} -i ${script} -o ${rewritten_src} + OUTPUT ${rewritten_src} + COMMENT "Generating .py.tr file into binary directory: ${rewritten_src_file}") + + list(APPEND rewritten_scripts_to_translate_for_context ${rewritten_src}) + endforeach() + endif() + + set_source_files_properties(${ts_files} PROPERTIES OUTPUT_LOCATION ${qm_output_dir}) if(Slicer_UPDATE_TRANSLATION) - QT5_CREATE_TRANSLATION(QM_OUTPUT_FILES ${FILES_TO_TRANSLATE} ${TS_FILES}) + # Add custom command for creating or updating "*_.ts" translation files, and for + # generating the associated "*_.qm" files. + QT5_CREATE_TRANSLATION( + QM_OUTPUT_FILES ${srcs_to_translate} ${rewritten_scripts_to_translate_for_context} ${ts_files} + OPTIONS -source-language en_US -no-ui-lines + ) else() - QT5_ADD_TRANSLATION(QM_OUTPUT_FILES ${TS_FILES}) + # Add custom command for generating the associated "*_.qm" files. + QT5_ADD_TRANSLATION(QM_OUTPUT_FILES ${ts_files}) endif() + list(APPEND rewritten_scripts_to_translate ${rewritten_scripts_to_translate_for_context}) + list(APPEND qm_output_dirs ${qm_output_dir}) + endforeach() + # --------------------------------------------------------------------------------- - # Set the variable qm_output_dir + # Targets # --------------------------------------------------------------------------------- - # Extract the path associated with the first file of the list QM_OUTPUT_FILES - # -> QM_OUTPUT_DIR + if(Slicer_USE_PYTHONQT) + add_custom_target(RewritePythonScriptsForTranslation DEPENDS + ${rewritten_scripts_to_translate} + ) + endif() - list(GET QM_OUTPUT_FILES 0 QM_OUTPUT_FIRST_FILE) - get_filename_component(qm_output_dir "${QM_OUTPUT_FIRST_FILE}" PATH) + add_custom_target(GenerateSlicerTranslationQMFiles ALL DEPENDS + ${QM_OUTPUT_FILES} + ) # --------------------------------------------------------------------------------- # Install language @@ -104,17 +186,11 @@ function(SlicerMacroTranslation) FILES ${QM_OUTPUT_FILES} DESTINATION ${Slicer_INSTALL_QM_DIR} COMPONENT Runtime - ) + ) # --------------------------------------------------------------------------------- - # ADD custom command and target - # --------------------------------------------------------------------------------- - - #add_custom_command(OUTPUT ${TS_FILES} DEPENDS ${FILES_TO_TRANSLATE} APPEND) - #add_custom_target(TS_TRANSLATE DEPENDS ${MY_QM_FILES}) - # Output variables - set(${MY_QM_OUTPUT_DIR_VAR} ${qm_output_dir} PARENT_SCOPE) - set(${MY_QM_OUTPUT_FILES_VAR} ${QM_OUTPUT_FILES} PARENT_SCOPE) + # --------------------------------------------------------------------------------- + set(${MY_QM_OUTPUT_DIRS_VAR} ${qm_output_dirs} PARENT_SCOPE) endfunction() diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b25f4d6a4f..7286498b433 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -417,8 +417,8 @@ include(SlicerFunctionAddPythonQtResources) #----------------------------------------------------------------------------- if(Slicer_BUILD_I18N_SUPPORT) set(Slicer_LANGUAGES - "es_Es" - "fr_FR" + "es_ES" + "fr_FR" ) set_property(GLOBAL PROPERTY Slicer_LANGUAGES ${Slicer_LANGUAGES}) endif() @@ -1046,9 +1046,27 @@ endforeach() unset(Slicer_DIR) # -------------------------------------------------------------------------- -# Recover the QM output directories +# Create targets CopySlicerPython{Resource, Script}Files, CompileSlicerPythonFiles +# -------------------------------------------------------------------------- +if(Slicer_USE_PYTHONQT) + slicerFunctionAddPythonQtResourcesTargets(SlicerPythonResources) + ctkFunctionAddCompilePythonScriptTargets( + ${CTK_COMPILE_PYTHON_SCRIPTS_GLOBAL_TARGET_NAME} + DEPENDS + SlicerPythonResources + ) +endif() + +# -------------------------------------------------------------------------- +# Create target GenerateSlicerTranslationQMFiles (Slicer_QM_OUTPUT_DIRS is used in vtkSlicerConfigure.h) # -------------------------------------------------------------------------- -get_property(Slicer_QM_OUTPUT_DIRS GLOBAL PROPERTY Slicer_QM_OUTPUT_DIRS) +if(Slicer_BUILD_I18N_SUPPORT) + SlicerFunctionAddGenerateSlicerTranslationQMFilesTarget( + QM_OUTPUT_DIRS_VAR Slicer_QM_OUTPUT_DIRS + ) +else() + set(Slicer_QM_OUTPUT_DIRS) +endif() # -------------------------------------------------------------------------- # Configure and install headers @@ -1149,22 +1167,6 @@ endif() # This must come after all tests have been added that reference the group, so we put it last. ExternalData_Add_Target(${Slicer_ExternalData_DATA_MANAGEMENT_TARGET}) -#----------------------------------------------------------------------------- -# Create targets CopySlicerPython{Resource, Script}Files, CompileSlicerPythonFiles -if(Slicer_USE_PYTHONQT) - - slicerFunctionAddPythonQtResourcesTargets(SlicerPythonResources) - ctkFunctionAddCompilePythonScriptTargets( - ${CTK_COMPILE_PYTHON_SCRIPTS_GLOBAL_TARGET_NAME} - DEPENDS - SlicerPythonResources - ) - - SlicerFunctionAddPythonScriptTrFilesTargets( - ${CTK_COMPILE_PYTHON_SCRIPTS_GLOBAL_TARGET_NAME} - ) -endif() - #----------------------------------------------------------------------------- # The commands in this directory are intended to be executed as # the end of the whole configuration process, as a "last step". diff --git a/Libs/MRML/Widgets/CMakeLists.txt b/Libs/MRML/Widgets/CMakeLists.txt index 649c1af2f1a..62bc0f49b9f 100644 --- a/Libs/MRML/Widgets/CMakeLists.txt +++ b/Libs/MRML/Widgets/CMakeLists.txt @@ -458,9 +458,7 @@ endif() # Translation # -------------------------------------------------------------------------- if(Slicer_BUILD_I18N_SUPPORT) - set(TS_DIR - "${CMAKE_CURRENT_SOURCE_DIR}/Resources/Translations/" - ) + set(TS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Resources/Translations") get_property(Slicer_LANGUAGES GLOBAL PROPERTY Slicer_LANGUAGES) include(SlicerMacroTranslation) @@ -470,13 +468,7 @@ endif() TS_DIR ${TS_DIR} TS_BASEFILENAME ${PROJECT_NAME} TS_LANGUAGES ${Slicer_LANGUAGES} - QM_OUTPUT_DIR_VAR QM_OUTPUT_DIR - QM_OUTPUT_FILES_VAR QM_OUTPUT_FILES ) - - set_property(GLOBAL APPEND PROPERTY Slicer_QM_OUTPUT_DIRS ${QM_OUTPUT_DIR}) - else() - set(QM_OUTPUT_FILES ) endif() # -------------------------------------------------------------------------- @@ -490,7 +482,6 @@ add_library(${lib_name} ${MRMLWidgets_MOC_CXX} ${MRMLWidgets_UI_CXX} ${MRMLWidgets_QRC_CXX} - ${QM_OUTPUT_FILES} ) set(MRMLWidgets_LIBRARIES From 3b6e3ffb5249d28ad2e463adcc09e619c255eebc Mon Sep 17 00:00:00 2001 From: Jean-Christophe Fillion-Robin Date: Fri, 28 Jun 2019 08:12:58 -0400 Subject: [PATCH 3/5] STYLE: i18n: Simplify buildsystem removing RewritePythonScriptsForTranslation target --- CMake/SlicerMacroTranslation.cmake | 7 ------- 1 file changed, 7 deletions(-) diff --git a/CMake/SlicerMacroTranslation.cmake b/CMake/SlicerMacroTranslation.cmake index f5f0d312af2..e90f9f02b70 100644 --- a/CMake/SlicerMacroTranslation.cmake +++ b/CMake/SlicerMacroTranslation.cmake @@ -108,7 +108,6 @@ function(SlicerFunctionAddGenerateSlicerTranslationQMFilesTarget) # --------------------------------------------------------------------------------- set(qm_output_dirs) - set(rewritten_scripts_to_translate) # --------------------------------------------------------------------------------- # UPDATE or ADD translation @@ -162,18 +161,12 @@ function(SlicerFunctionAddGenerateSlicerTranslationQMFilesTarget) QT5_ADD_TRANSLATION(QM_OUTPUT_FILES ${ts_files}) endif() - list(APPEND rewritten_scripts_to_translate ${rewritten_scripts_to_translate_for_context}) list(APPEND qm_output_dirs ${qm_output_dir}) endforeach() # --------------------------------------------------------------------------------- # Targets # --------------------------------------------------------------------------------- - if(Slicer_USE_PYTHONQT) - add_custom_target(RewritePythonScriptsForTranslation DEPENDS - ${rewritten_scripts_to_translate} - ) - endif() add_custom_target(GenerateSlicerTranslationQMFiles ALL DEPENDS ${QM_OUTPUT_FILES} From 5684447e810a49ddf57ccd37c6b7702a484e0887 Mon Sep 17 00:00:00 2001 From: Jean-Christophe Fillion-Robin Date: Fri, 28 Jun 2019 09:04:45 -0400 Subject: [PATCH 4/5] ENH: i18n: Add support for generating translation templates This commit adds GenerateSlicerTranslationTemplates target allowing to generate "_untranslated.ts" files. To facilitate their distribution, the files are generated in the directory "/TranslationTemplates". --- CMake/SlicerMacroTranslation.cmake | 73 +++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/CMake/SlicerMacroTranslation.cmake b/CMake/SlicerMacroTranslation.cmake index e90f9f02b70..d02c4b76364 100644 --- a/CMake/SlicerMacroTranslation.cmake +++ b/CMake/SlicerMacroTranslation.cmake @@ -67,7 +67,7 @@ function(SlicerMacroTranslation) foreach(language ${MY_TS_LANGUAGES}) set(ts_file "${MY_TS_DIR}/${MY_TS_BASEFILENAME}_${language}.ts") - if(NOT Slicer_UPDATE_TRANSLATION AND NOT EXISTS ${ts_file}) + if(NOT EXISTS ${ts_file}) continue() endif() @@ -79,6 +79,7 @@ function(SlicerMacroTranslation) # --------------------------------------------------------------------------------- set_property(GLOBAL APPEND PROPERTY Slicer_TS_BASEFILENAMES ${MY_TS_BASEFILENAME}) set_property(GLOBAL PROPERTY Slicer_${MY_TS_BASEFILENAME}_FILES_TO_TRANSLATE "${FILES_TO_TRANSLATE}") + set_property(GLOBAL PROPERTY Slicer_${MY_TS_BASEFILENAME}_TS_DIR "${MY_TS_DIR}") set_property(GLOBAL PROPERTY Slicer_${MY_TS_BASEFILENAME}_TS_FILES "${TS_FILES}") set_property(GLOBAL PROPERTY Slicer_${MY_TS_BASEFILENAME}_QM_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") @@ -108,6 +109,7 @@ function(SlicerFunctionAddGenerateSlicerTranslationQMFilesTarget) # --------------------------------------------------------------------------------- set(qm_output_dirs) + set(untranslated_ts_files) # --------------------------------------------------------------------------------- # UPDATE or ADD translation @@ -115,6 +117,7 @@ function(SlicerFunctionAddGenerateSlicerTranslationQMFilesTarget) get_property(ts_basefilenames GLOBAL PROPERTY Slicer_TS_BASEFILENAMES) foreach(ts_basefilename IN LISTS ts_basefilenames) get_property(files_to_translate GLOBAL PROPERTY Slicer_${ts_basefilename}_FILES_TO_TRANSLATE) + get_property(ts_dir GLOBAL PROPERTY Slicer_${ts_basefilename}_TS_DIR) get_property(ts_files GLOBAL PROPERTY Slicer_${ts_basefilename}_TS_FILES) get_property(qm_output_dir GLOBAL PROPERTY Slicer_${ts_basefilename}_QM_OUTPUT_DIR) @@ -147,8 +150,15 @@ function(SlicerFunctionAddGenerateSlicerTranslationQMFilesTarget) endforeach() endif() - set_source_files_properties(${ts_files} PROPERTIES OUTPUT_LOCATION ${qm_output_dir}) + # Add custom commands for creating or updating "*_untranslated.ts" files. + set(untranslated_ts_dir "${CMAKE_BINARY_DIR}/TranslationTemplates") + set(untranslated_ts_file ${untranslated_ts_dir}/${ts_basefilename}_untranslated.ts) + SLICER_CREATE_TRANSLATION_ONLY( + ${srcs_to_translate} ${rewritten_scripts_to_translate_for_context} ${untranslated_ts_file} + OPTIONS -source-language en_US -no-ui-lines + ) + set_source_files_properties(${ts_files} PROPERTIES OUTPUT_LOCATION ${qm_output_dir}) if(Slicer_UPDATE_TRANSLATION) # Add custom command for creating or updating "*_.ts" translation files, and for # generating the associated "*_.qm" files. @@ -161,6 +171,7 @@ function(SlicerFunctionAddGenerateSlicerTranslationQMFilesTarget) QT5_ADD_TRANSLATION(QM_OUTPUT_FILES ${ts_files}) endif() + list(APPEND untranslated_ts_files ${untranslated_ts_file}) list(APPEND qm_output_dirs ${qm_output_dir}) endforeach() @@ -168,6 +179,14 @@ function(SlicerFunctionAddGenerateSlicerTranslationQMFilesTarget) # Targets # --------------------------------------------------------------------------------- + set(_all) + if(Slicer_UPDATE_TRANSLATION) + set(_all ALL) + endif() + add_custom_target(GenerateSlicerTranslationTemplates ${_all} DEPENDS + ${untranslated_ts_files} + ) + add_custom_target(GenerateSlicerTranslationQMFiles ALL DEPENDS ${QM_OUTPUT_FILES} ) @@ -187,3 +206,53 @@ function(SlicerFunctionAddGenerateSlicerTranslationQMFilesTarget) set(${MY_QM_OUTPUT_DIRS_VAR} ${qm_output_dirs} PARENT_SCOPE) endfunction() + + +function(SLICER_CREATE_TRANSLATION_ONLY) + # Adapted from QT5_CREATE_TRANSLATION: + # - remove call to "qt5_add_translation" + # - remove setting of "_qm_files" output variable + set(options) + set(oneValueArgs) + set(multiValueArgs OPTIONS) + + cmake_parse_arguments(_LUPDATE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + set(_lupdate_files ${_LUPDATE_UNPARSED_ARGUMENTS}) + set(_lupdate_options ${_LUPDATE_OPTIONS}) + + set(_my_sources) + set(_my_tsfiles) + foreach(_file ${_lupdate_files}) + get_filename_component(_ext ${_file} EXT) + get_filename_component(_abs_FILE ${_file} ABSOLUTE) + if(_ext MATCHES "ts") + list(APPEND _my_tsfiles ${_abs_FILE}) + else() + list(APPEND _my_sources ${_abs_FILE}) + endif() + endforeach() + foreach(_ts_file ${_my_tsfiles}) + if(_my_sources) + # make a list file to call lupdate on, so we don't make our commands too + # long for some systems + get_filename_component(_ts_name ${_ts_file} NAME_WE) + set(_ts_lst_file "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_ts_name}_lst_file") + set(_lst_file_srcs) + foreach(_lst_file_src ${_my_sources}) + set(_lst_file_srcs "${_lst_file_src}\n${_lst_file_srcs}") + endforeach() + + get_directory_property(_inc_DIRS INCLUDE_DIRECTORIES) + foreach(_pro_include ${_inc_DIRS}) + get_filename_component(_abs_include "${_pro_include}" ABSOLUTE) + set(_lst_file_srcs "-I${_pro_include}\n${_lst_file_srcs}") + endforeach() + + file(WRITE ${_ts_lst_file} "${_lst_file_srcs}") + endif() + add_custom_command(OUTPUT ${_ts_file} + COMMAND ${Qt5_LUPDATE_EXECUTABLE} + ARGS ${_lupdate_options} "@${_ts_lst_file}" -ts ${_ts_file} + DEPENDS ${_my_sources} ${_ts_lst_file} VERBATIM) + endforeach() +endfunction() From 71e06d40b3a8154b6b078ee15234d6d7d99fe203 Mon Sep 17 00:00:00 2001 From: Jean-Christophe Fillion-Robin Date: Fri, 28 Jun 2019 09:28:59 -0400 Subject: [PATCH 5/5] STYLE: i18n: Simplify *.ts files removing location After talking with "Carlos Luque ", we decided to keep the file simpler. This could be revisited later. Co-authored-by: Carlos Luque --- CMake/SlicerMacroTranslation.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMake/SlicerMacroTranslation.cmake b/CMake/SlicerMacroTranslation.cmake index d02c4b76364..18e49f12f7d 100644 --- a/CMake/SlicerMacroTranslation.cmake +++ b/CMake/SlicerMacroTranslation.cmake @@ -155,7 +155,7 @@ function(SlicerFunctionAddGenerateSlicerTranslationQMFilesTarget) set(untranslated_ts_file ${untranslated_ts_dir}/${ts_basefilename}_untranslated.ts) SLICER_CREATE_TRANSLATION_ONLY( ${srcs_to_translate} ${rewritten_scripts_to_translate_for_context} ${untranslated_ts_file} - OPTIONS -source-language en_US -no-ui-lines + OPTIONS -source-language en_US -no-ui-lines -locations none ) set_source_files_properties(${ts_files} PROPERTIES OUTPUT_LOCATION ${qm_output_dir}) @@ -164,7 +164,7 @@ function(SlicerFunctionAddGenerateSlicerTranslationQMFilesTarget) # generating the associated "*_.qm" files. QT5_CREATE_TRANSLATION( QM_OUTPUT_FILES ${srcs_to_translate} ${rewritten_scripts_to_translate_for_context} ${ts_files} - OPTIONS -source-language en_US -no-ui-lines + OPTIONS -source-language en_US -no-ui-lines -locations none ) else() # Add custom command for generating the associated "*_.qm" files.