@@ -3,6 +3,7 @@ import { dirname, join, relative } from 'node:path'
3
3
4
4
import { glob } from 'fast-glob'
5
5
import type { EdgeFunctionDefinition as NextDefinition } from 'next/dist/build/webpack/plugins/middleware-plugin.js'
6
+ import { pathToRegexp } from 'path-to-regexp'
6
7
7
8
import { EDGE_HANDLER_NAME , PluginContext } from '../plugin-context.js'
8
9
@@ -37,6 +38,33 @@ const copyRuntime = async (ctx: PluginContext, handlerDirectory: string): Promis
37
38
)
38
39
}
39
40
41
+ /**
42
+ * When i18n is enabled the matchers assume that paths _always_ include the
43
+ * locale. We manually add an extra matcher for the original path without
44
+ * the locale to ensure that the edge function can handle it.
45
+ * We don't need to do this for data routes because they always have the locale.
46
+ */
47
+ const augmentMatchers = (
48
+ matchers : NextDefinition [ 'matchers' ] ,
49
+ ctx : PluginContext ,
50
+ ) : NextDefinition [ 'matchers' ] => {
51
+ if ( ! ctx . buildConfig . i18n ) {
52
+ return matchers
53
+ }
54
+ return matchers . flatMap ( ( matcher ) => {
55
+ if ( matcher . originalSource && matcher . locale !== false ) {
56
+ return [
57
+ matcher ,
58
+ {
59
+ ...matcher ,
60
+ regexp : pathToRegexp ( matcher . originalSource ) . source ,
61
+ } ,
62
+ ]
63
+ }
64
+ return matcher
65
+ } )
66
+ }
67
+
40
68
const writeHandlerFile = async ( ctx : PluginContext , { matchers, name } : NextDefinition ) => {
41
69
const nextConfig = ctx . buildConfig
42
70
const handlerName = getHandlerName ( { name } )
@@ -49,7 +77,10 @@ const writeHandlerFile = async (ctx: PluginContext, { matchers, name }: NextDefi
49
77
50
78
// Writing a file with the matchers that should trigger this function. We'll
51
79
// read this file from the function at runtime.
52
- await writeFile ( join ( handlerRuntimeDirectory , 'matchers.json' ) , JSON . stringify ( matchers ) )
80
+ await writeFile (
81
+ join ( handlerRuntimeDirectory , 'matchers.json' ) ,
82
+ JSON . stringify ( augmentMatchers ( matchers , ctx ) ) ,
83
+ )
53
84
54
85
// The config is needed by the edge function to match and normalize URLs. To
55
86
// avoid shipping and parsing a large file at runtime, let's strip it down to
@@ -140,9 +171,10 @@ const buildHandlerDefinition = (
140
171
const funName = name . endsWith ( 'middleware' )
141
172
? 'Next.js Middleware Handler'
142
173
: `Next.js Edge Handler: ${ page } `
143
- const cache = name . endsWith ( 'middleware' ) ? undefined : 'manual'
174
+ const cache = name . endsWith ( 'middleware' ) ? undefined : ( 'manual' as const )
144
175
const generator = `${ ctx . pluginName } @${ ctx . pluginVersion } `
145
- return matchers . map ( ( matcher ) => ( {
176
+
177
+ return augmentMatchers ( matchers , ctx ) . map ( ( matcher ) => ( {
146
178
function : fun ,
147
179
name : funName ,
148
180
pattern : matcher . regexp ,
0 commit comments