Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a reliable way to change and then unchange the locale in R?

Tags:

r

locale

Within a function, I want to change the locale, do some stuff, then unchange it. Because side effects are bad.

old_locale <- Sys.getlocale()

# do some stuff

Sys.setlocale(old_locale)

However, Sys.setlocale requires a category and locale argument.

On the other hand, Sys.getlocale() gives me this:

"LC_COLLATE=English_Australia.1252;LC_CTYPE=English_Australia.1252;LC_MONETARY=English_Australia.1252;LC_NUMERIC=C;LC_TIME=English_Australia.1252"

Ok. I can probably deal with this:

old_locale <- Sys.getlocale()
locale_key_values <- strsplit(strsplit(old_locale, ';')[[1]], '=')[[1]], '=')
locale_keys <- lapply(locale_key_values, getElement, name=1)
locale_values <- lapply(locale_key_values, getElement, name=2)

# do some stuff

mapply(Sys.setlocale, category=locale_keys, locale=locale_values)

Problem solved!

...or is it?

Sys.setlocale(locale='C')

Sys.getlocale() now returns "C"! That's not going to work with my key-value parser above.

And I suddenly realise that I don't know anything about locales or the range of strings that Sys.getlocale() might return.

Does anyone know of a reliable way to save and restore locale state?

like image 591
logworthy Avatar asked Sep 05 '16 03:09

logworthy


1 Answers

?Sys.getlocale says:

For category = "LC_ALL" the details of the string are system-specific: it might be a single locale name or a set of locale names separated by "/" (Solaris, OS X) or ";" (Windows, Linux). For portability, it is best to query categories individually: it is not necessarily the case that the result of foo <- Sys.getlocale() can be used in Sys.setlocale("LC_ALL", locale = foo).

So you need to do something like:

localeCategories <- c("LC_COLLATE","LC_CTYPE","LC_MONETARY","LC_NUMERIC","LC_TIME")
locales <- setNames(lapply(localeCategories, Sys.getlocale), localeCategories)

Better yet, you should determine which locale setting(s) you need to change, and only change the one(s) you need to. For example, you might only need to change LC_TIME if you're parsing date-time character strings, or you might only need to change LC_COLLATE if you need to change the character string collation order.

like image 60
Joshua Ulrich Avatar answered Sep 20 '22 20:09

Joshua Ulrich