CP4.2: review — ProofLang::tag() names each pack language (its locale) for keys, settings and reported values; code() stays 'static and empty for packs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8LsYYE8fsj4byBm2
This commit is contained in:
Martin BallandClaude Opus 5.5 committed 2026-11-01 22:34:33 +00:00
1 parent 664af9bc6f
commit 409c8facfd
2 files changed
+28 -2

No files matched your search

+1 -1
View File
@@ -93,7 +93,7 @@ through the shared affix engine with default tuning, and hyphenated from its pac
dictionary or pack it behaves exactly as `Other` did (no marks, English hyphenation fallback).
`has_dictionary(tag)` / `ProofLang::is_proofed()` say whether a `Pack` language has a dictionary
now (read on first use, cached). Loaded `Pack` dictionaries share a 256 MB budget (estimated from their files); the least recently used goes first, but never one used in the paragraph being checked, and languages with no dictionary take no room. Downstream `match`es on `ProofLang` need a `Pack(_)` arm; `code()` stays `&'static str`
and is `""` for it, as for `Other`: use `pack_locale()` for its locale.
and is `""` for it, as for `Other`: anything that keys, saves or reports a language (settings, caches, JSON/MCP output) uses `tag()`, which is `code()` for the built-ins and the locale (`nl`, `fr-fr`) for a pack language.
**Which pack serves a language:** its locale, then shorter prefixes (`fr-ca` → `fr`), then another
region's pack of the same language (`nl` → `nl-be`), never another script's (`sr-latn` never reads
+27 -1
View File
@@ -176,7 +176,8 @@ impl ProofLang {
/// The primary language subtag (`en`, `pl`, `bg`, `tr`, `ru`, `cs`, `id`, `de`, `es`); empty for
/// [`ProofLang::Other`] and for a [`ProofLang::Pack`] language, whose locale isn't `'static`:
/// use [`ProofLang::pack_locale`] (`PackLocale::as_str`) for it. Kept `'static` so existing
/// use [`ProofLang::tag`] wherever the code names the language (keys, settings, saved or
/// reported values), or every pack language would read the same. Kept `'static` so existing
/// callers (`PROOFED.map(ProofLang::code)`) don't break.
pub fn code(self) -> &'static str {
match self {
@@ -210,6 +211,18 @@ impl ProofLang {
}
}
/// The code that names this language, for keys, settings and reported values: [`code`] for
/// the built-in languages (`en`, `es`, …), the locale for a [`ProofLang::Pack`] one (`nl`,
/// `sr-latn`), so no two pack languages share one; empty for [`ProofLang::Other`].
///
/// [`code`]: ProofLang::code
pub fn tag(self) -> std::borrow::Cow<'static, str> {
match self {
ProofLang::Pack(l) => std::borrow::Cow::Owned(l.as_str().to_string()),
other => std::borrow::Cow::Borrowed(other.code()),
}
}
/// The locale of a [`ProofLang::Pack`] language.
pub fn pack_locale(self) -> Option<PackLocale> {
if let ProofLang::Pack(l) = self { Some(l) } else { None }
@@ -478,6 +491,18 @@ mod tests {
assert!(ProofLang::Pl.is_proofed() && !ProofLang::Other.is_proofed());
}
/// Two pack languages never share a key: `tag()` is the locale, while `code()` is empty.
#[test]
fn tag_names_each_pack_language() {
let (nl, fr) = (ProofLang::from_tag(Some("nl")), ProofLang::from_tag(Some("fr-FR")));
assert_eq!((nl.code(), fr.code()), ("", ""));
assert_eq!((nl.tag().as_ref(), fr.tag().as_ref()), ("nl", "fr-fr"));
for l in ProofLang::PROOFED {
assert_eq!(l.tag(), l.code());
}
assert_eq!(ProofLang::Other.tag(), "");
}
#[test]
fn tags_reject_unknown_or_partial_language_codes() {
// A partial code is another language, never the one it starts like.
@@ -485,6 +510,7 @@ mod tests {
let lang = ProofLang::from_tag(Some(tag));
assert_eq!(lang.pack_locale().map(|l| l.to_string()), Some(tag.to_ascii_lowercase()), "{tag}");
assert_eq!(lang.code(), "", "{tag}: a pack language's locale is pack_locale()");
assert_eq!(lang.tag(), lang.pack_locale().map(|l| l.as_str().to_string()).unwrap_or_default(), "{tag}");
}
assert_tags(&["x-none", "e", "-", "und", "zxx", "i-klingon"], ProofLang::Other);
}