From aa5a1bd42129a365b4de9fbde60694ea076cb5f6 Mon Sep 17 00:00:00 2001 From: lokses Date: Tue, 28 Jul 2026 10:06:22 +0300 Subject: [PATCH] =?UTF-8?q?i18n:=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B2=D0=BE?= =?UTF-8?q?=D0=B4=20=D1=81=D1=82=D1=80=D0=B0=D0=BD=D0=B8=D1=86=D1=8B=20tim?= =?UTF-8?q?etrack=20(ru/uk/en)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Учёт рабочего времени: заголовок, навигация по месяцам, фильтры, столбцы таблицы, пустое состояние — {% trans %}; метрики (из вью) переведены через gettext. uk/en. Co-Authored-By: Claude Opus 4.8 --- core/views.py | 11 +++-- locale/en/LC_MESSAGES/django.mo | Bin 25348 -> 26372 bytes locale/en/LC_MESSAGES/django.po | 80 ++++++++++++++++++++++++++++++-- locale/uk/LC_MESSAGES/django.mo | Bin 31202 -> 32462 bytes locale/uk/LC_MESSAGES/django.po | 80 ++++++++++++++++++++++++++++++-- templates/pages/timetrack.html | 30 ++++++------ 6 files changed, 174 insertions(+), 27 deletions(-) diff --git a/core/views.py b/core/views.py index 334fcdd..9949dcc 100644 --- a/core/views.py +++ b/core/views.py @@ -12,6 +12,7 @@ from core.models.directories import Directory from core.models import ConnectorConfig from core.utils.htmx import render_page from core.utils.pagination import paginate +from django.utils.translation import gettext_lazy as _ # Create your views here. @@ -345,11 +346,11 @@ def timetrack_view(request): fg, muted, warn = 'var(--color-foreground)', 'var(--color-muted-foreground)', 'var(--color-warning)' metrics = [ - {'label': 'Робочих днів', 'value': stats['workdays'], 'hint': 'з відмітками', 'color': fg}, - {'label': 'Співробітників', 'value': stats['employees'], 'hint': 'відмічались', 'color': fg}, - {'label': 'Змін', 'value': stats['shifts'], 'hint': 'за місяць', 'color': fg}, - {'label': 'Незакритих', 'value': stats['incomplete'],'hint': 'без уходу', 'color': warn if stats['incomplete'] else muted}, - {'label': 'Всього годин', 'value': stats['hours'], 'hint': 'відпрацьовано','color': fg}, + {'label': _('Рабочих дней'), 'value': stats['workdays'], 'hint': _('с отметками'), 'color': fg}, + {'label': _('Сотрудников'), 'value': stats['employees'], 'hint': _('отмечались'), 'color': fg}, + {'label': _('Смен'), 'value': stats['shifts'], 'hint': _('за месяц'), 'color': fg}, + {'label': _('Незакрытых'), 'value': stats['incomplete'],'hint': _('без ухода'), 'color': warn if stats['incomplete'] else muted}, + {'label': _('Всего часов'), 'value': stats['hours'], 'hint': _('отработано'), 'color': fg}, ] page = paginate(request, rows) diff --git a/locale/en/LC_MESSAGES/django.mo b/locale/en/LC_MESSAGES/django.mo index 27acb5c76064316186bb3a1e4e949b2f2afa8cfe..0bfdf35c71b2a1e7477a4069df85d9e0d401c59b 100644 GIT binary patch delta 9169 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 L=dNdW?y&y?B`Ki; delta 8302 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\n" "Language-Team: LANGUAGE \n" @@ -19,7 +19,7 @@ msgstr "" #: apps/ad_connector/models.py:10 apps/employees/models/base.py:186 #: apps/employees/models/permissions.py:47 templates/pages/employees.html:103 -#: templates/pages/hr-portal.html:215 +#: templates/pages/hr-portal.html:215 templates/pages/timetrack.html:58 msgid "Сотрудник" msgstr "Employee" @@ -272,7 +272,7 @@ msgstr "Warehouse" #: apps/employees/models/base.py:83 apps/locations/models/base.py:31 #: templates/pages/employees.html:56 templates/pages/hr-portal.html:124 -#: templates/pages/hr-portal.html:440 +#: templates/pages/hr-portal.html:440 templates/pages/timetrack.html:47 msgid "Офис" msgstr "Office" @@ -925,7 +925,8 @@ msgid "" "организации><номер>@домен. Можно задать вручную." msgstr "" -#: apps/locations/admin.py:376 templates/pages/structure.html:61 +#: apps/locations/admin.py:376 core/views.py:350 +#: templates/pages/structure.html:61 msgid "Сотрудников" msgstr "" @@ -1114,6 +1115,7 @@ msgstr "" #: apps/locations/models/pharmacies.py:211 templates/index.html:381 #: templates/pages/dislocation.html:16 templates/pages/pharmacies.html:6 +#: templates/pages/timetrack.html:49 msgid "Аптеки" msgstr "Pharmacies" @@ -1657,6 +1659,42 @@ msgstr "" msgid "Неверная контрольная сумма ИНН" msgstr "" +#: core/views.py:349 +msgid "Рабочих дней" +msgstr "Working days" + +#: core/views.py:349 +msgid "с отметками" +msgstr "with check-ins" + +#: core/views.py:350 +msgid "отмечались" +msgstr "checked in" + +#: core/views.py:351 +msgid "Смен" +msgstr "Shifts" + +#: core/views.py:351 +msgid "за месяц" +msgstr "this month" + +#: core/views.py:352 templates/pages/timetrack.html:62 +msgid "Незакрытых" +msgstr "Open" + +#: core/views.py:352 +msgid "без ухода" +msgstr "without checkout" + +#: core/views.py:353 +msgid "Всего часов" +msgstr "Total hours" + +#: core/views.py:353 +msgid "отработано" +msgstr "worked" + #: templates/index.html:210 msgid "Сеть аптек" msgstr "Pharmacy network" @@ -1740,6 +1778,7 @@ msgid "Рекрутинг" msgstr "Recruiting" #: templates/index.html:410 templates/pages/hr-portal.html:292 +#: templates/pages/timetrack.html:7 msgid "Учёт рабочего времени" msgstr "Time tracking" @@ -2161,6 +2200,7 @@ msgstr "employees, of them" #: templates/pages/employees.html:48 templates/pages/hr-portal.html:122 #: templates/pages/news.html:111 templates/pages/tasks.html:60 +#: templates/pages/timetrack.html:45 msgid "Все" msgstr "All" @@ -2955,3 +2995,35 @@ msgstr "No tasks with this status" #: templates/pages/tasks.html:144 msgid "Задач пока нет — создайте первую" msgstr "No tasks yet — create the first" + +#: templates/pages/timetrack.html:9 +msgid "сотрудников с отметками" +msgstr "employees with check-ins" + +#: templates/pages/timetrack.html:16 +msgid "Предыдущий месяц" +msgstr "Previous month" + +#: templates/pages/timetrack.html:22 +msgid "Следующий месяц" +msgstr "Next month" + +#: templates/pages/timetrack.html:59 +msgid "Часов" +msgstr "Hours" + +#: templates/pages/timetrack.html:60 +msgid "Дней" +msgstr "Days" + +#: templates/pages/timetrack.html:61 +msgid "Сред./день" +msgstr "Avg/day" + +#: templates/pages/timetrack.html:84 +msgid "Нет отметок рабочего времени за" +msgstr "No time records for" + +#: templates/pages/timetrack.html:92 +msgid "сотрудников" +msgstr "employees" diff --git a/locale/uk/LC_MESSAGES/django.mo b/locale/uk/LC_MESSAGES/django.mo index bd7e967193091bef4fd398b5118583434a6f8bea..650dd86d9c0683e397bbf3504b57de67f4c82558 100644 GIT binary patch delta 9279 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 O<6-;ny!@x**8c_T3r3Xy delta 8304 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 XI?mg1c1>^D>=5t#*^9h6bLRaIEdaRE diff --git a/locale/uk/LC_MESSAGES/django.po b/locale/uk/LC_MESSAGES/django.po index 99ded67..84e7559 100644 --- a/locale/uk/LC_MESSAGES/django.po +++ b/locale/uk/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-27 21:58+0300\n" +"POT-Creation-Date: 2026-07-28 10:05+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -22,7 +22,7 @@ msgstr "" #: apps/ad_connector/models.py:10 apps/employees/models/base.py:186 #: apps/employees/models/permissions.py:47 templates/pages/employees.html:103 -#: templates/pages/hr-portal.html:215 +#: templates/pages/hr-portal.html:215 templates/pages/timetrack.html:58 msgid "Сотрудник" msgstr "Співробітник" @@ -275,7 +275,7 @@ msgstr "Склад" #: apps/employees/models/base.py:83 apps/locations/models/base.py:31 #: templates/pages/employees.html:56 templates/pages/hr-portal.html:124 -#: templates/pages/hr-portal.html:440 +#: templates/pages/hr-portal.html:440 templates/pages/timetrack.html:47 msgid "Офис" msgstr "Офіс" @@ -928,7 +928,8 @@ msgid "" "организации><номер>@домен. Можно задать вручную." msgstr "" -#: apps/locations/admin.py:376 templates/pages/structure.html:61 +#: apps/locations/admin.py:376 core/views.py:350 +#: templates/pages/structure.html:61 msgid "Сотрудников" msgstr "" @@ -1117,6 +1118,7 @@ msgstr "" #: apps/locations/models/pharmacies.py:211 templates/index.html:381 #: templates/pages/dislocation.html:16 templates/pages/pharmacies.html:6 +#: templates/pages/timetrack.html:49 msgid "Аптеки" msgstr "Аптеки" @@ -1660,6 +1662,42 @@ msgstr "" msgid "Неверная контрольная сумма ИНН" msgstr "" +#: core/views.py:349 +msgid "Рабочих дней" +msgstr "Робочих днів" + +#: core/views.py:349 +msgid "с отметками" +msgstr "з відмітками" + +#: core/views.py:350 +msgid "отмечались" +msgstr "відмічались" + +#: core/views.py:351 +msgid "Смен" +msgstr "Змін" + +#: core/views.py:351 +msgid "за месяц" +msgstr "за місяць" + +#: core/views.py:352 templates/pages/timetrack.html:62 +msgid "Незакрытых" +msgstr "Незакритих" + +#: core/views.py:352 +msgid "без ухода" +msgstr "без виходу" + +#: core/views.py:353 +msgid "Всего часов" +msgstr "Всього годин" + +#: core/views.py:353 +msgid "отработано" +msgstr "відпрацьовано" + #: templates/index.html:210 msgid "Сеть аптек" msgstr "Мережа аптек" @@ -1743,6 +1781,7 @@ msgid "Рекрутинг" msgstr "Рекрутинг" #: templates/index.html:410 templates/pages/hr-portal.html:292 +#: templates/pages/timetrack.html:7 msgid "Учёт рабочего времени" msgstr "Облік робочого часу" @@ -2164,6 +2203,7 @@ msgstr "співробітників, з них" #: templates/pages/employees.html:48 templates/pages/hr-portal.html:122 #: templates/pages/news.html:111 templates/pages/tasks.html:60 +#: templates/pages/timetrack.html:45 msgid "Все" msgstr "Всі" @@ -2958,3 +2998,35 @@ msgstr "Задач з таким статусом немає" #: templates/pages/tasks.html:144 msgid "Задач пока нет — создайте первую" msgstr "Задач поки немає — створіть першу" + +#: templates/pages/timetrack.html:9 +msgid "сотрудников с отметками" +msgstr "співробітників з відмітками" + +#: templates/pages/timetrack.html:16 +msgid "Предыдущий месяц" +msgstr "Попередній місяць" + +#: templates/pages/timetrack.html:22 +msgid "Следующий месяц" +msgstr "Наступний місяць" + +#: templates/pages/timetrack.html:59 +msgid "Часов" +msgstr "Годин" + +#: templates/pages/timetrack.html:60 +msgid "Дней" +msgstr "Днів" + +#: templates/pages/timetrack.html:61 +msgid "Сред./день" +msgstr "Сер./день" + +#: templates/pages/timetrack.html:84 +msgid "Нет отметок рабочего времени за" +msgstr "Немає відміток робочого часу за" + +#: templates/pages/timetrack.html:92 +msgid "сотрудников" +msgstr "співробітників" diff --git a/templates/pages/timetrack.html b/templates/pages/timetrack.html index b4ad2e9..ea79da1 100644 --- a/templates/pages/timetrack.html +++ b/templates/pages/timetrack.html @@ -1,24 +1,25 @@ {% load common_tags %} +{% load i18n %}
-

