Coverage for app/venv/lib/python3.14/site-packages/weblate/trans/context_processors.py: 72%

78 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 

6import random 

7from typing import TYPE_CHECKING 

8from urllib.parse import urlparse 

9 

10from django.conf import settings 

11from django.utils.html import format_html 

12from django.utils.http import url_has_allowed_host_and_scheme 

13from django.utils.translation import gettext 

14 

15import weblate.utils.version 

16from weblate.configuration.views import CustomCSSView 

17from weblate.utils.site import get_site_domain, get_site_url 

18from weblate.wladmin.models import ConfigurationError, get_support_status 

19 

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

21 from weblate.auth.models import AuthenticatedHttpRequest 

22 

23WEBLATE_URL = "https://weblate.org/" 

24DONATE_URL = "https://weblate.org/donate/" 

25SUPPORT_URL = "https://weblate.org/support/" 

26 

27CONTEXT_SETTINGS = [ 

28 "SITE_TITLE", 

29 "SITE_DOMAIN", 

30 "ENABLE_HTTPS", 

31 "OFFER_HOSTING", 

32 "ENABLE_AVATARS", 

33 "ENABLE_SHARING", 

34 "MATOMO_SITE_ID", 

35 "MATOMO_URL", 

36 "GOOGLE_ANALYTICS_ID", 

37 "ENABLE_HOOKS", 

38 "REGISTRATION_OPEN", 

39 "GET_HELP_URL", 

40 "STATUS_URL", 

41 "LEGAL_URL", 

42 "PRIVACY_URL", 

43 "FONTS_CDN_URL", 

44 "AVATAR_URL_PREFIX", 

45 "HIDE_VERSION", 

46 "EXTRA_HTML_HEAD", 

47 "PRIVATE_COMMIT_EMAIL_OPT_IN", 

48 # Hosted Weblate integration 

49 "PAYMENT_ENABLED", 

50 "IP_ADDRESSES", 

51] 

52 

53CONTEXT_APPS = ["billing", "legal", "gitexport"] 

54 

55 

56def add_settings_context(context) -> None: 

57 for name in CONTEXT_SETTINGS: 

58 context[name.lower()] = getattr(settings, name, None) 

59 

60 

61def add_optional_context(context) -> None: 

62 for name in CONTEXT_APPS: 

63 appname = f"weblate.{name}" 

64 context[f"has_{name}"] = appname in settings.INSTALLED_APPS 

65 

66 

67def get_preconnect_list(): 

68 result = [] 

69 if settings.MATOMO_URL: 69 ↛ 70line 69 didn't jump to line 70 because the condition on line 69 was never true

70 result.append(urlparse(settings.MATOMO_URL).hostname) 

71 if settings.GOOGLE_ANALYTICS_ID: 71 ↛ 72line 71 didn't jump to line 72 because the condition on line 71 was never true

72 result.append("www.google-analytics.com") 

73 return result 

74 

75 

76def get_bread_image(path) -> str: 

77 if path == "/": 77 ↛ 78line 77 didn't jump to line 78 because the condition on line 77 was never true

78 return "dashboard.svg" 

79 first = path.split("/", 2)[1] 

80 if first in {"user", "accounts"}: 80 ↛ 81line 80 didn't jump to line 81 because the condition on line 80 was never true

81 return "account.svg" 

82 if first == "checks": 82 ↛ 83line 82 didn't jump to line 83 because the condition on line 82 was never true

83 return "alert.svg" 

84 if first == "languages": 84 ↛ 85line 84 didn't jump to line 85 because the condition on line 84 was never true

85 return "language.svg" 

86 if first == "manage": 86 ↛ 87line 86 didn't jump to line 87 because the condition on line 86 was never true

87 return "wrench.svg" 

88 if first in {"about", "stats", "keys", "legal", "donate"}: 88 ↛ 89line 88 didn't jump to line 89 because the condition on line 88 was never true

89 return "weblate.svg" 

90 if first in { 90 ↛ 96line 90 didn't jump to line 96 because the condition on line 90 was never true

91 "glossaries", 

92 "upload-glossaries", 

93 "delete-glossaries", 

94 "edit-glossaries", 

95 }: 

