Is it possible to use Sparkle in Qt (Golang bindings) app? - qt

We build a Qt app using: https://github.com/therecipe/qt.
Now we need an auto updater and found this: https://sparkle-project.org
Looks like it is being used by multiple apps on my machine:
/Applications/VLC.app/Contents/Frameworks/Sparkle.framework
/Applications/Adium.app/Contents/Frameworks/Sparkle.framework
/Applications/TeamViewer.app/Contents/Frameworks/Sparkle.framework
/Applications/Docker.app/Contents/Frameworks/Sparkle.framework
...
Some articles show me how to use it in Qt:
http://www.discoversdk.com/knowledge-base/using-sparkle-in-qt
https://github.com/sparkle-project/Sparkle/issues/1137#issuecomment-336667547
but it's for C++/Objective C code.
Is it possible to use with Golang? If so, how?

https://github.com/therecipe/qt/issues/743#issuecomment-444689169
sparkle.m:
#import <Headers/SUUpdater.h>
static SUUpdater* updater = nil;
void sparkle_checkUpdates()
{
if (!updater) {
updater = [[SUUpdater sharedUpdater] retain];
}
[updater setUpdateCheckInterval:3600];
[updater checkForUpdatesInBackground];
}
sparkle.go:
// +build darwin windows
package main
/*
#cgo CFLAGS: -I ${SRCDIR}/Sparkle.framework
#cgo LDFLAGS: -F ${SRCDIR} -framework Sparkle
void sparkle_checkUpdates();
*/
import "C"
func sparkle_checkUpdates() {
C.sparkle_checkUpdates()
}
And in main.go, call that func:
action := widgets.NewQMenuBar(nil).AddMenu2("").AddAction("Check for Updates...")
// http://doc.qt.io/qt-5/qaction.html#MenuRole-enum
action.SetMenuRole(widgets.QAction__ApplicationSpecificRole)
action.ConnectTriggered(func(bool) { sparkle_checkUpdates() })
appcast.xml:
<?xml version="1.0" standalone="yes"?>
<rss xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" version="2.0">
<channel>
<title>Premium VPN</title>
<item>
<title>1.0.0.2905</title>
<pubDate>Tue, 11 Dec 2018 11:09:10 +0800</pubDate>
<sparkle:minimumSystemVersion>10.7</sparkle:minimumSystemVersion>
<enclosure url="https://example.com/x.zip" sparkle:version="1.0.0.2905" sparkle:shortVersionString="1.0.0.2905" sparkle:edSignature="$(/path/to/Sparkle/bin/sign_update)" length="104408678" type="application/octet-stream"/>
</item>
</channel>
</rss>
Info.plist:
<key>SUFeedURL</key>
<string>https://example.com/appcast.xml</string>
<key>SUPublicEDKey</key>
<string>$(/path/to/Sparkle/bin/generate_keys)</string>

Related

use http src in qt scxml data attribute

