rshinyshinyappssetlocalersconnect

Use multiple locales in R ShinyApp deployed to shinyapps.io


I've built an app where users have the option to generate reports in English, Spanish, and Portuguese. The reports have a time stamp at the top that relies on Sys.setlocale and format to translate and display the date properly depending on the selected language. (E.g. "02 março, 2023" for Portuguese.) Works locally, but fails on shinyapps.io with the following warnings in the log:

OS reports request to set locale to "pt_BR.UTF-8" cannot be honored

OS reports request to set locale to "en_US.UTF-8" cannot be honored

Stripped down app.R:

library(shiny)
library(dplyr)
library(tools) # cap functions

ui <- fluidPage(
  selectInput(
    inputId="langSel",
    label="Select Lanugage",
    choices=c("English"="en_US",
              "Spanish"="es_MX",
              "Portuguese"="pt_BR"),
    selected="en_US"
  ),
  textOutput("repDateOut")
)

server <- function(input, output, session) {
  
  timeStamp <- "2023-03-02"
  
  # set locale depending on language selection to translate month
  observeEvent(input$langSel,{
    Sys.setlocale("LC_TIME", paste0(input$langSel,".UTF-8"))
  })
  
  repDate <- reactive({
    dateOrder <- if (input$langSel=="en_US"){
      '%B %d, %Y' # month before day for English
    } else {
      '%d %B, %Y' # day before month for everything else
    }
    fmDate <- format(as.Date(timeStamp), dateOrder) %>%
      {if (input$langSel=="en_US") toTitleCase(.) else .} # cap month for English only
    fmDate
  })
  
  # print timestamp
  output$repDateOut <- renderText({repDate()})
  
}

shinyApp(ui = ui, server = server)

Following the advice here about making non-local locales available in rsconnect before deploying, I've tried running a few things in the console to deploy the app:

Attempt 1:

options(rsconnect.locale.cache = FALSE, rsconnect.locale = "en_US.UTF-8")
options(rsconnect.locale.cache = FALSE, rsconnect.locale = "pt_BR.UTF-8")
options(rsconnect.locale.cache = FALSE, rsconnect.locale = "es_MX.UTF-8")
rsconnect::deployApp()

Attempt 2:

options(rsconnect.locale.cache = FALSE, rsconnect.locale = "en_US.UTF-8")
options(rsconnect.locale = "pt_BR.UTF-8")
options(rsconnect.locale = "es_MX.UTF-8")
rsconnect::deployApp()

Attempt 3:

options(rsconnect.locale.cache = FALSE, rsconnect.locale = "en_US.UTF-8", rsconnect.locale = "pt_BR.UTF-8", 
rsconnect.locale = "es_MX.UTF-8")
rsconnect::deployApp()

In each case, only the Spanish locale (last one specified) works. (rsconnect.locale=c("en_US.UTF-8","pt_BR.UTF-8","es_MX.UTF-8") errors out at deployment.) Is there a way to make all three available in shinyapps.io?


Solution

  • @hadley provided an answer on rsconnect GitHub which worked like a charm:

    While we might want to somehow fix this on shinyapps, there is a fix that's available now (and is also more reliable than relying system locales): use a date-time package that has different locales built in. For example, here's an example using the clock package:

    library(clock)
    
    date <- as.Date("2023-01-02")
    
    date_format(date, format = "%d %B %Y", locale = clock_locale("en"))
    #> [1] "02 January 2023"
    date_format(date, format = "%d %B %Y", locale = clock_locale("es"))
    #> [1] "02 enero 2023"
    date_format(date, format = "%d %B %Y", locale = clock_locale("pt"))
    #> [1] "02 janeiro 2023"
    

    Not only does it translate the months, but UTF-8 is also built-in so special characters are handled automatically, and month capitalization is also handled according to language.