zyphra-textnorm 0.1.0__tar.gz

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.
Files changed (491) hide show
  1. zyphra_textnorm-0.1.0/Cargo.lock +218 -0
  2. zyphra_textnorm-0.1.0/Cargo.toml +87 -0
  3. zyphra_textnorm-0.1.0/LICENSE +21 -0
  4. zyphra_textnorm-0.1.0/NOTICE +32 -0
  5. zyphra_textnorm-0.1.0/PKG-INFO +156 -0
  6. zyphra_textnorm-0.1.0/README.md +138 -0
  7. zyphra_textnorm-0.1.0/benches/normalize.rs +99 -0
  8. zyphra_textnorm-0.1.0/data/de/electronic/domain.tsv +844 -0
  9. zyphra_textnorm-0.1.0/data/de/electronic/server_name.tsv +17 -0
  10. zyphra_textnorm-0.1.0/data/de/electronic/symbols.tsv +20 -0
  11. zyphra_textnorm-0.1.0/data/de/fractions.tsv +30 -0
  12. zyphra_textnorm-0.1.0/data/de/measure/measurements.tsv +82 -0
  13. zyphra_textnorm-0.1.0/data/de/measure/suppletive.tsv +10 -0
  14. zyphra_textnorm-0.1.0/data/de/money/currency.tsv +25 -0
  15. zyphra_textnorm-0.1.0/data/de/money/currency_minor_plural.tsv +3 -0
  16. zyphra_textnorm-0.1.0/data/de/money/currency_minor_singular.tsv +3 -0
  17. zyphra_textnorm-0.1.0/data/de/months/abbr_to_name.tsv +13 -0
  18. zyphra_textnorm-0.1.0/data/de/months/numbers.tsv +24 -0
  19. zyphra_textnorm-0.1.0/data/de/numbers/digit.tsv +8 -0
  20. zyphra_textnorm-0.1.0/data/de/numbers/ones.tsv +3 -0
  21. zyphra_textnorm-0.1.0/data/de/numbers/quantities.tsv +12 -0
  22. zyphra_textnorm-0.1.0/data/de/numbers/teen.tsv +10 -0
  23. zyphra_textnorm-0.1.0/data/de/numbers/ties.tsv +8 -0
  24. zyphra_textnorm-0.1.0/data/de/numbers/zero.tsv +1 -0
  25. zyphra_textnorm-0.1.0/data/de/ordinals/digit.tsv +9 -0
  26. zyphra_textnorm-0.1.0/data/de/ordinals/thousands.tsv +4 -0
  27. zyphra_textnorm-0.1.0/data/de/ordinals/ties.tsv +8 -0
  28. zyphra_textnorm-0.1.0/data/de/time/hour_to.tsv +12 -0
  29. zyphra_textnorm-0.1.0/data/de/time/hour_to_night.tsv +13 -0
  30. zyphra_textnorm-0.1.0/data/de/time/minute_to.tsv +59 -0
  31. zyphra_textnorm-0.1.0/data/de/time/time_zone.tsv +7 -0
  32. zyphra_textnorm-0.1.0/data/de/whitelist.tsv +21 -0
  33. zyphra_textnorm-0.1.0/data/en/address/address_word.tsv +14 -0
  34. zyphra_textnorm-0.1.0/data/en/address/state.tsv +49 -0
  35. zyphra_textnorm-0.1.0/data/en/date/day.tsv +31 -0
  36. zyphra_textnorm-0.1.0/data/en/date/month_abbr.tsv +12 -0
  37. zyphra_textnorm-0.1.0/data/en/date/month_name.tsv +12 -0
  38. zyphra_textnorm-0.1.0/data/en/date/month_number.tsv +24 -0
  39. zyphra_textnorm-0.1.0/data/en/date/year_suffix.tsv +16 -0
  40. zyphra_textnorm-0.1.0/data/en/electronic/cc_cues.tsv +5 -0
  41. zyphra_textnorm-0.1.0/data/en/electronic/domain.tsv +13 -0
  42. zyphra_textnorm-0.1.0/data/en/electronic/symbol.tsv +19 -0
  43. zyphra_textnorm-0.1.0/data/en/electronic/words.tsv +16 -0
  44. zyphra_textnorm-0.1.0/data/en/measure/math_operation.tsv +8 -0
  45. zyphra_textnorm-0.1.0/data/en/measure/unit.tsv +135 -0
  46. zyphra_textnorm-0.1.0/data/en/measure/unit_alternatives.tsv +43 -0
  47. zyphra_textnorm-0.1.0/data/en/money/currency_major.tsv +39 -0
  48. zyphra_textnorm-0.1.0/data/en/money/currency_minor_plural.tsv +4 -0
  49. zyphra_textnorm-0.1.0/data/en/money/currency_minor_singular.tsv +3 -0
  50. zyphra_textnorm-0.1.0/data/en/money/per_unit.tsv +70 -0
  51. zyphra_textnorm-0.1.0/data/en/number/digit.tsv +9 -0
  52. zyphra_textnorm-0.1.0/data/en/number/fraction.tsv +18 -0
  53. zyphra_textnorm-0.1.0/data/en/number/hundred.tsv +1 -0
  54. zyphra_textnorm-0.1.0/data/en/number/quantity_abbr.tsv +10 -0
  55. zyphra_textnorm-0.1.0/data/en/number/teen.tsv +10 -0
  56. zyphra_textnorm-0.1.0/data/en/number/thousand.tsv +22 -0
  57. zyphra_textnorm-0.1.0/data/en/number/ty.tsv +8 -0
  58. zyphra_textnorm-0.1.0/data/en/number/zero.tsv +1 -0
  59. zyphra_textnorm-0.1.0/data/en/ordinal/digit.tsv +9 -0
  60. zyphra_textnorm-0.1.0/data/en/ordinal/teen.tsv +1 -0
  61. zyphra_textnorm-0.1.0/data/en/roman/female.tsv +4998 -0
  62. zyphra_textnorm-0.1.0/data/en/roman/key_word.tsv +6 -0
  63. zyphra_textnorm-0.1.0/data/en/roman/male.tsv +2946 -0
  64. zyphra_textnorm-0.1.0/data/en/roman/roman_to_spoken.tsv +2000 -0
  65. zyphra_textnorm-0.1.0/data/en/suppletive.tsv +112 -0
  66. zyphra_textnorm-0.1.0/data/en/telephone/ip_prompt.tsv +2 -0
  67. zyphra_textnorm-0.1.0/data/en/telephone/ssn_prompt.tsv +4 -0
  68. zyphra_textnorm-0.1.0/data/en/telephone/telephone_prompt.tsv +5 -0
  69. zyphra_textnorm-0.1.0/data/en/time/suffix.tsv +12 -0
  70. zyphra_textnorm-0.1.0/data/en/time/zone.tsv +14 -0
  71. zyphra_textnorm-0.1.0/data/en/whitelist/alternatives.tsv +45 -0
  72. zyphra_textnorm-0.1.0/data/en/whitelist/alternatives_all_format.tsv +14 -0
  73. zyphra_textnorm-0.1.0/data/en/whitelist/asr.tsv +14713 -0
  74. zyphra_textnorm-0.1.0/data/en/whitelist/asr_with_pc.tsv +71 -0
  75. zyphra_textnorm-0.1.0/data/en/whitelist/ipa_symbols.tsv +521 -0
  76. zyphra_textnorm-0.1.0/data/en/whitelist/lj_speech.tsv +21 -0
  77. zyphra_textnorm-0.1.0/data/en/whitelist/symbol.tsv +23 -0
  78. zyphra_textnorm-0.1.0/data/en/whitelist/tts.tsv +3890 -0
  79. zyphra_textnorm-0.1.0/data/es/dates/days_abbr.tsv +27 -0
  80. zyphra_textnorm-0.1.0/data/es/dates/months.tsv +12 -0
  81. zyphra_textnorm-0.1.0/data/es/dates/months_abbr.tsv +44 -0
  82. zyphra_textnorm-0.1.0/data/es/dates/year_suffix.tsv +51 -0
  83. zyphra_textnorm-0.1.0/data/es/electronic/domain.tsv +6 -0
  84. zyphra_textnorm-0.1.0/data/es/electronic/server_name.tsv +11 -0
  85. zyphra_textnorm-0.1.0/data/es/electronic/symbols.tsv +22 -0
  86. zyphra_textnorm-0.1.0/data/es/fractions/fraction_symbols.tsv +15 -0
  87. zyphra_textnorm-0.1.0/data/es/fractions/ordinal_exceptions.tsv +2 -0
  88. zyphra_textnorm-0.1.0/data/es/fractions/powers_of_ten.tsv +9 -0
  89. zyphra_textnorm-0.1.0/data/es/fractions/powers_of_ten_fem.tsv +6 -0
  90. zyphra_textnorm-0.1.0/data/es/measures/math_symbols.tsv +7 -0
  91. zyphra_textnorm-0.1.0/data/es/measures/measurements.tsv +18 -0
  92. zyphra_textnorm-0.1.0/data/es/measures/measurements_complex.tsv +5 -0
  93. zyphra_textnorm-0.1.0/data/es/measures/measurements_plural_fem.tsv +3 -0
  94. zyphra_textnorm-0.1.0/data/es/measures/measurements_plural_masc.tsv +21 -0
  95. zyphra_textnorm-0.1.0/data/es/money/currency_major.tsv +64 -0
  96. zyphra_textnorm-0.1.0/data/es/money/currency_major_ext.tsv +215 -0
  97. zyphra_textnorm-0.1.0/data/es/money/currency_minor.tsv +64 -0
  98. zyphra_textnorm-0.1.0/data/es/money/currency_minor_ext.tsv +181 -0
  99. zyphra_textnorm-0.1.0/data/es/money/currency_plural_fem.tsv +8 -0
  100. zyphra_textnorm-0.1.0/data/es/money/currency_plural_fem_ext.tsv +56 -0
  101. zyphra_textnorm-0.1.0/data/es/money/currency_plural_masc.tsv +51 -0
  102. zyphra_textnorm-0.1.0/data/es/money/currency_plural_masc_ext.tsv +199 -0
  103. zyphra_textnorm-0.1.0/data/es/numbers/digit.tsv +9 -0
  104. zyphra_textnorm-0.1.0/data/es/numbers/hundreds.tsv +8 -0
  105. zyphra_textnorm-0.1.0/data/es/numbers/quantities.tsv +6 -0
  106. zyphra_textnorm-0.1.0/data/es/numbers/teen.tsv +10 -0
  107. zyphra_textnorm-0.1.0/data/es/numbers/ties.tsv +7 -0
  108. zyphra_textnorm-0.1.0/data/es/numbers/twenties.tsv +10 -0
  109. zyphra_textnorm-0.1.0/data/es/numbers/zero.tsv +1 -0
  110. zyphra_textnorm-0.1.0/data/es/ordinals/digit.tsv +11 -0
  111. zyphra_textnorm-0.1.0/data/es/ordinals/gender_suffix.tsv +20 -0
  112. zyphra_textnorm-0.1.0/data/es/ordinals/hundreds.tsv +18 -0
  113. zyphra_textnorm-0.1.0/data/es/ordinals/roman_exceptions.tsv +10 -0
  114. zyphra_textnorm-0.1.0/data/es/ordinals/teen.tsv +10 -0
  115. zyphra_textnorm-0.1.0/data/es/ordinals/ties.tsv +8 -0
  116. zyphra_textnorm-0.1.0/data/es/ordinals/twenties.tsv +11 -0
  117. zyphra_textnorm-0.1.0/data/es/roman/digit.tsv +9 -0
  118. zyphra_textnorm-0.1.0/data/es/roman/hundreds.tsv +9 -0
  119. zyphra_textnorm-0.1.0/data/es/roman/thousands.tsv +3 -0
  120. zyphra_textnorm-0.1.0/data/es/roman/ties.tsv +9 -0
  121. zyphra_textnorm-0.1.0/data/es/telephone/ip_prompt.tsv +2 -0
  122. zyphra_textnorm-0.1.0/data/es/telephone/telephone_prompt.tsv +10 -0
  123. zyphra_textnorm-0.1.0/data/es/time/afternoon_times.tsv +6 -0
  124. zyphra_textnorm-0.1.0/data/es/time/alt_minutes.tsv +2 -0
  125. zyphra_textnorm-0.1.0/data/es/time/evening_times.tsv +5 -0
  126. zyphra_textnorm-0.1.0/data/es/time/hour_to_12.tsv +12 -0
  127. zyphra_textnorm-0.1.0/data/es/time/hour_to_24.tsv +25 -0
  128. zyphra_textnorm-0.1.0/data/es/time/hour_to_night.tsv +13 -0
  129. zyphra_textnorm-0.1.0/data/es/time/minute_to.tsv +59 -0
  130. zyphra_textnorm-0.1.0/data/es/time/morning_times.tsv +12 -0
  131. zyphra_textnorm-0.1.0/data/es/time/time_suffix.tsv +20 -0
  132. zyphra_textnorm-0.1.0/data/es/time/time_zone.tsv +42 -0
  133. zyphra_textnorm-0.1.0/data/es/time/time_zone_ext.tsv +105 -0
  134. zyphra_textnorm-0.1.0/data/es/whitelist.tsv +62 -0
  135. zyphra_textnorm-0.1.0/data/fr/dates/eras.tsv +8 -0
  136. zyphra_textnorm-0.1.0/data/fr/dates/months.tsv +12 -0
  137. zyphra_textnorm-0.1.0/data/fr/fractions/irregular_denominators.tsv +7 -0
  138. zyphra_textnorm-0.1.0/data/fr/measures/measurements.tsv +17 -0
  139. zyphra_textnorm-0.1.0/data/fr/numbers/digit.tsv +9 -0
  140. zyphra_textnorm-0.1.0/data/fr/numbers/eighty.tsv +1 -0
  141. zyphra_textnorm-0.1.0/data/fr/numbers/ninety.tsv +1 -0
  142. zyphra_textnorm-0.1.0/data/fr/numbers/quantities.tsv +10 -0
  143. zyphra_textnorm-0.1.0/data/fr/numbers/seventy.tsv +1 -0
  144. zyphra_textnorm-0.1.0/data/fr/numbers/teens.tsv +9 -0
  145. zyphra_textnorm-0.1.0/data/fr/numbers/ten.tsv +1 -0
  146. zyphra_textnorm-0.1.0/data/fr/numbers/tens_simple.tsv +5 -0
  147. zyphra_textnorm-0.1.0/data/fr/numbers/zero.tsv +1 -0
  148. zyphra_textnorm-0.1.0/data/fr/ordinals/irregular_numbers.tsv +30 -0
  149. zyphra_textnorm-0.1.0/data/fr/ordinals/suffixes.tsv +6 -0
  150. zyphra_textnorm-0.1.0/data/fr/whitelist.tsv +13 -0
  151. zyphra_textnorm-0.1.0/data/it/electronic/domain.tsv +14 -0
  152. zyphra_textnorm-0.1.0/data/it/electronic/server_name.tsv +11 -0
  153. zyphra_textnorm-0.1.0/data/it/electronic/symbols.tsv +22 -0
  154. zyphra_textnorm-0.1.0/data/it/measure/measurements.tsv +64 -0
  155. zyphra_textnorm-0.1.0/data/it/measure/suppletive.tsv +13 -0
  156. zyphra_textnorm-0.1.0/data/it/money/currency_major.tsv +11 -0
  157. zyphra_textnorm-0.1.0/data/it/money/currency_minor.tsv +11 -0
  158. zyphra_textnorm-0.1.0/data/it/money/currency_plural_fem.tsv +2 -0
  159. zyphra_textnorm-0.1.0/data/it/money/currency_plural_masc.tsv +10 -0
  160. zyphra_textnorm-0.1.0/data/it/numbers/digit.tsv +9 -0
  161. zyphra_textnorm-0.1.0/data/it/numbers/hundreds.tsv +8 -0
  162. zyphra_textnorm-0.1.0/data/it/numbers/quantities.tsv +2 -0
  163. zyphra_textnorm-0.1.0/data/it/numbers/teen.tsv +10 -0
  164. zyphra_textnorm-0.1.0/data/it/numbers/tens.tsv +8 -0
  165. zyphra_textnorm-0.1.0/data/it/numbers/tens_eight.tsv +8 -0
  166. zyphra_textnorm-0.1.0/data/it/numbers/tens_one.tsv +8 -0
  167. zyphra_textnorm-0.1.0/data/it/numbers/zero.tsv +1 -0
  168. zyphra_textnorm-0.1.0/data/it/whitelist/whitelist.tsv +65 -0
  169. zyphra_textnorm-0.1.0/data/ja/date/day.tsv +31 -0
  170. zyphra_textnorm-0.1.0/data/ja/date/era.tsv +12 -0
  171. zyphra_textnorm-0.1.0/data/ja/date/era_abbrev.tsv +5 -0
  172. zyphra_textnorm-0.1.0/data/ja/date/month.tsv +12 -0
  173. zyphra_textnorm-0.1.0/data/ja/date/week.tsv +15 -0
  174. zyphra_textnorm-0.1.0/data/ja/numbers/digit.tsv +9 -0
  175. zyphra_textnorm-0.1.0/data/ja/numbers/teen.tsv +10 -0
  176. zyphra_textnorm-0.1.0/data/ja/numbers/ties.tsv +8 -0
  177. zyphra_textnorm-0.1.0/data/ja/numbers/zero.tsv +1 -0
  178. zyphra_textnorm-0.1.0/data/ja/symbol.tsv +23 -0
  179. zyphra_textnorm-0.1.0/data/ja/time/division.tsv +23 -0
  180. zyphra_textnorm-0.1.0/data/ja/time/hour.tsv +24 -0
  181. zyphra_textnorm-0.1.0/data/ja/time/minute.tsv +60 -0
  182. zyphra_textnorm-0.1.0/data/ja/time/second.tsv +60 -0
  183. zyphra_textnorm-0.1.0/data/ja/whitelist.tsv +40 -0
  184. zyphra_textnorm-0.1.0/data/ko/date/exceptions.tsv +2 -0
  185. zyphra_textnorm-0.1.0/data/ko/date/week.tsv +8 -0
  186. zyphra_textnorm-0.1.0/data/ko/electronic/cc_cues.tsv +11 -0
  187. zyphra_textnorm-0.1.0/data/ko/electronic/domain.tsv +28 -0
  188. zyphra_textnorm-0.1.0/data/ko/electronic/extensions.tsv +6 -0
  189. zyphra_textnorm-0.1.0/data/ko/electronic/symbol.tsv +12 -0
  190. zyphra_textnorm-0.1.0/data/ko/measure/unit.tsv +18 -0
  191. zyphra_textnorm-0.1.0/data/ko/money/currency_major.tsv +22 -0
  192. zyphra_textnorm-0.1.0/data/ko/number/counter_suffix.tsv +16 -0
  193. zyphra_textnorm-0.1.0/data/ko/number/digit.tsv +9 -0
  194. zyphra_textnorm-0.1.0/data/ko/number/native_ones.tsv +9 -0
  195. zyphra_textnorm-0.1.0/data/ko/number/tens.tsv +9 -0
  196. zyphra_textnorm-0.1.0/data/ko/number/zero.tsv +1 -0
  197. zyphra_textnorm-0.1.0/data/ko/ordinal/digit.tsv +8 -0
  198. zyphra_textnorm-0.1.0/data/ko/ordinal/exceptions.tsv +5 -0
  199. zyphra_textnorm-0.1.0/data/ko/ordinal/tens.tsv +2 -0
  200. zyphra_textnorm-0.1.0/data/ko/ordinal/tens_prefix.tsv +3 -0
  201. zyphra_textnorm-0.1.0/data/ko/time/division.tsv +7 -0
  202. zyphra_textnorm-0.1.0/data/ko/time/hour.tsv +12 -0
  203. zyphra_textnorm-0.1.0/data/ko/whitelist.tsv +38 -0
  204. zyphra_textnorm-0.1.0/data/perluniprops/IsAlpha.txt +1 -0
  205. zyphra_textnorm-0.1.0/data/perluniprops/IsSc.txt +1 -0
  206. zyphra_textnorm-0.1.0/data/pt/date/months.tsv +21 -0
  207. zyphra_textnorm-0.1.0/data/pt/date/numeric_separators.tsv +3 -0
  208. zyphra_textnorm-0.1.0/data/pt/date/verbal_phrases.tsv +1 -0
  209. zyphra_textnorm-0.1.0/data/pt/electronic/domain.tsv +7 -0
  210. zyphra_textnorm-0.1.0/data/pt/electronic/electronic_spoken_unit.tsv +16 -0
  211. zyphra_textnorm-0.1.0/data/pt/electronic/server_name.tsv +6 -0
  212. zyphra_textnorm-0.1.0/data/pt/electronic/symbols.tsv +22 -0
  213. zyphra_textnorm-0.1.0/data/pt/fractions/ordinal_exceptions.tsv +2 -0
  214. zyphra_textnorm-0.1.0/data/pt/fractions/powers_of_ten.tsv +1 -0
  215. zyphra_textnorm-0.1.0/data/pt/fractions/specials.tsv +5 -0
  216. zyphra_textnorm-0.1.0/data/pt/measure/measurements_plural.tsv +64 -0
  217. zyphra_textnorm-0.1.0/data/pt/measure/measurements_singular.tsv +65 -0
  218. zyphra_textnorm-0.1.0/data/pt/money/currency_major.tsv +5 -0
  219. zyphra_textnorm-0.1.0/data/pt/money/currency_major_plural.tsv +5 -0
  220. zyphra_textnorm-0.1.0/data/pt/money/currency_minor.tsv +5 -0
  221. zyphra_textnorm-0.1.0/data/pt/money/currency_minor_plural.tsv +1 -0
  222. zyphra_textnorm-0.1.0/data/pt/numbers/cardinal_specials.tsv +4 -0
  223. zyphra_textnorm-0.1.0/data/pt/numbers/decimal_fractional_specials.tsv +3 -0
  224. zyphra_textnorm-0.1.0/data/pt/numbers/decimal_specials.tsv +2 -0
  225. zyphra_textnorm-0.1.0/data/pt/numbers/digit.tsv +9 -0
  226. zyphra_textnorm-0.1.0/data/pt/numbers/hundreds.tsv +8 -0
  227. zyphra_textnorm-0.1.0/data/pt/numbers/quantity_words.tsv +9 -0
  228. zyphra_textnorm-0.1.0/data/pt/numbers/scales.tsv +4 -0
  229. zyphra_textnorm-0.1.0/data/pt/numbers/teens.tsv +10 -0
  230. zyphra_textnorm-0.1.0/data/pt/numbers/tens.tsv +8 -0
  231. zyphra_textnorm-0.1.0/data/pt/numbers/zero.tsv +1 -0
  232. zyphra_textnorm-0.1.0/data/pt/ordinals/digit.tsv +10 -0
  233. zyphra_textnorm-0.1.0/data/pt/ordinals/feminine.tsv +11 -0
  234. zyphra_textnorm-0.1.0/data/pt/ordinals/hundreds.tsv +10 -0
  235. zyphra_textnorm-0.1.0/data/pt/ordinals/specials.tsv +2 -0
  236. zyphra_textnorm-0.1.0/data/pt/ordinals/teen.tsv +9 -0
  237. zyphra_textnorm-0.1.0/data/pt/ordinals/ties.tsv +8 -0
  238. zyphra_textnorm-0.1.0/data/pt/telephone/ip_prompt.tsv +2 -0
  239. zyphra_textnorm-0.1.0/data/pt/telephone/telephone_prompt.tsv +4 -0
  240. zyphra_textnorm-0.1.0/data/pt/time/day_period_suffix.tsv +4 -0
  241. zyphra_textnorm-0.1.0/data/pt/whitelist/ipa_symbols.tsv +521 -0
  242. zyphra_textnorm-0.1.0/data/pt/whitelist/symbol.tsv +23 -0
  243. zyphra_textnorm-0.1.0/data/pt/whitelist/tts.tsv +0 -0
  244. zyphra_textnorm-0.1.0/data/unicode/isspace.txt +30 -0
  245. zyphra_textnorm-0.1.0/data/unicode/nd_ranges.txt +65 -0
  246. zyphra_textnorm-0.1.0/data/unicode/punct_ranges.txt +192 -0
  247. zyphra_textnorm-0.1.0/data/unicode/word_ranges.txt +749 -0
  248. zyphra_textnorm-0.1.0/data/zh/char/charset_extension.tsv +6 -0
  249. zyphra_textnorm-0.1.0/data/zh/char/charset_national_standard_2013_8105.tsv +8105 -0
  250. zyphra_textnorm-0.1.0/data/zh/char/fullwidth_to_halfwidth.tsv +92 -0
  251. zyphra_textnorm-0.1.0/data/zh/char/oov_tags.tsv +1 -0
  252. zyphra_textnorm-0.1.0/data/zh/char/punctuations_zh.tsv +74 -0
  253. zyphra_textnorm-0.1.0/data/zh/char/upper_to_lower.tsv +9 -0
  254. zyphra_textnorm-0.1.0/data/zh/date/day.tsv +40 -0
  255. zyphra_textnorm-0.1.0/data/zh/date/months.tsv +21 -0
  256. zyphra_textnorm-0.1.0/data/zh/date/suffix.tsv +16 -0
  257. zyphra_textnorm-0.1.0/data/zh/date/suffixes.tsv +16 -0
  258. zyphra_textnorm-0.1.0/data/zh/denylist/denylist.tsv +2 -0
  259. zyphra_textnorm-0.1.0/data/zh/erhua/whitelist.tsv +35 -0
  260. zyphra_textnorm-0.1.0/data/zh/math/score.tsv +2 -0
  261. zyphra_textnorm-0.1.0/data/zh/math/symbol.tsv +8 -0
  262. zyphra_textnorm-0.1.0/data/zh/measure/units_en.tsv +67 -0
  263. zyphra_textnorm-0.1.0/data/zh/money/currency_major.tsv +200 -0
  264. zyphra_textnorm-0.1.0/data/zh/money/currency_mandarin.tsv +52 -0
  265. zyphra_textnorm-0.1.0/data/zh/number/digit.tsv +9 -0
  266. zyphra_textnorm-0.1.0/data/zh/number/digit_alt.tsv +9 -0
  267. zyphra_textnorm-0.1.0/data/zh/number/digit_tens.tsv +8 -0
  268. zyphra_textnorm-0.1.0/data/zh/number/sign.tsv +2 -0
  269. zyphra_textnorm-0.1.0/data/zh/number/suffix.tsv +23 -0
  270. zyphra_textnorm-0.1.0/data/zh/number/teen.tsv +10 -0
  271. zyphra_textnorm-0.1.0/data/zh/number/teen_alt.tsv +10 -0
  272. zyphra_textnorm-0.1.0/data/zh/number/ties.tsv +8 -0
  273. zyphra_textnorm-0.1.0/data/zh/number/zero.tsv +1 -0
  274. zyphra_textnorm-0.1.0/data/zh/time/AM.tsv +8 -0
  275. zyphra_textnorm-0.1.0/data/zh/time/PM.tsv +8 -0
  276. zyphra_textnorm-0.1.0/data/zh/time/hour.tsv +35 -0
  277. zyphra_textnorm-0.1.0/data/zh/time/minute.tsv +71 -0
  278. zyphra_textnorm-0.1.0/data/zh/time/second.tsv +71 -0
  279. zyphra_textnorm-0.1.0/data/zh/time/zero.tsv +1 -0
  280. zyphra_textnorm-0.1.0/data/zh/whitelist.tsv +157 -0
  281. zyphra_textnorm-0.1.0/examples/normalize.rs +12 -0
  282. zyphra_textnorm-0.1.0/include/zyphra_textnorm.h +48 -0
  283. zyphra_textnorm-0.1.0/licenses/nemo-Apache-2.0.txt +202 -0
  284. zyphra_textnorm-0.1.0/licenses/sacremoses-MIT.txt +21 -0
  285. zyphra_textnorm-0.1.0/pyproject.toml +46 -0
  286. zyphra_textnorm-0.1.0/python/Cargo.toml +17 -0
  287. zyphra_textnorm-0.1.0/python/src/lib.rs +56 -0
  288. zyphra_textnorm-0.1.0/src/ffi.rs +106 -0
  289. zyphra_textnorm-0.1.0/src/lang/common.rs +242 -0
  290. zyphra_textnorm-0.1.0/src/lang/de/crossing.rs +130 -0
  291. zyphra_textnorm-0.1.0/src/lang/de/mod.rs +314 -0
  292. zyphra_textnorm-0.1.0/src/lang/de/taggers/cardinal.rs +381 -0
  293. zyphra_textnorm-0.1.0/src/lang/de/taggers/date.rs +273 -0
  294. zyphra_textnorm-0.1.0/src/lang/de/taggers/decimal.rs +134 -0
  295. zyphra_textnorm-0.1.0/src/lang/de/taggers/electronic.rs +168 -0
  296. zyphra_textnorm-0.1.0/src/lang/de/taggers/fraction.rs +101 -0
  297. zyphra_textnorm-0.1.0/src/lang/de/taggers/measure.rs +291 -0
  298. zyphra_textnorm-0.1.0/src/lang/de/taggers/money.rs +216 -0
  299. zyphra_textnorm-0.1.0/src/lang/de/taggers/ordinal.rs +43 -0
  300. zyphra_textnorm-0.1.0/src/lang/de/taggers/telephone.rs +108 -0
  301. zyphra_textnorm-0.1.0/src/lang/de/taggers/time.rs +124 -0
  302. zyphra_textnorm-0.1.0/src/lang/de/taggers/whitelist.rs +42 -0
  303. zyphra_textnorm-0.1.0/src/lang/de/taggers/word.rs +46 -0
  304. zyphra_textnorm-0.1.0/src/lang/de/verbalizers/cardinal.rs +18 -0
  305. zyphra_textnorm-0.1.0/src/lang/de/verbalizers/date.rs +41 -0
  306. zyphra_textnorm-0.1.0/src/lang/de/verbalizers/decimal.rs +44 -0
  307. zyphra_textnorm-0.1.0/src/lang/de/verbalizers/electronic.rs +125 -0
  308. zyphra_textnorm-0.1.0/src/lang/de/verbalizers/fraction.rs +57 -0
  309. zyphra_textnorm-0.1.0/src/lang/de/verbalizers/measure.rs +29 -0
  310. zyphra_textnorm-0.1.0/src/lang/de/verbalizers/mod.rs +13 -0
  311. zyphra_textnorm-0.1.0/src/lang/de/verbalizers/money.rs +43 -0
  312. zyphra_textnorm-0.1.0/src/lang/de/verbalizers/ordinal.rs +41 -0
  313. zyphra_textnorm-0.1.0/src/lang/de/verbalizers/telephone.rs +12 -0
  314. zyphra_textnorm-0.1.0/src/lang/de/verbalizers/time.rs +65 -0
  315. zyphra_textnorm-0.1.0/src/lang/en/graph_utils.rs +123 -0
  316. zyphra_textnorm-0.1.0/src/lang/en/lazy.rs +180 -0
  317. zyphra_textnorm-0.1.0/src/lang/en/mod.rs +166 -0
  318. zyphra_textnorm-0.1.0/src/lang/en/taggers/cardinal.rs +449 -0
  319. zyphra_textnorm-0.1.0/src/lang/en/taggers/date.rs +713 -0
  320. zyphra_textnorm-0.1.0/src/lang/en/taggers/decimal.rs +209 -0
  321. zyphra_textnorm-0.1.0/src/lang/en/taggers/electronic.rs +360 -0
  322. zyphra_textnorm-0.1.0/src/lang/en/taggers/fraction.rs +191 -0
  323. zyphra_textnorm-0.1.0/src/lang/en/taggers/measure.rs +847 -0
  324. zyphra_textnorm-0.1.0/src/lang/en/taggers/mod.rs +15 -0
  325. zyphra_textnorm-0.1.0/src/lang/en/taggers/money.rs +406 -0
  326. zyphra_textnorm-0.1.0/src/lang/en/taggers/ordinal.rs +105 -0
  327. zyphra_textnorm-0.1.0/src/lang/en/taggers/range.rs +199 -0
  328. zyphra_textnorm-0.1.0/src/lang/en/taggers/serial.rs +251 -0
  329. zyphra_textnorm-0.1.0/src/lang/en/taggers/telephone.rs +425 -0
  330. zyphra_textnorm-0.1.0/src/lang/en/taggers/time.rs +214 -0
  331. zyphra_textnorm-0.1.0/src/lang/en/taggers/whitelist.rs +239 -0
  332. zyphra_textnorm-0.1.0/src/lang/en/taggers/word.rs +166 -0
  333. zyphra_textnorm-0.1.0/src/lang/en/verbalizers/date.rs +68 -0
  334. zyphra_textnorm-0.1.0/src/lang/en/verbalizers/decimal.rs +86 -0
  335. zyphra_textnorm-0.1.0/src/lang/en/verbalizers/electronic.rs +164 -0
  336. zyphra_textnorm-0.1.0/src/lang/en/verbalizers/measure.rs +77 -0
  337. zyphra_textnorm-0.1.0/src/lang/en/verbalizers/mod.rs +11 -0
  338. zyphra_textnorm-0.1.0/src/lang/en/verbalizers/money.rs +63 -0
  339. zyphra_textnorm-0.1.0/src/lang/en/verbalizers/ordinal.rs +31 -0
  340. zyphra_textnorm-0.1.0/src/lang/en/verbalizers/post_processing.rs +303 -0
  341. zyphra_textnorm-0.1.0/src/lang/en/verbalizers/telephone.rs +34 -0
  342. zyphra_textnorm-0.1.0/src/lang/en/verbalizers/time.rs +63 -0
  343. zyphra_textnorm-0.1.0/src/lang/en/verbalizers/verbalize_final.rs +93 -0
  344. zyphra_textnorm-0.1.0/src/lang/es/graph_utils.rs +245 -0
  345. zyphra_textnorm-0.1.0/src/lang/es/mod.rs +286 -0
  346. zyphra_textnorm-0.1.0/src/lang/es/taggers/cardinal.rs +431 -0
  347. zyphra_textnorm-0.1.0/src/lang/es/taggers/date.rs +443 -0
  348. zyphra_textnorm-0.1.0/src/lang/es/taggers/decimals.rs +358 -0
  349. zyphra_textnorm-0.1.0/src/lang/es/taggers/electronic.rs +146 -0
  350. zyphra_textnorm-0.1.0/src/lang/es/taggers/fraction.rs +166 -0
  351. zyphra_textnorm-0.1.0/src/lang/es/taggers/measure.rs +413 -0
  352. zyphra_textnorm-0.1.0/src/lang/es/taggers/mod.rs +22 -0
  353. zyphra_textnorm-0.1.0/src/lang/es/taggers/money.rs +550 -0
  354. zyphra_textnorm-0.1.0/src/lang/es/taggers/ordinal.rs +203 -0
  355. zyphra_textnorm-0.1.0/src/lang/es/taggers/telephone.rs +340 -0
  356. zyphra_textnorm-0.1.0/src/lang/es/taggers/time.rs +351 -0
  357. zyphra_textnorm-0.1.0/src/lang/es/taggers/whitelist.rs +27 -0
  358. zyphra_textnorm-0.1.0/src/lang/es/taggers/word.rs +26 -0
  359. zyphra_textnorm-0.1.0/src/lang/es/verbalizers/cardinal.rs +42 -0
  360. zyphra_textnorm-0.1.0/src/lang/es/verbalizers/date.rs +65 -0
  361. zyphra_textnorm-0.1.0/src/lang/es/verbalizers/decimals.rs +89 -0
  362. zyphra_textnorm-0.1.0/src/lang/es/verbalizers/electronic.rs +114 -0
  363. zyphra_textnorm-0.1.0/src/lang/es/verbalizers/fraction.rs +157 -0
  364. zyphra_textnorm-0.1.0/src/lang/es/verbalizers/measure.rs +132 -0
  365. zyphra_textnorm-0.1.0/src/lang/es/verbalizers/mod.rs +56 -0
  366. zyphra_textnorm-0.1.0/src/lang/es/verbalizers/money.rs +120 -0
  367. zyphra_textnorm-0.1.0/src/lang/es/verbalizers/ordinal.rs +37 -0
  368. zyphra_textnorm-0.1.0/src/lang/es/verbalizers/telephone.rs +28 -0
  369. zyphra_textnorm-0.1.0/src/lang/es/verbalizers/time.rs +70 -0
  370. zyphra_textnorm-0.1.0/src/lang/fr/lazy.rs +132 -0
  371. zyphra_textnorm-0.1.0/src/lang/fr/mod.rs +172 -0
  372. zyphra_textnorm-0.1.0/src/lang/fr/taggers/cardinal.rs +585 -0
  373. zyphra_textnorm-0.1.0/src/lang/fr/taggers/date.rs +268 -0
  374. zyphra_textnorm-0.1.0/src/lang/fr/taggers/decimals.rs +221 -0
  375. zyphra_textnorm-0.1.0/src/lang/fr/taggers/fraction.rs +78 -0
  376. zyphra_textnorm-0.1.0/src/lang/fr/taggers/ordinal.rs +27 -0
  377. zyphra_textnorm-0.1.0/src/lang/fr/taggers/whitelist.rs +61 -0
  378. zyphra_textnorm-0.1.0/src/lang/fr/taggers/word.rs +159 -0
  379. zyphra_textnorm-0.1.0/src/lang/fr/verbalizers/cardinal.rs +17 -0
  380. zyphra_textnorm-0.1.0/src/lang/fr/verbalizers/date.rs +27 -0
  381. zyphra_textnorm-0.1.0/src/lang/fr/verbalizers/decimals.rs +30 -0
  382. zyphra_textnorm-0.1.0/src/lang/fr/verbalizers/fraction.rs +50 -0
  383. zyphra_textnorm-0.1.0/src/lang/fr/verbalizers/ordinal.rs +59 -0
  384. zyphra_textnorm-0.1.0/src/lang/it/mod.rs +126 -0
  385. zyphra_textnorm-0.1.0/src/lang/it/taggers/cardinal.rs +419 -0
  386. zyphra_textnorm-0.1.0/src/lang/it/taggers/decimals.rs +418 -0
  387. zyphra_textnorm-0.1.0/src/lang/it/taggers/electronic.rs +120 -0
  388. zyphra_textnorm-0.1.0/src/lang/it/taggers/measure.rs +279 -0
  389. zyphra_textnorm-0.1.0/src/lang/it/taggers/mod.rs +41 -0
  390. zyphra_textnorm-0.1.0/src/lang/it/taggers/money.rs +476 -0
  391. zyphra_textnorm-0.1.0/src/lang/it/taggers/time.rs +97 -0
  392. zyphra_textnorm-0.1.0/src/lang/it/taggers/whitelist.rs +24 -0
  393. zyphra_textnorm-0.1.0/src/lang/it/taggers/word.rs +67 -0
  394. zyphra_textnorm-0.1.0/src/lang/it/verbalizers/cardinal.rs +18 -0
  395. zyphra_textnorm-0.1.0/src/lang/it/verbalizers/decimal.rs +40 -0
  396. zyphra_textnorm-0.1.0/src/lang/it/verbalizers/electronic.rs +125 -0
  397. zyphra_textnorm-0.1.0/src/lang/it/verbalizers/measure.rs +31 -0
  398. zyphra_textnorm-0.1.0/src/lang/it/verbalizers/mod.rs +37 -0
  399. zyphra_textnorm-0.1.0/src/lang/it/verbalizers/money.rs +82 -0
  400. zyphra_textnorm-0.1.0/src/lang/it/verbalizers/time.rs +43 -0
  401. zyphra_textnorm-0.1.0/src/lang/ja/mod.rs +89 -0
  402. zyphra_textnorm-0.1.0/src/lang/ja/taggers/cardinal.rs +171 -0
  403. zyphra_textnorm-0.1.0/src/lang/ja/taggers/date.rs +345 -0
  404. zyphra_textnorm-0.1.0/src/lang/ja/taggers/decimal.rs +40 -0
  405. zyphra_textnorm-0.1.0/src/lang/ja/taggers/fraction.rs +145 -0
  406. zyphra_textnorm-0.1.0/src/lang/ja/taggers/mod.rs +60 -0
  407. zyphra_textnorm-0.1.0/src/lang/ja/taggers/ordinal.rs +32 -0
  408. zyphra_textnorm-0.1.0/src/lang/ja/taggers/punctuation.rs +70 -0
  409. zyphra_textnorm-0.1.0/src/lang/ja/taggers/time.rs +220 -0
  410. zyphra_textnorm-0.1.0/src/lang/ja/taggers/tokenize_and_classify.rs +250 -0
  411. zyphra_textnorm-0.1.0/src/lang/ja/taggers/whitelist.rs +45 -0
  412. zyphra_textnorm-0.1.0/src/lang/ja/taggers/word.rs +22 -0
  413. zyphra_textnorm-0.1.0/src/lang/ja/verbalizers/mod.rs +161 -0
  414. zyphra_textnorm-0.1.0/src/lang/ko/graph_utils.rs +82 -0
  415. zyphra_textnorm-0.1.0/src/lang/ko/mod.rs +494 -0
  416. zyphra_textnorm-0.1.0/src/lang/ko/number.rs +137 -0
  417. zyphra_textnorm-0.1.0/src/lang/ko/taggers/cardinal.rs +148 -0
  418. zyphra_textnorm-0.1.0/src/lang/ko/taggers/date.rs +456 -0
  419. zyphra_textnorm-0.1.0/src/lang/ko/taggers/decimal.rs +54 -0
  420. zyphra_textnorm-0.1.0/src/lang/ko/taggers/electronic.rs +215 -0
  421. zyphra_textnorm-0.1.0/src/lang/ko/taggers/fraction.rs +135 -0
  422. zyphra_textnorm-0.1.0/src/lang/ko/taggers/measure.rs +94 -0
  423. zyphra_textnorm-0.1.0/src/lang/ko/taggers/mod.rs +16 -0
  424. zyphra_textnorm-0.1.0/src/lang/ko/taggers/money.rs +176 -0
  425. zyphra_textnorm-0.1.0/src/lang/ko/taggers/ordinal.rs +69 -0
  426. zyphra_textnorm-0.1.0/src/lang/ko/taggers/punctuation.rs +9 -0
  427. zyphra_textnorm-0.1.0/src/lang/ko/taggers/telephone.rs +87 -0
  428. zyphra_textnorm-0.1.0/src/lang/ko/taggers/time.rs +263 -0
  429. zyphra_textnorm-0.1.0/src/lang/ko/taggers/whitelist.rs +21 -0
  430. zyphra_textnorm-0.1.0/src/lang/ko/taggers/word.rs +57 -0
  431. zyphra_textnorm-0.1.0/src/lang/ko/verbalizers/mod.rs +437 -0
  432. zyphra_textnorm-0.1.0/src/lang/mod.rs +50 -0
  433. zyphra_textnorm-0.1.0/src/lang/pt/graph_utils.rs +115 -0
  434. zyphra_textnorm-0.1.0/src/lang/pt/mod.rs +108 -0
  435. zyphra_textnorm-0.1.0/src/lang/pt/taggers/cardinal.rs +566 -0
  436. zyphra_textnorm-0.1.0/src/lang/pt/taggers/date.rs +193 -0
  437. zyphra_textnorm-0.1.0/src/lang/pt/taggers/decimal.rs +116 -0
  438. zyphra_textnorm-0.1.0/src/lang/pt/taggers/electronic.rs +116 -0
  439. zyphra_textnorm-0.1.0/src/lang/pt/taggers/fraction.rs +157 -0
  440. zyphra_textnorm-0.1.0/src/lang/pt/taggers/measure.rs +107 -0
  441. zyphra_textnorm-0.1.0/src/lang/pt/taggers/mod.rs +41 -0
  442. zyphra_textnorm-0.1.0/src/lang/pt/taggers/money.rs +228 -0
  443. zyphra_textnorm-0.1.0/src/lang/pt/taggers/ordinal.rs +84 -0
  444. zyphra_textnorm-0.1.0/src/lang/pt/taggers/telephone.rs +268 -0
  445. zyphra_textnorm-0.1.0/src/lang/pt/taggers/time.rs +209 -0
  446. zyphra_textnorm-0.1.0/src/lang/pt/taggers/whitelist.rs +70 -0
  447. zyphra_textnorm-0.1.0/src/lang/pt/taggers/word.rs +124 -0
  448. zyphra_textnorm-0.1.0/src/lang/pt/verbalizers/cardinal.rs +19 -0
  449. zyphra_textnorm-0.1.0/src/lang/pt/verbalizers/date.rs +36 -0
  450. zyphra_textnorm-0.1.0/src/lang/pt/verbalizers/decimal.rs +49 -0
  451. zyphra_textnorm-0.1.0/src/lang/pt/verbalizers/electronic.rs +154 -0
  452. zyphra_textnorm-0.1.0/src/lang/pt/verbalizers/fraction.rs +80 -0
  453. zyphra_textnorm-0.1.0/src/lang/pt/verbalizers/measure.rs +46 -0
  454. zyphra_textnorm-0.1.0/src/lang/pt/verbalizers/mod.rs +63 -0
  455. zyphra_textnorm-0.1.0/src/lang/pt/verbalizers/money.rs +80 -0
  456. zyphra_textnorm-0.1.0/src/lang/pt/verbalizers/ordinal.rs +38 -0
  457. zyphra_textnorm-0.1.0/src/lang/pt/verbalizers/telephone.rs +21 -0
  458. zyphra_textnorm-0.1.0/src/lang/pt/verbalizers/time.rs +38 -0
  459. zyphra_textnorm-0.1.0/src/lang/zh/mod.rs +86 -0
  460. zyphra_textnorm-0.1.0/src/lang/zh/taggers/cardinal.rs +318 -0
  461. zyphra_textnorm-0.1.0/src/lang/zh/taggers/date.rs +305 -0
  462. zyphra_textnorm-0.1.0/src/lang/zh/taggers/decimal.rs +90 -0
  463. zyphra_textnorm-0.1.0/src/lang/zh/taggers/fraction.rs +236 -0
  464. zyphra_textnorm-0.1.0/src/lang/zh/taggers/measure.rs +155 -0
  465. zyphra_textnorm-0.1.0/src/lang/zh/taggers/mod.rs +587 -0
  466. zyphra_textnorm-0.1.0/src/lang/zh/taggers/money.rs +407 -0
  467. zyphra_textnorm-0.1.0/src/lang/zh/taggers/ordinal.rs +70 -0
  468. zyphra_textnorm-0.1.0/src/lang/zh/taggers/punctuation.rs +61 -0
  469. zyphra_textnorm-0.1.0/src/lang/zh/taggers/time.rs +329 -0
  470. zyphra_textnorm-0.1.0/src/lang/zh/taggers/whitelist.rs +49 -0
  471. zyphra_textnorm-0.1.0/src/lang/zh/taggers/word.rs +19 -0
  472. zyphra_textnorm-0.1.0/src/lang/zh/verbalizers/cardinal.rs +38 -0
  473. zyphra_textnorm-0.1.0/src/lang/zh/verbalizers/date.rs +134 -0
  474. zyphra_textnorm-0.1.0/src/lang/zh/verbalizers/decimal.rs +57 -0
  475. zyphra_textnorm-0.1.0/src/lang/zh/verbalizers/fraction.rs +66 -0
  476. zyphra_textnorm-0.1.0/src/lang/zh/verbalizers/measure.rs +55 -0
  477. zyphra_textnorm-0.1.0/src/lang/zh/verbalizers/mod.rs +229 -0
  478. zyphra_textnorm-0.1.0/src/lang/zh/verbalizers/money.rs +83 -0
  479. zyphra_textnorm-0.1.0/src/lang/zh/verbalizers/ordinal.rs +70 -0
  480. zyphra_textnorm-0.1.0/src/lang/zh/verbalizers/time.rs +139 -0
  481. zyphra_textnorm-0.1.0/src/lang/zh/verbalizers/whitelist.rs +27 -0
  482. zyphra_textnorm-0.1.0/src/lattice.rs +397 -0
  483. zyphra_textnorm-0.1.0/src/lib.rs +68 -0
  484. zyphra_textnorm-0.1.0/src/moses.rs +181 -0
  485. zyphra_textnorm-0.1.0/src/permute.rs +239 -0
  486. zyphra_textnorm-0.1.0/src/pipeline.rs +147 -0
  487. zyphra_textnorm-0.1.0/src/punct_post.rs +149 -0
  488. zyphra_textnorm-0.1.0/src/tag.rs +280 -0
  489. zyphra_textnorm-0.1.0/src/text.rs +527 -0
  490. zyphra_textnorm-0.1.0/src/wrapper.rs +914 -0
  491. zyphra_textnorm-0.1.0/tests/wrapper.rs +82 -0
