wovn-nextjs 0.0.23 → 0.0.26

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/bin/wovn-nextjs CHANGED
@@ -38,6 +38,15 @@ async function main() {
38
38
  if (process.env.WOVN_DEBUG) {
39
39
  console.dir(context, {depth: null})
40
40
  }
41
+ } else if (command === 'update' && context.projectToken && context.hostname) {
42
+ context.wovnJsData = await httpsRequest(`https://data.wovn.io/js_data/json/1/${context.projectToken}/?u=http%3A%2F%2F${context.hostname}`).then(body => JSON.parse(body.toString()))
43
+ await walkTsxAndJsx(context, transform)
44
+ await reportToWovn(context)
45
+ await overwriteInitializationProcess(context)
46
+ await createMiddlewareFile(context)
47
+ if (process.env.WOVN_DEBUG) {
48
+ console.dir(context, {depth: null})
49
+ }
41
50
  } else if (command === 'enable' && context.projectToken && context.hostname) {
42
51
  context.wovnJsData = await httpsRequest(`https://data.wovn.io/js_data/json/1/${context.projectToken}/?u=http%3A%2F%2F${context.hostname}`).then(body => JSON.parse(body.toString()))
43
52
  await walkTsxAndJsx(context, transform)
@@ -257,7 +266,7 @@ setTranslations(JSON.parse(${ JSON.stringify(JSON.stringify(context.wovnJsData))
257
266
  state.projectToken = ${ JSON.stringify(context.projectToken) }
258
267
  state.sourceLanguage = ${ JSON.stringify(context.wovnJsData.language) }
259
268
  state.languages = ${ JSON.stringify(context.wovnJsData.convert_langs?.map((lang) => lang.code) || []) };
260
- wovnMiddlewareConfig.matcher = ${ JSON.stringify(targetLanguages.map(language => '/' + language + '/:path*')) }`
269
+ wovnProxyMiddlewareConfig.matcher = ${ JSON.stringify(targetLanguages.map(language => '/' + language + '/:path*')) }`
261
270
  await overwriteJavaScriptFiles('index.js', code => code.split(appendMarker)[0] + indexCode)
262
271
  await overwriteJavaScriptFiles('server.js', code => code.split(appendMarker)[0] + serverCode)
263
272
  }
@@ -282,7 +291,7 @@ async function overwriteJavaScriptFiles(filename, convert) {
282
291
 
283
292
  async function overwriteTsxAndJsxFiles(context, convert) {
284
293
  const promises = []
285
- await walkTsxAndJsx(async (context, source) => {
294
+ await walkTsxAndJsx(context, async (context, source) => {
286
295
  const convertedSource = convert(context, source)
287
296
  if (source !== convertedSource) {
288
297
  promises.push(fsp.writeFile(context.pathname, convertedSource))
@@ -417,12 +426,12 @@ function isTranslatableAttribute(tag, attr, attrs) {
417
426
  return targets && targets.includes(attr)
418
427
  }
419
428
 
420
- const middlewarePath = path.join(buildDir, 'middleware.js')
421
- const targetMiddlewarePaths = ['', 'src'].flatMap(dir => ['.js', '.ts'].flatMap(ext => path.join(buildDir, dir, 'middleware' + ext)))
429
+ const proxyPath = path.join(buildDir, 'proxy.js')
430
+ const targetMiddlewarePaths = ['', 'src'].flatMap(dir => ['.js', '.ts'].flatMap(ext => path.join(buildDir, dir, 'proxy' + ext)))
422
431
 
423
432
  async function canMiddlewareDelete() {
424
433
  try {
425
- return (await fsp.readFile(middlewarePath, 'utf-8')).startsWith('// wovn-nextjs-command-appended')
434
+ return (await fsp.readFile(proxyPath, 'utf-8')).startsWith('// wovn-nextjs-command-appended')
426
435
  } catch (e) {
427
436
  if (e.message.startsWith('ENOENT:')) {
428
437
  return true
@@ -434,21 +443,23 @@ async function canMiddlewareDelete() {
434
443
 
435
444
  async function createMiddlewareFile(context) {
436
445
  const found = targetMiddlewarePaths.find(pathname => fs.existsSync(pathname))
437
- if (found && found !== middlewarePath) {
446
+ if (found && found !== proxyPath) {
438
447
  return
439
448
  }
440
- if (await canMiddlewareDelete(middlewarePath)) {
441
- await fsp.writeFile(middlewarePath, `// wovn-nextjs-command-appended
442
- import { wovnMiddleware as middleware, wovnMiddlewareConfig as config } from 'wovn-nextjs/server';
443
- export { middleware, config }
449
+ if (await canMiddlewareDelete(proxyPath)) {
450
+ await fsp.writeFile(proxyPath, `// wovn-nextjs-command-appended
451
+ import { wovnProxyMiddleware as proxy, wovnProxyMiddlewareConfig } from 'wovn-nextjs/server';
452
+ export { proxy }
453
+ export const config = {}
454
+ Object.assign(config, wovnProxyMiddlewareConfig)
444
455
  `)
445
456
  }
446
457
  }
447
458
 
448
459
  async function unlinkMiddlewareFileSafely() {
449
- if (await canMiddlewareDelete(middlewarePath)) {
460
+ if (await canMiddlewareDelete(proxyPath)) {
450
461
  try {
451
- await fsp.unlink(middlewarePath)
462
+ await fsp.unlink(proxyPath)
452
463
  } catch {
453
464
  // ignore the error
454
465
  }
@@ -1,6 +1,6 @@
1
- import type { UrlObject } from "url";
2
1
  import { AppContext, AppProps } from "next/app";
3
2
  import * as React from "react";
3
+ import { LinkProps } from "next/link";
4
4
  import { NextRouter } from "next/router";
5
5
  import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
6
6
  export declare function t(source: string): string;
@@ -11,33 +11,7 @@ export declare function useTranslation(): {
11
11
  changeLanguage(language: string): void;
12
12
  };
13
13
  };
14
- export declare const Link: React.ForwardRefExoticComponent<Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof {
15
- href: string | UrlObject;
16
- as?: string | UrlObject;
17
- replace?: boolean;
18
- scroll?: boolean;
19
- shallow?: boolean;
20
- passHref?: boolean;
21
- prefetch?: boolean;
22
- locale?: string | false;
23
- legacyBehavior?: boolean;
24
- onMouseEnter?: any;
25
- onTouchStart?: any;
26
- onClick?: any;
27
- }> & {
28
- href: string | UrlObject;
29
- as?: string | UrlObject;
30
- replace?: boolean;
31
- scroll?: boolean;
32
- shallow?: boolean;
33
- passHref?: boolean;
34
- prefetch?: boolean;
35
- locale?: string | false;
36
- legacyBehavior?: boolean;
37
- onMouseEnter?: any;
38
- onTouchStart?: any;
39
- onClick?: any;
40
- } & {
14
+ export declare const Link: React.ForwardRefExoticComponent<Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof LinkProps<any>> & LinkProps<any> & {
41
15
  children?: React.ReactNode | undefined;
42
16
  } & React.RefAttributes<HTMLAnchorElement>>;
43
17
  export declare function usePageRouter(): NextRouter;
package/dist/cjs/index.js CHANGED
@@ -18,6 +18,8 @@ const server_2 = require("./server");
18
18
  const format_url_1 = require("next/dist/shared/lib/router/utils/format-url");
19
19
  const router_1 = require("next/router");
20
20
  const navigation_1 = require("next/navigation");
21
+ const react_1 = require("react");
22
+ const router_context_shared_runtime_1 = require("next/dist/shared/lib/router-context.shared-runtime");
21
23
  function t(source) {
22
24
  return wovnInternalT(source);
23
25
  }
@@ -31,7 +33,10 @@ function currentLanguage() {
31
33
  }
32
34
  }
33
35
  function useTranslation() {
34
- const router = wovnAsyncLocalStorage.getStore() ? (0, router_1.useRouter)() : (0, navigation_1.useRouter)();
36
+ const isPageRouter = !!(0, react_1.useContext)(router_context_shared_runtime_1.RouterContext);
37
+ const router = isPageRouter ?
38
+ (0, router_1.useRouter)() :
39
+ (0, navigation_1.useRouter)();
35
40
  return {
36
41
  t,
37
42
  i18n: {
@@ -167,7 +172,7 @@ function fetchJsonDataIfNeeded() {
167
172
  if (res.status === 200) {
168
173
  res.json().then(setTranslations);
169
174
  }
170
- });
175
+ }).catch(e => { }); // Ignore error because most translations are already embedded by deploy
171
176
  }
172
177
  }
173
178
  function translate(source) {
@@ -188,7 +193,8 @@ function get(key) {
188
193
  if (server_1.state.isServer) {
189
194
  try {
190
195
  const s = wovnAsyncLocalStorage.getStore();
191
- return s ? s[key] : (0, server_2.headers)().get(key);
196
+ const t = server_2.workUnitAsyncStorage.getStore();
197
+ return s ? s[key] : t ? t["headers"]?.get(key) : '';
192
198
  }
193
199
  catch (e) {
194
200
  return e instanceof Error ? `(${e.message})` : '';
@@ -1,4 +1,4 @@
1
- export { headers } from "next/headers";
1
+ export { workUnitAsyncStorage } from 'next/dist/server/app-render/work-unit-async-storage.external';
2
2
  import { type MiddlewareConfig, NextRequest, NextResponse } from "next/server";
3
3
  declare const state: {
4
4
  isServer: boolean;
@@ -13,9 +13,9 @@ declare const state: {
13
13
  data: string;
14
14
  }[]>>;
15
15
  };
16
- declare const wovnMiddlewareConfig: MiddlewareConfig & {
16
+ declare const wovnProxyMiddlewareConfig: MiddlewareConfig & {
17
17
  matcher: string[];
18
18
  };
19
- export declare function wovnMiddleware(request: NextRequest): NextResponse<unknown>;
20
- export { state, wovnMiddlewareConfig };
19
+ export declare function wovnProxyMiddleware(request: NextRequest): NextResponse<unknown>;
20
+ export { state, wovnProxyMiddlewareConfig };
21
21
  export declare function log(...args: any[]): void;
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  // This will be compiled into .next/server/src/middleware.js that has limitations: https://vercel.com/docs/functions/edge-middleware/limitations
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.wovnMiddlewareConfig = exports.state = exports.headers = void 0;
5
- exports.wovnMiddleware = wovnMiddleware;
4
+ exports.wovnProxyMiddlewareConfig = exports.state = exports.workUnitAsyncStorage = void 0;
5
+ exports.wovnProxyMiddleware = wovnProxyMiddleware;
6
6
  exports.log = log;
7
- var headers_1 = require("next/headers"); // To avoid Next.js errors because index.ts has 'use client' and can not import next/headers
8
- Object.defineProperty(exports, "headers", { enumerable: true, get: function () { return headers_1.headers; } });
7
+ var work_unit_async_storage_external_1 = require("next/dist/server/app-render/work-unit-async-storage.external"); // To avoid Next.js errors because index.ts has 'use client' and can not import next/headers
8
+ Object.defineProperty(exports, "workUnitAsyncStorage", { enumerable: true, get: function () { return work_unit_async_storage_external_1.workUnitAsyncStorage; } });
9
9
  const server_1 = require("next/server");
10
10
  const state = {
11
11
  isServer: typeof window === 'undefined',
@@ -19,8 +19,8 @@ const state = {
19
19
  rawTranslations: {} // [source]?.[currentLanguage()]?.[0]?.data == translation
20
20
  };
21
21
  exports.state = state;
22
- const wovnMiddlewareConfig = { matcher: [] }; // this values will be override by wovn-nextjs build command
23
- exports.wovnMiddlewareConfig = wovnMiddlewareConfig;
22
+ const wovnProxyMiddlewareConfig = { matcher: [] }; // this values will be override by wovn-nextjs build command
23
+ exports.wovnProxyMiddlewareConfig = wovnProxyMiddlewareConfig;
24
24
  function rewritePath(targetLanguages, request) {
25
25
  if (request.nextUrl.pathname.startsWith('/_next') || request.nextUrl.pathname.startsWith('/favicon')) {
26
26
  return server_1.NextResponse.next();
@@ -46,7 +46,7 @@ function rewritePath(targetLanguages, request) {
46
46
  log('do not rewrite', request.nextUrl.pathname);
47
47
  return server_1.NextResponse.next({ headers });
48
48
  }
49
- function wovnMiddleware(request) {
49
+ function wovnProxyMiddleware(request) {
50
50
  return rewritePath(state.languages.filter(l => l !== state.sourceLanguage), request);
51
51
  }
52
52
  // for debug
@@ -1,6 +1,6 @@
1
- import type { UrlObject } from "url";
2
1
  import { AppContext, AppProps } from "next/app";
3
2
  import * as React from "react";
3
+ import { LinkProps } from "next/link";
4
4
  import { NextRouter } from "next/router";
5
5
  import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
6
6
  export declare function t(source: string): string;
@@ -11,33 +11,7 @@ export declare function useTranslation(): {
11
11
  changeLanguage(language: string): void;
12
12
  };
13
13
  };
14
- export declare const Link: React.ForwardRefExoticComponent<Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof {
15
- href: string | UrlObject;
16
- as?: string | UrlObject;
17
- replace?: boolean;
18
- scroll?: boolean;
19
- shallow?: boolean;
20
- passHref?: boolean;
21
- prefetch?: boolean;
22
- locale?: string | false;
23
- legacyBehavior?: boolean;
24
- onMouseEnter?: React.MouseEventHandler<HTMLAnchorElement>;
25
- onTouchStart?: React.TouchEventHandler<HTMLAnchorElement>;
26
- onClick?: React.MouseEventHandler<HTMLAnchorElement>;
27
- }> & {
28
- href: string | UrlObject;
29
- as?: string | UrlObject;
30
- replace?: boolean;
31
- scroll?: boolean;
32
- shallow?: boolean;
33
- passHref?: boolean;
34
- prefetch?: boolean;
35
- locale?: string | false;
36
- legacyBehavior?: boolean;
37
- onMouseEnter?: React.MouseEventHandler<HTMLAnchorElement>;
38
- onTouchStart?: React.TouchEventHandler<HTMLAnchorElement>;
39
- onClick?: React.MouseEventHandler<HTMLAnchorElement>;
40
- } & {
14
+ export declare const Link: React.ForwardRefExoticComponent<Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof LinkProps<any>> & LinkProps<any> & {
41
15
  children?: React.ReactNode | undefined;
42
16
  } & React.RefAttributes<HTMLAnchorElement>>;
43
17
  export declare function usePageRouter(): NextRouter;
package/dist/esm/index.js CHANGED
@@ -3,10 +3,12 @@ import { state, log } from "./server";
3
3
  import App from "next/app";
4
4
  import * as React from "react";
5
5
  import NextLink from "next/link";
6
- import { headers } from "./server";
6
+ import { workUnitAsyncStorage } from "./server";
7
7
  import { formatUrl } from "next/dist/shared/lib/router/utils/format-url";
8
8
  import { useRouter as useInternalPageRouter } from "next/router";
9
9
  import { useRouter as useInternalAppRouter } from "next/navigation";
10
+ import { useContext } from "react";
11
+ import { RouterContext } from "next/dist/shared/lib/router-context.shared-runtime";
10
12
  export function t(source) {
11
13
  return wovnInternalT(source);
12
14
  }
@@ -20,7 +22,10 @@ export function currentLanguage() {
20
22
  }
21
23
  }
22
24
  export function useTranslation() {
23
- const router = wovnAsyncLocalStorage.getStore() ? useInternalPageRouter() : useInternalAppRouter();
25
+ const isPageRouter = !!useContext(RouterContext);
26
+ const router = isPageRouter ?
27
+ useInternalPageRouter() :
28
+ useInternalAppRouter();
24
29
  return {
25
30
  t,
26
31
  i18n: {
@@ -156,7 +161,7 @@ function fetchJsonDataIfNeeded() {
156
161
  if (res.status === 200) {
157
162
  res.json().then(setTranslations);
158
163
  }
159
- });
164
+ }).catch(e => { }); // Ignore error because most translations are already embedded by deploy
160
165
  }
161
166
  }
162
167
  function translate(source) {
@@ -177,7 +182,8 @@ function get(key) {
177
182
  if (state.isServer) {
178
183
  try {
179
184
  const s = wovnAsyncLocalStorage.getStore();
180
- return s ? s[key] : headers().get(key);
185
+ const t = workUnitAsyncStorage.getStore();
186
+ return s ? s[key] : t ? t["headers"]?.get(key) : '';
181
187
  }
182
188
  catch (e) {
183
189
  return e instanceof Error ? `(${e.message})` : '';
@@ -1,4 +1,4 @@
1
- export { headers } from "next/headers";
1
+ export { workUnitAsyncStorage } from 'next/dist/server/app-render/work-unit-async-storage.external';
2
2
  import { type MiddlewareConfig, NextRequest, NextResponse } from "next/server";
3
3
  declare const state: {
4
4
  isServer: boolean;
@@ -13,9 +13,9 @@ declare const state: {
13
13
  data: string;
14
14
  }[]>>;
15
15
  };
16
- declare const wovnMiddlewareConfig: MiddlewareConfig & {
16
+ declare const wovnProxyMiddlewareConfig: MiddlewareConfig & {
17
17
  matcher: string[];
18
18
  };
19
- export declare function wovnMiddleware(request: NextRequest): NextResponse<unknown>;
20
- export { state, wovnMiddlewareConfig };
19
+ export declare function wovnProxyMiddleware(request: NextRequest): NextResponse<unknown>;
20
+ export { state, wovnProxyMiddlewareConfig };
21
21
  export declare function log(...args: any[]): void;
@@ -1,5 +1,5 @@
1
1
  // This will be compiled into .next/server/src/middleware.js that has limitations: https://vercel.com/docs/functions/edge-middleware/limitations
2
- export { headers } from "next/headers"; // To avoid Next.js errors because index.ts has 'use client' and can not import next/headers
2
+ export { workUnitAsyncStorage } from 'next/dist/server/app-render/work-unit-async-storage.external'; // To avoid Next.js errors because index.ts has 'use client' and can not import next/headers
3
3
  import { NextResponse } from "next/server";
4
4
  const state = {
5
5
  isServer: typeof window === 'undefined',
@@ -12,7 +12,7 @@ const state = {
12
12
  translations: {}, // [language][major][minor] == translation
13
13
  rawTranslations: {} // [source]?.[currentLanguage()]?.[0]?.data == translation
14
14
  };
15
- const wovnMiddlewareConfig = { matcher: [] }; // this values will be override by wovn-nextjs build command
15
+ const wovnProxyMiddlewareConfig = { matcher: [] }; // this values will be override by wovn-nextjs build command
16
16
  function rewritePath(targetLanguages, request) {
17
17
  if (request.nextUrl.pathname.startsWith('/_next') || request.nextUrl.pathname.startsWith('/favicon')) {
18
18
  return NextResponse.next();
@@ -38,10 +38,10 @@ function rewritePath(targetLanguages, request) {
38
38
  log('do not rewrite', request.nextUrl.pathname);
39
39
  return NextResponse.next({ headers });
40
40
  }
41
- export function wovnMiddleware(request) {
41
+ export function wovnProxyMiddleware(request) {
42
42
  return rewritePath(state.languages.filter(l => l !== state.sourceLanguage), request);
43
43
  }
44
- export { state, wovnMiddlewareConfig };
44
+ export { state, wovnProxyMiddlewareConfig };
45
45
  // for debug
46
46
  export function log(...args) {
47
47
  if (state.debug) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wovn-nextjs",
3
- "version": "0.0.23",
3
+ "version": "0.0.26",
4
4
  "description": "Localize the Next.js web application without changing the code",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -41,26 +41,26 @@
41
41
  "author": "",
42
42
  "license": "UNLICENSED",
43
43
  "volta": {
44
- "node": "20.16.0"
44
+ "node": "v24.4.1"
45
45
  },
46
46
  "devDependencies": {
47
- "@types/react": "^18.3.7",
48
- "@types/react-dom": "^18.3.0",
47
+ "@types/react": "^19.0.0",
48
+ "@types/react-dom": "^19.0.0",
49
49
  "jsdom": "^25.0.0",
50
50
  "tsx": "^4.19.1",
51
- "typescript": "5.5.4",
51
+ "typescript": "5.8.3",
52
52
  "typescript-eslint": "^8.0.0"
53
53
  },
54
54
  "bundledDependencies": [
55
55
  "typescript-eslint"
56
56
  ],
57
57
  "peerDependencies": {
58
- "@types/node": "^20.0.0",
59
- "@types/react": "^18.0.0",
60
- "@types/react-dom": "^18.0.0",
61
- "next": "^14.0.0",
62
- "react": "^18.0.0",
63
- "react-dom": "^18.0.0"
58
+ "@types/node": "^24.0.0",
59
+ "@types/react": "^19.0.0",
60
+ "@types/react-dom": "^19.0.0",
61
+ "next": "^16.0.0",
62
+ "react": "^19.0.0",
63
+ "react-dom": "^19.0.0"
64
64
  },
65
65
  "bundleDependencies": [
66
66
  "typescript-eslint"