epub-translator 0.0.6__py3-none-any.whl → 0.1.0__py3-none-any.whl

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 (82) hide show
  1. epub_translator/__init__.py +3 -1
  2. epub_translator/data/fill.jinja +66 -0
  3. epub_translator/data/mmltex/README.md +67 -0
  4. epub_translator/data/mmltex/cmarkup.xsl +1106 -0
  5. epub_translator/data/mmltex/entities.xsl +459 -0
  6. epub_translator/data/mmltex/glayout.xsl +222 -0
  7. epub_translator/data/mmltex/mmltex.xsl +36 -0
  8. epub_translator/data/mmltex/scripts.xsl +375 -0
  9. epub_translator/data/mmltex/tables.xsl +130 -0
  10. epub_translator/data/mmltex/tokens.xsl +328 -0
  11. epub_translator/data/translate.jinja +15 -12
  12. epub_translator/epub/__init__.py +4 -2
  13. epub_translator/epub/common.py +43 -0
  14. epub_translator/epub/math.py +193 -0
  15. epub_translator/epub/placeholder.py +53 -0
  16. epub_translator/epub/spines.py +42 -0
  17. epub_translator/epub/toc.py +505 -0
  18. epub_translator/epub/zip.py +67 -0
  19. epub_translator/iter_sync.py +24 -0
  20. epub_translator/language.py +23 -0
  21. epub_translator/llm/__init__.py +2 -1
  22. epub_translator/llm/core.py +175 -0
  23. epub_translator/llm/error.py +38 -35
  24. epub_translator/llm/executor.py +159 -136
  25. epub_translator/llm/increasable.py +28 -28
  26. epub_translator/llm/types.py +17 -0
  27. epub_translator/serial/__init__.py +2 -0
  28. epub_translator/serial/chunk.py +52 -0
  29. epub_translator/serial/segment.py +17 -0
  30. epub_translator/serial/splitter.py +50 -0
  31. epub_translator/template.py +35 -33
  32. epub_translator/translator.py +205 -168
  33. epub_translator/utils.py +7 -0
  34. epub_translator/xml/__init__.py +4 -3
  35. epub_translator/xml/deduplication.py +38 -0
  36. epub_translator/xml/firendly/__init__.py +2 -0
  37. epub_translator/xml/firendly/decoder.py +75 -0
  38. epub_translator/xml/firendly/encoder.py +84 -0
  39. epub_translator/xml/firendly/parser.py +177 -0
  40. epub_translator/xml/firendly/tag.py +118 -0
  41. epub_translator/xml/firendly/transform.py +36 -0
  42. epub_translator/xml/xml.py +52 -0
  43. epub_translator/xml/xml_like.py +176 -0
  44. epub_translator/xml_translator/__init__.py +3 -0
  45. epub_translator/xml_translator/const.py +2 -0
  46. epub_translator/xml_translator/fill.py +128 -0
  47. epub_translator/xml_translator/format.py +282 -0
  48. epub_translator/xml_translator/fragmented.py +125 -0
  49. epub_translator/xml_translator/group.py +183 -0
  50. epub_translator/xml_translator/progressive_locking.py +256 -0
  51. epub_translator/xml_translator/submitter.py +102 -0
  52. epub_translator/xml_translator/text_segment.py +263 -0
  53. epub_translator/xml_translator/translator.py +178 -0
  54. epub_translator/xml_translator/utils.py +29 -0
  55. epub_translator-0.1.0.dist-info/METADATA +283 -0
  56. epub_translator-0.1.0.dist-info/RECORD +58 -0
  57. epub_translator/data/format.jinja +0 -33
  58. epub_translator/epub/content_parser.py +0 -162
  59. epub_translator/epub/html/__init__.py +0 -1
  60. epub_translator/epub/html/dom_operator.py +0 -62
  61. epub_translator/epub/html/empty_tags.py +0 -23
  62. epub_translator/epub/html/file.py +0 -80
  63. epub_translator/epub/html/texts_searcher.py +0 -46
  64. epub_translator/llm/node.py +0 -201
  65. epub_translator/translation/__init__.py +0 -2
  66. epub_translator/translation/chunk.py +0 -118
  67. epub_translator/translation/splitter.py +0 -78
  68. epub_translator/translation/store.py +0 -36
  69. epub_translator/translation/translation.py +0 -231
  70. epub_translator/translation/types.py +0 -45
  71. epub_translator/translation/utils.py +0 -11
  72. epub_translator/xml/decoder.py +0 -71
  73. epub_translator/xml/encoder.py +0 -95
  74. epub_translator/xml/parser.py +0 -172
  75. epub_translator/xml/tag.py +0 -93
  76. epub_translator/xml/transform.py +0 -34
  77. epub_translator/xml/utils.py +0 -12
  78. epub_translator/zip_context.py +0 -74
  79. epub_translator-0.0.6.dist-info/METADATA +0 -170
  80. epub_translator-0.0.6.dist-info/RECORD +0 -36
  81. {epub_translator-0.0.6.dist-info → epub_translator-0.1.0.dist-info}/LICENSE +0 -0
  82. {epub_translator-0.0.6.dist-info → epub_translator-0.1.0.dist-info}/WHEEL +0 -0