Облік робочого часу

+

{% trans "Учёт рабочего времени" %}

- {{ month_label }} · {{ stats.employees }} співробітників з відмітками + {{ month_label }} · {{ stats.employees }} {% trans "сотрудников с отметками" %}

@@ -41,11 +42,11 @@
Всі · {{ counts.all }} + style="display:inline-flex;align-items:center;padding:0.25rem 0.875rem;font-size:0.8125rem;border-radius:calc(var(--radius) - 2px);font-weight:500;text-decoration:none;transition:all 150ms;{% if not location_type %}background:var(--color-card);color:var(--color-card-foreground);box-shadow:0 1px 2px rgb(0 0 0/0.08);{% else %}color:var(--color-muted-foreground);{% endif %}">{% trans "Все" %} · {{ counts.all }} Офіс · {{ counts.office }} + style="display:inline-flex;align-items:center;padding:0.25rem 0.875rem;font-size:0.8125rem;border-radius:calc(var(--radius) - 2px);font-weight:500;text-decoration:none;transition:all 150ms;{% if location_type == 'office' %}background:var(--color-card);color:var(--color-card-foreground);box-shadow:0 1px 2px rgb(0 0 0/0.08);{% else %}color:var(--color-muted-foreground);{% endif %}">{% trans "Офис" %} · {{ counts.office }} Аптеки · {{ counts.pharmacy }} + style="display:inline-flex;align-items:center;padding:0.25rem 0.875rem;font-size:0.8125rem;border-radius:calc(var(--radius) - 2px);font-weight:500;text-decoration:none;transition:all 150ms;{% if location_type == 'pharmacy' %}background:var(--color-card);color:var(--color-card-foreground);box-shadow:0 1px 2px rgb(0 0 0/0.08);{% else %}color:var(--color-muted-foreground);{% endif %}">{% trans "Аптеки" %} · {{ counts.pharmacy }}
@@ -54,11 +55,11 @@ - - - - - + + + + + @@ -80,7 +81,7 @@ {% empty %} {% endfor %} @@ -88,6 +89,7 @@
СпівробітникГодинДнівСер./деньНезакритих{% trans "Сотрудник" %}{% trans "Часов" %}{% trans "Дней" %}{% trans "Сред./день" %}{% trans "Незакрытых" %}
- За {{ month_label }} немає відміток робочого часу. + {% trans "Нет отметок рабочего времени за" %} {{ month_label }}.
- {% include "partials/pagination.html" with page=page base_url="/timetrack/" page_param="page" size_param="per_page" item_label="співробітників" %} + {% trans "сотрудников" as tt_item_label %} + {% include "partials/pagination.html" with page=page base_url="/timetrack/" page_param="page" size_param="per_page" item_label=tt_item_label %}