Creating a Multilingual Blog with Quarto - Guide

QuartoMultilingual BlogNetlifyWeb DevelopmentYAMLRStudio
Read in about 9 min read
Published: 2023-11-19
Last modified: 2023-11-19
View count: 145

Summary

Learn how to implement a multilingual blog supporting both Korean and English using Quarto's project profile feature. Covers YAML configuration, content-visible tag usage, and the complete Netlify deployment process step by step.

This guide covers how to implement a multilingual blog using Quarto. Let's create a blog that simultaneously supports both Korean and English versions.

📋 Important Note

This article heavily references Mario Angst's 'A multi-language (German/ English) Quarto website' and follows the approach he implemented.

If this guide lacks certain details, following Mario Angst's approach would be an effective solution.

⚠️ Warning

This guide doesn't start from creating a blog from scratch.

Those who haven't started creating a blog can follow the official Quarto website guide.

However, reading through the preparation section below before following the official Quarto guide will help reduce trial and error.

0. Prerequisites

RStudio

This guide uses RStudio. Quarto can also be used with other IDEs like Jupyter Notebook and VS Code. We're using RStudio version 2023.06.

Quarto

Obviously, Quarto is required. However, it seems necessary to match the version before following the guide. Quarto has many fixes and updates, so functionality may vary depending on the version.

💡 Tip

If installation is needed, check the official Quarto documentation.

You can check Quarto's version by entering quarto check in the terminal:

zsh
(...)

[✓] Checking versions of quarto dependencies......OK
[✓] Checking Quarto installation......OK
      Version: 1.3.353

(...)

Netlify

I chose Netlify because:

  1. It's used by many users and
  2. It has excellent integration with GitHub.

Particularly, the service that automatically handles building and deployment on Netlify as soon as you commit to GitHub was exactly the killer product I wanted.

However, due to Quarto's incompleteness(?), to deploy to Netlify in the desired way using project profiles, you need to use the command line.

Surprisingly, the command line approach is intuitive, and I'm currently very satisfied using it.

Anyway, since this guide uses Netlify, beginners are recommended to use Netlify as well.

Also, when deploying to Netlify, we'll use the command line input method, so it's better not to configure other plugins or GitHub actions.

⚠️ Warning

If you use Netlify plugins or GitHub actions, the blog may not work as intended with every commit.

1. Overall Picture

Before starting the explanation, let's briefly go over the overall picture of how the Korean-English switching was implemented.

Understanding the flow will make the subsequent explanations feel easier.

I'll explain in reverse flow, starting from the result (deployment).

1.1 Netlify Deployment

We send the output in the _site folder to Netlify.

Netlify receives the output, uploads it to the server, and deploys it.

So, how do we create the output in the _site folder?

1.2 Creating Output in _site Folder

When Quarto renders qmd files (cmd+shift+k), it applies predefined options to create output in the _site folder.

For example, if we render the index.qmd file in our workspace root folder, it considers the _site folder as the new root folder and generates an index.html file.

This index.html file is deployed on Netlify and becomes the main page when you visit https://oooo12.ooo, the blog you're currently viewing.

💡 Information

Currently, https://oooo12.ooo is not being operated. The blog you're viewing is made with Next.js.

Blog links that appear later also don't work. Please understand.

Quarto blog structure explanation image
Quarto blog structure explanation image

Let me give another example.

I created a blog folder in the root folder, and the blog folder contains posts (e.g., hypothesis testing(1), which is currently the only other post on my blog, is in the blog folder).

Then I create a hypothesis-testing-1 folder in the blog folder and create index.qmd inside it. (This has different content from the index.qmd mentioned earlier. Only the name is the same.)

When I write content in this index.qmd and render it, a hypothesis-testing-1 folder is created in the blog folder within the _site folder, and an index.html file is generated inside this folder.

Blog folder structure explanation
Blog folder structure explanation

This index.html file will be visible at https://oooo12.ooo/blog/hypothesis-testing-1/ when deployed.

1.3 Creating Two Versions: English and Korean

If you want to run a multilingual blog like me, you need to create two HTML files for each post: English and Korean versions.

Using this blog as an example, https://oooo12.ooo/blog/hypothesis-testing-1/ is in English, but https://oooo12.ooo/**ko**/blog/hypothesis-testing-1/ appears in Korean.

