BabelDOC 0.3.62__tar.gz → 0.3.64__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 (295) hide show
  1. {babeldoc-0.3.62 → babeldoc-0.3.64}/PKG-INFO +16 -3
  2. {babeldoc-0.3.62 → babeldoc-0.3.64}/README.md +15 -2
  3. babeldoc-0.3.64/babeldoc/__init__.py +1 -0
  4. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/assets/embedding_assets_metadata.py +21 -21
  5. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/const.py +1 -1
  6. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/backend/pdf_creater.py +5 -1
  7. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/midend/detect_scanned_file.py +30 -6
  8. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/midend/il_translator.py +1 -1
  9. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/midend/il_translator_llm_only.py +2 -2
  10. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/utils/fontmap.py +37 -0
  11. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/docvision/doclayout.py +1 -1
  12. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/docvision/rpc_doclayout.py +1 -1
  13. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/docvision/table_detection/rapidocr.py +1 -1
  14. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/high_level.py +43 -6
  15. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/main.py +17 -1
  16. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/tools/generate_font_metadata.py +15 -1
  17. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/translation_config.py +16 -0
  18. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/CONTRIBUTOR_REWARD.md +8 -1
  19. {babeldoc-0.3.62 → babeldoc-0.3.64}/pyproject.toml +2 -2
  20. {babeldoc-0.3.62 → babeldoc-0.3.64}/uv.lock +148 -64
  21. babeldoc-0.3.62/babeldoc/__init__.py +0 -1
  22. {babeldoc-0.3.62 → babeldoc-0.3.64}/.cursorignore +0 -0
  23. {babeldoc-0.3.62 → babeldoc-0.3.64}/.github/ISSUE_TEMPLATE/bug_report.yaml +0 -0
  24. {babeldoc-0.3.62 → babeldoc-0.3.64}/.github/ISSUE_TEMPLATE/feature_request.yaml +0 -0
  25. {babeldoc-0.3.62 → babeldoc-0.3.64}/.github/PULL_REQUEST_TEMPLATE/pr_form.yml +0 -0
  26. {babeldoc-0.3.62 → babeldoc-0.3.64}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  27. {babeldoc-0.3.62 → babeldoc-0.3.64}/.github/dependabot.yml +0 -0
  28. {babeldoc-0.3.62 → babeldoc-0.3.64}/.github/labels.yml +0 -0
  29. {babeldoc-0.3.62 → babeldoc-0.3.64}/.github/release-drafter.yml +0 -0
  30. {babeldoc-0.3.62 → babeldoc-0.3.64}/.github/workflows/codeql.yml +0 -0
  31. {babeldoc-0.3.62 → babeldoc-0.3.64}/.github/workflows/docs.yml +0 -0
  32. {babeldoc-0.3.62 → babeldoc-0.3.64}/.github/workflows/labeler.yml +0 -0
  33. {babeldoc-0.3.62 → babeldoc-0.3.64}/.github/workflows/lint.yml +0 -0
  34. {babeldoc-0.3.62 → babeldoc-0.3.64}/.github/workflows/pr-lint.yml +0 -0
  35. {babeldoc-0.3.62 → babeldoc-0.3.64}/.github/workflows/publish-to-pypi.yml +0 -0
  36. {babeldoc-0.3.62 → babeldoc-0.3.64}/.github/workflows/test.yml +0 -0
  37. {babeldoc-0.3.62 → babeldoc-0.3.64}/.gitignore +0 -0
  38. {babeldoc-0.3.62 → babeldoc-0.3.64}/.pre-commit-config.yaml +0 -0
  39. {babeldoc-0.3.62 → babeldoc-0.3.64}/LICENSE +0 -0
  40. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/assets/assets.py +0 -0
  41. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/asynchronize/__init__.py +0 -0
  42. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/converter.py +0 -0
  43. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/__init__.py +0 -0
  44. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/babeldoc_exception/BabelDOCException.py +0 -0
  45. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/backend/__init__.py +0 -0
  46. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/frontend/__init__.py +0 -0
  47. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/frontend/il_creater.py +0 -0
  48. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/il_version_1.py +0 -0
  49. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/il_version_1.rnc +0 -0
  50. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/il_version_1.rng +0 -0
  51. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/il_version_1.xsd +0 -0
  52. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/midend/__init__.py +0 -0
  53. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/midend/add_debug_information.py +0 -0
  54. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/midend/automatic_term_extractor.py +0 -0
  55. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/midend/layout_parser.py +0 -0
  56. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/midend/paragraph_finder.py +0 -0
  57. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/midend/remove_descent.py +0 -0
  58. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/midend/styles_and_formulas.py +0 -0
  59. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/midend/table_parser.py +0 -0
  60. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/midend/typesetting.py +0 -0
  61. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/translator/__init__.py +0 -0
  62. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/translator/cache.py +0 -0
  63. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/translator/translator.py +0 -0
  64. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/utils/atomic_integer.py +0 -0
  65. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/utils/layout_helper.py +0 -0
  66. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/utils/mupdf_helper.py +0 -0
  67. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/utils/paragraph_helper.py +0 -0
  68. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/utils/priority_thread_pool_executor.py +0 -0
  69. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/utils/style_helper.py +0 -0
  70. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/utils/zstd_helper.py +0 -0
  71. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/document_il/xml_converter.py +0 -0
  72. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/docvision/README.md +0 -0
  73. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/docvision/__init__.py +0 -0
  74. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/docvision/base_doclayout.py +0 -0
  75. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/format/office/__init__.py +0 -0
  76. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/glossary.py +0 -0
  77. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfinterp.py +0 -0
  78. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/LICENSE +0 -0
  79. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/__init__.py +0 -0
  80. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/_saslprep.py +0 -0
  81. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/arcfour.py +0 -0
  82. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/ascii85.py +0 -0
  83. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/casting.py +0 -0
  84. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/ccitt.py +0 -0
  85. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/78-EUC-H.pickle.gz +0 -0
  86. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/78-EUC-V.pickle.gz +0 -0
  87. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/78-H.pickle.gz +0 -0
  88. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/78-RKSJ-H.pickle.gz +0 -0
  89. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/78-RKSJ-V.pickle.gz +0 -0
  90. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/78-V.pickle.gz +0 -0
  91. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/78ms-RKSJ-H.pickle.gz +0 -0
  92. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/78ms-RKSJ-V.pickle.gz +0 -0
  93. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/83pv-RKSJ-H.pickle.gz +0 -0
  94. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/83pv-RKSJ-V.pickle.gz +0 -0
  95. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/90ms-RKSJ-H.pickle.gz +0 -0
  96. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/90ms-RKSJ-V.pickle.gz +0 -0
  97. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/90msp-RKSJ-H.pickle.gz +0 -0
  98. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/90msp-RKSJ-V.pickle.gz +0 -0
  99. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/90pv-RKSJ-H.pickle.gz +0 -0
  100. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/90pv-RKSJ-V.pickle.gz +0 -0
  101. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/Add-H.pickle.gz +0 -0
  102. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/Add-RKSJ-H.pickle.gz +0 -0
  103. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/Add-RKSJ-V.pickle.gz +0 -0
  104. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/Add-V.pickle.gz +0 -0
  105. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/B5-H.pickle.gz +0 -0
  106. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/B5-V.pickle.gz +0 -0
  107. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/B5pc-H.pickle.gz +0 -0
  108. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/B5pc-V.pickle.gz +0 -0
  109. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/CNS-EUC-H.pickle.gz +0 -0
  110. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/CNS-EUC-V.pickle.gz +0 -0
  111. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/CNS1-H.pickle.gz +0 -0
  112. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/CNS1-V.pickle.gz +0 -0
  113. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/CNS2-H.pickle.gz +0 -0
  114. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/CNS2-V.pickle.gz +0 -0
  115. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/ETHK-B5-H.pickle.gz +0 -0
  116. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/ETHK-B5-V.pickle.gz +0 -0
  117. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/ETen-B5-H.pickle.gz +0 -0
  118. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/ETen-B5-V.pickle.gz +0 -0
  119. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/ETenms-B5-H.pickle.gz +0 -0
  120. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/ETenms-B5-V.pickle.gz +0 -0
  121. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/EUC-H.pickle.gz +0 -0
  122. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/EUC-V.pickle.gz +0 -0
  123. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/Ext-H.pickle.gz +0 -0
  124. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/Ext-RKSJ-H.pickle.gz +0 -0
  125. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/Ext-RKSJ-V.pickle.gz +0 -0
  126. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/Ext-V.pickle.gz +0 -0
  127. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/GB-EUC-H.pickle.gz +0 -0
  128. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/GB-EUC-V.pickle.gz +0 -0
  129. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/GB-H.pickle.gz +0 -0
  130. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/GB-V.pickle.gz +0 -0
  131. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/GBK-EUC-H.pickle.gz +0 -0
  132. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/GBK-EUC-V.pickle.gz +0 -0
  133. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/GBK2K-H.pickle.gz +0 -0
  134. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/GBK2K-V.pickle.gz +0 -0
  135. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/GBKp-EUC-H.pickle.gz +0 -0
  136. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/GBKp-EUC-V.pickle.gz +0 -0
  137. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/GBT-EUC-H.pickle.gz +0 -0
  138. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/GBT-EUC-V.pickle.gz +0 -0
  139. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/GBT-H.pickle.gz +0 -0
  140. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/GBT-V.pickle.gz +0 -0
  141. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/GBTpc-EUC-H.pickle.gz +0 -0
  142. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/GBTpc-EUC-V.pickle.gz +0 -0
  143. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/GBpc-EUC-H.pickle.gz +0 -0
  144. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/GBpc-EUC-V.pickle.gz +0 -0
  145. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/H.pickle.gz +0 -0
  146. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/HKdla-B5-H.pickle.gz +0 -0
  147. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/HKdla-B5-V.pickle.gz +0 -0
  148. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/HKdlb-B5-H.pickle.gz +0 -0
  149. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/HKdlb-B5-V.pickle.gz +0 -0
  150. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/HKgccs-B5-H.pickle.gz +0 -0
  151. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/HKgccs-B5-V.pickle.gz +0 -0
  152. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/HKm314-B5-H.pickle.gz +0 -0
  153. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/HKm314-B5-V.pickle.gz +0 -0
  154. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/HKm471-B5-H.pickle.gz +0 -0
  155. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/HKm471-B5-V.pickle.gz +0 -0
  156. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/HKscs-B5-H.pickle.gz +0 -0
  157. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/HKscs-B5-V.pickle.gz +0 -0
  158. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/Hankaku-H.pickle.gz +0 -0
  159. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/Hankaku-V.pickle.gz +0 -0
  160. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/Hiragana-H.pickle.gz +0 -0
  161. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/Hiragana-V.pickle.gz +0 -0
  162. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/KSC-EUC-H.pickle.gz +0 -0
  163. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/KSC-EUC-V.pickle.gz +0 -0
  164. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/KSC-H.pickle.gz +0 -0
  165. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/KSC-Johab-H.pickle.gz +0 -0
  166. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/KSC-Johab-V.pickle.gz +0 -0
  167. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/KSC-V.pickle.gz +0 -0
  168. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/KSCms-UHC-H.pickle.gz +0 -0
  169. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/KSCms-UHC-HW-H.pickle.gz +0 -0
  170. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/KSCms-UHC-HW-V.pickle.gz +0 -0
  171. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/KSCms-UHC-V.pickle.gz +0 -0
  172. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/KSCpc-EUC-H.pickle.gz +0 -0
  173. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/KSCpc-EUC-V.pickle.gz +0 -0
  174. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/Katakana-H.pickle.gz +0 -0
  175. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/Katakana-V.pickle.gz +0 -0
  176. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/NWP-H.pickle.gz +0 -0
  177. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/NWP-V.pickle.gz +0 -0
  178. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/README.txt +0 -0
  179. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/RKSJ-H.pickle.gz +0 -0
  180. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/RKSJ-V.pickle.gz +0 -0
  181. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/Roman-H.pickle.gz +0 -0
  182. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/Roman-V.pickle.gz +0 -0
  183. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniCNS-UCS2-H.pickle.gz +0 -0
  184. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniCNS-UCS2-V.pickle.gz +0 -0
  185. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniCNS-UTF16-H.pickle.gz +0 -0
  186. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniCNS-UTF16-V.pickle.gz +0 -0
  187. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniCNS-UTF32-H.pickle.gz +0 -0
  188. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniCNS-UTF32-V.pickle.gz +0 -0
  189. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniCNS-UTF8-H.pickle.gz +0 -0
  190. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniCNS-UTF8-V.pickle.gz +0 -0
  191. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniGB-UCS2-H.pickle.gz +0 -0
  192. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniGB-UCS2-V.pickle.gz +0 -0
  193. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniGB-UTF16-H.pickle.gz +0 -0
  194. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniGB-UTF16-V.pickle.gz +0 -0
  195. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniGB-UTF32-H.pickle.gz +0 -0
  196. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniGB-UTF32-V.pickle.gz +0 -0
  197. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniGB-UTF8-H.pickle.gz +0 -0
  198. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniGB-UTF8-V.pickle.gz +0 -0
  199. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJIS-UCS2-H.pickle.gz +0 -0
  200. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJIS-UCS2-HW-H.pickle.gz +0 -0
  201. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJIS-UCS2-HW-V.pickle.gz +0 -0
  202. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJIS-UCS2-V.pickle.gz +0 -0
  203. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJIS-UTF16-H.pickle.gz +0 -0
  204. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJIS-UTF16-V.pickle.gz +0 -0
  205. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJIS-UTF32-H.pickle.gz +0 -0
  206. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJIS-UTF32-V.pickle.gz +0 -0
  207. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJIS-UTF8-H.pickle.gz +0 -0
  208. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJIS-UTF8-V.pickle.gz +0 -0
  209. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJIS2004-UTF16-H.pickle.gz +0 -0
  210. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJIS2004-UTF16-V.pickle.gz +0 -0
  211. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJIS2004-UTF32-H.pickle.gz +0 -0
  212. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJIS2004-UTF32-V.pickle.gz +0 -0
  213. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJIS2004-UTF8-H.pickle.gz +0 -0
  214. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJIS2004-UTF8-V.pickle.gz +0 -0
  215. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJISX0213-UTF32-H.pickle.gz +0 -0
  216. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJISX0213-UTF32-V.pickle.gz +0 -0
  217. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJISX02132004-UTF32-H.pickle.gz +0 -0
  218. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniJISX02132004-UTF32-V.pickle.gz +0 -0
  219. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniKS-UCS2-H.pickle.gz +0 -0
  220. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniKS-UCS2-V.pickle.gz +0 -0
  221. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniKS-UTF16-H.pickle.gz +0 -0
  222. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniKS-UTF16-V.pickle.gz +0 -0
  223. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniKS-UTF32-H.pickle.gz +0 -0
  224. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniKS-UTF32-V.pickle.gz +0 -0
  225. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniKS-UTF8-H.pickle.gz +0 -0
  226. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/UniKS-UTF8-V.pickle.gz +0 -0
  227. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/V.pickle.gz +0 -0
  228. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/WP-Symbol-H.pickle.gz +0 -0
  229. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/WP-Symbol-V.pickle.gz +0 -0
  230. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/to-unicode-Adobe-CNS1.pickle.gz +0 -0
  231. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/to-unicode-Adobe-GB1.pickle.gz +0 -0
  232. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/to-unicode-Adobe-Japan1.pickle.gz +0 -0
  233. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmap/to-unicode-Adobe-Korea1.pickle.gz +0 -0
  234. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/cmapdb.py +0 -0
  235. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/converter.py +0 -0
  236. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/data_structures.py +0 -0
  237. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/encodingdb.py +0 -0
  238. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/fontmetrics.py +0 -0
  239. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/glyphlist.py +0 -0
  240. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/high_level.py +0 -0
  241. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/image.py +0 -0
  242. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/jbig2.py +0 -0
  243. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/latin_enc.py +0 -0
  244. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/layout.py +0 -0
  245. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/lzw.py +0 -0
  246. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/pdfcolor.py +0 -0
  247. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/pdfdevice.py +0 -0
  248. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/pdfdocument.py +0 -0
  249. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/pdfexceptions.py +0 -0
  250. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/pdffont.py +0 -0
  251. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/pdfinterp.py +0 -0
  252. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/pdfpage.py +0 -0
  253. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/pdfparser.py +0 -0
  254. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/pdftypes.py +0 -0
  255. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/psexceptions.py +0 -0
  256. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/psparser.py +0 -0
  257. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/py.typed +0 -0
  258. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/runlength.py +0 -0
  259. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/settings.py +0 -0
  260. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/pdfminer/utils.py +0 -0
  261. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/progress_monitor.py +0 -0
  262. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/result_merger.py +0 -0
  263. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/split_manager.py +0 -0
  264. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/tools/italic_assistance.py +0 -0
  265. {babeldoc-0.3.62 → babeldoc-0.3.64}/babeldoc/tools/italic_recognize_tool.py +0 -0
  266. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/CODE_OF_CONDUCT.md +0 -0
  267. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/CONTRIBUTING.md +0 -0
  268. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/ImplementationDetails/AsyncTranslate/AsyncTranslate.md +0 -0
  269. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/ImplementationDetails/ILTranslator/ILTranslator.md +0 -0
  270. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/ImplementationDetails/PDFCreation/PDFCreation.md +0 -0
  271. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/ImplementationDetails/PDFParsing/PDFParsing.md +0 -0
  272. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/ImplementationDetails/ParagraphFinding/ParagraphFinding.md +0 -0
  273. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/ImplementationDetails/README.md +0 -0
  274. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/ImplementationDetails/StylesAndFormulas/StylesAndFormulas.md +0 -0
  275. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/ImplementationDetails/Typesetting/Typesetting.md +0 -0
  276. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/README.md +0 -0
  277. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/deploy.sh +0 -0
  278. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/example/demo_glossary.csv +0 -0
  279. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/images/babeldoc-banner.png +0 -0
  280. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/images/babeldoc-big-logo-darkmode-with-transparent-background.png +0 -0
  281. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/images/babeldoc-big-logo-darkmode-with-transparent-background.svg +0 -0
  282. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/images/babeldoc-big-logo-with-transparent-background.png +0 -0
  283. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/images/babeldoc-big-logo-with-transparent-background.svg +0 -0
  284. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/images/babeldoc-big-logo.png +0 -0
  285. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/images/babeldoc-contributor_reward_example.png +0 -0
  286. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/images/babeldoc-preview.gif +0 -0
  287. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/images/babeldoc-small-logo-with-transparent-background.png +0 -0
  288. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/images/babeldoc-small-logo-with-transparent-background.svg +0 -0
  289. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/images/babeldoc-small-logo.png +0 -0
  290. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/index.md +0 -0
  291. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/intro-to-pdf-object.md +0 -0
  292. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/requirements.txt +0 -0
  293. {babeldoc-0.3.62 → babeldoc-0.3.64}/docs/supported_languages.md +0 -0
  294. {babeldoc-0.3.62 → babeldoc-0.3.64}/mkdocs.yml +0 -0
  295. {babeldoc-0.3.62 → babeldoc-0.3.64}/tests/test_translation_config.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: BabelDOC
