anylang-dev 0.2.1 → 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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # anylang-dev
2
2
 
3
- `anylang-dev` is a bring-your-own-key website translation CLI and Vite plugin. It scans your source code, writes JSON locale files, and can automatically translate static JSX text.
3
+ `anylang-dev` is a bring-your-own-key website translation CLI with Vite and Next.js support. It scans your source code, writes JSON locale files, and can automatically translate static JSX text.
4
4
 
5
5
  ```tsx
6
6
  <h1>Translate your website with anylang</h1>
@@ -72,6 +72,18 @@ export default defineConfig({
72
72
  });
73
73
  ```
74
74
 
75
+ For Next.js, use the config wrapper in `next.config.mjs`:
76
+
77
+ ```js
78
+ import anylang from "anylang-dev/next";
79
+
80
+ const nextConfig = {};
81
+
82
+ export default anylang({
83
+ runtimeImport: "@/anylang",
84
+ })(nextConfig);
85
+ ```
86
+
75
87
  If you use `tr="false"`, add the JSX type augmentation once in `src/vite-env.d.ts`:
76
88
 
77
89
  ```ts
@@ -84,6 +96,8 @@ That makes this TypeScript-safe:
84
96
  <p tr="false">BrandName</p>
85
97
  ```
86
98
 
99
+ In a Next.js app, you can put the same import in any global declaration file, such as `src/anylang-env.d.ts`.
100
+
87
101
  `anylang scan` creates locale files without calling a translation provider. To translate for real with Gemini, add your own API key to `.env` in the project where you run `anylang`:
88
102
 
89
103
  ```env
@@ -265,6 +279,36 @@ root.render(
265
279
  );
266
280
  ```
267
281
 
282
+ For the Next.js App Router, create a client provider:
283
+
284
+ ```tsx
285
+ // app/providers.tsx
286
+ "use client";
287
+
288
+ import { AnyLangProvider } from "@/anylang";
289
+
290
+ export function Providers({ children }: { children: React.ReactNode }) {
291
+ return <AnyLangProvider>{children}</AnyLangProvider>;
292
+ }
293
+ ```
294
+
295
+ Then wrap your layout:
296
+
297
+ ```tsx
298
+ // app/layout.tsx
299
+ import { Providers } from "./providers";
300
+
301
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
302
+ return (
303
+ <html lang="en">
304
+ <body>
305
+ <Providers>{children}</Providers>
306
+ </body>
307
+ </html>
308
+ );
309
+ }
310
+ ```
311
+
268
312
  Then use translations in any component:
269
313
 
270
314
  ```tsx
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anylang-dev",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Bring-your-own-key website translation JSON generator.",
5
5
  "type": "module",
6
6
  "files": [
@@ -22,6 +22,10 @@
22
22
  "types": "./src/vite.d.ts",
23
23
  "default": "./src/vite.js"
24
24
  },
25
+ "./next": {
26
+ "types": "./src/next.d.ts",
27
+ "default": "./src/next.js"
28
+ },
25
29
  "./jsx-runtime": {
26
30
  "types": "./src/jsx-runtime.d.ts",
27
31
  "default": "./src/runtime.js"
@@ -0,0 +1,15 @@
1
+ module.exports = function anylangNextLoader(source) {
2
+ const callback = this.async();
3
+ const options = this.getOptions ? this.getOptions() : {};
4
+
5
+ import("./jsx.js")
6
+ .then(({ transformAutoJsx }) => {
7
+ const result = transformAutoJsx(source, this.resourcePath, {
8
+ keyPrefix: options.keyPrefix,
9
+ runtimeImport: options.runtimeImport || "@/anylang"
10
+ });
11
+
12
+ callback(null, result.code, null);
13
+ })
14
+ .catch((error) => callback(error));
15
+ };
package/src/next.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import type { NextConfig } from "next";
2
+
3
+ export type AnyLangNextOptions = {
4
+ keyPrefix?: string;
5
+ runtimeImport?: string;
6
+ };
7
+
8
+ export default function anylang(options?: AnyLangNextOptions): (nextConfig?: NextConfig) => NextConfig;
package/src/next.js ADDED
@@ -0,0 +1,32 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+
4
+ const dirname = path.dirname(fileURLToPath(import.meta.url));
5
+
6
+ export default function anylang(options = {}) {
7
+ return function withAnyLang(nextConfig = {}) {
8
+ return {
9
+ ...nextConfig,
10
+ webpack(config, context) {
11
+ if (typeof nextConfig.webpack === "function") {
12
+ config = nextConfig.webpack(config, context);
13
+ }
14
+
15
+ config.module.rules.unshift({
16
+ test: /\.[jt]sx$/,
17
+ exclude: /node_modules/,
18
+ enforce: "pre",
19
+ use: {
20
+ loader: path.join(dirname, "next-loader.cjs"),
21
+ options: {
22
+ keyPrefix: options.keyPrefix,
23
+ runtimeImport: options.runtimeImport || "@/anylang"
24
+ }
25
+ }
26
+ });
27
+
28
+ return config;
29
+ }
30
+ };
31
+ };
32
+ }
package/src/pipeline.js CHANGED
@@ -158,7 +158,8 @@ function generatedRuntimeSource({ importFrom, localeImports, sourceLocale }) {
158
158
  .map((item) => ` '${item.locale}': ${item.identifier}`)
159
159
  .join(",\n");
160
160
 
161
- return `/* This file is generated by anylang. Do not edit by hand. */
161
+ return `'use client'
162
+ /* This file is generated by anylang. Do not edit by hand. */
162
163
  import { createContext, createElement, useCallback, useContext, useMemo, useState, type ReactNode } from 'react'
163
164
  import { $tr as translate, configureAnyLang, setAnyLangLocale } from '${importFrom}'
164
165
  ${imports}