@dualkit/convert 0.0.0-stage → 0.1.0-beta.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.
- package/LICENSE +9 -0
- package/README.md +112 -2
- package/dist/index.cjs +3243 -0
- package/dist/index.d.cts +173 -0
- package/dist/index.d.ts +173 -0
- package/dist/index.js +3207 -0
- package/package.json +46 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sam Santos
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,113 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @dualkit/convert
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Turns an English React or Next.js app into an Arabic one, on a new git branch.
|
|
4
|
+
|
|
5
|
+
It is the engine behind `dualkit convert`. Most people run it through the CLI:
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npx dualkit@beta convert --mode bilingual --start "npm run dev" --port 3000
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Convert makes no model calls. It rewrites the code it can rewrite safely, lists every English string for you or your agent to translate, and checks the result in a browser. Every Arabic string a model drafts is marked for a native speaker to check.
|
|
12
|
+
|
|
13
|
+
## The two modes
|
|
14
|
+
|
|
15
|
+
| Mode | What you get | Branch |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| `bilingual` | English and Arabic in one app, with a language switch. English stays exactly as it is. | `dualkit/bilingual` |
|
|
18
|
+
| `arabic` | The whole app in Arabic and right to left, in place. There is no switch. | `dualkit/arabic` |
|
|
19
|
+
|
|
20
|
+
In a bilingual Next.js app the locale lives in the URL. English keeps its URLs, and Arabic pages sit under `/ar`. A bilingual Vite app keeps the locale in the `dk-locale` cookie and reads it before the first paint.
|
|
21
|
+
|
|
22
|
+
## The two phases
|
|
23
|
+
|
|
24
|
+
Phase 1, `dualkit convert --mode <mode>`:
|
|
25
|
+
|
|
26
|
+
1. Checks the repo. It needs a clean git working tree, and it refuses with a one-line reason if anything is uncommitted or the branch already exists.
|
|
27
|
+
2. In bilingual mode, takes English screenshots of every page it can reach, at 390 and 1280 pixels wide, if you gave it a start command. Arabic mode has no English pages to compare, so it skips them.
|
|
28
|
+
3. Makes the branch from your current commit. It never pushes and never touches your main branch.
|
|
29
|
+
4. Rewrites the code: physical Tailwind classes and CSS to logical ones, `dir="ltr"` on phone, email and url fields, `<bdi>` around prices and other numbers inside text, mirrored arrow icons from known icon packages, and every English string moved into `messages/en.json` behind a translation hook.
|
|
30
|
+
5. Wires in the translation library: next-intl for Next.js, react-i18next for Vite. It adds an Arabic font stylesheet scoped to Arabic pages.
|
|
31
|
+
6. Writes `dualkit-strings.json`, one entry per string with its Arabic left empty, and commits. If you stop it or a step fails, it puts the repo back as it was.
|
|
32
|
+
|
|
33
|
+
Then you fill the Arabic in `dualkit-strings.json`. The [dualkit-convert skill](../../plugin/skills/dualkit-convert/SKILL.md) walks an agent through it.
|
|
34
|
+
|
|
35
|
+
Phase 2, `dualkit convert --finish`:
|
|
36
|
+
|
|
37
|
+
1. Writes `messages/ar.json` from the filled ledger. It refuses while any string is still pending, unless you pass `--force`.
|
|
38
|
+
2. Starts the app and compares each English page with its screenshot from phase 1. A page passes when under 0.1% of its pixels differ.
|
|
39
|
+
3. Runs the 34 check rules on each Arabic page.
|
|
40
|
+
4. Runs your tests, if the config names a test command.
|
|
41
|
+
5. Writes `dualkit-convert.md` and commits. It exits 1 when an English page changed, an Arabic page has errors or the tests fail.
|
|
42
|
+
|
|
43
|
+
If a finish step itself fails, such as a start command that does not start, finish puts back the files it wrote and commits nothing. Your Arabic drafts in `dualkit-strings.json` stay as you left them.
|
|
44
|
+
|
|
45
|
+
## What goes into git
|
|
46
|
+
|
|
47
|
+
Convert keeps its state in `.dualkit/convert.json` and a run summary in `.dualkit/summary.json`. Both are committed on the branch, so a fresh clone of the branch can run convert again or run finish. The branch `.gitignore` gets three lines that ignore the rest of `.dualkit`, such as screenshots:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
.dualkit/*
|
|
51
|
+
!.dualkit/convert.json
|
|
52
|
+
!.dualkit/summary.json
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The English screenshots are taken on your base branch before the convert branch exists, so convert also adds `/.dualkit/*` to the repo's `.git/info/exclude`. Your base branch stays clean and nothing is added to its files.
|
|
56
|
+
|
|
57
|
+
## The config block
|
|
58
|
+
|
|
59
|
+
Convert reads a `convert` block from `dualkit.config.json`, or from the file `--config` names, which must be inside the app folder. The `--start` and `--port` flags are saved there for you.
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"convert": {
|
|
64
|
+
"start": "npm run build && npm start",
|
|
65
|
+
"port": 3000,
|
|
66
|
+
"test": "npm test",
|
|
67
|
+
"routes": ["/", "/pricing"],
|
|
68
|
+
"params": { "/orders/[id]": "/orders/42" },
|
|
69
|
+
"storageState": "auth.json"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
| Field | What it does |
|
|
75
|
+
| --- | --- |
|
|
76
|
+
| `start` | The command that starts your app. Without it there is no English baseline, and finish cannot run. A production build gives steadier screenshots than a dev server. |
|
|
77
|
+
| `port` | The port the app listens on. |
|
|
78
|
+
| `test` | Your test command. Finish runs it and puts the result in the report. |
|
|
79
|
+
| `routes` | The pages to check in a Vite app. Convert cannot read client-side routes, so it checks only `/` unless you list them. Next.js routes are read from the app folder. |
|
|
80
|
+
| `params` | A sample path for each dynamic route, such as `/orders/[id]`. Dynamic routes without one are listed in the report as not reached. |
|
|
81
|
+
| `storageState` | A Playwright storage state file, for pages behind a sign-in. |
|
|
82
|
+
|
|
83
|
+
## What it will not do
|
|
84
|
+
|
|
85
|
+
Convert flags these in the report instead of guessing:
|
|
86
|
+
|
|
87
|
+
- Text that shares an element with other elements, such as `Hello <b>{name}</b>`, or a plural built in code. These need rich text or a plural message, by hand. Rich text is not converted in this version.
|
|
88
|
+
- Text outside any component, such as a module-level constant or a Next.js `metadata` title, and the `<title>` in a Vite app's `index.html`.
|
|
89
|
+
- A `className` built at run time, which it cannot read in full.
|
|
90
|
+
- Classes with no logical form, inline SVG icons and files it cannot parse.
|
|
91
|
+
- Dates and numbers formatted in the browser's own locale or in US dollars, and date pickers with their own week start. These are regional suggestions only.
|
|
92
|
+
- Pages under `/api` and other paths the Next.js middleware skips. They stay English.
|
|
93
|
+
|
|
94
|
+
It refuses, with a one-line reason, when:
|
|
95
|
+
|
|
96
|
+
- The app is not Next.js App Router or Vite React. The Pages Router, Create React App, Remix, Vue, Svelte and Angular are refused.
|
|
97
|
+
- The app already has its own middleware or proxy file, or files with the names convert would write.
|
|
98
|
+
- The root layout is a client component, has no `<html>` element, or takes its props in a form convert cannot add params to.
|
|
99
|
+
|
|
100
|
+
## Known gaps
|
|
101
|
+
|
|
102
|
+
- Convert does not place the language switch, because that would change the English look. It writes `components/dualkit-language-switch.tsx` and tells you to add it.
|
|
103
|
+
- Next.js sends a visitor whose browser asks for Arabic from an English URL to the Arabic page. That is next-intl's locale detection, and convert leaves it on.
|
|
104
|
+
|
|
105
|
+
## Use from code
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
import { convert, finish } from '@dualkit/convert'
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Both take an `io` object for the browser, the shell and logging, so the CLI and tests can supply their own. See the exported `ConvertIo` and `FinishIo` types.
|
|
112
|
+
|
|
113
|
+
MIT licensed.
|