Я пытаюсь правильно обрабатывать запросы к локализованному угловому приложению, размещенному на 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
.
Любая помощь приветствуется.