Module to update ts files.
This commit is contained in:
parent
44b9e1b77c
commit
0a681d7f93
205
qbs/modules/i18n/i18n.qbs
Normal file
205
qbs/modules/i18n/i18n.qbs
Normal file
|
@ -0,0 +1,205 @@
|
|||
import qbs.File
|
||||
import qbs.FileInfo
|
||||
import qbs.TextFile
|
||||
|
||||
/**
|
||||
This module generates 'i18n.pro' artifact, which then acts as an input for 'lupdate' program, which in turn produces
|
||||
translation files, which are compiled by 'lrelease' program into 'qm' files, which can be loaded by an application.
|
||||
*/
|
||||
Module {
|
||||
Depends { name: "Qt.core" }
|
||||
|
||||
additionalProductTypes: ["i18n"]
|
||||
|
||||
/*
|
||||
Unfortunately you can not simply add empty files to the product, cause 'Qt.core' module has a rule, which calls 'lrelease' on
|
||||
every 'ts' file in the product and 'lrelease' triggers error if these files are empty. Additionaly 'lupdate' also triggers
|
||||
errors, when parsing 'pro' file. Instead this property can be used to create new translation file.
|
||||
*/
|
||||
property stringList additionalTranslations: []
|
||||
|
||||
// Explicitly trigger build even if build a product
|
||||
property bool update: false
|
||||
|
||||
// Build with legacy way though .pro file
|
||||
property bool buildWithPro: true
|
||||
|
||||
property string lupdateName: "lupdate"
|
||||
|
||||
Rule {
|
||||
condition: update && buildWithPro
|
||||
multiplex: true
|
||||
inputs: ["i18n.hpp", "i18n.src", "i18n.ui", "i18n.res", "i18n.ts"]
|
||||
|
||||
prepare: {
|
||||
var proCmd = new JavaScriptCommand();
|
||||
proCmd.description = 'generating ' + output.filePath;
|
||||
proCmd.highlight = 'codegen';
|
||||
proCmd.sourceCode = function() {
|
||||
var f = new TextFile(output.filePath, TextFile.WriteOnly);
|
||||
try {
|
||||
f.writeLine("lupdate_only {");
|
||||
if (inputs["i18n.hpp"] !== undefined)
|
||||
for (var i = 0; i < inputs["i18n.hpp"].length; i++)
|
||||
f.writeLine("HEADERS += " + FileInfo.relativePath(product.sourceDirectory, inputs["i18n.hpp"][i].filePath));
|
||||
f.writeLine("");
|
||||
if (inputs["i18n.src"] !== undefined)
|
||||
for (var i = 0; i < inputs["i18n.src"].length; i++)
|
||||
f.writeLine("SOURCES += " + FileInfo.relativePath(product.sourceDirectory, inputs["i18n.src"][i].filePath));
|
||||
f.writeLine("");
|
||||
if (inputs["i18n.ui"] !== undefined)
|
||||
for (var i = 0; i < inputs["i18n.ui"].length; i++)
|
||||
f.writeLine("FORMS += " + FileInfo.relativePath(product.sourceDirectory, inputs["i18n.ui"][i].filePath));
|
||||
f.writeLine("");
|
||||
// lupdate processes QML files that are listed in the .qrc file
|
||||
if (inputs["i18n.res"] !== undefined)
|
||||
for (var i = 0; i < inputs["i18n.res"].length; i++)
|
||||
f.writeLine("RESOURCES += " + FileInfo.relativePath(product.sourceDirectory, inputs["i18n.res"][i].filePath));
|
||||
f.writeLine("}");
|
||||
|
||||
f.writeLine("");
|
||||
if (inputs["i18n.ts"] !== undefined)
|
||||
for (var i = 0; i < inputs["i18n.ts"].length; i++)
|
||||
f.writeLine("TRANSLATIONS += " + FileInfo.relativePath(product.sourceDirectory, inputs["i18n.ts"][i].filePath));
|
||||
for (var i = 0; i < product.i18n.additionalTranslations.length; i++) {
|
||||
var targetDirectory = product.sourceDirectory + "/" + FileInfo.path(product.i18n.additionalTranslations[i]);
|
||||
if (!File.exists(targetDirectory))
|
||||
console.error("Directory '" + targetDirectory + "' does not exists. Please create it.");
|
||||
f.writeLine("TRANSLATIONS += " + product.i18n.additionalTranslations[i]);
|
||||
}
|
||||
} finally {
|
||||
f.close();
|
||||
}
|
||||
}
|
||||
return [proCmd];
|
||||
}
|
||||
|
||||
Artifact {
|
||||
filePath: product.sourceDirectory + "/" + product.name + ".i18n.pro"
|
||||
fileTags: ["i18n.pro"]
|
||||
}
|
||||
}
|
||||
|
||||
Rule {
|
||||
condition: buildWithPro
|
||||
inputs: ["i18n.pro"]
|
||||
|
||||
prepare: {
|
||||
var lupdateName = product.i18n.lupdateName;
|
||||
var cmdLupdate = new Command(product.Qt.core.binPath + '/' + lupdateName, ["-verbose", input.filePath]);
|
||||
cmdLupdate.description = "Invoking '" + lupdateName + "' program";
|
||||
cmdLupdate.highlight = 'filegen';
|
||||
|
||||
var cmdClean = new JavaScriptCommand();
|
||||
cmdClean.description = "Removing " + input.fileName;
|
||||
cmdClean.highlight = "filegen";
|
||||
cmdClean.sourceCode = function() {
|
||||
File.remove(input.filePath);
|
||||
}
|
||||
return [cmdLupdate, cmdClean]
|
||||
}
|
||||
|
||||
outputFileTags: ["i18n"]
|
||||
}
|
||||
|
||||
Rule {
|
||||
condition: update && !buildWithPro
|
||||
multiplex: true
|
||||
inputs: ["i18n.hpp", "i18n.src", "i18n.ui", "i18n.ts"]
|
||||
|
||||
prepare: {
|
||||
var proCmd = new JavaScriptCommand();
|
||||
proCmd.description = 'generating ' + output.filePath;
|
||||
proCmd.highlight = 'codegen';
|
||||
proCmd.sourceCode = function() {
|
||||
var f = new TextFile(output.filePath, TextFile.WriteOnly);
|
||||
try {
|
||||
// Since Qt 5.13 lupdate supports passing a project description in JSON file. For producing such a
|
||||
// description from .pro file we can use new tool lprodump. But tehnically we don't need it. We can
|
||||
// totally fake format.
|
||||
// JSON file structure:
|
||||
// Project ::= {
|
||||
// string projectFile // Name of the project file. (required)
|
||||
// string codec // Source code codec. Valid values are
|
||||
// // currently "utf-16" or "utf-8" (default).
|
||||
// string[] translations // List of .ts files of the project. (required)
|
||||
// string[] includePaths // List of include paths.
|
||||
// string[] sources // List of source files. (required)
|
||||
// string[] excluded // List of source files, which are
|
||||
// // excluded for translation.
|
||||
// Project[] subProjects // List of sub-projects.
|
||||
// }
|
||||
// It seems all we need are projectFile, sources and translations options.
|
||||
|
||||
var sources = [];
|
||||
if (inputs["i18n.hpp"] !== undefined)
|
||||
for (var i = 0; i < inputs["i18n.hpp"].length; i++)
|
||||
sources.push(inputs["i18n.hpp"][i].filePath);
|
||||
|
||||
if (inputs["i18n.src"] !== undefined)
|
||||
for (var i = 0; i < inputs["i18n.src"].length; i++)
|
||||
sources.push(inputs["i18n.src"][i].filePath);
|
||||
|
||||
if (inputs["i18n.ui"] !== undefined)
|
||||
for (var i = 0; i < inputs["i18n.ui"].length; i++)
|
||||
sources.push(inputs["i18n.ui"][i].filePath);
|
||||
|
||||
// lupdate processes QML files that are listed in the .qrc file
|
||||
if (inputs["i18n.res"] !== undefined)
|
||||
for (var i = 0; i < inputs["i18n.res"].length; i++)
|
||||
sources.push(inputs["i18n.res"][i].filePath);
|
||||
|
||||
var translations = [];
|
||||
if (inputs["i18n.ts"] !== undefined)
|
||||
for (var i = 0; i < inputs["i18n.ts"].length; i++)
|
||||
translations.push(inputs["i18n.ts"][i].filePath);
|
||||
|
||||
for (var i = 0; i < product.i18n.additionalTranslations.length; i++) {
|
||||
var targetDirectory = product.sourceDirectory + "/" + FileInfo.path(product.i18n.additionalTranslations[i]);
|
||||
if (!File.exists(targetDirectory))
|
||||
console.error("Directory '" + targetDirectory + "' does not exists. Please create it.");
|
||||
translations.push(product.i18n.additionalTranslations[i]);
|
||||
}
|
||||
|
||||
var project = {
|
||||
projectFile: "", // Looks like can be empty
|
||||
sources: sources.sort(),
|
||||
translations: translations.sort()
|
||||
};
|
||||
|
||||
f.write(JSON.stringify([project], null, 2));
|
||||
} finally {
|
||||
f.close();
|
||||
}
|
||||
}
|
||||
return [proCmd];
|
||||
}
|
||||
|
||||
Artifact {
|
||||
filePath: product.sourceDirectory + "/" + product.name + ".i18n.json"
|
||||
fileTags: ["i18n.json"]
|
||||
}
|
||||
}
|
||||
|
||||
Rule {
|
||||
condition: !buildWithPro
|
||||
inputs: ["i18n.json"]
|
||||
|
||||
prepare: {
|
||||
var lupdateName = product.i18n.lupdateName;
|
||||
var cmdLupdate = new Command(product.Qt.core.binPath + '/' + lupdateName, ["-verbose", "-project", input.filePath]);
|
||||
cmdLupdate.description = "Invoking '" + lupdateName + "' program";
|
||||
cmdLupdate.highlight = 'filegen';
|
||||
|
||||
var cmdClean = new JavaScriptCommand();
|
||||
cmdClean.description = "Removing " + input.fileName;
|
||||
cmdClean.highlight = "filegen";
|
||||
cmdClean.sourceCode = function() {
|
||||
File.remove(input.filePath);
|
||||
}
|
||||
return [cmdLupdate, cmdClean]
|
||||
}
|
||||
|
||||
outputFileTags: ["i18n"]
|
||||
}
|
||||
}
|
40
scripts/qbs_lupdate.sh
Executable file
40
scripts/qbs_lupdate.sh
Executable file
|
@ -0,0 +1,40 @@
|
|||
#!/bin/bash
|
||||
# Run this script if you want to find and update all strings in the code.
|
||||
# Please, run this script from folder <root_folder>/scripts.
|
||||
|
||||
start=$(date +%s)
|
||||
|
||||
# Download all translations from transifex.com.
|
||||
cd ../share/translations
|
||||
RESOURCES=`find . -regextype sed -regex ".*/measurements_p[0-9]\{1,2\}\.ts"`
|
||||
cd ../../scripts
|
||||
|
||||
# Empty means unstable branch
|
||||
MEASUREMENTS_BRANCH='' # For example _05x
|
||||
VALENTINA_BRANCH='' # for example 05x
|
||||
|
||||
NUMBER=( $RESOURCES )
|
||||
NUMBER=${#NUMBER[@]}
|
||||
|
||||
# Certant languages like he_IL and zh_CN are not supported by math parser
|
||||
for ((i=0;i<NUMBER;i++)); do
|
||||
tx pull -r valentina-project.measurements_p${i}${MEASUREMENTS_BRANCH}ts --mode=developer -f --skip -l "uk,de_DE,cs,he_IL,fr_FR,it_IT,nl,id,es,fi,en_US,en_CA,en_IN,ro_RO,zh_CN,pt_BR,el_GR,pl_PL" &
|
||||
sleep 1
|
||||
done
|
||||
|
||||
tx pull -r valentina-project.valentina_${VALENTINA_BRANCH}ts --mode=developer -f --skip &
|
||||
sleep 1
|
||||
tx pull -r valentina-project.measurements_p998${MEASUREMENTS_BRANCH}ts --mode=developer -f --skip -l "uk,de_DE,cs,he_IL,fr_FR,it_IT,nl,id,es,fi,en_US,en_CA,en_IN,ro_RO,zh_CN,pt_BR,el_GR,pl_PL" &
|
||||
|
||||
wait
|
||||
|
||||
# Resolve any changes to config
|
||||
qbs resolve -d ../../build_translations modules.i18n.update:true
|
||||
# Update local strings
|
||||
qbs -d ../../build_translations -f ../valentina.qbs -p 'Translations' modules.i18n.update:true
|
||||
qbs -d ../../build_translations -f ../valentina.qbs -p 'MTranslations' modules.i18n.update:true
|
||||
|
||||
end=$(date +%s)
|
||||
runtime=$(python -c "print('Time passed %u:%02u seconds' % ((${end} - ${start})/60, (${end} - ${start})%60))")
|
||||
echo $runtime
|
||||
|
72
share/translations/measurements.qbs
Normal file
72
share/translations/measurements.qbs
Normal file
|
@ -0,0 +1,72 @@
|
|||
import qbs.FileInfo
|
||||
|
||||
Product {
|
||||
Depends { name: "i18n" }
|
||||
|
||||
name: "MTranslations"
|
||||
type: "ts"
|
||||
builtByDefault: false
|
||||
|
||||
Group {
|
||||
name: "Headers"
|
||||
prefix: FileInfo.joinPaths(project.sourceDirectory, "src", FileInfo.pathSeparator())
|
||||
files: [
|
||||
"libs/vpatterndb/vtranslatemeasurements.h"
|
||||
]
|
||||
fileTags: "i18n.hpp"
|
||||
}
|
||||
|
||||
Group {
|
||||
name: "Sources"
|
||||
prefix: FileInfo.joinPaths(project.sourceDirectory, "src", FileInfo.pathSeparator())
|
||||
files: [
|
||||
"libs/vpatterndb/vtranslatemeasurements.cpp"
|
||||
]
|
||||
fileTags: "i18n.src"
|
||||
}
|
||||
|
||||
Group {
|
||||
name: "Translations"
|
||||
files: {
|
||||
var files = [];
|
||||
|
||||
var locales = [
|
||||
"uk_UA",
|
||||
"de_DE",
|
||||
"cs_CZ",
|
||||
"he_IL",
|
||||
"fr_FR",
|
||||
"it_IT",
|
||||
"nl_NL",
|
||||
"id_ID",
|
||||
"es_ES",
|
||||
"fi_FI",
|
||||
"en_US",
|
||||
"en_CA",
|
||||
"en_IN",
|
||||
"ro_RO",
|
||||
"zh_CN",
|
||||
"pt_BR",
|
||||
"el_GR",
|
||||
"pl_PL"
|
||||
];
|
||||
|
||||
var pmSystems = [
|
||||
"p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15",
|
||||
"p16", "p17", "p18", "p19", "p20", "p21", "p22", "p23", "p24", "p25", "p26", "p27", "p28", "p29",
|
||||
"p30", "p31", "p32", "p33", "p34", "p35", "p36", "p37", "p38", "p39", "p40", "p41", "p42", "p43",
|
||||
"p44", "p45", "p46", "p47", "p48", "p49", "p50", "p51", "p52", "p53", "p54", "p998"
|
||||
]
|
||||
|
||||
for (var i = 0; i < pmSystems.length; i++) {
|
||||
files.push("measurements_" + pmSystems[i] + ".ts");
|
||||
for (var j = 0; j < locales.length; j++) {
|
||||
files.push("measurements_" + pmSystems[i] + "_" + locales[j] + ".ts");
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
fileTags: "i18n.ts"
|
||||
}
|
||||
}
|
88
share/translations/translations.qbs
Normal file
88
share/translations/translations.qbs
Normal file
|
@ -0,0 +1,88 @@
|
|||
import qbs.FileInfo
|
||||
|
||||
Product {
|
||||
Depends { name: "i18n" }
|
||||
|
||||
name: "Translations"
|
||||
type: "ts"
|
||||
builtByDefault: false
|
||||
|
||||
Group {
|
||||
name: "Headers"
|
||||
prefix: FileInfo.joinPaths(project.sourceDirectory, "src", FileInfo.pathSeparator())
|
||||
files: [
|
||||
"app/**/*.h",
|
||||
"app/**/*.hpp",
|
||||
"libs/**/*.h",
|
||||
"libs/**/*.hpp"
|
||||
]
|
||||
excludeFiles: [
|
||||
"libs/vpatterndb/vtranslatemeasurements.h"
|
||||
]
|
||||
fileTags: "i18n.hpp"
|
||||
}
|
||||
|
||||
Group {
|
||||
name: "Sources"
|
||||
prefix: FileInfo.joinPaths(project.sourceDirectory, "src", FileInfo.pathSeparator())
|
||||
files: [
|
||||
"app/**/*.cpp",
|
||||
"app/**/*.js",
|
||||
"app/**/*.qml",
|
||||
"libs/**/*.cpp",
|
||||
"libs/**/*.js",
|
||||
"libs/**/*.qml"
|
||||
]
|
||||
excludeFiles: [
|
||||
"libs/vpatterndb/vtranslatemeasurements.cpp"
|
||||
]
|
||||
fileTags: "i18n.src"
|
||||
}
|
||||
|
||||
Group {
|
||||
name: "Forms"
|
||||
prefix: FileInfo.joinPaths(project.sourceDirectory, "src", FileInfo.pathSeparator())
|
||||
files: [
|
||||
"app/**/*.ui",
|
||||
"libs/**/*.ui"
|
||||
]
|
||||
fileTags: "i18n.ui"
|
||||
}
|
||||
|
||||
Group {
|
||||
name: "Translations"
|
||||
files: {
|
||||
var files = [];
|
||||
|
||||
var locales = [
|
||||
"uk_UA",
|
||||
"de_DE",
|
||||
"cs_CZ",
|
||||
"he_IL",
|
||||
"fr_FR",
|
||||
"it_IT",
|
||||
"nl_NL",
|
||||
"id_ID",
|
||||
"es_ES",
|
||||
"fi_FI",
|
||||
"en_US",
|
||||
"en_CA",
|
||||
"en_IN",
|
||||
"ro_RO",
|
||||
"zh_CN",
|
||||
"pt_BR",
|
||||
"el_GR",
|
||||
"pl_PL"
|
||||
];
|
||||
|
||||
files.push("valentina.ts");
|
||||
|
||||
for (var i = 0; i < locales.length; i++) {
|
||||
files.push("valentina_" + locales[i] + ".ts");
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
fileTags: "i18n.ts"
|
||||
}
|
||||
}
|
|
@ -3,6 +3,8 @@ Project {
|
|||
minimumQbsVersion: "1.16"
|
||||
references: [
|
||||
"src/src.qbs",
|
||||
"share/translations/translations.qbs",
|
||||
"share/translations/measurements.qbs",
|
||||
]
|
||||
qbsSearchPaths: "qbs"
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user