[education/rkward] rkward/rbackend: Handle runtime backend language changes

Thomas Friedrichsmeier null at kde.org
Thu Oct 16 20:57:56 BST 2025


Git commit 550c9b7138683efc65e011ec8797b9fa07efd702 by Thomas Friedrichsmeier.
Committed on 14/10/2025 at 16:13.
Pushed by tfry into branch 'master'.

Handle runtime backend language changes

M  +27   -1    rkward/rbackend/rkrbackend.cpp
M  +2    -4    rkward/rbackend/rpackages/rkward/R/base_overrides.R

https://invent.kde.org/education/rkward/-/commit/550c9b7138683efc65e011ec8797b9fa07efd702

diff --git a/rkward/rbackend/rkrbackend.cpp b/rkward/rbackend/rkrbackend.cpp
index d77b19369..805d2d381 100644
--- a/rkward/rbackend/rkrbackend.cpp
+++ b/rkward/rbackend/rkrbackend.cpp
@@ -885,6 +885,32 @@ QString getLibLoc() {
 	return RKRBackendProtocolBackend::dataDir() + u"/.rkward_packages/"_s + QString::number(RKRBackend::this_pointer->r_version / 10);
 }
 
+/* Check whether we still want to translate to the same language as last time.
+ * Calling this on every single i18n-call is silly, but not a real world performance problem
+ * (as translated strings imply user interaction). The underlying problem is that we have not
+ * good way of detecting, when R might switch the language. (Typical entry points include
+ * switchLanguage(), Sys.setenv(LANGUAGE=), Sys.setlocale("LC_MESSAGES")) */
+void checkCurrentLanguage() {
+	static QByteArray previous_locale;
+
+	// R's language always corresponds to LANGUAGE env-var, if set, but, on Unix falls back to
+	// LC_MESSAGES, if LANGUAGE is not set.
+	QByteArray current_locale = qgetenv("LANGUAGE");
+#if !defined(Q_OS_WIN)
+	if (current_locale.isEmpty()) current_locale = setlocale(LC_MESSAGES, nullptr);
+#endif
+	if (current_locale != previous_locale) {
+		previous_locale = current_locale;
+		KLocalizedString::clearLanguages();
+		auto langs = QString::fromUtf8(current_locale).split(u':');
+		for (int i = 0; i < langs.length(); ++i) {
+			langs[i] = langs[i].section(u'.', 0, 0).section(u'_', 0, 0);
+		}
+		//RFn::Rf_warning("%s->%s", qPrintable(QString::fromUtf8(lang)), qPrintable(langs.join(u',')));
+		KLocalizedString::setLanguages(langs);
+	}
+}
+
 // Function to handle several simple calls from R code, that do not need any special arguments, or interaction with the frontend process.
 SEXP doSimpleBackendCall(SEXP _call) {
 	RK_TRACE(RBACKEND);
@@ -893,6 +919,7 @@ SEXP doSimpleBackendCall(SEXP _call) {
 	QString call = list[0];
 
 	if (call == QStringLiteral("i18n")) {
+		checkCurrentLanguage();
 		auto msg = ki18n(list.value(1).toUtf8().constData());
 		for (int i = 2; i < list.length(); ++i) {
 			msg = msg.subs(list[i]);
@@ -939,7 +966,6 @@ SEXP doUpdateLocale() {
 	RK_TRACE(RBACKEND);
 
 	RK_DEBUG(RBACKEND, DL_WARNING, "Changing locale");
-	// TODO: properly handle re-initialization of translation, too!
 	RKTextCodec::reinit();
 
 	return ROb(R_NilValue);
diff --git a/rkward/rbackend/rpackages/rkward/R/base_overrides.R b/rkward/rbackend/rpackages/rkward/R/base_overrides.R
index 1fa7ca47e..7dd6ba35a 100644
--- a/rkward/rbackend/rpackages/rkward/R/base_overrides.R
+++ b/rkward/rbackend/rpackages/rkward/R/base_overrides.R
@@ -87,11 +87,9 @@
 #' @export
 #' @rdname base_overrides
 "Sys.setlocale" <- function (category = "LC_ALL", locale = "", ...) {
-	if (category == "LC_ALL" || category == "LC_CTYPE" || category == "LANG") {
-		 .rk.call("preLocaleChange")
-
+	if (category %in% c("LC_ALL", "LC_CTYPE", "LANG")) {
+		.rk.call("preLocaleChange")
 		ret <- base::Sys.setlocale (category, locale, ...)
-
 		.Call ("rk.update.locale", PACKAGE="(embedding)")
 		ret
 	} else {



More information about the rkward-tracker mailing list