3
- Version: 0.3.62
3
+ Version: 0.3.64
4
4
  Summary: Yet Another Document Translator
5
5
  Project-URL: Homepage, https://github.com/funstory-ai/BabelDOC
6
6
  Project-URL: Issues, https://github.com/funstory-ai/BabelDOC/issues
@@ -210,7 +210,8 @@ uv run babeldoc --files example.pdf --files example2.pdf --openai --openai-model
210
210
  - `--show-char-box`: Show character bounding boxes (debug only, default: False)
211
211
  - `--skip-scanned-detection`: Skip scanned document detection (default: False). When using split translation, only the first part performs detection if not skipped.
212
212
  - `--ocr-workaround`: Use OCR workaround (default: False). Only suitable for documents with black text on white background. When enabled, white rectangular blocks will be added below the translation to cover the original text content, and all text will be forced to black color.
213
-
213
+ - `--auto-enable-ocr-workaround`: Enable automatic OCR workaround (default: False). If a document is detected as heavily scanned, this will attempt to enable OCR processing and skip further scan detection. See "Important Interaction Note" below for crucial details on how this interacts with `--ocr-workaround` and `--skip-scanned-detection`.
214
+ - `--primary-font-family`: Override primary font family for translated text. Choices: 'serif' for serif fonts, 'sans-serif' for sans-serif fonts, 'script' for script/italic fonts. If not specified, uses automatic font selection based on original text properties.
214
215
 
