Coverage for app/venv/lib/python3.14/site-packages/weblate/trans/management/commands/auto_translate.py: 0%

53 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 django.core.management.base import CommandError 

10 

11from weblate.auth.models import User 

12from weblate.machinery.models import MACHINERY 

13from weblate.trans.autotranslate import AutoTranslate 

14from weblate.trans.management.commands import WeblateTranslationCommand 

15from weblate.trans.models import Component 

16 

17if TYPE_CHECKING: 

18 from django.core.management.base import CommandParser 

19 

20 

21class Command(WeblateTranslationCommand): 

22 """Command for mass automatic translation.""" 

23 

24 help = "performs automatic translation based on other components" 

25 

26 def add_arguments(self, parser: CommandParser) -> None: 

27 super().add_arguments(parser) 

28 parser.add_argument( 

29 "--user", default="anonymous", help=("User performing the change") 

30 ) 

31 parser.add_argument( 

32 "--source", default="", help=("Source component <project/component>") 

33 ) 

34 parser.add_argument( 

35 "--add", 

36 default=False, 

37 action="store_true", 

38 help=("Add translations if they do not exist"), 

39 ) 

40 parser.add_argument( 

41 "--overwrite", 

42 default=False, 

43 action="store_true", 

44 help=("Overwrite existing translations in target component"), 

45 ) 

46 parser.add_argument( 

47 "--inconsistent", 

48 default=False, 

49 action="store_true", 

50 help=("Process only inconsistent translations"), 

51 ) 

52 parser.add_argument( 

53 "--mt", action="append", default=[], help=("Add machine translation source") 

54 ) 

55 parser.add_argument( 

56 "--threshold", 

57 default=80, 

58 type=int, 

59 help=("Set machine translation threshold"), 

60 ) 

61 parser.add_argument( 

62 "--mode", 

63 default="translate", 

64 help=("Translation mode; translate, fuzzy or suggest"), 

65 ) 

66 

67 def handle(self, *args, **options) -> None: 

68 # Get translation object 

69 translation = self.get_translation(**options) 

70 

71 # Get user 

72 try: 

73 user = User.objects.get(username=options["user"]) 

74 except User.DoesNotExist as error: 

75 msg = "User does not exist!" 

76 raise CommandError(msg) from error 

77 

78 source = None 

79 if options["source"]: 

80 try: 

81 component = Component.objects.get_by_path(options["source"]) 

82 except Component.DoesNotExist as error: 

83 msg = "No matching source component found!" 

84 raise CommandError(msg) from error 

85 source = component.id 

86 

87 if options["mt"]: 

88 for translator in options["mt"]: 

89 if translator not in MACHINERY: 

90 msg = f"Machine translation {translator} is not available" 

91 raise CommandError(msg) 

92 

93 if options["mode"] not in {"translate", "fuzzy", "suggest"}: 

94 msg = "Invalid translation mode specified!" 

95 raise CommandError(msg) 

96 

97 if options["inconsistent"]: 

98 q = "check:inconsistent" 

99 elif options["overwrite"]: 

100 q = "" 

101 else: 

102 q = "state:<translated" 

103 

104 auto = AutoTranslate( 

105 user=user, 

106 translation=translation, 

107 mode=options["mode"], 

108 q=q, 

109 ) 

110 

111 message = auto.perform( 

112 auto_source="mt" if options["mt"] else "others", 

113 source=source, 

114 engines=options["mt"], 

115 threshold=options["threshold"], 

116 ) 

117 self.stdout.write(message)