supervertaler 1.9.153__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.
Potentially problematic release.
This version of supervertaler might be problematic. Click here for more details.
- Supervertaler.py +47886 -0
- modules/__init__.py +10 -0
- modules/ai_actions.py +964 -0
- modules/ai_attachment_manager.py +343 -0
- modules/ai_file_viewer_dialog.py +210 -0
- modules/autofingers_engine.py +466 -0
- modules/cafetran_docx_handler.py +379 -0
- modules/config_manager.py +469 -0
- modules/database_manager.py +1878 -0
- modules/database_migrations.py +417 -0
- modules/dejavurtf_handler.py +779 -0
- modules/document_analyzer.py +427 -0
- modules/docx_handler.py +689 -0
- modules/encoding_repair.py +319 -0
- modules/encoding_repair_Qt.py +393 -0
- modules/encoding_repair_ui.py +481 -0
- modules/feature_manager.py +350 -0
- modules/figure_context_manager.py +340 -0
- modules/file_dialog_helper.py +148 -0
- modules/find_replace.py +164 -0
- modules/find_replace_qt.py +457 -0
- modules/glossary_manager.py +433 -0
- modules/image_extractor.py +188 -0
- modules/keyboard_shortcuts_widget.py +571 -0
- modules/llm_clients.py +1211 -0
- modules/llm_leaderboard.py +737 -0
- modules/llm_superbench_ui.py +1401 -0
- modules/local_llm_setup.py +1104 -0
- modules/model_update_dialog.py +381 -0
- modules/model_version_checker.py +373 -0
- modules/mqxliff_handler.py +638 -0
- modules/non_translatables_manager.py +743 -0
- modules/pdf_rescue_Qt.py +1822 -0
- modules/pdf_rescue_tkinter.py +909 -0
- modules/phrase_docx_handler.py +516 -0
- modules/project_home_panel.py +209 -0
- modules/prompt_assistant.py +357 -0
- modules/prompt_library.py +689 -0
- modules/prompt_library_migration.py +447 -0
- modules/quick_access_sidebar.py +282 -0
- modules/ribbon_widget.py +597 -0
- modules/sdlppx_handler.py +874 -0
- modules/setup_wizard.py +353 -0
- modules/shortcut_manager.py +932 -0
- modules/simple_segmenter.py +128 -0
- modules/spellcheck_manager.py +727 -0
- modules/statuses.py +207 -0
- modules/style_guide_manager.py +315 -0
- modules/superbench_ui.py +1319 -0
- modules/superbrowser.py +329 -0
- modules/supercleaner.py +600 -0
- modules/supercleaner_ui.py +444 -0
- modules/superdocs.py +19 -0
- modules/superdocs_viewer_qt.py +382 -0
- modules/superlookup.py +252 -0
- modules/tag_cleaner.py +260 -0
- modules/tag_manager.py +333 -0
- modules/term_extractor.py +270 -0
- modules/termbase_entry_editor.py +842 -0
- modules/termbase_import_export.py +488 -0
- modules/termbase_manager.py +1060 -0
- modules/termview_widget.py +1172 -0
- modules/theme_manager.py +499 -0
- modules/tm_editor_dialog.py +99 -0
- modules/tm_manager_qt.py +1280 -0
- modules/tm_metadata_manager.py +545 -0
- modules/tmx_editor.py +1461 -0
- modules/tmx_editor_qt.py +2784 -0
- modules/tmx_generator.py +284 -0
- modules/tracked_changes.py +900 -0
- modules/trados_docx_handler.py +430 -0
- modules/translation_memory.py +715 -0
- modules/translation_results_panel.py +2134 -0
- modules/translation_services.py +282 -0
- modules/unified_prompt_library.py +659 -0
- modules/unified_prompt_manager_qt.py +3951 -0
- modules/voice_commands.py +920 -0
- modules/voice_dictation.py +477 -0
- modules/voice_dictation_lite.py +249 -0
- supervertaler-1.9.153.dist-info/METADATA +896 -0
- supervertaler-1.9.153.dist-info/RECORD +85 -0
- supervertaler-1.9.153.dist-info/WHEEL +5 -0
- supervertaler-1.9.153.dist-info/entry_points.txt +2 -0
- supervertaler-1.9.153.dist-info/licenses/LICENSE +21 -0
- supervertaler-1.9.153.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Translation Services Module
|
|
3
|
+
Handles Machine Translation (MT) and Large Language Model (LLM) integration
|
|
4
|
+
Keeps main application file clean and manageable
|
|
5
|
+
|
|
6
|
+
Author: Michael Beijer
|
|
7
|
+
License: MIT
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import Dict, List, Optional, Any
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
import logging
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class TranslationRequest:
|
|
17
|
+
"""Request object for translation services"""
|
|
18
|
+
source_text: str
|
|
19
|
+
source_lang: str
|
|
20
|
+
target_lang: str
|
|
21
|
+
context: Optional[str] = None
|
|
22
|
+
source_lang_code: Optional[str] = None
|
|
23
|
+
target_lang_code: Optional[str] = None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class TranslationResult:
|
|
28
|
+
"""Result object from translation services"""
|
|
29
|
+
source: str
|
|
30
|
+
target: str
|
|
31
|
+
relevance: int
|
|
32
|
+
metadata: Dict[str, Any]
|
|
33
|
+
match_type: str # 'MT' or 'LLM'
|
|
34
|
+
provider_code: str
|
|
35
|
+
success: bool = True
|
|
36
|
+
error: Optional[str] = None
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class TranslationServices:
|
|
40
|
+
"""
|
|
41
|
+
Main class for handling all translation services (MT and LLM)
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def __init__(self, config: Dict[str, Any] = None):
|
|
45
|
+
"""
|
|
46
|
+
Initialize translation services
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
config: Configuration dictionary with service settings
|
|
50
|
+
"""
|
|
51
|
+
self.config = config or {}
|
|
52
|
+
|
|
53
|
+
# Service availability flags
|
|
54
|
+
self.google_translate_enabled = self.config.get('google_translate_enabled', True)
|
|
55
|
+
self.deepl_enabled = self.config.get('deepl_enabled', False)
|
|
56
|
+
self.openai_enabled = self.config.get('openai_enabled', True)
|
|
57
|
+
self.claude_enabled = self.config.get('claude_enabled', True)
|
|
58
|
+
|
|
59
|
+
# Enable/disable flags
|
|
60
|
+
self.enable_mt_matching = self.config.get('enable_mt_matching', True)
|
|
61
|
+
self.enable_llm_matching = self.config.get('enable_llm_matching', True)
|
|
62
|
+
|
|
63
|
+
self.logger = logging.getLogger(__name__)
|
|
64
|
+
|
|
65
|
+
def get_all_translations(self, request: TranslationRequest) -> List[TranslationResult]:
|
|
66
|
+
"""
|
|
67
|
+
Get translations from all available services
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
request: TranslationRequest object
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
List of TranslationResult objects
|
|
74
|
+
"""
|
|
75
|
+
results = []
|
|
76
|
+
|
|
77
|
+
# Get MT translations
|
|
78
|
+
if self.enable_mt_matching:
|
|
79
|
+
mt_results = self.get_mt_translations(request)
|
|
80
|
+
results.extend(mt_results)
|
|
81
|
+
|
|
82
|
+
# Get LLM translations
|
|
83
|
+
if self.enable_llm_matching:
|
|
84
|
+
llm_results = self.get_llm_translations(request)
|
|
85
|
+
results.extend(llm_results)
|
|
86
|
+
|
|
87
|
+
return results
|
|
88
|
+
|
|
89
|
+
def get_mt_translations(self, request: TranslationRequest) -> List[TranslationResult]:
|
|
90
|
+
"""
|
|
91
|
+
Get Machine Translation results
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
request: TranslationRequest object
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
List of TranslationResult objects from MT services
|
|
98
|
+
"""
|
|
99
|
+
results = []
|
|
100
|
+
|
|
101
|
+
self.logger.info(f"🤖 DIRECT MT SEARCH: Getting machine translation for '{request.source_text[:50]}...'")
|
|
102
|
+
|
|
103
|
+
# Google Translate
|
|
104
|
+
if self.google_translate_enabled:
|
|
105
|
+
try:
|
|
106
|
+
from modules.llm_clients import get_google_translation
|
|
107
|
+
mt_result = get_google_translation(
|
|
108
|
+
request.source_text,
|
|
109
|
+
request.source_lang_code or 'auto',
|
|
110
|
+
request.target_lang_code or 'en'
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
if mt_result and mt_result.get('translation'):
|
|
114
|
+
result = TranslationResult(
|
|
115
|
+
source=request.source_text,
|
|
116
|
+
target=mt_result['translation'],
|
|
117
|
+
relevance=85, # Good relevance for MT
|
|
118
|
+
metadata={
|
|
119
|
+
'provider': 'Google Translate',
|
|
120
|
+
'confidence': mt_result.get('confidence', 'N/A'),
|
|
121
|
+
'detected_lang': mt_result.get('detected_source_language', request.source_lang_code)
|
|
122
|
+
},
|
|
123
|
+
match_type='MT',
|
|
124
|
+
provider_code='GT'
|
|
125
|
+
)
|
|
126
|
+
results.append(result)
|
|
127
|
+
self.logger.info(f"🤖 DIRECT MT SEARCH: Added Google Translate result")
|
|
128
|
+
|
|
129
|
+
except Exception as e:
|
|
130
|
+
self.logger.error(f"Error in Google Translate: {e}")
|
|
131
|
+
|
|
132
|
+
# DeepL (placeholder for future implementation)
|
|
133
|
+
if self.deepl_enabled:
|
|
134
|
+
try:
|
|
135
|
+
# DeepL integration would go here
|
|
136
|
+
pass
|
|
137
|
+
except Exception as e:
|
|
138
|
+
self.logger.error(f"Error in DeepL: {e}")
|
|
139
|
+
|
|
140
|
+
return results
|
|
141
|
+
|
|
142
|
+
def get_llm_translations(self, request: TranslationRequest) -> List[TranslationResult]:
|
|
143
|
+
"""
|
|
144
|
+
Get Large Language Model translation results
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
request: TranslationRequest object
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
List of TranslationResult objects from LLM services
|
|
151
|
+
"""
|
|
152
|
+
results = []
|
|
153
|
+
|
|
154
|
+
self.logger.info(f"🧠DIRECT LLM SEARCH: Getting AI translation for '{request.source_text[:50]}...'")
|
|
155
|
+
|
|
156
|
+
# OpenAI/ChatGPT
|
|
157
|
+
if self.openai_enabled:
|
|
158
|
+
try:
|
|
159
|
+
from modules.llm_clients import get_openai_translation
|
|
160
|
+
llm_result = get_openai_translation(
|
|
161
|
+
request.source_text,
|
|
162
|
+
request.source_lang or 'Dutch',
|
|
163
|
+
request.target_lang or 'English',
|
|
164
|
+
context=request.context or "Technical documentation translation"
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
if llm_result and llm_result.get('translation'):
|
|
168
|
+
# Clean the translation to remove provider prefix
|
|
169
|
+
clean_translation = self._clean_provider_prefix(
|
|
170
|
+
llm_result['translation'],
|
|
171
|
+
['[OpenAI]', '[openai]', 'OpenAI:', 'openai:']
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
result = TranslationResult(
|
|
175
|
+
source=request.source_text,
|
|
176
|
+
target=clean_translation,
|
|
177
|
+
relevance=90, # High relevance for LLM with context
|
|
178
|
+
metadata={
|
|
179
|
+
'provider': 'OpenAI GPT',
|
|
180
|
+
'model': llm_result.get('model', 'gpt-3.5-turbo'),
|
|
181
|
+
'context_aware': True,
|
|
182
|
+
'explanation': llm_result.get('explanation', '')
|
|
183
|
+
},
|
|
184
|
+
match_type='LLM',
|
|
185
|
+
provider_code='AI'
|
|
186
|
+
)
|
|
187
|
+
results.append(result)
|
|
188
|
+
self.logger.info(f"🧠DIRECT LLM SEARCH: Added OpenAI result")
|
|
189
|
+
|
|
190
|
+
except Exception as e:
|
|
191
|
+
self.logger.error(f"Error in OpenAI translation: {e}")
|
|
192
|
+
|
|
193
|
+
# Claude
|
|
194
|
+
if self.claude_enabled:
|
|
195
|
+
try:
|
|
196
|
+
from modules.llm_clients import get_claude_translation
|
|
197
|
+
claude_result = get_claude_translation(
|
|
198
|
+
request.source_text,
|
|
199
|
+
request.source_lang or 'Dutch',
|
|
200
|
+
request.target_lang or 'English',
|
|
201
|
+
context=request.context or "Technical documentation translation"
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
if claude_result and claude_result.get('translation'):
|
|
205
|
+
# Clean the translation to remove provider prefix
|
|
206
|
+
clean_translation = self._clean_provider_prefix(
|
|
207
|
+
claude_result['translation'],
|
|
208
|
+
['[Claude]', '[claude]', 'Claude:', 'claude:']
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
result = TranslationResult(
|
|
212
|
+
source=request.source_text,
|
|
213
|
+
target=clean_translation,
|
|
214
|
+
relevance=92, # Very high relevance for Claude
|
|
215
|
+
metadata={
|
|
216
|
+
'provider': 'Anthropic Claude',
|
|
217
|
+
'model': claude_result.get('model', 'claude-3'),
|
|
218
|
+
'context_aware': True,
|
|
219
|
+
'reasoning': claude_result.get('reasoning', '')
|
|
220
|
+
},
|
|
221
|
+
match_type='LLM',
|
|
222
|
+
provider_code='CL'
|
|
223
|
+
)
|
|
224
|
+
results.append(result)
|
|
225
|
+
self.logger.info(f"🧠DIRECT LLM SEARCH: Added Claude result")
|
|
226
|
+
|
|
227
|
+
except Exception as e:
|
|
228
|
+
self.logger.error(f"Error in Claude translation: {e}")
|
|
229
|
+
|
|
230
|
+
return results
|
|
231
|
+
|
|
232
|
+
def _clean_provider_prefix(self, translation: str, prefixes: List[str]) -> str:
|
|
233
|
+
"""
|
|
234
|
+
Remove provider prefixes from translation text
|
|
235
|
+
|
|
236
|
+
Args:
|
|
237
|
+
translation: Original translation text
|
|
238
|
+
prefixes: List of prefixes to remove
|
|
239
|
+
|
|
240
|
+
Returns:
|
|
241
|
+
Cleaned translation text
|
|
242
|
+
"""
|
|
243
|
+
if not translation:
|
|
244
|
+
return translation
|
|
245
|
+
|
|
246
|
+
cleaned = translation.strip()
|
|
247
|
+
|
|
248
|
+
for prefix in prefixes:
|
|
249
|
+
if cleaned.startswith(prefix):
|
|
250
|
+
cleaned = cleaned[len(prefix):].strip()
|
|
251
|
+
break
|
|
252
|
+
|
|
253
|
+
# Remove any remaining leading/trailing parentheses or brackets
|
|
254
|
+
cleaned = cleaned.strip('()[]')
|
|
255
|
+
|
|
256
|
+
# Remove common trailing patterns
|
|
257
|
+
trailing_patterns = [
|
|
258
|
+
f' (translated to {self.config.get("target_lang", "English")})',
|
|
259
|
+
' (translated)',
|
|
260
|
+
' - Translation',
|
|
261
|
+
' - translated'
|
|
262
|
+
]
|
|
263
|
+
|
|
264
|
+
for pattern in trailing_patterns:
|
|
265
|
+
if cleaned.lower().endswith(pattern.lower()):
|
|
266
|
+
cleaned = cleaned[:-len(pattern)]
|
|
267
|
+
break
|
|
268
|
+
|
|
269
|
+
return cleaned.strip()
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def create_translation_service(config: Dict[str, Any] = None) -> TranslationServices:
|
|
273
|
+
"""
|
|
274
|
+
Factory function to create a TranslationServices instance
|
|
275
|
+
|
|
276
|
+
Args:
|
|
277
|
+
config: Configuration dictionary
|
|
278
|
+
|
|
279
|
+
Returns:
|
|
280
|
+
TranslationServices instance
|
|
281
|
+
"""
|
|
282
|
+
return TranslationServices(config)
|