Coverage for src/dmxfy/client/client.py: 83%
36 statements
« prev ^ index » next coverage.py v7.10.1, created at 2025-08-12 11:37 +0800
« prev ^ index » next coverage.py v7.10.1, created at 2025-08-12 11:37 +0800
1import http.client
2import json
3import socket
4from typing import Any
6from dmxfy.config.config import Config
7from dmxfy.exceptions.exceptions import TranslationError
8from dmxfy.languages.languages import LANGUAGES
11class TranslationClient:
12 """Client for handling translations with the DashScope API"""
14 def __init__(self) -> None:
15 self.config = Config()
17 def translate(self, text: str, source_lang: str, target_lang: str) -> str:
18 """
19 Translate text using the DashScope API
21 Args:
22 text: The text to translate
23 source_lang: The source language name (in Chinese)
24 target_lang: The target language name (in Chinese)
26 Returns:
27 The translated text
29 Raises:
30 TranslationError: If there's an error during translation
31 """
32 if not text.strip():
33 return "请输入要翻译的文本"
35 try:
36 # Create a new connection for each request to avoid connection issues
37 conn: http.client.HTTPSConnection = http.client.HTTPSConnection(
38 "dashscope.aliyuncs.com"
39 )
41 # Prepare the request data
42 json_data = {
43 "model": "qwen-mt-turbo",
44 "messages": [
45 {
46 "role": "user",
47 "content": text,
48 },
49 ],
50 "translation_options": {
51 "source_lang": LANGUAGES.get(source_lang, "auto"),
52 "target_lang": LANGUAGES.get(target_lang, "English"),
53 },
54 }
56 # Make the request
57 conn.request(
58 "POST",
59 "/compatible-mode/v1/chat/completions",
60 json.dumps(json_data),
61 self.config.headers,
62 )
64 # Get and parse the response
65 response = conn.getresponse()
66 resp_str = response.read().decode("utf-8")
68 # Check if response is valid
69 if not resp_str:
70 raise TranslationError("Received empty response from server")
72 resp_json: dict[str, Any] = json.loads(resp_str)
74 # Close the connection
75 conn.close()
77 # Check if we have a valid response structure
78 if "choices" not in resp_json or not resp_json["choices"]:
79 raise TranslationError(f"Invalid response format: {resp_json}")
81 return str(resp_json["choices"][0]["message"]["content"])
83 except (socket.gaierror, TimeoutError, ConnectionRefusedError) as e:
84 raise TranslationError(f"Network connection error: {str(e)}") from e
85 except http.client.RemoteDisconnected as e:
86 raise TranslationError(
87 "Remote server disconnected unexpectedly. Please try again."
88 ) from e
89 except http.client.ResponseNotReady as e:
90 raise TranslationError(
91 "Server not ready to respond. Please try again."
92 ) from e
93 except json.JSONDecodeError as e:
94 raise TranslationError(f"Failed to parse server response: {str(e)}") from e
95 except Exception as e:
96 raise TranslationError(f"Translation failed: {str(e)}") from e