215
216
  - `--rpc-doclayout`: RPC service host address for document layout analysis (default: None)
216
217
  - `--working-dir`: Working directory for translation. If not set, use temp directory.
@@ -328,6 +329,7 @@ show_char_box = false # Show character bounding boxes (debug)
328
329
  ocr_workaround = false # Use OCR workaround for scanned PDFs
329
330
  rpc_doclayout = "" # RPC service host for document layout analysis
330
331
  working_dir = "" # Working directory for translation
332
+ auto_enable_ocr_workaround = false # Enable automatic OCR workaround for scanned PDFs. See docs for interaction with ocr_workaround and skip_scanned_detection.
331
333
 
332
334
  # Translation service
333
335
  openai = true
@@ -477,4 +479,15 @@ Everyone interacting in YADT and its sub-projects' codebases, issue trackers, ch
477
479
  <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=funstory-ai/babeldoc&type=Date" />
478
480
  <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=funstory-ai/babeldoc&type=Date"/>
479
481
  </picture>
480
- </a>
482
+ </a>
483
+
484
+ > [!WARNING]
485
+ > **Important Interaction Note for `--auto-enable-ocr-workaround`:**
486
+ >
487
+ > When `--auto-enable-ocr-workaround` is set to `true` (either via command line or config file):
488
+ >
489
+ > 1. During the initial setup, the values for `ocr_workaround` and `skip_scanned_detection` will be forced to `false` by `TranslationConfig`, regardless of whether you also set `--ocr-workaround` or `--skip-scanned-detection` flags.
490
+ > 2. Then, during the scanned document detection phase (`DetectScannedFile` stage):
491
+ > * If the document is identified as heavily scanned (e.g., >80% scanned pages) AND `auto_enable_ocr_workaround` is `true` (i.e., `translation_config.auto_enable_ocr_workaround` is true), the system will then attempt to set both `ocr_workaround` to `true` and `skip_scanned_detection` to `true`.
492
+ >
493
+ > This means that `--auto-enable-ocr-workaround` effectively gives the system control to enable OCR processing for scanned documents, potentially overriding manual settings for `--ocr-workaround` and `--skip_scanned_detection` based on its detection results. If the document is *not* detected as heavily scanned, then the initial `false` values for `ocr_workaround` and `skip_scanned_detection` (forced by `--auto-enable-ocr-workaround` at the `TranslationConfig` initialization stage) will remain in effect unless changed by other logic.
@@ -159,7 +159,8 @@ uv run babeldoc --files example.pdf --files example2.pdf --openai --openai-model
159
159
  - `--show-char-box`: Show character bounding boxes (debug only, default: False)
