Coverage for app/venv/lib/python3.14/site-packages/weblate/lang/views.py: 32%

106 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 

7 

8from django.contrib.auth.decorators import permission_required 

9from django.http import Http404 

10from django.shortcuts import redirect, render 

11from django.utils.decorators import method_decorator 

12from django.utils.translation import gettext 

13from django.views.generic import CreateView, UpdateView 

14 

15from weblate.lang.forms import LanguageForm, PluralForm 

16from weblate.lang.models import Language, Plural 

17from weblate.trans.forms import SearchForm, WorkflowSettingForm 

18from weblate.trans.models import Change, WorkflowSetting 

19from weblate.trans.models.project import prefetch_project_flags 

20from weblate.trans.util import sort_objects 

21from weblate.utils import messages 

22from weblate.utils.stats import ( 

23 GlobalStats, 

24 ProjectLanguage, 

25 ProjectLanguageStats, 

26 prefetch_stats, 

27) 

28from weblate.utils.views import get_paginator 

29 

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

31 from weblate.auth.models import AuthenticatedHttpRequest 

32 

33 

34def show_languages(request: AuthenticatedHttpRequest): 

35 custom_workflows = set() 

36 if request.user.has_perm("language.edit"): 

37 languages = Language.objects.all() 

38 custom_workflows = set( 

39 WorkflowSetting.objects.filter(project=None).values_list( 

40 "language_id", flat=True 

41 ) 

42 ) 

43 else: 

44 languages = Language.objects.have_translation() 

45 

46 return render( 

47 request, 

48 "languages.html", 

49 { 

50 "allow_index": True, 

51 "languages": prefetch_stats(sort_objects(languages)), 

52 "custom_workflows": custom_workflows, 

53 "title": gettext("Languages"), 

54 "global_stats": GlobalStats(), 

55 "bootstrap_5": True, 

56 }, 

57 ) 

58 

59 

60def show_language(request: AuthenticatedHttpRequest, lang): 

61 try: 

62 obj = Language.objects.get(code=lang) 

63 except Language.DoesNotExist as error: 

64 obj = Language.objects.fuzzy_get(lang) 

65 if isinstance(obj, Language): 

66 return redirect(obj) 

67 msg = "No Language matches the given query." 

68 raise Http404(msg) from error 

69 

70 user = request.user 

71 

72 if request.method == "POST" and user.has_perm("language.edit"): 

73 if obj.translation_set.exists(): 

74 messages.error( 

75 request, gettext("Remove all translations using this language first.") 

76 ) 

77 else: 

78 obj.delete() 

79 messages.success(request, gettext("Language %s removed.") % obj) 

80 return redirect("languages") 

81 

82 last_changes = Change.objects.last_changes(user, language=obj).recent() 

83 projects = prefetch_project_flags( 

84 get_paginator( 

85 request, 

86 user.allowed_projects.filter( 

87 component__translation__language=obj 

88 ).distinct(), 

89 stats=True, 

90 ) 

91 ) 

92 project_languages = [ProjectLanguage(project, obj) for project in projects] 

93 

94 ProjectLanguageStats.prefetch_many([project.stats for project in project_languages]) 

95 

96 return render( 

97 request, 

98 "language.html", 

99 { 

100 "allow_index": True, 

101 "object": obj, 

102 "last_changes": last_changes, 

103 "search_form": SearchForm( 

104 request=request, language=obj, obj=obj, bootstrap_5=True 

105 ), 

106 "projects": projects, 

107 "project_languages": project_languages, 

108 "bootstrap_5": True, 

109 }, 

110 ) 

111 

112 

113@method_decorator(permission_required("language.add"), name="dispatch") 

114class CreateLanguageView(CreateView): 

115 template_name = "lang/create.html" 

116 

117 def get_form(self, form_class=None): 

118 kwargs = self.get_form_kwargs() 

119 return (LanguageForm(**kwargs), PluralForm(**kwargs)) 

120 

121 def post(self, request: AuthenticatedHttpRequest, *args, **kwargs): 

122 self.object = None 

123 forms = self.get_form() 

124 if all(form.is_valid() for form in forms): 

125 return self.form_valid(forms) 

126 return self.form_invalid(forms) 

127 

128 def form_valid(self, form): 

129 """If the form is valid, save the associated model.""" 

130 self.object = form[0].save() 

131 plural = form[1].instance 

132 plural.language = self.object 

133 plural.save() 

134 return redirect(self.object) 

135 

136 

137@method_decorator(permission_required("language.edit"), name="dispatch") 

138class EditLanguageView(UpdateView): 

139 form_class = LanguageForm 

140 model = Language 

141 

142 def get_context_data(self, **kwargs): 

143 """Insert the form into the context dict.""" 

144 if "workflow_form" not in kwargs: 

145 kwargs["workflow_form"] = self.get_workflow_form() 

146 return super().get_context_data(**kwargs) 

147 

148 def get_workflow_form(self): 

149 kwargs = self.get_form_kwargs() 

150 kwargs.pop("instance", None) 

151 kwargs.pop("initial", None) 

152 if self.workflow_object: 

153 kwargs["instance"] = self.workflow_object 

154 return WorkflowSettingForm(**kwargs) 

155 

156 def get(self, request: AuthenticatedHttpRequest, *args, **kwargs): 

157 self.object = self.get_object() 

158 try: 

159 self.workflow_object = self.object.workflowsetting_set.get(project=None) 

160 except WorkflowSetting.DoesNotExist: 

161 self.workflow_object = None 

162 return super().get(request, *args, **kwargs) 

163 

164 def post(self, request: AuthenticatedHttpRequest, *args, **kwargs): 

165 self.object = self.get_object() 

166 try: 

167 self.workflow_object = self.object.workflowsetting_set.get(project=None) 

168 except WorkflowSetting.DoesNotExist: 

169 self.workflow_object = None 

170 form = self.get_form() 

171 workflow_form = self.get_workflow_form() 

172 if form.is_valid() and workflow_form.is_valid(): 

173 return self.form_valid(form, workflow_form) 

174 return self.render_to_response( 

175 self.get_context_data(form=form, workflow_form=workflow_form) 

176 ) 

177 

178 def form_valid(self, form, workflow_form): 

179 """If the form is valid, save the associated model.""" 

180 workflow_form.instance.language = self.object 

181 self.workflow_object = workflow_form.save() 

182 return super().form_valid(form) 

183 

184 

185@method_decorator(permission_required("language.edit"), name="dispatch") 

186class EditPluralView(UpdateView): 

187 form_class = PluralForm 

188 model = Plural