@@ -1,93 +0,0 @@
1
- from io import StringIO
2
- from enum import auto, Enum
3
- from typing import Generator
4
- from dataclasses import dataclass
5
-
6
-
7
- class TagKind(Enum):
8
- OPENING = auto()
9
- CLOSING = auto()
10
- SELF_CLOSING = auto()
11
-
12
- @dataclass
13
- class Tag:
14
- kind: TagKind
15
- name: str
16
- proto: str
17
- attributes: list[tuple[str, str]]
18
-
19
- def __str__(self):
20
- buffer = StringIO()
21
- buffer.write("<")
22
- if self.kind == TagKind.CLOSING:
23
- buffer.write("/")
24
- buffer.write(self.name)
25
- if len(self.attributes) > 0:
26
- buffer.write(" ")
27
- for i, (attr_name, attr_value) in enumerate(self.attributes):
28
- buffer.write(attr_name)
29
- buffer.write("=")
30
- buffer.write("\"")
31
- buffer.write(attr_value)
32
- buffer.write("\"")
33
- if i < len(self.attributes) - 1:
34
- buffer.write(" ")
35
- if self.kind == TagKind.SELF_CLOSING:
36
- buffer.write("/>")
37
- else:
38
- buffer.write(">")
39
- return buffer.getvalue()
40
-
41
- def find_invalid_name(self) -> str | None:
42
- for name in self._iter_tag_names():
43
- if not all(is_valid_value_char(c) for c in name):
44
- return name
45
- # https://www.w3schools.com/xml/xml_elements.asp
46
- # The following logic enforces a subset of XML naming rules:
47
- # - Names must not be empty.
48
- # - Names must start with a letter (a-z, A-Z) or an underscore (_).
49
- if name == "":
50
- return name
51
- char = name[0]
52
- if char == "_":
53
- continue
54
- if "a" <= char <= "z" or "A" <= char <= "Z":
55
- continue
56
- return name
57
-
58
- return None
59
-
60
- def find_invalid_attr_value(self) -> tuple[str, str] | None:
61
- for attr_name, attr_value in self.attributes:
62
- if not all(is_valid_value_char(c) for c in attr_value):
63
- return attr_name, attr_value
64
- return None
65
-
66
- def _iter_tag_names(self) -> Generator[str, None, None]:
67
- yield self.name
68
- for attr_name, _ in self.attributes:
69
- yield attr_name
70
-
71
- def is_valid_value_char(char: str) -> bool:
72
- if is_valid_name_char(char):
73
- return True
74
- if char == ",":
75
- return True
76
- if char == ".":
77
- return True
78
- if char == "/":
79
- return True
80
- return False
81
-
82
- def is_valid_name_char(char: str) -> bool:
83
- if "a" <= char <= "z":
84
- return True
85
- if "A" <= char <= "Z":
86
- return True
87
- if "0" <= char <= "9":
88
- return True
89
- if char == "_":
90
- return True
91
- if char == "-":
92
- return True
93
- return False
@@ -1,34 +0,0 @@
1
- from xml.etree.ElementTree import Element
2
- from .tag import Tag, TagKind
3
-
4
-
5
- def tag_to_element(tag: Tag) -> Element:
6
- element = Element(tag.name)
7
- for attr_name, attr_value in tag.attributes:
8
- element.set(attr_name, attr_value)
9
- return element
10
-
11
- def element_to_tag(element: Element, kind: TagKind, proto: str = "") -> Tag:
12
- tag = Tag(
13
- kind=kind,
14
- name=element.tag,
15
- proto=proto,
16
- attributes=[],
17
- )
18
- if kind != TagKind.CLOSING:
19
- for attr_name in sorted(list(element.keys())):
20
- attr_value = element.get(attr_name, "")
21
- tag.attributes.append((attr_name, attr_value))
22
-
23
- # To make LLM easier to understand, the naming here is restricted in a more strict way.
24
- # https://github.com/oomol-lab/pdf-craft/issues/149
25
- invalid_name = tag.find_invalid_name()
26
- if invalid_name is not None:
27
- raise ValueError(f"find invalid tag name or attribute name: {invalid_name}")
28
-
29
- invalid_attr_pair = tag.find_invalid_attr_value()
30
- if invalid_attr_pair is not None:
31
- attr_name, attr_value = invalid_attr_pair
32
- raise ValueError(f"find invalid attribute value: {attr_name}=\"{attr_value}\"")
33
-
34
- return tag
@@ -1,12 +0,0 @@
1
- from xml.etree.ElementTree import Element
2
-
3
- def clone(element: Element) -> Element:
4
- new_element = Element(element.tag)
5
- for attr_name, attr_value in element.items():
6
- new_element.set(attr_name, attr_value)
7
- new_element.text = element.text
8
- for child in element:
9
- new_child = clone(child)
10
- new_element.append(new_child)
11
- new_child.tail = child.tail
12
- return new_element
@@ -1,74 +0,0 @@
1
- import zipfile
2
-
3
- from typing import Generator, Callable
4
- from pathlib import Path
5
- from lxml.etree import parse
6
- from .epub import EpubContent, HTMLFile
7
-
8
-
9
- class ZipContext:
10
- def __init__(self, epub_path: Path, temp_dir: Path):
11
- with zipfile.ZipFile(epub_path, "r") as zip_ref:
12
- for member in zip_ref.namelist():
13
- target_path = temp_dir / member
14
- if member.endswith("/"):
15
- target_path.mkdir(parents=True, exist_ok=True)
16
- else:
17
- target_path.parent.mkdir(parents=True, exist_ok=True)
18
- with zip_ref.open(member) as source:
19
- with open(target_path, "wb") as file:
20
- file.write(source.read())
21
-
22
- self._temp_dir: Path = temp_dir
23
- self._epub_content: EpubContent = EpubContent(str(temp_dir))
24
-
25
- def archive(self, saved_path: Path):
26
- with zipfile.ZipFile(saved_path, "w") as zip_file:
27
- for file_path in self._temp_dir.rglob("*"):
28
- if not file_path.is_file():
29
- continue
30
- relative_path = file_path.relative_to(self._temp_dir)
31
- zip_file.write(
32
- filename=file_path,
33
- arcname=str(relative_path),
34
- )
35
-
36
- def search_spine_paths(self) -> Generator[Path, None, None]:
37
- for spine in self._epub_content.spines:
38
- if spine.media_type == "application/xhtml+xml":
39
- yield Path(spine.path)
40
-
41
- def read_spine_file(self, spine_path: Path) -> HTMLFile:
42
- with open(spine_path, "r", encoding="utf-8") as file:
43
- return HTMLFile(file.read())
44
-
45
- def write_spine_file(self, spine_path: Path, file: HTMLFile):
46
- with open(spine_path, "w", encoding="utf-8") as f:
47
- f.write(file.file_content)
48
-
49
- def replace_ncx(self, replace: Callable[[list[str]], list[str]]):
50
- ncx_path = self._epub_content.ncx_path
51
- if ncx_path is None:
52
- return
53
-
54
- tree = parse(ncx_path)
55
- root = tree.getroot()
56
- namespaces={ "ns": root.nsmap.get(None) }
57
- text_doms = []
58
- text_list = []
59
-
60
- for text_dom in root.xpath("//ns:text", namespaces=namespaces):
61
- text_doms.append(text_dom)
62
- text_list.append(text_dom.text or "")
63
-
64
- for index, text in enumerate(replace(text_list)):
65
- text_dom = text_doms[index]
66
- text_dom.text = self._link_translated(text_dom.text, text)
67
-
68
- tree.write(ncx_path, pretty_print=True)
69
-
70
- def _link_translated(self, origin: str, target: str) -> str:
71
- if origin == target:
72
- return origin
73
- else:
74
- return f"{origin} - {target}"
@@ -1,170 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: epub-translator
3
- Version: 0.0.6
4
- Summary: Translate the epub book using LLM. The translated book will retain the original text and list the translated text side by side with the original text.
5
- License: MIT
6
- Keywords: epub,llm,translation,translator
7
- Author: Tao Zeyu
8
- Author-email: i@taozeyu.com
9
- Maintainer: Tao Zeyu
10
- Maintainer-email: i@taozeyu.com
11
- Requires-Python: >=3.10,<3.13
12
- Classifier: License :: OSI Approved :: MIT License
13
- Classifier: Programming Language :: Python :: 3
14
- Classifier: Programming Language :: Python :: 3.10
15
- Classifier: Programming Language :: Python :: 3.11
16
- Classifier: Programming Language :: Python :: 3.12
17
- Requires-Dist: jinja2 (>=3.1.5,<4.0.0)
18
- Requires-Dist: langchain[openai] (>=0.3.21,<0.4.0)
19
- Requires-Dist: lxml (>=6.0.0,<7.0.0)
20
- Requires-Dist: resource-segmentation (>=0.0.3,<0.1.0)
21
- Requires-Dist: tiktoken (>=0.9.0,<0.10.0)
22
- Project-URL: Homepage, https://hub.oomol.com/package/book-translator
23
- Project-URL: Repository, https://github.com/oomol-flows/books-translator
24
- Description-Content-Type: text/markdown
25
-
26
- <div align=center>
27
- <h1>EPUB Translator</h1>
28
- <p>
29
- <a href="https://github.com/oomol-lab/epub-translator/actions/workflows/build.yml" target="_blank"><img src="https://img.shields.io/github/actions/workflow/status/oomol-lab/epub-translator/build.yml" alt"ci" /></a>
30
- <a href="https://pypi.org/project/epub-translator/" target="_blank"><img src="https://img.shields.io/badge/pip_install-epub--translator-blue" alt="pip install epub-translator" /></a>
31
- <a href="https://pypi.org/project/epub-translator/" target="_blank"><img src="https://img.shields.io/pypi/v/epub-translator.svg" alt"pypi epub-translator" /></a>
32
- <a href="https://pypi.org/project/epub-translator/" target="_blank"><img src="https://img.shields.io/pypi/pyversions/epub-translator.svg" alt="python versions" /></a>
33
- <a href="https://github.com/oomol-lab/epub-translator/blob/main/LICENSE" target="_blank"><img src="https://img.shields.io/github/license/oomol-lab/epub-translator" alt"license" /></a>
34
- </p>
35
- <p><a href="https://hub.oomol.com/package/books-translator?open=true" target="_blank"><img src="https://static.oomol.com/assets/button.svg" alt="Open in OOMOL Studio" /></a></p>
36
- <p>English | <a href="./README_zh-CN.md">中文</a></p>
37
- </div>
38
-
39
- ## Introduction
40
-
41
- epub-translator uses AI big models to automatically translate EPUB e-books, and retains 100% of the original book's format, illustrations, catalog and layout, while generating bilingual comparison versions for easy language learning or international sharing.
42
-
43
- Whether you are a developer, language learner, or e-book lover, epub-translator can help you easily overcome language barriers.
44
-
45
- - [x] **Multi-language translation**: Supports translation between mainstream languages ​​such as English, Chinese, Japanese, Spanish, French, and German.
46
- - [x] **Bilingual comparison**: Generates bilingual EPUBs with top-down comparisons for easy comparison and learning.
47
- - [x] **Insert prompt words**: Guide AI translation, such as glossary, character name list, etc.
48
- - [x] **Optional AI model**: Supports mainstream big models such as DeepSeek and ChatGPT.
49
- - [x] **High-performance parallelism**: AI requests multiple concurrent channels to quickly translate the entire book.
50
-
51
- ## Environment
52
-
53
- You can call EPUB Translator directly as a library, or use [OOMOL Studio](https://oomol.com/) to run it directly.
54
-
55
- ### Run with OOMOL Studio
56
-
57
- OOMOL uses container technology to directly package the dependencies required by EPUB Translator, and it is ready to use out of the box.
58
-
59
- [![](./docs/images/link2youtube.png)](https://www.youtube.com/watch?v=QsAdiskxfXI)
60
-
61
- ### Call directly as a library
62
-
63
- You can also write python code directly and call it as a library. At this time, you need python 3.10 or higher (3.10.16 is recommended).
64
-
65
- ```shell
66
- pip install epub-translator
67
- ```
68
-
69
- ## Quick start
70
-
71
- First, construct the `LLM` object that calls the AI ​​Large Language Model.
72
-
73
- ```python
74
- from epub_translator import LLM
75
-
76
- llm = LLM(
77
- key="<LLM-API-KEY>", # LLM's API key
78
- url="https://api.deepseek.com", # LLM's base URL
79
- model="deepseek-chat", # LLM's model name
80
- token_encoding="o200k_base", # Local model for calculating the number of tokens
81
- )
82
- ```
83
-
84
- Then, you can call the `translate` method to translate.
85
-
86
- ```python
87
- from epub_translator import translate, Language
88
-
89
- translate(
90
- llm=llm, # llm object constructed in the previous step
91
- source_path="/path/to/epub/file", # Original EPUB file to be translated
92
- translated_path="/path/to/translated/epub/file", # Path to save the translated EPUB
93
- target_language=Language.ENGLISH, # Target language for translation, in this case English.
94
- )
95
- ```
96
-
97
- After calling this method, the translation can be inserted under the original text while retaining the EPUB format.
98
-
99
- ![](./docs/images/translation.png)
100
-
101
- ## Function
102
-
103
- ### Save translation progress
104
-
105
- Calling `translate` to translate the entire EPUB e-book takes a long time, and this process may be interrupted for various reasons. For example, when calling LLM, an error is reported and the process is interrupted due to network reasons, or the user can't wait and manually interrupts the process.
106
-
107
- EPUB Translator can cache the translated content as a local file, so that when translating the same book, the translation progress can be saved and the progress can be restored from the last translation interruption.
108
-
109
- Just configure the `working_path` field when calling `translate` and specify a path to cache the files generated by the translation. The next time it is started, EPUB Translator will try to read the translation progress from this path in advance.
110
-
111
- ```python
112
- translate(
113
- ..., # other parameters
114
- working_path="/path/to/cache/translating/files",
115
- )
116
- ```
117
-
118
- Please note that each call to the `translate` method will write a cache file to the folder where the `workspace_path` is located. This will cause the folder to grow larger and larger. You need to handle it yourself, for example, automatically clear the folder after the translation is successful.
119
-
120
- ### Monitor translation progress
121
-
122
- When calling `translate`, pass a callback function through `report_progress`, and receive a `float` type parameter representing the progress from 0.0 to 1.0, so that the translation progress of the whole book can be monitored.
123
-
124
- ```python
125
- from tqdm import tqdm
126
- from epub_translator import translate
127
-
128
- with tqdm(total=1.0, desc="Translating") as bar:
129
- def refresh_progress(progress: float) -> None:
130
- bar.n = progress
131
- bar.refresh()
132
-
133
- translate(
134
- ..., # other parameters
135
- report_progress=refresh_progress,
136
- )
137
- ```
138
-
139
- ### Insert prompt words
140
-
141
- Insert prompt words to guide the AI ​​language model on how to translate. For example, you can insert a glossary so that AI can unify the terms when translating. Just add the `user_prompt` field when calling `translate`.
142
-
143
- ```python
144
- translate(
145
- ..., # other parameters
146
- user_prompt='Le Petit Prince should be translated as "Little Prince".',
147
- )
148
- ```
149
-
150
- ### Large Language Model Parameters
151
-
152
- There are more configuration options when building the `LLM` object.
153
-
154
- ```python
155
- llm = LLM(
156
- key="<LLM-API-KEY>", # LLM's API key
157
- url="https://api.deepseek.com", # LLM's base URL
158
- model="deepseek-chat", # LLM's model name
159
- token_encoding="o200k_base", # Local model for calculating the number of tokens
160
- timeout=60.0, # Request timeout (in seconds)
161
- top_p=0.6, # Creativity
162
- temperature=0.85, # Temperature
163
- retry_times=5, # Retry times. If the request still fails after this number, an error will be reported
164
- retry_interval_seconds=6.0, # Retry interval (in seconds)
165
- )
166
- ```
167
-
168
- ## Related open source libraries
169
-
170
- [PDF Craft](https://github.com/oomol-lab/pdf-craft) can convert PDF files into various other formats. This project will focus on the processing of PDF files of scanned books. Use this library with the scanned PDF books to convert and translate them. For more information, please refer to [Video: Convert scanned PDF books to EPUB format and translate them into bilingual books](https://www.bilibili.com/video/BV1tMQZY5EYY/).
@@ -1,36 +0,0 @@
1
- epub_translator/__init__.py,sha256=69k-70xbqxLgTvLyJE_MPFyymmPgyUAFg4mCSfEn49k,106
2
- epub_translator/data/format.jinja,sha256=1dXiMAhznuHWA2vpDx-968pm95FCXCRV3cKVmy3EXYA,3710
3
- epub_translator/data/translate.jinja,sha256=XWiMgeQS3tKCnh9cC6p1KQs9kqb1GO6m_j_cNeDq8lQ,1768
4
- epub_translator/epub/__init__.py,sha256=vqD29XWxgcfHw8LFCHQxupQeJufEEoS5_KHNphwfEYU,73
5
- epub_translator/epub/content_parser.py,sha256=Y-2fEcACCAl_ucA6VwwOoQ95BMHr9f-hryuxnsYNONM,4403
6
- epub_translator/epub/html/__init__.py,sha256=Yyg0TrWjecolaJP6qLzDnOlhi7SrkW0Is7wh9Fr0-Bg,26
7
- epub_translator/epub/html/dom_operator.py,sha256=Ryayv6hG0jEXv7RkXrZTbIP54P0fyPTbMVbymMtBUnU,1935
8
- epub_translator/epub/html/empty_tags.py,sha256=GSSe-CV4YkUhWv4F0fiiRsf2vz0ZBAsC21Ovnqo5oIA,601
9
- epub_translator/epub/html/file.py,sha256=AqUV-Tmptk5J2EYmw3oRVsLjGSqEMNz5rItnoRbGstc,2477
10
- epub_translator/epub/html/texts_searcher.py,sha256=vamO99pki6_sX2PeKCJk7mPwHdApZq1sOgSYDTPckx8,1376
11
- epub_translator/llm/__init__.py,sha256=wMBWLgh5iLNQBioniSOmWC83NS7RLM41hIs1V1uZiWI,21
12
- epub_translator/llm/error.py,sha256=fG0A3z69YoSNu0MNVWVFMtHCB_4fpOvAEb0Kajn9OHc,1401
13
- epub_translator/llm/executor.py,sha256=Z8mpsTAEEfG80E43Pv5VJJzaDKrrClyUhr8GFA2yVxA,4498
14
- epub_translator/llm/increasable.py,sha256=Dpu5z4JK5h1OtLorZgsOAdRFeTH2LOkdroasgmCWAIo,1136
15
- epub_translator/llm/node.py,sha256=qdkBY06OOt0mq8tnLgMJZS5dc3WFColzpeHmyWLE7KU,6104
16
- epub_translator/template.py,sha256=GdV3QnypProKFCMH1kBNfdt6wiShygP_-xGnE5EOUwU,1460
17
- epub_translator/translation/__init__.py,sha256=oYRMq3PJf2eZfIAAHkFmC_MZ3vLdeCQFzowuwAd9jd8,100
18
- epub_translator/translation/chunk.py,sha256=ERIDvhM7kZB_ZqWGw4UQfKgjIHn7TDWsxa-RuTpxRs0,3639
19
- epub_translator/translation/splitter.py,sha256=9YLEdRRA01NEWKmI-UUtAXHq2iJOyZtCnt1ZWQ0h0dU,2696
20
- epub_translator/translation/store.py,sha256=T6OYhQZETPz5p-ykmPC_wDLzmRet8o7jDY3sHxWVV1o,1057
21
- epub_translator/translation/translation.py,sha256=BBmaNME7Pd0zytK_7CCx10dsoWLootB3uggvYLW-rQM,7079
22
- epub_translator/translation/types.py,sha256=Pnzll2V4MnOsW_kIP0XU6Cj-QQkLTByB6dr_U4sdNH8,989
23
- epub_translator/translation/utils.py,sha256=G6Gqq6mot3lgFA-jqUD0UqtDS0GC1wrb9DnK7rTxJNs,223
24
- epub_translator/translator.py,sha256=t5vgiDPiYda1CiKtEB91hjqVrN2dDZ7sTBLTotIVv3w,5487
25
- epub_translator/xml/__init__.py,sha256=o2_qwUYU_MUcyfmfKkiOQ-cKUQyl4PiRL8YHVzCTAZU,106
26
- epub_translator/xml/decoder.py,sha256=UlqgmEKQDzxt3lvBeNGHgZP6jznmnq_1HLJuAe5X0C4,2181
27
- epub_translator/xml/encoder.py,sha256=p4A7GRSOM2i0WOh1lLtEdTTg2gXSQrxDdzMgUqbiV18,2428
28
- epub_translator/xml/parser.py,sha256=3JuFLFLX4w98pzME72ywdpq0JzSBgzwZMFbH8IfB9T4,5545
29
- epub_translator/xml/tag.py,sha256=QLZImF0PtYyiASI7swrB8DL_qUwcYpU6cL68jEXDnvg,2353
30
- epub_translator/xml/transform.py,sha256=vS_a4d_o2Qqf9B6k2CovQVLUknp6TyUi3FyLOu21Vio,1126
31
- epub_translator/xml/utils.py,sha256=KDNGWHwaIiFKS27sjZF0e-bBSjeTxzceae_aeuj4wzI,384
32
- epub_translator/zip_context.py,sha256=SwkqghokGLGx-tlZ_K7sJTF-g-cm6dErurSZCM-ZLeM,2414
33
- epub_translator-0.0.6.dist-info/LICENSE,sha256=5RF32sL3LtMOJIErdDKp1ZEYPGXS8WPpsiSz_jMBnGI,1066
34
- epub_translator-0.0.6.dist-info/METADATA,sha256=D_355033oXlgbht7x16tq6eHP50NZnHtStSyTDfF0-o,8081
35
- epub_translator-0.0.6.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
36
- epub_translator-0.0.6.dist-info/RECORD,,