@@ -0,0 +1,218 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "heck"
7
+ version = "0.5.0"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
10
+
11
+ [[package]]
12
+ name = "itoa"
13
+ version = "1.0.19"
14
+ source = "registry+https://github.com/rust-lang/crates.io-index"
15
+ checksum = "3bd1574e617a9a6c1f8f8181bd7e841e1f20e4277607ef28945765188d6284d4"
16
+
17
+ [[package]]
18
+ name = "libc"
19
+ version = "0.2.191"
20
+ source = "registry+https://github.com/rust-lang/crates.io-index"
21
+ checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a"
22
+
23
+ [[package]]
24
+ name = "memchr"
25
+ version = "2.8.3"
26
+ source = "registry+https://github.com/rust-lang/crates.io-index"
27
+ checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
28
+
29
+ [[package]]
30
+ name = "once_cell"
31
+ version = "1.21.4"
32
+ source = "registry+https://github.com/rust-lang/crates.io-index"
33
+ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
34
+
35
+ [[package]]
36
+ name = "portable-atomic"
37
+ version = "1.15.0"
38
+ source = "registry+https://github.com/rust-lang/crates.io-index"
39
+ checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85"
40
+
41
+ [[package]]
42
+ name = "proc-macro2"
43
+ version = "1.0.107"
44
+ source = "registry+https://github.com/rust-lang/crates.io-index"
45
+ checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
46
+ dependencies = [
47
+ "unicode-ident",
48
+ ]
49
+
50
+ [[package]]
51
+ name = "pyo3"
52
+ version = "0.30.1"
53
+ source = "registry+https://github.com/rust-lang/crates.io-index"
54
+ checksum = "229ca13b8a15bb0d1487b81ab975bfcd97513416499a8312011b6036e42e0de4"
55
+ dependencies = [
56
+ "libc",
57
+ "once_cell",
58
+ "portable-atomic",
59
+ "pyo3-build-config",
60
+ "pyo3-ffi",
61
+ "pyo3-macros",
62
+ ]
63
+
64
+ [[package]]
65
+ name = "pyo3-build-config"
66
+ version = "0.30.1"
67
+ source = "registry+https://github.com/rust-lang/crates.io-index"
68
+ checksum = "70130e2b6dd1ee589a8788026a429561ca5c40fa7a2fa7914c2282eddae24700"
69
+ dependencies = [
70
+ "target-lexicon",
71
+ ]
72
+
73
+ [[package]]
74
+ name = "pyo3-ffi"
75
+ version = "0.30.1"
76
+ source = "registry+https://github.com/rust-lang/crates.io-index"
77
+ checksum = "5e7ff73c555c286d212d4ce7e5fbda845a973c4f61bd5f160f5f2c3c2a04d1c4"
78
+ dependencies = [
79
+ "libc",
80
+ "pyo3-build-config",
81
+ ]
82
+
83
+ [[package]]
84
+ name = "pyo3-macros"
85
+ version = "0.30.1"
86
+ source = "registry+https://github.com/rust-lang/crates.io-index"
87
+ checksum = "c46d2e5862c7bb8207e3b639f713dda3c499933444784154c11d013c5a691b60"
88
+ dependencies = [
89
+ "proc-macro2",
90
+ "pyo3-macros-backend",
91
+ "quote",
92
+ "syn",
93
+ ]
94
+
95
+ [[package]]
96
+ name = "pyo3-macros-backend"
97
+ version = "0.30.1"
98
+ source = "registry+https://github.com/rust-lang/crates.io-index"
99
+ checksum = "38b89f066f2ae72a2aef52d1537ca2fcd104440ebfadee06e97aa90738a25b9b"
100
+ dependencies = [
101
+ "heck",
102
+ "proc-macro2",
103
+ "quote",
104
+ "syn",
105
+ ]
106
+
107
+ [[package]]
108
+ name = "quote"
109
+ version = "1.0.47"
110
+ source = "registry+https://github.com/rust-lang/crates.io-index"
111
+ checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
112
+ dependencies = [
113
+ "proc-macro2",
114
+ ]
115
+
116
+ [[package]]
117
+ name = "ruzstd"
118
+ version = "0.9.1"
119
+ source = "registry+https://github.com/rust-lang/crates.io-index"
120
+ checksum = "69e4ce4a039f42bf25920b95667e4d789e98749ab11bbb8d2c2936f788421bb5"
121
+ dependencies = [
122
+ "twox-hash",
123
+ ]
124
+
125
+ [[package]]
126
+ name = "serde"
127
+ version = "1.0.229"
128
+ source = "registry+https://github.com/rust-lang/crates.io-index"
129
+ checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
130
+ dependencies = [
131
+ "serde_core",
132
+ "serde_derive",
133
+ ]
134
+
135
+ [[package]]
136
+ name = "serde_core"
137
+ version = "1.0.229"
138
+ source = "registry+https://github.com/rust-lang/crates.io-index"
139
+ checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
140
+ dependencies = [
141
+ "serde_derive",
142
+ ]
143
+
144
+ [[package]]
145
+ name = "serde_derive"
146
+ version = "1.0.229"
147
+ source = "registry+https://github.com/rust-lang/crates.io-index"
148
+ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
149
+ dependencies = [
150
+ "proc-macro2",
151
+ "quote",
152
+ "syn",
153
+ ]
154
+
155
+ [[package]]
156
+ name = "serde_json"
157
+ version = "1.0.154"
158
+ source = "registry+https://github.com/rust-lang/crates.io-index"
159
+ checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6"
160
+ dependencies = [
161
+ "itoa",
162
+ "memchr",
163
+ "serde",
164
+ "serde_core",
165
+ "zmij",
166
+ ]
167
+
168
+ [[package]]
169
+ name = "syn"
170
+ version = "3.0.10"
171
+ source = "registry+https://github.com/rust-lang/crates.io-index"
172
+ checksum = "4ae9ccbea3a7b0b09443036490c8f34a8b1b760fd345e5c0dae0aac718faea79"
173
+ dependencies = [
174
+ "proc-macro2",
175
+ "quote",
176
+ "unicode-ident",
177
+ ]
178
+
179
+ [[package]]
180
+ name = "target-lexicon"
181
+ version = "0.13.5"
182
+ source = "registry+https://github.com/rust-lang/crates.io-index"
183
+ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
184
+
185
+ [[package]]
186
+ name = "twox-hash"
187
+ version = "2.1.5"
188
+ source = "registry+https://github.com/rust-lang/crates.io-index"
189
+ checksum = "86a801b3cea342a06d468c8710662aa29e5e05e4f5c0d62f00bbb7f2ad7941c2"
190
+
191
+ [[package]]
192
+ name = "unicode-ident"
193
+ version = "1.0.27"
194
+ source = "registry+https://github.com/rust-lang/crates.io-index"
195
+ checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563"
196
+
197
+ [[package]]
198
+ name = "zmij"
199
+ version = "1.0.23"
200
+ source = "registry+https://github.com/rust-lang/crates.io-index"
201
+ checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
202
+
203
+ [[package]]
204
+ name = "zyphra-textnorm"
205
+ version = "0.1.0"
206
+ dependencies = [
207
+ "ruzstd",
208
+ "serde",
209
+ "serde_json",
210
+ ]
211
+
212
+ [[package]]
213
+ name = "zyphra-textnorm-py"
214
+ version = "0.1.0"
215
+ dependencies = [
216
+ "pyo3",
217
+ "zyphra-textnorm",
218
+ ]
@@ -0,0 +1,87 @@
1
+ [package]
2
+ name = "zyphra-textnorm"
3
+ version.workspace = true
4
+ description = "Text normalization for TTS (written form to spoken form) in nine languages: hand-written Rust ports of the NeMo r1.2.0 grammars, no FST runtime"
5
+ edition.workspace = true
6
+ rust-version.workspace = true
7
+ license.workspace = true
8
+ repository.workspace = true
9
+ readme = "README.md"
10
+ keywords = ["tts", "text-normalization", "speech", "nemo"]
11
+ categories = ["text-processing", "internationalization"]
12
+ # The oracle, its corpus and goldens (≈ 15 MB) stay in the repository: the crate ships the library, its tables and
13
+ # the tests that need no golden.
14
+ include = [
15
+ "/src/**",
16
+ "/data/**",
17
+ "/include/**",
18
+ "/examples/**",
19
+ "/benches/**",
20
+ "/tests/wrapper.rs",
21
+ "/README.md",
22
+ "/LICENSE",
23
+ "/NOTICE",
24
+ "/licenses/**",
25
+ ]
26
+
27
+ [workspace]
28
+ members = ["python"]
29
+
30
+ [workspace.package]
31
+ version = "0.1.0"
32
+ edition = "2024"
33
+ # let chains
34
+ rust-version = "1.88"
35
+ license = "MIT AND Apache-2.0"
36
+ repository = "https://github.com/Zyphra/zyphra-textnorm"
37
+
38
+ [lib]
39
+ name = "zyphra_textnorm"
40
+
41
+ [features]
42
+ # One feature per grammar package; a port is built and tested alone with `--no-default-features --features lang-<l>`.
43
+ default = ["lang-en", "lang-de", "lang-es", "lang-fr", "lang-it", "lang-pt", "lang-ja", "lang-zh", "lang-ko"]
44
+ lang-en = []
45
+ lang-de = []
46
+ lang-es = []
47
+ lang-fr = []
48
+ lang-it = []
49
+ lang-pt = []
50
+ lang-ja = []
51
+ lang-zh = []
52
+ lang-ko = []
53
+ # The C ABI (include/zyphra_textnorm.h). Build the static library with
54
+ # `cargo rustc --release --lib --features capi --crate-type staticlib`.
55
+ capi = []
56
+
57
+ [dependencies]
58
+
59
+ [dev-dependencies]
60
+ # The goldens are committed zstd-compressed (tests/golden/*.jsonl.zst); pure-Rust decoder.
61
+ ruzstd = "0.9"
62
+ serde = { version = "1", features = ["derive"] }
63
+ serde_json = "1"
64
+
65
+ [[bench]]
66
+ name = "normalize"
67
+ harness = false
68
+
69
+ # The differential tests read tests/golden/ (repository only).
70
+ [[test]]
71
+ name = "golden"
72
+ path = "tests/golden.rs"
73
+
74
+ [[test]]
75
+ name = "en_cardinal"
76
+ path = "tests/en_cardinal.rs"
77
+
78
+ [profile.release]
79
+ lto = "fat"
80
+ codegen-units = 1
81
+ opt-level = 3
82
+ # unwind, not abort: a grammar panic becomes a grammar failure (the sentence kept as typed). Under panic = "abort" it
83
+ # aborts the process instead.
84
+ panic = "unwind"
85
+
86
+ [profile.bench]
87
+ inherits = "release"
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zyphra, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,32 @@
1
+ zyphra-textnorm
2
+ Copyright (c) 2026 Zyphra, Inc.
3
+
4
+ The original code of this project is under the MIT License (LICENSE). It includes the third-party components below;
5
+ the full text of each license is in licenses/.
6
+
7
+ ================================================================================
8
+ 1. NVIDIA NeMo-text-processing
9
+ https://github.com/NVIDIA/NeMo-text-processing
10
+ Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES
11
+ Portions Copyright 2015 and onwards Google, Inc.
12
+ SPDX-License-Identifier: Apache-2.0
13
+ Full license: licenses/nemo-Apache-2.0.txt
14
+
15
+ The Rust grammars in src/lang/ are a port of the r1.2.0 text_normalization
16
+ grammars, and the tables in data/ (except data/perluniprops/ and
17
+ data/unicode/) are copies of their data files. The r1.2.0 package itself is
18
+ vendored under oracle/nemo_text_processing/ (the differential-test oracle;
19
+ not part of the library or its packages), with its copyright and Apache-2.0
20
+ headers retained in each file. oracle/upstream_cases/ holds the r1.2.0 test
21
+ cases.
22
+
23
+ ================================================================================
24
+ 2. sacremoses
25
+ https://github.com/hplt-project/sacremoses
26
+ Copyright (c) 2020 alvations
27
+ SPDX-License-Identifier: MIT
28
+ Full license: licenses/sacremoses-MIT.txt
29
+
30
+ MosesDetokenizer and the perluniprops IsAlpha/IsSc tables are ported in
31
+ src/moses.rs and data/perluniprops/.
32
+ ================================================================================
@@ -0,0 +1,156 @@
1
+ Metadata-Version: 2.4
2
+ Name: zyphra-textnorm
3
+ Version: 0.1.0
4
+ Classifier: Programming Language :: Rust
5
+ Classifier: Programming Language :: Python :: Implementation :: CPython
6
+ Classifier: Topic :: Text Processing :: Linguistic
7
+ License-File: LICENSE
8
+ License-File: NOTICE
9
+ License-File: licenses/nemo-Apache-2.0.txt
10
+ License-File: licenses/sacremoses-MIT.txt
11
+ Summary: Text normalization for TTS (written form to spoken form) in nine languages: Rust ports of the NeMo r1.2.0 grammars
12
+ Keywords: tts,text-normalization,speech,nemo
13
+ License-Expression: MIT AND Apache-2.0
14
+ Requires-Python: >=3.9
15
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
16
+ Project-URL: Repository, https://github.com/Zyphra/zyphra-textnorm
17
+
18
+ # zyphra-textnorm
19
+
20
+ Text normalization for text-to-speech: written text to its spoken form ("$5.32" → "five dollars thirty two cents"),
21
+ for English, German, Spanish, French, Italian, Portuguese, Japanese, Mandarin Chinese and Korean. These are
22
+ hand-written Rust ports of the [NeMo-text-processing](https://github.com/NVIDIA/NeMo-text-processing) r1.2.0
23
+ grammars. There is no FST runtime and no pynini: every grammar is Rust code, every table is embedded at compile
24
+ time, and nothing is loaded at runtime. One library serves Rust, Python and C, with a 1024-entry memo per normalizer.
25
+
26
+ Every grammar call and every end-to-end output equals the NeMo pipeline on a differential corpus of 92,953 lines
27
+ (see [Parity](#parity)), at 13-20 µs per 100 characters.
28
+
29
+ ## Use
30
+
31
+ ```rust
32
+ use zyphra_textnorm::Normalizer;
33
+
34
+ assert_eq!(zyphra_textnorm::normalize("It costs $5.32.", "en"), "It costs five dollars thirty two cents.");
35
+ let tn = Normalizer::with_markup_tags(["laugh", "shouting"]);
36
+ assert_eq!(tn.normalize("So I said <laugh/> no way, $5.", "en"), "So I said <laugh/> no way, five dollars.");
37
+ ```
38
+
39
+ ```python
40
+ import zyphra_textnorm
41
+
42
+ zyphra_textnorm.normalize("Am 3. Oktober kostete es 5,32 €.", "de")
43
+ # 'Am dritter oktober kostete es fünf komma drei zwei €.'
44
+ tn = zyphra_textnorm.Normalizer(markup_tags=["laugh"])
45
+ tn.normalize("So I said <laugh/> no way, $5.", "en")
46
+ ```
47
+
48
+ ```c
49
+ #include "zyphra_textnorm.h"
50
+
51
+ zyphra_textnorm *tn = zyphra_textnorm_new("laugh\nshouting", 14);
52
+ char *out = zyphra_textnorm_normalize(tn, text, text_len, "en", 2);
53
+ /* ... */
54
+ zyphra_textnorm_free(out);
55
+ zyphra_textnorm_delete(tn);
56
+ ```
57
+
58
+ - **Languages**: `LANGUAGES` = `en de es fr it pt ja zh ko` (NeMo's names; `zh` is Mandarin). `supported(lang)` says
59
+ whether this build has a grammar. One cargo feature per language (`lang-en` …), all on by default.
60
+ - **Never fails**: a language without a grammar comes back with its line breaks collapsed, and a sentence the
61
+ grammar fails on is kept as typed (the rest of the text is still normalized).
62
+ - **Line breaks**: every whitespace run holding a line break, tab or other non-space whitespace becomes one space
63
+ first (`collapse_line_breaks`); runs of plain spaces are kept.
64
+ - **Markup** (`Normalizer::with_markup_tags`): the markup of the given tag names stays as typed: point tags
65
+ (`<laugh/>`, `<laugh>`) and span tags (`<shouting>…</shouting>`, `\s*` allowed before `/` or `>`), and the text
66
+ between markers is normalized piece by piece. Without tags, `<…>` is text like any other.
67
+ - **Verbatim spans**: anything between U+E000 and U+E001 (e.g. a pronunciation) is kept as typed.
68
+ - **Memo**: each `Normalizer` remembers its last 1024 results, shared by every thread that calls it;
69
+ `normalize(text, lang)` uses one shared normalizer without markup tags.
70
+
71
+ The output is the spoken form the NeMo grammars produce, quirks included: they are ported as they are, and parity is
72
+ the contract. On top of the grammars come the fixes of the wrapper the goldens were dumped with
73
+ (`oracle/reference_textnorm.py`, the wrapper of [ZONOS3](https://github.com/Zyphra/ZONOS3)): sentence punctuation
74
+ after a digit is spaced off where it breaks a grammar (pt, de, es, fr, it, ko, en), ja drops the ASCII space between
75
+ CJK characters, and en reads `24/7` and `$20k` as speech.
76
+
77
+ ## Install
78
+
79
+ | | |
80
+ | --- | --- |
81
+ | Rust | `cargo add zyphra-textnorm` (MSRV 1.88) |
82
+ | Python (≥ 3.9) | `pip install zyphra-textnorm`: abi3 wheels for Linux (manylinux, x86_64 and aarch64), macOS (x86_64, arm64) and Windows (x64, arm64); elsewhere pip builds the sdist, which needs cargo |
83
+ | C / C++ | `cargo rustc --release --lib --features capi --crate-type staticlib` → `target/release/libzyphra_textnorm.a` (`zyphra_textnorm.lib` on MSVC), header `include/zyphra_textnorm.h`. Link the platform's Rust std libraries (`-lpthread -ldl -lm` on Linux, `ws2_32 userenv ntdll bcrypt` on MSVC). |
84
+
85
+ The release profile keeps `panic = "unwind"`: a panic inside a grammar is a grammar failure (the sentence kept as
86
+ typed). A build with `panic = "abort"` aborts on one instead.
87
+
88
+ ## Layout
89
+
90
+ | Path | Contents |
91
+ | --- | --- |
92
+ | `src/` | The library: `lib.rs` (API), `wrapper.rs` (line breaks, markup, verbatim spans, per-language passes, sentence retry, memo), `pipeline.rs` (NeMo's `Normalizer.normalize`), `lattice.rs` (the tagger's Viterbi), `tag.rs`, `permute.rs`, `moses.rs`, `punct_post.rs`, `ffi.rs` (C ABI) |
93
+ | `src/lang/<l>/` | One grammar package: `taggers/` and `verbalizers/` mirror the upstream files one to one |
94
+ | `data/` | The upstream `.tsv` tables verbatim, the sacremoses perluniprops tables, frozen Unicode 15.0 tables |
95
+ | `include/` | The C header |
96
+ | `python/` | The Python extension `zyphra_textnorm` (PyO3; `pyproject.toml` at the root) |
97
+ | `oracle/` | The differential-test oracle: the vendored NeMo r1.2.0 package, the frozen reference wrapper, the Docker image, corpus and golden dump scripts |
98
+ | `tests/` | Differential tests; the corpus (`corpus/`), the oracle's outputs (`golden/*.jsonl.zst`) and the oracle-confirmed equal-cost ties the port resolves differently (`ties/`) |
99
+ | `PORTING.md` | How a NeMo grammar becomes Rust, with the verified pynini semantics |
100
+
101
+ ## Develop
102
+
103
+ ```sh
104
+ cargo test --release --features capi # unit tests + differential tests against the goldens
105
+ cargo run --release --example normalize -- en 'Save $20k.'
106
+ cargo bench # median µs per call and per 100 chars, allocations
107
+ cargo bench --no-default-features --features lang-de # one language, faster to build
108
+ uv venv && uv pip install -e . && .venv/bin/python -c 'import zyphra_textnorm'
109
+ ```
110
+
111
+ The bench warms every case before timing it and reports the median of 101 calls on a cleared memo. Run it at load
112
+ below 4: medians swing by 1.5× on a busy machine. The target is ≤ 20 µs per 100 characters on every language's line.
113
+
114
+ ## Release
115
+
116
+ The crate and the Python package share the version (`[workspace.package]` in `Cargo.toml`). Pushing a `v<version>`
117
+ tag runs `.github/workflows/release.yml`, which builds the wheels and the sdist and installs and runs each wheel on
118
+ its platform. Then:
119
+
120
+ ```sh
121
+ cargo publish -p zyphra-textnorm # crates.io
122
+ gh run download <run id> -D dist && uv publish dist/*/* # PyPI
123
+ ```
124
+
125
+ ## Parity
126
+
127
+ The goldens in `tests/golden/` are the outputs of the NeMo r1.2.0 pipeline (pynini) behind the reference wrapper
128
+ (`oracle/reference_textnorm.py`), committed `zstd -19`-compressed (the tests read the `.zst` directly; the plain
129
+ `.jsonl` the dump scripts write are gitignored). The corpus is generated from every table of each language
130
+ (`oracle/gen_corpus.py`) plus the upstream r1.2.0 test cases and handcrafted lines. The `calls` test checks every
131
+ NeMo grammar call the wrapper made, the `golden` test every end-to-end row. The only exceptions are 735 calls where
132
+ the oracle picks among paths of equal float32 cost by its compiled arc order (`tests/ties/`, PORTING.md "Ties");
133
+ a listed call that no longer differs fails as stale. The English number-name FARs, which have no source, are checked
134
+ against a 457k-row dump of the FSTs (`tests/en_cardinal.rs`).
135
+
136
+ pynini has no macOS wheel, so the oracle runs in a linux/amd64 container (Rosetta on Apple silicon):
137
+
138
+ ```sh
139
+ colima start --vz-rosetta --cpu 4 --memory 8
140
+ docker build --platform linux/amd64 -f oracle/Dockerfile -t zyphra-textnorm-oracle .
141
+ docker run --rm -v "$PWD":/repo -v "$HOME/.cache/zyphra-textnorm-oracle":/cache -w /repo zyphra-textnorm-oracle \
142
+ python oracle/dump_golden.py --cache /cache --lang en --corpus tests/corpus/en.jsonl --out tests/golden/en.jsonl
143
+ zstd -19 -f tests/golden/en.jsonl -o tests/golden/en.jsonl.zst
144
+ docker run --rm -v "$PWD":/repo -v "$HOME/.cache/zyphra-textnorm-oracle":/cache -w /repo zyphra-textnorm-oracle \
145
+ python oracle/triage.py --lang en --text 'Call me at 123 Main Street, please.'
146
+ ```
147
+
148
+ `zstd -d -k tests/golden/<l>.jsonl.zst` restores the plain file for inspection. `oracle/gen_corpus.py` (host Python)
149
+ regenerates `tests/corpus/`; `oracle/gen_unicode_tables.py` the Unicode tables (must run on CPython 3.12 / Unicode
150
+ 15.0, like the oracle).
151
+
152
+ ## License
153
+
154
+ MIT (`LICENSE`) for the original code; the grammars and tables ported from NeMo-text-processing are Apache-2.0, and
155
+ the Moses detokenizer port is MIT (sacremoses). See `NOTICE` and `licenses/`.
156
+
@@ -0,0 +1,138 @@
1
+ # zyphra-textnorm
2
+
3
+ Text normalization for text-to-speech: written text to its spoken form ("$5.32" → "five dollars thirty two cents"),
4
+ for English, German, Spanish, French, Italian, Portuguese, Japanese, Mandarin Chinese and Korean. These are
5
+ hand-written Rust ports of the [NeMo-text-processing](https://github.com/NVIDIA/NeMo-text-processing) r1.2.0
6
+ grammars. There is no FST runtime and no pynini: every grammar is Rust code, every table is embedded at compile
7
+ time, and nothing is loaded at runtime. One library serves Rust, Python and C, with a 1024-entry memo per normalizer.
8
+
9
+ Every grammar call and every end-to-end output equals the NeMo pipeline on a differential corpus of 92,953 lines
10
+ (see [Parity](#parity)), at 13-20 µs per 100 characters.
11
+
12
+ ## Use
13
+
14
+ ```rust
15
+ use zyphra_textnorm::Normalizer;
16
+
17
+ assert_eq!(zyphra_textnorm::normalize("It costs $5.32.", "en"), "It costs five dollars thirty two cents.");
18
+ let tn = Normalizer::with_markup_tags(["laugh", "shouting"]);
19
+ assert_eq!(tn.normalize("So I said <laugh/> no way, $5.", "en"), "So I said <laugh/> no way, five dollars.");
20
+ ```
21
+
22
+ ```python
23
+ import zyphra_textnorm
24
+
25
+ zyphra_textnorm.normalize("Am 3. Oktober kostete es 5,32 €.", "de")
26
+ # 'Am dritter oktober kostete es fünf komma drei zwei €.'
27
+ tn = zyphra_textnorm.Normalizer(markup_tags=["laugh"])
28
+ tn.normalize("So I said <laugh/> no way, $5.", "en")
29
+ ```
30
+
31
+ ```c
32
+ #include "zyphra_textnorm.h"
33
+
34
+ zyphra_textnorm *tn = zyphra_textnorm_new("laugh\nshouting", 14);
35
+ char *out = zyphra_textnorm_normalize(tn, text, text_len, "en", 2);
36
+ /* ... */
37
+ zyphra_textnorm_free(out);
38
+ zyphra_textnorm_delete(tn);
39
+ ```
40
+
41
+ - **Languages**: `LANGUAGES` = `en de es fr it pt ja zh ko` (NeMo's names; `zh` is Mandarin). `supported(lang)` says
42
+ whether this build has a grammar. One cargo feature per language (`lang-en` …), all on by default.
43
+ - **Never fails**: a language without a grammar comes back with its line breaks collapsed, and a sentence the
44
+ grammar fails on is kept as typed (the rest of the text is still normalized).
45
+ - **Line breaks**: every whitespace run holding a line break, tab or other non-space whitespace becomes one space
46
+ first (`collapse_line_breaks`); runs of plain spaces are kept.
47
+ - **Markup** (`Normalizer::with_markup_tags`): the markup of the given tag names stays as typed: point tags
48
+ (`<laugh/>`, `<laugh>`) and span tags (`<shouting>…</shouting>`, `\s*` allowed before `/` or `>`), and the text
49
+ between markers is normalized piece by piece. Without tags, `<…>` is text like any other.
50
+ - **Verbatim spans**: anything between U+E000 and U+E001 (e.g. a pronunciation) is kept as typed.
51
+ - **Memo**: each `Normalizer` remembers its last 1024 results, shared by every thread that calls it;
52
+ `normalize(text, lang)` uses one shared normalizer without markup tags.
53
+
54
+ The output is the spoken form the NeMo grammars produce, quirks included: they are ported as they are, and parity is
55
+ the contract. On top of the grammars come the fixes of the wrapper the goldens were dumped with
56
+ (`oracle/reference_textnorm.py`, the wrapper of [ZONOS3](https://github.com/Zyphra/ZONOS3)): sentence punctuation
57
+ after a digit is spaced off where it breaks a grammar (pt, de, es, fr, it, ko, en), ja drops the ASCII space between
58
+ CJK characters, and en reads `24/7` and `$20k` as speech.
59
+
60
+ ## Install
61
+
62
+ | | |
63
+ | --- | --- |
64
+ | Rust | `cargo add zyphra-textnorm` (MSRV 1.88) |
65
+ | Python (≥ 3.9) | `pip install zyphra-textnorm`: abi3 wheels for Linux (manylinux, x86_64 and aarch64), macOS (x86_64, arm64) and Windows (x64, arm64); elsewhere pip builds the sdist, which needs cargo |
66
+ | C / C++ | `cargo rustc --release --lib --features capi --crate-type staticlib` → `target/release/libzyphra_textnorm.a` (`zyphra_textnorm.lib` on MSVC), header `include/zyphra_textnorm.h`. Link the platform's Rust std libraries (`-lpthread -ldl -lm` on Linux, `ws2_32 userenv ntdll bcrypt` on MSVC). |
67
+
68
+ The release profile keeps `panic = "unwind"`: a panic inside a grammar is a grammar failure (the sentence kept as
69
+ typed). A build with `panic = "abort"` aborts on one instead.
70
+
71
+ ## Layout
72
+
73
+ | Path | Contents |
74
+ | --- | --- |
75
+ | `src/` | The library: `lib.rs` (API), `wrapper.rs` (line breaks, markup, verbatim spans, per-language passes, sentence retry, memo), `pipeline.rs` (NeMo's `Normalizer.normalize`), `lattice.rs` (the tagger's Viterbi), `tag.rs`, `permute.rs`, `moses.rs`, `punct_post.rs`, `ffi.rs` (C ABI) |
76
+ | `src/lang/<l>/` | One grammar package: `taggers/` and `verbalizers/` mirror the upstream files one to one |
77
+ | `data/` | The upstream `.tsv` tables verbatim, the sacremoses perluniprops tables, frozen Unicode 15.0 tables |
78
+ | `include/` | The C header |
79
+ | `python/` | The Python extension `zyphra_textnorm` (PyO3; `pyproject.toml` at the root) |
80
+ | `oracle/` | The differential-test oracle: the vendored NeMo r1.2.0 package, the frozen reference wrapper, the Docker image, corpus and golden dump scripts |
81
+ | `tests/` | Differential tests; the corpus (`corpus/`), the oracle's outputs (`golden/*.jsonl.zst`) and the oracle-confirmed equal-cost ties the port resolves differently (`ties/`) |
82
+ | `PORTING.md` | How a NeMo grammar becomes Rust, with the verified pynini semantics |
83
+
84
+ ## Develop
85
+
86
+ ```sh
87
+ cargo test --release --features capi # unit tests + differential tests against the goldens
88
+ cargo run --release --example normalize -- en 'Save $20k.'
89
+ cargo bench # median µs per call and per 100 chars, allocations
90
+ cargo bench --no-default-features --features lang-de # one language, faster to build
91
+ uv venv && uv pip install -e . && .venv/bin/python -c 'import zyphra_textnorm'
92
+ ```
93
+
94
+ The bench warms every case before timing it and reports the median of 101 calls on a cleared memo. Run it at load
95
+ below 4: medians swing by 1.5× on a busy machine. The target is ≤ 20 µs per 100 characters on every language's line.
96
+
97
+ ## Release
98
+
99
+ The crate and the Python package share the version (`[workspace.package]` in `Cargo.toml`). Pushing a `v<version>`
100
+ tag runs `.github/workflows/release.yml`, which builds the wheels and the sdist and installs and runs each wheel on
101
+ its platform. Then:
102
+
103
+ ```sh
104
+ cargo publish -p zyphra-textnorm # crates.io
105
+ gh run download <run id> -D dist && uv publish dist/*/* # PyPI
106
+ ```
107
+
108
+ ## Parity
109
+
110
+ The goldens in `tests/golden/` are the outputs of the NeMo r1.2.0 pipeline (pynini) behind the reference wrapper
111
+ (`oracle/reference_textnorm.py`), committed `zstd -19`-compressed (the tests read the `.zst` directly; the plain
112
+ `.jsonl` the dump scripts write are gitignored). The corpus is generated from every table of each language
113
+ (`oracle/gen_corpus.py`) plus the upstream r1.2.0 test cases and handcrafted lines. The `calls` test checks every
114
+ NeMo grammar call the wrapper made, the `golden` test every end-to-end row. The only exceptions are 735 calls where
115
+ the oracle picks among paths of equal float32 cost by its compiled arc order (`tests/ties/`, PORTING.md "Ties");
116
+ a listed call that no longer differs fails as stale. The English number-name FARs, which have no source, are checked
117
+ against a 457k-row dump of the FSTs (`tests/en_cardinal.rs`).
118
+
119
+ pynini has no macOS wheel, so the oracle runs in a linux/amd64 container (Rosetta on Apple silicon):
120
+
121
+ ```sh
122
+ colima start --vz-rosetta --cpu 4 --memory 8
123
+ docker build --platform linux/amd64 -f oracle/Dockerfile -t zyphra-textnorm-oracle .
124
+ docker run --rm -v "$PWD":/repo -v "$HOME/.cache/zyphra-textnorm-oracle":/cache -w /repo zyphra-textnorm-oracle \
125
+ python oracle/dump_golden.py --cache /cache --lang en --corpus tests/corpus/en.jsonl --out tests/golden/en.jsonl
126
+ zstd -19 -f tests/golden/en.jsonl -o tests/golden/en.jsonl.zst
127
+ docker run --rm -v "$PWD":/repo -v "$HOME/.cache/zyphra-textnorm-oracle":/cache -w /repo zyphra-textnorm-oracle \
128
+ python oracle/triage.py --lang en --text 'Call me at 123 Main Street, please.'
129
+ ```
130
+
131
+ `zstd -d -k tests/golden/<l>.jsonl.zst` restores the plain file for inspection. `oracle/gen_corpus.py` (host Python)
132
+ regenerates `tests/corpus/`; `oracle/gen_unicode_tables.py` the Unicode tables (must run on CPython 3.12 / Unicode
133
+ 15.0, like the oracle).
134
+
135
+ ## License
136
+
137
+ MIT (`LICENSE`) for the original code; the grammars and tables ported from NeMo-text-processing are Apache-2.0, and
138
+ the Moses detokenizer port is MIT (sacremoses). See `NOTICE` and `licenses/`.