Is there a way to use http sources for data in Qt's scxml implementation?
In other implementations this works, but not in my Qt Version 5.15.3
When using a simple state machine, with it's data src pointing to my running flask script I get the following error:
qrc:/main.qml:15:5: QML StateMachineLoader: :/http.scxml:5:59: error: src attribute resolves to non existing file (:/http://localhost:8080/) qrc:/main.qml: 15
Can't I define remote sources for data?
The statemachine:
<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" binding="early"
xmlns:qt="http://www.qt.io/2015/02/scxml-ext" datamodel="ecmascript" name="http_test" initial="test">
<datamodel>
<data id="http_data" src="http://localhost:8080/"/>
</datamodel>
<state id="test">
<onentry>
<send event="entried" delay="2s">
<param name="eventbody" location="http_data"/>
</send>
</onentry>
</state>
</scxml>
qml:
import QtScxml 5.15
id:theId
property StateMachine stateMachine: scxmlLoader.stateMachine
StateMachineLoader {
id: scxmlLoader
source: "http.scxml"
}
EventConnection {
events: ["entried"]
stateMachine: theId.stateMachine
onOccurred: {
var d=event.data
console.debug(d.eventbody)
}
}
Qt SCXML works only with local files

Why aren't my Qt5 language translations loading?

I am trying to write a simple qml application with language translations using CMake and although the application runs, it never shows translations. I'm on a Linux platform with CMake version 3.22.2 and Qt version 3.15.2 Here is the directory structure:
├── CMakeLists.txt
└── src
├── CMakeLists.txt
├── main.cpp
├── silly.qrc
└── qml
   ├── silly.qml
   └── translations
   ├── qml_de.ts
   ├── qml_en.ts
   └── qml_fr.ts
CMakeLists.txt
cmake_minimum_required(VERSION 3.22)
project(silly VERSION 1.0.0)
add_subdirectory(src)
src/CMakeLists.txt
cmake_minimum_required(VERSION 3.22)
find_package(Qt5 COMPONENTS Qml Quick LinguistTools REQUIRED)
set(TRANSLATIONS
qml/translations/qml_en.ts
qml/translations/qml_fr.ts
qml/translations/qml_de.ts
)
qt5_create_translation(QM_FILES ${CMAKE_CURRENT_SOURCE_DIR} ${TRANSLATIONS})
qt5_add_resources(QRC_RESOURCES "silly.qrc")
add_executable(silly main.cpp
"${QRC_RESOURCES}"
"${QM_FILES}"
)
target_compile_features(silly PUBLIC cxx_std_17)
set_target_properties(silly PROPERTIES AUTOMOC ON AUTORCC ON)
target_link_libraries(silly PRIVATE Qt5::Quick Qt5::Qml)
target_include_directories(silly
PUBLIC
$<INSTALL_INTERFACE:.>
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}>
)
install(TARGETS silly)
src/main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.addImportPath("qrc:/");
engine.load(QUrl("qrc:/qml/silly.qml"));
return app.exec();
}
src/silly.qrc
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/qml">
<file alias="silly.qml">qml/silly.qml</file>
</qresource>
</RCC>
src/qml/silly.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
visible: true
Button {
anchors.fill: parent
spacing: 20
text: qsTr("Hello")
}
}
src/qml/translations/qml_de.ts
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="de_DE">
<context>
<name>silly</name>
<message>
<location filename="../silly.qml" line="11"/>
<source>Hello</source>
<translation>Hallo</translation>
</message>
</context>
</TS>
src/qml/translations/qml_en.ts
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en_US">
<context>
<name>silly</name>
<message>
<location filename="../silly.qml" line="11"/>
<source>Hello</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>
src/qml/translations/qml_fr.ts
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="fr_FR">
<context>
<name>silly</name>
<message>
<location filename="../silly.qml" line="11"/>
<source>Hello</source>
<translation>Bonjour</translation>
</message>
</context>
</TS>
It builds and runs with no errors, but when I attempt to test with this:
LANGUAGE=fr src/silly I get a button that says "Hello" instead of a button that says "Bonjour". I've been trying to figure this out for hours which also leads me to the secondary question: how does one generally troubleshoot Qt language translations? This is my first time and I could find no documentation on that.
That's pretty badly documented stuff which works magically with ready-made example using dedicated qmake configuration parameter embed_translations. I advice you to take a look into the original example's build dir where .qm files and a special qrc file qmake_qmake_qm_files.qrc get generated.
You don't need to use QTranslator unless you want to support dynamic language switch. At startup, QML runtime automatically loads a translation file qml_<language_COUNTRY>.qm (qml_xx_XX.qm where xx is ISO639 and XX is optional ISO 3166 code) from the i18n subdirectory of the root QML file, based on the system language, if it finds one.
You need to get your .qm files to qrc:/qml/i18n/ folder because your main qml file is in qrc:/qml/.
With CMake you can do it as follows:
Add a new qrc file, e.g. cmake_qm_files.qrc to your project
<RCC>
<qresource prefix="/qml/i18n">
<file>qml_de.qm</file>
<file>qml_en.qm</file>
<file>qml_fr.qm</file>
</qresource>
</RCC>
Get CMake to copy the qrc file to binary dir where .qm files get created
configure_file(cmake_qm_files.qrc ${CMAKE_BINARY_DIR} COPYONLY)
Get qrc file resource compiled and embedded to your executable
add_executable(silly main.cpp
${QRC_RESOURCES}
${CMAKE_BINARY_DIR}/cmake_qm_files.qrc
)
I typically use QLocale for translation testing as follows:
QGuiApplication app(argc, argv);
QLocale systemLocale = QLocale::system();
QLocale::Language language = systemLocale.language();
QLocale::Country country = systemLocale.country();
qDebug() << "System locale language:" << language << ", country:" << country;
// TEST: change default locale by removing comments below
// language = QLocale::French;
// country = QLocale::France;
language = QLocale::English;
country = QLocale::Australia;
QLocale locale(language, country);
qDebug() << "Changing default locale to language:" << locale.language() << ", country:" << locale.country();
QLocale::setDefault(locale); // TEST: set default locale to something else than system locale
QQmlApplicationEngine engine;

