Modify Chirpy theme to build a functional bilingual Jekyll blog with Polyglot
How to manually modify the Chirpy theme to build a fully functional, smooth bilingual blog with Polyglot.
In the issue section of Polyglot, I found someone complaining that he cannot configure Polyglot correctly with the Chirpy theme and asked for some help.
Chirpy is the most popular technical-writing blog theme in Jekyll community right now. After all, Polyglot is a niche plugin with a unique implementation method, so it’s not realistic to expect most themes to have built-in support for Polyglot. You have to do it by yourself.
Basic Modification
Chirpy officially provides two different approaches to deploy itself . One is to use the starter repository template to create the project, another one is to fork the repository then modify it by yourself. The former is more convenient for updating and the latter can support you to modify it in a high flexibility.
You have to choose the latter if you want to customize it. Otherwise, all the webpage template files are integrated in the gem of the theme and is not support to be modified.
The principle of Polyglot execution is to scan the entire project when compiling the entire project, generating content for each language. Finally, in the _site
directory, the main language site is located in the root directory, while each non-main language will have their own website directory.
When generating the website, the variable site.active_lang
will be assigned with the identifier of the language currently being generated. Jekyll uses Liquid templates to generate HTML. You can reference these contents in webpage templates using Liquid syntax, such as modifying the website title interface to automatically switch different languages’ website titles:
1
2
3
4
<h1 class="site-title">
<a href="/">AnotherTurret</a>
</h1>
<p class="site-subtitle fst-italic mb-0">Just another study note blog</p>
Articles written in different languages need to be placed in directories with corresponding language code identifiers, but they should have the same file name. For example, on my website where English is the primary language, Chinese articles will be placed under _post/zh-CN
.
Chirpy defaults to using only one language for a site, defined by the lang
parameter in _config.yml
. During the rendering process, most language-related template entries use variable assignments defined in the _data
directory, which are then referenced by site.data.locales[site.lang].variable_name
.
In order to adapt to Polyglot, we need to replace all content related to [site.lang]
with [site.active_lang]
. I suggest use a text editor like VS Code to find within all the files and execute the replacement operation. Remember to tick the “match whole word” option.
For further information of the, you can also refer to the introduction from Polyglot official website.
Language Switcher
In order to let the readers to switch the language on all the pages, you need to add a language switcher in _include/sidebar.html
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<div class="sidebar-bottom d-flex flex-wrap align-items-center w-100">
<div class="lang-div d-flex flex-wrap w-100" >
<p style="font-weight: bold;" id="language"> {{site.data.locales[site.active_lang].tabs.languages}}
</p>
</div>
<!-- jekyll-polyglot will process ferh= into href= through the static_href liquid block tag without relativizing the url; useful for making language navigation switchers -->
<div class="lang-div d-flex flex-column">
{% for tongue in site.languages %}
<p class="lang-name-box">
{% if tongue == site.active_lang %}
<a class="lang-name" id="current-lang" style="font-weight: bold;">
{{ site.data.locales[tongue].tabs.lang_name }}
</a>
{% else %}
{% if page.lang-exclusive %}
{% assign is_lang_exclusive = false %}
{% for lang in page.lang-exclusive %}
{% if tongue == lang %}
{% assign is_lang_exclusive = true %}
<span>This language is in the lang_ex list</span>
{% endif %}
{% endfor %}
{% if is_lang_exclusive == false %}
<a class="lang-name disabled-lang">
{{ site.data.locales[tongue].tabs.lang_name }}
</a>
{% else %}
<a class="lang-name" {% static_href %}href="{% if tongue == site.default_lang %}{{site.baseurl}}{{page.url}}{% else %}{{site.baseurl}}/{{ tongue }}{{page.url}}{% endif %}"{% endstatic_href %}>
{{ site.data.locales[tongue].tabs.lang_name }}
</a>
{% endif %}
{% else %}
<a class="lang-name" {% static_href %}href="{% if tongue == site.default_lang %}{{site.baseurl}}{{page.url}}{% else %}{{site.baseurl}}/{{ tongue }}{{page.url}}{% endif %}"{% endstatic_href %}>
{{ site.data.locales[tongue].tabs.lang_name }}
</a>
{% endif %}
{% endif %}
</p>
{% endfor %}
</div>
</div>
In the previous article, I forgot to mention how to add the corresponding CSS. You need to modify _sass/addon/common.sass
and add the following content within .sidebar-bottom
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
.lang-name-box {
font-family: 'NotoColorEmojiLimited', -apple-system, BlinkMacSystemFont,
'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji',
'Segoe UI Emoji', 'Segoe UI Symbol';
margin: 0.1rem;
margin-bottom: 0.15rem;
.lang-name {
padding: 0.8rem;
border: 1px solid transparent;
border-radius: 25%/75%;
width: 100%;
text-align: left;
font-size: 0.9rem;
margin-bottom: 0.1rem;
justify-content: left;
color: var(--sidebar-active-color);
// background-color: var(--sidebar-bg);
}
.disabled-lang {
background-color: var(--sidebar-disabled-color);
color: #ff0000;
&:hover {
background-color: #ffe3e5;
}
}
#current-lang {
background-color: var(--sidebar-hover-bg);
}
}
.lang-div {
margin-bottom: 0.2rem;
padding: 0;
}
#language {
font-size: 1.1rem;
margin-bottom: 0.3rem;
}
In order to display the national flag on the Windows platform, I deliberately chose NotoColorEmoji
as the preferred font-family
for the language selection bar.
1
2
3
4
5
@font-face {
font-family: NotoColorEmojiLimited;
unicode-range: U+1F1E6-1F1FF;
src: url(https://raw.githack.com/googlefonts/noto-emoji/main/fonts/NotoColorEmoji.ttf);
}
RSS Customization
The author of Chirpy made a customized RSS file. It is stored at assets/feed.xml
.
I prefer RSS that can output full text. So I modified it: switch the <summary>
and <content>
. The RSS can output full text right now.
1
2
3
4
5
6
7
<summary></summary>
<content type="html">
<![CDATA[
{%- include no-linenos.html content=post.content -%}
{{- content | html -}}
]]>
</content>
Using the no-linenos.html
template is to remove line numbers from code blocks.
SEO Recipes
Chirpy theme uses jekyll-seo-tag as the SEO optimization plugin. jekyll-seo-tag defaults to assigning values of site.title
, site.description
, and site.lang
to the <meta>
tags for SEO content.
This conflicts with the specific language variables that need to be selected using site.active_lang
as mentioned earlier.
Directly modifying seo.html
will not solve this problem. I have created a jekyll-seo-tag specifically for Polyglot as a workaround. You need to remove or comment out the line using jekyll-seo-tag in jekyll-theme-chirpy.gemspec
. Also, include my modified plugin in GEMFILE
.
1
2
3
4
5
6
7
8
9
10
11
12
# jekyll-theme-chirpy.gemspec
spec.required_ruby_version = "~> 3.1"
spec.add_runtime_dependency "jekyll", "~> 4.3"
spec.add_runtime_dependency "jekyll-paginate", "~> 1.1"
spec.add_runtime_dependency "jekyll-redirect-from", "~> 0.16"
# spec.add_runtime_dependency "jekyll-seo-tag", "~> 2.8" <- remove it
spec.add_runtime_dependency "jekyll-archives", "~> 2.2"
spec.add_runtime_dependency "jekyll-sitemap", "~> 1.4"
spec.add_runtime_dependency "jekyll-include-cache", "~> 0.2"
1
2
3
4
5
6
7
8
# GEMFILE
group :jekyll_plugins do
gem "jekyll-polyglot"
gem "jekyll-seo-tag", git:"https://github.com/aturret/jekyll-seo-tag-polyglot.git" # my version of the plugin
end
If you are testing on your local machine, don’t forget to use bundle install
and bundle update
to install this new plugin.
In addition, Polyglot also has its own SEO solution. It is recommended to add both. That is, in head.html
, add `
` before the paragraph of SEO.
1
2
3
4
5
6
<meta http-equiv="Content-Language" content="en">
<link rel="alternate" hreflang="en" href="https://aturret.space//posts/:title/"/>
<link rel="alternate" hreflang="zh-CN" href="https://aturret.space/zh-CN//posts/:title/"/>
<!-- Setup Open Graph image -->
Possible Deployment Error in Vercel
I don’t know why, but after using my custom plugins, every time Vercel automatically deploys, there is an error in the git fetch
stage. It seems to be because its environment configuration does not support fetching Ruby gems from GitHub repositories.
I don’t want to research it anymore. So I just add edVERCEL_FORCE_NO_BUILD_CACHE=1
in the deployment environment variables of Vercel to disable using the previous environment cache, requiring it to compile from scratch every time it is deployed, which can solve this problem. In this way, the deployment time will increase from 40 seconds to 80 seconds. But is generally fine for a static blog deployment, as we don’t need to get the feedback that soon.