Language Codes and Names for your Grav Theme

I’ve been working on a site recently that’s intended to be small, easy-to-setup, yet international and easy for content editors to update… Grav to the rescue!

Grav is a lightweight, flat-file based CMS written in PHP. It uses a basic index.php to route the user to your pages, all of which are stored on the file system in a nice, version-controlled, easy-to-read format, Markdown. You use Twig templates to style them.

It’s simple, it’s fast, it allows your entire site to be version controlled, and it has a dope admin plugin to boot.

For internationalization, Grav has you covered. It’s baked into the core so that it’s tough to do wrong, and locales fall back to their appropriate language (e.g., UK English will borrow US English translations where UK English translations are missing). You can do full translations of all of your content, or use translation keys and translate your site as it’s ready.

Select “Twig” in Config -> System

However, my company wanted a language switcher page, where all of our supported languages are listed, along with their nice name.

Getting a list of currently supported languages in Grav while you’re in a Twig template is pretty easy. In fact, if you tell Grav to have your templates process Twig, you can embed the code directly in a page:

Once your pages are able to process Twig markup, your page’s content can look like this:

<div style="text-align:center">
    {% for language in config.system.languages.supported %}
        <a href="/{{language}}" title="{{ native_name(language) }}">{{ language }}</a><br>
    {% endfor %}
</div>

Woohoo! It shows our languages.

This ought to give you what you see above (or to the right, if you’re on mobile), as long as you have English (en) and English (Canada) (en-CA) supported in your configuration.

But now, we want to show the native name of the language… Who wants to sort through country codes to find what might be the proper one for them? After pouring over the Grav docs and various questions and answers on the web, I realized that there is no built-in way to get the native display names of culture codes from the codes themselves.

So I had to plug it in!

Fortunately, a plugin exists that provides that functionality, the Grav LangSwitcher plugin. I didn’t like the way it handled language switching out of the box, but I needed its Twig function native_name, which converts language codes to their native display names (e.g., en to English).

Grav, however, allows you to add Twig functions to your themes. In your theme’s initialization PHP folder (e.g., myTheme/myTheme.php), all you need is something like the following:

<?php
namespace Grav\Theme;

use Grav\Common\Language\LanguageCodes;
use Grav\Common\Theme;

class MyTheme extends Theme
{
    /**
     * @return array
     */
    public static function getSubscribedEvents()
    {
        return [
            'onThemeInitialized' => ['onThemeInitialized', 0]
        ];
    }
    /**
     * Initialize configuration
     */
    public function onThemeInitialized()
    {
        if ($this->isAdmin()) {
            $this->active = false;
            return;
        }
        $this->enable([
            'onTwigInitialized'   => ['onTwigInitialized', 0]
        ]);
    }

    /**
     * Add the native_name function. Cribbed from grav-plugin-langswitcher
     * at https://github.com/getgrav/grav-plugin-langswitcher/blob/develop/langswitcher.php
     */
    public function onTwigInitialized()
    {
        $this->grav['twig']->twig()->addFunction(
            new \Twig_SimpleFunction('native_name', function($key) {
                return LanguageCodes::getName($key);
            })
        );
    }
}

Now, you should have the Twig function native_name() available in your templates! This allows you to change your language switcher page content to the following:

<div style="text-align:center">
    {% for language in config.system.languages.supported %}
        <a href="/{{language}}" title="{{ native_name(language) }}">{{ native_name(language) }}</a><br>
    {% endfor %}
</div>

Our language switcher is complete!

Which should give you an output similar to what you see above (or to the left if you’re on mobile).

And there you have it! Now any languages you add support for in the backend will add a link to that list.

I highly recommend something like Grav. It’s a super flexible platform that’s a joy to work with. All we’re doing is setting up the repo and sending it to our DevOps person to push to any production server with PHP (and a few ubiquitous extensions). After that, it just works! We can even use plugins that sync between the prod site and our git repos, so that our sites are synced across development and production.

So get out there and Grav, ya’ll.