This is possible because the English version of the hypothesis testing(1) post exists in root/blog/hypothesis-testing-1/index.html (meaning index.html in the hypothesis-testing-1 folder within the blog folder within the root folder),

and the Korean version of the hypothesis testing(1) post exists in root/ko/blog/hypothesis-testing-1/index.html folder.

Like this, originally you would need to write two HTML files to present posts in two languages, but using Quarto's project profile feature, you only need to write one qmd file.

1.4 Project Profile

Project profile explanation diagram
Project profile explanation diagram

Project profiles have the functionality to show or hide content depending on the situation.

This ultimately means Quarto can render differently depending on the situation.

To do this, you need to set up profiles with YAML and mark content in qmd files to show or hide depending on the situation (i.e., by profile). (We'll learn more about this later.)

1.5 content-visible when-profile

To configure content that shows by profile, you need to use ::: {.content-visible when-profile="ko"}.

The code readability is so good that there's probably no need for further explanation, but to put it simply, it means to show content when the profile is ko.

Use it like this:

qmd
::: {.content-visible when-profile="ko"}
통계적 가설 검정을 그대로 풀어보면, "'통계적 가설(statistical hypothesis)'을 '검정(test)'한다"이다.

가설 검정을 이해하려면 '통계적 가설'이 무엇인지 정확히 아는 것이 필요하다.
:::

::: {.content-visible when-profile="en"}

Statistical hypothesis testing, when explained plainly, means to "test a statistical hypothesis."

To understand hypothesis testing, it's necessary to know exactly what a 'statistical hypothesis' is.
:::

1.6 Korean-English Switch Button

Naturally, we need to configure a Korean-English switch button to make it the multilingual blog we want.

There was some difficulty in configuring the Korean-English switch button.

In a way, it's also a part where I used a workaround.

2. YAML Configuration

Let's get into it in earnest.

YAML adjusts overall options in Quarto.

📝 Note

Of course, you can decide whether to adjust overall options by setting different levels, or adjust options only for specific directories.

However, this content is background knowledge not needed for this project configuration, so it's omitted.

For detailed information, refer to the quarto - Project Profile documentation.

When you first create a blog, you use two YAML files in the root folder.

You'll use the _quarto.yml file and the _publish.yml file, but the key is _quarto.yml.

_quarto.yml contains website settings, navbar, format, etc.

We'll move all these settings to profile YAML files.

To do that, we need to create profile YAML files.

YAML file structure
YAML file structure

If we name the profile YAML's profile 'en' (we'll do English blog-related settings in the en profile from now on), we need to create _quarto-en.yml in the root folder where _quarto.yml is located.

⚠️ Warning

The filename must be _quarto-en.yml.

If you use _quarto.en.yml, it won't be recognized as a profile.

This is because the rules for determining filenames have changed with updates.

We'll also need a Korean profile.

Similarly, create _quarto-ko.yml in the root folder where _quarto.yml is located.

If you want both blogs to show the same blog format, you can copy and paste the settings from _quarto.yml into both yml files.

However, let's first put important YAML at the top of each yml file.

📋 _quarto-en.yml Settings

Put the following code in _quarto-en.yml.

YAML
project:
  output-dir: ./_site

📋 _quarto-ko.yml Settings

Put the following code in _quarto-ko.yml.

YAML
project:
  output-dir: ./_site/ko

Those who are quick to notice will have realized that output-dir sets the directory address where the output comes out.

This way, output corresponding to the en profile will be created in the _site folder, and output corresponding to the ko profile will be created in the _site/ko folder.

So how should we configure _quarto.yml?

YAML
project:
  type: website

profile:
  default: en
  group:
    - [en, ko]

execute:
  freeze: auto

_quarto.yml, which can be considered the big boss, can be set with options commonly used for all profiles and profile group settings.

Actually, if you configure and understand the yml files well, it's almost finished.

Now let's work on the qmd files.

3. Creating Output for Each Profile from One qmd

As an example, I'll use root/blog/hypothesis-testing-1/index.qmd, which created my first post https://oooo12.ooo/blog/hypothesis-testing-1/.

First, let's look at the entire index.qmd file.

