Skip to content

Commit 75b3c9c

Browse files
authored
Merge pull request #306 from derek73/fix/ukrainian-conjunction
Add the Ukrainian conjunction й (#267 comment, #269 follow-up)
2 parents d09ac7f + 60943ed commit 75b3c9c

3 files changed

Lines changed: 31 additions & 1 deletion

File tree

docs/release_log.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Release Log
2626
- Fix the katakana middle dot ``・`` (U+30FB, and its halfwidth twin U+FF65) being read as part of a name rather than as the divider it is: it now separates tokens exactly as a space does. A transcribed foreign name therefore divides into its parts and, being wholly katakana, keeps its source order — ``"マイケル・ジャクソン"`` gives given ``マイケル``, family ``ジャクソン``, where 1.x left the whole string in ``first`` — while a kanji pair written the same way takes the family-first rule (``"高橋・一郎"`` → family ``高橋``). Native Japanese names never contain this character and no other script's names use it, so the separation is unconditional, which also means it is **not** covered by the two policy opt-outs. Rendering follows, the way the Korean split's does: the dot comes back as a space, so ``str(HumanName("マイケル・ジャクソン"))`` is now ``"マイケル ジャクソン"``, and that reaches delimited content too — the nickname in ``"山田 太郎 (マイケル・ジャクソン)"`` renders ``"マイケル ジャクソン"``. The Chinese interpunct ``·`` is not an unconditional separator like these two: U+00B7 is also the Catalan punt volat and appears inside legitimate names (``Gal·la``), so it divides only between classified-script characters — the transcription treatment it marks is #298's (#272)
2727
- Fix 间隔号-divided transcriptions parsing as one unsplit token: U+00B7 — the interpunct Chinese text divides a transcribed foreign name with, ``威廉·莎士比亚`` for William Shakespeare — is now a token separator between characters of a classified script, and a name it divides keeps its source order and is never segmented: the dot is the transcription marker, playing the role pure katakana plays in the kana license. It divides ONLY between classified-script characters, so the Catalan punt volat interior to names like ``Gal·la`` is untouched. The Japanese nakaguro is deliberately not a transcription marker — ``高橋・一郎`` is roster formatting, 姓・名, and keeps its family-first reading — so a transcription typed with the wrong dot (``威廉・莎士比亚``) reads by the convention of the codepoint it was typed with; like the spaced form, only the Chinese dot rescues it. Rendering stays space-joined (``str(HumanName("威廉·莎士比亚"))`` is ``"威廉 莎士比亚"``); a custom ``string_format`` such as ``"{first}·{last}"`` reinstates the dot (#298)
2828
- Fix NFD-decomposed input missing the East Asian defaults entirely: script classification now normalizes to NFC before deciding, so a Korean or Japanese name typed on macOS — where decomposed text is routine — gets the same order rule as its composed twin, which it silently did not before. Segmentation MATCHING deliberately stays raw, so an unspaced NFD hangul name is ordered correctly but not split, rather than being split in the wrong place. One gotcha worth stating plainly: parse output preserves the encoding it was given, so for NFD input ``name.family == "김"`` is ``False`` even though it is the same name — compare NFC-normalized text when comparing across encodings (#272)
29+
- Fix the Ukrainian conjunction ``й`` not joining the pieces around it: it is the euphonic alternate of ``і``, the two chosen by the surrounding vowel and consonant rather than by meaning (``"Олесь і Олена"`` but ``"Марія й Петро"``), so real Ukrainian data carries both spellings and shipping only ``і`` recognized just one of them. ``"Олесь й Олена Коваленки"`` now gives given ``"Олесь й Олена"`` where the ``й`` previously landed in ``middle``. Same treatment as the ``и``/``і`` entries added in 2.0.0, single-letter carve-out included: the conjunction joins only once the name has enough pieces, and a punctuated initial still wins, so ``"Й. Сліпий"`` is unaffected. Raised in a comment on #267
2930

3031
* 2.0.0 - July 27, 2026
3132

nameparser/config/conjunctions.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@
99
'the',
1010
'und',
1111
'y',
12-
# #269: Cyrillic (ru/uk/bg) "and": и, і, та.
12+
# #269: Cyrillic (ru/uk/bg) "and": и, і, та. Ukrainian writes і and
13+
# й for the same conjunction, alternating on the surrounding
14+
# vowel/consonant for euphony ("Олесь і Олена", "Марія й Петро"),
15+
# so real data carries both spellings and neither alone suffices.
1316
'и',
1417
'і',
18+
'й',
1519
'та',
1620
# #269: Greek "and": και.
1721
'και',

tests/v2/test_locales.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,16 @@ def test_non_interference_all_packs_combined() -> None:
931931
# Ukrainian "і" is single-character like "и", so the same
932932
# single-letter carve-out applies: pinned with a 5-piece name.
933933
("проф і акад Тарас Григорович Шевченко", "title", "проф і акад"),
934+
# Ukrainian "й" is the euphonic alternate of "і" (the two swap by
935+
# surrounding vowel/consonant, so real data carries both) -- same
936+
# single-letter carve-out, pinned with the same 5-piece shape.
937+
("проф й акад Тарас Григорович Шевченко", "title", "проф й акад"),
938+
# ...and joining two given names, the shape #267's reporter raised:
939+
# a bare Cyrillic letter between given names reads as the
940+
# conjunction, not an initial (Cyrillic typography writes initials
941+
# with periods -- see
942+
# test_267_dotted_cyrillic_initial_wins_over_conjunction).
943+
("Олесь й Олена Коваленки", "given", "Олесь й Олена"),
934944
# Greek titles + conjunction (και has 3 letters, so the single-char
935945
# initial carve-out above never applies to it). Bare κ is NOT
936946
# shipped -- it collides with the initial+surname shape (see the
@@ -1075,3 +1085,18 @@ def test_269_bare_greek_kappa_not_a_title() -> None:
10751085
assert n.title == ""
10761086
assert n.given == "Κ."
10771087
assert n.family == "Παπαδόπουλος"
1088+
1089+
1090+
def test_267_dotted_cyrillic_initial_wins_over_conjunction() -> None:
1091+
# Blast-radius guard for the single-letter Cyrillic conjunctions
1092+
# (и/і/й): each is also the first letter of real given names
1093+
# (Игорь, Ірина, Йосип), so the shipped entries would be a trap if
1094+
# membership could outrank a punctuated initial. It cannot -- the
1095+
# initial regex's dotted branch is Unicode-aware -- and #267 settled
1096+
# the BARE letter in the conjunction's favor precisely because
1097+
# Cyrillic typography writes initials with the period.
1098+
for dotted, family in (("И.", "Иванов"), ("І.", "Франко"),
1099+
("Й.", "Сліпий")):
1100+
n = parse(f"{dotted} {family}")
1101+
assert n.given == dotted
1102+
assert n.family == family

0 commit comments

Comments
 (0)