inline-i18n-multi-next 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,45 @@
1
+ import { NextResponse } from 'next/server';
2
+
3
+ // src/middleware.ts
4
+ function createI18nMiddleware(config) {
5
+ const {
6
+ locales,
7
+ defaultLocale,
8
+ localeDetection = true,
9
+ cookieName = "NEXT_LOCALE"
10
+ } = config;
11
+ return function middleware(request) {
12
+ const { pathname } = request.nextUrl;
13
+ const pathnameHasLocale = locales.some(
14
+ (locale2) => pathname.startsWith(`/${locale2}/`) || pathname === `/${locale2}`
15
+ );
16
+ if (pathnameHasLocale) {
17
+ const localeFromPath = pathname.split("/")[1] ?? defaultLocale;
18
+ const response2 = NextResponse.next();
19
+ response2.headers.set("x-locale", localeFromPath);
20
+ return response2;
21
+ }
22
+ let locale = defaultLocale;
23
+ const cookieLocale = request.cookies.get(cookieName)?.value;
24
+ if (cookieLocale && locales.includes(cookieLocale)) {
25
+ locale = cookieLocale;
26
+ } else if (localeDetection) {
27
+ const acceptLanguage = request.headers.get("accept-language");
28
+ if (acceptLanguage) {
29
+ const parts = acceptLanguage.split(",")[0]?.split("-");
30
+ const preferredLocale = parts?.[0];
31
+ if (preferredLocale && locales.includes(preferredLocale)) {
32
+ locale = preferredLocale;
33
+ }
34
+ }
35
+ }
36
+ request.nextUrl.pathname = `/${locale}${pathname}`;
37
+ const response = NextResponse.redirect(request.nextUrl);
38
+ response.headers.set("x-locale", locale);
39
+ return response;
40
+ };
41
+ }
42
+
43
+ export { createI18nMiddleware };
44
+ //# sourceMappingURL=chunk-7RR34VBV.mjs.map
45
+ //# sourceMappingURL=chunk-7RR34VBV.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/middleware.ts"],"names":["locale","response"],"mappings":";;;AA4BO,SAAS,qBAAqB,MAAA,EAA8B;AACjE,EAAA,MAAM;AAAA,IACJ,OAAA;AAAA,IACA,aAAA;AAAA,IACA,eAAA,GAAkB,IAAA;AAAA,IAClB,UAAA,GAAa;AAAA,GACf,GAAI,MAAA;AAEJ,EAAA,OAAO,SAAS,WAAW,OAAA,EAAsB;AAC/C,IAAA,MAAM,EAAE,QAAA,EAAS,GAAI,OAAA,CAAQ,OAAA;AAG7B,IAAA,MAAM,oBAAoB,OAAA,CAAQ,IAAA;AAAA,MAChC,CAACA,OAAAA,KAAW,QAAA,CAAS,UAAA,CAAW,CAAA,CAAA,EAAIA,OAAM,CAAA,CAAA,CAAG,CAAA,IAAK,QAAA,KAAa,CAAA,CAAA,EAAIA,OAAM,CAAA;AAAA,KAC3E;AAEA,IAAA,IAAI,iBAAA,EAAmB;AAErB,MAAA,MAAM,iBAAiB,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,IAAK,aAAA;AACjD,MAAA,MAAMC,SAAAA,GAAW,aAAa,IAAA,EAAK;AACnC,MAAAA,SAAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,UAAA,EAAY,cAAc,CAAA;AAC/C,MAAA,OAAOA,SAAAA;AAAA,IACT;AAGA,IAAA,IAAI,MAAA,GAAS,aAAA;AAGb,IAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,UAAU,CAAA,EAAG,KAAA;AACtD,IAAA,IAAI,YAAA,IAAgB,OAAA,CAAQ,QAAA,CAAS,YAAY,CAAA,EAAG;AAClD,MAAA,MAAA,GAAS,YAAA;AAAA,IACX,WAES,eAAA,EAAiB;AACxB,MAAA,MAAM,cAAA,GAAiB,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,iBAAiB,CAAA;AAC5D,MAAA,IAAI,cAAA,EAAgB;AAClB,QAAA,MAAM,KAAA,GAAQ,eAAe,KAAA,CAAM,GAAG,EAAE,CAAC,CAAA,EAAG,MAAM,GAAG,CAAA;AACrD,QAAA,MAAM,eAAA,GAAkB,QAAQ,CAAC,CAAA;AACjC,QAAA,IAAI,eAAA,IAAmB,OAAA,CAAQ,QAAA,CAAS,eAAyB,CAAA,EAAG;AAClE,UAAA,MAAA,GAAS,eAAA;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAGA,IAAA,OAAA,CAAQ,OAAA,CAAQ,QAAA,GAAW,CAAA,CAAA,EAAI,MAAM,GAAG,QAAQ,CAAA,CAAA;AAChD,IAAA,MAAM,QAAA,GAAW,YAAA,CAAa,QAAA,CAAS,OAAA,CAAQ,OAAO,CAAA;AACtD,IAAA,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,UAAA,EAAY,MAAM,CAAA;AAEvC,IAAA,OAAO,QAAA;AAAA,EACT,CAAA;AACF","file":"chunk-7RR34VBV.mjs","sourcesContent":["import { NextRequest, NextResponse } from 'next/server'\nimport type { Locale } from 'inline-i18n-multi'\n\ninterface I18nMiddlewareConfig {\n /**\n * Supported locales\n */\n locales: readonly Locale[] | Locale[]\n /**\n * Default locale when no match found\n */\n defaultLocale: Locale\n /**\n * Enable automatic locale detection from Accept-Language header\n * @default true\n */\n localeDetection?: boolean\n /**\n * Cookie name for storing user's locale preference\n * @default 'NEXT_LOCALE'\n */\n cookieName?: string\n}\n\n/**\n * Create Next.js middleware for i18n routing\n * @param config - Middleware configuration\n */\nexport function createI18nMiddleware(config: I18nMiddlewareConfig) {\n const {\n locales,\n defaultLocale,\n localeDetection = true,\n cookieName = 'NEXT_LOCALE',\n } = config\n\n return function middleware(request: NextRequest) {\n const { pathname } = request.nextUrl\n\n // check if pathname already has locale prefix\n const pathnameHasLocale = locales.some(\n (locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`\n )\n\n if (pathnameHasLocale) {\n // extract locale from pathname and set header\n const localeFromPath = pathname.split('/')[1] ?? defaultLocale\n const response = NextResponse.next()\n response.headers.set('x-locale', localeFromPath)\n return response\n }\n\n // determine locale\n let locale = defaultLocale\n\n // 1. check cookie first\n const cookieLocale = request.cookies.get(cookieName)?.value\n if (cookieLocale && locales.includes(cookieLocale)) {\n locale = cookieLocale\n }\n // 2. detect from Accept-Language header\n else if (localeDetection) {\n const acceptLanguage = request.headers.get('accept-language')\n if (acceptLanguage) {\n const parts = acceptLanguage.split(',')[0]?.split('-')\n const preferredLocale = parts?.[0]\n if (preferredLocale && locales.includes(preferredLocale as Locale)) {\n locale = preferredLocale as Locale\n }\n }\n }\n\n // redirect to locale-prefixed path\n request.nextUrl.pathname = `/${locale}${pathname}`\n const response = NextResponse.redirect(request.nextUrl)\n response.headers.set('x-locale', locale)\n\n return response\n }\n}\n\nexport type { I18nMiddlewareConfig }\n"]}
@@ -0,0 +1 @@
1
+ export { Dictionaries, Dictionary, Locale, LocaleProvider, PluralRules, T, TranslationVars, Translations, clearDictionaries, en_de, en_es, en_fr, en_ja, en_zh, getDictionary, getLoadedLocales, getLocale, hasTranslation, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadDictionaries, loadDictionary, setLocale, t, useLocale, useT, zh_es } from 'inline-i18n-multi-react';
@@ -0,0 +1 @@
1
+ export { Dictionaries, Dictionary, Locale, LocaleProvider, PluralRules, T, TranslationVars, Translations, clearDictionaries, en_de, en_es, en_fr, en_ja, en_zh, getDictionary, getLoadedLocales, getLocale, hasTranslation, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadDictionaries, loadDictionary, setLocale, t, useLocale, useT, zh_es } from 'inline-i18n-multi-react';
package/dist/client.js ADDED
@@ -0,0 +1,116 @@
1
+ 'use strict';
2
+
3
+ var inlineI18nMultiReact = require('inline-i18n-multi-react');
4
+
5
+
6
+
7
+ Object.defineProperty(exports, "LocaleProvider", {
8
+ enumerable: true,
9
+ get: function () { return inlineI18nMultiReact.LocaleProvider; }
10
+ });
11
+ Object.defineProperty(exports, "T", {
12
+ enumerable: true,
13
+ get: function () { return inlineI18nMultiReact.T; }
14
+ });
15
+ Object.defineProperty(exports, "clearDictionaries", {
16
+ enumerable: true,
17
+ get: function () { return inlineI18nMultiReact.clearDictionaries; }
18
+ });
19
+ Object.defineProperty(exports, "en_de", {
20
+ enumerable: true,
21
+ get: function () { return inlineI18nMultiReact.en_de; }
22
+ });
23
+ Object.defineProperty(exports, "en_es", {
24
+ enumerable: true,
25
+ get: function () { return inlineI18nMultiReact.en_es; }
26
+ });
27
+ Object.defineProperty(exports, "en_fr", {
28
+ enumerable: true,
29
+ get: function () { return inlineI18nMultiReact.en_fr; }
30
+ });
31
+ Object.defineProperty(exports, "en_ja", {
32
+ enumerable: true,
33
+ get: function () { return inlineI18nMultiReact.en_ja; }
34
+ });
35
+ Object.defineProperty(exports, "en_zh", {
36
+ enumerable: true,
37
+ get: function () { return inlineI18nMultiReact.en_zh; }
38
+ });
39
+ Object.defineProperty(exports, "getDictionary", {
40
+ enumerable: true,
41
+ get: function () { return inlineI18nMultiReact.getDictionary; }
42
+ });
43
+ Object.defineProperty(exports, "getLoadedLocales", {
44
+ enumerable: true,
45
+ get: function () { return inlineI18nMultiReact.getLoadedLocales; }
46
+ });
47
+ Object.defineProperty(exports, "getLocale", {
48
+ enumerable: true,
49
+ get: function () { return inlineI18nMultiReact.getLocale; }
50
+ });
51
+ Object.defineProperty(exports, "hasTranslation", {
52
+ enumerable: true,
53
+ get: function () { return inlineI18nMultiReact.hasTranslation; }
54
+ });
55
+ Object.defineProperty(exports, "it", {
56
+ enumerable: true,
57
+ get: function () { return inlineI18nMultiReact.it; }
58
+ });
59
+ Object.defineProperty(exports, "it_de", {
60
+ enumerable: true,
61
+ get: function () { return inlineI18nMultiReact.it_de; }
62
+ });
63
+ Object.defineProperty(exports, "it_es", {
64
+ enumerable: true,
65
+ get: function () { return inlineI18nMultiReact.it_es; }
66
+ });
67
+ Object.defineProperty(exports, "it_fr", {
68
+ enumerable: true,
69
+ get: function () { return inlineI18nMultiReact.it_fr; }
70
+ });
71
+ Object.defineProperty(exports, "it_ja", {
72
+ enumerable: true,
73
+ get: function () { return inlineI18nMultiReact.it_ja; }
74
+ });
75
+ Object.defineProperty(exports, "it_zh", {
76
+ enumerable: true,
77
+ get: function () { return inlineI18nMultiReact.it_zh; }
78
+ });
79
+ Object.defineProperty(exports, "ja_es", {
80
+ enumerable: true,
81
+ get: function () { return inlineI18nMultiReact.ja_es; }
82
+ });
83
+ Object.defineProperty(exports, "ja_zh", {
84
+ enumerable: true,
85
+ get: function () { return inlineI18nMultiReact.ja_zh; }
86
+ });
87
+ Object.defineProperty(exports, "loadDictionaries", {
88
+ enumerable: true,
89
+ get: function () { return inlineI18nMultiReact.loadDictionaries; }
90
+ });
91
+ Object.defineProperty(exports, "loadDictionary", {
92
+ enumerable: true,
93
+ get: function () { return inlineI18nMultiReact.loadDictionary; }
94
+ });
95
+ Object.defineProperty(exports, "setLocale", {
96
+ enumerable: true,
97
+ get: function () { return inlineI18nMultiReact.setLocale; }
98
+ });
99
+ Object.defineProperty(exports, "t", {
100
+ enumerable: true,
101
+ get: function () { return inlineI18nMultiReact.t; }
102
+ });
103
+ Object.defineProperty(exports, "useLocale", {
104
+ enumerable: true,
105
+ get: function () { return inlineI18nMultiReact.useLocale; }
106
+ });
107
+ Object.defineProperty(exports, "useT", {
108
+ enumerable: true,
109
+ get: function () { return inlineI18nMultiReact.useT; }
110
+ });
111
+ Object.defineProperty(exports, "zh_es", {
112
+ enumerable: true,
113
+ get: function () { return inlineI18nMultiReact.zh_es; }
114
+ });
115
+ //# sourceMappingURL=client.js.map
116
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"client.js","sourcesContent":[]}
@@ -0,0 +1,3 @@
1
+ export { LocaleProvider, T, clearDictionaries, en_de, en_es, en_fr, en_ja, en_zh, getDictionary, getLoadedLocales, getLocale, hasTranslation, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadDictionaries, loadDictionary, setLocale, t, useLocale, useT, zh_es } from 'inline-i18n-multi-react';
2
+ //# sourceMappingURL=client.mjs.map
3
+ //# sourceMappingURL=client.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"client.mjs","sourcesContent":[]}
@@ -0,0 +1,4 @@
1
+ export { LocaleProvider, T, clearDictionaries, getLoadedLocales, hasTranslation, loadDictionaries, loadDictionary, t, useLocale, useT } from 'inline-i18n-multi-react';
2
+ export { I18nMiddlewareConfig, createI18nMiddleware } from './middleware.mjs';
3
+ export { Dictionaries, Dictionary, Locale, PluralRules, TranslationVars, Translations } from 'inline-i18n-multi';
4
+ import 'next/server';
@@ -0,0 +1,4 @@
1
+ export { LocaleProvider, T, clearDictionaries, getLoadedLocales, hasTranslation, loadDictionaries, loadDictionary, t, useLocale, useT } from 'inline-i18n-multi-react';
2
+ export { I18nMiddlewareConfig, createI18nMiddleware } from './middleware.js';
3
+ export { Dictionaries, Dictionary, Locale, PluralRules, TranslationVars, Translations } from 'inline-i18n-multi';
4
+ import 'next/server';
package/dist/index.js ADDED
@@ -0,0 +1,88 @@
1
+ 'use strict';
2
+
3
+ var inlineI18nMultiReact = require('inline-i18n-multi-react');
4
+ var server = require('next/server');
5
+
6
+ // src/index.ts
7
+ function createI18nMiddleware(config) {
8
+ const {
9
+ locales,
10
+ defaultLocale,
11
+ localeDetection = true,
12
+ cookieName = "NEXT_LOCALE"
13
+ } = config;
14
+ return function middleware(request) {
15
+ const { pathname } = request.nextUrl;
16
+ const pathnameHasLocale = locales.some(
17
+ (locale2) => pathname.startsWith(`/${locale2}/`) || pathname === `/${locale2}`
18
+ );
19
+ if (pathnameHasLocale) {
20
+ const localeFromPath = pathname.split("/")[1] ?? defaultLocale;
21
+ const response2 = server.NextResponse.next();
22
+ response2.headers.set("x-locale", localeFromPath);
23
+ return response2;
24
+ }
25
+ let locale = defaultLocale;
26
+ const cookieLocale = request.cookies.get(cookieName)?.value;
27
+ if (cookieLocale && locales.includes(cookieLocale)) {
28
+ locale = cookieLocale;
29
+ } else if (localeDetection) {
30
+ const acceptLanguage = request.headers.get("accept-language");
31
+ if (acceptLanguage) {
32
+ const parts = acceptLanguage.split(",")[0]?.split("-");
33
+ const preferredLocale = parts?.[0];
34
+ if (preferredLocale && locales.includes(preferredLocale)) {
35
+ locale = preferredLocale;
36
+ }
37
+ }
38
+ }
39
+ request.nextUrl.pathname = `/${locale}${pathname}`;
40
+ const response = server.NextResponse.redirect(request.nextUrl);
41
+ response.headers.set("x-locale", locale);
42
+ return response;
43
+ };
44
+ }
45
+
46
+ Object.defineProperty(exports, "LocaleProvider", {
47
+ enumerable: true,
48
+ get: function () { return inlineI18nMultiReact.LocaleProvider; }
49
+ });
50
+ Object.defineProperty(exports, "T", {
51
+ enumerable: true,
52
+ get: function () { return inlineI18nMultiReact.T; }
53
+ });
54
+ Object.defineProperty(exports, "clearDictionaries", {
55
+ enumerable: true,
56
+ get: function () { return inlineI18nMultiReact.clearDictionaries; }
57
+ });
58
+ Object.defineProperty(exports, "getLoadedLocales", {
59
+ enumerable: true,
60
+ get: function () { return inlineI18nMultiReact.getLoadedLocales; }
61
+ });
62
+ Object.defineProperty(exports, "hasTranslation", {
63
+ enumerable: true,
64
+ get: function () { return inlineI18nMultiReact.hasTranslation; }
65
+ });
66
+ Object.defineProperty(exports, "loadDictionaries", {
67
+ enumerable: true,
68
+ get: function () { return inlineI18nMultiReact.loadDictionaries; }
69
+ });
70
+ Object.defineProperty(exports, "loadDictionary", {
71
+ enumerable: true,
72
+ get: function () { return inlineI18nMultiReact.loadDictionary; }
73
+ });
74
+ Object.defineProperty(exports, "t", {
75
+ enumerable: true,
76
+ get: function () { return inlineI18nMultiReact.t; }
77
+ });
78
+ Object.defineProperty(exports, "useLocale", {
79
+ enumerable: true,
80
+ get: function () { return inlineI18nMultiReact.useLocale; }
81
+ });
82
+ Object.defineProperty(exports, "useT", {
83
+ enumerable: true,
84
+ get: function () { return inlineI18nMultiReact.useT; }
85
+ });
86
+ exports.createI18nMiddleware = createI18nMiddleware;
87
+ //# sourceMappingURL=index.js.map
88
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/middleware.ts"],"names":["locale","response","NextResponse"],"mappings":";;;;;;AA4BO,SAAS,qBAAqB,MAAA,EAA8B;AACjE,EAAA,MAAM;AAAA,IACJ,OAAA;AAAA,IACA,aAAA;AAAA,IACA,eAAA,GAAkB,IAAA;AAAA,IAClB,UAAA,GAAa;AAAA,GACf,GAAI,MAAA;AAEJ,EAAA,OAAO,SAAS,WAAW,OAAA,EAAsB;AAC/C,IAAA,MAAM,EAAE,QAAA,EAAS,GAAI,OAAA,CAAQ,OAAA;AAG7B,IAAA,MAAM,oBAAoB,OAAA,CAAQ,IAAA;AAAA,MAChC,CAACA,OAAAA,KAAW,QAAA,CAAS,UAAA,CAAW,CAAA,CAAA,EAAIA,OAAM,CAAA,CAAA,CAAG,CAAA,IAAK,QAAA,KAAa,CAAA,CAAA,EAAIA,OAAM,CAAA;AAAA,KAC3E;AAEA,IAAA,IAAI,iBAAA,EAAmB;AAErB,MAAA,MAAM,iBAAiB,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,IAAK,aAAA;AACjD,MAAA,MAAMC,SAAAA,GAAWC,oBAAa,IAAA,EAAK;AACnC,MAAAD,SAAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,UAAA,EAAY,cAAc,CAAA;AAC/C,MAAA,OAAOA,SAAAA;AAAA,IACT;AAGA,IAAA,IAAI,MAAA,GAAS,aAAA;AAGb,IAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,UAAU,CAAA,EAAG,KAAA;AACtD,IAAA,IAAI,YAAA,IAAgB,OAAA,CAAQ,QAAA,CAAS,YAAY,CAAA,EAAG;AAClD,MAAA,MAAA,GAAS,YAAA;AAAA,IACX,WAES,eAAA,EAAiB;AACxB,MAAA,MAAM,cAAA,GAAiB,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,iBAAiB,CAAA;AAC5D,MAAA,IAAI,cAAA,EAAgB;AAClB,QAAA,MAAM,KAAA,GAAQ,eAAe,KAAA,CAAM,GAAG,EAAE,CAAC,CAAA,EAAG,MAAM,GAAG,CAAA;AACrD,QAAA,MAAM,eAAA,GAAkB,QAAQ,CAAC,CAAA;AACjC,QAAA,IAAI,eAAA,IAAmB,OAAA,CAAQ,QAAA,CAAS,eAAyB,CAAA,EAAG;AAClE,UAAA,MAAA,GAAS,eAAA;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAGA,IAAA,OAAA,CAAQ,OAAA,CAAQ,QAAA,GAAW,CAAA,CAAA,EAAI,MAAM,GAAG,QAAQ,CAAA,CAAA;AAChD,IAAA,MAAM,QAAA,GAAWC,mBAAA,CAAa,QAAA,CAAS,OAAA,CAAQ,OAAO,CAAA;AACtD,IAAA,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,UAAA,EAAY,MAAM,CAAA;AAEvC,IAAA,OAAO,QAAA;AAAA,EACT,CAAA;AACF","file":"index.js","sourcesContent":["import { NextRequest, NextResponse } from 'next/server'\nimport type { Locale } from 'inline-i18n-multi'\n\ninterface I18nMiddlewareConfig {\n /**\n * Supported locales\n */\n locales: readonly Locale[] | Locale[]\n /**\n * Default locale when no match found\n */\n defaultLocale: Locale\n /**\n * Enable automatic locale detection from Accept-Language header\n * @default true\n */\n localeDetection?: boolean\n /**\n * Cookie name for storing user's locale preference\n * @default 'NEXT_LOCALE'\n */\n cookieName?: string\n}\n\n/**\n * Create Next.js middleware for i18n routing\n * @param config - Middleware configuration\n */\nexport function createI18nMiddleware(config: I18nMiddlewareConfig) {\n const {\n locales,\n defaultLocale,\n localeDetection = true,\n cookieName = 'NEXT_LOCALE',\n } = config\n\n return function middleware(request: NextRequest) {\n const { pathname } = request.nextUrl\n\n // check if pathname already has locale prefix\n const pathnameHasLocale = locales.some(\n (locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`\n )\n\n if (pathnameHasLocale) {\n // extract locale from pathname and set header\n const localeFromPath = pathname.split('/')[1] ?? defaultLocale\n const response = NextResponse.next()\n response.headers.set('x-locale', localeFromPath)\n return response\n }\n\n // determine locale\n let locale = defaultLocale\n\n // 1. check cookie first\n const cookieLocale = request.cookies.get(cookieName)?.value\n if (cookieLocale && locales.includes(cookieLocale)) {\n locale = cookieLocale\n }\n // 2. detect from Accept-Language header\n else if (localeDetection) {\n const acceptLanguage = request.headers.get('accept-language')\n if (acceptLanguage) {\n const parts = acceptLanguage.split(',')[0]?.split('-')\n const preferredLocale = parts?.[0]\n if (preferredLocale && locales.includes(preferredLocale as Locale)) {\n locale = preferredLocale as Locale\n }\n }\n }\n\n // redirect to locale-prefixed path\n request.nextUrl.pathname = `/${locale}${pathname}`\n const response = NextResponse.redirect(request.nextUrl)\n response.headers.set('x-locale', locale)\n\n return response\n }\n}\n\nexport type { I18nMiddlewareConfig }\n"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,4 @@
1
+ export { createI18nMiddleware } from './chunk-7RR34VBV.mjs';
2
+ export { LocaleProvider, T, clearDictionaries, getLoadedLocales, hasTranslation, loadDictionaries, loadDictionary, t, useLocale, useT } from 'inline-i18n-multi-react';
3
+ //# sourceMappingURL=index.mjs.map
4
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.mjs","sourcesContent":[]}
@@ -0,0 +1,31 @@
1
+ import 'inline-i18n-multi-react';
2
+ import { NextRequest, NextResponse } from 'next/server';
3
+ import { Locale } from 'inline-i18n-multi';
4
+
5
+ interface I18nMiddlewareConfig {
6
+ /**
7
+ * Supported locales
8
+ */
9
+ locales: readonly Locale[] | Locale[];
10
+ /**
11
+ * Default locale when no match found
12
+ */
13
+ defaultLocale: Locale;
14
+ /**
15
+ * Enable automatic locale detection from Accept-Language header
16
+ * @default true
17
+ */
18
+ localeDetection?: boolean;
19
+ /**
20
+ * Cookie name for storing user's locale preference
21
+ * @default 'NEXT_LOCALE'
22
+ */
23
+ cookieName?: string;
24
+ }
25
+ /**
26
+ * Create Next.js middleware for i18n routing
27
+ * @param config - Middleware configuration
28
+ */
29
+ declare function createI18nMiddleware(config: I18nMiddlewareConfig): (request: NextRequest) => NextResponse<unknown>;
30
+
31
+ export { type I18nMiddlewareConfig, createI18nMiddleware };
@@ -0,0 +1,31 @@
1
+ import 'inline-i18n-multi-react';
2
+ import { NextRequest, NextResponse } from 'next/server';
3
+ import { Locale } from 'inline-i18n-multi';
4
+
5
+ interface I18nMiddlewareConfig {
6
+ /**
7
+ * Supported locales
8
+ */
9
+ locales: readonly Locale[] | Locale[];
10
+ /**
11
+ * Default locale when no match found
12
+ */
13
+ defaultLocale: Locale;
14
+ /**
15
+ * Enable automatic locale detection from Accept-Language header
16
+ * @default true
17
+ */
18
+ localeDetection?: boolean;
19
+ /**
20
+ * Cookie name for storing user's locale preference
21
+ * @default 'NEXT_LOCALE'
22
+ */
23
+ cookieName?: string;
24
+ }
25
+ /**
26
+ * Create Next.js middleware for i18n routing
27
+ * @param config - Middleware configuration
28
+ */
29
+ declare function createI18nMiddleware(config: I18nMiddlewareConfig): (request: NextRequest) => NextResponse<unknown>;
30
+
31
+ export { type I18nMiddlewareConfig, createI18nMiddleware };
@@ -0,0 +1,47 @@
1
+ 'use strict';
2
+
3
+ var server = require('next/server');
4
+
5
+ // src/middleware.ts
6
+ function createI18nMiddleware(config) {
7
+ const {
8
+ locales,
9
+ defaultLocale,
10
+ localeDetection = true,
11
+ cookieName = "NEXT_LOCALE"
12
+ } = config;
13
+ return function middleware(request) {
14
+ const { pathname } = request.nextUrl;
15
+ const pathnameHasLocale = locales.some(
16
+ (locale2) => pathname.startsWith(`/${locale2}/`) || pathname === `/${locale2}`
17
+ );
18
+ if (pathnameHasLocale) {
19
+ const localeFromPath = pathname.split("/")[1] ?? defaultLocale;
20
+ const response2 = server.NextResponse.next();
21
+ response2.headers.set("x-locale", localeFromPath);
22
+ return response2;
23
+ }
24
+ let locale = defaultLocale;
25
+ const cookieLocale = request.cookies.get(cookieName)?.value;
26
+ if (cookieLocale && locales.includes(cookieLocale)) {
27
+ locale = cookieLocale;
28
+ } else if (localeDetection) {
29
+ const acceptLanguage = request.headers.get("accept-language");
30
+ if (acceptLanguage) {
31
+ const parts = acceptLanguage.split(",")[0]?.split("-");
32
+ const preferredLocale = parts?.[0];
33
+ if (preferredLocale && locales.includes(preferredLocale)) {
34
+ locale = preferredLocale;
35
+ }
36
+ }
37
+ }
38
+ request.nextUrl.pathname = `/${locale}${pathname}`;
39
+ const response = server.NextResponse.redirect(request.nextUrl);
40
+ response.headers.set("x-locale", locale);
41
+ return response;
42
+ };
43
+ }
44
+
45
+ exports.createI18nMiddleware = createI18nMiddleware;
46
+ //# sourceMappingURL=middleware.js.map
47
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/middleware.ts"],"names":["locale","response","NextResponse"],"mappings":";;;;;AA4BO,SAAS,qBAAqB,MAAA,EAA8B;AACjE,EAAA,MAAM;AAAA,IACJ,OAAA;AAAA,IACA,aAAA;AAAA,IACA,eAAA,GAAkB,IAAA;AAAA,IAClB,UAAA,GAAa;AAAA,GACf,GAAI,MAAA;AAEJ,EAAA,OAAO,SAAS,WAAW,OAAA,EAAsB;AAC/C,IAAA,MAAM,EAAE,QAAA,EAAS,GAAI,OAAA,CAAQ,OAAA;AAG7B,IAAA,MAAM,oBAAoB,OAAA,CAAQ,IAAA;AAAA,MAChC,CAACA,OAAAA,KAAW,QAAA,CAAS,UAAA,CAAW,CAAA,CAAA,EAAIA,OAAM,CAAA,CAAA,CAAG,CAAA,IAAK,QAAA,KAAa,CAAA,CAAA,EAAIA,OAAM,CAAA;AAAA,KAC3E;AAEA,IAAA,IAAI,iBAAA,EAAmB;AAErB,MAAA,MAAM,iBAAiB,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,IAAK,aAAA;AACjD,MAAA,MAAMC,SAAAA,GAAWC,oBAAa,IAAA,EAAK;AACnC,MAAAD,SAAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,UAAA,EAAY,cAAc,CAAA;AAC/C,MAAA,OAAOA,SAAAA;AAAA,IACT;AAGA,IAAA,IAAI,MAAA,GAAS,aAAA;AAGb,IAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,UAAU,CAAA,EAAG,KAAA;AACtD,IAAA,IAAI,YAAA,IAAgB,OAAA,CAAQ,QAAA,CAAS,YAAY,CAAA,EAAG;AAClD,MAAA,MAAA,GAAS,YAAA;AAAA,IACX,WAES,eAAA,EAAiB;AACxB,MAAA,MAAM,cAAA,GAAiB,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,iBAAiB,CAAA;AAC5D,MAAA,IAAI,cAAA,EAAgB;AAClB,QAAA,MAAM,KAAA,GAAQ,eAAe,KAAA,CAAM,GAAG,EAAE,CAAC,CAAA,EAAG,MAAM,GAAG,CAAA;AACrD,QAAA,MAAM,eAAA,GAAkB,QAAQ,CAAC,CAAA;AACjC,QAAA,IAAI,eAAA,IAAmB,OAAA,CAAQ,QAAA,CAAS,eAAyB,CAAA,EAAG;AAClE,UAAA,MAAA,GAAS,eAAA;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAGA,IAAA,OAAA,CAAQ,OAAA,CAAQ,QAAA,GAAW,CAAA,CAAA,EAAI,MAAM,GAAG,QAAQ,CAAA,CAAA;AAChD,IAAA,MAAM,QAAA,GAAWC,mBAAA,CAAa,QAAA,CAAS,OAAA,CAAQ,OAAO,CAAA;AACtD,IAAA,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,UAAA,EAAY,MAAM,CAAA;AAEvC,IAAA,OAAO,QAAA;AAAA,EACT,CAAA;AACF","file":"middleware.js","sourcesContent":["import { NextRequest, NextResponse } from 'next/server'\nimport type { Locale } from 'inline-i18n-multi'\n\ninterface I18nMiddlewareConfig {\n /**\n * Supported locales\n */\n locales: readonly Locale[] | Locale[]\n /**\n * Default locale when no match found\n */\n defaultLocale: Locale\n /**\n * Enable automatic locale detection from Accept-Language header\n * @default true\n */\n localeDetection?: boolean\n /**\n * Cookie name for storing user's locale preference\n * @default 'NEXT_LOCALE'\n */\n cookieName?: string\n}\n\n/**\n * Create Next.js middleware for i18n routing\n * @param config - Middleware configuration\n */\nexport function createI18nMiddleware(config: I18nMiddlewareConfig) {\n const {\n locales,\n defaultLocale,\n localeDetection = true,\n cookieName = 'NEXT_LOCALE',\n } = config\n\n return function middleware(request: NextRequest) {\n const { pathname } = request.nextUrl\n\n // check if pathname already has locale prefix\n const pathnameHasLocale = locales.some(\n (locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`\n )\n\n if (pathnameHasLocale) {\n // extract locale from pathname and set header\n const localeFromPath = pathname.split('/')[1] ?? defaultLocale\n const response = NextResponse.next()\n response.headers.set('x-locale', localeFromPath)\n return response\n }\n\n // determine locale\n let locale = defaultLocale\n\n // 1. check cookie first\n const cookieLocale = request.cookies.get(cookieName)?.value\n if (cookieLocale && locales.includes(cookieLocale)) {\n locale = cookieLocale\n }\n // 2. detect from Accept-Language header\n else if (localeDetection) {\n const acceptLanguage = request.headers.get('accept-language')\n if (acceptLanguage) {\n const parts = acceptLanguage.split(',')[0]?.split('-')\n const preferredLocale = parts?.[0]\n if (preferredLocale && locales.includes(preferredLocale as Locale)) {\n locale = preferredLocale as Locale\n }\n }\n }\n\n // redirect to locale-prefixed path\n request.nextUrl.pathname = `/${locale}${pathname}`\n const response = NextResponse.redirect(request.nextUrl)\n response.headers.set('x-locale', locale)\n\n return response\n }\n}\n\nexport type { I18nMiddlewareConfig }\n"]}
@@ -0,0 +1,3 @@
1
+ export { createI18nMiddleware } from './chunk-7RR34VBV.mjs';
2
+ //# sourceMappingURL=middleware.mjs.map
3
+ //# sourceMappingURL=middleware.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"middleware.mjs"}
@@ -0,0 +1,114 @@
1
+ import { Locale, Translations, TranslationVars } from 'inline-i18n-multi';
2
+
3
+ interface I18nConfig {
4
+ locales: readonly Locale[] | Locale[];
5
+ defaultLocale: Locale;
6
+ baseUrl?: string;
7
+ }
8
+ /**
9
+ * Configure i18n settings for SEO utilities
10
+ */
11
+ declare function configureI18n(config: I18nConfig): void;
12
+ /**
13
+ * Get current i18n configuration
14
+ */
15
+ declare function getI18nConfig(): I18nConfig;
16
+ /**
17
+ * Get locale from route params (for /[locale]/... routes)
18
+ * Validates against configured locales
19
+ * @param params - Route params containing locale
20
+ * @returns Validated locale or throws if invalid
21
+ */
22
+ declare function getLocaleFromParams(params: {
23
+ locale: string;
24
+ }): Locale;
25
+ /**
26
+ * Get locale from headers (set by middleware)
27
+ */
28
+ declare function getLocaleFromHeaders(): Promise<Locale>;
29
+ /**
30
+ * Generate static params for all locales (for generateStaticParams)
31
+ * @example
32
+ * export function generateStaticParams() {
33
+ * return generateLocaleParams()
34
+ * }
35
+ */
36
+ declare function generateLocaleParams(): {
37
+ locale: Locale;
38
+ }[];
39
+ interface AlternateLinks {
40
+ canonical: string;
41
+ languages: Record<Locale | 'x-default', string>;
42
+ }
43
+ /**
44
+ * Generate alternate links for hreflang SEO
45
+ * @param pathname - Current page pathname (without locale prefix)
46
+ * @param currentLocale - Current locale for canonical
47
+ * @returns Object with canonical and language alternates
48
+ * @example
49
+ * export async function generateMetadata({ params }) {
50
+ * const alternates = getAlternates('/about', params.locale)
51
+ * return {
52
+ * alternates: {
53
+ * canonical: alternates.canonical,
54
+ * languages: alternates.languages,
55
+ * }
56
+ * }
57
+ * }
58
+ */
59
+ declare function getAlternates(pathname: string, currentLocale: Locale): AlternateLinks;
60
+ /**
61
+ * Create translated metadata for generateMetadata
62
+ * @example
63
+ * export async function generateMetadata({ params }) {
64
+ * const locale = getLocaleFromParams(params)
65
+ * return createMetadata({
66
+ * title: { ko: '홈', en: 'Home' },
67
+ * description: { ko: '환영합니다', en: 'Welcome' },
68
+ * }, locale, '/home')
69
+ * }
70
+ */
71
+ declare function createMetadata(translations: {
72
+ title: Translations;
73
+ description?: Translations;
74
+ keywords?: Translations;
75
+ }, locale: Locale, pathname?: string): {
76
+ title: string;
77
+ description?: string;
78
+ keywords?: string;
79
+ alternates?: {
80
+ canonical: string;
81
+ languages: Record<string, string>;
82
+ };
83
+ };
84
+ /**
85
+ * Server Component translation with two languages
86
+ * @param ko - Korean text
87
+ * @param en - English text
88
+ * @param vars - Variables for interpolation
89
+ * @param locale - Override locale (optional)
90
+ */
91
+ declare function it(ko: string, en: string, vars?: TranslationVars, locale?: Locale): Promise<string>;
92
+ /**
93
+ * Server Component translation with multiple languages
94
+ * @param translations - Translation map with locale keys
95
+ * @param vars - Variables for interpolation
96
+ * @param locale - Override locale (optional)
97
+ */
98
+ declare function it(translations: Translations, vars?: TranslationVars, locale?: Locale): Promise<string>;
99
+ type PairFunction = (text1: string, text2: string, vars?: TranslationVars, locale?: Locale) => Promise<string>;
100
+ declare const it_ja: PairFunction;
101
+ declare const it_zh: PairFunction;
102
+ declare const it_es: PairFunction;
103
+ declare const it_fr: PairFunction;
104
+ declare const it_de: PairFunction;
105
+ declare const en_ja: PairFunction;
106
+ declare const en_zh: PairFunction;
107
+ declare const en_es: PairFunction;
108
+ declare const en_fr: PairFunction;
109
+ declare const en_de: PairFunction;
110
+ declare const ja_zh: PairFunction;
111
+ declare const ja_es: PairFunction;
112
+ declare const zh_es: PairFunction;
113
+
114
+ export { type AlternateLinks, type I18nConfig, configureI18n, createMetadata, en_de, en_es, en_fr, en_ja, en_zh, generateLocaleParams, getAlternates, getI18nConfig, getLocaleFromHeaders, getLocaleFromParams, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, zh_es };
@@ -0,0 +1,114 @@
1
+ import { Locale, Translations, TranslationVars } from 'inline-i18n-multi';
2
+
3
+ interface I18nConfig {
4
+ locales: readonly Locale[] | Locale[];
5
+ defaultLocale: Locale;
6
+ baseUrl?: string;
7
+ }
8
+ /**
9
+ * Configure i18n settings for SEO utilities
10
+ */
11
+ declare function configureI18n(config: I18nConfig): void;
12
+ /**
13
+ * Get current i18n configuration
14
+ */
15
+ declare function getI18nConfig(): I18nConfig;
16
+ /**
17
+ * Get locale from route params (for /[locale]/... routes)
18
+ * Validates against configured locales
19
+ * @param params - Route params containing locale
20
+ * @returns Validated locale or throws if invalid
21
+ */
22
+ declare function getLocaleFromParams(params: {
23
+ locale: string;
24
+ }): Locale;
25
+ /**
26
+ * Get locale from headers (set by middleware)
27
+ */
28
+ declare function getLocaleFromHeaders(): Promise<Locale>;
29
+ /**
30
+ * Generate static params for all locales (for generateStaticParams)
31
+ * @example
32
+ * export function generateStaticParams() {
33
+ * return generateLocaleParams()
34
+ * }
35
+ */
36
+ declare function generateLocaleParams(): {
37
+ locale: Locale;
38
+ }[];
39
+ interface AlternateLinks {
40
+ canonical: string;
41
+ languages: Record<Locale | 'x-default', string>;
42
+ }
43
+ /**
44
+ * Generate alternate links for hreflang SEO
45
+ * @param pathname - Current page pathname (without locale prefix)
46
+ * @param currentLocale - Current locale for canonical
47
+ * @returns Object with canonical and language alternates
48
+ * @example
49
+ * export async function generateMetadata({ params }) {
50
+ * const alternates = getAlternates('/about', params.locale)
51
+ * return {
52
+ * alternates: {
53
+ * canonical: alternates.canonical,
54
+ * languages: alternates.languages,
55
+ * }
56
+ * }
57
+ * }
58
+ */
59
+ declare function getAlternates(pathname: string, currentLocale: Locale): AlternateLinks;
60
+ /**
61
+ * Create translated metadata for generateMetadata
62
+ * @example
63
+ * export async function generateMetadata({ params }) {
64
+ * const locale = getLocaleFromParams(params)
65
+ * return createMetadata({
66
+ * title: { ko: '홈', en: 'Home' },
67
+ * description: { ko: '환영합니다', en: 'Welcome' },
68
+ * }, locale, '/home')
69
+ * }
70
+ */
71
+ declare function createMetadata(translations: {
72
+ title: Translations;
73
+ description?: Translations;
74
+ keywords?: Translations;
75
+ }, locale: Locale, pathname?: string): {
76
+ title: string;
77
+ description?: string;
78
+ keywords?: string;
79
+ alternates?: {
80
+ canonical: string;
81
+ languages: Record<string, string>;
82
+ };
83
+ };
84
+ /**
85
+ * Server Component translation with two languages
86
+ * @param ko - Korean text
87
+ * @param en - English text
88
+ * @param vars - Variables for interpolation
89
+ * @param locale - Override locale (optional)
90
+ */
91
+ declare function it(ko: string, en: string, vars?: TranslationVars, locale?: Locale): Promise<string>;
92
+ /**
93
+ * Server Component translation with multiple languages
94
+ * @param translations - Translation map with locale keys
95
+ * @param vars - Variables for interpolation
96
+ * @param locale - Override locale (optional)
97
+ */
98
+ declare function it(translations: Translations, vars?: TranslationVars, locale?: Locale): Promise<string>;
99
+ type PairFunction = (text1: string, text2: string, vars?: TranslationVars, locale?: Locale) => Promise<string>;
100
+ declare const it_ja: PairFunction;
101
+ declare const it_zh: PairFunction;
102
+ declare const it_es: PairFunction;
103
+ declare const it_fr: PairFunction;
104
+ declare const it_de: PairFunction;
105
+ declare const en_ja: PairFunction;
106
+ declare const en_zh: PairFunction;
107
+ declare const en_es: PairFunction;
108
+ declare const en_fr: PairFunction;
109
+ declare const en_de: PairFunction;
110
+ declare const ja_zh: PairFunction;
111
+ declare const ja_es: PairFunction;
112
+ declare const zh_es: PairFunction;
113
+
114
+ export { type AlternateLinks, type I18nConfig, configureI18n, createMetadata, en_de, en_es, en_fr, en_ja, en_zh, generateLocaleParams, getAlternates, getI18nConfig, getLocaleFromHeaders, getLocaleFromParams, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, zh_es };
package/dist/server.js ADDED
@@ -0,0 +1,145 @@
1
+ 'use strict';
2
+
3
+ var headers = require('next/headers');
4
+
5
+ // src/server.ts
6
+ var VARIABLE_PATTERN = /\{(\w+)\}/g;
7
+ var _config = {
8
+ locales: ["ko", "en"],
9
+ defaultLocale: "ko"
10
+ };
11
+ function configureI18n(config) {
12
+ _config = { ..._config, ...config };
13
+ }
14
+ function getI18nConfig() {
15
+ return _config;
16
+ }
17
+ function getLocaleFromParams(params) {
18
+ const { locale } = params;
19
+ if (_config.locales.includes(locale)) {
20
+ return locale;
21
+ }
22
+ throw new Error(
23
+ `Invalid locale: "${locale}". Supported: ${_config.locales.join(", ")}`
24
+ );
25
+ }
26
+ async function getLocaleFromHeaders() {
27
+ const headersList = await headers.headers();
28
+ return headersList.get("x-locale") || _config.defaultLocale;
29
+ }
30
+ function generateLocaleParams() {
31
+ return _config.locales.map((locale) => ({ locale }));
32
+ }
33
+ function getAlternates(pathname, currentLocale) {
34
+ const baseUrl = _config.baseUrl || "";
35
+ const cleanPath = pathname.startsWith("/") ? pathname : `/${pathname}`;
36
+ const languages = {};
37
+ for (const locale of _config.locales) {
38
+ languages[locale] = `${baseUrl}/${locale}${cleanPath}`;
39
+ }
40
+ languages["x-default"] = `${baseUrl}/${_config.defaultLocale}${cleanPath}`;
41
+ return {
42
+ canonical: `${baseUrl}/${currentLocale}${cleanPath}`,
43
+ languages
44
+ };
45
+ }
46
+ function createMetadata(translations, locale, pathname) {
47
+ const result = {
48
+ title: translations.title[locale] || translations.title[_config.defaultLocale] || ""
49
+ };
50
+ if (translations.description) {
51
+ result.description = translations.description[locale] || translations.description[_config.defaultLocale];
52
+ }
53
+ if (translations.keywords) {
54
+ result.keywords = translations.keywords[locale] || translations.keywords[_config.defaultLocale];
55
+ }
56
+ if (pathname) {
57
+ const alternates = getAlternates(pathname, locale);
58
+ result.alternates = {
59
+ canonical: alternates.canonical,
60
+ languages: alternates.languages
61
+ };
62
+ }
63
+ return result;
64
+ }
65
+ function interpolate(template, vars) {
66
+ if (!vars) return template;
67
+ return template.replace(VARIABLE_PATTERN, (_, key) => {
68
+ const value = vars[key];
69
+ return value !== void 0 ? String(value) : `{${key}}`;
70
+ });
71
+ }
72
+ async function resolveLocale(localeParam) {
73
+ if (localeParam) return localeParam;
74
+ const headersList = await headers.headers();
75
+ return headersList.get("x-locale") || _config.defaultLocale;
76
+ }
77
+ function resolveTemplate(translations, locale) {
78
+ const template = translations[locale];
79
+ if (template) return template;
80
+ const fallback = translations.en ?? Object.values(translations)[0];
81
+ if (fallback) return fallback;
82
+ throw new Error(
83
+ `No translation found for locale "${locale}". Available: ${Object.keys(translations).join(", ")}`
84
+ );
85
+ }
86
+ async function it(first, second, third, fourth) {
87
+ if (typeof first === "object") {
88
+ const translations2 = first;
89
+ const vars2 = second;
90
+ const locale2 = await resolveLocale(third);
91
+ return interpolate(resolveTemplate(translations2, locale2), vars2);
92
+ }
93
+ const ko = first;
94
+ const en = second;
95
+ const vars = third;
96
+ const locale = await resolveLocale(fourth);
97
+ const translations = { ko, en };
98
+ return interpolate(resolveTemplate(translations, locale), vars);
99
+ }
100
+ function createPair(lang1, lang2) {
101
+ return async (text1, text2, vars, locale) => {
102
+ const translations = {
103
+ [lang1]: text1,
104
+ [lang2]: text2
105
+ };
106
+ return it(translations, vars, locale);
107
+ };
108
+ }
109
+ var it_ja = createPair("ko", "ja");
110
+ var it_zh = createPair("ko", "zh");
111
+ var it_es = createPair("ko", "es");
112
+ var it_fr = createPair("ko", "fr");
113
+ var it_de = createPair("ko", "de");
114
+ var en_ja = createPair("en", "ja");
115
+ var en_zh = createPair("en", "zh");
116
+ var en_es = createPair("en", "es");
117
+ var en_fr = createPair("en", "fr");
118
+ var en_de = createPair("en", "de");
119
+ var ja_zh = createPair("ja", "zh");
120
+ var ja_es = createPair("ja", "es");
121
+ var zh_es = createPair("zh", "es");
122
+
123
+ exports.configureI18n = configureI18n;
124
+ exports.createMetadata = createMetadata;
125
+ exports.en_de = en_de;
126
+ exports.en_es = en_es;
127
+ exports.en_fr = en_fr;
128
+ exports.en_ja = en_ja;
129
+ exports.en_zh = en_zh;
130
+ exports.generateLocaleParams = generateLocaleParams;
131
+ exports.getAlternates = getAlternates;
132
+ exports.getI18nConfig = getI18nConfig;
133
+ exports.getLocaleFromHeaders = getLocaleFromHeaders;
134
+ exports.getLocaleFromParams = getLocaleFromParams;
135
+ exports.it = it;
136
+ exports.it_de = it_de;
137
+ exports.it_es = it_es;
138
+ exports.it_fr = it_fr;
139
+ exports.it_ja = it_ja;
140
+ exports.it_zh = it_zh;
141
+ exports.ja_es = ja_es;
142
+ exports.ja_zh = ja_zh;
143
+ exports.zh_es = zh_es;
144
+ //# sourceMappingURL=server.js.map
145
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server.ts"],"names":["headers","translations","vars","locale"],"mappings":"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","file":"server.js","sourcesContent":["import { headers } from 'next/headers'\nimport type { Translations, TranslationVars, Locale } from 'inline-i18n-multi'\n\nconst VARIABLE_PATTERN = /\\{(\\w+)\\}/g\n\n// ============================================\n// SEO Configuration\n// ============================================\n\nexport interface I18nConfig {\n locales: readonly Locale[] | Locale[]\n defaultLocale: Locale\n baseUrl?: string\n}\n\nlet _config: I18nConfig = {\n locales: ['ko', 'en'],\n defaultLocale: 'ko',\n}\n\n/**\n * Configure i18n settings for SEO utilities\n */\nexport function configureI18n(config: I18nConfig): void {\n _config = { ..._config, ...config }\n}\n\n/**\n * Get current i18n configuration\n */\nexport function getI18nConfig(): I18nConfig {\n return _config\n}\n\n// ============================================\n// Locale Resolution\n// ============================================\n\n/**\n * Get locale from route params (for /[locale]/... routes)\n * Validates against configured locales\n * @param params - Route params containing locale\n * @returns Validated locale or throws if invalid\n */\nexport function getLocaleFromParams(params: { locale: string }): Locale {\n const { locale } = params\n if (_config.locales.includes(locale)) {\n return locale\n }\n throw new Error(\n `Invalid locale: \"${locale}\". Supported: ${_config.locales.join(', ')}`\n )\n}\n\n/**\n * Get locale from headers (set by middleware)\n */\nexport async function getLocaleFromHeaders(): Promise<Locale> {\n const headersList = await headers()\n return headersList.get('x-locale') || _config.defaultLocale\n}\n\n/**\n * Generate static params for all locales (for generateStaticParams)\n * @example\n * export function generateStaticParams() {\n * return generateLocaleParams()\n * }\n */\nexport function generateLocaleParams(): { locale: Locale }[] {\n return _config.locales.map((locale) => ({ locale }))\n}\n\n// ============================================\n// SEO Metadata Helpers\n// ============================================\n\nexport interface AlternateLinks {\n canonical: string\n languages: Record<Locale | 'x-default', string>\n}\n\n/**\n * Generate alternate links for hreflang SEO\n * @param pathname - Current page pathname (without locale prefix)\n * @param currentLocale - Current locale for canonical\n * @returns Object with canonical and language alternates\n * @example\n * export async function generateMetadata({ params }) {\n * const alternates = getAlternates('/about', params.locale)\n * return {\n * alternates: {\n * canonical: alternates.canonical,\n * languages: alternates.languages,\n * }\n * }\n * }\n */\nexport function getAlternates(pathname: string, currentLocale: Locale): AlternateLinks {\n const baseUrl = _config.baseUrl || ''\n const cleanPath = pathname.startsWith('/') ? pathname : `/${pathname}`\n\n const languages: Record<string, string> = {}\n\n for (const locale of _config.locales) {\n languages[locale] = `${baseUrl}/${locale}${cleanPath}`\n }\n\n // x-default points to default locale\n languages['x-default'] = `${baseUrl}/${_config.defaultLocale}${cleanPath}`\n\n return {\n canonical: `${baseUrl}/${currentLocale}${cleanPath}`,\n languages,\n }\n}\n\n/**\n * Create translated metadata for generateMetadata\n * @example\n * export async function generateMetadata({ params }) {\n * const locale = getLocaleFromParams(params)\n * return createMetadata({\n * title: { ko: '홈', en: 'Home' },\n * description: { ko: '환영합니다', en: 'Welcome' },\n * }, locale, '/home')\n * }\n */\nexport function createMetadata(\n translations: {\n title: Translations\n description?: Translations\n keywords?: Translations\n },\n locale: Locale,\n pathname?: string\n): {\n title: string\n description?: string\n keywords?: string\n alternates?: { canonical: string; languages: Record<string, string> }\n} {\n const result: ReturnType<typeof createMetadata> = {\n title: translations.title[locale] || translations.title[_config.defaultLocale] || '',\n }\n\n if (translations.description) {\n result.description =\n translations.description[locale] ||\n translations.description[_config.defaultLocale]\n }\n\n if (translations.keywords) {\n result.keywords =\n translations.keywords[locale] ||\n translations.keywords[_config.defaultLocale]\n }\n\n if (pathname) {\n const alternates = getAlternates(pathname, locale)\n result.alternates = {\n canonical: alternates.canonical,\n languages: alternates.languages,\n }\n }\n\n return result\n}\n\nfunction interpolate(template: string, vars?: TranslationVars): string {\n if (!vars) return template\n\n return template.replace(VARIABLE_PATTERN, (_, key) => {\n const value = vars[key]\n return value !== undefined ? String(value) : `{${key}}`\n })\n}\n\nasync function resolveLocale(localeParam?: Locale): Promise<Locale> {\n if (localeParam) return localeParam\n\n const headersList = await headers()\n return headersList.get('x-locale') || _config.defaultLocale\n}\n\nfunction resolveTemplate(translations: Translations, locale: Locale): string {\n const template = translations[locale]\n if (template) return template\n\n const fallback = translations.en ?? Object.values(translations)[0]\n if (fallback) return fallback\n\n throw new Error(\n `No translation found for locale \"${locale}\". Available: ${Object.keys(translations).join(', ')}`\n )\n}\n\n/**\n * Server Component translation with two languages\n * @param ko - Korean text\n * @param en - English text\n * @param vars - Variables for interpolation\n * @param locale - Override locale (optional)\n */\nexport async function it(\n ko: string,\n en: string,\n vars?: TranslationVars,\n locale?: Locale,\n): Promise<string>\n\n/**\n * Server Component translation with multiple languages\n * @param translations - Translation map with locale keys\n * @param vars - Variables for interpolation\n * @param locale - Override locale (optional)\n */\nexport async function it(\n translations: Translations,\n vars?: TranslationVars,\n locale?: Locale,\n): Promise<string>\n\nexport async function it(\n first: string | Translations,\n second?: string | TranslationVars,\n third?: TranslationVars | Locale,\n fourth?: Locale,\n): Promise<string> {\n // object syntax: it({ ko, en, ... }, vars?, locale?)\n if (typeof first === 'object') {\n const translations = first\n const vars = second as TranslationVars | undefined\n const locale = await resolveLocale(third as Locale | undefined)\n return interpolate(resolveTemplate(translations, locale), vars)\n }\n\n // shorthand syntax: it('한글', 'English', vars?, locale?)\n const ko = first\n const en = second as string\n const vars = third as TranslationVars | undefined\n const locale = await resolveLocale(fourth)\n\n const translations: Translations = { ko, en }\n return interpolate(resolveTemplate(translations, locale), vars)\n}\n\n// language pair helpers\ntype PairFunction = (\n text1: string,\n text2: string,\n vars?: TranslationVars,\n locale?: Locale,\n) => Promise<string>\n\nfunction createPair(lang1: Locale, lang2: Locale): PairFunction {\n return async (text1, text2, vars, locale) => {\n const translations: Translations = {\n [lang1]: text1,\n [lang2]: text2,\n }\n return it(translations, vars, locale)\n }\n}\n\nexport const it_ja = createPair('ko', 'ja')\nexport const it_zh = createPair('ko', 'zh')\nexport const it_es = createPair('ko', 'es')\nexport const it_fr = createPair('ko', 'fr')\nexport const it_de = createPair('ko', 'de')\n\nexport const en_ja = createPair('en', 'ja')\nexport const en_zh = createPair('en', 'zh')\nexport const en_es = createPair('en', 'es')\nexport const en_fr = createPair('en', 'fr')\nexport const en_de = createPair('en', 'de')\n\nexport const ja_zh = createPair('ja', 'zh')\nexport const ja_es = createPair('ja', 'es')\nexport const zh_es = createPair('zh', 'es')\n"]}
@@ -0,0 +1,123 @@
1
+ import { headers } from 'next/headers';
2
+
3
+ // src/server.ts
4
+ var VARIABLE_PATTERN = /\{(\w+)\}/g;
5
+ var _config = {
6
+ locales: ["ko", "en"],
7
+ defaultLocale: "ko"
8
+ };
9
+ function configureI18n(config) {
10
+ _config = { ..._config, ...config };
11
+ }
12
+ function getI18nConfig() {
13
+ return _config;
14
+ }
15
+ function getLocaleFromParams(params) {
16
+ const { locale } = params;
17
+ if (_config.locales.includes(locale)) {
18
+ return locale;
19
+ }
20
+ throw new Error(
21
+ `Invalid locale: "${locale}". Supported: ${_config.locales.join(", ")}`
22
+ );
23
+ }
24
+ async function getLocaleFromHeaders() {
25
+ const headersList = await headers();
26
+ return headersList.get("x-locale") || _config.defaultLocale;
27
+ }
28
+ function generateLocaleParams() {
29
+ return _config.locales.map((locale) => ({ locale }));
30
+ }
31
+ function getAlternates(pathname, currentLocale) {
32
+ const baseUrl = _config.baseUrl || "";
33
+ const cleanPath = pathname.startsWith("/") ? pathname : `/${pathname}`;
34
+ const languages = {};
35
+ for (const locale of _config.locales) {
36
+ languages[locale] = `${baseUrl}/${locale}${cleanPath}`;
37
+ }
38
+ languages["x-default"] = `${baseUrl}/${_config.defaultLocale}${cleanPath}`;
39
+ return {
40
+ canonical: `${baseUrl}/${currentLocale}${cleanPath}`,
41
+ languages
42
+ };
43
+ }
44
+ function createMetadata(translations, locale, pathname) {
45
+ const result = {
46
+ title: translations.title[locale] || translations.title[_config.defaultLocale] || ""
47
+ };
48
+ if (translations.description) {
49
+ result.description = translations.description[locale] || translations.description[_config.defaultLocale];
50
+ }
51
+ if (translations.keywords) {
52
+ result.keywords = translations.keywords[locale] || translations.keywords[_config.defaultLocale];
53
+ }
54
+ if (pathname) {
55
+ const alternates = getAlternates(pathname, locale);
56
+ result.alternates = {
57
+ canonical: alternates.canonical,
58
+ languages: alternates.languages
59
+ };
60
+ }
61
+ return result;
62
+ }
63
+ function interpolate(template, vars) {
64
+ if (!vars) return template;
65
+ return template.replace(VARIABLE_PATTERN, (_, key) => {
66
+ const value = vars[key];
67
+ return value !== void 0 ? String(value) : `{${key}}`;
68
+ });
69
+ }
70
+ async function resolveLocale(localeParam) {
71
+ if (localeParam) return localeParam;
72
+ const headersList = await headers();
73
+ return headersList.get("x-locale") || _config.defaultLocale;
74
+ }
75
+ function resolveTemplate(translations, locale) {
76
+ const template = translations[locale];
77
+ if (template) return template;
78
+ const fallback = translations.en ?? Object.values(translations)[0];
79
+ if (fallback) return fallback;
80
+ throw new Error(
81
+ `No translation found for locale "${locale}". Available: ${Object.keys(translations).join(", ")}`
82
+ );
83
+ }
84
+ async function it(first, second, third, fourth) {
85
+ if (typeof first === "object") {
86
+ const translations2 = first;
87
+ const vars2 = second;
88
+ const locale2 = await resolveLocale(third);
89
+ return interpolate(resolveTemplate(translations2, locale2), vars2);
90
+ }
91
+ const ko = first;
92
+ const en = second;
93
+ const vars = third;
94
+ const locale = await resolveLocale(fourth);
95
+ const translations = { ko, en };
96
+ return interpolate(resolveTemplate(translations, locale), vars);
97
+ }
98
+ function createPair(lang1, lang2) {
99
+ return async (text1, text2, vars, locale) => {
100
+ const translations = {
101
+ [lang1]: text1,
102
+ [lang2]: text2
103
+ };
104
+ return it(translations, vars, locale);
105
+ };
106
+ }
107
+ var it_ja = createPair("ko", "ja");
108
+ var it_zh = createPair("ko", "zh");
109
+ var it_es = createPair("ko", "es");
110
+ var it_fr = createPair("ko", "fr");
111
+ var it_de = createPair("ko", "de");
112
+ var en_ja = createPair("en", "ja");
113
+ var en_zh = createPair("en", "zh");
114
+ var en_es = createPair("en", "es");
115
+ var en_fr = createPair("en", "fr");
116
+ var en_de = createPair("en", "de");
117
+ var ja_zh = createPair("ja", "zh");
118
+ var ja_es = createPair("ja", "es");
119
+ var zh_es = createPair("zh", "es");
120
+
121
+ export { configureI18n, createMetadata, en_de, en_es, en_fr, en_ja, en_zh, generateLocaleParams, getAlternates, getI18nConfig, getLocaleFromHeaders, getLocaleFromParams, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, zh_es };
122
+ //# sourceMappingURL=server.mjs.map
123
+ //# sourceMappingURL=server.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server.ts"],"names":["translations","vars","locale"],"mappings":";;;AAGA,IAAM,gBAAA,GAAmB,YAAA;AAYzB,IAAI,OAAA,GAAsB;AAAA,EACxB,OAAA,EAAS,CAAC,IAAA,EAAM,IAAI,CAAA;AAAA,EACpB,aAAA,EAAe;AACjB,CAAA;AAKO,SAAS,cAAc,MAAA,EAA0B;AACtD,EAAA,OAAA,GAAU,EAAE,GAAG,OAAA,EAAS,GAAG,MAAA,EAAO;AACpC;AAKO,SAAS,aAAA,GAA4B;AAC1C,EAAA,OAAO,OAAA;AACT;AAYO,SAAS,oBAAoB,MAAA,EAAoC;AACtE,EAAA,MAAM,EAAE,QAAO,GAAI,MAAA;AACnB,EAAA,IAAI,OAAA,CAAQ,OAAA,CAAQ,QAAA,CAAS,MAAM,CAAA,EAAG;AACpC,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,MAAM,IAAI,KAAA;AAAA,IACR,oBAAoB,MAAM,CAAA,cAAA,EAAiB,QAAQ,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,GACvE;AACF;AAKA,eAAsB,oBAAA,GAAwC;AAC5D,EAAA,MAAM,WAAA,GAAc,MAAM,OAAA,EAAQ;AAClC,EAAA,OAAO,WAAA,CAAY,GAAA,CAAI,UAAU,CAAA,IAAK,OAAA,CAAQ,aAAA;AAChD;AASO,SAAS,oBAAA,GAA6C;AAC3D,EAAA,OAAO,QAAQ,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,MAAY,EAAE,QAAO,CAAE,CAAA;AACrD;AA2BO,SAAS,aAAA,CAAc,UAAkB,aAAA,EAAuC;AACrF,EAAA,MAAM,OAAA,GAAU,QAAQ,OAAA,IAAW,EAAA;AACnC,EAAA,MAAM,YAAY,QAAA,CAAS,UAAA,CAAW,GAAG,CAAA,GAAI,QAAA,GAAW,IAAI,QAAQ,CAAA,CAAA;AAEpE,EAAA,MAAM,YAAoC,EAAC;AAE3C,EAAA,KAAA,MAAW,MAAA,IAAU,QAAQ,OAAA,EAAS;AACpC,IAAA,SAAA,CAAU,MAAM,CAAA,GAAI,CAAA,EAAG,OAAO,CAAA,CAAA,EAAI,MAAM,GAAG,SAAS,CAAA,CAAA;AAAA,EACtD;AAGA,EAAA,SAAA,CAAU,WAAW,IAAI,CAAA,EAAG,OAAO,IAAI,OAAA,CAAQ,aAAa,GAAG,SAAS,CAAA,CAAA;AAExE,EAAA,OAAO;AAAA,IACL,WAAW,CAAA,EAAG,OAAO,CAAA,CAAA,EAAI,aAAa,GAAG,SAAS,CAAA,CAAA;AAAA,IAClD;AAAA,GACF;AACF;AAaO,SAAS,cAAA,CACd,YAAA,EAKA,MAAA,EACA,QAAA,EAMA;AACA,EAAA,MAAM,MAAA,GAA4C;AAAA,IAChD,KAAA,EAAO,aAAa,KAAA,CAAM,MAAM,KAAK,YAAA,CAAa,KAAA,CAAM,OAAA,CAAQ,aAAa,CAAA,IAAK;AAAA,GACpF;AAEA,EAAA,IAAI,aAAa,WAAA,EAAa;AAC5B,IAAA,MAAA,CAAO,WAAA,GACL,aAAa,WAAA,CAAY,MAAM,KAC/B,YAAA,CAAa,WAAA,CAAY,QAAQ,aAAa,CAAA;AAAA,EAClD;AAEA,EAAA,IAAI,aAAa,QAAA,EAAU;AACzB,IAAA,MAAA,CAAO,QAAA,GACL,aAAa,QAAA,CAAS,MAAM,KAC5B,YAAA,CAAa,QAAA,CAAS,QAAQ,aAAa,CAAA;AAAA,EAC/C;AAEA,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,MAAM,UAAA,GAAa,aAAA,CAAc,QAAA,EAAU,MAAM,CAAA;AACjD,IAAA,MAAA,CAAO,UAAA,GAAa;AAAA,MAClB,WAAW,UAAA,CAAW,SAAA;AAAA,MACtB,WAAW,UAAA,CAAW;AAAA,KACxB;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,WAAA,CAAY,UAAkB,IAAA,EAAgC;AACrE,EAAA,IAAI,CAAC,MAAM,OAAO,QAAA;AAElB,EAAA,OAAO,QAAA,CAAS,OAAA,CAAQ,gBAAA,EAAkB,CAAC,GAAG,GAAA,KAAQ;AACpD,IAAA,MAAM,KAAA,GAAQ,KAAK,GAAG,CAAA;AACtB,IAAA,OAAO,UAAU,MAAA,GAAY,MAAA,CAAO,KAAK,CAAA,GAAI,IAAI,GAAG,CAAA,CAAA,CAAA;AAAA,EACtD,CAAC,CAAA;AACH;AAEA,eAAe,cAAc,WAAA,EAAuC;AAClE,EAAA,IAAI,aAAa,OAAO,WAAA;AAExB,EAAA,MAAM,WAAA,GAAc,MAAM,OAAA,EAAQ;AAClC,EAAA,OAAO,WAAA,CAAY,GAAA,CAAI,UAAU,CAAA,IAAK,OAAA,CAAQ,aAAA;AAChD;AAEA,SAAS,eAAA,CAAgB,cAA4B,MAAA,EAAwB;AAC3E,EAAA,MAAM,QAAA,GAAW,aAAa,MAAM,CAAA;AACpC,EAAA,IAAI,UAAU,OAAO,QAAA;AAErB,EAAA,MAAM,WAAW,YAAA,CAAa,EAAA,IAAM,OAAO,MAAA,CAAO,YAAY,EAAE,CAAC,CAAA;AACjE,EAAA,IAAI,UAAU,OAAO,QAAA;AAErB,EAAA,MAAM,IAAI,KAAA;AAAA,IACR,CAAA,iCAAA,EAAoC,MAAM,CAAA,cAAA,EAAiB,MAAA,CAAO,KAAK,YAAY,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,GACjG;AACF;AA4BA,eAAsB,EAAA,CACpB,KAAA,EACA,MAAA,EACA,KAAA,EACA,MAAA,EACiB;AAEjB,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,MAAMA,aAAAA,GAAe,KAAA;AACrB,IAAA,MAAMC,KAAAA,GAAO,MAAA;AACb,IAAA,MAAMC,OAAAA,GAAS,MAAM,aAAA,CAAc,KAA2B,CAAA;AAC9D,IAAA,OAAO,WAAA,CAAY,eAAA,CAAgBF,aAAAA,EAAcE,OAAM,GAAGD,KAAI,CAAA;AAAA,EAChE;AAGA,EAAA,MAAM,EAAA,GAAK,KAAA;AACX,EAAA,MAAM,EAAA,GAAK,MAAA;AACX,EAAA,MAAM,IAAA,GAAO,KAAA;AACb,EAAA,MAAM,MAAA,GAAS,MAAM,aAAA,CAAc,MAAM,CAAA;AAEzC,EAAA,MAAM,YAAA,GAA6B,EAAE,EAAA,EAAI,EAAA,EAAG;AAC5C,EAAA,OAAO,WAAA,CAAY,eAAA,CAAgB,YAAA,EAAc,MAAM,GAAG,IAAI,CAAA;AAChE;AAUA,SAAS,UAAA,CAAW,OAAe,KAAA,EAA6B;AAC9D,EAAA,OAAO,OAAO,KAAA,EAAO,KAAA,EAAO,IAAA,EAAM,MAAA,KAAW;AAC3C,IAAA,MAAM,YAAA,GAA6B;AAAA,MACjC,CAAC,KAAK,GAAG,KAAA;AAAA,MACT,CAAC,KAAK,GAAG;AAAA,KACX;AACA,IAAA,OAAO,EAAA,CAAG,YAAA,EAAc,IAAA,EAAM,MAAM,CAAA;AAAA,EACtC,CAAA;AACF;AAEO,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AAEnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AAEnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI;AACnC,IAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,IAAI","file":"server.mjs","sourcesContent":["import { headers } from 'next/headers'\nimport type { Translations, TranslationVars, Locale } from 'inline-i18n-multi'\n\nconst VARIABLE_PATTERN = /\\{(\\w+)\\}/g\n\n// ============================================\n// SEO Configuration\n// ============================================\n\nexport interface I18nConfig {\n locales: readonly Locale[] | Locale[]\n defaultLocale: Locale\n baseUrl?: string\n}\n\nlet _config: I18nConfig = {\n locales: ['ko', 'en'],\n defaultLocale: 'ko',\n}\n\n/**\n * Configure i18n settings for SEO utilities\n */\nexport function configureI18n(config: I18nConfig): void {\n _config = { ..._config, ...config }\n}\n\n/**\n * Get current i18n configuration\n */\nexport function getI18nConfig(): I18nConfig {\n return _config\n}\n\n// ============================================\n// Locale Resolution\n// ============================================\n\n/**\n * Get locale from route params (for /[locale]/... routes)\n * Validates against configured locales\n * @param params - Route params containing locale\n * @returns Validated locale or throws if invalid\n */\nexport function getLocaleFromParams(params: { locale: string }): Locale {\n const { locale } = params\n if (_config.locales.includes(locale)) {\n return locale\n }\n throw new Error(\n `Invalid locale: \"${locale}\". Supported: ${_config.locales.join(', ')}`\n )\n}\n\n/**\n * Get locale from headers (set by middleware)\n */\nexport async function getLocaleFromHeaders(): Promise<Locale> {\n const headersList = await headers()\n return headersList.get('x-locale') || _config.defaultLocale\n}\n\n/**\n * Generate static params for all locales (for generateStaticParams)\n * @example\n * export function generateStaticParams() {\n * return generateLocaleParams()\n * }\n */\nexport function generateLocaleParams(): { locale: Locale }[] {\n return _config.locales.map((locale) => ({ locale }))\n}\n\n// ============================================\n// SEO Metadata Helpers\n// ============================================\n\nexport interface AlternateLinks {\n canonical: string\n languages: Record<Locale | 'x-default', string>\n}\n\n/**\n * Generate alternate links for hreflang SEO\n * @param pathname - Current page pathname (without locale prefix)\n * @param currentLocale - Current locale for canonical\n * @returns Object with canonical and language alternates\n * @example\n * export async function generateMetadata({ params }) {\n * const alternates = getAlternates('/about', params.locale)\n * return {\n * alternates: {\n * canonical: alternates.canonical,\n * languages: alternates.languages,\n * }\n * }\n * }\n */\nexport function getAlternates(pathname: string, currentLocale: Locale): AlternateLinks {\n const baseUrl = _config.baseUrl || ''\n const cleanPath = pathname.startsWith('/') ? pathname : `/${pathname}`\n\n const languages: Record<string, string> = {}\n\n for (const locale of _config.locales) {\n languages[locale] = `${baseUrl}/${locale}${cleanPath}`\n }\n\n // x-default points to default locale\n languages['x-default'] = `${baseUrl}/${_config.defaultLocale}${cleanPath}`\n\n return {\n canonical: `${baseUrl}/${currentLocale}${cleanPath}`,\n languages,\n }\n}\n\n/**\n * Create translated metadata for generateMetadata\n * @example\n * export async function generateMetadata({ params }) {\n * const locale = getLocaleFromParams(params)\n * return createMetadata({\n * title: { ko: '홈', en: 'Home' },\n * description: { ko: '환영합니다', en: 'Welcome' },\n * }, locale, '/home')\n * }\n */\nexport function createMetadata(\n translations: {\n title: Translations\n description?: Translations\n keywords?: Translations\n },\n locale: Locale,\n pathname?: string\n): {\n title: string\n description?: string\n keywords?: string\n alternates?: { canonical: string; languages: Record<string, string> }\n} {\n const result: ReturnType<typeof createMetadata> = {\n title: translations.title[locale] || translations.title[_config.defaultLocale] || '',\n }\n\n if (translations.description) {\n result.description =\n translations.description[locale] ||\n translations.description[_config.defaultLocale]\n }\n\n if (translations.keywords) {\n result.keywords =\n translations.keywords[locale] ||\n translations.keywords[_config.defaultLocale]\n }\n\n if (pathname) {\n const alternates = getAlternates(pathname, locale)\n result.alternates = {\n canonical: alternates.canonical,\n languages: alternates.languages,\n }\n }\n\n return result\n}\n\nfunction interpolate(template: string, vars?: TranslationVars): string {\n if (!vars) return template\n\n return template.replace(VARIABLE_PATTERN, (_, key) => {\n const value = vars[key]\n return value !== undefined ? String(value) : `{${key}}`\n })\n}\n\nasync function resolveLocale(localeParam?: Locale): Promise<Locale> {\n if (localeParam) return localeParam\n\n const headersList = await headers()\n return headersList.get('x-locale') || _config.defaultLocale\n}\n\nfunction resolveTemplate(translations: Translations, locale: Locale): string {\n const template = translations[locale]\n if (template) return template\n\n const fallback = translations.en ?? Object.values(translations)[0]\n if (fallback) return fallback\n\n throw new Error(\n `No translation found for locale \"${locale}\". Available: ${Object.keys(translations).join(', ')}`\n )\n}\n\n/**\n * Server Component translation with two languages\n * @param ko - Korean text\n * @param en - English text\n * @param vars - Variables for interpolation\n * @param locale - Override locale (optional)\n */\nexport async function it(\n ko: string,\n en: string,\n vars?: TranslationVars,\n locale?: Locale,\n): Promise<string>\n\n/**\n * Server Component translation with multiple languages\n * @param translations - Translation map with locale keys\n * @param vars - Variables for interpolation\n * @param locale - Override locale (optional)\n */\nexport async function it(\n translations: Translations,\n vars?: TranslationVars,\n locale?: Locale,\n): Promise<string>\n\nexport async function it(\n first: string | Translations,\n second?: string | TranslationVars,\n third?: TranslationVars | Locale,\n fourth?: Locale,\n): Promise<string> {\n // object syntax: it({ ko, en, ... }, vars?, locale?)\n if (typeof first === 'object') {\n const translations = first\n const vars = second as TranslationVars | undefined\n const locale = await resolveLocale(third as Locale | undefined)\n return interpolate(resolveTemplate(translations, locale), vars)\n }\n\n // shorthand syntax: it('한글', 'English', vars?, locale?)\n const ko = first\n const en = second as string\n const vars = third as TranslationVars | undefined\n const locale = await resolveLocale(fourth)\n\n const translations: Translations = { ko, en }\n return interpolate(resolveTemplate(translations, locale), vars)\n}\n\n// language pair helpers\ntype PairFunction = (\n text1: string,\n text2: string,\n vars?: TranslationVars,\n locale?: Locale,\n) => Promise<string>\n\nfunction createPair(lang1: Locale, lang2: Locale): PairFunction {\n return async (text1, text2, vars, locale) => {\n const translations: Translations = {\n [lang1]: text1,\n [lang2]: text2,\n }\n return it(translations, vars, locale)\n }\n}\n\nexport const it_ja = createPair('ko', 'ja')\nexport const it_zh = createPair('ko', 'zh')\nexport const it_es = createPair('ko', 'es')\nexport const it_fr = createPair('ko', 'fr')\nexport const it_de = createPair('ko', 'de')\n\nexport const en_ja = createPair('en', 'ja')\nexport const en_zh = createPair('en', 'zh')\nexport const en_es = createPair('en', 'es')\nexport const en_fr = createPair('en', 'fr')\nexport const en_de = createPair('en', 'de')\n\nexport const ja_zh = createPair('ja', 'zh')\nexport const ja_es = createPair('ja', 'es')\nexport const zh_es = createPair('zh', 'es')\n"]}
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "inline-i18n-multi-next",
3
+ "version": "0.1.0",
4
+ "description": "Next.js integration for inline-i18n-multi",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ },
14
+ "./server": {
15
+ "types": "./dist/server.d.ts",
16
+ "import": "./dist/server.mjs",
17
+ "require": "./dist/server.js"
18
+ },
19
+ "./client": {
20
+ "types": "./dist/client.d.ts",
21
+ "import": "./dist/client.mjs",
22
+ "require": "./dist/client.js"
23
+ },
24
+ "./middleware": {
25
+ "types": "./dist/middleware.d.ts",
26
+ "import": "./dist/middleware.mjs",
27
+ "require": "./dist/middleware.js"
28
+ }
29
+ },
30
+ "files": [
31
+ "dist"
32
+ ],
33
+ "sideEffects": false,
34
+ "keywords": [
35
+ "i18n",
36
+ "next.js",
37
+ "nextjs",
38
+ "internationalization",
39
+ "translation",
40
+ "inline"
41
+ ],
42
+ "author": "exiivy98",
43
+ "license": "MIT",
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "https://github.com/exiivy98/inline-i18n-multi.git",
47
+ "directory": "packages/next"
48
+ },
49
+ "peerDependencies": {
50
+ "next": "^13.0.0 || ^14.0.0 || ^15.0.0",
51
+ "react": "^18.0.0 || ^19.0.0"
52
+ },
53
+ "dependencies": {
54
+ "inline-i18n-multi": "0.1.0",
55
+ "inline-i18n-multi-react": "0.1.0"
56
+ },
57
+ "devDependencies": {
58
+ "@types/react": "^19.0.2",
59
+ "next": "^15.1.3",
60
+ "react": "^19.0.0",
61
+ "tsup": "^8.3.5",
62
+ "typescript": "^5.7.2",
63
+ "vitest": "^2.1.8"
64
+ },
65
+ "scripts": {
66
+ "build": "tsup",
67
+ "dev": "tsup --watch",
68
+ "test": "vitest",
69
+ "lint": "eslint src",
70
+ "typecheck": "tsc --noEmit",
71
+ "clean": "rm -rf dist"
72
+ }
73
+ }