Welcome Guest, Not a member yet? Register   Sign In
Router localization with empty {locale} (sitem.com/uri_here)) - CodeIgniter 4.3
#1

Hey there,
I've been trying to add multiple languages to my website, but it seems that I'm doing something wrong. I saw multiple topics with this issue and no solution at all. People were complaining in CodeIgniter's Github issues section and their threads were closed, without an answer.
I'd like to have a default language 'en'
public $defaultLocale = 'en';
public $negotiateLocale = false;
public $supportedLocales = ['fr'];
And I want to have these kinds of URLs:

website.com/fr/blog
website.com/fr/services
website.com/fr/contacts
website.com/fr
website.com/blog
website.com/services
website.com/contacts
website.com

Notice that there is no website.com/en/something. The reason is that this is a requirement for SEO to be good enough for Google.

In order to make proper routes for this, my Routes.php should look like that:

$routes->get('{locale}/blog', 'Blog::index');
$routes->get('{locale}/services', 'Services::index');
$routes->get('{locale}/contacts', 'Contacts::index');
$routes->get('{locale}', 'Home::index');
$routes->get('blog', 'Blog::index');
$routes->get('services', 'Services::index');
$routes->get('contacts', 'Contacts::index');
$routes->get('', 'Home::index');


I.e. I'll have to duplicate all my routes in order to have both languages supported. I got 100+ routes and this is really not an option for me.
How can I have this route: '{locale}/blog'and have it opened with and without provided locale in the url?

I'm experimenting with one super-ugly solution right now, that on the first glance seems to work. But I really don't like it, because it's a workaround and far from the proper way of doing things.

PHP Code:
$routesOptions $routes->getRoutesOptions(null'get');