160
160
  - `--skip-scanned-detection`: Skip scanned document detection (default: False). When using split translation, only the first part performs detection if not skipped.
161
161
  - `--ocr-workaround`: Use OCR workaround (default: False). Only suitable for documents with black text on white background. When enabled, white rectangular blocks will be added below the translation to cover the original text content, and all text will be forced to black color.
162
-
162
+ - `--auto-enable-ocr-workaround`: Enable automatic OCR workaround (default: False). If a document is detected as heavily scanned, this will attempt to enable OCR processing and skip further scan detection. See "Important Interaction Note" below for crucial details on how this interacts with `--ocr-workaround` and `--skip-scanned-detection`.
163
+ - `--primary-font-family`: Override primary font family for translated text. Choices: 'serif' for serif fonts, 'sans-serif' for sans-serif fonts, 'script' for script/italic fonts. If not specified, uses automatic font selection based on original text properties.
163
164
 
164
165
  - `--rpc-doclayout`: RPC service host address for document layout analysis (default: None)
165
166
  - `--working-dir`: Working directory for translation. If not set, use temp directory.
@@ -277,6 +278,7 @@ show_char_box = false # Show character bounding boxes (debug)
277
278
  ocr_workaround = false # Use OCR workaround for scanned PDFs
278
279
  rpc_doclayout = "" # RPC service host for document layout analysis
279
280
  working_dir = "" # Working directory for translation
281
+ auto_enable_ocr_workaround = false # Enable automatic OCR workaround for scanned PDFs. See docs for interaction with ocr_workaround and skip_scanned_detection.
280
282
 
281
283
  # Translation service
282
284
  openai = true
@@ -426,4 +428,15 @@ Everyone interacting in YADT and its sub-projects' codebases, issue trackers, ch
426
428
  <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=funstory-ai/babeldoc&type=Date" />
427
429
  <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=funstory-ai/babeldoc&type=Date"/>
428
430
  </picture>
429
- </a>
431
+ </a>
432
+
433
+ > [!WARNING]
434
+ > **Important Interaction Note for `--auto-enable-ocr-workaround`:**
435
+ >
436
+ > When `--auto-enable-ocr-workaround` is set to `true` (either via command line or config file):
437
+ >
438
+ > 1. During the initial setup, the values for `ocr_workaround` and `skip_scanned_detection` will be forced to `false` by `TranslationConfig`, regardless of whether you also set `--ocr-workaround` or `--skip-scanned-detection` flags.
439
+ > 2. Then, during the scanned document detection phase (`DetectScannedFile` stage):
440
+ > * If the document is identified as heavily scanned (e.g., >80% scanned pages) AND `auto_enable_ocr_workaround` is `true` (i.e., `translation_config.auto_enable_ocr_workaround` is true), the system will then attempt to set both `ocr_workaround` to `true` and `skip_scanned_detection` to `true`.
441
+ >
442
+ > This means that `--auto-enable-ocr-workaround` effectively gives the system control to enable OCR processing for scanned documents, potentially overriding manual settings for `--ocr-workaround` and `--skip_scanned_detection` based on its detection results. If the document is *not* detected as heavily scanned, then the initial `false` values for `ocr_workaround` and `skip_scanned_detection` (forced by `--auto-enable-ocr-workaround` at the `TranslationConfig` initialization stage) will remain in effect unless changed by other logic.
@@ -0,0 +1 @@
1
+ __version__ = "0.3.64"
@@ -49,7 +49,7 @@ EMBEDDING_FONT_METADATA = {
49
49
  "font_name": "Go Noto Kurrent-Bold Bold",
50
50
  "italic": 0,
51
51
  "monospace": 0,
52
- "serif": 1,
52
+ "serif": 0,
53
53
  "sha3_256": "000b37f592477945b27b7702dcad39f73e23e140e66ddff9847eb34f32389566",
54
54
  "size": 15303772,
55
55
  },
