Skip to content

Read a four-character Han name opening with two surnames as a surname pair (#845) - #1127

Merged
derek73 merged 7 commits into
masterfrom
feat/han-surname-pair
Nov 7, 2026
Merged

derek73 merged 7 commits into
masterfrom
feat/han-surname-pair

Conversation

@derek73

@derek73 derek73 commented Nov 7, 2026

Copy link
Copy Markdown
Owner

Closes #845

What changes

Under locales.ZH, a four-character Han name whose first two characters are each a listed single surname, and not a listed compound, reads both as the family, in two units (new rule W5 (a Han surname pair)):

Input (parser_for(locales.ZH)) 2.1.0 – 2.8.0 / master This branch
王李小明 family 王, given 李小明 family 王李, given 小明, surname1 王, surname2 李 (+ SEGMENTATION report naming 王 + 李小明)
王李 小明 family 王, given 李, middle 小明 family 王李, given 小明 (no report)
歐陽小明, 李林伟, 李林 伟, 王李 先生 unchanged unchanged

This is the married double surname (冠夫姓) Taiwan's Civil Code made the default until 1998, and the double surname some mainland children carry. Measured on the tw-donors local corpus: 4,868 four-character names have the shape and all read 1 + 3 before; for 2,076 of them the woman's own name (劉碧珠 beside 丁劉碧珠) is itself a donor in the file. Three-character names (51,047 of the shape, 1,188 with that sign) are left alone. Details and recompute recipe: docs/design/decisions/W5-han-surname-pair.md.

Decided with the proposal: the two surnames are the family's two units in the surname1/surname2 views (not maiden), the rule applies under locales.ZH alone, and the undivided form is reported.

Scope and boundaries

  • The pair is divided only where every name word is Han (post-nominals ending the name aside) and the name is read family-first, so a mixed-script name or script_orders=() reads exactly as before. A Latin title declines (Dr. 王李小明 → family 王), recorded as Accepted in W5.
  • The spaced form needs a two-character word after the pair, so 李林 伟 (a stray space; tw-donors' only two spaced names of the shape are this) keeps W1's reading.
  • R1 (fields are views of the parsed words): a field outside the suffix now joins words written with nothing between them, so the divided family renders 王李. This also rejoins any word a CJK division cut where its halves land in one field: 김민준 John gives given_names 김민준 where 2.1.0 – 2.8.0 gave 김 민준.
  • No committed agreement record moves; the snapshot only gains the new rule and case rows.

Docs

New rule W5 and decisions/W5; amended W1 (unspaced CJK division), R1, R10 (the second-surname view), R11 (the first-surname views) and their decisions Standing lines, root AGENTS.md, mechanisms.md (a field note: R1's join hides an extra division inside one field, so assert word counts), usage.rst, locales.rst, release log.

Review

Reviewed by four agents (design docs, code, comments, test coverage) and a second round on the fix commits. Their findings are fixed in the later commits: the split now waits for the order, the tag is stripped from published tokens, the spaced form is bounded, and the stale prose and counts are corrected. Every new guard row fails on the pre-fix code. Suite green on 3.11 (with the ja extra) and 3.15; mypy, ruff, both Sphinx builds and the frame benchmarks pass.

🤖 Generated with Claude Code

derek73 and others added 5 commits November 6, 2026 19:27
… pair (#845)

Under locales.ZH, a four-character Han name whose first two characters
are each a listed single surname, and no listed compound, now reads them
as the family in two units (rules/W5): 王李小明 gives family 王李, given
小明, surname1 王, surname2 李, where it gave family 王, given 李小明. The
same pair written with a space before the given name (王李 小明) reads
the same way, where it gave given 李, middle 小明. The unspaced division
records a SEGMENTATION report naming the longest-first reading.

script_segment divides the token after both surnames and tags the
second; post_rules makes it the family's second unit with the tags O6
writes, so the R10/R11 views read it unchanged. A field now joins words
written with nothing between them without a space (rules/R1), so the
divided family renders 王李.

Measured on tw-donors: 4,864 four-character names have the shape, and
for 2,076 the woman's own name is itself a donor in the same file. No
committed agreement record moves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The segment stage divided and reported the pair before the order was
known, so a mixed-script name read given-first reported a division its
reading did not take. post_rules now records the SEGMENTATION report when
it reads the pair, and only for a pair written undivided.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…845)

- The pair is divided only where every word of the name is Han and the
  name is read family-first, so a mixed-script name or a given-first
  Han order keeps W1's division and reads as before (Amy 王李小明,
  script_orders=()); a Latin title declines too, recorded as Accepted.
- A spaced pair needs a word of two after the space, so a
  three-character name with a stray space (李林 伟, tw-donors' 廖榮 清
  and 范文 豪) keeps W1's reading.
- SURNAME_PAIR_TAG is stripped from published tokens.
- R1's join is stated for every field but the suffix, and for any word
  a division cut; the release log says so.
- R10/R11 Signal lines and Standing, AGENTS.md, mechanisms.md and the
  assemble/state comments name W5 beside O6; decisions/W5 recounts
  4,868 with the parser's Han test and records the review's moves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Case rows for the pair (undivided with its report, spaced, spaced with a
middle, an honorific after the space, the word after the pair asked
rather than the last, three characters, a stray space, a mixed-script
name), and tests for a Latin word under a declared family-first order,
the folded middle's join guard and a revised pair family.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The order check counted a post-nominal ending the name, which is no name
piece of assign's, so 王李小明さん, 王李小明씨 and 王李小明 PhD lost the
pair; it now steps over that run as the honorific peel does (fuzzed:
40,460 parses, every division read). The Latin-word test asserts the
word count, since R1's join hides an extra division inside one field
(recorded in mechanisms.md's field notes); Han's own order outranking a
declared one is tested; W1, usage.rst and decisions/W5 name the
two-character given name the spaced pair needs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@derek73 derek73 added enhancement design Changes what the model can express (a shape decision) labels Nov 7, 2026
@derek73 derek73 self-assigned this Nov 7, 2026
# Conflicts:
#	nameparser/_pipeline/_assemble.py
@derek73 derek73 added this to the 3.0 milestone Nov 7, 2026
script_segment tags a pair only where post_rules will read it, so its
two declines (an order that is not family-first, a tag not right after
the family) are reached only by a hand-placed tag; the test places one
and holds that nothing is marked or reported.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@derek73
derek73 merged commit c321380 into master Nov 7, 2026
13 checks passed
@derek73
derek73 deleted the feat/han-surname-pair branch November 7, 2026 04:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

design Changes what the model can express (a shape decision) enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Should locales.ZH read 王李小明 as family 王李, given 小明?

1 participant