BabelDOC 0.2.32__tar.gz → 0.3.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 (98) hide show
  1. {babeldoc-0.2.32 → babeldoc-0.3.0}/PKG-INFO +4 -1
  2. {babeldoc-0.2.32 → babeldoc-0.3.0}/README.md +3 -0
  3. babeldoc-0.3.0/babeldoc/__init__.py +1 -0
  4. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/const.py +1 -1
  5. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/midend/il_translator.py +8 -2
  6. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/midend/il_translator_llm_only.py +15 -3
  7. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/midend/styles_and_formulas.py +2 -0
  8. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/translator/translator.py +8 -8
  9. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/high_level.py +15 -8
  10. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/main.py +8 -1
  11. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/translation_config.py +2 -0
  12. {babeldoc-0.2.32 → babeldoc-0.3.0}/pyproject.toml +2 -2
  13. {babeldoc-0.2.32 → babeldoc-0.3.0}/uv.lock +1 -1
  14. babeldoc-0.2.32/babeldoc/__init__.py +0 -1
  15. {babeldoc-0.2.32 → babeldoc-0.3.0}/.cursorignore +0 -0
  16. {babeldoc-0.2.32 → babeldoc-0.3.0}/.github/ISSUE_TEMPLATE/bug_report.yaml +0 -0
  17. {babeldoc-0.2.32 → babeldoc-0.3.0}/.github/ISSUE_TEMPLATE/feature_request.yaml +0 -0
  18. {babeldoc-0.2.32 → babeldoc-0.3.0}/.github/dependabot.yml +0 -0
  19. {babeldoc-0.2.32 → babeldoc-0.3.0}/.github/labels.yml +0 -0
  20. {babeldoc-0.2.32 → babeldoc-0.3.0}/.github/release-drafter.yml +0 -0
  21. {babeldoc-0.2.32 → babeldoc-0.3.0}/.github/workflows/codeql.yml +0 -0
  22. {babeldoc-0.2.32 → babeldoc-0.3.0}/.github/workflows/docs.yml +0 -0
  23. {babeldoc-0.2.32 → babeldoc-0.3.0}/.github/workflows/labeler.yml +0 -0
  24. {babeldoc-0.2.32 → babeldoc-0.3.0}/.github/workflows/publish-to-pypi.yml +0 -0
  25. {babeldoc-0.2.32 → babeldoc-0.3.0}/.github/workflows/test.yml +0 -0
  26. {babeldoc-0.2.32 → babeldoc-0.3.0}/.gitignore +0 -0
  27. {babeldoc-0.2.32 → babeldoc-0.3.0}/.pre-commit-config.yaml +0 -0
  28. {babeldoc-0.2.32 → babeldoc-0.3.0}/LICENSE +0 -0
  29. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/assets/assets.py +0 -0
  30. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/assets/embedding_assets_metadata.py +0 -0
  31. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/asynchronize/__init__.py +0 -0
  32. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/converter.py +0 -0
  33. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/__init__.py +0 -0
  34. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/babeldoc_exception/BabelDOCException.py +0 -0
  35. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/backend/__init__.py +0 -0
  36. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/backend/pdf_creater.py +0 -0
  37. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/frontend/__init__.py +0 -0
  38. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/frontend/il_creater.py +0 -0
  39. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/il_version_1.py +0 -0
  40. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/il_version_1.rnc +0 -0
  41. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/il_version_1.rng +0 -0
  42. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/il_version_1.xsd +0 -0
  43. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/midend/__init__.py +0 -0
  44. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/midend/add_debug_information.py +0 -0
  45. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/midend/detect_scanned_file.py +0 -0
  46. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/midend/layout_parser.py +0 -0
  47. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/midend/paragraph_finder.py +0 -0
  48. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/midend/remove_descent.py +0 -0
  49. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/midend/table_parser.py +0 -0
  50. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/midend/typesetting.py +0 -0
  51. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/translator/__init__.py +0 -0
  52. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/translator/cache.py +0 -0
  53. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/utils/atomic_integer.py +0 -0
  54. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/utils/fontmap.py +0 -0
  55. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/utils/layout_helper.py +0 -0
  56. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/utils/priority_thread_pool_executor.py +0 -0
  57. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/utils/style_helper.py +0 -0
  58. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/document_il/xml_converter.py +0 -0
  59. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/docvision/README.md +0 -0
  60. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/docvision/__init__.py +0 -0
  61. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/docvision/doclayout.py +0 -0
  62. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/docvision/rpc_doclayout.py +0 -0
  63. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/docvision/table_detection/rapidocr.py +0 -0
  64. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/pdfinterp.py +0 -0
  65. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/progress_monitor.py +0 -0
  66. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/result_merger.py +0 -0
  67. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/split_manager.py +0 -0
  68. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/tools/generate_font_metadata.py +0 -0
  69. {babeldoc-0.2.32 → babeldoc-0.3.0}/babeldoc/tools/italic_assistance.py +0 -0
  70. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/CODE_OF_CONDUCT.md +0 -0
  71. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/CONTRIBUTING.md +0 -0
  72. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/CONTRIBUTOR_REWARD.md +0 -0
  73. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/ImplementationDetails/AsyncTranslate/AsyncTranslate.md +0 -0
  74. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/ImplementationDetails/ILTranslator/ILTranslator.md +0 -0
  75. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/ImplementationDetails/PDFCreation/PDFCreation.md +0 -0
  76. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/ImplementationDetails/PDFParsing/PDFParsing.md +0 -0
  77. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/ImplementationDetails/ParagraphFinding/ParagraphFinding.md +0 -0
  78. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/ImplementationDetails/README.md +0 -0
  79. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/ImplementationDetails/StylesAndFormulas/StylesAndFormulas.md +0 -0
  80. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/ImplementationDetails/Typesetting/Typesetting.md +0 -0
  81. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/README.md +0 -0
  82. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/deploy.sh +0 -0
  83. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/images/babeldoc-banner.png +0 -0
  84. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/images/babeldoc-big-logo-darkmode-with-transparent-background.png +0 -0
  85. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/images/babeldoc-big-logo-darkmode-with-transparent-background.svg +0 -0
  86. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/images/babeldoc-big-logo-with-transparent-background.png +0 -0
  87. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/images/babeldoc-big-logo-with-transparent-background.svg +0 -0
  88. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/images/babeldoc-big-logo.png +0 -0
  89. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/images/babeldoc-contributor_reward_example.png +0 -0
  90. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/images/babeldoc-preview.gif +0 -0
  91. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/images/babeldoc-small-logo-with-transparent-background.png +0 -0
  92. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/images/babeldoc-small-logo-with-transparent-background.svg +0 -0
  93. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/images/babeldoc-small-logo.png +0 -0
  94. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/index.md +0 -0
  95. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/intro-to-pdf-object.md +0 -0
  96. {babeldoc-0.2.32 → babeldoc-0.3.0}/docs/requirements.txt +0 -0
  97. {babeldoc-0.2.32 → babeldoc-0.3.0}/mkdocs.yml +0 -0
  98. {babeldoc-0.2.32 → babeldoc-0.3.0}/tests/test_translation_config.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: BabelDOC
