M11 Phase 3 — Canon media types displayed Thai characters because CupsParsers.ppdChoiceLabels did last-write-wins and the Canon Pro9500 PPD's th.CNIJMediaType block sits after the unqualified base block.
Changes
CupsParsers.ppdChoiceLabels: collect (id, qualifier, label) then resolve per id with deterministic precedence — unqualified *Key > en_US. > en. > first-qualified-seen (E3). A qualified-only id still gets its first-seen qualified label (R9). looksLikeLocale heuristic unchanged.
New ppdUnescape decodes <XX> hex escapes (<2F>→/, <20>→space) in ids and labels; invalid pairs pass through (E2).
CupsService.loadPPD: UTF-8 first, .isoLatin1 only on decode failure — never Latin-1 first, so the UTF-8 Thai labels are not mojibake'd (E2/R10).
Canon-shaped fixture: unqualified base block early, trailing th. block — the ordering that exposed the bug.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Refs #181
M11 Phase 3 — Canon media types displayed Thai characters because
CupsParsers.ppdChoiceLabelsdid last-write-wins and the Canon Pro9500 PPD'sth.CNIJMediaTypeblock sits after the unqualified base block.Changes
CupsParsers.ppdChoiceLabels: collect(id, qualifier, label)then resolve per id with deterministic precedence — unqualified*Key>en_US.>en.> first-qualified-seen (E3). A qualified-only id still gets its first-seen qualified label (R9).looksLikeLocaleheuristic unchanged.ppdUnescapedecodes<XX>hex escapes (<2F>→/,<20>→space) in ids and labels; invalid pairs pass through (E2).CupsService.loadPPD: UTF-8 first,.isoLatin1only on decode failure — never Latin-1 first, so the UTF-8 Thai labels are not mojibake'd (E2/R10).th.block — the ordering that exposed the bug.Tests (fresh
build/DerivedData-feat-181-canon-media-locale, x86_64)Wider core suite (
-only-testing:ICCeryCoreTests): 475 executed, 0 failures.Errata honored: E1 (no hardcoded count — every enumerated
CNIJMediaTypechoice asserted non-Thai + 18 named spot-checks), E2 (UTF-8-first decode + hex unescape), E3 (deterministic precedence). ExistingtestPpdLabelsgoldens and EpsonEPIJ_Quallabels unaffected. Panel binding/capture-return untouched (#186 scope).