@comvi/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.
Files changed (92) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +256 -0
  3. package/dist/_virtual/_rolldown/runtime.cjs +23 -0
  4. package/dist/client/I18nProvider.cjs +101 -0
  5. package/dist/client/I18nProvider.d.ts +84 -0
  6. package/dist/client/I18nProvider.d.ts.map +1 -0
  7. package/dist/client/I18nProvider.js +99 -0
  8. package/dist/client/index.d.ts +5 -0
  9. package/dist/client/index.d.ts.map +1 -0
  10. package/dist/client.cjs +31 -0
  11. package/dist/client.d.ts +5 -0
  12. package/dist/client.d.ts.map +1 -0
  13. package/dist/client.js +5 -0
  14. package/dist/createNextI18n.cjs +153 -0
  15. package/dist/createNextI18n.d.ts +183 -0
  16. package/dist/createNextI18n.d.ts.map +1 -0
  17. package/dist/createNextI18n.js +152 -0
  18. package/dist/index.cjs +17 -0
  19. package/dist/index.d.ts +9 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +3 -0
  22. package/dist/middleware/createMiddleware.cjs +185 -0
  23. package/dist/middleware/createMiddleware.d.ts +38 -0
  24. package/dist/middleware/createMiddleware.d.ts.map +1 -0
  25. package/dist/middleware/createMiddleware.js +184 -0
  26. package/dist/middleware/types.d.ts +87 -0
  27. package/dist/middleware/types.d.ts.map +1 -0
  28. package/dist/middleware.cjs +3 -0
  29. package/dist/middleware.d.ts +3 -0
  30. package/dist/middleware.d.ts.map +1 -0
  31. package/dist/middleware.js +2 -0
  32. package/dist/navigation.cjs +8 -0
  33. package/dist/navigation.d.ts +5 -0
  34. package/dist/navigation.d.ts.map +1 -0
  35. package/dist/navigation.js +5 -0
  36. package/dist/routing/Link.cjs +42 -0
  37. package/dist/routing/Link.d.ts +25 -0
  38. package/dist/routing/Link.d.ts.map +1 -0
  39. package/dist/routing/Link.js +39 -0
  40. package/dist/routing/context.cjs +21 -0
  41. package/dist/routing/context.d.ts +9 -0
  42. package/dist/routing/context.d.ts.map +1 -0
  43. package/dist/routing/context.js +18 -0
  44. package/dist/routing/defineRouting.cjs +141 -0
  45. package/dist/routing/defineRouting.d.ts +123 -0
  46. package/dist/routing/defineRouting.d.ts.map +1 -0
  47. package/dist/routing/defineRouting.js +139 -0
  48. package/dist/routing/hooks.cjs +104 -0
  49. package/dist/routing/hooks.d.ts +66 -0
  50. package/dist/routing/hooks.d.ts.map +1 -0
  51. package/dist/routing/hooks.js +102 -0
  52. package/dist/routing/types.d.ts +35 -0
  53. package/dist/routing/types.d.ts.map +1 -0
  54. package/dist/routing/utils.cjs +94 -0
  55. package/dist/routing/utils.d.ts +8 -0
  56. package/dist/routing/utils.d.ts.map +1 -0
  57. package/dist/routing/utils.js +91 -0
  58. package/dist/routing.cjs +5 -0
  59. package/dist/routing.d.ts +4 -0
  60. package/dist/routing.d.ts.map +1 -0
  61. package/dist/routing.js +2 -0
  62. package/dist/server/cache.cjs +69 -0
  63. package/dist/server/cache.d.ts +42 -0
  64. package/dist/server/cache.d.ts.map +1 -0
  65. package/dist/server/cache.js +66 -0
  66. package/dist/server/ensureInitialized.cjs +19 -0
  67. package/dist/server/ensureInitialized.d.ts +7 -0
  68. package/dist/server/ensureInitialized.d.ts.map +1 -0
  69. package/dist/server/ensureInitialized.js +19 -0
  70. package/dist/server/getI18n.cjs +115 -0
  71. package/dist/server/getI18n.d.ts +61 -0
  72. package/dist/server/getI18n.d.ts.map +1 -0
  73. package/dist/server/getI18n.js +114 -0
  74. package/dist/server/getLocale.cjs +37 -0
  75. package/dist/server/getLocale.d.ts +22 -0
  76. package/dist/server/getLocale.d.ts.map +1 -0
  77. package/dist/server/getLocale.js +36 -0
  78. package/dist/server/loadTranslations.cjs +54 -0
  79. package/dist/server/loadTranslations.d.ts +34 -0
  80. package/dist/server/loadTranslations.d.ts.map +1 -0
  81. package/dist/server/loadTranslations.js +54 -0
  82. package/dist/server/setRequestLocale.cjs +31 -0
  83. package/dist/server/setRequestLocale.d.ts +26 -0
  84. package/dist/server/setRequestLocale.d.ts.map +1 -0
  85. package/dist/server/setRequestLocale.js +31 -0
  86. package/dist/server/types.d.ts +43 -0
  87. package/dist/server/types.d.ts.map +1 -0
  88. package/dist/server.cjs +11 -0
  89. package/dist/server.d.ts +8 -0
  90. package/dist/server.d.ts.map +1 -0
  91. package/dist/server.js +6 -0
  92. package/package.json +111 -0
