Подайте угловое приложение i18n в Firebase, используя функции - PullRequest
0 голосов
/ 24 января 2019

Я пытаюсь правильно обрабатывать запросы к локализованному угловому приложению, размещенному на Firebase.Цель состоит в том, чтобы загрузить правильный пакет приложений в зависимости от: 1) файла cookie с именем locale.2) Заголовок accept-language.3) По умолчанию en-us, когда другие недоступны.

При локализации приложений angular с i18n angular-cli генерирует пакеты (версии вашего приложения) для каждого языка / локали, присутствующего в angular.json.Firebase обслуживает ваши связки как статический контент, и он имеет серьезные меры безопасности, запрещающие обходы пути.

Я пробовал оба параметра перезаписывает и перенаправляет в firebase.json, но нет возможности перехватить cookie locale.Затем я использовал облачные функции для чтения файлов cookie, анализа запросов и возврата нужного ресурса, используя express, cookie-parser и express-locale.

1.Использование только хостинга

firebase.json

{
  "hosting": {
    "public": "dist",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "/en-us/**",
        "destination": "/en-us/index.html"
      },
      {
        "source": "/es-co/**",
        "destination": "/es-co/index.html"
      },
      {
        "source": "/zh-hans/**",
        "destination": "/zh-hans/index.html"
      },
      {
        "source": "**",
        "destination": "/en-us/index.html"
      }
    ]
  }
}

2.Использование облачных функций и экспресс

firebase.json

{
  "functions": {
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint"
    ]
  },
  "hosting": {
    "public": "dist",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "function": "multilang"
      }
    ]
  }
}

functions / index.js

const express = require('express')
const expressLocale = require('express-locale')
const cookieParser = require('cookie-parser')
const functions = require('firebase-functions')
const path = require('path')
const fs = require('fs')
const _ = require('lodash')

const app = express()

const localeMap = {
  en: 'en_US',
  es: 'es_CO',
  zh: 'zh_TW',
  'en-US': 'en_US',
  'es-CO': 'es_CO',
  'zh-TW': 'zh_TW',
  'zh-Hans': 'zh_TW',
  en_US: 'en_US',
  es_CO: 'es_CO',
  zh_TW: 'zh_TW',
  zh_Hans: 'zh_TW'
}

const defaultLocale = 'en_US'

const baseMap = {
  en_US: 'en-us',
  es_CO: 'es-co',
  zh_TW: 'zh-hans'
}

app
  .use(cookieParser())
  .use(expressLocale({
    priority: ['cookie', 'accept-language', 'map', 'default'],
    default: defaultLocale,
    map: localeMap
  }))
  .use('**', (req, res, next) => {
    const locale = localeMap[req.locale.language]
    const sanitized = req.originalUrl.replace(/\.{2,}/g, '').replace(/\/{2,}/g, '/')
    const url = sanitized.split('/')
    const idx = url.length === 1 ? 0 : 1

    url[0] = _.values(baseMap).includes(url[idx]) ?
      url[idx] : (baseMap[locale] || baseMap[defaultLocale])

    if (url.length > 1 && url[0] === url[1]) {
      url.shift()
    }

    let file = path.resolve(`dist/${url.join('/')}`)

    if (!url[url.length - 1].match(/^[\w,\s-]+\.[a-z0-9]{2,4}$/) || !fs.existsSync(file)) {
      file = path.resolve(`dist/${url[0]}/index.html`)
    }

    res.sendFile(file)
  })

exports.multilang = functions.https.onRequest(app)

Последние настройки хорошо работают для локальной эмуляции Firebaseразрешение пути к index.html или любому другому запрошенному файлу (например, ngsw-worker.js для поддержки прогрессивных приложений).

При развертывании в Firebase не удается разрешить и найти размещенные файлы (например, index.html), даже еслиВы изменяете путь на:

  • /${url[0]}/index.html
  • ../${url[0]}/index.html
  • /public/${url[0]}/index.html

Или переписываете req.sendFile вreq.redirect.

Любая помощь приветствуется.

...