Skip to content

Instantly share code, notes, and snippets.

@prutya
Created March 11, 2023 13:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save prutya/ff527e418231a430d5bba71090f7519a to your computer and use it in GitHub Desktop.
Save prutya/ff527e418231a430d5bba71090f7519a to your computer and use it in GitHub Desktop.
Transliteration of Ukrainian text into English
const MAP_NORMAL = {
"а": "a",
"б": "b",
"в": "v",
"г": "h",
"ґ": "g",
"д": "d",
"е": "e",
"є": "ie",
"ж": "zh",
"з": "z",
"и": "y",
"і": "i",
"ї": "i",
"й": "i",
"к": "k",
"л": "l",
"м": "m",
"н": "n",
"о": "o",
"п": "p",
"р": "r",
"с": "s",
"т": "t",
"у": "u",
"ф": "f",
"х": "kh",
"ц": "ts",
"ч": "ch",
"ш": "sh",
"щ": "shch",
"ь": "",
"ю": "iu",
"я": "ia",
"'": "",
};
const MAP_START_OF_WORD = {
"є": "ye",
"ї": "yi",
"й": "y",
"ю": "yu",
"я": "ya",
};
const LETTER_Z = "з";
const MAP_AFTER_LETTER_Z = {
"г": "gh",
};
const EMPTY_STRING = "";
const SLUG_SEPARATOR = "-";
function slugFromUA(string, separator = SLUG_SEPARATOR) {
return string
.toLowerCase()
.split(/\s+/)
.map((word) => wordFromUA(word))
.join(separator);
}
function wordFromUA(word) {
const result = [];
let prevChar = null;
for (const char of word) {
if (MAP_NORMAL.hasOwnProperty(char)) {
if (prevChar === null && MAP_START_OF_WORD.hasOwnProperty(char)) {
result.push(MAP_START_OF_WORD[char]);
} else if (
prevChar === LETTER_Z &&
MAP_AFTER_LETTER_Z.hasOwnProperty(char)
) {
result.push(MAP_AFTER_LETTER_Z[char]);
} else {
result.push(MAP_NORMAL[char]);
}
}
prevChar = char;
}
return result.join(EMPTY_STRING);
}
const cases = [
{
"uk": "алушта",
"en": "alushta",
},
{
"uk": "андрій",
"en": "andrii",
},
{
"uk": "борщагівка",
"en": "borshchahivka",
},
{
"uk": "борисенко",
"en": "borysenko",
},
{
"uk": "вінниця",
"en": "vinnytsia",
},
{
"uk": "володимир",
"en": "volodymyr",
},
{
"uk": "гадяч",
"en": "hadiach",
},
{
"uk": "богдан",
"en": "bohdan",
},
{
"uk": "згурський",
"en": "zghurskyi",
},
{
"uk": "ґалаґан",
"en": "galagan",
},
{
"uk": "ґорґани",
"en": "gorgany",
},
{
"uk": "донецьк",
"en": "donetsk",
},
{
"uk": "дмитро",
"en": "dmytro",
},
{
"uk": "рівне",
"en": "rivne",
},
{
"uk": "олег",
"en": "oleh",
},
{
"uk": "есьмань",
"en": "esman",
},
{
"uk": "єнакієве",
"en": "yenakiieve",
},
{
"uk": "гаєвич",
"en": "haievych",
},
{
"uk": "короп'є",
"en": "koropie",
},
{
"uk": "житомир",
"en": "zhytomyr",
},
{
"uk": "жанна",
"en": "zhanna",
},
{
"uk": "жежелів",
"en": "zhezheliv",
},
{
"uk": "закарпаття",
"en": "zakarpattia",
},
{
"uk": "казимирчук",
"en": "kazymyrchuk",
},
{
"uk": "медвин",
"en": "medvyn",
},
{
"uk": "михайленко",
"en": "mykhailenko",
},
{
"uk": "іванків",
"en": "ivankiv",
},
{
"uk": "іващенко",
"en": "ivashchenko",
},
{
"uk": "їжакевич",
"en": "yizhakevych",
},
{
"uk": "кадиївка",
"en": "kadyivka",
},
{
"uk": "мар'їне",
"en": "marine",
},
{
"uk": "йосипівка",
"en": "yosypivka",
},
{
"uk": "стрий",
"en": "stryi",
},
{
"uk": "олексій",
"en": "oleksii",
},
{
"uk": "київ",
"en": "kyiv",
},
{
"uk": "коваленко",
"en": "kovalenko",
},
{
"uk": "лебедин",
"en": "lebedyn",
},
{
"uk": "леонід",
"en": "leonid",
},
{
"uk": "миколаїв",
"en": "mykolaiv",
},
{
"uk": "маринич",
"en": "marynych",
},
{
"uk": "ніжин",
"en": "nizhyn",
},
{
"uk": "наталія",
"en": "nataliia",
},
{
"uk": "одеса",
"en": "odesa",
},
{
"uk": "онищенко",
"en": "onyshchenko",
},
{
"uk": "полтава",
"en": "poltava",
},
{
"uk": "петро",
"en": "petro",
},
{
"uk": "решетилівка",
"en": "reshetylivka",
},
{
"uk": "рибчинський",
"en": "rybchynskyi",
},
{
"uk": "суми",
"en": "sumy",
},
{
"uk": "соломія",
"en": "solomiia",
},
{
"uk": "тернопіль",
"en": "ternopil",
},
{
"uk": "троць",
"en": "trots",
},
{
"uk": "ужгород",
"en": "uzhhorod",
},
{
"uk": "уляна",
"en": "uliana",
},
{
"uk": "фастів",
"en": "fastiv",
},
{
"uk": "філіпчук",
"en": "filipchuk",
},
{
"uk": "харків",
"en": "kharkiv",
},
{
"uk": "христина",
"en": "khrystyna",
},
{
"uk": "біла",
"en": "bila",
},
{
"uk": "церква",
"en": "tserkva",
},
{
"uk": "стеценко",
"en": "stetsenko",
},
{
"uk": "чернівці",
"en": "chernivtsi",
},
{
"uk": "шевченко",
"en": "shevchenko",
},
{
"uk": "шостка",
"en": "shostka",
},
{
"uk": "кишеньки",
"en": "kyshenky",
},
{
"uk": "щербухи",
"en": "shcherbukhy",
},
{
"uk": "гоща",
"en": "hoshcha",
},
{
"uk": "гаращенко",
"en": "harashchenko",
},
{
"uk": "юрій",
"en": "yurii",
},
{
"uk": "корюківка",
"en": "koriukivka",
},
{
"uk": "яготин",
"en": "yahotyn",
},
{
"uk": "ярошенко",
"en": "yaroshenko",
},
{
"uk": "костянтин",
"en": "kostiantyn",
},
{
"uk": "знам'янка",
"en": "znamianka",
},
{
"uk": "феодосія",
"en": "feodosiia",
},
];
cases.forEach((c) => {
const input = c.uk;
const expectedOutput = c.en;
const actualOutput = wordFromUA(c.uk);
const ok = actualOutput === expectedOutput;
console.log({
input,
expectedOutput,
actualOutput,
ok,
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment