Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions hypha/addressfield/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from django import forms
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _

from .widgets import AddressWidget

Expand Down Expand Up @@ -49,7 +50,7 @@ def clean(self, value, **kwargs):
try:
country_data = self.data[country]
except KeyError:
raise ValidationError("Invalid country selected") from None
raise ValidationError(_("Invalid country selected")) from None

fields = flatten_data(country_data["fields"])

Expand All @@ -59,7 +60,9 @@ def clean(self, value, **kwargs):
if missing_fields:
missing_field_name = [fields[field]["label"] for field in missing_fields]
raise ValidationError(
"Please provide data for: {}".format(", ".join(missing_field_name))
_("Please provide data for: {fields}").format(
fields=", ".join(missing_field_name)
)
)

return super().clean(value, **kwargs)
Expand Down
4 changes: 2 additions & 2 deletions hypha/apply/activity/adapters/activity_feed.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,9 @@ def handle_report_frequency(self, config, **kwargs):

def handle_skipped_report(self, report, **kwargs):
if report.skipped:
return "Skipped a Report"
return _("Skipped a Report")
else:
return "Marked a Report as required"
return _("Marked a Report as required")

def handle_update_invoice_status(self, invoice, **kwargs):
base_message = _("Updated Invoice status to: {invoice_status}.")
Expand Down
9 changes: 6 additions & 3 deletions hypha/apply/activity/adapters/base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.conf import settings
from django.contrib import messages
from django.utils.translation import gettext as _

from hypha.apply.activity.options import MESSAGES

