Port detect-language.js to TypeScript (#50623)
This commit is contained in:
7
package-lock.json
generated
7
package-lock.json
generated
@@ -104,6 +104,7 @@
|
||||
"@graphql-tools/load": "^8.0.0",
|
||||
"@octokit/rest": "^20.1.0",
|
||||
"@playwright/test": "1.44.0",
|
||||
"@types/accept-language-parser": "1.5.6",
|
||||
"@types/connect-datadog": "0.0.10",
|
||||
"@types/connect-timeout": "0.0.39",
|
||||
"@types/cookie": "0.6.0",
|
||||
@@ -3117,6 +3118,12 @@
|
||||
"version": "0.3.0",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/accept-language-parser": {
|
||||
"version": "1.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/accept-language-parser/-/accept-language-parser-1.5.6.tgz",
|
||||
"integrity": "sha512-lhSQUsAhAtbKjYgaw3f0c4EQKNQHFXhX87+OXUIqDHMkycvHGaqGskSRtnzysIUiqHPqNJ4BqI5SE++drsxx6A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/body-parser": {
|
||||
"version": "1.19.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
|
||||
|
||||
@@ -290,6 +290,7 @@
|
||||
"@graphql-tools/load": "^8.0.0",
|
||||
"@octokit/rest": "^20.1.0",
|
||||
"@playwright/test": "1.44.0",
|
||||
"@types/accept-language-parser": "1.5.6",
|
||||
"@types/connect-datadog": "0.0.10",
|
||||
"@types/connect-timeout": "0.0.39",
|
||||
"@types/cookie": "0.6.0",
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
} from './set-fastly-surrogate-key.js'
|
||||
import handleErrors from '@/observability/middleware/handle-errors'
|
||||
import handleNextDataPath from './handle-next-data-path'
|
||||
import detectLanguage from '@/languages/middleware/detect-language.js'
|
||||
import detectLanguage from '@/languages/middleware/detect-language'
|
||||
import reloadTree from './reload-tree.js'
|
||||
import context from './context/context.js'
|
||||
import shortVersions from '@/versions/middleware/short-versions.js'
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import languages, { languageKeys } from '#src/languages/lib/languages.js'
|
||||
import type { Request, Response, NextFunction } from 'express'
|
||||
import parser from 'accept-language-parser'
|
||||
import type { Language as parserLanguage } from 'accept-language-parser'
|
||||
|
||||
import { USER_LANGUAGE_COOKIE_NAME } from '#src/frame/lib/constants.js'
|
||||
import languages, { languageKeys } from '@/languages/lib/languages.js'
|
||||
import { USER_LANGUAGE_COOKIE_NAME } from '@/frame/lib/constants.js'
|
||||
import type { ExtendedRequest, Languages } from '@/types'
|
||||
|
||||
const chineseRegions = [
|
||||
'CN', // Mainland
|
||||
@@ -10,25 +13,28 @@ const chineseRegions = [
|
||||
'TW', // Taiwan
|
||||
]
|
||||
|
||||
function translationExists(language) {
|
||||
function translationExists(language: parserLanguage) {
|
||||
if (language.code === 'zh') {
|
||||
return chineseRegions.includes(language.region)
|
||||
return language.region && chineseRegions.includes(language.region)
|
||||
}
|
||||
// 92BD1212-61B8-4E7A: Remove ` && !languages[language.code].wip` for the public ship of ko, fr, de, ru
|
||||
return languageKeys.includes(language.code) && !languages[language.code].wip
|
||||
return languageKeys.includes(language.code) && !(languages as Languages)[language.code].wip
|
||||
}
|
||||
|
||||
function getLanguageCode(language) {
|
||||
return language.code === 'cn' && chineseRegions.includes(language.region) ? 'zh' : language.code
|
||||
function getLanguageCode(language: parserLanguage) {
|
||||
return language.code === 'cn' && language.region && chineseRegions.includes(language.region)
|
||||
? 'zh'
|
||||
: language.code
|
||||
}
|
||||
|
||||
function getUserLanguage(browserLanguages) {
|
||||
function getUserLanguage(browserLanguages: parserLanguage[]) {
|
||||
try {
|
||||
let numTopPreferences = 1
|
||||
for (let lang = 0; lang < browserLanguages.length; lang++) {
|
||||
// If language has multiple regions, Chrome adds the non-region language to list
|
||||
if (lang > 0 && browserLanguages[lang].code !== browserLanguages[lang - 1].code)
|
||||
if (lang > 0 && browserLanguages[lang].code !== browserLanguages[lang - 1].code) {
|
||||
numTopPreferences++
|
||||
}
|
||||
if (translationExists(browserLanguages[lang]) && numTopPreferences < 3) {
|
||||
return getLanguageCode(browserLanguages[lang])
|
||||
}
|
||||
@@ -38,26 +44,27 @@ function getUserLanguage(browserLanguages) {
|
||||
}
|
||||
}
|
||||
|
||||
function getUserLanguageFromCookie(req) {
|
||||
const value = req.cookies[USER_LANGUAGE_COOKIE_NAME]
|
||||
function getUserLanguageFromCookie(req: Request) {
|
||||
const value: undefined | string = req.cookies[USER_LANGUAGE_COOKIE_NAME]
|
||||
|
||||
// 92BD1212-61B8-4E7A: Remove ` && !languages[value].wip` for the public ship of ko, fr, de, ru
|
||||
if (value && languages[value] && !languages[value].wip) {
|
||||
if (value && (languages as Languages)[value] && !(languages as Languages)[value].wip) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
// determine language code from a path. Default to en if no valid match
|
||||
export function getLanguageCodeFromPath(path) {
|
||||
export function getLanguageCodeFromPath(path: string) {
|
||||
const maybeLanguage = (path.split('/')[path.startsWith('/_next/data/') ? 4 : 1] || '').slice(0, 2)
|
||||
return languageKeys.includes(maybeLanguage) ? maybeLanguage : 'en'
|
||||
}
|
||||
|
||||
export function getLanguageCodeFromHeader(req) {
|
||||
export function getLanguageCodeFromHeader(req: Request) {
|
||||
const browserLanguages = parser.parse(req.headers['accept-language'])
|
||||
return getUserLanguage(browserLanguages)
|
||||
}
|
||||
|
||||
export default function detectLanguage(req, res, next) {
|
||||
export default function detectLanguage(req: ExtendedRequest, res: Response, next: NextFunction) {
|
||||
req.language = getLanguageCodeFromPath(req.path)
|
||||
// Detecting browser language by user preference
|
||||
req.userLanguage = getUserLanguageFromCookie(req)
|
||||
14
src/types.ts
14
src/types.ts
@@ -10,5 +10,19 @@ export type ExtendedRequest = Request & {
|
||||
currentCategory?: string
|
||||
error?: Error
|
||||
}
|
||||
language?: string
|
||||
userLanguage?: string
|
||||
// Add more properties here as needed
|
||||
}
|
||||
|
||||
type Language = {
|
||||
name: string
|
||||
code: string
|
||||
hreflang: string
|
||||
dir: string
|
||||
wip: boolean
|
||||
}
|
||||
|
||||
export type Languages = {
|
||||
[key: string]: Language
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user