clemdesign / grav-plugin-language-selector

Language Selector plugin with flags for Grav CMS
MIT License
6 stars 7 forks source link

Grav multilanguage site: Raw routes, redirects and slugs not translated: 2 Solutions for correct slugs #11

Open hh-ReBOOM opened 5 years ago

hh-ReBOOM commented 5 years ago

Hi there,

@clemdesign asked me to explain (and discuss) the problem with my multilanguage setup after I posted to closed topics regarding this problem.

First let me introduce the problem:

On a site with multilanguage setup and nested pages (help desk with collections of articles, nesting up to 5 levels) I tried to use the Grav langswitcher plugin as well clemdesigns language-selector. Both worked fine at a first glance. But then I realized that the URLs to the translated pages (as well as the href-lang-URLs) use the raw routes which are always built based on the default language. This in combination with 302 redirects is a base Grav functionality (which of course makes sense - but not always).

For example I configured

as languages of my Grav site. Then en is my default language. Every raw route is made up of this language.

Let's say we have a file structure like this (> indicates folder, slugs in brackets)

01.Home >
--home.de.md [start]
--home.en.md [home]
--01.Basic Knowledge >
----collection.de.md [grundlagen]
----collection.en.md [basics]
----01.Mail Fraud >
------article.de.md [mail_betrug]
------article.en.md [mail_fraud]

Ignore the different page types, it could all be article.

Assume an user on the Mail Fraud page. Then the slugged URLs for that page would be: en/home/basics/mail_fraud de/start/grundlagen/mail_betrug

If you're using langswitcher or language-selector and since both they only retrieve the slug for the page requested (not the pages on the path between, instead the raw route is used there) then the routes used for switching the language would be: (from en to de): de/home/basic%20knowledge/mail_betrug (from de to en): en/home/basic%20knowledge/mail_fraud

As you can see they differ from their corresponding slugged routes (the routes Grav will redirect to). It works since home/basic%20knowledge is the raw route part and Grav redirects with a 302 to the slugged routes successfully.

Second let me tell you what I found around this topic:

  1. Grav knows about configured languages, of course, but during handling a page request Grav knows nothing about pages in languages different than the active page.
  2. It's not impossible but it involves a certain amount of work to let Grav have any idea of pages of all configured languages. And this would certainly have an impact on Grav's performance.
  3. There are solutions that handle this problem more ore less well. Rather less (with at least one exception).
  4. Nobody thinks about performance. Hello? Why not using WordPress then?

Third I have solutions: Since I'm running out of time for now I will just outline the solutions to this problem and link to the corresponding solution. I will come back and give more detailed information here.

  1. Solution: Caching the slugged routes for each language. This is what I did. See https://github.com/getgrav/grav-plugin-langswitcher/issues/39#issuecomment-503979879 for detailed information. This solution is really fast, especially on sites with high level of nesting and higher number of supported languages. But it has drawbacks, too. One drawback is that under certain circumstances the cache is out of date. But precaching fights against that drawback.

  2. Solution: As posted here by pamtbaau one could traverse up the path to retrieve all slugs. This is a good solution, too. Indeed this solution ensures the slugs are always up-to-date. But it has the drawback that on sites with a high level of nesting and a rather high number of languages this produces heavy page loading (not from cache but from disk) just to produce slugged URLs for the language menu.

  3. Solution (to be done): A smart combination of 1 + 2 ;)

clemdesign commented 5 years ago

Thanks for your post. I shall analyze your solution and comme back here :).

hh-ReBOOM commented 5 years ago

Here is an update of my code: https://github.com/getgrav/grav-plugin-langswitcher/issues/39#issuecomment-506700705

In short terms:

If you are using the Grav's built in editor or maybe any editor plugin (untested) then an outdated cache will no longer occur. If you are using an external editor (as I do, my IDE is way better) then my cache will not recognize any changes until you perform precaching or any page of the corresponding language will be requested.

I want to point out what the drawback of pamtbaau's solution is. Imagine a page nested 5 levels deep with supported 10 languages. Then to retrieve the language specific slugged routes for the language switch will load up to 50(!) pages from disk (not from cache) on every single page request depending on which level the requested page resides.

The math is simple: Actual page loads needed = actual page level x supported languages Maximum page loads needed = maximum possible page level x supported languages

If your nesting is not very deep or you support only two languages or so then this may not be important. But on an international helpdesk page performance becomes critical.

And let me point out one last thing: My language specific slugged routes plugin is not for language switching only. It is universal and easy to use. No config necessary, it works straight forward and seemless. Maybe clemdesign integrates it in their language-selector plugin. Feel free to do so.