Expand Down Expand Up @@ -192,11 +193,13 @@ def process_send(

if not settings.SEND_MESSAGES:
if recipient:
debug_message = "{} [to: {}]: {}".format(
self.adapter_type, recipient, message
debug_message = _("{adapter} [to: {recipient}]: {message}").format(
adapter=self.adapter_type, recipient=recipient, message=message
)
else:
debug_message = "{}: {}".format(self.adapter_type, message)
debug_message = _("{adapter}: {message}").format(
adapter=self.adapter_type, message=message
)
messages.add_message(request, messages.DEBUG, debug_message)

def create_logs(self, message, recipient, *events):
Expand Down
8 changes: 5 additions & 3 deletions hypha/apply/activity/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ class Meta:
"assign_to",
)
labels = {
"visibility": "Visible to",
"message": "Message",
"visibility": _("Visible to"),
"message": _("Message"),
}
help_texts = {
"visibility": "Select a relevant user role. Staff can view every comment."
"visibility": _(
"Select a relevant user role. Staff can view every comment."
)
}
widgets = {
"visibility": forms.RadioSelect(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Generated by Django 5.2.13 on 2026-04-13 08:22

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("activity", "0090_alter_activity_visibility_alter_event_type"),
]

operations = [
migrations.AlterModelOptions(
name="activity",
options={
"base_manager_name": "objects",
"ordering": ["-timestamp"],
"verbose_name": "activity",
"verbose_name_plural": "activities",
},
),
migrations.AlterModelOptions(
name="activityattachment",
options={
"verbose_name": "activity attachment",
"verbose_name_plural": "activity attachments",
},
),
migrations.AlterModelOptions(
name="event",
options={"verbose_name": "event", "verbose_name_plural": "events"},
),
migrations.AlterModelOptions(
name="message",
options={"verbose_name": "message", "verbose_name_plural": "messages"},
),
migrations.AlterField(
model_name="activity",
name="message",
field=models.TextField(verbose_name="message"),
),
migrations.AlterField(
model_name="activity",
name="visibility",
field=models.CharField(
choices=[
("applicant", "Applicants"),
("team", "Staff only"),
("reviewers", "Reviewers"),
("all", "All"),
],
default="applicant",
max_length=30,
verbose_name="visibility",
),
),
]
34 changes: 24 additions & 10 deletions hypha/apply/activity/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from django.urls import reverse
from django.utils import timezone
from django.utils.text import get_valid_filename
from django.utils.translation import gettext as _
from django.utils.translation import gettext_lazy as _

from hypha.apply.utils.storage import PrivateStorage

Expand All @@ -26,13 +26,10 @@
ACTION: _("Action"),
}

# Visibility strings. Used to determine visibility states but are also
# sometimes shown to users.
# (ie. hypha.apply.activity.templatetags.activity_tags.py)
APPLICANT = _("applicant")
TEAM = _("team")
REVIEWER = _("reviewers")
ALL = _("all")
APPLICANT = "applicant"
TEAM = "team"
REVIEWER = "reviewers"
ALL = "all"

# Visibility choice strings
VISIBILITY = {
Expand Down Expand Up @@ -175,6 +172,10 @@ class ActivityAttachment(models.Model):
upload_to=get_attachment_upload_path, storage=PrivateStorage()
)

class Meta:
verbose_name = _("activity attachment")
verbose_name_plural = _("activity attachments")

@property
def filename(self):
return os.path.basename(self.file.name)
Expand All @@ -201,9 +202,12 @@ class Activity(models.Model):
source_object_id = models.PositiveIntegerField(blank=True, null=True, db_index=True)
source = GenericForeignKey("source_content_type", "source_object_id")

message = models.TextField()
message = models.TextField(_("message"))
visibility = models.CharField(
choices=list(VISIBILITY.items()), default=APPLICANT, max_length=30
_("visibility"),
choices=list(VISIBILITY.items()),
default=APPLICANT,
max_length=30,
)

# Fields for handling versioning of the comment activity models
Expand Down Expand Up @@ -232,6 +236,8 @@ class Activity(models.Model):
class Meta:
ordering = ["-timestamp"]
base_manager_name = "objects"
verbose_name = _("activity")
verbose_name_plural = _("activities")

def get_absolute_url(self):
# coverup for both submission and project as source.
Expand Down Expand Up @@ -330,6 +336,10 @@ class Event(models.Model):
object_id = models.PositiveIntegerField(blank=True, null=True)
source = GenericForeignKey("content_type", "object_id")

class Meta:
verbose_name = _("event")
verbose_name_plural = _("events")

def __str__(self):
if self.source and hasattr(self.source, "title"):
return f"{self.by} {self.get_type_display()} - {self.source.title}"
Expand Down Expand Up @@ -365,6 +375,10 @@ class Message(models.Model):
sent_in_email_digest = models.BooleanField(default=False)
objects = MessagesQueryset.as_manager()

class Meta:
verbose_name = _("message")
verbose_name_plural = _("messages")

def __str__(self):
return f"[{self.type}][{self.status}] {self.content}"

Expand Down
2 changes: 1 addition & 1 deletion hypha/apply/activity/options.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.db.models import TextChoices
from django.utils.translation import gettext as _
from django.utils.translation import gettext_lazy as _


class MESSAGES(TextChoices):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
hx-target="this"
hx-swap="outerHTML transition:true"
hx-select=".h-timeline"
>Show more...</a>
>{% trans "Show more..." %}</a>
{% endif %}
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
{% for role in activity.user.get_role_names %}
<span
class="inline-block py-0.5 px-2 text-sm font-semibold rounded-xl border border-gray-300 text-fg-muted"
data-tippy-content="This user is a {{ role }}"
data-tippy-content="{% blocktrans %}This user is a {{ role }}{% endblocktrans %}"
>
{{ role }}
</span>
Expand All @@ -34,7 +34,7 @@
{% endif %}

<a href="#communications--{{activity.id}}" class="hover:underline">
<span class="text-fg-muted">commented</span>
<span class="text-fg-muted">{% trans "commented" %}</span>
<relative-time
class="text-fg-muted"
datetime="{{ activity.timestamp|date:"c" }}"
Expand All @@ -58,7 +58,7 @@

{% with activity.visibility|visibility_display:request.user as visibility_text %}
<span class="flex gap-1 items-center py-0.5 px-1.5 text-xs uppercase rounded-xl border border-gray-300 text-fg-muted"
data-tippy-content="This is visible to {{ visibility_text }}">
data-tippy-content="{% blocktrans %}This is visible to {{ visibility_text }}{% endblocktrans %}">
{% heroicon_outline "eye" size=14 class="inline" aria_hidden=true %}
{{ visibility_text }}
</span>
Expand All @@ -69,7 +69,7 @@
<a
hx-get="{% url 'activity:edit-comment' activity.id %}"
hx-target="#text-comment-{{activity.id}}"
title="{% trans "Edit comment" %}"
title="{% trans 'Edit comment' %}"
class="btn btn-sm btn-square btn-ghost"
>
{% heroicon_micro "pencil-square" aria_hidden=true %}
Expand All @@ -81,8 +81,8 @@
<a
hx-delete="{% url 'activity:delete-comment' activity.id %}"
hx-target="#communications-wrapper--{{activity.id}}"
hx-confirm="{% trans "Are you sure you want to delete this comment? This action cannot be undone." %}"
title="{% trans "Delete comment" %}"
hx-confirm="{% trans 'Are you sure you want to delete this comment? This action cannot be undone.' %}"
title="{% trans 'Delete comment' %}"
class="btn btn-error btn-sm btn-square btn-ghost"
>
{% heroicon_micro "trash" class="opacity-80 size-4" aria_hidden=true %}
Expand Down
9 changes: 5 additions & 4 deletions hypha/apply/activity/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.core.paginator import Paginator
from django.shortcuts import get_object_or_404, render
from django.utils.decorators import method_decorator
from django.utils.translation import gettext as _
from django.views.decorators.http import require_http_methods
from django.views.generic import ListView
from rolepermissions.checkers import has_object_permission
Expand Down Expand Up @@ -57,10 +58,10 @@ def edit_comment(request, pk):
activity = get_object_or_404(Activity, id=pk)

if activity.type != COMMENT or activity.user != request.user:
raise PermissionError("You can only edit your own comments")
raise PermissionDenied(_("You can only edit your own comments"))

if activity.deleted:
raise PermissionError("You can not edit a deleted comment")
raise PermissionDenied(_("You can not edit a deleted comment"))

if request.GET.get("action") == "cancel":
return render(
Expand Down Expand Up @@ -88,10 +89,10 @@ def delete_comment(request, pk):
activity = get_object_or_404(Activity, id=pk)

if activity.type != COMMENT or activity.user != request.user:
raise PermissionError("You can only delete your own comments")
raise PermissionDenied(_("You can only delete your own comments"))

if activity.deleted:
raise PermissionError("You can not delete a deleted comment")
raise PermissionDenied(_("You can not delete a deleted comment"))

if request.method == "DELETE":
activity = services.delete_comment(activity)
Expand Down
3 changes: 2 additions & 1 deletion hypha/apply/categories/admin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.urls import re_path
from django.utils.translation import gettext_lazy as _
from wagtail_modeladmin.options import ModelAdmin

from hypha.apply.utils.admin import AdminIcon
Expand All @@ -9,7 +10,7 @@


class CategoryAdmin(ModelAdmin):
menu_label = "Category Questions"
menu_label = _("Category Questions")
menu_icon = str(AdminIcon.CATEGORY)
model = Category

Expand Down
10 changes: 7 additions & 3 deletions hypha/apply/categories/admin_helpers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.contrib.admin.utils import quote
from django.utils.translation import gettext as _
from wagtail_modeladmin.helpers import ButtonHelper


Expand Down Expand Up @@ -33,9 +34,12 @@ def add_child_button(self, pk, child_verbose_name, **kwargs):
)
return {
"classname": classname,
"label": "Add %s %s" % (child_verbose_name, self.verbose_name),
"title": "Add %s %s under this one"
% (child_verbose_name, self.verbose_name),
"label": _("Add {child_verbose_name} {verbose_name}").format(
child_verbose_name=child_verbose_name, verbose_name=self.verbose_name
),
"title": _("Add {child_verbose_name} {verbose_name} under this one").format(
child_verbose_name=child_verbose_name, verbose_name=self.verbose_name
),
"url": self.url_helper.get_action_url("add_child", quote(pk)),
}

Expand Down
11 changes: 6 additions & 5 deletions hypha/apply/categories/admin_views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.contrib.admin.utils import unquote
from django.shortcuts import get_object_or_404
from django.utils.translation import gettext as _
from wagtail_modeladmin.views import CreateView


Expand All @@ -18,11 +19,11 @@ def __init__(self, model_admin, parent_pk):

def get_page_title(self):
"""Generate a title that explains you are adding a child."""
title = super().get_page_title()
return title + " %s %s for %s" % (
self.model.node_child_verbose_name,
self.opts.verbose_name,
self.parent_instance,
return _("{title} {child_verbose_name} {verbose_name} for {parent}").format(
title=super().get_page_title(),
child_verbose_name=self.model.node_child_verbose_name,
verbose_name=self.opts.verbose_name,
parent=self.parent_instance,
)

def get_initial(self):
Expand Down
Loading
Loading