foreach (
$routes->getRoutes('get') as $key => $row) {
  $options $routesOptions[$key] ?? [];

  if (isset($options['redirect'])) {
    $redirectTo is_array($row) ? key($row) : $row;

    $routes->addRedirect("{locale}/{$key}""{locale}/{$redirectTo}");
  } else {
    if (is_string($row)) {
      $routes->get("{locale}/{$key}"$row$options);
    } else {
      $routes->get("{locale}/{$key}", function () {}, $options);
    }
  }

Reply
#2

(06-13-2023, 11:25 PM)sstefanov Wrote: In order to make proper routes for this, my Routes.php should look like that:

$routes->get('{locale}/blog', 'Blog::index');
$routes->get('{locale}/services', 'Services::index');
$routes->get('{locale}/contacts', 'Contacts::index');
$routes->get('{locale}', 'Home::index');
$routes->get('blog', 'Blog::index');
$routes->get('services', 'Services::index');
$routes->get('contacts', 'Contacts::index');
$routes->get('', 'Home::index');


I.e. I'll have to duplicate all my routes in order to have both languages supported. I got 100+ routes and this is really not an option for me.
How can I have this route: '{locale}/blog'and have it opened with and without provided locale in the url?

You can't. You need all of the routes above.

I recommend you to write code like this:

PHP Code:
foreach ($routeArray as $path => $handler) { 
    $routes->get($path$handler);
    $routes->get("{locale}/$path"$handler);

Reply
#3

I would suggest another implementation.
PHP Code:
foreach(['''{locale}']  as $prefix) {
    $routes->group($prefix, static function ($routes) {
        $routes->get('blog''Blog::index');
        // e.tc.
    })


@kenjis what do you think about this?
PHP Code:
-- public function group(string $name, ...$params)
++ public function 
group(array|string $name, ...$params
Reply
#4

(06-13-2023, 11:25 PM)sstefanov Wrote: And I want to have these kinds of URLs:

website.com/fr/blog
website.com/fr/services
website.com/fr/contacts
website.com/fr
website.com/blog
website.com/services
website.com/contacts
website.com

Notice that there is no website.com/en/something. The reason is that this is a requirement for SEO to be good enough for Google.

Is the following something wrong for SEO?

website.com/en/blog
website.com/en/services
website.com/en/contacts
website.com/en
website.com/fr/blog
website.com/fr/services
website.com/fr/contacts
website.com/fr
Reply
#5

@iRedds I can't think of a use case other than this one.
Reply
#6

(06-14-2023, 09:05 PM)kenjis Wrote:
(06-13-2023, 11:25 PM)sstefanov Wrote: And I want to have these kinds of URLs:

website.com/fr/blog
website.com/fr/services
website.com/fr/contacts
website.com/fr
website.com/blog
website.com/services
website.com/contacts
website.com

Notice that there is no website.com/en/something. The reason is that this is a requirement for SEO to be good enough for Google.

Is the following something wrong for SEO?

website.com/en/blog
website.com/en/services
website.com/en/contacts
website.com/en
website.com/fr/blog
website.com/fr/services
website.com/fr/contacts
website.com/fr
Yes. 
This is how your meta tags should look like for my example case:

<meta content="en" http-equiv="content-language">
<link rel="alternate" hreflang="x-default" href="https://website.com/">
<link rel="alternate" hreflang="en" href="https://website.com/">
<link rel="alternate" hreflang="fr" href="https://website.com/fr">

As you may have seen from meta tags, the default behaviour is to have the "en" version without the "en" at the end of your url.
If you have website.com/en - this is duplicate content for search engines. And you should be having some content on website.com (without any language at the end), right?
I can't wrap my head around why the CodeIgniter's team didn't think of this basic case. I've seen tens of people complaining about this issue everywhere, and they just ignore them.
It takes literally no more than a few lines of code to implement this in their core engine.

PHP Code:
foreach(['''{locale}']  as $prefix) {
    $routes->group($prefix, static function ($routes) {
        $routes->get('blog''Blog::index');
        // e.tc.
    })


    })
}
Actually I like this solution very much, thank you  iRedds
Reply
#7

(06-14-2023, 10:33 PM)sstefanov Wrote: I can't wrap my head around why the CodeIgniter's team didn't think of this basic case. I've seen tens of people complaining about this issue everywhere, and they just ignore them.
It takes literally no more than a few lines of code to implement this in their core engine.

If you know how to solve the problem qualitatively, then please send a PR.
Reply
#8

(06-14-2023, 10:33 PM)sstefanov Wrote:
Quote:Is the following something wrong for SEO?

website.com/en/blog
website.com/en/services
website.com/en/contacts
website.com/en
website.com/fr/blog
website.com/fr/services
website.com/fr/contacts
website.com/fr
Yes. 
This is how your meta tags should look like for my example case:

<meta content="en" http-equiv="content-language">
<link rel="alternate" hreflang="x-default" href="https://website.com/">
<link rel="alternate" hreflang="en" href="https://website.com/">
<link rel="alternate" hreflang="fr" href="https://website.com/fr">

As you may have seen from meta tags, the default behaviour is to have the "en" version without the "en" at the end of your url.
If you have website.com/en - this is duplicate content for search engines. And you should be having some content on website.com (without any language at the end), right?

You can have all contents in lang directories.

    <link rel="alternate" hreflang="x-default" href="https://www.mozilla.org/">
      <link rel="alternate" hreflang="en-CA" href="https://www.mozilla.org/en-CA/" title="English (Canadian)">
      <link rel="alternate" hreflang="en-GB" href="https://www.mozilla.org/en-GB/" title="English (British)">
      <link rel="alternate" hreflang="en-US" href="https://www.mozilla.org/en-US/" title="English (US)">
      <link rel="alternate" hreflang="fr" href="https://www.mozilla.org/fr/" title="Français">

And the URL structure, "Subdirectories with gTLD (example.com/de/)" is described in the Google documentation:
https://developers.google.com/search/doc...cific-urls
Reply
#9

(06-14-2023, 10:33 PM)sstefanov Wrote: I've seen tens of people complaining about this issue everywhere, and they just ignore them.

I remember seeing this issue once or twice before, but I have never seen tens of people complaining about it.

The surest way to solve an issue is to send a PR.
https://github.com/codeigniter4/CodeIgni...request.md

Sending a PR does not guarantee that the merge will occur, but there is no other way to improve the CI4 source code other than by PR.
Reply




Theme © iAndrew 2016 - Forum software by © MyBB