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
« 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
5from __future__ import annotations
7from typing import TYPE_CHECKING
9from weblate.lang.models import Language
11from .base import MachineTranslation
12from .types import TranslationResultDict
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
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}
45class CyrTranslitTranslation(MachineTranslation):
46 """Machine translation using cyrtranslit library."""
48 name = "CyrTranslit"
49 max_score = 100
50 cache_translations = False
51 replacement_start = "[___"
52 replacement_end = "___]"
54 def download_languages(self):
55 """List of supported languages."""
56 return list(CYRTRANSLIT_TO_WEBLATE_LANGS.keys())
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)
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")
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 )
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
79 # Return any if we failed to match
80 if languages:
81 return languages[0]
82 return super().get_default_source_language(translation)
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
96 target_language, script = target_language.split("@")
98 translated_text = (
99 cyrtranslit.to_cyrillic(text, target_language)
100 if script == "cyrillic"
101 else cyrtranslit.to_latin(text, target_language)
102 )
104 yield TranslationResultDict(
105 text=translated_text,
106 quality=self.max_score,
107 service=self.name,
108 source=text,
109 )
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
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