Skip to content

afrikaans: a word-final ⟨c⟩ is [k], not the soft [s] (#757) - #759

Merged
christopherthompson81 merged 2 commits into
mainfrom
afrikaans-final-c
Aug 8, 2026
Merged

afrikaans: a word-final ⟨c⟩ is [k], not the soft [s] (#757)#759
christopherthompson81 merged 2 commits into
mainfrom
afrikaans-final-c

Conversation

@christopherthompson81

@christopherthompson81 christopherthompson81 commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Closes #757.

The call

The rule is "soft [s] BEFORE a front vowel". Word-finally there is no following vowel, so the soft branch cannot apply — but it did:

out += "eiyêéè".includes(w[i + 1] ?? "") ? "s" : "k";   //  includes("") === true

franc → frans, arc → ars, bloc → blɔs. #756 preserved that verbatim, correctly — a data move must not change output — and left the decision to this issue.

The decision is that the accident inverted the rule rather than extending it: no following letter means the soft condition is unmet, not met. That is an argument from the rule's own statement, and it needs no corpus.

⚠ Not referee-confirmed, and it cannot be

af.wiktionary-af.tsv contains no word-final ⟨c⟩ at all… the letter name C → sɪə reaches output through the initialism path, not this rule. Both halves of that were wrong — see the addendum.

The corpus's one word-final ⟨c⟩ is the letter name C → sɪə, and it does traverse this branch. It simply misses both ways (s, now k, against sɪə), which is why the score is unmoved.

So af is unmoved at 1658/2220 (74.7%), exactly as predicted. The new goldens pin the rule being self-consistent and say so in the comment; they are not evidence of a measured improvement, and shouldn't be read as one.

Found along the way, deliberately not bundled: #758

The ⟨c⟩ code rule runs before the fixed table, so "ch": "ʃ" never fires — chemie → kɦiəmi, chirurg → kɦirœrχ. kɦ- is not a possible Afrikaans onset, and unlike #757 this one is referee-visible.

I measured the naive fix (let the digraph win): +1 word, but it breaks Christus → ʃrəstœs (should be [kr-]) and pushes chemie to [ʃ] where the referee wants [x]. Afrikaans ⟨ch⟩ is three sounds by source — [ʃ] French, [x] Greek/Dutch, [k] before ⟨r⟩ — so it needs a conditioning decision, not a reordering. Filed as #758 with those numbers so the next attempt starts from data.

npm run ci green — 228 files / 3141 tests.

🤖 Generated with Claude Code

https://claude.ai/code/session_012Lc3WnUgogC7okV7n53vjr


Review addendum — my stated reason was false

I claimed the referee holds no word-final ⟨c⟩, and that its C → sɪə entry reaches output via the initialism path. Both wrong, and the review caught it:

  • C is a word-final ⟨c⟩, and eval.ts feeds af through phonemizeWord directly, with no normalization pass — so that entry goes through this exact branch, sk with this change.
  • The initialism normalizer only fires on runs of ≥2 letters, so a lone C never reaches it.

My original grep was case-sensitive and lowercase-only. I then saw the C entry in later output and explained it away with an assumption I never checked — the same shape of error as the "corpus isn't in-repo" claim in #748.

The conclusion survives: s and k both miss against sɪə, so the folded backbone is unmoved at 1658/2220 and this change remains rule-consistency rather than a measured gain. But the reason has been corrected in the test comment, because as written it would have told the next reader that nothing exercises the branch.

The underlying gap — a bare single letter read as a sound instead of spelled as its name (C → k, B → p) — is filed as #761.

Test also moved into the g2p describe block, where it belongs.

The rule is "soft [s] BEFORE a front vowel". Word-finally there is no following vowel, so the soft
branch cannot apply — but it did, because the test was `"eiyêéè".includes(w[i + 1] ?? "")` and
includes("") is TRUE for any string. franc→frans, arc→ars, bloc→blɔs.

#756 preserved that verbatim, correctly: a data move must not change output. Deciding it needed the
phonological call, and the call is that the accident INVERTED the rule rather than extending it — no
following letter means the soft condition is unmet, not met.

⚠ NOT REFEREE-CONFIRMED, and it cannot be: af.wiktionary-af.tsv has no word-final ⟨c⟩ at all — its 20
⟨c⟩ entries are surnames (Coetzee, Terblanche), ⟨ch⟩ words, and the letter name C→sɪə. af is unmoved at
1658/2220, exactly as predicted. The goldens pin the rule being self-consistent, and say so.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Lc3WnUgogC7okV7n53vjr
… the conclusion was not

I wrote that af.wiktionary-af.tsv contains no word-final ⟨c⟩, and that its C→sɪə entry reaches output
through the initialism path. Both false. The entry IS a word-final ⟨c⟩, eval.ts feeds af through
phonemizeWord directly, and the initialism normalizer only fires on runs of two or more letters — so
that entry traverses this exact branch, going s→k with this change.

The conclusion survives: it misses both ways against sɪə, which is why the folded backbone is unmoved
at 1658/2220. But the stated reason would have told the next reader that nothing exercises the branch,
which is the opposite of true. My original grep was case-sensitive and lowercase-only; I then saw the C
entry in later output and explained it away with an assumption I never checked.

Filed the underlying gap as #761: a bare single letter is read as a sound rather than spelled as its
name (B→p too), because the initialism normalizer needs ≥2 letters. Also moved the new test into the
g2p describe block, where it belongs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Lc3WnUgogC7okV7n53vjr
@christopherthompson81
christopherthompson81 merged commit f9a2365 into main Aug 8, 2026
@christopherthompson81
christopherthompson81 deleted the afrikaans-final-c branch August 8, 2026 15:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

afrikaans: word-final ⟨c⟩ is [s] because includes("") is true — should be [k]

1 participant