Traduction d'un document rmarkdown à partir d'un tableau

Comment créer un modèle Rmarkdown autorisant plusieurs traductions?

Dans mon article “Rmarkdown avec conditions pour créer des pdf et html en différentes langues et avec des images”, je propose un moyen de créer des documents rmarkdown qui peuvent produire des documents identiques en plusieurs langues. Si vous travaillez avec plus de deux langues, la lecture du document rmarkdown peut devenir compliquée. Par ailleurs, si vous travaillez avec des personnes extérieures pour traduire vos documents, vous ne voulez probablement pas qu’elles jouent avec votre document rmarkdown et vous ne voulez pas non plus faire des copier-coller de chaque paragraphe dans votre document.

En revanche, vous pouvez proposer à vos traducteurs un fichier Excel par exemple, avec une colonne correspondant au langage d’origine et une colonne vide pour leur traduction. De cette façon, ils n’ont pas besoin de veiller à maintenir le format du document.
En utilisant les mêmes idées que mon article précédent, vous pouvez utiliser les “chunks” pour lire ce tableau (au format dataframe par exemple) et vous occuper uniquement de la mise en forme du document.
Le template Rmd simplifié que vous pouvez utiliser comme base pour votre document rmarkdown de traduction est ici sur mon github.

Définir la langue de sortie

La langue de sortie peut se définir directement dans le document rmarkdown. Si vous travaillez avec des sorties pdf, vous pourriez aussi changer lang: 'en' dans l’en-tête YAML.

# Define the output language
lang <- "en"

Créer une dataframe avec les traductions

Pour l’exemple, je crée un tableau de traduction directement dans R. Il est sauvegardé sous la forme langue.csv. Dans votre cas, ce peut être directement un fichier csv (ou Excel).

# Create an external dataframe of translation
# Col-1 is original language ("en" here)
# Col-2 is translation
trans.df <- data.frame(
  en = c("First title", 
         "This is a long paragraph, with different ponctuations ! We can also add the content of a list in the document as follows:",
         "item 1",
         "item 2",
         "item 3", "subitem 3",
         "item(s)"),
  fr = c("Premier titre", 
         " Ceci est un long paragraphe,    avec différentes ponctuations ! Nous pouvons aussi y ajouter le contenu d'une liste comme ci-dessous :  ",
         "élément 1",
         "élément 2", 
         "élément 3",
         "sous-élément 3",
         "élément(s)"))

# Save it with a name that contains the lang attribute
readr::write_csv(trans.df, path = file.path(tempdir(), paste0(lang, ".csv")))

Lecture du tableau dans un fichier externe

On lit le tableau comme si c’était un fichier extérieur (et c’est le cas ici). On retire les erreurs possibles avec les espaces, comme les espaces multiples ou ceux qui précédent et suivent les sequences de texte. Cela évitera des erreurs d’interprétation de markdown. J’ai mis ce genre d’espaces en trop dans la traduction en français ci-dessus.

trans.df <- readr::read_csv(file.path(tempdir(), paste0(lang, ".csv")))
# Remove space if before or after the text sequence
trans.df <- trans.df %>%
  mutate_all(function(.) gsub("[[:space:]]{2,}", " ", .)) %>%
  mutate_all(function(.) gsub("^[[:space:]]*|[[:space:]]*$", "", .)) %>%
  as.data.frame()
knitr::kable(trans.df)
en fr
First title Premier titre
This is a long paragraph, with different ponctuations ! We can also add the content of a list in the document as follows: Ceci est un long paragraphe, avec différentes ponctuations ! Nous pouvons aussi y ajouter le contenu d’une liste comme ci-dessous :
item 1 élément 1
item 2 élément 2
item 3 élément 3
subitem 3 sous-élément 3
item(s) élément(s)

La partie traduite du document

En utilisant la façon dont je propose de traduire un document dans mon article précédent, vous devez créer un “chunk” pour le langage original (ce qui vous permet de vous repérer dans le document) et un “chunk” pour la traduction.
Vous noterez que les séquences de texte sont séparées lorsqu’elles nécessitent un formatage différent. Vous noterez aussi l’utilisation de sep = "" dans la fonction cat pour créer le texte.

Le chunk suivant et sa sortie sont ceux du texte original en anglais

    ```{r title1_orig, eval=(lang == "en"), results='asis'}
    cat('
    #### First title
    
    This is a long paragraph, with different ponctuations ! We can also add the content of a list in the document as follows:
    
    - item 1
    - item 2
    - item 3
        + subitem 3
    ', sep = "")
    ```

First title

This is a long paragraph, with different ponctuations ! We can also add the content of a list in the document as follows:

  • item 1
  • item 2
  • item 3
    • subitem 3

Le chunk suivant et sa sortie sont ceux du texte traduit en français

lang <- "fr"
    ```{r title1_tr, eval=(lang != "en"), results='asis'}
    cat('
    #### ', trans.df[1, lang], '
    
    ', trans.df[2, lang], '
    
    - ', trans.df[3, lang], '
    - ', trans.df[4, lang], '
    - ', trans.df[5, lang], '
        + ', trans.df[6, lang], '
    ', sep = "")
    ```

Premier titre

Ceci est un long paragraphe, avec différentes ponctuations ! Nous pouvons aussi y ajouter le contenu d’une liste comme ci-dessous :

  • élément 1
  • élément 2
  • élément 3
    • sous-élément 3

Traduction avec un unique chunk

Ce serait quand même mieux de n’utiliser qu’un seul chunk pour l’original et sa traduction. De plus, si vous avez des modifications de dernière minute, vous ne voulez pas modifier tous les numéros de lignes du code. On crée donc un vecteur avec les traductions originales et on l’utilise comme référence pour trouver les traductions. Ce sera plus propre.

