Home > Net >  Angular routing, and localization
Angular routing, and localization

Time:05-24

I have an angular application, that I've localized in multiple languages (let's say english, and french).

I would like to serve different locale version of the app depending on the url:

  • myapp.io/en/account
  • myapp.io/en/settings
  • myapp.io/fr/account
  • ...

I tried to follow the steps in the Screenshot error

Does anyone know what I am doing wrong? Or can anyone point to an open source working example, or a good tutorial?

CodePudding user response:

Try with this setup in your location block:

location ~ ^/(en|it) {
  try_files $uri /$1/index.html?$args;
}

https://angular.io/guide/i18n-common-deploy#nginx-example

CodePudding user response:

You didn't follow the official documentation correctly. At least you missed the language code in the last try_files directive argument:

location ~ ^/(en|it)/ {
    try_files $uri /$1/index.html;
}

I don't see any sensible reason to use a regex here:

if ($accept_language ~ "^$") {
    set $accept_language "it";
}

Much more performant exact matching can be used here instead:

if ($accept_language = "") {
    set $accept_language "it";
}

And even that one isn't really needed if you add the default item to your map block:

map $http_accept_language $accept_language {
    ~*^en en;
    ~*^it it;
    default it;
}

However it won't work if supported language won't be specified as the very first one. Imagine a request header like Accept-Language: de;q=0.9, en;q=0.8. A default Italian language will be selected for this user while even not being specified in the preferred language list (rather than English one). If you want to make it considering the languages precedence set by user in his browser settings, for two supported languages you can use the following:

map $http_accept_language $accept_language {
    ~en.*it(*SKIP)(*F)|it  it; # when "it" substring present and not preceded with "en"
    ~it.*en(*SKIP)(*F)|en  en; # when "en" substring present and not preceded with "it"
    default                it;
}

(Regex provided by Wiktor Stribiżew)

Three languages, considering the precedence order, will require the following map block:

map $http_accept_language $accept_language {
    ~(?:en|fr).*it(*SKIP)(*F)|it  it;
    ~(?:fr|it).*en(*SKIP)(*F)|en  en;
    ~(?:en|it).*fr(*SKIP)(*F)|fr  fr;
    default                       it;
}

and so on.

Instead of

rewrite ^/$ /$accept_language permanent;

I'd rather use (again, for the efficiency)

location = / {
    return 301 /$accept_language/;
}

And for the same reason I'd also consider to split main location block in two (or more, depending on supported languages count):

location /en/ {
    try_files $uri /en/index.html;
}
location /it/ {
    try_files $uri /it/index.html;
}
...

Nginx is not that kind of thing where DRY principles is always for good.

  • Related