diff --git a/qbs/imports/VToolApp.qbs b/qbs/imports/VToolApp.qbs index 76cba1734..e8506e243 100644 --- a/qbs/imports/VToolApp.qbs +++ b/qbs/imports/VToolApp.qbs @@ -1,16 +1,19 @@ import qbs.FileInfo +import qbs.File VApp { Depends { name: "freedesktop2" } Depends { name: "tenv" } Depends { name: "windeployqt"; } Depends { name: "i18nconfig"; } + Depends { name: "i18n"; } version: "0.7.52" install: true installDir: buildconfig.installAppPath installDebugInformation: true consoleApplication: false + bundle.isBundle: qbs.buildVariant === "release" Properties { // Breakpoints do not work if debug the app inside of bundle. In debug mode we turn off creating a bundle. @@ -54,7 +57,6 @@ VApp { var pmSystems = i18nconfig.pmSystems; 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"); } @@ -64,6 +66,128 @@ VApp { } } + Group { + condition: !qbs.targetOS.contains("macos") || (qbs.targetOS.contains("macos") && !bundle.isBundle) + fileTagsFilter: "qm" + qbs.install: true + qbs.installDir: buildconfig.installDataPath + "/translations" + } + + Rule { + multiplex: true + condition: qbs.targetOS.contains("macos") && bundle.isBundle + inputs: ["qm"] + outputFileTags: ["bundle.qm", "bundle.content"] + outputArtifacts: { + var locales = product.i18nconfig.translationLocales; + var artifactNames = []; + + for (var i = 0; i < locales.length; i++) { + const lprojDir = FileInfo.joinPaths(product.buildDirectory, product.bundle.bundleName, + "Contents", "Resources", "translations", locales[i] + product.bundle.localizedResourcesFolderSuffix); + + var qmRex = new RegExp('.*_' + locales[i] + '\.qm$', 'g'); + artifactNames = artifactNames.concat((inputs["qm"] || []).filter(function(file){ + return qmRex.exec(file.fileName); + }).map(function(file){ + return FileInfo.joinPaths(lprojDir, file.fileName); + })); + + artifactNames.push(FileInfo.joinPaths(lprojDir, "Localizable.strings")); + + const qtTranslationsMask = [ + "qt_", + "qtbase_", + "qtxmlpatterns_" + ]; + + qtTranslationsMask.forEach(function(mask) { + var qmFile = FileInfo.joinPaths(product.i18n.qtTranslationsPath, mask + locales[i] + ".qm"); + if (File.exists(qmFile)) { + artifactNames.push(FileInfo.joinPaths(lprojDir, mask + locales[i] + ".qm")); + } else { + const lang = locales[i].split('_')[0]; + qmFile = FileInfo.joinPaths(product.i18n.qtTranslationsPath, mask + lang + ".qm"); + if (File.exists(qmFile)) + artifactNames.push(FileInfo.joinPaths(lprojDir, mask + lang + ".qm")); + } + }); + } + + var artifacts = artifactNames.map(function(art){ + var a = { + filePath: art, + fileTags: ["bundle.qm", "bundle.content"] + } + return a; + }); + return artifacts; + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = "Preparing Valentina translations"; + cmd.highlight = "filegen"; + + var data = []; + const locales = product.i18nconfig.translationLocales; + + for (var i = 0; i < locales.length; i++) { + const qmRex = new RegExp('.*_' + locales[i] + '.qm$', 'g'); + const src = (inputs["qm"] || []).filter(function(file){ + return qmRex.exec(file.fileName); + }); + + const lprojDir = FileInfo.joinPaths(product.buildDirectory, product.bundle.bundleName, + "Contents", "Resources", "translations", locales[i] + product.bundle.localizedResourcesFolderSuffix); + + for (var j = 0; j < src.length; j++) { + data.push({ + "source" : src[j].filePath, + "destination": FileInfo.joinPaths(lprojDir, src[j].fileName) + }); + } + + data.push({ + "source" : FileInfo.joinPaths(project.sourceDirectory, "share", "translations", "Localizable.strings"), + "destination": FileInfo.joinPaths(lprojDir, "Localizable.strings") + }); + + const qtTranslationsMask = [ + "qt_", + "qtbase_", + "qtxmlpatterns_" + ]; + + qtTranslationsMask.forEach(function(mask) { + var qmFile = FileInfo.joinPaths(product.i18n.qtTranslationsPath, mask + locales[i] + ".qm"); + if (File.exists(qmFile)) { + data.push({ + "source" : qmFile, + "destination": FileInfo.joinPaths(lprojDir, mask + locales[i] + ".qm") + }); + } else { + const lang = locales[i].split('_')[0]; + qmFile = FileInfo.joinPaths(product.i18n.qtTranslationsPath, mask + lang + ".qm"); + if (File.exists(qmFile)) { + data.push({ + "source" : qmFile, + "destination": FileInfo.joinPaths(lprojDir, mask + lang + ".qm") + }); + } + } + }); + } + cmd.data = data; + + cmd.sourceCode = function() { + data.forEach(function(copyData) { + File.copy(copyData.source, copyData.destination); + }); + }; + return [cmd]; + } + } + windeployqt.noVirtualkeyboard: true Properties { diff --git a/qbs/modules/i18n/i18n.qbs b/qbs/modules/i18n/i18n.qbs index 333bed20b..777c5ae3e 100644 --- a/qbs/modules/i18n/i18n.qbs +++ b/qbs/modules/i18n/i18n.qbs @@ -1,6 +1,7 @@ import qbs.File import qbs.FileInfo import qbs.TextFile +import qbs.Process /** This module generates 'i18n.pro' artifact, which then acts as an input for 'lupdate' program, which in turn produces @@ -26,6 +27,8 @@ Module { property string lupdateName: "lupdate" + readonly property string qtTranslationsPath: qtTranslationsProbe.qtTranslationsPath + Rule { condition: update && buildWithPro multiplex: true @@ -202,4 +205,39 @@ Module { outputFileTags: ["i18n"] } + + Probe { + id: qtTranslationsProbe + + readonly property string binPath: product.Qt.core.binPath + + property string qtTranslationsPath + + configure: { + var qmakeProcess = new Process(); + try { + var suffix = FileInfo.executableSuffix(); + var qmakePath = FileInfo.joinPaths(binPath, "qmake" + suffix); + qmakeProcess.exec(qmakePath, ["-query"]); + if (qmakeProcess.exitCode() !== 0) { + throw "The qmake executable '" + FileInfo.toNativeSeparators(qmakePath) + "' failed with exit code " + + qmakeProcess.exitCode() + "."; + } + while (!qmakeProcess.atEnd()) { + var line = qmakeProcess.readLine(); + var index = (line || "").indexOf(":"); + if (index !== -1) { + if (line.slice(0, index) === "QT_INSTALL_TRANSLATIONS") { + var path = line.slice(index + 1).trim(); + if (path) + qtTranslationsPath = FileInfo.fromNativeSeparators(path); + break; + } + } + } + } finally { + qmakeProcess.close(); + } + } + } } diff --git a/src/app/puzzle/puzzle.qbs b/src/app/puzzle/puzzle.qbs index 56e4de91c..765196700 100644 --- a/src/app/puzzle/puzzle.qbs +++ b/src/app/puzzle/puzzle.qbs @@ -255,13 +255,6 @@ VToolApp { fileTags: "freedesktop.512x512MimetypesIcons" } - Group { - condition: qbs.targetOS.contains("macos") - fileTagsFilter: "qm" - qbs.install: true - qbs.installDir: buildconfig.installDataPath + "/translations" - } - Group { name: "Puzzle RC" condition: qbs.targetOS.contains("windows") diff --git a/src/app/tape/tape.qbs b/src/app/tape/tape.qbs index b69192a9f..6ebe298a7 100644 --- a/src/app/tape/tape.qbs +++ b/src/app/tape/tape.qbs @@ -181,13 +181,6 @@ VToolApp { fileTags: "freedesktop.512x512MimetypesIcons" } - Group { - condition: qbs.targetOS.contains("macos") - fileTagsFilter: "qm" - qbs.install: true - qbs.installDir: buildconfig.installDataPath + "/translations" - } - Group { name: "Diagrams" prefix: product.sourceDirectory + "/share/resources/" diff --git a/src/app/valentina/valentina.qbs b/src/app/valentina/valentina.qbs index aeb2a4e6b..5a922362e 100644 --- a/src/app/valentina/valentina.qbs +++ b/src/app/valentina/valentina.qbs @@ -304,12 +304,6 @@ VToolApp { qbs.installDir: buildconfig.installAppPath } - Group { - fileTagsFilter: "qm" - qbs.install: true - qbs.installDir: buildconfig.installDataPath + "/translations" - } - Group { name: "Valentina RC" condition: qbs.targetOS.contains("windows")