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

43 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 

4 

5from __future__ import annotations 

6 

7from typing import TYPE_CHECKING 

8 

9from weblate.lang.models import Language 

10 

11from .base import MachineTranslation 

12from .types import TranslationResultDict 

13 

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

15 from weblate.trans.models import Translation 

16 

17CYRTRANSLIT_TO_WEBLATE_LANGS = { 

18 # bulgarian 

19 "bg@latin": ["bg"], 

20 "bg@cyrillic": [], 

21 # montenegrin 

22 "me@latin": ["me", "cnr"], 

23 "me@cyrillic": ["cnr_Cyrl"], 

24 # macedonian 

25 "mk@latin": ["mk"], 

26 "mk@cyrillic": [], 

27 # mongolian 

28 "mn@latin": [], 

29 "mn@cyrillic": ["mn"], 

30 # russian 

31 "ru@latin": [], 

32 "ru@cyrillic": ["ru"], 

33 # serbian 

34 "sr@latin": ["sr", "sr_Latn", "sr@ijekavian_Latn"], 

35 "sr@cyrillic": ["sr@ijekavian", "sr_Cyrl"], 

36 # tajik 

37 "tj@latin": [], 

38 "tj@cyrillic": ["tg"], 

39 # ukrainian 

40 "ua@latin": [], 

41 "ua@cyrillic": ["uk"], 

42} 

43 

44 

45class CyrTranslitTranslation(MachineTranslation): 

46 """Machine translation using cyrtranslit library.""" 

47 

48 name = "CyrTranslit" 

49 max_score = 100 

50 cache_translations = False 

51 replacement_start = "[___" 

52 replacement_end = "___]" 

53 

54 def download_languages(self): 

55 """List of supported languages.""" 

56 return list(CYRTRANSLIT_TO_WEBLATE_LANGS.keys()) 

57 

58 def get_default_source_language(self, translation: Translation) -> Language: 

59 """Return default source language for the translation.""" 

60 mapped_code = self.map_language_code(translation.language.code) 

61 

62 # Invert alphabet 

63 if mapped_code.endswith("@latin"): 

64 mapped_code = mapped_code.replace("@latin", "@cyrillic") 

65 else: 

66 mapped_code = mapped_code.replace("@cyrillic", "@latin") 

67 

68 if mapped_code in CYRTRANSLIT_TO_WEBLATE_LANGS: 

69 languages = Language.objects.filter( 

70 code__in=CYRTRANSLIT_TO_WEBLATE_LANGS[mapped_code], 

71 translation__component=translation.component, 

72 ) 

73 

74 # Try finding best fit based on the base code 

75 for language in languages: 

76 if language.code.startswith(translation.language.base_code): 

77 return language 

78 

79 # Return any if we failed to match 

80 if languages: 

81 return languages[0] 

82 return super().get_default_source_language(translation) 

83 

84 def download_translations( 

85 self, 

86 source_language, 

87 target_language, 

88 text: str, 

89 unit, 

90 user, 

91 threshold: int = 75, 

92 ): 

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

94 import cyrtranslit 

95 

96 target_language, script = target_language.split("@") 

97 

98 translated_text = ( 

99 cyrtranslit.to_cyrillic(text, target_language) 

100 if script == "cyrillic" 

101 else cyrtranslit.to_latin(text, target_language) 

102 ) 

103 

104 yield TranslationResultDict( 

105 text=translated_text, 

106 quality=self.max_score, 

107 service=self.name, 

108 source=text, 

109 ) 

110 

111 def is_supported(self, source_language, target_language): 

112 """Check whether given language combination is supported.""" 

113 if super().is_supported(source_language, target_language): 

114 return source_language.split("@")[0] == target_language.split("@")[0] 

115 return False 

116 

117 def map_language_code(self, code: str) -> str: 

118 """Map language code to service specific code.""" 

119 for key, values in CYRTRANSLIT_TO_WEBLATE_LANGS.items(): 

120 if code in values: 

121 return key 

122 return code