1
1
import { stringify } from 'devalue'
2
2
import { defineI18nMiddleware } from '@intlify/h3'
3
- import { defineNitroPlugin , useRuntimeConfig , useStorage } from 'nitropack/runtime'
3
+ import { defineNitroPlugin , useStorage } from 'nitropack/runtime'
4
4
import { tryUseI18nContext , createI18nContext } from './context'
5
5
import { createUserLocaleDetector } from './utils/locale-detector'
6
6
import { pickNested } from './utils/messages-utils'
@@ -31,11 +31,9 @@ export function prefixable(currentLocale: string, defaultLocale: string): boolea
31
31
}
32
32
33
33
export default defineNitroPlugin ( async nitro => {
34
- const runtimeConfig = useRuntimeConfig ( )
35
-
36
34
const runtimeI18n = useRuntimeI18n ( )
37
35
const rootRedirect = resolveRootRedirect ( runtimeI18n . rootRedirect )
38
- const defaultLocale : string = runtimeI18n . defaultLocale || ''
36
+ const _defaultLocale : string = runtimeI18n . defaultLocale || ''
39
37
40
38
// clear cache for i18n handlers on startup
41
39
const cacheStorage = useStorage ( 'cache' )
@@ -88,12 +86,22 @@ export default defineNitroPlugin(async nitro => {
88
86
}
89
87
const baseUrlGetter = createBaseUrlGetter ( )
90
88
89
+ async function doRedirect ( event : H3Event , to : string , code : number ) {
90
+ // console.log(`[nuxt-i18n] Redirecting to ${to} with code ${code}`)
91
+ await sendRedirect ( event , to , code )
92
+ }
93
+
94
+ function doSetCookie ( event : H3Event , name : string , value : string , options ?: Record < string , any > ) {
95
+ // console.log(`[nuxt-i18n] Setting cookie ${name} to ${value}`)
96
+ setCookie ( event , name , value , { path : '/' , maxAge : 60 * 60 * 24 * 365 , sameSite : 'lax' , ...options } )
97
+ }
98
+
91
99
nitro . hooks . hook ( 'request' , async ( event : H3Event ) => {
92
100
if ( event . path === '/.well-known/appspecific/com.chrome.devtools.json' || event . path === '/favicon.ico' ) {
93
101
sendNoContent ( event )
94
102
return
95
103
}
96
- const options = await setupVueI18nOptions ( getDefaultLocaleForDomain ( getHost ( event ) ) || defaultLocale )
104
+ const options = await setupVueI18nOptions ( getDefaultLocaleForDomain ( getHost ( event ) ) || _defaultLocale )
97
105
const localeConfigs = createLocaleConfigs ( options . fallbackLocale )
98
106
const detector = useDetectors ( event , detectConfig )
99
107
@@ -103,6 +111,9 @@ export default defineNitroPlugin(async nitro => {
103
111
if ( detectConfig . enabled ) {
104
112
for ( const detected of detect ( detector , event . path ) ) {
105
113
if ( detected . locale && isSupportedLocale ( detected . locale ) ) {
114
+ // console.log(
115
+ // `[nuxt-i18n] Detected locale "${detected.locale}" from ${detected.source} for path "${event.path}"`
116
+ // )
106
117
locale = detected . locale
107
118
break
108
119
}
@@ -114,50 +125,58 @@ export default defineNitroPlugin(async nitro => {
114
125
const skipRedirectOnRoot = detectConfig . redirectOn === 'root' && event . path !== '/'
115
126
116
127
if ( rootRedirect && event . path === '/' ) {
117
- const domainForLocale = getDomainFromLocale ( event , locale )
118
- const defaultLocale =
119
- ( __MULTI_DOMAIN_LOCALES__ && domainForLocale && getDefaultLocaleForDomain ( getHost ( event ) ) ) ||
120
- runtimeI18n . defaultLocale
121
-
122
128
const rootRedirectIsLocalized = isSupportedLocale ( detector . route ( rootRedirect . path ) )
123
129
const resolvedPath = rootRedirectIsLocalized
124
130
? rootRedirect . path
125
131
: matchLocalized (
126
132
rootRedirect . path ,
127
- detectConfig . enabled ? locale || defaultLocale : defaultLocale ,
128
- defaultLocale
133
+ ( detectConfig . enabled && locale ) || options . defaultLocale ,
134
+ options . defaultLocale
129
135
)
130
136
if ( resolvedPath ) {
131
- setCookie ( event , 'i18n_redirected' , locale , { path : '/' , maxAge : 60 * 60 * 24 * 365 , sameSite : 'lax' } )
132
- const fullDestination = withoutTrailingSlash ( joinURL ( baseUrlGetter ( event , defaultLocale ) , resolvedPath ) )
133
- await sendRedirect ( event , fullDestination , rootRedirect . code || 302 )
137
+ const _locale = detectConfig . enabled ? locale || options . defaultLocale : options . defaultLocale
138
+ doSetCookie ( event , 'i18n_redirected' , _locale , { path : '/' , maxAge : 60 * 60 * 24 * 365 , sameSite : 'lax' } )
139
+ event . context . nuxtI18n . detectLocale = _locale
140
+ await doRedirect (
141
+ event ,
142
+ withoutTrailingSlash ( joinURL ( baseUrlGetter ( event , options . defaultLocale ) , resolvedPath ) ) ,
143
+ rootRedirect . code || 302
144
+ )
134
145
return
135
146
}
136
147
}
137
148
138
- if ( locale && detectConfig . enabled && ! skipRedirectOnPrefix && ! skipRedirectOnRoot ) {
149
+ // path locale exists and we skip redirect on prefix or root
150
+ // ensure cookie is set to avoid redirecting from nuxt context
151
+ if ( skipRedirectOnPrefix && pathLocale && isSupportedLocale ( pathLocale ) ) {
152
+ doSetCookie ( event , 'i18n_redirected' , pathLocale )
153
+ event . context . nuxtI18n . detectLocale = pathLocale
154
+ locale = pathLocale
155
+ } else if ( locale && detectConfig . enabled && ! skipRedirectOnPrefix && ! skipRedirectOnRoot ) {
139
156
event . context . nuxtI18n . detectRoute = event . path
140
157
141
- const domainForLocale = getDomainFromLocale ( event , locale )
142
- const defaultLocale =
143
- ( __MULTI_DOMAIN_LOCALES__ && domainForLocale && getDefaultLocaleForDomain ( getHost ( event ) ) ) ||
144
- runtimeI18n . defaultLocale
145
- const localeInPath = detector . route ( event . path )
146
- const entry = isSupportedLocale ( localeInPath ) ? event . path . slice ( localeInPath ! . length + 1 ) : event . path
147
- const resolvedPath = matchLocalized ( entry || '/' , locale , defaultLocale )
158
+ const entry = isSupportedLocale ( pathLocale ) ? event . path . slice ( pathLocale ! . length + 1 ) : event . path
159
+ const resolvedPath = matchLocalized ( entry || '/' , locale , options . defaultLocale )
148
160
if ( resolvedPath && resolvedPath !== event . path ) {
149
- setCookie ( event , 'i18n_redirected' , locale , { path : '/' , maxAge : 60 * 60 * 24 * 365 , sameSite : 'lax' } )
150
- const fullDestination = withoutTrailingSlash ( joinURL ( baseUrlGetter ( event , defaultLocale ) , resolvedPath ) )
151
- await sendRedirect ( event , fullDestination , 302 )
161
+ event . context . nuxtI18n . detectLocale = locale
162
+ doSetCookie ( event , 'i18n_redirected' , locale , { path : '/' , maxAge : 60 * 60 * 24 * 365 , sameSite : 'lax' } )
163
+ await doRedirect (
164
+ event ,
165
+ withoutTrailingSlash ( joinURL ( baseUrlGetter ( event , options . defaultLocale ) , resolvedPath ) ) ,
166
+ 302
167
+ )
152
168
return
153
169
}
154
170
}
155
171
156
172
if ( ! pathLocale && __I18N_STRATEGY__ === 'prefix' ) {
157
- const resolvedPath = matchLocalized ( event . path , defaultLocale , defaultLocale )
173
+ const resolvedPath = matchLocalized ( event . path , options . defaultLocale , options . defaultLocale )
158
174
if ( resolvedPath && resolvedPath !== event . path ) {
159
- const fullDestination = withoutTrailingSlash ( joinURL ( baseUrlGetter ( event , defaultLocale ) , resolvedPath ) )
160
- sendRedirect ( event , fullDestination , 302 )
175
+ await doRedirect (
176
+ event ,
177
+ withoutTrailingSlash ( joinURL ( baseUrlGetter ( event , options . defaultLocale ) , resolvedPath ) ) ,
178
+ 302
179
+ )
161
180
162
181
return
163
182
}
@@ -207,7 +226,7 @@ export default defineNitroPlugin(async nitro => {
207
226
208
227
// enable server-side translations and user locale-detector
209
228
if ( localeDetector != null ) {
210
- const options = await setupVueI18nOptions ( defaultLocale )
229
+ const options = await setupVueI18nOptions ( _defaultLocale )
211
230
const i18nMiddleware = defineI18nMiddleware ( {
212
231
...( options as CoreOptions ) ,
213
232
locale : createUserLocaleDetector ( options . locale , options . fallbackLocale )
0 commit comments