codeigniter4 / CodeIgniter4

Open Source PHP Framework (originally from EllisLab)
https://codeigniter.com/
MIT License
5.39k stars 1.9k forks source link

Problem with Localization {locale} #6763

Closed mbnl closed 2 years ago

mbnl commented 2 years ago

PHP Version

8.1

CodeIgniter4 Version

2.1.7

CodeIgniter4 Installation Method

Manual (zip or tar.gz)

Which operating systems have you tested for this bug?

Linux

Which server did you use?

apache

Database

No response

What happened?

When I add a normal uncertain route after setting the localization routes, it does not scan after the localization route and opens the homepage as the default language instead of navigating to the route I want.

Steps to Reproduce

My Routes;

// Turkish Pages (/ and /maintenance)
$routes->get('/', 'Home::index',['as' => 'home|default']);
$routes->get('maintenance', 'Home::Maintenance',['as' => 'maintenance|default']);

// English Pages (/en and /en/maintenance)
$routes->get('{locale}', 'Home',['as' => 'home']);
$routes->get('{locale}/maintenance', 'Home::Maintenance',['as' => 'maintenance']);

// Turkish (/test-page or /page1 or /page2 etc.)
$routes->get('(:any)', 'FindPage::index/$1');

// English (/en/test-page or /en/page1 or /en/page2 etc.)
$routes->get('{locale}/(:any)', 'FindPage::index/$1');

Expected Output

following route is not working after localization location. sample; When I type /page 1, I want the "Find Page" controller to go, but the home controller is shown

// Turkish (/test-page or /page1 or /page2 etc.)
$routes->get('(:any)', 'FindPage::index/$1'); 

Anything else?

Turkish - Home page; https://domain.com/ English - Home page: https://domain.com/

Turkish - Find page route ; https://domain.com/test123 or https://domain.com/abcdefg etc. English - Find page route ; https://domain.com/en/test123 or https://domain.com/en/abcdefg etc.

why are the supported languages not checked in the {locale} check in the core router class and so I can't create a route for random pages after the {locale} tag?

/system/Router/Router.php 413. line;

// Are we dealing with a locale?
  if (strpos($routeKey, '{locale}') !== false) {
      $routeKey = str_replace('{locale}', '[^/]+', $routeKey);
  }

I think the supported languages should be checked and directed accordingly.

Sorry my english is not very good i used google translate for the articles.

kenjis commented 2 years ago

This is not a bug.

{locale} means (:segment):

The placeholder {locale} can be placed as a segment in your route. https://codeigniter4.github.io/CodeIgniter4/outgoing/localization.html#in-routes

/page1 matches | GET | {locale} | \App\Controllers\Home | | toolbar |:

$ php spark routes

CodeIgniter v4.2.7 Command Line Tool - Server Time: 2022-10-26 17:39:06 UTC-05:00

+--------+----------------------+------------------------------------------+----------------+---------------+
| Method | Route                | Handler                                  | Before Filters | After Filters |
+--------+----------------------+------------------------------------------+----------------+---------------+
| GET    | /                    | \App\Controllers\Home::index             |                | toolbar       |
| GET    | maintenance          | \App\Controllers\Home::Maintenance       |                | toolbar       |
| GET    | {locale}             | \App\Controllers\Home                    |                | toolbar       |
| GET    | {locale}/maintenance | \App\Controllers\Home::Maintenance       |                | toolbar       |
| GET    | (.*)                 | \App\Controllers\FindPage::index/$1      |                | toolbar       |
| GET    | {locale}/(.*)        | \App\Controllers\FindPage::index/$1      |                | toolbar       |
| CLI    | ci(.*)               | \CodeIgniter\CLI\CommandRunner::index/$1 |                |               |
+--------+----------------------+------------------------------------------+----------------+---------------+
kenjis commented 2 years ago

v4.3.0 will have $routes->useSupportedLocalesOnly(true):

Added $routes->useSupportedLocalesOnly(true) so that the Router returns 404 Not Found if the locale in the URL is not supported in Config\App::$supportedLocales. https://github.com/codeigniter4/CodeIgniter4/blob/4.3/user_guide_src/source/changelogs/v4.3.0.rst#others-3

kenjis commented 2 years ago

We use GitHub issues to track BUGS and to track approved DEVELOPMENT work packages. We use our forum to provide SUPPORT and to discuss FEATURE REQUESTS.

mbnl commented 2 years ago

Thank you for your explanation, but what you said didn't help me.

I think there is a logic error.

I got the solution as below.


system/Router/Router.php -> checkRoutes function

Before:

// Are we dealing with a locale?
            if (strpos($routeKey, '{locale}') !== false) {
                $routeKey = str_replace('{locale}', '[^/]+', $routeKey);
            }

After:

$locales = array_filter(config('App')->supportedLocales ?? []);
            $localeRegExp = "";
            foreach ($locales as $lcl){
$localeRegExp .= '^'.$lcl.'|';
}
            // Are we dealing with a locale?
            if (strpos($routeKey, '{locale}') !== false) {
                $routeKey = str_replace('{locale}', '('.$localeRegExp.')+', $routeKey);
            }

Route List

Before:

  | /
  | (^\)+
  | bakim
  | web-politika/([^/]+)
  | (^\)+/maintenance
  | (^\)+/web-policy/([^/]+)
  | (^\)+/([^/]+)
  | ([^/]+)

After:

  | /
  | (^tr\|^en\|)+
  | bakim
  | web-politika/([^/]+)
  | (^tr\|^en\|)+/maintenance
  | (^tr\|^en\|)+/web-policy/([^/]+)
  | (^tr\|^en\|)+/([^/]+)
  | ([^/]+)