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,77 @@ const DEFAULT_LOCALE = 'zh';
1112const FALLBACK_LOCALE = 'en' ;
1213const SUPPORTED_LOCALES = [ 'zh' , 'en' ] ;
1314
15+ const isStaticRoute = ( url ) => url . startsWith ( '/_next' ) || url . startsWith ( '/static' ) ;
16+
17+ const getLocaleFromUrl = ( path ) => {
18+ const urlParts = path . split ( '/' ) ;
19+ return SUPPORTED_LOCALES . includes ( urlParts [ 1 ] ) ? urlParts [ 1 ] : null ;
20+ } ;
21+
22+ const determineLocale = ( req , urlLocale ) => {
23+ let locale = req . cookies . locale ;
24+ if ( ! locale ) {
25+ const browserLocale = req . acceptsLanguages ( SUPPORTED_LOCALES ) ;
26+ locale = urlLocale || browserLocale || FALLBACK_LOCALE ;
27+ if ( browserLocale && browserLocale !== 'zh' ) {
28+ locale = FALLBACK_LOCALE ;
29+ }
30+ }
31+ return SUPPORTED_LOCALES . includes ( locale ) ? locale : FALLBACK_LOCALE ;
32+ } ;
33+
34+ const handleRedirect = ( req , res , locale , urlLocale ) => {
35+ if ( urlLocale ) {
36+ if ( urlLocale !== locale ) {
37+ locale = urlLocale ;
38+ }
39+ if ( locale === DEFAULT_LOCALE ) {
40+ const newUrl = req . url . replace ( `/${ DEFAULT_LOCALE } ` , '' ) || '/' ;
41+ return res . redirect ( 307 , newUrl ) ;
42+ }
43+ } else if ( locale !== DEFAULT_LOCALE ) {
44+ let newUrl = `/${ locale } ${ req . url } ` ;
45+ if ( newUrl . endsWith ( '/' ) && newUrl . length > 1 ) {
46+ newUrl = newUrl . slice ( 0 , - 1 ) ;
47+ }
48+ return res . redirect ( 307 , newUrl ) ;
49+ }
50+ return false ;
51+ } ;
52+
53+ const canSetCookie = ( req ) => {
54+ // 检查请求头中是否有 'cookie' 字段
55+ return req . headers . cookie !== undefined ;
56+ } ;
57+
1458async function startServer ( ) {
1559 try {
1660 await app . prepare ( ) ;
1761 const server = express ( ) ;
1862 server . use ( cookieParser ( ) ) ;
63+ server . use ( pino ) ;
1964
20- // 中间件处理语言选择和路由
2165 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- } ) ;
66+ if ( isStaticRoute ( req . url ) ) {
67+ return next ( ) ;
68+ }
7169
72- req . locale = locale ;
70+ const urlLocale = getLocaleFromUrl ( req . path ) ;
71+ let locale = determineLocale ( req , urlLocale ) ;
7372
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- // }
73+ if ( handleRedirect ( req , res , locale , urlLocale ) ) {
74+ return ; // 如果发生重定向,立即返回
75+ }
8076
81- next ( ) ;
77+ // 检查响应头是否已经发送
78+ if ( canSetCookie ( req ) && ! res . headersSent ) {
79+ res . cookie ( 'locale' , locale , { maxAge : 365 * 24 * 60 * 60 * 1000 } ) ;
8280 }
81+ req . locale = locale ;
82+ next ( ) ;
8383 } ) ;
8484
85- // 处理所有其他请求
86- server . all ( '*' , ( req , res ) => {
87- return handle ( req , res ) ;
88- } ) ;
85+ server . all ( '*' , ( req , res ) => handle ( req , res ) ) ;
8986
9087 server . listen ( PORT , ( err ) => {
9188 if ( err ) throw err ;
@@ -97,4 +94,4 @@ async function startServer() {
9794 }
9895}
9996
100- startServer ( ) ;
97+ startServer ( ) ;
0 commit comments