Skip to content

Instantly share code, notes, and snippets.

@markhowellsmead
Last active March 19, 2024 20:25
Show Gist options
  • Star 26 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save markhowellsmead/0c414cea619727a3618b to your computer and use it in GitHub Desktop.
Save markhowellsmead/0c414cea619727a3618b to your computer and use it in GitHub Desktop.
Detect browser language and redirect to appropriate language version of the website
# Redirect visitors who request the root domain path (e.g. www.mywebsite.ch) to the appropriate language version
# Fallback to English version if no matching browser language defined
# Based on language version being at e.g. www.mywebsite.ch/de/
# This has no effect on any subpaths of the website, and therefore has no effect on e.g. WordPress admin.
# Using a 302 temporary redirect header stops the redirection from being cached in the browser.
# language is ES-MX (Mexico)
RewriteCond %{HTTP:Accept-Language} ^es-mx [NC]
RewriteRule ^$ /mx/ [L,R=302]
# language is ES-ES (Spain)
RewriteCond %{HTTP:Accept-Language} ^es-es [NC]
RewriteRule ^$ /es/ [L,R=302]
# language starts with DE
RewriteCond %{HTTP:Accept-Language} ^de [NC]
RewriteRule ^$ /de/ [L,R=302]
# language starts with FR
RewriteCond %{HTTP:Accept-Language} ^fr [NC]
RewriteRule ^$ /fr/ [L,R=302]
# language starts with IT
RewriteCond %{HTTP:Accept-Language} ^it [NC]
RewriteRule ^$ /it/ [L,R=302]
# else redirect to the English version
RewriteRule ^$ /en/ [L,R=302]
@markhowellsmead
Copy link
Author

Great sample, but a space is missing in the DE section just before the flags.

Fixed now (far too late!) Thanks @rgisiger.

@dani3c
Copy link

dani3c commented Oct 24, 2019

@markhowellsmead Thx for the answer and your time!

@StellarWellness
Copy link

Hi!

Thanks a lot for this code! I am using it for my Swedish/English Wordpress page. It seems to work fine. However, on the homepage/frontpage, I am not able to change between the two languages. I am stuck on the page that my browser language is set to.
On all other pages, I am able to view both versions. Any idea why that is? Thanks

@markhowellsmead
Copy link
Author

The front page for each language needs to be under its own URL - so /de/ for German or /en/ for English.

@oceandiveloper
Copy link

thanks. this works well for my WordPress website and much faster than using the redirection provided by WPML plugin

@markhowellsmead
Copy link
Author

@oceandiveloper 👏 That's because the server doesn't start a PHP process or interact with the database.

@spaceone
Copy link

The whole code is wrong because it doesn't respect the quality value, which is the indicator for sorting the languages.

@markhowellsmead
Copy link
Author

@spaceone As far as I'm aware (and as far as all the Apache servers I've worked with over my career indicate), the primary preferred language is always at the start of the Accept-Language header. The browser sorts the languages by order of preference, so that the primary preferred language is first. The regex in this code checks for the first language in the sequence and uses that to determine which path to use.

@markhowellsmead
Copy link
Author

markhowellsmead commented Aug 17, 2021

@spaceone As this is open-source code, your suggestion on how to integrate the quality value would be more than welcome. (This code has been working perfectly as it is on every project I've worked on over the past ten years or so, though.)

@spaceone
Copy link

It's still wrong, even if some browsers sort these values.
A header Accept-Language: en-US; q=0, de-AT; q=0.5, de-DE; q=0.9 is perfectly valid HTTP and should be correctly handled.
As apache httpd sucks more than e.g. nginx I can't find a proper solution for it, (which i am searching for, which is the reason why i found this thread).

@Moeinich
Copy link

I know this is old, but I'm having some issues with it; it always redirects to English..

@markhowellsmead
Copy link
Author

@Shadiezz What preferred language is set in your browser?

@Moeinich
Copy link

@Shadiezz What preferred language is set in your browser?

Yeah I figured it was my own fault. I had a typo in it which resulted in everything just redirecting to english, for some reason.. it's working like a champ now :)

@markhowellsmead
Copy link
Author

👍

@Robertndrei
Copy link

This works perfect for the example, but if you access www.mywebsite.ch/privacy, it will not be redirected to www.mywebsite.ch/en/privacy. Do you know how to achieve that?

@markhowellsmead
Copy link
Author

Try something like this, which contains a regex condition:

RewriteEngine On
RewriteCond %{HTTP:Accept-Language} ^en [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}/en%{REQUEST_URI} [L,R=301]

or for a very specific case,

RewriteEngine On
RewriteCond %{REQUEST_URI} ^(privacy(/?))
RewriteRule (.*) /en/$1 [L,NC,R=301]

@KB-Concepts
Copy link

Very cool Mark! :-)
Thanks for sharing this. It's very interesting code. By the way, you mentioned you fixed the missing space under DE, but I don't see that in the first announcement.
Would you please post the entire updated working Code?
Thank you

@markhowellsmead
Copy link
Author

The code is correct as displayed above.

@KB-Concepts
Copy link

Thank you, Mark

@Moeinich
Copy link

Do you know if its possible to only redirect on the front-end of a Wordpress site and not the admin area?

@markhowellsmead
Copy link
Author

markhowellsmead commented Oct 27, 2021

@Shadiezz Yes, it is. Exclude the WordPress admin paths from the redirection rules. (This example has nothing to do with WordPress admin, so it doesn't need to be changed.)

@Moeinich
Copy link

Moeinich commented Oct 28, 2021

@Shadiezz Yes, it is. Exclude the WordPress admin paths from the redirection rules. (This example has nothing to do with WordPress admin, so it doesn't need to be changed.)

Do you have any examples of how to exclude a path from redirection rules?
Would it be something like;
RewriteRule ^(wp-admin)($|/) - [L]

@markhowellsmead
Copy link
Author

No, sorry, I don't.

@markhowellsmead
Copy link
Author

I've updated the code example to use a 302 (temporary redirect) header, as using 301 may break subsequent requests due to the 301 permanent redirect header being cached in the browser.

@KB-Concepts
Copy link

KB-Concepts commented Aug 9, 2022 via email

@tp-machura
Copy link

Hi Mark,
Thank you for this piece of code. I am trying to make aredirect of the home page so that users have their native language available and I never thought to do it using htaccess! I'll give it a try.
However, I'm worried that robots will also be redirected, does the HTTP:Accept-Language only refer to user using a browser ?
I tried a Wordpress plugin in the past for redirection and it messed up with my index in google as it changed all urls of the main language to the redirected one :/

@markhowellsmead
Copy link
Author

Any device or browser which sends the HTTP Accept-Language header will be redirected.

@imdraug
Copy link

imdraug commented May 18, 2023

How can i change the redirection from subpath to subdomain?

Ex.: I have 3 multilanguage websites instances in Wordpress Multisite:
Portuguese (pt-BR) - https://maxispuma.com.br/
English (us-EN) - https://en.maxispuma.com.br/
Spanish (es-ES) - https://es.maxispuma.com.br/

How can i make it redirect across subdomains based on browser preferred language?

@imdraug
Copy link

imdraug commented May 18, 2023

Ps.: I'm new to coding... 😐😐

@SKH-bytes
Copy link

Hey !

Thank you very much for this one !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment