From a046c1eb011c76bcd3bff8bb184f4dc5b596b6f4 Mon Sep 17 00:00:00 2001 From: bookfere Date: Mon, 25 Mar 2024 21:07:53 +0800 Subject: [PATCH] feat: Side-by-side translation for content with line breaks. resolved #148 --- advanced.py | 11 +- batch.py | 24 +++- lib/element.py | 84 ++++++++--- lib/translation.py | 5 +- tests/test_element.py | 98 ++++++++++++- translations/es.po | 8 +- translations/fr.po | 8 +- translations/message.pot | 96 +++++++------ translations/pt.po | 8 +- translations/tr.po | 295 ++++----------------------------------- translations/zh_CN.mo | Bin 17569 -> 17675 bytes translations/zh_CN.po | 8 +- translations/zh_TW.po | 8 +- ui.py | 4 +- 14 files changed, 294 insertions(+), 363 deletions(-) diff --git a/advanced.py b/advanced.py index a28eb0c2..98246cc1 100644 --- a/advanced.py +++ b/advanced.py @@ -73,8 +73,6 @@ def clean_cache(self, cache): @pyqtSlot() def prepare_ebook_data(self): - self.progress_detail.emit( - 'Start processing the ebook: %s' % self.ebook.title) input_path = self.ebook.get_input_path() element_handler = get_element_handler( self.engine_class.placeholder, self.engine_class.separator) @@ -88,6 +86,8 @@ def prepare_ebook_data(self): cache = get_cache(cache_id) if cache.is_fresh() or not cache.is_persistence(): + self.progress_detail.emit( + 'Start processing the ebook: %s' % self.ebook.title) cache.set_info('title', self.ebook.title) cache.set_info('engine_name', self.engine_class.name) cache.set_info('target_lang', self.ebook.target_lang) @@ -133,9 +133,10 @@ def prepare_ebook_data(self): if self.cancel(): self.clean_cache(cache) return - - self.progress_detail.emit( - 'The ebook content was extracted successfully.') + else: + self.progress_detail.emit( + 'Loading data from cache and preparing user interface...') + time.sleep(0.1) self.finished.emit(cache_id) diff --git a/batch.py b/batch.py index 91124143..1725f40c 100644 --- a/batch.py +++ b/batch.py @@ -3,6 +3,8 @@ from .lib.config import get_config from .lib.translation import get_engine_class +from .lib.conversion import extra_formats +from .lib.encodings import encoding_list from .engines.custom import CustomTranslate from .components import ( layout_info, AlertMessage, SourceLang, TargetLang, InputFormat, @@ -12,11 +14,11 @@ try: from qt.core import ( QDialog, QWidget, QPushButton, QHeaderView, QVBoxLayout, QTableWidget, - QTableWidgetItem, Qt) + QTableWidgetItem, Qt, QComboBox, QLabel) except ImportError: from PyQt5.Qt import ( QDialog, QWidget, QPushButton, QHeaderView, QVBoxLayout, QTableWidget, - QTableWidgetItem, Qt) + QTableWidgetItem, Qt, QComboBox, QLabel) load_translations() @@ -52,7 +54,7 @@ def layout_translate(self): table.setRowCount(len(self.ebooks)) table.setColumnCount(5) table.setHorizontalHeaderLabels([ - _('Title'), _('Input Format'), _('Output Format'), + _('Title'), _('Encoding'), _('Input Format'), _('Output Format'), _('Source Language'), _('Target Language')]) header = table.horizontalHeader() @@ -68,11 +70,21 @@ def layout_translate(self): ebook_title.setSizeHint(table.sizeHint()) table.setItem(row, 0, ebook_title) + if ebook.input_format in extra_formats.keys(): + input_encoding = QComboBox() + input_encoding.addItems(encoding_list) + input_encoding.currentTextChanged.connect( + lambda encoding, row=row: self.ebooks[row] + .set_encoding(encoding)) + else: + input_encoding = QLabel(_('Default')) + table.setCellWidget(row, 2, input_encoding) + input_fmt = InputFormat(ebook.files.keys()) table.setCellWidget(row, 1, input_fmt) output_format = OutputFormat() - table.setCellWidget(row, 2, output_format) + table.setCellWidget(row, 3, output_format) exist_format = output_format.findText(ebook.input_format) if ebook.is_extra_format() and exist_format: @@ -94,7 +106,7 @@ def change_output_format(format, row=row): output_format.currentTextChanged.connect(change_output_format) source_lang = SourceLang(book_lang=ebook.source_lang) - table.setCellWidget(row, 3, source_lang) + table.setCellWidget(row, 4, source_lang) self.source_langs.append(source_lang) def change_source_lang(lang, row=row): @@ -108,7 +120,7 @@ def change_source_lang(lang, row=row): not issubclass(translation_engine, CustomTranslate)) target_lang = TargetLang() - table.setCellWidget(row, 4, target_lang) + table.setCellWidget(row, 5, target_lang) self.target_langs.append(target_lang) def change_target_lang(lang, row=row): diff --git a/lib/element.py b/lib/element.py index a6b6c019..d013467c 100644 --- a/lib/element.py +++ b/lib/element.py @@ -193,9 +193,6 @@ def get_attributes(self): attributes = dict(self.element.attrib.items()) return json.dumps(attributes) if attributes else None - def delete(self): - self.element.getparent().remove(self.element) - def _safe_remove(self, element, replacement=''): previous, parent = element.getprevious(), element.getparent() if previous is not None: @@ -211,23 +208,25 @@ def get_content(self): element_copy = self._element_copy() for noise in self._get_descendents(element_copy, ('rt', 'rp')): self._safe_remove(noise) - + # Reserve the
element instead of using a line break to prevent + # conflicts with the mechanism of merge translation. target_elements = ( - 'img', 'code', 'hr', 'sub', 'sup', 'kbd', 'abbr', 'wbr', 'var', + 'img', 'code', 'br', 'hr', 'sub', 'sup', 'kbd', 'abbr', 'wbr', 'var', 'canvas', 'svg', 'script', 'style') self.reserve_elements = self._get_descendents( element_copy, target_elements) for eid, reserve in enumerate(self.reserve_elements): replacement = self.placeholder[0].format(format(eid, '05')) - parent = reserve.getparent() - if parent is not None and get_name(parent) == 'a': - index = self.reserve_elements.index(reserve) - self.reserve_elements[index] = reserve = parent + if get_name(reserve) in ['sub', 'sup']: + parent = reserve.getparent() + if parent is not None and get_name(parent) == 'a' and \ + parent.text is None and reserve.tail is None and \ + len(parent.getchildren()) == 1: + index = self.reserve_elements.index(reserve) + self.reserve_elements[index] = reserve = parent self._safe_remove(reserve, replacement) - for br in self._get_descendents(element_copy, 'br'): - self._safe_remove(br, '
') - return trim(''.join(element_copy.itertext())).replace('
', '\n') + return trim(''.join(element_copy.itertext())) def _polish_translation(self, translation): translation = translation.replace('\n', '
') @@ -261,7 +260,7 @@ def add_translation(self, translation=None): if translation is None: if self.position in ('left', 'right'): self.element.addnext(self._create_table()) - self.delete() + self._safe_remove(self.element) return # Escape the markups () to replace escaped markups. translation = xml_escape(translation) @@ -282,7 +281,7 @@ def add_translation(self, translation=None): if element_name in group_elements: if self.position == 'only': self.element.addnext(new_element) - self.delete() + self._safe_remove(self.element) new_element = self._create_new_element( 'span', translation, excluding_tags=['class']) if self.position in ['left', 'above']: @@ -320,25 +319,68 @@ def add_translation(self, translation=None): # Add translation for left or right position. if self.position in ('left', 'right') and not is_text_element: self.element.addnext(self._create_table(new_element)) - self.delete() + self._safe_remove(self.element) + return + + # TODO: Needs to be optimized for various situations. + # Add translation for line breaks. + line_break_tag = '{%s}br' % ns['x'] + original_br_list = list(self.element.iterchildren(line_break_tag)) + translation_br_list = list(new_element.iterchildren(line_break_tag)) + if len(original_br_list) == len(translation_br_list) >= 5: + tail = None + for index, br in enumerate(original_br_list): + new_br = etree.SubElement(self.element, 'br') + translation_br = translation_br_list[index] + br.addprevious(new_br) + if self.position == 'below': + for sibling in translation_br.itersiblings(preceding=True): + if get_name(sibling) == 'br': + break + new_br.addnext(sibling) + new_br.tail = new_element.text if index == 0 else tail + tail = translation_br.tail + if br == original_br_list[-1]: + new_br = etree.SubElement(self.element, 'br') + self.element.append(new_br) + translation_br = translation_br_list[-1] + for sibling in translation_br.itersiblings(): + new_br.addnext(sibling) + new_br.tail = translation_br.tail + else: + for sibling in translation_br.itersiblings(): + if get_name(sibling) == 'br': + break + new_br.addnext(sibling) + new_br.tail = translation_br.tail + if br == original_br_list[-1]: + new_br = etree.SubElement(self.element, 'br') + new_br.tail = self.element.text + self.element.text = new_element.text + self.element.insert(0, new_br) + translation_br = translation_br_list[0] + sblings = list( + translation_br.itersiblings(preceding=True)) + for sibling in reversed(sblings): + new_br.addprevious(sibling) return - parent = self.element.getparent() - is_table_element = parent is not None and \ - get_name(parent) in group_elements + parent_element = self.element.getparent() + is_table_descendant = parent_element is not None and \ + get_name(parent_element) in group_elements if self.position in ('left', 'above'): self.element.addprevious(new_element) - if is_text_element and is_table_element: + if is_text_element and is_table_descendant: new_element.addnext(etree.SubElement(self.element, 'br')) elif is_text_element: new_element.tail = ' ' else: self.element.addnext(new_element) if self.position == 'only': - self.delete() + self._safe_remove(self.element) return - if is_text_element and is_table_element: + if is_text_element and is_table_descendant: self.element.addnext(etree.SubElement(self.element, 'br')) elif is_text_element: if self.element.tail is not None: diff --git a/lib/translation.py b/lib/translation.py index ab942f8f..b10dabef 100644 --- a/lib/translation.py +++ b/lib/translation.py @@ -255,9 +255,8 @@ def handle(self, paragraphs=[]): raise Exception(_('Translation failed.')) consuming = round((time.time() - start_time) / 60, 2) self.log('Time consuming: %s minutes' % consuming) - message = _('Translation completed.') - self.log(message) - self.progress(1, message) + self.log(_('Translation completed.')) + self.progress(1, _('Outputting ebook file...')) def get_engine_class(engine_name=None): diff --git a/tests/test_element.py b/tests/test_element.py index d2b8eca4..1f80b7e9 100644 --- a/tests/test_element.py +++ b/tests/test_element.py @@ -216,7 +216,7 @@ def test_get_raw(self): def test_get_text(self): self.assertEqual('a', self.element.get_text()) - def test_test_content(self): + def test_get_content(self): self.assertEqual('a', self.element.get_content()) def test_add_translation_only(self): @@ -381,14 +381,38 @@ def test_get_text(self): def test_get_content(self): content = ('{{id_00000}} a {{id_00001}} b c {{id_00002}} d e ' '{{id_00003}} f g {{id_00004}} h {{id_00005}} i ' - '{{id_00006}} {{id_00007}} k{{id_00008}}\nl') + '{{id_00006}} {{id_00007}} k{{id_00008}}{{id_00009}}l') self.assertEqual(content, self.element.get_content()) - self.assertEqual(9, len(self.element.reserve_elements)) + self.assertEqual(10, len(self.element.reserve_elements)) for element in self.element.reserve_elements: with self.subTest(element=element): self.assertIsNone(element.tail) + def test_get_content_with_sup_sub(self): + xhtml = etree.XML(rb""" + + + Test Document + +

+ a[1] + b[1] x + cx [2] + d[3] x +

+ +""") + self.element = PageElement(xhtml.find('.//x:p', namespaces=ns), 'p1') + self.element.placeholder = Base.placeholder + content = ( + 'a{{id_00000}} b{{id_00001}} x cx {{id_00002}} d{{id_00003}} x') + self.assertEqual(content, self.element.get_content()) + self.assertEqual('a', get_name(self.element.reserve_elements[0])) + self.assertEqual('sup', get_name(self.element.reserve_elements[1])) + self.assertEqual('sup', get_name(self.element.reserve_elements[2])) + self.assertEqual('sup', get_name(self.element.reserve_elements[3])) + def test_get_attributes(self): self.assertEqual('{"class": "abc"}', self.element.get_attributes()) @@ -451,7 +475,8 @@ def test_add_translation_with_placeholder(self): translation = ('{{id_00000}} Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ' '{{id_00001}} Bbbbbbbbbbbbbbb C {{id_00002}} D E ' '{{id_00003}} F G {{id_00004}} H \n\n{{id_00005}} I ' - '{{id_00006}} {{id_00007}} K{ { id _ 0 00 08 } }\nL') + '{{id_00006}} {{id_00007}} K{ { id _ 0 00 08 } }' + '{{id_00009}}L') self.element.add_translation(translation) translation = ('

' @@ -473,7 +498,8 @@ def test_add_translation_with_markup(self): self.element.get_content() translation = (' A B C D ' 'E F G H ' - 'I K\nL') + 'I K' + 'L') self.element.add_translation(translation) translation = ('

' @@ -589,6 +615,68 @@ def test_add_translation_table(slef): def test_add_translation_table_only(slef): pass + def test_add_translation_line_break_below(self): + xhtml = etree.XML(rb""" + + + Test Document + +

+ a[1] b c[2]
+ d e
+ f g
h
i
j +

+ +""") + + element = PageElement(xhtml.find('.//x:p', namespaces=ns), 'p1') + element.placeholder = Base.placeholder + element.position = 'below' + element.get_content() + element.add_translation( + 'A{{id_00000}} B C{{id_00001}}{{id_00002}} D E {{id_00003}}' + '{{id_00004}} F G{{id_00005}}H{{id_00006}}I{{id_00007}}J ') + translation = ( + ' ' + 'Test Document ' + '

a[1] b c[2]
' + 'A[1] B C[2]
d e ' + '
D E
' + ' f g
F G
h
H
i
I
j ' + '
J

') + self.assertEqual(translation, get_string(xhtml)) + + def test_add_translation_line_break_above(self): + xhtml = etree.XML(rb""" + + + Test Document + +

+ a[1] b c[2]
+ d e
+ f g
h
i
j +

+ +""") + + element = PageElement(xhtml.find('.//x:p', namespaces=ns), 'p1') + element.placeholder = Base.placeholder + element.position = 'above' + element.get_content() + element.add_translation( + 'A{{id_00000}} B C{{id_00001}}{{id_00002}} D E {{id_00003}}' + '{{id_00004}} F G{{id_00005}}H{{id_00006}}I{{id_00007}}J') + translation = ( + ' ' + 'Test Document ' + '

A[1] B C[2]
' + ' a[1] b c[2]
' + ' D E
d e ' + '
F G
f g
' + 'H
h
I
i
J
j

') + self.assertEqual(translation, get_string(xhtml)) + def test_add_translation_attr(self): self.element.translation_lang = 'zh' self.element.original_color = 'green' diff --git a/translations/es.po b/translations/es.po index ea667b9c..7c8c8010 100644 --- a/translations/es.po +++ b/translations/es.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Ebook Translator Calibre Plugin\n" "Report-Msgid-Bugs-To: bookfere@gmail.com\n" -"POT-Creation-Date: 2024-03-21 20:51+0800\n" +"POT-Creation-Date: 2024-03-25 21:02+0800\n" "PO-Revision-Date: 2023-04-17 14:17+0800\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" @@ -160,6 +160,9 @@ msgstr "Formato de salida" msgid "Title" msgstr "Título" +msgid "Default" +msgstr "" + msgid "Translate" msgstr "Traducir" @@ -467,6 +470,9 @@ msgstr "No hay necesidad de traducir el contenido." msgid "Translation failed." msgstr "" +msgid "Outputting ebook file..." +msgstr "" + msgid "General" msgstr "" diff --git a/translations/fr.po b/translations/fr.po index 86aada54..452e7787 100644 --- a/translations/fr.po +++ b/translations/fr.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: Ebook Translator Calibre Plugin\n" "Report-Msgid-Bugs-To: bookfere@gmail.com\n" -"POT-Creation-Date: 2024-03-21 20:51+0800\n" +"POT-Creation-Date: 2024-03-25 21:02+0800\n" "PO-Revision-Date: 2023-10-01 15:35-0400\n" "Last-Translator: PoP\n" @@ -160,6 +160,9 @@ msgstr "Format de sortie" msgid "Title" msgstr "Titre" +msgid "Default" +msgstr "" + msgid "Translate" msgstr "Traduire" @@ -476,6 +479,9 @@ msgstr "Il n'y a pas de contenu à traduire." msgid "Translation failed." msgstr "La traduction a échoué." +msgid "Outputting ebook file..." +msgstr "" + msgid "General" msgstr "Général" diff --git a/translations/message.pot b/translations/message.pot index 1103276e..ce65c044 100644 --- a/translations/message.pot +++ b/translations/message.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Ebook Translator Calibre Plugin\n" "Report-Msgid-Bugs-To: bookfere@gmail.com\n" -"POT-Creation-Date: 2024-03-21 20:51+0800\n" +"POT-Creation-Date: 2024-03-25 21:02+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -27,19 +27,19 @@ msgid "" "keeping the original content)." msgstr "" -#: advanced.py:101 +#: advanced.py:100 msgid "Extracting ebook content..." msgstr "" -#: advanced.py:108 +#: advanced.py:107 msgid "Failed to extract ebook content" msgstr "" -#: advanced.py:120 +#: advanced.py:119 msgid "Filtering ebook content..." msgstr "" -#: advanced.py:129 +#: advanced.py:128 msgid "Preparing user interface..." msgstr "" @@ -47,15 +47,15 @@ msgstr "" msgid "Start" msgstr "" -#: advanced.py:223 batch.py:55 setting.py:186 +#: advanced.py:223 batch.py:57 setting.py:186 msgid "Input Format" msgstr "" -#: advanced.py:234 advanced.py:604 batch.py:56 setting.py:369 +#: advanced.py:234 advanced.py:604 batch.py:58 setting.py:369 msgid "Target Language" msgstr "" -#: advanced.py:250 +#: advanced.py:250 batch.py:57 msgid "Encoding" msgstr "" @@ -132,7 +132,7 @@ msgstr "" msgid "Translation Engine" msgstr "" -#: advanced.py:598 batch.py:56 setting.py:368 +#: advanced.py:598 batch.py:58 setting.py:368 msgid "Source Language" msgstr "" @@ -171,47 +171,51 @@ msgstr "" msgid "No translation yet" msgstr "" -#: advanced.py:783 components/engine.py:208 setting.py:98 +#: advanced.py:786 components/engine.py:208 setting.py:98 msgid "Save" msgstr "" -#: advanced.py:839 +#: advanced.py:842 msgid "Your changes have been saved." msgstr "" -#: advanced.py:852 +#: advanced.py:855 msgid "Translation log" msgstr "" -#: advanced.py:863 +#: advanced.py:866 msgid "Error log" msgstr "" -#: advanced.py:883 +#: advanced.py:886 msgid "Are you sure you want to translate all {:n} paragraphs?" msgstr "" -#: advanced.py:909 +#: advanced.py:912 msgid "Are you sure you want to stop the translation progress?" msgstr "" -#: batch.py:55 setting.py:187 +#: batch.py:57 setting.py:187 msgid "Output Format" msgstr "" -#: batch.py:55 cache.py:202 +#: batch.py:57 cache.py:202 msgid "Title" msgstr "" -#: batch.py:128 components/engine.py:139 components/table.py:133 +#: batch.py:80 +msgid "Default" +msgstr "" + +#: batch.py:140 components/engine.py:139 components/table.py:133 msgid "Translate" msgstr "" -#: batch.py:139 lib/cache.py:126 +#: batch.py:151 lib/cache.py:125 msgid "Unknown" msgstr "" -#: batch.py:148 cache.py:130 setting.py:1136 +#: batch.py:160 cache.py:130 setting.py:1136 msgid "The specified path does not exist." msgstr "" @@ -358,7 +362,7 @@ msgstr "" msgid "Choose a translation mode for clicking the icon button." msgstr "" -#: components/mode.py:33 setting.py:115 ui.py:54 ui.py:82 +#: components/mode.py:33 setting.py:115 ui.py:52 ui.py:80 msgid "Advanced Mode" msgstr "" @@ -368,7 +372,7 @@ msgid "" "for more control and customization." msgstr "" -#: components/mode.py:43 setting.py:116 ui.py:55 ui.py:109 +#: components/mode.py:43 setting.py:116 ui.py:53 ui.py:107 msgid "Batch Mode" msgstr "" @@ -511,53 +515,53 @@ msgstr "" msgid "Youdao" msgstr "" -#: lib/conversion.py:73 +#: lib/conversion.py:74 msgid "Start to convert ebook format..." msgstr "" -#: lib/conversion.py:96 +#: lib/conversion.py:98 msgid "Starting to output subtitles file..." msgstr "" -#: lib/conversion.py:102 +#: lib/conversion.py:104 msgid "The translation of the subtitles file was completed." msgstr "" -#: lib/conversion.py:120 +#: lib/conversion.py:123 msgid "Starting to output PGN file..." msgstr "" -#: lib/conversion.py:130 +#: lib/conversion.py:133 msgid "The translation of the PGN file was completed." msgstr "" -#: lib/conversion.py:267 +#: lib/conversion.py:269 msgid "[{} > {}] Translating \"{}\"" msgstr "" -#: lib/conversion.py:276 tests/test_convertion.py:40 +#: lib/conversion.py:278 tests/test_convertion.py:40 msgid "Translation job failed" msgstr "" -#: lib/conversion.py:324 tests/test_convertion.py:98 +#: lib/conversion.py:326 tests/test_convertion.py:98 #: tests/test_convertion.py:164 tests/test_convertion.py:228 #: tests/test_convertion.py:284 msgid "completed" msgstr "" -#: lib/conversion.py:337 tests/test_convertion.py:103 +#: lib/conversion.py:339 tests/test_convertion.py:103 #: tests/test_convertion.py:169 tests/test_convertion.py:235 #: tests/test_convertion.py:289 msgid "Ebook Translation Log" msgstr "" -#: lib/conversion.py:338 tests/test_convertion.py:104 +#: lib/conversion.py:340 tests/test_convertion.py:104 #: tests/test_convertion.py:170 tests/test_convertion.py:236 #: tests/test_convertion.py:290 msgid "Translation Completed" msgstr "" -#: lib/conversion.py:339 tests/test_convertion.py:106 +#: lib/conversion.py:341 tests/test_convertion.py:106 #: tests/test_convertion.py:172 tests/test_convertion.py:238 #: tests/test_convertion.py:292 msgid "The translation of \"{}\" was completed. Do you want to open the book?" @@ -619,6 +623,10 @@ msgstr "" msgid "Translation failed." msgstr "" +#: lib/translation.py:259 +msgid "Outputting ebook file..." +msgstr "" + #: setting.py:62 msgid "General" msgstr "" @@ -683,7 +691,7 @@ msgstr "" msgid "Test" msgstr "" -#: setting.py:271 ui.py:57 +#: setting.py:271 ui.py:55 msgid "Cache" msgstr "" @@ -975,42 +983,42 @@ msgstr "" msgid "{} is not a valid CSS seletor." msgstr "" -#: ui.py:38 +#: ui.py:36 msgid "Translate Book" msgstr "" -#: ui.py:38 +#: ui.py:36 msgid "Translate Ebook Content" msgstr "" -#: ui.py:58 ui.py:126 +#: ui.py:56 ui.py:124 msgid "Setting" msgstr "" -#: ui.py:59 ui.py:154 +#: ui.py:57 ui.py:152 msgid "About" msgstr "" -#: ui.py:90 +#: ui.py:88 msgid "Please choose one single book." msgstr "" -#: ui.py:103 +#: ui.py:101 msgid "Please choose at least one book." msgstr "" -#: ui.py:117 +#: ui.py:115 msgid "Cannot change setting while book(s) are under translation." msgstr "" -#: ui.py:134 +#: ui.py:132 msgid "Cannot manage cache while book(s) are under translation." msgstr "" -#: ui.py:143 +#: ui.py:141 msgid "Cache Manager" msgstr "" -#: ui.py:172 +#: ui.py:170 msgid "Choose Translation Mode" msgstr "" diff --git a/translations/pt.po b/translations/pt.po index 5710197f..4e798f92 100644 --- a/translations/pt.po +++ b/translations/pt.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Ebook Translator Calibre Plugin\n" "Report-Msgid-Bugs-To: bookfere@gmail.com\n" -"POT-Creation-Date: 2024-03-21 20:51+0800\n" +"POT-Creation-Date: 2024-03-25 21:02+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: none\n" @@ -159,6 +159,9 @@ msgstr "Formato de Saída" msgid "Title" msgstr "Título" +msgid "Default" +msgstr "" + msgid "Translate" msgstr "Traduzir" @@ -478,6 +481,9 @@ msgstr "Não há conteúdo para ser traduzido." msgid "Translation failed." msgstr "Tradução falhou." +msgid "Outputting ebook file..." +msgstr "" + msgid "General" msgstr "Geral" diff --git a/translations/tr.po b/translations/tr.po index 41274d73..234c8c8a 100644 --- a/translations/tr.po +++ b/translations/tr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Ebook Translator Calibre Plugin\n" "Report-Msgid-Bugs-To: bookfere@gmail.com\n" -"POT-Creation-Date: 2024-03-21 20:51+0800\n" +"POT-Creation-Date: 2024-03-25 21:02+0800\n" "PO-Revision-Date: 2024-03-23 15:12+0300\n" "Last-Translator: DogancanYr \n" "Language-Team: Turkish \n" @@ -17,482 +17,367 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: __init__.py:19 msgid "Ebook Translator" msgstr "E-kitap Çevirmeni" -#: __init__.py:26 msgid "" "A Calibre plugin to translate ebook into a specified language (optionally " "keeping the original content)." msgstr "" -"E-kitabı belirli bir dile çevirmek için bir Calibre eklentisi" -"(isteğe bağlı olarak orijinal içeriği korur)." +"E-kitabı belirli bir dile çevirmek için bir Calibre eklentisi(isteğe bağlı " +"olarak orijinal içeriği korur)." -#: advanced.py:101 msgid "Extracting ebook content..." msgstr "E-kitap içeriği çıkarılıyor..." -#: advanced.py:108 msgid "Failed to extract ebook content" msgstr "E-kitap içeriği çıkarılamadı" -#: advanced.py:120 msgid "Filtering ebook content..." msgstr "E-kitap içeriği filtreleniyor..." -#: advanced.py:129 msgid "Preparing user interface..." msgstr "Kullanıcı arayüzü hazırlanıyor..." -#: advanced.py:209 msgid "Start" msgstr "Başlat" -#: advanced.py:223 batch.py:55 setting.py:186 msgid "Input Format" msgstr "Giriş Formatı" -#: advanced.py:234 advanced.py:604 batch.py:56 setting.py:369 msgid "Target Language" msgstr "Hedef Dil" -#: advanced.py:250 msgid "Encoding" msgstr "Kodlama" -#: advanced.py:340 msgid "Failed to translate {} paragraph(s), Would you like to retry?" msgstr "{} paragrafın çevirisi başarısız oldu, Tekrar denemek ister misiniz?" -#: advanced.py:346 lib/translation.py:258 msgid "Translation completed." msgstr "Çeviri tamamlandı." -#: advanced.py:361 msgid "There is no content that needs to be translated." msgstr "Çeviri gerektiren bir içerik yok." -#: advanced.py:407 msgid "Loading ebook data, please wait..." msgstr "E-kitap verileri yükleniyor, lütfen bekleyin..." -#: advanced.py:436 msgid "Review" msgstr "İnceleme" -#: advanced.py:437 msgid "Log" msgstr "Günlük" -#: advanced.py:438 msgid "Errors" msgstr "Hatalar" -#: advanced.py:490 msgid "Total items: {}" msgstr "Toplam öğe: {}" -#: advanced.py:491 lib/translation.py:233 msgid "Character count: {}" msgstr "Karakter sayısı: {}" -#: advanced.py:519 cache.py:92 cache.py:182 components/engine.py:202 -#: components/table.py:135 msgid "Delete" msgstr "Sil" -#: advanced.py:520 msgid "Translate All" msgstr "Tümünü Çevir" -#: advanced.py:521 msgid "Translate Selected" msgstr "Seçilenleri Çevir" -#: advanced.py:546 advanced.py:557 msgid "Stop" msgstr "Dur" -#: advanced.py:552 msgid "Stopping..." msgstr "Duruyor..." -#: advanced.py:582 msgid "Cache Status" msgstr "Önbellek Durumu" -#: advanced.py:585 msgid "Disabled" msgstr "Devre Dışı" -#: advanced.py:585 msgid "Enabled" msgstr "Etkin" -#: advanced.py:592 setting.py:328 msgid "Translation Engine" msgstr "Çeviri Motoru" -#: advanced.py:598 batch.py:56 setting.py:368 msgid "Source Language" msgstr "Kaynak Dil" -#: advanced.py:610 msgid "Custom Ebook Title" msgstr "Özel E-Kitap Başlığı" -#: advanced.py:615 msgid "By default, title metadata will be translated." msgstr "Varsayılan olarak başlık meta verileri çevrilecek." -#: advanced.py:644 msgid "Output Ebook" msgstr "E-kitap Çıktıları" -#: advanced.py:646 msgid "Output" msgstr "Çıktı" -#: advanced.py:694 components/table.py:89 msgid "Translated" msgstr "Çeviri" -#: advanced.py:695 msgid "The ebook has not been translated yet." msgstr "E-kitap henüz tercüme edilmedi." -#: advanced.py:699 msgid "" "The number of lines in some translation units differs between the original " "text and the translated text. Are you sure you want to output without " "checking alignment?" msgstr "" -"Bazı çeviri birimlerindeki satır sayısı orijinal" -"metin ve çevrilmiş metin olmadan çıktı almak istediğinizden emin misiniz?" -"Hizalamayı kontrol et." +"Bazı çeviri birimlerindeki satır sayısı orijinalmetin ve çevrilmiş metin " +"olmadan çıktı almak istediğinizden emin misiniz?Hizalamayı kontrol et." -#: advanced.py:734 msgid "No translation yet" msgstr "Henüz çeviri yok" -#: advanced.py:783 components/engine.py:208 setting.py:98 msgid "Save" msgstr "Kaydet" -#: advanced.py:839 msgid "Your changes have been saved." msgstr "Değişiklikleriniz kaydedildi." -#: advanced.py:852 msgid "Translation log" msgstr "Çeviri günlüğü" -#: advanced.py:863 msgid "Error log" msgstr "Hata günlüğü" -#: advanced.py:883 msgid "Are you sure you want to translate all {:n} paragraphs?" msgstr "Tüm {:n} paragrafı çevirmek istediğinizden emin misiniz?" -#: advanced.py:909 msgid "Are you sure you want to stop the translation progress?" msgstr "Çeviri ilerlemesini durdurmak istediğinizden emin misiniz?" -#: batch.py:55 setting.py:187 msgid "Output Format" msgstr "Çıktı Formatı" -#: batch.py:55 cache.py:202 msgid "Title" msgstr "Başlık" -#: batch.py:128 components/engine.py:139 components/table.py:133 +msgid "Default" +msgstr "" + msgid "Translate" msgstr "Çevir" -#: batch.py:139 lib/cache.py:126 msgid "Unknown" msgstr "Bilinmiyor" -#: batch.py:148 cache.py:130 setting.py:1136 msgid "The specified path does not exist." msgstr "Belirtilen yol mevcut değil." -#: cache.py:72 msgid "Choose a path to store cache files." msgstr "Önbellek dosyalarını depolamak için bir yol seçin." -#: cache.py:73 components/mode.py:41 components/mode.py:51 setting.py:158 -#: setting.py:901 setting.py:920 setting.py:968 msgid "Choose" msgstr "Seç" -#: cache.py:74 msgid "Reset" msgstr "Sıfırla" -#: cache.py:75 msgid "Reveal" msgstr "Açıkla" -#: cache.py:77 msgid "Cache Path" msgstr "Önbellek Yolu" -#: cache.py:90 msgid "Clear All" msgstr "Hepsini Temizle" -#: cache.py:110 msgid "" "All cache(s) will be moved to the default path. Are you sure to proceed?" -msgstr "" -"Tüm önbellek(ler) varsayılan yola taşınacak. " +msgstr "Tüm önbellek(ler) varsayılan yola taşınacak. " -#: cache.py:125 msgid "All cache(s) will be moved to the new path. Are you sure to proceed?" msgstr "Tüm önbellekler yeni yola taşınacak. " -#: cache.py:133 msgid "Please choose an empty folder." msgstr "Lütfen boş bir klasör seçin." -#: cache.py:143 msgid "Are you sure you want to clear all caches?" msgstr "Tüm önbellekleri temizlemek istediğinizden emin misiniz?" -#: cache.py:153 msgid "No cache exists." msgstr "Önbellek yok." -#: cache.py:158 msgid "Total: {}" msgstr "Toplam: {}" -#: cache.py:189 msgid "Are you sure you want to delete the selected cache(s)?" msgstr "Seçili önbellekleri silmek istediğinizden emin misiniz?" -#: cache.py:202 components/table.py:40 setting.py:63 msgid "Engine" msgstr "Motor" -#: cache.py:202 components/table.py:40 msgid "Language" msgstr "Dil" -#: cache.py:202 msgid "Merge Length" msgstr "Birleştirme Uzunluğu" -#: cache.py:203 msgid "Filename" msgstr "Dosya adı" -#: cache.py:203 msgid "Size (MB)" msgstr "Boyut (MB)" -#: components/engine.py:65 lib/translation.py:173 tests/test_translation.py:108 -#: tests/test_translation.py:128 tests/test_translation.py:141 msgid "Translating..." msgstr "Çeviri yapılıyor..." -#: components/engine.py:97 msgid "Test Translation Engine" msgstr "Çeviri Motorunu Test Edin" -#: components/engine.py:144 msgid "Usage: checking..." msgstr "Kullanım: kontrol ediliyor..." -#: components/engine.py:155 msgid "Usage: {}" msgstr "Kullanım: {}" -#: components/engine.py:193 msgid "Custom Translation Engine" msgstr "Özel Çeviri Motoru" -#: components/engine.py:201 msgid "Add" msgstr "Ekle" -#: components/engine.py:205 msgid "Clear" msgstr "Temizle" -#: components/engine.py:206 msgid "Restore" msgstr "Geri Yükle" -#: components/engine.py:207 msgid "Verify" msgstr "Doğrula" -#: components/engine.py:248 msgid "Valid engine data format." msgstr "Geçerli motor veri formatı." -#: components/engine.py:267 msgid "The engine name is already in use." msgstr "Motor adı zaten kullanılıyor." -#: components/engine.py:289 setting.py:77 msgid "The setting has been saved." msgstr "Ayar kaydedildi." -#: components/format.py:27 setting.py:196 msgid "Ebook Specific" msgstr "E-kitaba Özel" -#: components/info.py:35 msgid "Donate" msgstr "Bağış yap" -#: components/info.py:35 msgid "Feedback" msgstr "Geri bildirim" -#: components/lang.py:34 engines/base.py:70 setting.py:1198 msgid "Auto detect" msgstr "Otomatik algılama" -#: components/mode.py:28 setting.py:125 msgid "Choose a translation mode for clicking the icon button." msgstr "Simge düğmesine tıklamak için bir çeviri modu seçin." -#: components/mode.py:33 setting.py:115 ui.py:54 ui.py:82 msgid "Advanced Mode" msgstr "Gelişmiş Mod" -#: components/mode.py:38 msgid "" "This mode provides additional options for the translation process, allowing " "for more control and customization." msgstr "" -"Bu mod, çeviri işlemi için ek seçenekler sağlayarak" -"daha fazla kontrol ve özelleştirme için." +"Bu mod, çeviri işlemi için ek seçenekler sağlayarakdaha fazla kontrol ve " +"özelleştirme için." -#: components/mode.py:43 setting.py:116 ui.py:55 ui.py:109 msgid "Batch Mode" msgstr "Toplu Mod" -#: components/mode.py:48 msgid "" "This mode allows users to translate multiple ebooks at once, streamlining " "the translation process and saving time." msgstr "" -"Bu mod, kullanıcıların birden fazla e-kitabı aynı anda çevirmesine olanak tanıyarak " -"çeviri sürecini kolaylaştırır ve zamandan tasarruf sağlar." +"Bu mod, kullanıcıların birden fazla e-kitabı aynı anda çevirmesine olanak " +"tanıyarak çeviri sürecini kolaylaştırır ve zamandan tasarruf sağlar." -#: components/table.py:40 setting.py:771 msgid "Original" msgstr "Orijinal" -#: components/table.py:40 msgid "Status" msgstr "Durum" -#: components/table.py:84 msgid "Untranslated" msgstr "çevrilmemiş" -#: components/table.py:111 msgid "" "The number of lines differs between the original text and the translated " "text." msgstr "" -"Orijinal metin ile çevrilmiş metin arasındaki satır sayısı farklılık gösteriyor." +"Orijinal metin ile çevrilmiş metin arasındaki satır sayısı farklılık " +"gösteriyor." -#: components/table.py:139 msgid "Select the whole chapter" msgstr "Tüm bölümü seç" -#: components/table.py:145 msgid "Select similar paragraphs: {}=\"{}\"" msgstr "Benzer paragrafları seç: {}=\"{}\"" -#: components/table.py:192 msgid "Retain at least one row." msgstr "En az bir satırı koru." -#: engines/anthropic.py:110 engines/base.py:210 engines/openai.py:109 -#: tests/test_engine.py:92 msgid "Can not parse returned response. Raw data: {}" msgstr "Geri dönen yanıt ayrıştırılamıyor. " -#: engines/baidu.py:18 msgid "Baidu" msgstr "Baidu" -#: engines/base.py:20 setting.py:349 msgid "API Keys" msgstr "API Anahtarları" -#: engines/base.py:87 msgid "A correct key format \"{}\" is required." msgstr "Doğru bir anahtar biçimi \"{}\" gerekli." -#: engines/custom.py:45 tests/test_engine.py:377 msgid "Engine data must be in valid JSON format." msgstr "Motor verileri geçerli JSON formatında olmalıdır." -#: engines/custom.py:48 tests/test_engine.py:380 msgid "Invalid engine data." msgstr "Geçersiz motor verileri." -#: engines/custom.py:52 tests/test_engine.py:383 msgid "Engine name is required." msgstr "Motor adı gerekli." -#: engines/custom.py:55 tests/test_engine.py:387 msgid "Engine name must be different from builtin engine name." msgstr "Motor adı yerleşik motor adından farklı olmalıdır." -#: engines/custom.py:59 tests/test_engine.py:390 tests/test_engine.py:393 msgid "Language codes are required." msgstr "Dil kodları gerekli." -#: engines/custom.py:63 tests/test_engine.py:396 tests/test_engine.py:399 msgid "Source and target must be added in pair." msgstr "Kaynak ve hedef çift olarak eklenmelidir." -#: engines/custom.py:67 tests/test_engine.py:402 msgid "Request information is required." msgstr "İstek bilgisi gerekli." -#: engines/custom.py:69 tests/test_engine.py:406 msgid "API URL is required." msgstr "API URL'si gerekli." -#: engines/custom.py:73 tests/test_engine.py:411 msgid "Placeholder is required." msgstr "Yer tutucu gerekli." -#: engines/custom.py:77 tests/test_engine.py:416 msgid "Request headers must be an JSON object." msgstr "İstek üstbilgileri bir JSON nesnesi olmalıdır." -#: engines/custom.py:80 tests/test_engine.py:422 msgid "A appropriate Content-Type in headers is required." msgstr "Başlıklarda uygun bir İçerik Türü gerekli." -#: engines/custom.py:84 tests/test_engine.py:427 msgid "Expression to parse response is required." msgstr "Yanıtı ayrıştırmak için ifade gerekli." -#: engines/custom.py:134 msgid "Response was parsed incorrectly." msgstr "Yanıt yanlış ayrıştırıldı." -#: engines/deepl.py:36 tests/test_engine.py:76 msgid "{} total, {} used, {} left" msgstr "{} toplam, {} kullanıldı, {} kaldı" -#: engines/google.py:66 msgid "" "This plugin uses Application Default Credentials (ADC) in your local " "environment to access your Google Translate service. To set up the ADC, " @@ -501,533 +386,401 @@ msgid "" "2. Run the command: gcloud auth application-default login.\n" "3. Sign in to your Google account and grant needed privileges." msgstr "" -"Bu eklenti, yerel bilgisayarınızdaki Uygulama Varsayılan Kimlik Bilgilerini (ADC) kullanır" -"ortamına Google Çeviri hizmetinize erişmek için. ADC'yi kurmak için " -"şu adımları izleyin:\n" +"Bu eklenti, yerel bilgisayarınızdaki Uygulama Varsayılan Kimlik Bilgilerini " +"(ADC) kullanırortamına Google Çeviri hizmetinize erişmek için. ADC'yi kurmak " +"için şu adımları izleyin:\n" "1. Talimatlarını kontrol ederek gcloud CLI'yi yükleyin {}.\n" "2. Şu komutu çalıştırın: gcloud auth application-default login.\n" "3. Google hesabınızda oturum açın ve gerekli ayrıcalıkları verin." -#: engines/google.py:76 msgid "Cannot run the command \"{}\"." msgstr "\"{}\" komutu çalıştırılamıyor." -#: engines/google.py:121 msgid "Cannot find the command \"{}\"." msgstr "\"{}\" komutu bulunamıyor." -#: engines/microsoft.py:39 msgid "Failed get APP key due to an invalid Token." msgstr "Geçersiz bir Belirteç nedeniyle APP anahtarı alınamadı." -#: engines/microsoft.py:43 msgid "Failed get APP key due to and invalid Base64 URL." msgstr "Geçersiz Base64 URL'si nedeniyle APP anahtarı alınamadı." -#: engines/youdao.py:19 msgid "Youdao" msgstr "Youdao" -#: lib/conversion.py:73 msgid "Start to convert ebook format..." msgstr "E-kitap formatını dönüştürmeye başla..." -#: lib/conversion.py:96 msgid "Starting to output subtitles file..." msgstr "Altyazı dosyasının çıktısı alınmaya başlanıyor..." -#: lib/conversion.py:102 msgid "The translation of the subtitles file was completed." msgstr "Altyazı dosyasının çevirisi tamamlandı." -#: lib/conversion.py:120 msgid "Starting to output PGN file..." msgstr "PGN dosyasının çıktısı alınmaya başlanıyor..." -#: lib/conversion.py:130 msgid "The translation of the PGN file was completed." msgstr "PGN dosyasının çevirisi tamamlandı." -#: lib/conversion.py:267 msgid "[{} > {}] Translating \"{}\"" msgstr "[{} > {}] \"{}\" Çevriliyor" -#: lib/conversion.py:276 tests/test_convertion.py:40 msgid "Translation job failed" msgstr "Çeviri işi başarısız oldu" -#: lib/conversion.py:324 tests/test_convertion.py:98 -#: tests/test_convertion.py:164 tests/test_convertion.py:228 -#: tests/test_convertion.py:284 msgid "completed" msgstr "tamamlandı" -#: lib/conversion.py:337 tests/test_convertion.py:103 -#: tests/test_convertion.py:169 tests/test_convertion.py:235 -#: tests/test_convertion.py:289 msgid "Ebook Translation Log" msgstr "E-kitap Çeviri Günlüğü" -#: lib/conversion.py:338 tests/test_convertion.py:104 -#: tests/test_convertion.py:170 tests/test_convertion.py:236 -#: tests/test_convertion.py:290 msgid "Translation Completed" msgstr "Çeviri Tamamlandı" -#: lib/conversion.py:339 tests/test_convertion.py:106 -#: tests/test_convertion.py:172 tests/test_convertion.py:238 -#: tests/test_convertion.py:292 msgid "The translation of \"{}\" was completed. Do you want to open the book?" msgstr "\"{}\" çevirisi tamamlandı. " -#: lib/translation.py:133 lib/translation.py:141 lib/translation.py:168 msgid "Translation canceled." msgstr "Çeviri iptal edildi." -#: lib/translation.py:145 msgid "No available API key." msgstr "Kullanılabilir API anahtarı yok." -#: lib/translation.py:147 msgid "API key was Changed due to previous one unavailable." msgstr "API anahtarı öncekinin kullanılamaması nedeniyle değiştirildi." -#: lib/translation.py:151 msgid "Failed to retrieve data from translate engine API." msgstr "Çeviri motoru API'sinden veri alınamadı." -#: lib/translation.py:159 lib/translation.py:209 lib/translation.py:217 msgid "Original: {}" msgstr "Orijinal: {}" -#: lib/translation.py:160 msgid "Status: Failed {} times / Sleeping for {} seconds" msgstr "Durum: {} kez başarısız oldu / {} saniye boyunca uyuyor" -#: lib/translation.py:161 lib/translation.py:219 msgid "Error: {}" msgstr "Hata: {}" -#: lib/translation.py:200 msgid "Translating: {}/{}" msgstr "Çeviriliyor: {}/{}" -#: lib/translation.py:211 msgid "Translation: {}" msgstr "Çeviri: {}" -#: lib/translation.py:213 msgid "Translation (Cached): {}" msgstr "Çeviri (Önbelleğe Alınmış): {}" -#: lib/translation.py:230 msgid "Start to translate ebook content" msgstr "E-kitap içeriğini çevirmeye başla" -#: lib/translation.py:232 msgid "Item count: {}" msgstr "Ürün sayısı: {}" -#: lib/translation.py:235 msgid "There is no content need to translate." msgstr "Çevirilmesi gereken içerik yok." -#: lib/translation.py:255 msgid "Translation failed." msgstr "Çeviri başarısız oldu." -#: setting.py:62 +msgid "Outputting ebook file..." +msgstr "" + msgid "General" msgstr "Genel" -#: setting.py:64 msgid "Content" msgstr "İçerik" -#: setting.py:113 msgid "Preferred Mode" msgstr "Tercih Edilen Mod" -#: setting.py:147 msgid "Output Path" msgstr "Çıkış Yolu" -#: setting.py:149 msgid "Library" msgstr "Kütüphane" -#: setting.py:150 msgid "Path" msgstr "Yol" -#: setting.py:155 msgid "Choose a path to store translated book(s)" msgstr "Çeviri kitap(lar)ı depolamak için bir yol seçin" -#: setting.py:182 msgid "Preferred Format" msgstr "Tercih Edilen Format" -#: setting.py:206 msgid "(Beta)" msgstr "(Beta)" -#: setting.py:206 msgid "Merge to Translate" msgstr "Çevirmek için Birleştir" -#: setting.py:208 setting.py:229 setting.py:273 setting.py:965 msgid "Enable" msgstr "Etkinleştir" -#: setting.py:214 msgid "The number of characters to translate at once." msgstr "Bir kerede çevrilecek karakter sayısı." -#: setting.py:226 msgid "HTTP Proxy" msgstr "HTTP Proxy" -#: setting.py:241 msgid "Host" msgstr "Host" -#: setting.py:244 msgid "Port" msgstr "Port" -#: setting.py:255 setting.py:331 msgid "Test" msgstr "Deneme" -#: setting.py:271 ui.py:57 msgid "Cache" msgstr "Önbellek" -#: setting.py:274 msgid "Manage" msgstr "Yönet" -#: setting.py:291 msgid "Job Log" msgstr "İş Günlüğü" -#: setting.py:292 msgid "Show translation" msgstr "Çeviriyi göster" -#: setting.py:305 msgid "Search Paths" msgstr "Arama Yolları" -#: setting.py:308 msgid "The plugin will search for external programs via these paths." msgstr "Eklenti bu yollar aracılığıyla harici programları arayacaktır." -#: setting.py:332 setting.py:582 setting.py:586 setting.py:593 setting.py:598 msgid "Custom" msgstr "Özel" -#: setting.py:339 msgid "Usage Tip" msgstr "Kullanım İpucu" -#: setting.py:353 msgid "Tip:" msgstr "İpucu:" -#: setting.py:354 msgid "API keys will auto-switch if the previous one is unavailable." -msgstr "API anahtarları, öncekinin mevcut olmaması durumunda otomatik olarak geçiş yapacaktır." +msgstr "" +"API anahtarları, öncekinin mevcut olmaması durumunda otomatik olarak geçiş " +"yapacaktır." -#: setting.py:364 msgid "Preferred Language" msgstr "Tercih Edilen Dil" -#: setting.py:375 msgid "HTTP Request" msgstr "HTTP İsteği" -#: setting.py:387 msgid "Concurrency limit" msgstr "Eşzamanlılık sınırı" -#: setting.py:388 msgid "Interval (seconds)" msgstr "Aralık (saniye)" -#: setting.py:389 msgid "Attempt times" msgstr "Deneme süreleri" -#: setting.py:390 msgid "Timeout (seconds)" msgstr "Zaman aşımı (saniye)" -#: setting.py:394 msgid "Abort Translation" msgstr "Çeviriyi İptal Et" -#: setting.py:398 msgid "Max errors" msgstr "Maksimum hatalar" -#: setting.py:401 msgid "The number of consecutive errors to abort translation." msgstr "Çeviriyi iptal etmek için ardışık hataların sayısı." -#: setting.py:413 msgid "Tune Gemini" msgstr "İkizler'i Ayarla" -#: setting.py:420 setting.py:467 msgid "Prompt" msgstr "İstem" -#: setting.py:450 setting.py:507 msgid "Sampling" msgstr "Örnekleme" -#: setting.py:469 msgid "Endpoint" msgstr "Son nokta" -#: setting.py:478 msgid "Model" msgstr "Model" -#: setting.py:512 msgid "Enable streaming text like in ChatGPT" msgstr "ChatGPT'deki gibi metin akışını etkinleştir" -#: setting.py:513 msgid "Stream" msgstr "Yayın" -#: setting.py:556 msgid "Tune ChatGPT" msgstr "ChatGPT'yi Ayarla" -#: setting.py:559 msgid "Tune Claude" msgstr "Claude'yi dinle" -#: setting.py:576 msgid "The model depends on your Azure project." msgstr "Model, Azure projenize bağlıdır." -#: setting.py:752 msgid "Below original" msgstr "Orijinalin altında" -#: setting.py:754 msgid "Above original" msgstr "Orijinalin üstünde" -#: setting.py:756 setting.py:758 msgid "Beta" msgstr "Beta" -#: setting.py:756 msgid "Right to original" msgstr "Orijinal hakkı" -#: setting.py:758 msgid "Left to original" msgstr "Orijinale sola" -#: setting.py:759 msgid "With no original" msgstr "Orijinali yok" -#: setting.py:778 msgid "Translation" msgstr "Çeviri" -#: setting.py:795 msgid "Column Gap" msgstr "Sütun Boşluğu" -#: setting.py:805 msgid "Percentage" msgstr "Yüzde" -#: setting.py:806 msgid "Space count" msgstr "Boşluk sayımı" -#: setting.py:837 msgid "Translation Position" msgstr "Çeviri Konumu" -#: setting.py:889 msgid "Original Text Color" msgstr "Orijinal Metin Rengi" -#: setting.py:894 setting.py:912 setting.py:1071 msgid "e.g.," msgstr "örneğin," -#: setting.py:908 msgid "Translation Text Color" msgstr "Çeviri Metni Rengi" -#: setting.py:963 msgid "Translation Glossary" msgstr "Çeviri Sözlüğü" -#: setting.py:967 msgid "Choose a glossary file" msgstr "Bir sözlük dosyası seç" -#: setting.py:986 msgid "Ignore Paragraph" msgstr "Paragrafı Yoksay" -#: setting.py:992 msgid "Scope" msgstr "Kapsam" -#: setting.py:993 msgid "Text only" msgstr "Yalnızca metin" -#: setting.py:995 msgid "HTML element" msgstr "HTML öğesi" -#: setting.py:1002 msgid "Mode" msgstr "Mod" -#: setting.py:1003 msgid "Normal" msgstr "Normal" -#: setting.py:1005 msgid "Normal (case-sensitive)" msgstr "Normal (büyük/küçük harfe duyarlı)" -#: setting.py:1006 msgid "Regular Expression" msgstr "Normal İfade" -#: setting.py:1048 msgid "Exclude paragraph by keyword. One keyword per line:" msgstr "Paragrafı anahtar kelimeye göre hariç tut. " -#: setting.py:1049 msgid "Exclude paragraph by case-sensitive keyword. One keyword per line:" msgstr "Paragrafı büyük/küçük harfe duyarlı anahtar sözcükle hariç tut. " -#: setting.py:1051 msgid "Exclude paragraph by regular expression pattern. One pattern per line:" msgstr "Paragrafı normal ifade düzeniyle hariç tut. " -#: setting.py:1067 msgid "Ignore Element" msgstr "Öğeyi Yoksay" -#: setting.py:1077 msgid "CSS selectors to exclude elements. One rule per line:" msgstr "Öğeleri dışlamak için CSS seçicileri. " -#: setting.py:1082 msgid "Ebook Metadata" msgstr "E-kitap Meta Verisi" -#: setting.py:1086 msgid "Append target language to title metadata" msgstr "Hedef dili başlık meta verilerine ekle" -#: setting.py:1088 msgid "Set target language code to language metadata" msgstr "Hedef dil kodunu dil meta verilerine ayarla" -#: setting.py:1091 msgid "Subjects of ebook (one subject per line)" msgstr "E-kitabın konuları (her satıra bir konu)" -#: setting.py:1092 msgid "Language Mark" msgstr "Dil İşareti" -#: setting.py:1093 msgid "Language Code" msgstr "Dil Kodu" -#: setting.py:1094 msgid "Append Subjects" msgstr "Konu Ekle" -#: setting.py:1115 setting.py:1150 msgid "Proxy host or port is incorrect." msgstr "Proxy ana bilgisayarı veya bağlantı noktası yanlış." -#: setting.py:1117 msgid "The proxy is available." msgstr "Proxy kullanılabilir." -#: setting.py:1118 msgid "The proxy is not available." msgstr "Proxy kullanılamıyor." -#: setting.py:1208 msgid "the prompt must include {}." msgstr "istem {} içermelidir." -#: setting.py:1237 setting.py:1244 msgid "Invalid color value." msgstr "Geçersiz renk değeri." -#: setting.py:1253 msgid "The specified glossary file does not exist." msgstr "Belirtilen sözlük dosyası mevcut değil." -#: setting.py:1265 msgid "{} is not a valid regular expression." msgstr "{} geçerli bir normal ifade değil." -#: setting.py:1277 msgid "{} is not a valid CSS seletor." msgstr "{} geçerli bir CSS seçici değil." -#: ui.py:38 msgid "Translate Book" msgstr "Kitabı Çevir" -#: ui.py:38 msgid "Translate Ebook Content" msgstr "E-kitap İçeriğini Çevir" -#: ui.py:58 ui.py:126 msgid "Setting" msgstr "Ayar" -#: ui.py:59 ui.py:154 msgid "About" msgstr "Hakkında" -#: ui.py:90 msgid "Please choose one single book." msgstr "Lütfen tek bir kitap seçin." -#: ui.py:103 msgid "Please choose at least one book." msgstr "Lütfen en az bir kitap seçin." -#: ui.py:117 msgid "Cannot change setting while book(s) are under translation." msgstr "Kitap(lar) çeviri aşamasındayken ayar değiştirilemez." -#: ui.py:134 msgid "Cannot manage cache while book(s) are under translation." msgstr "Kitap(lar) çeviri aşamasındayken önbellek yönetilemiyor." -#: ui.py:143 msgid "Cache Manager" msgstr "Önbellek Yöneticisi" -#: ui.py:172 msgid "Choose Translation Mode" msgstr "Çeviri Modunu Seçin" diff --git a/translations/zh_CN.mo b/translations/zh_CN.mo index ff300f5b09fade28526e3b0a5438e19e4e29139d..afd04dff2443c8b98982412626e1e33a699c4487 100644 GIT binary patch delta 5381 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 diff --git a/translations/zh_CN.po b/translations/zh_CN.po index d6f97e03..bb624ed8 100644 --- a/translations/zh_CN.po +++ b/translations/zh_CN.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Ebook Translator Calibre Plugin\n" "Report-Msgid-Bugs-To: bookfere@gmail.com\n" -"POT-Creation-Date: 2024-03-21 20:51+0800\n" +"POT-Creation-Date: 2024-03-25 21:02+0800\n" "PO-Revision-Date: 2023-04-17 14:17+0800\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" @@ -157,6 +157,9 @@ msgstr "输出格式" msgid "Title" msgstr "书名" +msgid "Default" +msgstr "默认" + msgid "Translate" msgstr "翻译" @@ -469,6 +472,9 @@ msgstr "没有需要翻译的内容。" msgid "Translation failed." msgstr "翻译已失败。" +msgid "Outputting ebook file..." +msgstr "正在输出电子书文件……" + msgid "General" msgstr "通用" diff --git a/translations/zh_TW.po b/translations/zh_TW.po index a1749295..76c2d450 100644 --- a/translations/zh_TW.po +++ b/translations/zh_TW.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Ebook Translator Calibre Plugin\n" "Report-Msgid-Bugs-To: bookfere@gmail.com\n" -"POT-Creation-Date: 2024-03-21 20:51+0800\n" +"POT-Creation-Date: 2024-03-25 21:02+0800\n" "PO-Revision-Date: 2023-04-25 15:36+0800\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" @@ -158,6 +158,9 @@ msgstr "輸出格式" msgid "Title" msgstr "書名" +msgid "Default" +msgstr "" + msgid "Translate" msgstr "翻譯" @@ -465,6 +468,9 @@ msgstr "沒有需要翻譯的內容。" msgid "Translation failed." msgstr "" +msgid "Outputting ebook file..." +msgstr "" + msgid "General" msgstr "" diff --git a/ui.py b/ui.py index b69b185d..f78b34ee 100644 --- a/ui.py +++ b/ui.py @@ -1,5 +1,3 @@ -from types import MethodType - from calibre.gui2.actions import InterfaceAction from . import EbookTranslator @@ -103,7 +101,7 @@ def show_batch_translation(self): _('Please choose at least one book.'), 'warning') worker = ConversionWorker(self.gui, self.icon) window = BatchTranslation(self.gui, worker, ebooks) - window.setMinimumWidth(600) + window.setMinimumWidth(800) window.setMinimumHeight(520) window.setWindowTitle( '%s - %s' % (_('Batch Mode'), self.title))