@ubean/i18n 0.2.2 → 0.3.1

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.
@@ -0,0 +1,3 @@
1
+ import { a as switchLocalePath, c as HonoLocalePath, d as I18nRoutingStrategy, f as LocaleRoutingConfig, i as localizePath, l as I18nLocaleMeta, n as extractLocaleFromPath, o as toVueRouterLocalePath, r as getVueLocaleParam, s as CompiledLocalePath, t as compileLocalePaths } from "./paths-CJVBLGJS.js";
2
+ import { a as parseLocaleCookie, i as detectLocaleFromAcceptLanguage, n as LocaleHeadTags, o as serializeLocaleCookie, r as buildLocaleHead, t as LocaleHeadInput } from "./head-CT8nH37d.js";
3
+ export { type CompiledLocalePath, type HonoLocalePath, type I18nLocaleMeta, type I18nRoutingStrategy, type LocaleHeadInput, type LocaleHeadTags, type LocaleRoutingConfig, buildLocaleHead, compileLocalePaths, detectLocaleFromAcceptLanguage, extractLocaleFromPath, getVueLocaleParam, localizePath, parseLocaleCookie, serializeLocaleCookie, switchLocalePath, toVueRouterLocalePath };
@@ -0,0 +1,3 @@
1
+ import { a as extractLocaleFromPath, c as switchLocalePath, i as compileLocalePaths, l as toVueRouterLocalePath, n as parseLocaleCookie, o as getVueLocaleParam, r as serializeLocaleCookie, s as localizePath, t as detectLocaleFromAcceptLanguage } from "./detect-BIURd4aL.js";
2
+ import { t as buildLocaleHead } from "./head-BzEFwnlD.js";
3
+ export { buildLocaleHead, compileLocalePaths, detectLocaleFromAcceptLanguage, extractLocaleFromPath, getVueLocaleParam, localizePath, parseLocaleCookie, serializeLocaleCookie, switchLocalePath, toVueRouterLocalePath };
@@ -0,0 +1,145 @@
1
+ //#region src/paths.ts
2
+ function escapeRegex(code) {
3
+ return code.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4
+ }
5
+ function joinCodes(codes) {
6
+ return codes.map(escapeRegex).join("|");
7
+ }
8
+ function normalizePath(path) {
9
+ if (!path || path === "") return "/";
10
+ const withSlash = path.startsWith("/") ? path : `/${path}`;
11
+ if (withSlash.length > 1 && withSlash.endsWith("/")) return withSlash.slice(0, -1);
12
+ return withSlash;
13
+ }
14
+ /**
15
+ * vue-router locale param segment for the given strategy.
16
+ *
17
+ * - `prefix_except_default`: `:locale(zh)?` (default unprefixed; `/en/about` 不匹配)
18
+ * - `prefix`: `:locale(en|zh)` (required)
19
+ * - `prefix_and_default`: `:locale(en|zh)?` (`/about` 与 `/en/about` 都匹配)
20
+ * - `no_prefix`: empty
21
+ */
22
+ function getVueLocaleParam(cfg) {
23
+ const { strategy, defaultLocale, locales } = cfg;
24
+ const others = locales.filter((c) => c !== defaultLocale);
25
+ switch (strategy) {
26
+ case "no_prefix": return "";
27
+ case "prefix": return locales.length === 0 ? "" : `:locale(${joinCodes(locales)})`;
28
+ case "prefix_except_default":
29
+ if (others.length === 0) return "";
30
+ return `:locale(${joinCodes(others)})?`;
31
+ case "prefix_and_default":
32
+ if (locales.length === 0) return "";
33
+ return `:locale(${joinCodes(locales)})?`;
34
+ default: return "";
35
+ }
36
+ }
37
+ /** Apply a vue-router locale param to a page path (`/` / `/about` / catch-all). */
38
+ function toVueRouterLocalePath(pagePath, localeParam) {
39
+ if (!localeParam) return pagePath;
40
+ const path = normalizePath(pagePath);
41
+ if (path === "/") return `/${localeParam}`;
42
+ return `/${localeParam}${path}`;
43
+ }
44
+ function extractLocaleFromPath(path, localeCodes) {
45
+ const normalized = normalizePath(path);
46
+ const segments = normalized.split("/").filter(Boolean);
47
+ const first = segments[0];
48
+ if (first && localeCodes.includes(first)) {
49
+ const rest = segments.slice(1).join("/");
50
+ return {
51
+ locale: first,
52
+ pathWithoutLocale: rest ? `/${rest}` : "/"
53
+ };
54
+ }
55
+ return {
56
+ locale: null,
57
+ pathWithoutLocale: normalized
58
+ };
59
+ }
60
+ function localizePath(path, locale, cfg) {
61
+ const { pathWithoutLocale } = extractLocaleFromPath(path, cfg.locales);
62
+ const clean = pathWithoutLocale;
63
+ const suffix = clean === "/" ? "" : clean;
64
+ switch (cfg.strategy) {
65
+ case "no_prefix": return clean;
66
+ case "prefix": return `/${locale}${suffix}`;
67
+ case "prefix_except_default":
68
+ case "prefix_and_default":
69
+ if (locale === cfg.defaultLocale) return clean;
70
+ return `/${locale}${suffix}`;
71
+ default: return clean;
72
+ }
73
+ }
74
+ function switchLocalePath(locale, currentPath, cfg) {
75
+ return localizePath(currentPath, locale, cfg);
76
+ }
77
+ function honoPathsFor(pagePath, cfg) {
78
+ const path = normalizePath(pagePath);
79
+ const suffix = path === "/" ? "" : path;
80
+ const { defaultLocale, locales, strategy } = cfg;
81
+ const result = [];
82
+ const push = (mounted, locale, isDefault) => {
83
+ result.push({
84
+ path: mounted || "/",
85
+ locale,
86
+ isDefault
87
+ });
88
+ };
89
+ switch (strategy) {
90
+ case "no_prefix":
91
+ push(path, defaultLocale, true);
92
+ break;
93
+ case "prefix":
94
+ for (const locale of locales) push(`/${locale}${suffix}`, locale, locale === defaultLocale);
95
+ break;
96
+ case "prefix_except_default":
97
+ push(path, defaultLocale, true);
98
+ for (const locale of locales) {
99
+ if (locale === defaultLocale) continue;
100
+ push(`/${locale}${suffix}`, locale, false);
101
+ }
102
+ break;
103
+ case "prefix_and_default":
104
+ push(path, defaultLocale, true);
105
+ for (const locale of locales) push(`/${locale}${suffix}`, locale, locale === defaultLocale);
106
+ break;
107
+ default: push(path, defaultLocale, true);
108
+ }
109
+ return result;
110
+ }
111
+ function compileLocalePaths(pagePath, cfg) {
112
+ return {
113
+ vuePath: toVueRouterLocalePath(pagePath, getVueLocaleParam(cfg)),
114
+ hono: honoPathsFor(pagePath, cfg)
115
+ };
116
+ }
117
+ //#endregion
118
+ //#region src/detect.ts
119
+ function detectLocaleFromAcceptLanguage(header, locales, fallback) {
120
+ if (!header) return fallback;
121
+ const requested = header.split(",").map((lang) => {
122
+ const [code, q = "q=1.0"] = lang.trim().split(";");
123
+ const quality = parseFloat(q.replace("q=", "")) || 0;
124
+ return {
125
+ code: code.trim().toLowerCase(),
126
+ quality
127
+ };
128
+ }).sort((a, b) => b.quality - a.quality);
129
+ const lower = locales.map((l) => ({
130
+ orig: l,
131
+ lower: l.toLowerCase()
132
+ }));
133
+ for (const { code } of requested) for (const loc of lower) if (code === loc.lower || code.startsWith(`${loc.lower}-`)) return loc.orig;
134
+ return fallback;
135
+ }
136
+ function parseLocaleCookie(cookieHeader, cookieName) {
137
+ if (!cookieHeader) return null;
138
+ const match = cookieHeader.match(new RegExp(`(?:^|;\\s*)${cookieName}=([^;]+)`));
139
+ return match ? decodeURIComponent(match[1]) : null;
140
+ }
141
+ function serializeLocaleCookie(cookieName, locale) {
142
+ return `${cookieName}=${encodeURIComponent(locale)}; Path=/; SameSite=Lax`;
143
+ }
144
+ //#endregion
145
+ export { extractLocaleFromPath as a, switchLocalePath as c, compileLocalePaths as i, toVueRouterLocalePath as l, parseLocaleCookie as n, getVueLocaleParam as o, serializeLocaleCookie as r, localizePath as s, detectLocaleFromAcceptLanguage as t };
@@ -0,0 +1,84 @@
1
+ import { a as extractLocaleFromPath, s as localizePath } from "./detect-BIURd4aL.js";
2
+ //#region src/head.ts
3
+ function abs(baseUrl, path) {
4
+ if (!baseUrl) return path;
5
+ return `${baseUrl.replace(/\/+$/, "")}${path}`;
6
+ }
7
+ function ogLocale(languageOrCode) {
8
+ return languageOrCode.replace(/-/g, "_");
9
+ }
10
+ function pagePathWithoutLocale(path, locales) {
11
+ return extractLocaleFromPath(path, locales).pathWithoutLocale;
12
+ }
13
+ /**
14
+ * Build hreflang / canonical / og:locale tags.
15
+ * `prefix_and_default` 下默认语言的 canonical 指向无前缀 URL,避免双 URL 重复收录。
16
+ */
17
+ function buildLocaleHead(input) {
18
+ const current = input.locales.find((l) => l.code === input.locale);
19
+ const lang = current?.language || input.locale;
20
+ const dir = current?.dir || "ltr";
21
+ const clean = pagePathWithoutLocale(input.path, input.routing.locales);
22
+ const codes = input.routing.locales;
23
+ const link = [];
24
+ const meta = [];
25
+ const languageGroups = /* @__PURE__ */ new Map();
26
+ for (const loc of input.locales) {
27
+ const href = abs(input.baseUrl || "", localizePath(clean, loc.code, input.routing));
28
+ const hreflang = loc.language || loc.code;
29
+ link.push({
30
+ rel: "alternate",
31
+ href,
32
+ hreflang
33
+ });
34
+ const group = hreflang.split("-")[0];
35
+ if (!languageGroups.has(group)) languageGroups.set(group, loc);
36
+ }
37
+ for (const [group, loc] of languageGroups) {
38
+ if (link.some((l) => l.hreflang === group)) continue;
39
+ link.push({
40
+ rel: "alternate",
41
+ href: abs(input.baseUrl || "", localizePath(clean, loc.code, input.routing)),
42
+ hreflang: group
43
+ });
44
+ }
45
+ const defaultLoc = input.locales.find((l) => l.isDefault) || input.locales.find((l) => l.code === input.routing.defaultLocale);
46
+ if (defaultLoc) {
47
+ const defaultUnprefixed = abs(input.baseUrl || "", localizePath(clean, defaultLoc.code, {
48
+ ...input.routing,
49
+ locales: codes,
50
+ strategy: "prefix_except_default"
51
+ }));
52
+ link.push({
53
+ rel: "alternate",
54
+ href: defaultUnprefixed,
55
+ hreflang: "x-default"
56
+ });
57
+ const canonicalPath = input.locale === defaultLoc.code && input.routing.strategy === "prefix_and_default" ? defaultUnprefixed : abs(input.baseUrl || "", localizePath(clean, input.locale, input.routing));
58
+ link.push({
59
+ rel: "canonical",
60
+ href: canonicalPath
61
+ });
62
+ }
63
+ meta.push({
64
+ property: "og:locale",
65
+ content: ogLocale(lang)
66
+ });
67
+ for (const loc of input.locales) {
68
+ if (loc.code === input.locale) continue;
69
+ meta.push({
70
+ property: "og:locale:alternate",
71
+ content: ogLocale(loc.language || loc.code)
72
+ });
73
+ }
74
+ return {
75
+ htmlAttrs: {
76
+ lang,
77
+ dir
78
+ },
79
+ link,
80
+ meta
81
+ };
82
+ }
83
+ //#endregion
84
+ export { buildLocaleHead as t };
@@ -0,0 +1,36 @@
1
+ import { f as LocaleRoutingConfig, l as I18nLocaleMeta } from "./paths-CJVBLGJS.js";
2
+ //#region src/detect.d.ts
3
+ declare function detectLocaleFromAcceptLanguage(header: string | undefined, locales: string[], fallback: string): string;
4
+ declare function parseLocaleCookie(cookieHeader: string | undefined, cookieName: string): string | null;
5
+ declare function serializeLocaleCookie(cookieName: string, locale: string): string;
6
+ //#endregion
7
+ //#region src/head.d.ts
8
+ interface LocaleHeadInput {
9
+ path: string;
10
+ locale: string;
11
+ locales: I18nLocaleMeta[];
12
+ routing: LocaleRoutingConfig;
13
+ baseUrl?: string;
14
+ }
15
+ interface LocaleHeadTags {
16
+ htmlAttrs: {
17
+ lang: string;
18
+ dir: 'ltr' | 'rtl';
19
+ };
20
+ link: Array<{
21
+ rel: string;
22
+ href: string;
23
+ hreflang?: string;
24
+ }>;
25
+ meta: Array<{
26
+ property: string;
27
+ content: string;
28
+ }>;
29
+ }
30
+ /**
31
+ * Build hreflang / canonical / og:locale tags.
32
+ * `prefix_and_default` 下默认语言的 canonical 指向无前缀 URL,避免双 URL 重复收录。
33
+ */
34
+ declare function buildLocaleHead(input: LocaleHeadInput): LocaleHeadTags;
35
+ //#endregion
36
+ export { parseLocaleCookie as a, detectLocaleFromAcceptLanguage as i, LocaleHeadTags as n, serializeLocaleCookie as o, buildLocaleHead as r, LocaleHeadInput as t };
package/dist/index.d.ts CHANGED
@@ -1,96 +1,59 @@
1
- //#region src/index.d.ts
2
- type I18nRoutingStrategy = 'prefix' | 'prefix_except_default' | 'prefix_and_default' | 'no_prefix';
3
- type DateTimeFormatStyle = 'short' | 'medium' | 'long' | 'full';
4
- type NumberFormatStyle = 'decimal' | 'percent' | 'currency';
5
- type ListFormatStyle = 'conjunction' | 'disjunction' | 'unit';
6
- type RelativeTimeUnit = 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year';
7
- interface I18nConfig {
8
- defaultLocale: string;
9
- strategy: I18nRoutingStrategy;
10
- locales: string[];
11
- }
12
- interface LocaleMessages {
13
- [key: string]: string | LocaleMessages;
1
+ import { a as switchLocalePath, c as HonoLocalePath, d as I18nRoutingStrategy, f as LocaleRoutingConfig, i as localizePath, l as I18nLocaleMeta, n as extractLocaleFromPath, o as toVueRouterLocalePath, r as getVueLocaleParam, s as CompiledLocalePath, t as compileLocalePaths, u as I18nMiddlewareOptions } from "./paths-CJVBLGJS.js";
2
+ import { a as parseLocaleCookie, i as detectLocaleFromAcceptLanguage, n as LocaleHeadTags, o as serializeLocaleCookie, r as buildLocaleHead, t as LocaleHeadInput } from "./head-CT8nH37d.js";
3
+ import { createI18nMiddleware, getPathWithoutLocale, getRequestLocale as getRequestLocale$1 } from "./routing.js";
4
+ import { LocaleMessage } from "@intlify/core";
5
+ //#region src/context.d.ts
6
+ type LocaleMessages = LocaleMessage;
7
+ declare function createI18nCoreContext(locale: string, fallback: string, messages: Record<string, LocaleMessages>): import("@intlify/core").CoreContext<string, Record<string, LocaleMessages>, {}, {}, string | import("@intlify/core").LocaleDetector<any[]>, string, string>;
8
+ type I18nCoreContext = ReturnType<typeof createI18nCoreContext>;
9
+ interface I18nRequestScope {
10
+ locale: string;
11
+ fallbackLocale: string;
12
+ ctx: I18nCoreContext;
13
+ t?: (key: string, ...args: unknown[]) => string;
14
+ d?: (value: Date | number | string, ...args: unknown[]) => string;
15
+ n?: (value: number, ...args: unknown[]) => string;
14
16
  }
15
- interface LocaleDefinition {
16
- code: string;
17
- messages: LocaleMessages;
17
+ type LocaleLoader = (code: string) => Promise<unknown>;
18
+ declare function setFallbackLocale(code: string): void;
19
+ declare function getFallbackLocale(): string;
20
+ declare function setLocaleMessages(code: string, messages: LocaleMessages): void;
21
+ declare function getLocaleMessages(code: string): LocaleMessages | undefined;
22
+ declare function mergeLocaleMessages(code: string, messages: LocaleMessages): LocaleMessages;
23
+ declare function setLocaleMeta(code: string, meta: {
18
24
  name?: string;
19
25
  dir?: 'ltr' | 'rtl';
26
+ language?: string;
20
27
  isDefault?: boolean;
21
- }
22
- type LocaleChangeCallback = (locale: string) => void;
23
- type MissingKeyHandler = (locale: string, key: string) => void;
24
- interface NumberFormatOptions extends Intl.NumberFormatOptions {
25
- style?: NumberFormatStyle;
26
- }
27
- interface I18nInstance {
28
- locale: string;
29
- fallbackLocale: string;
30
- availableLocales: string[];
31
- t(key: string, params?: Record<string, string | number>): string;
32
- d(value: Date | number, style?: DateTimeFormatStyle, options?: Intl.DateTimeFormatOptions): string;
33
- n(value: number, style?: NumberFormatStyle, options?: NumberFormatOptions): string;
34
- c(value: number, currency: string, options?: Intl.NumberFormatOptions): string;
35
- relativeTime(value: number, unit: RelativeTimeUnit, options?: Intl.RelativeTimeFormatOptions): string;
36
- list(items: string[], style?: ListFormatStyle, options?: Intl.ListFormatOptions): string;
37
- setLocale(locale: string): void;
38
- getLocale(): string;
39
- addLocale(code: string, messages: LocaleMessages, options?: {
40
- name?: string;
41
- dir?: 'ltr' | 'rtl';
42
- }): void;
43
- mergeLocale(code: string, messages: LocaleMessages): void;
44
- detectLocale(acceptLanguage?: string): string;
45
- onLocaleChange(callback: LocaleChangeCallback): () => void;
46
- getLocaleDir(locale?: string): 'ltr' | 'rtl';
47
- getLocaleName(locale?: string): string | undefined;
48
- onMissingKey(handler: MissingKeyHandler): () => void;
49
- }
50
- declare function defineLocale(definition: LocaleDefinition): LocaleDefinition;
51
- declare function setI18nConfig(config: Partial<I18nConfig>): void;
52
- declare function getI18nConfig(): I18nConfig;
53
- declare function getDefaultLocale(): string;
54
- declare function localizePath(path: string, locale?: string): string;
55
- declare function switchLocalePath(newLocale: string, currentPath?: string): string;
56
- declare function extractLocaleFromPath(path: string): {
57
- locale: string | null;
58
- pathWithoutLocale: string;
59
- };
60
- declare function useI18n(): I18nInstance;
61
- declare function t(key: string, params?: Record<string, string | number>): string;
62
- declare function setLocale(locale: string): void;
63
- declare function getLocale(): string;
64
- declare function getRegisteredLocales(): string[];
65
- interface LocaleMeta {
28
+ }): void;
29
+ declare function getLocaleMeta(code: string): {
30
+ name?: string;
31
+ dir: "ltr" | "rtl";
32
+ language?: string;
33
+ isDefault?: boolean;
34
+ } | undefined;
35
+ declare function listLocaleCodes(): string[];
36
+ declare function getRegisteredLocalesMeta(): Array<{
66
37
  code: string;
67
38
  name?: string;
68
39
  dir: 'ltr' | 'rtl';
40
+ language?: string;
69
41
  isDefault?: boolean;
70
- }
71
- /**
72
- * Returns metadata for all registered locales (without messages).
73
- * Used by SSR to serialize the full locale list so the client can
74
- * register all available locales during hydration — preventing
75
- * `availableLocales` hydration mismatches.
76
- */
77
- declare function getRegisteredLocalesMeta(): LocaleMeta[];
78
- declare function getLocaleMessages(locale?: string): LocaleMessages | undefined;
79
- declare function clearLocales(): void;
80
- declare function onLocaleChange(callback: LocaleChangeCallback): () => void;
42
+ }>;
81
43
  declare function getLocaleDir(locale?: string): 'ltr' | 'rtl';
82
44
  declare function getLocaleName(locale?: string): string | undefined;
83
- declare function detectLocale(acceptLanguage?: string): string;
84
- declare function addLocale(code: string, messages: LocaleMessages, options?: {
85
- name?: string;
86
- dir?: 'ltr' | 'rtl';
87
- }): void;
88
- declare function mergeLocale(code: string, messages: LocaleMessages): void;
89
- declare function detectBrowserLocale(): string;
90
- declare function formatDate(value: Date | number, style?: DateTimeFormatStyle, options?: Intl.DateTimeFormatOptions): string;
91
- declare function formatNumber(value: number, style?: NumberFormatStyle, options?: NumberFormatOptions): string;
92
- declare function formatCurrency(value: number, currency: string, options?: Intl.NumberFormatOptions): string;
93
- declare function formatRelativeTime(value: number, unit: RelativeTimeUnit, options?: Intl.RelativeTimeFormatOptions): string;
94
- declare function formatList(items: string[], style?: ListFormatStyle, options?: Intl.ListFormatOptions): string;
45
+ /**
46
+ * Vite 图里的 `ubean:locales` 在求值时注册;Node 侧中间件通过
47
+ * `ensureLocaleMessages` 调用,避免 `import('ubean:locales')` 在 CLI 进程里 404。
48
+ */
49
+ declare function registerLocaleLoader(loader?: LocaleLoader): void;
50
+ declare function ensureLocaleMessages(locale: string, fallback?: string): Promise<void>;
51
+ declare function createRequestContext(locale: string, fallback?: string): I18nCoreContext;
52
+ declare function runWithI18n<T>(scope: I18nRequestScope, fn: () => T): T;
53
+ declare function getI18nScope(): I18nRequestScope | undefined;
54
+ declare function getRequestLocale(): string;
55
+ declare function t(key: string, ...args: unknown[]): string;
56
+ declare function d(value: Date | number | string, ...args: unknown[]): string;
57
+ declare function n(value: number, ...args: unknown[]): string;
95
58
  //#endregion
96
- export { DateTimeFormatStyle, I18nConfig, I18nInstance, I18nRoutingStrategy, ListFormatStyle, LocaleChangeCallback, LocaleDefinition, LocaleMessages, LocaleMeta, MissingKeyHandler, NumberFormatOptions, NumberFormatStyle, RelativeTimeUnit, addLocale, clearLocales, defineLocale, detectBrowserLocale, detectLocale, extractLocaleFromPath, formatCurrency, formatDate, formatList, formatNumber, formatRelativeTime, getDefaultLocale, getI18nConfig, getLocale, getLocaleDir, getLocaleMessages, getLocaleName, getRegisteredLocales, getRegisteredLocalesMeta, localizePath, mergeLocale, onLocaleChange, setI18nConfig, setLocale, switchLocalePath, t, useI18n };
59
+ export { type CompiledLocalePath, type HonoLocalePath, type I18nCoreContext, type I18nLocaleMeta, type I18nMiddlewareOptions, type I18nRequestScope, type I18nRoutingStrategy, type LocaleHeadInput, type LocaleHeadTags, type LocaleMessages, type LocaleRoutingConfig, buildLocaleHead, compileLocalePaths, createI18nMiddleware, createRequestContext, d, detectLocaleFromAcceptLanguage, ensureLocaleMessages, extractLocaleFromPath, getRequestLocale as getAlsLocale, getFallbackLocale, getI18nScope, getLocaleDir, getLocaleMessages, getLocaleMeta, getLocaleName, getPathWithoutLocale, getRegisteredLocalesMeta, getRequestLocale$1 as getRequestLocale, getVueLocaleParam, listLocaleCodes, localizePath, mergeLocaleMessages, n, parseLocaleCookie, registerLocaleLoader, runWithI18n, serializeLocaleCookie, setFallbackLocale, setLocaleMessages, setLocaleMeta, switchLocalePath, t, toVueRouterLocalePath };