langtell 0.4.0 → 0.6.0
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.
- package/README.md +39 -13
- package/dist/chrome-ai.d.ts +1 -1
- package/dist/{chunk-KCK3XWCJ.js → chunk-7TDGJOIJ.js} +3 -3
- package/dist/{chunk-KCK3XWCJ.js.map → chunk-7TDGJOIJ.js.map} +1 -1
- package/dist/{chunk-U34Z3ZSV.js → chunk-BL627TWI.js} +4 -3
- package/dist/chunk-BL627TWI.js.map +1 -0
- package/dist/{chunk-3LDE35U2.js → chunk-FEKBPTHK.js} +3 -3
- package/dist/{chunk-3LDE35U2.js.map → chunk-FEKBPTHK.js.map} +1 -1
- package/dist/{chunk-G44HHVK5.js → chunk-JXGCCDSV.js} +5 -4
- package/dist/chunk-JXGCCDSV.js.map +1 -0
- package/dist/{chunk-KI4MAI3N.js → chunk-K4MXTIY7.js} +3 -3
- package/dist/{chunk-KI4MAI3N.js.map → chunk-K4MXTIY7.js.map} +1 -1
- package/dist/{chunk-OVSPOZ5J.js → chunk-YCUSX3GG.js} +17 -5
- package/dist/chunk-YCUSX3GG.js.map +1 -0
- package/dist/classify.d.ts +9 -2
- package/dist/classify.js +1 -1
- package/dist/cyrillic.d.ts +60 -0
- package/dist/cyrillic.js +69 -0
- package/dist/cyrillic.js.map +1 -0
- package/dist/franc.d.ts +1 -1
- package/dist/franc.js +1 -1
- package/dist/fuse.d.ts +1 -1
- package/dist/fuse.js +3 -3
- package/dist/headers.d.ts +1 -1
- package/dist/headers.js +2 -2
- package/dist/html.d.ts +1 -1
- package/dist/html.js +2 -2
- package/dist/index.d.ts +58 -7
- package/dist/index.js +47 -13
- package/dist/index.js.map +1 -1
- package/dist/profiles.d.ts +5 -2
- package/dist/profiles.js +431 -2
- package/dist/profiles.js.map +1 -1
- package/dist/text.d.ts +1 -1
- package/dist/text.js +2 -2
- package/dist/{types-BIXrkuAr.d.ts → types-DfHZ5hkh.d.ts} +19 -3
- package/package.json +5 -1
- package/dist/chunk-G44HHVK5.js.map +0 -1
- package/dist/chunk-OVSPOZ5J.js.map +0 -1
- package/dist/chunk-U34Z3ZSV.js.map +0 -1
package/dist/profiles.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/frequent.ts","../src/profiles.ts"],"names":[],"mappings":";AAOO,IAAM,kBAAA,GAAkE;AAAA,EAC7E,EAAA,EAAI;AAAA,IACF,cAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,sCAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,gCAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,sCAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,gCAAA;AAAA,IACA,gCAAA;AAAA,IACA,cAAA;AAAA,IACA,gCAAA;AAAA,IACA,gCAAA;AAAA,IACA,cAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,sCAAA;AAAA,IACA,oBAAA;AAAA,IACA,gCAAA;AAAA,IACA,sCAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,sCAAA;AAAA,IACA,oBAAA;AAAA,IACA,sCAAA;AAAA,IACA,cAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,sCAAA;AAAA,IACA,gCAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,gCAAA;AAAA,IACA,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,gCAAA;AAAA,IACA,sCAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,sCAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,sCAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,4CAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,sCAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,sCAAA;AAAA,IACA,gCAAA;AAAA,IACA,gCAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,oBAAA;AAAA,IACA,gCAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,sCAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,kDAAA;AAAA,IACA,cAAA;AAAA,IACA,gCAAA;AAAA,IACA,gCAAA;AAAA,IACA,gCAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,oBAAA;AAAA,IACA,sCAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,4CAAA;AAAA,IACA,4CAAA;AAAA,IACA,4CAAA;AAAA,IACA,gCAAA;AAAA,IACA,oBAAA;AAAA,IACA,gCAAA;AAAA,IACA,gCAAA;AAAA,IACA,gCAAA;AAAA,IACA,kDAAA;AAAA,IACA,cAAA;AAAA,IACA,gCAAA;AAAA,IACA,4CAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,sCAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,4CAA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AA;AAAA,IACA,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,4CAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,gCAAA;AAAA,IACA,sCAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,sCAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,gCAAA;AAAA,IACA,sCAAA;AAAA,IACA,cAAA;AAAA,IACA,0BAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,gCAAA;AAAA,IACA,sCAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,0BAAA;AAAA,IACA,sCAAA;AAAA,IACA,0BAAA;AAAA,IACA,sCAAA;AAAA,IACA,gCAAA;AAAA,IACA,4CAAA;AAAA,IACA,cAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,4CAAA;AAAA,IACA,sCAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,8DAAA;AAAA,IACA,gCAAA;AAAA,IACA,4CAAA;AAAA,IACA,4CAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,sCAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,sCAAA;AAAA,IACA,4CAAA;AAAA,IACA,sCAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,cAAA;AAAA,IACA,sCAAA;AAAA,IACA,4CAAA;AAAA,IA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","file":"profiles.js","sourcesContent":["// Generated frequency lists — the top everyday words for each language,\n// taken from an open subtitle-frequency corpus (general vocabulary; no\n// project-specific terms). Kept out of the zero-dependency core: this data\n// lives behind the `langtell/profiles` subpath only.\n//\n// Rung 2b of the classifier (internal/classify.ts) reads these. They sharpen\n// distinctive-free disambiguation (e.g. uk \"робота\" vs ru \"работа\").\nexport const FREQUENT_GENERATED: Readonly<Record<string, readonly string[]>> = {\n uk: [\n \"не\",\n \"що\",\n \"на\",\n \"це\",\n \"ти\",\n \"что\",\n \"так\",\n \"ты\",\n \"это\",\n \"ми\",\n \"все\",\n \"тебе\",\n \"він\",\n \"як\",\n \"за\",\n \"ви\",\n \"до\",\n \"мене\",\n \"он\",\n \"мені\",\n \"ні\",\n \"але\",\n \"мы\",\n \"мне\",\n \"да\",\n \"как\",\n \"просто\",\n \"меня\",\n \"нет\",\n \"тут\",\n \"для\",\n \"його\",\n \"вы\",\n \"но\",\n \"то\",\n \"ну\",\n \"знаю\",\n \"про\",\n \"нас\",\n \"вас\",\n \"вони\",\n \"тебя\",\n \"вона\",\n \"она\",\n \"тобі\",\n \"его\",\n \"там\",\n \"якщо\",\n \"ще\",\n \"та\",\n \"добре\",\n \"щоб\",\n \"вам\",\n \"по\",\n \"нам\",\n \"хочу\",\n \"коли\",\n \"если\",\n \"бы\",\n \"же\",\n \"вже\",\n \"було\",\n \"був\",\n \"они\",\n \"може\",\n \"чи\",\n \"чтобы\",\n \"дуже\",\n \"від\",\n \"хорошо\",\n \"чому\",\n \"буде\",\n \"хто\",\n \"есть\",\n \"всё\",\n \"давай\",\n \"тому\",\n \"де\",\n \"здесь\",\n \"треба\",\n \"от\",\n \"думаю\",\n \"когда\",\n \"из\",\n \"того\",\n \"щось\",\n \"гаразд\",\n \"был\",\n \"цього\",\n \"только\",\n \"зараз\",\n \"было\",\n \"может\",\n \"нічого\",\n \"моя\",\n \"тільки\",\n \"те\",\n \"бути\",\n \"один\",\n \"уже\",\n \"можу\",\n \"тепер\",\n \"мій\",\n \"быть\",\n \"ось\",\n \"почему\",\n \"дякую\",\n \"раз\",\n \"вот\",\n \"могу\",\n \"через\",\n \"нужно\",\n \"всі\",\n \"бо\",\n \"кто\",\n \"будет\",\n \"правда\",\n \"без\",\n \"себе\",\n \"більше\",\n \"тоді\",\n \"час\",\n \"день\",\n \"ладно\",\n \"сейчас\",\n \"можна\",\n \"була\",\n \"их\",\n \"боже\",\n \"еще\",\n \"спасибо\",\n \"или\",\n \"будь\",\n \"йому\",\n \"где\",\n \"лише\",\n \"очень\",\n \"была\",\n \"ним\",\n \"привіт\",\n \"них\",\n \"чем\",\n \"навіть\",\n \"ніколи\",\n \"знаешь\",\n \"этого\",\n \"буду\",\n \"би\",\n \"её\",\n \"зі\",\n \"ее\",\n \"мой\",\n \"ничего\",\n \"хочеш\",\n \"нього\",\n \"цей\",\n \"чого\",\n \"життя\",\n \"этом\",\n \"теж\",\n \"люди\",\n \"твоя\",\n \"со\",\n \"потому\",\n \"сказав\",\n \"больше\",\n \"теперь\",\n \"ещё\",\n \"людей\",\n \"або\",\n \"свою\",\n \"привет\",\n \"який\",\n \"сюди\",\n \"таке\",\n \"даже\",\n \"із\",\n \"об\",\n \"тобою\",\n \"були\",\n \"два\",\n \"краще\",\n \"пока\",\n \"ему\",\n \"завжди\",\n \"хочешь\",\n \"должен\",\n \"багато\",\n \"сьогодні\",\n \"ей\",\n \"точно\",\n \"ласка\",\n \"время\",\n \"эй\",\n \"той\",\n \"себя\",\n \"надо\",\n \"сам\",\n \"мною\",\n \"тоже\",\n \"этот\",\n \"прошу\",\n \"маю\",\n \"сказал\",\n \"мама\",\n \"ли\",\n \"зробити\",\n \"сказати\",\n \"сказала\",\n \"назад\",\n \"які\",\n \"можеш\",\n \"тобой\",\n \"трохи\",\n \"потрібно\",\n \"ці\",\n \"тогда\",\n \"порядке\",\n \"ага\",\n \"саме\",\n \"хотів\",\n \"можешь\",\n \"під\",\n \"три\",\n \"никогда\",\n \"можете\",\n \"років\",\n \"собі\",\n \"скажи\",\n \"него\",\n \"пане\",\n \"робити\",\n \"знову\",\n \"твій\",\n \"люблю\",\n \"пожалуйста\",\n \"наш\",\n \"ни\",\n \"сегодня\",\n \"мной\",\n \"потім\",\n \"ніж\",\n \"были\",\n \"гей\",\n \"дай\",\n \"перед\",\n \"завтра\",\n \"вами\",\n \"яка\",\n \"одного\",\n \"ваша\",\n \"конечно\",\n \"сделать\",\n \"лучше\",\n \"цьому\",\n \"ваш\",\n \"цю\",\n \"сказать\",\n \"пам\",\n \"ніхто\",\n \"сюда\",\n \"нами\",\n \"можливо\",\n \"після\",\n \"значит\",\n \"прямо\",\n \"скільки\",\n \"одна\",\n \"чудово\",\n \"давайте\",\n \"бачив\",\n \"такий\",\n \"кого\",\n \"хтось\",\n \"сер\",\n \"ця\",\n \"мою\",\n \"усе\",\n \"разом\",\n \"чего\",\n \"куди\",\n \"звичайно\",\n \"справді\",\n \"поки\",\n \"должны\",\n \"всегда\",\n \"делать\",\n \"дело\",\n \"гроші\",\n \"цим\",\n \"міг\",\n \"том\",\n \"хіба\",\n \"ней\",\n \"твой\",\n \"этим\",\n \"повинен\",\n \"друг\",\n \"можно\",\n \"дня\",\n \"досить\",\n \"можемо\",\n \"зробив\",\n \"много\",\n \"хотел\",\n \"над\",\n \"должна\",\n \"после\",\n \"хоче\",\n \"якби\",\n \"могли\",\n \"місце\",\n \"всего\",\n \"воно\",\n \"часу\",\n \"робиш\",\n \"хлопці\",\n \"вибачте\",\n \"додому\",\n \"весь\",\n \"руки\",\n \"ведь\",\n \"ясно\",\n \"возможно\",\n \"вибач\",\n \"такой\",\n \"доктор\",\n \"повинні\",\n \"эти\",\n \"говорить\",\n \"мого\",\n \"нема\",\n \"нб\",\n \"йди\",\n \"думаешь\",\n \"моей\",\n \"немного\",\n \"навіщо\",\n \"господи\",\n \"мабуть\",\n \"жизнь\",\n \"твою\",\n \"зачем\",\n \"чоловік\",\n \"ходімо\",\n \"лет\",\n \"такое\",\n \"случилось\",\n \"звідси\",\n \"слишком\",\n \"мати\",\n \"скажу\",\n \"скоро\",\n \"сталося\",\n \"прости\",\n \"нормально\",\n \"пані\",\n \"всіх\",\n \"також\",\n \"вместе\",\n \"кілька\",\n \"брат\",\n \"чорт\",\n \"сама\",\n \"во\",\n \"потом\",\n \"такого\",\n \"казав\",\n \"розумію\",\n \"батько\",\n \"отже\",\n \"сделал\",\n \"таким\",\n \"могла\",\n \"тим\",\n \"швидше\",\n \"жаль\",\n \"туди\",\n \"речі\",\n \"знати\",\n \"поэтому\",\n \"мог\",\n \"хочете\",\n \"помочь\",\n \"одну\",\n \"всех\",\n \"который\",\n \"им\",\n \"ім\",\n \"думав\",\n \"можем\",\n \"под\",\n \"допомогти\",\n \"людина\",\n \"куда\",\n \"яку\",\n \"правильно\",\n \"давно\",\n \"зовсім\",\n \"при\",\n ],\n ru: [\n \"не\",\n \"что\",\n \"ты\",\n \"это\",\n \"на\",\n \"он\",\n \"мы\",\n \"как\",\n \"вы\",\n \"да\",\n \"мне\",\n \"нет\",\n \"меня\",\n \"так\",\n \"но\",\n \"его\",\n \"все\",\n \"она\",\n \"тебя\",\n \"если\",\n \"за\",\n \"бы\",\n \"тебе\",\n \"они\",\n \"чтобы\",\n \"же\",\n \"есть\",\n \"просто\",\n \"из\",\n \"для\",\n \"ну\",\n \"когда\",\n \"хорошо\",\n \"здесь\",\n \"по\",\n \"был\",\n \"знаю\",\n \"то\",\n \"только\",\n \"всё\",\n \"было\",\n \"вас\",\n \"может\",\n \"нас\",\n \"вот\",\n \"от\",\n \"быть\",\n \"кто\",\n \"будет\",\n \"почему\",\n \"вам\",\n \"их\",\n \"очень\",\n \"могу\",\n \"уже\",\n \"спасибо\",\n \"или\",\n \"нам\",\n \"еще\",\n \"там\",\n \"нужно\",\n \"сейчас\",\n \"где\",\n \"чем\",\n \"хочу\",\n \"ничего\",\n \"этого\",\n \"была\",\n \"мой\",\n \"ее\",\n \"ладно\",\n \"знаешь\",\n \"до\",\n \"этом\",\n \"потому\",\n \"теперь\",\n \"думаю\",\n \"больше\",\n \"её\",\n \"со\",\n \"раз\",\n \"ему\",\n \"надо\",\n \"время\",\n \"этот\",\n \"ли\",\n \"ещё\",\n \"пока\",\n \"даже\",\n \"привет\",\n \"сказал\",\n \"себя\",\n \"должен\",\n \"тоже\",\n \"хочешь\",\n \"давай\",\n \"никогда\",\n \"эй\",\n \"того\",\n \"тогда\",\n \"него\",\n \"ни\",\n \"тут\",\n \"были\",\n \"конечно\",\n \"правда\",\n \"об\",\n \"моя\",\n \"пожалуйста\",\n \"тобой\",\n \"сказать\",\n \"сегодня\",\n \"один\",\n \"лучше\",\n \"можешь\",\n \"сюда\",\n \"мной\",\n \"значит\",\n \"сделать\",\n \"всегда\",\n \"дело\",\n \"можно\",\n \"ей\",\n \"должны\",\n \"порядке\",\n \"без\",\n \"день\",\n \"том\",\n \"буду\",\n \"делать\",\n \"хотел\",\n \"чего\",\n \"эти\",\n \"много\",\n \"после\",\n \"этим\",\n \"всего\",\n \"во\",\n \"твой\",\n \"ним\",\n \"лет\",\n \"боже\",\n \"них\",\n \"сэр\",\n \"ведь\",\n \"мистер\",\n \"жизнь\",\n \"потом\",\n \"ней\",\n \"такой\",\n \"который\",\n \"всех\",\n \"через\",\n \"им\",\n \"возможно\",\n \"немного\",\n \"такое\",\n \"слишком\",\n \"себе\",\n \"зачем\",\n \"должна\",\n \"моей\",\n \"люди\",\n \"знаете\",\n \"этой\",\n \"думаешь\",\n \"свою\",\n \"точно\",\n \"человек\",\n \"твоя\",\n \"под\",\n \"сказала\",\n \"назад\",\n \"эту\",\n \"можем\",\n \"случилось\",\n \"мама\",\n \"мог\",\n \"вместе\",\n \"отец\",\n \"сделал\",\n \"мои\",\n \"кажется\",\n \"друг\",\n \"куда\",\n \"никто\",\n \"поэтому\",\n \"эта\",\n \"которые\",\n \"два\",\n \"тот\",\n \"сколько\",\n \"понимаю\",\n \"снова\",\n \"жизни\",\n \"нравится\",\n \"людей\",\n \"помочь\",\n \"видел\",\n \"люблю\",\n \"хочет\",\n \"место\",\n \"знать\",\n \"прости\",\n \"отлично\",\n \"похоже\",\n \"парень\",\n \"домой\",\n \"всем\",\n \"деньги\",\n \"иди\",\n \"времени\",\n \"дома\",\n \"именно\",\n \"доктор\",\n \"думал\",\n \"говорил\",\n \"делаешь\",\n \"будем\",\n \"прямо\",\n \"стоит\",\n \"поговорить\",\n \"найти\",\n \"разве\",\n \"слушай\",\n \"своей\",\n \"лишь\",\n \"ага\",\n \"можете\",\n \"простите\",\n \"хотела\",\n \"сам\",\n \"тем\",\n \"будешь\",\n \"прошу\",\n \"три\",\n \"деле\",\n \"хотите\",\n \"говорить\",\n \"давайте\",\n \"совсем\",\n \"знал\",\n \"знает\",\n \"какой\",\n \"моего\",\n \"скажи\",\n \"дом\",\n \"дела\",\n \"вами\",\n \"свои\",\n \"говорит\",\n \"несколько\",\n \"должно\",\n \"про\",\n \"ваш\",\n \"происходит\",\n \"жаль\",\n \"туда\",\n \"действительно\",\n \"папа\",\n \"завтра\",\n \"оно\",\n \"черт\",\n \"одна\",\n \"перед\",\n \"наш\",\n \"уверен\",\n \"отсюда\",\n \"нужна\",\n \"самом\",\n \"тех\",\n \"нужен\",\n \"свой\",\n \"мою\",\n \"кого\",\n \"верно\",\n \"работу\",\n \"каждый\",\n \"твоей\",\n \"будут\",\n \"хватит\",\n \"понял\",\n \"нее\",\n \"уж\",\n \"имя\",\n \"против\",\n \"пор\",\n \"чём\",\n \"раньше\",\n \"говорю\",\n \"более\",\n \"надеюсь\",\n \"итак\",\n \"при\",\n \"ваша\",\n \"вообще\",\n \"пошли\",\n \"мать\",\n \"нельзя\",\n \"наверное\",\n \"нами\",\n \"твои\",\n \"могли\",\n \"дай\",\n \"ради\",\n \"всю\",\n \"ребята\",\n \"ко\",\n \"хотя\",\n \"понимаешь\",\n \"идти\",\n \"этих\",\n \"откуда\",\n \"такая\",\n \"ясно\",\n \"другой\",\n \"извините\",\n \"вижу\",\n \"видеть\",\n \"над\",\n \"могут\",\n \"равно\",\n \"мисс\",\n \"скоро\",\n \"будто\",\n \"зовут\",\n \"виду\",\n \"наши\",\n \"думала\",\n \"послушай\",\n \"между\",\n \"своего\",\n \"вопрос\",\n \"этому\",\n \"почти\",\n \"года\",\n \"человека\",\n \"которая\",\n \"подожди\",\n \"руки\",\n \"нормально\",\n \"такие\",\n \"возьми\",\n \"минут\",\n \"извини\",\n \"вещи\",\n \"могла\",\n \"смотри\",\n \"хоть\",\n \"работа\",\n \"пару\",\n \"сын\",\n \"ваше\",\n \"дня\",\n \"пора\",\n \"неё\",\n \"жить\",\n \"видишь\",\n \"достаточно\",\n \"господи\",\n \"быстро\",\n \"твою\",\n \"весь\",\n \"убить\",\n \"ночь\",\n \"говоришь\",\n \"собой\",\n \"скажу\",\n \"готов\",\n \"слышал\",\n \"какая\",\n \"посмотри\",\n \"первый\",\n \"самое\",\n \"видела\",\n \"пусть\",\n \"месте\",\n \"нашли\",\n \"сказали\",\n \"плохо\",\n \"смогу\",\n \"ваши\",\n \"отца\",\n \"детей\",\n \"знаем\",\n \"рад\",\n \"прав\",\n \"никаких\",\n \"имею\",\n \"миссис\",\n \"иногда\",\n \"смерти\",\n \"своих\",\n \"пойду\",\n \"брат\",\n \"вроде\",\n \"рядом\",\n \"мир\",\n \"произошло\",\n \"которую\",\n ],\n en: [],\n};\n","/**\n * `langtell/profiles` — ready-to-use {@link LanguageProfile} data.\n *\n * This is the heavy DATA half of the library: alphabets, curated function-word\n * lists, and corpus-frequent word lists. It is deliberately kept behind its own\n * subpath, OUT of the zero-dependency core, so `import { compile } from\n * \"langtell\"` never drags the word corpora into a bundle that only needs the\n * script/letter rungs. Pass these into `compile({ candidates: [...] })`.\n *\n * Each profile is declarative and auditable:\n * - `alphabet` — the language's lowercased alphabet (raw; distinctiveness\n * is computed at runtime per candidate set).\n * - `marks` — orthographic marks that count as rung-1 evidence but\n * are not alphabet letters (the intra-word apostrophe).\n * - `words.function` — curated grammatical markers, hand-verified.\n * - `words.frequent` — common everyday words from a subtitle-frequency corpus.\n * - `iso6393` — ISO 639-3 code for the optional franc engine.\n *\n * Curation rule for `function`: a token may appear in exactly one candidate's\n * list ONLY if that form is genuinely used by only that language among those we\n * support. Shared forms must be in every list that uses them (set-difference\n * then cancels them) or omitted from all. When in doubt, omit: a missing marker\n * only costs recall.\n */\nimport type { LanguageCode, LanguageProfile } from \"./types.js\";\nimport { FREQUENT_GENERATED } from \"./internal/frequent.js\";\n\n/** Belarusian has no subtitle frequency data — hand-curated content words. */\nconst BE_FREQUENT: readonly string[] = [\n \"навіны\",\n \"відэа\",\n \"горад\",\n \"краіна\",\n \"дзень\",\n \"жыццё\",\n \"людзі\",\n \"праца\",\n \"беларуская\",\n \"сёння\",\n \"вядомы\",\n];\n\n/** Bulgarian has no subtitle frequency data here — hand-curated content words,\n * mirroring the BE fallback. Forms whose spelling is genuinely Bulgarian\n * (e.g. `град`/`днес` vs ru `город`/`сегодня`) so set-difference can use them. */\nconst BG_FREQUENT: readonly string[] = [\n \"новини\",\n \"видео\",\n \"град\",\n \"държава\",\n \"днес\",\n \"живот\",\n \"хора\",\n \"работа\",\n \"българия\",\n \"български\",\n \"известен\",\n \"страна\",\n];\n\nconst uk: LanguageProfile = {\n code: \"uk\",\n iso6393: \"ukr\",\n // has і ї є ґ and и; lacks ё ъ ы э\n alphabet: \"абвгґдеєжзиіїйклмнопрстуфхцчшщьюя\",\n // intra-word apostrophe (uk/be use it where ru uses ъ/nothing). All three\n // codepoints: U+0027 ' U+2019 ’ U+02BC ʼ.\n marks: \"'’ʼ\",\n words: {\n function: [\n \"і\",\n \"й\",\n \"що\",\n \"як\",\n \"це\",\n \"бо\",\n \"ще\",\n \"дуже\",\n \"де\",\n \"його\",\n \"її\",\n \"але\",\n \"який\",\n \"яка\",\n \"цей\",\n \"ця\",\n \"навіть\",\n \"чи\",\n \"або\",\n \"ні\",\n \"щоб\",\n \"теж\",\n \"також\",\n \"він\",\n \"вона\",\n \"вони\",\n ],\n frequent: FREQUENT_GENERATED[\"uk\"] ?? [],\n },\n};\n\nconst ru: LanguageProfile = {\n code: \"ru\",\n iso6393: \"rus\",\n // has ё ъ ы э and и; lacks і ї є ґ ў\n alphabet: \"абвгдеёжзийклмнопрстуфхцчшщъыьэюя\",\n words: {\n function: [\n \"и\",\n \"что\",\n \"как\",\n \"это\",\n \"бы\",\n \"уже\",\n \"или\",\n \"нет\",\n \"очень\",\n \"его\",\n \"её\",\n \"ее\",\n \"где\",\n \"когда\",\n \"этот\",\n \"эта\",\n \"но\",\n \"какой\",\n \"какая\",\n \"даже\",\n \"ещё\",\n \"чтобы\",\n \"потому\",\n \"тоже\",\n \"он\",\n \"она\",\n \"они\",\n ],\n frequent: FREQUENT_GENERATED[\"ru\"] ?? [],\n },\n};\n\nconst be: LanguageProfile = {\n code: \"be\",\n iso6393: \"bel\",\n // has і ў and ы ё э; lacks и щ ъ ї є ґ\n alphabet: \"абвгдеёжзійклмнопрстуўфхцчшыьэюя\",\n // intra-word apostrophe — same uk/be keep-signal; inert between uk and be.\n marks: \"'’ʼ\",\n words: {\n function: [\n \"і\",\n \"што\",\n \"гэта\",\n \"вельмі\",\n \"дзе\",\n \"ці\",\n \"таксама\",\n \"як\",\n \"але\",\n \"бо\",\n \"каб\",\n \"ён\",\n \"яна\",\n \"яны\",\n \"быў\",\n ],\n frequent: FREQUENT_GENERATED[\"be\"] ?? BE_FREQUENT,\n },\n};\n\nconst bg: LanguageProfile = {\n code: \"bg\",\n iso6393: \"bul\",\n // 30-letter Bulgarian alphabet. Has и й щ ъ ь (ъ is a full vowel); lacks ё ы э\n // і ї є ґ ў. `ъ` is shared with ru — inert between {ru, bg}; the word rungs\n // decide, exactly the mechanism `be` relies on for its shared letters.\n alphabet: \"абвгдежзийклмнопрстуфхцчшщъьюя\",\n words: {\n // Bulgarian-distinctive grammatical markers. Shared forms are omitted.\n function: [\n \"ще\",\n \"съм\",\n \"това\",\n \"този\",\n \"тази\",\n \"който\",\n \"която\",\n \"което\",\n \"които\",\n \"защото\",\n \"също\",\n \"тя\",\n \"ние\",\n \"вие\",\n ],\n frequent: FREQUENT_GENERATED[\"bg\"] ?? BG_FREQUENT,\n },\n};\n\nconst en: LanguageProfile = {\n code: \"en\",\n iso6393: \"eng\",\n alphabet: \"abcdefghijklmnopqrstuvwxyz\",\n words: {\n function: [\n \"the\",\n \"and\",\n \"or\",\n \"but\",\n \"of\",\n \"to\",\n \"in\",\n \"on\",\n \"at\",\n \"is\",\n \"are\",\n \"was\",\n \"were\",\n \"this\",\n \"that\",\n \"for\",\n \"with\",\n \"you\",\n \"we\",\n \"they\",\n \"he\",\n \"she\",\n \"it\",\n \"his\",\n \"her\",\n \"what\",\n \"how\",\n \"when\",\n \"where\",\n \"why\",\n \"who\",\n \"which\",\n \"a\",\n \"an\",\n \"i\",\n \"my\",\n \"your\",\n ],\n frequent: FREQUENT_GENERATED[\"en\"] ?? [],\n },\n};\n\nexport { uk, ru, be, bg, en };\n\n/** Registry of shipped profiles, keyed by BCP-47 code. */\nexport const PROFILES: Readonly<Record<LanguageCode, LanguageProfile>> = { uk, ru, be, bg, en };\n\n/** BCP-47 codes for which langtell ships a ready-made {@link LanguageProfile}.\n * Handy for narrowing a caller's roster to codes that can actually classify —\n * e.g. `codes.filter(hasProfile)`. Derived from {@link PROFILES}. */\nexport const PROFILED_CODES: readonly LanguageCode[] = Object.keys(PROFILES);\n\n/** Whether langtell ships a ready-made {@link LanguageProfile} for `code`. An\n * own-property check, so inherited names (`\"toString\"`, `\"constructor\"`) read\n * as absent. */\nexport function hasProfile(code: LanguageCode): boolean {\n return Object.prototype.hasOwnProperty.call(PROFILES, code);\n}\n\n/** Resolve profiles for the given codes, skipping any without a shipped profile. */\nexport function getProfiles(codes: readonly LanguageCode[]): LanguageProfile[] {\n return codes.map((c) => PROFILES[c]).filter((p): p is LanguageProfile => p !== undefined);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/internal/frequent.ts","../src/profiles.ts"],"names":[],"mappings":";AAmBO,IAAM,kBAAA,GAAkE;AAAA,EAC7E,EAAA,EAAI;AAAA,IACF,cAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,sCAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,gCAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,sCAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,gCAAA;AAAA,IACA,gCAAA;AAAA,IACA,cAAA;AAAA,IACA,gCAAA;AAAA,IACA,gCAAA;AAAA,IACA,cAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,sCAAA;AAAA,IACA,oBAAA;AAAA,IACA,gCAAA;AAAA,IACA,sCAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,sCAAA;AAAA,IACA,oBAAA;AAAA,IACA,sCAAA;AAAA,IACA,cAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,sCAAA;AAAA,IACA,gCAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,gCAAA;AAAA,IACA,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,gCAAA;AAAA,IACA,sCAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,sCAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,sCAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,4CAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,sCAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,sCAAA;AAAA,IACA,gCAAA;AAAA,IACA,gCAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,oBAAA;AAAA,IACA,gCAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,sCAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,kDAAA;AAAA,IACA,cAAA;AAAA,IACA,gCAAA;AAAA,IACA,gCAAA;AAAA,IACA,gCAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,oBAAA;AAAA,IACA,sCAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,4CAAA;AAAA,IACA,4CAAA;AAAA,IACA,4CAAA;AAAA,IACA,gCAAA;AAAA,IACA,oBAAA;AAAA,IACA,gCAAA;AAAA,IACA,gCAAA;AAAA,IACA,gCAAA;AAAA,IACA,kDAAA;AAAA,IACA,cAAA;AAAA,IACA,gCAAA;AAAA,IACA,4CAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,sCAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,4CA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AAA;AAAA,IACA,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,4CAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,gCAAA;AAAA,IACA,sCAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,sCAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,oBAAA;AAAA,IACA,cAAA;AAAA,IACA,gCAAA;AAAA,IACA,sCAAA;AAAA,IACA,cAAA;AAAA,IACA,0BAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,gCAAA;AAAA,IACA,sCAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,sCAAA;AAAA,IACA,sCAAA;AAAA,IACA,0BAAA;AAAA,IACA,sCAAA;AAAA,IACA,0BAAA;AAAA,IACA,sCAAA;AAAA,IACA,gCAAA;AAAA,IACA,4CAAA;AAAA,IACA,cAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,0BAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA,4CAAA;AAAA,IACA,sCAAA;AAAA,IACA,cAAA;AAAA,IACA,oBAAA;AAAA,IACA,8DAAA;AAAA,IACA,gCAAA;AAAA,IACA,4CAAA;AAAA,IACA,4CAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,sCAAA;AAAA,IACA,0BAAA;AAAA,IACA,0BAAA;AAAA,IACA,sCAAA;AAAA,IACA,4CAAA;AAAA,IACA,sCAAA;AAAA,IACA,0BAAA;AAAA,IACA,gCAAA;AAAA,IACA,cAAA;AAAA,IACA,sCAAA;AAAA,IACA,4CAAA;AAAA,I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","file":"profiles.js","sourcesContent":["// Generated frequency lists — the top everyday words for each language,\n// taken from an open subtitle-frequency corpus (general vocabulary; no\n// project-specific terms). Source: hermitdave/FrequencyWords (OpenSubtitles,\n// the 2018 content set). Kept out of the zero-dependency core: this data lives\n// behind the `langtell/profiles` subpath only.\n//\n// Rung 2b of the classifier (internal/classify.ts) reads these. They sharpen\n// distinctive-free disambiguation (e.g. uk \"робота\" vs ru \"работа\").\n//\n// Coverage notes for the Cyrillic-sibling additions:\n// - mk — top words from the curated `mk_50k.txt` list (Cyrillic, clean).\n// - kk — top Cyrillic words from `kk_full.txt`; OpenSubtitles has no curated\n// `kk_50k.txt`, so this list is shorter and was filtered to drop a handful\n// of subtitle proper nouns (character/show names). Still corpus-derived, not\n// hand-written, but thinner than the Slavic lists.\n// - sr — NOT here: FrequencyWords Serbian is Latin script only, so there is no\n// Cyrillic-Serbian corpus to draw from. The sr profile uses a hand-curated\n// Cyrillic content-word fallback (see SR_FREQUENT in profiles.ts), mirroring\n// the be/bg precedent. Flagged there for native-speaker review.\nexport const FREQUENT_GENERATED: Readonly<Record<string, readonly string[]>> = {\n uk: [\n \"не\",\n \"що\",\n \"на\",\n \"це\",\n \"ти\",\n \"что\",\n \"так\",\n \"ты\",\n \"это\",\n \"ми\",\n \"все\",\n \"тебе\",\n \"він\",\n \"як\",\n \"за\",\n \"ви\",\n \"до\",\n \"мене\",\n \"он\",\n \"мені\",\n \"ні\",\n \"але\",\n \"мы\",\n \"мне\",\n \"да\",\n \"как\",\n \"просто\",\n \"меня\",\n \"нет\",\n \"тут\",\n \"для\",\n \"його\",\n \"вы\",\n \"но\",\n \"то\",\n \"ну\",\n \"знаю\",\n \"про\",\n \"нас\",\n \"вас\",\n \"вони\",\n \"тебя\",\n \"вона\",\n \"она\",\n \"тобі\",\n \"его\",\n \"там\",\n \"якщо\",\n \"ще\",\n \"та\",\n \"добре\",\n \"щоб\",\n \"вам\",\n \"по\",\n \"нам\",\n \"хочу\",\n \"коли\",\n \"если\",\n \"бы\",\n \"же\",\n \"вже\",\n \"було\",\n \"був\",\n \"они\",\n \"може\",\n \"чи\",\n \"чтобы\",\n \"дуже\",\n \"від\",\n \"хорошо\",\n \"чому\",\n \"буде\",\n \"хто\",\n \"есть\",\n \"всё\",\n \"давай\",\n \"тому\",\n \"де\",\n \"здесь\",\n \"треба\",\n \"от\",\n \"думаю\",\n \"когда\",\n \"из\",\n \"того\",\n \"щось\",\n \"гаразд\",\n \"был\",\n \"цього\",\n \"только\",\n \"зараз\",\n \"было\",\n \"может\",\n \"нічого\",\n \"моя\",\n \"тільки\",\n \"те\",\n \"бути\",\n \"один\",\n \"уже\",\n \"можу\",\n \"тепер\",\n \"мій\",\n \"быть\",\n \"ось\",\n \"почему\",\n \"дякую\",\n \"раз\",\n \"вот\",\n \"могу\",\n \"через\",\n \"нужно\",\n \"всі\",\n \"бо\",\n \"кто\",\n \"будет\",\n \"правда\",\n \"без\",\n \"себе\",\n \"більше\",\n \"тоді\",\n \"час\",\n \"день\",\n \"ладно\",\n \"сейчас\",\n \"можна\",\n \"була\",\n \"их\",\n \"боже\",\n \"еще\",\n \"спасибо\",\n \"или\",\n \"будь\",\n \"йому\",\n \"где\",\n \"лише\",\n \"очень\",\n \"была\",\n \"ним\",\n \"привіт\",\n \"них\",\n \"чем\",\n \"навіть\",\n \"ніколи\",\n \"знаешь\",\n \"этого\",\n \"буду\",\n \"би\",\n \"её\",\n \"зі\",\n \"ее\",\n \"мой\",\n \"ничего\",\n \"хочеш\",\n \"нього\",\n \"цей\",\n \"чого\",\n \"життя\",\n \"этом\",\n \"теж\",\n \"люди\",\n \"твоя\",\n \"со\",\n \"потому\",\n \"сказав\",\n \"больше\",\n \"теперь\",\n \"ещё\",\n \"людей\",\n \"або\",\n \"свою\",\n \"привет\",\n \"який\",\n \"сюди\",\n \"таке\",\n \"даже\",\n \"із\",\n \"об\",\n \"тобою\",\n \"були\",\n \"два\",\n \"краще\",\n \"пока\",\n \"ему\",\n \"завжди\",\n \"хочешь\",\n \"должен\",\n \"багато\",\n \"сьогодні\",\n \"ей\",\n \"точно\",\n \"ласка\",\n \"время\",\n \"эй\",\n \"той\",\n \"себя\",\n \"надо\",\n \"сам\",\n \"мною\",\n \"тоже\",\n \"этот\",\n \"прошу\",\n \"маю\",\n \"сказал\",\n \"мама\",\n \"ли\",\n \"зробити\",\n \"сказати\",\n \"сказала\",\n \"назад\",\n \"які\",\n \"можеш\",\n \"тобой\",\n \"трохи\",\n \"потрібно\",\n \"ці\",\n \"тогда\",\n \"порядке\",\n \"ага\",\n \"саме\",\n \"хотів\",\n \"можешь\",\n \"під\",\n \"три\",\n \"никогда\",\n \"можете\",\n \"років\",\n \"собі\",\n \"скажи\",\n \"него\",\n \"пане\",\n \"робити\",\n \"знову\",\n \"твій\",\n \"люблю\",\n \"пожалуйста\",\n \"наш\",\n \"ни\",\n \"сегодня\",\n \"мной\",\n \"потім\",\n \"ніж\",\n \"были\",\n \"гей\",\n \"дай\",\n \"перед\",\n \"завтра\",\n \"вами\",\n \"яка\",\n \"одного\",\n \"ваша\",\n \"конечно\",\n \"сделать\",\n \"лучше\",\n \"цьому\",\n \"ваш\",\n \"цю\",\n \"сказать\",\n \"пам\",\n \"ніхто\",\n \"сюда\",\n \"нами\",\n \"можливо\",\n \"після\",\n \"значит\",\n \"прямо\",\n \"скільки\",\n \"одна\",\n \"чудово\",\n \"давайте\",\n \"бачив\",\n \"такий\",\n \"кого\",\n \"хтось\",\n \"сер\",\n \"ця\",\n \"мою\",\n \"усе\",\n \"разом\",\n \"чего\",\n \"куди\",\n \"звичайно\",\n \"справді\",\n \"поки\",\n \"должны\",\n \"всегда\",\n \"делать\",\n \"дело\",\n \"гроші\",\n \"цим\",\n \"міг\",\n \"том\",\n \"хіба\",\n \"ней\",\n \"твой\",\n \"этим\",\n \"повинен\",\n \"друг\",\n \"можно\",\n \"дня\",\n \"досить\",\n \"можемо\",\n \"зробив\",\n \"много\",\n \"хотел\",\n \"над\",\n \"должна\",\n \"после\",\n \"хоче\",\n \"якби\",\n \"могли\",\n \"місце\",\n \"всего\",\n \"воно\",\n \"часу\",\n \"робиш\",\n \"хлопці\",\n \"вибачте\",\n \"додому\",\n \"весь\",\n \"руки\",\n \"ведь\",\n \"ясно\",\n \"возможно\",\n \"вибач\",\n \"такой\",\n \"доктор\",\n \"повинні\",\n \"эти\",\n \"говорить\",\n \"мого\",\n \"нема\",\n \"нб\",\n \"йди\",\n \"думаешь\",\n \"моей\",\n \"немного\",\n \"навіщо\",\n \"господи\",\n \"мабуть\",\n \"жизнь\",\n \"твою\",\n \"зачем\",\n \"чоловік\",\n \"ходімо\",\n \"лет\",\n \"такое\",\n \"случилось\",\n \"звідси\",\n \"слишком\",\n \"мати\",\n \"скажу\",\n \"скоро\",\n \"сталося\",\n \"прости\",\n \"нормально\",\n \"пані\",\n \"всіх\",\n \"також\",\n \"вместе\",\n \"кілька\",\n \"брат\",\n \"чорт\",\n \"сама\",\n \"во\",\n \"потом\",\n \"такого\",\n \"казав\",\n \"розумію\",\n \"батько\",\n \"отже\",\n \"сделал\",\n \"таким\",\n \"могла\",\n \"тим\",\n \"швидше\",\n \"жаль\",\n \"туди\",\n \"речі\",\n \"знати\",\n \"поэтому\",\n \"мог\",\n \"хочете\",\n \"помочь\",\n \"одну\",\n \"всех\",\n \"который\",\n \"им\",\n \"ім\",\n \"думав\",\n \"можем\",\n \"под\",\n \"допомогти\",\n \"людина\",\n \"куда\",\n \"яку\",\n \"правильно\",\n \"давно\",\n \"зовсім\",\n \"при\",\n ],\n ru: [\n \"не\",\n \"что\",\n \"ты\",\n \"это\",\n \"на\",\n \"он\",\n \"мы\",\n \"как\",\n \"вы\",\n \"да\",\n \"мне\",\n \"нет\",\n \"меня\",\n \"так\",\n \"но\",\n \"его\",\n \"все\",\n \"она\",\n \"тебя\",\n \"если\",\n \"за\",\n \"бы\",\n \"тебе\",\n \"они\",\n \"чтобы\",\n \"же\",\n \"есть\",\n \"просто\",\n \"из\",\n \"для\",\n \"ну\",\n \"когда\",\n \"хорошо\",\n \"здесь\",\n \"по\",\n \"был\",\n \"знаю\",\n \"то\",\n \"только\",\n \"всё\",\n \"было\",\n \"вас\",\n \"может\",\n \"нас\",\n \"вот\",\n \"от\",\n \"быть\",\n \"кто\",\n \"будет\",\n \"почему\",\n \"вам\",\n \"их\",\n \"очень\",\n \"могу\",\n \"уже\",\n \"спасибо\",\n \"или\",\n \"нам\",\n \"еще\",\n \"там\",\n \"нужно\",\n \"сейчас\",\n \"где\",\n \"чем\",\n \"хочу\",\n \"ничего\",\n \"этого\",\n \"была\",\n \"мой\",\n \"ее\",\n \"ладно\",\n \"знаешь\",\n \"до\",\n \"этом\",\n \"потому\",\n \"теперь\",\n \"думаю\",\n \"больше\",\n \"её\",\n \"со\",\n \"раз\",\n \"ему\",\n \"надо\",\n \"время\",\n \"этот\",\n \"ли\",\n \"ещё\",\n \"пока\",\n \"даже\",\n \"привет\",\n \"сказал\",\n \"себя\",\n \"должен\",\n \"тоже\",\n \"хочешь\",\n \"давай\",\n \"никогда\",\n \"эй\",\n \"того\",\n \"тогда\",\n \"него\",\n \"ни\",\n \"тут\",\n \"были\",\n \"конечно\",\n \"правда\",\n \"об\",\n \"моя\",\n \"пожалуйста\",\n \"тобой\",\n \"сказать\",\n \"сегодня\",\n \"один\",\n \"лучше\",\n \"можешь\",\n \"сюда\",\n \"мной\",\n \"значит\",\n \"сделать\",\n \"всегда\",\n \"дело\",\n \"можно\",\n \"ей\",\n \"должны\",\n \"порядке\",\n \"без\",\n \"день\",\n \"том\",\n \"буду\",\n \"делать\",\n \"хотел\",\n \"чего\",\n \"эти\",\n \"много\",\n \"после\",\n \"этим\",\n \"всего\",\n \"во\",\n \"твой\",\n \"ним\",\n \"лет\",\n \"боже\",\n \"них\",\n \"сэр\",\n \"ведь\",\n \"мистер\",\n \"жизнь\",\n \"потом\",\n \"ней\",\n \"такой\",\n \"который\",\n \"всех\",\n \"через\",\n \"им\",\n \"возможно\",\n \"немного\",\n \"такое\",\n \"слишком\",\n \"себе\",\n \"зачем\",\n \"должна\",\n \"моей\",\n \"люди\",\n \"знаете\",\n \"этой\",\n \"думаешь\",\n \"свою\",\n \"точно\",\n \"человек\",\n \"твоя\",\n \"под\",\n \"сказала\",\n \"назад\",\n \"эту\",\n \"можем\",\n \"случилось\",\n \"мама\",\n \"мог\",\n \"вместе\",\n \"отец\",\n \"сделал\",\n \"мои\",\n \"кажется\",\n \"друг\",\n \"куда\",\n \"никто\",\n \"поэтому\",\n \"эта\",\n \"которые\",\n \"два\",\n \"тот\",\n \"сколько\",\n \"понимаю\",\n \"снова\",\n \"жизни\",\n \"нравится\",\n \"людей\",\n \"помочь\",\n \"видел\",\n \"люблю\",\n \"хочет\",\n \"место\",\n \"знать\",\n \"прости\",\n \"отлично\",\n \"похоже\",\n \"парень\",\n \"домой\",\n \"всем\",\n \"деньги\",\n \"иди\",\n \"времени\",\n \"дома\",\n \"именно\",\n \"доктор\",\n \"думал\",\n \"говорил\",\n \"делаешь\",\n \"будем\",\n \"прямо\",\n \"стоит\",\n \"поговорить\",\n \"найти\",\n \"разве\",\n \"слушай\",\n \"своей\",\n \"лишь\",\n \"ага\",\n \"можете\",\n \"простите\",\n \"хотела\",\n \"сам\",\n \"тем\",\n \"будешь\",\n \"прошу\",\n \"три\",\n \"деле\",\n \"хотите\",\n \"говорить\",\n \"давайте\",\n \"совсем\",\n \"знал\",\n \"знает\",\n \"какой\",\n \"моего\",\n \"скажи\",\n \"дом\",\n \"дела\",\n \"вами\",\n \"свои\",\n \"говорит\",\n \"несколько\",\n \"должно\",\n \"про\",\n \"ваш\",\n \"происходит\",\n \"жаль\",\n \"туда\",\n \"действительно\",\n \"папа\",\n \"завтра\",\n \"оно\",\n \"черт\",\n \"одна\",\n \"перед\",\n \"наш\",\n \"уверен\",\n \"отсюда\",\n \"нужна\",\n \"самом\",\n \"тех\",\n \"нужен\",\n \"свой\",\n \"мою\",\n \"кого\",\n \"верно\",\n \"работу\",\n \"каждый\",\n \"твоей\",\n \"будут\",\n \"хватит\",\n \"понял\",\n \"нее\",\n \"уж\",\n \"имя\",\n \"против\",\n \"пор\",\n \"чём\",\n \"раньше\",\n \"говорю\",\n \"более\",\n \"надеюсь\",\n \"итак\",\n \"при\",\n \"ваша\",\n \"вообще\",\n \"пошли\",\n \"мать\",\n \"нельзя\",\n \"наверное\",\n \"нами\",\n \"твои\",\n \"могли\",\n \"дай\",\n \"ради\",\n \"всю\",\n \"ребята\",\n \"ко\",\n \"хотя\",\n \"понимаешь\",\n \"идти\",\n \"этих\",\n \"откуда\",\n \"такая\",\n \"ясно\",\n \"другой\",\n \"извините\",\n \"вижу\",\n \"видеть\",\n \"над\",\n \"могут\",\n \"равно\",\n \"мисс\",\n \"скоро\",\n \"будто\",\n \"зовут\",\n \"виду\",\n \"наши\",\n \"думала\",\n \"послушай\",\n \"между\",\n \"своего\",\n \"вопрос\",\n \"этому\",\n \"почти\",\n \"года\",\n \"человека\",\n \"которая\",\n \"подожди\",\n \"руки\",\n \"нормально\",\n \"такие\",\n \"возьми\",\n \"минут\",\n \"извини\",\n \"вещи\",\n \"могла\",\n \"смотри\",\n \"хоть\",\n \"работа\",\n \"пару\",\n \"сын\",\n \"ваше\",\n \"дня\",\n \"пора\",\n \"неё\",\n \"жить\",\n \"видишь\",\n \"достаточно\",\n \"господи\",\n \"быстро\",\n \"твою\",\n \"весь\",\n \"убить\",\n \"ночь\",\n \"говоришь\",\n \"собой\",\n \"скажу\",\n \"готов\",\n \"слышал\",\n \"какая\",\n \"посмотри\",\n \"первый\",\n \"самое\",\n \"видела\",\n \"пусть\",\n \"месте\",\n \"нашли\",\n \"сказали\",\n \"плохо\",\n \"смогу\",\n \"ваши\",\n \"отца\",\n \"детей\",\n \"знаем\",\n \"рад\",\n \"прав\",\n \"никаких\",\n \"имею\",\n \"миссис\",\n \"иногда\",\n \"смерти\",\n \"своих\",\n \"пойду\",\n \"брат\",\n \"вроде\",\n \"рядом\",\n \"мир\",\n \"произошло\",\n \"которую\",\n ],\n mk: [\n \"да\",\n \"не\",\n \"се\",\n \"е\",\n \"на\",\n \"го\",\n \"и\",\n \"што\",\n \"во\",\n \"за\",\n \"тоа\",\n \"ти\",\n \"дека\",\n \"од\",\n \"со\",\n \"ми\",\n \"си\",\n \"ја\",\n \"како\",\n \"јас\",\n \"ги\",\n \"ова\",\n \"сум\",\n \"добро\",\n \"ме\",\n \"те\",\n \"само\",\n \"ли\",\n \"нема\",\n \"но\",\n \"ако\",\n \"а\",\n \"тој\",\n \"беше\",\n \"треба\",\n \"кога\",\n \"сега\",\n \"многу\",\n \"знам\",\n \"кој\",\n \"му\",\n \"има\",\n \"нешто\",\n \"може\",\n \"мене\",\n \"би\",\n \"каде\",\n \"сакам\",\n \"тебе\",\n \"тука\",\n \"дали\",\n \"така\",\n \"зошто\",\n \"сите\",\n \"ајде\",\n \"ред\",\n \"ни\",\n \"па\",\n \"знаеш\",\n \"овде\",\n \"таа\",\n \"можам\",\n \"биде\",\n \"по\",\n \"мислам\",\n \"сакаш\",\n \"до\",\n \"еден\",\n \"ви\",\n \"уште\",\n \"или\",\n \"некој\",\n \"ама\",\n \"време\",\n \"ништо\",\n \"тие\",\n \"таму\",\n \"сме\",\n \"мора\",\n \"сте\",\n \"пред\",\n \"можеби\",\n \"имам\",\n \"ве\",\n \"малку\",\n \"молам\",\n \"ние\",\n \"еј\",\n \"одиме\",\n \"навистина\",\n \"можеш\",\n \"колку\",\n \"него\",\n \"мојот\",\n \"работа\",\n \"тогаш\",\n \"оди\",\n \"здраво\",\n \"толку\",\n \"никогаш\",\n \"имаш\",\n \"вие\",\n \"мислиш\",\n \"им\",\n \"кои\",\n \"значи\",\n \"затоа\",\n \"една\",\n \"благодарам\",\n \"мојата\",\n \"овој\",\n \"која\",\n \"татко\",\n \"работи\",\n \"нели\",\n \"без\",\n \"одам\",\n \"кажам\",\n \"човек\",\n \"имаме\",\n \"години\",\n \"нас\",\n \"ден\",\n \"оваа\",\n \"фала\",\n \"правиш\",\n \"кај\",\n \"сака\",\n \"направи\",\n \"о\",\n \"рече\",\n \"види\",\n \"твојот\",\n \"бев\",\n \"изгледа\",\n \"додека\",\n \"случи\",\n \"кажи\",\n \"пат\",\n \"вас\",\n \"твојата\",\n \"никој\",\n \"мислев\",\n \"место\",\n \"овие\",\n \"дома\",\n \"мајка\",\n \"секогаш\",\n \"жал\",\n \"морам\",\n ],\n kk: [\n \"мен\",\n \"ол\",\n \"сен\",\n \"не\",\n \"керек\",\n \"оны\",\n \"ба\",\n \"ма\",\n \"бар\",\n \"бе\",\n \"деп\",\n \"емес\",\n \"сіз\",\n \"біз\",\n \"ал\",\n \"мені\",\n \"де\",\n \"жатыр\",\n \"енді\",\n \"олар\",\n \"бір\",\n \"да\",\n \"сені\",\n \"неге\",\n \"адам\",\n \"осында\",\n \"болады\",\n \"келеді\",\n \"доктор\",\n \"мына\",\n \"болды\",\n \"тек\",\n \"рахмет\",\n \"сол\",\n \"еді\",\n \"ме\",\n \"болып\",\n \"егер\",\n \"осы\",\n \"мында\",\n \"солай\",\n \"едім\",\n \"міне\",\n \"президент\",\n \"екен\",\n \"кетті\",\n \"кім\",\n \"болса\",\n \"білмеймін\",\n \"бізге\",\n \"жарайды\",\n \"алып\",\n \"сізді\",\n \"пе\",\n \"сізге\",\n \"жерде\",\n \"ше\",\n \"кеттік\",\n \"бола\",\n \"шын\",\n \"жерден\",\n \"адамдар\",\n \"туралы\",\n \"жерге\",\n \"сонда\",\n \"келді\",\n \"мырза\",\n \"тірі\",\n \"деген\",\n \"болар\",\n \"білемін\",\n \"онда\",\n \"а\",\n \"бірге\",\n \"тым\",\n \"себебі\",\n \"екенін\",\n \"кел\",\n \"келген\",\n \"тауып\",\n \"дейді\",\n \"бер\",\n \"тіпті\",\n \"оларды\",\n \"алмаймын\",\n \"осылай\",\n \"олай\",\n \"одан\",\n \"бері\",\n \"жатырмын\",\n \"мынау\",\n \"келе\",\n \"у\",\n \"апа\",\n \"сондай\",\n \"кешірім\",\n \"ешкім\",\n \"бізді\",\n \"па\",\n \"іздеп\",\n \"тиіс\",\n \"сендер\",\n \"менде\",\n \"дене\",\n \"кейін\",\n \"тез\",\n \"тарт\",\n \"біреу\",\n \"болмайды\",\n \"ана\",\n \"тыныш\",\n \"ойлап\",\n \"екі\",\n \"болмаса\",\n \"айтты\",\n \"келдім\",\n \"арнайы\",\n \"былай\",\n \"шынымен\",\n \"келіп\",\n \"бол\",\n \"барып\",\n \"алтын\",\n \"отыр\",\n \"болу\",\n \"кішкене\",\n \"алмай\",\n \"келмейді\",\n \"керемет\",\n \"адамдары\",\n \"деймін\",\n \"жеп\",\n \"бойы\",\n \"сэр\",\n \"дегенмен\",\n \"кей\",\n \"боп\",\n \"тезірек\",\n \"біраз\",\n \"бара\",\n ],\n en: [],\n};\n","/**\n * `langtell/profiles` — ready-to-use {@link LanguageProfile} data.\n *\n * This is the heavy DATA half of the library: alphabets, curated function-word\n * lists, and corpus-frequent word lists. It is deliberately kept behind its own\n * subpath, OUT of the zero-dependency core, so `import { compile } from\n * \"langtell\"` never drags the word corpora into a bundle that only needs the\n * script/letter rungs. Pass these into `compile({ candidates: [...] })`.\n *\n * Each profile is declarative and auditable:\n * - `alphabet` — the language's lowercased alphabet (raw; distinctiveness\n * is computed at runtime per candidate set).\n * - `marks` — orthographic marks that count as rung-1 evidence but\n * are not alphabet letters (the intra-word apostrophe).\n * - `words.function` — curated grammatical markers, hand-verified.\n * - `words.frequent` — common everyday words from a subtitle-frequency corpus.\n * - `iso6393` — ISO 639-3 code for the optional franc engine.\n *\n * Curation rule for `function`: a token may appear in exactly one candidate's\n * list ONLY if that form is genuinely used by only that language among those we\n * support. Shared forms must be in every list that uses them (set-difference\n * then cancels them) or omitted from all. When in doubt, omit: a missing marker\n * only costs recall.\n */\nimport type { LanguageCode, LanguageProfile } from \"./types.js\";\nimport { FREQUENT_GENERATED } from \"./internal/frequent.js\";\n\n/** Belarusian has no subtitle frequency data — hand-curated content words. */\nconst BE_FREQUENT: readonly string[] = [\n \"навіны\",\n \"відэа\",\n \"горад\",\n \"краіна\",\n \"дзень\",\n \"жыццё\",\n \"людзі\",\n \"праца\",\n \"беларуская\",\n \"сёння\",\n \"вядомы\",\n];\n\n/** Bulgarian has no subtitle frequency data here — hand-curated content words,\n * mirroring the BE fallback. Forms whose spelling is genuinely Bulgarian\n * (e.g. `град`/`днес` vs ru `город`/`сегодня`) so set-difference can use them. */\nconst BG_FREQUENT: readonly string[] = [\n \"новини\",\n \"видео\",\n \"град\",\n \"държава\",\n \"днес\",\n \"живот\",\n \"хора\",\n \"работа\",\n \"българия\",\n \"български\",\n \"известен\",\n \"страна\",\n];\n\n/** Serbian Cyrillic has NO usable subtitle frequency data: hermitdave/\n * FrequencyWords ships Serbian in LATIN script only, and blind transliteration\n * would invent data, so this is a hand-curated Cyrillic content-word list,\n * mirroring the BE/BG fallbacks. Forms are everyday Serbian content words spelt\n * in Cyrillic; many use Serbian-distinctive letters (ј, ћ, ђ, џ) so they read as\n * distinctive at runtime. NEEDS NATIVE-SPEAKER / LINGUISTIC REVIEW before\n * release. */\nconst SR_FREQUENT: readonly string[] = [\n \"вести\",\n \"видео\",\n \"град\",\n \"држава\",\n \"данас\",\n \"живот\",\n \"људи\",\n \"посао\",\n \"србија\",\n \"српски\",\n \"познат\",\n \"земља\",\n \"време\",\n \"деца\",\n \"године\",\n \"човек\",\n \"новине\",\n \"свет\",\n \"данашњи\",\n \"недеља\",\n];\n\nconst uk: LanguageProfile = {\n code: \"uk\",\n iso6393: \"ukr\",\n // has і ї є ґ and и; lacks ё ъ ы э\n alphabet: \"абвгґдеєжзиіїйклмнопрстуфхцчшщьюя\",\n // intra-word apostrophe (uk/be use it where ru uses ъ/nothing). All three\n // codepoints: U+0027 ' U+2019 ’ U+02BC ʼ.\n marks: \"'’ʼ\",\n words: {\n function: [\n \"і\",\n \"й\",\n \"що\",\n \"як\",\n \"це\",\n \"бо\",\n \"ще\",\n \"дуже\",\n \"де\",\n \"його\",\n \"її\",\n \"але\",\n \"який\",\n \"яка\",\n \"цей\",\n \"ця\",\n \"навіть\",\n \"чи\",\n \"або\",\n \"ні\",\n \"щоб\",\n \"теж\",\n \"також\",\n \"він\",\n \"вона\",\n \"вони\",\n ],\n frequent: FREQUENT_GENERATED[\"uk\"] ?? [],\n },\n};\n\nconst ru: LanguageProfile = {\n code: \"ru\",\n iso6393: \"rus\",\n // has ё ъ ы э and и; lacks і ї є ґ ў\n alphabet: \"абвгдеёжзийклмнопрстуфхцчшщъыьэюя\",\n words: {\n function: [\n \"и\",\n \"что\",\n \"как\",\n \"это\",\n \"бы\",\n \"уже\",\n \"или\",\n \"нет\",\n \"очень\",\n \"его\",\n \"её\",\n \"ее\",\n \"где\",\n \"когда\",\n \"этот\",\n \"эта\",\n \"но\",\n \"какой\",\n \"какая\",\n \"даже\",\n \"ещё\",\n \"чтобы\",\n \"потому\",\n \"тоже\",\n \"он\",\n \"она\",\n \"они\",\n ],\n frequent: FREQUENT_GENERATED[\"ru\"] ?? [],\n },\n};\n\nconst be: LanguageProfile = {\n code: \"be\",\n iso6393: \"bel\",\n // has і ў and ы ё э; lacks и щ ъ ї є ґ\n alphabet: \"абвгдеёжзійклмнопрстуўфхцчшыьэюя\",\n // intra-word apostrophe — same uk/be keep-signal; inert between uk and be.\n marks: \"'’ʼ\",\n words: {\n function: [\n \"і\",\n \"што\",\n \"гэта\",\n \"вельмі\",\n \"дзе\",\n \"ці\",\n \"таксама\",\n \"як\",\n \"але\",\n \"бо\",\n \"каб\",\n \"ён\",\n \"яна\",\n \"яны\",\n \"быў\",\n ],\n frequent: FREQUENT_GENERATED[\"be\"] ?? BE_FREQUENT,\n },\n};\n\nconst bg: LanguageProfile = {\n code: \"bg\",\n iso6393: \"bul\",\n // 30-letter Bulgarian alphabet. Has и й щ ъ ь (ъ is a full vowel); lacks ё ы э\n // і ї є ґ ў. `ъ` is shared with ru — inert between {ru, bg}; the word rungs\n // decide, exactly the mechanism `be` relies on for its shared letters.\n alphabet: \"абвгдежзийклмнопрстуфхцчшщъьюя\",\n words: {\n // Bulgarian-distinctive grammatical markers. Shared forms are omitted.\n function: [\n \"ще\",\n \"съм\",\n \"това\",\n \"този\",\n \"тази\",\n \"който\",\n \"която\",\n \"което\",\n \"които\",\n \"защото\",\n \"също\",\n \"тя\",\n \"ние\",\n \"вие\",\n ],\n frequent: FREQUENT_GENERATED[\"bg\"] ?? BG_FREQUENT,\n },\n};\n\nconst en: LanguageProfile = {\n code: \"en\",\n iso6393: \"eng\",\n alphabet: \"abcdefghijklmnopqrstuvwxyz\",\n words: {\n function: [\n \"the\",\n \"and\",\n \"or\",\n \"but\",\n \"of\",\n \"to\",\n \"in\",\n \"on\",\n \"at\",\n \"is\",\n \"are\",\n \"was\",\n \"were\",\n \"this\",\n \"that\",\n \"for\",\n \"with\",\n \"you\",\n \"we\",\n \"they\",\n \"he\",\n \"she\",\n \"it\",\n \"his\",\n \"her\",\n \"what\",\n \"how\",\n \"when\",\n \"where\",\n \"why\",\n \"who\",\n \"which\",\n \"a\",\n \"an\",\n \"i\",\n \"my\",\n \"your\",\n ],\n frequent: FREQUENT_GENERATED[\"en\"] ?? [],\n },\n};\n\nconst sr: LanguageProfile = {\n code: \"sr\",\n iso6393: \"srp\",\n // Serbian Cyrillic azbuka (Вук), 30 letters. Distinctive vs the other Cyrillic\n // profiles: ђ ћ (sr-only) and ј љ њ џ (shared with mk, inert between them; the\n // word rungs decide sr↔mk). No ё й щ ъ ы ь э ю я.\n alphabet: \"абвгдђежзијклљмнњопрстћуфхцчџш\",\n words: {\n // Serbian-distinctive grammatical markers. `сам` (I am) is omitted: it\n // collides with Macedonian `сам` (\"alone\"). Shared forms with mk (и, да, се,\n // не, на, само, …) are omitted so set-difference is not cancelled to nothing.\n // The future markers use ћ, a letter no other profile has.\n function: [\n \"је\",\n \"су\",\n \"али\",\n \"ће\",\n \"ћемо\",\n \"ћеш\",\n \"због\",\n \"јер\",\n \"овај\",\n \"када\",\n \"увек\",\n \"сада\",\n ],\n // Hand-curated Cyrillic fallback — see SR_FREQUENT. Flagged for review.\n frequent: FREQUENT_GENERATED[\"sr\"] ?? SR_FREQUENT,\n },\n};\n\nconst mk: LanguageProfile = {\n code: \"mk\",\n iso6393: \"mkd\",\n // Macedonian alphabet, 31 letters. Distinctive: ѓ ќ ѕ (mk-only) plus ј љ њ џ\n // (shared with sr). No ё й щ ъ ы ь э ю я, no ђ ћ (those are Serbian).\n alphabet: \"абвгдѓежзѕијклљмнњопрстќуфхцчџш\",\n words: {\n // Macedonian-distinctive grammatical markers. The future particle `ќе` and\n // `зошто`/`затоа` use ќ (mk-only); the clitics `го`/`ги` and `сум` (I am) are\n // distinctively Macedonian. Forms shared with sr (и, да, се, не, само, …) are\n // omitted; `вие`/`ние` are omitted as they collide with bg.\n function: [\n \"го\",\n \"ги\",\n \"сум\",\n \"ќе\",\n \"дека\",\n \"зошто\",\n \"затоа\",\n \"тоа\",\n \"оваа\",\n \"овој\",\n \"тој\",\n \"таа\",\n \"тие\",\n \"сега\",\n \"сите\",\n ],\n frequent: FREQUENT_GENERATED[\"mk\"] ?? [],\n },\n};\n\nconst kk: LanguageProfile = {\n code: \"kk\",\n iso6393: \"kaz\",\n // Kazakh Cyrillic, 42 letters (post-1940). Distinctive Turkic letters ә ғ қ ң\n // ө ұ ү һ і set it apart from every Slavic profile; it keeps the Russian set\n // (и й ё ц щ ъ ы ь э ю я) for loanwords. Highly distinctive, so low-risk.\n alphabet: \"аәбвгғдеёжзийкқлмнңоөпрстуұүфхһцчшщъыіьэюя\",\n words: {\n // Kazakh function words — no overlap with any Slavic profile, so every form\n // is safely distinctive. (`ма`/`ба`/`бе`/`па` interrogative particles are\n // omitted: too short and ambiguous against Slavic two-letter clitics.)\n function: [\n \"мен\",\n \"сен\",\n \"бұл\",\n \"және\",\n \"бар\",\n \"жоқ\",\n \"ол\",\n \"үшін\",\n \"оны\",\n \"менің\",\n \"сенің\",\n \"оның\",\n \"бірақ\",\n \"егер\",\n \"сол\",\n \"осы\",\n \"біз\",\n \"сіз\",\n \"олар\",\n \"қайда\",\n \"неге\",\n \"себебі\",\n \"қандай\",\n \"мұнда\",\n \"деп\",\n \"ғой\",\n ],\n // Corpus-derived from the smaller `kk_full.txt` (no curated kk_50k exists).\n frequent: FREQUENT_GENERATED[\"kk\"] ?? [],\n },\n};\n\nexport { uk, ru, be, bg, en, sr, mk, kk };\n\n/** Registry of shipped profiles, keyed by BCP-47 code. */\nexport const PROFILES: Readonly<Record<LanguageCode, LanguageProfile>> = {\n uk,\n ru,\n be,\n bg,\n en,\n sr,\n mk,\n kk,\n};\n\n/** BCP-47 codes for which langtell ships a ready-made {@link LanguageProfile}.\n * Handy for narrowing a caller's roster to codes that can actually classify —\n * e.g. `codes.filter(hasProfile)`. Derived from {@link PROFILES}. */\nexport const PROFILED_CODES: readonly LanguageCode[] = Object.keys(PROFILES);\n\n/** Whether langtell ships a ready-made {@link LanguageProfile} for `code`. An\n * own-property check, so inherited names (`\"toString\"`, `\"constructor\"`) read\n * as absent. */\nexport function hasProfile(code: LanguageCode): boolean {\n return Object.prototype.hasOwnProperty.call(PROFILES, code);\n}\n\n/** Resolve profiles for the given codes, skipping any without a shipped profile. */\nexport function getProfiles(codes: readonly LanguageCode[]): LanguageProfile[] {\n return codes.map((c) => PROFILES[c]).filter((p): p is LanguageProfile => p !== undefined);\n}\n"]}
|
package/dist/text.d.ts
CHANGED
package/dist/text.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** A BCP-47 language code (e.g. `"uk"`, `"en"`, `"pt-BR"`). `"unknown"` is a
|
|
2
2
|
* sentinel value used in results, not a code. */
|
|
3
3
|
type LanguageCode = string;
|
|
4
|
-
type EvidenceKind = "title-script" | "html-lang" | "meta-content-language" | "meta-og-locale" | "http-content-language" | "source-prior" | "franc" | "chrome-ai" | "explicit-locale";
|
|
4
|
+
type EvidenceKind = "title-script" | "html-lang" | "node-lang" | "meta-content-language" | "meta-og-locale" | "http-content-language" | "source-prior" | "franc" | "chrome-ai" | "explicit-locale";
|
|
5
5
|
/** One signal contributing to a classification, kept for the audit trail. */
|
|
6
6
|
interface LanguageEvidence {
|
|
7
7
|
kind: EvidenceKind;
|
|
@@ -57,16 +57,25 @@ interface LanguageProfile {
|
|
|
57
57
|
iso6393?: string;
|
|
58
58
|
}
|
|
59
59
|
type HeaderBag = Headers | Record<string, string | string[] | undefined | null>;
|
|
60
|
+
/** Attribute values of the unit under detection, keyed by attribute name —
|
|
61
|
+
* `{ lang: el.getAttribute("lang") }`. Extraction is the caller's job
|
|
62
|
+
* (langtell never touches a DOM), including resolving the standard `lang`
|
|
63
|
+
* attribute's inheritance when that's wanted: `el.closest("[lang]")`. */
|
|
64
|
+
type AttrBag = Readonly<Record<string, string | null | undefined>>;
|
|
60
65
|
interface DetectInput {
|
|
61
66
|
text?: string;
|
|
62
67
|
html?: string;
|
|
63
68
|
headers?: HeaderBag;
|
|
69
|
+
/** The detection subject's own attributes. Enables per-node
|
|
70
|
+
* declared-language evidence; which attribute names count is compiled in
|
|
71
|
+
* via {@link DetectorConfig.nodeLangAttributes}. */
|
|
72
|
+
attrs?: AttrBag;
|
|
64
73
|
}
|
|
65
74
|
interface DetectContext {
|
|
66
75
|
signal?: AbortSignal;
|
|
67
76
|
maxChars?: number;
|
|
68
77
|
}
|
|
69
|
-
type SourceInput = "text" | "html" | "headers";
|
|
78
|
+
type SourceInput = "text" | "html" | "headers" | "attrs";
|
|
70
79
|
/** A synchronous, dependency-free evidence source (script, HTML tags, headers). */
|
|
71
80
|
interface SyncSource {
|
|
72
81
|
readonly id: string;
|
|
@@ -108,6 +117,13 @@ interface DetectorConfig<E extends readonly EvidenceSource[] = []> {
|
|
|
108
117
|
engines?: E;
|
|
109
118
|
weights?: Weights;
|
|
110
119
|
earlyExit?: EarlyExit;
|
|
120
|
+
/** Which of `input.attrs` count as per-node language declarations, in
|
|
121
|
+
* evidence order. Defaults to `["lang"]` — the one standardized bearer.
|
|
122
|
+
* Vendor conventions are deliberate opt-ins: `["lang", "data-rl"]`
|
|
123
|
+
* teaches a detector Google's response-language label. Weigh or silence
|
|
124
|
+
* one attribute via its namespaced source id
|
|
125
|
+
* (`weights: { "node-lang:data-rl": 0.8 }`). */
|
|
126
|
+
nodeLangAttributes?: readonly string[];
|
|
111
127
|
/** Forwarded to {@link fuse}. See {@link NonDiscriminatingScript}. Defaults to
|
|
112
128
|
* `"candidate"` (current behavior); opt into `"unknown"` for a roster-closed,
|
|
113
129
|
* evidence-only policy. */
|
|
@@ -117,4 +133,4 @@ interface DetectorConfig<E extends readonly EvidenceSource[] = []> {
|
|
|
117
133
|
* the moment an async engine is registered — so callers never guess `await`. */
|
|
118
134
|
type DetectFn<E extends readonly EvidenceSource[]> = HasAsync<E> extends true ? (input: DetectInput, ctx?: DetectContext) => Promise<Classification> : (input: DetectInput) => Classification;
|
|
119
135
|
|
|
120
|
-
export type { AsyncSource as A, Classification as C, DetectorConfig as D, EvidenceSource as E, HeaderBag as H, LanguageProfile as L, NonDiscriminatingScript as N, SyncSource as S, Weights as W, LanguageEvidence as a, LanguageCode as b, DetectFn as c,
|
|
136
|
+
export type { AsyncSource as A, Classification as C, DetectorConfig as D, EvidenceSource as E, HeaderBag as H, LanguageProfile as L, NonDiscriminatingScript as N, SyncSource as S, Weights as W, LanguageEvidence as a, LanguageCode as b, DetectFn as c, AttrBag as d, DetectContext as e, DetectInput as f, EarlyExit as g, EvidenceKind as h, HasAsync as i, SourceInput as j };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "langtell",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Tell me the language — evidence-fusion language detection for short strings, with an auditable confidence trail.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -65,6 +65,10 @@
|
|
|
65
65
|
"types": "./dist/chrome-ai.d.ts",
|
|
66
66
|
"import": "./dist/chrome-ai.js"
|
|
67
67
|
},
|
|
68
|
+
"./cyrillic": {
|
|
69
|
+
"types": "./dist/cyrillic.d.ts",
|
|
70
|
+
"import": "./dist/cyrillic.js"
|
|
71
|
+
},
|
|
68
72
|
"./package.json": "./package.json"
|
|
69
73
|
},
|
|
70
74
|
"files": [
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/fuse.ts"],"names":[],"mappings":";;;;AA2BA,IAAM,mBAAA,GAA8C;AAAA,EAClD,cAAA,EAAgB,CAAA;AAAA,EAChB,iBAAA,EAAmB,CAAA;AAAA,EACnB,WAAA,EAAa,CAAA;AAAA,EACb,cAAA,EAAgB,GAAA;AAAA,EAChB,KAAA,EAAO,GAAA;AAAA,EACP,uBAAA,EAAyB,GAAA;AAAA,EACzB,uBAAA,EAAyB,IAAA;AAAA,EACzB,gBAAA,EAAkB,IAAA;AAAA,EAClB,WAAA,EAAa;AACf,CAAA;AAKA,IAAM,+BAAe,IAAI,GAAA,CAAY,CAAC,cAAA,EAAgB,OAAA,EAAS,WAAW,CAAC,CAAA;AAI3E,IAAM,uBAAA,GAA0B,GAAA;AAEhC,IAAM,iBAAA,GAAoB,IAAA;AAC1B,IAAM,UAAA,GAAa,IAAA;AAcZ,SAAS,IAAA,CACd,QAAA,EACA,OAAA,GAAuB,EAAC,EACR;AAChB,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,IAAW,EAAC;AACpC,EAAA,MAAM,UAAA,GAAa,iBAAA,CAAkB,QAAA,EAAU,OAAA,CAAQ,UAAU,CAAA;AASjE,EAAA,MAAM,OAAA,GACJ,QAAQ,uBAAA,KAA4B,SAAA,GAChC,qBAAqB,UAAA,EAAY,OAAA,CAAQ,UAAU,CAAA,GACnD,UAAA;AAEN,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAoB;AACvC,EAAA,KAAA,MAAW,QAAQ,OAAA,EAAS;AAC1B,IAAA,IAAI,IAAA,CAAK,aAAa,SAAA,EAAW;AACjC,IAAA,MAAM,MAAA,GACJ,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAA,IAAK,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAA,IAAK,mBAAA,CAAoB,IAAA,CAAK,IAAI,CAAA,IAAK,GAAA;AAClF,IAAA,MAAA,CAAO,GAAA,CAAI,IAAA,CAAK,QAAA,EAAA,CAAW,MAAA,CAAO,GAAA,CAAI,IAAA,CAAK,QAAQ,CAAA,IAAK,CAAA,IAAK,OAAA,CAAQ,IAAA,CAAK,UAAU,IAAI,MAAM,CAAA;AAAA,EAChG;AAGA,EAAA,MAAM,MAAA,GAAS,wBAAwB,OAAO,CAAA;AAE9C,EAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAW,aAAY,GAAI,MAAA,CAAO,QAAQ,MAAM,CAAA;AAE9D,EAAA,IAAI,SAAS,IAAA,IAAQ,SAAA,GAAY,iBAAA,IAAqB,SAAA,GAAY,cAAc,UAAA,EAAY;AAG1F,IAAA,IAAI,MAAA,KAAW,IAAA,IAAQ,MAAA,CAAO,GAAA,CAAI,MAAM,CAAA,EAAG;AACzC,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,GAAA,CAAI,MAAM,CAAA,IAAK,CAAA;AACpC,MAAA,OAAO;AAAA,QACL,QAAA,EAAU,MAAA;AAAA,QACV,UAAA,EAAY,OAAA,CAAQ,KAAA,IAAS,KAAA,GAAQ,IAAA,CAAK,CAAA;AAAA,QAC1C,QAAA,EAAU,CAAC,GAAG,UAAU;AAAA,OAC1B;AAAA,IACF;AACA,IAAA,OAAO,EAAE,QAAA,EAAU,SAAA,EAAW,UAAA,EAAY,OAAA,CAAQ,SAAS,CAAA,EAAG,QAAA,EAAU,CAAC,GAAG,UAAU,CAAA,EAAE;AAAA,EAC1F;AAEA,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,IAAA;AAAA,IACV,UAAA,EAAY,OAAA,CAAQ,SAAA,IAAa,SAAA,GAAY,cAAc,IAAA,CAAK,CAAA;AAAA,IAChE,QAAA,EAAU,CAAC,GAAG,UAAU;AAAA,GAC1B;AACF;AAYA,SAAS,iBAAA,CACP,UACA,WAAA,EACoB;AACpB,EAAA,OAAO,QAAA,CAAS,GAAA,CAAI,CAAC,IAAA,KAAS;AAC5B,IAAA,IAAI,IAAA,CAAK,QAAA,KAAa,SAAA,EAAW,OAAO,IAAA;AACxC,IAAA,MAAM,UAAA,GAAa,cAAA,CAAe,IAAA,CAAK,QAAQ,KAAK,IAAA,CAAK,QAAA;AACzD,IAAA,IAAI,UAAA,KAAe,IAAA,CAAK,QAAA,EAAU,OAAO,IAAA;AACzC,IAAA,OAAO,EAAE,GAAG,IAAA,EAAM,QAAA,EAAU,UAAA,EAAW;AAAA,EACzC,CAAC,CAAA;AACH;AAoBA,SAAS,oBAAA,CACP,YACA,UAAA,EACoB;AACpB,EAAA,MAAM,SAAA,GAAY,WAAW,MAAA,CAAO,CAAC,SAAS,CAAC,aAAA,CAAc,IAAA,EAAM,UAAU,CAAC,CAAA;AAE9E,EAAA,MAAM,WAAA,GAAc,4BAAA,CAA6B,UAAA,EAAY,UAAU,CAAA;AACvE,EAAA,IAAI,WAAA,KAAgB,MAAM,OAAO,SAAA;AAEjC,EAAA,MAAM,QAAA,GAAW,YAAA,CAAa,UAAA,IAAc,EAAE,CAAA;AAC9C,EAAA,OAAO,SAAA,CAAU,MAAA,CAAO,CAAC,IAAA,KAAS;AAGhC,IAAA,IAAI,YAAA,CAAa,IAAI,IAAA,CAAK,IAAI,KAAK,IAAA,CAAK,QAAA,KAAa,WAAW,OAAO,IAAA;AACvE,IAAA,MAAM,UAAA,GAAa,QAAA,CAAS,GAAA,CAAI,IAAA,CAAK,QAAQ,CAAA;AAC7C,IAAA,OAAO,UAAA,KAAe,UAAa,UAAA,KAAe,WAAA;AAAA,EACpD,CAAC,CAAA;AACH;AAKA,SAAS,4BAAA,CACP,YACA,UAAA,EACmB;AACnB,EAAA,IAAI,UAAA,KAAe,QAAW,OAAO,IAAA;AACrC,EAAA,MAAM,QAAA,GAAW,aAAa,UAAU,CAAA;AACxC,EAAA,KAAA,MAAW,QAAQ,UAAA,EAAY;AAC7B,IAAA,IAAI,aAAA,CAAc,IAAA,EAAM,UAAU,CAAA,EAAG;AACnC,MAAA,MAAM,MAAA,GAAS,QAAA,CAAS,GAAA,CAAI,IAAA,CAAK,QAAQ,CAAA;AACzC,MAAA,IAAI,MAAA,KAAW,QAAW,OAAO,MAAA;AAAA,IACnC;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAIA,SAAS,aAAa,UAAA,EAAiE;AACrF,EAAA,MAAM,GAAA,uBAAU,GAAA,EAAwB;AACxC,EAAA,KAAA,MAAW,KAAK,UAAA,EAAY;AAC1B,IAAA,MAAM,MAAA,GAAS,gBAAgB,CAAC,CAAA;AAChC,IAAA,IAAI,WAAW,IAAA,EAAM,GAAA,CAAI,GAAA,CAAI,CAAA,CAAE,MAAM,MAAM,CAAA;AAAA,EAC7C;AACA,EAAA,OAAO,GAAA;AACT;AAUA,SAAS,aAAA,CAAc,MAAwB,GAAA,EAA2C;AACxF,EAAA,IAAI,IAAA,CAAK,mBAAmB,KAAA,IAAS,CAAC,aAAa,GAAA,CAAI,IAAA,CAAK,IAAI,CAAA,EAAG,OAAO,KAAA;AAC1E,EAAA,OAAO,CAAC,GAAA,CAAI,IAAA;AAAA,IACV,CAAC,KAAA,KACC,KAAA,CAAM,QAAA,KAAa,IAAA,CAAK,QAAA,IACxB,KAAA,CAAM,QAAA,KAAa,SAAA,IACnB,CAAC,YAAA,CAAa,GAAA,CAAI,MAAM,IAAI;AAAA,GAChC;AACF;AAKA,SAAS,wBAAwB,QAAA,EAAsD;AACrF,EAAA,IAAI,IAAA,GAAsB,IAAA;AAC1B,EAAA,IAAI,cAAA,GAAiB,CAAA;AACrB,EAAA,KAAA,MAAW,QAAQ,QAAA,EAAU;AAC3B,IAAA,IAAI,IAAA,CAAK,aAAa,SAAA,IAAa,CAAC,aAAa,GAAA,CAAI,IAAA,CAAK,IAAI,CAAA,EAAG;AACjE,IAAA,MAAM,CAAA,GAAI,OAAA,CAAQ,IAAA,CAAK,UAAU,CAAA;AACjC,IAAA,IAAI,IAAI,uBAAA,EAAyB;AACjC,IAAA,IAAI,IAAI,cAAA,EAAgB;AACtB,MAAA,cAAA,GAAiB,CAAA;AACjB,MAAA,IAAA,GAAO,IAAA,CAAK,QAAA;AAAA,IACd,CAAA,MAAA,IAAW,CAAA,KAAM,cAAA,IAAkB,IAAA,CAAK,aAAa,IAAA,EAAM;AAEzD,MAAA,IAAA,GAAO,IAAA;AAAA,IACT;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAQA,SAAS,MAAA,CACP,QACA,MAAA,EACiE;AACjE,EAAA,IAAI,IAAA,GAAsB,IAAA;AAC1B,EAAA,IAAI,SAAA,GAAY,CAAA;AAChB,EAAA,IAAI,WAAA,GAAc,CAAA;AAClB,EAAA,MAAM,cAAc,MAAA,KAAW,IAAA,GAAQ,OAAO,GAAA,CAAI,MAAM,KAAK,CAAA,GAAK,CAAA;AAElE,EAAA,KAAA,MAAW,CAAC,QAAA,EAAU,GAAG,CAAA,IAAK,MAAA,EAAQ;AAEpC,IAAA,MAAM,KAAA,GAAQ,WAAW,IAAA,IAAQ,QAAA,KAAa,SAAS,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,WAAW,CAAA,GAAI,GAAA;AACpF,IAAA,IAAI,QAAQ,SAAA,EAAW;AACrB,MAAA,WAAA,GAAc,SAAA;AACd,MAAA,SAAA,GAAY,KAAA;AACZ,MAAA,IAAA,GAAO,QAAA;AAAA,IACT,CAAA,MAAA,IAAW,QAAQ,WAAA,EAAa;AAC9B,MAAA,WAAA,GAAc,KAAA;AAAA,IAChB;AAAA,EACF;AAEA,EAAA,IAAI,WAAW,IAAA,IAAQ,IAAA,KAAS,UAAU,SAAA,KAAc,WAAA,IAAe,cAAc,CAAA,EAAG;AACtF,IAAA,WAAA,GAAc,SAAA;AACd,IAAA,IAAA,GAAO,MAAA;AACP,IAAA,SAAA,GAAY,WAAA;AAAA,EACd;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,WAAA,EAAY;AACxC;AAEA,SAAS,QAAQ,KAAA,EAAuB;AACtC,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,GAAG,OAAO,CAAA;AACpC,EAAA,IAAI,KAAA,GAAQ,GAAG,OAAO,CAAA;AACtB,EAAA,IAAI,KAAA,GAAQ,GAAG,OAAO,CAAA;AACtB,EAAA,OAAO,KAAA;AACT","file":"chunk-G44HHVK5.js","sourcesContent":["import type {\n Classification,\n LanguageEvidence,\n LanguageProfile,\n NonDiscriminatingScript,\n Weights,\n} from \"./types.js\";\nimport { normalizeBCP47 } from \"./internal/bcp47.js\";\nimport { scriptOfProfile, type ScriptName } from \"./internal/classify.js\";\n\nexport interface FuseOptions {\n weights?: Weights;\n /** The candidate roster. When present, incoming evidence tags are normalized\n * into it (`uk-UA` → `uk`, `ua` → `uk`) so context signals (page/header\n * locale) land on the same code the text rungs use. */\n candidates?: readonly LanguageProfile[];\n /** How to resolve a *non-discriminating* script read (one flagged\n * `discriminating: false` — its winning script owned by ≤1 roster candidate).\n * Default `\"candidate\"` keeps current behavior; `\"unknown\"` drops such a read\n * unless non-script evidence corroborates the same language. See\n * {@link NonDiscriminatingScript}. */\n nonDiscriminatingScript?: NonDiscriminatingScript;\n}\n\n/** Default per-kind weights. Clear lexical signal (script, explicit locale)\n * outweighs contextual signal (page tags, headers). Callers override per\n * `source` id or `kind` via {@link FuseOptions.weights}. */\nconst DEFAULT_KIND_WEIGHT: Record<string, number> = {\n \"title-script\": 1,\n \"explicit-locale\": 1,\n \"chrome-ai\": 1,\n \"source-prior\": 0.7,\n franc: 0.7,\n \"http-content-language\": 0.6,\n \"meta-content-language\": 0.55,\n \"meta-og-locale\": 0.55,\n \"html-lang\": 0.5,\n};\n\n/** Evidence kinds that constitute *clear script evidence* — a verdict the text\n * classifier or an on-device model reached by actually reading the string. The\n * guard below forbids weaker page/header *context* from flipping these. */\nconst SCRIPT_KINDS = new Set<string>([\"title-script\", \"franc\", \"chrome-ai\"]);\n\n/** A script verdict this confident is treated as settled — context may add to it\n * but must not flip the winner to a different language. */\nconst SCRIPT_CONFIDENCE_FLOOR = 0.6;\n\nconst MIN_WINNING_SCORE = 0.35;\nconst MIN_MARGIN = 0.12;\n\n/**\n * Combine evidence into a single weighted verdict with an audit trail.\n *\n * Three steps:\n * 1. Normalize each item's language tag into the candidate roster (BCP-47:\n * `uk-UA`/`ua` → `uk`) so text, page, and header signals agree on a code.\n * 2. Weighted argmax over languages (caller weights override per `source`/`kind`).\n * 3. Apply the guard **context must never override clear script evidence**: when\n * the text classifier (or an on-device model) confidently read one language,\n * weaker page/header context for a *different* language cannot win — a\n * Ukrainian page chrome does not make a Latin/English title Ukrainian.\n */\nexport function fuse(\n evidence: readonly LanguageEvidence[],\n options: FuseOptions = {},\n): Classification {\n const weights = options.weights ?? {};\n const normalized = normalizeEvidence(evidence, options.candidates);\n\n // Under `\"unknown\"`, a non-discriminating script read scores nothing on its own\n // — it's dropped from the tally and the pin below — but stays in the trail. AND\n // context written in a *different script* than that title is dropped too: a\n // foreign-script title's language is never named by page/transport context in\n // another script (a Latin title on a Ukrainian page is a foreign title in a\n // Ukrainian UI, not a Ukrainian title). The full `normalized` set is still\n // returned as evidence.\n const scoring =\n options.nonDiscriminatingScript === \"unknown\"\n ? filterForUnknownMode(normalized, options.candidates)\n : normalized;\n\n const scores = new Map<string, number>();\n for (const item of scoring) {\n if (item.language === \"unknown\") continue;\n const weight =\n weights[item.source] ?? weights[item.kind] ?? DEFAULT_KIND_WEIGHT[item.kind] ?? 0.5;\n scores.set(item.language, (scores.get(item.language) ?? 0) + clamp01(item.confidence) * weight);\n }\n\n // The context-vs-script guard: a confident script read pins the winner.\n const pinned = confidentScriptLanguage(scoring);\n\n const { best, bestScore, secondScore } = argmax(scores, pinned);\n\n if (best === null || bestScore < MIN_WINNING_SCORE || bestScore - secondScore < MIN_MARGIN) {\n // A pinned script language still wins even on a thin margin — clear script\n // evidence is never demoted to \"unknown\" by competing context.\n if (pinned !== null && scores.has(pinned)) {\n const score = scores.get(pinned) ?? 0;\n return {\n language: pinned,\n confidence: clamp01(score / (score + 0.15)),\n evidence: [...normalized],\n };\n }\n return { language: \"unknown\", confidence: clamp01(bestScore), evidence: [...normalized] };\n }\n\n return {\n language: best,\n confidence: clamp01(bestScore / (bestScore + secondScore + 0.15)),\n evidence: [...normalized],\n };\n}\n\n/** Normalize each item's tag into the roster's code space (BCP-47-aware). Items\n * already `\"unknown\"` pass through untouched. Tags are BCP-47-normalized\n * (`en-US` → `en`, `ua` → `uk`) so text, page, and header signals land on the\n * same code. The normalized code is kept even when it falls outside the roster —\n * argmax simply won't favor an out-of-roster context tag, but it stays in the\n * audit trail.\n *\n * The roster is accepted (and reserved) so a future revision can fold roster\n * aliasing in without a signature change; today BCP-47 normalization alone\n * reconciles the codes the producers emit. */\nfunction normalizeEvidence(\n evidence: readonly LanguageEvidence[],\n _candidates: readonly LanguageProfile[] | undefined,\n): LanguageEvidence[] {\n return evidence.map((item) => {\n if (item.language === \"unknown\") return item;\n const normalized = normalizeBCP47(item.language) ?? item.language;\n if (normalized === item.language) return item;\n return { ...item, language: normalized };\n });\n}\n\n/**\n * The scoring set under `nonDiscriminatingScript: \"unknown\"`. Two cuts:\n *\n * 1. Drop every *neutralized* non-discriminating script read (see\n * {@link isNeutralized}) — it names a language only by being the lone\n * candidate in its script, with nothing corroborating it.\n * 2. Drop context (page/transport) evidence whose language is in a **different\n * script** than such a neutralized title. A foreign-script title's language\n * is not the page's language: a Latin title on a `lang=\"uk\"` page must not\n * resolve to `uk`. Same-script context (an explicit `en` `Content-Language`\n * for a Latin title) survives and may still name — or, among same-script\n * candidates, disambiguate — the title.\n *\n * The second cut needs each language's script, which is derived from the\n * candidate roster's alphabets. When `candidates` is absent the scripts can't be\n * derived, so the cut is skipped and behavior falls back to cut 1 alone (the\n * 0.3.0 behavior) — never throwing.\n */\nfunction filterForUnknownMode(\n normalized: readonly LanguageEvidence[],\n candidates: readonly LanguageProfile[] | undefined,\n): LanguageEvidence[] {\n const surviving = normalized.filter((item) => !isNeutralized(item, normalized));\n\n const titleScript = nonDiscriminatingTitleScript(normalized, candidates);\n if (titleScript === null) return surviving;\n\n const scriptOf = scriptByCode(candidates ?? []);\n return surviving.filter((item) => {\n // Keep the script reads themselves and anything whose script we can't place;\n // only cross-script *context* in a known, different script is excluded.\n if (SCRIPT_KINDS.has(item.kind) || item.language === \"unknown\") return true;\n const itemScript = scriptOf.get(item.language);\n return itemScript === undefined || itemScript === titleScript;\n });\n}\n\n/** The script of the title under `\"unknown\"` mode, or `null` when there is no\n * neutralized non-discriminating script read to anchor on (so no cross-script\n * cut applies) or the roster can't place that read's language. */\nfunction nonDiscriminatingTitleScript(\n normalized: readonly LanguageEvidence[],\n candidates: readonly LanguageProfile[] | undefined,\n): ScriptName | null {\n if (candidates === undefined) return null;\n const scriptOf = scriptByCode(candidates);\n for (const item of normalized) {\n if (isNeutralized(item, normalized)) {\n const script = scriptOf.get(item.language);\n if (script !== undefined) return script;\n }\n }\n return null;\n}\n\n/** Map each roster code to the script of its alphabet (Cyrillic/Latin). Codes\n * whose alphabet carries no Cyrillic/Latin letter are omitted. */\nfunction scriptByCode(candidates: readonly LanguageProfile[]): Map<string, ScriptName> {\n const map = new Map<string, ScriptName>();\n for (const c of candidates) {\n const script = scriptOfProfile(c);\n if (script !== null) map.set(c.code, script);\n }\n return map;\n}\n\n/**\n * Whether a non-discriminating script read should score nothing (mode\n * `\"unknown\"`). True when `item` is a script kind flagged `discriminating:\n * false` (its winning script is owned by ≤1 roster candidate) AND no *non-script*\n * evidence corroborates its language. Corroboration must come from context kinds\n * (page tags, headers): two lone-candidate script reads agreeing is still two\n * defaults, not real evidence — so script kinds never corroborate one another.\n */\nfunction isNeutralized(item: LanguageEvidence, all: readonly LanguageEvidence[]): boolean {\n if (item.discriminating !== false || !SCRIPT_KINDS.has(item.kind)) return false;\n return !all.some(\n (other) =>\n other.language === item.language &&\n other.language !== \"unknown\" &&\n !SCRIPT_KINDS.has(other.kind),\n );\n}\n\n/** The language of a *clear script* read confident enough to pin the verdict, or\n * `null` when none qualifies. When two script reads disagree, the higher-\n * confidence one pins (a tie leaves nothing pinned — argmax decides normally). */\nfunction confidentScriptLanguage(evidence: readonly LanguageEvidence[]): string | null {\n let best: string | null = null;\n let bestConfidence = 0;\n for (const item of evidence) {\n if (item.language === \"unknown\" || !SCRIPT_KINDS.has(item.kind)) continue;\n const c = clamp01(item.confidence);\n if (c < SCRIPT_CONFIDENCE_FLOOR) continue;\n if (c > bestConfidence) {\n bestConfidence = c;\n best = item.language;\n } else if (c === bestConfidence && item.language !== best) {\n // Two equally-confident script reads for different languages — ambiguous.\n best = null;\n }\n }\n return best;\n}\n\n/**\n * Weighted argmax. When `pinned` is set (a confident script language), any\n * *other* language's score may only come from context kinds; that score is\n * capped so it can never exceed the pinned language. This enforces the guard\n * without discarding the context from the audit trail.\n */\nfunction argmax(\n scores: Map<string, number>,\n pinned: string | null,\n): { best: string | null; bestScore: number; secondScore: number } {\n let best: string | null = null;\n let bestScore = 0;\n let secondScore = 0;\n const pinnedScore = pinned !== null ? (scores.get(pinned) ?? 0) : 0;\n\n for (const [language, raw] of scores) {\n // Guard: a non-pinned language cannot out-score the pinned one.\n const score = pinned !== null && language !== pinned ? Math.min(raw, pinnedScore) : raw;\n if (score > bestScore) {\n secondScore = bestScore;\n bestScore = score;\n best = language;\n } else if (score > secondScore) {\n secondScore = score;\n }\n }\n // On a pinned tie (pinned capped equal to a context language), prefer pinned.\n if (pinned !== null && best !== pinned && bestScore === pinnedScore && pinnedScore > 0) {\n secondScore = bestScore;\n best = pinned;\n bestScore = pinnedScore;\n }\n return { best, bestScore, secondScore };\n}\n\nfunction clamp01(value: number): number {\n if (!Number.isFinite(value)) return 0;\n if (value < 0) return 0;\n if (value > 1) return 1;\n return value;\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/bcp47.ts"],"names":[],"mappings":"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","file":"chunk-OVSPOZ5J.js","sourcesContent":["/**\n * BCP-47 / language-code normalization.\n *\n * Two entry points with deliberately different strictness:\n * - {@link normalizeBCP47} — for inputs documented to be BCP-47 (`<html lang>`,\n * hreflang, `Content-Language`): try the full string, then strip a\n * region/script suffix (`en-US` → `en`, `zh_CN` → `zh`).\n * - {@link normalizeLanguageCode} — strict exact-match only, for free-text\n * contexts (URL slugs, link text) where a hyphen split could be a coincidence.\n *\n * Both resolve aliases that appear in the wild (`ua` → `uk`, `rus` → `ru`,\n * localized picker phrases) to a canonical ISO 639-1 code.\n */\n\n/**\n * Aliases mapped to canonical ISO 639-1 codes. Keys are lowercased.\n *\n * Ukrainian is the load-bearing case: most sites use `ua` in URLs even though\n * the ISO code is `uk`. Both are accepted on input; `uk` is always output.\n *\n * Includes localized phrases users see in language pickers (`українською`,\n * `по-русски`, `in english`, …).\n */\nconst ALIASES: Record<string, string> = {\n // Ukrainian\n ua: \"uk\",\n uk: \"uk\",\n укр: \"uk\",\n українська: \"uk\",\n українською: \"uk\",\n \"українська мова\": \"uk\",\n \"на українській\": \"uk\",\n \"українською мовою\": \"uk\",\n ukrainian: \"uk\",\n \"in ukrainian\": \"uk\",\n\n // Russian\n ru: \"ru\",\n rus: \"ru\",\n рус: \"ru\",\n русский: \"ru\",\n \"по-русски\": \"ru\",\n \"по русски\": \"ru\",\n \"русский язык\": \"ru\",\n \"на русском\": \"ru\",\n russian: \"ru\",\n \"in russian\": \"ru\",\n російська: \"ru\",\n \"російська мова\": \"ru\",\n \"по-російськи\": \"ru\",\n \"по російськи\": \"ru\",\n\n // Belarusian\n be: \"be\",\n bel: \"be\",\n беларуская: \"be\",\n \"беларуская мова\": \"be\",\n belarusian: \"be\",\n \"in belarusian\": \"be\",\n\n // Bulgarian\n bg: \"bg\",\n bul: \"bg\",\n български: \"bg\",\n \"български език\": \"bg\",\n bulgarian: \"bg\",\n \"in bulgarian\": \"bg\",\n\n // English\n en: \"en\",\n eng: \"en\",\n english: \"en\",\n \"in english\": \"en\",\n англійська: \"en\",\n английский: \"en\",\n\n // Polish\n pl: \"pl\",\n pol: \"pl\",\n polski: \"pl\",\n \"po polsku\": \"pl\",\n polish: \"pl\",\n польська: \"pl\",\n\n // German\n de: \"de\",\n deu: \"de\",\n ger: \"de\",\n deutsch: \"de\",\n \"auf deutsch\": \"de\",\n german: \"de\",\n німецька: \"de\",\n\n // French\n fr: \"fr\",\n fra: \"fr\",\n français: \"fr\",\n francais: \"fr\",\n \"en français\": \"fr\",\n french: \"fr\",\n французька: \"fr\",\n\n // Spanish\n es: \"es\",\n spa: \"es\",\n español: \"es\",\n espanol: \"es\",\n \"en español\": \"es\",\n spanish: \"es\",\n іспанська: \"es\",\n\n // Italian\n it: \"it\",\n ita: \"it\",\n italiano: \"it\",\n \"in italiano\": \"it\",\n italian: \"it\",\n італійська: \"it\",\n};\n\n/**\n * Strict, exact-match lookup. Returns `null` for unknown inputs and does NOT\n * fall back to a hyphen prefix. Use anywhere a hyphen split could be a\n * coincidence — URL path segments (`/ru-return-warranty`), title attrs, link\n * text. The phrase aliases (`по-русски`, `in english`) are in the table\n * directly, so exact lookup still finds them.\n */\nexport function normalizeLanguageCode(input: string | undefined | null): string | null {\n if (input === undefined || input === null) return null;\n const cleaned = input.trim().toLowerCase();\n if (cleaned.length === 0) return null;\n return ALIASES[cleaned] ?? null;\n}\n\n/**\n * BCP-47-aware normalization: try the full string first, then strip a\n * region/script suffix (`en-US` → `en`, `zh_CN` → `zh`). Use ONLY for inputs\n * documented to be BCP-47 — `hreflang`, `<html lang>`, `Content-Language`,\n * `data-lang`/`data-locale` — never for free-text URL slugs.\n *\n * Falls back to the raw primary subtag when no alias matches, so a code outside\n * the alias table (e.g. `pt-BR` → `pt`) still resolves to its language. The\n * roster decides relevance downstream.\n */\nexport function normalizeBCP47(input: string | undefined | null): string | null {\n if (input === undefined || input === null) return null;\n const cleaned = input.trim().toLowerCase().replace(/_/g, \"-\");\n if (cleaned.length === 0) return null;\n const direct = ALIASES[cleaned];\n if (direct !== undefined) return direct;\n const head = cleaned.split(\"-\")[0];\n if (head === undefined || head.length === 0) return null;\n return ALIASES[head] ?? head;\n}\n\n/**\n * Extract the primary subtag from a BCP-47-ish value, lowercased, then resolve\n * it through the alias table (`ua` → `uk`). Handles `Accept-Language`-style\n * comma lists (`en-US,en;q=0.9` → `en`). Returns `null` for empty/nullish.\n *\n * This is the header/HTML extraction helper: it tolerates the messy shapes those\n * sources carry (comma lists, `q` weights) where {@link normalizeBCP47} expects\n * a single tag.\n */\nexport function primarySubtag(value: string | undefined | null): string | null {\n if (value === undefined || value === null) return null;\n const first = value.split(\",\")[0]?.trim();\n if (first === undefined || first.length === 0) return null;\n // Drop a `;q=…` weight if present.\n const tag = first.split(\";\")[0]?.trim();\n return normalizeBCP47(tag);\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/classify.ts"],"names":[],"mappings":"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","file":"chunk-U34Z3ZSV.js","sourcesContent":["/**\n * Per-snippet language classification by candidate-set-relative set-difference.\n *\n * A ladder of rungs; the first rung whose leader clears a lead (margin) of ≥1\n * wins; otherwise `\"unknown\"`:\n *\n * 1 alphabet — characters distinctive within the candidate set\n * 2a function words — curated grammatical markers (highest precision)\n * 2b frequent words — corpus content words\n * 3 franc — optional trigram backstop for the distinctive-free\n * residual, injected as a resolver (this module stays\n * franc-free and importable without franc's tables)\n *\n * \"Distinctive\" is ALWAYS relative to the candidate set: a signal counts for a\n * candidate iff it appears in that candidate's profile and in NO other\n * candidate's. So `і` decides {uk, ru} (only uk has it) but is inert in\n * {uk, be} (both have it), and the word `и` decides {uk, ru} even though the\n * *letter* `и` is shared. Nothing is precomputed — uniqueness is the runtime\n * output, never stored.\n *\n * Adapted to langtell's {@link LanguageProfile} shape: the `words` and `iso6393`\n * fields are optional here, so a bare `{ code, alphabet }` profile still\n * classifies on rung 1.\n */\nimport type { LanguageProfile } from \"../types.js\";\n\nexport const FRANC_RUNG = 3;\n\n/** Which rung decided a verdict; `null` when unknown. */\nexport type Rung = 1 | \"2a\" | \"2b\" | typeof FRANC_RUNG | null;\n\nexport interface SnippetVerdict {\n /** Winning language code, or the sentinel `\"unknown\"`. */\n language: string;\n /** Lead of the winner over the runner-up, in the rung's own unit (distinctive\n * char/word count for rungs 1–2; franc score-gap for rung 3). 0 when unknown. */\n margin: number;\n /** Which rung decided; `null` when unknown. */\n rung: Rung;\n /** Whether ≥2 same-script candidates were in scope when the verdict was\n * reached. `true` ⇒ the distinctive-letter/word machinery actually chose\n * between candidates; `false` ⇒ the winner was the lone candidate in its\n * script, selected by script alone (no evidence it is *distinctively* that\n * language). `false` for `\"unknown\"`. */\n discriminating: boolean;\n}\n\n/** A rung's verdict before {@link classifyBySnippet} stamps on the scope-derived\n * `discriminating` flag (which a single rung can't know — it depends on how many\n * same-script candidates were scoped). */\nexport type RungVerdict = Pick<SnippetVerdict, \"language\" | \"margin\" | \"rung\">;\n\nconst UNKNOWN: SnippetVerdict = {\n language: \"unknown\",\n margin: 0,\n rung: null,\n discriminating: false,\n};\n\n/** Resolver for rung 3 (the optional trigram backstop), injected into\n * {@link classifyBySnippet} by callers that have franc available. Kept as an\n * injected seam — not a direct import — so this module stays franc-free and\n * importable without pulling franc's tables. Returns a rung-3 verdict or\n * `null` (abstain).\n *\n * Generic over the concrete profile type `P` the caller classifies with, so a\n * consumer that defines a stricter profile (e.g. `words` required) can type its\n * resolver over that exact shape and hand it to {@link classifyBySnippet} with\n * no adapter — the resolver sees `readonly P[]`, the same array the classifier\n * scoped from its input. Defaults to {@link LanguageProfile} for callers that\n * don't narrow. */\nexport type Rung3Resolver<P extends LanguageProfile = LanguageProfile> = (\n text: string,\n scoped: readonly P[],\n) => RungVerdict | null;\n\nconst CYRILLIC_RE = /\\p{Script=Cyrillic}/u;\nconst LATIN_RE = /\\p{Script=Latin}/u;\n\n/** A coarse script bucket — the only two the candidate-relative classifier\n * distinguishes today. `null` means \"no letters / undetermined\". */\nexport type ScriptName = \"cyrillic\" | \"latin\";\n\n/** Below this length, trigrams are too noisy to justify a rung-3 verdict. */\nexport const RUNG3_MIN_LENGTH = 24;\n\n/**\n * Trailing/inline Latin \"noise\" tokens — URLs, @handles, #hashtags — that a\n * Cyrillic title commonly carries (a headline followed by a link or a social\n * handle). These are almost always Latin even on Cyrillic-language content, so\n * left in they can flip {@link dominantScript} to Latin and let genuinely\n * Cyrillic content scope to the wrong roster. Stripped before the script vote\n * AND before the rung tallies so the URL's letters never contribute either.\n *\n * Kept as separate simple patterns (applied in order — schemes/www before bare\n * domains) rather than one big alternation, so each stays readable. ASCII-only\n * `[a-z0-9-]` in the domain pattern means a Cyrillic word is never mistaken for\n * a domain.\n */\nconst NOISE_PATTERNS: readonly RegExp[] = [\n /\\bhttps?:\\/\\/\\S+/gi, // full URLs\n /\\bwww\\.\\S+/gi, // www.… without a scheme\n /\\b[a-z0-9-]+(?:\\.[a-z0-9-]+)+(?:\\/\\S*)?/gi, // bare domains (example.com/path)\n /[@#][\\p{L}\\p{N}_]+/gu, // @handles and #hashtags\n];\n\n/** Drop URLs / @handles / #hashtags so trailing Latin noise can't outvote the\n * prose's script or pollute the per-rung tallies. */\nexport function stripNoise(text: string): string {\n let out = text;\n for (const re of NOISE_PATTERNS) out = out.replace(re, \" \");\n return out;\n}\n\n/** The script most of `text` is written in, or `null` if it carries no letters.\n * Noise (URLs/handles/hashtags) is stripped first so a single trailing link\n * can't flip a multi-word Cyrillic title's vote to Latin. */\nfunction dominantScript(text: string): \"cyrillic\" | \"latin\" | null {\n let cyr = 0;\n let lat = 0;\n for (const ch of stripNoise(text)) {\n if (CYRILLIC_RE.test(ch)) cyr += 1;\n else if (LATIN_RE.test(ch)) lat += 1;\n }\n if (cyr === 0 && lat === 0) return null;\n return cyr >= lat ? \"cyrillic\" : \"latin\";\n}\n\n/** The script a profile's alphabet is written in, or `null` if it carries no\n * Cyrillic/Latin letter. Exported so the fuser can derive each roster\n * candidate's script without re-deriving the script regexes — a Latin alphabet\n * ⇒ `\"latin\"`, a Cyrillic one ⇒ `\"cyrillic\"`. */\nexport function scriptOfProfile(profile: LanguageProfile): ScriptName | null {\n for (const ch of profile.alphabet) {\n if (CYRILLIC_RE.test(ch)) return \"cyrillic\";\n if (LATIN_RE.test(ch)) return \"latin\";\n }\n return null;\n}\n\n/** Candidates whose script matches the text's dominant script (others can't tip\n * the verdict). Empty when the text carries no letters. Generic over the\n * concrete profile type `P`: the result is a subset of the input array, so it\n * keeps `P` — a stricter caller's profiles stay strictly typed downstream. */\nexport function scopeCandidates<P extends LanguageProfile>(\n text: string,\n candidates: readonly P[],\n): P[] {\n const script = dominantScript(text);\n if (script === null) return [];\n // Keep one profile per code. A language listed twice would otherwise make its\n // own distinctive chars/words read as \"owned by ≥2 candidates\" in `tally`,\n // cancelling them out and collapsing the verdict to \"unknown\".\n const seen = new Set<string>();\n const scoped: P[] = [];\n for (const c of candidates) {\n if (scriptOfProfile(c) !== script || seen.has(c.code)) continue;\n seen.add(c.code);\n scoped.push(c);\n }\n return scoped;\n}\n\n/**\n * Per-language set of characters globally unique within `profiles` — present in\n * exactly one profile's alphabet. Relative to the given profile set: the unique\n * set shrinks as languages are added (a second Latin language un-uniques a–z).\n */\nexport function distinctiveChars(profiles: readonly LanguageProfile[]): Map<string, Set<string>> {\n const owners = new Map<string, string[]>();\n for (const p of profiles) {\n for (const ch of new Set(p.alphabet)) {\n const list = owners.get(ch);\n if (list) list.push(p.code);\n else owners.set(ch, [p.code]);\n }\n }\n const result = new Map<string, Set<string>>(profiles.map((p) => [p.code, new Set()]));\n for (const [ch, codes] of owners) {\n const [only] = codes;\n if (codes.length === 1 && only !== undefined) result.get(only)?.add(ch);\n }\n return result;\n}\n\ninterface Membership {\n code: string;\n set: ReadonlySet<string>;\n}\n\n/** Lowercased Unicode letter-run tokens. Keeps single-char tokens (`і`, `и`). */\nfunction tokenize(text: string): string[] {\n return text.toLowerCase().match(/\\p{L}+/gu) ?? [];\n}\n\n/**\n * Tally how many items (characters or word tokens) are distinctive to each\n * candidate — present in exactly one candidate's set. Items owned by zero or by\n * ≥2 candidates contribute nothing.\n */\nfunction tally(items: Iterable<string>, membership: readonly Membership[]): Map<string, number> {\n const scores = new Map<string, number>(membership.map((m) => [m.code, 0]));\n for (const item of items) {\n let owner: string | null = null;\n let owners = 0;\n for (const m of membership) {\n if (m.set.has(item)) {\n owners += 1;\n if (owners > 1) {\n owner = null;\n break;\n }\n owner = m.code;\n }\n }\n if (owner !== null) scores.set(owner, (scores.get(owner) ?? 0) + 1);\n }\n return scores;\n}\n\n/** The leading candidate and its lead over the runner-up, or `null` if <1. */\nfunction leader(scores: Map<string, number>): { code: string; margin: number } | null {\n let max = -1;\n let second = -1;\n let code: string | null = null;\n for (const [c, score] of scores) {\n if (score > max) {\n second = max;\n max = score;\n code = c;\n } else if (score > second) {\n second = score;\n }\n }\n if (code === null || max < 1) return null;\n const margin = max - Math.max(second, 0);\n return margin >= 1 ? { code, margin } : null;\n}\n\nfunction membershipFor(\n candidates: readonly LanguageProfile[],\n pick: (p: LanguageProfile) => Iterable<string>,\n): Membership[] {\n return candidates.map((c) => ({ code: c.code, set: new Set(pick(c)) }));\n}\n\n/** Rung 1 — characters (alphabet + orthographic {@link LanguageProfile.marks})\n * distinctive within the scoped candidate set. */\nfunction letterRung(text: string, scoped: readonly LanguageProfile[]): RungVerdict | null {\n const r = leader(\n tally(\n text.toLowerCase(),\n membershipFor(scoped, (p) => p.alphabet + (p.marks ?? \"\")),\n ),\n );\n return r ? { language: r.code, margin: r.margin, rung: 1 } : null;\n}\n\n/** Rung 2 — distinctive words from the given tier (2a function, 2b frequent). */\nfunction wordRung(\n tokens: readonly string[],\n scoped: readonly LanguageProfile[],\n tier: \"function\" | \"frequent\",\n rung: \"2a\" | \"2b\",\n): RungVerdict | null {\n const r = leader(\n tally(\n tokens,\n membershipFor(scoped, (p) => p.words?.[tier] ?? []),\n ),\n );\n return r ? { language: r.code, margin: r.margin, rung } : null;\n}\n\n/**\n * Classify `text` among `candidates`. Synchronous and allocation-light. Returns\n * `\"unknown\"` on empty evidence, on a tie inside the candidate set, or when\n * nothing is distinctive.\n *\n * Generic over the concrete profile type `P`, inferred from `candidates`. The\n * optional `rung3` resolver is typed over the same `P`, so a consumer with a\n * stricter profile (e.g. `words` required) can pass its own resolver directly,\n * with no adapter — the resolver sees exactly the profiles the caller passed.\n * `P` defaults to {@link LanguageProfile}, so the bare two-argument form and\n * every existing call site are unchanged.\n */\nexport function classifyBySnippet<P extends LanguageProfile = LanguageProfile>(\n text: string,\n candidates: readonly P[],\n rung3?: Rung3Resolver<P>,\n): SnippetVerdict {\n if (!text || candidates.length === 0) return UNKNOWN;\n\n // Drop URLs / @handles / #hashtags once, up front: trailing Latin noise must\n // not flip the dominant-script vote nor pollute the per-rung tallies.\n const cleaned = stripNoise(text);\n\n // Restrict to candidates in the text's dominant script.\n const scoped = scopeCandidates(cleaned, candidates);\n if (scoped.length === 0) return UNKNOWN;\n\n // ≥2 same-script candidates means the distinctive machinery actually had a\n // choice to make; a lone scoped candidate wins by script alone. Stamped onto\n // whichever rung decides — a single rung can't see the scope size.\n const discriminating = scoped.length >= 2;\n\n const byLetter = letterRung(cleaned, scoped);\n if (byLetter) return { ...byLetter, discriminating };\n\n const tokens = tokenize(cleaned);\n if (tokens.length === 0) return UNKNOWN;\n\n const byWord =\n wordRung(tokens, scoped, \"function\", \"2a\") ??\n wordRung(tokens, scoped, \"frequent\", \"2b\") ??\n rung3?.(cleaned, scoped);\n return byWord ? { ...byWord, discriminating } : UNKNOWN;\n}\n"]}
|