@@ -62,7 +62,7 @@ EMBEDDING_FONT_METADATA = {
62
62
  "font_name": "Go Noto Kurrent-Regular Regular",
63
63
  "italic": 0,
64
64
  "monospace": 0,
65
- "serif": 1,
65
+ "serif": 0,
66
66
  "sha3_256": "4324a60d507c691e6efc97420647f4d2c2d86d9de35009d1c769861b76074ae6",
67
67
  "size": 15515760,
68
68
  },
@@ -75,7 +75,7 @@ EMBEDDING_FONT_METADATA = {
75
75
  "font_name": "Klee One Regular",
76
76
  "italic": 0,
77
77
  "monospace": 0,
78
- "serif": 1,
78
+ "serif": 0,
79
79
  "sha3_256": "8585c29f89b322d937f83739f61ede5d84297873e1465cad9a120a208ac55ce0",
80
80
  "size": 8724704,
81
81
  },
@@ -88,7 +88,7 @@ EMBEDDING_FONT_METADATA = {
88
88
  "font_name": "LXGW WenKai GB Regular",
89
89
  "italic": 0,
90
90
  "monospace": 0,
91
- "serif": 1,
91
+ "serif": 0,
92
92
  "sha3_256": "b563a5e8d9db4cd15602a3a3700b01925e80a21f99fb88e1b763b1fb8685f8ee",
93
93
  "size": 19558756,
94
94
  },
@@ -101,7 +101,7 @@ EMBEDDING_FONT_METADATA = {
101
101
  "font_name": "LXGW WenKai Mono TC Regular",
102
102
  "italic": 0,
103
103
  "monospace": 1,
104
- "serif": 1,
104
+ "serif": 0,
105
105
  "sha3_256": "596b278d11418d374a1cfa3a50cbfb82b31db82d3650cfacae8f94311b27fdc5",
106
106
  "size": 13115416,
107
107
  },
@@ -114,7 +114,7 @@ EMBEDDING_FONT_METADATA = {
114
114
  "font_name": "LXGW WenKai TC Regular",
115
115
  "italic": 0,
116
116
  "monospace": 0,
117
- "serif": 1,
117
+ "serif": 0,
118
118
  "sha3_256": "66ccd0ffe8e56cd585dabde8d1292c3f551b390d8ed85f81d7a844825f9c2379",
119
119
  "size": 13100328,
120
120
  },
@@ -127,7 +127,7 @@ EMBEDDING_FONT_METADATA = {
127
127
  "font_name": "MaruBuri Regular",
128
128
  "italic": 0,
129
129
  "monospace": 0,
130
- "serif": 1,
130
+ "serif": 0,
131
131
  "sha3_256": "abb672dde7b89e06914ce27c59159b7a2933f26207bfcc47981c67c11c41e6d1",
132
132
  "size": 3268988,
133
133
  },
@@ -140,7 +140,7 @@ EMBEDDING_FONT_METADATA = {
140
140
  "font_name": "Noto Sans Bold",
141
141
  "italic": 0,
142
142
  "monospace": 0,
143
- "serif": 1,
143
+ "serif": 0,
144
144
  "sha3_256": "ecd38d472c1cad07d8a5dffd2b5a0f72edcd40fff2b4e68d770da8f2ef343a82",
145
145
  "size": 630964,
146
146
  },
@@ -153,7 +153,7 @@ EMBEDDING_FONT_METADATA = {
153
153
  "font_name": "Noto Sans Bold Italic",
154
154
  "italic": 1,
155
155
  "monospace": 0,
156
- "serif": 1,
156
+ "serif": 0,
157
157
  "sha3_256": "0b6c690a4a6b7d605b2ecbde00c7ac1a23e60feb17fa30d8b972d61ec3ff732b",
158
158
  "size": 644340,
159
159
  },
@@ -166,7 +166,7 @@ EMBEDDING_FONT_METADATA = {
166
166
  "font_name": "Noto Sans Italic",
167
167
  "italic": 1,
168
168
  "monospace": 0,
169
- "serif": 1,
169
+ "serif": 0,
170
170
  "sha3_256": "830652f61724c017e5a29a96225b484a2ccbd25f69a1b3f47e5f466a2dbed1ad",
171
171
  "size": 642344,
172
172
  },
@@ -179,7 +179,7 @@ EMBEDDING_FONT_METADATA = {
179
179
  "font_name": "Noto Sans Regular",
180
180
  "italic": 0,
181
181
  "monospace": 0,
182
- "serif": 1,
182
+ "serif": 0,
183
183
  "sha3_256": "7dfe2bbf97dc04c852d1223b220b63430e6ad03b0dbb28ebe6328a20a2d45eb8",
184
184
  "size": 629024,
185
185
  },
@@ -244,7 +244,7 @@ EMBEDDING_FONT_METADATA = {
244
244
  "font_name": "Source Han Sans CN Bold",
245
245
  "italic": 0,
246
246
  "monospace": 0,
247
- "serif": 1,
247
+ "serif": 0,
248
248
  "sha3_256": "82314c11016a04ef03e7afd00abe0ccc8df54b922dee79abf6424f3002a31825",
249
249
  "size": 10174460,
250
250
  },
@@ -257,7 +257,7 @@ EMBEDDING_FONT_METADATA = {
257
257
  "font_name": "Source Han Sans CN Regular",
258
258
  "italic": 0,
259
259
  "monospace": 0,
260
- "serif": 1,
260
+ "serif": 0,
261
261
  "sha3_256": "b45a80cf3650bfc62aa014e58243c6325e182c4b0c5819e41a583c699cce9a8f",
262
262
  "size": 10397552,
263
263
  },
@@ -270,7 +270,7 @@ EMBEDDING_FONT_METADATA = {
270
270
  "font_name": "Source Han Sans HK Bold",
271
271
  "italic": 0,
272
272
  "monospace": 0,
273
- "serif": 1,
273
+ "serif": 0,
274
274
  "sha3_256": "3eecd57457ba9a0fbad6c794f40e7ae704c4f825091aef2ac18902ffdde50608",
275
275
  "size": 6856692,
276
276
  },
