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 +21 -0
- package/dist/chunk-7RR34VBV.mjs +45 -0
- package/dist/chunk-7RR34VBV.mjs.map +1 -0
- package/dist/client.d.mts +1 -0
- package/dist/client.d.ts +1 -0
- package/dist/client.js +116 -0
- package/dist/client.js.map +1 -0
- package/dist/client.mjs +3 -0
- package/dist/client.mjs.map +1 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +88 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +4 -0
- package/dist/index.mjs.map +1 -0
- package/dist/middleware.d.mts +31 -0
- package/dist/middleware.d.ts +31 -0
- package/dist/middleware.js +47 -0
- package/dist/middleware.js.map +1 -0
- package/dist/middleware.mjs +3 -0
- package/dist/middleware.mjs.map +1 -0
- package/dist/server.d.mts +114 -0
- package/dist/server.d.ts +114 -0
- package/dist/server.js +145 -0
- package/dist/server.js.map +1 -0
- package/dist/server.mjs +123 -0
- package/dist/server.mjs.map +1 -0
- package/package.json +73 -0
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';
|
package/dist/client.d.ts
ADDED
|
@@ -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":[]}
|
package/dist/client.mjs
ADDED
|
@@ -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":[]}
|
package/dist/index.d.mts
ADDED
|
@@ -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';
|
package/dist/index.d.ts
ADDED
|
@@ -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 @@
|
|
|
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 };
|
package/dist/server.d.ts
ADDED
|
@@ -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"]}
|
package/dist/server.mjs
ADDED
|
@@ -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":"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","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
|
+
}
|