BabelDOC 0.1.17__tar.gz → 0.1.18__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 (77) hide show
  1. {babeldoc-0.1.17 → babeldoc-0.1.18}/PKG-INFO +3 -1
  2. {babeldoc-0.1.17 → babeldoc-0.1.18}/README.md +2 -0
  3. babeldoc-0.1.18/babeldoc/__init__.py +1 -0
  4. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/const.py +1 -1
  5. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/midend/typesetting.py +130 -20
  6. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/high_level.py +1 -0
  7. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/main.py +1 -1
  8. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/translation_config.py +9 -0
  9. {babeldoc-0.1.17 → babeldoc-0.1.18}/pyproject.toml +2 -2
  10. {babeldoc-0.1.17 → babeldoc-0.1.18}/uv.lock +1 -1
  11. babeldoc-0.1.17/babeldoc/__init__.py +0 -1
  12. {babeldoc-0.1.17 → babeldoc-0.1.18}/.cursorignore +0 -0
  13. {babeldoc-0.1.17 → babeldoc-0.1.18}/.github/ISSUE_TEMPLATE/bug_report.yaml +0 -0
  14. {babeldoc-0.1.17 → babeldoc-0.1.18}/.github/ISSUE_TEMPLATE/feature_request.yaml +0 -0
  15. {babeldoc-0.1.17 → babeldoc-0.1.18}/.github/dependabot.yml +0 -0
  16. {babeldoc-0.1.17 → babeldoc-0.1.18}/.github/labels.yml +0 -0
  17. {babeldoc-0.1.17 → babeldoc-0.1.18}/.github/release-drafter.yml +0 -0
  18. {babeldoc-0.1.17 → babeldoc-0.1.18}/.github/workflows/codeql.yml +0 -0
  19. {babeldoc-0.1.17 → babeldoc-0.1.18}/.github/workflows/docs.yml +0 -0
  20. {babeldoc-0.1.17 → babeldoc-0.1.18}/.github/workflows/labeler.yml +0 -0
  21. {babeldoc-0.1.17 → babeldoc-0.1.18}/.github/workflows/publish-to-pypi.yml +0 -0
  22. {babeldoc-0.1.17 → babeldoc-0.1.18}/.github/workflows/test.yml +0 -0
  23. {babeldoc-0.1.17 → babeldoc-0.1.18}/.gitignore +0 -0
  24. {babeldoc-0.1.17 → babeldoc-0.1.18}/.pre-commit-config.yaml +0 -0
  25. {babeldoc-0.1.17 → babeldoc-0.1.18}/LICENSE +0 -0
  26. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/asynchronize/__init__.py +0 -0
  27. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/converter.py +0 -0
  28. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/__init__.py +0 -0
  29. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/backend/__init__.py +0 -0
  30. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/backend/pdf_creater.py +0 -0
  31. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/frontend/__init__.py +0 -0
  32. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/frontend/il_creater.py +0 -0
  33. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/il_version_1.py +0 -0
  34. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/il_version_1.rnc +0 -0
  35. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/il_version_1.rng +0 -0
  36. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/il_version_1.xsd +0 -0
  37. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/midend/__init__.py +0 -0
  38. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/midend/add_debug_information.py +0 -0
  39. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/midend/il_translator.py +0 -0
  40. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/midend/layout_parser.py +0 -0
  41. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/midend/paragraph_finder.py +0 -0
  42. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/midend/remove_descent.py +0 -0
  43. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/midend/styles_and_formulas.py +0 -0
  44. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/translator/__init__.py +0 -0
  45. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/translator/cache.py +0 -0
  46. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/translator/translator.py +0 -0
  47. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/utils/fontmap.py +0 -0
  48. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/utils/layout_helper.py +0 -0
  49. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/utils/style_helper.py +0 -0
  50. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/document_il/xml_converter.py +0 -0
  51. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/docvision/README.md +0 -0
  52. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/docvision/__init__.py +0 -0
  53. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/docvision/doclayout.py +0 -0
  54. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/docvision/rpc_doclayout.py +0 -0
  55. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/pdfinterp.py +0 -0
  56. {babeldoc-0.1.17 → babeldoc-0.1.18}/babeldoc/progress_monitor.py +0 -0
  57. {babeldoc-0.1.17 → babeldoc-0.1.18}/docs/CODE_OF_CONDUCT.md +0 -0
  58. {babeldoc-0.1.17 → babeldoc-0.1.18}/docs/CONTRIBUTING.md +0 -0
  59. {babeldoc-0.1.17 → babeldoc-0.1.18}/docs/CONTRIBUTOR_REWARD.md +0 -0
  60. {babeldoc-0.1.17 → babeldoc-0.1.18}/docs/ImplementationDetails/AsyncTranslate/AsyncTranslate.md +0 -0
  61. {babeldoc-0.1.17 → babeldoc-0.1.18}/docs/ImplementationDetails/ILTranslator/ILTranslator.md +0 -0
  62. {babeldoc-0.1.17 → babeldoc-0.1.18}/docs/ImplementationDetails/PDFCreation/PDFCreation.md +0 -0
  63. {babeldoc-0.1.17 → babeldoc-0.1.18}/docs/ImplementationDetails/PDFParsing/PDFParsing.md +0 -0
  64. {babeldoc-0.1.17 → babeldoc-0.1.18}/docs/ImplementationDetails/ParagraphFinding/ParagraphFinding.md +0 -0
  65. {babeldoc-0.1.17 → babeldoc-0.1.18}/docs/ImplementationDetails/README.md +0 -0
  66. {babeldoc-0.1.17 → babeldoc-0.1.18}/docs/ImplementationDetails/StylesAndFormulas/StylesAndFormulas.md +0 -0
  67. {babeldoc-0.1.17 → babeldoc-0.1.18}/docs/ImplementationDetails/Typesetting/Typesetting.md +0 -0
  68. {babeldoc-0.1.17 → babeldoc-0.1.18}/docs/README.md +0 -0
  69. {babeldoc-0.1.17 → babeldoc-0.1.18}/docs/deploy.sh +0 -0
  70. {babeldoc-0.1.17 → babeldoc-0.1.18}/docs/images/babeldoc-banner.png +0 -0
  71. {babeldoc-0.1.17 → babeldoc-0.1.18}/docs/images/babeldoc-contributor_reward_example.png +0 -0
  72. {babeldoc-0.1.17 → babeldoc-0.1.18}/docs/images/babeldoc-preview.gif +0 -0
  73. {babeldoc-0.1.17 → babeldoc-0.1.18}/docs/index.md +0 -0
  74. {babeldoc-0.1.17 → babeldoc-0.1.18}/docs/intro-to-pdf-object.md +0 -0
  75. {babeldoc-0.1.17 → babeldoc-0.1.18}/docs/requirements.txt +0 -0
  76. {babeldoc-0.1.17 → babeldoc-0.1.18}/mkdocs.yml +0 -0
  77. {babeldoc-0.1.17 → babeldoc-0.1.18}/tests/test_translation_config.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: BabelDOC
