4

Consider the following RewriteRules:

RewriteEngline On

RewriteRule ^services$ services.php RewriteRule ^новости$ news.php

What they achieve is that www.example.com/services loads the content of services.php and www.example.com/новости loads the content of news.php. I would like to make the paths of both of those URLs case-insensitive. The English one could be done in one of three ways:

RewriteRule ^services$ services.php [NC]
RewriteRule ^[sS][eE][rR][vV][iI][cC][eE][sS]$ services.php
RewriteRule (?i)^services$ services.php

All three of the above work. They point all services paths to services.php regardless of case. Unfortunately, none of those approaches works for the rule with Cyrillic.

RewriteRule ^новости$ news.php [NC]
RewriteRule ^[нН][оО][вВ][оО][сС][тТ][иИ]$ news.php
RewriteRule (?i)^новости$ news.php

The first and third rules point ONLY www.example.com/новости to news.php. The second rule does literally nothing - it does not point ANY of the новости paths to news.php. It seems like when the square brackets are added, the Cyrillic characters within cease to exist. For example, the rule below points www.example.com/новостS to news.php but it DOES NOT point www.example.com/новости to it.

RewriteRule ^новост[иS]$ news.php

Finally, another thing that I have tried was to replace the Cyrillic characters with their UTF-8 representations - for example, replace [сС] with [\xd1\x81\xd0\xa1]. That did not work either.

Note: The rule below works as expected - it points both www.example.com/новости and www.example.com/НОВОСТИ to news.php. Unfortunately, I do not think it could be of use to me since it achieves the same as having two rewrite rules.

RewriteRule ^новости|НОВОСТИ$ news.php

The above is equivalent to:

RewriteRule ^новости$ news.php

RewriteRule ^НОВОСТИ$ news.php

1 Answers1

6

To achieve case insensitivity for Cyrillic characters in Apache .htaccess RewriteRules, the standard [NC] flag or the (?i) modifier doesn't work as expected. This is due to the limitation in Apache's handling of Unicode characters, specifically Cyrillic characters, for case-insensitive matching.

Solution: Use Perl Compatible Regular Expressions (PCRE)

By using the RewriteCond directive with PCRE (enabled by the RewriteOptions directive), you can match the input string case-insensitively, including for Cyrillic characters.

Enable PCRE in .htaccess:

RewriteEngine On
RewriteOptions Inherit

RewriteCond %{REQUEST_URI} ^/services$ [NC,OR] RewriteCond %{REQUEST_URI} ^/новости$ [NC] RewriteRule ^(.*)$ $1.php [L]

Alternatively, you can use RewriteCond with a NC flag:

RewriteEngine On

RewriteCond %{REQUEST_URI} ^/services$ [NC] RewriteRule ^services$ services.php [L]

RewriteCond %{REQUEST_URI} ^/новости$ [NC] RewriteRule ^новости$ news.php [L]

Explanation:

RewriteCond %{REQUEST_URI} ^/services$ [NC,OR]: This condition checks if the requested URI is /services case-insensitively.

RewriteCond %{REQUEST_URI} ^/новости$ [NC]: This condition checks if the requested URI is /новости case-insensitively.

RewriteRule ^(.*)$ $1.php [L]: If any of the above conditions are true, it rewrites the request to the corresponding .php file and stops further processing with the [L] flag.

Make sure that the .htaccess file is enabled and properly configured in your Apache configuration. For example, in your httpd.conf or apache2.conf file:

<Directory "/var/www/html">
    AllowOverride All
</Directory>

After making these changes, test your URLs to ensure that both /services and /новости work regardless of the case:

/services, /SERVICES, /SeRvIcEs
/новости, /НОВОСТИ, /НоВоСтИ

An Apache alternative: Nginx

Nginx was created by Игорь Владимирович Сысоев, who recognized that many users work with a variety of character encodings beyond Unicode. Nginx supports case-insensitivity for Cyrillic characters using the ~* modifier, which performs a case-insensitive match.

Nginx example:

server {
    listen 80;
    server_name example.com;
location / {
    # Case-insensitive rewrite for English URL
    if ($request_uri ~* ^/services$) {
        rewrite ^/services$ /services.php break;
    }

    # Case-insensitive rewrite for Cyrillic URL
    if ($request_uri ~* ^/новости$) {
        rewrite ^/новости$ /news.php break;
    }

    # Default location handling
    try_files $uri $uri/ =404;
}

}

Good luck!

Max Haase
  • 1,123