CMake 3.17 deletes Qt translations when updating the TS files

Update: Simplified problem
With CMake 3.16.8 or less, the following workflow was working, but 3.17+ deletes the Qt's TS files.
The idea is taken from Professional CMake, 7th Edition by Craig Scott
Requirements
cmake 3.17+, Qt 5.9+, ninja
Concept
To update the translation files for Qt, UPDATE_TRANSLATIONS can be enabled. When finished, disable it.
CMake 3.17+ deletes the updated TS files.
Adjust pathes in the script update_translation.sh to automate the workflow.
Steps to reproduce
git clone https://github.com/Macintron/QtTranslationDemo.git # or create files from below in QtTranslationDemo.
mkdir build # NOT in QtTranslationDemo
cd build
cmake -G Ninja -DCMAKE_PREFIX_PATH=[pathToQtDir/5.15.1/clang_64] ../QtTranslationDemo
ninja
./demo
Output should be:
Demo
de.qm: 85 bytes
Language: 'Deutsch'
greeting: ''
en.qm: 85 bytes
Language: 'English'
greeting: ''
now the problem starts:
cmake -DUPDATE_TRANSLATIONS=ON ../QtTranslationDemo
ninja demoTranslations
cmake -DUPDATE_TRANSLATIONS=OFF ../QtTranslationDemo
# new strings ("greeting") should haven been added to the ts files, but TS files are deleted instead!
Why are the TS files get deleted? Is this a bug in CMake 3.17+ or a bug in my workflow?
build info
The build directory must NOT be inside the sources.
Source files
CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
project(QtTranslationDemo LANGUAGES CXX)
find_package(Qt5
COMPONENTS
LinguistTools Core
REQUIRED
)
option(UPDATE_TRANSLATIONS "Enable rescanning sources to update .ts files" OFF)
set(_tsFiles en.ts de.ts)
if(UPDATE_TRANSLATIONS)
message("** parse sources for new translations")
qt5_create_translation(_qmFiles
main.cpp
${_tsFiles}
)
else()
message("** update qm files")
qt5_add_translation(_qmFiles
${_tsFiles}
)
endif()
add_custom_target(demoTranslations DEPENDS ${_qmFiles})
add_executable(demo
main.cpp
${_qmFiles}
)
target_link_libraries(demo
PUBLIC
Qt5::Core
)
main.cpp
#include <QTranslator>
#include <QDir>
#include <QStringList>
static const char* language = QT_TRANSLATE_NOOP("#default", "Language");
static const char* greeting = QT_TRANSLATE_NOOP("#default", "greeting"); // not in ts files now!
int main(int argc, char *argv[])
{
qDebug("Demo");
QStringList qms = QDir("./").entryList({"*.qm"});
for (const auto& qm: qms) {
qDebug("%s: %lld bytes", qPrintable(qm), QFileInfo("./" + qm).size());
QTranslator appTranslator;
if (appTranslator.load(qm, "./")) {
qDebug(" Language: '%s'", qPrintable(appTranslator.translate("#default", language)));
qDebug(" greeting: '%s'", qPrintable(appTranslator.translate("#default", greeting)));
} else {
qWarning("Failed to load %s", qPrintable(qm));
}
}
return 0;
}
en.ts
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en" sourcelanguage="en">
<context>
<name>#default</name>
<message>
<source>Language</source>
<translation>English</translation>
</message>
</context>
</TS>
de.ts
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="de" sourcelanguage="en">
<context>
<name>#default</name>
<message>
<source>Language</source>
<translation>Deutsch</translation>
</message>
</context>
</TS>
update_translation.sh
#!/bin/sh
set -e
thisdir=$(dirname $0)
qt_root=/usr/local/Trolltech/Qt5.15/5.15.1/clang_64
#cmaketool=/usr/local/Cellar/cmake/3.16.8/bin/cmake
cmaketool=cmake
# easier setup
rm -Rf en.qm de.qm CMakeFiles CMakeCache.txt cmake_install.cmake build.ninja .ninja_* > /dev/null 2>&1
git checkout $thisdir/de.ts $thisdir/en.ts # restore files
$cmaketool --version
$cmaketool -G Ninja -DCMAKE_PREFIX_PATH=$qt_root ../QtTranslationDemo
ninja
./demo
rm -f demo
echo "Starting CMake with DUPDATE_TRANSLATIONS..."
$cmaketool -DUPDATE_TRANSLATIONS=ON $thisdir
echo
echo "Updating translation files..."
ninja demoTranslations
echo
echo "Restore CMake configuration..."
$cmaketool -DUPDATE_TRANSLATIONS=OFF $thisdir
ninja
./demo
exit 0
This was a generic CMake problem, caused by the cleandead feature. It should be fixed in CMake 3.19.2.
Thank you all for your contributions to solve the problem.

