@better-auth/i18n 1.5.0-beta.12 → 1.5.0-beta.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.mts +2 -1
- package/dist/index.d.mts +55 -2
- package/dist/index.mjs +8 -8
- package/dist/index.mjs.map +1 -1
- package/dist/types-m1nrvPWg.d.mts +62 -0
- package/package.json +6 -6
- package/dist/index-DFgwTnpr.d.mts +0 -109
package/dist/client.d.mts
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -1,2 +1,55 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { n as LocaleDetectionStrategy, r as TranslationDictionary, t as I18nOptions } from "./types-m1nrvPWg.mjs";
|
|
2
|
+
import * as better_call0 from "better-call";
|
|
3
|
+
import { GenericEndpointContext } from "@better-auth/core";
|
|
4
|
+
|
|
5
|
+
//#region src/index.d.ts
|
|
6
|
+
declare module "@better-auth/core" {
|
|
7
|
+
interface BetterAuthPluginRegistry<AuthOptions, Options> {
|
|
8
|
+
i18n: {
|
|
9
|
+
creator: typeof i18n;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* i18n plugin for Better Auth
|
|
15
|
+
*
|
|
16
|
+
* Translates error messages based on detected locale.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { betterAuth } from "better-auth";
|
|
21
|
+
* import { i18n } from "@better-auth/i18n";
|
|
22
|
+
*
|
|
23
|
+
* export const auth = betterAuth({
|
|
24
|
+
* plugins: [
|
|
25
|
+
* i18n({
|
|
26
|
+
* translations: {
|
|
27
|
+
* en: { USER_NOT_FOUND: "User not found" },
|
|
28
|
+
* fr: { USER_NOT_FOUND: "Utilisateur non trouvé" },
|
|
29
|
+
* },
|
|
30
|
+
* detection: ["header", "cookie"],
|
|
31
|
+
* }),
|
|
32
|
+
* ],
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
declare const i18n: <Locales extends string[]>(options: I18nOptions<Locales>) => {
|
|
37
|
+
id: "i18n";
|
|
38
|
+
hooks: {
|
|
39
|
+
after: {
|
|
40
|
+
matcher: () => true;
|
|
41
|
+
handler: (inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<void>;
|
|
42
|
+
}[];
|
|
43
|
+
};
|
|
44
|
+
options: {
|
|
45
|
+
translations: { [Locale in Locales[number]]: TranslationDictionary };
|
|
46
|
+
defaultLocale: Locales[number];
|
|
47
|
+
detection: LocaleDetectionStrategy[];
|
|
48
|
+
localeCookie: string;
|
|
49
|
+
userLocaleField: string;
|
|
50
|
+
getLocale?: ((ctx: GenericEndpointContext) => Locales[number] | Promise<Locales[number] | null> | null) | undefined;
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
//#endregion
|
|
54
|
+
export { type I18nOptions, type LocaleDetectionStrategy, type TranslationDictionary, i18n };
|
|
55
|
+
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -53,15 +53,15 @@ const i18n = (options) => {
|
|
|
53
53
|
userLocaleField: "locale",
|
|
54
54
|
...options
|
|
55
55
|
};
|
|
56
|
-
async function detectLocale(
|
|
56
|
+
async function detectLocale(ctx) {
|
|
57
57
|
for (const strategy of opts.detection) {
|
|
58
58
|
let locale = null;
|
|
59
59
|
switch (strategy) {
|
|
60
60
|
case "header":
|
|
61
|
-
locale = parseAcceptLanguage(headers?.get("Accept-Language") ?? null).find((l) => availableLocales.includes(l)) ?? null;
|
|
61
|
+
locale = parseAcceptLanguage(ctx.headers?.get("Accept-Language") ?? null).find((l) => availableLocales.includes(l)) ?? null;
|
|
62
62
|
break;
|
|
63
63
|
case "cookie": {
|
|
64
|
-
const cookieHeader = headers?.get("Cookie");
|
|
64
|
+
const cookieHeader = ctx.headers?.get("Cookie");
|
|
65
65
|
if (cookieHeader) {
|
|
66
66
|
const cookieLocale = parseCookies(cookieHeader).get(opts.localeCookie);
|
|
67
67
|
if (cookieLocale && availableLocales.includes(cookieLocale)) locale = cookieLocale;
|
|
@@ -69,14 +69,14 @@ const i18n = (options) => {
|
|
|
69
69
|
break;
|
|
70
70
|
}
|
|
71
71
|
case "session":
|
|
72
|
-
if (ctx.session?.user) {
|
|
73
|
-
const userLocale = ctx.session.user[opts.userLocaleField];
|
|
72
|
+
if (ctx.context.session?.user) {
|
|
73
|
+
const userLocale = ctx.context.session.user[opts.userLocaleField];
|
|
74
74
|
if (typeof userLocale === "string" && availableLocales.includes(userLocale)) locale = userLocale;
|
|
75
75
|
}
|
|
76
76
|
break;
|
|
77
77
|
case "callback":
|
|
78
|
-
if (opts.getLocale
|
|
79
|
-
const callbackLocale = await opts.getLocale(
|
|
78
|
+
if (opts.getLocale) {
|
|
79
|
+
const callbackLocale = await opts.getLocale(ctx);
|
|
80
80
|
if (callbackLocale && availableLocales.includes(callbackLocale)) locale = callbackLocale;
|
|
81
81
|
}
|
|
82
82
|
break;
|
|
@@ -94,7 +94,7 @@ const i18n = (options) => {
|
|
|
94
94
|
if (!isAPIError(returned)) return;
|
|
95
95
|
const errorCode = returned.body?.code;
|
|
96
96
|
if (typeof errorCode !== "string") return;
|
|
97
|
-
const locale = await detectLocale(ctx
|
|
97
|
+
const locale = await detectLocale(ctx);
|
|
98
98
|
const translation = opts.translations[locale]?.[errorCode];
|
|
99
99
|
if (!translation) return;
|
|
100
100
|
throw new APIError(returned.status, {
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type {\n\tBetterAuthPlugin,\n\tGenericEndpointContext,\n} from \"@better-auth/core\";\nimport { APIError, createAuthMiddleware, isAPIError } from \"better-auth/api\";\nimport { parseCookies } from \"better-auth/cookies\";\nimport type { I18nOptions, LocaleDetectionStrategy } from \"./types\";\n\nexport type {\n\tI18nOptions,\n\tLocaleDetectionStrategy,\n\tTranslationDictionary,\n} from \"./types\";\n\ndeclare module \"@better-auth/core\" {\n\tinterface BetterAuthPluginRegistry<AuthOptions, Options> {\n\t\ti18n: {\n\t\t\tcreator: typeof i18n;\n\t\t};\n\t}\n}\n\n/**\n * Parse Accept-Language header and return locales sorted by quality\n */\nfunction parseAcceptLanguage(header: string | null): string[] {\n\tif (!header) return [];\n\treturn header\n\t\t.split(\",\")\n\t\t.map((part) => {\n\t\t\tconst [localeStr, quality = \"q=1\"] = part.trim().split(\";\");\n\t\t\tconst q = Number.parseFloat(quality.replace(\"q=\", \"\"));\n\t\t\t// Get base locale (e.g., \"en\" from \"en-US\")\n\t\t\tconst locale = localeStr?.trim().split(\"-\")[0] ?? \"\";\n\t\t\treturn { locale, q };\n\t\t})\n\t\t.filter((item) => item.locale.length > 0)\n\t\t.sort((a, b) => b.q - a.q)\n\t\t.map((item) => item.locale);\n}\n\n/**\n * i18n plugin for Better Auth\n *\n * Translates error messages based on detected locale.\n *\n * @example\n * ```ts\n * import { betterAuth } from \"better-auth\";\n * import { i18n } from \"@better-auth/i18n\";\n *\n * export const auth = betterAuth({\n * plugins: [\n * i18n({\n * translations: {\n * en: { USER_NOT_FOUND: \"User not found\" },\n * fr: { USER_NOT_FOUND: \"Utilisateur non trouvé\" },\n * },\n * detection: [\"header\", \"cookie\"],\n * }),\n * ],\n * });\n * ```\n */\nexport const i18n = <Locales extends string[]>(\n\toptions: I18nOptions<Locales>,\n) => {\n\tconst availableLocales = Object.keys(options.translations);\n\n\tlet defaultLocale: Locales[number];\n\tif (\n\t\toptions.defaultLocale &&\n\t\tavailableLocales.includes(options.defaultLocale)\n\t) {\n\t\tdefaultLocale = options.defaultLocale;\n\t} else if (availableLocales.includes(\"en\")) {\n\t\tdefaultLocale = \"en\" as Locales[number];\n\t} else if (availableLocales.length > 0) {\n\t\tdefaultLocale = availableLocales[0] as Locales[number];\n\t} else {\n\t\tthrow new Error(\n\t\t\t\"i18n plugin: translations object is empty. At least one locale must be provided.\",\n\t\t);\n\t}\n\n\tconst opts = {\n\t\tdefaultLocale,\n\t\tdetection: [\"header\"] as LocaleDetectionStrategy[],\n\t\tlocaleCookie: \"locale\",\n\t\tuserLocaleField: \"locale\",\n\t\t...options,\n\t};\n\n\tasync function detectLocale(\n\t\tctx: GenericEndpointContext,\n\t): Promise<Locales[number]> {\n\t\tfor (const strategy of opts.detection) {\n\t\t\tlet locale: Locales[number] | null = null;\n\n\t\t\tswitch (strategy) {\n\t\t\t\tcase \"header\": {\n\t\t\t\t\tconst acceptLang = ctx.headers?.get(\"Accept-Language\") ?? null;\n\t\t\t\t\tconst preferred = parseAcceptLanguage(acceptLang);\n\t\t\t\t\tlocale = preferred.find((l) => availableLocales.includes(l)) ?? null;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"cookie\": {\n\t\t\t\t\tconst cookieHeader = ctx.headers?.get(\"Cookie\");\n\t\t\t\t\tif (cookieHeader) {\n\t\t\t\t\t\tconst cookies = parseCookies(cookieHeader);\n\t\t\t\t\t\tconst cookieLocale = cookies.get(opts.localeCookie);\n\t\t\t\t\t\tif (cookieLocale && availableLocales.includes(cookieLocale)) {\n\t\t\t\t\t\t\tlocale = cookieLocale;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"session\": {\n\t\t\t\t\tif (ctx.context.session?.user) {\n\t\t\t\t\t\tconst userLocale = (\n\t\t\t\t\t\t\tctx.context.session.user as Record<string, unknown>\n\t\t\t\t\t\t)[opts.userLocaleField];\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypeof userLocale === \"string\" &&\n\t\t\t\t\t\t\tavailableLocales.includes(userLocale)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tlocale = userLocale;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"callback\": {\n\t\t\t\t\tif (opts.getLocale) {\n\t\t\t\t\t\tconst callbackLocale = await opts.getLocale(ctx);\n\t\t\t\t\t\tif (callbackLocale && availableLocales.includes(callbackLocale)) {\n\t\t\t\t\t\t\tlocale = callbackLocale;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (locale) return locale;\n\t\t}\n\n\t\treturn opts.defaultLocale;\n\t}\n\n\treturn {\n\t\tid: \"i18n\",\n\t\thooks: {\n\t\t\tafter: [\n\t\t\t\t{\n\t\t\t\t\tmatcher: () => true,\n\t\t\t\t\thandler: createAuthMiddleware(async (ctx) => {\n\t\t\t\t\t\tconst returned = ctx.context.returned;\n\n\t\t\t\t\t\tif (!isAPIError(returned)) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst errorCode = (returned.body as Record<string, unknown>)?.code;\n\t\t\t\t\t\tif (typeof errorCode !== \"string\") {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst locale = await detectLocale(ctx);\n\n\t\t\t\t\t\tconst translation = opts.translations[locale]?.[errorCode];\n\n\t\t\t\t\t\tif (!translation) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthrow new APIError(returned.status, {\n\t\t\t\t\t\t\tcode: errorCode,\n\t\t\t\t\t\t\tmessage: translation,\n\t\t\t\t\t\t\toriginalMessage: returned.message,\n\t\t\t\t\t\t});\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\n\t\toptions: opts,\n\t} satisfies BetterAuthPlugin;\n};\n\nexport type * from \"./types\";\n"],"mappings":";;;;;;;AAyBA,SAAS,oBAAoB,QAAiC;AAC7D,KAAI,CAAC,OAAQ,QAAO,EAAE;AACtB,QAAO,OACL,MAAM,IAAI,CACV,KAAK,SAAS;EACd,MAAM,CAAC,WAAW,UAAU,SAAS,KAAK,MAAM,CAAC,MAAM,IAAI;EAC3D,MAAM,IAAI,OAAO,WAAW,QAAQ,QAAQ,MAAM,GAAG,CAAC;AAGtD,SAAO;GAAE,QADM,WAAW,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM;GACjC;GAAG;GACnB,CACD,QAAQ,SAAS,KAAK,OAAO,SAAS,EAAE,CACxC,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,EAAE,CACzB,KAAK,SAAS,KAAK,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;AA0B7B,MAAa,QACZ,YACI;CACJ,MAAM,mBAAmB,OAAO,KAAK,QAAQ,aAAa;CAE1D,IAAI;AACJ,KACC,QAAQ,iBACR,iBAAiB,SAAS,QAAQ,cAAc,CAEhD,iBAAgB,QAAQ;UACd,iBAAiB,SAAS,KAAK,CACzC,iBAAgB;UACN,iBAAiB,SAAS,EACpC,iBAAgB,iBAAiB;KAEjC,OAAM,IAAI,MACT,mFACA;CAGF,MAAM,OAAO;EACZ;EACA,WAAW,CAAC,SAAS;EACrB,cAAc;EACd,iBAAiB;EACjB,GAAG;EACH;CAED,eAAe,aACd,KAC2B;AAC3B,OAAK,MAAM,YAAY,KAAK,WAAW;GACtC,IAAI,SAAiC;AAErC,WAAQ,UAAR;IACC,KAAK;AAGJ,cADkB,oBADC,IAAI,SAAS,IAAI,kBAAkB,IAAI,KACT,CAC9B,MAAM,MAAM,iBAAiB,SAAS,EAAE,CAAC,IAAI;AAChE;IAGD,KAAK,UAAU;KACd,MAAM,eAAe,IAAI,SAAS,IAAI,SAAS;AAC/C,SAAI,cAAc;MAEjB,MAAM,eADU,aAAa,aAAa,CACb,IAAI,KAAK,aAAa;AACnD,UAAI,gBAAgB,iBAAiB,SAAS,aAAa,CAC1D,UAAS;;AAGX;;IAGD,KAAK;AACJ,SAAI,IAAI,QAAQ,SAAS,MAAM;MAC9B,MAAM,aACL,IAAI,QAAQ,QAAQ,KACnB,KAAK;AACP,UACC,OAAO,eAAe,YACtB,iBAAiB,SAAS,WAAW,CAErC,UAAS;;AAGX;IAGD,KAAK;AACJ,SAAI,KAAK,WAAW;MACnB,MAAM,iBAAiB,MAAM,KAAK,UAAU,IAAI;AAChD,UAAI,kBAAkB,iBAAiB,SAAS,eAAe,CAC9D,UAAS;;AAGX;;AAIF,OAAI,OAAQ,QAAO;;AAGpB,SAAO,KAAK;;AAGb,QAAO;EACN,IAAI;EACJ,OAAO,EACN,OAAO,CACN;GACC,eAAe;GACf,SAAS,qBAAqB,OAAO,QAAQ;IAC5C,MAAM,WAAW,IAAI,QAAQ;AAE7B,QAAI,CAAC,WAAW,SAAS,CACxB;IAGD,MAAM,YAAa,SAAS,MAAkC;AAC9D,QAAI,OAAO,cAAc,SACxB;IAGD,MAAM,SAAS,MAAM,aAAa,IAAI;IAEtC,MAAM,cAAc,KAAK,aAAa,UAAU;AAEhD,QAAI,CAAC,YACJ;AAGD,UAAM,IAAI,SAAS,SAAS,QAAQ;KACnC,MAAM;KACN,SAAS;KACT,iBAAiB,SAAS;KAC1B,CAAC;KACD;GACF,CACD,EACD;EAED,SAAS;EACT"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { BetterAuthPluginRegistry, BetterAuthPluginRegistryIdentifier, GenericEndpointContext, UnionToIntersection } from "@better-auth/core";
|
|
2
|
+
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
type ALL_PLUGIN_ERROR_CODE_KEYS = keyof UnionToIntersection<{ [Key in Exclude<BetterAuthPluginRegistryIdentifier, "i18n">]: BetterAuthPluginRegistry<unknown, unknown>[Key] extends {
|
|
5
|
+
creator: infer C;
|
|
6
|
+
} ? C extends ((...args: any[]) => infer P) ? P extends {
|
|
7
|
+
$ERROR_CODES: infer E;
|
|
8
|
+
} ? E : {} : {} : {} }[Exclude<BetterAuthPluginRegistryIdentifier, "i18n">]>;
|
|
9
|
+
type InternalTranslationDictionary = Partial<{ [Key in ALL_PLUGIN_ERROR_CODE_KEYS]: string }>;
|
|
10
|
+
/**
|
|
11
|
+
* Translation dictionary mapping error codes to translated messages
|
|
12
|
+
*/
|
|
13
|
+
type TranslationDictionary = InternalTranslationDictionary & Record<string, string>;
|
|
14
|
+
/**
|
|
15
|
+
* Locale detection strategy
|
|
16
|
+
*/
|
|
17
|
+
type LocaleDetectionStrategy = "header" | "cookie" | "session" | "callback";
|
|
18
|
+
/**
|
|
19
|
+
* Options for the i18n plugin
|
|
20
|
+
*/
|
|
21
|
+
interface I18nOptions<Locales extends string[]> {
|
|
22
|
+
/**
|
|
23
|
+
* Translation dictionaries keyed by locale code
|
|
24
|
+
* @example
|
|
25
|
+
* {
|
|
26
|
+
* en: { USER_NOT_FOUND: "User not found" },
|
|
27
|
+
* fr: { USER_NOT_FOUND: "Utilisateur non trouvé" }
|
|
28
|
+
* }
|
|
29
|
+
*/
|
|
30
|
+
translations: { [Locale in Locales[number]]: TranslationDictionary };
|
|
31
|
+
/**
|
|
32
|
+
* Default/fallback locale when detection fails
|
|
33
|
+
* @default "en"
|
|
34
|
+
*/
|
|
35
|
+
defaultLocale?: Locales[number] | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Locale detection strategies in priority order
|
|
38
|
+
* @default ["header"]
|
|
39
|
+
*/
|
|
40
|
+
detection?: LocaleDetectionStrategy[] | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Cookie name for locale detection (when "cookie" strategy is used)
|
|
43
|
+
* @default "locale"
|
|
44
|
+
*/
|
|
45
|
+
localeCookie?: string | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* User field name for stored locale preference (when "session" strategy is used)
|
|
48
|
+
* @default "locale"
|
|
49
|
+
*/
|
|
50
|
+
userLocaleField?: string | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Custom locale detection function (when "callback" strategy is used).
|
|
53
|
+
* @example
|
|
54
|
+
* getLocale: (ctx) => {
|
|
55
|
+
* return ctx.headers?.get("X-Custom-Locale") ?? null;
|
|
56
|
+
* }
|
|
57
|
+
*/
|
|
58
|
+
getLocale?: undefined | ((ctx: GenericEndpointContext) => Promise<Locales[number] | null> | Locales[number] | null);
|
|
59
|
+
}
|
|
60
|
+
//#endregion
|
|
61
|
+
export { LocaleDetectionStrategy as n, TranslationDictionary as r, I18nOptions as t };
|
|
62
|
+
//# sourceMappingURL=types-m1nrvPWg.d.mts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-auth/i18n",
|
|
3
|
-
"version": "1.5.0-beta.
|
|
3
|
+
"version": "1.5.0-beta.15",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "i18n plugin for Better Auth - translate error messages",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -32,13 +32,13 @@
|
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"tsdown": "^0.20.
|
|
36
|
-
"@better-auth/core": "1.5.0-beta.
|
|
37
|
-
"better-auth": "1.5.0-beta.
|
|
35
|
+
"tsdown": "^0.20.3",
|
|
36
|
+
"@better-auth/core": "1.5.0-beta.15",
|
|
37
|
+
"better-auth": "1.5.0-beta.15"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"@better-auth/core": "1.5.0-beta.
|
|
41
|
-
"better-auth": "1.5.0-beta.
|
|
40
|
+
"@better-auth/core": "1.5.0-beta.15",
|
|
41
|
+
"better-auth": "1.5.0-beta.15"
|
|
42
42
|
},
|
|
43
43
|
"files": [
|
|
44
44
|
"dist"
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import * as better_call0 from "better-call";
|
|
2
|
-
import { AuthContext, BetterAuthPluginRegistry, BetterAuthPluginRegistryIdentifier, UnionToIntersection } from "@better-auth/core";
|
|
3
|
-
|
|
4
|
-
//#region src/types.d.ts
|
|
5
|
-
type ALL_PLUGIN_ERROR_CODE_KEYS = keyof UnionToIntersection<{ [Key in Exclude<BetterAuthPluginRegistryIdentifier, "i18n">]: BetterAuthPluginRegistry<unknown, unknown>[Key] extends {
|
|
6
|
-
creator: infer C;
|
|
7
|
-
} ? C extends ((...args: any[]) => infer P) ? P extends {
|
|
8
|
-
$ERROR_CODES: infer E;
|
|
9
|
-
} ? E : {} : {} : {} }[Exclude<BetterAuthPluginRegistryIdentifier, "i18n">]>;
|
|
10
|
-
type InternalTranslationDictionary = Partial<{ [Key in ALL_PLUGIN_ERROR_CODE_KEYS]: string }>;
|
|
11
|
-
/**
|
|
12
|
-
* Translation dictionary mapping error codes to translated messages
|
|
13
|
-
*/
|
|
14
|
-
type TranslationDictionary = InternalTranslationDictionary & Record<string, string>;
|
|
15
|
-
/**
|
|
16
|
-
* Locale detection strategy
|
|
17
|
-
*/
|
|
18
|
-
type LocaleDetectionStrategy = "header" | "cookie" | "session" | "callback";
|
|
19
|
-
/**
|
|
20
|
-
* Options for the i18n plugin
|
|
21
|
-
*/
|
|
22
|
-
interface I18nOptions<Locales extends string[]> {
|
|
23
|
-
/**
|
|
24
|
-
* Translation dictionaries keyed by locale code
|
|
25
|
-
* @example
|
|
26
|
-
* {
|
|
27
|
-
* en: { USER_NOT_FOUND: "User not found" },
|
|
28
|
-
* fr: { USER_NOT_FOUND: "Utilisateur non trouvé" }
|
|
29
|
-
* }
|
|
30
|
-
*/
|
|
31
|
-
translations: { [Locale in Locales[number]]: TranslationDictionary };
|
|
32
|
-
/**
|
|
33
|
-
* Default/fallback locale when detection fails
|
|
34
|
-
* @default "en"
|
|
35
|
-
*/
|
|
36
|
-
defaultLocale?: Locales[number] | undefined;
|
|
37
|
-
/**
|
|
38
|
-
* Locale detection strategies in priority order
|
|
39
|
-
* @default ["header"]
|
|
40
|
-
*/
|
|
41
|
-
detection?: LocaleDetectionStrategy[] | undefined;
|
|
42
|
-
/**
|
|
43
|
-
* Cookie name for locale detection (when "cookie" strategy is used)
|
|
44
|
-
* @default "locale"
|
|
45
|
-
*/
|
|
46
|
-
localeCookie?: string | undefined;
|
|
47
|
-
/**
|
|
48
|
-
* User field name for stored locale preference (when "session" strategy is used)
|
|
49
|
-
* @default "locale"
|
|
50
|
-
*/
|
|
51
|
-
userLocaleField?: string | undefined;
|
|
52
|
-
/**
|
|
53
|
-
* Custom locale detection function (when "callback" strategy is used)
|
|
54
|
-
* Receives request and AuthContext, return locale code or null
|
|
55
|
-
*/
|
|
56
|
-
getLocale?: undefined | ((request: Request, ctx: AuthContext) => Promise<Locales[number] | null> | Locales[number] | null);
|
|
57
|
-
}
|
|
58
|
-
//#endregion
|
|
59
|
-
//#region src/index.d.ts
|
|
60
|
-
declare module "@better-auth/core" {
|
|
61
|
-
interface BetterAuthPluginRegistry<AuthOptions, Options> {
|
|
62
|
-
i18n: {
|
|
63
|
-
creator: typeof i18n;
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* i18n plugin for Better Auth
|
|
69
|
-
*
|
|
70
|
-
* Translates error messages based on detected locale.
|
|
71
|
-
*
|
|
72
|
-
* @example
|
|
73
|
-
* ```ts
|
|
74
|
-
* import { betterAuth } from "better-auth";
|
|
75
|
-
* import { i18n } from "@better-auth/i18n";
|
|
76
|
-
*
|
|
77
|
-
* export const auth = betterAuth({
|
|
78
|
-
* plugins: [
|
|
79
|
-
* i18n({
|
|
80
|
-
* translations: {
|
|
81
|
-
* en: { USER_NOT_FOUND: "User not found" },
|
|
82
|
-
* fr: { USER_NOT_FOUND: "Utilisateur non trouvé" },
|
|
83
|
-
* },
|
|
84
|
-
* detection: ["header", "cookie"],
|
|
85
|
-
* }),
|
|
86
|
-
* ],
|
|
87
|
-
* });
|
|
88
|
-
* ```
|
|
89
|
-
*/
|
|
90
|
-
declare const i18n: <Locales extends string[]>(options: I18nOptions<Locales>) => {
|
|
91
|
-
id: "i18n";
|
|
92
|
-
hooks: {
|
|
93
|
-
after: {
|
|
94
|
-
matcher: () => true;
|
|
95
|
-
handler: (inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<void>;
|
|
96
|
-
}[];
|
|
97
|
-
};
|
|
98
|
-
options: {
|
|
99
|
-
translations: { [Locale in Locales[number]]: TranslationDictionary };
|
|
100
|
-
defaultLocale: Locales[number];
|
|
101
|
-
detection: LocaleDetectionStrategy[];
|
|
102
|
-
localeCookie: string;
|
|
103
|
-
userLocaleField: string;
|
|
104
|
-
getLocale?: ((request: Request, ctx: AuthContext) => Locales[number] | Promise<Locales[number] | null> | null) | undefined;
|
|
105
|
-
};
|
|
106
|
-
};
|
|
107
|
-
//#endregion
|
|
108
|
-
export { TranslationDictionary as i, I18nOptions as n, LocaleDetectionStrategy as r, i18n as t };
|
|
109
|
-
//# sourceMappingURL=index-DFgwTnpr.d.mts.map
|