Skip to content

Detect and fix KOI8-R mojibake (fixes #231) - #234

Open
sebollin wants to merge 1 commit into
rspeer:mainfrom
sebollin:koi8r-231
Open

Detect and fix KOI8-R mojibake (fixes #231)#234
sebollin wants to merge 1 commit into
rspeer:mainfrom
sebollin:koi8r-231

Conversation

@sebollin

Copy link
Copy Markdown

Fixes#231.

The example in the issue is reported as CP437/CP866, but I'm fairly sure it's KOI8-R. In KOI8-R, 0xD0 is п and 0xD1 is я — the two lead bytes of Cyrillic in UTF-8 — and 0x95 and 0x81 are and . That's why the mojibake comes out as Cyrillic letters interleaved with box-drawing characters.

>>>"п∙я│п╩п╦ п▓я▀ п╫п╣".encode("koi8-r").decode("utf-8")
'Если Вы не'

I tried the codepages the reporter suggested and the neighbouring Cyrillic ones too: cp866, koi8-u, iso-8859-5 and mac-cyrillic all fail to encode the text, so KOI8-R is the only one that round-trips it.

Two changes are needed, and neither one is enough on its own:

  • koi8-r in CHARMAP_ENCODINGS, so the text can be re-encoded at all.
  • lower_common and upper_common in the badness alternative that pairs a character with a box-drawing character. KOI8-R mojibake of Cyrillic puts a Cyrillic letter immediately before a box-drawing character, and no existing alternative covers that pair, so is_bad() never fires.

If you apply only the first one, the example still comes back unchanged. That took me a while to work out, so I mention it in case someone tries the shorter patch.

I added the example to in-the-wild.json. The suite goes from 351 to 353 passing with the same 10 xfails, and the negative cases are untouched.

The example in rspeer#231 is reported as CP437/CP866, but it is KOI8-R: in that
encoding 0xD0 is 'п' and 0xD1 is 'я', the two lead bytes of Cyrillic in
UTF-8, and 0x95/0x81 are '∙'/'│'. No other Cyrillic codepage round-trips
it -- cp866, koi8-u, iso-8859-5 and mac-cyrillic all fail to encode it.
Two changes are needed, and neither one alone is enough:
- add koi8-r to CHARMAP_ENCODINGS, so the text can be re-encoded;
- add lower_common/upper_common to the rule that pairs a character with a
box-drawing character, so that is_bad() fires. KOI8-R mojibake of
Cyrillic puts a Cyrillic letter immediately before a box-drawing
character, and no existing alternative covers that pair.
Adding koi8-r on its own leaves the example unchanged, because the badness
heuristic never flags it.
@sebollinsebollin mentioned this pull request Aug 8, 2026
Sign up for freeto 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.

Code Page 437 Cyrillic

1 participant

@sebollin