This version is the english version.
This page is presented here on my website
I want to be able to knit my rmarkdown documents in different speaking language (english and french). I also want them to give similar rendering in html and in latex pdf so that I can use them in my courses as html version on the laptop, but also as printed version through the latex pdf. By the way, I also have a teacher and a student version for the R-scripts that I can purl from the Rmd file.
This means many options for a unique rmarkdown document. Using a unique document allow me to directly modify things for the different versions at the same place. I do not have to jump from a file to another and verify that I copied every modification in the R-script or other…
I personally use an external “run-all” R-script to choose options to run the different versions and rename output files.
In this article, I list some of the tips I have to use to make this work and some bonus:
I will modify this list if I face new difficulties or I find better ways to do things.
Files needed to create this article are stored here on my github.
packageVersion("knitr")
## [1] '1.15.1'
Because some text and background colors are not written in the same way for html and lateX outputs, I need to use functions that will add either html formatting or latex formatting:
# Simple text color format functions
colFmt <- function(x, colorname, type = "span") {
outputFormat <- knitr:::pandoc_to()
if (outputFormat %in% c('latex', 'beamer'))
paste0("\\textcolor{", colorname, "}{", x, "}")
else if (outputFormat == 'html')
paste0("<", type, " style='color:", colorname, "'>", x, "</", type, ">")
else
x
}
# Style format function, not specific for textcolor
styleFmt <- function(x, textstyle, type = "span") {
outputFormat <- knitr:::pandoc_to()
if (outputFormat %in% c('latex', 'beamer'))
paste0("\\", textstyle, "{", x, "}")
else if (outputFormat == 'html')
paste0("<", type," class='", textstyle, "'>", x, "</", type, ">")
else
x
}
# Style format options for longer text output
beginStyleFmt <- function(textstyle, type = "span") {
outputFormat <- knitr:::pandoc_to()
if (outputFormat %in% c('latex', 'beamer')) {
if (type %in% c("div", "p")) {
paste0("\\nopandoc{\\begin{", textstyle, "}}\n")
} else {
paste0("\\nopandoc{\\", textstyle, "{")
}
} else if (outputFormat == 'html') {
paste0("<", type, " class='", textstyle, "'>")
} else {
""
}
}
endStyleFmt <- function(textstyle, type = "span") {
outputFormat <- knitr:::pandoc_to()
if (outputFormat %in% c('latex', 'beamer')) {
if (type %in% c("div", "p")) {
paste0("\n\\nopandoc{\\end{", textstyle, "}}")
} else {
paste0("}}")
}
} else if (outputFormat == 'html') {
paste0("</", type, ">")
} else {
""
}
}
# Specific inline verbatim environment
verbatimFmt <- function(x, type = "span") {
outputFormat <- knitr:::pandoc_to()
if (outputFormat %in% c('latex', 'beamer'))
paste0("\\nopandoc{\\begin{codebox}}\\verb|", x, "|\\nopandoc{\\end{codebox}}")
else if (outputFormat == 'html')
paste0("<", type," class='codebox'>`` ", x, " ``</", type, ">")
else
x
}
# Specific to verbatim environment
# to be able to show you the 'asis' chunks with background color.
beginVerbatim <- function() {
outputFormat <- knitr:::pandoc_to()
if (outputFormat %in% c('latex', 'beamer')) {
cat("\\begin{blueShaded}\n\\begin{verbatim}\n")
} else if (outputFormat == 'html') {
cat("<div class='blueShaded'>\n```\n", sep = "")
} else {
""
}
}
endVerbatim <- function() {
outputFormat <- knitr:::pandoc_to()
if (outputFormat %in% c('latex', 'beamer')) {
cat("\\end{verbatim}\\end{blueShaded}")
} else if (outputFormat == 'html') {
cat("\n```\n</div>", sep = "")
} else {
""
}
}
The definition of different styles are in external lateX header file for pdf outputs and should be called in the YAML header of your rmarkdown file in_header: header.tex. This lateX file should include the definition of all colors and format to be used with the previous functions. For instance, here:
\usepackage{color}
\definecolor{blueSeb}{RGB}{30,115,190}
\definecolor{advertcolor}{HTML}{FF8929}
\newenvironment{blueShaded}[1][D6E8F5]{
\definecolor{shadecolor}{HTML}{#1}%
\begin{snugshade}%
}{%
\end{snugshade}%
}
\newcommand{\advert}[1]{\textit{\advertcolor{#1}}}
\definecolor{backcolor}{RGB}{235, 235, 235}
\newcommand{\codecommand}[1]{\texttt{\colorbox{backcolor}{#1}}}
By the way, pandoc do not consider text between begin and end lateX entries as markdown syntax. To be able to consider your markdown syntax when using functions beginStyleFmt and beginStyleFmt you need to define a command in your header.tex file as follows:
\newcommand{\nopandoc}[1]{#1}
Similarly, for html rendering, functions should be used in an external css file with option css: style.css in the YAML header of your rmarkdown file. Here for instance the css file includes:
/* Look at the style.css file for the complete css file */
.advert {
color: #FF8929;
font-style: italic;
}
.codecommand {
background-color:#E0E0E0;
font-family: Courier New, Courier, monospace;
}
.Shaded {
background-color:#E0E0E0;
font-family: Courier New, Courier, monospace;
}
[edit: 22 March 2017] In my Rmd file, you will remark that I use styleFmt(“code”, “codecommand”) or, like here in this paragraph, verbatimFmt("code")
to highlight the code inline in the text. I could directly use the markdown syntax with back ticks `code`
to embed code. However in lateX this is only transformed as \texttt
command, which format could be modified but would be applied to all other text with this format, even if it is not a code. In HTML, this is embed in <code>code<\code>
so that you can modify the css according to your needs.
[edit: 4 April 2017] To modify output background differently for input and output, in HTML, you can use my functions beginStyleFmt
and endStyleFmt
, but in your css file, you will have to set the background-color
of classes pre
and code
to transparent
so that the surrounding div have an effect. However, to be able to do it with PDF or cleanly with HTML, you will have to play with hooks and add a new options for different background for input and output. Here, I can not show it to you for HTML output because I did not wanted to have to set all my others backgrounds. I may later add the modified hooks functions to allow this different background colors for HTML and PDF…
a <- 1 + 1
a
## [1] 2
If you want to be able to knit your documents in different language without using two different rmarkdown files, here are my tips.
```{r R-Lang, echo=TRUE, eval=FALSE}
# Choose the language at the beginning of your script or knit from external file
lang <- c("EN", "FR")[1]
```
In ‘asis’ chunks, with option echo=TRUE, you can write rmarkdown syntax which produces text (partially) in the correct format. The aim is to use the command eval to render the text according to the chosen language:
<!-- english -->
```{asis, eval=(lang == "EN"), echo=TRUE}
### For titles and subtitles when at the beginning
This above chunk allow for markdown syntax
### And for titles in the middle if there is space line above
And you can use it for normal text or _italic_ or **other**
```
<!-- french -->
```{asis, eval=(lang == "FR"), echo=TRUE}
### Pour les titres et sous-titres au début du "chunk"
Le "chunk" ci-dessus permet d'utiliser la syntaxe markdown
### Et les titres en milieu de "chunk" s'il y a une ligne vide avant
Et vous pouvez utiliser le texte normal, _italic_ ou **autre**
```
This above chunk allow for markdown syntax
And you can use it for normal text or italic or other
```{r CodeInChunkEN, echo=(lang == "EN"), eval=(lang == "EN"), results='asis'}
cat(
'### Example of title in a chunk
#### Example of subtitle in a chunk
- ', styleFmt("cat", "codecommand"), ' should be used with ',
styleFmt("sep = \"\"", "codecommand"), ' otherwise a space will be added
before "##subtitle", which avoid it to be recognised as a subtitle in markdown.
- ', styleFmt("eval", "codecommand"), ' can be used with R object to knit
chunk specific to language. Here ', styleFmt("lang", "codecommand"),
' is ', lang, '\n',
'- Double space should work to define new paragraph, but when using R
functions, it may require "\\\\n"
_(Note the number of backslash in the code here to print "\\\\n" correctly...)_.
+ ', styleFmt("For instance when using the format function,
following two spaces won\'t work:", "advert"), ' ',
' + This sentence won\'t be on a new line.',
sep = "")
```
```{asis, eval=(lang == "EN")}
![](./myfigdirectory/gb.png) Directory for english version
```
```{asis, eval=(lang == "FR")}
![](./myfigdirectory/fr.png) Fichier pour la version française
```
Only code of the last point is shown here, but you can find the others in the raw Rmarkdown file used to create this page.
figWD <- paste0("./myfigdirectory", lang)
- `r
if (lang == "EN") {
knitr::include_graphics(paste0(figWD, '/gb.png'), dpi = 400)
} else if (lang == "FR") {
knitr::include_graphics(paste0(figWD, '/fr.png'), dpi = 400)
}`
`r
if (lang == "EN") {
"Conditionnal image: English flag shown if 'lang' is 'EN'"
} else if (lang == "FR") {
"Image avec condition : Le drapeau français est affiché si 'lang' est 'FR'"
}`
A problem while using two images side by side using “knitr::include_graphics” in the same chunk is that option fig.align = ‘center’ applies separately to the two images, so that there are one under the other, in two different paragraphs:
[edit: 22 March 2017] With recent version of knitr, you can use fig.show=‘hold’ to show the two images side-by-side, but you can not use fig.align=‘center’ .
knitr::include_graphics(paste0(figWD, "/fr.png"))
knitr::include_graphics(paste0(figWD, "/gb.png"))
Here, we use two functions to be place before and after the chunk with results=‘asis’ and a space between images:
beginCentering <- function() {
outputFormat <- knitr:::pandoc_to()
if (outputFormat %in% c('latex', 'beamer'))
cat("\n\\nopandoc{\\begin{center}}\n", sep = "")
else if (outputFormat == 'html')
cat('\n<p style="text-align: center">\n', sep = "")
else
""
}
endCentering <- function() {
outputFormat <- knitr:::pandoc_to()
if (outputFormat %in% c('latex', 'beamer'))
cat("\n\\nopandoc{\\end{center}}\n", sep = "")
else if (outputFormat == 'html')
cat("\n</p>\n", sep = "")
else
""
}
The chunk is then written as follows:
```{r, echo=FALSE, out.width='25%', fig.align='default', results='asis'}
beginCentering()
knitr::include_graphics(paste0(figWD, "/fr.png"))
cat(
ifelse(knitr:::pandoc_to() == "html",
"<a style='margin-left: 10px'></a>",
"\vspace{1cm}"),
sep = "")
knitr::include_graphics(paste0(figWD, "/gb.png"))
endCentering()
```
This one is pretty easy. You only have to set your purl option depending if your chunk is for student or teacher. I personally use eval=TRUE with the teacher version that should produce the result targeted by students. And I use eval=FALSE with the student version because this version should not work.
Reproduce the following figure from the “cars” dataset.
## speed dist
## Min. : 4.0 Min. : 2
## 1st Qu.:12.0 1st Qu.: 26
## Median :15.0 Median : 36
## Mean :15.4 Mean : 43
## 3rd Qu.:19.0 3rd Qu.: 56
## Max. :25.0 Max. :120
If you purl this rmarkdown file using the “teacher” option, you’ll get this R script:
# A script for teacher with solutions ------------------------------------------
summary(cars)
# Plot pressure against temperature
plot(pressure)
And this R script if you purl with the “student” option:
# A script for students without solutions --------------------------------------
summary(cars)
# Plot pressure agains temperature
plot(...)
All files necessary to produce this page are available on my github. All outputs in french and english, in pdf and html, as well as student and teacher R-script are also in the repository. Use the “Run_all_and_choose_options.R” file to produce them on your own.
A limit to the use of “\begin” and “\end” environment with lateX is that pandoc do not convert markdown syntax included in that environment. It is read as verbatim. Maybe, I’ll find a way to get rid of that.
One of the drawback of this kind of multilingual rmarkdown script is that code highlighting is messy in Rstudio… This specific one in very messy because I wanted to show you the complete chunks in the output file, but it is quite difficult to do it in a clean way as “asis” chunks do not allow for “echo” and “verbatim” options. If you have any better way to do it, you can comment here or in the github repository itself.
By the way, if your file starts to be too big like the present one, do not hesitate to work with child Rmd files.
LateX default template of rmarkdown load several packages and defines several parameters to format the final text output. If you do not want to create your own template, you can define, like here a tex file to load “in_header”.
However, you may encounter some error messages due to incompatible options. In the “header_tips.tex” file provided with the present templates, you will find different modifications of the pdf template:
More tips on R, models and spatial things on my website
This page is presented here on my website