cloudflare-next-intl 0.2.0 → 0.2.2

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.
@@ -9,10 +9,10 @@ export declare const localesSet: Set<string>;
9
9
  * @param request The incoming request (pass through from your `middleware.ts`).
10
10
  * @param options.middlewareHandler Your own logic (auth, feature flags, etc.),
11
11
  * run alongside locale routing — see {@link MiddlewareCustomHandler} for the
12
- * full contract (when it runs, what `targetUrl` means, what to return).
13
- * @param options.runHandlerOnRedirect By default, `middlewareHandler` only
14
- * runs when the library is NOT performing a locale redirect (i.e. on
15
- * rewrite or `next()`). Set to `true` to also run it on redirects.
12
+ * full contract (`rewriteUrl` / `redirectUrl` and what to return).
13
+ * @param options.runHandlerOnRedirect By default, `middlewareHandler` does
14
+ * NOT run for the locale-redirect case (so it never receives a
15
+ * `redirectUrl`). Set to `true` to also run it on redirects.
16
16
  * Defaults to `false`.
17
17
  */
18
18
  export default function intlMiddleware(request: NextRequest, options?: {
@@ -26,10 +26,10 @@ export const localesSet = new Set(config.locales);
26
26
  * @param request The incoming request (pass through from your `middleware.ts`).
27
27
  * @param options.middlewareHandler Your own logic (auth, feature flags, etc.),
28
28
  * run alongside locale routing — see {@link MiddlewareCustomHandler} for the
29
- * full contract (when it runs, what `targetUrl` means, what to return).
30
- * @param options.runHandlerOnRedirect By default, `middlewareHandler` only
31
- * runs when the library is NOT performing a locale redirect (i.e. on
32
- * rewrite or `next()`). Set to `true` to also run it on redirects.
29
+ * full contract (`rewriteUrl` / `redirectUrl` and what to return).
30
+ * @param options.runHandlerOnRedirect By default, `middlewareHandler` does
31
+ * NOT run for the locale-redirect case (so it never receives a
32
+ * `redirectUrl`). Set to `true` to also run it on redirects.
33
33
  * Defaults to `false`.
34
34
  */
35
35
  export default async function intlMiddleware(request, options) {
@@ -67,16 +67,19 @@ export default async function intlMiddleware(request, options) {
67
67
  const effectiveLocaleForRequest = urlLocale ?? initialChosenLocale;
68
68
  let response;
69
69
  let isRedirect = false;
70
- let targetUrl;
70
+ let rewriteUrl;
71
+ let redirectUrl;
71
72
  if (!urlLocale) {
72
73
  const targetPath = `/${effectiveLocaleForRequest}${pathWithoutLocale === '/' ? '' : pathWithoutLocale}`;
73
- targetUrl = new URL(`${targetPath}${search}${hash}`, request.url);
74
+ const localeUrl = new URL(`${targetPath}${search}${hash}`, request.url);
74
75
  if (initialChosenLocale === config.defaultLocale) {
75
- response = NextResponse.rewrite(targetUrl, { request });
76
+ rewriteUrl = localeUrl;
77
+ response = NextResponse.rewrite(localeUrl, { request });
76
78
  }
77
79
  else {
78
80
  isRedirect = true;
79
- response = NextResponse.redirect(targetUrl, request);
81
+ redirectUrl = localeUrl;
82
+ response = NextResponse.redirect(localeUrl, request);
80
83
  }
81
84
  }
82
85
  else {
@@ -85,7 +88,7 @@ export default async function intlMiddleware(request, options) {
85
88
  });
86
89
  }
87
90
  if (options?.middlewareHandler && (!isRedirect || options.runHandlerOnRedirect)) {
88
- const customResponse = await options.middlewareHandler(request, effectiveLocaleForRequest, targetUrl);
91
+ const customResponse = await options.middlewareHandler(effectiveLocaleForRequest, rewriteUrl, redirectUrl);
89
92
  if (customResponse) {
90
93
  response = customResponse;
91
94
  }
@@ -4,6 +4,7 @@ import { localeCookieName } from "../../config/cookie_key";
4
4
  import { getLocaleCache, getMessageCache, setLocaleCache, setMessageForLocaleCache } from "../../general/cache_variables";
5
5
  import { cache } from "react";
6
6
  import { localesSet } from "../../config/middleware";
7
+ const isDev = process.env.NODE_ENV === 'development';
7
8
  /**
8
9
  * Loads and caches messages for a specific locale using dynamic import.
9
10
  * Prevents redundant file loads and handles import errors gracefully.
@@ -11,7 +12,10 @@ import { localesSet } from "../../config/middleware";
11
12
  * @returns A promise that resolves to the TranslationObject for the given locale.
12
13
  */
13
14
  async function iGetMessage(locale) {
14
- const message = getMessageCache(locale);
15
+ // In dev, always re-import so editing a messages/*.json file takes effect
16
+ // on the next request without a full server restart. loadedTranslations
17
+ // is a module-level cache that otherwise persists for the whole process.
18
+ const message = isDev ? undefined : getMessageCache(locale);
15
19
  if (message) {
16
20
  return message;
17
21
  }
@@ -1,4 +1,4 @@
1
- import type { NextRequest, NextResponse } from 'next/server';
1
+ import type { NextResponse } from 'next/server';
2
2
  import type { Languages } from 'next/dist/lib/metadata/types/alternative-urls-types';
3
3
  import type { Videos } from 'next/dist/lib/metadata/types/metadata-types';
4
4
  /**
@@ -6,44 +6,37 @@ import type { Videos } from 'next/dist/lib/metadata/types/metadata-types';
6
6
  * (e.g. auth, feature flags, A/B tests) — on top of the library's own
7
7
  * locale routing (locale-prefix rewrite/redirect).
8
8
  *
9
- * Called AFTER the library has resolved the locale for this request, but
10
- * BEFORE it builds its own `NextResponse`:
11
- * - When `targetUrl` is `undefined`: the request already had a valid
12
- * locale prefix (e.g. `/en/about`)the library would otherwise call
13
- * `NextResponse.next()`.
14
- * - When `targetUrl` is set: the library resolved a locale-prefixed URL
15
- * the request should be routed to (e.g. `/` -> `/en/`). By default the
16
- * library still performs this rewrite/redirect itself `targetUrl` is
17
- * informational, so you can react to it (e.g. log it, add a header),
18
- * NOT something you are required to apply yourself.
19
- * - If `initialChosenLocale === defaultLocale`, the library rewrites to
20
- * `targetUrl` (URL bar unchanged).
21
- * - Otherwise, the library redirects to `targetUrl` (only when
22
- * `runHandlerOnRedirect: true` is also passed — by default this
23
- * handler does NOT run on redirects).
9
+ * STRICT RULE at most ONE of `rewriteUrl` / `redirectUrl` is ever set, and
10
+ * whichever is set tells you exactly what to do:
11
+ * - `rewriteUrl` set: apply `NextResponse.rewrite(rewriteUrl, { request })`
12
+ * (locale matches the default locale URL bar stays unchanged).
13
+ * - `redirectUrl` set: apply `NextResponse.redirect(redirectUrl, request)`
14
+ * (locale differs from the URL visible redirect). The handler only runs
15
+ * for this case when `runHandlerOnRedirect: true` is passed.
16
+ * - BOTH undefined: no locale routing needed (URL already has the right
17
+ * locale prefix). This is where your own logic belongs return
18
+ * `NextResponse.next({ request })`, or your own redirect (e.g. auth).
24
19
  *
25
- * @param request The incoming request.
26
- * @param locale The resolved locale for this request (e.g. `"en"`).
27
- * @param targetUrl The locale-prefixed URL the library will rewrite/redirect
28
- * to, or `undefined` when no rewrite/redirect is needed.
29
- * @returns - A `NextResponse` to fully REPLACE the library's default
30
- * response (e.g. `NextResponse.redirect(...)` to send an
31
- * unauthenticated user to `/login` instead).
32
- * - `null` to keep the library's default response
33
- * (rewrite/redirect/`next()`) as-is — this is the common case.
20
+ * Returning `null` in any case makes the library apply its own default,
21
+ * which is the same rewrite/redirect/`next()` described above.
22
+ *
23
+ * @param locale The resolved locale for this request (e.g. `"en"`).
24
+ * @param rewriteUrl URL to rewrite to, or `undefined`.
25
+ * @param redirectUrl URL to redirect to, or `undefined`.
26
+ * @returns A `NextResponse` to use for this request, or `null` to
27
+ * let the library build the default one.
34
28
  *
35
29
  * @example
36
30
  * ```ts
37
- * middlewareHandler: (request, locale, targetUrl) => {
38
- * const session = request.cookies.get("session")?.value;
39
- * if (!session) {
40
- * return NextResponse.redirect(new URL(`/${locale}/login`, request.url));
41
- * }
42
- * return null; // keep default locale routing
31
+ * middlewareHandler: (locale, rewriteUrl, redirectUrl) => {
32
+ * if (rewriteUrl) return NextResponse.rewrite(rewriteUrl, { request });
33
+ * if (redirectUrl) return NextResponse.redirect(redirectUrl, request);
34
+ * // No locale routing needed — your own logic goes here.
35
+ * return NextResponse.next({ request });
43
36
  * }
44
37
  * ```
45
38
  */
46
- export type MiddlewareCustomHandler = (request: NextRequest, locale: string, targetUrl: URL | undefined) => NextResponse<unknown> | null | Promise<NextResponse<unknown> | null>;
39
+ export type MiddlewareCustomHandler = (locale: string, rewriteUrl: URL | undefined, redirectUrl: URL | undefined) => NextResponse<unknown> | null | Promise<NextResponse<unknown> | null>;
47
40
  /** Your app's list of supported locale codes, e.g. `["en", "de"] as const`. */
48
41
  export type Locales = readonly string[];
49
42
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudflare-next-intl",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Optimized Next Intl Package Special for App Router and Cloudflare",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",