qmd
---
title: "Hypothesis Testing (1)"

(...YAML...)

---

::: {.content-visible when-profile="en"}

Statistical hypothesis testing, when explained plainly, means to "test a statistical hypothesis."

To understand hypothesis testing, it's necessary to know exactly what a 'statistical hypothesis' is.

:::

::: {.content-visible when-profile="ko"}

통계적 가설 검정을 그대로 풀어보면, "'통계적 가설(statistical hypothesis)'을 '검정(test)'한다"이다.

가설 검정을 이해하려면 '통계적 가설'이 무엇인지 정확히 아는 것이 필요하다.

:::


As mentioned earlier, using "::: {.content-visible when-profile="ko"}" makes content visible only when the profile is ko.

That is, this part "::: {.content-visible when-profile="ko"} ~~ this part ~~ :::" receives options set in the previously configured _quarto-ko.yml.

Therefore,

qmd
통계적 가설 검정을 그대로 풀어보면, "'통계적 가설(statistical hypothesis)'을 '검정(test)'한다"이다.

가설 검정을 이해하려면 '통계적 가설'이 무엇인지 정확히 아는 것이 필요하다.

The above part is rendered only in index.html located in a subdirectory of the _site/ko directory.

Specifically, it will be saved in 'root/_site/ko/blog/hypothesis-testing-1/index.html'.

Now you've probably figured out how to use it.

Parts that should appear in the English blog go between:

qmd
::: {.content-visible when-profile="en"}


:::

Parts that should appear in the Korean blog go between:

qmd
::: {.content-visible when-profile="ko"}


:::

4. Adding Korean-English Switch to Navbar

Based on PC screen, you'll see an 'English' button in the top right.

This is because you're viewing the Korean version.

To make the English button appear in the navbar for users viewing the Korean version, you need to set the navbar option in _quarto-ko.yml.

Part of the _quarto-ko.yml settings is as follows:

YAML

project:
  output-dir: ./_site/ko

website:
  title: "oooo12"

(...)
  navbar:
    right:
      - text: "English"
        href: ..

The important point here is that href is ...

That is, it goes to the parent folder _site/ from _site/ko/.

This way, it goes to the main page of _site/, which is also the main page of the English blog, _site/index.html.

However, there's an important point to note when doing this.

🚨 Other Menu Settings

This blog has only one navbar menu: Blog.

This Blog menu is generated as HTML by the blog.qmd file...

The English version blog has the Blog menu setting in the navbar configured as follows in _quarto-en.yml:

YAML
website:
  navbar:
    title: "oooo12"
    left:
      - text: "Blog"
        href: ./blog.qmd

However, the Korean version blog needs to set href differently.

Below is the _quarto-ko.yml setting:

YAML
website:
  navbar:
    title: "oooo12"
    left:
      - text: "Blog"
        href: ../ko/blog.html

If you set the Blog menu's href in the Korean version blog the same as the English version, every time you click blog, it returns to the English version.

Be careful.

🚨 Korean Version Blog Blog Menu href Setting

href: ../ko/blog.html

5. Netlify Deployment

There are roughly 4 ways to deploy Netlify using Quarto.

Among these, only the Publish Command method, using the command line, seems to be able to confirm the profile functionality. (This might be due to my lack of skills. If there's a better method, please leave a comment anytime.)

5.1 Rendering

Rendering is done for each profile, with the en profile that outputs to the parent folder (root) rendered first, and the ko profile that outputs to the subfolder (/ko) done next.

The command to render the en profile is as follows:

⚠️ Warning

Must be entered in terminal.

zsh
quarto render --profile en

Next, let's enter the command to render the ko profile:

zsh
quarto render --profile ko

Now if you look at the root/_site folder, you'll see files rendered by the en profile and the ko folder rendered by the ko profile.

5.2 Deployment

The rendered folder must be sent to the Netlify server for Netlify to deploy.

zsh
quarto publish netlify

The result is as follows:

zsh
kimjaahyun-m1-mac:R-Quarto_Blog jaahyun$ quarto publish netlify
? Publish update to:
 https://oooo12.ooo (Netlify - jhdmbwy12@gmail.com)
  Add a new destination...

Press enter and it will automatically deploy.

Netlify deployment process GIF
Netlify deployment process GIF