From 9f4ae9f78f7e06675411a3d33ac91a8278eb2025 Mon Sep 17 00:00:00 2001 From: Phuoc Anh Kha Le <76896393+anhkha2003@users.noreply.github.com> Date: Sat, 25 May 2024 13:27:20 -0500 Subject: [PATCH] Organize contest list into timeline tabs (#111) --- judge/utils/problems.py | 12 +- judge/views/contests.py | 81 +++-- judge/views/organization.py | 14 +- locale/vi/LC_MESSAGES/django.po | 413 ++++++++++++----------- locale/vi/LC_MESSAGES/dmoj-user.po | 12 +- resources/users.scss | 2 +- templates/blog/list.html | 2 +- templates/contest/contest-list-tabs.html | 4 +- templates/contest/list.html | 348 +++++++++++-------- 9 files changed, 496 insertions(+), 392 deletions(-) diff --git a/judge/utils/problems.py b/judge/utils/problems.py index 67c4228..6423c70 100644 --- a/judge/utils/problems.py +++ b/judge/utils/problems.py @@ -114,13 +114,21 @@ def _get_result_data(results): # Using gettext_noop here since this will be tacked into the cache, so it must be language neutral. # The caller, SubmissionList.get_result_data will run ugettext on the name. {"code": "AC", "name": gettext_noop("Accepted"), "count": results["AC"]}, - {"code": "WA", "name": gettext_noop("Wrong"), "count": results["WA"]}, + { + "code": "WA", + "name": gettext_noop("Wrong Answer"), + "count": results["WA"], + }, { "code": "CE", "name": gettext_noop("Compile Error"), "count": results["CE"], }, - {"code": "TLE", "name": gettext_noop("Timeout"), "count": results["TLE"]}, + { + "code": "TLE", + "name": gettext_noop("Time Limit Exceeded"), + "count": results["TLE"], + }, { "code": "ERR", "name": gettext_noop("Error"), diff --git a/judge/views/contests.py b/judge/views/contests.py index cf7f260..42111ae 100644 --- a/judge/views/contests.py +++ b/judge/views/contests.py @@ -140,9 +140,9 @@ class ContestList( paginate_by = 10 template_name = "contest/list.html" title = gettext_lazy("Contests") - context_object_name = "past_contests" all_sorts = frozenset(("name", "user_count", "start_time")) default_desc = frozenset(("name", "user_count")) + context_object_name = "contests" def get_default_sort_order(self, request): if request.GET.get("contest") and settings.ENABLE_FTS: @@ -159,6 +159,11 @@ class ContestList( return request.GET.get(key, None) == "1" def get(self, request, *args, **kwargs): + default_tab = "active" + if not self.request.user.is_authenticated: + default_tab = "current" + self.current_tab = self.request.GET.get("tab", default_tab) + self.contest_query = None self.org_query = [] self.show_orgs = 0 @@ -225,43 +230,63 @@ class ContestList( return queryset - def get_queryset(self): + def _get_past_contests_queryset(self): return ( self._get_queryset() - .order_by(self.order, "key") .filter(end_time__lt=self._now) + .order_by(self.order, "key") ) + def _active_participations(self): + return ContestParticipation.objects.filter( + virtual=0, + user=self.request.profile, + contest__start_time__lte=self._now, + contest__end_time__gte=self._now, + ) + + @cached_property + def _active_contests_ids(self): + return self._active_participations().values_list("contest_id", flat=True) + + def _get_current_contests_queryset(self): + return ( + self._get_queryset() + .exclude(id__in=self._active_contests_ids) + .filter(start_time__lte=self._now, end_time__gte=self._now) + .order_by(self.order, "key") + ) + + def _get_future_contests_queryset(self): + return ( + self._get_queryset() + .filter(start_time__gt=self._now) + .order_by("start_time", "key") + ) + + def _get_active_participations_queryset(self): + active_contests = self._get_queryset().filter(id__in=self._active_contests_ids) + return self._active_participations().filter(contest_id__in=active_contests) + + def get_queryset(self): + if self.current_tab == "past": + return self._get_past_contests_queryset() + elif self.current_tab == "current": + return self._get_current_contests_queryset() + elif self.current_tab == "future": + return self._get_future_contests_queryset() + else: # Default to active + return self._get_active_participations_queryset() + def get_context_data(self, **kwargs): context = super(ContestList, self).get_context_data(**kwargs) - present, active, future = [], [], [] - if not context["page_obj"] or context["page_obj"].number == 1: - for contest in self._get_queryset().exclude(end_time__lt=self._now): - if contest.start_time > self._now: - future.append(contest) - else: - present.append(contest) - if self.request.user.is_authenticated: - for participation in ( - ContestParticipation.objects.filter( - virtual=0, user=self.request.profile, contest_id__in=present - ) - .select_related("contest") - .annotate(key=F("contest__key")) - ): - if not participation.ended: - active.append(participation) - present.remove(participation.contest) + context["current_tab"] = self.current_tab - if not ("contest" in self.request.GET and settings.ENABLE_FTS): - active.sort(key=attrgetter("end_time", "key")) - present.sort(key=attrgetter("end_time", "key")) - future.sort(key=attrgetter("start_time")) + context["current_count"] = self._get_current_contests_queryset().count() + context["future_count"] = self._get_future_contests_queryset().count() + context["active_count"] = self._get_active_participations_queryset().count() - context["active_participations"] = active - context["current_contests"] = present - context["future_contests"] = future context["now"] = self._now context["first_page_href"] = "." context["contest_query"] = self.contest_query diff --git a/judge/views/organization.py b/judge/views/organization.py index 513f121..176b5e3 100644 --- a/judge/views/organization.py +++ b/judge/views/organization.py @@ -434,14 +434,12 @@ class OrganizationContests( args=[self.organization.id, self.organization.slug], ) - for participation in context["active_participations"]: - self.set_editable_contest(participation.contest) - for contest in context["past_contests"]: - self.set_editable_contest(contest) - for contest in context["current_contests"]: - self.set_editable_contest(contest) - for contest in context["future_contests"]: - self.set_editable_contest(contest) + if self.current_tab == "active": + for participation in context["contests"]: + self.set_editable_contest(participation.contest) + else: + for contest in context["contests"]: + self.set_editable_contest(contest) return context diff --git a/locale/vi/LC_MESSAGES/django.po b/locale/vi/LC_MESSAGES/django.po index ef0eaab..c468efd 100644 --- a/locale/vi/LC_MESSAGES/django.po +++ b/locale/vi/LC_MESSAGES/django.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: lqdoj2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-05-04 11:35+0700\n" +"POT-Creation-Date: 2024-05-25 07:24+0700\n" "PO-Revision-Date: 2021-07-20 03:44\n" "Last-Translator: Icyene\n" "Language-Team: Vietnamese\n" @@ -48,7 +48,7 @@ msgstr "Gần đây" #: chat_box/views.py:448 templates/base.html:196 #: templates/comments/content-list.html:72 -#: templates/contest/contest-list-tabs.html:4 +#: templates/contest/contest-list-tabs.html:5 #: templates/contest/ranking-table.html:52 templates/course/left_sidebar.html:8 #: templates/internal/problem/problem.html:63 #: templates/organization/org-left-sidebar.html:12 @@ -138,11 +138,12 @@ msgstr "" msgid "Details" msgstr "Chi tiết" -#: judge/admin/contest.py:187 templates/contest/list.html:196 +#: judge/admin/contest.py:187 templates/contest/list.html:236 msgid "Format" msgstr "Thể thức" #: judge/admin/contest.py:191 templates/contest/ranking-table.html:5 +#: templates/profile-table.html:14 templates/profile-table.html:38 #: templates/user/user-about.html:15 templates/user/user-about.html:45 msgid "Rating" msgstr "" @@ -254,6 +255,7 @@ msgstr "" #: templates/contest/contest.html:117 #: templates/contest/contests_summary.html:41 templates/problem/data.html:536 #: templates/problem/list.html:22 templates/problem/list.html:48 +#: templates/profile-table.html:31 templates/profile-table.html:43 #: templates/user/base-users-table.html:10 templates/user/user-about.html:36 #: templates/user/user-about.html:52 templates/user/user-problems.html:58 msgid "Points" @@ -424,9 +426,9 @@ msgstr[0] "%d bài nộp đã được tính điểm lại." msgid "Rescore the selected submissions" msgstr "Tính điểm lại cái bài nộp" -#: judge/admin/submission.py:332 templates/contest/list.html:220 -#: templates/contest/list.html:259 templates/contest/list.html:298 -#: templates/contest/list.html:339 templates/notification/list.html:12 +#: judge/admin/submission.py:332 templates/contest/list.html:285 +#: templates/contest/list.html:325 templates/contest/list.html:360 +#: templates/contest/list.html:392 templates/notification/list.html:12 #: templates/organization/requests/log.html:10 #: templates/organization/requests/pending.html:20 #: templates/problem/list.html:154 @@ -584,7 +586,7 @@ msgid "Contest id must be ^[a-z0-9]+$" msgstr "Mã kỳ thi phải có dạng ^[a-z0-9]+$" #: judge/forms.py:498 templates/contest/clone.html:47 -#: templates/problem/search-form.html:39 +#: templates/contest/search-form.html:12 templates/problem/search-form.html:39 msgid "Group" msgstr "Nhóm" @@ -2336,10 +2338,12 @@ msgid "Accepted" msgstr "Accepted" #: judge/models/submission.py:21 judge/models/submission.py:48 +#: judge/utils/problems.py:117 msgid "Wrong Answer" msgstr "Wrong Answer" #: judge/models/submission.py:22 judge/models/submission.py:50 +#: judge/utils/problems.py:123 msgid "Time Limit Exceeded" msgstr "Time Limit Exceeded" @@ -2681,14 +2685,6 @@ msgstr "Invalid Return" msgid "Invalid signature header" msgstr "" -#: judge/utils/problems.py:117 -msgid "Wrong" -msgstr "Sai" - -#: judge/utils/problems.py:123 -msgid "Timeout" -msgstr "Quá thời gian" - #: judge/utils/problems.py:126 msgid "Error" msgstr "Lỗi" @@ -2733,6 +2729,10 @@ msgctxt "hours and minutes" msgid "%h:%m" msgstr "%h:%m" +#: judge/utils/users.py:55 +msgid "M j, Y" +msgstr "j M, Y" + #: judge/views/about.py:10 templates/course/course.html:5 #: templates/organization/home.html:40 #: templates/organization/org-right-sidebar.html:81 @@ -2745,183 +2745,183 @@ msgstr "Giới thiệu" msgid "Custom Checker Sample" msgstr "Hướng dẫn viết trình chấm" -#: judge/views/blog.py:111 +#: judge/views/blog.py:132 #, python-format msgid "Page %d of Posts" msgstr "Trang %d" -#: judge/views/blog.py:151 +#: judge/views/blog.py:172 msgid "Ticket feed" msgstr "Báo cáo" -#: judge/views/blog.py:168 +#: judge/views/blog.py:189 msgid "Comment feed" msgstr "Bình luận" -#: judge/views/comment.py:70 judge/views/pagevote.py:32 +#: judge/views/comment.py:71 judge/views/pagevote.py:32 msgid "Messing around, are we?" msgstr "Messing around, are we?" -#: judge/views/comment.py:86 judge/views/pagevote.py:48 +#: judge/views/comment.py:87 judge/views/pagevote.py:48 msgid "You must solve at least one problem before you can vote." msgstr "Bạn phải giải ít nhất 1 bài trước khi được vote." -#: judge/views/comment.py:112 +#: judge/views/comment.py:113 msgid "You already voted." msgstr "Bạn đã vote." -#: judge/views/comment.py:263 judge/views/organization.py:820 -#: judge/views/organization.py:970 judge/views/organization.py:1149 +#: judge/views/comment.py:267 judge/views/organization.py:821 +#: judge/views/organization.py:971 judge/views/organization.py:1150 msgid "Edited from site" msgstr "Chỉnh sửa từ web" -#: judge/views/comment.py:284 +#: judge/views/comment.py:288 msgid "Editing comment" msgstr "Chỉnh sửa bình luận" -#: judge/views/comment.py:336 +#: judge/views/comment.py:340 msgid "Comment body" msgstr "Nội dung bình luận" -#: judge/views/comment.py:342 judge/views/ticket.py:73 +#: judge/views/comment.py:346 judge/views/ticket.py:73 msgid "Your part is silent, little toad." msgstr "Bạn không được phép bình luận." -#: judge/views/comment.py:351 templates/comments/list.html:17 +#: judge/views/comment.py:355 templates/comments/list.html:17 msgid "" "You need to have solved at least one problem before your voice can be heard." msgstr "Bạn phải giải ít nhất một bài trước khi được phép bình luận." -#: judge/views/comment.py:394 +#: judge/views/comment.py:398 msgid "Posted comment" msgstr "Bình luận đã đăng" -#: judge/views/contests.py:122 judge/views/contests.py:407 -#: judge/views/contests.py:412 judge/views/contests.py:712 +#: judge/views/contests.py:122 judge/views/contests.py:424 +#: judge/views/contests.py:429 judge/views/contests.py:729 msgid "No such contest" msgstr "Không có contest nào như vậy" -#: judge/views/contests.py:123 judge/views/contests.py:408 +#: judge/views/contests.py:123 judge/views/contests.py:425 #, python-format msgid "Could not find a contest with the key \"%s\"." msgstr "Không tìm thấy kỳ thi với mã \"%s\"." -#: judge/views/contests.py:142 judge/views/contests.py:1483 -#: judge/views/stats.py:178 templates/contest/list.html:216 -#: templates/contest/list.html:255 templates/contest/list.html:294 -#: templates/contest/list.html:335 +#: judge/views/contests.py:142 judge/views/contests.py:1500 +#: judge/views/stats.py:178 templates/contest/list.html:281 +#: templates/contest/list.html:321 templates/contest/list.html:356 +#: templates/contest/list.html:388 #: templates/organization/org-left-sidebar.html:5 templates/stats/site.html:21 #: templates/user/user-bookmarks.html:56 msgid "Contests" msgstr "Kỳ thi" -#: judge/views/contests.py:412 +#: judge/views/contests.py:429 msgid "Could not find such contest." msgstr "Không tìm thấy kỳ thi nào như vậy." -#: judge/views/contests.py:420 +#: judge/views/contests.py:437 #, python-format msgid "Access to contest \"%s\" denied" msgstr "Truy cập tới kỳ thi \"%s\" bị từ chối" -#: judge/views/contests.py:498 +#: judge/views/contests.py:515 msgid "Clone Contest" msgstr "Nhân bản kỳ thi" -#: judge/views/contests.py:590 +#: judge/views/contests.py:607 msgid "Contest not ongoing" msgstr "Kỳ thi đang không diễn ra" -#: judge/views/contests.py:591 +#: judge/views/contests.py:608 #, python-format msgid "\"%s\" is not currently ongoing." msgstr "\"%s\" kỳ thi đang không diễn ra." -#: judge/views/contests.py:604 +#: judge/views/contests.py:621 msgid "Banned from joining" msgstr "Bị cấm tham gia" -#: judge/views/contests.py:606 +#: judge/views/contests.py:623 msgid "" "You have been declared persona non grata for this contest. You are " "permanently barred from joining this contest." msgstr "Bạn không được phép tham gia kỳ thi này." -#: judge/views/contests.py:696 +#: judge/views/contests.py:713 #, python-format msgid "Enter access code for \"%s\"" msgstr "Nhập mật khẩu truy cập cho \"%s\"" -#: judge/views/contests.py:713 +#: judge/views/contests.py:730 #, python-format msgid "You are not in contest \"%s\"." msgstr "Bạn không ở trong kỳ thi \"%s\"." -#: judge/views/contests.py:736 +#: judge/views/contests.py:753 msgid "ContestCalendar requires integer year and month" msgstr "Lịch thi yêu cầu giá trị cho năm và tháng là số nguyên" -#: judge/views/contests.py:794 +#: judge/views/contests.py:811 #, python-format msgid "Contests in %(month)s" msgstr "Các kỳ thi trong %(month)s" -#: judge/views/contests.py:795 +#: judge/views/contests.py:812 msgid "F Y" msgstr "F Y" -#: judge/views/contests.py:855 +#: judge/views/contests.py:872 #, python-format msgid "%s Statistics" msgstr "%s Thống kê" -#: judge/views/contests.py:1164 +#: judge/views/contests.py:1181 #, python-format msgid "%s Rankings" msgstr "%s Bảng điểm" -#: judge/views/contests.py:1175 +#: judge/views/contests.py:1192 msgid "???" msgstr "???" -#: judge/views/contests.py:1202 +#: judge/views/contests.py:1219 #, python-format msgid "Your participation in %s" msgstr "Lần tham gia trong %s" -#: judge/views/contests.py:1203 +#: judge/views/contests.py:1220 #, python-format msgid "%s's participation in %s" msgstr "Lần tham gia của %s trong %s" -#: judge/views/contests.py:1217 +#: judge/views/contests.py:1234 msgid "Live" msgstr "Trực tiếp" -#: judge/views/contests.py:1236 templates/contest/contest-tabs.html:21 +#: judge/views/contests.py:1253 templates/contest/contest-tabs.html:21 msgid "Participation" msgstr "Lần tham gia" -#: judge/views/contests.py:1285 +#: judge/views/contests.py:1302 #, python-format msgid "%s MOSS Results" msgstr "%s Kết quả MOSS" -#: judge/views/contests.py:1321 +#: judge/views/contests.py:1338 #, python-format msgid "Running MOSS for %s..." msgstr "Đang chạy MOSS cho %s..." -#: judge/views/contests.py:1344 +#: judge/views/contests.py:1361 #, python-format msgid "Contest tag: %s" msgstr "Nhãn kỳ thi: %s" -#: judge/views/contests.py:1359 judge/views/ticket.py:67 +#: judge/views/contests.py:1376 judge/views/ticket.py:67 msgid "Issue description" msgstr "Mô tả vấn đề" -#: judge/views/contests.py:1402 +#: judge/views/contests.py:1419 #, python-format msgid "New clarification for %s" msgstr "Thông báo mới cho %s" @@ -3064,7 +3064,7 @@ msgid "You are not allowed to access this organization." msgstr "Bạn không được phép chỉnh sửa tổ chức này." #: judge/views/organization.py:245 judge/views/stats.py:184 -#: templates/contest/list.html:71 templates/problem/list-base.html:90 +#: templates/contest/list.html:111 templates/problem/list-base.html:90 #: templates/stats/site.html:33 templates/user/user-left-sidebar.html:4 #: templates/user/user-list-tabs.html:6 msgid "Groups" @@ -3075,61 +3075,61 @@ msgstr "Nhóm" msgid "%s Members" msgstr "%s Thành viên" -#: judge/views/organization.py:474 +#: judge/views/organization.py:475 #, python-brace-format msgid "All submissions in {0}" msgstr "Bài nộp trong {0}" -#: judge/views/organization.py:482 judge/views/submission.py:872 +#: judge/views/organization.py:483 judge/views/submission.py:857 msgid "Submissions in" msgstr "Bài nộp trong" -#: judge/views/organization.py:507 judge/views/organization.py:513 -#: judge/views/organization.py:520 +#: judge/views/organization.py:508 judge/views/organization.py:514 +#: judge/views/organization.py:521 msgid "Joining group" msgstr "Tham gia nhóm" -#: judge/views/organization.py:508 +#: judge/views/organization.py:509 msgid "You are already in the group." msgstr "Bạn đã ở trong nhóm." -#: judge/views/organization.py:513 +#: judge/views/organization.py:514 msgid "This group is not open." msgstr "Nhóm này là nhóm kín." -#: judge/views/organization.py:521 +#: judge/views/organization.py:522 #, python-brace-format msgid "You may not be part of more than {count} public groups." msgstr "Bạn không thể tham gia nhiều hơn {count} nhóm công khai." -#: judge/views/organization.py:537 +#: judge/views/organization.py:538 msgid "Leaving group" msgstr "Rời nhóm" -#: judge/views/organization.py:538 +#: judge/views/organization.py:539 #, python-format msgid "You are not in \"%s\"." msgstr "Bạn không ở trong \"%s\"." -#: judge/views/organization.py:564 +#: judge/views/organization.py:565 #, python-format msgid "Request to join %s" msgstr "Đăng ký tham gia %s" -#: judge/views/organization.py:594 +#: judge/views/organization.py:595 msgid "Join request detail" msgstr "Chi tiết đơn đăng ký" -#: judge/views/organization.py:636 +#: judge/views/organization.py:637 msgid "Manage join requests" msgstr "Quản lý đơn đăng ký" -#: judge/views/organization.py:640 +#: judge/views/organization.py:641 #, python-format msgid "Managing join requests for %s" msgstr "Quản lý đơn đăng ký cho %s" -#: judge/views/organization.py:680 +#: judge/views/organization.py:681 #, python-format msgid "" "Your organization can only receive %d more members. You cannot approve %d " @@ -3138,84 +3138,84 @@ msgstr "" "Tổ chức chỉ có thể chứa %d thành viên. Bạn không thể chấp thuận nhiều hơn %d " "người." -#: judge/views/organization.py:698 +#: judge/views/organization.py:699 #, python-format msgid "Approved %d user." msgid_plural "Approved %d users." msgstr[0] "Đã chấp thuận %d người." -#: judge/views/organization.py:701 +#: judge/views/organization.py:702 #, python-format msgid "Rejected %d user." msgid_plural "Rejected %d users." msgstr[0] "Đã từ chối %d người." -#: judge/views/organization.py:741 +#: judge/views/organization.py:742 #, python-format msgid "Add member for %s" msgstr "Thêm thành viên cho %s" -#: judge/views/organization.py:753 +#: judge/views/organization.py:754 #, fuzzy #| msgid "Edited from site" msgid "Added members from site" msgstr "Chỉnh sửa từ web" -#: judge/views/organization.py:773 judge/views/organization.py:781 +#: judge/views/organization.py:774 judge/views/organization.py:782 msgid "Can't kick user" msgstr "Không thể đuổi" -#: judge/views/organization.py:774 +#: judge/views/organization.py:775 msgid "The user you are trying to kick does not exist!" msgstr "" -#: judge/views/organization.py:782 +#: judge/views/organization.py:783 #, python-format msgid "The user you are trying to kick is not in organization: %s." msgstr "" -#: judge/views/organization.py:803 judge/views/organization.py:959 +#: judge/views/organization.py:804 judge/views/organization.py:960 #, python-format msgid "Edit %s" msgstr "Chỉnh sửa %s" -#: judge/views/organization.py:831 templates/organization/list.html:46 +#: judge/views/organization.py:832 templates/organization/list.html:46 msgid "Create group" msgstr "Tạo nhóm" -#: judge/views/organization.py:846 +#: judge/views/organization.py:847 msgid "Exceeded limit" msgstr "" -#: judge/views/organization.py:847 +#: judge/views/organization.py:848 #, python-format msgid "You created too many groups. You can only create at most %d groups" msgstr "" -#: judge/views/organization.py:852 judge/views/organization.py:877 -#: judge/views/organization.py:1050 +#: judge/views/organization.py:853 judge/views/organization.py:878 +#: judge/views/organization.py:1051 msgid "Added from site" msgstr "Thêm từ web" -#: judge/views/organization.py:868 +#: judge/views/organization.py:869 #: templates/organization/org-right-sidebar.html:52 msgid "Add contest" msgstr "Thêm kỳ thi" -#: judge/views/organization.py:911 judge/views/organization.py:1100 +#: judge/views/organization.py:912 judge/views/organization.py:1101 msgid "Permission denied" msgstr "Truy cập bị từ chối" -#: judge/views/organization.py:912 +#: judge/views/organization.py:913 #, fuzzy #| msgid "You are not allowed to edit this organization." msgid "You are not allowed to edit this contest" msgstr "Bạn không được phép chỉnh sửa tổ chức này." -#: judge/views/organization.py:963 templates/blog/blog.html:31 +#: judge/views/organization.py:964 templates/blog/blog.html:31 #: templates/comments/content-list.html:53 #: templates/comments/content-list.html:66 -#: templates/contest/contest-tabs.html:36 templates/contest/list.html:110 +#: templates/contest/contest-tabs.html:36 templates/contest/list.html:150 #: templates/contest/tag-title.html:9 templates/flatpages/admin_link.html:3 #: templates/license.html:10 templates/problem/editorial.html:15 #: templates/problem/feed/items.html:50 @@ -3223,21 +3223,21 @@ msgstr "Bạn không được phép chỉnh sửa tổ chức này." msgid "Edit" msgstr "Chỉnh sửa" -#: judge/views/organization.py:1039 +#: judge/views/organization.py:1040 #, python-format msgid "Add blog for %s" msgstr "Thêm bài đăng cho %s" -#: judge/views/organization.py:1101 +#: judge/views/organization.py:1102 msgid "Not allowed to edit this blog" msgstr "Bạn không được phép chỉnh sửa bài đăng này." -#: judge/views/organization.py:1133 +#: judge/views/organization.py:1134 #, python-format msgid "Edit blog %s" msgstr "Chỉnh sửa %s" -#: judge/views/organization.py:1180 +#: judge/views/organization.py:1181 #, python-format msgid "Pending blogs in %s" msgstr "Bài đang đợi duyệt trong %s" @@ -3264,8 +3264,9 @@ msgstr "Hướng dẫn cho {0}" #: judge/views/problem.py:459 templates/contest/contest.html:112 #: templates/course/lesson.html:14 #: templates/organization/org-left-sidebar.html:4 -#: templates/user/user-about.html:28 templates/user/user-bookmarks.html:35 -#: templates/user/user-tabs.html:5 templates/user/users-table.html:19 +#: templates/profile-table.html:25 templates/user/user-about.html:28 +#: templates/user/user-bookmarks.html:35 templates/user/user-tabs.html:5 +#: templates/user/users-table.html:19 msgid "Problems" msgstr "Bài tập" @@ -3273,34 +3274,34 @@ msgstr "Bài tập" msgid "Problem feed" msgstr "Bài tập" -#: judge/views/problem.py:1029 judge/views/problem.py:1062 +#: judge/views/problem.py:1035 judge/views/problem.py:1068 msgid "