# Multilingual & Language Support in Kensaku
Kensaku is designed from the ground up for **local-first, multilingual search**. Whether searching through codebase repositories in 50+ code and data formats, mixed-script documents (e.g., Japanese/English technical specs), or extracting text from screenshots and scanned invoices across European, Asian, and Middle-Eastern scripts, all processing occurs 100% locally on your machine with zero cloud round-trips.
---
## 1. Natural Languages & Scripts
Kensaku treats human languages and scripts through dedicated tokenization pipelines in Tantivy and local neural network models.
```mermaid
flowchart TD
Input["Input Document / Query"] --> Check{"Script Classification"}
Check -->|CJK Ideographs & Syllables| CJK["KensakuTokenizer (Unigram + Bigram)"]
Check -->|Latin, Cyrillic, Greek, Numbers| Simple["Alphanumeric Tokenizer + LowerCaser"]
Check -->|Images / Scanned PDFs| OCR["OCR Engine Router (Indra / PP-OCR)"]
CJK --> Index["Tantivy Full-Text Index"]
Simple --> Index
OCR --> Index
```
### A. CJK (Chinese, Japanese, Korean)
Standard Western tokenizers split on whitespace and punctuation. Because CJK scripts do not use spaces between words, standard tokenization renders East Asian text unsearchable.
Kensaku implements a custom CJK tokenizer (`KensakuTokenizer` in `src-tauri/src/indexer/tokenizer.rs`) that performs **character-class segmentation** and generates an **interleaved unigram + bigram token stream** with exact byte-offset tracking.
#### Supported Unicode Blocks
| Script | Unicode Ranges | Description |
|---|---|---|
| **Chinese (Hanzi / 汉字 / 漢字)** | `0x4E00..0x9FFF`
`0x3400..0x4DBF`
`0x20000..0x2FA1F`
`0xF900..0xFAFF` | CJK Unified Ideographs, Extension A, Extensions B–F, and Compatibility Ideographs. |
| **Bopomofo (注音符號)** | `0x3100..0x312F`
`0x31A0..0x31BF` | Standard and Extended Bopomofo phonetic symbols. |
| **Japanese (Kanji, Hiragana, Katakana)** | `0x3040..0x309F`
`0x30A0..0x30FF`
`0x31F0..0x31FF`
`0xFF65..0xFF9F` | Hiragana, Katakana, Katakana Phonetic Extensions, and Halfwidth Katakana. |
| **Korean (Hangul / 한글)** | `0xAC00..0xD7AF`
`0x1100..0x11FF`
`0xFFA0..0xFFDC` | Precomposed Hangul Syllables, Hangul Jamo, and Halfwidth Hangul variants. |
#### Tokenization Mechanics
For a text such as `最終報告書` (Final Report):
1. **Unigrams**: `最`, `終`, `報`, `告`, `書` (guarantees 100% recall on single-character queries).
2. **Bigrams**: `最終`, `終報`, `報告`, `告書` (guarantees high precision for compound words and phrases).
3. **Interleaved Stream**: The token stream preserves exact sequential offsets and relative positions so phrase proximity queries (`near[x]`) operate consistently across East Asian text.
#### Mixed-Script Segmentation
When code or file paths mix CJK with Latin or numbers (e.g. `src/组件/index.ts` or `README最終_v2.md`), Kensaku automatically flushes boundaries between character classes:
* `README最終.md` → `["readme", "最", "最終", "終", "md"]`
* `第12回 Rust勉強会 2026年` → `["第", "12", "回", "rust", "勉", "勉強", "強", "強会", "会", "2026", "年"]`
---
### B. Latin, Cyrillic, Greek & European Languages
* **Boundary Splitting**: Alphanumeric words are segmented on punctuation and non-alphanumeric delimiters (`_`, `-`, `.`, `/`, etc.). Snake_case (`calculate_total_tax`) and kebab-case (`user-auth-token`) identifiers split cleanly into individual searchable terms.
* **Case Folding**: All terms undergo full Unicode lowercasing (`LowerCaser`). Queries are case-insensitive by default.
* **Length Filtering**: Tokens exceeding 40 characters are discarded (`RemoveLongFilter`) to prevent machine hashes or minified hex dumps from bloating the term dictionary.
---
### C. Right-to-Left (RTL) & Indic Scripts
* **Plain Text / Documents**: Native UTF-8 parsing handles Arabic, Hebrew, Persian, Urdu, and Devanagari natively.
* **OCR Text Recognition**: Images containing RTL or Indic scripts are routed through specialized recognizers (see [Section 3](#3-multilingual-ocr-engines)).
---
## 2. Programming, Markup & Configuration Languages
Kensaku indexes source code and structured data files natively. Comments, string literals, and identifiers are searchable in the following formats:
### Supported Languages & Extensions
| Category | Languages | File Extensions / Names |
|---|---|---|
| **Systems & Native** | Rust, C, C++, Go, Swift | `.rs`, `.c`, `.cpp`, `.cc`, `.cxx`, `.h`, `.hpp`, `.go`, `.swift` |
| **Web & Scripting** | TypeScript, JavaScript, Python, Ruby, PHP, Lua, R | `.ts`, `.tsx`, `.js`, `.jsx`, `.py`, `.rb`, `.php`, `.lua`, `.r` |
| **JVM & Mobile** | Java, Kotlin | `.java`, `.kt` |
| **Shell & Terminal** | Bash, POSIX Shell, Zsh, Fish | `.sh`, `.bash`, `.zsh`, `.fish` |
| **Markup & Styles** | HTML, CSS, SCSS, Markdown, LaTeX, Vue, Svelte, Astro | `.html`, `.htm`, `.css`, `.scss`, `.md`, `.markdown`, `.tex`, `.vue`, `.svelte`, `.astro` |
| **Data & Query** | JSON, YAML, TOML, XML, CSV, SQL, GraphQL, Protobuf | `.json`, `.yaml`, `.yml`, `.toml`, `.xml`, `.csv`, `.sql`, `.graphql`, `.proto` |
| **Config & Build** | Docker, Make, Environment, Config, Logs, Git | `Dockerfile`, `Makefile`, `justfile`, `Cargo.toml`, `package.json`, `.gitignore`, `.editorconfig`, `.env`, `.ini`, `.cfg`, `.conf`, `.log` |
| **Version Control** | Diffs, Patches | `.diff`, `.patch` |
> [!NOTE]
> File names without extensions (e.g. `Dockerfile`, `Makefile`, `justfile`, `.env`) are matched by filename sniffers and fully indexed.
---
## 3. Multilingual OCR Engines
For images (`.png`, `.jpg`, `.jpeg`, `.webp`, `.bmp`, `.tiff`, `.gif`) and scanned PDF pages, Kensaku provides three local OCR options:
| Feature / Metric | Indra OCR (`"indra"`) | PP-OCRv6 (`"accurate"`) | Tesseract (`"tesseract"`) |
|---|---|---|---|
| **Engine Type** | Native Rust ONNX Runtime port | Native Rust ONNX Runtime port | System C++ library binding |
| **Model Size** | ~27 MB (8 ONNX models) | ~6 MB (compact tiny model) | Depends on system packages |
| **Download Mode** | On demand when selected | Automatic on first use (setup can pre-fetch) | Installed by user via package manager |
| **Script Routing** | Automatic via `script.onnx` classifier | Single joint multilingual model | Requires `-l` language pack flags |
| **Supported Scripts** | • Latin & Cyrillic (`rec.onnx`)
• CJK (`rec_cjk.onnx`)
• RTL / Arabic / Hebrew (`rec_rtl.onnx`)
• Indic & World (`rec_world.onnx`) | Latin, Chinese, Japanese, Korean, Cyrillic | Broad language coverage via `tessdata` |
| **Orientation & Deskew** | Automatic (`orient.onnx`) | Fixed angle detection | Leptonica deskew |
### OCR Configuration Options
In `config.json` (see [`docs/CONFIG.md`](CONFIG.md)):
```json
{
"ocr_enabled": true,
"ocr_engine": "accurate",
"ocr_languages": ["eng"],
"ocr_max_image_bytes": 0
}
```
* `ocr_enabled` (`bool`): Toggle OCR on or off. Defaults to `true`.
* `ocr_engine` (`string`): `"accurate"` (PP-OCRv6, default), `"indra"`, or `"tesseract"`.
Indra falls back to PP-OCR and then Tesseract when its pack cannot load;
PP-OCR falls back to Tesseract.
* `ocr_languages` (`string[]`): Tesseract language codes. Empty means English
when installed.
* `ocr_max_image_bytes` (`int`): Skip OCR above this size in bytes. `0` means no
limit.
---
## 4. Document & Office Formats
Kensaku extracts formatted text from structured document formats, decoding XML entities and preserving word-level boundaries:
| Format | Extensions | Extraction Method |
|---|---|---|
| **PDF Documents** | `.pdf` | Native `lopdf` text-layer extraction; scanned/image-only pages fall back to OCR, one page at a time. |
| **Microsoft Word** | `.docx` | ZIP-stream XML extraction (`word/document.xml`), XML entity decoding. |
| **Microsoft Excel** | `.xlsx` | Shared string table accumulation across all cell `` tags. |
| **Microsoft PowerPoint** | `.pptx` | Slide text extraction across slide XML trees. |
| **OpenDocument** | `.odt`, `.ods`, `.odp` | OASIS OpenDocument XML stream extraction (`content.xml`). |
| **eBooks & Rich Text** | `.epub`, `.rtf` | OEBPS HTML/XHTML extraction; RTF control word stripping. |
| **Delimited text** | `.csv`, `.tsv` | Delimiter sniff; rows become `column = "value"` with the header repeated. |
| **Email** | `.eml`, `.msg` | RFC 822/MIME headers and body via `mail-parser`; Outlook OLE/MAPI fields via `msg_parser`. Subject, date, participants, body, and attachment names are indexed. |
> Legacy binary Office formats (`.doc`, `.xls`, `.ppt`) and Apple iWork files
> are not decoded natively. Use an [external extractor](EXTRACTORS.md) if you
> need them.
---
## 5. Adding Unsupported Languages or Formats
If you need to index a language or proprietary format not listed above (for example, audio/video transcription, STL models, or legacy formats), you can plug in an external tool via Kensaku's **External Extractors System** ([`docs/EXTRACTORS.md`](EXTRACTORS.md)).
Example configuration in `config.json`:
```json
{
"extractors": [
{
"name": "Audio Transcription (Whisper)",
"extensions": ["mp3", "m4a", "wav"],
"mime": ["audio/*"],
"command": "/usr/local/bin/whisper-dump",
"args": ["--language", "auto", "{path}"],
"timeout_ms": 7000,
"max_output_bytes": 1000000,
"enabled": true
}
]
}
```
The output text is ingested straight into Kensaku's CJK-aware Tantivy index and becomes searchable in milliseconds.