UNPKG

@natlibfi/sfs-4900

Version:

Transliteration from cyrillic (Russian, Ukrainian) text to latin (Finnish) as defined in the SFS-4900 standard

243 lines (239 loc) 6.26 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.convertToLatin = convertToLatin; // Based on https://fi.wikipedia.org/wiki/Ven%C3%A4j%C3%A4n_translitterointi and https://fi.wikipedia.org/wiki/Ukrainan_translitterointi const consonants = ['б', 'в', 'г', 'ґ', 'д', 'ж', 'з', 'к', 'л', 'м', 'н', 'п', 'р', 'с', 'т', 'ф', 'х', 'ц', 'ч', 'ш', 'щ', 'Б', 'В', 'Г', 'Ґ', 'Д', 'Ж', 'З', 'К', 'Л', 'М', 'Н', 'П', 'Р', 'С', 'Т', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ']; const characters = ['А', 'а', 'Б', 'б', 'В', 'в', 'Г', 'г', 'Ґ', 'ґ', 'Д', 'д', 'Е', 'е', 'E', 'e', 'Ё', 'ё', 'Ё', 'ё', 'Є', 'є', 'Ж', 'ж', 'З', 'з', 'И', 'и', 'И', 'и', 'І', 'і', 'Ї', 'ї', 'Й', 'й', 'Й', 'й', 'Й', 'й', 'К', 'к', 'Л', 'л', 'М', 'м', 'Н', 'н', 'О', 'о', 'П', 'п', 'Р', 'р', 'С', 'с', 'Т', 'т', 'У', 'у', 'Ф', 'ф', 'Х', 'х', 'Ц', 'ц', 'Ч', 'ч', 'Ш', 'ш', 'Щ', 'щ', 'Ъ', 'ъ', 'Ы', 'ы', 'Ь', 'ь', 'Э', 'э', 'Ю', 'ю', 'Я', 'я', '’']; const map = { 'А': 'A', // Both 'а': 'a', 'Б': 'B', // Both 'б': 'b', 'В': 'V', // Both 'в': 'v', 'Г': 'G', // rus, ukr h, Ґ ґ g, see code 'г': 'g', 'Ґ': 'G', // UKR-only 'ґ': 'g', 'Д': 'D', // both 'д': 'd', // 'Е': 'E', // UKR is simpler // 'е': 'e', // 'E': 'Je', // 'e': 'je', // 'Ё': 'O', // RUS only // 'ё': 'o', // 'Ё': 'Jo', // 'ё': 'jo', 'Є': 'Je', // UKR only 'є': 'je', 'Ж': 'Ž', // Both 'ж': 'ž', 'З': 'Z', // Both 'з': 'z', 'И': 'I', // RUS: 'i'/'ji'. UKR: 'y'. Default to 'i' 'и': 'i', //'И': 'Ji', //'и': 'ji',*/ 'І': 'I', // UKR only 'і': 'i', 'Ї': 'Ji', // UKR only 'ї': 'ji', 'Й': 'I', // RUS and UKR both map to 'i'/'j'/'', but the rules differ slightly. Map to I/i by default 'й': 'i', //'Й': 'J', //'й': 'j', //'Й': '', //'й': '', 'К': 'K', // both 'к': 'k', 'Л': 'L', // both 'л': 'l', 'М': 'M', // both 'м': 'm', 'Н': 'N', // both 'н': 'n', 'О': 'O', // both 'о': 'o', 'П': 'P', // both 'п': 'p', 'Р': 'R', // both 'р': 'r', 'С': 'S', // both 'с': 's', 'Т': 'T', // both 'т': 't', 'У': 'U', // both 'у': 'u', 'Ф': 'F', // both 'ф': 'f', 'Х': 'H', // UKR: h’ 'х': 'h', 'Ц': 'Ts', // both 'ц': 'ts', 'Ч': 'Tš', // both 'ч': 'tš', 'Ш': 'Š', // both 'ш': 'š', 'Щ': 'Štš', // both 'щ': 'štš', 'Ъ': '', // both (UKR: no longer used) 'ъ': '', 'Ы': 'Y', // RUS onlt 'ы': 'y', 'Ь': '', // both 'ь': '', 'Э': 'E', // RUS only 'э': 'e', 'Ю': 'Ju', // Both 'ю': 'ju', 'Я': 'Ja', // Both 'я': 'ja', '’': '' // UKR only }; function createConverter(word, lang = 'rus') { // lang: 'rus' and 'ukr' supported const warnings = []; console.log(`LANG: ${lang}`); // eslint-disable-line no-console function eOrJe(char, previousCharacter) { if (lang === 'ukr') { return char === 'Е' ? 'E' : 'e'; } if (isConsonant(previousCharacter)) { if (['Ъ', 'Ь', 'ъ', 'ь'].includes(previousCharacter)) { return char === 'Е' ? 'Je' : 'je'; } return char === 'Е' ? 'E' : 'e'; } //if (isFirstCharacter || ['Ъ','Ь','ъ','ь'].includes(previousCharacter) || !isConsonant(previousCharacter)) { return char === 'Е' ? 'Je' : 'je'; } function gOrH(char) { if (lang === 'ukr') { return char === 'Г' ? 'H' : 'h'; } return char === 'Г' ? 'G' : 'g'; } function iOrJ(char, previousCharacter, isFirstCharacter, isLastCharacter) { if (isFirstCharacter) { // Both RUS and UKR return char === 'Й' ? 'J' : 'j'; } if (lang === 'ukr' && ['І', 'і'].includes(previousCharacter)) { if (isLastCharacter) { return ''; } return char === 'Й' ? 'J' : 'j'; } if (lang === 'rus' && ['и', 'И'].includes(previousCharacter)) { if (isLastCharacter) { return ''; } return char === 'Й' ? 'J' : 'j'; } return char === 'Й' ? 'I' : 'i'; } function convertCharacter(char, i) { const previousCharacter = word[i - 1]; const nextCharacter = word[i + 1]; const isFirstCharacter = i === 0 || !characters.some(c => c === previousCharacter); if (['Г', 'г'].includes(char)) { // 'gogol' vs 'hohol' return gOrH(char); } if (['Е', 'е'].includes(char)) { return eOrJe(char, previousCharacter); } if (['Ё', 'ё'].includes(char)) { // RUS only if (['ж', 'ч', 'ш', 'щ', 'Ж', 'Ч', 'Ш', 'Щ'].includes(previousCharacter)) { return previousCharacter === 'Ё' ? 'O' : 'o'; } return previousCharacter === 'Ё' ? 'Jo' : 'jo'; } if (['И', 'и'].includes(char)) { if (lang === 'ukr') { return char === 'И' ? 'Y' : 'y'; } if (['Ь', 'ь'].includes(previousCharacter)) { return char === 'И' ? 'Ji' : 'ji'; } return char === 'И' ? 'I' : 'i'; } if (['Й', 'й'].includes(char)) { const isLastCharacter = i === word.length - 1 || !characters.some(c => c === nextCharacter); return iOrJ(char, previousCharacter, isFirstCharacter, isLastCharacter); } if (lang === 'ukr') { if (char === 'Х') { return 'H\''; } if (char === 'х') { return 'h\''; } } return convertCharacter2(); function convertCharacter2() { const converted = map[char]; if (converted === undefined) { warnings.push(`Character ${char} at position ${i} was not cyrillic.`); // eslint-disable-line functional/immutable-data return char; } return converted; } } return { warnings, convertCharacter }; } function convertToLatin(word, lang = 'rus') { const converter = createConverter(word, lang); const convertedWord = word.split('').map(converter.convertCharacter).join(''); return { from: word, result: convertedWord, warnings: converter.warnings }; } function isConsonant(char) { return consonants.includes(char); } //# sourceMappingURL=transliteration.js.map