2
2
const express = require ( 'express' ) ;
3
3
const next = require ( 'next' ) ;
4
4
const cookieParser = require ( 'cookie-parser' ) ;
5
+ const pino = require ( 'pino-http' ) ( ) ;
5
6
6
7
const app = next ( { dev : false } ) ;
7
8
const handle = app . getRequestHandler ( ) ;
@@ -11,81 +12,77 @@ const DEFAULT_LOCALE = 'zh';
11
12
const FALLBACK_LOCALE = 'en' ;
12
13
const SUPPORTED_LOCALES = [ 'zh' , 'en' ] ;
13
14
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
+
14
58
async function startServer ( ) {
15
59
try {
16
60
await app . prepare ( ) ;
17
61
const server = express ( ) ;
18
62
server . use ( cookieParser ( ) ) ;
63
+ server . use ( pino ) ;
19
64
20
- // 中间件处理语言选择和路由
21
65
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
+ }
71
69
72
- req . locale = locale ;
70
+ const urlLocale = getLocaleFromUrl ( req . path ) ;
71
+ let locale = determineLocale ( req , urlLocale ) ;
73
72
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
+ }
80
76
81
- next ( ) ;
77
+ // 检查响应头是否已经发送
78
+ if ( canSetCookie ( req ) && ! res . headersSent ) {
79
+ res . cookie ( 'locale' , locale , { maxAge : 365 * 24 * 60 * 60 * 1000 } ) ;
82
80
}
81
+ req . locale = locale ;
82
+ next ( ) ;
83
83
} ) ;
84
84
85
- // 处理所有其他请求
86
- server . all ( '*' , ( req , res ) => {
87
- return handle ( req , res ) ;
88
- } ) ;
85
+ server . all ( '*' , ( req , res ) => handle ( req , res ) ) ;
89
86
90
87
server . listen ( PORT , ( err ) => {
91
88
if ( err ) throw err ;
@@ -97,4 +94,4 @@ async function startServer() {
97
94
}
98
95
}
99
96
100
- startServer ( ) ;
97
+ startServer ( ) ;
0 commit comments