Search code examples
angular.htaccessurlinternationalization

How to redirect assets and page URLs for i18n angular application


I am in the process of internationalizing an Angular 11 application. Things work fine with ng serve but I am facing issues when deploying, as I can't manage to address the following:

  • make sure that assets referred from the code as /assets/picture.png are loaded properly (i.e. transformed in /xx/assets/picture.png where xx is the language such as en or fr): they trigger a 404 error.
  • make sure that a URL such as https://example.com/records/12 does not trigger an error, and is automatically converted to https://example.com/xx/records/12 (where again, xx is the language such as en or fr).

The angular.json file contains the standard stuff:

      "i18n": {
        "sourceLocale": "fr",
        "locales": {
          "en": {
            "translation": "src/locale/messages.en.xlf"
          }
        }
      }
...
      "localize": true
...

The application is built in 2 languages with ng build --prod --localize, which generates 2 en and fr subfolders within dist, which I then deploy to the root of the server, next to the following .htaccess file:

RewriteEngine on
RewriteBase /
RewriteRule ^../index\.html$ - [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (..) $1/index.html [L]

RewriteCond %{HTTP:Accept-Language} ^en [NC]
RewriteRule ^$ /en/ [R]

RewriteCond %{HTTP:Accept-Language} !^en [NC]
RewriteRule ^$ /fr/ [R]

(Please note that fr is the source and default locale, and en is a translation)

I imagine that the issue comes from the .htaccess file, because nothing there specifies that https://example.com/assets/picture.png should transform to https://example.com/en/assets/picture.png, and likewise for URLs for Angular routes.

Could you please tell me how to fix this?

Note: by viewing the source code of the resulting web page, I could verify that it contains the proper href, e.g. for fr:

<!doctype html>
<html lang="fr">
<head>
  <meta charset="utf-8">
  <title>MyApp</title>
  <base href="/fr/">

Solution

  • It looks like the following works:

    RewriteEngine on
    RewriteBase /
    
    # keep index.html unchanged
    RewriteRule ^(en|fr)/index\.html$ - [L]
    
    # if the URL has no locale prefix, add it (for French)
    RewriteCond %{HTTP:Accept-Language} ^fr [NC]
    RewriteRule ^(?!(fr|en))(.*)$ fr/$2 [L,DPI]
    
    # same for English
    RewriteCond %{HTTP:Accept-Language} ^en [NC]
    RewriteRule ^(?!(fr|en))(.*)$ en/$2 [L,DPI]
    
    # at this stage, the URL has a locale prefix
    # If the requested resource is not a file/directory, then submit it
    # to Angular as a potential route starting with locale 
    # => redirect to index.html prefixed with the first 2 letters (= locale)
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(..).*$ $1/index.html [L]