Open qwerdee opened 4 years ago
It also would be awesome to be able to deactivate the fallback to default language, if the page is not translated. It is not always what you want.
This all is doable as a plugin, however I think kirby's behavior is not really what you would expect, if you don't know about it. Here the plugin I use, with page and pages methods for convenience (eg. filter to only show blog posts that are translated)
<?php
use Kirby\Cms\Page;
use Kirby\Toolkit\Str;
use Kirby\Cms\ModelWithContent;
use Kirby\Exception\NotFoundException;
Kirby::plugin('querdee/better-multilang', [
'hooks' => [
'route:after' => function ($route, $path, $method, $result) {
$language = kirby()->language();
$defaultLanguage = kirby()->defaultLanguage();
if ($language === $defaultLanguage) {
return $result;
}
// block untranslated pages to prevent fallback to default language
if ($result instanceof ModelWithContent && $result->translation($language)->exists() === false) {
return new NotFoundException();
}
// block alternative urls (containing default language slugs)
if (
$result instanceof Page
&& Str::rtrim(implode('/', [$language->baseUrl(), $path]), '/') !== $result->url()
) {
return new NotFoundException();
}
return $result;
},
],
'pageMethods' => [
'isTranslated' => function (?string $languageCode = null) {
return $this->translation($languageCode)->exists();
},
],
'pagesMethods' => [
'translated' => function (?string $languageCode = null) {
return $this->filter(fn (ModelWithContent $model) => $model->translation($languageCode)->exists());
},
],
]);
When content and slugs are translated to english and default language is set to german, kirby's current behavior is as follows:
mysite.com/de/preise -> german content mysite.com/de/pricing -> 404 mysite.com/en/pricing -> english content mysite.com/en/preise -> english content
Despite being a bit inconsistent it does lead to duplicate content since every page has at least two valid url for each non default translation. This number even increases exponentially for each level a page is nested, so a page like
/news/february/a-title
can have up to 8 valid urls for the same translation, if each parent page has translated slugs as well.I would argue that it would make sense to implement either or both (via config) of these behaviors:
strict:
each page has only one url per language, everything else results in 404
mysite.com/de/preise -> german content mysite.com/de/pricing -> 404 mysite.com/en/pricing -> english content mysite.com/en/preise-> 404
There is no problem with duplicate content and it is always clear which url is the correct one.
redirect:
each page site has only one url, alternative slugs result in redirect
mysite.com/de/preise -> german content mysite.com/de/pricing -> 301 to /de/preise mysite.com/en/pricing -> english content mysite.com/en/preise -> 301 to /en/pricing
This be more like how kirby handles non-default-lang prefix with default-lang slug, except that it avoids duplicate content via correct redircts and works from the other way round as well. This would mean more work for the router, but of course only if it does not find a page with the given path right away