@@ -283,7 +283,7 @@ EMBEDDING_FONT_METADATA = {
283
283
  "font_name": "Source Han Sans HK Regular",
284
284
  "italic": 0,
285
285
  "monospace": 0,
286
- "serif": 1,
286
+ "serif": 0,
287
287
  "sha3_256": "5fe4141f9164c03616323400b2936ee4c8265314492e2b822c3a6fbfb63ffe08",
288
288
  "size": 6999792,
289
289
  },
@@ -296,7 +296,7 @@ EMBEDDING_FONT_METADATA = {
296
296
  "font_name": "Source Han Sans JP Bold",
297
297
  "italic": 0,
298
298
  "monospace": 0,
299
- "serif": 1,
299
+ "serif": 0,
300
300
  "sha3_256": "fb05bd84d62e8064117ee357ab6a4481e1cde931e8e984c0553c8c4b09dc3938",
301
301
  "size": 5603068,
302
302
  },
@@ -309,7 +309,7 @@ EMBEDDING_FONT_METADATA = {
309
309
  "font_name": "Source Han Sans JP Regular",
310
310
  "italic": 0,
311
311
  "monospace": 0,
312
- "serif": 1,
312
+ "serif": 0,
313
313
  "sha3_256": "722cfbdcc0fd83fe07a3d1b10e9e64343c924a351d02cfe8dbb6ec4c6bc38230",
314
314
  "size": 5723960,
315
315
  },
@@ -322,7 +322,7 @@ EMBEDDING_FONT_METADATA = {
322
322
  "font_name": "Source Han Sans KR Bold",
323
323
  "italic": 0,
324
324
  "monospace": 0,
325
- "serif": 1,
325
+ "serif": 0,
326
326
  "sha3_256": "02959eb2c1eea0786a736aeb50b6e61f2ab873cd69c659389b7511f80f734838",
327
327
  "size": 5858892,
328
328
  },
@@ -335,7 +335,7 @@ EMBEDDING_FONT_METADATA = {
335
335
  "font_name": "Source Han Sans KR Regular",
336
336
  "italic": 0,
337
337
  "monospace": 0,
338
- "serif": 1,
338
+ "serif": 0,
339
339
  "sha3_256": "aba70109eff718e8f796f0185f8dca38026c1661b43c195883c84577e501adf2",
340
340
  "size": 5961704,
341
341
  },
@@ -348,7 +348,7 @@ EMBEDDING_FONT_METADATA = {
348
348
  "font_name": "Source Han Sans TW Bold",
349
349
  "italic": 0,
350
350
  "monospace": 0,
351
- "serif": 1,
351
+ "serif": 0,
352
352
  "sha3_256": "4a92730e644a1348e87bba7c77e9b462f257f381bd6abbeac5860d8f8306aee6",
353
353
  "size": 6883224,
354
354
  },
@@ -361,7 +361,7 @@ EMBEDDING_FONT_METADATA = {
361
361
  "font_name": "Source Han Sans TW Regular",
362
362
  "italic": 0,
363
363
  "monospace": 0,
364
- "serif": 1,
364
+ "serif": 0,
365
365
  "sha3_256": "6129b68ff4b0814624cac7edca61fbacf8f4d79db6f4c3cfc46b1c48ea2f81ac",
366
366
  "size": 7024812,
367
367
  },
@@ -3,7 +3,7 @@ import shutil
3
3
  import subprocess
4
4
  from pathlib import Path
5
5
 
6
- __version__ = "0.3.62"
6
+ __version__ = "0.3.64"
7
7
 
8
8
  CACHE_FOLDER = Path.home() / ".cache" / "babeldoc"
9
9
 
@@ -99,6 +99,7 @@ def parse_truetype_data(data):
99
99
  TOUNICODE_HEAD = """\
100
100
  /CIDInit /ProcSet findresource begin
101
101
  12 dict begin
102
+ begincmap
102
103
  /CIDSystemInfo <</Registry(Adobe)/Ordering(UCS)/Supplement 0>> def
103
104
  /CMapName /Adobe-Identity-UCS def
104
105
  /CMapType 2 def
@@ -124,7 +125,10 @@ def make_tounicode(cmap, used):
124
125
  if code < 0x10000:
125
126
  line.append(f"<{glyph:04x}><{code:04x}>")
126
127
  else:
127
- line.append(f"<{glyph:04x}><{code:08x}>")
128
+ code -= 0x10000
129
+ high = 0xD800 + (code >> 10)
130
+ low = 0xDC00 + (code & 0b1111111111)
131
+ line.append(f"<{glyph:04x}><{high:04x}{low:04x}>")
128
132
  line.append("endbfchar")
129
133
  line.append(TOUNICODE_TAIL)
130
134
  return "\n".join(line)
@@ -3,6 +3,7 @@ import logging
3
3
  import cv2
4
4
  import numpy as np
5
5
  import pymupdf
6
+ import regex
6
7
  from skimage.metrics import structural_similarity
7
8
 
8
9
  from babeldoc.document_il import il_version_1
@@ -63,6 +64,20 @@ class DetectScannedFile:
63
64
  ),
64
65
  )
65
66
 
67
+ def fast_check(self, doc: pymupdf.Document) -> bool:
68
+ if doc:
69
+ hit_list = [0] * len(doc)
70
+ for page in doc:
71
+ contents_list = page.get_contents()
72
+ for index in contents_list:
73
+ contents = doc.xref_stream(index)
74
+ if regex.search(rb"/Artifact(\s*\<\<|\s+BDC)", contents):
75
+ hit_list[page.number] += 1
76
+ if regex.search(rb"\s3\s+Tr\s", contents):
77
+ hit_list[page.number] += 1
78
+ return bool(sum(hit_list) > len(doc) * 0.8)
79
+ return False
80
+
66
81
  def process(self, docs: il_version_1.Document):
67
82
  """Generate layouts for all pages that need to be translated."""
68
83
  # Get pages that need to be translated
@@ -96,11 +111,20 @@ class DetectScannedFile:
96
111
  progress.advance(1)
97
112
 
98
113
  if scanned > threshold:
99
- logger.warning(
100
- f"Detected {scanned} scanned pages, which is more than 80% of the total pages. "
101
- "Please check the input PDF file.",
102
- )
103
- raise ScannedPDFError("Scanned PDF detected.")
114
+ if self.translation_config.auto_enable_ocr_workaround:
115
+ logger.warning(
116
+ f"Detected {scanned} scanned pages, which is more than 80% of the total pages. "
117
+ "Turning on OCR workaround.",
118
+ )
119
+ self.translation_config.shared_context_cross_split_part.auto_enabled_ocr_workaround = True
120
+ self.translation_config.ocr_workaround = True
121
+ self.translation_config.skip_scanned_detection = True
122
+ else:
123
+ logger.warning(
124
+ f"Detected {scanned} scanned pages, which is more than 80% of the total pages. "
125
+ "Please check the input PDF file.",
126
+ )
127
+ raise ScannedPDFError("Scanned PDF detected.")
104
128
 
105
129
  @staticmethod
106
130
  def detect_page_is_scanned(page: il_version_1.Page, pdf: pymupdf.Document) -> bool:
@@ -130,4 +154,4 @@ class DetectScannedFile:
130
154
  )[:, :, ::-1]
131
155
  before_page_image = cv2.cvtColor(before_page_image, cv2.COLOR_RGB2GRAY)
132
156
  after_page_image = cv2.cvtColor(after_page_image, cv2.COLOR_RGB2GRAY)
133
- return structural_similarity(before_page_image, after_page_image) > 0.98
157
+ return structural_similarity(before_page_image, after_page_image) > 0.97
@@ -867,7 +867,7 @@ class ILTranslator:
867
867
  "3. If there is no need to translate (such as proper nouns, codes, etc.), then return the original text."
868
868
  )
869
869
  llm_input.append(
870
- "4. Only output the translation result without explanations and annotations."
870
+ f"4. Only output the translation result in {self.translation_config.lang_out} without explanations and annotations."
871
871
  )
872
872
  llm_input.append(f"5. Translate text into {self.translation_config.lang_out}.")
873
873
  prompt_template = f"""