3
- Version: 0.2.32
3
+ Version: 0.3.0
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
@@ -187,6 +187,7 @@ uv run babeldoc --files example.pdf --files example2.pdf --openai --openai-model
187
187
  - `--max-pages-per-part`: Maximum number of pages per part for split translation. If not set, no splitting will be performed.
188
188
  - `--no-watermark`: [DEPRECATED] Use --watermark-output-mode=no_watermark instead.
189
189
  - `--translate-table-text`: Translate table text (experimental, default: False)
190
+ - `--skip-scanned-detection`: Skip scanned document detection (default: False). When using split translation, only the first part performs detection if not skipped.
190
191
 
191
192
  > [!TIP]
192
193
  > - Both `--skip-clean` and `--dual-translate-first` may help improve compatibility with some PDF readers
@@ -194,6 +195,7 @@ uv run babeldoc --files example.pdf --files example2.pdf --openai --openai-model
194
195
  > - However, using `--skip-clean` will result in larger file sizes
195
196
  > - If you encounter any compatibility issues, try using `--enhance-compatibility` first
196
197
  > - Use `--max-pages-per-part` for large documents to split them into smaller parts for translation and automatically merge them back.
198
+ > - Use `--skip-scanned-detection` to speed up processing when you know your document is not a scanned PDF.
197
199
 
