Locale-rendered website, based of shared languages

I have following requirement, and I’m unsure how to handle this properly in Kirby:

Customer wants a website that contains content translated in 5 different languages. That’s easy :slight_smile:

But, they want to serve it via locales mapped to one of those languages. E.g.:

  • nl_BENL
  • fr_BEFR
  • de_BEDE
  • de_DEDE
  • nl_NLNL
  • en_GBEN
  • en_CZEN
  • intlEN

The rendered content in a selected locale is drawn from the mapped language, only for the price of the product which is country-specific (which could be handled from a helper function in a model).

They explicitely don’t want to setup the locales in Kirby to avoid managing all the different locales; instead they want to administer only the translated content in the panel.

How would you set this up?


i would use a non translatable object field for the price and set a field for each locale. then you could do things like $page->price()->toObject()->{$local}()->toNumber()

Thanks for you reply @bnomei. The problem isn’t so much the price.

The problem is I’ld like to setup those 5 languages in Kirby’s config (and in panel); but then have a frontend that serves locales: instead of mysite.tld/en/some-pagemysite.tld/en_GB/some-page.

How do you set up something like that; e.g. in Kirby’s router, in the
$page->url() helpers, … ?

something like this? untested.

     'routes' => [
                'pattern' => '(:any)',
                'action' => function (string $locale) {
                    if(in_array($locale, $myLocales)) {
                        return site()->visit(site()->homePage(), substr($locale, 0, 2)); // TODO: intl
                    $this->next(); // other routing like assets etc.
                'pattern' => '(:any)/(:all)',
                'action' => function (string $locale, string $id) {
                    if(in_array($locale, $myLocales) && $page = page($id)) {
                        return site()->visit($page, substr($locale, 0, 2)); // TODO: intl
                    $this->next(); // other routing like assets etc.

that wont fix the urls generated by kirby for things like $page->url() etc. you might need custom page methods for that $page->urlWithLocale()

but it would need special setup for sitemap and canonical urls.

another idea would be to create a language for each locale BUT have custom page model that overwrites the content read/write method to just load the one from the corresponding language. not sure if that works but it might.

public function readContent(string $languageCode = null): array
        return  parent::readContent(substr($languageCode, 0, 2));

    public function writeContent(array $data, string $languageCode = null): bool
        return parent::writeContent($data, substr($languageCode, 0, 2)));

Thanks @bnomei , interesting takes.

I’m testdriving the first option and the PoC seems to work. ATM, smaller things such as idd sitemaps, anything url-related and etc $site->homepage()->url(), … need extra work.


I can’t get the second suggestion to work.

First one has major drawbacks too; e.g. default page caching doens’t work as expected, no url helper support, …


whats the error on the second solution? maybe you need to have all 5 languages as well so kirby know how to create the meta files?

you could hide dem from the pickers via custom panel css

There wasn’t really a hard error, but pages appeared “empty” as if the content wasn’t in the content files…

Also; I’m unsure we can have a global model for all templates as I don’t really want to create a model for each template that is added. And, I don’t really know how to deal with reading from $site neither as I don’t think we can have a model there to force Kirby to read from the right site content files.

Maybe use two installations? One for the multilanguage content and a second one with all languages which pulls in content via content representations from the first installation?

How would that work @texnixe ? :thinking: