@korioinc/next-core 2.0.34 → 2.0.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/locale-switcher/index.d.ts.map +1 -1
- package/dist/components/locale-switcher/index.js +14 -0
- package/dist/i18n/routing.client.d.ts +2 -0
- package/dist/i18n/routing.client.d.ts.map +1 -0
- package/dist/i18n/routing.client.js +7 -0
- package/dist/i18n/routing.d.ts +5 -0
- package/dist/i18n/routing.d.ts.map +1 -1
- package/dist/i18n/routing.js +54 -15
- package/package.json +14 -14
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/locale-switcher/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/locale-switcher/index.tsx"],"names":[],"mappings":"AAeA,UAAU,mBAAmB;IAC3B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,EAAE,SAAS,EAAE,GAAE,mBAAwB,kDAiG7E"}
|
|
@@ -7,6 +7,7 @@ import { Menu, MenuButton, MenuItem, MenuItems, Transition } from '@headlessui/r
|
|
|
7
7
|
import { useLingui } from '@lingui/react';
|
|
8
8
|
import { allLanguages } from './language-options';
|
|
9
9
|
import { resolveVisibleLanguages } from './resolve-visible-languages';
|
|
10
|
+
import { setCookie } from 'cookies-next/client';
|
|
10
11
|
import linguiConfig from 'lingui.config';
|
|
11
12
|
export default function LocaleSwitcher({ languages } = {}) {
|
|
12
13
|
const router = useRouter();
|
|
@@ -16,6 +17,15 @@ export default function LocaleSwitcher({ languages } = {}) {
|
|
|
16
17
|
useEffect(() => {
|
|
17
18
|
setMounted(true);
|
|
18
19
|
}, []);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (!mounted || !i18n.locale) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
setCookie('NEXT_LOCALE', i18n.locale, {
|
|
25
|
+
path: '/',
|
|
26
|
+
sameSite: 'lax',
|
|
27
|
+
});
|
|
28
|
+
}, [mounted, i18n.locale]);
|
|
19
29
|
const availableLanguages = resolveVisibleLanguages({
|
|
20
30
|
allLanguages,
|
|
21
31
|
defaultLanguageCodes: linguiConfig.locales,
|
|
@@ -30,6 +40,10 @@ export default function LocaleSwitcher({ languages } = {}) {
|
|
|
30
40
|
const changeLanguage = (nextLocale) => {
|
|
31
41
|
const currentLocale = i18n.locale;
|
|
32
42
|
const newPath = getChangeLocalePath(pathname, currentLocale, nextLocale);
|
|
43
|
+
setCookie('NEXT_LOCALE', nextLocale, {
|
|
44
|
+
path: '/',
|
|
45
|
+
sameSite: 'lax',
|
|
46
|
+
});
|
|
33
47
|
router.replace(newPath);
|
|
34
48
|
router.refresh();
|
|
35
49
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routing.client.d.ts","sourceRoot":"","sources":["../../src/i18n/routing.client.ts"],"names":[],"mappings":"AAMA,wBAAgB,eAAe,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,KAAK,MAAM,CAIlE"}
|
package/dist/i18n/routing.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare function getLocales(): string[];
|
|
|
8
8
|
* Get default locale
|
|
9
9
|
*/
|
|
10
10
|
export declare function getDefaultLocale(): string;
|
|
11
|
+
export declare function getPathLocale(pathname: string): string | undefined;
|
|
11
12
|
export declare function handleLocaleRouting(request: NextRequest): NextResponse<unknown>;
|
|
12
13
|
export declare function getRequestLocale(requestHeaders: Headers): string;
|
|
13
14
|
export declare function getCookieLocale(requestHeaders: Headers, pathname?: string): string | undefined;
|
|
@@ -18,6 +19,10 @@ export declare function getPathname({ locale, href }: {
|
|
|
18
19
|
}): string;
|
|
19
20
|
export declare function getLanguageAlternates(pathname?: string): Record<string, string>;
|
|
20
21
|
export declare function getCurrentPathname(): Promise<string>;
|
|
22
|
+
export declare function getCurrentPathLocale(): Promise<string | undefined>;
|
|
23
|
+
export declare function getPathLocalePathname(pathname: string, href?: string | null): string;
|
|
24
|
+
export declare function toLocalePath(pathname: string, href?: string | null): string;
|
|
25
|
+
export declare function getLocalePathname(href: string): Promise<string>;
|
|
21
26
|
export declare function getCurrentSearchParams(): Promise<URLSearchParams>;
|
|
22
27
|
export declare function getDefaultPathname(): Promise<string>;
|
|
23
28
|
export declare function getCurrentLanguageAlternates(): Promise<Record<string, string>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/i18n/routing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,KAAK,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/i18n/routing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,KAAK,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAoC7D;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,EAAE,CAErC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AA4BD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAElE;AAiFD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,WAAW,yBA2EvD;AAED,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,OAAO,GAAG,MAAM,CAShE;AAED,wBAAgB,eAAe,CAAC,cAAc,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAW9F;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAevG;AAED,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,UAY7E;AAsBD,wBAAgB,qBAAqB,CAAC,QAAQ,GAAE,MAAY,0BAwB3D;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAK1D;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAKxE;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAuBpF;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAE3E;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAKrE;AAED,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,eAAe,CAAC,CAMvE;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAU1D;AAED,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAIpF;AAED,KAAK,aAAa,GACd,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GAC7C,eAAe,GACf,uBAAuB,GACvB,SAAS,CAAC;AAiDd,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,MAAM,CAErF;AAED,wBAAsB,UAAU,CAAC,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAIxE;AAED,wBAAsB,2BAA2B,IAAI,OAAO,CAAC,MAAM,CAAC,CAKnE"}
|
package/dist/i18n/routing.js
CHANGED
|
@@ -19,11 +19,10 @@ const DEFAULT_FALLBACK = () => {
|
|
|
19
19
|
const LOCALE_COOKIE_NAME = 'NEXT_LOCALE';
|
|
20
20
|
const LOCALE_PREFIX = 'as-needed';
|
|
21
21
|
const PATHNAME_HEADER_NAME = 'x-pathname';
|
|
22
|
+
const PATH_LOCALE_HEADER_NAME = 'x-path-locale';
|
|
22
23
|
const SEARCH_PARAMS_HEADER_NAME = 'x-search-params';
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
response.headers.set(SEARCH_PARAMS_HEADER_NAME, search.replace(/^\?/, ''));
|
|
26
|
-
return response;
|
|
24
|
+
const isDocumentRequest = (request) => {
|
|
25
|
+
return request.headers.get('accept')?.includes('text/html') || false;
|
|
27
26
|
};
|
|
28
27
|
/**
|
|
29
28
|
* Get all available locales
|
|
@@ -57,6 +56,16 @@ const getPathLocaleSegment = (pathname) => {
|
|
|
57
56
|
const pathMatch = pathname.match(/^\/([^\\/]+)(?:\/|$)/);
|
|
58
57
|
return pathMatch?.[1];
|
|
59
58
|
};
|
|
59
|
+
export function getPathLocale(pathname) {
|
|
60
|
+
return getCanonicalLocale(getPathLocaleSegment(pathname));
|
|
61
|
+
}
|
|
62
|
+
const setRoutingHeaders = (response, pathname, search) => {
|
|
63
|
+
const pathLocale = getCanonicalLocale(getPathLocaleSegment(pathname));
|
|
64
|
+
response.headers.set(PATHNAME_HEADER_NAME, pathname);
|
|
65
|
+
response.headers.set(PATH_LOCALE_HEADER_NAME, pathLocale || '');
|
|
66
|
+
response.headers.set(SEARCH_PARAMS_HEADER_NAME, search.replace(/^\?/, ''));
|
|
67
|
+
return response;
|
|
68
|
+
};
|
|
60
69
|
const replacePathLocale = (pathname, locale) => {
|
|
61
70
|
return pathname.replace(/^\/[^\\/]+(?=\/|$)/, `/${locale}`);
|
|
62
71
|
};
|
|
@@ -107,6 +116,7 @@ export function handleLocaleRouting(request) {
|
|
|
107
116
|
const localeCookie = request.cookies.get(LOCALE_COOKIE_NAME);
|
|
108
117
|
const cookieLocale = getCanonicalLocale(localeCookie?.value);
|
|
109
118
|
const defaultFallback = DEFAULT_FALLBACK();
|
|
119
|
+
const documentRequest = isDocumentRequest(request);
|
|
110
120
|
// 1. URL에서 locale 감지
|
|
111
121
|
const pathLocaleSegment = getPathLocaleSegment(pathname);
|
|
112
122
|
const pathLocale = getCanonicalLocale(pathLocaleSegment);
|
|
@@ -114,7 +124,7 @@ export function handleLocaleRouting(request) {
|
|
|
114
124
|
// 2. URL에 locale이 포함된 경우
|
|
115
125
|
if (pathnameHasLocale) {
|
|
116
126
|
if (pathLocaleSegment !== pathLocale) {
|
|
117
|
-
return redirectWithLocale(request, pathname, pathLocale, cookieLocale !== pathLocale);
|
|
127
|
+
return redirectWithLocale(request, pathname, pathLocale, cookieLocale !== pathLocale && documentRequest);
|
|
118
128
|
}
|
|
119
129
|
// 이미 path에 locale이 있을 때
|
|
120
130
|
const response = setRoutingHeaders(NextResponse.next(), pathname, request.nextUrl.search);
|
|
@@ -122,9 +132,12 @@ export function handleLocaleRouting(request) {
|
|
|
122
132
|
if (cookieLocale !== pathLocale) {
|
|
123
133
|
// 기본 locale인 경우 URL에서 제거
|
|
124
134
|
if (LOCALE_PREFIX === 'as-needed' && pathLocale === defaultFallback) {
|
|
125
|
-
return redirectWithoutLocale(request, pathname, pathLocale,
|
|
135
|
+
return redirectWithoutLocale(request, pathname, pathLocale, documentRequest);
|
|
126
136
|
}
|
|
127
137
|
// 다른 locale의 경우 쿠키 설정
|
|
138
|
+
if (!documentRequest) {
|
|
139
|
+
return response;
|
|
140
|
+
}
|
|
128
141
|
return setCookie(response, pathLocale);
|
|
129
142
|
}
|
|
130
143
|
// locale은 같지만 기본 locale이고 as-needed 설정인 경우
|
|
@@ -154,7 +167,7 @@ export function handleLocaleRouting(request) {
|
|
|
154
167
|
request.nextUrl.pathname = newPathname;
|
|
155
168
|
const response = setRoutingHeaders(NextResponse.redirect(request.nextUrl), newPathname, request.nextUrl.search);
|
|
156
169
|
// 쿠키가 없는 경우 설정
|
|
157
|
-
if (localeCookie?.value === undefined) {
|
|
170
|
+
if (localeCookie?.value === undefined && documentRequest) {
|
|
158
171
|
setCookie(response, locale);
|
|
159
172
|
}
|
|
160
173
|
return response;
|
|
@@ -178,25 +191,20 @@ export function getCookieLocale(requestHeaders, pathname) {
|
|
|
178
191
|
return getCanonicalLocale(getPathLocaleSegment(pathname));
|
|
179
192
|
}
|
|
180
193
|
export function getChangeLocalePath(pathname, currentLocale, nextLocale) {
|
|
181
|
-
// Create the new path based on whether the current path has a locale segment or not
|
|
182
194
|
let pathNameWithoutLocale;
|
|
183
|
-
// Check if pathname starts with current locale
|
|
184
195
|
if (pathname === `/${currentLocale}` || pathname.startsWith(`/${currentLocale}/`)) {
|
|
185
|
-
|
|
186
|
-
pathNameWithoutLocale = pathname.slice(currentLocale.length + 1); // Remove /locale part
|
|
196
|
+
pathNameWithoutLocale = pathname.slice(currentLocale.length + 1);
|
|
187
197
|
if (pathNameWithoutLocale.startsWith('/')) {
|
|
188
|
-
pathNameWithoutLocale = pathNameWithoutLocale.slice(1);
|
|
198
|
+
pathNameWithoutLocale = pathNameWithoutLocale.slice(1);
|
|
189
199
|
}
|
|
190
200
|
}
|
|
191
201
|
else if (pathname === '/') {
|
|
192
|
-
// Root path
|
|
193
202
|
pathNameWithoutLocale = '';
|
|
194
203
|
}
|
|
195
204
|
else {
|
|
196
|
-
// Path doesn't have locale prefix: /something
|
|
197
205
|
pathNameWithoutLocale = pathname.startsWith('/') ? pathname.slice(1) : pathname;
|
|
198
206
|
}
|
|
199
|
-
return `/${nextLocale}${pathNameWithoutLocale ?
|
|
207
|
+
return `/${nextLocale}${pathNameWithoutLocale ? `/${pathNameWithoutLocale}` : ''}`;
|
|
200
208
|
}
|
|
201
209
|
export function getPathname({ locale, href }) {
|
|
202
210
|
const defaultFallback = DEFAULT_FALLBACK();
|
|
@@ -251,6 +259,37 @@ export async function getCurrentPathname() {
|
|
|
251
259
|
const headersList = await headers();
|
|
252
260
|
return headersList.get(PATHNAME_HEADER_NAME) || '';
|
|
253
261
|
}
|
|
262
|
+
export async function getCurrentPathLocale() {
|
|
263
|
+
const { headers } = await import('next/headers');
|
|
264
|
+
const headersList = await headers();
|
|
265
|
+
return getCanonicalLocale(headersList.get(PATH_LOCALE_HEADER_NAME) || undefined);
|
|
266
|
+
}
|
|
267
|
+
export function getPathLocalePathname(pathname, href) {
|
|
268
|
+
if (href == null || href === '#') {
|
|
269
|
+
return '#';
|
|
270
|
+
}
|
|
271
|
+
const normalizedHref = href === '' ? '/' : href.startsWith('/') ? href : `/${href}`;
|
|
272
|
+
const hrefLocale = getPathLocale(normalizedHref);
|
|
273
|
+
if (hrefLocale) {
|
|
274
|
+
return normalizedHref;
|
|
275
|
+
}
|
|
276
|
+
const pathLocale = getPathLocale(pathname);
|
|
277
|
+
if (!pathLocale) {
|
|
278
|
+
return normalizedHref;
|
|
279
|
+
}
|
|
280
|
+
if (normalizedHref === '/') {
|
|
281
|
+
return `/${pathLocale}`;
|
|
282
|
+
}
|
|
283
|
+
return `/${pathLocale}${normalizedHref}`;
|
|
284
|
+
}
|
|
285
|
+
export function toLocalePath(pathname, href) {
|
|
286
|
+
return getPathLocalePathname(pathname, href);
|
|
287
|
+
}
|
|
288
|
+
export async function getLocalePathname(href) {
|
|
289
|
+
const pathLocale = await getCurrentPathLocale();
|
|
290
|
+
const currentPathname = pathLocale ? `/${pathLocale}` : '/';
|
|
291
|
+
return getPathLocalePathname(currentPathname, href);
|
|
292
|
+
}
|
|
254
293
|
export async function getCurrentSearchParams() {
|
|
255
294
|
const { headers } = await import('next/headers');
|
|
256
295
|
const headersList = await headers();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@korioinc/next-core",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.43",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./ads": {
|
|
@@ -72,29 +72,29 @@
|
|
|
72
72
|
"LICENSE"
|
|
73
73
|
],
|
|
74
74
|
"devDependencies": {
|
|
75
|
-
"@headlessui/react": "^2.2.
|
|
76
|
-
"@lingui/conf": "^5.9.
|
|
77
|
-
"@lingui/core": "^5.9.
|
|
78
|
-
"@lingui/react": "^5.9.
|
|
75
|
+
"@headlessui/react": "^2.2.10",
|
|
76
|
+
"@lingui/conf": "^5.9.5",
|
|
77
|
+
"@lingui/core": "^5.9.5",
|
|
78
|
+
"@lingui/react": "^5.9.5",
|
|
79
79
|
"@tailwindcss/typography": "^0.5.19",
|
|
80
80
|
"@types/negotiator": "^0.6.4",
|
|
81
|
-
"@types/node": "^25.
|
|
81
|
+
"@types/node": "^25.6.0",
|
|
82
82
|
"@types/react": "^19.2.14",
|
|
83
83
|
"@types/react-dom": "^19.2.3",
|
|
84
|
-
"eslint": "^10.
|
|
85
|
-
"jsdom": "^29.0.
|
|
86
|
-
"react": "^19.2.
|
|
87
|
-
"react-dom": "^19.2.
|
|
84
|
+
"eslint": "^10.2.0",
|
|
85
|
+
"jsdom": "^29.0.2",
|
|
86
|
+
"react": "^19.2.5",
|
|
87
|
+
"react-dom": "^19.2.5",
|
|
88
88
|
"tailwindcss": "^4.2.2",
|
|
89
89
|
"tsc-alias": "^1.8.16",
|
|
90
90
|
"tw-animate-css": "^1.4.0",
|
|
91
91
|
"typescript": "^6.0.2",
|
|
92
|
-
"vitest": "^4.1.
|
|
93
|
-
"@korioinc/next-configs": "2.0.
|
|
92
|
+
"vitest": "^4.1.4",
|
|
93
|
+
"@korioinc/next-configs": "2.0.43"
|
|
94
94
|
},
|
|
95
95
|
"dependencies": {
|
|
96
96
|
"@floating-ui/react": "^0.27.19",
|
|
97
|
-
"@formatjs/intl-localematcher": "^0.8.
|
|
97
|
+
"@formatjs/intl-localematcher": "^0.8.3",
|
|
98
98
|
"clsx": "^2.1.1",
|
|
99
99
|
"cookies-next": "^6.1.1",
|
|
100
100
|
"cosmiconfig": "^9.0.1",
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"schema-dts": "^2.0.0",
|
|
106
106
|
"tailwind-merge": "^3.5.0",
|
|
107
107
|
"valtio": "^2.3.1",
|
|
108
|
-
"@korioinc/next-conf": "2.0.
|
|
108
|
+
"@korioinc/next-conf": "2.0.43"
|
|
109
109
|
},
|
|
110
110
|
"publishConfig": {
|
|
111
111
|
"access": "public",
|