Coverage for app/venv/lib/python3.14/site-packages/weblate/urls.py: 80%
79 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
7import django.contrib.sitemaps.views
8import django.views.i18n
9import django.views.static
10from django.conf import settings
11from django.contrib import admin
12from django.urls import include, path, re_path
13from django.views.decorators.cache import cache_control, cache_page
14from django.views.decorators.vary import vary_on_cookie
15from django.views.generic import RedirectView, TemplateView
16from drf_spectacular.views import (
17 SpectacularAPIView,
18 SpectacularRedocView,
19)
21import weblate.accounts.urls
22import weblate.accounts.views
23import weblate.addons.views
24import weblate.api.urls
25import weblate.auth.views
26import weblate.checks.views
27import weblate.fonts.views
28import weblate.glossary.views
29import weblate.lang.views
30import weblate.machinery.views
31import weblate.memory.views
32import weblate.screenshots.views
33import weblate.trans.views.about
34import weblate.trans.views.acl
35import weblate.trans.views.agreement
36import weblate.trans.views.basic
37import weblate.trans.views.charts
38import weblate.trans.views.create
39import weblate.trans.views.dashboard
40import weblate.trans.views.edit
41import weblate.trans.views.error
42import weblate.trans.views.files
43import weblate.trans.views.git
44import weblate.trans.views.js
45import weblate.trans.views.labels
46import weblate.trans.views.lock
47import weblate.trans.views.reports
48import weblate.trans.views.search
49import weblate.trans.views.settings
50import weblate.trans.views.source
51import weblate.trans.views.widgets
52import weblate.wladmin.views
53from weblate.auth.decorators import management_access
54from weblate.configuration.views import CustomCSSView
55from weblate.sitemaps import SITEMAPS
56from weblate.trans.feeds import ChangesFeed, LanguageChangesFeed, TranslationChangesFeed
57from weblate.trans.views.changes import ChangesCSVView, ChangesView, show_change
58from weblate.trans.views.hooks import ServiceHookView
59from weblate.utils.version import VERSION
61handler400 = weblate.trans.views.error.bad_request
62handler403 = weblate.trans.views.error.denied
63handler404 = weblate.trans.views.error.not_found
64handler500 = weblate.trans.views.error.server_error
66widget_pattern = "<word:widget>-<word:color>.<extension:extension>"
68URL_PREFIX = settings.URL_PREFIX
69if URL_PREFIX: 69 ↛ 70line 69 didn't jump to line 70 because the condition on line 69 was never true
70 URL_PREFIX = URL_PREFIX.strip("/") + "/"
72real_patterns = [
73 path("", weblate.trans.views.dashboard.home, name="home"),
74 path("projects/", weblate.trans.views.basic.list_projects, name="projects"),
75 # Object display
76 path(
77 "projects/<object_path:path>/",
78 weblate.trans.views.basic.show,
79 name="show",
80 ),
81 # Engagement pages
82 path(
83 "engage/<object_path:path>/",
84 weblate.trans.views.basic.show_engage,
85 name="engage",
86 ),
87 # Component pages
88 path(
89 "guide/<object_path:path>/",
90 weblate.trans.views.basic.guide,
91 name="guide",
92 ),
93 path(
94 "matrix/<object_path:path>/",
95 weblate.trans.views.source.matrix,
96 name="matrix",
97 ),
98 path(
99 "js/matrix/<object_path:path>/",
100 weblate.trans.views.source.matrix_load,
101 name="matrix-load",
102 ),
103 path(
104 "source/<int:pk>/context/",
105 weblate.trans.views.source.edit_context,
106 name="edit_context",
107 ),
108 # Translation pages
109 path(
110 "component-list/<name:name>/",
111 weblate.trans.views.basic.show_component_list,
112 name="component-list",
113 ),
114 path(
115 "component-list/<name:name>/dashboard/",
116 weblate.trans.views.dashboard.component_list_user,
117 name="component-list-dashboard",
118 ),
119 path(
120 "browse/<object_path:path>/",
121 weblate.trans.views.edit.browse,
122 name="browse",
123 ),
124 path(
125 "translate/<object_path:path>/",
126 weblate.trans.views.edit.translate,
127 name="translate",
128 ),
129 path(
130 "zen/<object_path:path>/",
131 weblate.trans.views.edit.zen,
132 name="zen",
133 ),
134 path(
135 "download/<object_path:path>/",
136 weblate.trans.views.files.download,
137 name="download",
138 ),
139 path(
140 "download-list/<name:name>/",
141 weblate.trans.views.files.download_component_list,
142 name="download_component_list",
143 ),
144 path(
145 "upload/<object_path:path>/",
146 weblate.trans.views.files.upload,
147 name="upload",
148 ),
149 path(
150 "unit/<int:unit_id>/delete/",
151 weblate.trans.views.edit.delete_unit,
152 name="delete-unit",
153 ),
154 path(
155 "new-unit/<object_path:path>/",
156 weblate.trans.views.edit.new_unit,
157 name="new-unit",
158 ),
159 path(
160 "auto-translate/<object_path:path>/",
161 weblate.trans.views.edit.auto_translation,
162 name="auto_translation",
163 ),
164 path(
165 "replace/<object_path:path>/",
166 weblate.trans.views.search.search_replace,
167 name="replace",
168 ),
169 path(
170 "bulk-edit/<object_path:path>/",
171 weblate.trans.views.search.bulk_edit,
172 name="bulk-edit",
173 ),
174 path("credits/", weblate.trans.views.reports.get_credits, name="credits"),
175 path("counts/", weblate.trans.views.reports.get_counts, name="counts"),
176 path(
177 "credits/<object_path:path>/",
178 weblate.trans.views.reports.get_credits,
179 name="credits",
180 ),
181 path(
182 "counts/<object_path:path>/",
183 weblate.trans.views.reports.get_counts,
184 name="counts",
185 ),
186 path(
187 "new-lang/<object_path:path>/",
188 weblate.trans.views.basic.new_language,
189 name="new-language",
190 ),
191 path(
192 "new-lang/",
193 weblate.lang.views.CreateLanguageView.as_view(),
194 name="create-language",
195 ),
196 path(
197 "addons/<object_path:path>/",
198 weblate.addons.views.AddonList.as_view(),
199 name="addons",
200 ),
201 path(
202 "addon/<int:pk>/",
203 weblate.addons.views.AddonDetail.as_view(),
204 name="addon-detail",
205 ),
206 path(
207 "addon/<int:pk>/logs/",
208 weblate.addons.views.AddonLogs.as_view(),
209 name="addon-logs",
210 ),
211 path(
212 "access/<name:project>/",
213 weblate.trans.views.acl.manage_access,
214 name="manage-access",
215 ),
216 path(
217 "settings/<object_path:path>/",
218 weblate.trans.views.settings.change,
219 name="settings",
220 ),
221 path(
222 "backups/<name:project>/",
223 weblate.trans.views.settings.BackupsView.as_view(),
224 name="backups",
225 ),
226 path(
227 "backups/<name:project>/<name:backup>",
228 weblate.trans.views.settings.BackupsDownloadView.as_view(),
229 name="backups-download",
230 ),
231 path(
232 "labels/<name:project>/",
233 weblate.trans.views.labels.project_labels,
234 name="labels",
235 ),
236 path(
237 "labels/<name:project>/edit/<int:pk>/",
238 weblate.trans.views.labels.label_edit,
239 name="label_edit",
240 ),
241 path(
242 "labels/<name:project>/delete/<int:pk>/",
243 weblate.trans.views.labels.label_delete,
244 name="label_delete",
245 ),
246 path(
247 "fonts/<name:project>/",
248 weblate.fonts.views.FontListView.as_view(),
249 name="fonts",
250 ),
251 path(
252 "fonts/<name:project>/font/<int:pk>/",
253 weblate.fonts.views.FontDetailView.as_view(),
254 name="font",
255 ),
256 path(
257 "fonts/<name:project>/group/<int:pk>/",
258 weblate.fonts.views.FontGroupDetailView.as_view(),
259 name="font_group",
260 ),
261 path(
262 "create/project/",
263 weblate.trans.views.create.CreateProject.as_view(),
264 name="create-project",
265 ),
266 path(
267 "create/project/import/",
268 weblate.trans.views.create.ImportProject.as_view(),
269 name="create-project-import",
270 ),
271 path(
272 "create/component/",
273 weblate.trans.views.create.CreateComponentSelection.as_view(),
274 name="create-component",
275 ),
276 path(
277 "create/component/vcs/",
278 weblate.trans.views.create.CreateComponent.as_view(),
279 name="create-component-vcs",
280 ),
281 path(
282 "create/component/zip/",
283 weblate.trans.views.create.CreateFromZip.as_view(),
284 name="create-component-zip",
285 ),
286 path(
287 "create/component/doc/",
288 weblate.trans.views.create.CreateFromDoc.as_view(),
289 name="create-component-doc",
290 ),
291 path(
292 "contributor-agreement/<object_path:path>",
293 weblate.trans.views.agreement.agreement_confirm,
294 name="contributor-agreement",
295 ),
296 path(
297 "access/<name:project>/add/",
298 weblate.trans.views.acl.add_user,
299 name="add-user",
300 ),
301 path(
302 "access/<name:project>/block/",
303 weblate.trans.views.acl.block_user,
304 name="block-user",
305 ),
306 path(
307 "access/<name:project>/unblock/",
308 weblate.trans.views.acl.unblock_user,
309 name="unblock-user",
310 ),
311 path(
312 "access/<name:project>/invite/",
313 weblate.trans.views.acl.invite_user,
314 name="invite-user",
315 ),
316 path(
317 "access/<name:project>/remove/",
318 weblate.trans.views.acl.delete_user,
319 name="delete-user",
320 ),
321 path(
322 "access/<name:project>/set/",
323 weblate.trans.views.acl.set_groups,
324 name="set-groups",
325 ),
326 path(
327 "access/<name:project>/team/create/",
328 weblate.trans.views.acl.create_group,
329 name="create-project-group",
330 ),
331 path(
332 "token/<name:project>/create/",
333 weblate.trans.views.acl.create_token,
334 name="create-project-token",
335 ),
336 # Used by weblate.org to render own activity chart on homepage
337 path(
338 "activity/month.json",
339 weblate.trans.views.charts.monthly_activity_json,
340 name="monthly_activity_json",
341 ),
342 # Comments
343 path("comment/<int:pk>/", weblate.trans.views.edit.comment, name="comment"),
344 path(
345 "comment/<int:pk>/delete/",
346 weblate.trans.views.edit.delete_comment,
347 name="delete-comment",
348 ),
349 path(
350 "comment/<int:pk>/resolve/",
351 weblate.trans.views.edit.resolve_comment,
352 name="resolve-comment",
353 ),
354 # VCS manipulation - commit
355 path(
356 "commit/<object_path:path>/",
357 weblate.trans.views.git.commit,
358 name="commit",
359 ),
360 # VCS manipulation - update
361 path(
362 "update/<object_path:path>/",
363 weblate.trans.views.git.update,
364 name="update",
365 ),
366 # VCS manipulation - push
367 path(
368 "push/<object_path:path>/",
369 weblate.trans.views.git.push,
370 name="push",
371 ),
372 # VCS manipulation - reset
373 path(
374 "reset/<object_path:path>/",
375 weblate.trans.views.git.reset,
376 name="reset",
377 ),
378 # VCS manipulation - cleanup
379 path(
380 "cleanup/<object_path:path>/",
381 weblate.trans.views.git.cleanup,
382 name="cleanup",
383 ),
384 # VCS manipulation - force sync
385 path(
386 "file-sync/<object_path:path>/",
387 weblate.trans.views.git.file_sync,
388 name="file_sync",
389 ),
390 # VCS manipulation - force scan
391 path(
392 "file-scan/<object_path:path>/",
393 weblate.trans.views.git.file_scan,
394 name="file_scan",
395 ),
396 path(
397 "progress/<object_path:path>/",
398 weblate.trans.views.settings.show_progress,
399 name="show_progress",
400 ),
401 # Announcements
402 path(
403 "announcement/<object_path:path>/",
404 weblate.trans.views.settings.announcement,
405 name="announcement",
406 ),
407 path(
408 "js/announcement/<int:pk>/delete/",
409 weblate.trans.views.settings.announcement_delete,
410 name="announcement-delete",
411 ),
412 # VCS manipulation - remove
413 path(
414 "remove/<object_path:path>/",
415 weblate.trans.views.settings.remove,
416 name="remove",
417 ),
418 # Project renaming and moving
419 path(
420 "rename/<object_path:path>/", weblate.trans.views.settings.rename, name="rename"
421 ),
422 path(
423 "category/add/<object_path:path>/",
424 weblate.trans.views.settings.add_category,
425 name="add-category",
426 ),
427 # Alerts dismiss
428 path(
429 "alerts/<object_path:path>/dismiss/",
430 weblate.trans.views.settings.dismiss_alert,
431 name="dismiss-alert",
432 ),
433 # Locking
434 path(
435 "lock/<object_path:path>/",
436 weblate.trans.views.lock.lock,
437 name="lock",
438 ),
439 path(
440 "unlock/<object_path:path>/",
441 weblate.trans.views.lock.unlock,
442 name="unlock",
443 ),
444 # Screenshots
445 path(
446 "screenshots/<object_path:path>/",
447 weblate.screenshots.views.ScreenshotList.as_view(),
448 name="screenshots",
449 ),
450 path(
451 "screenshot/<int:pk>/",
452 weblate.screenshots.views.ScreenshotDetail.as_view(),
453 name="screenshot",
454 ),
455 path(
456 "screenshot/<int:pk>/delete/",
457 weblate.screenshots.views.delete_screenshot,
458 name="screenshot-delete",
459 ),
460 path(
461 "screenshot/<int:pk>/remove/",
462 weblate.screenshots.views.remove_source,
463 name="screenshot-remove-source",
464 ),
465 path(
466 "js/screenshot/<int:pk>/get/",
467 weblate.screenshots.views.get_sources,
468 name="screenshot-js-get",
469 ),
470 path(
471 "js/screenshot/<int:pk>/search/",
472 weblate.screenshots.views.search_source,
473 name="screenshot-js-search",
474 ),
475 path(
476 "js/screenshot/<int:pk>/ocr/",
477 weblate.screenshots.views.ocr_search,
478 name="screenshot-js-ocr",
479 ),
480 path(
481 "js/screenshot/<int:pk>/add/",
482 weblate.screenshots.views.add_source,
483 name="screenshot-js-add",
484 ),
485 # Translation memory
486 path("memory/", weblate.memory.views.MemoryView.as_view(), name="memory"),
487 path(
488 "memory/delete/",
489 weblate.memory.views.DeleteView.as_view(),
490 name="memory-delete",
491 ),
492 path(
493 "memory/rebuild/",
494 weblate.memory.views.RebuildView.as_view(),
495 name="memory-rebuild",
496 ),
497 path(
498 "memory/upload/",
499 weblate.memory.views.UploadView.as_view(),
500 name="memory-upload",
501 ),
502 path(
503 "memory/download/",
504 weblate.memory.views.DownloadView.as_view(),
505 name="memory-download",
506 ),
507 path(
508 "manage/memory/",
509 management_access(weblate.memory.views.MemoryView.as_view()),
510 kwargs={"manage": 1},
511 name="manage-memory",
512 ),
513 path(
514 "manage/memory/upload/",
515 management_access(weblate.memory.views.UploadView.as_view()),
516 kwargs={"manage": 1},
517 name="manage-memory-upload",
518 ),
519 path(
520 "manage/memory/delete/",
521 management_access(weblate.memory.views.DeleteView.as_view()),
522 kwargs={"manage": 1},
523 name="manage-memory-delete",
524 ),
525 path(
526 "manage/memory/rebuild/",
527 management_access(weblate.memory.views.RebuildView.as_view()),
528 kwargs={"manage": 1},
529 name="manage-memory-rebuild",
530 ),
531 path(
532 "manage/memory/download/",
533 management_access(weblate.memory.views.DownloadView.as_view()),
534 kwargs={"manage": 1},
535 name="manage-memory-download",
536 ),
537 path(
538 "memory/project/<name:project>/",
539 weblate.memory.views.MemoryView.as_view(),
540 name="memory",
541 ),
542 path(
543 "memory/project/<name:project>/delete/",
544 weblate.memory.views.DeleteView.as_view(),
545 name="memory-delete",
546 ),
547 path(
548 "memory/project/<name:project>/rebuild/",
549 weblate.memory.views.RebuildView.as_view(),
550 name="memory-rebuild",
551 ),
552 path(
553 "memory/project/<name:project>/upload/",
554 weblate.memory.views.UploadView.as_view(),
555 name="memory-upload",
556 ),
557 path(
558 "memory/project/<name:project>/download/",
559 weblate.memory.views.DownloadView.as_view(),
560 name="memory-download",
561 ),
562 # Machinery
563 path(
564 "manage/machinery/",
565 management_access(weblate.machinery.views.ListMachineryGlobalView.as_view()),
566 name="manage-machinery",
567 ),
568 path(
569 "manage/machinery/<name:machinery>/",
570 management_access(weblate.machinery.views.EditMachineryGlobalView.as_view()),
571 name="machinery-edit",
572 ),
573 path(
574 "machinery/<name:project>/",
575 weblate.machinery.views.ListMachineryProjectView.as_view(),
576 name="machinery-list",
577 ),
578 path(
579 "machinery/<name:project>/<name:machinery>/",
580 weblate.machinery.views.EditMachineryProjectView.as_view(),
581 name="machinery-edit",
582 ),
583 # Languages browsing
584 path("languages/", weblate.lang.views.show_languages, name="languages"),
585 path(
586 "languages/<name:lang>/",
587 weblate.lang.views.show_language,
588 name="show_language",
589 ),
590 path(
591 "edit-language/<int:pk>/",
592 weblate.lang.views.EditLanguageView.as_view(),
593 name="edit-language",
594 ),
595 path(
596 "edit-plural/<int:pk>/",
597 weblate.lang.views.EditPluralView.as_view(),
598 name="edit-plural",
599 ),
600 path(
601 "languages/<name:lang>/<name:project>/",
602 weblate.trans.views.basic.ProjectLanguageRedirectView.as_view(),
603 name="project-language-redirect",
604 ),
605 path(
606 "languages/<name:lang>/<name:project>/search/",
607 weblate.trans.views.basic.ProjectLanguageRedirectView.as_view(
608 pattern_name="search",
609 ),
610 name="project-language-search-redirect",
611 ),
612 # Checks browsing
613 path("checks/", weblate.checks.views.CheckList.as_view(), name="checks"),
614 path(
615 "checks/<name:name>/", weblate.checks.views.CheckList.as_view(), name="checks"
616 ),
617 path(
618 "checks/-/<object_path:path>/",
619 weblate.checks.views.CheckList.as_view(),
620 name="checks",
621 ),
622 path(
623 "checks/<name:name>/<object_path:path>/",
624 weblate.checks.views.CheckList.as_view(),
625 name="checks",
626 ),
627 # Changes browsing
628 path("changes/", ChangesView.as_view(), name="changes"),
629 path("changes/browse/<object_path:path>/", ChangesView.as_view(), name="changes"),
630 path("changes/csv/", ChangesCSVView.as_view(), name="changes-csv"),
631 path(
632 "changes/csv/<object_path:path>/", ChangesCSVView.as_view(), name="changes-csv"
633 ),
634 path("changes/render/<int:pk>/", show_change, name="show_change"),
635 # Notification hooks
636 path(
637 "hooks/<slug:service>/",
638 ServiceHookView.as_view(),
639 name="webhook",
640 ),
641 # Compatibility URL with no trailing slash
642 path(
643 "hooks/<slug:service>",
644 ServiceHookView.as_view(),
645 ),
646 # RSS exports
647 path("exports/rss/", ChangesFeed(), name="rss"),
648 path(
649 "exports/rss/language/<name:lang>/",
650 LanguageChangesFeed(),
651 name="rss-language",
652 ),
653 path("exports/rss/<object_path:path>/", TranslationChangesFeed(), name="rss"),
654 # Engagement widgets
655 path("exports/og.png", weblate.trans.views.widgets.render_og, name="og-image"),
656 path(
657 f"widgets/<name:project>/-/{widget_pattern}",
658 weblate.trans.views.widgets.WidgetRedirectView.as_view(),
659 ),
660 path(
661 f"widgets/<name:project>/<name:lang>/{widget_pattern}",
662 weblate.trans.views.widgets.WidgetRedirectView.as_view(),
663 ),
664 path(
665 f"widgets/<name:project>/-/<name:component>/{widget_pattern}",
666 weblate.trans.views.widgets.WidgetRedirectView.as_view(),
667 ),
668 path(
669 f"widgets/<name:project>/<name:lang>/<name:component>/{widget_pattern}",
670 weblate.trans.views.widgets.WidgetRedirectView.as_view(),
671 ),
672 path(
673 f"widget/<object_path:path>/{widget_pattern}",
674 weblate.trans.views.widgets.render_widget,
675 name="widget-image",
676 ),
677 path(
678 "widgets/<object_path:path>/",
679 weblate.trans.views.widgets.widgets,
680 name="widgets",
681 ),
682 path(
683 "widgets/",
684 RedirectView.as_view(
685 pattern_name="projects", permanent=True, query_string=True
686 ),
687 ),
688 # Data exports pages
689 path(
690 "data/",
691 RedirectView.as_view(
692 pattern_name="projects", permanent=True, query_string=True
693 ),
694 ),
695 path(
696 "data/<name:project>/",
697 weblate.trans.views.basic.data_project,
698 name="data_project",
699 ),
700 # AJAX/JS backends
701 path(
702 "js/render-check/<int:unit_id>/<name:check_id>/",
703 weblate.checks.views.render_check,
704 name="render-check",
705 ),
706 path(
707 "js/ignore-check/<int:check_id>/",
708 weblate.trans.views.js.ignore_check,
709 name="js-ignore-check",
710 ),
711 path(
712 "js/ignore-check/<int:check_id>/source/",
713 weblate.trans.views.js.ignore_check_source,
714 name="js-ignore-check-source",
715 ),
716 path(
717 "js/i18n/",
718 cache_page(3600, key_prefix=VERSION)(
719 vary_on_cookie(
720 django.views.i18n.JavaScriptCatalog.as_view(packages=["weblate"])
721 )
722 ),
723 name="js-catalog",
724 ),
725 path("js/matomo/", weblate.trans.views.js.matomo, name="js-matomo"),
726 path(
727 "js/translate/<name:service>/<int:unit_id>/",
728 weblate.machinery.views.translate,
729 name="js-translate",
730 ),
731 path(
732 "js/memory/<int:unit_id>/",
733 weblate.machinery.views.memory,
734 name="js-memory",
735 ),
736 path(
737 "js/translations/<int:unit_id>/",
738 weblate.trans.views.js.get_unit_translations,
739 name="js-unit-translations",
740 ),
741 path(
742 "js/git/<object_path:path>/",
743 weblate.trans.views.js.git_status,
744 name="git_status",
745 ),
746 path(
747 "js/zen/<object_path:path>/",
748 weblate.trans.views.edit.load_zen,
749 name="load_zen",
750 ),
751 path(
752 "js/save-zen/<object_path:path>/",
753 weblate.trans.views.edit.save_zen,
754 name="save_zen",
755 ),
756 # Glossary add
757 path(
758 "js/glossary/<int:unit_id>/",
759 weblate.glossary.views.add_glossary_term,
760 name="js-add-glossary",
761 ),
762 path(
763 "css/custom.css",
764 CustomCSSView.as_view(),
765 name="css-custom",
766 ),
767 # Admin interface
768 path("admin/", admin.site.urls),
769 # Weblate management interface
770 path("manage/", weblate.wladmin.views.manage, name="manage"),
771 path("manage/support/", weblate.wladmin.views.support_form, name="manage-support"),
772 path(
773 "manage/addons/", weblate.addons.views.AddonList.as_view(), name="manage-addons"
774 ),
775 path("manage/tools/", weblate.wladmin.views.tools, name="manage-tools"),
776 path(
777 "manage/users/",
778 weblate.wladmin.views.AdminUserList.as_view(),
779 name="manage-users",
780 ),
781 path(
782 "manage/teams/",
783 weblate.wladmin.views.TeamListView.as_view(),
784 name="manage-teams",
785 ),
786 path(
787 "teams/<int:pk>/",
788 weblate.auth.views.TeamUpdateView.as_view(),
789 name="team",
790 ),
791 path(
792 "manage/users/check/",
793 weblate.wladmin.views.users_check,
794 name="manage-users-check",
795 ),
796 path("manage/activate/", weblate.wladmin.views.activate, name="manage-activate"),
797 path("manage/discovery/", weblate.wladmin.views.discovery, name="manage-discovery"),
798 path("manage/alerts/", weblate.wladmin.views.alerts, name="manage-alerts"),
799 path("manage/repos/", weblate.wladmin.views.repos, name="manage-repos"),
800 path("manage/ssh/", weblate.wladmin.views.ssh, name="manage-ssh"),
801 path("manage/ssh/key/", weblate.wladmin.views.ssh_key, name="manage-ssh-key"),
802 path("manage/backup/", weblate.wladmin.views.backups, name="manage-backups"),
803 path(
804 "manage/appearance/", weblate.wladmin.views.appearance, name="manage-appearance"
805 ),
806 path(
807 "manage/performance/",
808 weblate.wladmin.views.performance,
809 name="manage-performance",
810 ),
811 # Accounts
812 path("accounts/", include(weblate.accounts.urls)),
813 # Auth
814 path("api/", include((weblate.api.urls, "weblate.api"), namespace="api")),
815 # OpenAPI schema
816 path("api/schema/", SpectacularAPIView.as_view(), name="api-schema"),
817 # API documentation
818 path(
819 "api/docs/", SpectacularRedocView.as_view(url_name="api-schema"), name="redoc"
820 ),
821 # Static pages
822 path("contact/", weblate.accounts.views.contact, name="contact"),
823 path("hosting/", weblate.accounts.views.hosting, name="hosting"),
824 path("trial/", weblate.accounts.views.trial, name="trial"),
825 path("about/", weblate.trans.views.about.AboutView.as_view(), name="about"),
826 path("donate/", weblate.trans.views.about.DonateView.as_view(), name="donate"),
827 path("keys/", weblate.trans.views.about.KeysView.as_view(), name="keys"),
828 path("stats/", weblate.trans.views.about.StatsView.as_view(), name="stats"),
829 # User pages
830 path("user/", weblate.accounts.views.UserList.as_view(), name="user_list"),
831 path(
832 "user/<name:user>/", weblate.accounts.views.UserPage.as_view(), name="user_page"
833 ),
834 path(
835 "user/<name:user>/contributions/",
836 weblate.accounts.views.user_contributions,
837 name="user_contributions",
838 ),
839 path(
840 "user/<name:user>/suggestions/",
841 weblate.accounts.views.SuggestionView.as_view(),
842 name="user_suggestions",
843 ),
844 # Avatars
845 path(
846 "avatar/<int:size>/<name:user>.png",
847 weblate.accounts.views.user_avatar,
848 name="user_avatar",
849 ),
850 # Sitemap
851 path(
852 "sitemap.xml",
853 cache_page(3600, key_prefix=VERSION)(django.contrib.sitemaps.views.index),
854 {"sitemaps": SITEMAPS, "sitemap_url_name": "sitemap"},
855 name="sitemap-index",
856 ),
857 path(
858 "sitemap-<slug:section>.xml",
859 cache_page(3600, key_prefix=VERSION)(django.contrib.sitemaps.views.sitemap),
860 {"sitemaps": SITEMAPS},
861 name="sitemap",
862 ),
863 # Site wide search
864 path("search/", weblate.trans.views.search.search, name="search"),
865 path(
866 "search/<object_path:path>/", weblate.trans.views.search.search, name="search"
867 ),
868 # Health check
869 path("healthz/", weblate.trans.views.basic.healthz, name="healthz"),
870 # Aliases for static files
871 re_path(
872 r"^(android-chrome|favicon)-(?P<size>192|512)x(?P=size)\.png$",
873 RedirectView.as_view(
874 url=settings.STATIC_URL + "weblate-%(size)s.png",
875 permanent=True,
876 ),
877 ),
878 path(
879 "apple-touch-icon.png",
880 RedirectView.as_view(
881 url=settings.STATIC_URL + "weblate-180.png",
882 permanent=True,
883 ),
884 ),
885 path(
886 "favicon.ico",
887 RedirectView.as_view(
888 url=settings.STATIC_URL + "favicon.ico",
889 permanent=True,
890 ),
891 ),
892 path(
893 "robots.txt",
894 cache_control(max_age=86400)(
895 TemplateView.as_view(template_name="robots.txt", content_type="text/plain")
896 ),
897 ),
898 path(
899 "browserconfig.xml",
900 cache_control(max_age=86400)(
901 TemplateView.as_view(
902 template_name="browserconfig.xml", content_type="application/xml"
903 )
904 ),
905 ),
906 path(
907 "site.webmanifest",
908 cache_control(max_age=86400)(
909 TemplateView.as_view(
910 template_name="site.webmanifest", content_type="application/json"
911 )
912 ),
913 ),
914 # Redirects for .well-known
915 path(
916 ".well-known/change-password",
917 RedirectView.as_view(pattern_name="password", permanent=True),
918 ),
919]
921# Billing integration
922if "weblate.billing" in settings.INSTALLED_APPS: 922 ↛ 923line 922 didn't jump to line 923 because the condition on line 922 was never true
923 import weblate.billing.views
925 real_patterns += [
926 path(
927 "invoice/<int:pk>/download/",
928 weblate.billing.views.download_invoice,
929 name="invoice-download",
930 ),
931 path("billing/", weblate.billing.views.overview, name="billing"),
932 path("billing/<int:pk>/", weblate.billing.views.detail, name="billing-detail"),
933 path("manage/billing/", weblate.wladmin.views.billing, name="manage-billing"),
934 ]
936# Git exporter integration
937if "weblate.gitexport" in settings.INSTALLED_APPS: 937 ↛ 993line 937 didn't jump to line 993 because the condition on line 937 was always true
938 import weblate.gitexport.views
940 real_patterns += [
941 # Redirect clone from the Weblate project URL
942 path(
943 "projects/<object_path:path>.git/<git_path:git_request>",
944 RedirectView.as_view(
945 pattern_name="git-export",
946 permanent=True,
947 query_string=True,
948 ),
949 ),
950 path(
951 "projects/<object_path:path>/<git_path:git_request>",
952 RedirectView.as_view(
953 pattern_name="git-export",
954 permanent=True,
955 query_string=True,
956 ),
957 ),
958 # Redirect clone in case user adds .git to the path
959 path(
960 "git/<object_path:path>.git/<git_path:git_request>",
961 RedirectView.as_view(
962 pattern_name="git-export",
963 permanent=True,
964 query_string=True,
965 ),
966 ),
967 # Redirect accessing Git URL with a browser
968 path(
969 "git/<object_path:path>.git/",
970 RedirectView.as_view(
971 pattern_name="show",
972 permanent=True,
973 query_string=True,
974 ),
975 ),
976 path(
977 "git/<object_path:path>/",
978 RedirectView.as_view(
979 pattern_name="show",
980 permanent=True,
981 query_string=True,
982 ),
983 ),
984 # Actual git server
985 path(
986 "git/<object_path:path>/<git_path:git_request>",
987 weblate.gitexport.views.git_export,
988 name="git-export",
989 ),
990 ]
992# Legal integartion
993if "weblate.legal" in settings.INSTALLED_APPS: 993 ↛ 994line 993 didn't jump to line 994 because the condition on line 993 was never true
994 real_patterns.extend(
995 (
996 path(
997 "legal/",
998 include(("weblate.legal.urls", "weblate.legal"), namespace="legal"),
999 ),
1000 path(
1001 "security.txt",
1002 RedirectView.as_view(url="/.well-known/security.txt", permanent=True),
1003 ),
1004 path(
1005 ".well-known/security.txt",
1006 TemplateView.as_view(
1007 template_name="security.txt", content_type="text/plain"
1008 ),
1009 ),
1010 )
1011 )
1013# Serving media files in DEBUG mode
1014if settings.DEBUG: 1014 ↛ 1015line 1014 didn't jump to line 1015 because the condition on line 1014 was never true
1015 real_patterns.append(
1016 path(
1017 "media/<path:path>",
1018 django.views.static.serve,
1019 {"document_root": settings.MEDIA_ROOT},
1020 )
1021 )
1023# Django debug toolbar integration
1024if settings.DEBUG and "debug_toolbar" in settings.INSTALLED_APPS: 1024 ↛ 1025line 1024 didn't jump to line 1025 because the condition on line 1024 was never true
1025 real_patterns.append(
1026 path("__debug__/", include("debug_toolbar.urls")),
1027 )
1029# Hosted Weblate integration
1030if "wlhosted.integrations" in settings.INSTALLED_APPS: 1030 ↛ 1031line 1030 didn't jump to line 1031 because the condition on line 1030 was never true
1031 from wlhosted.integrations.views import CreateBillingView
1033 real_patterns.append(
1034 path("create/billing/", CreateBillingView.as_view(), name="create-billing"),
1035 )
1037# Django SAML2 Identity Provider
1038if "djangosaml2idp" in settings.INSTALLED_APPS: 1038 ↛ 1039line 1038 didn't jump to line 1039 because the condition on line 1038 was never true
1039 real_patterns.append(
1040 path("idp/", include("djangosaml2idp.urls")),
1041 )
1043# Handle URL prefix configuration
1044if not URL_PREFIX: 1044 ↛ 1047line 1044 didn't jump to line 1047 because the condition on line 1044 was always true
1045 urlpatterns = real_patterns
1046else:
1047 urlpatterns = [path(URL_PREFIX, include(real_patterns))]