Draft

Multilingual Quarto site

The options you can use and the considerations to keep in mind if you have a site that’s a touch complex

quarto
Published

January 3, 2026

Modified

March 11, 2026

Abstract

As far as I am aware (as of eary 2026), there isn’t a good assessment of the options (and their tradeoffs) when it comes to setting up a multilingual site using Quarto. There are a large number of customizations and some blogs summarizing one or another option, often with nuances and weaknesses. This blog tries to provide a coherent narrative and summarize my own assessment of the options and tradeoffs. For context, I wanted to aim for something semi-robust and make it look like it approached official multilingual sites (such as Government of Canada or UN sites).

“There are no solutions—there are only tradeoffs.” -Thomas Sowell

Notetl;dr
  • Quarto can handle multilingual sites (as in multiple human languages), however it is not set up to do so easily by default.1
  • As of early 2026, it seems to me that there are 3 options to choose from if you want to set this up:
    1. Setting up one quarto project (i.e. one _quarto.yml) and using profiles to render language specific sub-sites
    2. Setting up two (or more) separate quarto projects in separate sub-directories and hosting them together.
    3. A semi-automated way using babelquarto that is quite similar to option i.
  • All options end up working, however there are some nuances in how each are set up and tradeoffs that you face. There is no clear winner in my mind.
  • To trial the options myself, I built (and share alongside this blog) basic working examples of each.

Options

As far as I am aware, there are three options. In reality there are lots of nuances and similarities between the options (and there are off course different ways you can set up each). For simplicity however, let’s consider each.

Option 1: Quarto profiles