3
- Version: 0.1.17
3
+ Version: 0.1.18
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
@@ -58,6 +58,7 @@ Description-Content-Type: text/markdown
58
58
 
59
59
  PDF scientific paper translation and bilingual comparison library.
60
60
 
61
+ - Beta version launched [Immersive Translate - BabelDOC](https://app.immersivetranslate.com/babel-doc/) 1000 free pages per month.
61
62
  - Provides a simple [command line interface](#getting-started).
62
63
  - Provides a [Python API](#python-api).
63
64
  - Mainly designed to be embedded into other programs, but can also be used directly for simple translation tasks.
@@ -133,6 +134,7 @@ uv run babeldoc --bing --files example.pdf --files example2.pdf
133
134
 
134
135
  > [!TIP]
135
136
  > Currently, this project mainly focuses on English-to-Chinese translation, and other scenarios have not been tested yet.
137
+ > (2025.3.1 update): Basic English target language support has been added, primarily to minimize line breaks within words([0-9A-Za-z]+).
136
138
 
137
139
  ### PDF Processing Options
138
140
 
@@ -24,6 +24,7 @@
24
24
 
25
25
  PDF scientific paper translation and bilingual comparison library.
26
26
 
27
+ - Beta version launched [Immersive Translate - BabelDOC](https://app.immersivetranslate.com/babel-doc/) 1000 free pages per month.
27
28
  - Provides a simple [command line interface](#getting-started).
28
29
  - Provides a [Python API](#python-api).
29
30
  - Mainly designed to be embedded into other programs, but can also be used directly for simple translation tasks.
@@ -99,6 +100,7 @@ uv run babeldoc --bing --files example.pdf --files example2.pdf
99
100
 
100
101
  > [!TIP]
101
102
  > Currently, this project mainly focuses on English-to-Chinese translation, and other scenarios have not been tested yet.
103
+ > (2025.3.1 update): Basic English target language support has been added, primarily to minimize line breaks within words([0-9A-Za-z]+).
102
104
 
103
105
  ### PDF Processing Options
104
106
 
@@ -0,0 +1 @@
1
+ __version__ = "0.1.18"
@@ -2,7 +2,7 @@ import shutil
2
2
  import subprocess
3
3
  from pathlib import Path
4
4
 
5
- __version__ = "0.1.17"
5
+ __version__ = "0.1.18"
6
6
 
7
7
  CACHE_FOLDER = Path.home() / ".cache" / "babeldoc"
8
8
 
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ import re
2
3
  import statistics
3
4
  import unicodedata
4
5
  from functools import cache
@@ -83,6 +84,15 @@ class TypesettingUnit:
83
84
  ]
84
85
  return False
85
86
 
87
+ @property
88
+ def can_break_line(self):
89
+ unicode = self.try_get_unicode()
90
+ if not unicode:
91
+ return True
92
+ if re.match(r"^[a-zA-Z0-9]+$", unicode):
93
+ return False
94
+ return True
95
+
86
96
  @property
87
97
  def is_chinese_char(self):
88
98
  if self.formular:
@@ -146,33 +156,85 @@ class TypesettingUnit:
146
156
 
147
157
  if unicode:
148
158
  return unicode in [
159
+ # 英文标点
149
160
  ",",
150
161
  ".",
151
162
  ":",
152
163
  ";",
153
164
  "?",
154
165
  "!",
155
- ",",
156
- "。",
157
- ":",
158
- "?",
159
- "!",
160
- "]",
161
- "}",
162
- ")",
163
- "〕",
164
- "〉",
165
- "】",
166
- "〗",
167
- "」",
168
- "』",
169
- "、",
170
- "”",
171
- '"',
172
- ";",
166
+ # 中文点号
167
+ ",", # 逗号
168
+ "。", # 句号
169
+ ".", # 全角句号
170
+ "、", # 顿号
171
+ ":", # 冒号
172
+ ";", # 分号
173
+ "!", # 叹号
174
+ "‼", # 双叹号
175
+ "?", # 问号
176
+ "⁇", # 双问号
177
+ # 结束引号
178
+ "”", # 右双引号
179
+ "’", # 右单引号
180
+ "」", # 右直角单引号
181
+ "』", # 右直角双引号
182
+ # 结束括号
183
+ ")", # 右圆括号
184
+ "]", # 右方括号
185
+ "}", # 右花括号
186
+ ")", # 右圆括号
187
+ "〕", # 右龟甲括号
188
+ "〉", # 右单书名号
189
+ "】", # 右黑色方头括号
190
+ "〗", # 右空白方头括号
191
+ "]", # 全角右方括号
192
+ "}", # 全角右花括号
193
+ # 结束双书名号
194
+ "》", # 右双书名号
195
+ # 连接号
196
+ "~", # 全角波浪号
197
+ "-", # 连字符减号
198
+ "–", # 短破折号(EN DASH)
199
+ "—", # 长破折号(EM DASH)
200
+ # 间隔号
201
+ "·", # 中间点
202
+ "・", # 片假名中间点
203
+ "‧", # 连字点
204
+ # 分隔号
205
+ "/", # 斜杠
206
+ "/", # 全角斜杠
207
+ "⁄", # 分数斜杠
173
208
  ]
174
209
  return False
175
210
 
211
+ @property
212
+ def is_cannot_appear_in_line_end_punctuation(self):
213
+ if self.formular:
214
+ return False
215
+ unicode = self.try_get_unicode()
216
+ if not unicode:
217
+ return False
218
+ return unicode in [
219
+ # 开始引号
220
+ "“", # 左双引号
221
+ "‘", # 左单引号
222
+ "「", # 左直角单引号
223
+ "『", # 左直角双引号
224
+ # 开始括号
225
+ "(", # 左圆括号
226
+ "[", # 左方括号
227
+ "{", # 左花括号
228
+ "(", # 左圆括号
229
+ "〔", # 左龟甲括号
230
+ "〈", # 左单书名号
231
+ "《", # 左双书名号
232
+ # 开始单双书名号
233
+ "〖", # 左空白方头括号
234
+ "〘", # 左黑色方头括号
235
+ "〚", # 左单书名号
236
+ ]
237
+
176
238
  def passthrough(self) -> [PdfCharacter]:
177
239
  if self.char:
178
240
  return [self.char]
@@ -450,6 +512,21 @@ class Typesetting:
450
512
  paragraph.pdf_paragraph_composition = []
451
513
  self.retypeset(paragraph, page, typesetting_units)
452
514
 
515
+ def _get_width_before_next_break_point(
516
+ self, typesetting_units: list[TypesettingUnit], scale: float
517
+ ) -> float:
518
+ if not typesetting_units:
519
+ return 0
520
+ if typesetting_units[0].can_break_line:
521
+ return 0
522
+
523
+ total_width = 0
524
+ for unit in typesetting_units:
525
+ if unit.can_break_line:
526
+ return total_width * scale
527
+ total_width += unit.width
528
+ return total_width * scale
529
+
453
530
  def _layout_typesetting_units(
454
531
  self,
455
532
  typesetting_units: list[TypesettingUnit],
@@ -457,6 +534,7 @@ class Typesetting:
457
534
  scale: float,
458
535
  line_spacing: float,
459
536
  paragraph: il_version_1.PdfParagraph,
537
+ use_english_line_break: bool = True,
460
538
  ) -> tuple[list[TypesettingUnit], bool]:
461
539
  """布局排版单元。
462
540
 
@@ -504,7 +582,7 @@ class Typesetting:
504
582
  if paragraph.first_line_indent:
505
583
  current_x += space_width * 4
506
584
  # 遍历所有排版单元
507
- for unit in typesetting_units:
585
+ for i, unit in enumerate(typesetting_units):
508
586
  # 计算当前单元在当前缩放下的尺寸
509
587
  unit_width = unit.width * scale
510
588
  unit_height = unit.height * scale
@@ -528,11 +606,36 @@ class Typesetting:
528
606
  and current_x > box.x # 不是行首
529
607
  and unit.try_get_unicode() != " " # 不是空格
530
608
  and last_unit.try_get_unicode() != " " # 不是空格
609
+ and last_unit.try_get_unicode()
610
+ not in [
611
+ "。",
612
+ "!",
613
+ "?",
614
+ ";",
615
+ ":",
616
+ ",",
617
+ ]
531
618
  ):
532
619
  current_x += space_width * 0.5
620
+ if use_english_line_break:
621
+ width_before_next_break_point = self._get_width_before_next_break_point(
622
+ typesetting_units[i + 1 :], scale
623
+ )
624
+ else:
625
+ width_before_next_break_point = 0
533
626
 
534
627
  # 如果当前行放不下这个元素,换行
535
- if current_x + unit_width > box.x2 and not unit.is_hung_punctuation:
628
+ if not unit.is_hung_punctuation and (
629
+ (current_x + unit_width > box.x2)
630
+ or (
631
+ use_english_line_break
632
+ and current_x + unit_width + width_before_next_break_point > box.x2
633
+ )
634
+ or (
635
+ unit.is_cannot_appear_in_line_end_punctuation
636
+ and current_x + unit_width * 2 > box.x2
637
+ )
638
+ ):
536
639
  # 换行
537
640
  current_x = box.x
538
641
  current_y -= line_height * line_spacing
@@ -568,6 +671,7 @@ class Typesetting:
568
671
  paragraph: il_version_1.PdfParagraph,
569
672
  page: il_version_1.Page,
570
673
  typesetting_units: list[TypesettingUnit],
674
+ use_english_line_break: bool = True,
571
675
  ):
572
676
  box = paragraph.box
573
677
  scale = 1.0
@@ -584,6 +688,7 @@ class Typesetting:
584
688
  scale,
585
689
  line_spacing,
586
690
  paragraph,
691
+ use_english_line_break,
587
692
  )
588
693
 
589
694
  # 如果所有单元都放得下,就完成排版
@@ -629,6 +734,11 @@ class Typesetting:
629
734
  min_line_spacing = 1.1
630
735
  scale = 1.0
631
736
  line_spacing = 1.5
737
+ # 如果仍然放不下,则尝试去除英文换行限制
738
+ if use_english_line_break:
739
+ self.retypeset(
740
+ paragraph, page, typesetting_units, use_english_line_break=False
741
+ )
632
742
 
633
743
  def create_typesetting_units(
634
744
  self,
@@ -419,6 +419,7 @@ def do_translate(pm, translation_config):
419
419
  finally:
420
420
  logger.debug("do_translate finally")
421
421
  pm.on_finish()
422
+ translation_config.cleanup_temp_files()
422
423
 
423
424
 
424
425
  def download_font_assets():
@@ -23,7 +23,7 @@ from babeldoc.docvision.rpc_doclayout import RpcDocLayoutModel
23
23
  from babeldoc.translation_config import TranslationConfig
24
24
 
25
25
  logger = logging.getLogger(__name__)
26
- __version__ = "0.1.17"
26
+ __version__ = "0.1.18"
27
27
 
28
28
 
29
29
  def create_parser():
@@ -1,3 +1,5 @@
1
+ import logging
2
+ import shutil
1
3
  import tempfile
2
4
  import threading
3
5
  from pathlib import Path
@@ -7,6 +9,8 @@ from babeldoc.document_il.translator.translator import BaseTranslator
7
9
  from babeldoc.docvision.doclayout import DocLayoutModel
8
10
  from babeldoc.progress_monitor import ProgressMonitor
9
11
 
12
+ logger = logging.getLogger(__name__)
13
+
10
14
 
11
15
  class TranslationConfig:
12
16
  def __init__(
@@ -158,6 +162,11 @@ class TranslationConfig:
158
162
  if self.progress_monitor is not None:
159
163
  self.progress_monitor.cancel()
160
164
 
165
+ def cleanup_temp_files(self):
166
+ if self._is_temp_dir:
167
+ logger.info(f"cleanup temp files: {self.working_dir}")
168
+ shutil.rmtree(self.working_dir)
169
+
161
170
 
162
171
  class TranslateResult:
163
172
  original_pdf_path: str
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "BabelDOC"
3
- version = "0.1.17"
3
+ version = "0.1.18"
4
4
  description = "Yet Another Document Translator"
5
5
  license = "AGPL-3.0"
6
6
  readme = "README.md"
@@ -132,7 +132,7 @@ pythonpath = [".", "src"]
132
132
  testpaths = ["tests"]
133
133
 
134
134
  [bumpver]
135
- current_version = "0.1.17"
135
+ current_version = "0.1.18"
136
136
  version_pattern = "MAJOR.MINOR.PATCH[.PYTAGNUM]"
137
137
 
138
138
  [bumpver.file_patterns]
@@ -48,7 +48,7 @@ wheels = [
48
48
 
49
49
  [[package]]
50
50
  name = "babeldoc"
51
- version = "0.1.17"
51
+ version = "0.1.18"
52
52
  source = { editable = "." }
53
53
  dependencies = [
54
54
  { name = "bitstring" },
@@ -1 +0,0 @@
1
- __version__ = "0.1.17"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes