Zola 0.15.3 issue: not all pages/sections have their language and translations set properly

We have just started to evaluate zola (currently 0.15.3) as we’d like to replace our ageing current (flat file) CMS. As an international company, built-in multilingual capabilities are particularly important to us.

We were fiddling around with the zola Papaya theme (GitHub - justint/papaya: A clean Zola theme for blogging and projects.) as that has “demo” content in English and Chinese already included (but missing e.g. a language switcher and a hreflang implementation)…

Unfortunately there’s an issue: Some of the pages have their languages set properly (and linked as translations) but others don’t - i.e. if they don’t have content files. E.g. the home page “/” renders the “index.html” template but does not pull in content from the content folder - neither does it seem to have a correct language set nor is it linked to its translations. The same is true also for the “tags” listing page or the 404 error page. All of these are generated from their template without pulling in data from the content folder.

With that said, all pages do have their languages encoded in the URLs. I.e. the Chinese language tags page can be found at http://www.example.com/zh/tags.

Did we miss something in the docs? Or is that a known zola issue? If so, is a bug report on Github the best way to get this worked on?

Thanks for the insight


1 Like

Can you check the next branch (Next version by Keats · Pull Request #1741 · getzola/zola · GitHub)? There’s been a bunch of fixes for multiple languages.
Alternatively 0.16 should be released sometimes this week

@keats, thanks for your message. Compiled the next branch and ran zola build on the stock papaya template from github:

Error: Page /somewhere/papaya-main/content/projects/project-3/index.md has taxonomy "categories" which is not defined in config.toml

Taxonomies are in fact defined in config.toml and work okay as-is in zola 0.15.3. First taxonomies definition is in the “global” section of config.toml and the one for the second language appears further down under [languages.zh]. If I move the first definition to the [languages.en] section, I can get past this error. However, what’s stopping me now are out-of-bounds errors that I am struggling to track down:

Building site...
Checking all internal links with anchors.
> Successfully checked 0 internal link(s) with anchors.
-> Creating 13 pages (0 orphan) and 5 sections
thread '<unnamed>' panicked at 'byte index 1 is out of bounds of ``', library/core/src/str/mod.rs:107:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread '<unnamed>' panicked at 'byte index 1 is out of bounds of ``', library/core/src/str/mod.rs:107:9
thread '<unnamed>' panicked at 'byte index 1 is out of bounds of ``', library/core/src/str/mod.rs:107:9
thread '<unnamed>' panicked at 'byte index 1 is out of bounds of ``', library/core/src/str/mod.rs:107:9
thread '<unnamed>' panicked at 'byte index 1 is out of bounds of ``', library/core/src/str/mod.rs:107:9

Any thoughts how to get this diagnosed?

Thanks a lot for your support and this great project!


Whoa that’s weird and good to find that before releasing.

The has taxonomy "categories" which is not defined in config.toml is a tricky one that will probably be fixed eventually. In short, the config.toml defines a default taxonomies array but then overrides the languages.en dict of the default language. Right now the default language top level and inner level are not merged and we just take the languages.DEFAULT_LANGUAGE data which in this case doesn’t contain any taxonomies. Ideally we would merge both dicts but I had never had this issue in practice so it didn’t get into my radar. I’ve created Merge default data language data in config.toml · Issue #1918 · getzola/zola · GitHub to track it.

As for the panic, it seems papaya calls get_url with an empty path in the social.html, which wasn’t handled in the new version. I’ve pushed a commit which fixes a couple of issues I found while building papaya.

You’re welcome!

@keats, I checked again with today’s build of zola-next and yes, it doesn’t crash anymore when building the papaya template demo site.

However, “next” still requires the taxonomy array being moved to language.en whereas 0.15.3 was okay with it being in the global section of config.toml. (Knowing the workaround, this is hardly a dealbraker…)

Moreover, I don’t see any difference between 0.15.3 and “next” regarding lang and translations of the generated pages:

  • Pages that pull in Markdown content (e.g. the “about” page/s) have their languages set and their translations linked.
  • Pages that are generated solely based on a template html file (i.e. without pulling in Markdown from the content folder, e.g. the homepage) have their language set but their
    translations are empty / not linked. I find that particularly interesting as the URLs involved are correctly generated by zola (both versions), so it should “know” about these.
  • I haven’t dug into that further but for some reason, the “tags” page does not even have a lang set at all…

What can I do to get this fixed? I have quite a bunch of programming languages under my belt but haven’t really gotten to get my feet wet with rust…

You’re not meant to access translations directly, you have to use the trans function. It’s a bit weird translations are ever passed to the template tbh, I’ll have to make sure it doesn’t happen - I can see how that’s confusing.

That’s odd, every single template should have lang passed in :thinking: I’ll have a look

Just to avoid misunderstandings: I’ve been using the snippet below to iterate over the translations array - e.g. to build the hreflang links for a page/section or a language switcher:

        {% if section %}
			{% for t in section.translations %}
		        Language: {{t.lang}}
        	{% endfor %}
        {% elif page %}
			{% for t in page.translations %}
		        Language: {{t.lang}}
        	{% endfor %}

If this is not the intended way to access “all translations of this page”, how should that be done instead? I thought the trans function would just be to access translations of a text…

With that said, I noticed one limitation of my approach above: E.g. the 404 page does not seem to have an associated page object - gives me this build error in zola:

Error: Failed to build the site
Error: Failed to render '404.html' (error happened in a parent template)
Error: Reason: Variable `page.translations` not found in context while rendering '404.html'

Are 404 pages not meant to be translated?

Ah sorry miscommunication. I thought you were trying to accesss the config.toml translations dict. I see the issue now, it might be sections are not filled with alternative languages.

It’s impossible to translate the 404 in a pure static site engine, we could generate one for each language but someone will still need to setup some server rules to redirect to the right one depending on the language.

I can’t reproduce those two

Will look into this further tomorrow.

Just for my understanding: Am I right that a “web page” in zola is either a page or a section - i.e. it has either a page or section object?

Thanks on the note regarding the 404 page - right, I didn’t think of that. But it is good practise to have such pages translated as well… even if one would need e.g. htaccess rules to “access” them.

Not necessarily. All the taxonomies page for example don’t have those.

@keats, I put a project on github at: GitHub - peterkelm/papaya: A clean Zola theme for blogging and projects. to demonstrate this issue. Compared to the stock template I only added a snippet to the base.html template to print the available languages for a page.

  • Although the home page ( does indeed have a Chinese language translated version ( it only shows one language: its own…
  • The “tags” page ( does not print any languages. This is most likely a consequence of it being treated as a “taxonomies” page and not having a section object… For a multilingual site that’s quite counterintuitive as visitors would expect a consistent set of languages across all pages. In fact, there is a Chinese tags page (…
  • The same is true e.g. for the 404 page…

Generally speaking, I would expect that all generated pages (not talking about the page object here of course) under /zh/ to appear as being Chinese language and all pages without that language “prefix” to be seen as using the site’s default language.

In my eyes, all of this is critical in multiple ways:

  1. for creating hreflang links in the html head
  2. to generate a (consistent) language switcher
  3. to generate a corresponding sitemap

As mentioned I have used a fair number of programming languages professionally over the decades but rust is not one of them… I will do my best to study the zola code and improve my understanding of its inner workings as I do think that zola is a great tool for our client’s websites as well as our own ones.

So the tags and 404 page it’s normal that there are no translations as they are not linked in any ways across languages currently. Solving both of those is not that hard but not going to happen for 0.16.

As for the home page, both the en and zh pages are automatically generated and it looks like they are not added to translations in that case, that should be easy to fix tomorrow.

Thanks for that info. For now, my workaround, at least for the home page, is to pull in content from the content folder. That way the page does have both languages…

The homepage issue should now be fixed in next

Just checked the next version. Works for me.

I know this is a bit late, I recently added multi-lingual support during an overhaul and refactor of Abridge. The refactor is mostly complete: Abridge Refactor · Issue #105 · Jieiku/abridge · GitHub

I hope you or others can use Abridge as a reference for a multi-lingual site.

git clone --branch refactor https://github.com/Jieiku/abridge
cd abridge
zola serve

Listing all articles

It is quite a cursed solution, but it works for me - at least for now - also it isn’t written in the best way possible.

It could be quite nice if zola had something like hugo :melting_face:




default_language = "us"

random html file:

<!-- Ensure not using us language -->
{% if lang == "us" %}
    {% set lang = "en" %}
{% endif %}

{% set_global pages = [] %}

{% for lang in [lang, 'en', 'pl'] | unique %}
    {% set section = get_section(path="articles/_index." ~ lang ~ ".md") %}
    {% set_global pages = pages | concat(with=section.pages) %}
    {{ section.pages | length }}
{% endfor %}

{{ pages | length }}

{% set_global allowed = [] %}

{% for page in pages %}
  {% set path = page.path | trim_start_matches(pat="/" ~ page.lang) %}

  {% if path not in allowed %}
      {% set_global allowed = allowed | concat(with=path) %}

      <li><a href="{{ page.permalink | safe }}">{{page.date}} - {{page.lang}} - {{ page.title }}</a></li>
  {% endif %}

{% endfor %}

Issues :upside_down_face:

Firstly, it claims one language (us), which you can’t use.

It doesn’t detect files (.md) that doesn’t end with lang code.


post.md won’t be visible, but post.en.md will be