-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmiddleware.ts
129 lines (112 loc) · 4.35 KB
/
middleware.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { i18n } from './i18n-config';
import { match as matchLocale } from '@formatjs/intl-localematcher';
import Negotiator from 'negotiator';
function getLocale(request: NextRequest): string | undefined {
// Negotiator expects plain object so we need to transform headers
const negotiatorHeaders: Record<string, string> = {};
request.headers.forEach((value, key) => (negotiatorHeaders[key] = value));
// Use negotiator and intl-localematcher to get best locale
let languages = new Negotiator({ headers: negotiatorHeaders }).languages();
// @ts-ignore locales are readonly
const locales: string[] = i18n.locales;
return matchLocale(languages, locales, i18n.defaultLocale);
}
// Redirect works on auto mode, for lang switch manually use cookies to set desired locale and skip locale detection as long as cookie is there
export function middleware(request: NextRequest) {
const { pathname, searchParams, hostname } = request.nextUrl;
if (
['.json', '.ico', '.xml', '.jpg', '.svg', '.png', '.jpg'].some((e) =>
pathname.endsWith(e)
)
) {
// Probably some public folder stuff, let it pass
return NextResponse.next();
}
const locale = getLocale(request);
const usedDomain = i18n.domains.find((domain) => domain.domain === hostname);
if (process.env.DEBUG) {
console.log(
`Request locale: ${locale}, used domain: ${
usedDomain?.domain || 'unknown'
}, path: ${pathname}`
);
}
if (usedDomain && usedDomain.locales.includes(locale!)) {
if (
pathname.startsWith(`/${usedDomain.defaultLocale}/`) ||
pathname === `/${usedDomain.defaultLocale}`
) {
const newUrl = new URL(
pathname.replace(
`/${usedDomain.defaultLocale}`,
pathname === `/${usedDomain.defaultLocale}` ? '/' : ''
),
request.url
);
newUrl.search = searchParams.toString();
return NextResponse.redirect(newUrl, { status: 301 });
}
const pathnameIsMissingLocale = usedDomain.locales.every(
(locale) =>
!pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
);
if (pathnameIsMissingLocale) {
if (locale !== usedDomain.defaultLocale) {
const newUrl = new URL(`/${locale}${pathname}`, request.url);
newUrl.search = searchParams.toString();
return NextResponse.redirect(newUrl, { status: 302 });
} else {
const newUrl = new URL(
`/${usedDomain.defaultLocale}${pathname}`,
request.url
);
newUrl.search = searchParams.toString();
return NextResponse.rewrite(newUrl);
}
}
} else {
if (usedDomain) {
const possibleDomains = i18n.domains
.filter((e) => e.locales.includes(locale!))
.sort((a, b) => (b.defaultLocale === locale ? 1 : -1));
if (possibleDomains.length > 0) {
const useFirst = possibleDomains[0];
if (locale === useFirst.defaultLocale) {
console.log(pathname);
const newUrl = new URL(`${pathname}`, `https://${useFirst.domain}`);
newUrl.search = searchParams.toString();
return NextResponse.redirect(newUrl, { status: 302 });
} else {
const newUrl = new URL(
`/${locale}${pathname}`,
`https://${useFirst.domain}`
);
newUrl.search = searchParams.toString();
return NextResponse.redirect(newUrl, { status: 302 });
}
} else {
console.log('no domain found');
// No domain found for this locale, return general default locale
const newUrl = new URL(`/${locale}${pathname}`, request.url);
newUrl.search = searchParams.toString();
return NextResponse.rewrite(newUrl);
}
} else {
const pathnameIsMissingLocale = i18n.locales.every(
(locale) =>
!pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
);
if (pathnameIsMissingLocale) {
// No domain found for this locale, return site since domain is not known for general locale
const newUrl = new URL(`/${locale}${pathname}`, request.url);
newUrl.search = searchParams.toString();
return NextResponse.rewrite(newUrl);
}
}
}
}
export const config = {
matcher: ['/((?!api|_next/static|_next/image|assets|favicon.ico|sw.js).*)'],
};