198
200
  ### Translation Service Options
199
201
 
@@ -268,6 +270,7 @@ use-alternating-pages-dual = false
268
270
  watermark-output-mode = "watermarked" # Choices: "watermarked", "no_watermark", "both"
269
271
  max-pages-per-part = 50 # Automatically split the document for translation and merge it back.
270
272
  # no-watermark = false # DEPRECATED: Use watermark-output-mode instead
273
+ skip-scanned-detection = false # Skip scanned document detection for faster processing
271
274
 
272
275
  # Translation service
273
276
  openai = true
@@ -141,6 +141,7 @@ uv run babeldoc --files example.pdf --files example2.pdf --openai --openai-model
141
141
  - `--max-pages-per-part`: Maximum number of pages per part for split translation. If not set, no splitting will be performed.
142
142
  - `--no-watermark`: [DEPRECATED] Use --watermark-output-mode=no_watermark instead.
143
143
  - `--translate-table-text`: Translate table text (experimental, default: False)
144
+ - `--skip-scanned-detection`: Skip scanned document detection (default: False). When using split translation, only the first part performs detection if not skipped.
144
145
 
145
146
  > [!TIP]
146
147
  > - Both `--skip-clean` and `--dual-translate-first` may help improve compatibility with some PDF readers
@@ -148,6 +149,7 @@ uv run babeldoc --files example.pdf --files example2.pdf --openai --openai-model
148
149
  > - However, using `--skip-clean` will result in larger file sizes
149
150
  > - If you encounter any compatibility issues, try using `--enhance-compatibility` first
150
151
  > - Use `--max-pages-per-part` for large documents to split them into smaller parts for translation and automatically merge them back.
152
+ > - Use `--skip-scanned-detection` to speed up processing when you know your document is not a scanned PDF.
151
153
 
152
154
  ### Translation Service Options
153
155
 
@@ -222,6 +224,7 @@ use-alternating-pages-dual = false
222
224
  watermark-output-mode = "watermarked" # Choices: "watermarked", "no_watermark", "both"
223
225
  max-pages-per-part = 50 # Automatically split the document for translation and merge it back.
224
226
  # no-watermark = false # DEPRECATED: Use watermark-output-mode instead
227
+ skip-scanned-detection = false # Skip scanned document detection for faster processing
225
228
 
226
229
  # Translation service
227
230
  openai = true
@@ -0,0 +1 @@
1
+ __version__ = "0.3.0"
@@ -3,7 +3,7 @@ import shutil
3
3
  import subprocess
4
4
  from pathlib import Path
5
5
 
6
- __version__ = "0.2.32"
6
+ __version__ = "0.3.0"
7
7
 
8
8
  CACHE_FOLDER = Path.home() / ".cache" / "babeldoc"
9
9
 
@@ -181,6 +181,7 @@ class ILTranslator:
181
181
  for font in xobj.pdf_font:
182
182
  page_xobj_font_map[xobj.xobj_id][font.font_id] = font
183
183
  # self.translate_paragraph(paragraph, pbar,tracker.new_paragraph(), page_font_map, page_xobj_font_map)
184
+ paragraph_token_count = self.calc_token_count(paragraph.unicode)
184
185
  executor.submit(
185
186
  self.translate_paragraph,
186
187
  paragraph,
@@ -188,7 +189,8 @@ class ILTranslator:
188
189
  tracker.new_paragraph(),
189
190
  page_font_map,
190
191
  page_xobj_font_map,
191
- priority=1048576 - self.calc_token_count(paragraph.unicode),
192
+ priority=1048576 - paragraph_token_count,
193
+ paragraph_token_count=paragraph_token_count,
192
194
  )
193
195
 
194
196
  class TranslateInput:
@@ -597,6 +599,7 @@ class ILTranslator:
597
599
  tracker: ParagraphTranslateTracker = None,
