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

35 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, Any 

8 

9from django.conf import settings 

10from django.db.models import Value 

11from django.db.models.functions import MD5, Lower 

12 

13from weblate.trans.models import Unit 

14from weblate.utils.db import adjust_similarity_threshold 

15from weblate.utils.state import STATE_TRANSLATED 

16 

17from .base import InternalMachineTranslation 

18 

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

20 from .base import DownloadTranslations 

21 

22 

23class WeblateTranslation(InternalMachineTranslation): 

24 """Translation service using strings already translated in Weblate.""" 

25 

26 name = "Weblate" 

27 rank_boost = 1 

28 cache_translations = True 

29 # Cache results for 1 hour to avoid frequent database hits 

30 cache_expiry = 3600 

31 

32 def download_translations( 

33 self, 

34 source_language, 

35 target_language, 

36 text: str, 

37 unit, 

38 user, 

39 threshold: int = 10, 

40 ) -> DownloadTranslations: 

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

42 # Filter based on user access 

43 base = Unit.objects.filter_access(user) if user else Unit.objects.all() 

44 

45 # Use memory_db for the query in case it exists. This is supposed 

46 # to be a read-only replica for offloading expensive translation 

47 # queries. 

48 if "memory_db" in settings.DATABASES: 

49 base = base.using("memory_db") 

50 

51 # Build search query 

52 lookup: dict[str, Any] = {} 

53 if threshold < 100: 

54 # Full text search 

55 lookup["source__search"] = text 

56 else: 

57 # Utilize PostgreSQL index 

58 lookup["source__lower__md5"] = MD5(Lower(Value(text))) 

59 lookup["source"] = text 

60 

61 matching_units = ( 

62 base.filter( 

63 translation__component__source_language=source_language, 

64 translation__language=target_language, 

65 state__gte=STATE_TRANSLATED, 

66 **lookup, 

67 ) 

68 .exclude( 

69 # The read-only strings can be possibly blank 

70 target__lower__md5=MD5(Lower(Value(""))) 

71 ) 

72 .prefetch() 

73 ) 

74 

75 # We want only close matches here 

76 adjust_similarity_threshold(0.98) 

77 

78 for munit in matching_units: 

79 source = munit.source_string 

80 if "forbidden" in munit.all_flags: 

81 continue 

82 quality = self.comparer.similarity(text, source) 

83 if quality < threshold: 

84 continue 

85 yield { 

86 "text": munit.get_target_plurals()[0], 

87 "quality": quality, 

88 "show_quality": True, 

89 "service": self.name, 

90 "origin": str(munit.translation.component), 

91 "origin_url": munit.get_absolute_url(), 

92 "source": source, 

93 }