Multilingual Jekyll Blog Deployment
The record of deployment for this blog.
I have learned a lot about programming from technical blogs website like CSDN and cnblogs.com. The programming community has a great atmosphere of sharing our ideas and skills by technical blogs. This is a mutually beneficial process. Technical blogs don’t need complex features, simple text with images are sufficient. Therefore, I prefer using static blogs that are more lightweight in writing, deployment, and reading experience.
I did some research in 2019 and deployed my first static blog. On that time the most popular ones are Jekyll, Hugo, and Hexo. I initially used Hexo with Next theme and wrote some articles. Later, the blog was neglected. It was the beginning of 2023 when I thought about setting up another static technical blog and I decided to use Jekyll this time.
Why Static Blog? Why Jekyll?
Actually, you can choose any platform if you really want to write something. But I prefer using independent static blog, which has the following advantages(comparing to WordPress):
-
It can be serverless and deployed freely by a 3rd party provider (it is not a problem to me though)
- You can manage all the original post data by yourself. The text editor is separated with the webpage generating tools.
- It is easier to adjust theme or even add new features by yourself.
Besides of having a technical blog, the other motivation of setting up this blog is to have a multilingual blog. I hope that it can encourage myself to practice English writing more frequently and a cool multilingual blog also makes me feel good. Almost all static site generators don’t support multilingual switching in a native way. But fortunately I found a Jekyll plugin Jekyll-Polyglot can achieve my. And according to my previous experience of using Hexo, I feel like that Hexo is not popular so its community support is worse than other main static site frameworks. Finally I decided to use Jekyll, which has a better community support, as the static site generator.
Jekyll Basic
The tutorial from Jekyll official website has already given a great guide. I would like to just point out some confusing concepts in this post.
Ruby Installation
Jekyll is a static site generator written in Ruby. Therefore, we have to know a little bit Ruby when using it.
The good news is that the installation of Ruby is much easier than Java and Python. There is almost no trap during the installation if you correctly follow the instruction from Jekyll official website. For Windows users, a single installation wizard can fix all problems.
Ruby has a package manager called GEM which uses bundle
as the basic command for the current environment. Like npm run
in Node.js, you can add bundle exec
before all the Jekyll commands you want to execute under the website directory. It is easy to get started if you have experience using package managers like Python’s PIP and Node.js’s NPM.
Theme and Configuration
One of the biggest advantage of using a static site is that most configuration works can be done in a line of code so you only need to manage your posts. If you want to switch to another theme that already installed by bundle
, you can just rewrite the line of the configuration code in _config.yml
.
1
2
# Import the theme
theme: jekyll-theme-chirpy
You can find a lot of great themes by googling like “best jekyll blog theme 2024”. And you can also refer to some websites like https://jekyll-themes.com/
I finally chose Chirpy as the theme of my blog. Chirpy is a double-frame theme focuses on text presentation. It has a good support for common blog functionalities like category, archive, media insertion, and comments, which meets my current need.
Chirpy provides two different ways to deploy it. The one is to copy the basic configuration files from the official start repository, the other one is to fork the project repository and modify it as you want. I have some programming experience so I chose the latter for modifying it later.
If you are a new beginner to Jekyll, maybe following the instruction from the official website is a better choice. And if you have already found a preferred theme, you should refer to the theme’s instruction first to avoid unnecessary work.
Site Generation and Deployment
You can use bundle exec jekyll serve
to preview the result locally when developing the site on your computer.
If you want to upload the stuff to an online server to show them to everyone, you need to execute bundle exec jekyll build
to generate the whole website and configure your gateway to make the root directory of the website be accessible to outside.
For convenience, we generally adopt an automated deployment process: upload the entire project directory to GitHub, trigger GitHub Action after each update, generate the static site on a temporary virtual server, then upload it to our pre-configured server to achieve updates.
The good news is that there are many service providers that offer one-click hosting for the above content. Therefore, we only need to do the writing and uploading work; the rest of the work will be done by third parties.
GitHub itself provides free static page hosting projects through GitHub Pages. In addition, Vercel and Netlify are also good options for hosting providers. This blog is currently deployed on Vercel. Register and log in to Vercel using your own GitHub account, select your Jekyll blog repository, and you can achieve one-click deployment and bind your own domain name.
Jekyll Multilingual Support Plugin Polyglot
Polyglot is a treasure I discovered during my search for a smooth multilingual switching solution for static blogs across the web. Even with the current popularity of Next.js and Gatsby, and Hugo surpassing Jekyll in usage, it’s still the only one that can help me achieve my needs of having a multilingual blog gracefully.
I was stuck by a bug when I first started debugging. So I went ahead and helped fix this bug and translated the entire demo site of this plugin into Chinese.
Usage
Declare the plugin in the _config.yml
. You should also define the default language and and all the languages your site uses.
1
2
3
4
5
6
plugins:
- jekyll-polyglot
# polyglot configuration
languages: ["en", "zh-CN"]
default_lang: "en"
You can also introduce language code to define other variables of your site, like title and description, and so on.
1
2
3
4
5
6
7
8
9
10
11
title: # the main title
en: AnotherTurret
zh-CN: 交界处的空间站
tagline: # it will display as the sub-title
en: Just another study note blog
zh-CN: 各类技能笔记
description: # used by seo meta and the atom feed
en: Just another study note blog
zh-CN: 干正事博客
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
.
In the front matter of each article, use lang
to define the language to which that article belongs:
1
2
3
title: Jekyll 双语静态博客部署
date: 2024-09-28 11:33:00 -0400
lang: zh-CN
According to the design of Polyglot, if not specifically marked, articles will be displayed on sub-sites in other languages by default to maintain consistency, which is like what happened when many international enterprise official websites have not localized the latest blog posts yet. If you want this article to only appear during the rendering process on specific language websites, you can use lang_exclusive
for customization:
1
lang_exclusive: ['zh-CN']
Which means that this article only appears on the Chinese version of the website. The English version of the website will not have the Chinese version of this article.
Language Switcher
For a generated site, you can add the language codes within the URL path. For example, example.com/zh-CN/post-title/
is the Simplified Chinese version of that article. However, plugins only render multiple times based on the number of languages and language identifiers for the same template, without affecting the front-end template of the website itself. Therefore, we need to manually write HTML and CSS to create a language selection menu.
Here is a sample code for the language selection menu:
1
2
3
4
5
6
7
8
9
10
11
12
<!-- 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">
<a class="lang-name" {% if tongue == site.active_lang %} style="font-weight: bold;" {% endif %} {% 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>
</p>
{% endfor %}
</div>
You can try to put the code snippet to anywhere you want and tweak the HTML and CSS code by yourself.
This is the reason why I need a blog theme that basically doesn’t change its layout through all the pages within. The position arrangement for the selection menu can be tricky if the layout changes a lot in different pages. The left-bottom corner is the best position for it in Chirpy.
Troubleshooting
There were a lot of troubles when I using this plugin for the first time. Here’s the note for it:
RegexpError
This error might happen when generating the whole site:
1
C:/Ruby33-x64/lib/ruby/gems/3.3.0/gems/jekyll-polyglot-1.8.1/lib/jekyll/polyglot/patches/jekyll/site.rb:234:in `relative_url_regex': target of repeat operator is not specified: /href="?\/((?:(?!*.gem)(?!*.gemspec)(?!docs)(?!tools)(?!README.md)(?!LICENSE)(?!*.config.js)(?!package*.json)(?!.sass-cache)(?!.jekyll-cache)(?!gemfiles)(?!Gemfile)(?!Gemfile.lock)(?!node_modules)(?!vendor\/bundle\/)(?!vendor\/cache\/)(?!vendor\/gems\/)(?!vendor\/ruby\/)(?!en\/)(?!zh-CN\/)[^,'"\s\/?.]+\.?)*(?:\/[^\]\[)("'\s]*)?)"/ (RegexpError)
The principle of Polyglot execution is to scan the entire project when compiling the entire project, and generate content for each language. Regular expressions are used for matching. If an asterisk and a period are encountered at this time, it will be considered as a regular expression statement that needs to be executed.
This error can be fixed by commenting out the code in the configuration files.
1
2
3
4
5
6
7
8
9
exclude:
# - "*.gem"
# - "*.gemspec"
- docs
- tools
- README.md
- LICENSE
# - "*.config.js"
# - package*.json
Ruby Execution Error in Windows
As what said in the readme file of Polyglot. It doesn’t support parallel_localization
under Windows environment. So you should switch it to false
if you are using Windows as your development system.
1
2
3
4
5
6
7
8
plugins:
- jekyll-polyglot
# polyglot configuration
languages: ["en", "zh-CN"]
default_lang: "en"
exclude_from_localization: ["javascript", "images", "assets", "public"]
parallel_localization: false
Other
That’s all for this post. Maybe I will talk more about how to use Chirpy to achieve some interesting effects and how I modify the theme to meet my own needs later.