tr.orig <- trans.df[,"en"]

Évidemment, vous pourriez faire l’équivalent avec du code “inline”, comme `r trans.df[tr.orig == "example text", lang]`, mais personnellement, je préfère utiliser cat et asis dans un chunk parce que :

  • La coloration syntaxique de rstudio me permet de mettre en évidence mon texte dans le chunk, alors qu’avec le “R-inline” tout est bleu.
  • Cela permet d’insérer directement des sorties de commande R sans remettre `r` au milieu de ma phrase (pour mettre un chiffre par exemple).
  • En fait, cela évite d’ajouter `r` partout (bien que je mette des '', ..., '').

Nous pouvons comparer les deux syntaxes, dans le cas où on a une variable calculée dans R (nb).

# Define nb and increment in the text
nb <- 0

L’unique “chunk” et sa sortie sont les suivants

Coloration syntaxique dans Rstudio :

Chunk :
    ```{r title1_all, results='asis'}
    cat('
    ##### ', trans.df[tr.orig == "First title", lang], '
    
    ', trans.df[tr.orig == "This is a long paragraph, with different ponctuations ! We can also add the content of a list in the document as follows:", lang], '
    
    - ', trans.df[tr.orig == "item 1", lang], ': ', nb + 1,' ', trans.df[tr.orig == "item(s)", lang], '
    - ', trans.df[tr.orig == "item 2", lang], ': ', nb + 2,' ', trans.df[tr.orig == "item(s)", lang], '
    - ', trans.df[tr.orig == "item 3", lang], ': ', nb + 3,' ', trans.df[tr.orig == "item(s)", lang], '
        + ', trans.df[tr.orig == "subitem 3", lang], '
    ', sep = "")
    ```
Premier titre

Ceci est un long paragraphe, avec différentes ponctuations ! Nous pouvons aussi y ajouter le contenu d’une liste comme ci-dessous :

  • élément 1: 1 élément(s)
  • élément 2: 2 élément(s)
  • élément 3: 3 élément(s)
    • sous-élément 3

Comparaison avec la version “inline”

Coloration syntaxique dans Rstudio :

Code :


##### `r trans.df[tr.orig == "First title", lang]`

`r trans.df[tr.orig == "This is a long paragraph, with different ponctuations ! We can also add the content of a list in the document as follows:", lang]`

- `r trans.df[tr.orig == "item 1", lang]`: `r nb + 1` `r  trans.df[tr.orig == "item(s)", lang]`
- `r trans.df[tr.orig == "item 2", lang]`: `r nb + 2` `r  trans.df[tr.orig == "item(s)", lang]`
- `r trans.df[tr.orig == "item 3", lang]`: `r nb + 3` `r  trans.df[tr.orig == "item(s)", lang]`
    + `r trans.df[tr.orig == "subitem 3", lang]`:

Récupérer toutes les traductions et créer une table vide pour les traducteurs

Ce qui est intéresant avec la version en “chunk” unique, c’est qu’il est possible d’extraire toutes les séquences de texte à traduire. Vous pouvez ensuite en créer une table vide à envoyer à vos traducteurs. Vous pouvez aussi enlever les parties de texte qui sont répétées pour diverses raisons en utilisant unique dans le code.
Ici, nous lisons donc directment le document Rmarkdown actuel, que j’utilise pour écrire cet article.

thisfile <- readr::read_lines("2017-10-06-translation-rmarkdown-documents-using-data-frame.fr.Rmd")
# Find lines with translations
all_trans <- thisfile[grep('trans.df\\[tr.orig == "', thisfile)]
  
# Extract translations
empty.file <- purrr::map(
  strsplit(all_trans, 'trans.df\\[tr.orig == "'), ~.x[2:length(.x)]) %>% 
  unlist() %>%
  purrr::map_chr(~strsplit(.x, '", lang]', fixed = TRUE)[[1]][1]) %>%
  unique() %>%
  data.frame(en = ., translation = "")
# Show empty file
knitr::kable(empty.file)
en translation
example text
First title
This is a long paragraph, with different ponctuations ! We can also add the content of a list in the document as follows:
item 1
item(s)
item 2
item 3
subitem 3

Ensuite vous pouvez enregistrer ce document en csv (ou Excel).

# Save empty translation file
readr::write_csv(empty.file, path = "myemptyfile.csv")

Après cela, vous pouvez imaginer aller plus loin:

  • Intégrer plus de formattage du texte comme italique ou gras
  • Mettre à jour la table de traduction pour n’envoyer que les traductions manquantes à vos traducteurs
  • Utiliser une table avec plusieurs colonnes pour de multiples traductions

Soyez créatifs !
Le template Rmd simplifié que vous pouvez utiliser comme base pour votre document rmarkdown de traduction est ici sur mon github.
Vous pouvez aussi me contacter pour vos projets de ce genre ou tout autre projet !



Citation :

Merci de citer ce travail avec :
Rochette Sébastien. (2017, oct.. 06). "Traduction d'un document rmarkdown à partir d'un tableau". Retrieved from https://statnmap.com/fr/2017-10-06-traduction-document-rmarkdown-avec-tableau/.


Citation BibTex :
@misc{Roche2017Tradu,
    author = {Rochette Sébastien},
    title = {Traduction d'un document rmarkdown à partir d'un tableau},
    url = {https://statnmap.com/fr/2017-10-06-traduction-document-rmarkdown-avec-tableau/},
    year = {2017}
  }