Multiple language in Ariadne (padnamen..)

12 views
Skip to first unread message

RengaBeats

unread,
Jul 23, 2015, 4:18:13 AM7/23/15
to Ariadne
Beste Ariadne Heads,

Ik heb een vraagje over het meer talig maken van een website.

Dit werkt default al 'like a charm', maar nu heb ik een vraagje over de pad-namen.

Ik zou graag vriendelijke URL's willen gebruiken.. 
Maar dan ook voor de beide talen, dus zoiets als dit:
test.nl/this-is-my-test/

Ik begrijp dat dit lastig is, omdat de beide talen gekoppeld zijn aan het zelfde object.
Maar misschien is hier al een goede oplossing voor, 
en ik denk, ik vraag het even, voordat ik zelf ga knutselen..

Ik ben benieuwd naar jullie gedachten!
Alvast bedankt.

Groetjes Renger

Auke Van Slooten

unread,
Jul 27, 2015, 7:58:04 AM7/27/15
to Ariadne, renga...@gmail.com, renga...@gmail.com
English translation for our international users:

The question is about writing a multilingual website where not only the page content is in multiple languages, but also the URL's for those pages.
How to do this in Ariadne.

First off: Ariadne is not designed for this use case. Ariadne is built around the concept that a URL is a unique pointer to some content and that the same content can be represented in multiple languages. However, there are some things you can do, depending on the situation.

In most cases when you need different URL's for different languages, it is already the case that you in fact need a different website for each language or region. In this case the answer is simple: create a site for each language or region. When you switch language, you simply redirect to the main page for that language. This allows you to create completely custom websites.

But if you have content that is completely shared between multiple languages and you need the correct words in the URL for the SEO ranking, you could use the notfound event to mimick a routing component. For example you have a product called 'shovel' in english and 'schop' in dutch. In the english version you'd like 'shovel' to show up in the URL, in the dutch you need 'schop'. In this case its best to pick one language as the default and use that as the real pathname, or you could use a non-specific identifier e.g. a number.

Next you need the list of pathnames for each language. This is not the same as the name of the object, but you could create a mapping from the name to a pathname, e.g. by using url_encode() or simply stripping special characters. I assume you'' use UrlEncode for now.

Given that a user has clicked on such a link, never mind how we created it, you need to find the correct object. Since that url doesn't actually exist in Ariadne as a path. But it does exist as a name for a specific language. I'll assume the language is also coded into the URL, either through a specific domain or through the NLS code in the url ( /-en-/ ). 

Ariadne cannot find an object which matches the URL, so it finds the nearest parent and fires a 'onnotfound' event on it. You can listen for this event as follows:

    ar('events')->listen('onnotfound')->call('my.router');

And create a template called 'my.router' like this:

    <pinp>
      $event = ar('events')->event();
      $arRequestedPath = $event->data['arRequestedPath'];
      $arRequestedTemplate = $event->data['arRequestedTemplate'];
      $arCallArgs = $event->data['arCallArgs'];

      $missingPart = substr($arRequestedPath, strlen($path), -1);
      $name = RawUrlDecode(basename($missingPart));
      $object = ar::find("name.value='$name' and name.nls='$nls'")->limit(1)->call('system.get.phtml');
      ar::get($object->path)->call($arRequestedTemplate, $arCallArgs);

      return $event->preventDefault();
    </pinp> 

The idea is to use the name encoded in the URL to search for the same name in an object in the current language. Obviously you'll need to do some more work if you have a hierarchy of objects all of which put their names in the URL instead of their pathnames. But the principle is the same. BTW. if you do need a nested solution, you may be better of with seperate sites anyway.

Generating the URL's is simple:

    <pinp>
       echo '<a href="'
       .ar('loader')->makeURL($parent)
       .RawUrlEncode($nlsdata->name)
       .'/">'.htmlspecialchars($nlsdata->name).'</a>';
    </pinp>

To generate URL's for other languages, pass the correct nls value to makeURL and use getValue('name', 'nl') to get the correct name (or use $data->{$nls}->name)
Again, if you need a hierarchy of names, you might want to create a template that creates the full URL by calling it on each of you parents.

The problem with this approach is that there is no safeguard against double names. A path in Ariadne is guaranteed to be unique. These are not.
You can create a check template that is triggered by the onbeforesave event which prevents an object being saved if another object has the same name, but this may not be very userfriendly. An alternative is to encode a guaranteed unique identifier in your URL as well, e.g. the pathname, which may be a number.

This leads to the final and perhaps simplest solution: just add a slug to the URL. This may be a new variable or you can also use the nlsdata->name for this.

Generating the URL is simple:

    <pinp>
       echo '<a href="'
       .ar('loader')->makeURL()
       .RawUrlEncode($nlsdata->name)
       .'/">'.htmlspecialchars($nlsdata->name).'</a>';
    </pinp>

And the onnotfound handler is simpler still:

    <pinp>
      $event = ar('events')->event();
      $arRequestedTemplate = $event->data['arRequestedTemplate'];
      $arCallArgs = $event->data['arCallArgs'];

      ar::call($arRequestedTemplate, $arCallArgs);

      return $event->preventDefault();
    </pinp> 

However, this blindly assumes that any missing page is because of the slug, you may want to double check that the name in the requested path matches with the name of the current object in the current language.

good luck,
Auke van Slooten
Muze

Op donderdag 23 juli 2015 10:18:13 UTC+2 schreef RengaBeats:
Reply all
Reply to author
Forward
0 new messages