Quarto multilanguage website
-
No native support
-
R package exists, but I don’t feel like digging into R at all: Renders a Multilingual Quarto Book • babelquarto
-
The other approaches I found are all based on project profiles and conditional output
- oooo12 - Multi-language Blog with Quarto - Guide
- Mario Angst - A multi-language (German/ English) Quarto website
- only difference is that it’s /de/ /en/ instead of ENG being /en/
- nice and more detailed about interesting corner cases
-
Document Language – Quarto1 for setting one language in the page and doing per-language changes to the template texts
Config files
_quarto-profilename.yml
ONLY, the rest won’t get parsed
profile:
default: en
# mutually exclusive group: you can do only one
# (otherwise `--profile one,two` does multiple)
group:
- [en, de, uk]
Page content
# `unless-profile` exists as well
::: {.content-visible when-profile="en"}
This content will only appear in the advanced version.
:::
Links
Links are going to be interesting!
Currently /de
is German, /
is English.
Main home page is ..
from DE lang, or /de
from EN.
Menu items:
- ENG as-is. (`href: whatever.qmd)
- DEU:
href: ../de/lehre.html
— note the HTML bit!
But when previewing DEU, all of these pages are at /
— ergo menu items don’t work, as they lead to a non-existing ../de/...
ALSO: marioangst.de shows nicely how one can link to other languages from the menu!
- icon: book
href: publications.qmd
text: Publikationen
- href: ../en/blog
text: Blog (englisch)
Site language
Website Options – Quarto tells me I can do this in each _quarto-de.yml
etc. profile:
format:
html:
lang: de
#lang: ua
#lang: en
This changes the interface to follow the corresponding quarto-cli/src/resources/language/_language.yml at main · quarto-dev/quarto-cli
Unsolved
How do I change front matter (e.g. title)?
Not dealt with in any of the approaches: quarto’s native Document Language1 thing
So:
- How do I do different post titles per language?
- How do I change site language, so , conditionally?_languages.yml
-
Project Basics – Quarto discusses the various approaches to metadata
- And I can conditionally include stuff
-
… I could literally do a bash script that puts a
_metadata.yaml
, builds with a proflie, then removes that file. Oh this would be painful -
Skimming Website Options – Quarto doesn’t really help
- except that I can set html format
lang: de
from within profiles! NICE
- except that I can set html format
Do variables magic
- title gets taken from variable
title[currnet-profile-name]
or something? _variables.yml
works for var shortcodes (240619-1845 Quarto error title.trim() is not a function), and shortcodes can do metadata too
# works
title-en: "Publications and Awards"
title: "{\{< meta title-en >}}"
If only I could do per-language attributes as shown in the docu2:
language:
en:
title-block-published: "Updated"
fr:
title-block-published: "Mis à jour"
It would be so cool if one could overwrite the other variables
language:
de:
title: german post title
The above would nicely get a language from the profile _quarto-lang.yml
and automatically change the things.
Can I do this for titles and front-matter?
I can get the current profile from the env variable
profile: {\{< env QUARTO_PROFILE >}}
If I could just
title: vars['titles']['postname'][QUARTO_PROFILE]
- Asked this on Github: How do I do conditional YAML frontmatter, e.g. based on profile? · quarto-dev/quarto-cli · Discussion #10064
- Mea culpa, discussed already: Conditional metada for different profiles on a website · Issue #4516 · quarto-dev/quarto-cli Conditional metada for different profiles on a website · quarto-dev/quarto-cli · Discussion #4455 no idea how I missed this.
Use scripts
- Project Scripts – Quarto
- A python script that sets title based on QUARTO_PROFILE
Quarto lua filters
OK let’s do this. No choice.
First3 attempt to write anything in lua:
function Meta(m)
local profiles = quarto.project.profile
local profile = profiles[1]
if profile then
print("Profile: " .. profile)
m.active_profile = profile
end
if profile and m.titles and m.titles[profile] then
cleantitle = pandoc.utils.stringify(m.titles[profile])
oldtitle = pandoc.utils.stringify(m.title)
m.title = cleantitle
print("Profile:" .. profile)
print("Old title:" .. oldtitle)
print("New title:" .. cleantitle)
end
return m
end
I’d need to make it more robust:
- multiple profiles? Not now
- No titles set in titles — use the default one
So:
- Always require a title
- Optionally add array of titles, indexed by language=profile name
- If present use one of these.
function Meta(m)
local profiles = quarto.project.profile
if not profiles then
-- TODO: missing YAML key? Empty YAML key?..
-- TODO even more later: filter multiple profiles to use the language one
return m
end
local profile = profiles[1]
-- If we have a named profile, save it, otherwise return
if profile then
print("Profile: " .. profile)
m.active_profile = profile
else
return m
end
if m.titles then
local titles = m.titles
if titles[profile] then
newtitle = pandoc.utils.stringify(titles[profile])
oldtitle = pandoc.utils.stringify(m.title)
-- log both if they differ
if newtitle ~= oldtitle then
m.title = newtitle
-- print("Old title:" .. oldtitle)
-- print("New title:" .. newtitle)
print(oldtitle .. " => " .. newtitle)
end
else
print("Title for profile " .. profile .. " not found among ")
for lang, title in pairs(titles) do -- Table iteration.
print(" " .. lang .. ": " .. pandoc.utils.stringify(title))
end
end
end
return m
end
Main problems:
- listing pages use the old title anyway
- supports only title, not e.g. description (used, again, in listings)
- and side menus!
-
[Document Language (alternates) – Quarto](https://quarto.org/docs/authoring/language.html) ↩︎
-
I think Master Thesis pandoc required lua magic and I tried some small pandoc filter bits, але це було давно і неправда. ↩︎