96 return "glossary.svg" 

97 return "project.svg" 

98 

99 

100def get_interledger_payment_pointer() -> str: 

101 interledger_payment_pointers: list[str] = [] 

102 if settings.INTERLEDGER_PAYMENT_BUILTIN: 102 ↛ 106line 102 didn't jump to line 106 because the condition on line 102 was always true

103 # Weblate funding 

104 interledger_payment_pointers.append("$ilp.uphold.com/ENU7fREdeZi9") 

105 

106 interledger_payment_pointers.extend(settings.INTERLEDGER_PAYMENT_POINTERS) 

107 

108 if not interledger_payment_pointers: 108 ↛ 109line 108 didn't jump to line 109 because the condition on line 108 was never true

109 return None 

110 

111 return random.choice(interledger_payment_pointers) # noqa: S311 

112 

113 

114def weblate_context(request: AuthenticatedHttpRequest): 

115 """Context processor to inject various useful variables into context.""" 

116 if url_has_allowed_host_and_scheme(request.GET.get("next", ""), allowed_hosts=None): 116 ↛ 117line 116 didn't jump to line 117 because the condition on line 116 was never true

117 login_redirect_url = request.GET["next"] 

118 elif request.resolver_match is None or ( 118 ↛ 124line 118 didn't jump to line 124 because the condition on line 118 was always true

119 not request.resolver_match.view_name.startswith("social:") 

120 and request.resolver_match.view_name != "logout" 

121 ): 

122 login_redirect_url = request.get_full_path() 

123 else: 

124 login_redirect_url = "" 

125 

126 # Load user translations if user is authenticated 

127 watched_projects = None 

128 theme = "auto" 

129 if hasattr(request, "user"): 129 ↛ 134line 129 didn't jump to line 134 because the condition on line 129 was always true

130 if request.user.is_authenticated: 130 ↛ 131line 130 didn't jump to line 131 because the condition on line 130 was never true

131 watched_projects = request.user.watched_projects 

132 theme = request.user.profile.theme 

133 

134 if settings.OFFER_HOSTING: 134 ↛ 135line 134 didn't jump to line 135 because the condition on line 134 was never true

135 description = gettext( 

136 "Hosted Weblate, the place to localize your software project." 

137 ) 

138 else: 

139 description = gettext( 

140 "This site runs Weblate for localizing various software projects." 

141 ) 

142 

143 support_status = get_support_status(request) 

144 

145 context = { 

146 "support_status": support_status, 

147 "cache_param": f"?v={weblate.utils.version.GIT_VERSION}" 

148 if not settings.COMPRESS_ENABLED 

149 else "", 

150 "version": weblate.utils.version.VERSION, 

151 "bread_image": get_bread_image(request.path), 

152 "description": description, 

153 "weblate_link": format_html('<a href="{}">weblate.org</a>', WEBLATE_URL), 

154 "weblate_name_link": format_html('<a href="{}">Weblate</a>', WEBLATE_URL), 

155 "weblate_version_link": format_html( 

156 '<a href="{}">Weblate {}</a>', 

157 WEBLATE_URL, 

158 "" if settings.HIDE_VERSION else weblate.utils.version.VERSION, 

159 ), 

160 "donate_url": DONATE_URL, 

161 "support_url": SUPPORT_URL, 

162 "site_url": get_site_url(), 

163 "site_domain": get_site_domain(), 

164 "login_redirect_url": login_redirect_url, 

165 "has_antispam": False, # Akismet integration removed 

166 "has_sentry": bool(settings.SENTRY_DSN), 

167 "watched_projects": watched_projects, 

168 "allow_index": False, 

169 "configuration_errors": ConfigurationError.objects.filter( 

170 ignored=False 

171 ).order_by("-timestamp"), 

172 "preconnect_list": get_preconnect_list(), 

173 "custom_css_hash": CustomCSSView.get_hash(request), 

174 "interledger_payment_pointer": get_interledger_payment_pointer(), 

175 "theme": theme, 

176 } 

177 

178 add_settings_context(context) 

179 add_optional_context(context) 

180 

181 return context