I am trying to configure an Nginx server to automatically redirect the user to their preferred browser language.
I know the solution is not perfect and dosn't take into account the qualifier for the language. This would require the AcceptLanguageModule
, but that's currently not necessary.
The current situation is as follows, for each language there is a folder with the respective files inside the dist folder (nginx root). This is the standard for Angular multi language projects.
dist/
├─ de/
│ ├─ index.html
├─ en/
│ ├─ index.html
├─ pl/
│ ├─ index.html
The current Nginx configuration (unnecessary elements removed):
# Browser preferred language detection (does NOT require AcceptLanguageModule)
map $http_accept_language $accept_language {
default de;
~*^en en;
~*^pl pl;
}
server {
listen 80;
server_name example.com;
root /var/www/dist;
index index.html index.htm;
location / {
rewrite ^/(.*)$ /$accept_language/$1 permanent;
}
location ~ ^/(de|en|pl) {
try_files $uri $uri/ /$1/index.html?$args;
}
}
The language should be prefixed to the URL so for example: /en
for the English language version. This works well if the user navigates to the root path of the domain.
But if a user calls a URL without a prefix for the language, this should be set automatically in front. If I call e.g. /account
the user should be redirected to /en/account
.
So a curl -I http://example.com/account -H "Accept-Language: en"
should return /en/account
but instead it returns /en
. If Accept-Language
is set to de
it works and returns the correct /de/account
location.
So how do I configure Nginx to correctly redirect the user if they have not specified a language prefix?
Is it possible to redirect URLs like /EN/account
to the correct URL? So if the prefix for the language is not correct.
After some trial and error, I solved the problem. It was probably due to the type of redirecting. With a return it works as desired.
Also the Nginx page with common config pitfalls recommends to use a return instead of a redirect.
I have further extended the configuration, which stores the selected language of the user in a cookie, named language
and prefers it over the accept language from the browser. This cookie can be easily set in the Angular application when the user selects another language.
The updated Nginx configuration (unnecessary elements removed):
# Browser preferred language detection (does NOT require AcceptLanguageModule)
map $http_accept_language $accept_language {
default de;
~*^en en;
~*^pl pl;
}
# Get preferred language from cookie or default to accept language
map $http_cookie $preferred_language {
default $accept_language;
"~*language=(?<language>(de|en|pl))" $language;
}
server {
listen 80;
server_name example.com;
root /var/www/dist;
index index.html index.htm;
location / {
return 302 $scheme://$host/$preferred_language$request_uri;
}
location ~ ^/(de|en|pl) {
try_files $uri $uri/ /$1/index.html?$args;
}
}