Type Arabic with Latin letters — intelligently.
Rebuilt from the original Yamli 5523 (2010) engine in clean, modern TypeScript.
Dual package: headless Node.js library + drop-in browser/CDN script.
العربية · API Docs · Architecture · Business Logic
You type salam 3alaykom → Yamli offers سلام عليكم in a popup.
Press Space to accept the best guess, ↑/↓ to cycle, click to pick.
- Smart word detection — finds the word under the caret, ignoring punctuation and markup.
- Arabic-aware punctuation —
,→،,;→؛,?→؟automatically. - Hindi digits —
123→١٢٣with locale toggle. - Excluded tokens —
http:,www.,AND/OR, emails never transliterated. - Dashed compounds —
al-kitabhandled as connected Arabic words. - Caching & dedup — one network request per unique word, LRU + arabic→roman index.
- RTL/LTR aware — auto-switches direction, popup clamps to viewport.
bun add @plground/yamli
# or
npm i @plground/yamli
# or
pnpm add @plground/yamli
# also available as `@1t_na/yamli-js` — same build
# GitHub: github.com/abdou-da0wew/yamli<!-- jsDelivr (auto-updates on npm publish) -->
<script src="https://cdn.jsdelivr.net/npm/@plground/yamli/dist/web.min.js"></script>
<script>
Yamli.init({ apiBase: "https://api.yamli.com" });
Yamli.yamlify("myTextarea");
Yamli.yamlifyClass("yamli-input");
Yamli.yamlifyType("any");
</script>
<!-- unpkg alternative -->
<!-- <script src="https://unpkg.com/@plground/yamli/dist/web.min.js"></script> -->import { Yamli } from "@plground/yamli/web";
const mgr = Yamli.init({
apiBase: "https://api.yamli.com",
uiLanguage: "en", // en | fr | ar
startMode: "onOrUserDefault",
});
mgr.yamlify("editor"); // by id
mgr.yamlifyClass("arabic-field"); // by class
mgr.yamlifyType("any"); // all text inputsimport { YamliNode } from "@plground/yamli/node";
const yamli = new YamliNode({ apiBase: "https://api.yamli.com" });
// one word → ranked Arabic candidates
const candidates = await yamli.transliterate("salam");
console.log(candidates);
// [{ trans: "سلام", type: 1 }, { trans: "سالم", type: 2 }, ...]
yamli.classify("hello"); // "pure_roman"
yamli.classify("123"); // "pure_number"
yamli.classify("مرحبا"); // "pure_arabic"
yamli.classify("http://x"); // "excluded"import { fetchTransliterations } from "@plground/yamli";
const { roman, items } = await fetchTransliterations("kitab", {
apiBase: "https://api.yamli.com",
tool: "api",
});| Option | Default | Description |
|---|---|---|
apiBase |
https://api.yamli.com |
Transliteration endpoint |
uiLanguage |
"en" |
en / fr / ar |
startMode |
"onOrUserDefault" |
on / off / onOrUserDefault / offOrUserDefault |
toggleAffectsAll |
true |
Toggle affects every instance |
maxResults |
undefined |
Cap popup items |
showHint |
false |
Show onboarding hint |
zIndexBase |
1000 |
Stacking base |
settingsPlacement |
"bottomRight" |
12 placement presets |
popupDirection |
"down" |
up / down |
disableInMarkup |
true |
Skip words inside <tag / [ |
generateOnChangeEvent |
false |
Fire change on replace |
Full table → docs/API.md
| Key | Action |
|---|---|
| Space | Accept top candidate |
| ↑ ↓ | Cycle candidates |
| Enter | Accept highlighted |
| Esc | Dismiss popup |
| Shift+Space | Force commit |
yamli/
├── src/constants/ — word types, regex, punctuation & digit maps, i18n
├── src/utils/ — classifier, text expansion, DOM & positioning
├── src/api/ — fetch + JSONP client, response parser
├── src/core/ — cache, engine, dashed-words, instance, manager
├── src/ui/ — menu, settings, hint, draggable, styles
├── src/index.ts — ESM re-exports
├── src/node.ts — Node headless entry
└── src/web.ts — CDN / window.Yamli entry
Deep dive → docs/ARCHITECTURE.md Business rules → docs/BUSINESS_LOGIC.md
- Caret → word — expand left/right to nearest
space, then to nearest punctuation (HasPunctuationRegexp). Validate word isn't inside markup tail (<[^<>]*$). - Classify —
empty→excluded→pure_number→pure_arabic→pure_roman→roman_arabic→mixed. - Gate — only
pure_roman/roman_arabichit the API.pure_numbermaps digits locally.excluded/mixedignored. - Fetch —
GET /transliterate.ashx?word=...→{ w, r: "سلام/0|سالم/1" }. Deduped + cached (roman→set, arabic→roman, dashed→parts). - Replace — swap
wordwithpickedat[start,end), move caret, firechange/yamliStateChange, registerarabic→roman.
Built-in en / fr / ar strings. RTL layout flips automatically when dir="rtl". Add a locale in src/constants/i18n.ts:
import { I18N } from "@plground/yamli";
I18N.de = { dir: "ltr", show_more: "mehr …", /* … */ };bun install
bun run typecheck
bun run build # → dist/{index,node,web}.{js,cjs,d.ts} + dist/yamli.min.js
bun testMIT — original engine © 2010 Language Analytics LLC, modern port © 2026 contributors.
Made with care for everyone who types Arabic with Latin letters.