In this article
With BananaPlus you can provide translations to your extensions in a very simple and straightforward way. After you make the extension ready to be translated, adding a new language is as simple as adding a file to the package, without the need to change the source code.
Make an extension translatable
To make an extension translatable you need to:
- Install CMake, Visual Studio code and setup your development environment
- Mark strings for translation with the functions qsTr() or QT_TRANSLATE_NOOP() in *.js and *.qml files;
- Add a CMakeLists.txt file to your project and modify it;
- Translate strings with QtLinguist;
- Add the translations files *.qm in the resource file *.qrc;
- Build and deploy the extension's package;
You find a working complete example with the code described in this page on our GitHub Repository at: Sample extension for string translations
Limitations:
- JS and QML files can not contains a dot '.' in the file name: for example my.extention.js is no valid, but my_extension.js is valid;
- JS and QML files can not be renamed via the property Alias in resource files (*.qrc), for example from my.extention.js to my_extention.js or main.js;
- Translations files (*.qm) have to be found under the subfolder /translations;
Setup development environment
Follow the steps on the page setup your development environment.
Mark strings for translation
Strings to be translated have to be marked in .js or .qml files using the function qsTr() or QT_TRANSLATE_NOOP().
Strings marked for translations are extracted from .js and .qml files and inserted in translation's files *.ts. Translations files are created and compiled with Qt Creator and the translations done with Qt Linguist.
Function qsTR()
With the function qsTr() you mark strings to be translated in the application's language. Those are usually texts showed in the user interface (dialogs, messages, ...).
Example:
var translatedText = qsTr("Account card");
// The variabile translatedText contains the translated string "Account card"
// in the application's language
Function QT_TRANSLATE_NOOP()
With the function QT_TRANSLATE_NOOP() you mark strings to be translated in the document language. Those are usually texts printed in reports or invoices.
Those translation are retrieved through the API Banana.Translations.
Example:
// Exemple for function QT_TRANSLATE_NOOP
var myReportTexts = {};
myReportTexts.account_card = QT_TRANSLATE_NOOP("MyReport", "Account card"); // Mark text for translation
// NB: The variable myReportTexts.account_card contains the source code string "Account card"
// You need a Banana.Translator object to translate it in the desired language
// Get translator for the document's language
var documentLanguage = "en"; //default
if (Banana.document) {
documentLanguage = Banana.document.locale.substring(0,2);
}
var docTranslator = Banana.Translations.getTranslator(documentLanguage, "MyReport");
// Translate to the document's language
var myReportTranslatedText = docTranslator.tr(myReportTexts.account_card);
Add a CMake project file
A CMakeLists.txt project file is needed to extract all strings marked for translation from .js and .qml files and build the .sbaa extension's package.
Below is a template of a project file for translating an extension, you can copy it and modify it:
- copy the example and save it as CMakeLists.txt in your project folder;
- rename the project name translations_project to your desired name;
- renane the extension id ch.banana.translations to your desired id;
- add the desired languages under the variable translations_files;
- add source files as needed to the main target;
cmake_minimum_required(VERSION 3.16)
project(translations_project) # <!-- CHANGE THE PROJECT'S NAME
set(EXTENSION_ID "ch.banana.translations") # <!-- CHANGE THE EXTENSION'S ID
# CMake options
# Create a file .vscode/settings.json with the following content to set the options,
# adapt the path to your environment
# {
# "cmake.configureSettings": {
# "BAN_QT_RCC": "C:\users\user_name\AppData\Local\Programs\BananaPlusDev\rcc.exe",
# "BAN_EXE_PATH": "C:\users\user_name\AppData\Local\Programs\BananaPlusDev\BananaPlusDev.exe",
# "BAN_QT_LUPDATE": "C:\Qt\6.5.2\macos\bin\lupdate",
# "BAN_QT_LRELEASE": "C:\Qt\6.5.2\macos\bin\lrelease"
# }
# }
set(BAN_QT_RCC $ENV{BAN_QT_RCC} CACHE FILEPATH "Path to Qt rcc executable")
set(BAN_EXE_PATH $ENV{BAN_EXE_PATH} CACHE FILEPATH "Path to BananaPlus executable, used to run tests")
set(BAN_QT_LUPDATE $ENV{BAN_QT_LUPDATE} CACHE FILEPATH "Path to Qt lupdate executable")
set(BAN_QT_LRELEASE $ENV{BAN_QT_LRELEASE} CACHE FILEPATH "Path to Qt lrelease executable")
# This target is used to build the extension to a sbaa package
add_custom_target(translations_project ALL # <!-- CHANGE THE PROJECT'S NAME
COMMAND ${BAN_QT_RCC} -o ${EXTENSION_ID}.sbaa --binary ${EXTENSION_ID}.qrc
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
SOURCES ${EXTENSION_ID}.qrc
)
add_dependencies(${PROJECT_NAME} lrelease) #build .qm files when building the sbaa package
# The variable translations_files contains the list of translations files
set(translations_files
translations/translations_de.ts
translations/translations_it.ts
translations/translations_fr.ts
#translations/translations_xx.ts # <!-- ADD LANGUAGES AS NEEDED
)
# The target lupdate is used to update *.ts translations files
set(lupdate_commands)
foreach(tr_file ${translations_files})
list(APPEND lupdate_commands
COMMAND ${BAN_QT_LUPDATE} ${EXTENSION_ID}.qrc -ts ${tr_file})
endforeach()
add_custom_target(lupdate
${lupdate_commands}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
# The target lrelease is used to compile *.ts files to *.qm files
set(lrelease_commands)
set(lrelease_files)
string(REPLACE ".ts" "" lrelease_files "${translations_files}") #remove file extension
foreach(tr_file ${lrelease_files})
list(APPEND lrelease_commands
COMMAND ${BAN_QT_LRELEASE} ${tr_file}.ts -qm ${tr_file}.qm)
endforeach()
add_custom_target(lrelease
${lrelease_commands}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
Set Cmake options
Create the file .vscode/settings.json and set the following options:
- BAN_QT_RCC: path to the Qt rcc tool. The rcc Tool is used to compile the extension to a sbaa package.
- BAN_EXE_ PATH: path to the BananaPlus executable. The BananaPlus executable is used to run the tests defined in the project.
- BAN_QT_LUPDATE: path to the Qt lupdate tool. The lupdate tool is used to update the translations, it will search for text to translate in the code and update the content of *.ts files. If you don't have translations, this options is not necessary.
- BAN_QT_RELEASE: path to the Qt lrealease tool. The lrelease tool is used to compile the translations, the compiled translation are integrated in the package.If you don't have translations, this options is not necessary.
{
"cmake.configureSettings": {
"BAN_QT_RCC": "C:\Programms\BananaPlusDev\rcc.exe",
"BAN_EXE_PATH": "C:\Programms\BananaPlusDev\BananaPlusDev.exe",
"BAN_QT_LUPDATE": "C:\Qt\6.5.2\macos\bin\lupdate",
"BAN_QT_LRELEASE": "C:\Qt\6.5.2\macos\bin\lrelease"
}
}
Translate strings
- Create a folder /translations in your repository;
- Open the CMakeLists.txt project file with QtCreator;
- Build in QtCreator the target lupdate (figure 1);
- Open the generated translations/*.ts files with QtLinguist and enter the translations (figure 2)
Keep the generated translations/*.ts files in the repository, as they are needed for updating the translations after one or more strings are changed or modified in the code.
Add translations to resource file
Add the *.qm files to the resource *.qrc file.
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>manifest.json</file>
<file>translations/translations_de.qm</file>
<file>translations/translations_fr.qm</file>
<file>translations/translations_it.qm</file>
</qresource>
</RCC>
Build and deploy
- Build the extension;
- The translations files *.qm are automatically released and included in the package;
- Copy the generated *.sbaa file to the destination folder;
- Add the extension in Banana AccountingPlus (see installing an'extension);
- Test it;
Implementation details
Loading of translation's files
Translations are automatically loaded by the application.
Translations are provided as *.qm binary files located in the extension's subfolder /translations.
sample_extention.js // extension translations/ translations_de.qm. // translation's files translations_it_CH.qm translations_it.qm ...
Translations files have the following naming convention:
translations_lang[_country].qm
Before the execution of the extension the application loads the translation corresponding to the application's language and country. For example if the application has the locale fr_FR the application looks for the following files, the first file found is taken.
translations_fr_FR.qm translations_fr.qm