A browser-based Computer-Assisted Translation (CAT) workbench, KAG/Artemis script dumper, and deterministic Latin word-wrapping engine for visual novel localization pipelines.
Runs entirely client-side via Web Workers and IndexedDB, removing the need for local compiler toolchains or desktop dependencies.
Figure 1: Side-by-side script editor with word-boundary ruler and real-time KAG macro injection.
Additional Interface Screenshots
Translating Japanese visual novel scripts into Latin scripts (Indonesian, English) introduces two recurring structural issues:
- Glyph vs. Word-Boundary Breaking: Japanese KAG engines format monospaced glyphs and break lines at arbitrary character boundaries. Latin scripts require whitespace word-boundary wrapping. Without explicit line breaks (
[r]), target text overflows textbox boundaries or breaks mid-word. - Bytecode Desynchronization (Mojibake): Mismatches between legacy multi-byte encodings (Shift-JIS / CP932) and UTF-8 corrupt engine control macros and dialogue strings.
unred isolates engine control codes, calculates visible character metrics, and injects engine delimiters before scenario recompilation.
- In-Browser Scenario Tokenization: Parses
.ks,.txt, and.astsource scripts into isolated dialogue segments while preserving inline engine macros (@bg,@playse,[wait]). - Deterministic Latin Word Wrapping: Splits text along whitespace boundaries and injects KAG line-break macros (
[r]) at a configurable character threshold (default: 42 characters/line, 3 lines maximum per frame). - Macro-Stripped Line Metrics: Filters formatting tags (
[ruby],[l],[p]) prior to width calculation to prevent false-positive overflow warnings. - Encoding QA & Bytecode Inspector: Detects unbalanced bracket syntax, broken multi-byte sequences (CP932/Shift-JIS desyncs), and character count threshold violations.
- Memory-Buffered Patch Export: Rebuilds modified scenario files and packages them into
.ziparchives directly via browser memory. - Offline Persistence: Syncs active translation progress and project states using IndexedDB.
unred/
├── app/
│ ├── layout.tsx
│ ├── page.tsx # CAT workbench & word-wrapping interface
│ ├── linter/page.tsx # Encoding QA & bytecode inspector
│ ├── patch/page.tsx # Script dumper & patch compiler
│ ├── preview/page.tsx # Dialogue box canvas simulator
│ └── globals.css
├── components/
│ ├── HeaderNav.tsx # Project selector and patch build trigger
│ ├── SidebarExplorer.tsx # File tree and segment filter list
│ ├── CATSegmentRow.tsx # Side-by-side translation row
│ ├── SmartWrappingPanel.tsx # Boundary guides & macro injection
│ └── LiveVNTextbox.tsx # Viewport dialogue renderer
├── docs/
│ └── screenshots/ # Documentation visual assets
├── lib/
│ ├── kag-lexer.ts # Tokenizer and AST parser for KAG
│ ├── word-wrapper.ts # Latin word-boundary wrapping logic
│ ├── mojibake-detector.ts # Multi-byte anomaly detection
│ ├── patch-builder.ts # Browser-based script bundler
│ └── types.ts # Core type definitions
└── store/
└── useVNLocStore.ts # Zustand store with IndexedDB sync
- Node.js 18.17 or later
- npm, pnpm, or yarn
git clone https://github.com/Unjou/unred.git
cd unred
npm installnpm run devOpen http://localhost:3000 in your browser.
npm run build
npm run startThe wrapping pipeline (lib/word-wrapper.ts) operates under the following sequence:
- Strips existing auto-generated
[r]delimiters and normalizes whitespace sequences. - Isolates engine macro tokens (
\[.*?\]) so non-rendered formatting characters do not contribute to line width. - Iterates over whitespace-separated tokens, accumulating words into the current line buffer.
- If adding the next word exceeds
maxCharsPerLine(default: 42), writes the buffer and appends the engine delimiter ([r]). - Generates an overflow warning if the line count exceeds
maxLinesPerBox(default: 3).
MIT



