Internationalization of shiny apps has never been easier!

[This article was first published on r – Appsilon Data Science | We Provide End­ to­ End Data Science Solutions, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.


Have you ever created a multilingual Shiny app? It is very likely that the answer is no, because Shiny just doesn’t have any good tools for that. In Appsilon we came across the internationalization problem many times, so we decided to make a tool which makes a live easier when it comes to mulitlingual. shiny.i18n is the new kid on the block and still under rapid development, but the 0.1.0 version is already ready to go.

NOTE:shiny.i18n usage is not limited to Shiny apps. You can use it as standalone R package for generating multilingual reports or visualizations. We decided on this name because Shiny is the most common and obvious use-case scenario.


The latest version the package (0.1.0) will be released to CRAN (edit: it’s being currently reviewed, should be live at 14th of September, for now please use GitHub repository), so you can simply get it like this:


To install the development version always check the GitHub project first.


In the GitHub page, you can also find more examples, read the documentation, post some issues or your own contributions.


Now it’s time to learn more about how to use shiny.i18n. The package utilizes specific translation file data formats. Currently two approaches are supported.

JSON translation format

Example of a JSON translation file for English and polish language you can find below:

  "languages": ["en", "pl"],
  "translation": [
      {"en": "Hello Shiny!", "pl": "Witaj Shiny!"},
      {"en": "Number of bins:", "pl": "Liczba podziałek"},
        "en": "This is description of the plot.",
        "pl": "To jest opis obrazka."
        "en": "Histogram of x",
        "pl": "Histogram x"
        "en": "Frequency",
        "pl": "Częstotliwość"

It consists of a single file translation.json with two mandatory fields:

  • “languages”with a list of all language codes;
  • “translation”with a list of dictionaries assigning translation to a language code.

Other fields (such as cultural_date_format) are optional and if missing will be read from default config yaml file.

CSV translation format

Another approach is to use a CSV format. The main idea behind it is to support distributed translation tasks among many translators. Instead of having to concatenate results of work from many translators together, we can just store them in a common folder with the specific name of the file: translation_.csv.

You can imagine a situation with the following folder structure:


which have translations for pl Polish, it Italian and – as the language code is completely arbitrary – kl for Klingon language.

Let’s have a look at how typical CSV translation file should look like:

en, it
Hello Shiny!, Ciao Shiny!
Histogram of x,	Istogramma di x
This is description of the plot., Questa è la descrizione della trama.
Frequency, Frequenza
Number of bins:, Numero di scomparti:
Change language, Cambia lingua

This time we need to remember that all CSV files from one dictionary must share common reference language in the left column (which is en English in the above case).

Creating the app

To integrate our translations with Shiny we start from loading packages and an example JSON file.


i18n <- Translator$new(translation_json_path = "translations/translation.json")

Having that, we can check in RStudio console all languages stored in i18n object.

> i18n$languages
[1] "en" "pl" "kl"

Now within Shiny app we need to surround all text elements within i18n$translate or in short i18n$t method. For instance:

            i18n$t("Number of bins:"),
            min = 1,
            max = 50,
            value = 30)

to translate a message displayed by sliderInput element, or:

titlePanel(i18n$t("Hello Shiny!"))

to translate a titlePanel content.
If we decide to run an instance of the app with a specific language (let’s say Klingon) we should call:


right after defining Translator object.

Below you can see the full example:


i18n <- Translator$new(translation_json_path = "../data/translation.json")

ui <- shinyUI(fluidPage(
  titlePanel(i18n$t("Hello Shiny!")),
                  i18n$t("Number of bins:"),
                  min = 1,
                  max = 50,
                  value = 30)
      p(i18n$t("This is description of the plot."))

server <- shinyServer(function(input, output) {
  output$distPlot <- renderPlot({
    x    <- faithful[, 2]
    bins <- seq(min(x), max(x), length.out = input$bins + 1)
    hist(x, breaks = bins,
         col = "darkgray", border = "white",
         main = i18n$t("Histogram of x"), ylab = i18n$t("Frequency"))

shinyApp(ui = ui, server = server)

Above code should convince you about how easy it is to start using shiny.i18n. For more examples once again I refer you to the GitHub page. We hope that shiny.i18n will help you to forget about problems with internationalization.

We are also intensifying work on authentication package for Shiny – subscribe to our waitlist.

Bye, cześć, ciao, tschüs, 再见!

Artykuł Internationalization of shiny apps has never been easier! pochodzi z serwisu Appsilon Data Science | We Provide End­ to­ End Data Science Solutions.

To leave a comment for the author, please follow the link and comment on their blog: r – Appsilon Data Science | We Provide End­ to­ End Data Science Solutions. offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)