Quarto profiles is at a glance an effective option as it leverages Quarto functionality (which was technically intended for something else). Instead (or alongside) using profiles for environments, you set up language specific profiles and create a toggle to switch between them. Your project will leverage one _quarto.yml, meaning that you have one standard project with shared configuration. This may help in some nuanced ways, such creating one folder structure for your project (which helps simplify navigation), helps slightly simplify developing common components (as you could with some limitation use one qmd file for both languages for ex, or make writing code once (i.e. do not repeat yourself approach) a tad simpler.2

Overview

  • Setup a _quarto-{language}.yml for each language profile and language specific metadata (such as navigation) alongside the a regular _quarto.yml for overall project setup (and for shared content).

  • Render each specific language profile separately (i.e. quarto render --profile en renders the _quarto_en.yml to _site/en) as well as a shared content that connects the two sub-sites (such as central index.qmd , 404.qmd, etc).

  • When it comes to writing content, there are some options:

    • For simple cases, one .qmd file can be used with language specific sections (using conditional content feature, i.e. {.content-visible when-profile="en"} can contain content in that language.
      • Pros - quite easy to start with!
      • Cons
        • I could see this approach being simple at first but get really messy quickly.
        • You have to get creative in setting metadata in other languages, and you face a low bar for metadata you can use. For example you if you want your page title to be in a language of your choice - you must use _quarto-{language}.yml to specify the title and can’t use the title: bar in the page. If you want to specify advanced metadata like description or tags, you have to do this yourself manually.3
    • For more complex scenarios (such as to keep cleaner qmd files or to add multilingual metadata), you can separate language specific pages (i.e. *.en.qmd and *.fr.qmd). For content that needs to be shared between both languages, a separate file can be created and integrated, such as using {{ < include _shared-content.qmd >}}.
      • Pros: can start separating content for cleanliness
      • Cons: this makes the directory really messy as you basically double each file. In this case its almost easier to go to Option 2.
  • A toggle between languages can be hard coded to redirect to the home page of the other language or handled dynamically (a custom metadata tag can be added to each .qmd file and referenced in the _quarto-{language}.yml (i.e. href: ../fr/content/blogs/tech-topics/multilingual-quarto/index.html will reference filename: "/blog/blog1" in each qmd file).

Challenges

  • If translation of all page metadata is needed, it becomes necessary to specify the info using language specific qmd files (similar to option 3 as babelquarto requires the same).
  • I didn’t explore this, but image that if you want to use Quarto profiles for its other intended purpose (such as environments), then it could get more complex quite quickly as you’d be dealing with 4 or more files.

Notable examples / resources

ImportantPersonal examples

This site is organized using this approach (see the repo). In setting it up, I also created a separate vanilla example: https://github.com/sergegoussev/multilingual-quarto-ex

I would also recommend:

Option 2: Separate Quarto projects in one repo

The second option for even more customization is to setup separate directories per language with separate _quarto.yml per language. This setup creates two (or more) isolated quarto projects. This is quite similar to using profiles with separate language directories, but ensures more isolation between language.

Overview

  • Using separate projects ensures that you have maximum isolation between each language part of the site. However to not have to repeat yourself (such as to not have to duplicate css, code, or other content), you can put them in common folders.
  • Each project is rendered separately and combined in a custom way
CautionArea still WIP

I’ll prob explore this option in a bit more detail and flush out the description.

/root
  ├── _common/
  │    ├── index.qmd    <-- home landing page
  │    ├── 404.qmd 
  │    ├── styles.css
  │    └── theme.scss
  ├── en/
  │    ├── _quarto.yml  <-- references ../_common/theme.scss
  │    └── index.qmd
  └── fr/
       ├── _quarto.yml  <-- references ../_common/theme.scss
       └── index.qmd

Examples / further reading

ImportantPersonal example

In exploring this option, I set up this example: https://github.com/sergegoussev/multilingual-separate-projects-example/

A few examples seem to be:

Option 3: babelquarto

babelquarto is a third option. It requires the use of R (instead of quarto) and is not rendered from CRAN but from R Open Science. The option is very similar to option 1 if separate language specific files are used.

Overview

  • Instead of doing the customization of language switching and being careful about rendering and redirects, babelquarto can do the setup for you. As its an R package, you need to use R to render locally and within your publish.yml to have GitHub render your site. Once set up, it basically makes it easier to maintain language switching as you don’t have to do this part yourself and let babelquarto do it for you.

Nuances

  • The biggest issue that I can see is that the main language is rendered from the root directory, whereas the other languages use a sub-directory. In other words if English is the default, its rendered from project/index.html and French as a secondary would be rendered from project/fr/index.html. This is counter to i18n guidelines as consistency between languages is recommended.

    • This also makes it a tad less intuitive if you need to setup a default index.html page to give visitors a choice about which site they wish to proceed to (as with the other two options).
  • As a separate R package, this option comes with its own nuances and tradeoffs, including:

    • Using it introduces a new dependency. You have to learn how to use it and keep an eye on its evolution and interaction with Quarto.

    • By learning and maintaining your skills in babelquarto, you are adding a to your knowledge of Quarto in a way that does not make you more competent in Quarto itself. In other words, this option slightly broadens your cognitive load as you need to also know this package and still know quarto, whereas deeper expertise in just quarto may serve you well in the future.

  • As you are setting up and running R to render you need to ensure your setup is appropriate. For instance a GitHub runner needs to takes a bit longer to setup R and install your renv.lock and also render compared to just using Quarto. T

    • Furthermore, walking away from Quarto CLI features means you are loosing some ability to customize things that the CLI gives you, such as rendering a specific language to a specific directory (say quarto render —profile: en – )

Notable examples / resources

ImportantPersonal examples

In exploring this option, I created a separate vanilla example: https://github.com/sergegoussev/babelquarto-example.

If this sounds interesting, have a look at:

Requirements for a multilingual site

It may be tough to choose between these options (I definitely struggled at first before diving in), hence we can introduce a few requirements to help choose the best option:

  • How ‘multilingual’ do you want to be? A dive into i18n standard shows that many things should be multilingual - from the data output to the URL itself. This obviously includes metadata in your quarto docs.

  • Do you intend to use things like quarto listings (such as to write a blog and generate it dynamically?)

  • Do you want to avoid extra things and do things as ‘vanilla’ as possible? For instance if you already know Quarto well enough but are less up to speed on lua or R - then babelquarto may be less attractive.

Key takeaways

  • Choosing between the Quarto profiles option or babelquarto option for me comes down to a choice between

  • Whether using the custom R library to automate the work is sufficiently beneficial compared to the loss of flexibility and ability to rely on Quarto CLI defaults.

    1. Whether the language switch is a concern (i.e. / for default and /fr for the secondary).
  • While at first glance, the Quarto profile option of using a single .qmd file with conditional content seemed like a great solution, this option will likely be quite hard to maintain and I could see defaulting to just having separate language specific files:

    1. A single document will get very messy! Say you are rendering lots of text and code – needing to switch between language will make the document long and hard to edit.

    2. There is no default way to translate the metadata and you are forced to come up with hacks. Either a lua filter4 or simply having two different qmd files that have language specific content.

  • The language toggle is a pain. Notable solutions include:

    • The babelquarto option deals with it in the most seamless way (its biggest selling feature)

    • I found that ../other_lang/blogs/tech-topics/multilingual-quarto/index.html worked very well as long as you didn’t forget to specify the filename and the sub-folder path in each qmd file’s yml.

    • Another option would naturally to be write a small javascript file to do the work for all pages automatically, which will probably be simpler than remembering to keep the custom metadata correct in each qmd file.

Back to top

Footnotes

  1. There is a rich discussion on the topic here: https://github.com/quarto-dev/quarto-cli/issues/275↩︎

  2. A few like Martin Angst wrote about it.↩︎

  3. Check out the thread on multilingual Quarto for examples of this.↩︎

  4. See example by Lino Galiana.↩︎