@@ -284,7 +284,7 @@ class ILTranslatorLLMOnly:
284
284
  llm_prompt_parts.append(self.translation_config.custom_system_prompt)
285
285
  else:
286
286
  llm_prompt_parts.append(
287
- f"You are a professional and reliable machine translation engine responsible for translating the input text into {self.translation_config.lang_out}."
287
+ f"You are a professional and reliable machine translation engine responsible for translating the input text into {self.translation_config.lang_out}.\n"
288
288
  "When translating, strictly follow the instructions below to ensure translation quality and preserve all formatting, tags, and placeholders:\n"
289
289
  )
290
290
 
@@ -378,7 +378,7 @@ class ILTranslatorLLMOnly:
378
378
  '1. You will receive a JSON object with entries containing "id" and "input" fields.'
379
379
  )
380
380
  llm_prompt_parts.append(
381
- '2. Your task is to translate the value of "input" into zh-CN, while applying the rules above.'
381
+ f'2. Your task is to translate the value of "input" into {self.translation_config.lang_out}, while applying the rules above.'
382
382
  )
383
383
  llm_prompt_parts.append(
384
384
  '3. Return a new JSON object with the same "id" and the translated "output" field.'
@@ -1,3 +1,4 @@
1
+ import enum
1
2
  import functools
2
3
  import logging
3
4
  import re
@@ -12,11 +13,39 @@ from babeldoc.translation_config import TranslationConfig
12
13
  logger = logging.getLogger(__name__)
13
14
 
14
15
 
16
+ class PrimaryFontFamily(enum.IntEnum):
17
+ SERIF = 1
18
+ SANS_SERIF = 2
19
+ SCRIPT = 3
20
+ NONE = 4
21
+
22
+ @classmethod
23
+ def from_str(cls, value: str):
24
+ if value == "serif":
25
+ return cls.SERIF
26
+ elif value == "sans-serif":
27
+ return cls.SANS_SERIF
28
+ elif value == "script":
29
+ return cls.SCRIPT
30
+ else:
31
+ return cls.NONE
32
+
33
+
15
34
  class FontMapper:
16
35
  stage_name = "Add Fonts"
17
36
 
18
37
  def __init__(self, translation_config: TranslationConfig):
19
38
  self.translation_config = translation_config
39
+ assert translation_config.primary_font_family in [
40
+ None,
41
+ "serif",
42
+ "sans-serif",
43
+ "script",
44
+ ]
45
+ self.primary_font_family = PrimaryFontFamily.from_str(
46
+ translation_config.primary_font_family,
47
+ )
48
+
20
49
  font_family = assets.get_font_family(translation_config.lang_out)
21
50
  self.font_file_names = []
22
51
  for k in (
@@ -141,6 +170,14 @@ class FontMapper:
141
170
  )
142
171
  return None
143
172
 
173
+ if self.primary_font_family == PrimaryFontFamily.SERIF:
174
+ serif = True
175
+ elif self.primary_font_family == PrimaryFontFamily.SANS_SERIF:
176
+ serif = False
177
+ elif self.primary_font_family == PrimaryFontFamily.SCRIPT:
178
+ serif = False
179
+ italic = True
180
+
144
181
  script_font_map_result = self.map_in_type(
145
182
  bold, italic, monospaced, serif, char_unicode, "script"
146
183
  )
@@ -217,7 +217,7 @@ class OnnxModel(DocLayoutModel):
217
217
  with self.lock:
218
218
  # pix = mupdf_doc[page.page_number].get_pixmap(dpi=72)
219
219
  pix = get_no_rotation_img(mupdf_doc[page.page_number])
220
- image = np.fromstring(pix.samples, np.uint8).reshape(
220
+ image = np.frombuffer(pix.samples, np.uint8).reshape(
221
221
  pix.height,
222
222
  pix.width,
223
223
  3,
@@ -259,7 +259,7 @@ class RpcDocLayoutModel(DocLayoutModel):
259
259
  with self.lock:
260
260
  # pix = mupdf_doc[page.page_number].get_pixmap(dpi=72)
261
261
  pix = get_no_rotation_img(mupdf_doc[page.page_number])
262
- image = np.fromstring(pix.samples, np.uint8).reshape(
262
+ image = np.frombuffer(pix.samples, np.uint8).reshape(
263
263
  pix.height,
264
264
  pix.width,
265
265
  3,
@@ -239,7 +239,7 @@ class RapidOCRModel:
239
239
  with self.lock:
240
240
  # pix = mupdf_doc[page.page_number].get_pixmap(dpi=72)
241
241
  pix = get_no_rotation_img(mupdf_doc[page.page_number])
242
- image = np.fromstring(pix.samples, np.uint8).reshape(
242
+ image = np.frombuffer(pix.samples, np.uint8).reshape(
243
243
  pix.height,
244
244
  pix.width,
245
245
  3,
@@ -4,6 +4,7 @@ import hashlib
4
4
  import io
5
5
  import logging
6
6
  import pathlib
7
+ import re
7
8
  import shutil
8
9
  import threading
9
10
  import time
@@ -21,6 +22,8 @@ from babeldoc.assets.assets import warmup
21
22
  from babeldoc.const import CACHE_FOLDER
22
23
  from babeldoc.converter import TranslateConverter
23
24
  from babeldoc.document_il import il_version_1
25
+ from babeldoc.document_il.babeldoc_exception.BabelDOCException import ExtractTextError
26
+ from babeldoc.document_il.babeldoc_exception.BabelDOCException import ScannedPDFError
24
27
  from babeldoc.document_il.backend.pdf_creater import SAVE_PDF_STAGE_NAME
25
28
  from babeldoc.document_il.backend.pdf_creater import SUBSET_FONT_STAGE_NAME
26
29
  from babeldoc.document_il.backend.pdf_creater import PDFCreater
@@ -185,7 +188,7 @@ def start_parse_il(
185
188
  # but in order to facilitate the migration of pdf2zh,
186
189
  # the relevant code is temporarily retained.
187
190
  # pix = doc_zh[page.pageno].get_pixmap()
188
- # image = np.fromstring(pix.samples, np.uint8).reshape(
191
+ # image = np.frombuffer(pix.samples, np.uint8).reshape(
189
192
  # pix.height, pix.width, 3
190
193
  # )[:, :, ::-1]
191
194
  # page_layout = model.predict(
@@ -590,11 +593,7 @@ def do_translate(
590
593
  result.original_pdf_path = translation_config.input_file
591
594
  result.peak_memory_usage = peak_memory_usage
592
595
 
593
- # should fix macOS preview compatibility
594
- # Although the issue of Windows Edge
595
- # not being able to copy translated text can be fixed,
596
- # the macOS preview is broken
597
- # fix_cmap(result, translation_config)
596
+ fix_cmap(result, translation_config)
598
597
  try:
599
598
  migrate_toc(translation_config, result)
600
599
  except Exception as e:
@@ -684,12 +683,30 @@ def fix_media_box(doc: Document) -> None:
684
683
  return mediabox_data
685
684
 
686
685
 
686
+ def check_cid_char(il: il_version_1.Document):
687
+ chars = []
688
+ for page in il.page:
689
+ chars.extend(page.pdf_character)
690
+
691
+ cid_count = 0
692
+ for char in chars:
693
+ if re.match(r"^\(cid:\d+\)$", char.char_unicode):
694
+ cid_count += 1
695
+
696
+ return cid_count > len(chars) * 0.8
697
+
698
+
687
699
  def _do_translate_single(
688
700
  pm: ProgressMonitor,
689
701
  translation_config: TranslationConfig,
690
702
  ) -> TranslateResult:
691
703
  """Original translation logic for a single document or part"""
692
704
  translation_config.progress_monitor = pm
705
+
706
+ if translation_config.shared_context_cross_split_part.auto_enabled_ocr_workaround:
707
+ translation_config.ocr_workaround = True
708
+ translation_config.skip_scanned_detection = True
709
+
693
710
  original_pdf_path = translation_config.input_file
694
711
  if translation_config.debug:
695
712
  doc_input = Document(original_pdf_path)
@@ -725,6 +742,23 @@ def _do_translate_single(
725
742
 
726
743
  resfont = None
727
744
  doc_pdf2zh.save(temp_pdf_path)
745
+
746
+ if not translation_config.skip_scanned_detection and DetectScannedFile(
747
+ translation_config
748
+ ).fast_check(doc_pdf2zh):
749
+ if translation_config.auto_enable_ocr_workaround:
750
+ logger.warning(
751
+ "Fast scanned check hit, Turning on OCR workaround.",
752
+ )
753
+ translation_config.shared_context_cross_split_part.auto_enabled_ocr_workaround = True
754
+ translation_config.ocr_workaround = True
755
+ translation_config.skip_scanned_detection = True
756
+ else:
757
+ logger.warning(
758
+ "Fast scanned check hit, Please check the input PDF file.",
759
+ )
760
+ raise ScannedPDFError("Scanned PDF detected.")
761
+
728
762
  il_creater = ILCreater(translation_config)
729
763
  il_creater.mupdf = doc_pdf2zh
730
764
  xml_converter = XMLConverter()
@@ -747,6 +781,9 @@ def _do_translate_single(
747
781
  translation_config.get_working_file_path("create_il.debug.json"),
748
782
  )
749
783
 
784
+ if check_cid_char(docs):
785
+ raise ExtractTextError("The document contains too many CID chars.")
786
+
750
787
  # Rest of the original translation logic...
751
788
  # [Previous implementation of do_translate continues here]
752
789
 
@@ -21,7 +21,7 @@ from babeldoc.translation_config import TranslationConfig
21
21
  from babeldoc.translation_config import WatermarkOutputMode
22
22
 
23
23
  logger = logging.getLogger(__name__)
24
- __version__ = "0.3.62"
24
+ __version__ = "0.3.64"
25
25
 
26
26
 
27
27
  def create_parser():
@@ -248,6 +248,19 @@ def create_parser():
248
248
  default=True,
249
249
  help="Disable automatic term extraction. (Config file: set auto_extract_glossary = false)",
250
250
  )
251
+ translation_group.add_argument(
252
+ "--auto-enable-ocr-workaround",
253
+ action="store_true",
254
+ default=False,
255
+ help="Enable automatic OCR workaround. If a document is detected as heavily scanned, this will attempt to enable OCR processing and skip further scan detection. Note: This option interacts with `--ocr-workaround` and `--skip-scanned-detection`. See documentation for details. (default: False)",
256
+ )
257
+ translation_group.add_argument(
258
+ "--primary-font-family",
259
+ type=str,
260
+ choices=["serif", "sans-serif", "script"],
261
+ default=None,
262
+ help="Override primary font family for translated text. Choices: 'serif' for serif fonts, 'sans-serif' for sans-serif fonts, 'script' for script/italic fonts. If not specified, uses automatic font selection based on original text properties.",
263
+ )
251
264
  # service option argument group
252
265
  service_group = translation_group.add_mutually_exclusive_group()
253
266
  service_group.add_argument(
@@ -468,6 +481,8 @@ async def main():
468
481
  glossaries=loaded_glossaries,
469
482
  pool_max_workers=args.pool_max_workers,
470
483
  auto_extract_glossary=args.auto_extract_glossary,
484
+ auto_enable_ocr_workaround=args.auto_enable_ocr_workaround,
485
+ primary_font_family=args.primary_font_family,
471
486
  )
472
487
 
473
488
  # Create progress handler
@@ -602,6 +617,7 @@ def cli():
602
617
  or v.name.startswith("httpx")
603
618
  or "http11" in v.name
604
619
  or "openai" in v.name
620
+ or "pdfminer" in v.name
605
621
  ):
606
622
  v.disabled = True
607
623
  v.propagate = False