598
600
  page_font_map: dict[str, PdfFont] = None,
599
601
  xobj_font_map: dict[int, dict[str, PdfFont]] = None,
602
+ paragraph_token_count: int = 0,
600
603
  ):
601
604
  """Translate a paragraph using pre and post processing functions."""
602
605
  self.translation_config.raise_if_cancelled()
@@ -610,7 +613,10 @@ class ILTranslator:
610
613
  return
611
614
 
612
615
  # Perform translation
613
- translated_text = self.translate_engine.translate(text)
616
+ translated_text = self.translate_engine.translate(
617
+ text,
618
+ rate_limit_params={"paragraph_token_count": paragraph_token_count},
619
+ )
614
620
  translated_text = re.sub(r"[. 。…,]{20,}", ".", translated_text)
615
621
 
616
622
  # Post-translation processing
@@ -179,6 +179,7 @@ class ILTranslatorLLMOnly:
179
179
  self.translation_config.shared_context_cross_split_part.recent_title_paragraph,
180
180
  executor2,
181
181
  priority=1048576 - total_token_count,
182
+ paragraph_token_count=total_token_count,
182
183
  )
183
184
  paragraphs = []
184
185
  total_token_count = 0
@@ -194,6 +195,7 @@ class ILTranslatorLLMOnly:
194
195
  self.translation_config.shared_context_cross_split_part.recent_title_paragraph,
195
196
  executor2,
196
197
  priority=1048576 - total_token_count,
198
+ paragraph_token_count=total_token_count,
197
199
  )
198
200
 
199
201
  def translate_paragraph(
@@ -205,6 +207,7 @@ class ILTranslatorLLMOnly:
205
207
  title_paragraph: PdfParagraph | None = None,
206
208
  local_title_paragraph: PdfParagraph | None = None,
207
209
  executor: PriorityThreadPoolExecutor | None = None,
210
+ paragraph_token_count: int = 0,
208
211
  ):
209
212
  """Translate a paragraph using pre and post processing functions."""
210
213
  self.translation_config.raise_if_cancelled()
@@ -293,7 +296,10 @@ class ILTranslatorLLMOnly:
293
296
  llm_input.append(prompt_template)
294
297
 
295
298
  final_input = "\n".join(llm_input).strip()
296
- llm_output = self.translate_engine.llm_translate(final_input)
299
+ llm_output = self.translate_engine.llm_translate(
300
+ final_input,
301
+ rate_limit_params={"paragraph_token_count": paragraph_token_count},
302
+ )
297
303
  llm_output = llm_output.strip()
298
304
 
299
305
  llm_output = self._clean_json_output(llm_output)
@@ -364,6 +370,9 @@ class ILTranslatorLLMOnly:
364
370
  logger.warning(
365
371
  f"Fallback to simple translation. paragraph id: {inputs[id_][2].debug_id}"
366
372
  )
373
+ paragraph_token_count = self.calc_token_count(
374
+ inputs[id_][2].unicode
375
+ )
367
376
  executor.submit(
368
377
  self.il_translator.translate_paragraph,
369
378
  inputs[id_][2],
@@ -371,7 +380,8 @@ class ILTranslatorLLMOnly:
371
380
  inputs[id_][3],
372
381
  page_font_map,
373
382
  xobj_font_map,
374
- priority=1048576 - self.calc_token_count(paragraph.unicode),
383
+ priority=1048576 - paragraph_token_count,
384
+ paragraph_token_count=paragraph_token_count,
375
385
  )
376
386
 
377
387
  except Exception as e:
@@ -385,6 +395,7 @@ class ILTranslatorLLMOnly:
385
395
  tracker = batch_paragraph.trackers[i]
386
396
  if paragraph.debug_id is None:
387
397
  continue
398
+ paragraph_token_count = self.calc_token_count(paragraph.unicode)
388
399
  executor.submit(
389
400
  self.il_translator.translate_paragraph,
390
401
  paragraph,
@@ -392,7 +403,8 @@ class ILTranslatorLLMOnly:
392
403
  tracker,
393
404
  page_font_map,
394
405
  xobj_font_map,
395
- priority=1048576 - self.calc_token_count(paragraph.unicode),
406
+ priority=1048576 - paragraph_token_count,
407
+ paragraph_token_count=paragraph_token_count,
396
408
  )
