Coverage for app/venv/lib/python3.14/site-packages/weblate/machinery/google.py: 48%

44 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-07 07:15 +0000

1# Copyright © Michal Čihař <michal@weblate.org> 

2# 

3# SPDX-License-Identifier: GPL-3.0-or-later 

4from __future__ import annotations 

5 

6from typing import TYPE_CHECKING, ClassVar 

7 

8from requests.exceptions import RequestException 

9 

10from .base import MachineTranslation, MachineTranslationError 

11from .forms import KeyMachineryForm 

12 

13if TYPE_CHECKING: 13 ↛ 14line 13 didn't jump to line 14 because the condition on line 13 was never true

14 from .base import DownloadTranslations 

15 

16GOOGLE_API_ROOT = "https://translation.googleapis.com/language/translate/v2/" 

17 

18 

19class GoogleBaseTranslation(MachineTranslation): 

20 # Map codes used by Google to the ones used by Weblate 

21 language_map: ClassVar[dict[str, str]] = { 

22 "nb": "no", 

23 "nb_NO": "no", 

24 "fil": "tl", 

25 "zh_Hant": "zh-TW", 

26 "zh_Hans": "zh-CN", 

27 "ber-Latn": "kab", # Adding Kabyle language by mapping Tamazight latin 

28 } 

29 language_aliases = ({"zh-CN", "zh"},) 

30 

31 def map_language_code(self, code): 

32 """Convert language to service specific code.""" 

33 return super().map_language_code(code).replace("_", "-").split("@")[0] 

34 

35 def is_supported(self, source, language): 

36 # Avoid translation between aliases 

37 return super().is_supported(source, language) and not any( 

38 {source, language} == item for item in self.language_aliases 

39 ) 

40 

41 

42class GoogleTranslation(GoogleBaseTranslation): 

43 """Google Translate API v2 machine translation support.""" 

44 

45 name = "Google Cloud Translation Basic" 

46 max_score = 90 

47 settings_form = KeyMachineryForm 

48 

49 @classmethod 

50 def get_identifier(cls) -> str: 

51 return "google-translate" 

52 

53 def check_failure(self, response) -> None: 

54 super().check_failure(response) 

55 payload = response.json() 

56 

57 if "error" in payload: 

58 raise MachineTranslationError(payload["error"]["message"]) 

59 

60 def download_languages(self): 

61 """List of supported languages.""" 

62 response = self.request( 

63 "get", GOOGLE_API_ROOT + "languages", params={"key": self.settings["key"]} 

64 ) 

65 payload = response.json() 

66 

67 return [d["language"] for d in payload["data"]["languages"]] 

68 

69 def download_translations( 

70 self, 

71 source, 

72 language, 

73 text: str, 

74 unit, 

75 user, 

76 threshold: int = 75, 

77 ) -> DownloadTranslations: 

78 """Download list of possible translations from a service.""" 

79 response = self.request( 

80 "get", 

81 GOOGLE_API_ROOT, 

82 params={ 

83 "key": self.settings["key"], 

84 "q": text, 

85 "source": source, 

86 "target": language, 

87 "format": "text", 

88 }, 

89 ) 

90 payload = response.json() 

91 

92 translation = payload["data"]["translations"][0]["translatedText"] 

93 

94 yield { 

95 "text": translation, 

96 "quality": self.max_score, 

97 "service": self.name, 

98 "source": text, 

99 } 

100 

101 def get_error_message(self, exc): 

102 if isinstance(exc, RequestException) and exc.response is not None: 

103 data = exc.response.json() 

104 try: 

105 return data["error"]["message"] 

106 except KeyError: 

107 pass 

108 

109 return super().get_error_message(exc)