You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
attached base packages:
[1] stats graphics grDevices utils datasets methods base
loaded via a namespace (and not attached):
[1] compiler_4.2.0 tools_4.2.0
R/setLanguage.R with fix:
Management of locales and message translation using msgcat
#' Change or get the language used in R and Tcl/Tk, strings translation in Tcl
#'
#' The function changes dynamically the language used by both R (messages only)
#' and Tcl/Tk, retrieves its current value, and manage string translation in
#' Tcl.
#'
#' @param lang An identification for the targeted language, for instance, "en"
#' for English, "en_US" for american English, "fr" for French, "de" for
#' German, "it" for Italian, etc. Facultative argument for [tclmclocale()].
#' @param msg A single character string with the message to translate.
#' @param translation The corresponding version in lang. Substitutions markers
#' like %s for strings, or %d for numbers are allowed (same syntax as
#' [base::gettextf()]). These translations are added in the Tcl catalog in the
#' main domain, i.e., you don't need to give a domain name with [tclmc()] to
#' retrieve the translation.
#' @param fmt A single character vector of format string.
#' @param ... Values to be passed into \code{fmt} for the substitution.
#' @param domain The 'domain", i;e., Tcl namespace where the translation is
#' defined. Use NULL (the default) or "" for the main domain where
#' translations using [tclmcset()] are stored.
#'
#' @return
#' [setLanguage()] returns TRUE if language was successfully changed in
#' Tcl/Tk, FALSE otherwise. [getLanguage()] returns a string with current
#' language in use for R, or an empty string if it cannot determinate which is
#' the language currently used, and a tcl.language attribute with the
#' different catalogs that are used in priority order (ending with "" for no
#' translation, i.e., Tcl translations do not return an error, but the initial
#' string if the item is not found in the catalog).
#' [tclmclocale()] allows to change and get language for Tcl only, without
#' changing anything for R.
#'
#' The two functions [tclmcset()] and [tclmc()] allow to record and retrieve the
#' translation of strings in the main R domain. Moreover, [tclmc()] also allows
#' to retrieve translations of Tcl strings in other Tcl namespaces (a.k.a.,
#' domains), see the examples.
#'
#' @note You need the msgcat Tcl package to use this (but it is provided with
#' all recent distributions of Tcl/Tk by default).
#'
#' @author Philippe Grosjean
#' @export
#' @Keywords utilities
#' @concept Tcl/Tk language translation
#'
#' @examples
#' # What is the language used by Tcl?
#' tclmclocale()
#'
#' # Define a simple translation in French and German
#' tclmcset("de", "Yes", "Ja")
#' tclmcset("fr", "Yes", "Oui")
#'
#' # Determine which language is currently in use in R
#' (oldlang <- getLanguage())
#' if (oldlang != "") {
#' # Switch to English; test a command that issues a warning and a Tcl string
#' setLanguage("en_US")
#' 1:3 + 1:2
#' tclmc("Yes")
#'
#' # Switch to German and test
#' setLanguage("de")
#' 1:3 + 1:2
#' tclmc("Yes")
#'
#' # Switch to Belgian French and test
#' setLanguage("fr_BE")
#' 1:3 + 1:2
#' tclmc("Yes")
#'
#' # A more complex trnaslation message with a substitution
#' tclmcset("fr", "Directory contains %d files",
#' "Le repertoire contient %d fichiers")
#' tclmc("Directory contains %d files", 9)
#' # or from a R/Tcl variable...
#' nfiles <- tclVar(12)
#' tclmc("Directory contains %d files", tclvalue(nfiles))
#'
#' # Retrieve a translation defined in the "tk" domain
#' tclmc("Replace existing file?", domain = "tk")
#'
#' # Tcl dialog boxes are translated according to the current language
#' \dontrun{
#' tkgetOpenFile()
#' }
#'
#' # Restore previous language
#' setLanguage(oldlang)
#' }
setLanguage <- function(lang) {
Change locale for both R and Tcl/Tk
Sys.setenv(language = lang)
Sys.setenv(LANG = lang)
#try(Sys.setlocale("LC_MESSAGES", lang), silent = TRUE) # Fails on Windows!
res <- tclRequire("msgcat")
if (inherits(res, "tclObj")) {
.Tcl("namespace import msgcat::")
# If the tcl.language attribute is defined, use it
tcllang <- attr(lang, "tcl.language")
if (!is.null(tcllang) && tcllang[1] != "") {
lang <- tcllang[1] # Use only first item
} else {
# Tcl does not accept locales like en_US.UF-8: must be en_us only
lang <- tolower(sub("^([^.]+)\..$", "\1", lang))
}
tclmclocale(lang)
TRUE
} else {
FALSE
}
}
#' @export
#' @Rdname setLanguage
tclmclocale <- function(lang) {
if (missing(lang)) {
as.character(tcl("mclocale"))
} else {
# Make sure lang is made compatible to Tcl
lang <- tolower(sub("^([^.]+)\..*$", "\1", lang))
as.character(tcl("mclocale", lang))
}
}
Loading the library crashes RStudio.
A quick fix in the setLanguage.R file solved the issue, but I cannot push it. File content is copied here below:
RStudio version:
RStudio 2022.07.1+554 "Spotted Wakerobin" Release (7872775ebddc40635780ca1ed238934c3345c5de, 2022-07-22) for Windows
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.12.8 Chrome/69.0.3497.128 Safari/537.36
Matrix products: default
locale:
[1] LC_COLLATE=Dutch_Belgium.1252 LC_CTYPE=Dutch_Belgium.1252 LC_MONETARY=Dutch_Belgium.1252 LC_NUMERIC=C LC_TIME=Dutch_Belgium.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
loaded via a namespace (and not attached):
[1] compiler_4.2.0 tools_4.2.0
R/setLanguage.R with fix:
Management of locales and message translation using msgcat
#' Change or get the language used in R and Tcl/Tk, strings translation in Tcl
#'
#' The function changes dynamically the language used by both R (messages only)
#' and Tcl/Tk, retrieves its current value, and manage string translation in
#' Tcl.
#'
#' @param lang An identification for the targeted language, for instance, "en"
#' for English, "en_US" for american English, "fr" for French, "de" for
#' German, "it" for Italian, etc. Facultative argument for [tclmclocale()].
#' @param msg A single character string with the message to translate.
#' @param translation The corresponding version in
lang
. Substitutions markers#' like %s for strings, or %d for numbers are allowed (same syntax as
#' [base::gettextf()]). These translations are added in the Tcl catalog in the
#' main domain, i.e., you don't need to give a domain name with [tclmc()] to
#' retrieve the translation.
#' @param fmt A single character vector of format string.
#' @param ... Values to be passed into \code{fmt} for the substitution.
#' @param domain The 'domain", i;e., Tcl namespace where the translation is
#' defined. Use
NULL
(the default) or""
for the main domain where#' translations using [tclmcset()] are stored.
#'
#' @return
#' [setLanguage()] returns
TRUE
if language was successfully changed in#' Tcl/Tk,
FALSE
otherwise. [getLanguage()] returns a string with current#' language in use for R, or an empty string if it cannot determinate which is
#' the language currently used, and a
tcl.language
attribute with the#' different catalogs that are used in priority order (ending with
""
for no#' translation, i.e., Tcl translations do not return an error, but the initial
#' string if the item is not found in the catalog).
#' [tclmclocale()] allows to change and get language for Tcl only, without
#' changing anything for R.
#'
#' The two functions [tclmcset()] and [tclmc()] allow to record and retrieve the
#' translation of strings in the main R domain. Moreover, [tclmc()] also allows
#' to retrieve translations of Tcl strings in other Tcl namespaces (a.k.a.,
#' domains), see the examples.
#'
#' @note You need the msgcat Tcl package to use this (but it is provided with
#' all recent distributions of Tcl/Tk by default).
#'
#' @author Philippe Grosjean
#' @export
#' @Keywords utilities
#' @concept Tcl/Tk language translation
#'
#' @examples
#' # What is the language used by Tcl?
#' tclmclocale()
#'
#' # Define a simple translation in French and German
#' tclmcset("de", "Yes", "Ja")
#' tclmcset("fr", "Yes", "Oui")
#'
#' # Determine which language is currently in use in R
#' (oldlang <- getLanguage())
#' if (oldlang != "") {
#' # Switch to English; test a command that issues a warning and a Tcl string
#' setLanguage("en_US")
#' 1:3 + 1:2
#' tclmc("Yes")
#'
#' # Switch to German and test
#' setLanguage("de")
#' 1:3 + 1:2
#' tclmc("Yes")
#'
#' # Switch to Belgian French and test
#' setLanguage("fr_BE")
#' 1:3 + 1:2
#' tclmc("Yes")
#'
#' # A more complex trnaslation message with a substitution
#' tclmcset("fr", "Directory contains %d files",
#' "Le repertoire contient %d fichiers")
#' tclmc("Directory contains %d files", 9)
#' # or from a R/Tcl variable...
#' nfiles <- tclVar(12)
#' tclmc("Directory contains %d files", tclvalue(nfiles))
#'
#' # Retrieve a translation defined in the "tk" domain
#' tclmc("Replace existing file?", domain = "tk")
#'
#' # Tcl dialog boxes are translated according to the current language
#' \dontrun{
#' tkgetOpenFile()
#' }
#'
#' # Restore previous language
#' setLanguage(oldlang)
#' }
setLanguage <- function(lang) {
Change locale for both R and Tcl/Tk
Sys.setenv(language = lang)
Sys.setenv(LANG = lang)
#try(Sys.setlocale("LC_MESSAGES", lang), silent = TRUE) # Fails on Windows!
res <- tclRequire("msgcat")
if (inherits(res, "tclObj")) {
.Tcl("namespace import msgcat::")
# If the tcl.language attribute is defined, use it
tcllang <- attr(lang, "tcl.language")
if (!is.null(tcllang) && tcllang[1] != "") {
lang <- tcllang[1] # Use only first item
} else {
# Tcl does not accept locales like en_US.UF-8: must be en_us only
lang <- tolower(sub("^([^.]+)\..$", "\1", lang))
}
tclmclocale(lang)
TRUE
} else {
FALSE
}
}
#' @export
#' @Rdname setLanguage
getLanguage <- function() {
Try to recover current language used for messages and GUI stuff in R
lang <- Sys.getenv("language")
if (lang == "")
lang <- Sys.getlocale("LC_MESSAGES")
This is a bad hack that probably does not work all the time, but at least,
it works under Windows for getting "fr" for French language
if (lang == "")
lang <- tolower(substr(Sys.getlocale("LC_COLLATE"), 1, 2))
Try to get language information from Tcl
tcllang <- try(as.character(tcl("mcpreferences")), silent = TRUE)
attr(lang, "tcl.language") <- tcllang
lang
}
#' @export
#' @Rdname setLanguage
tclmclocale <- function(lang) {
if (missing(lang)) {
as.character(tcl("mclocale"))
} else {
# Make sure lang is made compatible to Tcl
lang <- tolower(sub("^([^.]+)\..*$", "\1", lang))
as.character(tcl("mclocale", lang))
}
}
#' @export
#' @Rdname setLanguage
tclmcset <- function(lang, msg, translation)
invisible(tclvalue(tcl("mcset", lang, msg, translation)))
#' @export
#' @Rdname setLanguage
tclmc <- function(fmt, ..., domain = NULL) {
if (is.null(domain) || domain == "") {
# Simpler form
tclvalue(tcl("mc", fmt, ...))
} else {
# Need to evaluate in 'domain' Tcl namespace
transl <- .Tcl(paste0("namespace eval ", domain, " {set ::Rtransl [mc {",
fmt, "}]}"))
sprintf(tclvalue(transl), ...)
}
}
The text was updated successfully, but these errors were encountered: