Skip to content

Instantly share code, notes, and snippets.

@dotemacs
Created June 11, 2026 09:02
Show Gist options
  • Select an option

  • Save dotemacs/0525260a5d5c608187823664284f917b to your computer and use it in GitHub Desktop.

Select an option

Save dotemacs/0525260a5d5c608187823664284f917b to your computer and use it in GitHub Desktop.

Српски речник за коридер (KOreader), набрзака

Поводом дискусије https://cirilicalab.org/d/10-srpski-elektronski-recnik/27

Преузмите и распакујте

mkdir eng_serb_cyrl
cd eng_serb_cyrl

curl -L -O \
  https://gitlab.com/avsej/dicts-stardict-form-xdxf/raw/d636cc5e8d4a47e22ac7466f4af6d435a8a3f650/002c/stardict-comn_sdict05_eng_serb-2.4.2.tar.gz

tar xzf stardict-comn_sdict05_eng_serb-2.4.2.tar.gz
cd stardict-eng_serb-2.4.2

Сачувајте ову скрипту као latin_to_cyrillic_stardict.py

#!/usr/bin/env python3
import gzip
import re
import struct
from pathlib import Path

SRC_BASENAME = "eng_serb"
DST_BASENAME = "eng_serb_cyrl"

latin_to_cyr = {
    "dž": "џ", "Dž": "Џ", "DŽ": "Џ",
    "lj": "љ", "Lj": "Љ", "LJ": "Љ",
    "nj": "њ", "Nj": "Њ", "NJ": "Њ",

    "a": "а", "b": "б", "v": "в", "g": "г", "d": "д",
    "đ": "ђ", "e": "е", "ž": "ж", "z": "з", "i": "и",
    "j": "ј", "k": "к", "l": "л", "m": "м", "n": "н",
    "o": "о", "p": "п", "r": "р", "s": "с", "t": "т",
    "ć": "ћ", "u": "у", "f": "ф", "h": "х", "c": "ц",
    "č": "ч", "š": "ш",

    "A": "А", "B": "Б", "V": "В", "G": "Г", "D": "Д",
    "Đ": "Ђ", "E": "Е", "Ž": "Ж", "Z": "З", "I": "И",
    "J": "Ј", "K": "К", "L": "Л", "M": "М", "N": "Н",
    "O": "О", "P": "П", "R": "Р", "S": "С", "T": "Т",
    "Ć": "Ћ", "U": "У", "F": "Ф", "H": "Х", "C": "Ц",
    "Č": "Ч", "Š": "Ш",
}

pattern = re.compile("|".join(sorted(map(re.escape, latin_to_cyr), key=len, reverse=True)))

def transliterate_text(s):
    return pattern.sub(lambda m: latin_to_cyr[m.group(0)], s)

def transliterate_definition(s):
    # Preserve StarDict/HTML tags like <k>, </k>, <br>, etc.
    # Also preserve contents of <k>...</k>, because those are English headwords.
    parts = re.split(r"(<k>.*?</k>|<[^>]+>)", s, flags=re.DOTALL)

    out = []
    for part in parts:
        if not part:
            continue
        if part.startswith("<k>") and part.endswith("</k>"):
            out.append(part)
        elif part.startswith("<") and part.endswith(">"):
            out.append(part)
        else:
            out.append(transliterate_text(part))
    return "".join(out)

def read_idx(path):
    entries = []
    data = Path(path).read_bytes()
    i = 0

    while i < len(data):
        end = data.index(b"\0", i)
        word = data[i:end]
        offset, size = struct.unpack(">II", data[end + 1:end + 9])
        entries.append((word, offset, size))
        i = end + 9

    return entries

def update_ifo(src, dst, idx_size):
    text = Path(src).read_text(encoding="utf-8")

    text = re.sub(r"^bookname=.*$",
                  "bookname=English-Serbian dictionary Cyrillic",
                  text,
                  flags=re.MULTILINE)

    text = re.sub(r"^idxfilesize=\d+$",
                  f"idxfilesize={idx_size}",
                  text,
                  flags=re.MULTILINE)

    if "description=" in text:
        text = re.sub(r"^description=.*$",
                      "description=Serbian definitions transliterated from Latin to Cyrillic",
                      text,
                      flags=re.MULTILINE)
    else:
        text += "\ndescription=Serbian definitions transliterated from Latin to Cyrillic\n"

    Path(dst).write_text(text, encoding="utf-8")

idx_entries = read_idx(f"{SRC_BASENAME}.idx")

with gzip.open(f"{SRC_BASENAME}.dict.dz", "rb") as f:
    src_dict = f.read()

new_dict = bytearray()
new_idx = bytearray()

for word, offset, size in idx_entries:
    raw_entry = src_dict[offset:offset + size]
    text = raw_entry.decode("utf-8", errors="replace")

    converted = transliterate_definition(text).encode("utf-8")

    new_offset = len(new_dict)
    new_size = len(converted)

    new_dict.extend(converted)
    new_idx.extend(word + b"\0" + struct.pack(">II", new_offset, new_size))

Path(f"{DST_BASENAME}.dict").write_bytes(new_dict)
Path(f"{DST_BASENAME}.idx").write_bytes(new_idx)
update_ifo(f"{SRC_BASENAME}.ifo", f"{DST_BASENAME}.ifo", len(new_idx))

print("Created:")
print(f"  {DST_BASENAME}.ifo")
print(f"  {DST_BASENAME}.idx")
print(f"  {DST_BASENAME}.dict")

А онда:

  python3 latin_to_cyrillic_stardict.py

Требало би да добијете:

  eng_serb_cyrl.ifo
  eng_serb_cyrl.idx
  eng_serb_cyrl.dict

Инсталирајте у коридер

Направите директоријум за речник:

koreader/data/dict/English Serbian Cyrillic dictionary/

Копирајте ова три фајла тамо:

  eng_serb_cyrl.ifo
  eng_serb_cyrl.idx
  eng_serb_cyrl.dict

Поново покрените KOReader, па изаберите речник са списка речника:

лупа -> Settings -> Dictionary settings -> Manage dictionaries

и ту изаберите речник (који ће имати исто име као директоријум који сте направили горе English Serbian Cyrillic dictionary).

Напомена: речи за претрагу остају на енглеском. И пошто су српске речи биле на ”ћелавој” латиници, онда су речи типа cudo, krivicno, пресловљене у цудо, кривицно.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment