bytesense 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
bytesense/constant.py ADDED
@@ -0,0 +1,1313 @@
1
+ """
2
+ All constants, encoding metadata, language frequency tables, and
3
+ pre-computed similarity mappings used by bytesense.
4
+ """
5
+ from __future__ import annotations
6
+
7
+ # ---------------------------------------------------------------------------
8
+ # BOM / SIG markers — longest first so prefix matching is unambiguous
9
+ # ---------------------------------------------------------------------------
10
+ BOM_MARKERS: dict[str, bytes] = {
11
+ "utf_32_be": b"\x00\x00\xfe\xff",
12
+ "utf_32_le": b"\xff\xfe\x00\x00",
13
+ "utf_8_sig": b"\xef\xbb\xbf",
14
+ "utf_16_be": b"\xfe\xff",
15
+ "utf_16_le": b"\xff\xfe",
16
+ "gb18030": b"\x84\x31\x95\x33",
17
+ "utf_7": b"\x2b\x2f\x76",
18
+ }
19
+
20
+ # ---------------------------------------------------------------------------
21
+ # Encoding families — used for candidate ordering and similarity skipping
22
+ # ---------------------------------------------------------------------------
23
+ ENCODING_FAMILIES: dict[str, list[str]] = {
24
+ "utf": [
25
+ "utf_8",
26
+ "utf_8_sig",
27
+ "utf_16",
28
+ "utf_16_be",
29
+ "utf_16_le",
30
+ "utf_32",
31
+ "utf_32_be",
32
+ "utf_32_le",
33
+ "utf_7",
34
+ ],
35
+ "windows": [
36
+ "cp1250",
37
+ "cp1251",
38
+ "cp1252",
39
+ "cp1253",
40
+ "cp1254",
41
+ "cp1255",
42
+ "cp1256",
43
+ "cp1257",
44
+ "cp1258",
45
+ ],
46
+ "latin": [
47
+ "latin_1",
48
+ "iso8859_2",
49
+ "iso8859_3",
50
+ "iso8859_4",
51
+ "iso8859_5",
52
+ "iso8859_6",
53
+ "iso8859_7",
54
+ "iso8859_8",
55
+ "iso8859_9",
56
+ "iso8859_10",
57
+ "iso8859_11",
58
+ "iso8859_13",
59
+ "iso8859_14",
60
+ "iso8859_15",
61
+ "iso8859_16",
62
+ ],
63
+ "cjk": [
64
+ "gb2312",
65
+ "gb18030",
66
+ "gbk",
67
+ "big5",
68
+ "big5hkscs",
69
+ "hz",
70
+ "euc_jp",
71
+ "euc_jis_2004",
72
+ "euc_jisx0213",
73
+ "shift_jis",
74
+ "shift_jis_2004",
75
+ "shift_jisx0213",
76
+ "iso2022_jp",
77
+ "iso2022_jp_1",
78
+ "iso2022_jp_2",
79
+ "iso2022_jp_3",
80
+ "iso2022_jp_ext",
81
+ "iso2022_jp_2004",
82
+ "cp932",
83
+ "euc_kr",
84
+ "iso2022_kr",
85
+ "johab",
86
+ "cp949",
87
+ ],
88
+ "cyrillic": [
89
+ "cp1251",
90
+ "koi8_r",
91
+ "koi8_u",
92
+ "koi8_t",
93
+ "mac_cyrillic",
94
+ "cp855",
95
+ "cp866",
96
+ "iso8859_5",
97
+ "ptcp154",
98
+ "kz1048",
99
+ ],
100
+ "ibm": [
101
+ "cp037",
102
+ "cp273",
103
+ "cp424",
104
+ "cp437",
105
+ "cp500",
106
+ "cp775",
107
+ "cp850",
108
+ "cp852",
109
+ "cp855",
110
+ "cp857",
111
+ "cp858",
112
+ "cp860",
113
+ "cp861",
114
+ "cp862",
115
+ "cp863",
116
+ "cp864",
117
+ "cp865",
118
+ "cp866",
119
+ "cp869",
120
+ "cp1026",
121
+ "cp1125",
122
+ "cp1140",
123
+ ],
124
+ "mac": [
125
+ "mac_roman",
126
+ "mac_greek",
127
+ "mac_iceland",
128
+ "mac_latin2",
129
+ "mac_turkish",
130
+ "mac_cyrillic",
131
+ ],
132
+ "misc": [
133
+ "ascii",
134
+ "hp_roman8",
135
+ "tis_620",
136
+ "ptcp154",
137
+ "kz1048",
138
+ ],
139
+ }
140
+
141
+ # Multibyte-first flat list — multibyte encodings tried before single-byte
142
+ # because they fail fast on non-matching data (UnicodeDecodeError)
143
+ ALL_ENCODINGS: list[str] = (
144
+ ENCODING_FAMILIES["utf"]
145
+ + ENCODING_FAMILIES["cjk"]
146
+ + ENCODING_FAMILIES["cyrillic"]
147
+ + ENCODING_FAMILIES["windows"]
148
+ + ENCODING_FAMILIES["latin"]
149
+ + ENCODING_FAMILIES["ibm"]
150
+ + ENCODING_FAMILIES["mac"]
151
+ + ENCODING_FAMILIES["misc"]
152
+ )
153
+
154
+ # Encodings that are so similar their byte distributions overlap heavily.
155
+ # If one fails chaos probing, skip the rest of its group.
156
+ SIMILAR_ENCODINGS: dict[str, list[str]] = {
157
+ "cp1252": ["latin_1", "iso8859_15", "iso8859_9", "iso8859_3", "iso8859_14", "cp1254"],
158
+ "cp1251": ["kz1048", "ptcp154", "iso8859_5"],
159
+ "cp1250": ["iso8859_2"],
160
+ "cp1253": ["iso8859_7"],
161
+ "cp1257": ["iso8859_13"],
162
+ "latin_1": ["cp1252", "iso8859_9", "iso8859_15", "cp1254"],
163
+ "cp437": ["cp850", "cp858", "cp860", "cp861", "cp862", "cp863", "cp865"],
164
+ "cp850": ["cp437", "cp857", "cp858", "cp865"],
165
+ "euc_jp": ["iso2022_jp", "iso2022_jp_2", "euc_jis_2004"],
166
+ "shift_jis": ["cp932", "shift_jis_2004", "shift_jisx0213"],
167
+ "euc_kr": ["iso2022_kr", "johab", "cp949"],
168
+ # gb2312 strict decode can fail while gbk/gb18030 still succeed — do not skip those.
169
+ "gb2312": ["hz"],
170
+ "big5": ["big5hkscs", "cp950"],
171
+ "iso8859_11": ["tis_620"],
172
+ "mac_roman": ["mac_iceland", "mac_turkish"],
173
+ "cp037": ["cp1026", "cp1140", "cp273", "cp500"],
174
+ }
175
+
176
+ # ---------------------------------------------------------------------------
177
+ # Thresholds
178
+ # ---------------------------------------------------------------------------
179
+ TOO_SMALL: int = 16 # Below this, results are unreliable
180
+ TOO_LARGE: int = 10_000_000 # 10 MB — use sampling above this
181
+ OPTIMAL_SAMPLE: int = 8_192 # Bytes to sample for large files
182
+
183
+ # ---------------------------------------------------------------------------
184
+ # Language character frequency tables
185
+ # Most-common → least-common for each language.
186
+ # Used by the coherence detector.
187
+ # ---------------------------------------------------------------------------
188
+ CHAR_FREQUENCIES: dict[str, list[str]] = {
189
+ "English": list("eatoinshrdlcumwfgypbvkjxqz"),
190
+ "German": list("enirsatdhulgocmbfkwzpvüäöj"),
191
+ "French": list("easnitrluodcpmévgfbhqàxèyj"),
192
+ "Dutch": list("enairtodsglhvmukpcbwjzfyxë"),
193
+ "Italian": list("eiaonltrscdupgmvfbzhqèàkyò"),
194
+ "Polish": [
195
+ "a",
196
+ "i",
197
+ "o",
198
+ "e",
199
+ "n",
200
+ "r",
201
+ "z",
202
+ "w",
203
+ "s",
204
+ "c",
205
+ "t",
206
+ "k",
207
+ "y",
208
+ "d",
209
+ "p",
210
+ "m",
211
+ "u",
212
+ "l",
213
+ "j",
214
+ "ł",
215
+ "g",
216
+ "b",
217
+ "h",
218
+ "ą",
219
+ "ę",
220
+ "ó",
221
+ ],
222
+ "Spanish": list("eaosnrilctdumpbgvfyóhqíjzá"),
223
+ "Portuguese": [
224
+ "a",
225
+ "e",
226
+ "o",
227
+ "s",
228
+ "i",
229
+ "r",
230
+ "d",
231
+ "n",
232
+ "t",
233
+ "m",
234
+ "u",
235
+ "c",
236
+ "l",
237
+ "p",
238
+ "g",
239
+ "v",
240
+ "b",
241
+ "f",
242
+ "h",
243
+ "ã",
244
+ "q",
245
+ "é",
246
+ "ç",
247
+ "á",
248
+ "z",
249
+ "í",
250
+ ],
251
+ "Swedish": [
252
+ "e",
253
+ "a",
254
+ "n",
255
+ "r",
256
+ "t",
257
+ "s",
258
+ "i",
259
+ "l",
260
+ "d",
261
+ "o",
262
+ "m",
263
+ "k",
264
+ "g",
265
+ "v",
266
+ "h",
267
+ "f",
268
+ "u",
269
+ "p",
270
+ "ä",
271
+ "c",
272
+ "b",
273
+ "ö",
274
+ "å",
275
+ "y",
276
+ "j",
277
+ "x",
278
+ ],
279
+ "Norwegian": [
280
+ "e",
281
+ "r",
282
+ "n",
283
+ "t",
284
+ "a",
285
+ "s",
286
+ "i",
287
+ "o",
288
+ "l",
289
+ "d",
290
+ "g",
291
+ "k",
292
+ "m",
293
+ "v",
294
+ "f",
295
+ "p",
296
+ "u",
297
+ "b",
298
+ "h",
299
+ "å",
300
+ "y",
301
+ "j",
302
+ "ø",
303
+ "c",
304
+ "æ",
305
+ "w",
306
+ ],
307
+ "Danish": [
308
+ "e",
309
+ "r",
310
+ "n",
311
+ "t",
312
+ "a",
313
+ "i",
314
+ "s",
315
+ "d",
316
+ "l",
317
+ "o",
318
+ "g",
319
+ "m",
320
+ "k",
321
+ "f",
322
+ "v",
323
+ "u",
324
+ "b",
325
+ "h",
326
+ "p",
327
+ "å",
328
+ "y",
329
+ "ø",
330
+ "æ",
331
+ "c",
332
+ "j",
333
+ "w",
334
+ ],
335
+ "Finnish": [
336
+ "a",
337
+ "i",
338
+ "n",
339
+ "t",
340
+ "e",
341
+ "s",
342
+ "l",
343
+ "o",
344
+ "u",
345
+ "k",
346
+ "ä",
347
+ "m",
348
+ "r",
349
+ "v",
350
+ "j",
351
+ "h",
352
+ "p",
353
+ "y",
354
+ "d",
355
+ "ö",
356
+ "g",
357
+ "c",
358
+ "b",
359
+ "f",
360
+ "w",
361
+ "z",
362
+ ],
363
+ "Hungarian": [
364
+ "e",
365
+ "a",
366
+ "t",
367
+ "l",
368
+ "s",
369
+ "n",
370
+ "k",
371
+ "r",
372
+ "i",
373
+ "o",
374
+ "z",
375
+ "á",
376
+ "é",
377
+ "g",
378
+ "m",
379
+ "b",
380
+ "y",
381
+ "v",
382
+ "d",
383
+ "h",
384
+ "u",
385
+ "p",
386
+ "j",
387
+ "ö",
388
+ "f",
389
+ "c",
390
+ ],
391
+ "Czech": [
392
+ "o",
393
+ "e",
394
+ "a",
395
+ "n",
396
+ "t",
397
+ "s",
398
+ "i",
399
+ "l",
400
+ "v",
401
+ "r",
402
+ "k",
403
+ "d",
404
+ "u",
405
+ "m",
406
+ "p",
407
+ "í",
408
+ "c",
409
+ "h",
410
+ "z",
411
+ "á",
412
+ "y",
413
+ "j",
414
+ "b",
415
+ "ě",
416
+ "é",
417
+ "ř",
418
+ ],
419
+ "Slovak": [
420
+ "o",
421
+ "a",
422
+ "e",
423
+ "n",
424
+ "i",
425
+ "r",
426
+ "v",
427
+ "t",
428
+ "s",
429
+ "l",
430
+ "k",
431
+ "d",
432
+ "m",
433
+ "p",
434
+ "u",
435
+ "c",
436
+ "h",
437
+ "j",
438
+ "b",
439
+ "z",
440
+ "á",
441
+ "y",
442
+ "ý",
443
+ "í",
444
+ "č",
445
+ "é",
446
+ ],
447
+ "Romanian": [
448
+ "e",
449
+ "i",
450
+ "a",
451
+ "r",
452
+ "n",
453
+ "t",
454
+ "u",
455
+ "l",
456
+ "o",
457
+ "c",
458
+ "s",
459
+ "d",
460
+ "p",
461
+ "m",
462
+ "ă",
463
+ "f",
464
+ "v",
465
+ "î",
466
+ "g",
467
+ "b",
468
+ "ș",
469
+ "ț",
470
+ "z",
471
+ "h",
472
+ "â",
473
+ "j",
474
+ ],
475
+ "Croatian": list("aionrjstukl vdmpgzbcčhšžćf"),
476
+ "Slovene": list("eaionrsljtv kdpmuzb gčcšžfy"),
477
+ "Lithuanian": [
478
+ "i",
479
+ "a",
480
+ "s",
481
+ "o",
482
+ "r",
483
+ "e",
484
+ "t",
485
+ "n",
486
+ "u",
487
+ "k",
488
+ "m",
489
+ "l",
490
+ "p",
491
+ "v",
492
+ "d",
493
+ "j",
494
+ "g",
495
+ "ė",
496
+ "b",
497
+ "y",
498
+ "ų",
499
+ "š",
500
+ "ž",
501
+ "c",
502
+ "ą",
503
+ "į",
504
+ ],
505
+ "Estonian": [
506
+ "a",
507
+ "i",
508
+ "e",
509
+ "s",
510
+ "t",
511
+ "l",
512
+ "u",
513
+ "n",
514
+ "o",
515
+ "k",
516
+ "r",
517
+ "d",
518
+ "m",
519
+ "v",
520
+ "g",
521
+ "p",
522
+ "j",
523
+ "h",
524
+ "ä",
525
+ "b",
526
+ "õ",
527
+ "ü",
528
+ "f",
529
+ "c",
530
+ "ö",
531
+ "y",
532
+ ],
533
+ "Serbian": [
534
+ "а",
535
+ "и",
536
+ "о",
537
+ "е",
538
+ "н",
539
+ "р",
540
+ "с",
541
+ "у",
542
+ "т",
543
+ "к",
544
+ "ј",
545
+ "в",
546
+ "д",
547
+ "м",
548
+ "п",
549
+ "л",
550
+ "г",
551
+ "з",
552
+ "б",
553
+ "a",
554
+ "i",
555
+ "e",
556
+ "o",
557
+ "n",
558
+ "ц",
559
+ "ш",
560
+ ],
561
+ "Bulgarian": [
562
+ "а",
563
+ "и",
564
+ "о",
565
+ "е",
566
+ "н",
567
+ "т",
568
+ "р",
569
+ "с",
570
+ "в",
571
+ "л",
572
+ "к",
573
+ "д",
574
+ "п",
575
+ "м",
576
+ "з",
577
+ "г",
578
+ "я",
579
+ "ъ",
580
+ "у",
581
+ "б",
582
+ "ч",
583
+ "ц",
584
+ "й",
585
+ "ж",
586
+ "щ",
587
+ "х",
588
+ ],
589
+ "Russian": [
590
+ "о",
591
+ "е",
592
+ "а",
593
+ "и",
594
+ "н",
595
+ "т",
596
+ "с",
597
+ "р",
598
+ "в",
599
+ "л",
600
+ "к",
601
+ "м",
602
+ "д",
603
+ "п",
604
+ "у",
605
+ "г",
606
+ "я",
607
+ "ы",
608
+ "з",
609
+ "б",
610
+ "й",
611
+ "ь",
612
+ "ч",
613
+ "х",
614
+ "ж",
615
+ "ц",
616
+ ],
617
+ "Ukrainian": [
618
+ "о",
619
+ "а",
620
+ "н",
621
+ "і",
622
+ "и",
623
+ "р",
624
+ "в",
625
+ "т",
626
+ "е",
627
+ "с",
628
+ "к",
629
+ "л",
630
+ "у",
631
+ "д",
632
+ "м",
633
+ "п",
634
+ "з",
635
+ "я",
636
+ "ь",
637
+ "б",
638
+ "г",
639
+ "й",
640
+ "ч",
641
+ "х",
642
+ "ц",
643
+ "ї",
644
+ ],
645
+ "Kazakh": [
646
+ "а",
647
+ "ы",
648
+ "е",
649
+ "н",
650
+ "т",
651
+ "р",
652
+ "л",
653
+ "і",
654
+ "д",
655
+ "с",
656
+ "м",
657
+ "қ",
658
+ "к",
659
+ "о",
660
+ "б",
661
+ "и",
662
+ "у",
663
+ "ғ",
664
+ "ж",
665
+ "ң",
666
+ "з",
667
+ "ш",
668
+ "й",
669
+ "п",
670
+ "г",
671
+ "ө",
672
+ ],
673
+ "Greek": [
674
+ "α",
675
+ "τ",
676
+ "ο",
677
+ "ι",
678
+ "ε",
679
+ "ν",
680
+ "ρ",
681
+ "σ",
682
+ "κ",
683
+ "η",
684
+ "π",
685
+ "ς",
686
+ "υ",
687
+ "μ",
688
+ "λ",
689
+ "ί",
690
+ "ό",
691
+ "ά",
692
+ "γ",
693
+ "έ",
694
+ "δ",
695
+ "ή",
696
+ "ω",
697
+ "χ",
698
+ "θ",
699
+ "ύ",
700
+ ],
701
+ "Turkish": [
702
+ "a",
703
+ "e",
704
+ "i",
705
+ "n",
706
+ "r",
707
+ "l",
708
+ "ı",
709
+ "k",
710
+ "d",
711
+ "t",
712
+ "s",
713
+ "m",
714
+ "y",
715
+ "u",
716
+ "o",
717
+ "b",
718
+ "ü",
719
+ "ş",
720
+ "v",
721
+ "g",
722
+ "z",
723
+ "h",
724
+ "c",
725
+ "p",
726
+ "ç",
727
+ "ğ",
728
+ ],
729
+ "Hebrew": [
730
+ "י",
731
+ "ו",
732
+ "ה",
733
+ "ל",
734
+ "ר",
735
+ "ב",
736
+ "ת",
737
+ "מ",
738
+ "א",
739
+ "ש",
740
+ "נ",
741
+ "ע",
742
+ "ם",
743
+ "ד",
744
+ "ק",
745
+ "ח",
746
+ "פ",
747
+ "ס",
748
+ "כ",
749
+ "ג",
750
+ "ט",
751
+ "צ",
752
+ "ן",
753
+ "ז",
754
+ "ך",
755
+ ],
756
+ "Arabic": [
757
+ "ا",
758
+ "ل",
759
+ "ي",
760
+ "م",
761
+ "و",
762
+ "ن",
763
+ "ر",
764
+ "ت",
765
+ "ب",
766
+ "ة",
767
+ "ع",
768
+ "د",
769
+ "س",
770
+ "ف",
771
+ "ه",
772
+ "ك",
773
+ "ق",
774
+ "أ",
775
+ "ح",
776
+ "ج",
777
+ "ش",
778
+ "ط",
779
+ "ص",
780
+ "ى",
781
+ "خ",
782
+ "إ",
783
+ ],
784
+ "Farsi": [
785
+ "ا",
786
+ "ی",
787
+ "ر",
788
+ "د",
789
+ "ن",
790
+ "ه",
791
+ "و",
792
+ "م",
793
+ "ت",
794
+ "ب",
795
+ "س",
796
+ "ل",
797
+ "ک",
798
+ "ش",
799
+ "ز",
800
+ "ف",
801
+ "گ",
802
+ "ع",
803
+ "خ",
804
+ "ق",
805
+ "ج",
806
+ "آ",
807
+ "پ",
808
+ "ح",
809
+ "ط",
810
+ "ص",
811
+ ],
812
+ "Hindi": [
813
+ "क",
814
+ "र",
815
+ "स",
816
+ "न",
817
+ "त",
818
+ "म",
819
+ "ह",
820
+ "प",
821
+ "य",
822
+ "ल",
823
+ "व",
824
+ "ज",
825
+ "द",
826
+ "ग",
827
+ "ब",
828
+ "श",
829
+ "ट",
830
+ "अ",
831
+ "ए",
832
+ "थ",
833
+ "भ",
834
+ "ड",
835
+ "च",
836
+ "ध",
837
+ "ष",
838
+ "इ",
839
+ ],
840
+ "Thai": [
841
+ "า",
842
+ "น",
843
+ "ร",
844
+ "อ",
845
+ "ก",
846
+ "เ",
847
+ "ง",
848
+ "ม",
849
+ "ย",
850
+ "ล",
851
+ "ว",
852
+ "ด",
853
+ "ท",
854
+ "ส",
855
+ "ต",
856
+ "ะ",
857
+ "ป",
858
+ "บ",
859
+ "ค",
860
+ "ห",
861
+ "แ",
862
+ "จ",
863
+ "พ",
864
+ "ช",
865
+ "ข",
866
+ "ใ",
867
+ ],
868
+ "Vietnamese": [
869
+ "n",
870
+ "h",
871
+ "t",
872
+ "i",
873
+ "c",
874
+ "g",
875
+ "a",
876
+ "o",
877
+ "u",
878
+ "m",
879
+ "l",
880
+ "r",
881
+ "à",
882
+ "đ",
883
+ "s",
884
+ "e",
885
+ "v",
886
+ "p",
887
+ "b",
888
+ "y",
889
+ "ư",
890
+ "d",
891
+ "á",
892
+ "k",
893
+ "ộ",
894
+ "ế",
895
+ ],
896
+ "Indonesian": list("aneirtusdk mlgpbohyjcwfvzxq"),
897
+ "Malay": list("aneirtusdk mlgpbohyjcwfvzxq"),
898
+ "Chinese": [
899
+ "的",
900
+ "一",
901
+ "是",
902
+ "不",
903
+ "了",
904
+ "在",
905
+ "人",
906
+ "有",
907
+ "我",
908
+ "他",
909
+ "这",
910
+ "个",
911
+ "们",
912
+ "中",
913
+ "来",
914
+ "上",
915
+ "大",
916
+ "为",
917
+ "和",
918
+ "国",
919
+ "地",
920
+ "到",
921
+ "以",
922
+ "说",
923
+ "时",
924
+ "要",
925
+ "就",
926
+ "出",
927
+ "会",
928
+ "可",
929
+ "也",
930
+ "你",
931
+ "对",
932
+ "生",
933
+ "能",
934
+ "而",
935
+ "子",
936
+ "那",
937
+ "得",
938
+ "于",
939
+ ],
940
+ "Japanese": [
941
+ "日",
942
+ "一",
943
+ "人",
944
+ "年",
945
+ "大",
946
+ "十",
947
+ "二",
948
+ "本",
949
+ "中",
950
+ "長",
951
+ "出",
952
+ "三",
953
+ "時",
954
+ "行",
955
+ "見",
956
+ "月",
957
+ "分",
958
+ "後",
959
+ "前",
960
+ "生",
961
+ "五",
962
+ "間",
963
+ "上",
964
+ "東",
965
+ "四",
966
+ "今",
967
+ "金",
968
+ "九",
969
+ "入",
970
+ "学",
971
+ ],
972
+ "Korean": [
973
+ "이",
974
+ "다",
975
+ "에",
976
+ "의",
977
+ "는",
978
+ "로",
979
+ "하",
980
+ "을",
981
+ "가",
982
+ "고",
983
+ "지",
984
+ "서",
985
+ "한",
986
+ "은",
987
+ "기",
988
+ "으",
989
+ "년",
990
+ "대",
991
+ "사",
992
+ "시",
993
+ "를",
994
+ "리",
995
+ "도",
996
+ "인",
997
+ "스",
998
+ "일",
999
+ ],
1000
+ "Tamil": [
1001
+ "க",
1002
+ "த",
1003
+ "ப",
1004
+ "ட",
1005
+ "ர",
1006
+ "ம",
1007
+ "ல",
1008
+ "ன",
1009
+ "வ",
1010
+ "ற",
1011
+ "ய",
1012
+ "ள",
1013
+ "ச",
1014
+ "ந",
1015
+ "இ",
1016
+ "ண",
1017
+ "அ",
1018
+ "ஆ",
1019
+ "ழ",
1020
+ "ங",
1021
+ ],
1022
+ }
1023
+
1024
+ # Top bigrams per language — used for mess detection validation
1025
+ BIGRAM_FREQUENCIES: dict[str, list[str]] = {
1026
+ "English": [
1027
+ "th",
1028
+ "he",
1029
+ "in",
1030
+ "er",
1031
+ "an",
1032
+ "re",
1033
+ "on",
1034
+ "en",
1035
+ "at",
1036
+ "es",
1037
+ "ed",
1038
+ "te",
1039
+ "ti",
1040
+ "ou",
1041
+ "to",
1042
+ "it",
1043
+ "is",
1044
+ "hi",
1045
+ "ar",
1046
+ "nt",
1047
+ "st",
1048
+ "or",
1049
+ "nd",
1050
+ "ng",
1051
+ "ha",
1052
+ ],
1053
+ "German": [
1054
+ "en",
1055
+ "er",
1056
+ "ch",
1057
+ "de",
1058
+ "ei",
1059
+ "te",
1060
+ "in",
1061
+ "ie",
1062
+ "ge",
1063
+ "ne",
1064
+ "an",
1065
+ "st",
1066
+ "be",
1067
+ "un",
1068
+ "nd",
1069
+ "ng",
1070
+ "he",
1071
+ "es",
1072
+ "re",
1073
+ "le",
1074
+ "ck",
1075
+ "ht",
1076
+ "ss",
1077
+ "sch",
1078
+ "au",
1079
+ ],
1080
+ "French": [
1081
+ "es",
1082
+ "en",
1083
+ "le",
1084
+ "de",
1085
+ "on",
1086
+ "re",
1087
+ "nt",
1088
+ "er",
1089
+ "ou",
1090
+ "an",
1091
+ "te",
1092
+ "it",
1093
+ "la",
1094
+ "at",
1095
+ "ai",
1096
+ "se",
1097
+ "el",
1098
+ "qu",
1099
+ "ti",
1100
+ "si",
1101
+ "me",
1102
+ "et",
1103
+ "ion",
1104
+ "que",
1105
+ "ait",
1106
+ ],
1107
+ "Spanish": [
1108
+ "es",
1109
+ "en",
1110
+ "de",
1111
+ "el",
1112
+ "la",
1113
+ "re",
1114
+ "ar",
1115
+ "er",
1116
+ "on",
1117
+ "te",
1118
+ "an",
1119
+ "al",
1120
+ "os",
1121
+ "as",
1122
+ "ci",
1123
+ "se",
1124
+ "un",
1125
+ "io",
1126
+ "co",
1127
+ "or",
1128
+ "que",
1129
+ "por",
1130
+ "con",
1131
+ "para",
1132
+ "los",
1133
+ ],
1134
+ "Russian": [
1135
+ "то",
1136
+ "не",
1137
+ "на",
1138
+ "ен",
1139
+ "ст",
1140
+ "ко",
1141
+ "по",
1142
+ "ро",
1143
+ "ли",
1144
+ "во",
1145
+ "ни",
1146
+ "ра",
1147
+ "ит",
1148
+ "ть",
1149
+ "ло",
1150
+ "та",
1151
+ "ов",
1152
+ "ос",
1153
+ "ат",
1154
+ "ве",
1155
+ "ет",
1156
+ "го",
1157
+ "те",
1158
+ "ны",
1159
+ "ых",
1160
+ ],
1161
+ "Turkish": [
1162
+ "ar",
1163
+ "er",
1164
+ "an",
1165
+ "in",
1166
+ "ir",
1167
+ "en",
1168
+ "le",
1169
+ "la",
1170
+ "al",
1171
+ "il",
1172
+ "de",
1173
+ "da",
1174
+ "un",
1175
+ "ur",
1176
+ "ak",
1177
+ "ek",
1178
+ "ik",
1179
+ "at",
1180
+ "et",
1181
+ "it",
1182
+ "lar",
1183
+ "ler",
1184
+ "nin",
1185
+ "nın",
1186
+ "dan",
1187
+ ],
1188
+ "Portuguese": [
1189
+ "as",
1190
+ "es",
1191
+ "de",
1192
+ "en",
1193
+ "os",
1194
+ "re",
1195
+ "ar",
1196
+ "er",
1197
+ "on",
1198
+ "te",
1199
+ "an",
1200
+ "al",
1201
+ "ção",
1202
+ "que",
1203
+ "os",
1204
+ "ão",
1205
+ "do",
1206
+ "da",
1207
+ "para",
1208
+ "com",
1209
+ ],
1210
+ "Italian": [
1211
+ "re",
1212
+ "er",
1213
+ "in",
1214
+ "al",
1215
+ "io",
1216
+ "li",
1217
+ "on",
1218
+ "no",
1219
+ "si",
1220
+ "ti",
1221
+ "ar",
1222
+ "to",
1223
+ "la",
1224
+ "di",
1225
+ "il",
1226
+ "un",
1227
+ "mi",
1228
+ "he",
1229
+ "ho",
1230
+ "ma",
1231
+ "ed",
1232
+ "le",
1233
+ "ta",
1234
+ "so",
1235
+ "co",
1236
+ ],
1237
+ "Polish": [
1238
+ "ie",
1239
+ "ni",
1240
+ "pr",
1241
+ "st",
1242
+ "po",
1243
+ "cz",
1244
+ "na",
1245
+ "rz",
1246
+ "się",
1247
+ "do",
1248
+ "że",
1249
+ "to",
1250
+ "jest",
1251
+ "nie",
1252
+ "co",
1253
+ "jak",
1254
+ "już",
1255
+ "ale",
1256
+ "go",
1257
+ "ze",
1258
+ ],
1259
+ }
1260
+
1261
+ # Language → typical encoding(s). Used to boost candidate scoring.
1262
+ LANGUAGE_ENCODINGS: dict[str, list[str]] = {
1263
+ # Germanic / Western European
1264
+ "English": ["ascii", "utf_8", "latin_1", "cp1252"],
1265
+ "German": ["utf_8", "cp1252", "latin_1", "iso8859_15"],
1266
+ "French": ["utf_8", "cp1252", "latin_1", "iso8859_15"],
1267
+ "Dutch": ["utf_8", "cp1252", "latin_1", "iso8859_15"],
1268
+ "Swedish": ["utf_8", "cp1252", "iso8859_15", "latin_1"],
1269
+ "Norwegian": ["utf_8", "cp1252", "iso8859_15", "latin_1"],
1270
+ "Danish": ["utf_8", "cp1252", "iso8859_15", "latin_1"],
1271
+ "Finnish": ["utf_8", "cp1252", "iso8859_15", "latin_1"],
1272
+ # Romance
1273
+ "Spanish": ["utf_8", "cp1252", "latin_1", "iso8859_15"],
1274
+ "Italian": ["utf_8", "cp1252", "latin_1", "iso8859_15"],
1275
+ "Portuguese": ["utf_8", "cp1252", "latin_1", "iso8859_15"],
1276
+ "Romanian": ["utf_8", "cp1250", "iso8859_2"],
1277
+ # Slavic Latin
1278
+ "Polish": ["utf_8", "cp1250", "iso8859_2"],
1279
+ "Czech": ["utf_8", "cp1250", "iso8859_2"],
1280
+ "Slovak": ["utf_8", "cp1250", "iso8859_2"],
1281
+ "Croatian": ["utf_8", "cp1250", "iso8859_2"],
1282
+ "Slovene": ["utf_8", "cp1250", "iso8859_2"],
1283
+ # Baltic
1284
+ "Lithuanian": ["utf_8", "cp1257", "iso8859_13"],
1285
+ "Estonian": ["utf_8", "cp1257", "iso8859_13"],
1286
+ # Cyrillic
1287
+ "Russian": ["utf_8", "cp1251", "koi8_r", "cp866", "mac_cyrillic", "iso8859_5"],
1288
+ "Ukrainian": ["utf_8", "cp1251", "koi8_u", "iso8859_5"],
1289
+ "Bulgarian": ["utf_8", "cp1251", "iso8859_5"],
1290
+ "Serbian": ["utf_8", "cp1251"],
1291
+ "Kazakh": ["utf_8", "cp1251", "ptcp154", "kz1048"],
1292
+ # Greek
1293
+ "Greek": ["utf_8", "cp1253", "iso8859_7"],
1294
+ # Turkish / Central Asian
1295
+ "Turkish": ["utf_8", "cp1254", "iso8859_9"],
1296
+ "Hungarian": ["utf_8", "cp1250", "iso8859_2"],
1297
+ # Semitic
1298
+ "Hebrew": ["utf_8", "cp1255", "iso8859_8"],
1299
+ "Arabic": ["utf_8", "cp1256", "iso8859_6"],
1300
+ "Farsi": ["utf_8", "cp1256", "iso8859_6"],
1301
+ # South/Southeast Asian
1302
+ "Hindi": ["utf_8"],
1303
+ "Tamil": ["utf_8"],
1304
+ "Thai": ["utf_8", "tis_620", "iso8859_11"],
1305
+ "Vietnamese": ["utf_8", "cp1258"],
1306
+ # East Asian
1307
+ "Chinese": ["utf_8", "gb18030", "gbk", "gb2312", "big5"],
1308
+ "Japanese": ["utf_8", "shift_jis", "euc_jp", "cp932", "iso2022_jp"],
1309
+ "Korean": ["utf_8", "euc_kr", "cp949", "johab"],
1310
+ # Austronesian
1311
+ "Indonesian": ["utf_8", "ascii", "latin_1", "cp1252"],
1312
+ "Malay": ["utf_8", "ascii", "latin_1", "cp1252"],
1313
+ }