Featured image of post migrated to Hugo migrated to Hugo now uses Hugo. Hugo is a fast and modern static site generator written in Go. It provides a few improvements over the old system that was using plain PHP. A large part of the work was done by Anuj during GSoC 2020. This was a massive work, converting the repository storing more than 20 years of KDE history.

The website is now generated once and no longer uses PHP to generate itself at runtime. This improves the loading speed of the website, but the speed boost is not significant, since the PHP code used before was quite small and KDE’s servers are powerful.

But the biggest improvement is in terms of features. We are now working with markdown files instead of raw HTML files, this makes the life of the promo team much easier.

The internationalization of the website now creates a unique URL per language, this should allow Google to link to the version of the website using the correct language. A French, Ukrainian, Catalan, Dutch, and a few more languages are already available. There is also a proper language selector! We also don’t need to manually tag each string for translations.

There is also now an RSS feed with all the latest announcements. Another big improvement is that the announcements list is autogenerated and no longer modified by hand and with the help of the release scripts.

Another nice change for website developers is that now the SCSS code for the individual pages is located in the kde-org repository itself instead of another repository. Overall the developer experience is much better, there is no need to set up an apache server and to the PHP configs to include the capacity framework, just to get the website running locally. Now you only need to download the Hugo binary from their release page and run it on the repo.

Hugo and Gettext

The internationalization of was quite a challenge. When working on a multilingual website with Hugo, Hugo expects a markdown document per language for each translated page.

The problem is that traditional translations workflow rely on a string-based approach, where a document is split in paragraphs and translated individually. So I couldn’t just put each file markdown file as big blobs in the po files. To solve this problem, I created a python script splitting the markdown files in paragraphs, simplifying the markdown syntax (removing leading # and + for heading and list item). This script also handles Hugo shortcodes transforming:

{{< img caption="My figure caption" alt="My accessible description" src="..." >}}

in two strings:

  • My figure caption
  • My accessible description

The script can obliviously put the individual strings back in place. The scripts also handle the menu translation, and the translations of the strings in the footers. For now, the script is just a file in the kde-org repository, but I would like to transform it to a standalone library so that other gettext and Hugo users can translate their website.

Using Hugo API, the language selector was trivial to write:

<ul class="navbar-nav ml-auto">
  {{ if .IsTranslated }}
    <li class="nav-item dropdown" aria-describedby="language-picker-description">
      <p class="sr-only" id="language-picker-description">{{ i18n "Select-your-language" }}</p>
      <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
        <img src="/Language-Icons/icon20x24px-exported-transparent.png" alt="" />
        <span>{{ i18n "translations" }}</span>
      <div class="dropdown-menu dropdonw-trans" role="listbox">
        <a class="dropdown-item" aria-selected="true" hreflang="{{ .Site.Language.Lang }}" role="option" lang="{{ .Site.Language.Lang }}" href="{{ .Permalink }}">{{ .Site.Language.LanguageName }}</a>
        {{ range .Translations }}
          <a class="dropdown-item" hreflang="{{ .Language.Lang }}" role="option" lang="{{ .Language.Lang }}" href="{{ .Permalink }}">{{ .Language.LanguageName }}</a>
        {{ end }}
  {{ end }}

This is a bit verbose because this selector is also fully accessible for screen readers.

There are a few more tricks employed in to improve the internationalization, for example when a page doesn’t exist in a language, there is an Apache rule redirecting it to the English version. Another nice trick is that there is a special Hugo shortcode called i18n_var and used to parametrize the strings. For example:

{{< i18n_var "Today KDE releases a bugfix update to KDE Plasma 5, versioned %[1]s" "5.20.2" >}}

And the extractor is clever and only extract the part that needs to be translated.

The script

You can comment this post on r/kde and HN.


With an account on the Fediverse or Mastodon, you can respond to this post. Since Mastodon is decentralized, you can use your existing account hosted by another Mastodon server or compatible platform if you don't have an account on this one. Known non-private replies are displayed below.

Learn how this is implemented here.

Licensed under CC BY-SA 4.0