Interactive Quarto Reports with Shiny using {shiny.i18n}
Quarto is exciting! It is simple, seamless, and easy to use! Do you know what makes it even better? Interaction. Quarto integrates with R/Shiny instances and provides you with a way to make your documents interactive. In our previous tutorial on shiny.i18n + Quarto, we cooked up a static document. In this example, we will do something different. We’ll try to make a Quarto instance that is powered by R/Shiny. Instead of using static translations, we will leverage a dropdown to select the languages instead. TOC: <ul><li><a href="#final">The final product </a></li><li><a href="#quarto">Making a Quarto document</a></li><li><a href="#markdown">Adding some Markdown</a></li><li><a href="#translation">translation.json</a></li><li><a href="#UI">UI: The Selector</a></li><li><a href="#server">Server: The Output</a></li></ul> <hr /> <h2 id="final">What are we making? (Quarto + Shiny interactive document) 👀</h2> <img class="aligncenter size-full wp-image-18456" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b01bb46d4bc088a0245d62_interactive-quarto-report-with-shiny-i18n.gif" alt="Interactive Quarto report using Shiny and shiny.i18n" width="600" height="440" /> Note that this is a simple example. The possibilities are vast! So, let’s dive into making a document that looks like the one above. <blockquote>Are you new to Quarto? Try our <a href="https://appsilon.com/r-quarto-tutorial/" target="_blank" rel="noopener">beginner's R Quarto tutorial</a>.</blockquote> <h2 id="quarto">Let's begin: Quarto document + Shiny🌱</h2> To begin, let's make a Quarto document. Posit has a wonderful page where you can learn how to <a href="https://quarto.org/docs/get-started/" target="_blank" rel="nofollow noopener">get started.</a> Once you have a .qmd file ready, edit the beginning to look like the following. <pre><code> --- title: "Quarto (Interactive Example)" author: "Appsilon" format: html: default server: shiny --- </code></pre> Notice the <b>server: shiny</b> bit. This is crucial since it tells Quarto that this is an interactive document. Please make sure you do have the <b>Shiny</b> installed. If not, use<b> install.packages(“shiny”)</b> to get it up and running. This tutorial assumes that <b>quarto</b>, <b>Shiny, </b>and<b> shiny.i18n, </b>along with all their imports such as <b>rmarkdown, jsonlite </b>et al. are all installed and loaded in the environment. <h2 id="markdown">Adding some Markdown 📃</h2> As you would in a standard .rmd or .qmd file, you can use the markdown syntax to create headings and hyperlinks. <pre><code> ## Introduction <br>In this example, we will try to define a Quarto document to showcase how we can use `shiny.i18n` in an interactive manner. To learn more about Quarto and how it integrates with R/Shiny, check out the [official documentation](https://quarto.org/docs/interactive/shiny/). <br>## An Illustration <br>Here, we translate a famous quote from the one of the most famous people to have ever existed in tech, **Steve Jobs**... </code></pre> This will set a basic structure with some text and two headings. Now we can move on to the more interesting stuff. <blockquote>Are you more of a <code>ipynb</code> fan? Try our tutorial on <a href="https://appsilon.com/quarto-and-jupyter-notebooks/" target="_blank" rel="noopener">Quarto and Jupyter Notebooks</a>.</blockquote> <h2 id="tinkering">Onto the tinkering with shiny.i18n🧰</h2> So far, so good. We have most of our work ready. Now, we need to do the following: <ul><li style="font-weight: 400;" aria-level="1">Build a translation.json file</li><li style="font-weight: 400;" aria-level="1">Build the UI</li><li style="font-weight: 400;" aria-level="1">Build the Server</li></ul> So, let’s get going! <h3 id="translation">translation.json 🌐</h3> If you’ve followed any of our previous tutorials, you know that the shiny.i18n package relies on a translations.json file, which is simply a mapping of all the strings in a key-value format where the key maps to several languages. For the file here, we only have one string, which is the quote. <pre><code> { "languages": [ "key", "en", "pl", "de", "fr" ], "translation": [ { "key": "quote", "en": "Here's to the crazy ones. The misfits, the rebels, the troublemakers, the round pegs in the square holes, the ones who see things differently. They're not fond of rules, and they have no respect for the status quo.", "pl": "Oto dla szalonych. Odmieńcy, buntownicy, wichrzyciele, okrągłe kołki w kwadratowych dziurach, ci, którzy widzą rzeczy inaczej. Nie lubią zasad i nie mają szacunku dla status quo.", "de": "Auf die Verrückten. Die Außenseiter, die Rebellen, die Unruhestifter, die runden Stifte in den eckigen Löchern, die das anders sehen. Sie mögen keine Regeln und haben keinen Respekt vor dem Status quo.", "fr": "Voici pour les fous. Les inadaptés, les rebelles, les fauteurs de troubles, les chevilles rondes dans les trous carrés, ceux qui voient les choses différemment. Ils n'aiment pas les règles et n'ont aucun respect pour le statu quo." } ] } </code></pre> Please ensure that the file is in the same directory as the .qmd file to make things simpler. Once you have the above in the JSON file, we can begin adding the UI elements to the document. <h3 id="UI">UI: The Selector 👆</h3> In the .qmd file, we will create an {r} code chunk using the following syntax. <pre><code> ```{r} YOUR CODE HERE ``` </code></pre> Here, we use some functions from Shiny to build a simple UI. <pre><code> ```{r} library(shiny) selectInput( inputId = "language", label = "Select language: ", choices = list("English 🇬🇧" = "en", "Polish 🇵🇱" = "pl", "German 🇩🇪" = "de", "French 🇫🇷" = "fr"), selected = "en", multiple = FALSE, selectize = TRUE ) <br>htmlOutput("quote") HTML("<em>— Steve Jobs</em>") br() ``` </code></pre> The above sets the UI part of the document. If you are familiar with R/Shiny apps, this is typically what would go in the ui.R in a simple app. <h3 id="server">Server: The Output 💬</h3> To tell Quarto which {r} chunk is the server, we use <b>#| context: server </b>in the code. For more information, the Quarto documentation discusses <a href="https://quarto.org/docs/interactive/shiny/execution.html" target="_blank" rel="nofollow noopener">Execution Contexts</a>. The rest is as you would build the code for the server in an R/Shiny app. <pre><code> ```{r} #| context: server library(shiny.i18n) <br>i18n <- Translator$new(translation_json_path = "translation.json") output$quote <- renderText({ i18n$set_translation_language(input$language) paste0("<blockquote style='text-align: justify;'>", i18n$t("quote"), "</blockquote>") }) ``` </code></pre> In the chunk above, we first tell Quarto this is the server for this interactive document. Then, we load the {shiny.i18n} package and also load the translation file by building a Translator object. Then, we simply set the translation language using i18n$set_translation_language() and pass the input$language which contains the result from the dropdown selector. Finally, we use i18n$t(“quote”) to fetch the string from the translations.json file, and that’s it! In the end, your document should look like the following. <pre><code> --- title: "Quarto (Interactive Example)" author: "Appsilon" format: html: default server: shiny --- <br>## Introduction <br>In this example, we will try to define a Quarto document to showcase how we can use `shiny.i18n` in an interactive manner. To learn more about Quarto and how it integrates with R/Shiny, check out the [official documentation](https://quarto.org/docs/interactive/shiny/>). <br>## An Illustration <br>Here, we translate a famous quote from the one of the most famous people to have ever existed in tech, **Steve Jobs**... <br>```{r} <br>selectInput( inputId = "language", label = "Select language: ", choices = list("English 🇬🇧" = "en", "Polish 🇵🇱" = "pl", "German 🇩🇪" = "de", "French 🇫🇷" = "fr"), selected = "en", multiple = FALSE, selectize = TRUE ) <br>htmlOutput("quote") HTML("<em>— Steve Jobs</em>") br() ``` <br>```{r} #| context: server library(shiny.i18n) <br>i18n <- Translator$new(translation_json_path = "translation.json") output$quote <- renderText({ i18n$set_translation_language(input$language) paste0("<blockquote style='text-align: justify;'>", i18n$t("quote"), "</blockquote>") }) ``` </code></pre> <h2>Let's Knit it up!🧶</h2> All you have to do now is <b>Run</b> the document and you should see the document in your browser. Are you on your phone? No worries, you can also explore the document on our shiny.i18n demo app. In this tutorial, we’ve built a simple interactive Quarto document and used the {shiny.i18n} package to dynamically translate a string using a selectInput dropdown. And now, we leave it up to you to build your own interactive documents and translate them on the fly! If you're like us, you work with international teams across the globe. Use translation in your reporting to make things easier and faster for everyone to understand. If you want to explore <a href="https://rhinoverse.dev/#shiny-i18n" target="_blank" rel="noopener">shiny.i18n </a> or our other Shiny packages - head over to <a href="https://rhinoverse.dev/#shiny-i18n" target="_blank" rel="noopener">rhinoverse.dev</a> to discover demos, documentation, tutorials, and more!