Shiny App: translation in modules and update language choice while browsing between them

Viewed 365

Problem description: I have a modularized Shiny App, written in English, which has a translation for Portuguese (translated using the shiny.i18n package). Its' base is written in a mainPanel/tabPanel format and each tabPanel, which corresponds to each module, has an UI that is translated and a textOutput which is based in a multicolumn dataset filtered by language. I use the same input (input$language) to both translate the UI and define the value of the two_languages_dataset$languagecolumn that will produce the output.

The translation works fine but when I change panels, the second panel "inherits" the UI translation from the first, but the input$languageis not updated, thus leaving the UI "inconsistent".

For a minimal example (code in the end):

(1) This is the original homepage for the app.

1

(2) I translate it to Portuguese (works fine)

2

(3) When I switch to the second panel, the UI "inherits" the Portuguese translation but the textOutputis in English, since it's the app's base-language (and first choice for the input$language.

3

Question: how can I update the input$language when changing tabs/modules, so that the language chosen is the same for the whole UI?. It seems that a good option might be inserting a "translation button" on the homepage but I couldn't figure out how to carry this information to every module.

[The problem is adapted from a more complex app in a way that I hope helps other users understand my issue, so I can adapt the solution to the "larger app". This means that changing the tabPanel structure, eliminate modules or inserting a new language input are not attractive solutions for me.]

Code:

Module 1:

# MODULE 1

mod1_server <- function(id, global_session) {
  
  shiny::moduleServer(
    id,
    function(input, output, session) {
      
      observeEvent(input$language, {
        # Here is where we update language in session
        shiny.i18n::update_lang(global_session, input$language)
      })
      
      
      output$initial_text1 <- renderText({
        
        two_languages_dataset <- data.frame(language = c("en", "pt"),
                                            text = c("Welcome!", "Bem-vindo!"))
        
        two_languages_dataset %>%
          filter(language == input$language) %>%
          .$text
        
        
      })
      
    }
    
  )
  
}

mod1_ui <- function(id, i18n){
  
  ns <- NS(id)
  
  tagList(
    
    # Page title and description
    tags$div(class = "sheet_topper",
             tags$div(tags$h1(i18n$t("Initial text"), style = "text-align:center"),
                      tags$p(i18n$t("This text is an example")),
                      tags$br(),
                      selectInput(inputId = ns("language"),
                                  label = tags$div(icon("language", class = "icons"), i18n$t('Choose language')),
                                  c("Português" = "pt",
                                    "English" = "en"),
                                  selected = i18n$get_key_translation())
             )),
    
    textOutput(ns("initial_text1"))
    
  )
  
}

Module 2:

### MODULE 2

mod2_server <- function(id, global_session) {
  
  shiny::moduleServer(
    id,
    function(input, output, session) {
      
      observeEvent(input$language, {
        # Here is where we update language in session
        shiny.i18n::update_lang(global_session, input$language)
      })
      
      
      output$initial_text2 <- renderText({
        
        two_languages_dataset <- data.frame(language = c("en", "pt"),
                                            text = c("Welcome!", "Bem-vindo!"))
        
        two_languages_dataset %>%
          filter(language == input$language) %>%
          .$text
        
        
      })
      
    }
    
  )
  
}


mod2_ui <- function(id, i18n){
  
  ns <- NS(id)
  
  tagList(
    
    # Page title and description
    tags$div(class = "sheet_topper",
             tags$div(tags$h1(i18n$t("Initial text 2"), style = "text-align:center"),
                      tags$p(i18n$t("This text is an example 2")),
                      tags$br(),
                      selectInput(inputId = ns("language"),
                                  label = tags$div(icon("language", class = "icons"), i18n$t('Choose language')),
                                  c("Português" = "pt",
                                    "English" = "en"),
                                  selected = i18n$get_key_translation())
             )),
    
    textOutput(ns("initial_text2"))
    
  )
  
}

app.R:

library(shiny)
library(tidyverse)
library(shiny.i18n)

i18n <- Translator$new(translation_csvs_path = "data")

# FINAL APP

server <- function(input, output, session){
  
  mod1_server("module1", global_session = session)
  mod2_server("module2", global_session = session)
  
}

ui <- fluidPage(
  
  shiny.i18n::usei18n(i18n),
  
  mainPanel(
    tabsetPanel(
      tabPanel(i18n$t("First subset of data"),
               mod1_ui("module1", i18n = i18n)),
      tabPanel(i18n$t("Second subset of data"),
               mod2_ui("module2", i18n = i18n))
     
    # Close tabset 
    )
    
    # Close mainPanel
    )
  # Close fluidPage
)

###################################################################################################

shinyApp(ui = ui, server = server)
0 Answers
Related