397
409
 
398
410
  def _clean_json_output(self, llm_output: str) -> str:
@@ -541,6 +541,8 @@ class StylesAndFormulas:
541
541
  r"|Times-Italic.*"
542
542
  r"|MeridienLTStd.*"
543
543
  r"|Calibri.*"
544
+ r"|STIXMathJax_Main-Regular.*"
545
+ r"|STIXMathJax_Main-Italic.*"
544
546
  r")$"
545
547
  )
546
548
  if self.translation_config.formular_font_pattern:
@@ -104,7 +104,7 @@ class BaseTranslator(ABC):
104
104
  """
105
105
  self.cache.add_params(k, v)
106
106
 
107
- def translate(self, text, ignore_cache=False):
107
+ def translate(self, text, ignore_cache=False, rate_limit_params: dict = None):
108
108
  """
109
109
  Translate the text, and the other part should call this method.
110
110
  :param text: text to translate
@@ -117,12 +117,12 @@ class BaseTranslator(ABC):
117
117
  self.translate_cache_call_count += 1
118
118
  return cache
119
119
  _translate_rate_limiter.wait()
120
- translation = self.do_translate(text)
120
+ translation = self.do_translate(text, rate_limit_params)
121
121
  if not (self.ignore_cache or ignore_cache):
122
122
  self.cache.set(text, translation)
123
123
  return translation
124
124
 
125
- def llm_translate(self, text, ignore_cache=False):
125
+ def llm_translate(self, text, ignore_cache=False, rate_limit_params: dict = None):
126
126
  """
127
127
  Translate the text, and the other part should call this method.
128
128
  :param text: text to translate
@@ -135,13 +135,13 @@ class BaseTranslator(ABC):
135
135
  self.translate_cache_call_count += 1
136
136
  return cache
137
137
  _translate_rate_limiter.wait()
138
- translation = self.do_llm_translate(text)
138
+ translation = self.do_llm_translate(text, rate_limit_params)
139
139
  if not (self.ignore_cache or ignore_cache):
140
140
  self.cache.set(text, translation)
141
141
  return translation
142
142
 
143
143
  @abstractmethod
144
- def do_llm_translate(self, text):
144
+ def do_llm_translate(self, text, rate_limit_params: dict = None):
145
145
  """
146
146
  Actual translate text, override this method
147
147
  :param text: text to translate
@@ -150,7 +150,7 @@ class BaseTranslator(ABC):
150
150
  raise NotImplementedError
151
151
 
152
152
  @abstractmethod
