22const express = require ( 'express' ) ;
33const next = require ( 'next' ) ;
44const cookieParser = require ( 'cookie-parser' ) ;
5+ const pino = require ( 'pino-http' ) ( ) ;
56
67const app = next ( { dev : false } ) ;
78const handle = app . getRequestHandler ( ) ;
@@ -11,81 +12,78 @@ const DEFAULT_LOCALE = 'zh';
1112const FALLBACK_LOCALE = 'en' ;
1213const SUPPORTED_LOCALES = [ 'zh' , 'en' ] ;
1314
15+ const isStaticRoute = ( url ) =>
16+ url . startsWith ( '/_next' ) || url . startsWith ( '/static' ) ;
17+
18+ const getLocaleFromUrl = ( path ) => {
19+ const urlParts = path . split ( '/' ) ;
20+ return SUPPORTED_LOCALES . includes ( urlParts [ 1 ] ) ? urlParts [ 1 ] : null ;
21+ } ;
22+
23+ const determineLocale = ( req , urlLocale ) => {
24+ let locale = req . cookies . locale ;
25+ if ( ! locale ) {
26+ const browserLocale = req . acceptsLanguages ( SUPPORTED_LOCALES ) ;
27+ locale = urlLocale || browserLocale || FALLBACK_LOCALE ;
28+ if ( browserLocale && browserLocale !== 'zh' ) {
29+ locale = FALLBACK_LOCALE ;
30+ }
31+ }
32+ return SUPPORTED_LOCALES . includes ( locale ) ? locale : FALLBACK_LOCALE ;
33+ } ;
34+
35+ const handleRedirect = ( req , res , locale , urlLocale ) => {
36+ if ( urlLocale ) {
37+ if ( urlLocale !== locale ) {
38+ locale = urlLocale ;
39+ }
40+ if ( locale === DEFAULT_LOCALE ) {
41+ const newUrl = req . url . replace ( `/${ DEFAULT_LOCALE } ` , '' ) || '/' ;
42+ return res . redirect ( 307 , newUrl ) ;
43+ }
44+ } else if ( locale !== DEFAULT_LOCALE ) {
45+ let newUrl = `/${ locale } ${ req . url } ` ;
46+ if ( newUrl . endsWith ( '/' ) && newUrl . length > 1 ) {
47+ newUrl = newUrl . slice ( 0 , - 1 ) ;
48+ }
49+ return res . redirect ( 307 , newUrl ) ;
50+ }
51+ return false ;
52+ } ;
53+
54+ const canSetCookie = ( req ) => {
55+ // 检查请求头中是否有 'cookie' 字段
56+ return req . headers . cookie !== undefined ;
57+ } ;
58+
1459async function startServer ( ) {
1560 try {
1661 await app . prepare ( ) ;
1762 const server = express ( ) ;
1863 server . use ( cookieParser ( ) ) ;
64+ server . use ( pino ) ;
1965
20- // 中间件处理语言选择和路由
2166 server . use ( ( req , res , next ) => {
22- if ( req . url . startsWith ( '/_next' ) || req . url . startsWith ( '/static' ) ) {
23- next ( ) ;
24- } else {
25- let locale = req . cookies . locale ;
26-
27- // 解析 URL 中的语言设置
28- const urlParts = req . path . split ( '/' ) ;
29- const urlLocale = SUPPORTED_LOCALES . includes ( urlParts [ 1 ] )
30- ? urlParts [ 1 ]
31- : null ;
32-
33- if ( ! locale ) {
34- // 如果没有 cookie,使用 URL 中的语言或浏览器偏好
35- const browserLocale = req . acceptsLanguages ( SUPPORTED_LOCALES ) ;
36- locale = urlLocale || browserLocale || FALLBACK_LOCALE ;
37-
38- // 如果浏览器语言不是中文,默认使用英语
39- if ( browserLocale && browserLocale !== 'zh' ) {
40- locale = FALLBACK_LOCALE ;
41- }
42- }
43-
44- // 确保 locale 是支持的语言之一
45- locale = SUPPORTED_LOCALES . includes ( locale ) ? locale : FALLBACK_LOCALE ;
46- if ( urlLocale ) {
47- // URL 中有语言前缀
48- if ( urlLocale !== locale ) {
49- // URL 语言与 cookie 不匹配,更新 locale
50- locale = urlLocale ;
51- }
52- if ( locale === DEFAULT_LOCALE ) {
53- // 默认语言不应该在 URL 中显示,重定向到无前缀的 URL
54- const newUrl = req . url . replace ( `/${ DEFAULT_LOCALE } ` , '' ) || '/' ;
55- return res . redirect ( 307 , newUrl ) ;
56- }
57- } else if ( locale !== DEFAULT_LOCALE ) {
58- // URL 中没有语言前缀,且不是默认语言,添加前缀并重定向
59- let newUrl = `/${ locale } ${ req . url } ` ;
60- if ( newUrl . endsWith ( '/' ) ) {
61- // 如果以 '/' 结尾,去掉末尾的 '/'
62- newUrl = newUrl . slice ( 0 , - 1 ) ;
63- }
64- return res . redirect ( 307 , newUrl ) ;
65- }
66-
67- // 设置或更新 cookie
68- res . cookie ( 'locale' , locale , {
69- maxAge : 365 * 24 * 60 * 60 * 1000 ,
70- } ) ;
67+ if ( isStaticRoute ( req . url ) ) {
68+ return next ( ) ;
69+ }
7170
72- req . locale = locale ;
71+ const urlLocale = getLocaleFromUrl ( req . path ) ;
72+ let locale = determineLocale ( req , urlLocale ) ;
7373
74- // // 处理尾部斜杠并重定向
75- // if (req.url.length > 1 && req.path.endsWith('/')) {
76- // const newUrl =
77- // req.path.slice(0, -1) + req.params
78- // return res.redirect(301, newUrl);
79- // }
74+ if ( handleRedirect ( req , res , locale , urlLocale ) ) {
75+ return ; // 如果发生重定向,立即返回
76+ }
8077
81- next ( ) ;
78+ // 检查响应头是否已经发送
79+ if ( canSetCookie ( req ) && ! res . headersSent ) {
80+ res . cookie ( 'locale' , locale , { maxAge : 365 * 24 * 60 * 60 * 1000 } ) ;
8281 }
82+ req . locale = locale ;
83+ next ( ) ;
8384 } ) ;
8485
85- // 处理所有其他请求
86- server . all ( '*' , ( req , res ) => {
87- return handle ( req , res ) ;
88- } ) ;
86+ server . all ( '*' , ( req , res ) => handle ( req , res ) ) ;
8987
9088 server . listen ( PORT , ( err ) => {
9189 if ( err ) throw err ;
0 commit comments