I recently stumbled over a post in the Kirby forums about the HTML lang
attribute for multilingual sites.
It made me realise that I never even thought about how to handle the lang
attribute when content of a page isnāt fully translated. A good opportunity to diving a bit deeper and writing an article about my learnings and ideas.
What the lang
attribute does
The lang
attribute helps screen readers pronounce words correctly and enables translation tools to work more reliably. There is automatic language detection for both screen readers and translation tools, but theyāre often unreliable. Thatās why we have to do this:
<html lang="en">
If youāre dealing with mixed-language content itās nice to put an additional lang
attribute on specific elements. For example, letās say youāre writing a web dev article and suddenly thereās an Eichhƶrnchen šæļø
there's an <span lang="de">Eichhƶrnchen</span> šæļø
How Kirby handles translations
Kirbyās language handling is quite straightforward. Once you create a translation of a page, meaning you e.g. add a file like default.de.txt
next to your default.en.txt
, the pageās content can be returned in that language. If thereās no translation, the default language will be used. You can read more about this in Kirbyās docs.
Setting the lang attribute with Kirby looks something like this:
<html lang="<?= $kirby->language()->code() ?>">
This will set the lang
attribute to the current languageās code. If the current language is German, the attribute will be lang="de"
.
Mixed-language pages
So what happens when a page isnāt fully translated? If a visitor views a German page that falls back to English content, some content is actually in English. Actually, we have a page thatās partially English and partially German. While the menu with other pagesā titles might be fully translated, the content of the article is using the fallback language.
What we need is an easy way to set a lang
attribute on our content wrapper, in addition to the lang
attribute on our document element, our <html>
. To prevent this complex logic from polluting our template code, we can create some custom page methods.
One method to check if the current page is translated:
'isTranslated' => function () {
return $this->translation(kirby()->language()->code())->exists();
}
And one method to return a lang
attribute for the fallback language:
'fallbackLang' => function () {
if ($this->isTranslated()) return null;
return 'lang="' . kirby()->defaultLanguage()->code() . '"';
}
The fallbackLang()
method returns null
when the page is fully translated in the current language, which means no lang
attribute is needed since the content matches the language specified in the <html>
element. If the page is not translated, it returns a lang
attribute with the default languageās code.
Now we can use them in our templates like this:
<main <?= $page->fallbackLang() ?>>
<?php if($page->isTranslated() === false): ?>
<p class="notice">
Oops, this page has not been translated yet.
</p>
<?php endif ?>
<?= $page->text()->kt() ?>
</main>
To be honest, I havenāt worked on a multi language site for some time, but I wanted to publish this article anyways as itās getting a bit dusty in my drafts. Thereās a good chance Iāll update it with some practical learnings in the future.
Have you implemented something similar on your multi language sites? Iād love to hear about your approaches over on Mastodon.