AWS Cloudfront distribute multilingual angular apps

≡放荡痞女 提交于 2019-12-21 05:45:18

问题


I have an Angular app which is store in a AWS S3 bucket and distributed by Cloudfront.

Now I want to distribute my app in multiple languages. I've already translated my angular app and for each language I have on build.

So my S3 bucket looks like this:

de
   /index.html
   /script.js
en
   /index.html
   /script.js

For each language I want to serve another app.

In Cloudfront I created two Origins which points to Origin Path /de and /en

So my URL schema is like this:

<appname>.<mydomain>.com/:lang

But my problem is, I dont get the Error Pages to work with these specific language folders. I need these Error Response Handlers to deliver the angular app(s) when a 404 occurred (due to a reload)

Does anyone know how I can solve this? Or should i create one more subdomain for each language? So it looks like this:

<lang>.<appname>.<mydomain>.com

回答1:


I've recently bumped into the same problem. My situation:

  • I have an Angular 5 app
  • I'm using i18n for 2 languages (en & fr)
  • S3 for website hosting and Cloudfront for CDN & custom domain name/ssl certificate
  • My default language is EN, so https://example.com redirects to https://example.com/en/
  • When a user navigates directly to a route (eg https://example.com/en/product/1234), it should also work, irrespectively of the number of subfolders

Solution:

  • Create 2 separate deployments, 1 for each language (en, fr). Git bash tends to replace the /en/ with a local folder, so make sure your index.html file contains the right base url

ng build -prod -aot --base-href /en/ --i18nFile=src/locale/messages.en.xlf --i1nFormat=xlf --locale=en

  • Deploy these into an /en/ and /fr/ folder at the root of your S3 bucket
  • Create a new CloudFront distribution. Make sure to leave the Default Root Object empty!
  • Add your bucket as an S3 origin (as you otherwise would).
  • Now, create a new Lambda function, use Node 6.10. Important: select US-EAST-1, as this is the only region supported by Lambda@Edge. Code:

const path = require('path')

exports.handler = (evt, ctx, cb) => {
  const { request } = evt.Records[0].cf

  if (!path.extname(request.uri)) {
      if (request.uri.startsWith('/fr'))
        request.uri = '/fr/index.html'
      else
        request.uri = '/en/index.html'
  }
  cb(null, request)
}
  • Next: publish this version (in the Action dropdown)
  • Copy the ARN of this version, and go back to CloudFront -> Behaviors -> Default Behavior
  • Select Origin Request as Event Type in the Lambda Function Associations, and paste the ARN of the Lambda function.

Building Angular with the base path parameter will establish the right subdirectory for your Angular app. The rewrite will make sure that resource files will not be rewritten, but all your routes will be redirected to index.html




回答2:


I had the same problem but also wanted automatic redirection to the closest language when going to

<mydomain>.com/

Using Dries Van Hansewijck's solution and npm's locale package you can had redirection with the following code:

const path = require('path');
const locale = require("locale");
const supportedLocales = new locale.Locales(['en', 'de']);
locale.Locale["default"] = new locale.Locales('de');

module.exports.pendixPortalI18n = (event, context, callback) => {
  const { request } = event.Records[0].cf;
  const locale = getBestLocale(request);
  if (!path.extname(request.uri)) {
    console.log(JSON.stringify(event, null, 2));
    if (request.uri.startsWith('/en')) {
      console.log('ENGLISH detected')
      request.uri = '/en/index.html';
    } else if (request.uri.startsWith('/de')) {
      console.log('GERMAN detected')
      request.uri = '/de/index.html';
    } else {
      console.log('Default matching locale is ' + locale);
      request.uri = `/${locale}/index.html`;
    }
  }
  callback(null, request)
};

function getBestLocale(request) {
  /* First we try to find the accept-language value */
  if (request && request.headers
    && request.headers['accept-language'] && request.headers['accept-language'].length > 0
    && request.headers['accept-language'][0].value) {
    const acceptLanguage = request.headers['accept-language'][0].value;
    const locales = new locale.Locales(acceptLanguage);
    const bestMatch = locales.best(supportedLocales);
    console.log("You asked for: " + JSON.stringify(acceptLanguage));
    console.log("We support: " + supportedLocales);
    console.log("Our default is: " + locale.Locale["default"]);
    console.log('best match is ' + bestMatch);
    return bestMatch;
  }
  return 'de';
}

Here we try to find the user's language in the supported language list. In order to do that you need to forward the accept-language header to the origin in cloudfront (in the behavior tab). If the user's language is not in the supported languages list we redirect to german.



来源:https://stackoverflow.com/questions/49066634/aws-cloudfront-distribute-multilingual-angular-apps

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!