How to translate default qsTr fields - e.g. MessageDialog Yes / No buttons

I have a small app that uses a Qt Quick MessageDialog. I created translations files with command
lupdate-qt5 ../myapp.pro .
In myapp.pro I indicated:
lupdate_only {
SOURCES += $$PWD/ui/*.qml
}
and
TRANSLATIONS += \
translations/i18n_nl.ts translations/i18n_fr.ts translations/i18n_en.ts
All translations are generated correctly. But I have no idea how to generate translations for the standard buttons that MessageDialog provides. In the following example the translations for "Warning" and "Please select Yes or No" are generated. But I can't get them generated for "Yes" and "No" (which is the text value of the StandardButtons property)
MessageDialog {
title: qsTr("Warning")
text: qsTr("Please select Yes or No")
icon: StandardIcon.Warning
standardButtons: StandardButton.Yes | StandardButton.No
//.....
}
I have checked the source code and it indicates that they should be translated:
Button {
id: yesButton
text: qsTr("Yes")
onClicked: root.click(StandardButton.Yes)
visible: root.standardButtons & StandardButton.Yes
}
I've also tried manually adding an entry Yes and No but that doesn't seem to help.
I've found an issue on stackoverflow that talks about adding the qml file to the .pro file to make it work, and that is something I already do. I though about adding the built-in MessageDialog, but I have no idea how to do this.
As a final note: I know that in Qt 5.3 the qsTr's weren't in MessageDialog. But starting from Qt 5.4 they are. I am currently on Qt 5.5
Any help is greatly appreciated.
EDIT
After posting this I kept looking and found an interesting post of someone who has had the same issue. Unfortunately, no answer there.
EDIT 2
Thank you tynn for the response. I have tried both suggestions but no succes. I did try something else as well. I added a qDebug in my code to see if it would translate. I was hoping the same translation would then be used for the MessageDialog, but unfortunatly that doesn't seem to be the case.
qDebug() << "Translate yes :" << tr("Yes"); //translates correctly, dialog doesn't
I have also tried to build a dialog from scratch that does the same as the built-in messagedialog, but at the moment my knowledge of qml is too limited to get this working.
Well, it may be a bit tricky.
First of all, localized strings for Qt widgets may be in Qt's .qm files. Remember that in general you will need all Qt's .qm files for locales you translate into. That's because Qt may, for example, use native MessageDialogs on platforms where they are available, and related code in this case will be located in qtbase, so you will need not only qtquickcontrols_XX.qm files, but also qtbase_XX.qm files for selected locales. And so on.
However, there may be cases when the above does not help. Required strings may simply be missing in the Qt's localization files for your locale (it's a quite common), so you will need to make .ts and .qm files for these strings by yourself. In this case you will need to study Qt sources in order to understand internals of those widgets you are interested in.
Please note that the following example depends on implementation details which may change in future Qt versions.
For example, Qt implementation of QML MessageDialog for Android and iOS uses QPlatformTheme that may be further subclassed to work with different platforms. In QPlatformTheme texts for button labels are returned by defaultStandardButtonText() method which looks like this:
QString QPlatformTheme::defaultStandardButtonText(int button)
{
switch (button) {
case QPlatformDialogHelper::Ok:
return QCoreApplication::translate("QPlatformTheme", "OK");
case QPlatformDialogHelper::Save:
return QCoreApplication::translate("QPlatformTheme", "Save");
case QPlatformDialogHelper::SaveAll:
return QCoreApplication::translate("QPlatformTheme", "Save All");
case QPlatformDialogHelper::Open:
return QCoreApplication::translate("QPlatformTheme", "Open");
case QPlatformDialogHelper::Yes:
return QCoreApplication::translate("QPlatformTheme", "&Yes");
case QPlatformDialogHelper::YesToAll:
return QCoreApplication::translate("QPlatformTheme", "Yes to &All");
case QPlatformDialogHelper::No:
return QCoreApplication::translate("QPlatformTheme", "&No");
case QPlatformDialogHelper::NoToAll:
return QCoreApplication::translate("QPlatformTheme", "N&o to All");
case QPlatformDialogHelper::Abort:
return QCoreApplication::translate("QPlatformTheme", "Abort");
case QPlatformDialogHelper::Retry:
return QCoreApplication::translate("QPlatformTheme", "Retry");
case QPlatformDialogHelper::Ignore:
return QCoreApplication::translate("QPlatformTheme", "Ignore");
case QPlatformDialogHelper::Close:
return QCoreApplication::translate("QPlatformTheme", "Close");
case QPlatformDialogHelper::Cancel:
return QCoreApplication::translate("QPlatformTheme", "Cancel");
case QPlatformDialogHelper::Discard:
return QCoreApplication::translate("QPlatformTheme", "Discard");
case QPlatformDialogHelper::Help:
return QCoreApplication::translate("QPlatformTheme", "Help");
case QPlatformDialogHelper::Apply:
return QCoreApplication::translate("QPlatformTheme", "Apply");
case QPlatformDialogHelper::Reset:
return QCoreApplication::translate("QPlatformTheme", "Reset");
case QPlatformDialogHelper::RestoreDefaults:
return QCoreApplication::translate("QPlatformTheme", "Restore Defaults");
default:
break;
}
return QString();
}
So, in order to localize Yes/No buttons, you will need to add in your .ts file the following:
<context>
<name>QPlatformTheme</name>
<message>
<source>&Yes</source>
<translation>[...]</translation>
</message>
<message>
<source>&No</source>
<translation>[...]</translation>
</message>
</context>
Android have its own subclassed platform theme (QAndroidPlatformTheme) with overriden defaultStandardButtonText(), so for Android you will need to add the following:
<context>
<name>QAndroidPlatformTheme</name>
<message>
<source>Yes</source>
<translation>[...]</translation>
</message>
<message>
<source>No</source>
<translation>[...]</translation>
</message>
</context>
iOS does not override this method in its own QPlatformTheme subclass, so no additional action is needed for it.
You can take a look on one of my projects which use the technique described above for QML MessageBox localization on Android and iOS.
The translations you need should be found inside a qtquickcontrols_*.qm file. Deploying Translations states concerning this
Usually, there are .qm files for the application, and, if a version of Qt is used that is not installed on the system, Qt's .qm files need to be deployed as well.
However your application might just fail to find a suitable translation file. If you only need the translations for Yes and No, you could as well add these to your translation files with a context of DefaultMessageDialog
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>DefaultMessageDialog</name>
<message>
<source>Yes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>No</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>
Adding the built-in MessageDialog would work as well. Or if you'd like to, you could just use a dummy file DefaultMessageDialog.qml
Rectangle {
Button {
id: yesButton
text: qsTr("Yes")
}
Button {
id: noButton
text: qsTr("No")
}
}
and add this one instead.
On Desktop platforms, such as Windows, macOS and Linux, most Dialog components from QtQuick.Dialogs uses C++ widget components. Their source translations are covered in qtbase_{lang}.ts files and their compiled translations are covered in qtbase_{lang}.qmfiles.
In Qt5.13.1:
refer to C:\Qt\Qt5.13.1\5.13.1\Src\qttranslations\translations for source translations
refer to C:\Qt\Qt5.13.1\5.13.1\mingw83_64\translations for the compiled translations
If you find the sizes of qtbase to be too large for your liking, you can deploy a minified version of the translation files. The following Windows Batch file creates French, German and Japanese subsets of the qtbase files:
setlocal
set QTDIR=C:\Qt\Qt5.13.1\5.13.1\msvc2017_64\
set QTSRC=C:\Qt\Qt5.13.1\5.13.1\Src
ECHO %QTSRC%\qtbase\src\widgets\dialogs\qmessagebox.cpp > %TEMP%\qtbase_min.lst
ECHO %QTSRC%\qtbase\src\widgets\dialogs\qfiledialog.cpp >> %TEMP%\qtbase_min.lst
ECHO %QTSRC%\qtbase\src\widgets\dialogs\qcolordialog.cpp >> %TEMP%\qtbase_min.lst
ECHO %QTSRC%\qtbase\src\widgets\dialogs\qfontdialog.cpp >> %TEMP%\qtbase_min.lst
ECHO %QTSRC%\qtbase\src\widgets\dialogs\qinputdialog.cpp >> %TEMP%\qtbase_min.lst
ECHO %QTSRC%\qtbase\src\widgets\dialogs\qprogressdialog.cpp >> %TEMP%\qtbase_min.lst
ECHO %QTSRC%\qtbase\src\widgets\dialogs\qwizard.cpp >> %TEMP%\qtbase_min.lst
ECHO %QTSRC%\qtbase\src\gui\kernel\qplatformtheme.cpp >> %TEMP%\qtbase_min.lst
ECHO %QTSRC%\qtbase\src\plugins\platforms\android\qandroidplatformtheme.cpp >> %TEMP%\qtbase_min.lst
ECHO %QTSRC%\qtbase\src\platformsupport\themes\genericunix\qgenericunixthemes.cpp >> %TEMP%\qtbase_min.lst
for /d %%F in (fr de ja en) do copy %QTSRC%\qttranslations\translations\qtbase_%%F.ts qtbase_min_%%F.ts
%QTDIR%\bin\lupdate #%TEMP%/qtbase_min.lst -pluralonly -locations none -ts qtbase_min_en.ts
for /d %%F in (fr de ja en) do if "%%F" neq "en" %QTDIR%\bin\lupdate.exe #%TEMP%/qtbase_min.lst -no-obsolete -locations none -ts qtbase_min_%%F.ts
for /d %%F in (fr de ja en) do %QTDIR%\bin\lrelease qtbase_min_%%F.ts
On mobile platforms, such as iOS and Android, Dialog the MessageDialog component the translatable text are still covered in the qtbase_{lang}.ts files. For the other components, such as ColorDialog, FontDialog, they are implemented in QML as QtQuick components. The translations will be found in the qtquickcontrols_{lang}.ts and qtquickcontrols_{lang}.qm files.
The following demonstrates how to create minified versions of the qtquickcontrols_{lang}.ts and qtquickcontrols_{lang}.qm files for French, German and Japanese:
setlocal
set QTDIR=C:\Qt\Qt5.13.1\5.13.1\msvc2017_64\
set QTSRC=C:\Qt\Qt5.13.1\5.13.1\Src
ECHO %QTSRC%\qtquickcontrols\src\dialogs\DefaultMessageDialog.qml > %TEMP%\qtquickcontrols_min.lst
ECHO %QTSRC%\qtquickcontrols\src\dialogs\DefaultColorDialog.qml >> %TEMP%\qtquickcontrols_min.lst
ECHO %QTSRC%\qtquickcontrols\src\dialogs\DefaultFileDialog.qml >> %TEMP%\qtquickcontrols_min.lst
ECHO %QTSRC%\qtquickcontrols\src\dialogs\DefaultFontDialog.qml >> %TEMP%\qtquickcontrols_min.lst
ECHO %QTSRC%\qtquickcontrols\src\dialogs\DefaultDialogWrapper.qml >> %TEMP%\qtquickcontrols_min.lst
for /d %%F in (fr de ja en) do copy %QTSRC%\qttranslations\translations\qtquickcontrols_%%F.ts qtquickcontrols_min_%%F.ts
%QTDIR%\bin\lupdate #%TEMP%/qtquickcontrols_min.lst -pluralonly -locations none -ts qtquickcontrols_min_en.ts
for /d %%F in (fr de ja en) do if "%%F" neq "en" %QTDIR%\bin\lupdate.exe #%TEMP%/qtquickcontrols_min.lst -no-obsolete -locations none -ts qtquickcontrols_min_%%F.ts
for /d %%F in (fr de ja en) do %QTDIR%\bin\lrelease qtquickcontrols_min_%%F.ts
Presently, at Qt5.13.1, there are 22 languages (including English). If your desired language is not covered in this list (e.g. Indonesian, Vietnamese), then, you can still use the above scripts to create placeholder minified version of qtbase/qtquickcontrols but you will have to populate the qtbase_min_{lang}.ts files yourself.

How to include nmath.h?

I would like to include the header nmath.h for my C code (within an R package) to find R_FINITE and ML_ERR_return_NAN. I found that one cannot include nmath.h directly. For R_FINITE to be found, I could include R_ext/libextern.h. But I don't know what to include so that ML_ERR_return_NAN is found. Any ideas? I found here that Prof. Brian Ripley referred to Writing R Extensions, but I couldn't find nmath.h being addressed there (where exactly?)
On Debian or Ubuntu:
sudo apt-get install r-mathlib
after which you can build test programs such as this:
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4;
// compile-command: "gcc -s -Wall -O3 \
// -I/usr/share/R/include -o rmath_rnorm \
// rmath_rnorm.c -lRmath -lm" -*-
// Compare to
// $ Rscript -e "RNGkind('Marsaglia'); \
// .Random.seed[2:3] <- c(123L, 456L); rnorm(2)"
// [1] -0.2934974 -0.3343770
#include <stdio.h>
#define MATHLIB_STANDALONE 1
#include <Rmath.h>
int main(void) {
set_seed(123, 456);
printf("rnorm: %f %f\n", rnorm(0.0, 1.0), rnorm(0.0, 1.0));
return 0;
}
Note: The first four lines should be one-line in the file you safe, then M-x compile build the program for your. Ditto for the Rscript invocation: one line.
Edit: Drats. Answered the wrong question :) nmath.h appears to not be exported from src/nmath/nmath.h but this R Mathlibrary is what is exported by R Core for use by others. Where as the nmath.h file has
/* Private header file for use during compilation of Mathlib */
#ifndef MATHLIB_PRIVATE_H
#define MATHLIB_PRIVATE_H
so you are not supposed to rely on it.

Resources