package bible import ( "fmt" "regexp" "sort" "strconv" "strings" "github.com/lukaszkasprzak/lectio/internal/psalter" ) // polishToEn maps Polish Biblical abbreviations to the book name accepted by // the kjv-family tools. Gospels use the short forms (Mat/Mark/Luke/John); // other books use full names that the tools resolve by unique prefix. // Ported verbatim from ewangelia.py POLISH_TO_EN. var polishToEn = map[string]string{ // Old Testament "Rdz": "Genesis", "Wj": "Exodus", "Kpł": "Leviticus", "Lb": "Numbers", "Pwt": "Deuteronomy", "Joz": "Joshua", "Sdz": "Judges", "Rt": "Ruth", "1 Sm": "1 Samuel", "2 Sm": "2 Samuel", "1 Krl": "1 Kings", "2 Krl": "2 Kings", "1 Krn": "1 Chronicles", "2 Krn": "2 Chronicles", "Ezd": "Ezra", "Ne": "Nehemiah", "Tb": "Tobit", "Jdt": "Judith", "Est": "Esther", "1 Mch": "1 Maccabees", "2 Mch": "2 Maccabees", "Hi": "Job", "Ps": "Psalms", "Prz": "Proverbs", "Koh": "Ecclesiastes", "Pnp": "Song of Solomon", "Mdr": "Wisdom", "Syr": "Sirach", "Iz": "Isaiah", "Jr": "Jeremiah", "Lm": "Lamentations", "Ba": "Baruch", "Ez": "Ezekiel", "Dn": "Daniel", "Oz": "Hosea", "Jl": "Joel", "Am": "Amos", "Ab": "Obadiah", "Jon": "Jonah", "Mi": "Micah", "Na": "Nahum", "Ha": "Habakkuk", "So": "Zephaniah", "Ag": "Haggai", "Za": "Zechariah", "Ml": "Malachi", // New Testament "Mt": "Mat", "Mk": "Mark", "Łk": "Luke", "J": "John", "Dz": "Acts", "Rz": "Romans", "1 Kor": "1 Corinthians", "2 Kor": "2 Corinthians", "Ga": "Galatians", "Ef": "Ephesians", "Flp": "Philippians", "Kol": "Colossians", "1 Tes": "1 Thessalonians", "2 Tes": "2 Thessalonians", "1 Tm": "1 Timothy", "2 Tm": "2 Timothy", "Tt": "Titus", "Flm": "Philemon", "Hbr": "Hebrews", "Jk": "James", "1 P": "1 Peter", "2 P": "2 Peter", "1 J": "1 John", "2 J": "2 John", "3 J": "3 John", "Jud": "Jude", "Ap": "Revelation", } var ( porRe = regexp.MustCompile(`(?i)^\s*por\.\s*`) refrainRe = regexp.MustCompile(`\s*\(R\.:.*$`) wsRe = regexp.MustCompile(`\s+`) iRe = regexp.MustCompile(`\s+i\s+`) dashRe = regexp.MustCompile(`\s*[-–—]\s*`) verseLetterRe = regexp.MustCompile(`(\d)[a-c]\b`) psalmRestRe = regexp.MustCompile(`(\d+)(?:\s*\((\d+)\))?(.*)$`) digitsRe = regexp.MustCompile(`\d+`) ) // polishBookKeys holds the POLISH_TO_EN keys sorted longest-first, matching // the Python `sorted(POLISH_TO_EN, key=len, reverse=True)` traversal order. var polishBookKeys = sortedPolishBookKeys() func sortedPolishBookKeys() []string { keys := make([]string, 0, len(polishToEn)) for k := range polishToEn { keys = append(keys, k) } sort.SliceStable(keys, func(i, j int) bool { return len(keys[i]) > len(keys[j]) }) return keys } // psalmRef maps the psalm citation body ("63 (62), 2. 3-4. ...") to the target Psalter. func psalmRef(rest, system string) string { m := psalmRestRe.FindStringSubmatch(rest) if m == nil { return rest } heb, _ := strconv.Atoi(m[1]) tail := m[3] if system == "vulgate" { ch := m[1] if m[2] != "" { ch = m[2] } return ch + tail } if system == "drb" { tail = digitsRe.ReplaceAllStringFunc(tail, func(s string) string { n, _ := strconv.Atoi(s) return strconv.Itoa(psalter.DrbVerse(heb, n)) }) } return strconv.Itoa(heb) + tail } // ToEnglishRef converts a Polish citation to kjv-tool style: "Mt 7, 1-5" -> "Mat 7:1-5". // // Handles the extra apparatus of non-gospel readings: a leading "por." (compare) // marker, a trailing "(R.: ...)" responsorial refrain, and psalm versification. // system selects the target Psalter: "vulgate" (vul/grb/wuj) uses the citation's // Vulgate chapter (62 of "63 (62)"); "drb" uses the Hebrew chapter (63) with the // DRB title-fold verse shift; other values use the Hebrew chapter unshifted. func ToEnglishRef(plRef, system string) (string, error) { plRef = porRe.ReplaceAllString(plRef, "") // 'compare' marker plRef = refrainRe.ReplaceAllString(plRef, "") // responsorial refrain plRef = wsRe.ReplaceAllString(strings.TrimSpace(plRef), " ") var book string found := false for _, k := range polishBookKeys { if plRef == k || strings.HasPrefix(plRef, k+" ") { book = k found = true break } } if !found { return "", fmt.Errorf("unknown book in reference: %q", plRef) } rest := strings.TrimSpace(plRef[len(book):]) if polishToEn[book] == "Psalms" { rest = psalmRef(rest, system) } rest = strings.ReplaceAll(rest, ", ", ":") // chapter/verse separator rest = strings.ReplaceAll(rest, ". ", ",") // disjoint verse groups rest = iRe.ReplaceAllString(rest, ",") // Polish 'and' rest = dashRe.ReplaceAllString(rest, "-") // normalise ranges rest = verseLetterRe.ReplaceAllString(rest, "$1") // drop verse-part letters (15a -> 15) rest = strings.ReplaceAll(rest, " ", "") return strings.TrimSpace(fmt.Sprintf("%s %s", polishToEn[book], rest)), nil }