The goal of babeldown is to support workflows that include automatic translation of Markdown-based R content, through DeepL API. With babeldown you can translate: Markdown strings (babeldown::deepl_translate_markdown_string()
) and Markdown files (babeldown::deepl_translate()
) in general; Quarto book chapters (babeldown::deepl_translate_quarto()
) and Hugo blog posts (babeldown::deepl_translate_hugo()
) in particular.
With babeldown you can also update translations, see babeldown::deepl_update()
.
Installation and setup
You can install the development version of babeldown from rOpenSci R-universe:
install.packages('babeldown', repos = c('https://ropensci.r-universe.dev', 'https://cloud.r-project.org'))
Or from GitHub with:
# install.packages("pak")
pak::pak("ropensci-review-tools/babeldown")
API URL
The DeepL API URL depends on your API plan. babeldown uses the DeepL free API URL by default. If you use a Pro plan, set the API URL via
Sys.setenv("DEEPL_API_URL" = "https://api.deepl.com")
API key
Set your API key via the environment variable DEEPL_API_KEY
.
You could store it with the keyring package, once per user/machine. The code below will prompt you to enter your API key interactively.
keyring::key_set("deepl", prompt = "API key:")
In any script you use babeldown, you’d retrieve the key like so:
Sys.setenv(DEEPL_API_KEY = keyring::key_get("deepl"))
Line wrapping
We recommend to start a new line in your Markdown document after each sentence or sentence part (after a comma for instance), for more informative Git diffs.
We also recommend not starting a new line in the middle of something that’s between square brackets (in particular references and in-line footnotes) as it would break the way babeldown tries to protect those.
You might be interested in the aeolus package for fixing line breaks.
RStudio Visual Editor
If you use RStudio Visual Editor, you can choose “sentence” as line-wrapping option.
Troubleshooting
Getting an HTTP error 456 means you’ve used up all your API credits. Use deepl_usage()
(or the online DeepL API interface) to get your usage data.
The DeepL API might mix up some punctuation, for instance:
babeldown::deepl_translate_markdown_string(
"[So _incredibly_ **wonderful**](https://ropensci.org)!",
source_lang = "EN",
target_lang = "ES"
)
#> [1] "[Así que *increíblemente* **maravilloso**](https://ropensci.org) ¡!"
babeldown::deepl_translate_markdown_string(
"[So _incredibly_ **wonderful**!](https://ropensci.org)",
source_lang = "EN",
target_lang = "ES"
)
#> [1] "[Así que *increíblemente* **maravilloso** ¡!](https://ropensci.org)"
babeldown::deepl_translate_markdown_string(
"[So _incredibly_ **wonderful!**](https://ropensci.org)",
source_lang = "EN",
target_lang = "ES"
)
#> [1] "[Así que *increíblemente* **¡maravilloso!**](https://ropensci.org)"
Examples
Markdown string translation
babeldown::deepl_translate_markdown_string(
"[So _incredibly_ **wonderful**](https://ropensci.org)",
source_lang = "EN",
target_lang = "ES"
)
#> [1] "[Así que *increíblemente* **maravilloso**](https://ropensci.org)"
File translation
english_lines <- c(
"## A cool section", "",
"This is the first paragraph. `system.file()` is cool, right?", "",
"Another paragraph. I really enjoy developing R packages.", "",
"Do you enjoy debugging?"
)
file <- withr::local_tempfile()
brio::write_lines(english_lines, file)
out_path <- withr::local_tempfile()
babeldown::deepl_translate(
path = file,
out_path = out_path,
source_lang = "EN",
target_lang = "ES",
formality = "less"
)
readLines(out_path)
#> [1] "## Una sección genial"
#> [2] ""
#> [3] "Este es el primer párrafo. `system.file()` es guay, ¿verdad?"
#> [4] ""
#> [5] "Otro párrafo. Me gusta mucho desarrollar paquetes de R."
#> [6] ""
#> [7] "¿Disfrutas depurando?"
#> [8] ""
#> [9] ""
You can also indicate YAML fields to translate, using the yaml_fields
argument. By default, title
and description
are translated.
english_lines <- c(
"---",
"title: Nice document",
"description: An example for sure",
"---",
"## A cool section", "",
"This is the first paragraph. `system.file()` is cool, right?", "",
"Another paragraph. I really enjoy developing R packages.", "",
"Do you enjoy debugging?"
)
file <- withr::local_tempfile()
brio::write_lines(english_lines, file)
out_path <- withr::local_tempfile()
babeldown::deepl_translate(
path = file,
out_path = out_path,
source_lang = "EN",
target_lang = "ES",
formality = "less"
)
readLines(out_path)
#> [1] "---"
#> [2] "title: Buen documento"
#> [3] "description: Un ejemplo seguro"
#> [4] "---"
#> [5] ""
#> [6] "## Una sección genial"
#> [7] ""
#> [8] "Este es el primer párrafo. `system.file()` es guay, ¿verdad?"
#> [9] ""
#> [10] "Otro párrafo. Me gusta mucho desarrollar paquetes de R."
#> [11] ""
#> [12] "¿Disfrutas depurando?"
#> [13] ""
#> [14] ""
Glossary creation or update
filename <- system.file("example-es-en.csv", package = "babeldown")
# file contents for info
readr::read_csv(filename, show_col_types = FALSE)
#> # A tibble: 2 × 2
#> Spanish English
#> <chr> <chr>
#> 1 paquete package
#> 2 repositorio repository
# create (or update) glossary
babeldown::deepl_upsert_glossary(
filename,
glossary_name = "rstats-glosario",
target_lang = "Spanish",
source_lang = "English"
)
#> Updating glossary rstats-glosario
File translation with glossary
file <- withr::local_tempfile()
brio::write_lines(english_lines, file)
out_path <- withr::local_tempfile()
babeldown::deepl_translate(
path = file,
out_path = out_path,
source_lang = "EN",
target_lang = "ES",
formality = "less",
glossary = "rstats-glosario"
)
readLines(out_path)
#> [1] "---"
#> [2] "title: Buen documento"
#> [3] "description: Un ejemplo seguro"
#> [4] "---"
#> [5] ""
#> [6] "## Una sección genial"
#> [7] ""
#> [8] "Este es el primer párrafo. `system.file()` es guay, ¿verdad?"
#> [9] ""
#> [10] "Otro párrafo. Me gusta mucho desarrollar paquetes de R."
#> [11] ""
#> [12] "¿Disfrutas depurando?"
#> [13] ""
#> [14] ""
Quarto book chapters
You can use babeldown to translate chapters of a Quarto multilingual book set up with babelquarto. See the article describing the workflow.
Hugo posts
You can also use babeldown to translate blog posts of a Hugo multilingual website using leaf bundles (posts as index.md
inside a content subfolder) and saving translations along each other (for instance Spanish post as index.es.md
inside the same subfolder). See babeldown::deepl_translate_hugo()
.
If your Hugo website is set up differently, either open an issue or use babeldown::deepl_translate()
.