153
- def do_translate(self, text):
153
+ def do_translate(self, text, rate_limit_params: dict = None):
154
154
  """
155
155
  Actual translate text, override this method
156
156
  :param text: text to translate
@@ -209,7 +209,7 @@ class OpenAITranslator(BaseTranslator):
209
209
  f"(Attempt {retry_state.attempt_number}/100)"
210
210
  ),
211
211
  )
212
- def do_translate(self, text) -> str:
212
+ def do_translate(self, text, rate_limit_params: dict = None) -> str:
213
213
  response = self.client.chat.completions.create(
214
214
  model=self.model,
215
215
  **self.options,
@@ -241,7 +241,7 @@ class OpenAITranslator(BaseTranslator):
241
241
  f"(Attempt {retry_state.attempt_number}/100)"
242
242
  ),
243
243
  )
244
- def do_llm_translate(self, text):
244
+ def do_llm_translate(self, text, rate_limit_params: dict = None):
245
245
  if text is None:
246
246
  return None
247
247
 
@@ -431,6 +431,10 @@ def do_translate(
431
431
  (x, x) for x in should_translate_pages
432
432
  ]
433
433
 
434
+ # Only first part should do scanned detection if enabled
435
+ if i > 0:
436
+ part_config.skip_scanned_detection = True
437
+
434
438
  part_config.working_dir = (
435
439
  translation_config.get_part_working_dir(i)
436
440
  )
@@ -576,14 +580,17 @@ def _do_translate_single(
576
580
  # [Previous implementation of do_translate continues here]
577
581
 
578
582
  # 检测是否为扫描文件
579
- logger.debug("start detect scanned file")
580
- DetectScannedFile(translation_config).process(docs)
581
- logger.debug("finish detect scanned file")
582
- if translation_config.debug:
583
- xml_converter.write_json(
584
- docs,
585
- translation_config.get_working_file_path("detect_scanned_file.json"),
586
- )
583
+ if translation_config.skip_scanned_detection:
584
+ logger.debug("skipping scanned file detection")
585
+ else:
586
+ logger.debug("start detect scanned file")
587
+ DetectScannedFile(translation_config).process(docs)
588
+ logger.debug("finish detect scanned file")
589
+ if translation_config.debug:
590
+ xml_converter.write_json(
591
+ docs,
592
+ translation_config.get_working_file_path("detect_scanned_file.json"),
593
+ )
587
594
 
588
595
  # Generate layouts for all pages
589
596
  logger.debug("start generating layouts")
@@ -23,7 +23,7 @@ from babeldoc.translation_config import TranslationConfig
23
23
  from babeldoc.translation_config import WatermarkOutputMode
24
24
 
25
25
  logger = logging.getLogger(__name__)
26
- __version__ = "0.2.32"
26
+ __version__ = "0.3.0"
27
27
 
28
28
 
29
29
  def create_parser():
@@ -204,6 +204,12 @@ def create_parser():
204
204
  default=False,
205
205
  help="Show character box (debug only)",
206
206
  )
207
+ translation_group.add_argument(
208
+ "--skip-scanned-detection",
209
+ action="store_true",
210
+ default=False,
211
+ help="Skip scanned document detection (speeds up processing for non-scanned documents)",
212
+ )
207
213
  # service option argument group
208
214
  service_group = translation_group.add_mutually_exclusive_group()
209
215
  service_group.add_argument(
@@ -370,6 +376,7 @@ async def main():
370
376
  split_strategy=split_strategy,
371
377
  table_model=table_model,
372
378
  show_char_box=args.show_char_box,
379
+ skip_scanned_detection=args.skip_scanned_detection,
373
380
  )
374
381
 
375
382
  # Create progress handler
@@ -67,6 +67,7 @@ class TranslationConfig:
67
67
  split_strategy: BaseSplitStrategy | None = None,
68
68
  table_model=None,
69
69
  show_char_box: bool = False,
70
+ skip_scanned_detection: bool = False,
70
71
  ):
71
72
  self.translator = translator
72
73
 
@@ -97,6 +98,7 @@ class TranslationConfig:
97
98
  self.doc_layout_model = doc_layout_model
98
99
 
99
100
  self.skip_clean = skip_clean or enhance_compatibility
101
+ self.skip_scanned_detection = skip_scanned_detection
100
102
 
101
103
  self.dual_translate_first = dual_translate_first or enhance_compatibility
102
104
  self.disable_rich_text_translate = (
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "BabelDOC"
3
- version = "0.2.32"
3
+ version = "0.3.0"
4
4
  description = "Yet Another Document Translator"
5
5
  license = "AGPL-3.0"
6
6
  readme = "README.md"
@@ -148,7 +148,7 @@ pythonpath = [".", "src"]
148
148
  testpaths = ["tests"]
149
149
 
150
150
  [bumpver]
151
- current_version = "0.2.32"
151
+ current_version = "0.3.0"
152
152
  version_pattern = "MAJOR.MINOR.PATCH[.PYTAGNUM]"
153
153
 
154
154
  [bumpver.file_patterns]
@@ -48,7 +48,7 @@ wheels = [
48
48
 
49
49
  [[package]]
50
50
  name = "babeldoc"
51
- version = "0.2.32"
51
+ version = "0.3.0"
52
52
  source = { editable = "." }
53
53
  dependencies = [
54
54
  { name = "bitstring" },
@@ -1 +0,0 @@
1
- __version__ = "0.2.32"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes