# Routing issues with multi language

**URL:** <https://forum.getkirby.com/t/routing-issues-with-multi-language/10979>\
**Category:** Questions\
**Tags:** v2\
**Created:** [August 6, 2018, 8:25pm UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979 "2018-08-06T20:25:10Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![jonabaptistella](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jonabaptistella/32/5797_2.png) [@jonabaptistella](https://forum.getkirby.com/u/jonabaptistella)\
**Post date:** [August 6, 2018, 8:25pm UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/1 "2018-08-06T20:25:10Z")

</div>

I have started with a little routing and than it have been growing for a while… All routes worked when the website was single language… 😉 And the now with multilingual setup, routes brakes down everywhere. 😕

So home is fine with `/` but with `/br` it gives me the error 404 page. So how do I make sure all my routes works fine with the new languages?

PS: None of the routes work with the language code. Inclusive the default Kirby routes.

I need a little help to get out of this mess of mine. Please, @texnixe 🙏

```auto
c::set('routes', array(
  // Articles route
  array(
    'pattern' => 'articles/(:any)/amp',
    'action' => function($article) {
      $page = page('articles/' . $article);
      site()->visit($page);

      tpl::$data = array_merge(tpl::$data, array(
        'kirby' => kirby(),
        'site' => site(),
        'pages' => pages(),
        'page' => page()
      ), $page->templateData());

      echo tpl::load(kirby()->roots()->templates() . DS . 'amp.php');
      return false;
    }
  ),
  // Logout route
  array(
    'pattern' => 'logout',
    'action' => function () {
      if ($user = site()->user()) $user->logout();
      go('login');
    }
  ),
  // Omit lander and link pages
  array(
    'pattern' => '(:any)',
    'action' => function($uid) {

      $page = page($uid);

      // if(!$page) $page = page('articles/' . $uid);
      if(!$page) $page = page('lander/' . $uid);
      if(!$page) $page = page('legacy/' . $uid);
      if(!$page) $page = page('link/' . $uid);
      if(!$page) $page = site()->errorPage();

      return site()->visit($page);
      return false;
    }
  ),
  array(
    'pattern' => 'lander/(:any)',
    'action' => function($uid) {
      go($uid);
    }
  ),
  array(
    'pattern' => 'legacy/(:any)',
    'action' => function($uid) {
      go($uid);
    }
  ),
  array(
    'pattern' => 'link/(:any)',
    'action' => function($uid) {
      go($uid);
    }
  )
));

if(!function_exists('panel')) return;
panel()->routes(array(
  array(
    'pattern' => '(logout)', // the trick here is the parens around the route pattern
    'method' => 'GET|POST',
    'filter' => array('auth'),
    'action' => function() {
      if($user = panel()->user()) {
        $user->logout();
      }
      go('/');
    },
  ),
));

```

---

<div class="post-metadata">

**Author:** ![jimbobrjames](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jimbobrjames/32/5802_2.png) [@jimbobrjames](https://forum.getkirby.com/u/jimbobrjames)\
**Post date:** [August 6, 2018, 8:34pm UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/2 "2018-08-06T20:34:57Z")

</div>

Do the routes work in the sites default language but not in others?

---

<div class="post-metadata">

**Author:** ![jonabaptistella](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jonabaptistella/32/5797_2.png) [@jonabaptistella](https://forum.getkirby.com/u/jonabaptistella)\
**Post date:** [August 6, 2018, 8:40pm UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/3 "2018-08-06T20:40:29Z")

</div>

So before I added multi language it all worked fine. The default route like `/home` only works as long I keep the language setup this way `'url' => '/',` but when I add `/br` than it goes to the 404 error page.

---

<div class="post-metadata">

**Author:** ![jonabaptistella](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jonabaptistella/32/5797_2.png) [@jonabaptistella](https://forum.getkirby.com/u/jonabaptistella)\
**Post date:** [August 6, 2018, 8:45pm UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/4 "2018-08-06T20:45:37Z")

</div>

So in short everything that gets the language code in the url seems to fail. Did that answer the question? Ideas @jimbobrjames ?

---

<div class="post-metadata">

**Author:** ![jimbobrjames](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jimbobrjames/32/5802_2.png) [@jimbobrjames](https://forum.getkirby.com/u/jimbobrjames)\
**Post date:** [August 6, 2018, 9:02pm UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/5 "2018-08-06T21:02:47Z")

</div>

I dont have a huge experience with routes, but I have done a couple of funky things with them. Since you are getting a 404 page, i guess the codes ok, otherwise you would get a Whoops page, I guess, becuase it cant find the page rather bombing out from a coding error.

Feels like the pattern is the problem. I think maybe you need something like:

```auto
'pattern' => '(:any)/articles/(:any)/amp',

```

Thats a total stab in the dark, but i think its not working becuase the page you have in the pattern does work from the site root with no language, but when you switch languages you technically add an other level of depth, virtually, as if it was a folder. I hope @texnixe can clear that assumption up if I have it totally wrong.

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [August 6, 2018, 10:06pm UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/6 "2018-08-06T22:06:19Z")

</div>

If you use the language code only on the non-default language, you have two options

- either duplicate your routes to include one with the language code and one without
- make the language code an optional placeholder (there are some examples here on the forum), just `(:any)`as suggested. by @jimbobrjames won’t work

Also, you will have to add the language code with `site()->visit('some-page', $langcode)`.

It’s a bit late now and I’m tired, will get back to you tomorrow if you can’t sort it out in the. meantime.

---

<div class="post-metadata">

**Author:** ![jonabaptistella](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jonabaptistella/32/5797_2.png) [@jonabaptistella](https://forum.getkirby.com/u/jonabaptistella)\
**Post date:** [August 6, 2018, 10:35pm UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/7 "2018-08-06T22:35:51Z")

</div>

Get some sleep. I think I will need a little help one way or another tomorrow. 🙂 Good night!

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [August 7, 2018, 8:02am UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/8 "2018-08-07T08:02:56Z")

</div>

Have a look at this post: [Routes pattern for multilanguage site](https://forum.getkirby.com/t/routes-pattern-for-multilanguage-site/10503/4?u=texnixe)

So your first route (e.g. the first one, should start like this:

```auto
'pattern' => '(?:(^[A-Za-z]{2})//?)?articles/(:any)/amp',
'action' => function($lang, $article) {
    $lang = $lang ?: 'en'; // the default language
    // do stuff
  }

```

---

<div class="post-metadata">

**Author:** ![jonabaptistella](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jonabaptistella/32/5797_2.png) [@jonabaptistella](https://forum.getkirby.com/u/jonabaptistella)\
**Post date:** [August 7, 2018, 11:29am UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/9 "2018-08-07T11:29:14Z")

</div>

On the first rule I have added the code. But not sure if I get this right yet.

I get an error `"session_start(): Cannot send session cache limiter - headers already sent "`

On this line: `echo tpl::load(kirby()->roots()->templates() . DS . 'amp.php');`

I have tried to search here on the forum but there is very little with multi lang setup and routes.

---

<div class="post-metadata">

**Author:** ![jonabaptistella](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jonabaptistella/32/5797_2.png) [@jonabaptistella](https://forum.getkirby.com/u/jonabaptistella)\
**Post date:** [August 7, 2018, 11:31am UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/10 "2018-08-07T11:31:37Z")

</div>

On the second rule set is also failing, the omiting rules. The logout rules works without any issues.

How will you make it generic?

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [August 7, 2018, 11:48am UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/11 "2018-08-07T11:48:04Z")

</div>

Maybe the error occurs because of the echo statement, see this: [Exception with custom route](https://forum.getkirby.com/t/exception-with-custom-route/10080/8?u=texnixe)

---

<div class="post-metadata">

**Author:** ![jonabaptistella](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jonabaptistella/32/5797_2.png) [@jonabaptistella](https://forum.getkirby.com/u/jonabaptistella)\
**Post date:** [August 7, 2018, 11:59am UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/12 "2018-08-07T11:59:25Z")

</div>

Yes you are right. That worked well! 😄 That leaves me with the last rule set, the omiting. I have tried, but without success, and everything I see on the forum is using different approaches.

Does it exist a kirby way? And a generic way?

```auto
array(
    'pattern' => '(:any)',
    'action' => function($uid) {
  
      $page = page($uid);
  
      // if(!$page) $page = page('articles/' . $uid);
      if(!$page) $page = page('lander/' . $uid);
      if(!$page) $page = page('legacy/' . $uid);
      if(!$page) $page = page('link/' . $uid);
      if(!$page) $page = site()->errorPage();
  
      return site()->visit($page);
      return false;
    }
  ),
  array(
    'pattern' => 'lander/(:any)',
    'action' => function($uid) {
      go($uid);
    }
  ),
  array(
    'pattern' => 'legacy/(:any)',
    'action' => function($uid) {
      go($uid);
    }
  ),
  array(
    'pattern' => 'link/(:any)',
    'action' => function($uid) {
      go($uid);
    }
  ),

```

I don´t seem to understand the logic of the language code etc. 😕

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [August 7, 2018, 12:29pm UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/13 "2018-08-07T12:29:23Z")

</div>

This should work. Note I changed the pages to test this in a starter kit, so you have to adapt again.

```auto
c::set('routes', array(
  // Articles route

  // Omit lander and link pages
  array(
    'pattern' => '(?:(^[A-Za-z]{2})//?)?(:any)',
    'action' => function($lang,$uid) {
      $lang = $lang ?: 'en';
      $page = page($uid);

      // if(!$page) $page = page('articles/' . $uid);
      if(!$page) $page = page('projects/' . $uid);
      if(!$page) $page = page('blog/' . $uid);
      //if(!$page) $page = page('link/' . $uid);
      if(!$page) $page = site()->errorPage();

      return site()->visit($page, $lang);

    }
  ),
  array(
    'pattern' => '(?:(^[A-Za-z]{2})//?)?projects/(:any)',
    'action' => function($lang,$uid) {
      $lang = $lang ?: '';
    go($lang.'/'.$uid);
    }
  ),
  array(
    'pattern' => '(?:(^[A-Za-z]{2})//?)?blog/(:any)',
    'action' => function($lang,$uid) {
        $lang = $lang ?: '';
      go($lang.'/'.$uid);
    }
  )
));

```

---

<div class="post-metadata">

**Author:** ![jonabaptistella](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jonabaptistella/32/5797_2.png) [@jonabaptistella](https://forum.getkirby.com/u/jonabaptistella)\
**Post date:** [August 7, 2018, 2:00pm UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/14 "2018-08-07T14:00:50Z")

</div>

All the custom routes seems to work with the code you have made @texnixe . (I have not test all pages but if one work the rest should too, I hope.) 🙂

**Case #1**  
So the `domain.com/en` fails with my current custom routes. Even though the other pages for ex. `domain.com/articles` works fine, and swaps languages without any issues. All other pages seems to work.  
And the pages that uses the `URL-key` parameter is also failing to load. They gives a error 404, and goes to the default error page.

My current routes:

```auto
c::set('routes', array(
  // Articles route
  array(
    'pattern' => '(?:(^[A-Za-z]{2})//?)?articles/(:any)/amp',
    'action' => function($lang, $article) {
      $lang = $lang ?: 'br'; // the default language
      $page = page('articles/' . $article);
      site()->visit($page, $lang);

      tpl::$data = array_merge(tpl::$data, array(
        'kirby' => kirby(),
        'site' => site(),
        'pages' => pages(),
        'page' => page()
      ), $page->templateData());

      return new Response(tpl::load(kirby()->roots()->templates() . DS . 'amp.php'), 'html', 200);
    }
  ),
  // Omit lander and link pages
  array(
    'pattern' => '(?:(^[A-Za-z]{2})//?)?(:any)',
    'action' => function($lang,$uid) {
      $lang = $lang ?: 'br';
      $page = page($uid);

      // if(!$page) $page = page('articles/' . $uid);
      if(!$page) $page = page('lander/' . $uid);
      if(!$page) $page = page('blog/' . $uid);
      //if(!$page) $page = page('link/' . $uid);
      if(!$page) $page = site()->errorPage();

      return site()->visit($page, $lang);

    }
  ),
  array(
    'pattern' => '(?:(^[A-Za-z]{2})//?)?lander/(:any)',
    'action' => function($lang,$uid) {
      $lang = $lang ?: '';
    go($lang.'/'.$uid);
    }
  ),
  array(
    'pattern' => '(?:(^[A-Za-z]{2})//?)?blog/(:any)',
    'action' => function($lang,$uid) {
        $lang = $lang ?: '';
      go($lang.'/'.$uid);
    }
  ),
  // Logout route
  array(
    'pattern' => 'logout',
    'action' => function () {
      if ($user = site()->user()) $user->logout();
      go('login');
    }
  ),

));

```

**Case #2**  
If I add `/br` to the url for the default language. `domain.com` do not work anymore. The initial redirect do not work. Any idea for why? This seems to be the case even if I comment out all custom routes and restart the server. Did work before… So I don´t know what that can have caused this.

**Case #3**  
When I remove (comment out) all custom routes and restart my server I get faced with a odd issue. On the home page I click the `English` language and than I go back to the default `Portuguese` the page reloads with the `/en` language extension. Is this a nav issue? Cause the other pages seems to work.

**Case #4**  
This code seems to also not work as intended in multi-language setup. This is not a deal-breaker, but upon logout from the panel you get redirected to the home page.

```auto
if(!function_exists('panel')) return;
panel()->routes(array(
  array(
    'pattern' => '(logout)', // the trick here is the parens around the route pattern
    'method' => 'GET|POST',
    'filter' => array('auth'),
    'action' => function() {
      if($user = panel()->user()) {
        $user->logout();
      }
      go('/');
    },
  ),
));

```

**Question**  
What will you recommend run the default language with or without the language code in the url? Are there any benefits to one or the other?

**Info**  
You can put any two letters in the language code and it will still load the page. This is not important but if this goes to the error page that will be more consistent. It there is a way… 😊

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [August 7, 2018, 2:06pm UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/15 "2018-08-07T14:06:06Z")

</div>

Oh my, routing with multi-lang is a chore, really.

If you use URL-keys, that complicates it and you need separate routes for those pages.

Routes are easier to deal with, I think, if you use the lang code for all languages.

To avoid the issue with none existing language code, check if the lang code exists in an array with possible lang codes, otherwise hit the error page or redirect.

---

<div class="post-metadata">

**Author:** ![jonabaptistella](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jonabaptistella/32/5797_2.png) [@jonabaptistella](https://forum.getkirby.com/u/jonabaptistella)\
**Post date:** [August 7, 2018, 2:17pm UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/16 "2018-08-07T14:17:28Z")

</div>

> If you use URL-keys, that complicates it and you need separate routes for those pages.

Yes, but that URL-keys for ex. is some of what makes it really good. So how will the separation of they look like?

> Routes are easier to deal with, I think, if you use the lang code for all languages.

So how do you attack the routes this way?

> To avoid the issue with none existing language code, check if the lang code exists in an array with possible lang codes, otherwise hit the error page or redirect.

Is this need if we drop the regular expression?

What is your take @texnixe on this:

> What will you recommend run the default language with or without the language code in the url? Are there any benefits to one or the other? And to use both languages with the codes seems to work better in Kirby or is that the case?

---

<div class="post-metadata">

**Author:** ![jonabaptistella](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jonabaptistella/32/5797_2.png) [@jonabaptistella](https://forum.getkirby.com/u/jonabaptistella)\
**Post date:** [August 7, 2018, 2:20pm UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/17 "2018-08-07T14:20:07Z")

</div>

And in my Case #1 above, the home page do not work in the none default language, how to get around that?

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [August 7, 2018, 2:31pm UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/18 "2018-08-07T14:31:52Z")

</div>

Case #1 is probably caused by the omit rule, maybe only redirect if the page is not the home page.

> [@jonabaptistella](#):
>
> What will you recommend run the default language with or without the language code in the url? Are there any benefits to one or the other? And to use both languages with the codes seems to work better in Kirby or is that the case?

Don’t know, but this answer on SO has some good points, I think:

> <https://stackoverflow.com/questions/38309154/should-default-language-of-multilingual-website-be-a-part-of-the-url/38363403#38363403>

For pages with URL-key, you would have separate routes, but the final solution depends on whether or not you use the lang code for the default language or not

With lang code, en

```auto
'pattern' => 'en/lander/(:any)',

```

With lang code, br

```auto
'pattern' => 'br/whatever-that-page-is-called-in brasilian/(:any)',

```

---

<div class="post-metadata">

**Author:** ![jonabaptistella](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jonabaptistella/32/5797_2.png) [@jonabaptistella](https://forum.getkirby.com/u/jonabaptistella)\
**Post date:** [August 7, 2018, 7:06pm UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/19 "2018-08-07T19:06:09Z")

</div>

So I take the master-decision and go for language codes on both languages. Meaning /br is the default language and the /en is the secondary language. With the AMP route active it all works. After clearing some cache issues etc.

Is there any way to just put in the language code if there is none, aka default for ex.?

---

<div class="post-metadata">

**Author:** ![jonabaptistella](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jonabaptistella/32/5797_2.png) [@jonabaptistella](https://forum.getkirby.com/u/jonabaptistella)\
**Post date:** [August 7, 2018, 7:12pm UTC](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979/20 "2018-08-07T19:12:23Z")

</div>

> [@texnixe](#):
>
> For pages with URL-key, you would have separate routes, but the final solution depends on whether or not you use the lang code for the default language or not
> 
> With lang code, en
> 
> ```auto
> 'pattern' => 'en/lander/(:any)',
> 
> ```
> 
> With lang code, br
> 
> ```auto
> 'pattern' => 'br/whatever-that-page-is-called-in brasilian/(:any)',
> 
> ```

Based on my choice with leaving the default code in how will this look?

PS: I really miss good docs on this. AMP pages and Omit with multi-language and retain all functions like URL-keys… 😉 Also AMP pages with omiting the blog url for ex. and with multi-lang. (Advanced stuff 😄 )

[Next page](https://forum.getkirby.com/t/routing-issues-with-multi-language/10979.md?page=2)
