Repository navigation
Read two family names in the Czech and Slovak packs (3.0, 3f amended) - #973
Merged
Merged
Conversation
locales.CS and locales.SK turn on Policy.two_family_names (rules/O6)
through a [rules] table in cs.toml and sk.toml, compiled into each pack's
policy patch as locales.ES carries its own: "Alena Pešová Řehořová" gives
family "Pešová Řehořová" where the default gives middle "Pešová". There
is no given-name list beside it, so two given names pay for it ("Petr
Pavel Novák" gives family "Pavel Novák"); a family comma keeps both.
locales.SL and locales.HR are unchanged, two_given_names stays off, and
the default's parses do not move.
Measured with local_agreement.py --base on the built tree, records
agreeing in every field, the pack before -> after: cz-candidates 96.97%
-> 97.47% (1,295 fixed, 442 broken), ORCID CZ 94.99% -> 96.41%, ORCID SK
94.84% -> 96.40%. Every broken record has two or more given words.
- The packs now carry a patch beside their choice, so each declares
DEVIATES for the patch's part. ES's declaration, rules/O6's, moves into
_locale.deviates_by_two_family_names, which all three packs return.
- tests/v2/test_locales.py: the choice-word rotators rewritten as names
the patch alone leaves unmoved, rotators for the patch, pinned rows for
the double surname and the two-given-name cost under both packs, a
contents test, and the combined gate expecting the same-value scalar
warning that stacking es with cs or sk now raises.
- test_vocab.py fixtures named cs.toml move to pl.toml.
- cldr_agreement_locales.json re-recorded for cs and sk only.
- Decisions entries in vocabulary-model, O6 and deviates-registry;
docs/locales.rst, the 3f release-log bullet, the RFC's surname-span
line and AGENTS.md updated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…less words
- parser_for warned whenever two packs set one scalar policy field, even
to the same value, so parser_for(locales.CS, locales.SK), which both
turn two_family_names on, warned though nothing was overridden, and
failed a caller running with warnings as errors. It now warns only
where the later value differs. test_parser.py pins both sides, and
docs/locales.rst's composition list says so.
- _locale.deviates_by_two_family_names missed a word the tokenizer
splits beside a word holding no letter ('김민준 1', 'JanPavel -'
moved undeclared). It now counts each letterless word as a unit too,
which fixes locales.ES's declaration as well, since the three packs
share it. Both inputs are now rotators of cs, sk and es.
- Docs:
- _locale's docstring no longer gives cs and sk a given-name list.
- decisions/O6 says no population-wide list is published (ČSÚ's
newborn top 100 is the open lead), and adds the against-default
row: 1,318 fixed, 440 broken.
- decisions/vocabulary-model gives every run behind its figures,
drops the unmeasured cause of the two-given ratio, and names the
3f entry's "Each module ships no DEVIATES" among the claims
amended.
- docs/locales.rst counts records, not candidates, and notes the
RU and ES stacks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ry field - parser_for compared the raw patch values, so two packs writing the same script_orders mapping in another key order warned, though the policies they build are equal. Each scalar is now compared as the applied Policy holds it, canonical, after the pack's patch is applied. - test_parser.py parametrizes both sides over every scalar PolicyPatch field, the table held to dataclasses.fields so a new field cannot escape it, with a respelled script_orders row. Against the previous commit's parser the respelled row fails; against 8aa0898's, every same-value row and the shipped stacks fail. - Release log: a Behavior Changes bullet. Packs agreeing on a value no longer warn, where 2.0.0 through 2.8.0 did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this changes
locales.CSandlocales.SKnow read two family names (Policy.two_family_names, rules/O6). A Czech or Slovak woman who keeps her own surname beside her husband's writes the two without a hyphen, and the packs keep that double surname whole:This was decided in chat on 2026-10-30, after measuring three populations. The parser gains in all three, and the cost is the same in each: a name with two given names reads its second given name into the family.
locales.SLandlocales.HRare unchanged.two_given_namesstays off. The default parser does not move.How
nameparser/vocab/cs.tomlandsk.tomleach gain a[rules]table withtwo_family_names = true.tools/vocab/build.py'sPACK_RULESgainscsandsk, the build rewritesnameparser/config/_rules.py, and each pack carriespolicy=rules_patch(tag). This is howlocales.EScarries its switch.DEVIATES, covering what the patch changes. ES's declaration is exactly rules/O6's: three or more name words, or three or more runs of letters. I moved it intonameparser/_locale.pyasdeviates_by_two_family_names, and theDEVIATESof all three packs return it, so the three declarations can't drift apart. ES's behavior is unchanged. The second commit also fixes a gap the shared predicate inherited from ES: a word the tokenizer splits, beside a word with no letters (김민준 1,Jan\u200bPavel -), moved undeclared. Each word with no letters now counts as a unit, which fixes ES too.tests/v2/test_locales.py).MUDr Novák,Novák PhDr.,Jana Nováková (roz. Svobodová)), because the patch alone moved the old three-word ones. The patch gets rotators of its own.FAMILY_FIRSTand before a family comma;St Clair Smithunder CS now reads familyClair Smith.test_cs_and_sk_pack_contentschecks what each pack holds and that the threeDEVIATESagree.jaextra.test_vocab.py. Four build fixtures named a syntheticcs.tomlwithout a[rules]table, which the build now refuses for a file a pack reads. They move topl.toml, as Add the Spanish and Portuguese packs, locales.ES and locales.PT (3.0, 3g) #964 moved itses.tomlfixtures.tools/differential/cldr_agreement_locales.jsonis re-recorded forcsandskonly (checked key by key). Whole renderings agreeing went from 14/24 to 12/24 for cs and from 15/24 to 11/24 for sk: the native double surnames are gained and the given-given-surname renderings lost. The default's records (cldr_agreement.json, GND, Wikidata) and the committed snapshot are unchanged.docs/locales.rst: the cs/sk rows, a paragraph with doctests (the gain, the cost, the comma, the measurement, and how to switch it off while keeping the vocabulary).vocabulary-model(dated, after the 3f entry),O6(a Standing line and a Log entry) anddeviates-registry.Measured on the built tree (2026-10-30)
Run with
local_agreement.py SOURCE [--locale cs] --base <bfb91163 checkout>. Each figure counts records agreeing in every field:locales.CSbeforelocales.CSnowlocales.SK, cz-candidates scores 165,878. On ORCID the two packs read alike.--basechecks report "matches the base".For the reviewer
A cost found in review: unlisted birth markers. A birth marker the chosen language doesn't list, standing between two surnames, is now taken into the family. Under both packs,
Jana Nováková rod. Svobodováreads familyrod. Svobodová, where the default reads middleNováková rod.. Slovakrodenábehaves the same way, and so does Czechroz.underSK. The listedroz.(under CS) androzená(under both) still route the maiden name. A Slovakrod./rodenáreading is vocabulary work, recorded as Open in the decisions entry rather than added here.Packs agreeing on a scalar no longer warn. Before this PR,
parser_forwarned whenever two packs set the same scalar policy field, even to the same value, asdocs/locales.rstdocumented. With CS, SK and ES all turningtwo_family_nameson, the most natural stack,parser_for(locales.CS, locales.SK), would have warned although nothing was overridden, and failed callers running with warnings as errors. It now warns only where the later value differs.test_parser.pypins both sides, anddocs/locales.rstand the decisions entry say so. This changes the warning's condition for every pack, not just these.Checks
uv run pytest: 33,647 passed (with thejaextra), plus-n0 -m serial(42).uv run mypy,uv run ruff check: clean.test_locales.pyand the CLDR tests with thejaextra installed.sphinx-build -b doctest docs: 570 tests, 0 failures.python -m doctest README.rst.deviates-registry's Standing line still listed CS and SK as choice-only packs;_letter_runsgave a reason that no longer applies.It also surfaced the birth-marker cost above.
Resolves the draft issue "Should locales.CS turn on two_family_names?", which was never filed.
🤖 Generated with Claude Code