Multilang routes

I’m trying to redirect a bunch of subpages to a specific point of the parent (or other) page using URL hashtags.

E.g.:
/faa/fee/fii/foo/fuu
to
/faa/fee/fii/foo#fuu

Now the issue comes in with multilang. I’ve managed to make it work, however I feel like the code is unnecessarily long and quite clunky.

c::set('routes', array(
	array(
		'pattern' => '(:any)/(:all)/foo/(:any)',
		'action'  => function($lang, $all, $uid) {
			if($lang == 'es') {
				$page = page($all.'/foo');
				return go(site()->url() . '/es/' . $page->uri() . '#' . $uid);
			} else {
				// in this case $lang is actually the first directory :(
				$page = page($lang . '/' . $all . '/foo');
				return go(site()->url() . '/' . $page->uri() . '#' . $uid);
			}
		}
	)
)

Since I can’t use go() nor page() with a language param, and since page won’t find the page if I pass the full URL with the language code included, I try to catch the URL in bits and reconstruct both the actual URL as the translated one manually. It bothers me in particular that the first wildcard brackets in my pattern is supposed to catch the language code but it actually just catches the first directory, as my filtering is poor.

I get the feeling that using something like (es/?) (which I’ve seen used in other threats) I could make the code much cleaner and ideally not even need the if statement.

This code only works for es/ pages, but I supect it’s just a matter of syntax for it to work also in default language. The logic to me seems correct…

c::set('routes', array(
	array(
		'pattern' => '(es/?)(:all)/foo/(:any)',
		'action'  => function($lang, $all, $uid) {
			$page = page($all . '/foo');
			return go(site()->url() . '/' . $lang . $page->uri() . '#' . $uid);
		}
	)
)

Try this: https://getkirby.com/docs/developer-guide/advanced/routing#multi-language-setup

OK, but that’s a static query. Do you have an example of a query with (:all), (:any), etc + multilang? I’m looking to implement this for hundreds of pages.

EDIT: I forgot, I couldn’t find a way to introduce a hashtag after my URL using the site()->visit() approach, that’s why both my examples work with go().

I think you’re overcomplicating things?

Why not add an id (#subpageid) to the elements on the parent page you’ld like to point to? That way you can use default browser mechanisms to do so?

e.g.:
for /faa/fee/fii/foo#fuu, if you have an element (div#fuu) on that page, the browser will automatically point to that.

Edit: Now that I come to think of it, if you have “aggregated” the subpages’ content on a parent page, but leave the subpages accessible you’ll have duplicate content issues imho.

Short answer: I can’t.

Long answer: the backend is designed in a way that the client can highlight any given page in other pages. They select a page from a list of all pages and the URL of that page is stored. However, not all pages have a template of their own - some are just displayed grouped with others in a shared template. They do have a page of their own in the panel though, so that they are autonomous and so that panel fields can be consistently reused.

I’m so close to the solution. It can’t be that hard. I think it’s simply a matter of regular expressions (which I don’t know at all).

I made it work!!!

c::set('routes', array(
	array(
		'pattern' => '(es/|/?)(:all)/foo/(:any)',
		'action'  => function($lang, $all, $uid) {
			$page = page($all.'/foo');
			return go(site()->url().'/'.$lang.$page->uri().'#'.$uid);
		}
	)
)

Looks pretty clean and readable to me.