Russian transliteration for Swedish
Also attempted for French, not very successful.
!pip install PyICU
import icu
def transliterator_from_rules(name, rules):
fromrules = icu.Transliterator.createFromRules(name, rules)
icu.Transliterator.registerInstance(fromrules)
return icu.Transliterator.createInstance(name)
rules = r"""
::NFC;
$wordBoundary = [^[:L:][:M:][:N:]];
$upperVowels = [АЕЁЭИОУЫЮЯ];
$lowerVowels = [аеёэиоуыюя];
$vowels = [$upperVowels $lowerVowels];
$upper = [:Uppercase:];
$lower = [:Lowercase:];
$ZSTC = [ЗзСсТтЦц];
$CHSH = [ЧчШшЩщЖж];
$IJ = [ИиЙй];
$Front = [ЕеИиЫыЭэ];
$FrontUpper = [ЕИЫЭ];
$FrontLower = [еиыэ];
# --- Г: gu before e/i/ы; else g ---
Г } $FrontLower → Gu;
Г } $FrontUpper → GU;
г } $FrontLower → gu;
г } $FrontUpper → gu;
# --- Е (E) ---
# after consonant → e
[$upper-$upperVowels] { Е } → E;
[$lower-$lowerVowels] { е } → e;
# after И/Й → e
$IJ { Е } → E;
$IJ { е } → e;
# after soft/hard sign → ie
Ь { Е } $lower → ie;
Ь { Е } [^$lower] → IE;
ь { е } → ie;
Ъ { Е } $lower → ie;
Ъ { Е } [^$lower] → IE;
ъ { е } → ie;
# word-initial default (Wikipedia): Ie
$wordBoundary { Е } $lower → Ie;
$wordBoundary { Е } [^$lower] → IE;
$wordBoundary { е } → ie;
# after vowel (≠ и/й) → ïe
[$vowels-[Ии]] { Е } $lower → ïe;
[$vowels-[Ии]] { Е } [^$lower] → ÏE;
[$vowels-[Ии]] { е } → ïe;
# --- Ё (YO) ---
# default io with right-case
Ё } $lower → io;
Ё } [^$lower] → IO;
ё → io;
# convention admitted: after sibilants map to e (e.g., Gorbatchev)
$CHSH { Ё } → e;
$CHSH { ё } → e;
# --- И (I) ---
# after vowel (≠ и) → ï
[$vowels-[Ии]] { И } → Ï;
[$vowels-[Ии]] { и } → ï;
# --- Й (JOT) ---
# finals
ий $ → i;
Ий $ → i;
ый $ → y;
Ый $ → y;
# suppress in ...ьев / ...иев cluster
[ИиЬь] { Й } [Ее] → ;
# otherwise ï
Й → Ï;
й → ï;
# --- Ю (YU) ---
# after И/Й → ou
$IJ { Ю } $lower → ou;
$IJ { Ю } [^$lower] → OU;
$IJ { ю } → ou;
# after other vowel:
# front vowels (ЕЭИЯЮ) → ïou ; back vowels (АОУЫ) → you
[ЕЭИЯЮеэияю] { Ю } $lower → ïou;
[ЕЭИЯЮеэияю] { Ю } [^$lower] → ÏOU;
[ЕЭИЯЮеэияю] { ю } → ïou;
[АОУЫаоуы] { Ю } $lower → you;
[АОУЫаоуы] { Ю } [^$lower] → YOU;
[АОУЫаоуы] { ю } → you;
# elsewhere (initial/after consonant) → iou
Ю } $lower → iou;
Ю } [^$lower] → IOU;
ю → iou;
# --- Я (YA) ---
# after И/Й → a
$IJ { Я } $lower → a;
$IJ { Я } [^$lower] → A;
$IJ { я } → a;
# after other vowel → ïa
[$vowels-$IJ] { Я } $lower → ïa;
[$vowels-$IJ] { Я } [^$lower] → ÏA;
[$vowels-$IJ] { я } → ïa;
# word-initial convention admitted: Ya
$wordBoundary { Я } $lower → Ya;
$wordBoundary { Я } [^$lower] → YA;
$wordBoundary { я } → ya;
# elsewhere (after consonant) → ia
Я } $lower → ia;
Я } [^$lower] → IA;
я → ia;
# --- С between vowels → ss ---
$vowels { С } $vowels → ss;
$vowels { с } $vowels → ss;
# --- Н final after и/ы → ne (lowercase words only) ---
[иы] { н } $ → ne;
[иы] { н } $wordBoundary → ne;
# --- Final -ев (Tourgueniev, Prokofiev) → -iev ---
ЕВ $ → iev;
ев $ → iev;
А → A;
а → a;
Б → B;
б → b;
В → V;
в → v;
Г → G;
г → g;
Д → D;
д → d;
Е → E;
е → e;
Ж → J;
ж → j;
З → Z;
з → z;
И → I;
и → i;
К → K;
к → k;
Л → L;
л → l;
М → M;
м → m;
Н → N;
н → n;
О → O;
о → o;
П → P;
п → p;
Р → R;
р → r;
С → S;
с → s;
Т → T;
т → t;
У } $lower → ou;
У } [^$lower] → OU;
у → ou;
Х } $lower → kh;
Х } [^$lower] → KH;
х → kh;
Ц } $lower → ts;
Ц } [^$lower] → TS;
ц → ts;
Ч } $lower → tch;
Ч } [^$lower] → TCH;
ч → tch;
Ш } $lower → ch;
Ш } [^$lower] → CH;
ш → ch;
Щ } $lower → chtch;
Щ } [^$lower] → CHTCH;
щ → chtch;
Ъ → ;
ъ → ;
Ы → y;
ы → y;
Ь → ;
ь → ;
Э } $lower → e;
Э } [^$lower] → E;
э → e;
::NFC;
"""
rusv = transliterator_from_rules("ru-sv", rules)
tests = [
("Москва", "Moskva"),
("Чайковский", "Tjajkovskij"),
("Щука", "Sjtjuka"),
("Жириновский", "Zjirinovskij"),
("Юрий", "Jurij"),
("Яковлев", "Jakovlev"),
("Хрущёв", "Chrusjtjov"),
("Циолковский", "Tsiolkovskij")
]
# --- Run test ---
for w in tests:
assert w[1] == rusv.transliterate(w[0])
print(f"{w[0]:15s} → {rusv.transliterate(w[0])}")
fr_rules = r"""
::[АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщ];
::NFC;
$upper = [:Uppercase:];
$vU = [АЕЁИОУЫЭЮЯ];
$vL = [аеёиоуыэюя];
$v = [АЕЁИОУЫЭЮЯаеёиоуыэюя];
$WB = [^[:L:][:M:][:N:]];
А > A;
а > a;
Б > B;
б > b;
В > V;
в > v;
ГЕ > GUE;
Ги > Gui;
ГИ > GUI;
Ге > Gue;
ГЫ > GY;
Гы > Gy;
ге > gue;
ги > gui;
гы > gy;
Г > G;
г > g;
Д > D;
д > d;
$WB { Е } $upper > IE;
$WB { Е > Ie;
$WB { е > ie;
[ЬЪ] { Е > IE;
[ьъ] { Е > Ie;
[АЕЁОУЫЭЮЯ] { Е > ÏE;
[аеёоуыэюя] { е > ïe;
Е > E;
е > e;
Ё } $upper > IO;
$upper { Ё > IO;
Ё > Io;
ё > io;
Ж > J;
ж > j;
З > Z;
з > z;
ИЙ } $WB > I;
ий } $WB > i;
ЫЙ } $WB > Y;
ый } $WB > y;
[АаЕеЁёОоУуЫыЭэЮюЯя] { И > Ï;
[АаЕеЁёОоУуЫыЭэЮюЯя] { и > ï;
И > I;
и > i;
Й > Ï;
й > ï;
К > K;
к > k;
Л > L;
л > l;
М > M;
м > m;
[ИиЫы] { н } $WB > ne;
[ИиЫы] { Н } $WB > NE;
Н > N;
н > n;
О > O;
о > o;
П > P;
п > p;
Р > R;
р > r;
$v { С } $v > ss;
$v { с } $v > ss;
С > S;
с > s;
Т > T;
т > t;
У } $upper > OU;
$upper { У > OU;
У > Ou;
у > ou;
Ф > F;
ф > f;
Х } $upper > KH;
$upper { Х > KH;
Х > Kh;
х > kh;
Ц } $upper > TS;
$upper { Ц > TS;
Ц > Ts;
ц > ts;
Ч } $upper > TCH;
$upper { Ч > TCH;
Ч > Tch;
ч > tch;
Ш } $upper > CH;
$upper { Ш > CH;
Ш > Ch;
ш > ch;
Щ } $upper > CHTCH;
$upper { Щ > CHTCH;
Щ > Chtch;
щ > chtch;
Ъ > ;
ъ > ;
Ь > ;
ь > ;
Ы > Y;
ы > y;
Э > E;
э > e;
[ИиЙй] { Ю } $upper > OU;
[ИиЙй] { Ю > Ou;
[ИиЙй] { ю > ou;
[АаЕеЁёОоУуЫыЭэЮюЯя] { Ю } $upper > ÏOU;
[АаЕеЁёОоУуЫыЭэЮюЯя] { Ю > Ïou;
[АаЕеЁёОоУуЫыЭэЮюЯя] { ю > ïou;
Ю } $upper > IOU;
Ю > Iou;
ю > iou;
[ИиЙй] { Я } $upper > A;
[ИиЙй] { Я > A;
[ИиЙй] { я > a;
[АаЕеЁёОоУуЫыЭэЮюЯя] { Я } $upper > ÏA;
[АаЕеЁёОоУуЫыЭэЮюЯя] { Я > Ïa;
[АаЕеЁёОоУуЫыЭэЮюЯя] { я > ïa;
Я } $upper > IA;
Я > Ia;
я > ia;
::NFC;
"""
fr_examples = """
Владимир → Vladimir
Борис → Boris
Смирнов → Smirnov
Сергей → Sergueï
Георгий → Gueorgui
Новгород → Novgorod
Менделеев → Mendeleïev
Чехов → Tchekhov
Дмитриев → Dmitriev
Дудаев → Doudaïev
Екатеринбург → Iekaterinbourg
Васильев → Vassiliev
Тургенев → Tourgueniev
Пётр → Piotr
Королёв → Koroliov
Нижний → Nijni
Казимир → Kazimir
Михаил → Mikhaïl
Мир → Mir
Достоевский → Dostoïevski
Грозный → Grozny
Алексей → Alekseï
Андрей → Andreï
Александр → Aleksandr
Калининград → Kaliningrad
Малевич → Malevitch
Дума → Douma
Гагарин → Gagarine
Солженицын → Soljenitsyne
Магадан → Magadan
Байконур → Baïkonour
Волга → Volga
Спутник → Spoutnik
Самара → Samara
Новосибирск → Novossibirsk
Курск → Koursk
Владивосток → Vladivostok
Ульянов → Oulianov
Туполев → Tupolev
Прокофьев → Prokofiev
Михаил → Mikhaïl
Хабаровск → Khabarovsk
Цветаева → Tsvetaïeva
Черненко → Tchernenko
Пушкин → Pouchkine
Щедрин → Chtchedrine
Черномырдин → Tchernomyrdine
Область → Oblast
Элиста → Elista
Биюлин → Biouline
Нефтеюганск → Nefteïougansk
Юрий → Iouri
Союз → Soyouz
Мария → Maria
Майя → Maïa
Маяковский → Maïakovski
Ярославль → Iaroslavl
Ялта → Yalta
"""
tests = []
for line in fr_examples.split("\n"):
line = line.strip()
if line == "":
continue
parts = line.split(" → ")
tests.append(parts)
rufr = transliterator_from_rules("ru-fr", fr_rules)
for w in tests:
# assert w[1] == rufr.transliterate(w[0]), f"{w[0]:15s} → {rufr.transliterate(w[0])}"
if w[1] != rufr.transliterate(w[0]):
print("Error", f"{w[0]:15s} → {rufr.transliterate(w[0])} ({w[1]})")
if w[1].upper() != rufr.transliterate(w[0].upper()):
print("Uppercase error", f"{w[0].upper():15s} → {rufr.transliterate(w[0].upper())} ({w[1].upper()})")
# print(f"{w[0]:15s} → {rufr.transliterate(w[0])}")