diff --git a/weblate/static/priorities/dash.svg b/weblate/static/priorities/dash.svg
new file mode 100644
index 000000000000..a29f353bd87c
--- /dev/null
+++ b/weblate/static/priorities/dash.svg
@@ -0,0 +1,7 @@
+
+
diff --git a/weblate/static/priorities/double_arrow_down.svg b/weblate/static/priorities/double_arrow_down.svg
new file mode 100644
index 000000000000..099ef4a63d98
--- /dev/null
+++ b/weblate/static/priorities/double_arrow_down.svg
@@ -0,0 +1,8 @@
+
+
diff --git a/weblate/static/priorities/double_arrow_up.svg b/weblate/static/priorities/double_arrow_up.svg
new file mode 100644
index 000000000000..f45dbac374b7
--- /dev/null
+++ b/weblate/static/priorities/double_arrow_up.svg
@@ -0,0 +1,8 @@
+
+
diff --git a/weblate/static/priorities/single_arrow_down.svg b/weblate/static/priorities/single_arrow_down.svg
new file mode 100644
index 000000000000..de3d0ba54af2
--- /dev/null
+++ b/weblate/static/priorities/single_arrow_down.svg
@@ -0,0 +1,7 @@
+
+
diff --git a/weblate/static/priorities/single_arrow_up.svg b/weblate/static/priorities/single_arrow_up.svg
new file mode 100644
index 000000000000..201f42133fdb
--- /dev/null
+++ b/weblate/static/priorities/single_arrow_up.svg
@@ -0,0 +1,7 @@
+
+
diff --git a/weblate/trans/templatetags/translations.py b/weblate/trans/templatetags/translations.py
index afdcff8e5037..d4fbbb264f68 100644
--- a/weblate/trans/templatetags/translations.py
+++ b/weblate/trans/templatetags/translations.py
@@ -47,6 +47,7 @@
from weblate.utils.docs import get_doc_url
from weblate.utils.hash import hash_to_checksum
from weblate.utils.html import format_html_join_comma, list_to_tuples
+from weblate.utils.icons import load_icon
from weblate.utils.markdown import render_markdown
from weblate.utils.messages import get_message_kind as get_message_kind_impl
from weblate.utils.random import get_random_identifier
@@ -1221,6 +1222,35 @@ def indicate_alerts(
# GhostProjectLanguageStats and GhostCategoryLanguageStats as these would
# be confusing (showing alert or admin icon on ghost containers).
+ priority_html = ""
+ if component and (priority := getattr(component, "priority", None)) is not None:
+ levels = (
+ (60, "double_arrow_up", "text-danger", gettext_lazy("Priority: Very high")),
+ (80, "single_arrow_up", "text-warning", gettext_lazy("Priority: High")),
+ (100, "dash", "text-info", gettext_lazy("Priority: Medium")),
+ (120, "single_arrow_down", "text-muted", gettext_lazy("Priority: Low")),
+ )
+
+ selected_svg = "double_arrow_down"
+ css_class = "text-secondary"
+ title_text = gettext_lazy("Priority: Very low")
+ for threshold, svg, css, title in levels:
+ if priority <= threshold:
+ selected_svg = svg
+ css_class = css
+ title_text = title
+ break
+
+ priority_html = format_html(
+ '{}',
+ css_class,
+ title_text,
+ title_text,
+ mark_safe( # noqa: S308
+ load_icon(f"priorities/{selected_svg}.svg", auto_prefix=False).decode()
+ ),
+ )
+
icons = format_html_join(
"\n",
'{}{}{}',
@@ -1256,7 +1286,7 @@ def indicate_alerts(
component.license,
)
- return format_html("{}{}", icons, license_badge)
+ return format_html("{}{}{}", priority_html, icons, license_badge)
@register.filter(is_safe=True)
diff --git a/weblate/trans/tests/test_templatetags.py b/weblate/trans/tests/test_templatetags.py
index aaab1be30a8d..96f4340748cb 100644
--- a/weblate/trans/tests/test_templatetags.py
+++ b/weblate/trans/tests/test_templatetags.py
@@ -6,6 +6,9 @@
from __future__ import annotations
+from unittest.mock import patch
+
+from django.template import Context
from django.test import SimpleTestCase, TestCase
from django.utils import timezone
@@ -17,6 +20,7 @@
from weblate.trans.templatetags.translations import (
format_translation,
get_location_links,
+ indicate_alerts,
naturaltime,
translation_progress_render,
)
@@ -35,6 +39,50 @@ def test_natural(self) -> None:
self.assertIn('class="naturaltime"', result)
+class IndicateAlertsPriorityTest(SimpleTestCase):
+ def test_priority_icons(self) -> None:
+ project = Project(slug="p", name="p")
+ context = Context({})
+
+ cases = (
+ (1, "double_arrow_up", "text-danger", 'title="Priority: Very high"'),
+ (60, "double_arrow_up", "text-danger", 'title="Priority: Very high"'),
+ (61, "single_arrow_up", "text-warning", 'title="Priority: High"'),
+ (80, "single_arrow_up", "text-warning", 'title="Priority: High"'),
+ (81, "dash", "text-info", 'title="Priority: Medium"'),
+ (100, "dash", "text-info", 'title="Priority: Medium"'),
+ (101, "single_arrow_down", "text-muted", 'title="Priority: Low"'),
+ (120, "single_arrow_down", "text-muted", 'title="Priority: Low"'),
+ (121, "double_arrow_down", "text-secondary", 'title="Priority: Very low"'),
+ (999, "double_arrow_down", "text-secondary", 'title="Priority: Very low"'),
+ )
+
+ def fake_load_icon(path: str, *, auto_prefix: bool = True) -> bytes:
+ return f''.encode()
+
+ with (
+ patch(
+ "weblate.trans.templatetags.translations.get_alerts", return_value=[]
+ ),
+ patch(
+ "weblate.trans.templatetags.translations.load_icon",
+ side_effect=fake_load_icon,
+ ),
+ ):
+ for priority, svg, css_class, title in cases:
+ component = Component(
+ project=project,
+ slug="c",
+ name="c",
+ priority=priority,
+ source_language=Language(),
+ )
+ html = str(indicate_alerts(context, component))
+ self.assertIn(f'data-icon="priorities/{svg}.svg"', html)
+ self.assertIn(f'class="state-icon {css_class}"', html)
+ self.assertIn(title, html)
+
+
class LocationLinksTest(TestCase):
def setUp(self) -> None:
self.unit = Unit(