kmu-translit
v1.0.0
Published
Ukrainian to Latin transliteration by the official passport standard (KMU-2010, Resolution No 55), with per-letter rule output, URL slugs and ICAO 9303 MRZ. Zero dependencies.
Maintainers
Readme
kmu-translit
Ukrainian to Latin transliteration by the official Ukrainian passport standard: Cabinet of Ministers of Ukraine Resolution No 55 of 27 January 2010 (KMU-2010). The same table was adopted by BGN/PCGN in 2019 as the romanization of Ukrainian, superseding their 1965 system.
Zero dependencies. ESM and CommonJS. Types included. Works in Node and in the browser.
npm install kmu-translitWhy another transliteration package
Most packages implement a plain letter table and get the contextual rules wrong. The standard has four of them, and they are exactly the cases that decide whether a name matches a passport:
| Rule | Example |
| --- | --- |
| зг becomes zgh, not zh | Згурський → Zghurskyi |
| Я, Ю, Є, Ї, Й take a different form at the start of a word | Yahotyn, but Zakarpattia |
| the soft sign is dropped | Донецьк → Donetsk |
| the apostrophe is dropped | Знам'янка → Znamianka |
This package is the engine behind translit.org.ua and is tested against all 45 examples in the annex to the resolution, plus the ALL-CAPS cases that break naive implementations (ЮРІЙ must give YURII, not YuRII).
Usage
import { transliterate, transliterateName, slugify, buildMrz } from "kmu-translit";
transliterateName("Юрій Згурський");
// "Yurii Zghurskyi"
slugify("Як подати заяву до ДМС?");
// "yak-podaty-zaiavu-do-dms"
slugify("Топ-10 міст", { maxLength: 12 });
// "top-10-mist"Explaining the result
transliterate returns the output plus one entry per input character, so you can show the user why each letter came out the way it did.
const { latin, glyphs, rules } = transliterate("Згурський");
latin; // "Zghurskyi"
rules; // ["zgh", "soft-sign"]
glyphs[1];
// { ch: "г", latin: "gh", kind: "contextual", rule: "zgh" }
glyphs.find((g) => g.ch === "ь");
// { ch: "ь", latin: "", kind: "omitted", rule: "soft-sign" }kind is one of base, contextual, omitted, passthrough. rule is zgh, word-initial, soft-sign or apostrophe. Characters outside the Ukrainian alphabet pass through untouched.
Passport machine-readable zone
buildMrz produces the two 44-character lines of an ICAO Doc 9303 TD3 zone, with the 7-3-1 check digits.
buildMrz({
surnameLatin: "Zghurskyi",
givenLatin: "Yurii",
documentNumber: "FE123456",
birthDate: "1990-04-17",
expiryDate: "2033-04-16",
sex: "M",
});
// {
// line1: "P<UKRZGHURSKYI<<YURII<<<<<<<<<<<<<<<<<<<<<<<",
// line2: "FE123456<8UKR9004171M3304167<<<<<<<<<<<<<<06",
// checkPositions: [9, 19, 27, 42, 43],
// truncated: false,
// }truncated reports that the name did not fit into the 39 available positions. Per Doc 9303 Part 4, 4.2.3 the truncated field must end with an alphabetic character, which this package handles: a naive slice can leave a filler there and the truncation becomes invisible to a reader.
API
| Export | Description |
| --- | --- |
| transliterate(text) | { latin, glyphs, rules } for arbitrary text |
| transliterateName(name) | transliterate and title-case, for personal and place names |
| titleCase(latin) | title-case an already transliterated string |
| slugify(text, options?) | URL slug; options are separator, lower, maxLength |
| buildMrz(input) | ICAO 9303 TD3 machine-readable zone |
| checkDigit(str) | the 7-3-1 mod 10 check digit used by MRZ fields |
Types exported: Glyph, GlyphKind, RuleId, TranslitResult, SlugOptions, MrzInput, MrzResult.
What this package is not
It does not do the reverse direction. Latin to Cyrillic is not a function: the standard drops the soft sign and the apostrophe, and maps і, ї and й all to i inside a word, so Kovalskyi cannot be resolved to Ковальський without a dictionary. There is a decoder with a curated dictionary at translit.org.ua/zvorotna, but it belongs to the site rather than to a general-purpose library.
It also does not implement the scientific systems (ДСТУ 9112:2021, ISO 9, ALA-LC). Those are compared side by side at translit.org.ua/naukova.
Українською
Пакет реалізує таблицю транслітерації, затверджену постановою Кабінету Міністрів України № 55 від 27 січня 2010 року, тобто те саме написання, яке ставлять у закордонному паспорті. Включно з контекстними правилами, на яких найчастіше помиляються: зг як zgh, окремі форми Я, Ю, Є, Ї, Й на початку слова, пропуск м'якого знака й апострофа.
Перевірено на всіх 45 прикладах із додатка до постанови. Онлайн-версія з поясненням кожної літери: translit.org.ua.
Це довідковий інструмент. Остаточне написання у документах визначає орган, що їх оформлює: ДМС може відступити від таблиці за письмовою заявою, якщо треба узгодити написання з раніше виданими документами.
Development
The engine sources in src/ are copied verbatim from the site repository, which is where they are developed. npm run sync refreshes them, npm run sync -- --check fails if they have drifted, and prepublishOnly runs that check so a stale copy cannot be released. Pull requests are welcome; accepted changes are ported back to the site before the next release.
npm test # engine, slug and public API
npm run build # dist/ via tsup
npm run test:dist # loads the build as a consumer would, ESM and CJSLicense
MIT
