diff --git a/backend/civil_society_vote/common/contants.py b/backend/civil_society_vote/common/contants.py new file mode 100644 index 00000000..5e8d226b --- /dev/null +++ b/backend/civil_society_vote/common/contants.py @@ -0,0 +1,5 @@ +# Constants for memory sizes +KIBIBYTE = 1024 +MEBIBYTE = KIBIBYTE * 1024 +GIBIBYTE = MEBIBYTE * 1024 +TEBIBYTE = GIBIBYTE * 1024 diff --git a/backend/civil_society_vote/common/formatting.py b/backend/civil_society_vote/common/formatting.py new file mode 100644 index 00000000..1fe7c262 --- /dev/null +++ b/backend/civil_society_vote/common/formatting.py @@ -0,0 +1,21 @@ +from civil_society_vote.common.contants import GIBIBYTE, KIBIBYTE, MEBIBYTE, TEBIBYTE + + +def get_human_readable_size(num_bytes: int): + if num_bytes >= TEBIBYTE: + size_unit = "TB" + size_in_unit = num_bytes / TEBIBYTE + elif num_bytes >= GIBIBYTE: + size_unit = "GB" + size_in_unit = num_bytes / GIBIBYTE + elif num_bytes >= MEBIBYTE: + size_unit = "MB" + size_in_unit = num_bytes / MEBIBYTE + elif num_bytes >= KIBIBYTE: + size_unit = "KB" + size_in_unit = num_bytes / KIBIBYTE + else: + size_unit = "B" + size_in_unit = num_bytes + + return {"size": size_in_unit, "unit": size_unit} diff --git a/backend/civil_society_vote/settings.py b/backend/civil_society_vote/settings.py index 5a00e19f..1b1591c9 100644 --- a/backend/civil_society_vote/settings.py +++ b/backend/civil_society_vote/settings.py @@ -16,13 +16,8 @@ import sentry_sdk from django.urls import reverse_lazy # noqa - -# Constants for memory sizes -KIBIBYTE = 1024 -MEBIBYTE = KIBIBYTE * 1024 -GIBIBYTE = MEBIBYTE * 1024 -TEBIBYTE = GIBIBYTE * 1024 - +from civil_society_vote.common.contants import MEBIBYTE +from civil_society_vote.common.formatting import get_human_readable_size # Environment parameters root = Path(__file__).resolve().parent.parent.parent @@ -73,7 +68,7 @@ TIME_ZONE=(str, "Europe/Bucharest"), AUDITLOG_EXPIRY_DAYS=(int, 45), DATA_UPLOAD_MAX_MEMORY_SIZE=(int, 3 * MEBIBYTE), - MAX_DOCUMENT_SIZE=(int, 2 * MEBIBYTE), + MAX_DOCUMENT_SIZE=(int, 50 * MEBIBYTE), IMPERSONATE_READ_ONLY=(bool, False), # db settings # DATABASE_ENGINE=(str, "sqlite3"), @@ -425,12 +420,18 @@ def show_toolbar(request): STATIC_ROOT = os.path.abspath(os.path.join(os.sep, "var", "www", "votong", "backend", "static")) MEDIA_ROOT = os.path.abspath(os.path.join(os.sep, "var", "www", "votong", "backend", "media")) -# Maximum request size excludind the uploaded files +# Maximum request size excluding the uploaded files DATA_UPLOAD_MAX_MEMORY_SIZE = env.int("DATA_UPLOAD_MAX_MEMORY_SIZE") # Maximum single file size for uploaded files MAX_DOCUMENT_SIZE = env.int("MAX_DOCUMENT_SIZE") +MAX_DOCUMENT_READABLE_SIZE = get_human_readable_size(MAX_DOCUMENT_SIZE) + +MAX_DOCUMENT_SIZE_UNIT = MAX_DOCUMENT_READABLE_SIZE["unit"] +MAX_DOCUMENT_SIZE_IN_UNIT = MAX_DOCUMENT_READABLE_SIZE["size"] + + STATICFILES_DIRS = (os.path.abspath(os.path.join(BASE_DIR, "static_extras")),) diff --git a/backend/hub/migrations/0068_alter_candidate_criminal_record_alter_candidate_cv_and_more.py b/backend/hub/migrations/0068_alter_candidate_criminal_record_alter_candidate_cv_and_more.py new file mode 100644 index 00000000..7b75b2d8 --- /dev/null +++ b/backend/hub/migrations/0068_alter_candidate_criminal_record_alter_candidate_cv_and_more.py @@ -0,0 +1,209 @@ +# Generated by Django 4.2.16 on 2024-10-29 14:33 + +from django.db import migrations, models +import hub.models + + +class Migration(migrations.Migration): + + dependencies = [ + ("hub", "0067_remove_organization_user"), + ] + + operations = [ + migrations.AlterField( + model_name="candidate", + name="criminal_record", + field=models.FileField( + blank=True, + help_text="(Optional) Criminal record, valid at the time of submitting the candidacy", + max_length=300, + null=True, + upload_to="", + validators=[hub.models.file_validator], + verbose_name="Criminal record", + ), + ), + migrations.AlterField( + model_name="candidate", + name="cv", + field=models.FileField( + blank=True, + help_text="Europass format CV", + max_length=300, + null=True, + upload_to="", + validators=[hub.models.file_validator], + verbose_name="CV", + ), + ), + migrations.AlterField( + model_name="candidate", + name="declaration_of_interests", + field=models.FileField( + blank=True, + help_text="Official format Declaration of interests", + max_length=300, + null=True, + upload_to="", + validators=[hub.models.file_validator], + verbose_name="Declaration of interests", + ), + ), + migrations.AlterField( + model_name="candidate", + name="fiscal_record", + field=models.FileField( + blank=True, + help_text="Fiscal record, valid at the time of submitting the candidacy", + max_length=300, + null=True, + upload_to="", + validators=[hub.models.file_validator], + verbose_name="Fiscal record", + ), + ), + migrations.AlterField( + model_name="candidate", + name="letter_of_intent", + field=models.FileField( + blank=True, + help_text="Letter of intent (with the mention of the domain to be represented in the CES)", + max_length=300, + null=True, + upload_to="", + validators=[hub.models.file_validator], + verbose_name="Letter of intent", + ), + ), + migrations.AlterField( + model_name="candidate", + name="mandate", + field=models.FileField( + blank=True, + help_text="Mandate from the organization (signed in original + electronic) with the highlighting of the domain for which it is running", + max_length=300, + null=True, + upload_to="", + validators=[hub.models.file_validator], + verbose_name="Mandate", + ), + ), + migrations.AlterField( + model_name="candidate", + name="photo", + field=models.ImageField( + blank=True, + default="", + max_length=300, + storage=hub.models.select_public_storage, + upload_to="", + validators=[hub.models.file_validator], + verbose_name="Candidate photo", + ), + ), + migrations.AlterField( + model_name="candidate", + name="statement", + field=models.FileField( + blank=True, + help_text="Declaration of the designated representative stating that he/she is not a member of the leadership of a political party, has not been elected to a public office and is not a dignitary of the Romanian state.", + max_length=300, + null=True, + upload_to="", + validators=[hub.models.file_validator], + verbose_name="Representative statement", + ), + ), + migrations.AlterField( + model_name="organization", + name="fiscal_certificate_anaf", + field=models.FileField( + blank=True, + default="", + help_text="Certificat fiscal emis de ANAF", + max_length=300, + upload_to="", + validators=[hub.models.file_validator], + verbose_name="Fiscal certificate ANAF", + ), + ), + migrations.AlterField( + model_name="organization", + name="fiscal_certificate_local", + field=models.FileField( + blank=True, + default="", + help_text="Certificat fiscal emis de Direcția de Impozite și Taxe Locale", + max_length=300, + upload_to="", + validators=[hub.models.file_validator], + verbose_name="Fiscal certificate local", + ), + ), + migrations.AlterField( + model_name="organization", + name="report_2021", + field=models.FileField( + blank=True, + default="", + help_text="Rapoartele anuale trebuie să includă sursele de finanțare din care să rezulte că organizația dispune de resurse financiare şi umane pentru îndeplinirea mandatului de membru în Comisia Electorală a VotONG.", + max_length=300, + upload_to="", + validators=[hub.models.file_validator], + verbose_name="Yearly report 2021", + ), + ), + migrations.AlterField( + model_name="organization", + name="report_2022", + field=models.FileField( + blank=True, + default="", + help_text="Rapoartele anuale trebuie să includă sursele de finanțare din care să rezulte că organizația dispune de resurse financiare şi umane pentru îndeplinirea mandatului de membru în Comisia Electorală a VotONG.", + max_length=300, + upload_to="", + validators=[hub.models.file_validator], + verbose_name="Yearly report 2022", + ), + ), + migrations.AlterField( + model_name="organization", + name="report_2023", + field=models.FileField( + blank=True, + default="", + help_text="Rapoartele anuale trebuie să includă sursele de finanțare din care să rezulte că organizația dispune de resurse financiare şi umane pentru îndeplinirea mandatului de membru în Comisia Electorală a VotONG.", + max_length=300, + upload_to="", + validators=[hub.models.file_validator], + verbose_name="Yearly report 2023", + ), + ), + migrations.AlterField( + model_name="organization", + name="statement_discrimination", + field=models.FileField( + blank=True, + default="", + help_text="Declarație pe proprie răspundere prin care declară că nu realizează activități sau susține cauze de natură politică sau care discriminează pe considerente legate de etnie, rasă, sex, orientare sexuală, religie, capacități fizice sau psihice sau de apartenența la una sau mai multe categorii sociale sau economice.", + max_length=300, + upload_to="", + validators=[hub.models.file_validator], + verbose_name="Non-discrimination statement", + ), + ), + migrations.AlterField( + model_name="organization", + name="statement_political", + field=models.FileField( + blank=True, + default="", + help_text="Declarație pe propria răspundere prin care declar că ONG-ul nu are între membrii conducerii organizației (Președinte sau Consiliul Director) membri ai conducerii unui partid politic sau persoane care au fost alese într-o funcție publică.", + max_length=300, + upload_to="", + validators=[hub.models.file_validator], + verbose_name="Non-political statement", + ), + ), + ] diff --git a/backend/hub/models.py b/backend/hub/models.py index 3c609bbe..bed8ba35 100644 --- a/backend/hub/models.py +++ b/backend/hub/models.py @@ -15,7 +15,7 @@ from model_utils.models import StatusModel, TimeStampedModel from accounts.models import User, STAFF_GROUP, COMMITTEE_GROUP, SUPPORT_GROUP, NGO_GROUP - +from civil_society_vote.common.formatting import get_human_readable_size REPORTS_HELP_TEXT = ( "Rapoartele anuale trebuie să includă sursele de finanțare din care să rezulte că organizația dispune de resurse " @@ -25,6 +25,20 @@ logger = logging.getLogger(__name__) +def file_validator(file): + if file.size > settings.MAX_DOCUMENT_SIZE: + human_readable_size = get_human_readable_size(file.size) + raise ValidationError( + _("The file size is %d %s but it must be under %d %s") + % ( + human_readable_size["size"], + human_readable_size["unit"], + settings.MAX_DOCUMENT_SIZE_IN_UNIT, + settings.MAX_DOCUMENT_SIZE_UNIT, + ) + ) + + def select_public_storage(): return storages["public"] @@ -258,8 +272,14 @@ class Organization(StatusModel, TimeStampedModel): # organization_head_name = models.CharField(_("Organization Head Name"), max_length=254, blank=True, default="") board_council = models.CharField(_("Board council"), max_length=1000, blank=True, default="") - logo = models.FileField(_("Logo"), max_length=300, storage=select_public_storage, blank=True, default="") + logo = models.FileField( + _("Logo"), + max_length=300, + storage=select_public_storage, + blank=True, + default="", + ) last_balance_sheet = models.FileField( _("First page of last balance sheet for %(CURRENT_EDITION_YEAR)s") % {"CURRENT_EDITION_YEAR": str(settings.CURRENT_EDITION_YEAR - 1)}, @@ -281,6 +301,7 @@ class Organization(StatusModel, TimeStampedModel): default="", max_length=300, help_text=REPORTS_HELP_TEXT, + validators=[file_validator], ) report_2022 = models.FileField( _("Yearly report 2022"), @@ -288,6 +309,7 @@ class Organization(StatusModel, TimeStampedModel): default="", max_length=300, help_text=REPORTS_HELP_TEXT, + validators=[file_validator], ) report_2021 = models.FileField( _("Yearly report 2021"), @@ -295,6 +317,7 @@ class Organization(StatusModel, TimeStampedModel): default="", max_length=300, help_text=REPORTS_HELP_TEXT, + validators=[file_validator], ) statement_discrimination = models.FileField( @@ -303,6 +326,7 @@ class Organization(StatusModel, TimeStampedModel): default="", max_length=300, help_text="Declarație pe proprie răspundere prin care declară că nu realizează activități sau susține cauze de natură politică sau care discriminează pe considerente legate de etnie, rasă, sex, orientare sexuală, religie, capacități fizice sau psihice sau de apartenența la una sau mai multe categorii sociale sau economice.", + validators=[file_validator], ) statement_political = models.FileField( _("Non-political statement"), @@ -310,6 +334,7 @@ class Organization(StatusModel, TimeStampedModel): default="", max_length=300, help_text="Declarație pe propria răspundere prin care declar că ONG-ul nu are între membrii conducerii organizației (Președinte sau Consiliul Director) membri ai conducerii unui partid politic sau persoane care au fost alese într-o funcție publică.", + validators=[file_validator], ) fiscal_certificate_anaf = models.FileField( @@ -318,6 +343,7 @@ class Organization(StatusModel, TimeStampedModel): default="", max_length=300, help_text="Certificat fiscal emis de ANAF", + validators=[file_validator], ) fiscal_certificate_local = models.FileField( _("Fiscal certificate local"), @@ -325,6 +351,7 @@ class Organization(StatusModel, TimeStampedModel): default="", max_length=300, help_text="Certificat fiscal emis de Direcția de Impozite și Taxe Locale", + validators=[file_validator], ) accept_terms_and_conditions = models.BooleanField(_("Accepted Terms and Conditions"), default=False) @@ -573,7 +600,12 @@ class Candidate(StatusModel, TimeStampedModel): help_text=_("The role of the designated person in the organization."), ) photo = models.ImageField( - _("Candidate photo"), max_length=300, storage=select_public_storage, blank=True, default="" + _("Candidate photo"), + max_length=300, + storage=select_public_storage, + blank=True, + default="", + validators=[file_validator], ) # files expected in different cases @@ -587,6 +619,7 @@ class Candidate(StatusModel, TimeStampedModel): "of the leadership of a political party, has not been elected to a public office " "and is not a dignitary of the Romanian state." ), + validators=[file_validator], ) mandate = models.FileField( _("Mandate"), @@ -597,6 +630,7 @@ class Candidate(StatusModel, TimeStampedModel): "Mandate from the organization (signed in original + electronic) " "with the highlighting of the domain for which it is running" ), + validators=[file_validator], ) letter_of_intent = models.FileField( _("Letter of intent"), @@ -604,6 +638,7 @@ class Candidate(StatusModel, TimeStampedModel): blank=True, max_length=300, help_text=_("Letter of intent (with the mention of the domain to be represented in the CES)"), + validators=[file_validator], ) cv = models.FileField( _("CV"), @@ -611,6 +646,7 @@ class Candidate(StatusModel, TimeStampedModel): blank=True, max_length=300, help_text=_("Europass format CV"), + validators=[file_validator], ) declaration_of_interests = models.FileField( _("Declaration of interests"), @@ -618,6 +654,7 @@ class Candidate(StatusModel, TimeStampedModel): blank=True, max_length=300, help_text=_("Official format Declaration of interests"), + validators=[file_validator], ) fiscal_record = models.FileField( _("Fiscal record"), @@ -625,6 +662,7 @@ class Candidate(StatusModel, TimeStampedModel): blank=True, max_length=300, help_text=_("Fiscal record, valid at the time of submitting the candidacy"), + validators=[file_validator], ) criminal_record = models.FileField( _("Criminal record"), @@ -632,6 +670,7 @@ class Candidate(StatusModel, TimeStampedModel): blank=True, max_length=300, help_text=_("(Optional) Criminal record, valid at the time of submitting the candidacy"), + validators=[file_validator], ) is_proposed = models.BooleanField(_("Is proposed?"), default=False) diff --git a/backend/locale/en/LC_MESSAGES/django.po b/backend/locale/en/LC_MESSAGES/django.po index 30e92ae1..fc476795 100644 --- a/backend/locale/en/LC_MESSAGES/django.po +++ b/backend/locale/en/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-29 16:52+0200\n" +"POT-Creation-Date: 2024-10-29 17:00+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -33,7 +33,7 @@ msgstr "" msgid "Important dates" msgstr "" -#: accounts/admin.py:119 hub/models.py:341 +#: accounts/admin.py:119 hub/models.py:368 msgid "Organization" msgstr "" @@ -574,299 +574,304 @@ msgstr "" msgid "Uploaded file is not a CSV file" msgstr "" -#: hub/models.py:83 +#: hub/models.py:32 +#, python-format +msgid "The file size is %d %s but it must be under %d %s" +msgstr "" + +#: hub/models.py:97 msgid "Active" msgstr "" -#: hub/models.py:84 +#: hub/models.py:98 msgid "Inactive" msgstr "" -#: hub/models.py:88 +#: hub/models.py:102 msgid "Enable organization registration" msgstr "" -#: hub/models.py:89 +#: hub/models.py:103 msgid "Enable organization approvals" msgstr "" -#: hub/models.py:90 +#: hub/models.py:104 msgid "Enable candidate registration" msgstr "" -#: hub/models.py:91 +#: hub/models.py:105 msgid "Enable candidate supporting" msgstr "" -#: hub/models.py:92 +#: hub/models.py:106 msgid "Enable candidate voting" msgstr "" -#: hub/models.py:93 +#: hub/models.py:107 msgid "Enable candidate confirmation" msgstr "" -#: hub/models.py:94 +#: hub/models.py:108 msgid "Enable the display of results" msgstr "" -#: hub/models.py:97 +#: hub/models.py:111 msgid "Voting round with just one domain (some restrictions will apply)" msgstr "" -#: hub/models.py:98 +#: hub/models.py:112 msgid "" "Enable global support (the support of at least 10 organizations is required)" msgstr "" -#: hub/models.py:99 +#: hub/models.py:113 msgid "Enable the voting domain restriction for an organization" msgstr "" -#: hub/models.py:117 +#: hub/models.py:131 msgid "Flag" msgstr "" -#: hub/models.py:121 +#: hub/models.py:135 msgid "Feature flag" msgstr "" -#: hub/models.py:122 +#: hub/models.py:136 msgid "Feature flags" msgstr "" -#: hub/models.py:139 +#: hub/models.py:153 msgid "Title" msgstr "" -#: hub/models.py:141 +#: hub/models.py:155 msgid "Author" msgstr "" -#: hub/models.py:142 +#: hub/models.py:156 msgid "Content preview" msgstr "" -#: hub/models.py:144 +#: hub/models.py:158 msgid "Content" msgstr "" -#: hub/models.py:146 +#: hub/models.py:160 msgid "Is visible?" msgstr "" -#: hub/models.py:147 +#: hub/models.py:161 msgid "Date published" msgstr "" -#: hub/models.py:150 +#: hub/models.py:164 msgid "Blog post" msgstr "" -#: hub/models.py:151 +#: hub/models.py:165 msgid "Blog posts" msgstr "" -#: hub/models.py:163 hub/templates/hub/home.html:289 +#: hub/models.py:177 hub/templates/hub/home.html:289 #: hub/templates/hub/home.html:290 msgid "Name" msgstr "" -#: hub/models.py:164 +#: hub/models.py:178 msgid "Description" msgstr "" -#: hub/models.py:166 +#: hub/models.py:180 msgid "Number of seats" msgstr "" -#: hub/models.py:172 hub/models.py:550 +#: hub/models.py:186 hub/models.py:577 msgid "Domain" msgstr "" -#: hub/models.py:173 +#: hub/models.py:187 msgid "Domains" msgstr "" -#: hub/models.py:194 hub/models.py:199 hub/models.py:245 +#: hub/models.py:208 hub/models.py:213 hub/models.py:259 msgid "City" msgstr "" -#: hub/models.py:195 hub/models.py:244 +#: hub/models.py:209 hub/models.py:258 msgid "County" msgstr "" -#: hub/models.py:196 +#: hub/models.py:210 msgid "Is county residence" msgstr "" -#: hub/models.py:200 +#: hub/models.py:214 msgid "Cities" msgstr "" -#: hub/models.py:220 +#: hub/models.py:234 msgid "Draft" msgstr "" -#: hub/models.py:221 +#: hub/models.py:235 msgid "Pending approval" msgstr "" -#: hub/models.py:222 +#: hub/models.py:236 msgid "NGO Hub accepted" msgstr "" -#: hub/models.py:223 hub/models.py:530 +#: hub/models.py:237 hub/models.py:557 msgid "Accepted" msgstr "" -#: hub/models.py:224 hub/models.py:532 +#: hub/models.py:238 hub/models.py:559 msgid "Rejected" msgstr "" -#: hub/models.py:226 hub/models.py:534 +#: hub/models.py:240 hub/models.py:561 msgid "Status" msgstr "" -#: hub/models.py:228 +#: hub/models.py:242 msgid "NGO Hub linked organization ID" msgstr "" -#: hub/models.py:232 +#: hub/models.py:246 msgid "Voting domain" msgstr "" -#: hub/models.py:238 +#: hub/models.py:252 msgid "" "The domain in which the organization can vote, support, and propose " "candidates – once set, the field can only be modified by the platform's " "administrators." msgstr "" -#: hub/models.py:243 +#: hub/models.py:257 msgid "NGO Name" msgstr "" -#: hub/models.py:246 +#: hub/models.py:260 msgid "Address" msgstr "" -#: hub/models.py:247 +#: hub/models.py:261 msgid "Registration number" msgstr "" -#: hub/models.py:249 +#: hub/models.py:263 msgid "Organization Email" msgstr "" -#: hub/models.py:250 +#: hub/models.py:264 msgid "Organization Phone" msgstr "" -#: hub/models.py:251 +#: hub/models.py:265 msgid "Short Description" msgstr "" -#: hub/models.py:253 +#: hub/models.py:267 msgid "Legal Representative Name" msgstr "" -#: hub/models.py:254 +#: hub/models.py:268 msgid "Legal Representative Email" msgstr "" -#: hub/models.py:256 +#: hub/models.py:270 msgid "Legal Representative Phone" msgstr "" -#: hub/models.py:260 +#: hub/models.py:274 msgid "Board council" msgstr "" -#: hub/models.py:261 +#: hub/models.py:277 msgid "Logo" msgstr "" -#: hub/models.py:264 +#: hub/models.py:284 #, python-format msgid "First page of last balance sheet for %(CURRENT_EDITION_YEAR)s" msgstr "" -#: hub/models.py:271 hub/templates/hub/partials/organization_documents.html:16 +#: hub/models.py:291 hub/templates/hub/partials/organization_documents.html:16 msgid "NGO Statute" msgstr "" -#: hub/models.py:279 hub/templates/hub/partials/organization_documents.html:31 +#: hub/models.py:299 hub/templates/hub/partials/organization_documents.html:31 msgid "Yearly report 2023" msgstr "" -#: hub/models.py:286 hub/templates/hub/partials/organization_documents.html:36 +#: hub/models.py:307 hub/templates/hub/partials/organization_documents.html:36 msgid "Yearly report 2022" msgstr "" -#: hub/models.py:293 hub/templates/hub/partials/organization_documents.html:41 +#: hub/models.py:315 hub/templates/hub/partials/organization_documents.html:41 msgid "Yearly report 2021" msgstr "" -#: hub/models.py:301 +#: hub/models.py:324 msgid "Non-discrimination statement" msgstr "" -#: hub/models.py:308 +#: hub/models.py:332 msgid "Non-political statement" msgstr "" -#: hub/models.py:316 hub/templates/hub/partials/organization_documents.html:21 +#: hub/models.py:341 hub/templates/hub/partials/organization_documents.html:21 msgid "Fiscal certificate ANAF" msgstr "" -#: hub/models.py:323 hub/templates/hub/partials/organization_documents.html:26 +#: hub/models.py:349 hub/templates/hub/partials/organization_documents.html:26 msgid "Fiscal certificate local" msgstr "" -#: hub/models.py:330 +#: hub/models.py:357 msgid "Accepted Terms and Conditions" msgstr "" -#: hub/models.py:332 +#: hub/models.py:359 msgid "Rejection message" msgstr "" -#: hub/models.py:334 +#: hub/models.py:361 msgid "Filename cache" msgstr "" -#: hub/models.py:336 hub/models.py:337 +#: hub/models.py:363 hub/models.py:364 msgid "Last NGO Hub update" msgstr "" -#: hub/models.py:340 hub/templates/hub/header.html:60 +#: hub/models.py:367 hub/templates/hub/header.html:60 msgid "Organizations" msgstr "" -#: hub/models.py:529 +#: hub/models.py:556 msgid "Pending" msgstr "" -#: hub/models.py:531 +#: hub/models.py:558 msgid "Confirmed" msgstr "" -#: hub/models.py:544 +#: hub/models.py:571 msgid "" "If this is set, the `org` field will be unset and the candidate is removed " "as the official proposal of the organization." msgstr "" -#: hub/models.py:555 +#: hub/models.py:582 msgid "The domain in which the candidate is running." msgstr "" -#: hub/models.py:559 hub/templates/hub/candidate/detail.html:115 +#: hub/models.py:586 hub/templates/hub/candidate/detail.html:115 msgid "Representative name" msgstr "" -#: hub/models.py:563 +#: hub/models.py:590 msgid "" "The name of the designated person who will represent the organization in the " "Electoral Commission in case of a favorable response.The designated person " @@ -874,119 +879,119 @@ msgid "" "structures (member of the Board of Directors, Executive Director, etc.)." msgstr "" -#: hub/models.py:570 +#: hub/models.py:597 msgid "Representative role in organization" msgstr "" -#: hub/models.py:573 +#: hub/models.py:600 msgid "The role of the designated person in the organization." msgstr "" -#: hub/models.py:576 +#: hub/models.py:603 msgid "Candidate photo" msgstr "" -#: hub/models.py:581 hub/templates/hub/candidate/detail.html:119 +#: hub/models.py:613 hub/templates/hub/candidate/detail.html:119 msgid "Representative statement" msgstr "Candidate statement" -#: hub/models.py:586 +#: hub/models.py:618 msgid "" "Declaration of the designated representative stating that he/she is not a " "member of the leadership of a political party, has not been elected to a " "public office and is not a dignitary of the Romanian state." msgstr "" -#: hub/models.py:592 hub/templates/hub/candidate/detail.html:124 +#: hub/models.py:625 hub/templates/hub/candidate/detail.html:124 msgid "Mandate" msgstr "" -#: hub/models.py:597 +#: hub/models.py:630 msgid "" "Mandate from the organization (signed in original + electronic) with the " "highlighting of the domain for which it is running" msgstr "" -#: hub/models.py:602 hub/templates/hub/candidate/detail.html:129 +#: hub/models.py:636 hub/templates/hub/candidate/detail.html:129 msgid "Letter of intent" msgstr "" -#: hub/models.py:606 +#: hub/models.py:640 msgid "" "Letter of intent (with the mention of the domain to be represented in the " "CES)" msgstr "" -#: hub/models.py:609 hub/templates/hub/candidate/detail.html:134 +#: hub/models.py:644 hub/templates/hub/candidate/detail.html:134 msgid "CV" msgstr "" -#: hub/models.py:613 +#: hub/models.py:648 msgid "Europass format CV" msgstr "" -#: hub/models.py:616 hub/templates/hub/candidate/detail.html:139 +#: hub/models.py:652 hub/templates/hub/candidate/detail.html:139 msgid "Declaration of interests" msgstr "" -#: hub/models.py:620 +#: hub/models.py:656 msgid "Official format Declaration of interests" msgstr "" -#: hub/models.py:623 hub/templates/hub/candidate/detail.html:144 +#: hub/models.py:660 hub/templates/hub/candidate/detail.html:144 msgid "Fiscal record" msgstr "" -#: hub/models.py:627 +#: hub/models.py:664 msgid "Fiscal record, valid at the time of submitting the candidacy" msgstr "" -#: hub/models.py:630 hub/templates/hub/candidate/detail.html:149 +#: hub/models.py:668 hub/templates/hub/candidate/detail.html:149 msgid "Criminal record" msgstr "" -#: hub/models.py:634 +#: hub/models.py:672 msgid "" "(Optional) Criminal record, valid at the time of submitting the candidacy" msgstr "" -#: hub/models.py:637 +#: hub/models.py:676 msgid "Is proposed?" msgstr "" -#: hub/models.py:643 +#: hub/models.py:682 msgid "Candidates" msgstr "" -#: hub/models.py:644 +#: hub/models.py:683 msgid "Candidate" msgstr "" -#: hub/models.py:704 +#: hub/models.py:743 msgid "Cannot update candidate after votes have been cast." msgstr "" -#: hub/models.py:734 +#: hub/models.py:773 msgid "Candidate votes" msgstr "" -#: hub/models.py:735 +#: hub/models.py:774 msgid "Candidate vote" msgstr "" -#: hub/models.py:758 +#: hub/models.py:797 msgid "Canditate supporters" msgstr "" -#: hub/models.py:759 +#: hub/models.py:798 msgid "Candidate supporter" msgstr "" -#: hub/models.py:773 +#: hub/models.py:812 msgid "Candidate confirmations" msgstr "" -#: hub/models.py:774 +#: hub/models.py:813 msgid "Candidate confirmation" msgstr "" diff --git a/backend/locale/ro/LC_MESSAGES/django.po b/backend/locale/ro/LC_MESSAGES/django.po index 48f50baf..0cb8397a 100644 --- a/backend/locale/ro/LC_MESSAGES/django.po +++ b/backend/locale/ro/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-29 16:52+0200\n" +"POT-Creation-Date: 2024-10-29 17:00+0200\n" "PO-Revision-Date: 2020-04-23 17:54+0300\n" "Last-Translator: \n" "Language-Team: \n" @@ -35,7 +35,7 @@ msgstr "Permisiuni" msgid "Important dates" msgstr "Date importante" -#: accounts/admin.py:119 hub/models.py:341 +#: accounts/admin.py:119 hub/models.py:368 msgid "Organization" msgstr "Organizație" @@ -594,171 +594,176 @@ msgstr "Fișier CSV" msgid "Uploaded file is not a CSV file" msgstr "Fișierul încărcat nu e de tip CSV" -#: hub/models.py:83 +#: hub/models.py:32 +#, python-format +msgid "The file size is %d %s but it must be under %d %s" +msgstr "Fișierul are %d %s dar trebuie să fie sub %d %s" + +#: hub/models.py:97 msgid "Active" msgstr "Activ" -#: hub/models.py:84 +#: hub/models.py:98 msgid "Inactive" msgstr "Inactiv" -#: hub/models.py:88 +#: hub/models.py:102 msgid "Enable organization registration" msgstr "Activează înregistrare organizație" -#: hub/models.py:89 +#: hub/models.py:103 msgid "Enable organization approvals" msgstr "Activează aprobare organizație" -#: hub/models.py:90 +#: hub/models.py:104 msgid "Enable candidate registration" msgstr "Activează înregistrare candidatură" -#: hub/models.py:91 +#: hub/models.py:105 msgid "Enable candidate supporting" msgstr "Activează susținere candidatură" -#: hub/models.py:92 +#: hub/models.py:106 msgid "Enable candidate voting" msgstr "Activează votare candidatură" -#: hub/models.py:93 +#: hub/models.py:107 msgid "Enable candidate confirmation" msgstr "Activează confirmare candidatură" -#: hub/models.py:94 +#: hub/models.py:108 msgid "Enable the display of results" msgstr "Activează afișarea rezultatelor" -#: hub/models.py:97 +#: hub/models.py:111 msgid "Voting round with just one domain (some restrictions will apply)" msgstr "Rundă de vot cu un singur domeniu (vor fi aplicate unele restricții)" -#: hub/models.py:98 +#: hub/models.py:112 msgid "" "Enable global support (the support of at least 10 organizations is required)" msgstr "" "Activează susținere globală (este necesară susținerea a cel puțin 10 " "organizații)" -#: hub/models.py:99 +#: hub/models.py:113 msgid "Enable the voting domain restriction for an organization" msgstr "Activează restricția domeniului de vot pentru o organizație" -#: hub/models.py:117 +#: hub/models.py:131 msgid "Flag" msgstr "Acțiune" -#: hub/models.py:121 +#: hub/models.py:135 msgid "Feature flag" msgstr "Acțiune etapă" -#: hub/models.py:122 +#: hub/models.py:136 msgid "Feature flags" msgstr "Acțiuni etape" -#: hub/models.py:139 +#: hub/models.py:153 msgid "Title" msgstr "Titlu" -#: hub/models.py:141 +#: hub/models.py:155 msgid "Author" msgstr "Autor" -#: hub/models.py:142 +#: hub/models.py:156 msgid "Content preview" msgstr "Sumar conținut" -#: hub/models.py:144 +#: hub/models.py:158 msgid "Content" msgstr "Conținut" -#: hub/models.py:146 +#: hub/models.py:160 msgid "Is visible?" msgstr "Este vizibil?" -#: hub/models.py:147 +#: hub/models.py:161 msgid "Date published" msgstr "Dată publicare" -#: hub/models.py:150 +#: hub/models.py:164 msgid "Blog post" msgstr "Articol blog" -#: hub/models.py:151 +#: hub/models.py:165 msgid "Blog posts" msgstr "Articole blog" -#: hub/models.py:163 hub/templates/hub/home.html:289 +#: hub/models.py:177 hub/templates/hub/home.html:289 #: hub/templates/hub/home.html:290 msgid "Name" msgstr "Nume" -#: hub/models.py:164 +#: hub/models.py:178 msgid "Description" msgstr "Descriere" -#: hub/models.py:166 +#: hub/models.py:180 msgid "Number of seats" msgstr "Numărul de fotolii" -#: hub/models.py:172 hub/models.py:550 +#: hub/models.py:186 hub/models.py:577 msgid "Domain" msgstr "Domeniu" -#: hub/models.py:173 +#: hub/models.py:187 msgid "Domains" msgstr "Domenii" -#: hub/models.py:194 hub/models.py:199 hub/models.py:245 +#: hub/models.py:208 hub/models.py:213 hub/models.py:259 msgid "City" msgstr "Oraș" -#: hub/models.py:195 hub/models.py:244 +#: hub/models.py:209 hub/models.py:258 msgid "County" msgstr "Județ" -#: hub/models.py:196 +#: hub/models.py:210 msgid "Is county residence" msgstr "E reședință de județ" -#: hub/models.py:200 +#: hub/models.py:214 msgid "Cities" msgstr "Orașe" -#: hub/models.py:220 +#: hub/models.py:234 msgid "Draft" msgstr "Schiță" -#: hub/models.py:221 +#: hub/models.py:235 msgid "Pending approval" msgstr "Așteaptă aprobare" -#: hub/models.py:222 +#: hub/models.py:236 msgid "NGO Hub accepted" msgstr "Acceptat din NGO Hub" -#: hub/models.py:223 hub/models.py:530 +#: hub/models.py:237 hub/models.py:557 msgid "Accepted" msgstr "Acceptat" -#: hub/models.py:224 hub/models.py:532 +#: hub/models.py:238 hub/models.py:559 msgid "Rejected" msgstr "Respins" -#: hub/models.py:226 hub/models.py:534 +#: hub/models.py:240 hub/models.py:561 msgid "Status" msgstr "Stare" -#: hub/models.py:228 +#: hub/models.py:242 msgid "NGO Hub linked organization ID" msgstr "ID organizație în NGO Hub" -#: hub/models.py:232 +#: hub/models.py:246 msgid "Voting domain" msgstr "Domeniul de votare" -#: hub/models.py:238 +#: hub/models.py:252 msgid "" "The domain in which the organization can vote, support, and propose " "candidates – once set, the field can only be modified by the platform's " @@ -767,120 +772,120 @@ msgstr "" "Domeniul în care organizația poate vota, susține și propune candidați - " "odată setat, câmpul poate fi modificat doar de administratorii platformei." -#: hub/models.py:243 +#: hub/models.py:257 msgid "NGO Name" msgstr "Nume organizație" -#: hub/models.py:246 +#: hub/models.py:260 msgid "Address" msgstr "Adresă" -#: hub/models.py:247 +#: hub/models.py:261 msgid "Registration number" msgstr "" "Număr de înregistrare în Registrul Național al ONG-urilor (de forma 11111/" "A/2016)" -#: hub/models.py:249 +#: hub/models.py:263 msgid "Organization Email" msgstr "Adresă de email organizație" -#: hub/models.py:250 +#: hub/models.py:264 msgid "Organization Phone" msgstr "Telefon organizație (opțional)" -#: hub/models.py:251 +#: hub/models.py:265 msgid "Short Description" msgstr "Scurtă descriere (opțional)" -#: hub/models.py:253 +#: hub/models.py:267 msgid "Legal Representative Name" msgstr "Nume reprezentant legal" -#: hub/models.py:254 +#: hub/models.py:268 msgid "Legal Representative Email" msgstr "Adresă de email reprezentant legal" -#: hub/models.py:256 +#: hub/models.py:270 msgid "Legal Representative Phone" msgstr "Telefon reprezentant legal (opțional)" -#: hub/models.py:260 +#: hub/models.py:274 msgid "Board council" msgstr "" "Consiliu Director (adaugă numele complet al fiecărui membru, separate prin " "virgulă)" -#: hub/models.py:261 +#: hub/models.py:277 msgid "Logo" msgstr "Siglă" -#: hub/models.py:264 +#: hub/models.py:284 #, python-format msgid "First page of last balance sheet for %(CURRENT_EDITION_YEAR)s" msgstr "Prima pagină a bilanțului contabil pe anul %(CURRENT_EDITION_YEAR)s" -#: hub/models.py:271 hub/templates/hub/partials/organization_documents.html:16 +#: hub/models.py:291 hub/templates/hub/partials/organization_documents.html:16 msgid "NGO Statute" msgstr "Statutul organizației" -#: hub/models.py:279 hub/templates/hub/partials/organization_documents.html:31 +#: hub/models.py:299 hub/templates/hub/partials/organization_documents.html:31 msgid "Yearly report 2023" msgstr "Raport anual 2023" -#: hub/models.py:286 hub/templates/hub/partials/organization_documents.html:36 +#: hub/models.py:307 hub/templates/hub/partials/organization_documents.html:36 msgid "Yearly report 2022" msgstr "Raport anual 2022" -#: hub/models.py:293 hub/templates/hub/partials/organization_documents.html:41 +#: hub/models.py:315 hub/templates/hub/partials/organization_documents.html:41 msgid "Yearly report 2021" msgstr "Raport anual 2021" -#: hub/models.py:301 +#: hub/models.py:324 msgid "Non-discrimination statement" msgstr "Declarație nediscriminare" -#: hub/models.py:308 +#: hub/models.py:332 msgid "Non-political statement" msgstr "Declarație neapartenență politică" -#: hub/models.py:316 hub/templates/hub/partials/organization_documents.html:21 +#: hub/models.py:341 hub/templates/hub/partials/organization_documents.html:21 msgid "Fiscal certificate ANAF" msgstr "Certificat fiscal emis de ANAF" -#: hub/models.py:323 hub/templates/hub/partials/organization_documents.html:26 +#: hub/models.py:349 hub/templates/hub/partials/organization_documents.html:26 msgid "Fiscal certificate local" msgstr "Certificat fiscal emis de Direcția de Impozite și Taxe Locale" -#: hub/models.py:330 +#: hub/models.py:357 msgid "Accepted Terms and Conditions" msgstr "A acceptat termenii și condițiile" -#: hub/models.py:332 +#: hub/models.py:359 msgid "Rejection message" msgstr "Motiv respingere" -#: hub/models.py:334 +#: hub/models.py:361 msgid "Filename cache" msgstr "Cache nume fișier" -#: hub/models.py:336 hub/models.py:337 +#: hub/models.py:363 hub/models.py:364 msgid "Last NGO Hub update" msgstr "Ultima actualizare NGO Hub" -#: hub/models.py:340 hub/templates/hub/header.html:60 +#: hub/models.py:367 hub/templates/hub/header.html:60 msgid "Organizations" msgstr "Organizații" -#: hub/models.py:529 +#: hub/models.py:556 msgid "Pending" msgstr "În așteptare" -#: hub/models.py:531 +#: hub/models.py:558 msgid "Confirmed" msgstr "Confirmat" -#: hub/models.py:544 +#: hub/models.py:571 msgid "" "If this is set, the `org` field will be unset and the candidate is removed " "as the official proposal of the organization." @@ -888,15 +893,15 @@ msgstr "" "Dacă este setat, câmpul `org` va fi șters și candidatul va fi eliminat ca " "propunere oficială a organizației." -#: hub/models.py:555 +#: hub/models.py:582 msgid "The domain in which the candidate is running." msgstr "Domeniul pentru care candidează candidatul." -#: hub/models.py:559 hub/templates/hub/candidate/detail.html:115 +#: hub/models.py:586 hub/templates/hub/candidate/detail.html:115 msgid "Representative name" msgstr "Nume reprezentant" -#: hub/models.py:563 +#: hub/models.py:590 msgid "" "The name of the designated person who will represent the organization in the " "Electoral Commission in case of a favorable response.The designated person " @@ -908,23 +913,23 @@ msgstr "" "cadrul organizației și parte din structurile de conducere ale acesteia " "(membru în Consiliul Director, Director Executiv etc)" -#: hub/models.py:570 +#: hub/models.py:597 msgid "Representative role in organization" msgstr "Funcția reprezentantului în organizație" -#: hub/models.py:573 +#: hub/models.py:600 msgid "The role of the designated person in the organization." msgstr "Funcția în organizației a persoanei desemnate" -#: hub/models.py:576 +#: hub/models.py:603 msgid "Candidate photo" msgstr "Fotografia candidatului" -#: hub/models.py:581 hub/templates/hub/candidate/detail.html:119 +#: hub/models.py:613 hub/templates/hub/candidate/detail.html:119 msgid "Representative statement" msgstr "Declarație candidat" -#: hub/models.py:586 +#: hub/models.py:618 msgid "" "Declaration of the designated representative stating that he/she is not a " "member of the leadership of a political party, has not been elected to a " @@ -934,11 +939,11 @@ msgstr "" "declară că nu este membru al conducerii unui partid politic, nu a fost ales " "într-o funcție publică și nu este demnitar al statului român." -#: hub/models.py:592 hub/templates/hub/candidate/detail.html:124 +#: hub/models.py:625 hub/templates/hub/candidate/detail.html:124 msgid "Mandate" msgstr "Mandat" -#: hub/models.py:597 +#: hub/models.py:630 msgid "" "Mandate from the organization (signed in original + electronic) with the " "highlighting of the domain for which it is running" @@ -946,11 +951,11 @@ msgstr "" "Mandat din partea organizației (semnat în original + electronică) cu " "sublinierea domeniului pentru care candidează" -#: hub/models.py:602 hub/templates/hub/candidate/detail.html:129 +#: hub/models.py:636 hub/templates/hub/candidate/detail.html:129 msgid "Letter of intent" msgstr "Scrisoare de intenție" -#: hub/models.py:606 +#: hub/models.py:640 msgid "" "Letter of intent (with the mention of the domain to be represented in the " "CES)" @@ -958,76 +963,76 @@ msgstr "" "Scrisoare de intenție (cu menționarea domeniului pe care dorește să îl " "reprezinte în CES)" -#: hub/models.py:609 hub/templates/hub/candidate/detail.html:134 +#: hub/models.py:644 hub/templates/hub/candidate/detail.html:134 msgid "CV" msgstr "CV" -#: hub/models.py:613 +#: hub/models.py:648 msgid "Europass format CV" msgstr "CV în format Europass" -#: hub/models.py:616 hub/templates/hub/candidate/detail.html:139 +#: hub/models.py:652 hub/templates/hub/candidate/detail.html:139 msgid "Declaration of interests" msgstr "Declarație de interese" -#: hub/models.py:620 +#: hub/models.py:656 msgid "Official format Declaration of interests" msgstr "Declarație de interese în format oficial" -#: hub/models.py:623 hub/templates/hub/candidate/detail.html:144 +#: hub/models.py:660 hub/templates/hub/candidate/detail.html:144 msgid "Fiscal record" msgstr "Cazier fiscal" -#: hub/models.py:627 +#: hub/models.py:664 msgid "Fiscal record, valid at the time of submitting the candidacy" msgstr "Cazier fiscal, valabil la data depunerii candidaturii" -#: hub/models.py:630 hub/templates/hub/candidate/detail.html:149 +#: hub/models.py:668 hub/templates/hub/candidate/detail.html:149 msgid "Criminal record" msgstr "Cazier judiciar" -#: hub/models.py:634 +#: hub/models.py:672 msgid "" "(Optional) Criminal record, valid at the time of submitting the candidacy" msgstr "(Opțional) Cazier judiciar, valabil la data depunerii candidaturii" -#: hub/models.py:637 +#: hub/models.py:676 msgid "Is proposed?" msgstr "Este propus?" -#: hub/models.py:643 +#: hub/models.py:682 msgid "Candidates" msgstr "Candidaturi" -#: hub/models.py:644 +#: hub/models.py:683 msgid "Candidate" msgstr "Candidatură" -#: hub/models.py:704 +#: hub/models.py:743 msgid "Cannot update candidate after votes have been cast." msgstr "Nu se poate modifica candidatura după ce s-au înregistrat voturi." -#: hub/models.py:734 +#: hub/models.py:773 msgid "Candidate votes" msgstr "Voturi candidatură" -#: hub/models.py:735 +#: hub/models.py:774 msgid "Candidate vote" msgstr "Vot candidatură" -#: hub/models.py:758 +#: hub/models.py:797 msgid "Canditate supporters" msgstr "Susținători candidatură" -#: hub/models.py:759 +#: hub/models.py:798 msgid "Candidate supporter" msgstr "Susținător candidatură" -#: hub/models.py:773 +#: hub/models.py:812 msgid "Candidate confirmations" msgstr "Confirmări candidatură" -#: hub/models.py:774 +#: hub/models.py:813 msgid "Candidate confirmation" msgstr "Confirmare candidatură"