BabelDOC 0.3.40__tar.gz → 0.3.42__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.
- {babeldoc-0.3.40 → babeldoc-0.3.42}/PKG-INFO +1 -1
- babeldoc-0.3.42/babeldoc/__init__.py +1 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/const.py +1 -1
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/midend/il_translator.py +83 -26
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/midend/il_translator_llm_only.py +57 -17
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/translator/translator.py +6 -3
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/main.py +1 -1
- {babeldoc-0.3.40 → babeldoc-0.3.42}/pyproject.toml +2 -2
- {babeldoc-0.3.40 → babeldoc-0.3.42}/uv.lock +1 -1
- babeldoc-0.3.40/babeldoc/__init__.py +0 -1
- {babeldoc-0.3.40 → babeldoc-0.3.42}/.cursorignore +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/.github/ISSUE_TEMPLATE/bug_report.yaml +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/.github/ISSUE_TEMPLATE/feature_request.yaml +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/.github/PULL_REQUEST_TEMPLATE/pr_form.yml +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/.github/dependabot.yml +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/.github/labels.yml +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/.github/release-drafter.yml +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/.github/workflows/codeql.yml +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/.github/workflows/docs.yml +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/.github/workflows/labeler.yml +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/.github/workflows/lint.yml +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/.github/workflows/pr-lint.yml +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/.github/workflows/publish-to-pypi.yml +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/.github/workflows/test.yml +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/.gitignore +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/.pre-commit-config.yaml +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/LICENSE +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/README.md +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/assets/assets.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/assets/embedding_assets_metadata.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/asynchronize/__init__.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/converter.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/__init__.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/babeldoc_exception/BabelDOCException.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/backend/__init__.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/backend/pdf_creater.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/frontend/__init__.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/frontend/il_creater.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/il_version_1.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/il_version_1.rnc +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/il_version_1.rng +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/il_version_1.xsd +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/midend/__init__.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/midend/add_debug_information.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/midend/detect_scanned_file.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/midend/layout_parser.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/midend/paragraph_finder.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/midend/remove_descent.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/midend/styles_and_formulas.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/midend/table_parser.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/midend/typesetting.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/translator/__init__.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/translator/cache.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/utils/atomic_integer.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/utils/fontmap.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/utils/layout_helper.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/utils/paragraph_helper.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/utils/priority_thread_pool_executor.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/utils/style_helper.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/utils/zstd_helper.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/xml_converter.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/docvision/README.md +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/docvision/__init__.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/docvision/doclayout.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/docvision/rpc_doclayout.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/docvision/table_detection/rapidocr.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/format/office/__init__.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/high_level.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/pdfinterp.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/progress_monitor.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/result_merger.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/split_manager.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/tools/generate_font_metadata.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/tools/italic_assistance.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/tools/italic_recognize_tool.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/translation_config.py +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/CODE_OF_CONDUCT.md +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/CONTRIBUTING.md +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/CONTRIBUTOR_REWARD.md +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/ImplementationDetails/AsyncTranslate/AsyncTranslate.md +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/ImplementationDetails/ILTranslator/ILTranslator.md +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/ImplementationDetails/PDFCreation/PDFCreation.md +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/ImplementationDetails/PDFParsing/PDFParsing.md +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/ImplementationDetails/ParagraphFinding/ParagraphFinding.md +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/ImplementationDetails/README.md +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/ImplementationDetails/StylesAndFormulas/StylesAndFormulas.md +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/ImplementationDetails/Typesetting/Typesetting.md +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/README.md +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/deploy.sh +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/images/babeldoc-banner.png +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/images/babeldoc-big-logo-darkmode-with-transparent-background.png +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/images/babeldoc-big-logo-darkmode-with-transparent-background.svg +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/images/babeldoc-big-logo-with-transparent-background.png +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/images/babeldoc-big-logo-with-transparent-background.svg +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/images/babeldoc-big-logo.png +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/images/babeldoc-contributor_reward_example.png +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/images/babeldoc-preview.gif +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/images/babeldoc-small-logo-with-transparent-background.png +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/images/babeldoc-small-logo-with-transparent-background.svg +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/images/babeldoc-small-logo.png +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/index.md +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/intro-to-pdf-object.md +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/requirements.txt +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/docs/supported_languages.md +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/mkdocs.yml +0 -0
- {babeldoc-0.3.40 → babeldoc-0.3.42}/tests/test_translation_config.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.3.42"
|
|
@@ -39,18 +39,29 @@ class RichTextPlaceholder:
|
|
|
39
39
|
composition: PdfSameStyleCharacters,
|
|
40
40
|
left_placeholder: str,
|
|
41
41
|
right_placeholder: str,
|
|
42
|
+
left_regex_pattern: str = None,
|
|
43
|
+
right_regex_pattern: str = None,
|
|
42
44
|
):
|
|
43
45
|
self.id = placeholder_id
|
|
44
46
|
self.composition = composition
|
|
45
47
|
self.left_placeholder = left_placeholder
|
|
46
48
|
self.right_placeholder = right_placeholder
|
|
49
|
+
self.left_regex_pattern = left_regex_pattern
|
|
50
|
+
self.right_regex_pattern = right_regex_pattern
|
|
47
51
|
|
|
48
52
|
|
|
49
53
|
class FormulaPlaceholder:
|
|
50
|
-
def __init__(
|
|
54
|
+
def __init__(
|
|
55
|
+
self,
|
|
56
|
+
placeholder_id: int,
|
|
57
|
+
formula: PdfFormula,
|
|
58
|
+
placeholder: str,
|
|
59
|
+
regex_pattern: str,
|
|
60
|
+
):
|
|
51
61
|
self.id = placeholder_id
|
|
52
62
|
self.formula = formula
|
|
53
63
|
self.placeholder = placeholder
|
|
64
|
+
self.regex_pattern = regex_pattern
|
|
54
65
|
|
|
55
66
|
|
|
56
67
|
class PbarContext:
|
|
@@ -328,10 +339,14 @@ class ILTranslator:
|
|
|
328
339
|
paragraph: PdfParagraph,
|
|
329
340
|
):
|
|
330
341
|
placeholder = self.translate_engine.get_formular_placeholder(formula_id)
|
|
342
|
+
if isinstance(placeholder, tuple):
|
|
343
|
+
placeholder, regex_pattern = placeholder
|
|
344
|
+
else:
|
|
345
|
+
regex_pattern = re.escape(placeholder)
|
|
331
346
|
if placeholder in paragraph.unicode:
|
|
332
347
|
return self.create_formula_placeholder(formula, formula_id + 1, paragraph)
|
|
333
348
|
|
|
334
|
-
return FormulaPlaceholder(formula_id, formula, placeholder)
|
|
349
|
+
return FormulaPlaceholder(formula_id, formula, placeholder, regex_pattern)
|
|
335
350
|
|
|
336
351
|
def create_rich_text_placeholder(
|
|
337
352
|
self,
|
|
@@ -345,6 +360,14 @@ class ILTranslator:
|
|
|
345
360
|
right_placeholder = self.translate_engine.get_rich_text_right_placeholder(
|
|
346
361
|
composition_id,
|
|
347
362
|
)
|
|
363
|
+
if isinstance(left_placeholder, tuple):
|
|
364
|
+
left_placeholder, left_placeholder_regex_pattern = left_placeholder
|
|
365
|
+
else:
|
|
366
|
+
left_placeholder_regex_pattern = re.escape(left_placeholder)
|
|
367
|
+
if isinstance(right_placeholder, tuple):
|
|
368
|
+
right_placeholder, right_placeholder_regex_pattern = right_placeholder
|
|
369
|
+
else:
|
|
370
|
+
right_placeholder_regex_pattern = re.escape(right_placeholder)
|
|
348
371
|
if (
|
|
349
372
|
left_placeholder in paragraph.unicode
|
|
350
373
|
or right_placeholder in paragraph.unicode
|
|
@@ -360,6 +383,8 @@ class ILTranslator:
|
|
|
360
383
|
composition,
|
|
361
384
|
left_placeholder,
|
|
362
385
|
right_placeholder,
|
|
386
|
+
left_placeholder_regex_pattern,
|
|
387
|
+
right_placeholder_regex_pattern,
|
|
363
388
|
)
|
|
364
389
|
|
|
365
390
|
def get_translate_input(
|
|
@@ -550,13 +575,14 @@ class ILTranslator:
|
|
|
550
575
|
for placeholder in input_text.placeholders:
|
|
551
576
|
if isinstance(placeholder, FormulaPlaceholder):
|
|
552
577
|
# 转义特殊字符
|
|
553
|
-
pattern = re.escape(placeholder.placeholder)
|
|
578
|
+
# pattern = re.escape(placeholder.placeholder)
|
|
579
|
+
pattern = placeholder.regex_pattern
|
|
554
580
|
patterns.append(f"({pattern})")
|
|
555
581
|
placeholder_patterns.append(f"({pattern})")
|
|
556
582
|
placeholder_map[placeholder.placeholder] = placeholder
|
|
557
583
|
else:
|
|
558
|
-
left =
|
|
559
|
-
right =
|
|
584
|
+
left = placeholder.left_regex_pattern
|
|
585
|
+
right = placeholder.right_regex_pattern
|
|
560
586
|
patterns.append(f"({left}.*?{right})")
|
|
561
587
|
placeholder_patterns.append(f"({left})")
|
|
562
588
|
placeholder_patterns.append(f"({right})")
|
|
@@ -569,6 +595,8 @@ class ILTranslator:
|
|
|
569
595
|
if all_match:
|
|
570
596
|
if llm_translate_tracker:
|
|
571
597
|
llm_translate_tracker.set_placeholder_full_match()
|
|
598
|
+
else:
|
|
599
|
+
logger.debug(f"Failed to match all placeholder for {input_text.unicode}")
|
|
572
600
|
# 合并所有模式
|
|
573
601
|
combined_pattern = "|".join(patterns)
|
|
574
602
|
combined_placeholder_pattern = "|".join(placeholder_patterns)
|
|
@@ -618,13 +646,12 @@ class ILTranslator:
|
|
|
618
646
|
p
|
|
619
647
|
for p in input_text.placeholders
|
|
620
648
|
if not isinstance(p, FormulaPlaceholder)
|
|
621
|
-
and
|
|
649
|
+
and re.match(f"^{p.left_regex_pattern}", matched_text)
|
|
622
650
|
)
|
|
623
|
-
text =
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
]
|
|
651
|
+
text = re.match(
|
|
652
|
+
f"^{placeholder.left_regex_pattern}(.+){placeholder.right_regex_pattern}$",
|
|
653
|
+
matched_text,
|
|
654
|
+
).group(1)
|
|
628
655
|
|
|
629
656
|
if isinstance(
|
|
630
657
|
placeholder.composition,
|
|
@@ -738,39 +765,69 @@ class ILTranslator:
|
|
|
738
765
|
llm_input = [self.translation_config.custom_system_prompt]
|
|
739
766
|
else:
|
|
740
767
|
llm_input = [
|
|
741
|
-
"You are a professional
|
|
768
|
+
f"You are a professional and reliable machine translation engine responsible for translating the input text into {self.translation_config.lang_out}."
|
|
742
769
|
]
|
|
770
|
+
llm_hint = []
|
|
743
771
|
|
|
744
772
|
if title_paragraph:
|
|
745
|
-
|
|
773
|
+
llm_hint.append(
|
|
746
774
|
f"The first title in the full text: {title_paragraph.unicode}"
|
|
747
775
|
)
|
|
748
776
|
if (
|
|
749
777
|
local_title_paragraph
|
|
750
778
|
and local_title_paragraph.debug_id != title_paragraph.debug_id
|
|
751
779
|
):
|
|
752
|
-
|
|
780
|
+
llm_hint.append(
|
|
753
781
|
f"The most similar title in the full text: {local_title_paragraph.unicode}"
|
|
754
782
|
)
|
|
755
|
-
# Create a structured prompt template for LLM translation
|
|
756
|
-
llm_input.append(
|
|
757
|
-
f'Please do not translate style tags like "{self.translate_engine.get_rich_text_left_placeholder(1)}xxx{self.translate_engine.get_rich_text_right_placeholder(2)}"!'
|
|
758
|
-
)
|
|
759
783
|
|
|
760
|
-
llm_input.append(
|
|
761
|
-
f'Please do not translate formula placeholders like "{self.translate_engine.get_formular_placeholder(3)}"!'
|
|
762
|
-
)
|
|
763
784
|
if self.translation_config.add_formula_placehold_hint:
|
|
764
785
|
placeholders_hint = translate_input.get_placeholders_hint()
|
|
765
786
|
if placeholders_hint:
|
|
766
|
-
|
|
787
|
+
llm_hint.append(
|
|
767
788
|
f"This is the formula placeholder hint: \n{placeholders_hint}"
|
|
768
789
|
)
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
790
|
+
|
|
791
|
+
if llm_hint:
|
|
792
|
+
llm_input.append(
|
|
793
|
+
"When translating, please refer to the following information to improve translation quality:"
|
|
794
|
+
)
|
|
795
|
+
for i, line in enumerate(llm_hint):
|
|
796
|
+
llm_input.append(f"{i}. {line}")
|
|
797
|
+
llm_input.append("When translating, please follow the following rules:")
|
|
798
|
+
|
|
799
|
+
rich_text_left_placeholder = (
|
|
800
|
+
self.translate_engine.get_rich_text_left_placeholder(1)
|
|
801
|
+
)
|
|
802
|
+
if isinstance(rich_text_left_placeholder, tuple):
|
|
803
|
+
rich_text_left_placeholder = rich_text_left_placeholder[0]
|
|
804
|
+
rich_text_right_placeholder = (
|
|
805
|
+
self.translate_engine.get_rich_text_right_placeholder(2)
|
|
806
|
+
)
|
|
807
|
+
if isinstance(rich_text_right_placeholder, tuple):
|
|
808
|
+
rich_text_right_placeholder = rich_text_right_placeholder[0]
|
|
809
|
+
|
|
810
|
+
# Create a structured prompt template for LLM translation
|
|
811
|
+
llm_input.append(
|
|
812
|
+
f'1. Do not translate style tags, such as "{rich_text_left_placeholder}xxx{rich_text_right_placeholder}"!'
|
|
813
|
+
)
|
|
814
|
+
|
|
815
|
+
formula_placeholder = self.translate_engine.get_formular_placeholder(3)
|
|
816
|
+
if isinstance(formula_placeholder, tuple):
|
|
817
|
+
formula_placeholder = formula_placeholder[0]
|
|
818
|
+
|
|
819
|
+
llm_input.append(
|
|
820
|
+
f'2. Do not translate formula placeholders, such as "{formula_placeholder}". The system will automatically replace the placeholders with the corresponding formulas.'
|
|
821
|
+
)
|
|
822
|
+
llm_input.append(
|
|
823
|
+
"3. If there is no need to translate (such as proper nouns, codes, etc.), then return the original text."
|
|
824
|
+
)
|
|
825
|
+
llm_input.append(
|
|
826
|
+
"4. Only output the translation result without explanations and annotations."
|
|
827
|
+
)
|
|
828
|
+
llm_input.append(f"5. Translate text into {self.translation_config.lang_out}.")
|
|
772
829
|
prompt_template = f"""
|
|
773
|
-
|
|
830
|
+
Now, please carefully read the following text to be translated and directly output your translation.\n\n{text}
|
|
774
831
|
|
|
775
832
|
"""
|
|
776
833
|
llm_input.append(prompt_template)
|
|
@@ -177,7 +177,7 @@ class ILTranslatorLLMOnly:
|
|
|
177
177
|
copy.deepcopy(paragraph)
|
|
178
178
|
)
|
|
179
179
|
|
|
180
|
-
if total_token_count >
|
|
180
|
+
if total_token_count > 200 or len(paragraphs) > 10:
|
|
181
181
|
executor.submit(
|
|
182
182
|
self.translate_paragraph,
|
|
183
183
|
BatchParagraph(paragraphs, tracker),
|
|
@@ -224,6 +224,7 @@ class ILTranslatorLLMOnly:
|
|
|
224
224
|
try:
|
|
225
225
|
inputs = []
|
|
226
226
|
llm_translate_trackers = []
|
|
227
|
+
paragraph_unicodes = []
|
|
227
228
|
for i in range(len(batch_paragraph.paragraphs)):
|
|
228
229
|
paragraph = batch_paragraph.paragraphs[i]
|
|
229
230
|
tracker = batch_paragraph.trackers[i]
|
|
@@ -237,8 +238,16 @@ class ILTranslatorLLMOnly:
|
|
|
237
238
|
should_translate_paragraph.append(i)
|
|
238
239
|
llm_translate_trackers.append(llm_translate_tracker)
|
|
239
240
|
inputs.append(
|
|
240
|
-
(
|
|
241
|
+
(
|
|
242
|
+
text,
|
|
243
|
+
translate_input,
|
|
244
|
+
paragraph,
|
|
245
|
+
tracker,
|
|
246
|
+
llm_translate_tracker,
|
|
247
|
+
paragraph_unicodes,
|
|
248
|
+
)
|
|
241
249
|
)
|
|
250
|
+
paragraph_unicodes.append(paragraph.unicode)
|
|
242
251
|
if not inputs:
|
|
243
252
|
return
|
|
244
253
|
json_format_input = []
|
|
@@ -265,24 +274,57 @@ class ILTranslatorLLMOnly:
|
|
|
265
274
|
llm_input = [self.translation_config.custom_system_prompt]
|
|
266
275
|
else:
|
|
267
276
|
llm_input = [
|
|
268
|
-
"You are a professional
|
|
277
|
+
f"You are a professional and reliable machine translation engine responsible for translating the input text into {self.translation_config.lang_out}."
|
|
269
278
|
]
|
|
270
279
|
|
|
280
|
+
llm_hint = []
|
|
271
281
|
if title_paragraph:
|
|
272
|
-
|
|
282
|
+
llm_hint.append(
|
|
273
283
|
f"The first title in the full text: {title_paragraph.unicode}"
|
|
274
284
|
)
|
|
275
285
|
if (
|
|
276
286
|
local_title_paragraph
|
|
277
287
|
and local_title_paragraph.debug_id != title_paragraph.debug_id
|
|
278
288
|
):
|
|
279
|
-
|
|
289
|
+
llm_hint.append(
|
|
280
290
|
f"The most similar title in the full text: {local_title_paragraph.unicode}"
|
|
281
291
|
)
|
|
292
|
+
|
|
293
|
+
if llm_hint:
|
|
294
|
+
llm_input.append(
|
|
295
|
+
"When translating, please refer to the following information to improve translation quality:"
|
|
296
|
+
)
|
|
297
|
+
for i, line in enumerate(llm_hint):
|
|
298
|
+
llm_input.append(f"{i}. {line}")
|
|
299
|
+
llm_input.append("When translating, please follow the following rules:")
|
|
300
|
+
# Create a structured prompt template for LLM translation
|
|
301
|
+
rich_text_left_placeholder = (
|
|
302
|
+
self.translate_engine.get_rich_text_left_placeholder(1)
|
|
303
|
+
)
|
|
304
|
+
if isinstance(rich_text_left_placeholder, tuple):
|
|
305
|
+
rich_text_left_placeholder = rich_text_left_placeholder[0]
|
|
306
|
+
rich_text_right_placeholder = (
|
|
307
|
+
self.translate_engine.get_rich_text_right_placeholder(2)
|
|
308
|
+
)
|
|
309
|
+
if isinstance(rich_text_right_placeholder, tuple):
|
|
310
|
+
rich_text_right_placeholder = rich_text_right_placeholder[0]
|
|
311
|
+
llm_input.append(
|
|
312
|
+
f'1. Do not translate style tags, such as "{rich_text_left_placeholder}xxx{rich_text_right_placeholder}"!'
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
formula_placeholder = self.translate_engine.get_formular_placeholder(3)
|
|
316
|
+
if isinstance(formula_placeholder, tuple):
|
|
317
|
+
formula_placeholder = formula_placeholder[0]
|
|
318
|
+
llm_input.append(
|
|
319
|
+
f'2. Do not translate formula placeholders, such as "{formula_placeholder}". The system will automatically replace the placeholders with the corresponding formulas.'
|
|
320
|
+
)
|
|
321
|
+
llm_input.append(
|
|
322
|
+
"3. If there is no need to translate (such as proper nouns, codes, etc.), then return the original text."
|
|
323
|
+
)
|
|
282
324
|
# Create a structured prompt template for LLM translation
|
|
283
325
|
prompt_template = (
|
|
284
326
|
f"""
|
|
285
|
-
You will be given a JSON formatted input containing entries with "id" and "input" fields.
|
|
327
|
+
4. You will be given a JSON formatted input containing entries with "id" and "input" fields.
|
|
286
328
|
|
|
287
329
|
For each entry in the JSON, translate the contents of the "input" field into {self.translation_config.lang_out}.
|
|
288
330
|
Write the translation back into the "output" field for that entry.
|
|
@@ -318,16 +360,6 @@ class ILTranslatorLLMOnly:
|
|
|
318
360
|
"""
|
|
319
361
|
)
|
|
320
362
|
llm_input.append(prompt_template)
|
|
321
|
-
llm_input.append(
|
|
322
|
-
f'Please do not translate style tags like "{self.translate_engine.get_rich_text_left_placeholder(1)}xxx{self.translate_engine.get_rich_text_right_placeholder(2)}"!'
|
|
323
|
-
)
|
|
324
|
-
llm_input.append(
|
|
325
|
-
f'Please do not translate formula placeholders like "{self.translate_engine.get_formular_placeholder(3)}"!'
|
|
326
|
-
)
|
|
327
|
-
if self.translation_config.add_formula_placehold_hint:
|
|
328
|
-
llm_input.append(
|
|
329
|
-
"The system will automatically replace placeholders with corresponding formulas, please do not translate the placeholders!"
|
|
330
|
-
)
|
|
331
363
|
llm_input.append(
|
|
332
364
|
f"""Here is the input:
|
|
333
365
|
|
|
@@ -350,7 +382,10 @@ class ILTranslatorLLMOnly:
|
|
|
350
382
|
|
|
351
383
|
parsed_output = json.loads(llm_output)
|
|
352
384
|
|
|
353
|
-
translation_results = {
|
|
385
|
+
translation_results = {
|
|
386
|
+
item["id"]: item.get("output", item.get("input"))
|
|
387
|
+
for item in parsed_output
|
|
388
|
+
}
|
|
354
389
|
|
|
355
390
|
if len(translation_results) != len(inputs):
|
|
356
391
|
raise Exception(
|
|
@@ -428,6 +463,8 @@ class ILTranslatorLLMOnly:
|
|
|
428
463
|
paragraph_token_count = self.calc_token_count(
|
|
429
464
|
inputs[id_][2].unicode
|
|
430
465
|
)
|
|
466
|
+
paragraph_unicodes = inputs[id_][5]
|
|
467
|
+
inputs[id_][2].unicode = paragraph_unicodes[id_]
|
|
431
468
|
executor.submit(
|
|
432
469
|
self.il_translator.translate_paragraph,
|
|
433
470
|
inputs[id_][2],
|
|
@@ -446,6 +483,9 @@ class ILTranslatorLLMOnly:
|
|
|
446
483
|
logger.warning(error_message)
|
|
447
484
|
for llm_translate_tracker in llm_translate_trackers:
|
|
448
485
|
llm_translate_tracker.set_error_message(error_message)
|
|
486
|
+
llm_translate_tracker.set_fallback_to_translate()
|
|
487
|
+
for input_ in inputs:
|
|
488
|
+
input_[2].unicode = input_[5]
|
|
449
489
|
if not should_translate_paragraph:
|
|
450
490
|
should_translate_paragraph = list(
|
|
451
491
|
range(len(batch_paragraph.paragraphs))
|
|
@@ -277,11 +277,14 @@ class OpenAITranslator(BaseTranslator):
|
|
|
277
277
|
logger.exception("Error updating token count")
|
|
278
278
|
|
|
279
279
|
def get_formular_placeholder(self, placeholder_id: int):
|
|
280
|
-
return "{v" + str(placeholder_id) + "}"
|
|
280
|
+
return "{v" + str(placeholder_id) + "}", f"{{\\s*v\\s*{placeholder_id}\\s*}}"
|
|
281
281
|
return "{{" + str(placeholder_id) + "}}"
|
|
282
282
|
|
|
283
283
|
def get_rich_text_left_placeholder(self, placeholder_id: int):
|
|
284
|
-
return
|
|
284
|
+
return (
|
|
285
|
+
f"<style id='{placeholder_id}'>",
|
|
286
|
+
f"<\\s*style\\s*id\\s*=\\s*'\\s*{placeholder_id}\\s*'\\s*>",
|
|
287
|
+
)
|
|
285
288
|
|
|
286
289
|
def get_rich_text_right_placeholder(self, placeholder_id: int):
|
|
287
|
-
return "</style>"
|
|
290
|
+
return "</style>", r"<\s*\/\s*style\s*>"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "BabelDOC"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.42"
|
|
4
4
|
description = "Yet Another Document Translator"
|
|
5
5
|
license = "AGPL-3.0"
|
|
6
6
|
readme = "README.md"
|
|
@@ -150,7 +150,7 @@ pythonpath = [".", "src"]
|
|
|
150
150
|
testpaths = ["tests"]
|
|
151
151
|
|
|
152
152
|
[bumpver]
|
|
153
|
-
current_version = "0.3.
|
|
153
|
+
current_version = "0.3.42"
|
|
154
154
|
version_pattern = "MAJOR.MINOR.PATCH[.PYTAGNUM]"
|
|
155
155
|
|
|
156
156
|
[bumpver.file_patterns]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.3.40"
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/babeldoc_exception/BabelDOCException.py
RENAMED
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{babeldoc-0.3.40 → babeldoc-0.3.42}/babeldoc/document_il/utils/priority_thread_pool_executor.py
RENAMED
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{babeldoc-0.3.40 → babeldoc-0.3.42}/docs/ImplementationDetails/AsyncTranslate/AsyncTranslate.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{babeldoc-0.3.40 → babeldoc-0.3.42}/docs/ImplementationDetails/ParagraphFinding/ParagraphFinding.md
RENAMED
|
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
|
{babeldoc-0.3.40 → babeldoc-0.3.42}/docs/images/babeldoc-big-logo-with-transparent-background.png
RENAMED
|
File without changes
|
{babeldoc-0.3.40 → babeldoc-0.3.42}/docs/images/babeldoc-big-logo-with-transparent-background.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{babeldoc-0.3.40 → babeldoc-0.3.42}/docs/images/babeldoc-small-logo-with-transparent-background.png
RENAMED
|
File without changes
|
{babeldoc-0.3.40 → babeldoc-0.3.42}/docs/images/babeldoc-small-logo-with-transparent-background.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|