@@ -0,0 +1,102 @@
1
+ "use client";
2
+ "use client";
3
+ import { useRoutingConfig } from "./context.js";
4
+ import { getCanonicalPathname, localizeHref, stripLocalePrefix } from "./utils.js";
5
+ import { useCallback } from "react";
6
+ import { useI18n } from "@comvi/react";
7
+ import { usePathname, useRouter } from "next/navigation";
8
+ //#region src/routing/hooks.ts
9
+ /**
10
+ * Get pathname without locale prefix
11
+ *
12
+ * This hook returns the current pathname with the locale prefix removed,
13
+ * making it easier to work with routes in a locale-agnostic way.
14
+ *
15
+ * @returns Pathname without locale prefix
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * import { usePathname } from '@comvi/next/navigation';
20
+ *
21
+ * function MyComponent() {
22
+ * const pathname = usePathname();
23
+ * // If URL is /en/about, pathname is /about
24
+ * return <p>Current page: {pathname}</p>;
25
+ * }
26
+ * ```
27
+ */
28
+ function usePathname$1() {
29
+ const pathname = usePathname() ?? "/";
30
+ const routing = useRoutingConfig();
31
+ const { locale } = useI18n();
32
+ if (routing) return getCanonicalPathname(stripLocalePrefix(pathname, routing.locales), routing, locale);
33
+ if (pathname.startsWith(`/${locale}/`)) return pathname.slice(locale.length + 1);
34
+ if (pathname === `/${locale}`) return "/";
35
+ return pathname;
36
+ }
37
+ /**
38
+ * Localized router with automatic locale prefixing
39
+ *
40
+ * This hook wraps Next.js useRouter and automatically adds locale
41
+ * prefixes to navigation methods.
42
+ *
43
+ * @returns Localized router object
44
+ *
45
+ * @example
46
+ * ```tsx
47
+ * import { useLocalizedRouter } from '@comvi/next/navigation';
48
+ *
49
+ * function MyComponent() {
50
+ * const router = useLocalizedRouter();
51
+ *
52
+ * const handleClick = () => {
53
+ * router.push('/about'); // Navigates to /en/about (or current locale)
54
+ * };
55
+ *
56
+ * const handleGerman = () => {
57
+ * router.push('/about', 'de'); // Navigates to /de/about
58
+ * };
59
+ *
60
+ * return <button onClick={handleClick}>Go to About</button>;
61
+ * }
62
+ * ```
63
+ */
64
+ function useLocalizedRouter() {
65
+ const router = useRouter();
66
+ const { locale } = useI18n();
67
+ const routing = useRoutingConfig();
68
+ const push = useCallback((href, targetLocale) => {
69
+ const localizedHref = localizeHref(href, targetLocale ?? locale, routing ?? void 0);
70
+ router.push(localizedHref);
71
+ }, [
72
+ router,
73
+ locale,
74
+ routing
75
+ ]);
76
+ const replace = useCallback((href, targetLocale) => {
77
+ const localizedHref = localizeHref(href, targetLocale ?? locale, routing ?? void 0);
78
+ router.replace(localizedHref);
79
+ }, [
80
+ router,
81
+ locale,
82
+ routing
83
+ ]);
84
+ const prefetch = useCallback((href, targetLocale) => {
85
+ const localizedHref = localizeHref(href, targetLocale ?? locale, routing ?? void 0);
86
+ router.prefetch(localizedHref);
87
+ }, [
88
+ router,
89
+ locale,
90
+ routing
91
+ ]);
92
+ return {
93
+ push,
94
+ replace,
95
+ back: router.back,
96
+ forward: router.forward,
97
+ refresh: router.refresh,
98
+ prefetch
99
+ };
100
+ }
101
+ //#endregion
102
+ export { useLocalizedRouter, usePathname$1 as usePathname };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Locale prefix mode for URL routing
3
+ */
4
+ export type LocalePrefixMode = "always" | "as-needed" | "never";
5
+ /**
6
+ * Configuration for i18n routing
7
+ *
8
+ * @typeParam T - Union type of supported locale strings (e.g., 'en' | 'uk' | 'de')
9
+ */
10
+ export interface RoutingConfig<T extends string = string> {
11
+ /** Supported locales */
12
+ locales: readonly T[];
13
+ /** Default locale */
14
+ defaultLocale: T;
15
+ /**
16
+ * Locale prefix mode:
17
+ * - 'always': All routes have locale prefix (/en/about, /de/about)
18
+ * - 'as-needed': Only non-default locales have prefix (/about for en, /de/about for de)
19
+ * - 'never': No locale prefixes (use cookie/header only)
20
+ * @default 'as-needed'
21
+ */
22
+ localePrefix?: LocalePrefixMode;
23
+ /**
24
+ * Cookie name for storing locale preference
25
+ * @default 'NEXT_LOCALE'
26
+ */
27
+ localeCookie?: string;
28
+ /**
29
+ * Path configurations for different locales (optional)
30
+ * Allows different URL paths per locale
31
+ * @example { '/about': { en: '/about', de: '/ueber-uns' } }
32
+ */
33
+ pathnames?: Record<string, Partial<Record<T, string>>>;
34
+ }
35
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/routing/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,WAAW,GAAG,OAAO,CAAC;AAEhE;;;;GAIG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACtD,wBAAwB;IACxB,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC;IACtB,qBAAqB;IACrB,aAAa,EAAE,CAAC,CAAC;IACjB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;CACxD"}
@@ -0,0 +1,94 @@
1
+ const require_defineRouting = require("./defineRouting.cjs");
2
+ //#region src/routing/utils.ts
3
+ var getPathnameCache = /* @__PURE__ */ new WeakMap();
4
+ var isExternalHref = (href) => {
5
+ return /^[a-z][a-z0-9+.-]*:/i.test(href) || href.startsWith("//");
6
+ };
7
+ var isRelativeFragmentOrQuery = (href) => {
8
+ return href.startsWith("#") || href.startsWith("?");
9
+ };
10
+ var normalizePath = (path) => {
11
+ if (!path) return "/";
12
+ return path.startsWith("/") ? path : `/${path}`;
13
+ };
14
+ var getCanonicalPathMatch = (pathname, routing, preferredLocale) => {
15
+ const normalizedPath = normalizePath(pathname);
16
+ const localesToTry = preferredLocale ? [preferredLocale, ...routing.locales.filter((locale) => locale !== preferredLocale)] : [...routing.locales];
17
+ for (const [canonicalPath, localizedByLocale] of Object.entries(routing.pathnames)) {
18
+ const normalizedCanonicalPath = normalizePath(canonicalPath);
19
+ if (normalizedPath === normalizedCanonicalPath) return normalizedCanonicalPath;
20
+ for (const locale of localesToTry) {
21
+ const localizedPath = localizedByLocale[locale];
22
+ if (localizedPath && normalizePath(localizedPath) === normalizedPath) return normalizedCanonicalPath;
23
+ }
24
+ }
25
+ };
26
+ var stripLocalePrefix = (pathname, locales) => {
27
+ const normalized = normalizePath(pathname);
28
+ const segments = normalized.split("/").filter(Boolean);
29
+ if (segments.length === 0) return "/";
30
+ const first = segments[0];
31
+ if (locales.includes(first)) {
32
+ const rest = segments.slice(1).join("/");
33
+ return rest ? `/${rest}` : "/";
34
+ }
35
+ return normalized;
36
+ };
37
+ var getCanonicalPathname = (pathname, routing, preferredLocale) => {
38
+ const normalizedPath = normalizePath(pathname);
39
+ return getCanonicalPathMatch(normalizedPath, routing, preferredLocale) ?? normalizedPath;
40
+ };
41
+ var splitHref = (href) => {
42
+ const match = href.match(/[?#]/);
43
+ if (!match || match.index === void 0) return {
44
+ path: href,
45
+ suffix: ""
46
+ };
47
+ const index = match.index;
48
+ return {
49
+ path: href.slice(0, index),
50
+ suffix: href.slice(index)
51
+ };
52
+ };
53
+ var localizePathname = (pathname, locale, routing) => {
54
+ const { path, suffix } = splitHref(pathname);
55
+ const canonicalPath = getCanonicalPathname(stripLocalePrefix(path, routing.locales), routing, locale);
56
+ let getPathname = getPathnameCache.get(routing);
57
+ if (!getPathname) {
58
+ getPathname = require_defineRouting.createGetPathname(routing);
59
+ getPathnameCache.set(routing, getPathname);
60
+ }
61
+ return `${getPathname({
62
+ locale,
63
+ href: canonicalPath
64
+ })}${suffix}`;
65
+ };
66
+ var localizeHref = (href, locale, routing) => {
67
+ if (isExternalHref(href)) return href;
68
+ if (isRelativeFragmentOrQuery(href)) return href;
69
+ if (!routing) {
70
+ const normalized = normalizePath(href);
71
+ return `/${locale}${normalized === "/" ? "" : normalized}`;
72
+ }
73
+ return localizePathname(href, locale, routing);
74
+ };
75
+ var localizeUrlObject = (href, locale, routing) => {
76
+ if (href.protocol) return href;
77
+ const pathname = typeof href.pathname === "string" ? href.pathname : "/";
78
+ if (!routing) {
79
+ const normalized = normalizePath(pathname);
80
+ return {
81
+ ...href,
82
+ pathname: `/${locale}${normalized === "/" ? "" : normalized}`
83
+ };
84
+ }
85
+ return {
86
+ ...href,
87
+ pathname: localizePathname(pathname, locale, routing)
88
+ };
89
+ };
90
+ //#endregion
91
+ exports.getCanonicalPathname = getCanonicalPathname;
92
+ exports.localizeHref = localizeHref;
93
+ exports.localizeUrlObject = localizeUrlObject;
94
+ exports.stripLocalePrefix = stripLocalePrefix;
@@ -0,0 +1,8 @@
1
+ import { UrlObject } from 'url';
2
+ import { RoutingConfig } from './types';
3
+ export declare const stripLocalePrefix: (pathname: string, locales: readonly string[]) => string;
4
+ export declare const getCanonicalPathname: (pathname: string, routing: Required<RoutingConfig>, preferredLocale?: string) => string;
5
+ export declare const localizePathname: (pathname: string, locale: string, routing: Required<RoutingConfig>) => string;
6
+ export declare const localizeHref: (href: string, locale: string, routing?: Required<RoutingConfig>) => string;
7
+ export declare const localizeUrlObject: (href: UrlObject, locale: string, routing?: Required<RoutingConfig>) => UrlObject;
8
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/routing/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AACrC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAiD7C,eAAO,MAAM,iBAAiB,GAAI,UAAU,MAAM,EAAE,SAAS,SAAS,MAAM,EAAE,KAAG,MAYhF,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,UAAU,MAAM,EAChB,SAAS,QAAQ,CAAC,aAAa,CAAC,EAChC,kBAAkB,MAAM,KACvB,MAGF,CAAC;AAWF,eAAO,MAAM,gBAAgB,GAC3B,UAAU,MAAM,EAChB,QAAQ,MAAM,EACd,SAAS,QAAQ,CAAC,aAAa,CAAC,KAC/B,MAWF,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,MAAM,MAAM,EACZ,QAAQ,MAAM,EACd,UAAU,QAAQ,CAAC,aAAa,CAAC,KAChC,MAQF,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,MAAM,SAAS,EACf,QAAQ,MAAM,EACd,UAAU,QAAQ,CAAC,aAAa,CAAC,KAChC,SAgBF,CAAC"}
@@ -0,0 +1,91 @@
1
+ import { createGetPathname } from "./defineRouting.js";
2
+ //#region src/routing/utils.ts
3
+ var getPathnameCache = /* @__PURE__ */ new WeakMap();
4
+ var isExternalHref = (href) => {
5
+ return /^[a-z][a-z0-9+.-]*:/i.test(href) || href.startsWith("//");
6
+ };
7
+ var isRelativeFragmentOrQuery = (href) => {
8
+ return href.startsWith("#") || href.startsWith("?");
9
+ };
10
+ var normalizePath = (path) => {
11
+ if (!path) return "/";
12
+ return path.startsWith("/") ? path : `/${path}`;
13
+ };
14
+ var getCanonicalPathMatch = (pathname, routing, preferredLocale) => {
15
+ const normalizedPath = normalizePath(pathname);
16
+ const localesToTry = preferredLocale ? [preferredLocale, ...routing.locales.filter((locale) => locale !== preferredLocale)] : [...routing.locales];
17
+ for (const [canonicalPath, localizedByLocale] of Object.entries(routing.pathnames)) {
18
+ const normalizedCanonicalPath = normalizePath(canonicalPath);
19
+ if (normalizedPath === normalizedCanonicalPath) return normalizedCanonicalPath;
20
+ for (const locale of localesToTry) {
21
+ const localizedPath = localizedByLocale[locale];
22
+ if (localizedPath && normalizePath(localizedPath) === normalizedPath) return normalizedCanonicalPath;
23
+ }
24
+ }
25
+ };
26
+ var stripLocalePrefix = (pathname, locales) => {
27
+ const normalized = normalizePath(pathname);
28
+ const segments = normalized.split("/").filter(Boolean);
29
+ if (segments.length === 0) return "/";
30
+ const first = segments[0];
31
+ if (locales.includes(first)) {
32
+ const rest = segments.slice(1).join("/");
33
+ return rest ? `/${rest}` : "/";
34
+ }
35
+ return normalized;
36
+ };
37
+ var getCanonicalPathname = (pathname, routing, preferredLocale) => {
38
+ const normalizedPath = normalizePath(pathname);
39
+ return getCanonicalPathMatch(normalizedPath, routing, preferredLocale) ?? normalizedPath;
40
+ };
41
+ var splitHref = (href) => {
42
+ const match = href.match(/[?#]/);
43
+ if (!match || match.index === void 0) return {
44
+ path: href,
45
+ suffix: ""
46
+ };
47
+ const index = match.index;
48
+ return {
49
+ path: href.slice(0, index),
50
+ suffix: href.slice(index)
51
+ };
52
+ };
53
+ var localizePathname = (pathname, locale, routing) => {
54
+ const { path, suffix } = splitHref(pathname);
55
+ const canonicalPath = getCanonicalPathname(stripLocalePrefix(path, routing.locales), routing, locale);
56
+ let getPathname = getPathnameCache.get(routing);
57
+ if (!getPathname) {
58
+ getPathname = createGetPathname(routing);
59
+ getPathnameCache.set(routing, getPathname);
60
+ }
61
+ return `${getPathname({
62
+ locale,
63
+ href: canonicalPath
64
+ })}${suffix}`;
65
+ };
66
+ var localizeHref = (href, locale, routing) => {
67
+ if (isExternalHref(href)) return href;
68
+ if (isRelativeFragmentOrQuery(href)) return href;
69
+ if (!routing) {
70
+ const normalized = normalizePath(href);
71
+ return `/${locale}${normalized === "/" ? "" : normalized}`;
72
+ }
73
+ return localizePathname(href, locale, routing);
74
+ };
75
+ var localizeUrlObject = (href, locale, routing) => {
76
+ if (href.protocol) return href;
77
+ const pathname = typeof href.pathname === "string" ? href.pathname : "/";
78
+ if (!routing) {
79
+ const normalized = normalizePath(pathname);
80
+ return {
81
+ ...href,
82
+ pathname: `/${locale}${normalized === "/" ? "" : normalized}`
83
+ };
84
+ }
85
+ return {
86
+ ...href,
87
+ pathname: localizePathname(pathname, locale, routing)
88
+ };
89
+ };
90
+ //#endregion
91
+ export { getCanonicalPathname, localizeHref, localizeUrlObject, stripLocalePrefix };
@@ -0,0 +1,5 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_defineRouting = require("./routing/defineRouting.cjs");
3
+ exports.createGetPathname = require_defineRouting.createGetPathname;
4
+ exports.defineRouting = require_defineRouting.defineRouting;
5
+ exports.hasLocale = require_defineRouting.hasLocale;
@@ -0,0 +1,4 @@
1
+ export { defineRouting, hasLocale, createGetPathname } from './routing/defineRouting';
2
+ export type { GetPathnameOptions } from './routing/defineRouting';
3
+ export type { RoutingConfig, LocalePrefixMode } from './routing/types';
4
+ //# sourceMappingURL=routing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../src/routing.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEtF,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAElE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { createGetPathname, defineRouting, hasLocale } from "./routing/defineRouting.js";
2
+ export { createGetPathname, defineRouting, hasLocale };
@@ -0,0 +1,69 @@
1
+ require("../_virtual/_rolldown/runtime.cjs");
2
+ //#region src/server/cache.ts
3
+ /**
4
+ * Request-scoped locale storage using React cache()
5
+ * This allows setRequestLocale() to store locale that getTranslations() can read
6
+ *
7
+ * React's cache() creates a per-request memoized value in Server Components,
8
+ * allowing us to share state across the component tree without prop drilling.
9
+ */
10
+ var getRequestStore = (0, require("react").cache)(() => ({ locale: void 0 }));
11
+ /**
12
+ * Global i18n reference (set once via setI18n)
13
+ * This is safe because Next.js creates separate module instances for server/client
14
+ */
15
+ var globalI18n;
16
+ /**
17
+ * Configure the global i18n instance for server-side usage
18
+ *
19
+ * Call this once in your i18n configuration file to make getTranslations() work.
20
+ *
21
+ * @param i18n - The i18n instance created with createI18n
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * // i18n/index.ts
26
+ * import { createI18n } from '@comvi/next';
27
+ * import { setI18n } from '@comvi/next/server';
28
+ * import { translations } from './translations';
29
+ *
30
+ * export const i18n = createI18n({
31
+ * locale: 'en',
32
+ * defaultNs: 'default',
33
+ * translation: translations,
34
+ * });
35
+ *
36
+ * // Configure for server-side usage
37
+ * setI18n(i18n);
38
+ * ```
39
+ */
40
+ function setI18n(i18n) {
41
+ globalI18n = i18n;
42
+ }
43
+ /**
44
+ * Get the global i18n instance
45
+ * @internal
46
+ */
47
+ function getI18nInstance() {
48
+ if (!globalI18n) throw new Error("[comvi/next] i18n not configured. Call setI18n(i18n) in your i18n configuration file.");
49
+ return globalI18n;
50
+ }
51
+ /**
52
+ * Set the request locale in the cache
53
+ * @internal
54
+ */
55
+ function setRequestLocaleInternal(locale) {
56
+ getRequestStore().locale = locale;
57
+ }
58
+ /**
59
+ * Get the request locale from cache
60
+ * @internal
61
+ */
62
+ function getRequestLocaleFromCache() {
63
+ return getRequestStore().locale;
64
+ }
65
+ //#endregion
66
+ exports.getI18nInstance = getI18nInstance;
67
+ exports.getRequestLocaleFromCache = getRequestLocaleFromCache;
68
+ exports.setI18n = setI18n;
69
+ exports.setRequestLocaleInternal = setRequestLocaleInternal;
@@ -0,0 +1,42 @@
1
+ import { I18n } from '@comvi/core';
2
+ /**
3
+ * Configure the global i18n instance for server-side usage
4
+ *
5
+ * Call this once in your i18n configuration file to make getTranslations() work.
6
+ *
7
+ * @param i18n - The i18n instance created with createI18n
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * // i18n/index.ts
12
+ * import { createI18n } from '@comvi/next';
13
+ * import { setI18n } from '@comvi/next/server';
14
+ * import { translations } from './translations';
15
+ *
16
+ * export const i18n = createI18n({
17
+ * locale: 'en',
18
+ * defaultNs: 'default',
19
+ * translation: translations,
20
+ * });
21
+ *
22
+ * // Configure for server-side usage
23
+ * setI18n(i18n);
24
+ * ```
25
+ */
26
+ export declare function setI18n(i18n: I18n): void;
27
+ /**
28
+ * Get the global i18n instance
29
+ * @internal
30
+ */
31
+ export declare function getI18nInstance(): I18n;
32
+ /**
33
+ * Set the request locale in the cache
34
+ * @internal
35
+ */
36
+ export declare function setRequestLocaleInternal(locale: string): void;
37
+ /**
38
+ * Get the request locale from cache
39
+ * @internal
40
+ */
41
+ export declare function getRequestLocaleFromCache(): string | undefined;
42
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/server/cache.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAsBxC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAExC;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAOtC;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAE7D;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,GAAG,SAAS,CAE9D"}
@@ -0,0 +1,66 @@
1
+ import { cache } from "react";
2
+ //#region src/server/cache.ts
3
+ /**
4
+ * Request-scoped locale storage using React cache()
5
+ * This allows setRequestLocale() to store locale that getTranslations() can read
6
+ *
7
+ * React's cache() creates a per-request memoized value in Server Components,
8
+ * allowing us to share state across the component tree without prop drilling.
9
+ */
10
+ var getRequestStore = cache(() => ({ locale: void 0 }));
11
+ /**
12
+ * Global i18n reference (set once via setI18n)
13
+ * This is safe because Next.js creates separate module instances for server/client
14
+ */
15
+ var globalI18n;
16
+ /**
17
+ * Configure the global i18n instance for server-side usage
18
+ *
19
+ * Call this once in your i18n configuration file to make getTranslations() work.
20
+ *
21
+ * @param i18n - The i18n instance created with createI18n
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * // i18n/index.ts
26
+ * import { createI18n } from '@comvi/next';
27
+ * import { setI18n } from '@comvi/next/server';
28
+ * import { translations } from './translations';
29
+ *
30
+ * export const i18n = createI18n({
31
+ * locale: 'en',
32
+ * defaultNs: 'default',
33
+ * translation: translations,
34
+ * });
35
+ *
36
+ * // Configure for server-side usage
37
+ * setI18n(i18n);
38
+ * ```
39
+ */
40
+ function setI18n(i18n) {
41
+ globalI18n = i18n;
42
+ }
43
+ /**
44
+ * Get the global i18n instance
45
+ * @internal
46
+ */
47
+ function getI18nInstance() {
48
+ if (!globalI18n) throw new Error("[comvi/next] i18n not configured. Call setI18n(i18n) in your i18n configuration file.");
49
+ return globalI18n;
50
+ }
51
+ /**
52
+ * Set the request locale in the cache
53
+ * @internal
54
+ */
55
+ function setRequestLocaleInternal(locale) {
56
+ getRequestStore().locale = locale;
57
+ }
58
+ /**
59
+ * Get the request locale from cache
60
+ * @internal
61
+ */
62
+ function getRequestLocaleFromCache() {
63
+ return getRequestStore().locale;
64
+ }
65
+ //#endregion
66
+ export { getI18nInstance, getRequestLocaleFromCache, setI18n, setRequestLocaleInternal };
@@ -0,0 +1,19 @@
1
+ //#region src/server/ensureInitialized.ts
2
+ var initPromises = /* @__PURE__ */ new WeakMap();
3
+ /**
4
+ * Ensure i18n instance is initialized, deduplicating concurrent calls.
5
+ * @internal
6
+ */
7
+ var ensureInitialized = async (i18n) => {
8
+ if (i18n.isInitialized) return;
9
+ let initPromise = initPromises.get(i18n);
10
+ if (!initPromise) {
11
+ initPromise = i18n.init().then(() => void 0).finally(() => {
12
+ if (initPromises.get(i18n) === initPromise) initPromises.delete(i18n);
13
+ });
14
+ initPromises.set(i18n, initPromise);
15
+ }
16
+ await initPromise;
17
+ };
18
+ //#endregion
19
+ exports.ensureInitialized = ensureInitialized;
@@ -0,0 +1,7 @@
1
+ import { I18n } from '@comvi/core';
2
+ /**
3
+ * Ensure i18n instance is initialized, deduplicating concurrent calls.
4
+ * @internal
5
+ */
6
+ export declare const ensureInitialized: (i18n: I18n) => Promise<void>;
7
+ //# sourceMappingURL=ensureInitialized.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ensureInitialized.d.ts","sourceRoot":"","sources":["../../src/server/ensureInitialized.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAIxC;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAU,MAAM,IAAI,KAAG,OAAO,CAAC,IAAI,CAmBhE,CAAC"}
@@ -0,0 +1,19 @@
1
+ //#region src/server/ensureInitialized.ts
2
+ var initPromises = /* @__PURE__ */ new WeakMap();
3
+ /**
4
+ * Ensure i18n instance is initialized, deduplicating concurrent calls.
5
+ * @internal
6
+ */
7
+ var ensureInitialized = async (i18n) => {
8
+ if (i18n.isInitialized) return;
9
+ let initPromise = initPromises.get(i18n);
10
+ if (!initPromise) {
11
+ initPromise = i18n.init().then(() => void 0).finally(() => {
12
+ if (initPromises.get(i18n) === initPromise) initPromises.delete(i18n);
13
+ });
14
+ initPromises.set(i18n, initPromise);
15
+ }
16
+ await initPromise;
17
+ };
18
+ //#endregion
19
+ export { ensureInitialized };