From 73e8e811416dcb5007ad9cc9d1632aaca95bf302 Mon Sep 17 00:00:00 2001 From: Chiara Mezzavilla <2512470+samurang87@users.noreply.github.com> Date: Mon, 30 Sep 2024 18:31:26 +0200 Subject: [PATCH 01/40] Relocated path() explanation to docs/ref/urls.txt to simplify tutorial 1. Co-authored-by: Natalia <124304+nessita@users.noreply.github.com> --- docs/intro/tutorial01.txt | 41 ++------------------------------------- docs/ref/urls.txt | 34 ++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 41 deletions(-) diff --git a/docs/intro/tutorial01.txt b/docs/intro/tutorial01.txt index 3f89220949..d45fa6bcb6 100644 --- a/docs/intro/tutorial01.txt +++ b/docs/intro/tutorial01.txt @@ -275,6 +275,8 @@ include the URLconf defined in ``polls.urls``. To do this, add an import for path("admin/", admin.site.urls), ] +The :func:`~django.urls.path` function expects at least two arguments: +``route`` and ``view``. The :func:`~django.urls.include` function allows referencing other URLconfs. Whenever Django encounters :func:`~django.urls.include`, it chops off whatever part of the URL matched up to that point and sends the remaining string to the @@ -307,45 +309,6 @@ text "*Hello, world. You're at the polls index.*", which you defined in the If you get an error page here, check that you're going to http://localhost:8000/polls/ and not http://localhost:8000/. -The :func:`~django.urls.path` function is passed four arguments, two required: -``route`` and ``view``, and two optional: ``kwargs``, and ``name``. -At this point, it's worth reviewing what these arguments are for. - -:func:`~django.urls.path` argument: ``route`` ---------------------------------------------- - -``route`` is a string that contains a URL pattern. When processing a request, -Django starts at the first pattern in ``urlpatterns`` and makes its way down -the list, comparing the requested URL against each pattern until it finds one -that matches. - -Patterns don't search GET and POST parameters, or the domain name. For example, -in a request to ``https://www.example.com/myapp/``, the URLconf will look for -``myapp/``. In a request to ``https://www.example.com/myapp/?page=3``, the -URLconf will also look for ``myapp/``. - -:func:`~django.urls.path` argument: ``view`` --------------------------------------------- - -When Django finds a matching pattern, it calls the specified view function with -an :class:`~django.http.HttpRequest` object as the first argument and any -"captured" values from the route as keyword arguments. We'll give an example -of this in a bit. - -:func:`~django.urls.path` argument: ``kwargs`` ----------------------------------------------- - -Arbitrary keyword arguments can be passed in a dictionary to the target view. We -aren't going to use this feature of Django in the tutorial. - -:func:`~django.urls.path` argument: ``name`` --------------------------------------------- - -Naming your URL lets you refer to it unambiguously from elsewhere in Django, -especially from within templates. This powerful feature allows you to make -global changes to the URL patterns of your project while only touching a single -file. - When you're comfortable with the basic request and response flow, read :doc:`part 2 of this tutorial ` to start working with the database. diff --git a/docs/ref/urls.txt b/docs/ref/urls.txt index 2ef873d348..95eb03f35a 100644 --- a/docs/ref/urls.txt +++ b/docs/ref/urls.txt @@ -25,6 +25,9 @@ Returns an element for inclusion in ``urlpatterns``. For example:: ..., ] +``route`` +--------- + The ``route`` argument should be a string or :func:`~django.utils.translation.gettext_lazy()` (see :ref:`translating-urlpatterns`) that contains a URL pattern. The string @@ -33,16 +36,43 @@ URL and send it as a keyword argument to the view. The angle brackets may include a converter specification (like the ``int`` part of ````) which limits the characters matched and may also change the type of the variable passed to the view. For example, ```` matches a string -of decimal digits and converts the value to an ``int``. See +of decimal digits and converts the value to an ``int``. + +When processing a request, Django starts at the first pattern in +``urlpatterns`` and makes its way down the list, comparing the requested URL +against each pattern until it finds one that matches. See :ref:`how-django-processes-a-request` for more details. +Patterns don't match GET and POST parameters, or the domain name. For example, +in a request to ``https://www.example.com/myapp/``, the URLconf will look for +``myapp/``. In a request to ``https://www.example.com/myapp/?page=3``, the +URLconf will also look for ``myapp/``. + +``view`` +-------- + The ``view`` argument is a view function or the result of :meth:`~django.views.generic.base.View.as_view` for class-based views. It can -also be an :func:`django.urls.include`. +also be a :func:`django.urls.include`. + +When Django finds a matching pattern, it calls the specified view function with +an :class:`~django.http.HttpRequest` object as the first argument and any +"captured" values from the route as keyword arguments. + +``kwargs`` +---------- The ``kwargs`` argument allows you to pass additional arguments to the view function or method. See :ref:`views-extra-options` for an example. +``name`` +-------- + +Naming your URL lets you refer to it unambiguously from elsewhere in Django, +especially from within templates. This powerful feature allows you to make +global changes to the URL patterns of your project while only touching a single +file. + See :ref:`Naming URL patterns ` for why the ``name`` argument is useful. From 6765b6adf924c1bc8792a4a454d5a788c1abc98e Mon Sep 17 00:00:00 2001 From: Marc Gibbons <1726961+marcgibbons@users.noreply.github.com> Date: Mon, 30 Sep 2024 15:52:28 -0400 Subject: [PATCH 02/40] Fixed #35797 -- Removed debug context processor from default project template. --- django/conf/project_template/project_name/settings.py-tpl | 1 - docs/intro/tutorial07.txt | 1 - docs/ref/templates/api.txt | 1 - docs/releases/5.2.txt | 3 +++ tests/admin_views/tests.py | 2 -- tests/runtests.py | 1 - 6 files changed, 3 insertions(+), 6 deletions(-) diff --git a/django/conf/project_template/project_name/settings.py-tpl b/django/conf/project_template/project_name/settings.py-tpl index 3b6caab333..5631ec9a31 100644 --- a/django/conf/project_template/project_name/settings.py-tpl +++ b/django/conf/project_template/project_name/settings.py-tpl @@ -58,7 +58,6 @@ TEMPLATES = [ 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ - 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', diff --git a/docs/intro/tutorial07.txt b/docs/intro/tutorial07.txt index e0c87be898..60a5c43bb3 100644 --- a/docs/intro/tutorial07.txt +++ b/docs/intro/tutorial07.txt @@ -324,7 +324,6 @@ Open your settings file (:file:`mysite/settings.py`, remember) and add a "APP_DIRS": True, "OPTIONS": { "context_processors": [ - "django.template.context_processors.debug", "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", diff --git a/docs/ref/templates/api.txt b/docs/ref/templates/api.txt index a46717b8d7..8d5c66367d 100644 --- a/docs/ref/templates/api.txt +++ b/docs/ref/templates/api.txt @@ -660,7 +660,6 @@ settings file, the default template engine contains the following context processors:: [ - "django.template.context_processors.debug", "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", diff --git a/docs/releases/5.2.txt b/docs/releases/5.2.txt index 14ad32b706..c445e02694 100644 --- a/docs/releases/5.2.txt +++ b/docs/releases/5.2.txt @@ -328,6 +328,9 @@ Miscellaneous * ``HttpRequest.accepted_types`` is now sorted by the client's preference, based on the request's ``Accept`` header. +* The :func:`~django.template.context_processors.debug` context processor is no + longer included in the default project template. + .. _deprecated-features-5.2: Features deprecated in 5.2 diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index fc1bb86d85..16d76f5da2 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -1686,7 +1686,6 @@ class AdminViewBasicTest(AdminViewBasicTestCase): "APP_DIRS": True, "OPTIONS": { "context_processors": [ - "django.template.context_processors.debug", "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", @@ -7695,7 +7694,6 @@ class AdminDocsTest(TestCase): "APP_DIRS": True, "OPTIONS": { "context_processors": [ - "django.template.context_processors.debug", "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", diff --git a/tests/runtests.py b/tests/runtests.py index c5bb637d33..516da84768 100755 --- a/tests/runtests.py +++ b/tests/runtests.py @@ -221,7 +221,6 @@ def setup_collect_tests(start_at, start_after, test_labels=None): "APP_DIRS": True, "OPTIONS": { "context_processors": [ - "django.template.context_processors.debug", "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", From efc3b0c627f7e3cb4e337280ecd2483758dcb0a5 Mon Sep 17 00:00:00 2001 From: Aditya Chaudhary <113302312+userAdityaa@users.noreply.github.com> Date: Wed, 2 Oct 2024 21:45:21 +0530 Subject: [PATCH 03/40] Fixed #35670 -- Clarified the return value for LoginRequiredMiddleware's methods. --- docs/ref/middleware.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/ref/middleware.txt b/docs/ref/middleware.txt index 4aab186c8b..ded684b972 100644 --- a/docs/ref/middleware.txt +++ b/docs/ref/middleware.txt @@ -563,19 +563,19 @@ unauthenticated requests. .. method:: get_login_url() - Returns the URL that unauthenticated requests will be redirected to. If - defined, this returns the ``login_url`` set on the - :func:`~.django.contrib.auth.decorators.login_required` decorator. Defaults - to :setting:`settings.LOGIN_URL `. + Returns the URL that unauthenticated requests will be redirected to. This + result is either the ``login_url`` set on the + :func:`~django.contrib.auth.decorators.login_required` decorator (if not + ``None``), or :setting:`settings.LOGIN_URL `. .. method:: get_redirect_field_name() Returns the name of the query parameter that contains the URL the user - should be redirected to after a successful login. If defined, this returns + should be redirected to after a successful login. This result is either the ``redirect_field_name`` set on the - :func:`~.django.contrib.auth.decorators.login_required` decorator. Defaults - to :attr:`redirect_field_name`. If ``None`` is returned, a query parameter - won't be added. + :func:`~.django.contrib.auth.decorators.login_required` decorator (if not + ``None``), or :attr:`redirect_field_name`. If ``None`` is returned, a query + parameter won't be added. .. class:: RemoteUserMiddleware From 1feedc8ef8a34484cb5afe33f5c45b543b860210 Mon Sep 17 00:00:00 2001 From: nessita <124304+nessita@users.noreply.github.com> Date: Wed, 2 Oct 2024 14:21:10 -0300 Subject: [PATCH 04/40] Reindented attributes and methods for classes in docs/ref/middleware.txt. --- docs/ref/middleware.txt | 72 ++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/docs/ref/middleware.txt b/docs/ref/middleware.txt index ded684b972..b5534ce8f6 100644 --- a/docs/ref/middleware.txt +++ b/docs/ref/middleware.txt @@ -34,6 +34,12 @@ defines. See the :doc:`cache documentation `. .. class:: CommonMiddleware + .. attribute:: response_redirect_class + + Defaults to :class:`~django.http.HttpResponsePermanentRedirect`. Subclass + ``CommonMiddleware`` and override the attribute to customize the redirects + issued by the middleware. + Adds a few conveniences for perfectionists: * Forbids access to user agents in the :setting:`DISALLOWED_USER_AGENTS` @@ -75,12 +81,6 @@ Adds a few conveniences for perfectionists: * Sets the ``Content-Length`` header for non-streaming responses. -.. attribute:: CommonMiddleware.response_redirect_class - -Defaults to :class:`~django.http.HttpResponsePermanentRedirect`. Subclass -``CommonMiddleware`` and override the attribute to customize the redirects -issued by the middleware. - .. class:: BrokenLinkEmailsMiddleware * Sends broken link notification emails to :setting:`MANAGERS` (see @@ -164,16 +164,16 @@ Locale middleware .. class:: LocaleMiddleware + .. attribute:: LocaleMiddleware.response_redirect_class + + Defaults to :class:`~django.http.HttpResponseRedirect`. Subclass + ``LocaleMiddleware`` and override the attribute to customize the + redirects issued by the middleware. + Enables language selection based on data from the request. It customizes content for each user. See the :doc:`internationalization documentation `. -.. attribute:: LocaleMiddleware.response_redirect_class - -Defaults to :class:`~django.http.HttpResponseRedirect`. Subclass -``LocaleMiddleware`` and override the attribute to customize the redirects -issued by the middleware. - Message middleware ------------------ @@ -500,6 +500,29 @@ every incoming ``HttpRequest`` object. See :ref:`Authentication in web requests .. class:: LoginRequiredMiddleware + Subclass the middleware and override the following attributes and methods + to customize behavior for unauthenticated requests. + + .. attribute:: redirect_field_name + + Defaults to ``"next"``. + + .. method:: get_login_url() + + Returns the URL that unauthenticated requests will be redirected to. This + result is either the ``login_url`` set on the + :func:`~django.contrib.auth.decorators.login_required` decorator (if not + ``None``), or :setting:`settings.LOGIN_URL `. + + .. method:: get_redirect_field_name() + + Returns the name of the query parameter that contains the URL the user + should be redirected to after a successful login. This result is either + the ``redirect_field_name`` set on the + :func:`~.django.contrib.auth.decorators.login_required` decorator (if not + ``None``), or :attr:`redirect_field_name`. If ``None`` is returned, a query + parameter won't be added. + .. versionadded:: 5.1 Redirects all unauthenticated requests to a login page, except for views @@ -552,31 +575,6 @@ Customize the login URL or field name for authenticated views with the :ref:`enabled unauthenticated requests ` to your login view. -**Methods and Attributes** - -Subclass the middleware and override these to customize behavior for -unauthenticated requests. - -.. attribute:: redirect_field_name - - Defaults to ``"next"``. - -.. method:: get_login_url() - - Returns the URL that unauthenticated requests will be redirected to. This - result is either the ``login_url`` set on the - :func:`~django.contrib.auth.decorators.login_required` decorator (if not - ``None``), or :setting:`settings.LOGIN_URL `. - -.. method:: get_redirect_field_name() - - Returns the name of the query parameter that contains the URL the user - should be redirected to after a successful login. This result is either - the ``redirect_field_name`` set on the - :func:`~.django.contrib.auth.decorators.login_required` decorator (if not - ``None``), or :attr:`redirect_field_name`. If ``None`` is returned, a query - parameter won't be added. - .. class:: RemoteUserMiddleware Middleware for utilizing web server provided authentication. See From c334c1a8ff4579cdb1dd77cce8da747070ac9fc4 Mon Sep 17 00:00:00 2001 From: nessita <124304+nessita@users.noreply.github.com> Date: Thu, 3 Oct 2024 17:49:02 -0300 Subject: [PATCH 05/40] Bumped latest PostgreSQL to 17 in scheduled tests workflow. --- .github/workflows/schedule_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/schedule_tests.yml b/.github/workflows/schedule_tests.yml index 78b06ba5de..2cf62493c3 100644 --- a/.github/workflows/schedule_tests.yml +++ b/.github/workflows/schedule_tests.yml @@ -200,10 +200,10 @@ jobs: strategy: fail-fast: false matrix: - version: [16, 17rc1] + version: [16, 17] server_side_bindings: [0, 1] runs-on: ubuntu-latest - name: Newer PostgreSQL Versions + name: PostgreSQL Versions env: SERVER_SIDE_BINDING: ${{ matrix.server_side_bindings }} services: From d876be794f59fd37c8edc33ecde4577d820a9c75 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Mon, 7 Oct 2024 10:07:39 +0200 Subject: [PATCH 06/40] Fixed #35807 -- Mentioned async case for internal get/set urlconf helpers. --- django/urls/base.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/django/urls/base.py b/django/urls/base.py index 753779c75b..bb40ba2224 100644 --- a/django/urls/base.py +++ b/django/urls/base.py @@ -127,8 +127,9 @@ def clear_script_prefix(): def set_urlconf(urlconf_name): """ - Set the URLconf for the current thread (overriding the default one in - settings). If urlconf_name is None, revert back to the default. + Set the URLconf for the current thread or asyncio task (overriding the + default one in settings). If urlconf_name is None, revert back to the + default. """ if urlconf_name: _urlconfs.value = urlconf_name @@ -139,8 +140,8 @@ def set_urlconf(urlconf_name): def get_urlconf(default=None): """ - Return the root URLconf to use for the current thread if it has been - changed from the default one. + Return the root URLconf to use for the current thread or asyncio task if it + has been changed from the default one. """ return getattr(_urlconfs, "value", default) From 4cad317ff1f9a79d54c1d5b12f1ccbd260ca009f Mon Sep 17 00:00:00 2001 From: "aditya.chaudhary1558@gmail.com" Date: Wed, 2 Oct 2024 02:08:43 +0530 Subject: [PATCH 07/40] Fixed #35804 -- Removed unused rules for ul.tools from admin CSS. --- django/contrib/admin/static/admin/css/forms.css | 12 ------------ .../admin/static/admin/css/responsive_rtl.css | 1 - 2 files changed, 13 deletions(-) diff --git a/django/contrib/admin/static/admin/css/forms.css b/django/contrib/admin/static/admin/css/forms.css index 776a920e25..302d515751 100644 --- a/django/contrib/admin/static/admin/css/forms.css +++ b/django/contrib/admin/static/admin/css/forms.css @@ -445,17 +445,6 @@ body.popup .submit-row { _width: 700px; } -.inline-group ul.tools { - padding: 0; - margin: 0; - list-style: none; -} - -.inline-group ul.tools li { - display: inline; - padding: 0 5px; -} - .inline-group div.add-row, .inline-group .tabular tr.add-row td { color: var(--body-quiet-color); @@ -469,7 +458,6 @@ body.popup .submit-row { border-bottom: 1px solid var(--hairline-color); } -.inline-group ul.tools a.add, .inline-group div.add-row a, .inline-group .tabular tr.add-row td a { background: url(../img/icon-addlink.svg) 0 1px no-repeat; diff --git a/django/contrib/admin/static/admin/css/responsive_rtl.css b/django/contrib/admin/static/admin/css/responsive_rtl.css index 33b5784842..f7c90adb23 100644 --- a/django/contrib/admin/static/admin/css/responsive_rtl.css +++ b/django/contrib/admin/static/admin/css/responsive_rtl.css @@ -28,7 +28,6 @@ margin-left: 0; } - [dir="rtl"] .inline-group ul.tools a.add, [dir="rtl"] .inline-group div.add-row a, [dir="rtl"] .inline-group .tabular tr.add-row td a { padding: 8px 26px 8px 10px; From 50f89ae850f6b4e35819fe725a08c7e579bfd099 Mon Sep 17 00:00:00 2001 From: Jon Janzen Date: Sun, 31 Mar 2024 12:29:10 -0700 Subject: [PATCH 08/40] Fixed #35303 -- Implemented async auth backends and utils. --- django/contrib/auth/__init__.py | 172 +++++++++-- django/contrib/auth/backends.py | 111 +++++++ django/contrib/auth/base_user.py | 3 + django/contrib/auth/decorators.py | 2 +- django/contrib/auth/middleware.py | 85 +++++- django/contrib/auth/models.py | 134 ++++++++- docs/ref/contrib/auth.txt | 144 ++++++++- docs/releases/5.2.txt | 30 ++ docs/topics/auth/customizing.txt | 29 ++ tests/async/test_async_auth.py | 31 ++ tests/auth_tests/models/custom_user.py | 13 + tests/auth_tests/test_auth_backends.py | 324 +++++++++++++++++++++ tests/auth_tests/test_basic.py | 39 ++- tests/auth_tests/test_decorators.py | 6 +- tests/auth_tests/test_models.py | 41 ++- tests/auth_tests/test_remote_user.py | 180 +++++++++++- tests/deprecation/test_middleware_mixin.py | 2 - 17 files changed, 1285 insertions(+), 61 deletions(-) diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py index 3db1445d9e..689567ca6c 100644 --- a/django/contrib/auth/__init__.py +++ b/django/contrib/auth/__init__.py @@ -1,8 +1,6 @@ import inspect import re -from asgiref.sync import sync_to_async - from django.apps import apps as django_apps from django.conf import settings from django.core.exceptions import ImproperlyConfigured, PermissionDenied @@ -40,6 +38,39 @@ def get_backends(): return _get_backends(return_tuples=False) +def _get_compatible_backends(request, **credentials): + for backend, backend_path in _get_backends(return_tuples=True): + backend_signature = inspect.signature(backend.authenticate) + try: + backend_signature.bind(request, **credentials) + except TypeError: + # This backend doesn't accept these credentials as arguments. Try + # the next one. + continue + yield backend, backend_path + + +def _get_backend_from_user(user, backend=None): + try: + backend = backend or user.backend + except AttributeError: + backends = _get_backends(return_tuples=True) + if len(backends) == 1: + _, backend = backends[0] + else: + raise ValueError( + "You have multiple authentication backends configured and " + "therefore must provide the `backend` argument or set the " + "`backend` attribute on the user." + ) + else: + if not isinstance(backend, str): + raise TypeError( + "backend must be a dotted import path string (got %r)." % backend + ) + return backend + + @sensitive_variables("credentials") def _clean_credentials(credentials): """ @@ -62,19 +93,21 @@ def _get_user_session_key(request): return get_user_model()._meta.pk.to_python(request.session[SESSION_KEY]) +async def _aget_user_session_key(request): + # This value in the session is always serialized to a string, so we need + # to convert it back to Python whenever we access it. + session_key = await request.session.aget(SESSION_KEY) + if session_key is None: + raise KeyError() + return get_user_model()._meta.pk.to_python(session_key) + + @sensitive_variables("credentials") def authenticate(request=None, **credentials): """ If the given credentials are valid, return a User object. """ - for backend, backend_path in _get_backends(return_tuples=True): - backend_signature = inspect.signature(backend.authenticate) - try: - backend_signature.bind(request, **credentials) - except TypeError: - # This backend doesn't accept these credentials as arguments. Try - # the next one. - continue + for backend, backend_path in _get_compatible_backends(request, **credentials): try: user = backend.authenticate(request, **credentials) except PermissionDenied: @@ -96,7 +129,23 @@ def authenticate(request=None, **credentials): @sensitive_variables("credentials") async def aauthenticate(request=None, **credentials): """See authenticate().""" - return await sync_to_async(authenticate)(request, **credentials) + for backend, backend_path in _get_compatible_backends(request, **credentials): + try: + user = await backend.aauthenticate(request, **credentials) + except PermissionDenied: + # This backend says to stop in our tracks - this user should not be + # allowed in at all. + break + if user is None: + continue + # Annotate the user object with the path of the backend. + user.backend = backend_path + return user + + # The credentials supplied are invalid to all backends, fire signal. + await user_login_failed.asend( + sender=__name__, credentials=_clean_credentials(credentials), request=request + ) def login(request, user, backend=None): @@ -125,23 +174,7 @@ def login(request, user, backend=None): else: request.session.cycle_key() - try: - backend = backend or user.backend - except AttributeError: - backends = _get_backends(return_tuples=True) - if len(backends) == 1: - _, backend = backends[0] - else: - raise ValueError( - "You have multiple authentication backends configured and " - "therefore must provide the `backend` argument or set the " - "`backend` attribute on the user." - ) - else: - if not isinstance(backend, str): - raise TypeError( - "backend must be a dotted import path string (got %r)." % backend - ) + backend = _get_backend_from_user(user=user, backend=backend) request.session[SESSION_KEY] = user._meta.pk.value_to_string(user) request.session[BACKEND_SESSION_KEY] = backend @@ -154,7 +187,36 @@ def login(request, user, backend=None): async def alogin(request, user, backend=None): """See login().""" - return await sync_to_async(login)(request, user, backend) + session_auth_hash = "" + if user is None: + user = await request.auser() + if hasattr(user, "get_session_auth_hash"): + session_auth_hash = user.get_session_auth_hash() + + if await request.session.ahas_key(SESSION_KEY): + if await _aget_user_session_key(request) != user.pk or ( + session_auth_hash + and not constant_time_compare( + await request.session.aget(HASH_SESSION_KEY, ""), + session_auth_hash, + ) + ): + # To avoid reusing another user's session, create a new, empty + # session if the existing session corresponds to a different + # authenticated user. + await request.session.aflush() + else: + await request.session.acycle_key() + + backend = _get_backend_from_user(user=user, backend=backend) + + await request.session.aset(SESSION_KEY, user._meta.pk.value_to_string(user)) + await request.session.aset(BACKEND_SESSION_KEY, backend) + await request.session.aset(HASH_SESSION_KEY, session_auth_hash) + if hasattr(request, "user"): + request.user = user + rotate_token(request) + await user_logged_in.asend(sender=user.__class__, request=request, user=user) def logout(request): @@ -177,7 +239,19 @@ def logout(request): async def alogout(request): """See logout().""" - return await sync_to_async(logout)(request) + # Dispatch the signal before the user is logged out so the receivers have a + # chance to find out *who* logged out. + user = getattr(request, "auser", None) + if user is not None: + user = await user() + if not getattr(user, "is_authenticated", True): + user = None + await user_logged_out.asend(sender=user.__class__, request=request, user=user) + await request.session.aflush() + if hasattr(request, "user"): + from django.contrib.auth.models import AnonymousUser + + request.user = AnonymousUser() def get_user_model(): @@ -243,7 +317,43 @@ def get_user(request): async def aget_user(request): """See get_user().""" - return await sync_to_async(get_user)(request) + from .models import AnonymousUser + + user = None + try: + user_id = await _aget_user_session_key(request) + backend_path = await request.session.aget(BACKEND_SESSION_KEY) + except KeyError: + pass + else: + if backend_path in settings.AUTHENTICATION_BACKENDS: + backend = load_backend(backend_path) + user = await backend.aget_user(user_id) + # Verify the session + if hasattr(user, "get_session_auth_hash"): + session_hash = await request.session.aget(HASH_SESSION_KEY) + if not session_hash: + session_hash_verified = False + else: + session_auth_hash = user.get_session_auth_hash() + session_hash_verified = session_hash and constant_time_compare( + session_hash, user.get_session_auth_hash() + ) + if not session_hash_verified: + # If the current secret does not verify the session, try + # with the fallback secrets and stop when a matching one is + # found. + if session_hash and any( + constant_time_compare(session_hash, fallback_auth_hash) + for fallback_auth_hash in user.get_session_auth_fallback_hash() + ): + await request.session.acycle_key() + await request.session.aset(HASH_SESSION_KEY, session_auth_hash) + else: + await request.session.aflush() + user = None + + return user or AnonymousUser() def get_permission_codename(action, opts): diff --git a/django/contrib/auth/backends.py b/django/contrib/auth/backends.py index dd3c2e527b..f14fb3e96f 100644 --- a/django/contrib/auth/backends.py +++ b/django/contrib/auth/backends.py @@ -1,3 +1,5 @@ +from asgiref.sync import sync_to_async + from django.contrib.auth import get_user_model from django.contrib.auth.models import Permission from django.db.models import Exists, OuterRef, Q @@ -9,24 +11,45 @@ class BaseBackend: def authenticate(self, request, **kwargs): return None + async def aauthenticate(self, request, **kwargs): + return await sync_to_async(self.authenticate)(request, **kwargs) + def get_user(self, user_id): return None + async def aget_user(self, user_id): + return await sync_to_async(self.get_user)(user_id) + def get_user_permissions(self, user_obj, obj=None): return set() + async def aget_user_permissions(self, user_obj, obj=None): + return await sync_to_async(self.get_user_permissions)(user_obj, obj) + def get_group_permissions(self, user_obj, obj=None): return set() + async def aget_group_permissions(self, user_obj, obj=None): + return await sync_to_async(self.get_group_permissions)(user_obj, obj) + def get_all_permissions(self, user_obj, obj=None): return { *self.get_user_permissions(user_obj, obj=obj), *self.get_group_permissions(user_obj, obj=obj), } + async def aget_all_permissions(self, user_obj, obj=None): + return { + *await self.aget_user_permissions(user_obj, obj=obj), + *await self.aget_group_permissions(user_obj, obj=obj), + } + def has_perm(self, user_obj, perm, obj=None): return perm in self.get_all_permissions(user_obj, obj=obj) + async def ahas_perm(self, user_obj, perm, obj=None): + return perm in await self.aget_all_permissions(user_obj, obj) + class ModelBackend(BaseBackend): """ @@ -48,6 +71,23 @@ class ModelBackend(BaseBackend): if user.check_password(password) and self.user_can_authenticate(user): return user + async def aauthenticate(self, request, username=None, password=None, **kwargs): + if username is None: + username = kwargs.get(UserModel.USERNAME_FIELD) + if username is None or password is None: + return + try: + user = await UserModel._default_manager.aget_by_natural_key(username) + except UserModel.DoesNotExist: + # Run the default password hasher once to reduce the timing + # difference between an existing and a nonexistent user (#20760). + UserModel().set_password(password) + else: + if await user.acheck_password(password) and self.user_can_authenticate( + user + ): + return user + def user_can_authenticate(self, user): """ Reject users with is_active=False. Custom user models that don't have @@ -84,6 +124,25 @@ class ModelBackend(BaseBackend): ) return getattr(user_obj, perm_cache_name) + async def _aget_permissions(self, user_obj, obj, from_name): + """See _get_permissions().""" + if not user_obj.is_active or user_obj.is_anonymous or obj is not None: + return set() + + perm_cache_name = "_%s_perm_cache" % from_name + if not hasattr(user_obj, perm_cache_name): + if user_obj.is_superuser: + perms = Permission.objects.all() + else: + perms = getattr(self, "_get_%s_permissions" % from_name)(user_obj) + perms = perms.values_list("content_type__app_label", "codename").order_by() + setattr( + user_obj, + perm_cache_name, + {"%s.%s" % (ct, name) async for ct, name in perms}, + ) + return getattr(user_obj, perm_cache_name) + def get_user_permissions(self, user_obj, obj=None): """ Return a set of permission strings the user `user_obj` has from their @@ -91,6 +150,10 @@ class ModelBackend(BaseBackend): """ return self._get_permissions(user_obj, obj, "user") + async def aget_user_permissions(self, user_obj, obj=None): + """See get_user_permissions().""" + return await self._aget_permissions(user_obj, obj, "user") + def get_group_permissions(self, user_obj, obj=None): """ Return a set of permission strings the user `user_obj` has from the @@ -98,6 +161,10 @@ class ModelBackend(BaseBackend): """ return self._get_permissions(user_obj, obj, "group") + async def aget_group_permissions(self, user_obj, obj=None): + """See get_group_permissions().""" + return await self._aget_permissions(user_obj, obj, "group") + def get_all_permissions(self, user_obj, obj=None): if not user_obj.is_active or user_obj.is_anonymous or obj is not None: return set() @@ -108,6 +175,9 @@ class ModelBackend(BaseBackend): def has_perm(self, user_obj, perm, obj=None): return user_obj.is_active and super().has_perm(user_obj, perm, obj=obj) + async def ahas_perm(self, user_obj, perm, obj=None): + return user_obj.is_active and await super().ahas_perm(user_obj, perm, obj=obj) + def has_module_perms(self, user_obj, app_label): """ Return True if user_obj has any permissions in the given app_label. @@ -117,6 +187,13 @@ class ModelBackend(BaseBackend): for perm in self.get_all_permissions(user_obj) ) + async def ahas_module_perms(self, user_obj, app_label): + """See has_module_perms()""" + return user_obj.is_active and any( + perm[: perm.index(".")] == app_label + for perm in await self.aget_all_permissions(user_obj) + ) + def with_perm(self, perm, is_active=True, include_superusers=True, obj=None): """ Return users that have permission "perm". By default, filter out @@ -159,6 +236,13 @@ class ModelBackend(BaseBackend): return None return user if self.user_can_authenticate(user) else None + async def aget_user(self, user_id): + try: + user = await UserModel._default_manager.aget(pk=user_id) + except UserModel.DoesNotExist: + return None + return user if self.user_can_authenticate(user) else None + class AllowAllUsersModelBackend(ModelBackend): def user_can_authenticate(self, user): @@ -210,6 +294,29 @@ class RemoteUserBackend(ModelBackend): user = self.configure_user(request, user, created=created) return user if self.user_can_authenticate(user) else None + async def aauthenticate(self, request, remote_user): + """See authenticate().""" + if not remote_user: + return + created = False + user = None + username = self.clean_username(remote_user) + + # Note that this could be accomplished in one try-except clause, but + # instead we use get_or_create when creating unknown users since it has + # built-in safeguards for multiple threads. + if self.create_unknown_user: + user, created = await UserModel._default_manager.aget_or_create( + **{UserModel.USERNAME_FIELD: username} + ) + else: + try: + user = await UserModel._default_manager.aget_by_natural_key(username) + except UserModel.DoesNotExist: + pass + user = await self.aconfigure_user(request, user, created=created) + return user if self.user_can_authenticate(user) else None + def clean_username(self, username): """ Perform any cleaning on the "username" prior to using it to get or @@ -227,6 +334,10 @@ class RemoteUserBackend(ModelBackend): """ return user + async def aconfigure_user(self, request, user, created=True): + """See configure_user()""" + return await sync_to_async(self.configure_user)(request, user, created) + class AllowAllUsersRemoteUserBackend(RemoteUserBackend): def user_can_authenticate(self, user): diff --git a/django/contrib/auth/base_user.py b/django/contrib/auth/base_user.py index 0c9538d69d..5bb88ac4dd 100644 --- a/django/contrib/auth/base_user.py +++ b/django/contrib/auth/base_user.py @@ -36,6 +36,9 @@ class BaseUserManager(models.Manager): def get_by_natural_key(self, username): return self.get(**{self.model.USERNAME_FIELD: username}) + async def aget_by_natural_key(self, username): + return await self.aget(**{self.model.USERNAME_FIELD: username}) + class AbstractBaseUser(models.Model): password = models.CharField(_("password"), max_length=128) diff --git a/django/contrib/auth/decorators.py b/django/contrib/auth/decorators.py index 78e76a9ae9..77fbc79855 100644 --- a/django/contrib/auth/decorators.py +++ b/django/contrib/auth/decorators.py @@ -111,7 +111,7 @@ def permission_required(perm, login_url=None, raise_exception=False): async def check_perms(user): # First check if the user has the permission (even anon users). - if await sync_to_async(user.has_perms)(perms): + if await user.ahas_perms(perms): return True # In case the 403 handler should be called raise the exception. if raise_exception: diff --git a/django/contrib/auth/middleware.py b/django/contrib/auth/middleware.py index cb409ee778..85f58ec9a5 100644 --- a/django/contrib/auth/middleware.py +++ b/django/contrib/auth/middleware.py @@ -1,6 +1,8 @@ from functools import partial from urllib.parse import urlsplit +from asgiref.sync import iscoroutinefunction, markcoroutinefunction + from django.conf import settings from django.contrib import auth from django.contrib.auth import REDIRECT_FIELD_NAME, load_backend @@ -88,7 +90,7 @@ class LoginRequiredMiddleware(MiddlewareMixin): ) -class RemoteUserMiddleware(MiddlewareMixin): +class RemoteUserMiddleware: """ Middleware for utilizing web-server-provided authentication. @@ -102,13 +104,27 @@ class RemoteUserMiddleware(MiddlewareMixin): different header. """ + sync_capable = True + async_capable = True + + def __init__(self, get_response): + if get_response is None: + raise ValueError("get_response must be provided.") + self.get_response = get_response + self.is_async = iscoroutinefunction(get_response) + if self.is_async: + markcoroutinefunction(self) + super().__init__() + # Name of request header to grab username from. This will be the key as # used in the request.META dictionary, i.e. the normalization of headers to # all uppercase and the addition of "HTTP_" prefix apply. header = "REMOTE_USER" force_logout_if_no_header = True - def process_request(self, request): + def __call__(self, request): + if self.is_async: + return self.__acall__(request) # AuthenticationMiddleware is required so that request.user exists. if not hasattr(request, "user"): raise ImproperlyConfigured( @@ -126,13 +142,13 @@ class RemoteUserMiddleware(MiddlewareMixin): # AnonymousUser by the AuthenticationMiddleware). if self.force_logout_if_no_header and request.user.is_authenticated: self._remove_invalid_user(request) - return + return self.get_response(request) # If the user is already authenticated and that user is the user we are # getting passed in the headers, then the correct user is already # persisted in the session and we don't need to continue. if request.user.is_authenticated: if request.user.get_username() == self.clean_username(username, request): - return + return self.get_response(request) else: # An authenticated user is associated with the request, but # it does not match the authorized user in the header. @@ -146,6 +162,51 @@ class RemoteUserMiddleware(MiddlewareMixin): # by logging the user in. request.user = user auth.login(request, user) + return self.get_response(request) + + async def __acall__(self, request): + # AuthenticationMiddleware is required so that request.user exists. + if not hasattr(request, "user"): + raise ImproperlyConfigured( + "The Django remote user auth middleware requires the" + " authentication middleware to be installed. Edit your" + " MIDDLEWARE setting to insert" + " 'django.contrib.auth.middleware.AuthenticationMiddleware'" + " before the RemoteUserMiddleware class." + ) + try: + username = request.META["HTTP_" + self.header] + except KeyError: + # If specified header doesn't exist then remove any existing + # authenticated remote-user, or return (leaving request.user set to + # AnonymousUser by the AuthenticationMiddleware). + if self.force_logout_if_no_header: + user = await request.auser() + if user.is_authenticated: + await self._aremove_invalid_user(request) + return await self.get_response(request) + user = await request.auser() + # If the user is already authenticated and that user is the user we are + # getting passed in the headers, then the correct user is already + # persisted in the session and we don't need to continue. + if user.is_authenticated: + if user.get_username() == self.clean_username(username, request): + return await self.get_response(request) + else: + # An authenticated user is associated with the request, but + # it does not match the authorized user in the header. + await self._aremove_invalid_user(request) + + # We are seeing this user for the first time in this session, attempt + # to authenticate the user. + user = await auth.aauthenticate(request, remote_user=username) + if user: + # User is valid. Set request.user and persist user in the session + # by logging the user in. + request.user = user + await auth.alogin(request, user) + + return await self.get_response(request) def clean_username(self, username, request): """ @@ -176,6 +237,22 @@ class RemoteUserMiddleware(MiddlewareMixin): if isinstance(stored_backend, RemoteUserBackend): auth.logout(request) + async def _aremove_invalid_user(self, request): + """ + Remove the current authenticated user in the request which is invalid + but only if the user is authenticated via the RemoteUserBackend. + """ + try: + stored_backend = load_backend( + await request.session.aget(auth.BACKEND_SESSION_KEY, "") + ) + except ImportError: + # Backend failed to load. + await auth.alogout(request) + else: + if isinstance(stored_backend, RemoteUserBackend): + await auth.alogout(request) + class PersistentRemoteUserMiddleware(RemoteUserMiddleware): """ diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py index e5ef1bb523..d4a8dd902b 100644 --- a/django/contrib/auth/models.py +++ b/django/contrib/auth/models.py @@ -95,6 +95,9 @@ class GroupManager(models.Manager): def get_by_natural_key(self, name): return self.get(name=name) + async def aget_by_natural_key(self, name): + return await self.aget(name=name) + class Group(models.Model): """ @@ -137,10 +140,7 @@ class Group(models.Model): class UserManager(BaseUserManager): use_in_migrations = True - def _create_user(self, username, email, password, **extra_fields): - """ - Create and save a user with the given username, email, and password. - """ + def _create_user_object(self, username, email, password, **extra_fields): if not username: raise ValueError("The given username must be set") email = self.normalize_email(email) @@ -153,14 +153,32 @@ class UserManager(BaseUserManager): username = GlobalUserModel.normalize_username(username) user = self.model(username=username, email=email, **extra_fields) user.password = make_password(password) + return user + + def _create_user(self, username, email, password, **extra_fields): + """ + Create and save a user with the given username, email, and password. + """ + user = self._create_user_object(username, email, password, **extra_fields) user.save(using=self._db) return user + async def _acreate_user(self, username, email, password, **extra_fields): + """See _create_user()""" + user = self._create_user_object(username, email, password, **extra_fields) + await user.asave(using=self._db) + return user + def create_user(self, username, email=None, password=None, **extra_fields): extra_fields.setdefault("is_staff", False) extra_fields.setdefault("is_superuser", False) return self._create_user(username, email, password, **extra_fields) + async def acreate_user(self, username, email=None, password=None, **extra_fields): + extra_fields.setdefault("is_staff", False) + extra_fields.setdefault("is_superuser", False) + return await self._acreate_user(username, email, password, **extra_fields) + def create_superuser(self, username, email=None, password=None, **extra_fields): extra_fields.setdefault("is_staff", True) extra_fields.setdefault("is_superuser", True) @@ -172,6 +190,19 @@ class UserManager(BaseUserManager): return self._create_user(username, email, password, **extra_fields) + async def acreate_superuser( + self, username, email=None, password=None, **extra_fields + ): + extra_fields.setdefault("is_staff", True) + extra_fields.setdefault("is_superuser", True) + + if extra_fields.get("is_staff") is not True: + raise ValueError("Superuser must have is_staff=True.") + if extra_fields.get("is_superuser") is not True: + raise ValueError("Superuser must have is_superuser=True.") + + return await self._acreate_user(username, email, password, **extra_fields) + def with_perm( self, perm, is_active=True, include_superusers=True, backend=None, obj=None ): @@ -210,6 +241,15 @@ def _user_get_permissions(user, obj, from_name): return permissions +async def _auser_get_permissions(user, obj, from_name): + permissions = set() + name = "aget_%s_permissions" % from_name + for backend in auth.get_backends(): + if hasattr(backend, name): + permissions.update(await getattr(backend, name)(user, obj)) + return permissions + + def _user_has_perm(user, perm, obj): """ A backend can raise `PermissionDenied` to short-circuit permission checking. @@ -225,6 +265,19 @@ def _user_has_perm(user, perm, obj): return False +async def _auser_has_perm(user, perm, obj): + """See _user_has_perm()""" + for backend in auth.get_backends(): + if not hasattr(backend, "ahas_perm"): + continue + try: + if await backend.ahas_perm(user, perm, obj): + return True + except PermissionDenied: + return False + return False + + def _user_has_module_perms(user, app_label): """ A backend can raise `PermissionDenied` to short-circuit permission checking. @@ -240,6 +293,19 @@ def _user_has_module_perms(user, app_label): return False +async def _auser_has_module_perms(user, app_label): + """See _user_has_module_perms()""" + for backend in auth.get_backends(): + if not hasattr(backend, "ahas_module_perms"): + continue + try: + if await backend.ahas_module_perms(user, app_label): + return True + except PermissionDenied: + return False + return False + + class PermissionsMixin(models.Model): """ Add the fields and methods necessary to support the Group and Permission @@ -285,6 +351,10 @@ class PermissionsMixin(models.Model): """ return _user_get_permissions(self, obj, "user") + async def aget_user_permissions(self, obj=None): + """See get_user_permissions()""" + return await _auser_get_permissions(self, obj, "user") + def get_group_permissions(self, obj=None): """ Return a list of permission strings that this user has through their @@ -293,9 +363,16 @@ class PermissionsMixin(models.Model): """ return _user_get_permissions(self, obj, "group") + async def aget_group_permissions(self, obj=None): + """See get_group_permissions()""" + return await _auser_get_permissions(self, obj, "group") + def get_all_permissions(self, obj=None): return _user_get_permissions(self, obj, "all") + async def aget_all_permissions(self, obj=None): + return await _auser_get_permissions(self, obj, "all") + def has_perm(self, perm, obj=None): """ Return True if the user has the specified permission. Query all @@ -311,6 +388,15 @@ class PermissionsMixin(models.Model): # Otherwise we need to check the backends. return _user_has_perm(self, perm, obj) + async def ahas_perm(self, perm, obj=None): + """See has_perm()""" + # Active superusers have all permissions. + if self.is_active and self.is_superuser: + return True + + # Otherwise we need to check the backends. + return await _auser_has_perm(self, perm, obj) + def has_perms(self, perm_list, obj=None): """ Return True if the user has each of the specified permissions. If @@ -320,6 +406,15 @@ class PermissionsMixin(models.Model): raise ValueError("perm_list must be an iterable of permissions.") return all(self.has_perm(perm, obj) for perm in perm_list) + async def ahas_perms(self, perm_list, obj=None): + """See has_perms()""" + if not isinstance(perm_list, Iterable) or isinstance(perm_list, str): + raise ValueError("perm_list must be an iterable of permissions.") + for perm in perm_list: + if not await self.ahas_perm(perm, obj): + return False + return True + def has_module_perms(self, app_label): """ Return True if the user has any permissions in the given app label. @@ -331,6 +426,14 @@ class PermissionsMixin(models.Model): return _user_has_module_perms(self, app_label) + async def ahas_module_perms(self, app_label): + """See has_module_perms()""" + # Active superusers have all permissions. + if self.is_active and self.is_superuser: + return True + + return await _auser_has_module_perms(self, app_label) + class AbstractUser(AbstractBaseUser, PermissionsMixin): """ @@ -471,23 +574,46 @@ class AnonymousUser: def get_user_permissions(self, obj=None): return _user_get_permissions(self, obj, "user") + async def aget_user_permissions(self, obj=None): + return await _auser_get_permissions(self, obj, "user") + def get_group_permissions(self, obj=None): return set() + async def aget_group_permissions(self, obj=None): + return self.get_group_permissions(obj) + def get_all_permissions(self, obj=None): return _user_get_permissions(self, obj, "all") + async def aget_all_permissions(self, obj=None): + return await _auser_get_permissions(self, obj, "all") + def has_perm(self, perm, obj=None): return _user_has_perm(self, perm, obj=obj) + async def ahas_perm(self, perm, obj=None): + return await _auser_has_perm(self, perm, obj=obj) + def has_perms(self, perm_list, obj=None): if not isinstance(perm_list, Iterable) or isinstance(perm_list, str): raise ValueError("perm_list must be an iterable of permissions.") return all(self.has_perm(perm, obj) for perm in perm_list) + async def ahas_perms(self, perm_list, obj=None): + if not isinstance(perm_list, Iterable) or isinstance(perm_list, str): + raise ValueError("perm_list must be an iterable of permissions.") + for perm in perm_list: + if not await self.ahas_perm(perm, obj): + return False + return True + def has_module_perms(self, module): return _user_has_module_perms(self, module) + async def ahas_module_perms(self, module): + return await _auser_has_module_perms(self, module) + @property def is_anonymous(self): return True diff --git a/docs/ref/contrib/auth.txt b/docs/ref/contrib/auth.txt index d5fc724b54..c8699a2913 100644 --- a/docs/ref/contrib/auth.txt +++ b/docs/ref/contrib/auth.txt @@ -197,13 +197,23 @@ Methods been called for this user. .. method:: get_user_permissions(obj=None) + .. method:: aget_user_permissions(obj=None) + + *Asynchronous version*: ``aget_user_permissions()`` Returns a set of permission strings that the user has directly. If ``obj`` is passed in, only returns the user permissions for this specific object. + .. versionchanged:: 5.2 + + ``aget_user_permissions()`` method was added. + .. method:: get_group_permissions(obj=None) + .. method:: aget_group_permissions(obj=None) + + *Asynchronous version*: ``aget_group_permissions()`` Returns a set of permission strings that the user has, through their groups. @@ -211,7 +221,14 @@ Methods If ``obj`` is passed in, only returns the group permissions for this specific object. + .. versionchanged:: 5.2 + + ``aget_group_permissions()`` method was added. + .. method:: get_all_permissions(obj=None) + .. method:: aget_all_permissions(obj=None) + + *Asynchronous version*: ``aget_all_permissions()`` Returns a set of permission strings that the user has, both through group and user permissions. @@ -219,7 +236,14 @@ Methods If ``obj`` is passed in, only returns the permissions for this specific object. + .. versionchanged:: 5.2 + + ``aget_all_permissions()`` method was added. + .. method:: has_perm(perm, obj=None) + .. method:: ahas_perm(perm, obj=None) + + *Asynchronous version*: ``ahas_perm()`` Returns ``True`` if the user has the specified permission, where perm is in the format ``"."``. (see @@ -230,7 +254,14 @@ Methods If ``obj`` is passed in, this method won't check for a permission for the model, but for this specific object. + .. versionchanged:: 5.2 + + ``ahas_perm()`` method was added. + .. method:: has_perms(perm_list, obj=None) + .. method:: ahas_perms(perm_list, obj=None) + + *Asynchronous version*: ``ahas_perms()`` Returns ``True`` if the user has each of the specified permissions, where each perm is in the format @@ -241,13 +272,24 @@ Methods If ``obj`` is passed in, this method won't check for permissions for the model, but for the specific object. + .. versionchanged:: 5.2 + + ``ahas_perms()`` method was added. + .. method:: has_module_perms(package_name) + .. method:: ahas_module_perms(package_name) + + *Asynchronous version*: ``ahas_module_perms()`` Returns ``True`` if the user has any permissions in the given package (the Django app label). If the user is inactive, this method will always return ``False``. For an active superuser, this method will always return ``True``. + .. versionchanged:: 5.2 + + ``ahas_module_perms()`` method was added. + .. method:: email_user(subject, message, from_email=None, **kwargs) Sends an email to the user. If ``from_email`` is ``None``, Django uses @@ -264,6 +306,9 @@ Manager methods by :class:`~django.contrib.auth.models.BaseUserManager`): .. method:: create_user(username, email=None, password=None, **extra_fields) + .. method:: acreate_user(username, email=None, password=None, **extra_fields) + + *Asynchronous version*: ``acreate_user()`` Creates, saves and returns a :class:`~django.contrib.auth.models.User`. @@ -285,11 +330,22 @@ Manager methods See :ref:`Creating users ` for example usage. + .. versionchanged:: 5.2 + + ``acreate_user()`` method was added. + .. method:: create_superuser(username, email=None, password=None, **extra_fields) + .. method:: acreate_superuser(username, email=None, password=None, **extra_fields) + + *Asynchronous version*: ``acreate_superuser()`` Same as :meth:`create_user`, but sets :attr:`~models.User.is_staff` and :attr:`~models.User.is_superuser` to ``True``. + .. versionchanged:: 5.2 + + ``acreate_superuser()`` method was added. + .. method:: with_perm(perm, is_active=True, include_superusers=True, backend=None, obj=None) Returns users that have the given permission ``perm`` either in the @@ -499,23 +555,51 @@ The following backends are available in :mod:`django.contrib.auth.backends`: methods. By default, it will reject any user and provide no permissions. .. method:: get_user_permissions(user_obj, obj=None) + .. method:: aget_user_permissions(user_obj, obj=None) + + *Asynchronous version*: ``aget_user_permissions()`` Returns an empty set. + .. versionchanged:: 5.2 + + ``aget_user_permissions()`` function was added. + .. method:: get_group_permissions(user_obj, obj=None) + .. method:: aget_group_permissions(user_obj, obj=None) + + *Asynchronous version*: ``aget_group_permissions()`` Returns an empty set. + .. versionchanged:: 5.2 + + ``aget_group_permissions()`` function was added. + .. method:: get_all_permissions(user_obj, obj=None) + .. method:: aget_all_permissions(user_obj, obj=None) + + *Asynchronous version*: ``aget_all_permissions()`` Uses :meth:`get_user_permissions` and :meth:`get_group_permissions` to get the set of permission strings the ``user_obj`` has. + .. versionchanged:: 5.2 + + ``aget_all_permissions()`` function was added. + .. method:: has_perm(user_obj, perm, obj=None) + .. method:: ahas_perm(user_obj, perm, obj=None) + + *Asynchronous version*: ``ahas_perm()`` Uses :meth:`get_all_permissions` to check if ``user_obj`` has the permission string ``perm``. + .. versionchanged:: 5.2 + + ``ahas_perm()`` function was added. + .. class:: ModelBackend This is the default authentication backend used by Django. It @@ -539,6 +623,9 @@ The following backends are available in :mod:`django.contrib.auth.backends`: unlike others methods it returns an empty queryset if ``obj is not None``. .. method:: authenticate(request, username=None, password=None, **kwargs) + .. method:: aauthenticate(request, username=None, password=None, **kwargs) + + *Asynchronous version*: ``aauthenticate()`` Tries to authenticate ``username`` with ``password`` by calling :meth:`User.check_password @@ -552,38 +639,77 @@ The following backends are available in :mod:`django.contrib.auth.backends`: if it wasn't provided to :func:`~django.contrib.auth.authenticate` (which passes it on to the backend). + .. versionchanged:: 5.2 + + ``aauthenticate()`` function was added. + .. method:: get_user_permissions(user_obj, obj=None) + .. method:: aget_user_permissions(user_obj, obj=None) + + *Asynchronous version*: ``aget_user_permissions()`` Returns the set of permission strings the ``user_obj`` has from their own user permissions. Returns an empty set if :attr:`~django.contrib.auth.models.AbstractBaseUser.is_anonymous` or :attr:`~django.contrib.auth.models.CustomUser.is_active` is ``False``. + .. versionchanged:: 5.2 + + ``aget_user_permissions()`` function was added. + .. method:: get_group_permissions(user_obj, obj=None) + .. method:: aget_group_permissions(user_obj, obj=None) + + *Asynchronous version*: ``aget_group_permissions()`` Returns the set of permission strings the ``user_obj`` has from the permissions of the groups they belong. Returns an empty set if :attr:`~django.contrib.auth.models.AbstractBaseUser.is_anonymous` or :attr:`~django.contrib.auth.models.CustomUser.is_active` is ``False``. + .. versionchanged:: 5.2 + + ``aget_group_permissions()`` function was added. + .. method:: get_all_permissions(user_obj, obj=None) + .. method:: aget_all_permissions(user_obj, obj=None) + + *Asynchronous version*: ``aget_all_permissions()`` Returns the set of permission strings the ``user_obj`` has, including both user permissions and group permissions. Returns an empty set if :attr:`~django.contrib.auth.models.AbstractBaseUser.is_anonymous` or :attr:`~django.contrib.auth.models.CustomUser.is_active` is ``False``. + + .. versionchanged:: 5.2 + + ``aget_all_permissions()`` function was added. .. method:: has_perm(user_obj, perm, obj=None) + .. method:: ahas_perm(user_obj, perm, obj=None) + + *Asynchronous version*: ``ahas_perm()`` Uses :meth:`get_all_permissions` to check if ``user_obj`` has the permission string ``perm``. Returns ``False`` if the user is not :attr:`~django.contrib.auth.models.CustomUser.is_active`. + .. versionchanged:: 5.2 + + ``ahas_perm()`` function was added. + .. method:: has_module_perms(user_obj, app_label) + .. method:: ahas_module_perms(user_obj, app_label) + + *Asynchronous version*: ``ahas_module_perms()`` Returns whether the ``user_obj`` has any permissions on the app ``app_label``. + .. versionchanged:: 5.2 + + ``ahas_module_perms()`` function was added. + .. method:: user_can_authenticate() Returns whether the user is allowed to authenticate. To match the @@ -637,6 +763,9 @@ The following backends are available in :mod:`django.contrib.auth.backends`: created if not already in the database Defaults to ``True``. .. method:: authenticate(request, remote_user) + .. method:: aauthenticate(request, remote_user) + + *Asynchronous version*: ``aauthenticate()`` The username passed as ``remote_user`` is considered trusted. This method returns the user object with the given username, creating a new @@ -651,6 +780,10 @@ The following backends are available in :mod:`django.contrib.auth.backends`: if it wasn't provided to :func:`~django.contrib.auth.authenticate` (which passes it on to the backend). + .. versionchanged:: 5.2 + + ``aauthenticate()`` function was added. + .. method:: clean_username(username) Performs any cleaning on the ``username`` (e.g. stripping LDAP DN @@ -658,12 +791,17 @@ The following backends are available in :mod:`django.contrib.auth.backends`: the cleaned username. .. method:: configure_user(request, user, created=True) + .. method:: aconfigure_user(request, user, created=True) + + *Asynchronous version*: ``aconfigure_user()`` Configures the user on each authentication attempt. This method is called immediately after fetching or creating the user being authenticated, and can be used to perform custom setup actions, such as setting the user's groups based on attributes in an LDAP directory. - Returns the user object. + Returns the user object. When fetching or creating an user is called + from a synchronous context, ``configure_user`` is called, + ``aconfigure_user`` is called from async contexts. The setup can be performed either once when the user is created (``created`` is ``True``) or on existing users (``created`` is @@ -674,6 +812,10 @@ The following backends are available in :mod:`django.contrib.auth.backends`: if it wasn't provided to :func:`~django.contrib.auth.authenticate` (which passes it on to the backend). + .. versionchanged:: 5.2 + + ``aconfigure_user()`` function was added. + .. method:: user_can_authenticate() Returns whether the user is allowed to authenticate. This method diff --git a/docs/releases/5.2.txt b/docs/releases/5.2.txt index c445e02694..9aa232b902 100644 --- a/docs/releases/5.2.txt +++ b/docs/releases/5.2.txt @@ -52,6 +52,36 @@ Minor features * The default iteration count for the PBKDF2 password hasher is increased from 870,000 to 1,000,000. +* The following new asynchronous methods on are now provided, using an ``a`` + prefix: + + * :meth:`.UserManager.acreate_user` + * :meth:`.UserManager.acreate_superuser` + * :meth:`.BaseUserManager.aget_by_natural_key` + * :meth:`.User.aget_user_permissions()` + * :meth:`.User.aget_all_permissions()` + * :meth:`.User.aget_group_permissions()` + * :meth:`.User.ahas_perm()` + * :meth:`.User.ahas_perms()` + * :meth:`.User.ahas_module_perms()` + * :meth:`.User.aget_user_permissions()` + * :meth:`.User.aget_group_permissions()` + * :meth:`.User.ahas_perm()` + * :meth:`.ModelBackend.aauthenticate()` + * :meth:`.ModelBackend.aget_user_permissions()` + * :meth:`.ModelBackend.aget_group_permissions()` + * :meth:`.ModelBackend.aget_all_permissions()` + * :meth:`.ModelBackend.ahas_perm()` + * :meth:`.ModelBackend.ahas_module_perms()` + * :meth:`.RemoteUserBackend.aauthenticate()` + * :meth:`.RemoteUserBackend.aconfigure_user()` + +* Auth backends can now provide async implementations which are used when + calling async auth functions (e.g. + :func:`~.django.contrib.auth.aauthenticate`) to reduce context-switching which + improves performance. See :ref:`adding an async interface + ` for more details. + :mod:`django.contrib.contenttypes` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/topics/auth/customizing.txt b/docs/topics/auth/customizing.txt index f41b10fb4a..6fdcd136c0 100644 --- a/docs/topics/auth/customizing.txt +++ b/docs/topics/auth/customizing.txt @@ -790,10 +790,17 @@ utility methods: email address. .. method:: models.BaseUserManager.get_by_natural_key(username) + .. method:: models.BaseUserManager.aget_by_natural_key(username) + + *Asynchronous version*: ``aget_by_natural_key()`` Retrieves a user instance using the contents of the field nominated by ``USERNAME_FIELD``. + .. versionchanged:: 5.2 + + ``aget_by_natural_key()`` method was added. + Extending Django's default ``User`` ----------------------------------- @@ -1186,3 +1193,25 @@ Finally, specify the custom model as the default user model for your project using the :setting:`AUTH_USER_MODEL` setting in your ``settings.py``:: AUTH_USER_MODEL = "customauth.MyUser" + +.. _writing-authentication-backends-async-interface: + +Adding an async interface +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 5.2 + +To optimize performance when called from an async context authentication, +backends can implement async versions of each function - ``aget_user(user_id)`` +and ``aauthenticate(request, **credentials)``. When an authentication backend +extends ``BaseBackend`` and async versions of these functions are not provided, +they will be automatically synthesized with ``sync_to_async``. This has +:ref:`performance penalties `. + +While an async interface is optional, a synchronous interface is always +required. There is no automatic synthesis for a synchronous interface if an +async interface is implemented. + +Django's out-of-the-box authentication backends have native async support. If +these native backends are extended take special care to make sure the async +versions of modified functions are modified as well. diff --git a/tests/async/test_async_auth.py b/tests/async/test_async_auth.py index f6551c63ee..37884d13a6 100644 --- a/tests/async/test_async_auth.py +++ b/tests/async/test_async_auth.py @@ -33,9 +33,40 @@ class AsyncAuthTest(TestCase): self.assertIsInstance(user, User) self.assertEqual(user.username, self.test_user.username) + async def test_changed_password_invalidates_aget_user(self): + request = HttpRequest() + request.session = await self.client.asession() + await alogin(request, self.test_user) + + self.test_user.set_password("new_password") + await self.test_user.asave() + + user = await aget_user(request) + + self.assertIsNotNone(user) + self.assertTrue(user.is_anonymous) + # Session should be flushed. + self.assertIsNone(request.session.session_key) + + async def test_alogin_new_user(self): + request = HttpRequest() + request.session = await self.client.asession() + await alogin(request, self.test_user) + second_user = await User.objects.acreate_user( + "testuser2", "test2@example.com", "testpw2" + ) + await alogin(request, second_user) + user = await aget_user(request) + self.assertIsInstance(user, User) + self.assertEqual(user.username, second_user.username) + async def test_alogin_without_user(self): + async def auser(): + return self.test_user + request = HttpRequest() request.user = self.test_user + request.auser = auser request.session = await self.client.asession() await alogin(request, None) user = await aget_user(request) diff --git a/tests/auth_tests/models/custom_user.py b/tests/auth_tests/models/custom_user.py index b9938681ca..4586e452cd 100644 --- a/tests/auth_tests/models/custom_user.py +++ b/tests/auth_tests/models/custom_user.py @@ -29,6 +29,19 @@ class CustomUserManager(BaseUserManager): user.save(using=self._db) return user + async def acreate_user(self, email, date_of_birth, password=None, **fields): + """See create_user()""" + if not email: + raise ValueError("Users must have an email address") + + user = self.model( + email=self.normalize_email(email), date_of_birth=date_of_birth, **fields + ) + + user.set_password(password) + await user.asave(using=self._db) + return user + def create_superuser(self, email, password, date_of_birth, **fields): u = self.create_user( email, password=password, date_of_birth=date_of_birth, **fields diff --git a/tests/auth_tests/test_auth_backends.py b/tests/auth_tests/test_auth_backends.py index 3b4f40e6e0..b612d27ab0 100644 --- a/tests/auth_tests/test_auth_backends.py +++ b/tests/auth_tests/test_auth_backends.py @@ -2,6 +2,8 @@ import sys from datetime import date from unittest import mock +from asgiref.sync import sync_to_async + from django.contrib.auth import ( BACKEND_SESSION_KEY, SESSION_KEY, @@ -55,17 +57,33 @@ class BaseBackendTest(TestCase): def test_get_user_permissions(self): self.assertEqual(self.user.get_user_permissions(), {"user_perm"}) + async def test_aget_user_permissions(self): + self.assertEqual(await self.user.aget_user_permissions(), {"user_perm"}) + def test_get_group_permissions(self): self.assertEqual(self.user.get_group_permissions(), {"group_perm"}) + async def test_aget_group_permissions(self): + self.assertEqual(await self.user.aget_group_permissions(), {"group_perm"}) + def test_get_all_permissions(self): self.assertEqual(self.user.get_all_permissions(), {"user_perm", "group_perm"}) + async def test_aget_all_permissions(self): + self.assertEqual( + await self.user.aget_all_permissions(), {"user_perm", "group_perm"} + ) + def test_has_perm(self): self.assertIs(self.user.has_perm("user_perm"), True) self.assertIs(self.user.has_perm("group_perm"), True) self.assertIs(self.user.has_perm("other_perm", TestObj()), False) + async def test_ahas_perm(self): + self.assertIs(await self.user.ahas_perm("user_perm"), True) + self.assertIs(await self.user.ahas_perm("group_perm"), True) + self.assertIs(await self.user.ahas_perm("other_perm", TestObj()), False) + def test_has_perms_perm_list_invalid(self): msg = "perm_list must be an iterable of permissions." with self.assertRaisesMessage(ValueError, msg): @@ -73,6 +91,13 @@ class BaseBackendTest(TestCase): with self.assertRaisesMessage(ValueError, msg): self.user.has_perms(object()) + async def test_ahas_perms_perm_list_invalid(self): + msg = "perm_list must be an iterable of permissions." + with self.assertRaisesMessage(ValueError, msg): + await self.user.ahas_perms("user_perm") + with self.assertRaisesMessage(ValueError, msg): + await self.user.ahas_perms(object()) + class CountingMD5PasswordHasher(MD5PasswordHasher): """Hasher that counts how many times it computes a hash.""" @@ -125,6 +150,25 @@ class BaseModelBackendTest: user.save() self.assertIs(user.has_perm("auth.test"), False) + async def test_ahas_perm(self): + user = await self.UserModel._default_manager.aget(pk=self.user.pk) + self.assertIs(await user.ahas_perm("auth.test"), False) + + user.is_staff = True + await user.asave() + self.assertIs(await user.ahas_perm("auth.test"), False) + + user.is_superuser = True + await user.asave() + self.assertIs(await user.ahas_perm("auth.test"), True) + self.assertIs(await user.ahas_module_perms("auth"), True) + + user.is_staff = True + user.is_superuser = True + user.is_active = False + await user.asave() + self.assertIs(await user.ahas_perm("auth.test"), False) + def test_custom_perms(self): user = self.UserModel._default_manager.get(pk=self.user.pk) content_type = ContentType.objects.get_for_model(Group) @@ -174,6 +218,55 @@ class BaseModelBackendTest: self.assertIs(user.has_perm("test"), False) self.assertIs(user.has_perms(["auth.test2", "auth.test3"]), False) + async def test_acustom_perms(self): + user = await self.UserModel._default_manager.aget(pk=self.user.pk) + content_type = await sync_to_async(ContentType.objects.get_for_model)(Group) + perm = await Permission.objects.acreate( + name="test", content_type=content_type, codename="test" + ) + await user.user_permissions.aadd(perm) + + # Reloading user to purge the _perm_cache. + user = await self.UserModel._default_manager.aget(pk=self.user.pk) + self.assertEqual(await user.aget_all_permissions(), {"auth.test"}) + self.assertEqual(await user.aget_user_permissions(), {"auth.test"}) + self.assertEqual(await user.aget_group_permissions(), set()) + self.assertIs(await user.ahas_module_perms("Group"), False) + self.assertIs(await user.ahas_module_perms("auth"), True) + + perm = await Permission.objects.acreate( + name="test2", content_type=content_type, codename="test2" + ) + await user.user_permissions.aadd(perm) + perm = await Permission.objects.acreate( + name="test3", content_type=content_type, codename="test3" + ) + await user.user_permissions.aadd(perm) + user = await self.UserModel._default_manager.aget(pk=self.user.pk) + expected_user_perms = {"auth.test2", "auth.test", "auth.test3"} + self.assertEqual(await user.aget_all_permissions(), expected_user_perms) + self.assertIs(await user.ahas_perm("test"), False) + self.assertIs(await user.ahas_perm("auth.test"), True) + self.assertIs(await user.ahas_perms(["auth.test2", "auth.test3"]), True) + + perm = await Permission.objects.acreate( + name="test_group", content_type=content_type, codename="test_group" + ) + group = await Group.objects.acreate(name="test_group") + await group.permissions.aadd(perm) + await user.groups.aadd(group) + user = await self.UserModel._default_manager.aget(pk=self.user.pk) + self.assertEqual( + await user.aget_all_permissions(), {*expected_user_perms, "auth.test_group"} + ) + self.assertEqual(await user.aget_user_permissions(), expected_user_perms) + self.assertEqual(await user.aget_group_permissions(), {"auth.test_group"}) + self.assertIs(await user.ahas_perms(["auth.test3", "auth.test_group"]), True) + + user = AnonymousUser() + self.assertIs(await user.ahas_perm("test"), False) + self.assertIs(await user.ahas_perms(["auth.test2", "auth.test3"]), False) + def test_has_no_object_perm(self): """Regressiontest for #12462""" user = self.UserModel._default_manager.get(pk=self.user.pk) @@ -188,6 +281,20 @@ class BaseModelBackendTest: self.assertIs(user.has_perm("auth.test"), True) self.assertEqual(user.get_all_permissions(), {"auth.test"}) + async def test_ahas_no_object_perm(self): + """See test_has_no_object_perm()""" + user = await self.UserModel._default_manager.aget(pk=self.user.pk) + content_type = await sync_to_async(ContentType.objects.get_for_model)(Group) + perm = await Permission.objects.acreate( + name="test", content_type=content_type, codename="test" + ) + await user.user_permissions.aadd(perm) + + self.assertIs(await user.ahas_perm("auth.test", "object"), False) + self.assertEqual(await user.aget_all_permissions("object"), set()) + self.assertIs(await user.ahas_perm("auth.test"), True) + self.assertEqual(await user.aget_all_permissions(), {"auth.test"}) + def test_anonymous_has_no_permissions(self): """ #17903 -- Anonymous users shouldn't have permissions in @@ -220,6 +327,38 @@ class BaseModelBackendTest: self.assertEqual(backend.get_user_permissions(user), set()) self.assertEqual(backend.get_group_permissions(user), set()) + async def test_aanonymous_has_no_permissions(self): + """See test_anonymous_has_no_permissions()""" + backend = ModelBackend() + + user = await self.UserModel._default_manager.aget(pk=self.user.pk) + content_type = await sync_to_async(ContentType.objects.get_for_model)(Group) + user_perm = await Permission.objects.acreate( + name="test", content_type=content_type, codename="test_user" + ) + group_perm = await Permission.objects.acreate( + name="test2", content_type=content_type, codename="test_group" + ) + await user.user_permissions.aadd(user_perm) + + group = await Group.objects.acreate(name="test_group") + await user.groups.aadd(group) + await group.permissions.aadd(group_perm) + + self.assertEqual( + await backend.aget_all_permissions(user), + {"auth.test_user", "auth.test_group"}, + ) + self.assertEqual(await backend.aget_user_permissions(user), {"auth.test_user"}) + self.assertEqual( + await backend.aget_group_permissions(user), {"auth.test_group"} + ) + + with mock.patch.object(self.UserModel, "is_anonymous", True): + self.assertEqual(await backend.aget_all_permissions(user), set()) + self.assertEqual(await backend.aget_user_permissions(user), set()) + self.assertEqual(await backend.aget_group_permissions(user), set()) + def test_inactive_has_no_permissions(self): """ #17903 -- Inactive users shouldn't have permissions in @@ -254,11 +393,52 @@ class BaseModelBackendTest: self.assertEqual(backend.get_user_permissions(user), set()) self.assertEqual(backend.get_group_permissions(user), set()) + async def test_ainactive_has_no_permissions(self): + """See test_inactive_has_no_permissions()""" + backend = ModelBackend() + + user = await self.UserModel._default_manager.aget(pk=self.user.pk) + content_type = await sync_to_async(ContentType.objects.get_for_model)(Group) + user_perm = await Permission.objects.acreate( + name="test", content_type=content_type, codename="test_user" + ) + group_perm = await Permission.objects.acreate( + name="test2", content_type=content_type, codename="test_group" + ) + await user.user_permissions.aadd(user_perm) + + group = await Group.objects.acreate(name="test_group") + await user.groups.aadd(group) + await group.permissions.aadd(group_perm) + + self.assertEqual( + await backend.aget_all_permissions(user), + {"auth.test_user", "auth.test_group"}, + ) + self.assertEqual(await backend.aget_user_permissions(user), {"auth.test_user"}) + self.assertEqual( + await backend.aget_group_permissions(user), {"auth.test_group"} + ) + + user.is_active = False + await user.asave() + + self.assertEqual(await backend.aget_all_permissions(user), set()) + self.assertEqual(await backend.aget_user_permissions(user), set()) + self.assertEqual(await backend.aget_group_permissions(user), set()) + def test_get_all_superuser_permissions(self): """A superuser has all permissions. Refs #14795.""" user = self.UserModel._default_manager.get(pk=self.superuser.pk) self.assertEqual(len(user.get_all_permissions()), len(Permission.objects.all())) + async def test_aget_all_superuser_permissions(self): + """See test_get_all_superuser_permissions()""" + user = await self.UserModel._default_manager.aget(pk=self.superuser.pk) + self.assertEqual( + len(await user.aget_all_permissions()), await Permission.objects.acount() + ) + @override_settings( PASSWORD_HASHERS=["auth_tests.test_auth_backends.CountingMD5PasswordHasher"] ) @@ -277,6 +457,24 @@ class BaseModelBackendTest: authenticate(username="no_such_user", password="test") self.assertEqual(CountingMD5PasswordHasher.calls, 1) + @override_settings( + PASSWORD_HASHERS=["auth_tests.test_auth_backends.CountingMD5PasswordHasher"] + ) + async def test_aauthentication_timing(self): + """See test_authentication_timing()""" + # Re-set the password, because this tests overrides PASSWORD_HASHERS. + self.user.set_password("test") + await self.user.asave() + + CountingMD5PasswordHasher.calls = 0 + username = getattr(self.user, self.UserModel.USERNAME_FIELD) + await aauthenticate(username=username, password="test") + self.assertEqual(CountingMD5PasswordHasher.calls, 1) + + CountingMD5PasswordHasher.calls = 0 + await aauthenticate(username="no_such_user", password="test") + self.assertEqual(CountingMD5PasswordHasher.calls, 1) + @override_settings( PASSWORD_HASHERS=["auth_tests.test_auth_backends.CountingMD5PasswordHasher"] ) @@ -320,6 +518,15 @@ class ModelBackendTest(BaseModelBackendTest, TestCase): self.user.save() self.assertIsNone(authenticate(**self.user_credentials)) + async def test_aauthenticate_inactive(self): + """ + An inactive user can't authenticate. + """ + self.assertEqual(await aauthenticate(**self.user_credentials), self.user) + self.user.is_active = False + await self.user.asave() + self.assertIsNone(await aauthenticate(**self.user_credentials)) + @override_settings(AUTH_USER_MODEL="auth_tests.CustomUserWithoutIsActiveField") def test_authenticate_user_without_is_active_field(self): """ @@ -332,6 +539,18 @@ class ModelBackendTest(BaseModelBackendTest, TestCase): ) self.assertEqual(authenticate(username="test", password="test"), user) + @override_settings(AUTH_USER_MODEL="auth_tests.CustomUserWithoutIsActiveField") + async def test_aauthenticate_user_without_is_active_field(self): + """ + A custom user without an `is_active` field is allowed to authenticate. + """ + user = await CustomUserWithoutIsActiveField.objects._acreate_user( + username="test", + email="test@example.com", + password="test", + ) + self.assertEqual(await aauthenticate(username="test", password="test"), user) + @override_settings(AUTH_USER_MODEL="auth_tests.ExtensionUser") class ExtensionUserModelBackendTest(BaseModelBackendTest, TestCase): @@ -403,6 +622,15 @@ class CustomUserModelBackendAuthenticateTest(TestCase): authenticated_user = authenticate(email="test@example.com", password="test") self.assertEqual(test_user, authenticated_user) + async def test_aauthenticate(self): + test_user = await CustomUser._default_manager.acreate_user( + email="test@example.com", password="test", date_of_birth=date(2006, 4, 25) + ) + authenticated_user = await aauthenticate( + email="test@example.com", password="test" + ) + self.assertEqual(test_user, authenticated_user) + @override_settings(AUTH_USER_MODEL="auth_tests.UUIDUser") class UUIDUserTests(TestCase): @@ -416,6 +644,13 @@ class UUIDUserTests(TestCase): UUIDUser.objects.get(pk=self.client.session[SESSION_KEY]), user ) + async def test_alogin(self): + """See test_login()""" + user = await UUIDUser.objects.acreate_user(username="uuid", password="test") + self.assertTrue(await self.client.alogin(username="uuid", password="test")) + session_key = await self.client.session.aget(SESSION_KEY) + self.assertEqual(await UUIDUser.objects.aget(pk=session_key), user) + class TestObj: pass @@ -435,9 +670,15 @@ class SimpleRowlevelBackend: return True return False + async def ahas_perm(self, user, perm, obj=None): + return self.has_perm(user, perm, obj) + def has_module_perms(self, user, app_label): return (user.is_anonymous or user.is_active) and app_label == "app1" + async def ahas_module_perms(self, user, app_label): + return self.has_module_perms(user, app_label) + def get_all_permissions(self, user, obj=None): if not obj: return [] # We only support row level perms @@ -452,6 +693,9 @@ class SimpleRowlevelBackend: else: return ["simple"] + async def aget_all_permissions(self, user, obj=None): + return self.get_all_permissions(user, obj) + def get_group_permissions(self, user, obj=None): if not obj: return # We only support row level perms @@ -524,10 +768,18 @@ class AnonymousUserBackendTest(SimpleTestCase): self.assertIs(self.user1.has_perm("perm", TestObj()), False) self.assertIs(self.user1.has_perm("anon", TestObj()), True) + async def test_ahas_perm(self): + self.assertIs(await self.user1.ahas_perm("perm", TestObj()), False) + self.assertIs(await self.user1.ahas_perm("anon", TestObj()), True) + def test_has_perms(self): self.assertIs(self.user1.has_perms(["anon"], TestObj()), True) self.assertIs(self.user1.has_perms(["anon", "perm"], TestObj()), False) + async def test_ahas_perms(self): + self.assertIs(await self.user1.ahas_perms(["anon"], TestObj()), True) + self.assertIs(await self.user1.ahas_perms(["anon", "perm"], TestObj()), False) + def test_has_perms_perm_list_invalid(self): msg = "perm_list must be an iterable of permissions." with self.assertRaisesMessage(ValueError, msg): @@ -535,13 +787,27 @@ class AnonymousUserBackendTest(SimpleTestCase): with self.assertRaisesMessage(ValueError, msg): self.user1.has_perms(object()) + async def test_ahas_perms_perm_list_invalid(self): + msg = "perm_list must be an iterable of permissions." + with self.assertRaisesMessage(ValueError, msg): + await self.user1.ahas_perms("perm") + with self.assertRaisesMessage(ValueError, msg): + await self.user1.ahas_perms(object()) + def test_has_module_perms(self): self.assertIs(self.user1.has_module_perms("app1"), True) self.assertIs(self.user1.has_module_perms("app2"), False) + async def test_ahas_module_perms(self): + self.assertIs(await self.user1.ahas_module_perms("app1"), True) + self.assertIs(await self.user1.ahas_module_perms("app2"), False) + def test_get_all_permissions(self): self.assertEqual(self.user1.get_all_permissions(TestObj()), {"anon"}) + async def test_aget_all_permissions(self): + self.assertEqual(await self.user1.aget_all_permissions(TestObj()), {"anon"}) + @override_settings(AUTHENTICATION_BACKENDS=[]) class NoBackendsTest(TestCase): @@ -561,6 +827,14 @@ class NoBackendsTest(TestCase): with self.assertRaisesMessage(ImproperlyConfigured, msg): self.user.has_perm(("perm", TestObj())) + async def test_araises_exception(self): + msg = ( + "No authentication backends have been defined. " + "Does AUTHENTICATION_BACKENDS contain anything?" + ) + with self.assertRaisesMessage(ImproperlyConfigured, msg): + await self.user.ahas_perm(("perm", TestObj())) + @override_settings( AUTHENTICATION_BACKENDS=["auth_tests.test_auth_backends.SimpleRowlevelBackend"] @@ -593,12 +867,21 @@ class PermissionDeniedBackend: def authenticate(self, request, username=None, password=None): raise PermissionDenied + async def aauthenticate(self, request, username=None, password=None): + raise PermissionDenied + def has_perm(self, user_obj, perm, obj=None): raise PermissionDenied + async def ahas_perm(self, user_obj, perm, obj=None): + raise PermissionDenied + def has_module_perms(self, user_obj, app_label): raise PermissionDenied + async def ahas_module_perms(self, user_obj, app_label): + raise PermissionDenied + class PermissionDeniedBackendTest(TestCase): """ @@ -631,10 +914,25 @@ class PermissionDeniedBackendTest(TestCase): [{"password": "********************", "username": "test"}], ) + @modify_settings(AUTHENTICATION_BACKENDS={"prepend": backend}) + async def test_aauthenticate_permission_denied(self): + self.assertIsNone(await aauthenticate(username="test", password="test")) + # user_login_failed signal is sent. + self.assertEqual( + self.user_login_failed, + [{"password": "********************", "username": "test"}], + ) + @modify_settings(AUTHENTICATION_BACKENDS={"append": backend}) def test_authenticates(self): self.assertEqual(authenticate(username="test", password="test"), self.user1) + @modify_settings(AUTHENTICATION_BACKENDS={"append": backend}) + async def test_aauthenticate(self): + self.assertEqual( + await aauthenticate(username="test", password="test"), self.user1 + ) + @modify_settings(AUTHENTICATION_BACKENDS={"prepend": backend}) def test_has_perm_denied(self): content_type = ContentType.objects.get_for_model(Group) @@ -646,6 +944,17 @@ class PermissionDeniedBackendTest(TestCase): self.assertIs(self.user1.has_perm("auth.test"), False) self.assertIs(self.user1.has_module_perms("auth"), False) + @modify_settings(AUTHENTICATION_BACKENDS={"prepend": backend}) + async def test_ahas_perm_denied(self): + content_type = await sync_to_async(ContentType.objects.get_for_model)(Group) + perm = await Permission.objects.acreate( + name="test", content_type=content_type, codename="test" + ) + await self.user1.user_permissions.aadd(perm) + + self.assertIs(await self.user1.ahas_perm("auth.test"), False) + self.assertIs(await self.user1.ahas_module_perms("auth"), False) + @modify_settings(AUTHENTICATION_BACKENDS={"append": backend}) def test_has_perm(self): content_type = ContentType.objects.get_for_model(Group) @@ -657,6 +966,17 @@ class PermissionDeniedBackendTest(TestCase): self.assertIs(self.user1.has_perm("auth.test"), True) self.assertIs(self.user1.has_module_perms("auth"), True) + @modify_settings(AUTHENTICATION_BACKENDS={"append": backend}) + async def test_ahas_perm(self): + content_type = await sync_to_async(ContentType.objects.get_for_model)(Group) + perm = await Permission.objects.acreate( + name="test", content_type=content_type, codename="test" + ) + await self.user1.user_permissions.aadd(perm) + + self.assertIs(await self.user1.ahas_perm("auth.test"), True) + self.assertIs(await self.user1.ahas_module_perms("auth"), True) + class NewModelBackend(ModelBackend): pass @@ -715,6 +1035,10 @@ class TypeErrorBackend: def authenticate(self, request, username=None, password=None): raise TypeError + @sensitive_variables("password") + async def aauthenticate(self, request, username=None, password=None): + raise TypeError + class SkippedBackend: def authenticate(self): diff --git a/tests/auth_tests/test_basic.py b/tests/auth_tests/test_basic.py index d7a7750b54..8d54e187fc 100644 --- a/tests/auth_tests/test_basic.py +++ b/tests/auth_tests/test_basic.py @@ -1,5 +1,3 @@ -from asgiref.sync import sync_to_async - from django.conf import settings from django.contrib.auth import aget_user, get_user, get_user_model from django.contrib.auth.models import AnonymousUser, User @@ -44,6 +42,12 @@ class BasicTestCase(TestCase): u2 = User.objects.create_user("testuser2", "test2@example.com") self.assertFalse(u2.has_usable_password()) + async def test_acreate(self): + u = await User.objects.acreate_user("testuser", "test@example.com", "testpw") + self.assertTrue(u.has_usable_password()) + self.assertFalse(await u.acheck_password("bad")) + self.assertTrue(await u.acheck_password("testpw")) + def test_unicode_username(self): User.objects.create_user("jörg") User.objects.create_user("Григорий") @@ -73,6 +77,15 @@ class BasicTestCase(TestCase): self.assertTrue(super.is_active) self.assertTrue(super.is_staff) + async def test_asuperuser(self): + "Check the creation and properties of a superuser" + super = await User.objects.acreate_superuser( + "super", "super@example.com", "super" + ) + self.assertTrue(super.is_superuser) + self.assertTrue(super.is_active) + self.assertTrue(super.is_staff) + def test_superuser_no_email_or_password(self): cases = [ {}, @@ -171,13 +184,25 @@ class TestGetUser(TestCase): self.assertIsInstance(user, User) self.assertEqual(user.username, created_user.username) - async def test_aget_user(self): - created_user = await sync_to_async(User.objects.create_user)( + async def test_aget_user_fallback_secret(self): + created_user = await User.objects.acreate_user( "testuser", "test@example.com", "testpw" ) await self.client.alogin(username="testuser", password="testpw") request = HttpRequest() request.session = await self.client.asession() - user = await aget_user(request) - self.assertIsInstance(user, User) - self.assertEqual(user.username, created_user.username) + prev_session_key = request.session.session_key + with override_settings( + SECRET_KEY="newsecret", + SECRET_KEY_FALLBACKS=[settings.SECRET_KEY], + ): + user = await aget_user(request) + self.assertIsInstance(user, User) + self.assertEqual(user.username, created_user.username) + self.assertNotEqual(request.session.session_key, prev_session_key) + # Remove the fallback secret. + # The session hash should be updated using the current secret. + with override_settings(SECRET_KEY="newsecret"): + user = await aget_user(request) + self.assertIsInstance(user, User) + self.assertEqual(user.username, created_user.username) diff --git a/tests/auth_tests/test_decorators.py b/tests/auth_tests/test_decorators.py index e585b28bd5..fa2672beb4 100644 --- a/tests/auth_tests/test_decorators.py +++ b/tests/auth_tests/test_decorators.py @@ -1,7 +1,5 @@ from asyncio import iscoroutinefunction -from asgiref.sync import sync_to_async - from django.conf import settings from django.contrib.auth import models from django.contrib.auth.decorators import ( @@ -374,7 +372,7 @@ class UserPassesTestDecoratorTest(TestCase): def test_decorator_async_test_func(self): async def async_test_func(user): - return await sync_to_async(user.has_perms)(["auth_tests.add_customuser"]) + return await user.ahas_perms(["auth_tests.add_customuser"]) @user_passes_test(async_test_func) def sync_view(request): @@ -410,7 +408,7 @@ class UserPassesTestDecoratorTest(TestCase): async def test_decorator_async_view_async_test_func(self): async def async_test_func(user): - return await sync_to_async(user.has_perms)(["auth_tests.add_customuser"]) + return await user.ahas_perms(["auth_tests.add_customuser"]) @user_passes_test(async_test_func) async def async_view(request): diff --git a/tests/auth_tests/test_models.py b/tests/auth_tests/test_models.py index 983424843c..a3e7a3205b 100644 --- a/tests/auth_tests/test_models.py +++ b/tests/auth_tests/test_models.py @@ -1,7 +1,5 @@ from unittest import mock -from asgiref.sync import sync_to_async - from django.conf.global_settings import PASSWORD_HASHERS from django.contrib.auth import get_user_model from django.contrib.auth.backends import ModelBackend @@ -30,10 +28,19 @@ class NaturalKeysTestCase(TestCase): self.assertEqual(User.objects.get_by_natural_key("staff"), staff_user) self.assertEqual(staff_user.natural_key(), ("staff",)) + async def test_auser_natural_key(self): + staff_user = await User.objects.acreate_user(username="staff") + self.assertEqual(await User.objects.aget_by_natural_key("staff"), staff_user) + self.assertEqual(staff_user.natural_key(), ("staff",)) + def test_group_natural_key(self): users_group = Group.objects.create(name="users") self.assertEqual(Group.objects.get_by_natural_key("users"), users_group) + async def test_agroup_natural_key(self): + users_group = await Group.objects.acreate(name="users") + self.assertEqual(await Group.objects.aget_by_natural_key("users"), users_group) + class LoadDataWithoutNaturalKeysTestCase(TestCase): fixtures = ["regular.json"] @@ -157,6 +164,17 @@ class UserManagerTestCase(TransactionTestCase): is_superuser=False, ) + async def test_acreate_super_user_raises_error_on_false_is_superuser(self): + with self.assertRaisesMessage( + ValueError, "Superuser must have is_superuser=True." + ): + await User.objects.acreate_superuser( + username="test", + email="test@test.com", + password="test", + is_superuser=False, + ) + def test_create_superuser_raises_error_on_false_is_staff(self): with self.assertRaisesMessage(ValueError, "Superuser must have is_staff=True."): User.objects.create_superuser( @@ -166,6 +184,15 @@ class UserManagerTestCase(TransactionTestCase): is_staff=False, ) + async def test_acreate_superuser_raises_error_on_false_is_staff(self): + with self.assertRaisesMessage(ValueError, "Superuser must have is_staff=True."): + await User.objects.acreate_superuser( + username="test", + email="test@test.com", + password="test", + is_staff=False, + ) + def test_runpython_manager_methods(self): def forwards(apps, schema_editor): UserModel = apps.get_model("auth", "User") @@ -301,9 +328,7 @@ class AbstractUserTestCase(TestCase): @override_settings(PASSWORD_HASHERS=PASSWORD_HASHERS) async def test_acheck_password_upgrade(self): - user = await sync_to_async(User.objects.create_user)( - username="user", password="foo" - ) + user = await User.objects.acreate_user(username="user", password="foo") initial_password = user.password self.assertIs(await user.acheck_password("foo"), True) hasher = get_hasher("default") @@ -557,6 +582,12 @@ class AnonymousUserTests(SimpleTestCase): self.assertEqual(self.user.get_user_permissions(), set()) self.assertEqual(self.user.get_group_permissions(), set()) + async def test_properties_async_versions(self): + self.assertEqual(await self.user.groups.acount(), 0) + self.assertEqual(await self.user.user_permissions.acount(), 0) + self.assertEqual(await self.user.aget_user_permissions(), set()) + self.assertEqual(await self.user.aget_group_permissions(), set()) + def test_str(self): self.assertEqual(str(self.user), "AnonymousUser") diff --git a/tests/auth_tests/test_remote_user.py b/tests/auth_tests/test_remote_user.py index d3cf4b9da5..85de931c1a 100644 --- a/tests/auth_tests/test_remote_user.py +++ b/tests/auth_tests/test_remote_user.py @@ -1,12 +1,18 @@ from datetime import datetime, timezone from django.conf import settings -from django.contrib.auth import authenticate +from django.contrib.auth import aauthenticate, authenticate from django.contrib.auth.backends import RemoteUserBackend from django.contrib.auth.middleware import RemoteUserMiddleware from django.contrib.auth.models import User from django.middleware.csrf import _get_new_csrf_string, _mask_cipher_secret -from django.test import Client, TestCase, modify_settings, override_settings +from django.test import ( + AsyncClient, + Client, + TestCase, + modify_settings, + override_settings, +) @override_settings(ROOT_URLCONF="auth_tests.urls") @@ -30,6 +36,11 @@ class RemoteUserTest(TestCase): ) super().setUpClass() + def test_passing_explicit_none(self): + msg = "get_response must be provided." + with self.assertRaisesMessage(ValueError, msg): + RemoteUserMiddleware(None) + def test_no_remote_user(self): """Users are not created when remote user is not specified.""" num_users = User.objects.count() @@ -46,6 +57,18 @@ class RemoteUserTest(TestCase): self.assertTrue(response.context["user"].is_anonymous) self.assertEqual(User.objects.count(), num_users) + async def test_no_remote_user_async(self): + """See test_no_remote_user.""" + num_users = await User.objects.acount() + + response = await self.async_client.get("/remote_user/") + self.assertTrue(response.context["user"].is_anonymous) + self.assertEqual(await User.objects.acount(), num_users) + + response = await self.async_client.get("/remote_user/", **{self.header: ""}) + self.assertTrue(response.context["user"].is_anonymous) + self.assertEqual(await User.objects.acount(), num_users) + def test_csrf_validation_passes_after_process_request_login(self): """ CSRF check must access the CSRF token from the session or cookie, @@ -75,6 +98,31 @@ class RemoteUserTest(TestCase): response = csrf_client.post("/remote_user/", data, **headers) self.assertEqual(response.status_code, 200) + async def test_csrf_validation_passes_after_process_request_login_async(self): + """See test_csrf_validation_passes_after_process_request_login.""" + csrf_client = AsyncClient(enforce_csrf_checks=True) + csrf_secret = _get_new_csrf_string() + csrf_token = _mask_cipher_secret(csrf_secret) + csrf_token_form = _mask_cipher_secret(csrf_secret) + headers = {self.header: "fakeuser"} + data = {"csrfmiddlewaretoken": csrf_token_form} + + # Verify that CSRF is configured for the view + csrf_client.cookies.load({settings.CSRF_COOKIE_NAME: csrf_token}) + response = await csrf_client.post("/remote_user/", **headers) + self.assertEqual(response.status_code, 403) + self.assertIn(b"CSRF verification failed.", response.content) + + # This request will call django.contrib.auth.alogin() which will call + # django.middleware.csrf.rotate_token() thus changing the value of + # request.META['CSRF_COOKIE'] from the user submitted value set by + # CsrfViewMiddleware.process_request() to the new csrftoken value set + # by rotate_token(). Csrf validation should still pass when the view is + # later processed by CsrfViewMiddleware.process_view() + csrf_client.cookies.load({settings.CSRF_COOKIE_NAME: csrf_token}) + response = await csrf_client.post("/remote_user/", data, **headers) + self.assertEqual(response.status_code, 200) + def test_unknown_user(self): """ Tests the case where the username passed in the header does not exist @@ -90,6 +138,22 @@ class RemoteUserTest(TestCase): response = self.client.get("/remote_user/", **{self.header: "newuser"}) self.assertEqual(User.objects.count(), num_users + 1) + async def test_unknown_user_async(self): + """See test_unknown_user.""" + num_users = await User.objects.acount() + response = await self.async_client.get( + "/remote_user/", **{self.header: "newuser"} + ) + self.assertEqual(response.context["user"].username, "newuser") + self.assertEqual(await User.objects.acount(), num_users + 1) + await User.objects.aget(username="newuser") + + # Another request with same user should not create any new users. + response = await self.async_client.get( + "/remote_user/", **{self.header: "newuser"} + ) + self.assertEqual(await User.objects.acount(), num_users + 1) + def test_known_user(self): """ Tests the case where the username passed in the header is a valid User. @@ -106,6 +170,24 @@ class RemoteUserTest(TestCase): self.assertEqual(response.context["user"].username, "knownuser2") self.assertEqual(User.objects.count(), num_users) + async def test_known_user_async(self): + """See test_known_user.""" + await User.objects.acreate(username="knownuser") + await User.objects.acreate(username="knownuser2") + num_users = await User.objects.acount() + response = await self.async_client.get( + "/remote_user/", **{self.header: self.known_user} + ) + self.assertEqual(response.context["user"].username, "knownuser") + self.assertEqual(await User.objects.acount(), num_users) + # A different user passed in the headers causes the new user + # to be logged in. + response = await self.async_client.get( + "/remote_user/", **{self.header: self.known_user2} + ) + self.assertEqual(response.context["user"].username, "knownuser2") + self.assertEqual(await User.objects.acount(), num_users) + def test_last_login(self): """ A user's last_login is set the first time they make a @@ -128,6 +210,29 @@ class RemoteUserTest(TestCase): response = self.client.get("/remote_user/", **{self.header: self.known_user}) self.assertEqual(default_login, response.context["user"].last_login) + async def test_last_login_async(self): + """See test_last_login.""" + user = await User.objects.acreate(username="knownuser") + # Set last_login to something so we can determine if it changes. + default_login = datetime(2000, 1, 1) + if settings.USE_TZ: + default_login = default_login.replace(tzinfo=timezone.utc) + user.last_login = default_login + await user.asave() + + response = await self.async_client.get( + "/remote_user/", **{self.header: self.known_user} + ) + self.assertNotEqual(default_login, response.context["user"].last_login) + + user = await User.objects.aget(username="knownuser") + user.last_login = default_login + await user.asave() + response = await self.async_client.get( + "/remote_user/", **{self.header: self.known_user} + ) + self.assertEqual(default_login, response.context["user"].last_login) + def test_header_disappears(self): """ A logged in user is logged out automatically when @@ -148,6 +253,25 @@ class RemoteUserTest(TestCase): response = self.client.get("/remote_user/") self.assertEqual(response.context["user"].username, "modeluser") + async def test_header_disappears_async(self): + """See test_header_disappears.""" + await User.objects.acreate(username="knownuser") + # Known user authenticates + response = await self.async_client.get( + "/remote_user/", **{self.header: self.known_user} + ) + self.assertEqual(response.context["user"].username, "knownuser") + # During the session, the REMOTE_USER header disappears. Should trigger logout. + response = await self.async_client.get("/remote_user/") + self.assertTrue(response.context["user"].is_anonymous) + # verify the remoteuser middleware will not remove a user + # authenticated via another backend + await User.objects.acreate_user(username="modeluser", password="foo") + await self.async_client.alogin(username="modeluser", password="foo") + await aauthenticate(username="modeluser", password="foo") + response = await self.async_client.get("/remote_user/") + self.assertEqual(response.context["user"].username, "modeluser") + def test_user_switch_forces_new_login(self): """ If the username in the header changes between requests @@ -164,11 +288,35 @@ class RemoteUserTest(TestCase): # In backends that do not create new users, it is '' (anonymous user) self.assertNotEqual(response.context["user"].username, "knownuser") + async def test_user_switch_forces_new_login_async(self): + """See test_user_switch_forces_new_login.""" + await User.objects.acreate(username="knownuser") + # Known user authenticates + response = await self.async_client.get( + "/remote_user/", **{self.header: self.known_user} + ) + self.assertEqual(response.context["user"].username, "knownuser") + # During the session, the REMOTE_USER changes to a different user. + response = await self.async_client.get( + "/remote_user/", **{self.header: "newnewuser"} + ) + # The current user is not the prior remote_user. + # In backends that create a new user, username is "newnewuser" + # In backends that do not create new users, it is '' (anonymous user) + self.assertNotEqual(response.context["user"].username, "knownuser") + def test_inactive_user(self): User.objects.create(username="knownuser", is_active=False) response = self.client.get("/remote_user/", **{self.header: "knownuser"}) self.assertTrue(response.context["user"].is_anonymous) + async def test_inactive_user_async(self): + await User.objects.acreate(username="knownuser", is_active=False) + response = await self.async_client.get( + "/remote_user/", **{self.header: "knownuser"} + ) + self.assertTrue(response.context["user"].is_anonymous) + class RemoteUserNoCreateBackend(RemoteUserBackend): """Backend that doesn't create unknown users.""" @@ -190,6 +338,14 @@ class RemoteUserNoCreateTest(RemoteUserTest): self.assertTrue(response.context["user"].is_anonymous) self.assertEqual(User.objects.count(), num_users) + async def test_unknown_user_async(self): + num_users = await User.objects.acount() + response = await self.async_client.get( + "/remote_user/", **{self.header: "newuser"} + ) + self.assertTrue(response.context["user"].is_anonymous) + self.assertEqual(await User.objects.acount(), num_users) + class AllowAllUsersRemoteUserBackendTest(RemoteUserTest): """Backend that allows inactive users.""" @@ -201,6 +357,13 @@ class AllowAllUsersRemoteUserBackendTest(RemoteUserTest): response = self.client.get("/remote_user/", **{self.header: self.known_user}) self.assertEqual(response.context["user"].username, user.username) + async def test_inactive_user_async(self): + user = await User.objects.acreate(username="knownuser", is_active=False) + response = await self.async_client.get( + "/remote_user/", **{self.header: self.known_user} + ) + self.assertEqual(response.context["user"].username, user.username) + class CustomRemoteUserBackend(RemoteUserBackend): """ @@ -311,3 +474,16 @@ class PersistentRemoteUserTest(RemoteUserTest): response = self.client.get("/remote_user/") self.assertFalse(response.context["user"].is_anonymous) self.assertEqual(response.context["user"].username, "knownuser") + + async def test_header_disappears_async(self): + """See test_header_disappears.""" + await User.objects.acreate(username="knownuser") + # Known user authenticates + response = await self.async_client.get( + "/remote_user/", **{self.header: self.known_user} + ) + self.assertEqual(response.context["user"].username, "knownuser") + # Should stay logged in if the REMOTE_USER header disappears. + response = await self.async_client.get("/remote_user/") + self.assertFalse(response.context["user"].is_anonymous) + self.assertEqual(response.context["user"].username, "knownuser") diff --git a/tests/deprecation/test_middleware_mixin.py b/tests/deprecation/test_middleware_mixin.py index f4eafc14e3..7e86832e2b 100644 --- a/tests/deprecation/test_middleware_mixin.py +++ b/tests/deprecation/test_middleware_mixin.py @@ -6,7 +6,6 @@ from django.contrib.admindocs.middleware import XViewMiddleware from django.contrib.auth.middleware import ( AuthenticationMiddleware, LoginRequiredMiddleware, - RemoteUserMiddleware, ) from django.contrib.flatpages.middleware import FlatpageFallbackMiddleware from django.contrib.messages.middleware import MessageMiddleware @@ -48,7 +47,6 @@ class MiddlewareMixinTests(SimpleTestCase): LocaleMiddleware, MessageMiddleware, RedirectFallbackMiddleware, - RemoteUserMiddleware, SecurityMiddleware, SessionMiddleware, UpdateCacheMiddleware, From a417c0efb4b37fe9f59d7b982b2ecf276bf2e306 Mon Sep 17 00:00:00 2001 From: GappleBee Date: Sat, 14 Sep 2024 10:26:12 +0100 Subject: [PATCH 09/40] Fixed #35449 -- Fixed validation of array items in SplitArrayField when remove_trailing_nulls=True. --- django/contrib/postgres/forms/array.py | 2 +- tests/postgres_tests/test_array.py | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/django/contrib/postgres/forms/array.py b/django/contrib/postgres/forms/array.py index ddb022afc3..fd5cd219f8 100644 --- a/django/contrib/postgres/forms/array.py +++ b/django/contrib/postgres/forms/array.py @@ -228,7 +228,7 @@ class SplitArrayField(forms.Field): params={"nth": index + 1}, ) ) - cleaned_data.append(None) + cleaned_data.append(item) else: errors.append(None) cleaned_data, null_index = self._remove_trailing_nulls(cleaned_data) diff --git a/tests/postgres_tests/test_array.py b/tests/postgres_tests/test_array.py index ff0c4aabb1..ea7807687e 100644 --- a/tests/postgres_tests/test_array.py +++ b/tests/postgres_tests/test_array.py @@ -1339,6 +1339,22 @@ class TestSplitFormField(PostgreSQLSimpleTestCase): ], ) + def test_invalid_char_length_with_remove_trailing_nulls(self): + field = SplitArrayField( + forms.CharField(max_length=2, required=False), + size=3, + remove_trailing_nulls=True, + ) + with self.assertRaises(exceptions.ValidationError) as cm: + field.clean(["abc", "", ""]) + self.assertEqual( + cm.exception.messages, + [ + "Item 1 in the array did not validate: Ensure this value has at most 2 " + "characters (it has 3).", + ], + ) + def test_splitarraywidget_value_omitted_from_data(self): class Form(forms.ModelForm): field = SplitArrayField(forms.IntegerField(), required=False, size=2) From 7d9dd7b68fc7b1817e84095e687f82553a24d68d Mon Sep 17 00:00:00 2001 From: nessita <124304+nessita@users.noreply.github.com> Date: Mon, 7 Oct 2024 17:35:43 -0300 Subject: [PATCH 10/40] Updated translations from Transifex. Forwardport of e245f62d0052d7b15fa2a60926d59eeeefee9be1 from stable/5.1.x. --- django/conf/locale/cs/LC_MESSAGES/django.mo | Bin 29060 -> 30186 bytes django/conf/locale/cs/LC_MESSAGES/django.po | 82 ++-- django/conf/locale/dsb/LC_MESSAGES/django.mo | Bin 30694 -> 30724 bytes django/conf/locale/dsb/LC_MESSAGES/django.po | 27 +- .../conf/locale/es_AR/LC_MESSAGES/django.mo | Bin 29643 -> 29668 bytes .../conf/locale/es_AR/LC_MESSAGES/django.po | 29 +- django/conf/locale/fr/LC_MESSAGES/django.mo | Bin 30289 -> 30291 bytes django/conf/locale/fr/LC_MESSAGES/django.po | 4 +- django/conf/locale/ga/LC_MESSAGES/django.mo | Bin 14025 -> 31429 bytes django/conf/locale/ga/LC_MESSAGES/django.po | 441 ++++++++++++------ django/conf/locale/hsb/LC_MESSAGES/django.mo | Bin 30347 -> 30380 bytes django/conf/locale/hsb/LC_MESSAGES/django.po | 27 +- django/conf/locale/sk/LC_MESSAGES/django.mo | Bin 29942 -> 29965 bytes django/conf/locale/sk/LC_MESSAGES/django.po | 27 +- django/conf/locale/ug/LC_MESSAGES/django.mo | Bin 35453 -> 35467 bytes django/conf/locale/ug/LC_MESSAGES/django.po | 27 +- django/conf/locale/uk/LC_MESSAGES/django.mo | Bin 30194 -> 29855 bytes django/conf/locale/uk/LC_MESSAGES/django.po | 39 +- .../conf/locale/zh_Hans/LC_MESSAGES/django.mo | Bin 26927 -> 26944 bytes .../conf/locale/zh_Hans/LC_MESSAGES/django.po | 27 +- .../admin/locale/cs/LC_MESSAGES/django.mo | Bin 17736 -> 19004 bytes .../admin/locale/cs/LC_MESSAGES/django.po | 91 +++- .../admin/locale/cs/LC_MESSAGES/djangojs.mo | Bin 5851 -> 6596 bytes .../admin/locale/cs/LC_MESSAGES/djangojs.po | 84 +++- .../admin/locale/dsb/LC_MESSAGES/django.mo | Bin 18813 -> 19122 bytes .../admin/locale/dsb/LC_MESSAGES/django.po | 29 +- .../admin/locale/es/LC_MESSAGES/django.mo | Bin 19163 -> 19193 bytes .../admin/locale/es/LC_MESSAGES/django.po | 12 +- .../admin/locale/es_AR/LC_MESSAGES/django.mo | Bin 19032 -> 19355 bytes .../admin/locale/es_AR/LC_MESSAGES/django.po | 32 +- .../admin/locale/ga/LC_MESSAGES/django.mo | Bin 15075 -> 19428 bytes .../admin/locale/ga/LC_MESSAGES/django.po | 309 +++++++----- .../admin/locale/ga/LC_MESSAGES/djangojs.mo | Bin 5247 -> 6910 bytes .../admin/locale/ga/LC_MESSAGES/djangojs.po | 143 +++++- .../admin/locale/hsb/LC_MESSAGES/django.mo | Bin 18595 -> 18894 bytes .../admin/locale/hsb/LC_MESSAGES/django.po | 28 +- .../admin/locale/id/LC_MESSAGES/django.mo | Bin 17412 -> 17877 bytes .../admin/locale/id/LC_MESSAGES/django.po | 14 +- .../admin/locale/ko/LC_MESSAGES/django.mo | Bin 18721 -> 18815 bytes .../admin/locale/ko/LC_MESSAGES/django.po | 11 +- .../admin/locale/sk/LC_MESSAGES/django.mo | Bin 18706 -> 18945 bytes .../admin/locale/sk/LC_MESSAGES/django.po | 29 +- .../admin/locale/ug/LC_MESSAGES/django.mo | Bin 22887 -> 23241 bytes .../admin/locale/ug/LC_MESSAGES/django.po | 32 +- .../admindocs/locale/ga/LC_MESSAGES/django.mo | Bin 1940 -> 6786 bytes .../admindocs/locale/ga/LC_MESSAGES/django.po | 110 +++-- .../auth/locale/cs/LC_MESSAGES/django.mo | Bin 7836 -> 8888 bytes .../auth/locale/cs/LC_MESSAGES/django.po | 65 ++- .../auth/locale/dsb/LC_MESSAGES/django.mo | Bin 8249 -> 9303 bytes .../auth/locale/dsb/LC_MESSAGES/django.po | 61 ++- .../auth/locale/es/LC_MESSAGES/django.mo | Bin 9039 -> 9100 bytes .../auth/locale/es/LC_MESSAGES/django.po | 14 +- .../auth/locale/es_AR/LC_MESSAGES/django.mo | Bin 8244 -> 9235 bytes .../auth/locale/es_AR/LC_MESSAGES/django.po | 59 ++- .../auth/locale/ga/LC_MESSAGES/django.mo | Bin 3572 -> 9476 bytes .../auth/locale/ga/LC_MESSAGES/django.po | 143 ++++-- .../auth/locale/hsb/LC_MESSAGES/django.mo | Bin 8082 -> 9100 bytes .../auth/locale/hsb/LC_MESSAGES/django.po | 59 ++- .../auth/locale/sk/LC_MESSAGES/django.mo | Bin 7917 -> 8862 bytes .../auth/locale/sk/LC_MESSAGES/django.po | 58 ++- .../auth/locale/ug/LC_MESSAGES/django.mo | Bin 9516 -> 10714 bytes .../auth/locale/ug/LC_MESSAGES/django.po | 56 ++- .../auth/locale/zh_Hans/LC_MESSAGES/django.mo | Bin 6902 -> 7741 bytes .../auth/locale/zh_Hans/LC_MESSAGES/django.po | 54 ++- .../locale/ga/LC_MESSAGES/django.mo | Bin 1097 -> 1081 bytes .../locale/ga/LC_MESSAGES/django.po | 17 +- .../flatpages/locale/ga/LC_MESSAGES/django.mo | Bin 2191 -> 2351 bytes .../flatpages/locale/ga/LC_MESSAGES/django.po | 26 +- .../gis/locale/ga/LC_MESSAGES/django.mo | Bin 1420 -> 1957 bytes .../gis/locale/ga/LC_MESSAGES/django.po | 32 +- .../humanize/locale/ga/LC_MESSAGES/django.mo | Bin 5112 -> 6346 bytes .../humanize/locale/ga/LC_MESSAGES/django.po | 344 +++++--------- .../postgres/locale/cs/LC_MESSAGES/django.mo | Bin 3388 -> 3418 bytes .../postgres/locale/cs/LC_MESSAGES/django.po | 18 +- .../postgres/locale/ga/LC_MESSAGES/django.mo | Bin 0 -> 3652 bytes .../postgres/locale/ga/LC_MESSAGES/django.po | 125 +++++ .../redirects/locale/ga/LC_MESSAGES/django.mo | Bin 1075 -> 1182 bytes .../redirects/locale/ga/LC_MESSAGES/django.po | 25 +- .../redirects/locale/ko/LC_MESSAGES/django.mo | Bin 1134 -> 1152 bytes .../redirects/locale/ko/LC_MESSAGES/django.po | 13 +- .../sessions/locale/ko/LC_MESSAGES/django.mo | Bin 700 -> 653 bytes .../sessions/locale/ko/LC_MESSAGES/django.po | 13 +- .../sites/locale/ga/LC_MESSAGES/django.mo | Bin 683 -> 814 bytes .../sites/locale/ga/LC_MESSAGES/django.po | 9 +- .../sites/locale/ko/LC_MESSAGES/django.mo | Bin 807 -> 744 bytes .../sites/locale/ko/LC_MESSAGES/django.po | 13 +- docs/releases/5.1.2.txt | 3 +- 87 files changed, 1913 insertions(+), 948 deletions(-) create mode 100644 django/contrib/postgres/locale/ga/LC_MESSAGES/django.mo create mode 100644 django/contrib/postgres/locale/ga/LC_MESSAGES/django.po diff --git a/django/conf/locale/cs/LC_MESSAGES/django.mo b/django/conf/locale/cs/LC_MESSAGES/django.mo index 66e08fed436e1d7ef4089eb56a50c9fa2b22faed..95086e3d52e9217bbba809a355eb3ec8203cfb2f 100644 GIT binary patch delta 8753 zcmb8!33wIdy~pth34|o90c3|sAdrL*AnXL$!VbzNLRf^8oFRlH=cH#zZ)oLsi{e5> zG!}}Wm8F6TZiiBfK$Vb7TNO71(E=*BC`hfKy&_A!-(TjmAbPTB+2s26eQo01n3SxE)pR@5p~vawp5m z#ojmwOK~v%8r$GWY=;+-|Ew0B-RpCZ@`yFXO;}6JiMy~q6*n2T8J{ukH15U}>b;Eh z@MEOk)?Y9VKf%U$&YZu53FNP0LyWgAt10)lnvu{AZES$uum$!+RUB!Yh&n$5lW`6* zSymaUyb=@f4vfc@*b=KyBj1Ky@gVB_Ic&-Ot*=O^fdq!r6q})XYNIM;vJ~^`%&$`idu@dP#x1x7 z`=_xV@O>PLw=GWb4u10OfH?TD(rMq@P&1^1m3u_W;fc|vmUu(JC6s$2m zg_`1hsNH)M)!+rx?oZ6HtQ)X9s-a=1kx$2bEW)Yy3hF^hX8q`^m5vEG1sh_1#3Tw( zk5dW8;k{UZt56r5M@`vfRD-cS-14@VO}-0iNv2~g=9~O{)OB8*gQch&A2deZB%uqB zp+@*2YRxX1@_(3o{Vex}Ntnp_R;Z5J*a*{%Ii`F#s^gAo8JE9%AgH@P|ZSf6MJ7-Y!&SR{e z|F21?rgo6! z>bf2|%ztwd!$`=f#sXsq)v*<5;{&J>JcrsVFQP{BrYS#y>c|Nkf*+ak4t*_aEcvd; z7_AcYeyH}QSX9U6qh`=Sbv$g! zm!US{3R8X`s$Nxp=6?){%@mBoGg!NJ1Kb94QEQ!t$v6#l-izv(&*a0{o_qvVe?6*0 zPhul{9(Dab)MNe@)-HuEP|tb{bQ|o2x^RGT7;4v#MNRc|<80$?sE&A1yS&6$j=E78 zJ7X25VicKu>j<(9tVrS@_Z2!6^=4a&8p&GJn=gv3@euO6VVy>GxFIicO>raCja#8M zT{~=n!%_8SpawL{xWHJ1v>UPfBvkQk)JRsMruZS$2sWS^*p2zPA2r1t*kQVHChEFg zs2Li7-Eb(j#X{87-;R1rSK}&NkFk3GGg%1TFdNmtAXJBj;YA#UuVXI1JjXEMM)$_2 zP$T^mb%QI$ru-5qpK9!H9B-V9y3U8q_5AY7ZR8IQ$&-9{Caz@LSYl9ZBGQs~e_ZJa$LD z2YR6%v&pEXnS-iVgl(`4wV766LtKZ6xXHK!_4vJrJ@IYi)xo!yTYoUN)AK)ygnBd| zTVavO-;PP-??zsdR+Y*B2~)`*L3Q{WW6Wf?;|Zvl>4rUUyvc_!k^CCtMr@$xe>({^ z6h%$hOQ^@~HPmBr0yV-fQ6s*B>TuJW+^^rZXp89qIgUqY;z#*Y$SW$TZ}F>GnxG1jV?JhJ#2(ibbtBf;z3+K-y4 zOQB^-oXDc{Un>mW{wFiiEl#R9h@ol#Sp zj_T<+Y>d-U^%kN=T#9;cY(~xCyQq$SVDhI>13QE2$OUu$3N|7ix6mz*G&hO%s0-4J z*{B;2L^Uu5b$$wJsb-@(6hL)!8LHuXQP-`(-{Kb3?w{vzJLof3xJImHreFnX6RkqM z(YB&){FHGgP9VR}an=~0!zc&uVzL<$6*c#VhXM6^A{UL0RZ3?xAB9_&Ugep!! zJ>NyB$7LyM#4Axt@-S+Oqo@(RWX`{inu#N*wf`7r;3ufPlNJ5*b-ePxz{ZJK$qDGpBTJxExCGi_8jmxn&<@cjLH1?rp=O5dl)FUhPeCySTI0u1Z@#^#&G-Ro%D=*{*u2Dj!3;okXb9@Yd8m5hQA^`s zEdB)5p@{Kr)O+Fqti7L3sN!Bsz*jI4UqwyT5mSB@wW;Du-KCg|TB0x};ZIRFx(73G zHR{V}H>zW2QSHW;S=Qs2jGFmKl!Pwag&NU5REG{?ix@hBC&-`lS=RsPyx$%1Z^~VF z8-H&+fZB9_H2F77{;=_Vof^X;W^ZZ&Kobf6|8TK^?&4cFbP$!CF(})Q8Sl< z8b}XgUt_L0pJ(zn8E0aQp8xqIG~xxuLSqrCVX!lo`f~QeEK8-AW?LW<3!e@xrh%PGRc*>>rPrW}T6OR*H zh~Cs`MzC$HjYQqil|)y{U&7xL>xstP9~dns>W;5TXfz)Z#|Rxc=6n;>6gI^(wP)Nv z>XHAo>Jd{(Ya<^fDhVB9D4T#2un|@hn(2fX?ypy7GeXCwgr=$wF_y}GaUJn2p+nQE zBbIX>?19%F1!Nu}enO1koF2hz5B)3qClv7WUwaJD_n(ew*EIAd`K`n+39Yw|kBLsy znND;e%?D5IZ^lot?ij|obd&j;G2OJQN7y!HB9~Z9M246O&B@$EB#|GBUlM7=K0?Pq z;?CL>-+lN2!9KHQnd{9d%O?MY$&57Wy>W+0=W#xp^bGepcl}pUkW6SZ>L@4l8jhh- z3eF&Ala6yQs{Ja~6VQ!(Lt+@|_V_63=tR7%1cx^C2IB8TCehNgq2GrFTK_>5JWOUV z-iPCe+ld>AKBn>o(l?VHk97x6r8SST3?h|iLEc|?()haMTysLlJH)rODf5Rrem*v? zDO_pNrMQNeV=h*){vL1yvxtGjDPk&-O!<#d$328zI6A%|5;->)yQ_d>Ke2+CPSo9> zB>(G#7-epzAB)kXc@@+)DW-(lta1X&<)3SMVyKpY}@;Vxm4!B9{M$%15zfbHm zWxvHdVlwCIrgsVXwM0+K-owqrQDUAd3?+2jN}Q`r@&9OymvJ^RlnZslV?KIobNtL= zDv?Qf7E#~Sn~6gx?@25tGKlSjj?Tnf&QBsDpOg6m@n@p$NHdM}H9p6Q2Z(I)kKq+! z1W|V+kcbk8>I#et@iUX2hVdpXwh>?bbAtF+FbawYeRLeaJ;YnYC}K6yhWIP-0x^cr z(TckNkg{O&M5qq^jzaw#y_)p>uVh1spm`Rin=ZWWu zkz8DNbRh8rF@>^8*p28x=y;I0g{V-5qb)I-XieRBRgjkM^@N;Iaha15j6T{SC9bvO z3k5u-_M~vYTO3?$r_b;QJig+L=pMVW{+uj381e){#l9kYQNUkjr=|NBEeblJj9`}S zWEW+Brywo8!c$u8UBI7Vr;n<9rzA%u9-r3^`fa~2`gK}DOrx~)@_;|&FZ7pY1gk#k z-ll3^_u_{BGEcG3_IaW&bRQ7g*_tr5qMz;YdIL@{=w|!@o5BIg42XV_IjCWz)bRuz zI~Xn~D-PM7kga@(+xx<08D4vlKTwu!P5t3Y!Ryp2^Z#&5$^TL*7)|T@QcQxcw3r?_ z-i+vxehXvkR~9V}2crE3%}bm-(c`nHddi)eefH4BeqUwbQm14@p%x=tmR-1XSeBjB zyH8G5PVbz4iIY9PqOhmP>3NIeDH~$vEp-Z6sKudB`H)_{JmuxlBcr})kUAq&v(EAQ zs(08WtYytcR?TCl2eq7TCL?-i!r_F-9M6*CVCca5ki&8mRN5g=$Zs$9dwu?p$1bQW z^)PR>-F6o;BWU}oHwOI$B~F=L;glAaFd@ZuNx)wcwzKSV|AG6fclbO@obT)fpQpTL z-F3G|`uFb-x>I6%t2dT9Rp%$StlBx_a*Jy>2^)cZ5Uy%GbA9vbz3SOgr^5F7%c`IB zRYup%td8xf{bG$&HIKGQKX=dgoC5zfyQV0=I3Y5{>(p?gkYlq8gVj6AY)`2ZEce&k z^PQ~|F0J0kV61 A3;+NC delta 7659 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 Io;p7CKi;@*3jhEB diff --git a/django/conf/locale/cs/LC_MESSAGES/django.po b/django/conf/locale/cs/LC_MESSAGES/django.po index bf85e0c41d..14f5ef9684 100644 --- a/django/conf/locale/cs/LC_MESSAGES/django.po +++ b/django/conf/locale/cs/LC_MESSAGES/django.po @@ -3,10 +3,11 @@ # Translators: # Claude Paroz , 2020 # Jannis Leidel , 2011 -# Jan Papež , 2012 -# trendspotter , 2022 +# Jan Papež , 2012,2024 +# Jiří Podhorecký , 2024 +# Jiří Podhorecký , 2022 # Jirka Vejrazka , 2011 -# trendspotter , 2020 +# Jiří Podhorecký , 2020 # Tomáš Ehrlich , 2015 # Vláďa Macek , 2012-2014 # Vláďa Macek , 2015-2022 @@ -14,10 +15,10 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-05-17 05:23-0500\n" -"PO-Revision-Date: 2022-07-25 06:49+0000\n" -"Last-Translator: trendspotter \n" -"Language-Team: Czech (http://www.transifex.com/django/django/language/cs/)\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 06:49+0000\n" +"Last-Translator: Jan Papež , 2012,2024\n" +"Language-Team: Czech (http://app.transifex.com/django/django/language/cs/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -58,6 +59,9 @@ msgstr "bosensky" msgid "Catalan" msgstr "katalánsky" +msgid "Central Kurdish (Sorani)" +msgstr "Střední kurdština (soranština)" + msgid "Czech" msgstr "česky" @@ -298,6 +302,9 @@ msgstr "tatarsky" msgid "Udmurt" msgstr "udmurtsky" +msgid "Uyghur" +msgstr "Ujgurština" + msgid "Ukrainian" msgstr "ukrajinsky" @@ -345,6 +352,9 @@ msgstr "Stránka je bez výsledků" msgid "Enter a valid value." msgstr "Zadejte platnou hodnotu." +msgid "Enter a valid domain name." +msgstr "Zadejte platný název domény." + msgid "Enter a valid URL." msgstr "Zadejte platnou adresu URL." @@ -368,14 +378,18 @@ msgstr "" "Zadejte platný identifikátor složený pouze z písmen, čísel, podtržítek a " "pomlček typu Unicode." -msgid "Enter a valid IPv4 address." -msgstr "Zadejte platnou adresu typu IPv4." +#, python-format +msgid "Enter a valid %(protocol)s address." +msgstr "Zadejte platnou %(protocol)s adresu." -msgid "Enter a valid IPv6 address." -msgstr "Zadejte platnou adresu typu IPv6." +msgid "IPv4" +msgstr "IPv4" -msgid "Enter a valid IPv4 or IPv6 address." -msgstr "Zadejte platnou adresu typu IPv4 nebo IPv6." +msgid "IPv6" +msgstr "IPv6" + +msgid "IPv4 or IPv6" +msgstr "IPv4 nebo IPv6" msgid "Enter only digits separated by commas." msgstr "Zadejte pouze číslice oddělené čárkami." @@ -397,6 +411,15 @@ msgid "Ensure this value is a multiple of step size %(limit_value)s." msgstr "" "Ujistěte se, že tato hodnota je násobkem velikosti kroku %(limit_value)s." +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Zajistěte, aby tato hodnota byla %(limit_value)s násobkem velikosti kroku , " +"počínaje %(offset)s, např. %(offset)s, %(valid_value1)s, %(valid_value2)s, a " +"tak dále." + #, python-format msgid "" "Ensure this value has at least %(limit_value)d character (it has " @@ -533,6 +556,9 @@ msgstr "Pravdivost (buď Ano (True), nebo Ne (False))" msgid "String (up to %(max_length)s)" msgstr "Řetězec (max. %(max_length)s znaků)" +msgid "String (unlimited)" +msgstr "Řetězec (neomezený)" + msgid "Comma-separated integers" msgstr "Celá čísla oddělená čárkou" @@ -806,18 +832,18 @@ msgstr "" #, python-format msgid "Please submit at most %(num)d form." msgid_plural "Please submit at most %(num)d forms." -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "Odešlete prosím nejvíce %(num)d formulář." +msgstr[1] "Odešlete prosím nejvíce %(num)d formuláře." +msgstr[2] "Odešlete prosím nejvíce %(num)d formulářů." +msgstr[3] "Odešlete prosím nejvíce %(num)d formulářů." #, python-format msgid "Please submit at least %(num)d form." msgid_plural "Please submit at least %(num)d forms." -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "Odešlete prosím alespoň %(num)d formulář." +msgstr[1] "Odešlete prosím alespoň %(num)d formuláře." +msgstr[2] "Odešlete prosím alespoň %(num)d formulářů." +msgstr[3] "Odešlete prosím alespoň %(num)d formulářů." msgid "Order" msgstr "Pořadí" @@ -1233,8 +1259,8 @@ msgid "" "If you are using the tag or " "including the “Referrer-Policy: no-referrer” header, please remove them. The " "CSRF protection requires the “Referer” header to do strict referer checking. " -"If you’re concerned about privacy, use alternatives like for links to third-party sites." +"If you’re concerned about privacy, use alternatives like for links to third-party sites." msgstr "" "Pokud používáte značku nebo " "záhlaví \"Referrer-Policy: no-referrer\", odeberte je. Ochrana typu CSRF " @@ -1334,13 +1360,13 @@ msgstr "" #, python-format msgid "" "You are seeing this page because DEBUG=True is in your settings file and you have not configured any " -"URLs." +"%(version)s/ref/settings/#debug\" target=\"_blank\" " +"rel=\"noopener\">DEBUG=True is in your settings file and you have not " +"configured any URLs." msgstr "" "Tuto zprávu vidíte, protože máte v nastavení Djanga zapnutý vývojový režim " -"DEBUG=True a zatím nemáte " +"DEBUG=True a zatím nemáte " "nastavena žádná URL." msgid "Django Documentation" diff --git a/django/conf/locale/dsb/LC_MESSAGES/django.mo b/django/conf/locale/dsb/LC_MESSAGES/django.mo index 645e6c7c446bde1a393cf719d01d18eeeac04abc..4d70da4f1c888defb4a0a288795eaced6d63ed64 100644 GIT binary patch delta 7724 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 Dh-XUU diff --git a/django/conf/locale/dsb/LC_MESSAGES/django.po b/django/conf/locale/dsb/LC_MESSAGES/django.po index e7c0fb6ce5..4448d1a2d3 100644 --- a/django/conf/locale/dsb/LC_MESSAGES/django.po +++ b/django/conf/locale/dsb/LC_MESSAGES/django.po @@ -1,14 +1,14 @@ # This file is distributed under the same license as the Django package. # # Translators: -# Michael Wolf , 2016-2023 +# Michael Wolf , 2016-2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-09-18 11:41-0300\n" -"PO-Revision-Date: 2023-12-04 06:49+0000\n" -"Last-Translator: Michael Wolf , 2016-2023\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 06:49+0000\n" +"Last-Translator: Michael Wolf , 2016-2024\n" "Language-Team: Lower Sorbian (http://app.transifex.com/django/django/" "language/dsb/)\n" "MIME-Version: 1.0\n" @@ -344,6 +344,9 @@ msgstr "Toś ten bok njewopśimujo wuslědki" msgid "Enter a valid value." msgstr "Zapódajśo płaśiwu gódnotu." +msgid "Enter a valid domain name." +msgstr "Zapódajśo płaśiwe domenowe mě." + msgid "Enter a valid URL." msgstr "Zapódajśo płaśiwy URL." @@ -367,14 +370,18 @@ msgstr "" "Zapódajśo płaśiwe „adresowe mě“, kótarež jano wopśimujo unicodowe pismiki, " "licby, pódmužki abo wězawki." -msgid "Enter a valid IPv4 address." -msgstr "Zapódajśo płaśiwu IPv4-adresu." +#, python-format +msgid "Enter a valid %(protocol)s address." +msgstr "Zapódajśo płaśiwu %(protocol)s-adresu." -msgid "Enter a valid IPv6 address." -msgstr "Zapódajśo płaśiwu IPv6-adresu." +msgid "IPv4" +msgstr "IPv4" -msgid "Enter a valid IPv4 or IPv6 address." -msgstr "Zapódajśo płaśiwu IPv4- abo IPv6-adresu." +msgid "IPv6" +msgstr "IPv6" + +msgid "IPv4 or IPv6" +msgstr "IPv4 abo IPv6" msgid "Enter only digits separated by commas." msgstr "Zapódajśo jano cyfry źělone pśez komy." diff --git a/django/conf/locale/es_AR/LC_MESSAGES/django.mo b/django/conf/locale/es_AR/LC_MESSAGES/django.mo index 5f62b7125a91c0b4831e062bdd3dfa5ebe350c53..cdb8444a35e3dbc7b389884e9af7fe6f0d775c89 100644 GIT binary patch delta 7765 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, 2011 # lardissone , 2014 -# Natalia (Django Fellow), 2023 +# Natalia, 2023 # poli , 2014 -# Ramiro Morales, 2013-2023 +# Ramiro Morales, 2013-2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-09-18 11:41-0300\n" -"PO-Revision-Date: 2023-12-04 06:49+0000\n" -"Last-Translator: Natalia (Django Fellow), 2023\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 06:49+0000\n" +"Last-Translator: Ramiro Morales, 2013-2024\n" "Language-Team: Spanish (Argentina) (http://app.transifex.com/django/django/" "language/es_AR/)\n" "MIME-Version: 1.0\n" @@ -347,6 +347,9 @@ msgstr "Esa página no contiene resultados" msgid "Enter a valid value." msgstr "Introduzca un valor válido." +msgid "Enter a valid domain name." +msgstr "Introduzca un nombre de dominio válido." + msgid "Enter a valid URL." msgstr "Introduzca una URL válida." @@ -368,14 +371,18 @@ msgstr "" "Introduzca un “slug” compuesto por letras Unicode, números, guiones bajos o " "guiones." -msgid "Enter a valid IPv4 address." -msgstr "Introduzca una dirección IPv4 válida." +#, python-format +msgid "Enter a valid %(protocol)s address." +msgstr "Introduzca una dirección de %(protocol)s válida." -msgid "Enter a valid IPv6 address." -msgstr "Introduzca una dirección IPv6 válida." +msgid "IPv4" +msgstr "IPv4" -msgid "Enter a valid IPv4 or IPv6 address." -msgstr "Introduzca una dirección IPv4 o IPv6 válida." +msgid "IPv6" +msgstr "IPv6" + +msgid "IPv4 or IPv6" +msgstr "IPv4 o IPv6" msgid "Enter only digits separated by commas." msgstr "Introduzca sólo dígitos separados por comas." diff --git a/django/conf/locale/fr/LC_MESSAGES/django.mo b/django/conf/locale/fr/LC_MESSAGES/django.mo index 3178ac8effe46287a1187120d135f7e15a79d53b..bf4a0fe19f99750858318e225f297b3ca2328221 100644 GIT binary patch delta 2256 zcmXZeYfP7A7{~F8;Qt2{!%*U2`Y(t$Y!#? zHg0k@ZlrQSkYZ-%Ys}Jd5-V^96S1h)Yzj;8GA^!TF5bZWIJ2|$X6x{mN6j9@oK0p7 zZQEwEQ#gX8Y-@vAHJ)+*!5DF6qXlz=U5zYG;$08X^;bu(2R<{#XaSy69Z{i_5 zhIeAt*6_Y!)P}23_c!4RY{O(cit#w$*9QXzQ4+(r8%O*?c5`?`E^49Wn2DvBfc2cBF*9Sc!~m7&(HM9r(lv+Qq;3}Pe}wuKcIqY5cQb!H8!wd?T?+=$Az zpbBb3ovZ_SjBF2TgY%eNo!#Gca+7 zSsKRN5>#OiV*%Eo3V9Y)Xn-p4i09u%b>al>#M2mPLMjn&n5E+b*p07ZKk9YN*=1IR zwRi;k@O8{@4-5DVb>cD9(?5Ya`4x|Eq6*9C2oDrP#bq7zKf<7bL_BW5C~ib`;4!Sg zc2sAEP#gV)y3abp6Gc&-NyAjkLv?1QyB2eat5EB9dp_u-|GKf)C-kG9+A-7#uA>Tz zc7+Sh!$jgm9xp+)^j?f&vAYUY;969{l^)l*4R{~<=72#ygBMY)A4YwMe!zz?V|N%g zqgs0m@5WE?e*6xzFyYDYp<0G2_z_eAHSQ+V{4J<2?P1isV8AB~qMrI8Ovclgho7P* z{^^$*=q_jC80JBIp6#!>5hiNRcpeZnMa!|!oEUiADl>Mgm3F}#I(SeHI+ zwhC*p17E>ToW+CKu#c}HUU18w;V&ogF!HNg`F<<4at1^DdG~P&^>7p%2>+4Tj@85; bd;A}&;QG;-^q)#2b>qYB`$i{fdJF#txrZcA delta 2254 zcmXZeZ%md|7{~GJk-tKaXdnm-l<_Y&q-lhO;Rp)@(lCS=B8fs2gGy|*Wsj@Le3NA? z4JN!u7U~vR)Rt|$u(iy!+Q_xcWo9xV$J|{1=4{mW$9=u}oa?&Jea>~R=iKP|+0f){ z=u~AwIL^$zsxeE(NnDT97=s11W>>Hnf5F9%F&A%Qe#q>zO=jiz>t?eu%&s$IXxp}! z9mg>wWerc5RpUwbZ_FaDsJHO^U`M^#T_j$^yYUDv$1gAqr`$PQMx45p;&3(QU^8am zJ}kr`T!CjX9k2WI=mxVM;v8(l{)TWc;U5y~NGxeIQ%4@hSZsE8p(^f1b><-M!^4<@ zOP>thD?)9!7WIBT-h(Z;5Z}TG9Q5bIVFuA8MzIse{6T6{@WOJ`LMt&9*I*>pq6(?Q zC~QK_YegNP6E&|F@4%PcKF{}~3JSl=Koz}*L;QyC;}~&ev)K&(fm-P2ZNWxYP$!LpT(sZwS&`P zrdy0E>>(_`8dM>BP=)SA75Jv--$8X^2;1-khBYC9h%d{Q;419IJ{&-Oj@diS9>Hon zg#CCBb9V&=e1bah1nTymMV#3^7>n>crs0BTf=iWwD)?bk0gt+yQS-N={?hJ8%?l6ugkjXJAHjuq0&{U3HSs6U zUvj5We{yf4I+FNo@TWBe)sa3_N8U!QH{kIxEG0gPh5G)lGSKZ#=nB5uTs%r#jN15H zjKxXRMi)K*8!ii(UBf60byEz_V|s#<-$EVeKaV4y3-WR9B8=4cpW=!1`2?S$n};f3 zrN^t>HK^9Eb<5oisFPNs3a&>L+~T&Q3hH)uV}!o{ml)`US5PnPM=kUQF2EzGLIzO_ z47Myo|aWd3%EYNNmSy;!_^~ Xiz>Kw{P*NbB@tCUUE|->94P!BR=Om! diff --git a/django/conf/locale/fr/LC_MESSAGES/django.po b/django/conf/locale/fr/LC_MESSAGES/django.po index 291e051703..253672ee44 100644 --- a/django/conf/locale/fr/LC_MESSAGES/django.po +++ b/django/conf/locale/fr/LC_MESSAGES/django.po @@ -14,7 +14,7 @@ msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-05-22 11:46-0300\n" -"PO-Revision-Date: 2024-08-07 06:49+0000\n" +"PO-Revision-Date: 2024-10-07 06:49+0000\n" "Last-Translator: Claude Paroz , 2013-2024\n" "Language-Team: French (http://app.transifex.com/django/django/language/fr/)\n" "MIME-Version: 1.0\n" @@ -228,7 +228,7 @@ msgid "Nepali" msgstr "Népalais" msgid "Dutch" -msgstr "Hollandais" +msgstr "Néerlandais" msgid "Norwegian Nynorsk" msgstr "Norvégien nynorsk" diff --git a/django/conf/locale/ga/LC_MESSAGES/django.mo b/django/conf/locale/ga/LC_MESSAGES/django.mo index c2a8a88d70f7cef96f129fd807ff954b33f53005..e55658a3227204974e10761a8e399c021f4564f0 100644 GIT binary patch literal 31429 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 GY5xJjEKL3Y diff --git a/django/conf/locale/ga/LC_MESSAGES/django.po b/django/conf/locale/ga/LC_MESSAGES/django.po index 2b1b5289e1..21a1e19712 100644 --- a/django/conf/locale/ga/LC_MESSAGES/django.po +++ b/django/conf/locale/ga/LC_MESSAGES/django.po @@ -1,6 +1,7 @@ # This file is distributed under the same license as the Django package. # # Translators: +# Aindriú Mac Giolla Eoin, 2024 # Claude Paroz , 2020 # Jannis Leidel , 2011 # John Moylan , 2013 @@ -13,10 +14,10 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-05-19 20:23+0200\n" -"PO-Revision-Date: 2020-07-14 21:42+0000\n" -"Last-Translator: Transifex Bot <>\n" -"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 06:49+0000\n" +"Last-Translator: Aindriú Mac Giolla Eoin, 2024\n" +"Language-Team: Irish (http://app.transifex.com/django/django/language/ga/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -31,7 +32,7 @@ msgid "Arabic" msgstr "Araibis" msgid "Algerian Arabic" -msgstr "" +msgstr "Araibis na hAilgéire" msgid "Asturian" msgstr "Astúiris" @@ -57,6 +58,9 @@ msgstr "Boisnis" msgid "Catalan" msgstr "Catalóinis" +msgid "Central Kurdish (Sorani)" +msgstr "Coirdis Láir (Sorani)" + msgid "Czech" msgstr "Seicis" @@ -70,7 +74,7 @@ msgid "German" msgstr "Gearmáinis" msgid "Lower Sorbian" -msgstr "" +msgstr "Sorbais Íochtarach" msgid "Greek" msgstr "Gréigis" @@ -94,7 +98,7 @@ msgid "Argentinian Spanish" msgstr "Spáinnis na hAirgintíne" msgid "Colombian Spanish" -msgstr "" +msgstr "Spáinnis na Colóime" msgid "Mexican Spanish" msgstr "Spáinnis Mheicsiceo " @@ -142,13 +146,13 @@ msgid "Croatian" msgstr "Cróitis" msgid "Upper Sorbian" -msgstr "" +msgstr "Sorbian Uachtarach" msgid "Hungarian" msgstr "Ungáiris" msgid "Armenian" -msgstr "" +msgstr "Airméinis" msgid "Interlingua" msgstr "Interlingua" @@ -157,7 +161,7 @@ msgid "Indonesian" msgstr "Indinéisis" msgid "Igbo" -msgstr "" +msgstr "Igbo" msgid "Ido" msgstr "Ido" @@ -175,7 +179,7 @@ msgid "Georgian" msgstr "Seoirsis" msgid "Kabyle" -msgstr "" +msgstr "Cabaill" msgid "Kazakh" msgstr "Casaicis" @@ -190,7 +194,7 @@ msgid "Korean" msgstr "Cóiréis" msgid "Kyrgyz" -msgstr "" +msgstr "Chirgeastáin" msgid "Luxembourgish" msgstr "Lucsamburgach" @@ -213,11 +217,14 @@ msgstr "Mongóilis" msgid "Marathi" msgstr "Maraitis" +msgid "Malay" +msgstr "Malaeis" + msgid "Burmese" msgstr "Burmais" msgid "Norwegian Bokmål" -msgstr "" +msgstr "Ioruais Bokmål" msgid "Nepali" msgstr "Neipeailis" @@ -268,7 +275,7 @@ msgid "Swedish" msgstr "Sualainnis" msgid "Swahili" -msgstr "" +msgstr "Svahaílis" msgid "Tamil" msgstr "Tamailis" @@ -277,22 +284,25 @@ msgid "Telugu" msgstr "Teileagúis" msgid "Tajik" -msgstr "" +msgstr "Táidsíc" msgid "Thai" msgstr "Téalainnis" msgid "Turkmen" -msgstr "" +msgstr "Tuircméinis" msgid "Turkish" msgstr "Tuircis" msgid "Tatar" -msgstr "" +msgstr "Tatairis" msgid "Udmurt" -msgstr "" +msgstr "Udmurt" + +msgid "Uyghur" +msgstr "Uighur" msgid "Ukrainian" msgstr "Úcráinis" @@ -301,7 +311,7 @@ msgid "Urdu" msgstr "Urdais" msgid "Uzbek" -msgstr "" +msgstr "Úisbéicis" msgid "Vietnamese" msgstr "Vítneamais" @@ -316,7 +326,7 @@ msgid "Messages" msgstr "Teachtaireachtaí" msgid "Site Maps" -msgstr "" +msgstr "Léarscáileanna Suímh" msgid "Static Files" msgstr "Comhaid Statach" @@ -324,45 +334,61 @@ msgstr "Comhaid Statach" msgid "Syndication" msgstr "Sindeacáitiú" +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + msgid "That page number is not an integer" -msgstr "" +msgstr "Ní slánuimhir í an uimhir leathanaigh sin" msgid "That page number is less than 1" -msgstr "" +msgstr "Tá uimhir an leathanaigh sin níos lú ná 1" msgid "That page contains no results" -msgstr "" +msgstr "Níl aon torthaí ar an leathanach sin" msgid "Enter a valid value." msgstr "Iontráil luach bailí" +msgid "Enter a valid domain name." +msgstr "Cuir isteach ainm fearainn bailí." + msgid "Enter a valid URL." msgstr "Iontráil URL bailí." msgid "Enter a valid integer." -msgstr "" +msgstr "Cuir isteach slánuimhir bhailí." msgid "Enter a valid email address." -msgstr "" +msgstr "Cuir isteach seoladh ríomhphoist bailí." #. Translators: "letters" means latin letters: a-z and A-Z. msgid "" "Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." msgstr "" +"Cuir isteach “sluga” bailí ar a bhfuil litreacha, uimhreacha, foscórthaí nó " +"fleiscíní." msgid "" "Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " "hyphens." msgstr "" +"Cuir isteach “sluga” bailí ar a bhfuil litreacha Unicode, uimhreacha, fo-" +"scóranna, nó fleiscíní." -msgid "Enter a valid IPv4 address." -msgstr "Iontráil seoladh IPv4 bailí." +#, python-format +msgid "Enter a valid %(protocol)s address." +msgstr "Cuir isteach seoladh bailí %(protocol)s." -msgid "Enter a valid IPv6 address." -msgstr "Cuir seoladh bailí IPv6 isteach." +msgid "IPv4" +msgstr "IPv4" -msgid "Enter a valid IPv4 or IPv6 address." -msgstr "Cuir seoladh bailí IPv4 nó IPv6 isteach." +msgid "IPv6" +msgstr "IPv6" + +msgid "IPv4 or IPv6" +msgstr "IPv4 nó IPv6" msgid "Enter only digits separated by commas." msgstr "Ná hiontráil ach digití atá deighilte le camóga." @@ -382,6 +408,19 @@ msgid "Ensure this value is greater than or equal to %(limit_value)s." msgstr "" "Cinntigh go bhfuil an luach seo níos mó ná nó cothrom le %(limit_value)s." +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "Cinntigh gur iolraí de chéimmhéid %(limit_value)s an luach seo." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Cinntigh gur iolraí de chéimmhéid %(limit_value)s an luach seo, ag tosú ó " +"%(offset)s, m.sh. %(offset)s, %(valid_value1)s, %(valid_value2)s, agus mar " +"sin de." + #, python-format msgid "" "Ensure this value has at least %(limit_value)d character (it has " @@ -390,10 +429,20 @@ msgid_plural "" "Ensure this value has at least %(limit_value)d characters (it has " "%(show_value)d)." msgstr[0] "" +"Cinntigh go bhfuil ar a laghad %(limit_value)d carachtar ag an luach seo (tá " +"%(show_value)d aige)." msgstr[1] "" +"Cinntigh go bhfuil ar a laghad %(limit_value)d carachtar ag an luach seo (tá " +"%(show_value)d aige)." msgstr[2] "" +"Cinntigh go bhfuil ar a laghad %(limit_value)d carachtar ag an luach seo (tá " +"%(show_value)d aige)." msgstr[3] "" +"Cinntigh go bhfuil ar a laghad %(limit_value)d carachtar ag an luach seo (tá " +"%(show_value)d aige)." msgstr[4] "" +"Cinntigh go bhfuil ar a laghad %(limit_value)d carachtar ag an luach seo (tá " +"%(show_value)d aige)." #, python-format msgid "" @@ -403,10 +452,20 @@ msgid_plural "" "Ensure this value has at most %(limit_value)d characters (it has " "%(show_value)d)." msgstr[0] "" +"Cinntigh go bhfuil %(limit_value)d carachtar ar a mhéad ag an luach seo (tá " +"%(show_value)d aige)." msgstr[1] "" +"Cinntigh go bhfuil %(limit_value)d carachtar ar a mhéad ag an luach seo (tá " +"%(show_value)d aige)." msgstr[2] "" +"Cinntigh go bhfuil %(limit_value)d carachtar ar a mhéad ag an luach seo (tá " +"%(show_value)d aige)." msgstr[3] "" +"Cinntigh go bhfuil %(limit_value)d carachtar ar a mhéad ag an luach seo (tá " +"%(show_value)d aige)." msgstr[4] "" +"Cinntigh go bhfuil %(limit_value)d carachtar ar a mhéad ag an luach seo (tá " +"%(show_value)d aige)." msgid "Enter a number." msgstr "Iontráil uimhir." @@ -414,20 +473,20 @@ msgstr "Iontráil uimhir." #, python-format msgid "Ensure that there are no more than %(max)s digit in total." msgid_plural "Ensure that there are no more than %(max)s digits in total." -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgstr[0] "Cinntigh nach bhfuil níos mó ná %(max)s digit san iomlán." +msgstr[1] "Cinntigh nach bhfuil níos mó ná %(max)s digit san iomlán." +msgstr[2] "Cinntigh nach bhfuil níos mó ná %(max)s digit san iomlán." +msgstr[3] "Cinntigh nach bhfuil níos mó ná %(max)s digit san iomlán." +msgstr[4] "Cinntigh nach bhfuil níos mó ná %(max)s digit san iomlán." #, python-format msgid "Ensure that there are no more than %(max)s decimal place." msgid_plural "Ensure that there are no more than %(max)s decimal places." -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgstr[0] "Cinntigh nach bhfuil níos mó ná %(max)s ionad deachúlach ann." +msgstr[1] "Cinntigh nach bhfuil níos mó ná %(max)s de dheachúlacha ann." +msgstr[2] "Cinntigh nach bhfuil níos mó ná %(max)s de dheachúlacha ann." +msgstr[3] "Cinntigh nach bhfuil níos mó ná %(max)s de dheachúlacha ann." +msgstr[4] "Cinntigh nach bhfuil níos mó ná %(max)s de dheachúlacha ann." #, python-format msgid "" @@ -435,30 +494,41 @@ msgid "" msgid_plural "" "Ensure that there are no more than %(max)s digits before the decimal point." msgstr[0] "" +"Cinntigh nach bhfuil níos mó ná %(max)s digit ann roimh an bpointe deachúil." msgstr[1] "" +"Cinntigh nach bhfuil níos mó ná %(max)s dhigit roimh an bpointe deachúil." msgstr[2] "" +"Cinntigh nach bhfuil níos mó ná %(max)s dhigit roimh an bpointe deachúil." msgstr[3] "" +"Cinntigh nach bhfuil níos mó ná %(max)s dhigit roimh an bpointe deachúil." msgstr[4] "" +"Cinntigh nach bhfuil níos mó ná %(max)s dhigit roimh an bpointe deachúil." #, python-format msgid "" "File extension “%(extension)s” is not allowed. Allowed extensions are: " "%(allowed_extensions)s." msgstr "" +"Ní cheadaítear iarmhír chomhaid “%(extension)s”. Is iad seo a leanas " +"eisínteachtaí ceadaithe: %(allowed_extensions)s." msgid "Null characters are not allowed." -msgstr "" +msgstr "Ní cheadaítear carachtair null." msgid "and" msgstr "agus" #, python-format msgid "%(model_name)s with this %(field_labels)s already exists." -msgstr "" +msgstr "Tá %(model_name)s leis an %(field_labels)s seo ann cheana." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Tá srian “%(name)s” sáraithe." #, python-format msgid "Value %(value)r is not a valid choice." -msgstr "" +msgstr "Ní rogha bhailí é luach %(value)r." msgid "This field cannot be null." msgstr "Ní cheadaítear luach nialasach sa réimse seo." @@ -470,12 +540,14 @@ msgstr "Ní cheadaítear luach nialasach sa réimse seo." msgid "%(model_name)s with this %(field_label)s already exists." msgstr "Tá %(model_name)s leis an %(field_label)s seo ann cheana." -#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. -#. Eg: "Title must be unique for pub_date year" +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" #, python-format msgid "" "%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." msgstr "" +"Caithfidh %(field_label)s a bheith uathúil le haghaidh %(date_field_label)s " +"%(lookup_type)s." #, python-format msgid "Field of type: %(field_type)s" @@ -483,11 +555,11 @@ msgstr "Réimse de Cineál: %(field_type)s" #, python-format msgid "“%(value)s” value must be either True or False." -msgstr "" +msgstr "Caithfidh luach “%(value)s” a bheith Fíor nó Bréagach." #, python-format msgid "“%(value)s” value must be either True, False, or None." -msgstr "" +msgstr "Caithfidh luach “%(value)s” a bheith Fíor, Bréagach, nó Neamhní." msgid "Boolean (Either True or False)" msgstr "Boole" @@ -496,6 +568,9 @@ msgstr "Boole" msgid "String (up to %(max_length)s)" msgstr "Teaghrán (suas go %(max_length)s)" +msgid "String (unlimited)" +msgstr "Teaghrán (gan teorainn)" + msgid "Comma-separated integers" msgstr "Slánuimhireacha camóg-scartha" @@ -504,12 +579,16 @@ msgid "" "“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " "format." msgstr "" +"Tá formáid dáta neamhbhailí ag luach “%(value)s”. Caithfidh sé a bheith i " +"bhformáid BBBB-MM-LL." #, python-format msgid "" "“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " "date." msgstr "" +"Tá an fhormáid cheart ag luach “%(value)s” (BBBB-MM-DD) ach is dáta " +"neamhbhailí é." msgid "Date (without time)" msgstr "Dáta (gan am)" @@ -519,19 +598,23 @@ msgid "" "“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." "uuuuuu]][TZ] format." msgstr "" +"Tá formáid neamhbhailí ag luach “%(value)s”. Caithfidh sé a bheith san " +"fhormáid BBBB-MM-DD HH:MM[:ss[.uuuuuu]][TZ]." #, python-format msgid "" "“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" "[TZ]) but it is an invalid date/time." msgstr "" +"Tá an fhormáid cheart ag luach “%(value)s” (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) ach is dáta/am neamhbhailí é." msgid "Date (with time)" msgstr "Dáta (le am)" #, python-format msgid "“%(value)s” value must be a decimal number." -msgstr "" +msgstr "Caithfidh luach “%(value)s” a bheith ina uimhir dheachúil." msgid "Decimal number" msgstr "Uimhir deachúlach" @@ -541,6 +624,8 @@ msgid "" "“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." "uuuuuu] format." msgstr "" +"Tá formáid neamhbhailí ag luach “%(value)s”. Caithfidh sé a bheith i " +"bhformáid [DD] [[HH:]MM:]ss[.uuuuuu]." msgid "Duration" msgstr "Fad" @@ -553,14 +638,14 @@ msgstr "Conair comhaid" #, python-format msgid "“%(value)s” value must be a float." -msgstr "" +msgstr "Caithfidh luach “%(value)s” a bheith ina shnámhán." msgid "Floating point number" msgstr "Snámhphointe" #, python-format msgid "“%(value)s” value must be an integer." -msgstr "" +msgstr "Caithfidh luach “%(value)s” a bheith ina shlánuimhir." msgid "Integer" msgstr "Slánuimhir" @@ -568,6 +653,9 @@ msgstr "Slánuimhir" msgid "Big (8 byte) integer" msgstr "Mór (8 byte) slánuimhi" +msgid "Small integer" +msgstr "Slánuimhir beag" + msgid "IPv4 address" msgstr "Seoladh IPv4" @@ -576,13 +664,13 @@ msgstr "Seoladh IP" #, python-format msgid "“%(value)s” value must be either None, True or False." -msgstr "" +msgstr "Ní mór luach “%(value)s” a bheith Easpa, Fíor nó Bréagach." msgid "Boolean (Either True, False or None)" msgstr "Boole (Fíor, Bréagach nó Dada)" msgid "Positive big integer" -msgstr "" +msgstr "Slánuimhir mhór dhearfach" msgid "Positive integer" msgstr "Slánuimhir dearfach" @@ -594,9 +682,6 @@ msgstr "Slánuimhir beag dearfach" msgid "Slug (up to %(max_length)s)" msgstr "Slug (suas go %(max_length)s)" -msgid "Small integer" -msgstr "Slánuimhir beag" - msgid "Text" msgstr "Téacs" @@ -605,12 +690,16 @@ msgid "" "“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " "format." msgstr "" +"Tá formáid neamhbhailí ag luach “%(value)s”. Caithfidh sé a bheith i " +"bhformáid HH:MM[:ss[.uuuuuu]]." #, python-format msgid "" "“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " "invalid time." msgstr "" +"Tá an fhormáid cheart ag luach “%(value)s” (HH:MM[:ss[.uuuuuu]]) ach is am " +"neamhbhailí é." msgid "Time" msgstr "Am" @@ -619,14 +708,14 @@ msgid "URL" msgstr "URL" msgid "Raw binary data" -msgstr "" +msgstr "Sonraí dénártha amh" #, python-format msgid "“%(value)s” is not a valid UUID." -msgstr "" +msgstr "Ní UUID bailí é “%(value)s”." msgid "Universally unique identifier" -msgstr "" +msgstr "Aitheantóir uathúil uilíoch" msgid "File" msgstr "Comhaid" @@ -635,14 +724,14 @@ msgid "Image" msgstr "Íomhá" msgid "A JSON object" -msgstr "" +msgstr "Réad JSON" msgid "Value must be valid JSON." -msgstr "" +msgstr "Caithfidh an luach a bheith bailí JSON." #, python-format msgid "%(model)s instance with %(field)s %(value)r does not exist." -msgstr "" +msgstr "Níl sampla %(model)s le %(field)s %(value)r ann." msgid "Foreign Key (type determined by related field)" msgstr "Eochair Eachtracha (cineál a chinnfear de réir réimse a bhaineann)" @@ -652,11 +741,11 @@ msgstr "Duine-le-duine caidreamh" #, python-format msgid "%(from)s-%(to)s relationship" -msgstr "" +msgstr "%(from)s-%(to)s caidreamh" #, python-format msgid "%(from)s-%(to)s relationships" -msgstr "" +msgstr "%(from)s-%(to)s caidrimh" msgid "Many-to-many relationship" msgstr "Go leor le go leor caidreamh" @@ -683,11 +772,11 @@ msgid "Enter a valid date/time." msgstr "Iontráil dáta/am bailí." msgid "Enter a valid duration." -msgstr "" +msgstr "Cuir isteach ré bailí." #, python-brace-format msgid "The number of days must be between {min_days} and {max_days}." -msgstr "" +msgstr "Caithfidh líon na laethanta a bheith idir {min_days} agus {max_days}." msgid "No file was submitted. Check the encoding type on the form." msgstr "Níor seoladh comhad. Deimhnigh cineál an ionchódaithe ar an bhfoirm." @@ -703,10 +792,20 @@ msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." msgid_plural "" "Ensure this filename has at most %(max)d characters (it has %(length)d)." msgstr[0] "" +"Cinntigh go bhfuil %(max)d carachtar ar a mhéad ag an gcomhadainm seo (tá " +"%(length)d aige)." msgstr[1] "" +"Cinntigh go bhfuil %(max)d carachtar ar a mhéad ag an gcomhadainm seo (tá " +"%(length)d aige)." msgstr[2] "" +"Cinntigh go bhfuil %(max)d carachtar ar a mhéad ag an gcomhadainm seo (tá " +"%(length)d aige)." msgstr[3] "" +"Cinntigh go bhfuil %(max)d carachtar ar a mhéad ag an gcomhadainm seo (tá " +"%(length)d aige)." msgstr[4] "" +"Cinntigh go bhfuil %(max)d carachtar ar a mhéad ag an gcomhadainm seo (tá " +"%(length)d aige)." msgid "Please either submit a file or check the clear checkbox, not both." msgstr "" @@ -728,13 +827,13 @@ msgid "Enter a list of values." msgstr "Cuir liosta de luachanna isteach." msgid "Enter a complete value." -msgstr "" +msgstr "Cuir isteach luach iomlán." msgid "Enter a valid UUID." -msgstr "" +msgstr "Cuir isteach UUID bailí." msgid "Enter a valid JSON." -msgstr "" +msgstr "Cuir isteach JSON bailí." #. Translators: This is the default suffix added to form field labels msgid ":" @@ -742,28 +841,34 @@ msgstr ":" #, python-format msgid "(Hidden field %(name)s) %(error)s" -msgstr "" - -msgid "ManagementForm data is missing or has been tampered with" -msgstr "" +msgstr "(Réimse folaithe %(name)s) %(error)s" #, python-format -msgid "Please submit %d or fewer forms." -msgid_plural "Please submit %d or fewer forms." -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Tá sonraí ManagementForm in easnamh nó ar cuireadh isteach orthu. Réimsí ar " +"iarraidh: %(field_names)s. Seans go mbeidh ort tuairisc fhabht a chomhdú má " +"leanann an cheist." #, python-format -msgid "Please submit %d or more forms." -msgid_plural "Please submit %d or more forms." -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Cuir isteach %(num)d foirm ar a mhéad." +msgstr[1] "Cuir isteach %(num)d foirm ar a mhéad." +msgstr[2] "Cuir isteach %(num)d foirm ar a mhéad." +msgstr[3] "Cuir isteach %(num)d foirm ar a mhéad." +msgstr[4] "Cuir isteach %(num)d foirm ar a mhéad." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Cuir isteach ar a laghad %(num)d foirm." +msgstr[1] "Cuir isteach %(num)d foirm ar a laghad." +msgstr[2] "Cuir isteach %(num)d foirm ar a laghad." +msgstr[3] "Cuir isteach %(num)d foirm ar a laghad." +msgstr[4] "Cuir isteach %(num)d foirm ar a laghad." msgid "Order" msgstr "Ord" @@ -793,20 +898,22 @@ msgid "Please correct the duplicate values below." msgstr "Le do thoil ceartaigh na luachanna dúbail thíos." msgid "The inline value did not match the parent instance." -msgstr "" +msgstr "Níor mheaitseáil an luach inlíne leis an gcás tuismitheora." msgid "Select a valid choice. That choice is not one of the available choices." msgstr "Déan rogha bhailí. Ní ceann de na roghanna é do roghasa." #, python-format msgid "“%(pk)s” is not a valid value." -msgstr "" +msgstr "Ní luach bailí é “%(pk)s”." #, python-format msgid "" "%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " "may be ambiguous or it may not exist." msgstr "" +"Níorbh fhéidir %(datetime)s a léirmhíniú i gcrios ama %(current_timezone)s; " +"d'fhéadfadh sé a bheith débhríoch nó b'fhéidir nach bhfuil sé ann." msgid "Clear" msgstr "Glan" @@ -1088,12 +1195,12 @@ msgid "December" msgstr "Mí na Nollag" msgid "This is not a valid IPv6 address." -msgstr "" +msgstr "Ní seoladh IPv6 bailí é seo." #, python-format msgctxt "String to return when truncating text" msgid "%(truncated_text)s…" -msgstr "" +msgstr "%(truncated_text)s…" msgid "or" msgstr "nó" @@ -1103,96 +1210,117 @@ msgid ", " msgstr ", " #, python-format -msgid "%d year" -msgid_plural "%d years" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d bhliain" +msgstr[1] "%(num)d bliain" +msgstr[2] "%(num)d bliain" +msgstr[3] "%(num)d bliain" +msgstr[4] "%(num)d bliain" #, python-format -msgid "%d month" -msgid_plural "%d months" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mí" +msgstr[1] "%(num)d míonna" +msgstr[2] "%(num)d míonna" +msgstr[3] "%(num)d míonna" +msgstr[4] "%(num)d míonna" #, python-format -msgid "%d week" -msgid_plural "%d weeks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d seachtain" +msgstr[1] "%(num)d seachtainí" +msgstr[2] "%(num)d seachtainí" +msgstr[3] "%(num)d seachtainí" +msgstr[4] "%(num)d seachtainí" #, python-format -msgid "%d day" -msgid_plural "%d days" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d lá" +msgstr[1] "%(num)d laethanta" +msgstr[2] "%(num)d laethanta" +msgstr[3] "%(num)d laethanta" +msgstr[4] "%(num)d laethanta" #, python-format -msgid "%d hour" -msgid_plural "%d hours" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d uair" +msgstr[1] "%(num)d huaireanta" +msgstr[2] "%(num)d huaireanta" +msgstr[3] "%(num)d huaireanta" +msgstr[4] "%(num)d huaireanta" #, python-format -msgid "%d minute" -msgid_plural "%d minutes" -msgstr[0] "%d nóiméad" -msgstr[1] "%d nóiméad" -msgstr[2] "%d nóiméad" -msgstr[3] "%d nóiméad" -msgstr[4] "%d nóiméad" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d nóiméad" +msgstr[1] "%(num)d nóiméad" +msgstr[2] "%(num)d nóiméad" +msgstr[3] "%(num)d nóiméad" +msgstr[4] "%(num)d nóiméad" msgid "Forbidden" msgstr "Toirmiscthe" msgid "CSRF verification failed. Request aborted." -msgstr "" +msgstr "Theip ar fhíorú CSRF. Cuireadh deireadh leis an iarratas." msgid "" "You are seeing this message because this HTTPS site requires a “Referer " -"header” to be sent by your Web browser, but none was sent. This header is " +"header” to be sent by your web browser, but none was sent. This header is " "required for security reasons, to ensure that your browser is not being " "hijacked by third parties." msgstr "" +"Tá an teachtaireacht seo á fheiceáil agat toisc go bhfuil “ceanntásc " +"tarchuir” ag teastáil ón suíomh HTTPS seo le bheith seolta ag do bhrabhsálaí " +"gréasáin, ach níor seoladh aon cheann. Tá an ceanntásc seo ag teastáil ar " +"chúiseanna slándála, lena chinntiú nach bhfuil do bhrabhsálaí á fuadach ag " +"tríú páirtithe." msgid "" "If you have configured your browser to disable “Referer” headers, please re-" "enable them, at least for this site, or for HTTPS connections, or for “same-" "origin” requests." msgstr "" +"Má tá do bhrabhsálaí cumraithe agat chun ceanntásca “Tagairtí” a dhíchumasú, " +"le do thoil déan iad a athchumasú, le do thoil don suíomh seo, nó do naisc " +"HTTPS, nó d’iarratais “ar an mbunús céanna”." msgid "" "If you are using the tag or " "including the “Referrer-Policy: no-referrer” header, please remove them. The " "CSRF protection requires the “Referer” header to do strict referer checking. " -"If you’re concerned about privacy, use alternatives like for links to third-party sites." +"If you’re concerned about privacy, use alternatives like for links to third-party sites." msgstr "" +"Má tá an chlib 1 á úsáid agat nó má tá an ceanntásc “Polasaí Atreoraithe: " +"gan atreorú” san áireamh, bain amach iad le do thoil. Éilíonn an chosaint " +"CSRF go bhfuil an ceanntásc “Tagairtí” chun seiceáil docht atreoraithe a " +"dhéanamh. Má tá imní ort faoi phríobháideachas, bain úsáid as roghanna eile " +"amhail le haghaidh naisc chuig láithreáin tríú " +"páirtí." msgid "" "You are seeing this message because this site requires a CSRF cookie when " "submitting forms. This cookie is required for security reasons, to ensure " "that your browser is not being hijacked by third parties." msgstr "" +"Tá an teachtaireacht seo á fheiceáil agat toisc go bhfuil fianán CSRF ag " +"teastáil ón suíomh seo agus foirmeacha á gcur isteach agat. Tá an fianán seo " +"ag teastáil ar chúiseanna slándála, lena chinntiú nach bhfuil do bhrabhsálaí " +"á fuadach ag tríú páirtithe." msgid "" "If you have configured your browser to disable cookies, please re-enable " "them, at least for this site, or for “same-origin” requests." msgstr "" +"Má tá do bhrabhsálaí cumraithe agat chun fianáin a dhíchumasú, le do thoil " +"athchumasaigh iad, le do thoil, le haghaidh an tsuímh seo ar a laghad, nó le " +"haghaidh iarratais “ar an mbunús céanna”." msgid "More information is available with DEBUG=True." msgstr "Tá tuilleadh eolais ar fáil le DEBUG=True." @@ -1201,7 +1329,7 @@ msgid "No year specified" msgstr "Bliain gan sonrú" msgid "Date out of range" -msgstr "" +msgstr "Dáta as raon" msgid "No month specified" msgstr "Mí gan sonrú" @@ -1226,7 +1354,7 @@ msgstr "" #, python-format msgid "Invalid date string “%(datestr)s” given format “%(format)s”" -msgstr "" +msgstr "Teaghrán dáta neamhbhailí “%(datestr)s” tugtha formáid “%(format)s”" #, python-format msgid "No %(verbose_name)s found matching the query" @@ -1234,6 +1362,7 @@ msgstr "Níl bhfuarthas %(verbose_name)s le hadhaigh an iarratas" msgid "Page is not “last”, nor can it be converted to an int." msgstr "" +"Níl an leathanach “deireadh”, agus ní féidir é a thiontú go slánuimhir." #, python-format msgid "Invalid page (%(page_number)s): %(message)s" @@ -1241,53 +1370,57 @@ msgstr "Leathanach neamhbhailí (%(page_number)s): %(message)s" #, python-format msgid "Empty list and “%(class_name)s.allow_empty” is False." -msgstr "" +msgstr "Tá liosta folamh agus “%(class_name)s.allow_empty” bréagach." msgid "Directory indexes are not allowed here." msgstr "Níl innéacsanna chomhadlann cheadaítear anseo." #, python-format msgid "“%(path)s” does not exist" -msgstr "" +msgstr "Níl “%(path)s” ann" #, python-format msgid "Index of %(directory)s" msgstr "Innéacs de %(directory)s" -msgid "Django: the Web framework for perfectionists with deadlines." -msgstr "" +msgid "The install worked successfully! Congratulations!" +msgstr "D'éirigh leis an suiteáil! Comhghairdeachas!" #, python-format msgid "" "View release notes for Django %(version)s" msgstr "" - -msgid "The install worked successfully! Congratulations!" -msgstr "" +"Féach ar nótaí scaoilte le haghaidh Django " +"%(version)s" #, python-format msgid "" "You are seeing this page because DEBUG=True is in your settings file and you have not configured any " -"URLs." +"%(version)s/ref/settings/#debug\" target=\"_blank\" " +"rel=\"noopener\">DEBUG=True is in your settings file and you have not " +"configured any URLs." msgstr "" +"Tá an leathanach seo á fheiceáil agat toisc go bhfuil DEBUG=True i do chomhad socruithe agus nach bhfuil aon " +"URL cumraithe agat." msgid "Django Documentation" -msgstr "" +msgstr "Doiciméadú Django" msgid "Topics, references, & how-to’s" -msgstr "" +msgstr "Ábhair, tagairtí, & conas atá" msgid "Tutorial: A Polling App" -msgstr "" +msgstr "Teagaisc: A Vótaíocht Aip" msgid "Get started with Django" msgstr "Tosaigh le Django" msgid "Django Community" -msgstr "" +msgstr "Pobal Django" msgid "Connect, get help, or contribute" -msgstr "" +msgstr "Ceangail, faigh cúnamh, nó ranníoc" diff --git a/django/conf/locale/hsb/LC_MESSAGES/django.mo b/django/conf/locale/hsb/LC_MESSAGES/django.mo index 600b787b05fb1ff35a899e7b3ab1b184332799d8..16f40d3094df82f20661c4c85838f79004b90dd0 100644 GIT binary patch delta 7685 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 diff --git a/django/conf/locale/hsb/LC_MESSAGES/django.po b/django/conf/locale/hsb/LC_MESSAGES/django.po index a5fb97cfb5..46f12d09bc 100644 --- a/django/conf/locale/hsb/LC_MESSAGES/django.po +++ b/django/conf/locale/hsb/LC_MESSAGES/django.po @@ -1,14 +1,14 @@ # This file is distributed under the same license as the Django package. # # Translators: -# Michael Wolf , 2016-2023 +# Michael Wolf , 2016-2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-09-18 11:41-0300\n" -"PO-Revision-Date: 2023-12-04 06:49+0000\n" -"Last-Translator: Michael Wolf , 2016-2023\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 06:49+0000\n" +"Last-Translator: Michael Wolf , 2016-2024\n" "Language-Team: Upper Sorbian (http://app.transifex.com/django/django/" "language/hsb/)\n" "MIME-Version: 1.0\n" @@ -344,6 +344,9 @@ msgstr "Tuta strona wuslědki njewobsahuje" msgid "Enter a valid value." msgstr "Zapodajće płaćiwu hódnotu." +msgid "Enter a valid domain name." +msgstr "Zapodajće płaćiwe domenowe mjeno." + msgid "Enter a valid URL." msgstr "Zapodajće płaćiwy URL." @@ -367,14 +370,18 @@ msgstr "" "Zapodajće płaćiwe „adresowe mjeno“, kotrež jenož pismiki, ličby, podsmužki " "abo wjazawki wobsahuje." -msgid "Enter a valid IPv4 address." -msgstr "Zapodajće płaćiwu IPv4-adresu." +#, python-format +msgid "Enter a valid %(protocol)s address." +msgstr "Zapodajće płaćiwu %(protocol)s-adresu." -msgid "Enter a valid IPv6 address." -msgstr "Zapodajće płaćiwu IPv6-adresu." +msgid "IPv4" +msgstr "IPv4" -msgid "Enter a valid IPv4 or IPv6 address." -msgstr "Zapodajće płaćiwu IPv4- abo IPv6-adresu." +msgid "IPv6" +msgstr "IPv6" + +msgid "IPv4 or IPv6" +msgstr "IPv4 abo IPv6" msgid "Enter only digits separated by commas." msgstr "Zapodajće jenož přez komy dźělene cyfry," diff --git a/django/conf/locale/sk/LC_MESSAGES/django.mo b/django/conf/locale/sk/LC_MESSAGES/django.mo index e1f7271601d69286e28fbd09fd2696620eb186c6..ddfe767cc94414ed25b981d214cffefe57f71a03 100644 GIT binary patch delta 7753 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 XsQiB1F3Zw+ITH$Rx?}q2(y0Fe9Xn(f delta 7624 zcmXxp34Bgh8prXI2uUPl5hS)m5+rt#5X4R_DN;L$B?zLHX)L8JubNhi)~K|#6;oBM zmYQj(p;V{Vc8az$YEWxwEii$O~|;2L4jsxuc}NsH{@wLTWl!jG@>apGMW&kNk5N_-KQ!mUEeqg{^Qp#^M&N zhKG=U?mIqoePF!5+~?xGglmmDF#yYAu{qP6V?Jvx#M;zbf`Rw}(r>p7gK#@mz+HC! za||Va7(?(lMmV2y=Sb*=H?SPu#!7e(RWT~Tvl{Ar5=LWv48yjl@*c?Kxm*m!JdDB7 zsFBaaWL$x~+~0F1&sJ3k2% z$j`^R_%>=lM^Nn_N1rY{PeKj-fRT6|H3JV&4OU9@F06wU$u~yTZ;SP?3+lRws1eUb z-DoMQ{Z*((@dj#bY(Wj=N+R<=jl@qByoO_woST97a0yOhzSd*eI?k=bcQFflF`Q+% z5ZhuRy=aFcQHyacR>f21�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 diff --git a/django/conf/locale/sk/LC_MESSAGES/django.po b/django/conf/locale/sk/LC_MESSAGES/django.po index 14da7f96f2..e245cb14c5 100644 --- a/django/conf/locale/sk/LC_MESSAGES/django.po +++ b/django/conf/locale/sk/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # This file is distributed under the same license as the Django package. # # Translators: -# Adam Zahradník, 2023 +# Adam Zahradník, 2023-2024 # Jannis Leidel , 2011 # 18f25ad6fa9930fc67cb11aca9d16a27, 2012-2013 # Marian Andre , 2013,2015,2017-2018 @@ -14,9 +14,9 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-09-18 11:41-0300\n" -"PO-Revision-Date: 2023-12-04 06:49+0000\n" -"Last-Translator: Martin Tóth , 2017,2023\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 06:49+0000\n" +"Last-Translator: Adam Zahradník, 2023-2024\n" "Language-Team: Slovak (http://app.transifex.com/django/django/language/sk/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -351,6 +351,9 @@ msgstr "Stránka neobsahuje žiadne výsledky" msgid "Enter a valid value." msgstr "Zadajte platnú hodnotu." +msgid "Enter a valid domain name." +msgstr "Zadajte platný názov domény." + msgid "Enter a valid URL." msgstr "Zadajte platnú URL adresu." @@ -374,14 +377,18 @@ msgstr "" "Zadajte platnú skratku pozostávajúcu z písmen Unicode, čísel, " "podčiarkovníkov alebo pomlčiek." -msgid "Enter a valid IPv4 address." -msgstr "Zadajte platnú IPv4 adresu." +#, python-format +msgid "Enter a valid %(protocol)s address." +msgstr "Zadajte platnú %(protocol)s adresu." -msgid "Enter a valid IPv6 address." -msgstr "Zadajte platnú IPv6 adresu." +msgid "IPv4" +msgstr "IPv4" -msgid "Enter a valid IPv4 or IPv6 address." -msgstr "Zadajte platnú IPv4 alebo IPv6 adresu." +msgid "IPv6" +msgstr "IPv6" + +msgid "IPv4 or IPv6" +msgstr "IPv4 alebo IPv6" msgid "Enter only digits separated by commas." msgstr "Zadajte len číslice oddelené čiarkami." diff --git a/django/conf/locale/ug/LC_MESSAGES/django.mo b/django/conf/locale/ug/LC_MESSAGES/django.mo index 4b9aed37fd33c63bb399b341d632fa2851c1e702..ce10d7df7f524d3266cc65bedb8c831f80e3c850 100644 GIT binary patch delta 7785 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 diff --git a/django/conf/locale/ug/LC_MESSAGES/django.po b/django/conf/locale/ug/LC_MESSAGES/django.po index ccaf4dae10..daa3973d8d 100644 --- a/django/conf/locale/ug/LC_MESSAGES/django.po +++ b/django/conf/locale/ug/LC_MESSAGES/django.po @@ -2,7 +2,7 @@ # # Translators: # abdl erkin <84247764@qq.com>, 2018 -# Abduqadir Abliz , 2023 +# Abduqadir Abliz , 2023-2024 # Abduqadir Abliz , 2023 # Azat, 2023 # Murat Orhun , 2023 @@ -10,9 +10,9 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-09-18 11:41-0300\n" -"PO-Revision-Date: 2023-12-04 06:49+0000\n" -"Last-Translator: Abduqadir Abliz , 2023\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 06:49+0000\n" +"Last-Translator: Abduqadir Abliz , 2023-2024\n" "Language-Team: Uyghur (http://app.transifex.com/django/django/language/ug/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -348,6 +348,9 @@ msgstr "ئۇ بەتتە ھېچقانداق نەتىجە يوق" msgid "Enter a valid value." msgstr "بىر ئىناۋەتلىك قىممەتنى تولدۇرۇڭ" +msgid "Enter a valid domain name." +msgstr "ئىناۋەتلىك دائىرە ئىسمى كىرگۈزۈلىدۇ." + msgid "Enter a valid URL." msgstr "ئىناۋەتلىك URL نى تولدۇرۇڭ" @@ -371,14 +374,18 @@ msgstr "" "يۇنىكودلۇق ھەرپ، سان، ئاستى سىزىق ياكى سىزىقچىلاردىن تەركىب تاپقان ئۈنۈملۈك " "«slug» نى كىرگۈزۈڭ." -msgid "Enter a valid IPv4 address." -msgstr "ئىناۋەتلىك IPv4 ئادرېسىنى كىرگۈزۈڭ." +#, python-format +msgid "Enter a valid %(protocol)s address." +msgstr "ئىناۋەتلىك %(protocol)sئادرېسى كىرگۈزۈلىدۇ." -msgid "Enter a valid IPv6 address." -msgstr "ئىناۋەتلىك IPv6 ئادرېسىنى كىرگۈزۈڭ." +msgid "IPv4" +msgstr "IPv4" -msgid "Enter a valid IPv4 or IPv6 address." -msgstr "ئىناۋەتلىك IPv4 ياكى IPv6 ئادرېسىنى كىرگۈزۈڭ." +msgid "IPv6" +msgstr "IPv6" + +msgid "IPv4 or IPv6" +msgstr "IPv4 ياكى IPv6" msgid "Enter only digits separated by commas." msgstr "پەش ئارقىلىق ئايرىلغان رەقەملەرنىلا كىرگۈزۈڭ." diff --git a/django/conf/locale/uk/LC_MESSAGES/django.mo b/django/conf/locale/uk/LC_MESSAGES/django.mo index 7c96efb7d8f29f9f9eb2bddf80e92beb4a81e74b..0e9dc9f0794bba4ffe5d3f852d1f6bdd2ac180ca 100644 GIT binary patch delta 6909 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 L!Io2fKMwydHrr(@ diff --git a/django/conf/locale/uk/LC_MESSAGES/django.po b/django/conf/locale/uk/LC_MESSAGES/django.po index 8f50fc4d95..b2a71874be 100644 --- a/django/conf/locale/uk/LC_MESSAGES/django.po +++ b/django/conf/locale/uk/LC_MESSAGES/django.po @@ -11,6 +11,7 @@ # Max V. Stotsky , 2014 # Mikhail Kolesnik , 2015 # Mykola Zamkovoi , 2014 +# Natalia, 2024 # Alex Bolotov , 2013-2014 # Roman Kozlovskyi , 2012 # Sergiy Kuzmenko , 2011 @@ -21,10 +22,10 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-01-17 02:13-0600\n" -"PO-Revision-Date: 2023-04-25 06:49+0000\n" -"Last-Translator: Illia Volochii , 2019,2021-2023\n" -"Language-Team: Ukrainian (http://www.transifex.com/django/django/language/" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 06:49+0000\n" +"Last-Translator: Natalia, 2024\n" +"Language-Team: Ukrainian (http://app.transifex.com/django/django/language/" "uk/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -311,6 +312,9 @@ msgstr "Татарська" msgid "Udmurt" msgstr "Удмуртська" +msgid "Uyghur" +msgstr "" + msgid "Ukrainian" msgstr "Українська" @@ -358,6 +362,9 @@ msgstr "Сторінка не містить результатів" msgid "Enter a valid value." msgstr "Введіть коректне значення." +msgid "Enter a valid domain name." +msgstr "" + msgid "Enter a valid URL." msgstr "Введіть коректний URL." @@ -379,14 +386,18 @@ msgstr "" "Введіть коректне значення 'slug' (короткого заголовку), що може містити " "тільки літери, числа, символи підкреслювання або дефіси." -msgid "Enter a valid IPv4 address." -msgstr "Введіть коректну IPv4 адресу." +#, python-format +msgid "Enter a valid %(protocol)s address." +msgstr "" -msgid "Enter a valid IPv6 address." -msgstr "Введіть дійсну IPv6 адресу." +msgid "IPv4" +msgstr "" -msgid "Enter a valid IPv4 or IPv6 address." -msgstr "Введіть дійсну IPv4 чи IPv6 адресу." +msgid "IPv6" +msgstr "" + +msgid "IPv4 or IPv6" +msgstr "" msgid "Enter only digits separated by commas." msgstr "Введіть тільки цифри, що розділені комами." @@ -409,6 +420,12 @@ msgstr "Переконайтеся, що це значення більше чи msgid "Ensure this value is a multiple of step size %(limit_value)s." msgstr "" +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" + #, python-format msgid "" "Ensure this value has at least %(limit_value)d character (it has " @@ -799,7 +816,7 @@ msgid "Enter a complete value." msgstr "Введіть значення повністю." msgid "Enter a valid UUID." -msgstr "Введіть коректне значення UUID," +msgstr "Введіть коректне значення UUID." msgid "Enter a valid JSON." msgstr "Введіть коректний JSON." diff --git a/django/conf/locale/zh_Hans/LC_MESSAGES/django.mo b/django/conf/locale/zh_Hans/LC_MESSAGES/django.mo index 55517ea7b6ef216d6aba49fc926fe16d9ab3d504..c68035c84dd354975f87aec4a7772c227516279f 100644 GIT binary patch delta 7723 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 diff --git a/django/conf/locale/zh_Hans/LC_MESSAGES/django.po b/django/conf/locale/zh_Hans/LC_MESSAGES/django.po index 097e77d4b4..012741fb5a 100644 --- a/django/conf/locale/zh_Hans/LC_MESSAGES/django.po +++ b/django/conf/locale/zh_Hans/LC_MESSAGES/django.po @@ -15,6 +15,7 @@ # Le Yang , 2018 # li beite , 2020 # Liping Wang , 2016-2017 +# L., 2024 # matthew Yip , 2020 # mozillazg , 2016 # Ronald White , 2014 @@ -33,6 +34,7 @@ # ced773123cfad7b4e8b79ca80f736af9, 2011-2012 # Ziya Tang , 2018 # 付峥 , 2018 +# L., 2024 # LatteFang <370358679@qq.com>, 2020 # Kevin Sze , 2012 # 高乐喆 , 2023 @@ -40,9 +42,9 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-09-18 11:41-0300\n" -"PO-Revision-Date: 2023-12-25 06:49+0000\n" -"Last-Translator: jack yang, 2023\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 06:49+0000\n" +"Last-Translator: L., 2024\n" "Language-Team: Chinese (China) (http://app.transifex.com/django/django/" "language/zh_CN/)\n" "MIME-Version: 1.0\n" @@ -377,6 +379,9 @@ msgstr "本页结果为空" msgid "Enter a valid value." msgstr "输入一个有效的值。" +msgid "Enter a valid domain name." +msgstr "输入一个有效的域名。" + msgid "Enter a valid URL." msgstr "输入一个有效的 URL。" @@ -396,14 +401,18 @@ msgid "" "hyphens." msgstr "输入由Unicode字母,数字,下划线或连字符号组成的有效“字段”。" -msgid "Enter a valid IPv4 address." -msgstr "输入一个有效的 IPv4 地址。" +#, python-format +msgid "Enter a valid %(protocol)s address." +msgstr "输入一个有效的 %(protocol)s 地址。" -msgid "Enter a valid IPv6 address." -msgstr "输入一个有效的 IPv6 地址。" +msgid "IPv4" +msgstr "IPv4" -msgid "Enter a valid IPv4 or IPv6 address." -msgstr "输入一个有效的 IPv4 或 IPv6 地址." +msgid "IPv6" +msgstr "IPv6" + +msgid "IPv4 or IPv6" +msgstr "IPv4 或 IPv6" msgid "Enter only digits separated by commas." msgstr "只能输入用逗号分隔的数字。" diff --git a/django/contrib/admin/locale/cs/LC_MESSAGES/django.mo b/django/contrib/admin/locale/cs/LC_MESSAGES/django.mo index d3bfdd7ea07bc13c276eabfeb4add45591973a88..0dc5f9abc908503c60cc701942088687d61c6ff3 100644 GIT binary patch delta 5628 zcma*q33OD|9mnxINmv3BcG=;vCP3Ih5h#Sk1!a>R1odU|OomD3g_%iWqUp$LL8yf& z6(icHSX7|sU@H~^G^C>Rh}C*5TJdN-9+zrqUF*{J`VWzxO`y zw#^XKO!BY|&PNUOdei`29Drq*hj*g}@+xZJU!Vpa=uZBZQ0Ug(dto(3 zsPDiuY{rh#h+CqTs6A?Cy>J!|#0-q0GFgFY?=w_KbJ;-JTZ>We1yQLFqkg}sCvWwm zu$CK2`EJyV4xk25kL(k39M!-}sJ-wSasbRZ)Bpm#ybLr)EmddK^L_mL*{F^$^6Qr& zV>F8r6g0Edn1|IE$9kNHW60YkT#pkltB=?5OjOF3qh=C94YU-sH0x0*-hmq6eqGWvR%X@?9rVY*V#$a3*9oQi7rBh*N{u|9)w3@W87aWXo{HZc$4SUigCWAibV zVe9_J497L7Odi0I7+`14$I&=jyJiCgrT9f$ge&P?dm)J{upX6>9)rByJG(FP;rDPYeu3k#I>-BhCUF(@=ka?uk#s6^m6*_)-a$cYbJX_~s^OPWGkX;^u=h}# z<}=ju&3HKz+xzxF-5-dW;V3*BVArE2^yyGz_>`EeTyJ36x#a&PZp`4uGVIRI;zXG^ zUV+>2etZRK!&I}NEpQLE!~=f)5NauoqXzIIYVW*`>hN#KfifLNc#gzY)aQ&K|0*o= zZxo<9a8Wa;z&3a@>b!5p?O2POaX33F3lE_(aS}V@3#fM9K@I2}>QsD%YOn1m&t3@% zEQ=Y6dSM}IrYlhA`Bo%3rWQ5Olc-d_h;8wG)b9Thm64I7z5AD-I-cp*7onEW!R8o6 z4LDIrLFacJs^j}`JU)x+FntVPG0Z~k?%}8xug1IZ8eE4T<1xIE(QLv?*nxYo0o8Ho zMcyaA8a09Yv7^raQxr7P=dc65g6;7G)baTTPR0Hgd*1~In^C_FwTri51otA@H9Z)8 z7-yj}@+4}&$5E+2<=;Pp`8xk^Qc#1Ja<(4BtFQpSMy+lB1aB!;qh_)J)$w*zD);&I zgQ$*9qn<;2Gn|@m(fm`rSm_Qf_|8eI(D;=)R=jwJyGD-i%|{Vf?E5n z*adf?GWP`5;z?YE1(R5RJdG={8;75wsXz-4VnQ=~iGn(M3)S$SP^tO~b&Oi^z18mn zP9p1 z@85qNHNX%2`q!w8w9fP1?}|UAJ`M-rYrYw5pkdU9qB6Y znr2KP4neku*^VJR<=4mYw(1dFfxpL1IBtgbui~SqiFCizm?F%~ngQCW!Jr+z!KkxkZ2FH;cH}K~cLYu8$>W;Ur%D@i^_LFh^`y%L*EeIW<> z_Xgo{;uvuaaUHRNs3WvAjl{h~U!tjhvzSVELg(@pLf3YJk6`N3+RpaNgK-n_6!8F| zBg(c&eTFZ?3PRU3Vr{C#Uu4*uxSn8ZnVX2=>c1ID zgsv&XKBAi{Tu*qIJ-FI0i;;f$!f)JbD&|wDBDxS46RG}-DU=Yo#Dm0MLf25DHPMck zMd;Eu;s?YkB7?Y__%X47C?NV1x@=-B@h~x;&{as>m@0W++iLzd!moPY?djC6^6zZ+ z4f!6#+x@cMN+;U-^^G{nFCWHGPAxvBlsKU+=vw~3dQKH(6MfC zqm~`9?4aH^3!K!`sh_>a|NQ}Lm~~Ti&CcGFbDa43(V7KCZiRaA3SQr4L8!pVx1%*@ zdtcZw94fWqu2o`(A`C4OXHv<(_Wna!&At6PCr9)f6`1SwZ&idC=cHIX>P8ADI}y!z z(g?qLzQ6yMH0jMT*>=F7^fq)Etu*>Gmr!g)bGQC2cMST#A<8a;CK*qTqXd#Br_rO7Til^JR7gygNcP9Sqe)XjHJYzihYH;(%}twm|njWz5m zsi_`soiE=rzH8gLrBS;)&W84X{~z~~_l*BAZSmsDd?(6-<&AYtuqaZQ+N9xlr4_NQ zc*DbN8djfy2UBfXb~qR^P48$Mx&904DfO$jLpM##OU$ujal4#(X{N4O?&e4BDyr)0 zUo~$wW*U=9Wyg*qF&s zoP+ou3rF89Z@AblI8p1b-ZOaz6B=GA9mcH^Hy$dta_n%ttf8)0V@%y?+Ux(vgYgo( vyy3{;)Re!Y%@~_1UfggbFgSVh)Q#yqZByzNyN&hXO26QQ&lhUGm@(&{bcU>1 delta 4274 zcmYk;2~btn9mny*160tWBBF@OV^dT_5sjuGn=5WLQZ;UkAW(4u#U}(C@)C`4iCOfz zq{h~*E;UM|*QK^@qtnSYHdA9_=~$iEbjGBaX>2;R>ZIxS_wJ$7GydP_ob&Fx=bZmJ z_saS0Vef4Y3*L^6*kLGViQdGGNMj!3mX3T-p6zT*cWlIXd>s?S{bwM2J2Z^W&Wm~6V586vn*R8`2xEW*6 zL2hUcU=$v<-=D-L+UM{k92slO_wYQ%GrswNif;HB>WBA`f94<7$Zp24NYfJ&Fax!M zVjP5%kb9eY%)pJd-GchvRm{eZk>r}lIPdz77|r;m4;8H-12ut>s0)iw6Ptiq`83o7 zs<1!4fSSlr?29Mu_aEW2w7g+crAA2C#HnVUz zu0*{*4&!RPfLYq@oMbOGPjhT;Cs1;sC9nx#o zk5MaaMP>GHs0ltoZK0178llq`8>%p4)CIj!nMgyWJR3DY2`VF{_$1E9S8*qXV;X7E zjWcj9j=~Z6TV%V>@Ny&HE&tsnt4u?*C8BTy47 zvQD=BGckhxGQ1c@hENMhAHYitN24Y*3xl6fSw&?ImM{x_aS$isWjugUgS-hI$M&>u zqB3#Ew(p@*{WW$(U#539Vo(ESAm`K+S)ajZ+D)0{UzLq?=*A9e=5L`+^FGw$*^Jxp z5^lyBgT0LW8TI1&3iW#*CrT5DMjhgK)O`k6M`8x;aj5HSvdBM+H1%}olN2pUAJ;Ymi0jhr@YQU#$y8=7W4q!Wc5uM7fX8m}2gVQY|zG7!s==Ls@> zkOOW;c@g}?$wUFJYi8Z4#@f*|@UBe>0gPcbb zOlDb;R3@OF*Qr>8i;*$SOa9C)3GGu@f=N953$PmV@Llv{1TS<=Bpo&2 zaO{kEs6#jf6L7BmK7c8VZ=O>H_o60n1$9_HL1pGX>WuswHL>tqZ@?5BPkRjNvE7Us z=m=`1r)~Rv)QWH75&Rtc;TC2eRK=yj6J-8`N^J*TPh+qv>T#KgdZ#~+iFg5jjIBsg zOc7sJ;~JcgpJS-M!1iOPA2;dxLT{oU7LxzPbhOeDg~c3A9il0y_rMHPMrK==pss5| zrFMgD??O#{KkC#UL;dayCgJ<2>%YJ_e26@FCZ;%O%qvv#i@ihh0qTO^<68U+>M5uq z9sO|^K984>-7xuMy^J)XzTbg*%r2l({t<@ZE!%$^wUu9^CipmLD>37|nI~fxz8H*J zX+G)(^N61lX}&k(;P-Xxlcmx!LkY2s;O6``W7QrSVw3Dvy+M^0+| zb#xpiensphcwdBy4pdv&-Bz*w0(aT^KFlE4NwbkqsV1^QHSa*5p#Gw53q3tP;tj2T z3o(l*A$~;se|e5ZJTZ+pPU!ld5=F!jVmzU;%){j14{g1T23z?F&Lw8HeSyJrJ_>C| z4;(@Kj5uoh^qABUoWoGr%I6EjdLo-p`2nG)WG9hJL=k%4R}yE5V?nrFtD(nK^#Me0+gXOS#A@4)!HKqh$~p`W+VM>( zjR}OF$qJ$~@fPt8q0)}vWoPP%*N8kqrNzU%jjs}EM567Rjxz|?wx^(;{S+dJc#?49 z_?Sd&BUD%E zT3=^r+5_j;>AT(Y{c^*d$boy(19g=(6{}X%1_G6J{=6mCbxX^#RutCPE~{zGTC^rV z(?4wJuwl--1N(+IG&H#P1~x{x%ZAJkbFL44;NHk?Vum>>;m(047PzS+kA}IeqaOI2 zKjtPm-{tmjEAl?|Ia><~dd;mZuPa+q9q`xxZhxgIT~T*+e|?$1p|X6nJG^j6xO2HU g+UYVj-KiNf%3VIDG|WjH*WykczdqdgSIPMQ0>e7!lK=n! diff --git a/django/contrib/admin/locale/cs/LC_MESSAGES/django.po b/django/contrib/admin/locale/cs/LC_MESSAGES/django.po index 65159b8166..39c3679caf 100644 --- a/django/contrib/admin/locale/cs/LC_MESSAGES/django.po +++ b/django/contrib/admin/locale/cs/LC_MESSAGES/django.po @@ -2,7 +2,9 @@ # # Translators: # Jannis Leidel , 2011 -# trendspotter , 2022 +# Jan Papež , 2024 +# Jiří Podhorecký , 2024 +# Jiří Podhorecký , 2022 # Jirka Vejrazka , 2011 # Tomáš Ehrlich , 2015 # Vláďa Macek , 2013-2014 @@ -12,10 +14,10 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-05-17 05:10-0500\n" -"PO-Revision-Date: 2022-07-25 07:05+0000\n" -"Last-Translator: trendspotter \n" -"Language-Team: Czech (http://www.transifex.com/django/django/language/cs/)\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 07:05+0000\n" +"Last-Translator: Jan Papež , 2024\n" +"Language-Team: Czech (http://app.transifex.com/django/django/language/cs/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -184,6 +186,9 @@ msgstr "" "Výběr více než jedné položky je možný přidržením klávesy \"Control\", na " "Macu \"Command\"." +msgid "Select this object for an action - {}" +msgstr "Vyberte tento objekt pro akci - {}" + #, python-brace-format msgid "The {name} “{obj}” was added successfully." msgstr "Položka typu {name} \"{obj}\" byla úspěšně přidána." @@ -205,12 +210,6 @@ msgstr "" "Položka typu {name} \"{obj}\" byla úspěšně změněna. Níže ji můžete dále " "upravovat." -#, python-brace-format -msgid "The {name} “{obj}” was added successfully. You may edit it again below." -msgstr "" -"Položka \"{obj}\" typu {name} byla úspěšně přidána. Níže ji můžete dále " -"upravovat." - #, python-brace-format msgid "" "The {name} “{obj}” was changed successfully. You may add another {name} " @@ -352,6 +351,9 @@ msgstr "Vybrat všechny položky typu %(module_name)s, celkem %(total_count)s." msgid "Clear selection" msgstr "Zrušit výběr" +msgid "Breadcrumbs" +msgstr "Drobečky" + #, python-format msgid "Models in the %(name)s application" msgstr "Modely v aplikaci %(name)s" @@ -378,16 +380,36 @@ msgstr "Zadejte uživatelské jméno a heslo." msgid "Change password" msgstr "Změnit heslo" -msgid "Please correct the error below." -msgstr "Opravte níže uvedenou chybu." +msgid "Set password" +msgstr "Nastavit heslo" -msgid "Please correct the errors below." -msgstr "Opravte níže uvedené chyby." +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Opravte prosím níže uvedenou chybu." +msgstr[1] "Opravte prosím níže uvedené chyby." +msgstr[2] "Opravte prosím níže uvedené chyby." +msgstr[3] "Opravte prosím níže uvedené chyby." #, python-format msgid "Enter a new password for the user %(username)s." msgstr "Zadejte nové heslo pro uživatele %(username)s." +msgid "" +"This action will enable password-based authentication for " +"this user." +msgstr "" +"Tato akce povolí pro tohoto uživatele ověřování na základě " +"hesla." + +msgid "Disable password-based authentication" +msgstr "Zakázat ověřování pomocí hesla" + +msgid "Enable password-based authentication" +msgstr "Povolit ověřování pomocí hesla" + +msgid "Skip to main content" +msgstr "Přeskočit na hlavní obsah" + msgid "Welcome," msgstr "Vítejte, uživateli" @@ -413,6 +435,12 @@ msgstr "Zobrazení na webu" msgid "Filter" msgstr "Filtr" +msgid "Hide counts" +msgstr "Skrýt počty" + +msgid "Show counts" +msgstr "Zobrazit počty" + msgid "Clear all filters" msgstr "Zrušit všechny filtry" @@ -426,6 +454,15 @@ msgstr "Priorita řazení: %(priority_number)s" msgid "Toggle sorting" msgstr "Přehodit řazení" +msgid "Toggle theme (current theme: auto)" +msgstr "Přepnout motiv (aktuální motiv: auto)" + +msgid "Toggle theme (current theme: light)" +msgstr "Přepnout motiv (aktuální motiv: světlý)" + +msgid "Toggle theme (current theme: dark)" +msgstr "Přepnout motiv (aktuální motiv: tmavý)" + msgid "Delete" msgstr "Odstranit" @@ -512,6 +549,15 @@ msgstr "Moje akce" msgid "None available" msgstr "Nic" +msgid "Added:" +msgstr "Přidáno:" + +msgid "Changed:" +msgstr "Změněno:" + +msgid "Deleted:" +msgstr "Smazáno:" + msgid "Unknown content" msgstr "Neznámý obsah" @@ -538,6 +584,9 @@ msgstr "Zapomněli jste heslo nebo uživatelské jméno?" msgid "Toggle navigation" msgstr "Přehodit navigaci" +msgid "Sidebar" +msgstr "Boční panel" + msgid "Start typing to filter…" msgstr "Filtrovat začnete vepsáním textu..." @@ -554,10 +603,11 @@ msgid "Action" msgstr "Operace" msgid "entry" -msgstr "" - -msgid "entries" -msgstr "" +msgid_plural "entries" +msgstr[0] "položka" +msgstr[1] "položky" +msgstr[2] "položek" +msgstr[3] "položek" msgid "" "This object doesn’t have a change history. It probably wasn’t added via this " @@ -719,6 +769,9 @@ msgstr "E-mailová adresa:" msgid "Reset my password" msgstr "Obnovit heslo" +msgid "Select all objects on this page for an action" +msgstr "Vyberte všechny objekty na této stránce pro akci" + msgid "All dates" msgstr "Všechna data" diff --git a/django/contrib/admin/locale/cs/LC_MESSAGES/djangojs.mo b/django/contrib/admin/locale/cs/LC_MESSAGES/djangojs.mo index 828f705ac7ffdd88e6abcad9d159627b96598426..db715bc9fcda54e676e5233b94290fa497ad99a5 100644 GIT binary patch delta 2513 zcmbW1U2GIp6oBuRr7c!yg|<|Mc0k*L&=p%05U3zOVu6CR@*5LoyF*&o?ku~r#a5Fg zA;N>Lp;-wQqol?dNGwqojZu)mwu!v)!TVKe*z@))Zq$9gysJD~PLcrW%+ zwbv;(!O8fyDnmIYO$_B8Iu61~@Ksm?kHI?lF)W7PD}RC#z)j_C$YbvCl9>Gr7EXc^ z*c3PcmO~y>#Y^VTf_{@UW)8}B91XA?9)>*TDleIM1Ih-!LYa6AO2EHE9#cTn5_kzO z>92sV!x?Z8eh6jUDke!l8=%-*U=jP9T_{Uo2YeEqgv>GDDR02Hv2VgR;6RBnQCLTw zE8%hF8CZoqruH>>KlW`n9hQ=RvFoAOD`8S5>_B+{#*_n42A+bl!6oIlP$u4j6|i_p zZeBH%@k`)?unkUwuJRC+@yFF3QTyT)@?TEJ*EnRO-{1uwX)iVAB6g!fl3?~IrRK;V6p~9itm7Sq@fJ_97?fW zf>M0DD3sms4=4-n;=tv0>{f=9olyG2%Kge7?SDy`%rR*W>3}2J(XaMVnVikrV+`v*{V>(X1(f5U<>jPQlq{_u$ukNqw0`Clr}4e>`#UZkv%VQN%RjR@|&KC zNSZewQm}Glk05i9wMf2EUS>YBFz^uGX++Z6gv>=6kbGOIirkcZ zdj>_W-g0$pgi=qBBhMmSB=ZC!|Al!-Dd!1j>XB8* zW2u3O%bIKBR@@0Y9i9`i+^E;(My!bISv_6xu3*?P|LuNm|9x&USP$b)Jb~tg*k=4^LPx{E0M6q(w_<^y5!I;w% zu*98<%n!!7+cY{q%J`0KjDA8L=Wf?{{i2NTNjS45WIv&g>-albKU%uBBv4S-Vn?ja zcGMaB!dlkpMtVE?oP8@goQM}obO$>6n&(@M3mO-uUYuM#!H!1LLzA!glAJ_OZ!l&@ zGQ(Dn8xGo5#EE1^IH^#V=Y(;~Vd;?5*&)3Q*&BBgcgLLm-(yPuwNSdVbe^wpb7t6c z_N9i(nu;Q!(Ko}Hk@V%V^#wEA+@R~(rY|!*Hk27Lt&Vg$lt5p^?oRD5uS&0)=J(AQ z?e}_OEMQi1o@Qre#EaP`bAltyoKI~j-_f$u4rPY<%5E# delta 1844 zcmXxkZ%ma{9Ki8&k@#l>@i&w36hdlnLC`cJkaUEbhBoy=|sxwF;A(4+Ds;wify<7Td@XT#2kFn_%`yVPVkVqO<^{kHs!O%^T=3g4%gr% zlzuLo->>2el&@ho1!Co=Gl zDE-~w@g)9%@?I5>{aA-n_zIq6d{sg3QJlkatXZqn1K5fW;sK+J>nM+58BQDLQQlj@ zQoM!o-WtwB+E?Ow+=<25Z46>UUN~YZCQ!;}umnFt8E6^jeM;TL1nQIXMcKjkjb~8Keg^4ET`FMzC3BSuCaqRb2L26O@lWi;?S<(9Uqu<{E#nx< z07+AxMA_;OkW*0~8)uE58ow}pRmlGTN5gNaC}V}o_ooNCS(F~=HcCf-8SkJ>IGcTx z`Vy40uE24uHeN)zBhRoJnczM=fL*417CR`L^!z9_2 zM@;@Plu62^e3*EYV1w0m;vu4*s3N!v3DrnOZl|A+&#aB$6jpC8sEvetMw70dpJL=hky|$~mg3fUAd~Ru~A-BYr?*yz7)$I&Au1ob) zUVXncWQD?3Z`jt=F~91uW1j6wqaG)&gVvC(t*~obfe{^x_YQ_U&kkrW7>ena9e2>L z+g)3a&@vV`nPDs9Y0ojOb;#3JzZHtKrEcZT`cixIt1~)0*Ny~YQHQ=<-7*kz4_W@` zt|2EJ8S(dxw$|##hQ`LceO9DDZuQ%B-L^H@tap#veL=k`=y}oR`ugGF;nZBgbziEa zXp1ka>yW$nxtH8i+?0B)xHF@0bn(>Edy6ybpwsJGqaiQ#YiX5l?VgAoQwJAkJl9HA zmiIjS{FO1=wN$qqVY;%Kcv#-k1MGkv2rbQPCt%0IRygF>`=hQk6o~5qdqDRE`)pdI WfAsWd#2JdWr54I3eaXY?_WlnfM+;H_ diff --git a/django/contrib/admin/locale/cs/LC_MESSAGES/djangojs.po b/django/contrib/admin/locale/cs/LC_MESSAGES/djangojs.po index f4b781881f..1e8fa73739 100644 --- a/django/contrib/admin/locale/cs/LC_MESSAGES/djangojs.po +++ b/django/contrib/admin/locale/cs/LC_MESSAGES/djangojs.po @@ -2,7 +2,9 @@ # # Translators: # Jannis Leidel , 2011 -# trendspotter , 2022 +# Jan Papež , 2024 +# Jiří Podhorecký , 2024 +# Jiří Podhorecký , 2022 # Jirka Vejrazka , 2011 # Vláďa Macek , 2012,2014 # Vláďa Macek , 2015-2016,2020-2021 @@ -10,10 +12,10 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-05-17 05:26-0500\n" -"PO-Revision-Date: 2022-07-25 07:59+0000\n" -"Last-Translator: trendspotter \n" -"Language-Team: Czech (http://www.transifex.com/django/django/language/cs/)\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 07:59+0000\n" +"Last-Translator: Jan Papež , 2024\n" +"Language-Team: Czech (http://app.transifex.com/django/django/language/cs/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -67,6 +69,10 @@ msgstr "" "Seznam vybraných položek %s. Jednotlivě je lze odebrat tak, že na ně v " "rámečku klepnete a pak klepnete na šipku \"Odebrat mezi rámečky." +#, javascript-format +msgid "Type into this box to filter down the list of selected %s." +msgstr "Zadáním do tohoto pole vyfiltrujete seznam vybraných %s." + msgid "Remove all" msgstr "Odebrat vše" @@ -74,6 +80,14 @@ msgstr "Odebrat vše" msgid "Click to remove all chosen %s at once." msgstr "Chcete-li najednou odebrat všechny vybrané položky %s, klepněte sem." +#, javascript-format +msgid "%s selected option not visible" +msgid_plural "%s selected options not visible" +msgstr[0] "%s vybraná volba není viditelná" +msgstr[1] "%s vybrané volby nejsou viditelné" +msgstr[2] "%s vybrané volby nejsou viditelné" +msgstr[3] "%s vybrané volby nejsou viditelné" + msgid "%(sel)s of %(cnt)s selected" msgid_plural "%(sel)s of %(cnt)s selected" msgstr[0] "Vybrána je %(sel)s položka z celkem %(cnt)s." @@ -240,6 +254,55 @@ msgctxt "abbrev. month December" msgid "Dec" msgstr "Pro" +msgid "Sunday" +msgstr "Neděle" + +msgid "Monday" +msgstr "Pondělí" + +msgid "Tuesday" +msgstr "Úterý" + +msgid "Wednesday" +msgstr "Středa" + +msgid "Thursday" +msgstr "Čtvrtek" + +msgid "Friday" +msgstr "Pátek" + +msgid "Saturday" +msgstr "Sobota" + +msgctxt "abbrev. day Sunday" +msgid "Sun" +msgstr "Ned" + +msgctxt "abbrev. day Monday" +msgid "Mon" +msgstr "Pon" + +msgctxt "abbrev. day Tuesday" +msgid "Tue" +msgstr "Úte" + +msgctxt "abbrev. day Wednesday" +msgid "Wed" +msgstr "Stř" + +msgctxt "abbrev. day Thursday" +msgid "Thur" +msgstr "Čtv" + +msgctxt "abbrev. day Friday" +msgid "Fri" +msgstr "Pát" + +msgctxt "abbrev. day Saturday" +msgid "Sat" +msgstr "Sob" + msgctxt "one letter Sunday" msgid "S" msgstr "N" @@ -267,14 +330,3 @@ msgstr "P" msgctxt "one letter Saturday" msgid "S" msgstr "S" - -msgid "" -"You have already submitted this form. Are you sure you want to submit it " -"again?" -msgstr "Tento formulář jste již odeslali. Opravdu jej chcete odeslat znovu?" - -msgid "Show" -msgstr "Zobrazit" - -msgid "Hide" -msgstr "Skrýt" diff --git a/django/contrib/admin/locale/dsb/LC_MESSAGES/django.mo b/django/contrib/admin/locale/dsb/LC_MESSAGES/django.mo index db0f50af56795d943916e5201a3ffcaa8fefcc5f..cc67569f5460f75cc7328f5ae135f982e16ef45a 100644 GIT binary patch delta 4770 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 IJGLzR|8#M^;s5{u diff --git a/django/contrib/admin/locale/dsb/LC_MESSAGES/django.po b/django/contrib/admin/locale/dsb/LC_MESSAGES/django.po index 2c700c370f..31cbbba1e0 100644 --- a/django/contrib/admin/locale/dsb/LC_MESSAGES/django.po +++ b/django/contrib/admin/locale/dsb/LC_MESSAGES/django.po @@ -1,14 +1,14 @@ # This file is distributed under the same license as the Django package. # # Translators: -# Michael Wolf , 2016-2023 +# Michael Wolf , 2016-2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-09-18 11:41-0300\n" -"PO-Revision-Date: 2023-12-04 07:05+0000\n" -"Last-Translator: Michael Wolf , 2016-2023\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 07:05+0000\n" +"Last-Translator: Michael Wolf , 2016-2024\n" "Language-Team: Lower Sorbian (http://app.transifex.com/django/django/" "language/dsb/)\n" "MIME-Version: 1.0\n" @@ -199,11 +199,6 @@ msgid "" msgstr "" "{name} „{obj}“ jo se wuspěšnje změnił. Móžośo jen dołojce znowego wobźěłowaś." -#, python-brace-format -msgid "The {name} “{obj}” was added successfully. You may edit it again below." -msgstr "" -"{name} „{obj}“ jo se wuspěšnje pśidał. Móžośo jen dołojce znowego wobźěłowaś." - #, python-brace-format msgid "" "The {name} “{obj}” was changed successfully. You may add another {name} " @@ -373,6 +368,9 @@ msgstr "Zapódajśo wužywarske mě a gronidło." msgid "Change password" msgstr "Gronidło změniś" +msgid "Set password" +msgstr "Gronidło póstajiś" + msgid "Please correct the error below." msgid_plural "Please correct the errors below." msgstr[0] "Pšosym korigěrujśo slědujucu zmólku." @@ -384,6 +382,19 @@ msgstr[3] "Pšosym korigěrujśo slědujuce zmólki." msgid "Enter a new password for the user %(username)s." msgstr "Zapódajśo nowe gronidło za wužywarja %(username)s." +msgid "" +"This action will enable password-based authentication for " +"this user." +msgstr "" +"Toś ta akcija awtentifikaciju na zakłaźe gronidła za toś togo wužywarja " +" zmóžnijo ." + +msgid "Disable password-based authentication" +msgstr "Awtentifikaciju na zakłaźe gronidła znjemóžniś" + +msgid "Enable password-based authentication" +msgstr "Awtentifikaciju na zakłaźe gronidła zmóžniś" + msgid "Skip to main content" msgstr "Dalej ku głownemu wopśimjeśeju" diff --git a/django/contrib/admin/locale/es/LC_MESSAGES/django.mo b/django/contrib/admin/locale/es/LC_MESSAGES/django.mo index f1818ea1cd9e3deb5e04adc1c06e194b889779b7..379f20424b8554cbbdf5db4540f93221430338a9 100644 GIT binary patch delta 1678 zcmXZcYfO%D7{~D|MGl=vJS9A`(K;y{ z!Yn_-Y?PV3%rqN=y`Dp}%uX_%ge7~!Fj|)+m*ocX^4;9!cQ~+0zwX7RQ;x{B&78NoZhC%dU0gk{5 zoR1rD5MIJ0ypG!Uk;6qY7q3vM`GtDWa@-B0F_mEgPQYwb0OhC+9rWW7RB1X<>)gkK z*n>N9WviUmIK}cO{k{mL^a7(R1Z8ub@eCIi{DYtMb2{P zV=;+wl4mB4W?Y1{hb_khJdC^W3^t>$fXt{{JGnTA!)Ke7;T2Q>|4VSumG3S5Kwcii;GUp&kBTAgIR4f~t1)XivXsY6uUXlFt-^^yO9 zn1+#7IG0 z)EDCg+=B`vz*j^~l!FJb1o_C>LsSO-pbnC`z-$q=p&xsZf274Pbl)#Sm9P>cu&AC3 z)vUpDH>xL2pla8F%0M@&rah<=yv1nz(bW{=8<$bBwXUYYzqqElZc~-NV8_m6CgL;CFL<6fI@hcWFQV?h!R0uJHCQ^!Yy!68NbJB-*yY8&m_YmnW3eCg zy}?=L*klI&*=CuTkD6#5#^7Gh!>9?5qaW*WI9^6geAT;t7aiiq7{TBi_xaZtNBkKx zZ~!%bQXWt1MtYuE0H>o?whG5$7`3oNs0BojcdZ$d@i~$t`+%d-Ki4b`Ct?!L#|kXR z5qJ($unG0uTMmQq3?86T(~ElWJ?ev>Fde^P7RJqU7cd+3!HpQe8dPcOQS;ou(|8Y$ zU~xWUY)8dA=DV@;fq`n)SYXDVHScwpQit(6O=mN({iqK5*FZ74CjhCgrxHkP^zc#HbrA5<^IFLrmDiW7+Q zFo3I33*3$4uol%b^*9DwQS;nKW%8+ay$2no>Ky~UIEa+n{7X2~7{XjUfdRaO|1*F} z`A5`ye^IGTUh0-G3-#fA)F}yK2Cl~rtVLyJVUYZ*HamknjAv0hd4y_~PRzo;I1e+I zxjSErEyR0}gJJ$Mvke$T9nULX-0eA)U#s(6KaN{5CFExGXvpDgbD@q4s_Acx#^KZ< z3S&_{5RckvHcrJN)WXB41=gXC<8@Ro+(T`o6E$BCs)Vo5kMB_>{N^xF>SD`XQ&FkU z!CSZ)wUC4gw~3PR6!8?~N6v1dGSG+G$e5L8m3RUJ*n@@m9o2->R=FiCLLYIkl7Wt0 zmFFf@PaHti?kp+;EvTBdqju1NBk^V1nYgq`F;(H(@a~=A+(28`jA^5N2QU0Axa2$7 O)=)SY4<|#l(f, 2020-2023 +# Uriel Medina , 2020-2024 # Veronicabh , 2015 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-05-22 11:46-0300\n" -"PO-Revision-Date: 2024-08-07 07:05+0000\n" -"Last-Translator: Natalia, 2024\n" +"PO-Revision-Date: 2024-10-07 07:05+0000\n" +"Last-Translator: Uriel Medina , 2020-2024\n" "Language-Team: Spanish (http://app.transifex.com/django/django/language/" "es/)\n" "MIME-Version: 1.0\n" @@ -411,13 +411,13 @@ msgid "" "this user." msgstr "" "Esta acción habilitará la autenticación basada en " -"contraseñas para este usuario." +"contraseña para este usuario." msgid "Disable password-based authentication" -msgstr "Deshabilitar la autenticación basada en contraseñas" +msgstr "Deshabilitar la autenticación basada en contraseña" msgid "Enable password-based authentication" -msgstr "Habilitar la autenticación basada en contraseñas" +msgstr "Habilitar la autenticación basada en contraseña" msgid "Skip to main content" msgstr "Saltar al contenido principal" diff --git a/django/contrib/admin/locale/es_AR/LC_MESSAGES/django.mo b/django/contrib/admin/locale/es_AR/LC_MESSAGES/django.mo index 22f0ba35b2d52b114adc0b756b8dd50de5b18d95..6ffb9267c6e4fb9fc67ceeca39bb22ea557217d2 100644 GIT binary patch delta 4818 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 delta 4384 zcmXxm3sBWn0>|+Km!}9QqJpAc1VKPh6f~2StD$0wlGu_dt1Kp~7=mI#YB$LwA7yx@ zR;3lSHO<9Gx6(>oQ`*|m-qUNgux*;Q*R1Q#HtE<*`~BVj;f%lgIsgB?_q_iX_dOl- z>FywJcU(xDp>&ZXQV?cLc#tuRdh4z+jeU&ik4-oLcj90?jQ8S2Ov534o%=;NgX<-j zk4I47??#$7|HE*+g)U>f#uaCb`U*#VARhIF!KeY{TIb+Eu4_=Ad&Ig8Be-tG7~G3A zY>r|icG~w(<3_G8;AWiM&zNZXHT?yS0al?_ zWCdy<&6tkur~!51P`qN_{{c0SP-fYPG3c$Q(n94p-o#~igjNq>Y=ZLzKk{937B#>R zFdDx`4e-CHfdw%N4~C;UE=CQs8a2>bEXOUFirtB!^-jMs@fmYNj8f2KohRORl4q*fq=<;9%rf88@=pCLcA?xu^kDpxW^+ zr=l6up&EP;)!-ADi5-}YmvIE%M9pNF+ga*Ks1+(kZQVjt2TM^aQip1{5jCJ4cnS|7 z?RiaEvNOUa%-{_l>Wk-aGQNRqvk772@^Bb(PR)E=i#3>o|3s}|pA=(eVI_{iPMn9` zSc18nJgu-7d+8KKGK@vsh)1nNJ%-|X>n7BSw4kCZCDWb~@xY$}>rE^1^RjK&hw2Nz-_R$J@s{q?9Bw%~yv_7=4@ zIayA}(@9 z_!xEg{)1Y&;9TdqosRlRElwK6RjhPzN5?m=zEK}^B($Uo!#iq|MA@nfAO zbfX63K{d1xTX7lcu-?EIv2mR9XEd8<@++=iz;JBiL~7vAptj^R#^5IykKdpMbPMOI z$&m5J(59J>YM=$(xDy-kBx4^_o6oTiMo;3=!J+sX?!yKwFW@_P1sC8(9(o1Rz`WC9gZXAwb)13ikpw7Z9FBN^T95s{sQ4Oud zFl<5{%7;-~^CYU{PSg^fMxG?|2JXRIsPDJUaL&#i+`;wpn1vIHorzZALtJ|wr@~}S z@0reCm7*G~M;*TBPgk$-nqVoa9hFEu z|G7>*usqwTYuV3|*<=aPlc2JS=(KB}pCuXOI5|Yv9kYe7?WUgGLv-T*Kv?;}?*Rn< zno5<|$!mK4wLGVEhw>K((_~Gz{?00xK;UnJ_D?fc(HZ(ZNh8{ZT|{LWd6KXzf$}J? zTJ~+urAeUw!2e3t+Z*BuGR$7zg?S{CJWuW=TS*O32_+lI{Y1~co(h#_vNuq39_>o% z+J-;bd#_>v@doqKNVIo7MF&l#%)wMxIV$D?`6JPx-AP81a-#AISwm9EQKIwHQ=X=h zOdcaXvXP9{{;QlJO9M6M@ZCn;P3DnWa*_0uRw^fm4%tiO2vK>FJVHk3f)YWhiHGbb zestoA`g>GWH~7%o5{=MFsULFNpF%vRuYwS4uSs@9;5z@y&hy; zXI)_p*V)`{FXF5Vak2kgpW+B#R^n`bdtzC*{};F0Z?ip*?(rlcOgUOR5nzuTwduOS+t_EwtAI&`h6=`u3DEd$~|_>*m3?>Gq*, 2011 # Leonardo José Guzmán , 2013 -# Natalia (Django Fellow), 2023 -# Natalia (Django Fellow), 2023 -# Ramiro Morales, 2013-2023 +# Natalia, 2023 +# Natalia, 2023 +# Ramiro Morales, 2013-2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-09-18 11:41-0300\n" -"PO-Revision-Date: 2023-12-04 07:05+0000\n" -"Last-Translator: Natalia (Django Fellow), 2023\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 07:05+0000\n" +"Last-Translator: Ramiro Morales, 2013-2024\n" "Language-Team: Spanish (Argentina) (http://app.transifex.com/django/django/" "language/es_AR/)\n" "MIME-Version: 1.0\n" @@ -205,10 +205,6 @@ msgid "" msgstr "" "Se modificó con éxito {name} \"{obj}”. Puede modificarlo/a nuevamente abajo." -#, python-brace-format -msgid "The {name} “{obj}” was added successfully. You may edit it again below." -msgstr "Se agregó con éxito {name} \"{obj}”. Puede modificarlo/a abajo." - #, python-brace-format msgid "" "The {name} “{obj}” was changed successfully. You may add another {name} " @@ -377,6 +373,9 @@ msgstr "Introduzca un nombre de usuario y una contraseña." msgid "Change password" msgstr "Cambiar contraseña" +msgid "Set password" +msgstr "Establecer contraseña" + msgid "Please correct the error below." msgid_plural "Please correct the errors below." msgstr[0] "Por favor, corrija el siguiente error." @@ -389,6 +388,19 @@ msgstr "" "Introduzca una nueva contraseña para el usuario %(username)s." +msgid "" +"This action will enable password-based authentication for " +"this user." +msgstr "" +"Esta acción activará la autenticación basada en contraseñas " +"para este usuario." + +msgid "Disable password-based authentication" +msgstr "Desactivar la autenticación basada en contraseñas" + +msgid "Enable password-based authentication" +msgstr "Activar la autenticación basada en contraseñas" + msgid "Skip to main content" msgstr "Ir al contenido principal" diff --git a/django/contrib/admin/locale/ga/LC_MESSAGES/django.mo b/django/contrib/admin/locale/ga/LC_MESSAGES/django.mo index 8c029af57b53832163a22c957cdb819f8fad363d..4f4d2865003a55d0b68e3233eb05f39bb9ddcd7b 100644 GIT binary patch literal 19428 zcmdU$dz4*OeaANfiUE9sMtmI5m>HOvBm@M9#4yPuAxa=70|+YN%)MvsJ>=eVF6W$^ zVN@zA+N!9vRaBJL_@)|Pu~nl*>4;i&wLaRa%c@JX{^446VQrVKk7YmKz4tly+{uK( zvi32Ho$q<QHn4-`K>0*a0=f~&zFf}-an7V`w~ zQJ~(h2SvwD@Otoa@H+5s!4H5_3^oVe1HJ>i;xVrOFTqvZAIBgJZO#O>jtfEYZ#O79 zuK`703O*U^gBOCgf}-Qwpy>VuD7ue%EOUS>LG`~5Ou$>f2Y|;TOrrM$Q2X<6Q0sa; zcrmyNJPypj7lHGj#``&_c`ikGBv+S%`mO=YdZLBM=cW?*z{QKMf+n=3l`+ zc;b_cnE+o5ijN-x*Mi3&WV^w$!JXjCK=JqM;APv6XzyB^M{{0BlzWof;yeF=9{5u7F z8uw2CUkyGRJQn;BsBwP`z6AUQcrJLuh_joAz-zhx3b+xx0A`AB3!wJ%^`Q3U(;mMB zYTR#tTGzKh(e-2SWbo&p`XA574+bCZ@ib7+SAkmJI`GxUAn%~o^Vzf9e*YsVdASGt zGI-LMvp3%Y5qWdrxYO&a!CSe1ABgEO+t|zpfqOy8Q_J7?Kv`AX z1N;hjJb2pKPX12^AHx0lpyt~Sik`jT1HrbxPeJM5^`Q3SW)KlE?*&EASHS@MHmG@j z<)1%#J+_nk)4|^dUk%;@o`Mp_;QPT3fu|yb8t3yMB$}^+4+oEBk<#l^K;5qa#m6a7 z^j!h6<>qSeS>VketTx{TwT_3J=jeSjcs}>*L54OR@D1SGLCNp=yj1@Upw_t+6rZjH zuL1Y^`_F)HnLGANlP;zq@h-)!l1s?(a1l0G(T;S}?N>KD|0KWt7 z2LBLTy8)jD-U%K8H*R!%{3)pMwqQI(*EOK#TL87Lo506{w|M+8D7wE42H-z{TJO(6 z(Q(=)x9;_z_%RJiuXci>>nc#=^*~h3yb9z$bJ*Yi0>s3d(F@)Bo(YPstNs1F$5(=< z^87YX>6wh$>?PDOUHQxZG zCo7-n=o|%)X(ikd;*Z#1GjpX+xz3lqzBjS7|rj#@wT9u zMtO4gjc+c3=z5kr5$uYxcG$~vwLCjA_#?k2YoCTY=*GTwDlXo218Ie5B1%4X9%@*AU1uY z=LW6x1?lXyka+`3o$xR1`rTv80{`5Dr6zXd4T}Klv}<}1bLj8!91-Uxe9b8kt=8Jhwz5^m{(xwO+s=i{Wsu6LNF$#z8D zJeZH^GaHq=0WlBd9Dv&fqOq|^xA~u=LSrj%KS-(4*n=N6&{*|n# z_IHa_4dWnKML+u>Xd{7XwlGAyfA=HjT+%x{3P z+0mrKeKY7gQGLBsVi2s?!_0;yI!7e^r_9%h!Yl~cBxhH6WuG__Wk|Mk;>NxJiH;;A z?z!FaitCLm&0#)c^uiXBwxxr7n=NTF7iZmy8O+tsvM4D!3zKF#EW+6^kAf)6(oDC} znj-E-_KMe5hdl&ctVrDJM1h~Ne7+1D-G`n^gmBeJUETKfI{hq^O1gfVJRVj5T(_pP zK&9YMpqk}}o>a;Gy%^kJKJ9m!2<3JC7&bPwI(;&%IK3<_tbwYe*RL1p8u41?wNG1U zX)8xrs;{e$)YsL&Efv4TjPe6PoD5c88VSF`v0%1e$S5I-4eJe@nO|K5?Qnk-^rEaA z=Q-lI#7+&&PO;F7a#^F2X~X2!WW{$VP1|p|H}`j%|3y}y%+qlm&Z0@BMH-h9;+^`4 zVp7Bn7duQ}OCXRgjVS!n9K-Hjnd!9A@A94dYHK%)JG^P))$>WSwc9He%+};S%(pcm zq6xwviRLTHtl^V_^mE>AAg)Q1*3(yw=+-&i4Qu?v31)EvlrOC(DAzb)w%L%$Ly&~~ z2wW653F8zA=3HAxW-dxGRLyigkQ<#1}=|@uJa=@Kcswc`xiLB56k1gxO)^kZwOO6o*uH0BeMYX2aP) z%nNR|i|w&Hr=>AvcOtkX^3nE&!d#rTFliowuoe27v|s2U+m|f_m)c;C z`*dHwXLc$eBv7@(W7K_|OZ<+HbxO2zp`^lGQqzV>b4kj7{#~_-2|crW3A%`3K;R`Q zTO+1+qhK~{?4xfI*?)p?KdLJ6<(4?wYN{hOH@ooRfnuOJB%{f#i)H+{gL||*DwfXoCkdijOsSIkrDzlh&I_#>-wEEPaO4qzNCXwQhi+eq{J8tZcbnblG%18vA8xzp{>Vcxm!(~Jl*tnD z4510?A@c6N(}qeh-6&=ce&7CMDM9-|n^+AVB5VxWN0KnW8eQMm?)&3t-rwc&DrOH+ zZlet-1yrzJU1|AFr-z@pAzXijwo4O6o8I+1RUYRDR97EhI5QIGY%ly&9FK^Ut8)Vv zjD{hN%1Wk#pCs9o?{otMZ+TpM6KCQMMEBi%PD{o_0E~ z0Nq`9lfMV^KO1IdPvy`ts=j)#XJ6bCXK*}{U!*Q6%pS}+6l>3s%y~IvYk!^5#SFQS z-WD1KL>N|AJVy*DA@Q&Ga~DZ&hsw9sQ|TC~fAB-ndum5?%pWe8WV zPbY3Yf_b#JM@LWlxR`ys@ym23CfHK@IqOfbnDvb_olumZyWS^~{#L0dr zh50?Qx_GuD!`KMnr>t3<*dgqQ@p_Cw;(2o-2)tcWh7)1*mxOY51}!dHlFF*eVJAhu zF_*)Ir~B7ExRR2F%y`XIl(X50>0ameUj4pPu^FxBT^XFmMyq^9HMQ_0*yuptQW)b5w9pZ zlyE3OoN!+%T341rMazyl&g&eJ6I3TDRLTp6tcEjnhTwnvU=?3)~s$?p1R^Po=-p21_H@x zo!p2I6Tuah5hAS<Hx&9Jv`fF1v#OFPz8xgPhy%e!h^K)jb`P0?K$k*K z8gE?YI$^84wiQFtQRBuV(aCdm$M}FnEj;H&}b#Tvejv(KS_((1Fk@flqBWUwQP^L8-OE{fjdnl;2e69jK$E_2cK6R7kWM`Q^d z|M8kuxMp<4&K*0q4wkcSV(p48F2)<5fn}3H5nW%b>2(PHF3?_OZ1l#f$m*Ty z9-}e=Wfoqvvk=P@1qd=>aC`A^ti!1PHy!N(8-f%z+a=lMBl6wFgTMX5<<9KlwA)!c zkeEvr4=PFW%*1WBEi*Yt;TAko=#4-_VUOm@dyghElSLOWeimnBArF zB$msL)y>5NMQEmoDEw6t%(mzHRC)_6RU=Nw4GEC~$aPkwj>MXPJdz(5DM)YF>hn*Kj4vL<<6wVUVcIFmrC{KfrAz0Eh;&1?i0H$b zB$OnW^HN_Y(`${HvNovIMu@l~^ixDvKBSVxARH{$9(Bo9(?-bYU5IQ9x-R>0u=<+3 zm7}u=O}=O8#FnkbMb)7WZ@lo0V&Y3Bu z%FbhmJ8+8*M>Uqqy5n#Pu5cCe5}mjiKWJo#SlMY)%n;LDkW32{ORRpMT+gfO|C2UzEs!Jf&|N+ zVk+BX@D@U^lj|htN}(u;*EP0InN{cp&IMPrgt|$ybMb)h%X@3mjv!-MDja{%I!G^# zS7jL{f+=iTB9Dk^As}v%vIY$T4y*~BDnEdlfwij{uG&^$mj+wGrzMY;F=@eY&vrG7 zH&xjvYF3PYwb879NFIF|v)m2stKBo|Tx3Ev&d?4(l(U(dri(_1$ra7i@P=3+ zKA@*!M6H(w!IhxR9VylDX6ju(?@8wu57r1q(GD_JH)L7TSxi^fc0?|$HWdX+XJx6ebAb*WB(%UXu@ia2i3euN26bM9bT8S8+_DDM2c5VuW zmdd-lz0AfSqHGg&0K0UoLkDH;VknAC9FdgO_tAL|7YJw@kU@keTRcp0Xz_M)F_mZ8 zce~r#8Zs=o12QoTe8CmJcOe$it6cNS&?0S}#l!aWRIBC5r5VDcnkS30N2ktb*$=vO z5icDLjLYT`IFzny!faM~#q1<;QUoReu{Ks=ShW(JW80Wagdj?A2USJP6eKYjGNS&K zoM2r%@1UsB#>Vm8MZ0G% zQrSvmewsx7I9_y(x?;P}p`1*mq>ELTg2)~aMrZ>#O|`1xsa|q_EzDdzm{(83E}LsE zEdxqE-fAlVTl!(v)T=#A?92>RD(826{6+jr;upp_C$#|?ht+e=2HM*9D$0_YavlrG z<}!>;&~p81#*<@qRM!d2G#+1$Kkn)zO<|ogMSRbXszQ!v7Z0^04@@gp#xJ0nXo9}t z;hYw3N8@--vR1B35r>9QEN&^ZE2)Jv3ar?~n#w6G%aLhkEeGo<;~sj$aVz#mbU9A} zkW+IfAK3Xq0Z0bBkQbKAwJe%W>#aQ3qz~&<^~A)mY}Xa~|1WnQvZxAAR1or_veckT zZ8=1;*4xL+-rvuqamJ4!f|*cp5nHNovPthy@h$r&7c=KWAY{f13%tRqE*{9qI#R{M z=)pjrDV0?oWQk!#xef$Jnv- zGA*n<3j9HQX>zN8)XZS(dvbv;5hbK@k8r6{l3Hl7Ssn?~K`hTQ%KD5|njlg+ztR-Dger=~bZT58*HU*lY{}W2 zl)BOK2m3S1c;uas_qwI9Q5SRjN<$>=onFnXw&a2URp|>x-_?JI4*RG0VNBem-m+bl zVzx%VlaQ|3c$FU}C=?`e?aGHYCG)Lz(`~LIWy=&rKekdQI(+7_U9zd5J%I~J+}F?b zj-0>>xX%#SuZC=War)60;5`=gI5N7?{0#jtQIV_csk~b4q{nQ=yxJ6CI252?-4>E9 zCoL9m0oh@IC8WJtPdhg#YEk}&b7WoAtZ#HjZJBXxxOr}%uFyjbHRsxyi@O4I_7E{u+%SZMyEE0^d znYo0ikR&76rT7f16B7|c5sydOU(#$Q zbnGuZql!Oee(WNIS|OlHk}Cr|s0ffC*&JKzi_i-B1!a5(;;yf4+dyAGBIG4RQYci2 z<7`vqO8CVAzo}h3gl;Q`lckb|L8Ox%*r8+5O3}qPe4*8JJL43Fu%j9_cV?KsElw{j-k;WT{^{4K5C}? zd@j7Ny>oJveAK2bvUU9Gl;x-}VVP)aF$wk7#amr%gXDRt3OTAP1s3{0b7WVm;*8m5 zg9tsTj!bHam;1o;i~XuN&UeH}{32rU#nN+#LW*w>6`i{BRGMMMs}m_ctVI<{3t^oi z8?rcRONgOTX_9~F5F>3hh~GWoSmXi*B?bi9S(f1%#z6YV$oUS)l_D~(Du!9MLIVx; zp{=SSgSGUXL$pexn#g4ktJbJhC?2fTO5#lI%BGq%x#p=IY^ZJ~+18@!xlYBSs+y^) z%n*m9f6Dgp#9_?g-c*?kST^dX5tgKSTH#hJGrP&D7}1C-r5gJ_mznr|P|HnWEsFG0 zSuA|Rsw>Yb)mik`xhaBKzh{-5wV<5WuxW+%+p>o7N+VU;4j79$lH2uF%ql*yRkmSw zYAuO6*ZrDm0ZokE5%zc~m-xMF%r6VAOI|XDw93^HD78_Mf$2l_KDLbCl7ua+H)7z= z>y&d2)#NO%InkJ<=phD${sfaB&sUe&ZDVVSGJsNHdRi_UU$2FYHm@~RLRwzg8q0mX iVez4|K2=5ChxI4qITRMKTK168=+_y8yJ`opBmW8a8=u_( delta 5741 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 DEy-(n diff --git a/django/contrib/admin/locale/ga/LC_MESSAGES/django.po b/django/contrib/admin/locale/ga/LC_MESSAGES/django.po index 252e50d065..bc55f33531 100644 --- a/django/contrib/admin/locale/ga/LC_MESSAGES/django.po +++ b/django/contrib/admin/locale/ga/LC_MESSAGES/django.po @@ -1,6 +1,7 @@ # This file is distributed under the same license as the Django package. # # Translators: +# Aindriú Mac Giolla Eoin, 2024 # Jannis Leidel , 2011 # Luke Blaney , 2019 # Michael Thornhill , 2011-2012,2015 @@ -8,10 +9,10 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-01-16 20:42+0100\n" -"PO-Revision-Date: 2019-06-22 21:17+0000\n" -"Last-Translator: Luke Blaney \n" -"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 07:05+0000\n" +"Last-Translator: Aindriú Mac Giolla Eoin, 2024\n" +"Language-Team: Irish (http://app.transifex.com/django/django/language/ga/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -19,6 +20,10 @@ msgstr "" "Plural-Forms: nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : " "4);\n" +#, python-format +msgid "Delete selected %(verbose_name_plural)s" +msgstr "Scrios %(verbose_name_plural) roghnaithe" + #, python-format msgid "Successfully deleted %(count)d %(items)s." msgstr "D'éirigh le scriosadh %(count)d %(items)s." @@ -30,10 +35,6 @@ msgstr "Ní féidir scriosadh %(name)s " msgid "Are you sure?" msgstr "An bhfuil tú cinnte?" -#, python-format -msgid "Delete selected %(verbose_name_plural)s" -msgstr "Scrios %(verbose_name_plural) roghnaithe" - msgid "Administration" msgstr "Riarachán" @@ -70,6 +71,12 @@ msgstr "Gan dáta" msgid "Has date" msgstr "Le dáta" +msgid "Empty" +msgstr "Folamh" + +msgid "Not empty" +msgstr "Gan folamh" + #, python-format msgid "" "Please enter the correct %(username)s and password for a staff account. Note " @@ -89,7 +96,7 @@ msgid "Remove" msgstr "Tóg amach" msgid "Addition" -msgstr "" +msgstr "Suimiú" msgid "Change" msgstr "Athraigh" @@ -104,7 +111,7 @@ msgid "user" msgstr "úsáideoir" msgid "content type" -msgstr "" +msgstr "cineál ábhair" msgid "object id" msgstr "id oibiacht" @@ -127,23 +134,23 @@ msgid "log entries" msgstr "loga iontrálacha" #, python-format -msgid "Added \"%(object)s\"." -msgstr "\"%(object)s\" curtha isteach." +msgid "Added “%(object)s”." +msgstr "Curtha leis “%(object)s”." #, python-format -msgid "Changed \"%(object)s\" - %(changes)s" -msgstr "\"%(object)s\" - %(changes)s aithrithe" +msgid "Changed “%(object)s” — %(changes)s" +msgstr "Athraithe “%(object)s” — %(changes)s" #, python-format -msgid "Deleted \"%(object)s.\"" -msgstr "\"%(object)s.\" scrioste" +msgid "Deleted “%(object)s.”" +msgstr "Scriosta “%(object)s.”" msgid "LogEntry Object" msgstr "Oibiacht LogEntry" #, python-brace-format -msgid "Added {name} \"{object}\"." -msgstr "{name} curtha leis \"{object}\"." +msgid "Added {name} “{object}”." +msgstr "Cuireadh {name} “{object}”." msgid "Added." msgstr "Curtha leis." @@ -152,16 +159,16 @@ msgid "and" msgstr "agus" #, python-brace-format -msgid "Changed {fields} for {name} \"{object}\"." -msgstr "{fields} athrithe don {name} \"{object}\"." +msgid "Changed {fields} for {name} “{object}”." +msgstr "Athraíodh {fields} le haghaidh {name} “{object}”." #, python-brace-format msgid "Changed {fields}." msgstr "{fields} athrithe." #, python-brace-format -msgid "Deleted {name} \"{object}\"." -msgstr "{name} scrioste: \"{object}\"." +msgid "Deleted {name} “{object}”." +msgstr "Scriosadh {name} “{object}”." msgid "No fields changed." msgstr "Dada réimse aithraithe" @@ -169,48 +176,46 @@ msgstr "Dada réimse aithraithe" msgid "None" msgstr "Dada" -msgid "" -"Hold down \"Control\", or \"Command\" on a Mac, to select more than one." +msgid "Hold down “Control”, or “Command” on a Mac, to select more than one." msgstr "" -"Coinnigh síos \"Control\", nó \"Command\" ar Mac chun níos mó ná ceann " -"amháin a roghnú." +"Coinnigh síos “Rialú”, nó “Ordú” ar Mac, chun níos mó ná ceann amháin a " +"roghnú." + +msgid "Select this object for an action - {}" +msgstr "Roghnaigh an réad seo le haghaidh gnímh - {}" #, python-brace-format -msgid "The {name} \"{obj}\" was added successfully." -msgstr "Bhí {name} \"{obj}\" curtha leis go rathúil" +msgid "The {name} “{obj}” was added successfully." +msgstr "Cuireadh an {name} “{obj}” leis go rathúil." msgid "You may edit it again below." msgstr "Thig leat é a athrú arís faoi seo." #, python-brace-format msgid "" -"The {name} \"{obj}\" was added successfully. You may add another {name} " +"The {name} “{obj}” was added successfully. You may add another {name} below." +msgstr "" +"Cuireadh an {name} “{obj}” leis go rathúil. Is féidir leat {name} eile a " +"chur leis thíos." + +#, python-brace-format +msgid "" +"The {name} “{obj}” was changed successfully. You may edit it again below." +msgstr "" +"Athraíodh an {name} “{obj}” go rathúil. Is féidir leat é a chur in eagar " +"arís thíos." + +#, python-brace-format +msgid "" +"The {name} “{obj}” was changed successfully. You may add another {name} " "below." msgstr "" +"Athraíodh an {name} “{obj}” go rathúil. Is féidir leat {name} eile a chur " +"leis thíos." #, python-brace-format -msgid "" -"The {name} \"{obj}\" was changed successfully. You may edit it again below." -msgstr "" -"D'athraigh {name} \"{obj}\" go rathúil.\n" -"Thig leat é a athrú arís faoi seo." - -#, python-brace-format -msgid "" -"The {name} \"{obj}\" was added successfully. You may edit it again below." -msgstr "" - -#, python-brace-format -msgid "" -"The {name} \"{obj}\" was changed successfully. You may add another {name} " -"below." -msgstr "" -"D'athraigh {name} \"{obj}\" go rathúil.\n" -"Thig leat {name} eile a chuir leis." - -#, python-brace-format -msgid "The {name} \"{obj}\" was changed successfully." -msgstr "D'athraigh {name} \"{obj}\" go rathúil." +msgid "The {name} “{obj}” was changed successfully." +msgstr "Athraíodh an {name} “{obj}” go rathúil." msgid "" "Items must be selected in order to perform actions on them. No items have " @@ -223,12 +228,12 @@ msgid "No action selected." msgstr "Uimh gníomh roghnaithe." #, python-format -msgid "The %(name)s \"%(obj)s\" was deleted successfully." -msgstr "Bhí %(name)s \"%(obj)s\" scrioste go rathúil." +msgid "The %(name)s “%(obj)s” was deleted successfully." +msgstr "D'éirigh le scriosadh %(name)s \"%(obj)s\"." #, python-format -msgid "%(name)s with ID \"%(key)s\" doesn't exist. Perhaps it was deleted?" -msgstr "Níl%(name)s ann le aitheantais \"%(key)s\". B'fhéidir gur scriosadh é?" +msgid "%(name)s with ID “%(key)s” doesn’t exist. Perhaps it was deleted?" +msgstr "Níl %(name)s le haitheantas “%(key)s” ann. B'fhéidir gur scriosadh é?" #, python-format msgid "Add %s" @@ -271,8 +276,9 @@ msgstr "0 as %(cnt)s roghnaithe." msgid "Change history: %s" msgstr "Athraigh stáir %s" -#. Translators: Model verbose name and instance representation, -#. suitable to be an item in a list. +#. Translators: Model verbose name and instance +#. representation, suitable to be an item in a +#. list. #, python-format msgid "%(class_name)s %(instance)s" msgstr "%(class_name)s %(instance)s" @@ -304,8 +310,8 @@ msgstr "%(app)s riaracháin" msgid "Page not found" msgstr "Ní bhfuarthas an leathanach" -msgid "We're sorry, but the requested page could not be found." -msgstr "Tá brón orainn, ach ní bhfuarthas an leathanach iarraite." +msgid "We’re sorry, but the requested page could not be found." +msgstr "Ár leithscéal, ach níorbh fhéidir an leathanach iarrtha a aimsiú." msgid "Home" msgstr "Baile" @@ -320,11 +326,11 @@ msgid "Server Error (500)" msgstr "Botún Freastalaí (500)" msgid "" -"There's been an error. It's been reported to the site administrators via " +"There’s been an error. It’s been reported to the site administrators via " "email and should be fixed shortly. Thanks for your patience." msgstr "" -"Tharla earráid. Tuairiscíodh don riarthóirí suíomh tríd an ríomhphost agus " -"ba chóir a shocrú go luath. Go raibh maith agat as do foighne." +"Tharla earráid. Tuairiscíodh do riarthóirí an tsuímh trí ríomhphost agus ba " +"cheart é a shocrú go luath. Go raibh maith agat as do foighne." msgid "Run the selected action" msgstr "Rith an gníomh roghnaithe" @@ -343,12 +349,26 @@ msgstr "Roghnaigh gach %(total_count)s %(module_name)s" msgid "Clear selection" msgstr "Scroiseadh modhnóir" +msgid "Breadcrumbs" +msgstr "Brioscáin aráin" + +#, python-format +msgid "Models in the %(name)s application" +msgstr "Samhlacha ins an %(name)s iarratais" + +msgid "Add" +msgstr "Cuir le" + +msgid "View" +msgstr "Amharc ar" + +msgid "You don’t have permission to view or edit anything." +msgstr "Níl cead agat aon rud a fheiceáil ná a chur in eagar." + msgid "" -"First, enter a username and password. Then, you'll be able to edit more user " +"First, enter a username and password. Then, you’ll be able to edit more user " "options." -msgstr "" -"Ar dtús, iontráil ainm úsaideoir agus focal faire. Ansin, beidh tú in ann " -"cuir in eagar níos mó roghaí úsaideoira." +msgstr "Níl cead agat aon rud a fheiceáil ná a chur in eagar." msgid "Enter a username and password." msgstr "Cuir isteach ainm úsáideora agus focal faire." @@ -356,11 +376,16 @@ msgstr "Cuir isteach ainm úsáideora agus focal faire." msgid "Change password" msgstr "Athraigh focal faire" -msgid "Please correct the error below." -msgstr "Ceartaigh an botún thíos le do thoil." +msgid "Set password" +msgstr "Socraigh pasfhocal" -msgid "Please correct the errors below." -msgstr "Le do thoil cheartú earráidí thíos." +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Ceartaigh an earráid thíos le do thoil." +msgstr[1] "Ceartaigh na hearráidí thíos le do thoil." +msgstr[2] "Ceartaigh na hearráidí thíos le do thoil." +msgstr[3] "Ceartaigh na hearráidí thíos le do thoil." +msgstr[4] "Ceartaigh na hearráidí thíos le do thoil." #, python-format msgid "Enter a new password for the user %(username)s." @@ -368,6 +393,22 @@ msgstr "" "Iontráil focal faire nua le hadhaigh an úsaideor %(username)s." +msgid "" +"This action will enable password-based authentication for " +"this user." +msgstr "" +"Cumasóidh an gníomh seo fhíordheimhniú pasfhocal-bhunaithe " +"don úsáideoir seo." + +msgid "Disable password-based authentication" +msgstr "Díchumasaigh fíordheimhniú pasfhocal-bhunaithe" + +msgid "Enable password-based authentication" +msgstr "Cumasaigh fíordheimhniú pasfhocal-bhunaithe" + +msgid "Skip to main content" +msgstr "Téigh ar aghaidh chuig an bpríomhábhar" + msgid "Welcome," msgstr "Fáilte" @@ -393,6 +434,15 @@ msgstr "Breath ar suíomh" msgid "Filter" msgstr "Scagaire" +msgid "Hide counts" +msgstr "Folaigh comhaireamh" + +msgid "Show counts" +msgstr "Taispeáin comhaireamh" + +msgid "Clear all filters" +msgstr "Glan na scagairí go léir" + msgid "Remove from sorting" msgstr "Bain as sórtáil" @@ -403,6 +453,15 @@ msgstr "Sórtáil tosaíocht: %(priority_number)s" msgid "Toggle sorting" msgstr "Toggle sórtáil" +msgid "Toggle theme (current theme: auto)" +msgstr "Scoránaigh an téama (téama reatha: uathoibríoch)" + +msgid "Toggle theme (current theme: light)" +msgstr "Scoránaigh an téama (téama reatha: solas)" + +msgid "Toggle theme (current theme: dark)" +msgstr "Scoránaigh an téama (téama reatha: dorcha)" + msgid "Delete" msgstr "Cealaigh" @@ -434,8 +493,8 @@ msgstr "" msgid "Objects" msgstr "Oibiachtaí" -msgid "Yes, I'm sure" -msgstr "Táim cinnte" +msgid "Yes, I’m sure" +msgstr "Sea, táim cinnte" msgid "No, take me back" msgstr "Ní hea, tóg ar ais mé" @@ -469,9 +528,6 @@ msgstr "" "An bhfuil tú cinnte gur mian leat a scriosadh %(objects_name)s roghnaithe? " "Beidh gach ceann de na nithe seo a leanas agus a n-ítimí gaolta scroiste:" -msgid "View" -msgstr "Amharc ar" - msgid "Delete?" msgstr "Cealaigh?" @@ -482,46 +538,59 @@ msgstr " Trí %(filter_title)s " msgid "Summary" msgstr "Achoimre" -#, python-format -msgid "Models in the %(name)s application" -msgstr "Samhlacha ins an %(name)s iarratais" - -msgid "Add" -msgstr "Cuir le" - -msgid "You don't have permission to view or edit anything." -msgstr "" - msgid "Recent actions" -msgstr "" +msgstr "Gníomhartha le déanaí" msgid "My actions" -msgstr "" +msgstr "Mo ghníomhartha" msgid "None available" msgstr "Dada ar fáil" +msgid "Added:" +msgstr "Curtha leis:" + +msgid "Changed:" +msgstr "Athraithe:" + +msgid "Deleted:" +msgstr "Scriosta:" + msgid "Unknown content" msgstr "Inneachair anaithnid" msgid "" -"Something's wrong with your database installation. Make sure the appropriate " +"Something’s wrong with your database installation. Make sure the appropriate " "database tables have been created, and make sure the database is readable by " "the appropriate user." msgstr "" -"Tá rud éigin mícheart le suitéail do bunachar sonraí. Déan cinnte go bhfuil " -"boird an bunachar sonraI cruthaithe cheana, agus déan cinnte go bhfuil do " -"úsaideoir in ann an bunacchar sonraí a léamh." +"Tá rud éigin cearr le suiteáil do bhunachar sonraí. Cinntigh go bhfuil na " +"táblaí bunachar sonraí cuí cruthaithe, agus cinntigh go bhfuil an bunachar " +"sonraí inléite ag an úsáideoir cuí." #, python-format msgid "" "You are authenticated as %(username)s, but are not authorized to access this " "page. Would you like to login to a different account?" msgstr "" +"Tá tú fíordheimhnithe mar %(username)s, ach níl cead agat an leathanach seo " +"a rochtain. Ar mhaith leat logáil isteach i gcuntas eile?" msgid "Forgotten your password or username?" msgstr "Dearmad déanta ar do focal faire nó ainm úsaideora" +msgid "Toggle navigation" +msgstr "Scoránaigh an nascleanúint" + +msgid "Sidebar" +msgstr "Barra Taoibh" + +msgid "Start typing to filter…" +msgstr "Tosaigh ag clóscríobh chun an scagaire…" + +msgid "Filter navigation items" +msgstr "Scag míreanna nascleanúna" + msgid "Date/time" msgstr "Dáta/am" @@ -531,12 +600,20 @@ msgstr "Úsaideoir" msgid "Action" msgstr "Aicsean" +msgid "entry" +msgid_plural "entries" +msgstr[0] "iontráil" +msgstr[1] "iontrálacha" +msgstr[2] "iontrálacha" +msgstr[3] "iontrálacha" +msgstr[4] "iontrálacha" + msgid "" -"This object doesn't have a change history. It probably wasn't added via this " +"This object doesn’t have a change history. It probably wasn’t added via this " "admin site." msgstr "" -"Níl stáir aitraithe ag an oibiacht seo agús is dócha ná cuir le tríd an an " -"suíomh riarachán." +"Níl stair athruithe ag an réad seo. Is dócha nár cuireadh leis tríd an " +"suíomh riaracháin seo." msgid "Show all" msgstr "Taispéan gach rud" @@ -545,7 +622,7 @@ msgid "Save" msgstr "Sábháil" msgid "Popup closing…" -msgstr "" +msgstr "Preabfhuinneog ag dúnadh…" msgid "Search" msgstr "Cuardach" @@ -590,8 +667,14 @@ msgstr "Cuir le %(model)s" msgid "Delete selected %(model)s" msgstr "Scrios roghnaithe %(model)s" -msgid "Thanks for spending some quality time with the Web site today." -msgstr "Go raibh maith agat le hadhaigh do cuairt ar an suíomh idirlínn inniú." +#, python-format +msgid "View selected %(model)s" +msgstr "Féach ar %(model)s roghnaithe" + +msgid "Thanks for spending some quality time with the web site today." +msgstr "" +"Go raibh maith agat as roinnt ama ardchaighdeáin a chaitheamh leis an suíomh " +"Gréasáin inniu." msgid "Log in again" msgstr "Logáil isteacj arís" @@ -603,12 +686,12 @@ msgid "Your password was changed." msgstr "Bhí do focal faire aithraithe." msgid "" -"Please enter your old password, for security's sake, and then enter your new " +"Please enter your old password, for security’s sake, and then enter your new " "password twice so we can verify you typed it in correctly." msgstr "" -"Le do thoil, iontráil do sean-focal faire, ar son slándáil, agus ansin " -"iontráil do focal faire dhá uaire cé go mbeimid in ann a seiceal go bhfuil " -"sé scríobhte isteach i gceart." +"Cuir isteach do sheanphasfhocal, ar mhaithe le slándáil, agus ansin cuir " +"isteach do phasfhocal nua faoi dhó ionas gur féidir linn a fhíorú gur " +"chlóscríobh tú i gceart é." msgid "Change my password" msgstr "Athraigh mo focal faire" @@ -643,28 +726,35 @@ msgstr "" "úsaidte cheana. Le do thoil, iarr ar athsocraigh focal faire nua." msgid "" -"We've emailed you instructions for setting your password, if an account " +"We’ve emailed you instructions for setting your password, if an account " "exists with the email you entered. You should receive them shortly." msgstr "" +"Chuireamar ríomhphost chugat treoracha maidir le do phasfhocal a shocrú, má " +"tá cuntas ann leis an ríomhphost a chuir tú isteach. Ba cheart duit iad a " +"fháil go luath." msgid "" -"If you don't receive an email, please make sure you've entered the address " +"If you don’t receive an email, please make sure you’ve entered the address " "you registered with, and check your spam folder." msgstr "" +"Mura bhfaigheann tú ríomhphost, cinntigh le do thoil gur chuir tú isteach an " +"seoladh ar chláraigh tú leis, agus seiceáil d’fhillteán turscair." #, python-format msgid "" "You're receiving this email because you requested a password reset for your " "user account at %(site_name)s." msgstr "" +"Tá an ríomhphost seo á fháil agat toisc gur iarr tú athshocrú pasfhocail do " +"do chuntas úsáideora ag %(site_name)s." msgid "Please go to the following page and choose a new password:" msgstr "" "Le do thoil té go dtí an leathanach a leanúint agus roghmaigh focal faire " "nua:" -msgid "Your username, in case you've forgotten:" -msgstr "Do ainm úsaideoir, má tá dearmad déanta agat." +msgid "Your username, in case you’ve forgotten:" +msgstr "D’ainm úsáideora, ar eagla go bhfuil dearmad déanta agat ar:" msgid "Thanks for using our site!" msgstr "Go raibh maith agat le hadhaigh do cuairt!" @@ -674,9 +764,11 @@ msgid "The %(site_name)s team" msgstr "Foireann an %(site_name)s" msgid "" -"Forgotten your password? Enter your email address below, and we'll email " +"Forgotten your password? Enter your email address below, and we’ll email " "instructions for setting a new one." msgstr "" +"Dearmad déanta agat ar do phasfhocal? Cuir isteach do sheoladh ríomhphoist " +"thíos, agus seolfaimid treoracha ríomhphoist chun ceann nua a shocrú." msgid "Email address:" msgstr "Seoladh ríomhphoist:" @@ -684,6 +776,9 @@ msgstr "Seoladh ríomhphoist:" msgid "Reset my password" msgstr "Athsocraigh mo focal faire" +msgid "Select all objects on this page for an action" +msgstr "Roghnaigh gach oibiacht ar an leathanach seo le haghaidh gnímh" + msgid "All dates" msgstr "Gach dáta" @@ -697,7 +792,7 @@ msgstr "Roghnaigh %s a athrú" #, python-format msgid "Select %s to view" -msgstr "" +msgstr "Roghnaigh %s le féachaint" msgid "Date:" msgstr "Dáta:" diff --git a/django/contrib/admin/locale/ga/LC_MESSAGES/djangojs.mo b/django/contrib/admin/locale/ga/LC_MESSAGES/djangojs.mo index ee000e278fc13e2dc8161c599d4e23b713519804..e46bd504c65ca3799cc65b82e4cb14a949977e0c 100644 GIT binary patch literal 6910 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 diff --git a/django/contrib/admin/locale/ga/LC_MESSAGES/djangojs.po b/django/contrib/admin/locale/ga/LC_MESSAGES/djangojs.po index ce0a412d10..6f6e50dcc2 100644 --- a/django/contrib/admin/locale/ga/LC_MESSAGES/djangojs.po +++ b/django/contrib/admin/locale/ga/LC_MESSAGES/djangojs.po @@ -1,6 +1,7 @@ # This file is distributed under the same license as the Django package. # # Translators: +# Aindriú Mac Giolla Eoin, 2024 # Jannis Leidel , 2011 # Luke Blaney , 2019 # Michael Thornhill , 2011-2012,2015 @@ -8,10 +9,10 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-05-17 11:50+0200\n" -"PO-Revision-Date: 2019-06-22 21:36+0000\n" -"Last-Translator: Luke Blaney \n" -"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 07:59+0000\n" +"Last-Translator: Aindriú Mac Giolla Eoin, 2024\n" +"Language-Team: Irish (http://app.transifex.com/django/django/language/ga/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -66,6 +67,11 @@ msgstr "" "roghnaionn tú cuid acu sa bhosca thíos agus ansin cliceáil ar an saighead " "\"Bain\" idir an dá boscaí." +#, javascript-format +msgid "Type into this box to filter down the list of selected %s." +msgstr "" +"Clóscríobh isteach sa bhosca seo chun liosta na %s roghnaithe a scagadh." + msgid "Remove all" msgstr "Scrois gach ceann" @@ -73,6 +79,15 @@ msgstr "Scrois gach ceann" msgid "Click to remove all chosen %s at once." msgstr "Cliceáil anseo chun %s go léir roghnaithe a scroiseadh." +#, javascript-format +msgid "%s selected option not visible" +msgid_plural "%s selected options not visible" +msgstr[0] "Níl an rogha roghnaithe %s le feiceáil" +msgstr[1] "Níl %s roghanna roghnaithe le feiceáil" +msgstr[2] "Níl %s roghanna roghnaithe le feiceáil" +msgstr[3] "Níl %s roghanna roghnaithe le feiceáil" +msgstr[4] "Níl %s roghanna roghnaithe le feiceáil" + msgid "%(sel)s of %(cnt)s selected" msgid_plural "%(sel)s of %(cnt)s selected" msgstr[0] "%(sel)s de %(cnt)s roghnaithe" @@ -89,20 +104,21 @@ msgstr "" "gníomh, caillfidh tú do chuid aithrithe." msgid "" -"You have selected an action, but you haven't saved your changes to " -"individual fields yet. Please click OK to save. You'll need to re-run the " +"You have selected an action, but you haven’t saved your changes to " +"individual fields yet. Please click OK to save. You’ll need to re-run the " "action." msgstr "" -"Tá gníomh roghnaithe agat, ach níl do aithrithe sabhailte ar cuid de na " -"réímse. Clic OK chun iad a sábháil. Caithfidh tú an gníomh a rith arís." +"Tá gníomh roghnaithe agat, ach níor shábháil tú d'athruithe ar réimsí aonair " +"fós. Cliceáil OK le do thoil a shábháil. Beidh ort an t-aicsean a rith arís." msgid "" -"You have selected an action, and you haven't made any changes on individual " -"fields. You're probably looking for the Go button rather than the Save " +"You have selected an action, and you haven’t made any changes on individual " +"fields. You’re probably looking for the Go button rather than the Save " "button." msgstr "" -"Tá gníomh roghnaithe agat, ach níl do aithrithe sabhailte ar cuid de na " -"réímse. Is dócha go bhfuil tú ag iarraidh an cnaipe Té ná an cnaipe Sábháil." +"Tá gníomh roghnaithe agat, agus níl aon athruithe déanta agat ar réimsí " +"aonair. Is dócha go bhfuil an cnaipe Téigh á lorg agat seachas an cnaipe " +"Sábháil." msgid "Now" msgstr "Anois" @@ -199,6 +215,103 @@ msgstr "Samhain" msgid "December" msgstr "Nollaig" +msgctxt "abbrev. month January" +msgid "Jan" +msgstr "Ean" + +msgctxt "abbrev. month February" +msgid "Feb" +msgstr "Feabh" + +msgctxt "abbrev. month March" +msgid "Mar" +msgstr "Már" + +msgctxt "abbrev. month April" +msgid "Apr" +msgstr "Aib" + +msgctxt "abbrev. month May" +msgid "May" +msgstr "Beal" + +msgctxt "abbrev. month June" +msgid "Jun" +msgstr "Meith" + +msgctxt "abbrev. month July" +msgid "Jul" +msgstr "Lúil" + +msgctxt "abbrev. month August" +msgid "Aug" +msgstr "Lún" + +msgctxt "abbrev. month September" +msgid "Sep" +msgstr "Meán Fóm" + +msgctxt "abbrev. month October" +msgid "Oct" +msgstr "Deireadh Fóm" + +msgctxt "abbrev. month November" +msgid "Nov" +msgstr "Sam" + +msgctxt "abbrev. month December" +msgid "Dec" +msgstr "Noll" + +msgid "Sunday" +msgstr "Domhnach" + +msgid "Monday" +msgstr "Dé Luain" + +msgid "Tuesday" +msgstr "Dé Máirt" + +msgid "Wednesday" +msgstr "Dé Céadaoin" + +msgid "Thursday" +msgstr "Déardaoin" + +msgid "Friday" +msgstr "Dé hAoine" + +msgid "Saturday" +msgstr "Dé Sathairn" + +msgctxt "abbrev. day Sunday" +msgid "Sun" +msgstr "Dom" + +msgctxt "abbrev. day Monday" +msgid "Mon" +msgstr "Lua" + +msgctxt "abbrev. day Tuesday" +msgid "Tue" +msgstr "Mái" + +msgctxt "abbrev. day Wednesday" +msgid "Wed" +msgstr "Céa" + +msgctxt "abbrev. day Thursday" +msgid "Thur" +msgstr "Déa" + +msgctxt "abbrev. day Friday" +msgid "Fri" +msgstr "Aoi" + +msgctxt "abbrev. day Saturday" +msgid "Sat" +msgstr "Sat" + msgctxt "one letter Sunday" msgid "S" msgstr "D" @@ -226,9 +339,3 @@ msgstr "A" msgctxt "one letter Saturday" msgid "S" msgstr "S" - -msgid "Show" -msgstr "Taispeán" - -msgid "Hide" -msgstr "Folaigh" diff --git a/django/contrib/admin/locale/hsb/LC_MESSAGES/django.mo b/django/contrib/admin/locale/hsb/LC_MESSAGES/django.mo index e0e9215544122ec48c0cb166726a8c410ac31488..8d8267184e04715f4f69eceb08a77a1137f44344 100644 GIT binary patch delta 4770 zcma*pdvH|M0mtzZ@&FP72@sM%2p2*~AOQ>s0VO~n3ZW8F%BwUyHeq9yM;5Z12C#JH zC2B*JMj{WXBBr%M5m_viN`RUu#YbD)4r8hOp$v6whoa~(1v>5bxA%mxun58n-c7bWf*Nt$lOao&zfZ~s6^dRjq1=kYYV1Q52G4- z+xk9sqy7Q*#E+1M&1cvhzqG&q3pY^j*2kDF_y{KQe3Q_Za3UQw!fcH66xBc(a<8ed zF2!Ed1DKARQ6t)idDw~!+WZc4@ncj6doU`UPeI+Eg9SX_jH3{XK6`;5a-F`Ie}tZL#-B*p8`W2|(AIjja zArv-oLQ~#~8qpC{2ilN*V$Pr%_#h(j$^3hMen_IwWN!Ns;d z4e6tq8=|0*t-(^~LDdknYWUD$Jw``{Uhi4WD$)u^S}f|}wMR0j_u z`_P1u**9lV0}XvdK^?e?YUmbf1ksM$U?Qr)!8ig7aU?EA?TIGTNRFbW`aRSPU9j~l zs3p9KdQQw>cV?214u?z{1@$Z+U%@G;hOeP|n$G$R$3oPUF2YIZMYf4~0gLbyvX9Ld z*nkOH#*D&^sF^&1cVHAdb2g5_3hkP$6g0)Z$GNzOr)w{Su@c)*GcsV9ySuZkd8nBw zKrKZX@@zBP+JHRM>_Tq;jLBqJ5`fqU}PGCAUbL%jqHGPVL*5;J;ZB)bOQ6sy6>e#2K zO>-S}eJnS3$7JgO)cI`G2n+C76uTa^#DC3mm&oM1dnPrX`9IAMg`8M`Um*L>RItNJ zaTQkKVbq5wnFWo*9PEmtP@Ah5wG@+49e4owW|>9k;CE1a>SpQOv&zpV$+h zV^8Y0FcuR=yL%xSbv^@wn1_w{9BO9L*jd{3*{HW+JgQ@JP#s!?+MGVrOgxOeaA$~u z)}j^Fk<(a!=TPtSEoAT}iIed-2{jWlP!C*!kbPo`Q4KCZO`Q)Ne8QeTg4%2+a3xMGH0Bw6376pXB4ZxMpPPQXh`YotE@g(Xk+J`B)-=05i>+RTw=bJxK(3)I9t<{&PhT`vXAJ7lesb``dJRbXD zIqCzm1bgFV+=VUH(G!fRrG6IoU_pud{=b6`^>{u8p(F}<6!gFn%)oNgF7{$7ZnVGe zw&z=M2&tSohBXdCh(nS-bf{u#BzAD4#QKQ1Lx z+#c1SrgArK#Y4!az>Jyd{>Q?Ds=sFIpWs~TrDeu6V+&T{h`ZfQy&Y?)??pYh%RTO< z?2g(yy+RZ;b*Y$!BQXc3;c%?OJluua#qFpWc-PiHv|dIn;oni4^(OYm#A)vJxu_W% zkGzp)D(=HjBL(f!lEVrWLdCJg&ok;(gdy?(X_GQ6H#FsDbpJ;qLxi zjG{gk)uC~y*L(&#I3M{?h0IzCn(`*pYx68>CJv!S+<|I{O&z%rB8S%RSEP+R89Bpu z9-k%J13J{Pjby$m9F;^Hk9}$n)_*s}S32vMLw1oCqBYggO5!3VMu0Dq0NG25$w8uH zC}}5ih-RY;nME{m9oxxM%qZ&E1oXZE{PzE55vV~LJ1*-RQ#;aK4k z`L~vT-}p-XIm+5YeaM?+Ckc{gh&JuF$oI$=a)cZwC&_4yUtg-uV=jfRq=a-%%`YkY z$qurJ{G8lF29nO>$DIW{O716bkzAs;MaOEF+yB;68qoO=eXX?Xe?j(<4Dvh~L>?eI zCX=6$bX7QBbulmE8e0~3*mA$Goa-!BQCLq>$v6^u{z?j~NIrRi93ndMNCHVBGl`DA zw>;& zPxJA#*+c&KB|)FRE*zIWuWN!gc)OwSLT5;H^UR?s&AqZRFta&z==E8iYF+F!`c|%V zN&>-pf8B$Vyme~6WVEf`ZsBWPiQHP_uXlpAzJSvZ@YaXBW@p4k6@`b6@W&T42G!#l z-wIE)Z+U}L=W*71R&;FgEbBPob!xoRhYg8o{+ d)7a3_=4URqWb`)`YeNp=7L delta 4348 zcmXxmc~Di?0mt$4d?1Umh=`yp&w!vlmlDOOAR^dG3@*VeM5PIdl_(LxprX{=x%DN(^>ys`IXy`chYUwINhd`EjfwIZvuv==8q=I;%rM-DDfkkO#5ZsWUdLR_7~-9u zgLA1rg$3A&y1oawwfPrD;XU*l;~0OEF={Ic^@C*81tU=%%C|1S;neF;zuRWrjnUNi zV>}*3ZfxGf7(8RYzkr*mU&HNKJk*#t+BY{S4C2HeQ6u~U!#zda;2v^~iA?rP#RTd> zOv6Idh#titRwIKmtvCjcp*q-Y&wqlt{!7fKee)fKNF2qmbzvUH;&jxA=Ab&V81=hq zR0p3y&B!WLN48=fwxc@KjhXnd{r($NMC=D(hTe}pjua4o8b>rhMb z0%|0?u>ucZ1b&H{xn9%_m$M_)&}GzKx`DdxQ`A)d*?#{u-bejA)C?!3a~F*ygPo=h z1d-)76HzxPMXmijWTTsER0rx&BYz&XG+R->Z?oqQq8je7^$^mgxsDoG50>CgCmh`Wdg`-n*!887os{) zjk=Gsl7dFifV$x()D8FII6Q$9@FN_J-=jv774W9I5H&;PsHIzqYG65PMjBA}ZANvd z4d2C+$o(9%c$C+}jX0JsT-1eEuoyo?mf1wGa8ob~*{9|aT!(cy5x+vsU}Cm04`B`d z0MB40_TYTXXXj~#9gNj3ilH0JIFXE+iAIdX7V8$&jO;`$!4ae_(`o$(xwpB4>UdJF zxAr4Ydu5z;66*UYs7+dg!)f0v12^*UqayqC!WTL3EqpQ76($_j8V89qp=OO z6o+sSo8|XpXBZK7Szc0qB?dO)u9k-b9SL-;xkOZZ%|8d57nU*c4j^X9140oDv?f`6{wCJ zM7?rfLp@&SaT@*(bpsz)>$*Xx4rHMk9D}-kCTa%D?e_~&GgXD^NF%ZxjMGLzH$0D; zx-JahU+wvU_j{Wy5uf9{i|uG88}lR_$KBY6y3ejDUdIohW~dY6up5WqEmVhlkpVg8 zTMBG&lgn0C&*vjAKU0Nka6K|>=5MHmQl@%Kb`o`?Q<#A7pgM33^*I0Dp3i%L4NCn1 ztimqTQl--R5Iz4n6x8rk)Qx7NHr>Ohjy!?7U;}CoY(qUY`*0W@wC7LT`UTX|e1ckn zuP_Af{j;>V;B?TKn~Q7+bCP%`oO!>X+~+<`jC*dlv?% z_hBMt7I_U$!gT6|s3obw;n;+ZdemmWIE;F;okMlxbJPg$phgnGTSYT92>E+sQc%Ay zKrK-fvOUZ$)aJT``du$-fPUWRy5CTY$FarCzrL8p39Vf@s%Mp$hO6)*ZpU$0Jj)9QFR_L9J;oYJ~s5R2(qJ`d zU>+kn_IQLpf5Yb`J^yVK-nC!6W!2Q^$n!8iwu*V=b)w}-BRbd~;Xh!xc!V4vI#!T< zgh>t`FY@^U+3i(LD(#2=D`~MO#9oqR>klI@$nfqzjY~)?sUtcf$xq2@l0md|I<^wM z8+7PVt|9T{Rifk9gs0j#1NdkrdPDUe>9(-gT5VQOOSKy>&$!k_JYK1!aj=g#0M@{q0fv#h^>O}5;P zkC3&tz7Df(d6TsZ)xLR|%vFKo0*NI*BR9xOvWRRa?~^ykGh{j$OeT`&h>j~BCIWv& zj@$YO>jvv8Yn1lpL0d_(F2yH9R}#yk-C$Zps6B0QROo+!fZuJ;9_sdF$GBH>Qr%rS z6Wq76)7=v}nQmRqe?lLO9v11F9J)DfO|08cuq5=~f})tv+*z;q-5sUL?#8kV_x{q+ Pp`Ox(zR, 2016-2023 +# Michael Wolf , 2016-2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-09-18 11:41-0300\n" -"PO-Revision-Date: 2023-12-04 07:05+0000\n" -"Last-Translator: Michael Wolf , 2016-2023\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 07:05+0000\n" +"Last-Translator: Michael Wolf , 2016-2024\n" "Language-Team: Upper Sorbian (http://app.transifex.com/django/django/" "language/hsb/)\n" "MIME-Version: 1.0\n" @@ -199,10 +199,6 @@ msgid "" "The {name} “{obj}” was changed successfully. You may edit it again below." msgstr "{name} „{obj}“ je so wuspěšnje změnił. Móžeće jón deleka wobdźěłować." -#, python-brace-format -msgid "The {name} “{obj}” was added successfully. You may edit it again below." -msgstr "{name} „{obj}“ je so wuspěšnje přidał. Móžeće jón deleka wobdźěłować." - #, python-brace-format msgid "" "The {name} “{obj}” was changed successfully. You may add another {name} " @@ -372,6 +368,9 @@ msgstr "Zapodajće wužiwarske mjeno a hesło." msgid "Change password" msgstr "Hesło změnić" +msgid "Set password" +msgstr "Hesło postajić" + msgid "Please correct the error below." msgid_plural "Please correct the errors below." msgstr[0] "Prošu porjedźće slědowacy zmylk." @@ -383,6 +382,19 @@ msgstr[3] "Prošu porjedźće slědowace zmylki." msgid "Enter a new password for the user %(username)s." msgstr "Zapodajće nowe hesło za %(username)s." +msgid "" +"This action will enable password-based authentication for " +"this user." +msgstr "" +"Tuta akcija awtentifikacija na zakładźe hesła za tutoho wužiwarja " +"zmóžni ." + +msgid "Disable password-based authentication" +msgstr "Awtentifikaciju na zakładźe hesła znjemóžnić" + +msgid "Enable password-based authentication" +msgstr "Awtentifikaciju na zakładźe hesła zmóžnić" + msgid "Skip to main content" msgstr "Dale k hłownemu wobsahej" diff --git a/django/contrib/admin/locale/id/LC_MESSAGES/django.mo b/django/contrib/admin/locale/id/LC_MESSAGES/django.mo index 8dbc5b5eb63cb5ba0355a129da8296c1e7437d64..dbba65c99a9255d3a9653e153a1049f6e0724a6b 100644 GIT binary patch delta 4772 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 diff --git a/django/contrib/admin/locale/id/LC_MESSAGES/django.po b/django/contrib/admin/locale/id/LC_MESSAGES/django.po index a49fd66792..791412ed6a 100644 --- a/django/contrib/admin/locale/id/LC_MESSAGES/django.po +++ b/django/contrib/admin/locale/id/LC_MESSAGES/django.po @@ -3,7 +3,7 @@ # Translators: # Bayu Satiyo , 2024 # Claude Paroz , 2014 -# Fery Setiawan , 2015-2019,2021-2023 +# Fery Setiawan , 2015-2019,2021-2024 # Jannis Leidel , 2011 # M Asep Indrayana , 2015 # oon arfiandwi (OonID) , 2016,2020 @@ -16,8 +16,8 @@ msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-05-22 11:46-0300\n" -"PO-Revision-Date: 2013-04-25 07:05+0000\n" -"Last-Translator: Bayu Satiyo , 2024\n" +"PO-Revision-Date: 2024-10-07 07:05+0000\n" +"Last-Translator: Fery Setiawan , 2015-2019,2021-2024\n" "Language-Team: Indonesian (http://app.transifex.com/django/django/language/" "id/)\n" "MIME-Version: 1.0\n" @@ -372,7 +372,7 @@ msgid "Change password" msgstr "Ganti sandi" msgid "Set password" -msgstr "" +msgstr "Setel sandi" msgid "Please correct the error below." msgid_plural "Please correct the errors below." @@ -386,12 +386,14 @@ msgid "" "This action will enable password-based authentication for " "this user." msgstr "" +"Tindakan ini akan enable autentifikasi brerdasarkan-sandi " +"untuk pengguna ini." msgid "Disable password-based authentication" -msgstr "" +msgstr "Tiadakan autentifikasu berdasarkan-sandi" msgid "Enable password-based authentication" -msgstr "" +msgstr "Adakan autentifikasu berdasarkan-sandi" msgid "Skip to main content" msgstr "Lewati ke isi utama" diff --git a/django/contrib/admin/locale/ko/LC_MESSAGES/django.mo b/django/contrib/admin/locale/ko/LC_MESSAGES/django.mo index f8c12f3c524eab4d12581b1a92bf6a50787e6332..2d1eb80a3d25a5bb951aefa79b15ee1c82440618 100644 GIT binary patch delta 4254 zcmXxm32;@_9mnziBZQcjJrDwcz+(vsgs{ZM3W*^CLP`-4Oc5lO2tt4w3?XF^e6kn_ zf?&cTvX@1oHGWMU>%qim{MBHQV^!h6d7y3zjsgW@XzO*`|dr<|D1Dm zcb)J1I$!W&a_f!8)l76I3fh=O`OGHA>aN*>M6(oJi0yG5cEbHQ37fDNrYCv#hvP`< zQ!oz?px(cTG;ROED7=pmW_1tpjYJ7nD8yJso zAq`stM&o<#_rth^`Y~LAg>B8^=--Z0h~dVcP&2%M;gO;mxR1PJk?lM?U;_1Q?1=fO z8I@o*mLik0TFk<&r~x*+`+r2ee+dWDzulq`iQSmCUd%*44noanIBFo{QO}j41~?U! zky)sLEW=FPh8j>acELZm->;(v63HwVU_1sZDXgT>i1%BTHNZQlf%zCk5k{dpE=CP>25O)cI00+0CtmDG{wpX%q?xtCxu_9Vqn6}l)J#_6 zXspB5cnOucE2sviu_M*dQPf^Kj(YDjD%I!Q@BhN?)Ni3OoZOjKG?R38ng)=KEVuPT zH82#l_M?!EZl$OJRG?;Fg<6_rsOQ(X`x{Ul?{W1I(x)|{CUy~v@LG_SvxCqtY>(~c(VGe$d8F&vhldb_T)%mCl6}$Q~s3j~%bySJU%o0@luc8LF1rKQz z8!4#aDc!u0)?jbyyHGEl#6moSEVm`GfIq;#$bPjlti}b{4{xF}ncl-}09N2Q+=-9l z9jwJ7cA#Io=p=>7-1sv_V=kl7ZZ2>RMP;NIwFHxpK5V9Q4brB)j~eh<)Y|_ATjO=- zH}3bls7?AErqaLpdwCsqN2RVW4#GTKi*qmnze6?b%Vfi066WCsWEO)+8Bq{@AFdCo5L@Y

i1+=hClvtJJR*Nr@GsKEl~2wX{htn(bIqbck#S&3xXmZ9E% z2lf6T)G_=NwcF1+zea7|`=|-E@6Tr)y96m{Gfl-JtU*0+0(DHjz&N~uKgK(#4hu>-;xS(2M6W760k# z|3i+b#c&qY(LmJiLr`ly0W-18{a%a8+-B^6AEO3(26YO~V>`Ty>d#O9Gj#q_DYV5$ zusuGBeEzK*W3UEUcB{jM*o2i>kk7`$M&zGOEb!Xdh#GJMs-wfM-i&Jh4DzkBs~FS> zrYWeA=VM2F3e`{r>bb?JnJ-5Tcr6BSHx^+N4#Nn(*PLVBx9vEBXWoQ7hiEIpNfSZwhYCD{#k$=|eQE&4N z!KsT2A`ukI`8V&unqP9y8GWd6My90 z?}mCl%Q*-&fKjM5FT-f8Mjz^;UOzH6F1UvB6U0$sG%;#GWIRxGh9D(>R@YgBU^RdX><&c}*2A9kR!XmsHU=NY^?-TS3>8gg%OWhbLt6htRXHq)$ delta 4156 zcmYk;2~bs40LJkHJW&<{cLgI96jYSZa7*l|p@q1wm`hQC`+}gU)hne?!BSpHD(<*% z;Y%|UEQ@KXX_~R7GNxuKQ70WWbJ`pGfA=0|I>YyV=iK-1x#ym9?$tZxK|9NXeBU?s zylyDxNPChJYE0uGV+KU(s4(aX2uMo?ZtFljXJ*; z>DqjWjjjPaSDsOVak?GJ9FPWT%&pk~codte*d!%-bQX`PKtXfMKha5>VkS%YD? z&VFBk&(Yq2#TeJZn5JCc?4}aIfojwp)}S*|R0s9QIi|t-2S(A3XlYD4j78m1I(EYh zWb9@ZCgTd!0ITfrBdGJwVj9;spHpdsLEN@ZY>eU94s}O~sDboC{VoGFz#*s^$wCbz z7nAT=)PSlm4iDS!KSd3s0iVI^=vzc3pW8l)7cdW3)9Y@$fjYt8)?JcH)BulTQ~VG$ z!1Jhq{eWJ)jJj|#qtZZ!p$0krs2C0-ZZYP4Qv-{Tb{?`vcU>UP9f#FR}Ed3*X@Y%W8tzaq6HoYR%)2 zjcw9U0~n0D<6)>JnTY!R$I*+mScrFgR7O)Nyq6t|b=V(A zF@L)7TGR!%pzib_YM|AqrKm$q?boOQ-axjKxs6P!3A@j|(*)E2(op?mpl-nTFcoz; z64hZYcEv*Mj@z*leulb}Ur|#X74ObadsI6WwO0n9W+W5U?+Da@p1^8cg6c21gEK&% z8A+uJ2WFy9EXRSk8Chm?0UyBIsK>Jl3t5C-?13jyGuVLlWA6m^5$59vJdK*!CW-Fa zm*Z60TQN+#=`SkUy&i@o!%;I4jhgz7NZ%&SIv(lMEJY1?3u?`GqXz@lQ}+8B)C|?3 zmg+oe>VL*2T;JTL(hvW|b=aq~`v$8+b^I}|#0!{?QDTh>2O{h98}zbfHu^%87ptwdcYksT(}ky$oFQ60`lomYff zQy*%#S6C0BHt$)~4SkCbbG|E7^uyRRx8n@-)6T?Icmcn_Y5aNt zru8zW5_h65G>~Ug1IR?p#5mOPIoJ#f?Dxg^2<>v@&(!n5?|dejEv*yV;47GleXte} z;BTl7cd$`(p?w&MCvXj(L+$EpPAb9CSdQPImS|32cTW_d&MU(2(RHmoc^FO{F$%;ZbzA@0p*}BlyBRGs0*w_-fdwrla++k58AQWVnNN-qo=>xjbRmbyPQtXAmx+eFkW3MKgl7h$!wz1h^!!UiMD=sqVgiq z!mDV$A1C*aN}_U#@En_9vXtn}bNBkrL#g&yeNd*lIL}lq^^HW^)OqjXM56LG(Q}eW z_7UxryX6R#4y1(WJ^L)_NmNdfCy8_a=~ViXcru2}Bkz&BWxcIv_XNmZ+dhsfNhjNG zf_cPCwvydM&u9vHlk_5b_+KO238lI7Pt`VRp(KtxhuCNl`|ySsk#4`tfrnp zHj#JzBcf7UZKgJ!OeQLa$R7WOs20A*oVNS1*w)YCII_sL3o*ggmsxA9uOknoQ%>+1 zPBdTdlbJ+i6?uzPkzCS`M3Np_$~jd2UpzDpkS+G0ULz_?$V+6F8kEMw@6_D?xvM&b zOb--AM}!B;VlFibJRjdbEF!CD*@B|^`SIDa<^?|L(zR(IxX-qb;5}yod-|t(0zVGi G8vY+sNvw7N diff --git a/django/contrib/admin/locale/ko/LC_MESSAGES/django.po b/django/contrib/admin/locale/ko/LC_MESSAGES/django.po index d91718ce63..717f2d5995 100644 --- a/django/contrib/admin/locale/ko/LC_MESSAGES/django.po +++ b/django/contrib/admin/locale/ko/LC_MESSAGES/django.po @@ -22,13 +22,14 @@ # 정훈 이, 2021 # 박태진, 2021 # Yang Chan Woo , 2019 +# Youngkwang Yang, 2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-05-22 11:46-0300\n" -"PO-Revision-Date: 2024-08-07 07:05+0000\n" -"Last-Translator: Juyoung Lim, 2024\n" +"PO-Revision-Date: 2024-10-07 07:05+0000\n" +"Last-Translator: Youngkwang Yang, 2024\n" "Language-Team: Korean (http://app.transifex.com/django/django/language/ko/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -392,7 +393,7 @@ msgstr "비밀번호 설정" msgid "Please correct the error below." msgid_plural "Please correct the errors below." -msgstr[0] "아래 오류를 수정하기 바랍니다. " +msgstr[0] "아래 오류들을 수정하기 바랍니다. " #, python-format msgid "Enter a new password for the user %(username)s." @@ -438,10 +439,10 @@ msgid "Filter" msgstr "필터" msgid "Hide counts" -msgstr "" +msgstr "개수 숨기기" msgid "Show counts" -msgstr "" +msgstr "개수 표시" msgid "Clear all filters" msgstr "모든 필터 삭제" diff --git a/django/contrib/admin/locale/sk/LC_MESSAGES/django.mo b/django/contrib/admin/locale/sk/LC_MESSAGES/django.mo index 597165e2cff9135b1b0f41f4cb7c5a9f682302be..dc548e5b07bf219f42a9fa107e50b913273e4917 100644 GIT binary patch delta 4760 zcmajh3vg7`0mktYlkf_V@CYQ~wLq2t36BtB6c7{A016n40VD;<5*D%$c0+a(NRe*C zBR(3f5J(kEtraR2L1a-|E5R73P_@-!Wh_M;w6x>2OdP6o#2Nel_MR}zIAibl`8((C zz2~0Sy zj6yH!d=t*X{g{g#sQX9tHHN0mH0+9n7;8+}%%PxX726Azpl+x@b*SFjf&-~XPz}9h z{WEr>{vr0pi%7%fbL@^^*x$dwP1L*fGiEC`VlSR=68aNPq@qUX#%NDb4HP2xnt9f8 zOr##fRNR6Z(H_jieaN8AdpH_DL3OYvqtf|g)cqNl&GStjg?RMY3j)}KdIM@iO{k7M ziMnnds)GkmGjasgkw0Jtev0Z)PewBo`=fr(L3LyvZoq{YUPs|i6b@klt*yikdFEsHI9qT|dm8&pDQ-b^@DQ>O zO$3>Ja|$)k@I?yhKnJR!uTdk2bvX_8LNz!X$6^kS!~0Nsq6syUBdDqVBWi}u+4^PF z5?(_+CvLbiGf7B?!zP7-dX|MRVgah*E2y5PvOZ%l2Q{TjaXNaDZDRJ~WIT@SWAh)Z z#e|W@jK>DlOdiIG7{ksi!AUqzyJi~&P4O9AfJ=G0_Cf@gU@K}y290udx7(VDnwf0W zQWPT3HYL_tM^V}-AO@fbKLqCs^PP!k)1@(D+ zxr(|zo}0U4AL}60c{gf=+4w>XyB_(3m`j;XN54VsnZzvSKSCih%b3M@0rkVJ?66t5 z0Jq^D)Y^_@LE~`>cENn?inCC!V=?x?a?}XdAlt|^BKz9xx93lxI{wLc=3j+>b3#48 zifS-+f@1<|YWtyHuaUSN^Y8&Yjhd0W*;&1D8S>^DKdPN3REKtA5w_9_IF$k)G2=#kqh}zKU_7Wbe+;#Y_t@XtPz`;I+Ps%he@y&2#=L|7KtI03J9!Ax z*@~mCyzs4FIlxGa9 zVID~0i z`2p(nyntGoYp9O7_#UeRxu~_Bjhd-Nn2gIY1vlU%+>Y!=b7DI4ug&!(Cp3j=w>xW; zhw4BPs)LJBQ|3eMjg6?aY_j#;sQVA#+jt83*qL4V&Oc6DaUAu(qrMyc3XHi2(+a}Q z>*ePJ%V(ZIjpPjSlevWI>Bbtidur0na&jVK+QlZs^JXO5@w^?yA3rX zC8(JTpzd!#UKsN*K7!#k3hGJmENA4U7@)oib>UeYgS}@vuh}igV9Wv3=IcPsT*4hr z$BIyEUy3of47G$Fdww0JQ@qhyg-8FNupUg zKy+wiCrByL&cBHi6AeU%rhF$kt_sH?Z89AzNfY7Q6a7a7MAxf3K1wv@Ueb9~*g_fJ zNeYPDo*RX2{F?o*g_aS;j`2QAC>r~Ae ztEeRHH`ISYS+8wB@_Vw2gvifGJy}eCNVby0h6uOdWq;qP1M_F&g zcA{^<%cO`5A)UvsItzG&=(GDK8BOjYI;tJ6|G$RPpw5SkrJ_&dZ^#}pnEa9qBX<)W zx08b;RTYkx9L#=PXUk%uEf2WiTxW4Pg&&ZCB#%U&uP@YEl128C=ZTI?l0cHkT%toC zmj}se5=VBEpOSmX3Nn)D@Q}&m*QA8#SVcBOOU^&xH}TiqR-M0Gh1BNQGY?yR)}#0n zTh?8%B+=FzG2513!>P8MAE`~6-Oc3-dX`stUDcjoaDAX=#kl33pm&AKQyZ%E`a`}7 zPxC7&B_qE3l8`Upk90|0*fqf$y53Nv%rzpmd2V`gbK=OsIJ9|S`qg4jg)Vlj_f=K7 zrUgSa0spG$UcZ{3Ho;b}xA3j5L~mUgsBwiVeL+`k&|4Gf>h6e3D_G%K>nih9)_7L< z+YheEa!r~zDQ6u2n;aQF)}4^Pu)f;g{_4qnuId_JWtArwsPp)J3^}kiP!XtgReFO} zp5~(5vh?|ZxV+-LLd^F{&H-jamJFE()MF(LxJn# qt5&P+2SYauF%(!^%N5mu+LNvA2kSf`?}^qxo$tFk7`afG6aPP`B1nV) delta 4385 zcmXxmeNa_p0>|+OF9@h05-JD^#+&jc;JXqc`2r?pqP2#UcZG-$0)!1^^CoJDsRh?| zGc7U8s21A1YgTHRpzUlmY3n$<&4}Af%~g=@Zx_|8VchAF_`SE$4bI*Cs^LEa# zZGS*lSAb_QGVpoBF+k!--f&}r1B_WWN@tB}i7;j?ZpLx=EXLw7d=SrJ3Qip3oL_`X zsjtVG*n_%%5NX={3xn}Cx{UD{SEMm|Rxs*l8Njzbs!yC zZj*&-pb)k8%aDz3%26GtLydeBYH8X~*YC0C_oE(s)Yg5-GtD{Fzy`4ZzxPmRqL4n( zn3dR#9e4xhVJq{f2fvGY;3ue&UO{#ADr!k?pr+Ur?{qL0*;Xb2nQb!@HPCxe9Vkb& zTFUQHOEZ>fmXpz=hBGN>WI3pw6<`>ape`)KP^_{x*z>KZ5w_z;0jw?Z zDKN{^osL$b_DVDQuoKtf;tc2f;SA<~DJM>GVkf#Xowe=2AnM&X9FJiz_M+Z~6R7w1 z0&0YpkZofAj_gkp&W6zWEDXhBYblPTUXE(7I*a*Np@9>6UpJ$6YX^4XOW2Onra3cm z62qyVN8V6#8Fl|nREPeH>R=E%PjAII48y6Y4$a08T!oC;lzAxV!d<8}I*97=1=Ra| z5l7>7)Smc{{XI9w*_3&x2d_X~w-)ulYE;LbK#kag+9S^(p9<51jLmpHp`bPY8MTXD zxy}WtsD_rHHtA|?!OQqLmQ3d>h_SqreYhLd&Rlk+W@rg&0Bca~)M6yIVg&BP#cKL6 zg;Y*_iyBGTET;p}*hqagGOOlIR0qC7O=0P5=lXT12UMZ8rnq)dhoZXDf}mD$~51avQentr=mtU1NGJ{L`~&l)b$lO2J3MgwxO2bfc^al zY6g1k`Lh_Msr{q9;3}#E-=Q|kEz}KB^Ne{NQ?V1jz?JBp?~Lp?=24%)p9E|`wbO;_ z*ef_5`%s(vf~|jr9!=#<3VKg(BVR=`p09_#)p@86+=p7z3e-$&!m+p&qj5jxVlT3d z%->LZDU$DZ9L_>5Q7NheZq!UQ=QID>4DI%U7f|(Ms2fk>XLuR;c$p&$oPRd|gqhTD zpuP|B1vHK+n1)-B$uqB^25=2E(>GBaY+UHsf{NWBI%bM>f^?!g+ zYgd+#R(nG1Bk{I=AM$1O@9H=4LDE5Lh>jrgYf?)ll1!qbjlAeDIm_UttmS;!p8Ejv zh-VmoT8K8;(4mc{L$8z$y%9QCLUWe9K=l4UOQw+rh>rKkCZhfD28kd;$8RZ2CcB82 zJW2RwX#B>!M=Ja!=RcY`loQA*Qb*2_p`(+++eEL|3DQG!{DEvI$*ORKkSbC@4wKi2 zo|Zw5lj&rP&OA@y2+>hby2)@diByu&gxB3HAUe{CUL_s+YU3E&h`(#dT6?Y+Unlq2`Vi}e3fN@J1Gt(r+Ill4+VU3b zN2urfzi>w>SgS<tohn z?alqR5@{{Nhka)vibA~UG0T02VoHO3|4T@4c@HJt;T=p2^?sNX?cJ4>>3usf&fA?d z$y<~3Z{K^#-vy?XxEq_Q>k?M?`, 2011 # 18f25ad6fa9930fc67cb11aca9d16a27, 2012-2013 # Marian Andre , 2013-2015,2017 @@ -15,9 +15,9 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-09-18 11:41-0300\n" -"PO-Revision-Date: 2023-12-04 07:05+0000\n" -"Last-Translator: Martin Tóth , 2017,2023\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 07:05+0000\n" +"Last-Translator: Adam Zahradník, 2023-2024\n" "Language-Team: Slovak (http://app.transifex.com/django/django/language/sk/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -209,11 +209,6 @@ msgid "" msgstr "" "Objekt {name} „{obj}“ bol úspešne zmenený. Ďalšie zmeny môžete urobiť nižšie." -#, python-brace-format -msgid "The {name} “{obj}” was added successfully. You may edit it again below." -msgstr "" -"Objekt {name} „{obj}“ bol úspešne pridaný. Ďalšie zmeny môžete urobiť nižšie." - #, python-brace-format msgid "" "The {name} “{obj}” was changed successfully. You may add another {name} " @@ -383,6 +378,9 @@ msgstr "Zadajte používateľské meno a heslo." msgid "Change password" msgstr "Zmeniť heslo" +msgid "Set password" +msgstr "Nastaviť heslo" + msgid "Please correct the error below." msgid_plural "Please correct the errors below." msgstr[0] "Prosím, opravte chybu uvedenú nižšie." @@ -394,6 +392,19 @@ msgstr[3] "Prosím, opravte chyby uvedené nižšie." msgid "Enter a new password for the user %(username)s." msgstr "Zadajte nové heslo pre používateľa %(username)s." +msgid "" +"This action will enable password-based authentication for " +"this user." +msgstr "" +"Týmto povolíte tomuto používateľovi prihlasovanie pomocou " +"hesla." + +msgid "Disable password-based authentication" +msgstr "Vypnúť prihlasovanie pomocou hesla" + +msgid "Enable password-based authentication" +msgstr "Povoliť prihlasovanie pomocou hesla" + msgid "Skip to main content" msgstr "Preskočiť na hlavný obsah" diff --git a/django/contrib/admin/locale/ug/LC_MESSAGES/django.mo b/django/contrib/admin/locale/ug/LC_MESSAGES/django.mo index c517da656307a2f566ccc3df4b80ef2e6af7c54d..13b8d2c1443e20b063dd27a0893092c7b202b31d 100644 GIT binary patch delta 4909 zcmb8y3sl$T9mnwpK}8Wn1r;y&N4c0N3V6xHgiy2;F%nIt=AVlSAt;yOW$a%HDvfeR zm^0l{(+cMW{71SIcg~mB^E~{1 z&*l3(zaM(F+2`HYd|V&*^=mL(=ZGQ1{BFhs`WRE!ORdJ73N|JbPh)@l2nXYJ%*LL5 zjETm4RC^uH#8+?vcA%b*?rRKPnMNMd(?G7A3-Hqz# zyzNEwr|!WZyn=LW{*FEHYy0=Nv5LBXKVzzKGX^rg2?!x*2t%zf3cWK$b&!fYYtn6( zVQ=bX7>1irE82sxcmP?n`5lhLzn~`Ai&d#T6!m-z#xuT|M4>Ad*f*45PwG#iR#b{anKr3=i%xP2yAEM5}W#k1g9jFQT47D=Q4YgIFsQZW6?J=lN22#+>Mq?AEpgR5vHPbNm=N?Q%rF042kNLa0y!^zCV1WebdsiB}0e}GxIgwb^t+_)H9Q5hK=ZJq8Y+gMa);!#_X zii~YCZ7Yy5%}&(B-$I>%chC=iFB#u>>>EBtrSLP<-hG7{I3UJKVJJ?f9*$4rqv(sD zp*sE?H{wm4fK?-{FQ^*}slSg?aSG{F=GLK0d-@y&?afKs^QewLLanSFHL=f8hvo+A z{;oXS1N+zxMzu$wRv3@#eK_^Vc{WY4#_%aI7f=(p7EAt*Qt%yZ&Df3lQ2Z4O(4Uhw zA4@SF&!JwsZ%`}l$p&}BL8y#Hpe8&Sbtq>cW1Bo=&So2G0&k+8zZggURk%V!Py7-! zz`rpFgT`7N4@Diu3D}4k_&(l5?fH35mIl0zI=nrZt=@uhs4r$Js(lf%c;iCOw>hK& zW0~Kg-rrl8guw~c-lZc=rV#t!Zq)rpP#s*xV!VyYL~)|^Tm|-~{wyl>`%n`(h1#M& zpcd@9LP0b70+p&T-lcnSI%+GbQ0=>skDWP({qPff75{}zxQ`PT%wEr*Xv|^i`IDFc z^?r1wfktq0Q!oydsny8BT&9kK-rH8x03V`O@+GF?H<*i4?=xl^?nNEOKci0hb<|cw zPBG>&{2F~2IEysuzJ(n5zLg(So5MQx!6Nt*c^M!G0C$ct{Aff{HI>c$*Y zN9CxQ*J1?jM{UVjWbUQ|^<3No{6)j*coI+H8~6li4DsQum~PC2)aTBy{$a8cT{@Mg zDJVr(QD@;M>X1dJSs$D%R3^3|-w?A4Ns>8(+OjS)tvwxvx^D{VjHIC^nvIcIgPL$7 zF2-v!$$v718MF9E;AV`$6UZxWK1IFP{h0P(jJ2JK8Xy;kVs6Undo3zc4K4}^6kbHF_yc?defU9^OcrXuJ*b&qMP=xp zsIw71-)c|9Ueq5zEg%C&W1(Gt9)qbjBSV-oIF<#v`e#{xT+$X;sm{PpxnTveNRz&h zPH{J?{f}6LXCJlBO2Q(tLVYO?#S^HlYDYi3ff0BMbx6art;0PYxzASPxK(3A#^zNiOx%3L|r7uJVc}rQG~8&;xuuJ_#W{XQA6w{bVkk+ zKP4iF&hZV~?L9b&_ynQrSz@xcWbIkHUA_l(`i~R)2^~z{RPP_6G^`|a>D+AemW9=GuRT*=Qfchz5{+?VJ_{EBEG%8A{? zI${y=L!z2EM!Zg(AjWF_dJj9VEDGI;B%(7lzocA3Y$uiwzaVB1I_;g;!Oj9U6MP1| z|Dzs>dW&?ewz%`Nl+xhNK}Jy-NW4MpA%+n9h+zcZ4(~OMpNEMst7=}eeFfLpWiie! z_rI&HvzS9+Ju!foM0m&7`@D)6O}s?>oX{0Z1Q5Z*972~~$*n{o;YaKuo+ln5@`w?H zE+;Xbc$LT`bgdxPdP~;dk1FfaVYR#rsl;sihNo-`Y+G=fU0#a5L~pyk8RPBpTR6oo zC%Y?xXZbq{%A7ex`Ht1jva-sO(!4P_&a(VGhqI!5WqxsaL9Vm@^?{kg|NAZF1trDq zZea_$2jrLE>Byb!817p?Co;6Y_lO}FUOyo6Musz2H#;f|ii#XbW#y$M#VhX5FIM+S zW9{ml9=Dall)LES4 zT$j9Jm9wBIF1KXW{i7WT;}R0b@MF9?WYp52h^}V7SCoHFKwoAlNvlval@AS)%QL#?f>e*v(dA)t-0+uBQu-%)HjMe%ssu?!|Ncy0|8=5_v+PAbdu@-u5@lLssrmdHlwx)jRu=iL0%Ur!3cptj6J$KDI*q-*Cy>e&I H3+(Y9jJx2D delta 4376 zcmXxme^k}=9mnxEzvPF3{4zyBF9D)}C@3ufmB{%cg-|qSg2^PA!cbBtN_dk}(y-L4 zxr~)%7S_<|&2$^)FLriz+Ro6Ob@sQE+D*xE?b-!Oerx%aU=X>w{d_TXw zU;D$Upj#({y#4W^`;F2|l1cF(v+y9Zs{3@+tU13$P3I`+lTr`x?XXdkiu2T1dQ^?iG&uLL%x1BT)m&b1lbVwChpdd(L$yM$q1a zF?bN^*p6Z(cDtXS##Y+r@p+t42&?Gly2T)2#y;Z+Qb6xG4^$Zsqx(Q!Bqp`DFM zScICtdQ z4{Cr{FdA>52KXP;z=9Y>35KI?JR3F8I@CZLaWQVkbnH)J{Tr!-j4%tvr%@x^fZCER zsG01Q5}?`_Wn`ipj$O+0F9`buS0E38|wQV?)81B8y|Mte&n8Z5jC-XEWyvcRMu0; zPBE*%L%0L)Vj;G$j=J%Os2lzsHPcT}1HFpclDnuS4jJtXa3pf9%!9196`&^i7-|63 zsD8YwsAvXjQ5|kZb@&oy;UOH4A7ci7i<-%3kF(T8s1=%x+PbBv8`Pp!WG$-SX4HT> z@C3ez^yjt8RA+>na2y}_P(M72)9`o5Hd`ngHyKAG=hPPB2CTth4Q94DD45Nw*iKvxm!Z2)c-HKX~cGMQUirmY(Tt7zowmYbS$B%LL zegx{QWVud2eLfj=NQ-e8_qRDzbmJP-64v7sT#vi(7=~bRrqgi=w$ZM@0{jbdj4X02 z?*bfyQ*jS!<^GJ?%Fj_-Gn8ePspwV5%WT1+#L23PhlQLjdxCcG3qfY!$DY$ zI_0&f0Y8H}j4z^Q_%1RAyMh|PJ=E`qazJDTMqvT!sVd23{ngQYE~w+>sK=!l-^0Dw zhf^mwdmh7y(hc*F?Y1)1>0gI>LvDAkcOsLti^%!4J4ja+%k1<_5 zRKK5~Ch!%m(DVNtmFZkq#*x?IdmVL1-p4-t6raSCh5Q4jektfZ1P+#~A8JpcfJw};~G7(Er zGgypF+LmD)zJe@{bs_H-yNdc=aEY@ek*M#DM)i}2NnR>5sifj^%)&Ngkk*ab%iGw3 zK@YQx*otRxYAGEtvu|(??ZGpg|KV7KI-FZD9^Xdo{b|&h`V3iAi~k|(ubIxH!n?s1 zBa^jfF&WRH_VVwj@BI&TCPHR9109Cxv`bL~uEQ!kf+ZL{%Z%e;k09?T+l)Ms_7o3O&nPrD8W<4Eo% zGcgJ$Ay1%9L(Q}aEAb6vj`kI5tBMvl1K;MQlF5aAs6)}?esCG}G+aj=zAsQK5imhfbx991PT)*KZB=81lM%?KfCV zyutiwCfb{UlI&JEOMz1D%2R0P$_&2t43s@oj*|p(igXc`56E*QLk&s`8qqXTPE)m=UE+kL8?G2db);GJJL*3tA zA+uDWoF-A^S#pW2A{FF$@*#PLtRPd!eI%DO5S6nIf%nAw)PLc&N4RcuUF{mKv$@Z0 z#JeuVC;ew*XGi$5ljiw5lPbgg_dK2uUuRl^uRkr)_fh(A-wWyEeaF+1eTULV`RddE z>pzq6uh5k8n)Njet7<%BXRNMitXt!m`BX#0nvLUfJoyvzC;2aDEsOCrP3iC*DU9%_FpeA3-(`}A0GLC8L-dm diff --git a/django/contrib/admin/locale/ug/LC_MESSAGES/django.po b/django/contrib/admin/locale/ug/LC_MESSAGES/django.po index 5af1e41f54..bdac66a88d 100644 --- a/django/contrib/admin/locale/ug/LC_MESSAGES/django.po +++ b/django/contrib/admin/locale/ug/LC_MESSAGES/django.po @@ -3,18 +3,18 @@ # Translators: # abdl erkin <84247764@qq.com>, 2018 # ABDULLA , 2014 -# Abduqadir Abliz , 2023 +# Abduqadir Abliz , 2023-2024 # Azat, 2023 # Murat Orhun , 2023 -# Natalia (Django Fellow), 2023 +# Natalia, 2023 # Serpidin Uyghur, 2023 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-09-18 11:41-0300\n" -"PO-Revision-Date: 2023-12-04 07:05+0000\n" -"Last-Translator: Natalia (Django Fellow), 2023\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 07:05+0000\n" +"Last-Translator: Abduqadir Abliz , 2023-2024\n" "Language-Team: Uyghur (http://app.transifex.com/django/django/language/ug/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -204,12 +204,6 @@ msgstr "" "{name} “{obj}” مۇۋەپپەقىيەتلىك ئۆزگەرتىلدى. تۆۋەندە ئۇنى قايتا تەھرىرلىسىڭىز " "بولىدۇ." -#, python-brace-format -msgid "The {name} “{obj}” was added successfully. You may edit it again below." -msgstr "" -"{name} “{obj}” مۇۋەپپەقىيەتلىك قوشۇلدى. تۆۋەندە ئۇنى قايتا تەھرىرلىسىڭىز " -"بولىدۇ." - #, python-brace-format msgid "" "The {name} “{obj}” was changed successfully. You may add another {name} " @@ -376,6 +370,9 @@ msgstr "ئىشلەتكۈچى ئاتى ۋە پارول كىرگۈزۈڭ." msgid "Change password" msgstr "پارولنى ئۆزگەرتىش" +msgid "Set password" +msgstr "پارول تەڭشەك" + msgid "Please correct the error below." msgid_plural "Please correct the errors below." msgstr[0] "تۆۋەندىكى خاتالىقلارنى توغرىلاڭ." @@ -385,6 +382,19 @@ msgstr[1] "تۆۋەندىكى خاتالىقلارنى توغرىلاڭ." msgid "Enter a new password for the user %(username)s." msgstr "ئىشلەتكۈچى %(username)s ئۈچۈن يېڭى پارول كىرگۈزۈڭ." +msgid "" +"This action will enable password-based authentication for " +"this user." +msgstr "" +"بۇ مەشغۇلات مەزكۇر ئىشلەتكۈچىنىڭ ئىم ئاساسىدىكى دەلىللىشىنى " +"قوزغىتىدۇ" + +msgid "Disable password-based authentication" +msgstr "ئىم ئاساسىدىكى دەلىللەشنى چەكلەيدۇ" + +msgid "Enable password-based authentication" +msgstr "ئىم ئاساسىدىكى دەلىللەشنى قوزغىتىدۇ" + msgid "Skip to main content" msgstr "ئاساسلىق مەزمۇنغا ئاتلا" diff --git a/django/contrib/admindocs/locale/ga/LC_MESSAGES/django.mo b/django/contrib/admindocs/locale/ga/LC_MESSAGES/django.mo index ebd4321e4bf0c9fa393b9f5c4f47d2cfae88d378..201694dd51deaf814281e48b58275287b4a4da18 100644 GIT binary patch literal 6786 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 delta 783 zcmX}pJx^0n7{KuZRQke8fug2}QWFP__Qh5Zh#{sG<4^}|gM-s)Il>LMx1=p8Oe8Lv zXpH7qjiZBu1G68XgNsZ$=%AB{viSiV_&?>wlRo!%-tKvxp8II_Rdny?M4+Q+r-^Ce zD=|Yn>*GNS^(%D+!#Ip{ID!S7!WBG&E(Y-l2Ji)zu!A`~#6dheaJ+s2!%FR`Oa4R- zPq1MgW#bacfy@5*E=mDqOru6g^b#}p8s+^@_=e&SQ1%%nqu9Z5e2?exBc{o(zSE%+ z6(%cP6~h|F@fJQte(Ez1+4lt__yeWDKRASc{qaAPa{?@eFyb4-YmBE+)>kk`es$m9 z@D%0N#|TNpQ1K^v$s~ca2|`|$7CT09v%N&}S>!XG^ydX?`QPNWP7!j8qyFr$T*)LM zS7iGKQ+;`x4#w?FaDM2v, 2011 # Luke Blaney , 2019 # Michael Thornhill , 2012 @@ -8,10 +9,10 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-01-19 16:49+0100\n" -"PO-Revision-Date: 2019-06-22 21:37+0000\n" -"Last-Translator: Luke Blaney \n" -"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2024-10-07 20:19+0000\n" +"Last-Translator: Aindriú Mac Giolla Eoin, 2024\n" +"Language-Team: Irish (http://app.transifex.com/django/django/language/ga/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -20,7 +21,7 @@ msgstr "" "4);\n" msgid "Administrative Documentation" -msgstr "" +msgstr "Doiciméadúchán Riaracháin" msgid "Home" msgstr "Baile" @@ -39,6 +40,10 @@ msgid "" "click the link and add it to your bookmarks. Now you can select the " "bookmarklet from any page in the site." msgstr "" +"Chun leabharmharcanna a shuiteáil, tarraing an nasc chuig do bharra uirlisí " +"leabharmharcanna, nó deaschliceáil ar an nasc agus cuir le do " +"leabharmharcanna é. Anois is féidir leat an leabharmharc a roghnú ó aon " +"leathanach ar an suíomh." msgid "Documentation for this page" msgstr "Doiciméadúchán le hadhaigh an leathanach seo" @@ -54,7 +59,7 @@ msgid "Tags" msgstr "Clibeanna" msgid "List of all the template tags and their functions." -msgstr "" +msgstr "Liosta de na clibeanna teimpléid go léir agus a bhfeidhmeanna." msgid "Filters" msgstr "Scagairí" @@ -63,6 +68,8 @@ msgid "" "Filters are actions which can be applied to variables in a template to alter " "the output." msgstr "" +"Is gníomhartha iad na scagairí is féidir a chur i bhfeidhm ar athróga i " +"dteimpléad chun an t-aschur a athrú." msgid "Models" msgstr "Samhla" @@ -72,6 +79,9 @@ msgid "" "associated fields. Each model has a list of fields which can be accessed as " "template variables" msgstr "" +"Is éard atá i múnlaí ná cur síos ar na réada go léir sa chóras agus ar na " +"réimsí a bhaineann leo. Tá liosta réimsí ag gach samhail ar féidir rochtain " +"a fháil orthu mar athróga teimpléid" msgid "Views" msgstr "Radharcanna" @@ -81,138 +91,149 @@ msgid "" "template is used to generate the page and which objects are available to " "that template." msgstr "" +"Gintear gach leathanach ar an suíomh poiblí trí radharc. Sainmhíníonn an t-" +"amharc cén teimpléad a úsáidtear chun an leathanach a ghiniúint agus na " +"rudaí atá ar fáil don teimpléad sin." msgid "Tools for your browser to quickly access admin functionality." msgstr "" +"Uirlisí do do bhrabhsálaí chun rochtain tapa a fháil ar fheidhmiúlacht " +"riaracháin." msgid "Please install docutils" -msgstr "" +msgstr "Suiteáil docutils le do thoil" #, python-format msgid "" -"The admin documentation system requires Python's docutils library." +"The admin documentation system requires Python’s docutils library." msgstr "" +"Teastaíonn leabharlann Python docutils ón gcóras " +"doiciméadúcháin riaracháin." #, python-format msgid "" "Please ask your administrators to install docutils." -msgstr "" +msgstr "Iarr ar do riarthóirí docutils a shuiteáil." #, python-format msgid "Model: %(name)s" -msgstr "" +msgstr "Múnla: %(name)s" msgid "Fields" -msgstr "" +msgstr "Réimsí" msgid "Field" -msgstr "" +msgstr "Réimse" msgid "Type" msgstr "Cineál" msgid "Description" -msgstr "" +msgstr "Cur síos" msgid "Methods with arguments" -msgstr "" +msgstr "Modhanna le hargóintí" msgid "Method" -msgstr "" +msgstr "Modh" msgid "Arguments" -msgstr "" +msgstr "Argóintí" msgid "Back to Model documentation" -msgstr "" +msgstr "Ar ais chuig an doiciméadú Múnla" msgid "Model documentation" -msgstr "" +msgstr "Doiciméadú múnla" msgid "Model groups" -msgstr "" +msgstr "Grúpaí samhlacha" msgid "Templates" msgstr "Teimpléid" #, python-format msgid "Template: %(name)s" -msgstr "" +msgstr "Teimpléad: %(name)s" #, python-format -msgid "Template: \"%(name)s\"" -msgstr "" +msgid "Template: %(name)s" +msgstr "Teimpléad: %(name)s" #. Translators: Search is not a verb here, it qualifies path (a search path) #, python-format -msgid "Search path for template \"%(name)s\":" -msgstr "" +msgid "Search path for template %(name)s:" +msgstr "Teimpléad cuardaigh cosán %(name)s:" msgid "(does not exist)" -msgstr "" +msgstr "(níl ann)" msgid "Back to Documentation" -msgstr "" +msgstr "Ar ais go Doiciméadúchán" msgid "Template filters" -msgstr "" +msgstr "Ar ais go Doiciméadúchán" msgid "Template filter documentation" -msgstr "" +msgstr "Doiciméadú scagaire teimpléid" msgid "Built-in filters" -msgstr "" +msgstr "scagairí ionsuite" #, python-format msgid "" "To use these filters, put %(code)s in your template before " "using the filter." msgstr "" +"Chun na scagairí seo a úsáid, cuir%(code)s i do theimpléad sula " +"n-úsáideann tú an scagaire." msgid "Template tags" -msgstr "" +msgstr "Clibeanna teimpléid" msgid "Template tag documentation" -msgstr "" +msgstr "Doiciméadú clib teimpléad" msgid "Built-in tags" -msgstr "" +msgstr "Insuite i clibeanna" #, python-format msgid "" "To use these tags, put %(code)s in your template before using " "the tag." msgstr "" +"Chun na clibeanna seo a úsáid, cuir %(code)s i do theimpléad " +"sula n-úsáideann tú an chlib." #, python-format msgid "View: %(name)s" -msgstr "" +msgstr "Amharc: %(name)s" msgid "Context:" -msgstr "" +msgstr "Comhthéacs:" msgid "Templates:" -msgstr "" +msgstr "Teimpléid:" msgid "Back to View documentation" -msgstr "" +msgstr "Ar ais go dtí Féach ar na doiciméid" msgid "View documentation" -msgstr "" +msgstr "Féach ar cháipéisíocht" msgid "Jump to namespace" -msgstr "" +msgstr "Léim go spás ainm" msgid "Empty namespace" -msgstr "" +msgstr "Ainmspás folamh" #, python-format msgid "Views by namespace %(name)s" -msgstr "" +msgstr "Radhairc de réir ainmspáis %(name)s" msgid "Views by empty namespace" -msgstr "" +msgstr "Radhairc de réir ainmspás folamh" #, python-format msgid "" @@ -220,6 +241,9 @@ msgid "" " View function: %(full_name)s. Name: %(url_name)s.\n" msgstr "" +"\n" +" Féach ar fheidhm: %(full_name)s. Ainm: %(url_name)s.\n" msgid "tag:" msgstr "clib:" @@ -232,7 +256,7 @@ msgstr "radharc:" #, python-format msgid "App %(app_label)r not found" -msgstr "" +msgstr "Aip %(app_label)r gan aimsiú" #, python-format msgid "Model %(model_name)r not found in app %(app_label)r" diff --git a/django/contrib/auth/locale/cs/LC_MESSAGES/django.mo b/django/contrib/auth/locale/cs/LC_MESSAGES/django.mo index 71403aec1303aa1edc4c6313e452fa701c2de854..0bdcc7b63352c218fc6b71169f20c379703a8ff3 100644 GIT binary patch delta 3338 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 diff --git a/django/contrib/auth/locale/cs/LC_MESSAGES/django.po b/django/contrib/auth/locale/cs/LC_MESSAGES/django.po index 78b6fc49e2..6b5cf6b2d4 100644 --- a/django/contrib/auth/locale/cs/LC_MESSAGES/django.po +++ b/django/contrib/auth/locale/cs/LC_MESSAGES/django.po @@ -3,6 +3,7 @@ # Translators: # Jan Munclinger , 2013 # Jannis Leidel , 2011 +# Jiří Podhorecký , 2024 # Tomáš Ehrlich , 2015 # Vláďa Macek , 2013-2014 # Vláďa Macek , 2015-2017,2019,2021-2022 @@ -10,10 +11,10 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-09-21 10:22+0200\n" -"PO-Revision-Date: 2022-01-04 18:49+0000\n" -"Last-Translator: Vláďa Macek \n" -"Language-Team: Czech (http://www.transifex.com/django/django/language/cs/)\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 08:09+0000\n" +"Last-Translator: Jiří Podhorecký , 2024\n" +"Language-Team: Czech (http://app.transifex.com/django/django/language/cs/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -34,13 +35,23 @@ msgstr "Důležitá data" msgid "%(name)s object with primary key %(key)r does not exist." msgstr "Položka \"%(name)s\" s primárním klíčem \"%(key)r\" neexistuje." +msgid "Conflicting form data submitted. Please try again." +msgstr "Odeslání protichůdných údajů z formuláře. Zkuste to prosím znovu." + msgid "Password changed successfully." msgstr "Změna hesla byla úspěšná." +msgid "Password-based authentication was disabled." +msgstr "Ověřování pomocí hesla bylo zakázáno." + #, python-format msgid "Change password: %s" msgstr "Heslo pro uživatele %s: změnit" +#, python-format +msgid "Set password: %s" +msgstr "Nastavit heslo: %s" + msgid "Authentication and Authorization" msgstr "Autentizace a autorizace" @@ -56,9 +67,24 @@ msgstr "Heslo nenastaveno." msgid "Invalid password format or unknown hashing algorithm." msgstr "Neplatný formát hesla nebo neplatný hashovací algoritmus." +msgid "Reset password" +msgstr "Resetovat heslo" + +msgid "Set password" +msgstr "Nastavit heslo" + msgid "The two password fields didn’t match." msgstr "Hesla se neshodují." +msgid "" +"Whether the user will be able to authenticate using a password or not. If " +"disabled, they may still be able to authenticate using other backends, such " +"as Single Sign-On or LDAP." +msgstr "" +"Zda se uživatel bude moci ověřit pomocí hesla, nebo ne. Pokud je zakázáno, " +"může být stále schopen ověřit se pomocí jiných backendů, například Single " +"Sign-On nebo LDAP." + msgid "Password" msgstr "Heslo" @@ -68,12 +94,24 @@ msgstr "Potvrzení hesla" msgid "Enter the same password as before, for verification." msgstr "Zadejte pro ověření stejné heslo jako předtím." +msgid "Password-based authentication" +msgstr "Ověřování pomocí hesla" + +msgid "Enabled" +msgstr "Zapnuto" + +msgid "Disabled" +msgstr "Vypnuto" + msgid "" -"Raw passwords are not stored, so there is no way to see this user’s " -"password, but you can change the password using this form." +"Raw passwords are not stored, so there is no way to see the user’s password." msgstr "" -"Hesla se neukládají přímo a tak je nelze zobrazit. Je ale možné je změnit " -"pomocí tohoto formuláře." +"Neupravená hesla se neukládají, takže není možné zjistit heslo uživatele." + +msgid "" +"Enable password-based authentication for this user by setting a password." +msgstr "" +"Povolit ověřování na základě hesla pro tohoto uživatele nastavením hesla." #, python-format msgid "" @@ -101,9 +139,6 @@ msgstr "Vaše současné heslo nebylo zadáno správně. Zkuste to znovu." msgid "Old password" msgstr "Současné heslo" -msgid "Password (again)" -msgstr "Heslo (znovu)" - msgid "algorithm" msgstr "algoritmus" @@ -271,11 +306,11 @@ msgid "Password reset on %(site_name)s" msgstr "Obnovení hesla na webu %(site_name)s" msgid "" -"Enter a valid username. This value may contain only English letters, " -"numbers, and @/./+/-/_ characters." +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." msgstr "" -"Zadejte platné uživatelské jméno. Hodnota může obsahovat pouze písmena bez " -"diakritiky, tj. háčků a čárek, číslice a znaky @/./+/-/_." +"Zadejte platné uživatelské jméno. Tato hodnota může obsahovat pouze malá " +"písmena bez diakritiky a-z a velká písmena A-Z, číslice a znaky @/./+/-/_." msgid "" "Enter a valid username. This value may contain only letters, numbers, and " diff --git a/django/contrib/auth/locale/dsb/LC_MESSAGES/django.mo b/django/contrib/auth/locale/dsb/LC_MESSAGES/django.mo index 473025927e50f3afe43a9dfa45142a5418dbb52c..0f26ac6d565c8467d5875b6612a181992e9080e1 100644 GIT binary patch delta 3206 zcma)+d2AF_7{Ff-ESCrLfGX(23fi(=v498yQlLn&LInlI^L2MK{j z1pm^Fs9BGA#3RN8vl>ASQRzmFS5!Qs#v}0n|04V$CLX_UcG@C|$4kEXz4yJD?|a|z zX77qm*Ji(-T6vFRY(-`uzmzMLg|Cd`!Prx!)CF)aY=noQhBL-1RSlQH7I+!#gm=Kj z@MCDflP4&}RHdMpybZR)J0PaA>OCgcqxb~wgy&CGYASpUE`SH%$#B9Xr53_^h)QjM zli^la54+(h@b*xDHx$PYL;3zGcq-fjPlq4DS_$ZKLW%fJcs6_$ zN@PF5GhsPlNQq{{hu})M8-5F0;oVr3QXGIyuxg4@Yheq#72X0*fWJbLt^R~rN#z9c zEvc#rITOlB=Rk>YKIE|KA}H@)3Z<4;LNRz9tb|s$-y1Ro#nE;sc6LH}Z&$d^PbL52 z_(>FEcz3w*a`@sKP!94Al$3oA#o)nk|467m3dPPu>LmxOhBTL|4>=3U0UF_(W%Loe zko6xmhXc)=BVijc>G<>PpzYZ^fg!v)?kFrTt_^n{Hz}(cH~dhi_PId#0=3imSGSvHMk_gIc^$Bb{gj+obekL~G{XC-x4MthbY_%)*+Mng;Sf;;}pvfMQj z-(UN0CROLZ?dr7gbUZw0G}k!k`D!ch{oVHay-}CB`IFlt8!gTh^7;Cya=#j7}I5Q(D{8UH?sl3tIO3^eb!%r~^GO{Q{{ow$5VSD(3C9V+Hk3^_!%dwxkU*de98)FT{;w(FVmwTrZQ*X?Gywo8DsH z)jgTwBf~pvoiu~FSv7Tqq3ScsvRj>AE3v;&+~@SVPDZsg2mR5xzu<*mbthfNju(gA z2&tl{(!R9FwmuWHdsEsmIPEJAnc_>99(h%C+INe29^I}^r;7VBX_M?lUvgy^hoY*u zmqk_RI5(^I^un7pGs_D{>zc~4t)Uk?aAW?#jrxDD>0X!C)q|sv;@(6R88T_3wh*e@ zWjkJl@Q%o6!C3raJR+)*jtE1E=s`W;Cfry`$CIgU koBj;j)gfMR4}O1lZh7#e|M{GId*>|w z|C#$k$H?cdi9@&y&tM40 zO)y47^x+oVhWqe57UMG$jcGI{Wny&h;l^QHf*G8I*RcR^;tULMvk1#j_ZyJ0%rgJ} zTGTj?<4o+v+4v%s;=5Rg8Jvz^Vg>V?i*&S;f3OS-CmX|`spDe`HsN#Fif`ayY{w<6 zq6&ASgNKkEnH;_}7nh#-)1}^&kg38PdWR2!FGKa|{ZF;^0Rg&4L@v1R3j!wP*z(U{UsEOK919hUF zd)B{pP!mT{18?{552K!Y6}6E4$e($i4~=&m_5UyY`zMRYzXm$b4Xx|~a(>Je-``OS z_!CbDjJbo$xjxAWT7h>^HEyPU)9@)&DPp)8&*N^anws755!}x8G5icGOUb_u%a5Fp zMff*r!Wu?fi;GY@Ng~xS!>9>gN1c^VkSv?Cs2yHH<}|+|bC}y$gN2+p&C`fF6Pxfp zjHKvP)7gWycogU0cc`;)3stKso~CQ+a38M45AYneVS-Why%BsKui|{%%&Z!B7`5PI zsQJD|9p2OpI=!T}i2v#xFvJmEhG$U&iUi%a#_rU(rU?{9aqgXASXS_R{+`sQUoHS@KGwYh|L6;MkZ2 z#1dkxb<$DEnhB*|X;l+dYOO*};CJj^H57881_ zjWxXo)buk|)B8kqUQbjJ^9Z%M`lt!UoM@;vVco92P%_t#o9qqUeSoh-Vqv?&vAyxo)|Hhn?5bRq>}9B}ZalhTfwL<8+LZN~yu!JSc zx#?>qb8-g<2Q!nV9u8z~mNo^(x6SjGbbR{qoRW2MHx}s`-Q(Kej+i?b3cIzLKW5Yi z(nDn*33|bFVyGS=;_SpiI|%Xm(SkVV4eO@_KrJx(6!;aqwTQU t+^E|<@V|BPl+|$FVh8%2xT6)@9nr52#v, 2016-2017,2020-2021,2023 +# Michael Wolf , 2016-2017,2020-2021,2023-2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-17 03:19-0500\n" -"PO-Revision-Date: 2023-04-25 08:09+0000\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 08:09+0000\n" "Last-Translator: Michael Wolf , " -"2016-2017,2020-2021,2023\n" -"Language-Team: Lower Sorbian (http://www.transifex.com/django/django/" +"2016-2017,2020-2021,2023-2024\n" +"Language-Team: Lower Sorbian (http://app.transifex.com/django/django/" "language/dsb/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -32,13 +32,23 @@ msgstr "Wažne daty" msgid "%(name)s object with primary key %(key)r does not exist." msgstr "Objekt %(name)s z primarnym klucom %(key)r njeeksistěrujo." +msgid "Conflicting form data submitted. Please try again." +msgstr "Pśeśiwne formularowe daty zapódane. Pšosym wopytajśo hyšći raz." + msgid "Password changed successfully." msgstr "Gronidło jo se změniło." +msgid "Password-based authentication was disabled." +msgstr "Awtentifikacija na zakłaźe gronidła jo se znjemóžniła." + #, python-format msgid "Change password: %s" msgstr "Gronidło změniś: %s" +#, python-format +msgid "Set password: %s" +msgstr "Nastajone gronidło: %s" + msgid "Authentication and Authorization" msgstr "Awtentifikacija a awtorizacija" @@ -54,9 +64,24 @@ msgstr "Žedno gronidło nastajone." msgid "Invalid password format or unknown hashing algorithm." msgstr "Njepłaśiwy gronidłowy format abo njeznaty kontrolny algoritmus." +msgid "Reset password" +msgstr "Gronidło slědk stajiś" + +msgid "Set password" +msgstr "Gronidło póstajis" + msgid "The two password fields didn’t match." msgstr "Dwě gronidlowej póli njejstej jadnakej." +msgid "" +"Whether the user will be able to authenticate using a password or not. If " +"disabled, they may still be able to authenticate using other backends, such " +"as Single Sign-On or LDAP." +msgstr "" +"Lěc wužywaŕ móžo z gronidłom awtentificěrowaś abo nic. Jolic to jo " +"znjemóžnjone, jo hyšći móžno, z pomocu drugich backendami awtentificěrowaś, " +"na pśikład Single Sign-On abo LDAP." + msgid "Password" msgstr "Gronidło" @@ -66,13 +91,26 @@ msgstr "Gronidłowe wobkšuśenje" msgid "Enter the same password as before, for verification." msgstr "Zapódajśo to samske gronidło, za pśespytanje." +msgid "Password-based authentication" +msgstr "Awtentifikacija na zakłaźe gronidła" + +msgid "Enabled" +msgstr "Źmóžnjony" + +msgid "Disabled" +msgstr "Znjemóžnjony" + msgid "" -"Raw passwords are not stored, so there is no way to see this user’s " -"password, but you can change the password using this form." +"Raw passwords are not stored, so there is no way to see the user’s password." msgstr "" -"Grube gronidła se njeskładuju, togodla njejo móžno, gronidło wužywarja " -"wiźeś, ale móžośo gronidło z pomocu toś togo formulara " -"změniś." +"Gropne gronidła se njeskładuju, njedajo pótakem žednu móžnosć, gronidło " +"wužywarja wiźeś." + +msgid "" +"Enable password-based authentication for this user by setting a password." +msgstr "" +"Póstajśo gronidło, aby awtentifkaciju na zakłaźe gronidła za toś togo " +"wužywarja zmóžnił." #, python-format msgid "" @@ -101,9 +139,6 @@ msgstr "" msgid "Old password" msgstr "Stare gronidło" -msgid "Password (again)" -msgstr "Gronidło (znowego)" - msgid "algorithm" msgstr "algoritmus" diff --git a/django/contrib/auth/locale/es/LC_MESSAGES/django.mo b/django/contrib/auth/locale/es/LC_MESSAGES/django.mo index 9af417c804f35ce14d3e192023b2dc01e87d5bb8..9323380d979eca0678b8834768e271298b664361 100644 GIT binary patch delta 880 zcmXZZPe>GT6u|MPw58Q*rCYjXO=YFIife0FZGS*m^&rVgbSR8*chsTX8JK4G5XC@U zt4o)pL*UI0QEVML1Xhl52~tAd zpw|6?W!&5$auRQ1555doP(xNRfsM4MS8x>TxtfdkjQG+Xkx`5pwFymOiugW`;d@-d zIAdCmpRp0YqfWAl+Q3>Ew=yQp2M1Z`-3=jol0hvnhY@tcxP)7Xuc40oHZonANBvMG z+<$?3{vGOjA40$32I5uJiT*|EXJsu+tlM83T@;&np%e8$3iYnjsDC_xT3|Z#a;T3@ zlk^{cdr;Z*YQ0wZ|8j1vxzOop!SUG6-xz^OrJ5~dd7@d=4m_r Y>qW;m3vMNdosHaGiFZ~0#m_hV2YxPrL;wH) delta 821 zcmXZZO-NKx6u|K_(%6hSW{p$ols+d!Q_(0TB|ic|lOn|yA&T^v8D&6bzb{5(h@XHj%3~g0l#0lUq^5ZAe1>4|C!1e)rt_?z!)rJ2$vHkUcJPU5`jd zP^42tHY-Hx@dRtIA|!GZ?_e)J#3%R``*9zqF>*yDpz}y7S;TStf+gr9$qNkP2F~L( z?5`A8x)?mG6uFEaup8I#5*``Pu#UK_s_m$#v8MwoSZebPpNm-Tg%#@zXy|(2QQZZQ@QWC+~1T64V=8jd!t(_4~Q6-h+Vu zvF+G13A@G0{S2;n+8?FTR?K#I$CH_a9b=G=ThUa~nYCkyXgt|!jihF+DLcbEk#yob Vxo@FiuP40_2se7txsLEt-+y^MYKs5> diff --git a/django/contrib/auth/locale/es/LC_MESSAGES/django.po b/django/contrib/auth/locale/es/LC_MESSAGES/django.po index 1644c996d0..060af415c6 100644 --- a/django/contrib/auth/locale/es/LC_MESSAGES/django.po +++ b/django/contrib/auth/locale/es/LC_MESSAGES/django.po @@ -13,15 +13,15 @@ # Josue Naaman Nistal Guerra , 2014 # Leonardo J. Caballero G. , 2011 # Natalia, 2024 -# Uriel Medina , 2020-2021,2023 +# Uriel Medina , 2020-2021,2023-2024 # Veronicabh , 2015 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-05-22 11:46-0300\n" -"PO-Revision-Date: 2024-08-07 08:09+0000\n" -"Last-Translator: Natalia, 2024\n" +"PO-Revision-Date: 2024-10-07 08:09+0000\n" +"Last-Translator: Uriel Medina , 2020-2021,2023-2024\n" "Language-Team: Spanish (http://app.transifex.com/django/django/language/" "es/)\n" "MIME-Version: 1.0\n" @@ -44,13 +44,15 @@ msgid "%(name)s object with primary key %(key)r does not exist." msgstr "el objeto %(name)s con clave primaria %(key)r no existe." msgid "Conflicting form data submitted. Please try again." -msgstr "Los datos enviados se contradicen. Por favor intente de nuevo." +msgstr "" +"Se enviaron datos contradictorios en el formulario. Por favor inténtalo de " +"nuevo." msgid "Password changed successfully." msgstr "La contraseña se ha cambiado con éxito." msgid "Password-based authentication was disabled." -msgstr "La autenticación basada en contraseñas fue deshabilitada." +msgstr "La autenticación basada en contraseña fue deshabilitada." #, python-format msgid "Change password: %s" @@ -103,7 +105,7 @@ msgid "Enter the same password as before, for verification." msgstr "Para verificar, introduzca la misma contraseña anterior." msgid "Password-based authentication" -msgstr "Autenticación basada en contraseñas" +msgstr "Autenticación basada en contraseña" msgid "Enabled" msgstr "Habilitado" diff --git a/django/contrib/auth/locale/es_AR/LC_MESSAGES/django.mo b/django/contrib/auth/locale/es_AR/LC_MESSAGES/django.mo index d985402b26a4cbc90363ddcb882d3a78480513c9..80cd087426a621e17319aedc3a9f8ed2016ec3f9 100644 GIT binary patch delta 3152 zcmb8wd2AF_9Ki9{Lb>H=3#AD75Q-GaQp+JX6be!;v{1Pk159_P?a1y-*_myrs0#_f z1Uy+WF=~na;}Il~Z6r8Z}-sTIj@@_QdpvI;fvd3&cjFv9 zgC-8?uN0>$ffDjDtj66)sHFOYlg-@t0{7yq0ZQfLhd2XI;}GmWP^p<%jNDSSI0zfC z7@Kh@?h5YjM;Z7a%I{ytQFt83;^#PAmU@ko!QALav?46RJ8&Ax3TyFp4C5F~;uL%t z`KkICZ^JXV3BSWtxP+U_@mZAkXOTzh63Rrc<9JDR9#0J{MOpDaybDjDtn4!0iMcF8 zwx|R_?Vp={l*kxJc%oyeTk z_eoA9@NdXAs!BGTZBeUH_B@OwxCfcEI)t*46Udy@DU_nT5GW-s1C2#l$UKxd^*9OJ za4sH1De~kwPGo>zaSm!qT~^kBGC&yjVFxy29?>7h7|H;bkwyEnAcQJnHWIG_pTG@x zH(tb<@|BgFGr$WkHy|tf|BydC|fiOB}2kxe< zUG`G`7RZXJIlsvyq%EYcqSw$X>C(#RB-sCh#!mUIisO9x6xn}i_tK@9BnwhJz3A)c z@~PC*@1au`J*_r4TNF4AB~wf33xa#XJi63?wAC5>;|7k?>2qX!DTeO0krS!T_4NCL zo8>r(zBstf3(Tf2>tYG#@Nvm9H( zYp=y}b;32{y0JsMrst1q^!zXsM2e)HeqZOL9vtxLid%(Lb+>w|+YMJof{BJwr2~%@ znEu!ocD~^D44IlfsJd*8$y|DFsrrArn5#?N^o~L2bCT;@Oco~#%EZ*|Ry3*`P3s;o<|8$7#L-qecniW%vrhNW{B);J``@Hm=wn`J~eVVlE_?Zu6V z6*g_Qp5HbZZ5%DzV@kqb#&*fQP$)HN@t6CQAckhSms%4!X!;?)CP&j3dLB_?)9ej7C%}|(Pb9Rt6A@Fj{}WafR{0W<13A^xB^F`i|cSRF2qyl;($TM zXoybSfL-`9p2Jc2DE@&p7^8CpPC)h7BV(C`QU7w( zI1l1@OyXpG4#(o#I2=nj4nMU8aYj^-#a4xgB z9k-!_`;iryG9H?S^HCGufOWVTmEpH=AAW+(yx%;=v>NbDoQ`L(75~I-*vzuXzWEeM zhWQeit2v9xz=g=4QJJ}h%+cIH-eD?8o9-Wt+LFnr@upy504Fn|8)io?M!l#7HPAZL zeNRQ#4(i2e)WF?Q{|?lBuc9Wh2l+GaaL{;1Q2##}_4ke-{~G8V9h%vBq<+k$$g8Lc z{DvRIjJb)8Tpy-_rr})V@&+oS zRjfvtnv8nB0ojs*Sr~OJMHNR2DwV5IsecqzBkjocn=aG5X-_Vz7eQJ=>6eO$m)Vdc1<&(3EfZ3A=Fefw}ofMP`qKQ=cp~vHYvqxi6%mI zG@VdePpGg}{j4keM1xsOJV5CEVVliS1+=K|GAtgQ-c9H$rc|ma#dQSr6c&(*tG}(| zL^YrSD<_mqWvstZ(`G)=+TWq~-^;}kg8DP73GMM3VkNPZxQF0FXznD`8VG&W`dedk zGBi?Kr=Q>|LZ9cEgxWM6rp7Z)+D!!3-`MFUbGD~=s`AC+&OyIdtV}yzs`TC9i?PbM z)9!egMDbA7`QoXe#~$$ln-ARVPtWfSY?l)RJ$|;W-fqn2>}Ef2lTOAaJDg0rYjYj$ zKR57*mua_+j_t_0o0imV-Coy}>tLu&em31W%V{d^9=57fG5lhzv}eS;^3s{nrC6zV zY&_OClj7-dYfA^m#mmO}nOxQh+|Q3XHs0piOy2GG6UECl)y2~_)urn-<+0)u6W%YZ zOxeH-a&FqO8Q(gow3Bo*j!ij%P5wIs3(tD(UdBneti{jTly8%HC#7e?p1|9fa&5O4 z(CKY)xWW1F^OhO7yoJ@}ovi2A+b%cj+phe4m;a>wHgA)cbh12@51dS!|Nr%ePip=7 XlpYSV@XW;RrG`oGm6dkeo#lT6l;kM~ diff --git a/django/contrib/auth/locale/es_AR/LC_MESSAGES/django.po b/django/contrib/auth/locale/es_AR/LC_MESSAGES/django.po index bd89b28f39..c5f59b6971 100644 --- a/django/contrib/auth/locale/es_AR/LC_MESSAGES/django.po +++ b/django/contrib/auth/locale/es_AR/LC_MESSAGES/django.po @@ -2,14 +2,14 @@ # # Translators: # Jannis Leidel , 2011 -# Ramiro Morales, 2013-2017,2019,2021,2023 +# Ramiro Morales, 2013-2017,2019,2021,2023-2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-17 03:19-0500\n" -"PO-Revision-Date: 2023-12-04 08:09+0000\n" -"Last-Translator: Ramiro Morales, 2013-2017,2019,2021,2023\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 08:09+0000\n" +"Last-Translator: Ramiro Morales, 2013-2017,2019,2021,2023-2024\n" "Language-Team: Spanish (Argentina) (http://app.transifex.com/django/django/" "language/es_AR/)\n" "MIME-Version: 1.0\n" @@ -31,13 +31,23 @@ msgstr "Fechas importantes" msgid "%(name)s object with primary key %(key)r does not exist." msgstr "No existe un objeto %(name)s con una clave primaria %(key)r." +msgid "Conflicting form data submitted. Please try again." +msgstr "Los datos enviados se contradicen. Por favor intente de nuevo." + msgid "Password changed successfully." msgstr "Cambio de contraseña exitoso" +msgid "Password-based authentication was disabled." +msgstr "La autenticación basada en contraseñas fue desactivada." + #, python-format msgid "Change password: %s" msgstr "Cambiar contraseña: %s" +#, python-format +msgid "Set password: %s" +msgstr "Establecer contraseña: %s" + msgid "Authentication and Authorization" msgstr "Autenticación y Autorización" @@ -53,9 +63,24 @@ msgstr "No se ha establecido una contraseña." msgid "Invalid password format or unknown hashing algorithm." msgstr "Formato de contraseña inválido o algoritmo de hashing desconocido." +msgid "Reset password" +msgstr "Restablecer contraseña" + +msgid "Set password" +msgstr "Establecer contraseña" + msgid "The two password fields didn’t match." msgstr "Los dos campos de contraseñas no coinciden entre si." +msgid "" +"Whether the user will be able to authenticate using a password or not. If " +"disabled, they may still be able to authenticate using other backends, such " +"as Single Sign-On or LDAP." +msgstr "" +"Determina si el usuario podrá autenticarse usando una contraseña. Si está " +"desactivado, el usuario aún podría autenticarse mediante otros métodos, como " +"Single Sign-On o LDAP." + msgid "Password" msgstr "Contraseña" @@ -66,13 +91,26 @@ msgid "Enter the same password as before, for verification." msgstr "" "Introduzca la misma contraseña nuevamente, para poder verificar la misma." +msgid "Password-based authentication" +msgstr "Autenticación basada en contraseñas" + +msgid "Enabled" +msgstr "Activo" + +msgid "Disabled" +msgstr "Inactivo" + msgid "" -"Raw passwords are not stored, so there is no way to see this user’s " -"password, but you can change the password using this form." +"Raw passwords are not stored, so there is no way to see the user’s password." msgstr "" -"El sistema no almacena las contraseñas originales por lo cual no es posible " -"visualizar la contraseña de este usuario, pero puede modificarla usando este formulario." +"Las contraseñas en texto plano no se almacenan, por lo que no se puede ver " +"la contraseña del usuario." + +msgid "" +"Enable password-based authentication for this user by setting a password." +msgstr "" +"Active la autenticación por contraseña para este usuario estableciendo una " +"contraseña." #, python-format msgid "" @@ -102,9 +140,6 @@ msgstr "" msgid "Old password" msgstr "Contraseña antigua" -msgid "Password (again)" -msgstr "Contraseña (de nuevo)" - msgid "algorithm" msgstr "algoritmo" diff --git a/django/contrib/auth/locale/ga/LC_MESSAGES/django.mo b/django/contrib/auth/locale/ga/LC_MESSAGES/django.mo index 3221b186d7cfddf0fe5e445a43f8d304e407d182..84d145198984b06438473fe79a07ef9d19a30428 100644 GIT binary patch literal 9476 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 Pi$S=nJi}FQc&7Llo;Cz` diff --git a/django/contrib/auth/locale/ga/LC_MESSAGES/django.po b/django/contrib/auth/locale/ga/LC_MESSAGES/django.po index a91375aa8f..2d51e6dd28 100644 --- a/django/contrib/auth/locale/ga/LC_MESSAGES/django.po +++ b/django/contrib/auth/locale/ga/LC_MESSAGES/django.po @@ -1,16 +1,17 @@ # This file is distributed under the same license as the Django package. # # Translators: +# Aindriú Mac Giolla Eoin, 2024 # Jannis Leidel , 2011 # Michael Thornhill , 2012,2015 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-09-24 13:46+0200\n" -"PO-Revision-Date: 2017-09-24 14:24+0000\n" -"Last-Translator: Jannis Leidel \n" -"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 08:09+0000\n" +"Last-Translator: Aindriú Mac Giolla Eoin, 2024\n" +"Language-Team: Irish (http://app.transifex.com/django/django/language/ga/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -29,17 +30,28 @@ msgstr "Dáta tábhactach" #, python-format msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Níl %(name)s réad le príomheochair %(key)r ann." + +msgid "Conflicting form data submitted. Please try again." msgstr "" +"Sonraí foirmeacha contrártha curtha isteach. Déan iarracht eile le do thoil." msgid "Password changed successfully." msgstr "Focal faire aithraithe rathúil" +msgid "Password-based authentication was disabled." +msgstr "Díchumasaíodh fíordheimhniú pasfhocal-bhunaithe." + #, python-format msgid "Change password: %s" msgstr "Athraigh focal faire: %s" +#, python-format +msgid "Set password: %s" +msgstr "Socraigh pasfhocal: %s" + msgid "Authentication and Authorization" -msgstr "" +msgstr "Fíordheimhniú agus Údarú" msgid "password" msgstr "focal faire" @@ -48,13 +60,29 @@ msgid "last login" msgstr "logáil deirneach" msgid "No password set." -msgstr "" +msgstr "Uimh pasfhocal socraithe." msgid "Invalid password format or unknown hashing algorithm." -msgstr "" +msgstr "Formáid pasfhocail neamhbhailí nó algartam hashing anaithnid." -msgid "The two password fields didn't match." -msgstr "Níl an dá focla faire comhoiriúnigh" +msgid "Reset password" +msgstr "Athshocraigh pasfhocal" + +msgid "Set password" +msgstr "Socraigh pasfhocal" + +msgid "The two password fields didn’t match." +msgstr "Níorbh ionann an dá réimse pasfhocal." + +msgid "" +"Whether the user will be able to authenticate using a password or not. If " +"disabled, they may still be able to authenticate using other backends, such " +"as Single Sign-On or LDAP." +msgstr "" +"Cé acu an mbeidh an t-úsáideoir in ann a fhíordheimhniú ag baint úsáide as " +"pasfhocal nó nach bhfuil. Má tá sé díchumasaithe, seans go mbeidh siad fós " +"in ann fíordheimhniú a dhéanamh trí úsáid a bhaint as hinnill eile, mar " +"shampla Sign-On Aonair nó LDAP." msgid "Password" msgstr "Focal faire" @@ -64,17 +92,37 @@ msgstr "Focal faire deimhniú" msgid "Enter the same password as before, for verification." msgstr "" +"Cuir isteach an pasfhocal céanna agus a rinneadh roimhe seo, le haghaidh " +"fíorú." + +msgid "Password-based authentication" +msgstr "Fíordheimhniú pasfhocal-bhunaithe" + +msgid "Enabled" +msgstr "Cumasaithe" + +msgid "Disabled" +msgstr "Faoi ​​mhíchumas" msgid "" -"Raw passwords are not stored, so there is no way to see this user's " -"password, but you can change the password using this form." +"Raw passwords are not stored, so there is no way to see the user’s password." msgstr "" +"Ní stóráiltear pasfhocail amh, mar sin níl aon bhealach ann pasfhocal an " +"úsáideora a fheiceáil." + +msgid "" +"Enable password-based authentication for this user by setting a password." +msgstr "" +"Cumasaigh fíordheimhniú pasfhocal-bhunaithe don úsáideoir seo trí phasfhocal " +"a shocrú." #, python-format msgid "" "Please enter a correct %(username)s and password. Note that both fields may " "be case-sensitive." msgstr "" +"Cuir isteach %(username)sagus pasfhocal ceart. Tabhair faoi deara go " +"bhféadfadh an dá réimse a bheith cás-íogair." msgid "This account is inactive." msgstr "Tá an cuntas seo neamhghníomhach." @@ -95,9 +143,6 @@ msgstr "" msgid "Old password" msgstr "Sean-focal faire " -msgid "Password (again)" -msgstr "Focal faire (arís)" - msgid "algorithm" msgstr "algartam" @@ -111,19 +156,19 @@ msgid "hash" msgstr "haiseáil" msgid "variety" -msgstr "" +msgstr "éagsúlacht" msgid "version" -msgstr "" +msgstr "leagan" msgid "memory cost" -msgstr "" +msgstr "costas cuimhne" msgid "time cost" -msgstr "" +msgstr "costas ama" msgid "parallelism" -msgstr "" +msgstr "comhthreomhaireacht" msgid "work factor" msgstr "fachtóir oibre" @@ -131,11 +176,14 @@ msgstr "fachtóir oibre" msgid "checksum" msgstr "suim sheiceála" +msgid "block size" +msgstr "méid bloc" + msgid "name" msgstr "ainm" msgid "content type" -msgstr "" +msgstr "cineál ábhair" msgid "codename" msgstr "Ainm cód" @@ -166,18 +214,22 @@ msgid "" "The groups this user belongs to. A user will get all permissions granted to " "each of their groups." msgstr "" +"Na grúpaí ar leis an úsáideoir seo iad. Gheobhaidh úsáideoir gach cead a " +"thugtar do gach ceann dá ngrúpa." msgid "user permissions" msgstr "ceada úsáideoira" msgid "Specific permissions for this user." -msgstr "" +msgstr "Ceadanna sonracha don úsáideoir seo." msgid "username" msgstr "Ainm úsáideoir" msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." msgstr "" +"Ag teastáil. 150 carachtar nó níos lú. Litreacha, digití agus @/./+/-/_ " +"amháin." msgid "A user with that username already exists." msgstr "In ann do úsáideoir leis an ainm úsáideora." @@ -226,52 +278,73 @@ msgid_plural "" "This password is too short. It must contain at least %(min_length)d " "characters." msgstr[0] "" +"Tá an pasfhocal seo ró-ghearr. Caithfidh %(min_length)d carachtar ar a " +"laghad a bheith ann." msgstr[1] "" +"Tá an pasfhocal seo ró-ghearr. Caithfidh %(min_length)d carachtair ar a " +"laghad a bheith ann." msgstr[2] "" +"Tá an pasfhocal seo ró-ghearr. Caithfidh %(min_length)d carachtair ar a " +"laghad a bheith ann." msgstr[3] "" +"Tá an pasfhocal seo ró-ghearr. Caithfidh %(min_length)d carachtair ar a " +"laghad a bheith ann." msgstr[4] "" +"Tá an pasfhocal seo ró-ghearr. Caithfidh %(min_length)d carachtair ar a " +"laghad a bheith ann." #, python-format msgid "Your password must contain at least %(min_length)d character." msgid_plural "Your password must contain at least %(min_length)d characters." msgstr[0] "" +"Caithfidh %(min_length)d carachtar ar a laghad a bheith i do phasfhocal." msgstr[1] "" +"Caithfidh %(min_length)d carachtair ar a laghad a bheith i do phasfhocal." msgstr[2] "" +"Caithfidh %(min_length)d carachtair ar a laghad a bheith i do phasfhocal." msgstr[3] "" +"Caithfidh %(min_length)d carachtair ar a laghad a bheith i do phasfhocal." msgstr[4] "" +"Caithfidh %(min_length)d carachtair ar a laghad a bheith i do phasfhocal." #, python-format msgid "The password is too similar to the %(verbose_name)s." -msgstr "" +msgstr "Tá an focal faire róchosúil le %(verbose_name)s." -msgid "Your password can't be too similar to your other personal information." +msgid "Your password can’t be too similar to your other personal information." msgstr "" +"Ní féidir le do phasfhocal a bheith róchosúil le d'fhaisnéis phearsanta eile." msgid "This password is too common." -msgstr "" +msgstr "Tá an pasfhocal seo ró-choitianta." -msgid "Your password can't be a commonly used password." +msgid "Your password can’t be a commonly used password." msgstr "" +"Ní féidir le do phasfhocal a bheith ina phasfhocal a úsáidtear go coitianta." msgid "This password is entirely numeric." -msgstr "" +msgstr "Tá an pasfhocal seo go hiomlán uimhriúil." -msgid "Your password can't be entirely numeric." -msgstr "" +msgid "Your password can’t be entirely numeric." +msgstr "Ní féidir le do phasfhocal a bheith uimhriúil go hiomlán." #, python-format msgid "Password reset on %(site_name)s" msgstr "Athshocraigh focal faire ar %(site_name)s" msgid "" -"Enter a valid username. This value may contain only English letters, " -"numbers, and @/./+/-/_ characters." +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." msgstr "" +"Cuir isteach ainm úsáideora bailí. Ní fhéadfaidh an luach seo ach litreacha, " +"uimhreacha, agus @/./+//_ A bheith i gceist leis an luach seo." msgid "" "Enter a valid username. This value may contain only letters, numbers, and " "@/./+/-/_ characters." msgstr "" +"Cuir isteach ainm úsáideora bailí. Seans nach bhfuil sa luach seo ach " +"litreacha, uimhreacha, agus carachtair @/./+/-/_." msgid "Logged out" msgstr "Logáilte amach" @@ -283,16 +356,16 @@ msgid "Password reset sent" msgstr "Pasfhocal athshocrú sheoladh" msgid "Enter new password" -msgstr "" +msgstr "Cuir isteach pasfhocal nua" msgid "Password reset unsuccessful" -msgstr "" +msgstr "Níor éirigh le hathshocrú pasfhocail" msgid "Password reset complete" -msgstr "" +msgstr "Athshocrú pasfhocail críochnaithe" msgid "Password change" -msgstr "" +msgstr "Athrú pasfhocal" msgid "Password change successful" -msgstr "" +msgstr "D'éirigh le hathrú pasfhocal" diff --git a/django/contrib/auth/locale/hsb/LC_MESSAGES/django.mo b/django/contrib/auth/locale/hsb/LC_MESSAGES/django.mo index 5b76e7b43f4c31c925cc86fe422fd984bf6dba0d..ecc53cdd46dc22892bcd66ab7cd9eba7ccd6f182 100644 GIT binary patch delta 3127 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, 2016-2017,2019,2021,2023 +# Michael Wolf , 2016-2017,2019,2021,2023-2024 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-17 03:19-0500\n" -"PO-Revision-Date: 2023-04-25 08:09+0000\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 08:09+0000\n" "Last-Translator: Michael Wolf , " -"2016-2017,2019,2021,2023\n" -"Language-Team: Upper Sorbian (http://www.transifex.com/django/django/" +"2016-2017,2019,2021,2023-2024\n" +"Language-Team: Upper Sorbian (http://app.transifex.com/django/django/" "language/hsb/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -32,13 +32,23 @@ msgstr "Wažne daty" msgid "%(name)s object with primary key %(key)r does not exist." msgstr "Objekt %(name)s z primarnym klučom %(key)r njeeksistuje." +msgid "Conflicting form data submitted. Please try again." +msgstr "Přećiwne formularowe daty zapodate. Prošu spytajće hišće raz." + msgid "Password changed successfully." msgstr "Hesło je so wuspěšnje změniło." +msgid "Password-based authentication was disabled." +msgstr "Awtentifikacija na zakładźe hesła je so znjemóžniła." + #, python-format msgid "Change password: %s" msgstr "Hesło změnić: %s" +#, python-format +msgid "Set password: %s" +msgstr "Nastajene hesło: %s" + msgid "Authentication and Authorization" msgstr "Awtentifikacija a awtorizacija" @@ -54,9 +64,24 @@ msgstr "Žane hesło nastajene." msgid "Invalid password format or unknown hashing algorithm." msgstr "Njepłaćiwy hesłowy format abo njeznaty kontrolny algoritmus." +msgid "Reset password" +msgstr "Hesło wróćo stajić" + +msgid "Set password" +msgstr "Hesło postajić" + msgid "The two password fields didn’t match." msgstr "Dwě heslowej poli sej njewotpowědujetej." +msgid "" +"Whether the user will be able to authenticate using a password or not. If " +"disabled, they may still be able to authenticate using other backends, such " +"as Single Sign-On or LDAP." +msgstr "" +"Hač wužiwar móže z hesłom awtentifikować abo nic. Jeli to je znjemóžnjene, " +"je hišće móžno, z druhimi backendami awtentifikować, na přikład Single Sign-" +"On abo LDAP." + msgid "Password" msgstr "Hesło" @@ -66,12 +91,25 @@ msgstr "Hesłowe wobkrućenje" msgid "Enter the same password as before, for verification." msgstr "Zapodajće samsne hesło kaž do toho, za přepruwowanje." +msgid "Password-based authentication" +msgstr "Awtentifikacija na zakładźe hesła" + +msgid "Enabled" +msgstr "Zmóžnjeny" + +msgid "Disabled" +msgstr "Znjemóžnjeny" + msgid "" -"Raw passwords are not stored, so there is no way to see this user’s " -"password, but you can change the password using this form." +"Raw passwords are not stored, so there is no way to see the user’s password." msgstr "" -"Hrube hesła so njeskładuja, tohodla njeda so hesło tutoho wužwarja widźeć, " -"ale móžeće hesło z pomocu tutoho formulara změnić. " +"Hrube hesła so njeskładuja, tohodla móžnosć njeje, hesło wužiwarja widźeć." + +msgid "" +"Enable password-based authentication for this user by setting a password." +msgstr "" +"Postajće hesło, zo byšće awtentifikaciju na zakładźe hesło za tutoho " +"wužiwarja zmóžnił." #, python-format msgid "" @@ -99,9 +137,6 @@ msgstr "Waše stare hesło je so wopak zapodało. Prošu zapodajće jo hišće r msgid "Old password" msgstr "Stare hesło" -msgid "Password (again)" -msgstr "Hesło (znowa)" - msgid "algorithm" msgstr "algoritmus" diff --git a/django/contrib/auth/locale/sk/LC_MESSAGES/django.mo b/django/contrib/auth/locale/sk/LC_MESSAGES/django.mo index fa6e2e03a0595612b01969ad4e6d3ec606f94d34..c6df60e4e95671480dcfb2df1d223bf940b1f9b6 100644 GIT binary patch delta 3142 zcmajgeT-Dq8OQOnpzRbdv|8;-ORnS z2v$cE(xf&heL{fP0Xxs^%RUKjgxD_z2!G)tH(1J6wV9;&hyH zu`$=I=E+um!c^ zpW?UhHPp&J#&6&RmZ2?Lf=^>7zKAEW10SbXZNKf?R*BK#Z)w)qcM z70M~ZTcK)BU4)wHQq&5UBa=02P|x3i+RM999d5@9&`a+RrdCh`J%sA#5!7=(OV58k zllW`kUvfbmznI?mP5R*LsENFV3fcRp4nIlnpH8oTf$C=}`=yD^LXykOOT7v;ffoE# z6M2NIIRB`b_^+m6FK;Bpb|fn10bGWUp}vgQunQN=Zk#*RfUlw=a11x%Tc`=nBatFp zj4?iejA^FLH70`=b>35@p$X(rGd!3&g8Z3RII#WZ52#3-M6K|jsOL{3Ve@CroI&W#<*|-yz;5~Q%zlUF@_d9u6 z18qXB$e|)v!4f`;T5&U(yA;oCUk_$+>m|3YoW3ERk_lc))Oill}43YEOmuWH<1gqrBpI78q6O*9nRZdB52OUbYN|`Z_KhOPf*YA#U@l~qiS_4sroHhOjWT|<;4c-4b)~TJ7}s3rDm;A zD~v=lSsf%rE7zdf!#k+j0u8DOkSa;hDphW#c2hS}JE$tHROXlbpt0bjtmAkSm2KDh z8wtf1lI$BvVJ1?yP;aC5QNKea4aQ1O+FFx(E$XvfOV!tOrhJ!%BCE2gL2|sC<8tba z8ed6rru=}0vhyzL?de5j^VQT_(sS+Yxuy543!SvJZRBzCBh!w`D;0fVDod$%Qd<-X zmFpXrZ(>*4{(h>^{wpVxa4MUrTay<57iu3|^i=!WFxXM_bFm-v+Z|!KWb-a|HmYPx zejI!GjO{IYF7j+#-eq0C^Mg$7zDcLHWI9 zcBhMMKAmW$)^hPnv%F;NzdrP2G&W>y`LqqKn?2?-cFFXe?_`x-5{=$J?SrQ3T>~DA z(}Eg(+MRx}XtSP80uhI2FJ4b5zW-aNB@{szXY7U@V>4`3U%PC{5t#V@b+)YEhROI@ zmn(QdK5Avpas!qX_c0WE(dYLEZ9RcT+PJQxcXZ38mrb1Ck#{A#)eV$gKB$irT5bEX z_T_CHR*deSalC0+w>MODaZo>Khr(k=e3y5_1(&gXh5F$rCJ912R1Ty1NXhOF!eN)G z`Lq7LW6Q3gpc2;)nXa}Z8M<8*yJ3$3N_N1DiYz-E4vX~>dKd~T$BxuThF$C(JrWN4 z^yd#0T|{Sr@7YMtmcm?EX}p;+y?T|t4%I$vZW-O*e5k3marS%b&VFg!8>V+$hvV+q zY*-BKa5~*g?aDciZR=*#LC=<0E`!+JVYcjc`^SD^Bjz@KvSBi(u+;{x5FR~J2sPcv zl|lk`D7i=60I$yV~`M9-G$FXiYsiD3O;q)x{zH)A^rTHE*#k9%Y+7^F{JKS>by qz4MIX2ld~Qb0sgXkLFt~Q6V%#WfF@BoSTQP=w-u3Dy~{EI`O~IE@IsP delta 2211 zcmY+^TWnNC9LMqLjf>FA9V`eVg6+ZrrQBNR1&|_FEzyuh4dk>Oy4!a5G<&O5bS0V? zQA1>d2?P*=#z2A*mKS*_#AP2OF=7ls2ocZ+F-VM2BZ?1xf7^qJlm5?V&e_>HGynN- z54YTHOn*0~bf2MZBBl@@78?`6U>O(M%^}9r;Vleczdc24(mJTyU zQ*_~0?8V)93CG|I!;M*JOxi^0Jj{b*xCpcO5dMTC@ppU#i+DH+C!?MRk-1F0|9mBC zo@cQVJ8&w#isSJRR$vw<;^#Px_nT{Uw3EMaGFFT*hCeflOF1saEw~Eb!(+G_7qN=R zaVI)>1lf@(=1Wz$1hw$3I30JOGJFsZ<7c>n_nS7BRf`937Ji9q@E-2O6>N*_n*k&l zCXcMue1*!uHQyglnfV!6qxlPYhbbd%8b20wBvVoI&A@aio!S0?8sBB87p+E3)QTGS zqJQt8UK~M9obsRVLXCSDwUE8YpZS1`=KB=&`C0$@xl!a_6J6qgR(2JsA9KU^N7Mp- z!3#yk+{dNdpQnNv@jmK|>p8#C*oMzz7q(#DzaKGfaL3y*&hrQ+@YXo;<0r3Ym*t zsQdk>7o0>b;EwN~IEnj`34_Hn1+~-Js14MiQr?96-Uj5)v~f`_c*q{iTgd5{18F*{ z))S~A$)g6|#z(Q3Qq@^mq#R5Y_TgeYj-TLD*v6`A@CZimYt)9Cnd}LSqKbPT&cstV z8`D?l)REc}RU8!ssGTfB{jS%eGO)$}ya$!h zKGYGtjmp>|J;9JzrZXgLWGl*4$vZf3yCe)Nx zEmV!6g{C725X%d994l&0y}z(Ks~egYvVu^`HV_L5HT~mwtk5%t;w`iwS7mA?q0~P^ zG!fOrEJAG)v5ruNrV;go+A`v4Lhmm$6^{yI>ELbQ?A2XBP$Gp)=w3fh6{=D>k61)J zXsvXV+B%|y(0S`f9yDszEFn}+eoGgsw~;&Q%d98#^VmqV5Y5DsgpNbitX50t7#_3+ zzoS}EQ*r7T*An{oJcm%L(q(3K)QPx(xb@n*+>V6p%Um4#X6B7yzm~N`oN!O}^6=|L zL#v%mCmaoAJ|1y3b8+P9&EdFB#@*QWukDZ9UMC*!^J3eAwmq4!JG`XraH6&&CO-EiR-=;jwg~`4B%UFuif^0?J=i6od3v%3U5i~2XZG< zPQtw~;LNofb7%No!nGmKrt(LfZrdMmqZ-{C@FHFZ$@+gfypWgh3JFQFxR_H&%e~5V P+2rJd#o4=4PnG-&;8rw- diff --git a/django/contrib/auth/locale/sk/LC_MESSAGES/django.po b/django/contrib/auth/locale/sk/LC_MESSAGES/django.po index 63483a7ac1..dfa64b7b25 100644 --- a/django/contrib/auth/locale/sk/LC_MESSAGES/django.po +++ b/django/contrib/auth/locale/sk/LC_MESSAGES/django.po @@ -1,7 +1,7 @@ # This file is distributed under the same license as the Django package. # # Translators: -# Adam Zahradník, 2023 +# Adam Zahradník, 2023-2024 # Jannis Leidel , 2011 # 18f25ad6fa9930fc67cb11aca9d16a27, 2012-2014 # Marian Andre , 2015,2017 @@ -12,9 +12,9 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-17 03:19-0500\n" -"PO-Revision-Date: 2023-12-04 08:09+0000\n" -"Last-Translator: Martin Tóth , 2017-2018,2023\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 08:09+0000\n" +"Last-Translator: Adam Zahradník, 2023-2024\n" "Language-Team: Slovak (http://app.transifex.com/django/django/language/sk/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -36,13 +36,23 @@ msgstr "Dôležité dátumy" msgid "%(name)s object with primary key %(key)r does not exist." msgstr "Objekt %(name)s s primárnym kľúčom %(key)r neexistuje." +msgid "Conflicting form data submitted. Please try again." +msgstr "Neplatná požiadavka. Skúste to prosím znova." + msgid "Password changed successfully." msgstr "Heslo úspešne zmenené." +msgid "Password-based authentication was disabled." +msgstr "Prihlasovanie pomocou hesla bolo vypnuté." + #, python-format msgid "Change password: %s" msgstr "Zmeniť heslo: %s" +#, python-format +msgid "Set password: %s" +msgstr "Nastaviť heslo: %s" + msgid "Authentication and Authorization" msgstr "Autentifikácia a autorizácia" @@ -58,9 +68,24 @@ msgstr "Žiadne heslo." msgid "Invalid password format or unknown hashing algorithm." msgstr "Neplatný formát hesla alebo neznámy hašovací algoritmus." +msgid "Reset password" +msgstr "Obnoviť heslo" + +msgid "Set password" +msgstr "Nastaviť heslo" + msgid "The two password fields didn’t match." msgstr "Heslo a jeho potvrdenie sa nezhodujú." +msgid "" +"Whether the user will be able to authenticate using a password or not. If " +"disabled, they may still be able to authenticate using other backends, such " +"as Single Sign-On or LDAP." +msgstr "" +"Určuje, či sa bude používateľ môcť prihlásiť pomocou hesla. Ak je " +"prihlasovanie pomocou hesla vypnuté, stále sa bude môcť vedieť prihlásiť " +"pomocou iných metód, ako napríklad Single Sign-On alebo LDAP." + msgid "Password" msgstr "Heslo" @@ -70,13 +95,25 @@ msgstr "Potvrdenie hesla" msgid "Enter the same password as before, for verification." msgstr "Kvôli overeniu, znovu zadajte rovnaké heslo." +msgid "Password-based authentication" +msgstr "Prihlasovanie pomocou hesla" + +msgid "Enabled" +msgstr "Povolené" + +msgid "Disabled" +msgstr "Vypnuté" + msgid "" -"Raw passwords are not stored, so there is no way to see this user’s " -"password, but you can change the password using this form." +"Raw passwords are not stored, so there is no way to see the user’s password." msgstr "" -"Heslá v pôvodnom tvare nie sú ukladané, takže neexistuje spôsob zobraziť " -"heslo užívateľa. Môžete ho však zmeniť pomocou tohoto " -"formulára." +"Nie je možné zobraziť si používateľovo heslo, nakoľko sa samotné heslá " +"neukladajú." + +msgid "" +"Enable password-based authentication for this user by setting a password." +msgstr "" +"Nastavením hesla povolíte používateľovi prihlasovanie sa pomocou hesla." #, python-format msgid "" @@ -104,9 +141,6 @@ msgstr "Nezadali ste správne svoje staré heslo. Napíšte ho znovu, prosím." msgid "Old password" msgstr "Staré heslo" -msgid "Password (again)" -msgstr "Heslo (znova)" - msgid "algorithm" msgstr "algoritmus" diff --git a/django/contrib/auth/locale/ug/LC_MESSAGES/django.mo b/django/contrib/auth/locale/ug/LC_MESSAGES/django.mo index 2228f92e68f0fdd1a33077bc8b2ae2e425c845e1..481d10ada0b6b6730ec6906ab00784f46fd20608 100644 GIT binary patch delta 3412 zcma)+eQZ_b9mk(mOL><`fTQr%xyCGpZ^B#P1$Z5t zGtZa}umZAVn&Eu72Ufs#xCnkPSU(D7_$N^3C*X2;27Vs?9xhd=mzgYNVK&;Xhu6a! z;5w)Xo8b!B2CHBiu7NK>j+$S?1@I!=3;zu7huc`Z3;qB~zYFsYVeit5uv*14< z$u|FnX{B-w`BtjR16DzKdJ|NH^$=&xW~lx5LDlkMD203BwJ;ide=J}Rl%YdVdPbr4 zJr}&cxS0IQ@Hh)nd@A_xda&_4lp}9LrObm;cq#b)QLz3`C_QtjmmFIHX)aR{a3z!j zHSqBw`UpP4`>AsBzmdtprTLmR!IixCzyy3Az5`1?XG|}=2uENujp925<=`ba3_phD zFulx}XW+B&by!UuSHbt7ZpAD*5!I$M&EyD^KBy*J!~^F{EmY071Z)e|hoCa`LnudI zh6><3R1Xx>AnKV$7=n9Y13UtE!t-!5te}(Coax<6YMJ~LZh`MWf;0=cBLrir;VWMSq9t?pa^V|Bx0yY#9qx^SdFzn+Ksvl7jT1NeAyo1HKe+ z0!m*N%E7a+4*TW;6S8hfYx0JxA-2s%sP!cs3!c#3}rRfAP*t;Ag#!k5&Et$nuFQqfa)LB_)cU~ zuqNDwC}SEs^YEV!^Q=c2WM4I#8M~QqlguvUtHI)WNQKOn;JqZ^m1w!*WgBzdAa0s} zHS1t0qOm#;zmLAgyhf?e*pP?+lh_{29}Fm{G1UwFPyF!!&ppAsIP>nTAJyHNi0|u+ zwWVV5cDpap-DM+A%CX6wa91pqibg`Vr8DXzqc+vuYn^r{77t~DZtj$Tq5^<@wsg79E_9Ua-Hr#8I(Ufo3 zDI5$1nj+c6>^~M|zA^W=J3dXNY5BCT_JEVLk-*VVre@yMlBjR{{X;J#3nnx5^P6fP zh~i6O$+Z5jmyNbMnLRlF-JF9RiVW)RXyXqKfOLW~)YwOn6)vx7oOLl+R zuZq&g-Er>?cPcmRPP%8A4_Wus+?abZ_f&4o8?bIxYurU`(GGx6z4vxC0M+c{e-0|rXA>&TuhOK*yvr}jqb2Fpmi?X|x zoGz-G9zuD)7TJ5!8!_&&+%w*Q`!jYO&%9M>)12}Kv6ma0K7q$$vUW_?ygt6v^*cF(fUk0>`BGFPwRgYQmeVre9MaOrEs*`{S5 z7qx#j8$|Kh9kN&EU|QY|g)$Ax{}P%}qGI&nk4iF_kIenPRrRJ%XqlKud*-nf%UAN< z53fHrL}ir*@<#M3;V79H&TOd6l=#kN-mIuxQ*gA9Ua$X?)^tbSs{B`R=69>gGwBs2 z>6vU_RfSK=w1QC8XI#ONK{;Z*QFTy=gi={fx|3HW!p*Wol*i~X#W=|UrACEx$J6vzCu)k{~ws%bcj(`@3f ddPujeU`8HP@#wp%wOEjUYUI)Exf}ME{0A4RoJ0Ts delta 2262 zcmY+^eN0tl9Ki7h+@l>46b zt__rhn@}d+Rmo$zK>A8zvPX7nneC(qA>U+;$P&RN2 zpNvrIAAFAMDk^9Vp2Ix6f%oBD-s2T4#!mF5DAkKWlnupD2uCm#Kf%yk@}EVgCUvT6 z526&yZ`hAfREpHZF_aoPhw?5*J+FJ?v(lzAF&`OHOHnpdhO$uu%kd;iO-$kgcsod^ zgw9e%

&Bh89YZ{ekR7t)Zl4;%)doHsE41lFaT7b6rej$?w0wk1>70)VyP!u^fd5 z8Lz3oAbade?lwV0`=&g}u*$MtoLW5F68OH$cP8px{Ji|kPyML7*0 z;5~R1C6m`sHvSh%CTDY#yz)GxzJqEd9hqn&N>%PaUZ<+YCD@9x;0a`JY5=9^K1aFl zEARSe&s&~%Q0DXTer1F4ScprIq^PGcMb3W*9XYRuyf224?5eL(p5P|Rf-|zGewc_P z!mXPM+)QxN)G9)n6eMreZ6wug@*ugyL+%y-BTzOc>${U{xuD6;$_Xj9M~Rh$H2KFt z=G`XQl9o@%vD!dLCY~VH6FI~(LYmaXRzgmfWUqvfww8FDkoDbGz$XvpR;vt1u}E7% zNcy7Wf+ok4SLtR*3aE&fZdG(7W2=c7gw%l?-{~fGP)t-#56JotbFq$);&_DMh^xnl zO+*>7k)TlA;{xtGOpuP(N0&cZ~`-)X|PQYmL=eFtQU5);lcHLoK zj_xtLX8rEl)MPZgXnh+q5fPnZ)ENzdTr(8sn3v-(Jk`*qcenXle|+^sn{F}M+B%wB zU&zkfjV7k==xTF?Yc!T?_0FKy`HIRn_HVo zmmBNN!wFj~U*bfBbu4N2jF^{<_IzDfP`JVxOa3y#d{d`cI`v{iygd*;;&j>P!pH4F zGb_E;jE&8=veWw_6LgNV-wru__MjcgwN7V5Mw%&^la)~$u z{P+-;U0m8{WQn_{7ziI{A!fb%vF$VA9&MlH35LRNa7&jwzIG?I2iVuJOlS`>@reF^ v_ulv6^ltmY_z*un&x7z|qR)M>3+B#+rukiJnwgX~(|SfvL|QFbjlO>Y0wRYw diff --git a/django/contrib/auth/locale/ug/LC_MESSAGES/django.po b/django/contrib/auth/locale/ug/LC_MESSAGES/django.po index ef15de3fd3..e231cc2c3f 100644 --- a/django/contrib/auth/locale/ug/LC_MESSAGES/django.po +++ b/django/contrib/auth/locale/ug/LC_MESSAGES/django.po @@ -1,16 +1,16 @@ # This file is distributed under the same license as the Django package. # # Translators: -# Abduqadir Abliz , 2023 +# Abduqadir Abliz , 2023-2024 # Azat, 2023 # Murat Orhun , 2023 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-17 03:19-0500\n" -"PO-Revision-Date: 2023-12-04 08:09+0000\n" -"Last-Translator: Azat, 2023\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 08:09+0000\n" +"Last-Translator: Abduqadir Abliz , 2023-2024\n" "Language-Team: Uyghur (http://app.transifex.com/django/django/language/ug/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -31,13 +31,23 @@ msgstr "مۇھىم چېسلا" msgid "%(name)s object with primary key %(key)r does not exist." msgstr "%(key)r ئاساسىي ئاچقۇچى بار %(name)s ئوبيېكت مەۋجۇت ئەمەس." +msgid "Conflicting form data submitted. Please try again." +msgstr "تاپشۇرغان جەدۋەل سانلىق مەلۇماتىدا توقۇنۇش بار. قايتا سىناڭ." + msgid "Password changed successfully." msgstr "پارول مۇۋەپپەقىيەتلىك ئۆزگەرتىلدى." +msgid "Password-based authentication was disabled." +msgstr "ئىم ئاساسىدىكى دەلىللەش چەكلەنگەن." + #, python-format msgid "Change password: %s" msgstr "پارول ئۆزگەرتىش: %s" +#, python-format +msgid "Set password: %s" +msgstr "ئىم تەڭشەك %s" + msgid "Authentication and Authorization" msgstr "دەلىللەش ۋە ھوقۇق بېرىش" @@ -54,9 +64,24 @@ msgid "Invalid password format or unknown hashing algorithm." msgstr "" "ئىناۋەتسىز پارول پىچىمى ياكى يوچۇن مۇكەممەللىكىنى تەكشۈرۈش ھېسابلاش ئۇسۇلى." +msgid "Reset password" +msgstr "ئىم ئەسلىگە قايتۇر" + +msgid "Set password" +msgstr "ئىم تەڭشەك" + msgid "The two password fields didn’t match." msgstr "ئىككى پارول بۆلىكى ماس كەلمىدى." +msgid "" +"Whether the user will be able to authenticate using a password or not. If " +"disabled, they may still be able to authenticate using other backends, such " +"as Single Sign-On or LDAP." +msgstr "" +"ئىشلەتكۈچى ئىم ئارقىلىق دەلىللەشنى ئىشلىتەلەمدۇ يوق. ئەگەر چەكلەنسە، ئۇلار " +"يەنىلا باشقا ئارقا ئۇچ پىروگراممىسى يەنى يەككە تىزىمغا كىرىش ياكى LDAP " +"ئارقىلىق دەلىللىيەلەيدۇ." + msgid "Password" msgstr "پارول" @@ -66,13 +91,23 @@ msgstr "پارول جەزملەش" msgid "Enter the same password as before, for verification." msgstr "دەلىللەش ئۈچۈن، ئىلگىرىكى ئوخشاش ئىمنى قايتا كىرگۈزۈڭ." +msgid "Password-based authentication" +msgstr "ئىم ئاساسىدىكى دەلىللەش" + +msgid "Enabled" +msgstr "قوزغىتىلدى" + +msgid "Disabled" +msgstr "چەكلەندى" + msgid "" -"Raw passwords are not stored, so there is no way to see this user’s " -"password, but you can change the password using this form." +"Raw passwords are not stored, so there is no way to see the user’s password." +msgstr "ئەسلى ئىم ساقلانمىدى، شۇڭلاشقا ئىشلەتكۈچى ئىمنى كۆرسىتەلمەيدۇ." + +msgid "" +"Enable password-based authentication for this user by setting a password." msgstr "" -"ئەسلى پارول سىستېمىغا ساقلانمايدۇ، شۇڭلاشقا بۇ ئىشلەتكۈچى ئىشلەتكەن پارولىنى " -"كۆرگىلى بولمايدۇ، ئەمما بۇ جەدۋەل نى ئىشلىتىپ پارولنى " -"ئۆزگەرتەلەيسىز." +"بۇ ئىشلەتكۈچىگە ئىم تەڭشەش ئارقىلىق ئىم ئاساسىدىكى دەلىللەشنى قوزغىتىدۇ." #, python-format msgid "" @@ -100,9 +135,6 @@ msgstr "كونا پارولنى توغرا كىرگۈزمىدىڭىز. قايت msgid "Old password" msgstr "كونا پارول" -msgid "Password (again)" -msgstr "پارول (قايتا)" - msgid "algorithm" msgstr "ئالگورىزىم" diff --git a/django/contrib/auth/locale/zh_Hans/LC_MESSAGES/django.mo b/django/contrib/auth/locale/zh_Hans/LC_MESSAGES/django.mo index d4d2485b3ae0a6e7d0218e2cea750175c3b8ba8b..5622927c4441da9beeaba2d182406e1d10178379 100644 GIT binary patch delta 2978 zcmajfd2AF_9Ki8ct`;a)xr%~JLC`{3pxl?pQKVXE0R<$8Zri1-v|H2NiUh+JWY&v5$9kUuETM71s&L_ zty0{oe3T|vV=}Hon)0eIxp|$8Z*Vh?Zl_cXp2v}R89QOy_DYSyUPzWo#b{iFy)X+q z;~Jg64W;7>l=_wU1lHqI_%(Kysov(MBN8Jpuoy{ok?ae2W5bN;Y5t;5zbG-w|P#%*YEVBKCcWw& zH}ZMKa!JOKSd6Q22zKDeO9K<|XoYwzoA!7votb; zkWZ*D(T=#EWB~Hb+K5@ia6=X(sP9Dc?vOwkd#2k&r5!2vj38%6BCKS zvj37^AUMF*i64NnO!J8siFw2rf=M=~RDCyDI~3)!okmR3dBOxj4x6MoVXW&yuJRd< zlm2Bd?x$C|;oPYO#7jDJ7(Popub<@y^KeRgAVaP zvJ{d=g|SX}lD?PE?tbdX4aY)087s}@x=7!*@Lg+Do;WSnwKUtA;c>dMjHS7GIYy@4 zV>jIS={Zi1$B}6>(y|?Px5Mz{tu*XecBjkcdnfYt8`GU`dwRAbQzhlto!KhMB~Qj% zcDH*)ZeHe)bgE<;_I%GWhs)#4uzQ@jE@|HIEOWYze77UdNMC8V9UiM+dvisbZYi@i zH|qNc-{N*(&3s&wD(!Kl#tOUJ$kYS1`QqDu+|^vP9_v?(^%om&Nk8=hP4o$+y^HwZ^-)oGf#u1aOHYzM)K0; z5hh4mD~%jG3*-5}#)f4XxmN$__Kf8YSEf6GJx}>L+=~L2b z=XdPfGAhNEU?dJp99f&+WqHJ?ttI}31HrO&p?#HRQE8y`c%Z1-tlDXoSDG761dpt_ zS+F)#Q)g}{3e}YQ>k9(M_L1Ye9#b{{(3;@(N)_CG(yS_JT3hXJJf)fn%0lNhhN{n+ z)n#VQhTz^c{`!VM)d5}%Y^pO$YPc~g8vG5#;Zo_h`aq~gdQstGUx#jkYtMIG72!+m z{?V9+UT!+Fg_qSMbIrOFL2F1dzI)x5k1eh+4;S7aMUnq>S!n-Jb8RJ)yLEbtxqC0; z3Vg6PP+JtIH+l3QSeN4xVBjK$x$!{2z!-&kaBt)cF}s;@sqsaaAS jJX-T$BU0;ZA?>hd>`E|tSEIT9U|`b@Ynwld9ogbldTi zc?!p1A&$pwI2;dQ3WjhbeuWcwzPUm{Bl#Q0VoI_x{LEAi12G$4#5{Zl591Qdq8F2} z3SDeMMr0DW=>eRB>i8O*h+9!J+<+h88O-JR<{7$`i3f2iUcg83HdbLS!(#T$7szCo zuaUl*?@=>w#d-rZGruE!Gc~FiXBs)Ey_2ZFpSATJgPDIdbdd`6>@u=`%r$Ea)q!qw zJ;wZln&Q>0AkEZ1WRRvE@4*YU{u*X;-kcT z!jtyA9W_-qQ6spGx;}vw#WTzhRDCMyx*4`U8`aJ-d%gnC_0 zerN0dKs9Ve^fZ`+Pjfm9_o5HAM(&{Q-^|i}9P3dt6h^f-XjD%JW+Fecl!F#~U@e7Z z6sqt+{04R7Eu4%KSi;)Zc{m@pp*nQN`Xy=xzO`OLjr=ETr}azK(*7UU zQ!tMG!(>zg)2wrCeZDI=e278YYRD~;$AYB zWPzHMU??(BOrF~7w1Z4CX;@2V$hid*FR{At0Dk}n6(5BPMIuiU9D z_m*9+K2Yv#a?8uNl$O1e?yRer!@9E-HR7unGgX=sUs+G1^u;nS_%=k`S2Z;G}yNB1{HL-nzSHzT`FcAhvA zt80nw`aE`UXC&Ujjp`k-ou@jh_k`P, 2012 # Lele Long , 2011,2015 # Liping Wang , 2016-2017 +# L., 2024 # mozillazg , 2016 # Lemon Li , 2012-2013 # Wentao Han , 2020 @@ -22,9 +23,9 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-17 03:19-0500\n" -"PO-Revision-Date: 2023-12-04 08:09+0000\n" -"Last-Translator: Kaiqi Zhu, 2023\n" +"POT-Creation-Date: 2024-05-22 11:46-0300\n" +"PO-Revision-Date: 2024-10-07 08:09+0000\n" +"Last-Translator: L., 2024\n" "Language-Team: Chinese (China) (http://app.transifex.com/django/django/" "language/zh_CN/)\n" "MIME-Version: 1.0\n" @@ -46,13 +47,23 @@ msgstr "重要日期" msgid "%(name)s object with primary key %(key)r does not exist." msgstr "具有主键 %(key)r 的对象 %(name)s 不存在。" +msgid "Conflicting form data submitted. Please try again." +msgstr "提交的表单数据存在冲突。请再试一次。" + msgid "Password changed successfully." msgstr "密码修改成功。" +msgid "Password-based authentication was disabled." +msgstr "基于密码的验证已禁用。" + #, python-format msgid "Change password: %s" msgstr "修改密码:%s" +#, python-format +msgid "Set password: %s" +msgstr "设置密码: %s" + msgid "Authentication and Authorization" msgstr "认证和授权" @@ -68,9 +79,23 @@ msgstr "密码未设置。" msgid "Invalid password format or unknown hashing algorithm." msgstr "不可用的密码格式或未知的哈希算法。" +msgid "Reset password" +msgstr "重置密码" + +msgid "Set password" +msgstr "设置密码" + msgid "The two password fields didn’t match." msgstr "输入的两个密码不一致。" +msgid "" +"Whether the user will be able to authenticate using a password or not. If " +"disabled, they may still be able to authenticate using other backends, such " +"as Single Sign-On or LDAP." +msgstr "" +"用户是否能够使用密码进行认证。如果禁用,他们仍可能能够使用其他后端进行认证," +"例如单一登入或LDAP。" + msgid "Password" msgstr "密码" @@ -80,12 +105,22 @@ msgstr "密码确认" msgid "Enter the same password as before, for verification." msgstr "为了校验,请输入与上面相同的密码。" +msgid "Password-based authentication" +msgstr "基于密码的验证" + +msgid "Enabled" +msgstr "启用" + +msgid "Disabled" +msgstr "禁用" + msgid "" -"Raw passwords are not stored, so there is no way to see this user’s " -"password, but you can change the password using this form." -msgstr "" -"密码原文未存储在系统中,因此无法看到该用户的密码。然而你可以通过这个表单来修改密码。" +"Raw passwords are not stored, so there is no way to see the user’s password." +msgstr "原始密码不会被储存,因此无法查看用户的密码。" + +msgid "" +"Enable password-based authentication for this user by setting a password." +msgstr "通过设定密码为此用户启用基于密码的认证。" #, python-format msgid "" @@ -111,9 +146,6 @@ msgstr "你的旧密码不正确。请重新输入。" msgid "Old password" msgstr "旧密码" -msgid "Password (again)" -msgstr "密码(重复)" - msgid "algorithm" msgstr "算法" diff --git a/django/contrib/contenttypes/locale/ga/LC_MESSAGES/django.mo b/django/contrib/contenttypes/locale/ga/LC_MESSAGES/django.mo index 6b0363a86851977e2bdbbc9640c086784b167ea8..4b96fe58d006e767267a42f433ed29fa83d63c28 100644 GIT binary patch delta 366 zcmYk$F-yZh6bJB2Q#BMFEJ6nnPEe?5XuL+S!NGzeg5A28YZ9B2G%1%Wjw)`7P|4&X zI64cW4qYd8tUqGWr#WuhX-i*SWl60a!pVCo_nF;4dNT zRabQ)-uE{W8h6ipS0&Voqp!<{`_GOJ(x&$2)=kScnN7DF4r7}ZPU(av%4|y>B_UU_ zbZApVo)p;!ZE=?#i8u^7J&Z-PMVZBHypMWA-t*12&-)HNmLdsgHBf5c)M|V%csVT; hwX)2fxyR|htO@Xv0kmdo>^*|aV-vgw@f%GgOJspTQ z0kJud@5Kz%1EiaPv;~l!3ZyN8^f@3c2&6e!Ao5Z`S{lgL1=2vR3_!|`ffdML2VxLl z17e^aFkk|b98flcsz!22d|qO1s%Ei5eo|Iya!Ij5N`9XD#K-ZB>XTg=clcQ98kp%C z87UYUTA5gA8vp^9PhxS2Zb(sLUU5!hNq&))f=_97s)AEaVqR*cf=vlXA~P+u!XXDJ zoCFrtOU~CT&9<9t&m_lOUS7UAfr*7t9L4U;q|C(RjFQB|YbTd6D^7mGEX=8p4;7re Hj=38Ez1T$v diff --git a/django/contrib/contenttypes/locale/ga/LC_MESSAGES/django.po b/django/contrib/contenttypes/locale/ga/LC_MESSAGES/django.po index 864119019b..40229fc763 100644 --- a/django/contrib/contenttypes/locale/ga/LC_MESSAGES/django.po +++ b/django/contrib/contenttypes/locale/ga/LC_MESSAGES/django.po @@ -1,6 +1,7 @@ # This file is distributed under the same license as the Django package. # # Translators: +# Aindriú Mac Giolla Eoin, 2024 # Jannis Leidel , 2011 # Luke Blaney , 2019 # Michael Thornhill , 2012 @@ -8,10 +9,10 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-01-17 11:07+0100\n" -"PO-Revision-Date: 2019-06-22 21:48+0000\n" -"Last-Translator: Luke Blaney \n" -"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2024-10-07 19:22+0000\n" +"Last-Translator: Aindriú Mac Giolla Eoin, 2024\n" +"Language-Team: Irish (http://app.transifex.com/django/django/language/ga/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -36,9 +37,9 @@ msgid "Content type %(ct_id)s object has no associated model" msgstr "Ní bhaineann samhail leis an cineál inneachar %(ct_id)s" #, python-format -msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" -msgstr "Níl cineál inneachar %(ct_id)s oibiacht %(obj_id)s ann" +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Níl cineál ábhair %(ct_id)s réad %(obj_id)s ann" #, python-format -msgid "%(ct_name)s objects don't have a get_absolute_url() method" -msgstr "Níl modh get_absolute_url() ag %(ct_name)s oibiachtaí" +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Níl modh get_absolute_url() ag réada %(ct_name)s" diff --git a/django/contrib/flatpages/locale/ga/LC_MESSAGES/django.mo b/django/contrib/flatpages/locale/ga/LC_MESSAGES/django.mo index 8e80c1071e317e93685b8284578e39b60030b266..fdb167784da0f75b2f0b709b7b6d4366a723efaf 100644 GIT binary patch delta 1050 zcmajczfTlF6bJA*?l}Cd93U2muQ0)w`vJ!_LNviZ2nCv8Vr4>x+qvC|bGw(FSr7{E zOl*zC#uyVVEG#Gp1(n2Z{{Xcz@dw3K7KX~i!p83$USS|{a#PNxH9{I8_pynk=?Pk!jBGnIBN6A zu>VB)-`y@oAt$#Q$q@O6lx&g~0bx|LmEx2sb@xw;A7^u&Ykr>n emb#*_(0HK$KI77_+YLrYRFrH=hhgXluGk-rj0#l% delta 851 zcmZXQJ#5oJ6vr=aLLop)BJm+w;7JTd1t(5uRd6GOXe9_ODj)3x%O!E*1ILc+3t13l z>%f3S#K4%bsC=nRK>`UguoQ`r0Y;EmSXhzxpQB13p8W22@9z1%|Gnqg2bq+nPHQUVL?1-J)%3C@G>z$Q4NF_s4JfEKt4o>%wa4KO{#7(Uj(as<2u5_lgR z2G_w+##Y!XYj;T4>J0Plhaw+)0o24@gI z0X^^=XoJh>iW2NKsDp383G`>*u~7oD+XqU=!4bqI5DM8mcmTW(swqhjzpzyhdg5Gw z?SiXGW#FnFu4BVM7&OEN?Xjtcs#?s1t5+&h>b6WZ*a=qx{;2OMv_rHNrh9^)MR%vxqtQ|_dK*) zutm*wsdO_A&$@A#6JFgvlV0Fnqs<$(v1Ie6Mdd(*4jpr(Y+3nyr_<>kP5oM?|DHv2 z(Hi%tDm+ix)bOd|)Z44voEZL+7(;4P, 2011 # Michael Thornhill , 2011-2012,2015 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-10-09 17:42+0200\n" -"PO-Revision-Date: 2017-09-23 18:54+0000\n" -"Last-Translator: Jannis Leidel \n" -"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2024-10-07 19:03+0000\n" +"Last-Translator: Aindriú Mac Giolla Eoin, 2024\n" +"Language-Team: Irish (http://app.transifex.com/django/django/language/ga/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -28,9 +29,9 @@ msgid "URL" msgstr "URL" msgid "" -"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." msgstr "" -"Sampla '/about/contact/' Déan cinnte go bhfuil príomhslaid agus cúlslais " +"Sampla: “/ faoi/teagmháil/”. Bí cinnte go bhfuil slais tosaigh agus slaise " "agat." msgid "" @@ -40,6 +41,9 @@ msgstr "" "Ní mór an luach a bhfuil ach litreacha, uimhreacha, poncanna, béim, dashes, " "slaiseanna nó thilde." +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Sampla: “/ faoi/teagmháil”. Bí cinnte go bhfuil slais tosaigh." + msgid "URL is missing a leading slash." msgstr "Tá slais tosaigh in easnamh ag an URL." @@ -63,11 +67,11 @@ msgid "template name" msgstr "ainm an teimpléid" msgid "" -"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " -"will use 'flatpages/default.html'." +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." msgstr "" -"Sampla: 'flatpages/contact_page.html'. Muna bhfuil sé ar soláthair, bainfidh " -"an córás úsáid as 'flatpages/default.html'." +"Sampla: “flatpages/contact_page.html”. Mura gcuirtear é seo ar fáil, " +"úsáidfidh an córas “flatpages/default.html”." msgid "registration required" msgstr "clárúchán riachtanach" @@ -78,7 +82,7 @@ msgstr "" "leathanach seo a fheiceail" msgid "sites" -msgstr "" +msgstr "láithreáin" msgid "flat page" msgstr "leacleathanach" diff --git a/django/contrib/gis/locale/ga/LC_MESSAGES/django.mo b/django/contrib/gis/locale/ga/LC_MESSAGES/django.mo index 846f0d559c58ebd84939fd3163c9e3171f11f3c9..ea862555505dd80335ccf4e096d9e219d40d8ad7 100644 GIT binary patch delta 1110 zcmYk3OK4L;6ow~F)jrf}wLb8{X^YaT32BWY0T(rGL$Os%Ds)qEax=Xdn9L1xZ~AbP zE)^^;q6=}Ag$oyP<3`WIe84z`p(2=I-@zsD2RI6*x)?hI-T{w*28@Ca+WxJ!zYZRS|25bTeggM_U%`Xm z&z8T+{$Ozojviz=0S<$^z^mXMFb(bnueZ;aKr0{s=fV5n7Q}r4m$7#cd=7jM+I+vj z<6zJ3me3K<#-9a8SQQmvF$~8tH~>~btN0N(2tEV*z?YyE`UV^YKZE$#Z%jSlUvNLT z8>;QYL!hm60_0#CgwAGBwiC7}cGpg@0~j{g3b4tn0Q+b!1{%~fE5=%P3(YRsB?@o; zzP7vhs1;_bJY1WJEN7=hzT&!4yR;^C!CRv-Ul_@iyeA5@%2h>-vuUA3Ac!kPvw{Z| zBYZZq9ta)KlxkZ!YhfuY_tw&d-E}sc-g1GqX2O?%R<|*Tv<4BMLIl?o~8_fdYe(f zMp@L>yDs03WyPxWaTuG1)D%r7CN9Pj$=GC)Ca$ECm(C|(ee=*9TQpqziU*!a(G)sj zWcZdAxI-D~DaC2VlllS@OeSlI=;yI9w{shTfkhPEann=lJ-hP>6KJi*S51P-SYE*Q@+Th zf;P4oHoP*gHM&1mJ7KNnvm0SUkuPwqAZ+^`v(DALr_r&wT%1j5vK!NRdgm$I rcBtdVcfz_y=Q6Bh}< delta 544 zcmZ9{&r1S96bJBG*UGdK4N9?MDzbyD?3!9iR8-Ipq{2LSFvm5F^M5WD7Zp>>%yf z<_Iam9ca(rz%lp;$KfmV!7n%re_#Oq_T~dFLPDq~VFadOAI!r6LYkzAk1!^V;S+wk zfF;x^cekMhXHeh4Y4`&D@Eh8VJ1_`6IMoXy&~6xovv3vm!!q>1T5sKe9NFqF+OM|{ zLvMofoWSjz7{Z9XP7GqSUuhr2J2Ty;#CqpS)}`w?bf}(H>6}g#Lz_3L&Z>%GGM!bd zH$L4g2pc++O{K00o3hEWG$Bfhf+z`6hDzydG7}ReQS=_{3wd^~82|TWgv0`sma?g2 zOhkBdvSA7ZUDga$HtTwp?#h~`7&OO}3RCHF%_-MZr;IBae^Otuj@(mxqtSS1y4N`? Z+W#5eYu~HX=v}+4wy$+rF;7{X`~d=8Th0Ig diff --git a/django/contrib/gis/locale/ga/LC_MESSAGES/django.po b/django/contrib/gis/locale/ga/LC_MESSAGES/django.po index e8de66a38b..482e384cff 100644 --- a/django/contrib/gis/locale/ga/LC_MESSAGES/django.po +++ b/django/contrib/gis/locale/ga/LC_MESSAGES/django.po @@ -1,16 +1,17 @@ # This file is distributed under the same license as the Django package. # # Translators: +# Aindriú Mac Giolla Eoin, 2024 # Jannis Leidel , 2011 # Michael Thornhill , 2012 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-01-19 16:49+0100\n" -"PO-Revision-Date: 2017-09-23 18:54+0000\n" -"Last-Translator: Jannis Leidel \n" -"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2024-10-07 18:45+0000\n" +"Last-Translator: Aindriú Mac Giolla Eoin, 2024\n" +"Language-Team: Irish (http://app.transifex.com/django/django/language/ga/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -19,14 +20,16 @@ msgstr "" "4);\n" msgid "GIS" -msgstr "" +msgstr "GIS" msgid "The base GIS field." -msgstr "" +msgstr "Réimse bonn GIS." msgid "" -"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +"The base Geometry field — maps to the OpenGIS Specification Geometry type." msgstr "" +"An bonnréimse Céimseata — léarscáileanna chuig an gcineál Céimseata " +"Sonraíochta OpenGIS." msgid "Point" msgstr "Pointe" @@ -50,10 +53,10 @@ msgid "Geometry collection" msgstr "Céimseata bhailiú" msgid "Extent Aggregate Field" -msgstr "" +msgstr "Méid Réimse Comhiomlán" msgid "Raster Field" -msgstr "" +msgstr "Réimse Raster" msgid "No geometry value provided." msgstr "Ní soláthair méid geoiméadracht" @@ -72,17 +75,14 @@ msgstr "" "geoiméadracht." msgid "Delete all Features" -msgstr "" - -msgid "WKT debugging window:" -msgstr "" +msgstr "Scrios na Gnéithe go léir" msgid "Debugging window (serialized value)" -msgstr "" +msgstr "Fuinneog dífhabhtaithe (luach sraitheach)" msgid "No feeds are registered." msgstr "Níl fothaí cláraithe." #, python-format -msgid "Slug %r isn't registered." -msgstr "Níl slug %r cláraithe." +msgid "Slug %r isn’t registered." +msgstr "Níl seilide %r cláraithe." diff --git a/django/contrib/humanize/locale/ga/LC_MESSAGES/django.mo b/django/contrib/humanize/locale/ga/LC_MESSAGES/django.mo index 1fb51b9f436b3b88c353c28b310e43581a07e380..abbfd579808e24e8fefcc055d51d79400009276a 100644 GIT binary patch literal 6346 zcmeH~Uu+ab9LGngBBuzVDEN;>thB(kch?rm)zhee5@~3#Vhk@%@1}QK_GXUVz0!l= zgM@?-NsRx%1dY5HNlGGVgrre49ESL4)JOHj2Ms=$V4_dP@9%cHch}pNTCR{7Cz<=q z?>oPpnf=Y|%-oMln%-eZ8<8JG{`n@xwu7Vd@PqVA6Jra(U%@5dpWrGmatmXt!8ULu zxDzCOMC&IsFM?~K|E9U@R>oRkZ_<=tGwkEwZQyy3+PMUp;AL$upYPjA(15-hTm!xi zqG@&x#L(F1nioLo_Yz3$TmfU?N_5f=z5tSbQ1c8(h z-|xKU>czhP21xz<4ITm)!*~sR7d!|q$0B+gd>{M(jNi@J82AlH@jP^o|DH!cdY?DI z9`HSo#``_^GWf(&Uq23#{T=u`*oK!Q|9v3&p9QIY1tx*?B1rb9Ao(v^=J&e`r1-u9 z&I1RvKBTEMJnwC)&be6}5?#gKe zep`_{kh_twjLP3TrkBN$DLv|={7ZWXB}_*-b>WxR10{Td$MpapZ zj>;KQ?S(YV?Sg>AfMwg3lG7?_k*f0w(=tkBlwH+Sosg?*r(Tgt)_H|#D&^Jrg=u>V zJnhtZPNiD1zSTX2Fx3_LdeC>FYjrPt z=&Sym2R>C(UgsFpal;iUCDW5z^wo(LwNLO=b4$?Tgkw<0rIA$yXL5t2>E^UU@I+N> zzE@BqtW4HpgVwNMgLs}v?iCzvdsa@Eg9VgDQ*(<-+?nAW=}cxCit)OzQ+>&+}GHJ(?ANsaFeB2w#r zwRqHcUnLqfzG1Pjq+qnuDNs3SOLE(YHtj!vDVZ>1FkP==#?~3JIC4j=TO6iL2X0jB zRLss==dN0FeXY5n*6gk|H~OY4hJ|FVHNw2CBLwplt!hu@l;hxqyuFGQh3g527-zn@<-quGy~=Mx<}MxkC(Fo=6z+ zXspAGcAD`{Bi5bhjINC$MYdrDnf(rzuFXB=B#fsliG8#*ZuIh$@vNn6n;V;zCD);W zcqja2roc18>=!(jFt$3Dn>AXpo|jLwxAT0y&7-!gK{3*nQn_}2kQ1==!|fT~-WuuM z+Pk^(I-H^iXP1mkYamkwbb!_II zA$K$vyHDM9a#mvX8uzbxlNWg-)lH>SxRs^3k`h}GPiL7djafOUX``}T1y{Q3R$0># zm&$UnXhVkKZ=iEh=PE0O(=99vx~g<~t}7?TP;*XH1>%O(7r2Exyu>MMD=QNgf*a~l z-+A5ondCB6bg!SAO5x8;sx)q8SW0j&iwI*)`+r&N(#ctu=?#L1YhS0aa`3$d%{EHO zl}-n3{@b!Eu&H^t5(X_aN*T!7R&~1r*I@oX!NK(WwTaI d%q^W_o`a9UlF}+Lo-3Vn=wCy+G)59?{{b}5cf|kz literal 5112 zcmchaUuYaf9LJ{`O+BmCwrZ=kj@H`5c5}H)(x#W3e;QMWHW~d2yB{0{Nq0cf-_%?J>Ha@zc6LVN^l3g1?m_=+ zAcka%Ag02WG%sp?4${)T)chK}74~J#@4>rZ|E_JeG3wu}xl7a19M*hF^Epiyqj8Q_asbFKK?E`IY8n5L<*@ z0qH*9Y5fO~=Jg9m^ZHfy|DpB2Ks@%aP(ST8Dp+2)Kd8M8mEMsaGEjC!2(NT6Di-R) zsQXcA9xLTRG!P1g@Pq}AHQeXgWOt+S0P0>;dVlC0St$>pu>q^X+ z+*``?W^bb$m?j<*RV=zDB_2b?Omg23{c%;bJ zq#DAccndKWBJwndh5*$h;X1{DO}VpzP05PSJl7Mq2_;On018b~cJu7^LRFvU`Y1?yT;+U9`eqfC&$1PZgD~_^q zGQ$%SPg}>ttV^!e6LugnJl&f*Wc41f(rKPfW%~Q~^`az>+A6SezU`@!9Y{aJk5-Ng zez;_NVu23_)ZtEv`Nv9-CquO-FMBG-AHgp@r(!$8$_cxi;bXq5ioB~B1T&dra&B&} zr}ks~qMVGTy8?_9{y6E_$?nAX*!XCDVX2zeGJJ5-4Qi9jaK}zelq$YmvW`f=04(`crsIeZYUbl6H!e;=Ct-9w3n_Ct#5#-dv_qe$cBxJI zi*B`^QkeUiA5c5Qc>1KJv`dXAVY*wp)LJ5Mevto9NBqk`i#2^Q)>AipW@z~K%CYZN zbj$Y1(WkFDuIs7tm4mM0(MgDI)()|LpLnh^AEwsg*Oa6T2eE(cvHD@uQd2v``V)%h zCG!DrEq?KAWIjBu#m|_4R-HUoZ|rrG^wu`g8EnQ}N(pAjHzuG5HRhR$6MG2e6R@IML Z;8z!!>v?X4+2!g5A04bvT_Op+{{U9Y#%2Hj diff --git a/django/contrib/humanize/locale/ga/LC_MESSAGES/django.po b/django/contrib/humanize/locale/ga/LC_MESSAGES/django.po index 5108ded756..0e99520b73 100644 --- a/django/contrib/humanize/locale/ga/LC_MESSAGES/django.po +++ b/django/contrib/humanize/locale/ga/LC_MESSAGES/django.po @@ -1,6 +1,7 @@ # This file is distributed under the same license as the Django package. # # Translators: +# Aindriú Mac Giolla Eoin, 2024 # Jannis Leidel , 2011 # Luke Blaney , 2019 # Michael Thornhill , 2011-2012 @@ -8,10 +9,10 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-01-16 20:42+0100\n" -"PO-Revision-Date: 2019-06-22 21:44+0000\n" -"Last-Translator: Luke Blaney \n" -"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2024-10-07 18:40+0000\n" +"Last-Translator: Aindriú Mac Giolla Eoin, 2024\n" +"Language-Team: Irish (http://app.transifex.com/django/django/language/ga/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -20,7 +21,7 @@ msgstr "" "4);\n" msgid "Humanize" -msgstr "" +msgstr "Déan daonnachadh" #. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). msgctxt "ordinal 11, 12, 13" @@ -42,7 +43,7 @@ msgctxt "ordinal 2" msgid "{}nd" msgstr "{}ú" -#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +#. Translators: Ordinal format when value ends with 3, e.g. 83rd, except 13. msgctxt "ordinal 3" msgid "{}rd" msgstr "{}ú" @@ -77,15 +78,6 @@ msgctxt "ordinal 9" msgid "{}th" msgstr "{}ú" -#, python-format -msgid "%(value).1f million" -msgid_plural "%(value).1f million" -msgstr[0] "%(value).1f milliún" -msgstr[1] "%(value).1f milliún" -msgstr[2] "%(value).1f milliún" -msgstr[3] "%(value).1f milliún" -msgstr[4] "%(value).1f milliún" - #, python-format msgid "%(value)s million" msgid_plural "%(value)s million" @@ -95,15 +87,6 @@ msgstr[2] " %(value)s milliún" msgstr[3] " %(value)s milliún" msgstr[4] " %(value)s milliún" -#, python-format -msgid "%(value).1f billion" -msgid_plural "%(value).1f billion" -msgstr[0] "%(value).1f billiún" -msgstr[1] "%(value).1f billiún" -msgstr[2] "%(value).1f billiún" -msgstr[3] "%(value).1f billiún" -msgstr[4] "%(value).1f billiún" - #, python-format msgid "%(value)s billion" msgid_plural "%(value)s billion" @@ -113,15 +96,6 @@ msgstr[2] " %(value)s billiún" msgstr[3] " %(value)s billiún" msgstr[4] " %(value)s billiún" -#, python-format -msgid "%(value).1f trillion" -msgid_plural "%(value).1f trillion" -msgstr[0] "%(value).1f trilliún" -msgstr[1] "%(value).1f trilliún" -msgstr[2] "%(value).1f trilliún" -msgstr[3] "%(value).1f trilliún" -msgstr[4] "%(value).1f trilliún" - #, python-format msgid "%(value)s trillion" msgid_plural "%(value)s trillion" @@ -131,15 +105,6 @@ msgstr[2] " %(value)s trilliún" msgstr[3] " %(value)s trilliún" msgstr[4] " %(value)s trilliún" -#, python-format -msgid "%(value).1f quadrillion" -msgid_plural "%(value).1f quadrillion" -msgstr[0] "%(value).1f quadrilliún" -msgstr[1] "%(value).1f quadrilliún" -msgstr[2] "%(value).1f quadrilliún" -msgstr[3] "%(value).1f quadrilliún" -msgstr[4] "%(value).1f quadrilliún" - #, python-format msgid "%(value)s quadrillion" msgid_plural "%(value)s quadrillion" @@ -149,15 +114,6 @@ msgstr[2] "%(value)s quadrilliún" msgstr[3] "%(value)s quadrilliún" msgstr[4] "%(value)s quadrilliún" -#, python-format -msgid "%(value).1f quintillion" -msgid_plural "%(value).1f quintillion" -msgstr[0] "%(value).1f quintillion" -msgstr[1] "%(value).1f quintillion" -msgstr[2] "%(value).1f quintillion" -msgstr[3] "%(value).1f quintillion" -msgstr[4] "%(value).1f quintillion" - #, python-format msgid "%(value)s quintillion" msgid_plural "%(value)s quintillion" @@ -167,15 +123,6 @@ msgstr[2] "%(value)s quintillion" msgstr[3] "%(value)s quintillion" msgstr[4] "%(value)s quintillion" -#, python-format -msgid "%(value).1f sextillion" -msgid_plural "%(value).1f sextillion" -msgstr[0] "%(value).1f sextillion" -msgstr[1] "%(value).1f sextillion" -msgstr[2] "%(value).1f sextillion" -msgstr[3] "%(value).1f sextillion" -msgstr[4] "%(value).1f sextillion" - #, python-format msgid "%(value)s sextillion" msgid_plural "%(value)s sextillion" @@ -185,15 +132,6 @@ msgstr[2] "%(value)s sextillion" msgstr[3] "%(value)s sextillion" msgstr[4] "%(value)s sextillion" -#, python-format -msgid "%(value).1f septillion" -msgid_plural "%(value).1f septillion" -msgstr[0] "%(value).1f septillion" -msgstr[1] "%(value).1f septillion" -msgstr[2] "%(value).1f septillion" -msgstr[3] "%(value).1f septillion" -msgstr[4] "%(value).1f septillion" - #, python-format msgid "%(value)s septillion" msgid_plural "%(value)s septillion" @@ -203,15 +141,6 @@ msgstr[2] "%(value)s septillion" msgstr[3] "%(value)s septillion" msgstr[4] "%(value)s septillion" -#, python-format -msgid "%(value).1f octillion" -msgid_plural "%(value).1f octillion" -msgstr[0] "%(value).1f octillion" -msgstr[1] "%(value).1f octillion" -msgstr[2] "%(value).1f octillion" -msgstr[3] "%(value).1f octillion" -msgstr[4] "%(value).1f octillion" - #, python-format msgid "%(value)s octillion" msgid_plural "%(value)s octillion" @@ -221,15 +150,6 @@ msgstr[2] "%(value)s octillion" msgstr[3] "%(value)s octillion" msgstr[4] "%(value)s octillion" -#, python-format -msgid "%(value).1f nonillion" -msgid_plural "%(value).1f nonillion" -msgstr[0] "%(value).1f nonillion" -msgstr[1] "%(value).1f nonillion" -msgstr[2] "%(value).1f nonillion" -msgstr[3] "%(value).1f nonillion" -msgstr[4] "%(value).1f nonillion" - #, python-format msgid "%(value)s nonillion" msgid_plural "%(value)s nonillion" @@ -239,15 +159,6 @@ msgstr[2] "%(value)s nonillion" msgstr[3] "%(value)s nonillion" msgstr[4] "%(value)s nonillion" -#, python-format -msgid "%(value).1f decillion" -msgid_plural "%(value).1f decillion" -msgstr[0] "%(value).1f decillion" -msgstr[1] "%(value).1f decillion" -msgstr[2] "%(value).1f decillion" -msgstr[3] "%(value).1f decillion" -msgstr[4] "%(value).1f decillion" - #, python-format msgid "%(value)s decillion" msgid_plural "%(value)s decillion" @@ -257,15 +168,6 @@ msgstr[2] "%(value)s decillion" msgstr[3] "%(value)s decillion" msgstr[4] "%(value)s decillion" -#, python-format -msgid "%(value).1f googol" -msgid_plural "%(value).1f googol" -msgstr[0] "%(value).1f googol" -msgstr[1] "%(value).1f googol" -msgstr[2] "%(value).1f googol" -msgstr[3] "%(value).1f googol" -msgstr[4] "%(value).1f googol" - #, python-format msgid "%(value)s googol" msgid_plural "%(value)s googol" @@ -315,40 +217,40 @@ msgstr "inné" #. weeks' #, python-format msgid "%(delta)s ago" -msgstr "" +msgstr "%(delta)s ó shin" #. Translators: please keep a non-breaking space (U+00A0) between count #. and time unit. #, python-format msgid "an hour ago" msgid_plural "%(count)s hours ago" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgstr[0] "uair an chloig ó shin" +msgstr[1] "%(count)s uair an chloig ó shin" +msgstr[2] "%(count)s uair an chloig ó shin" +msgstr[3] "%(count)s uair an chloig ó shin" +msgstr[4] "%(count)s uair an chloig ó shin" #. Translators: please keep a non-breaking space (U+00A0) between count #. and time unit. #, python-format msgid "a minute ago" msgid_plural "%(count)s minutes ago" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgstr[0] "nóiméad ó shin" +msgstr[1] "%(count)s nóiméad ó shin" +msgstr[2] "%(count)s nóiméad ó shin" +msgstr[3] "%(count)s nóiméad ó shin" +msgstr[4] "%(count)s nóiméad ó shin" #. Translators: please keep a non-breaking space (U+00A0) between count #. and time unit. #, python-format msgid "a second ago" msgid_plural "%(count)s seconds ago" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgstr[0] "soicind ó shin" +msgstr[1] "%(count)s soicindí ó shin" +msgstr[2] "%(count)s soicindí ó shin" +msgstr[3] "%(count)s soicindí ó shin" +msgstr[4] "%(count)s soicindí ó shin" msgid "now" msgstr "anois" @@ -358,159 +260,159 @@ msgstr "anois" #, python-format msgid "a second from now" msgid_plural "%(count)s seconds from now" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgstr[0] "soicind as seo amach" +msgstr[1] "%(count)s soicind as seo amach" +msgstr[2] "%(count)s soicind as seo amach" +msgstr[3] "%(count)s soicind as seo amach" +msgstr[4] "%(count)s soicind as seo amach" #. Translators: please keep a non-breaking space (U+00A0) between count #. and time unit. #, python-format msgid "a minute from now" msgid_plural "%(count)s minutes from now" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgstr[0] "nóiméad ó anois" +msgstr[1] "%(count)s nóiméad as seo" +msgstr[2] "%(count)s nóiméad as seo" +msgstr[3] "%(count)s nóiméad as seo" +msgstr[4] "%(count)s nóiméad as seo" #. Translators: please keep a non-breaking space (U+00A0) between count #. and time unit. #, python-format msgid "an hour from now" msgid_plural "%(count)s hours from now" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgstr[0] "uair an chloig ó anois" +msgstr[1] "%(count)s uair an chloig as seo amach" +msgstr[2] "%(count)s uair an chloig as seo amach" +msgstr[3] "%(count)s uair an chloig as seo amach" +msgstr[4] "%(count)s uair an chloig as seo amach" #. Translators: delta will contain a string like '2 months' or '1 month, 2 #. weeks' #, python-format msgid "%(delta)s from now" -msgstr "" +msgstr "%(delta)s as seo amach" #. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' #, python-format msgctxt "naturaltime-past" -msgid "%d year" -msgid_plural "%d years" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d bhliain" +msgstr[1] "%(num)d bliain" +msgstr[2] "%(num)d bliain" +msgstr[3] "%(num)d bliain" +msgstr[4] "%(num)d bliain" #, python-format msgctxt "naturaltime-past" -msgid "%d month" -msgid_plural "%d months" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mí" +msgstr[1] "%(num)d mí" +msgstr[2] "%(num)d mí" +msgstr[3] "%(num)d mí" +msgstr[4] "%(num)d mí" #, python-format msgctxt "naturaltime-past" -msgid "%d week" -msgid_plural "%d weeks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d seachtain" +msgstr[1] "%(num)d seachtain" +msgstr[2] "%(num)d seachtain" +msgstr[3] "%(num)d seachtain" +msgstr[4] "%(num)d seachtain" #, python-format msgctxt "naturaltime-past" -msgid "%d day" -msgid_plural "%d days" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d lá" +msgstr[1] "%(num)d lá" +msgstr[2] "%(num)d lá" +msgstr[3] "%(num)d lá" +msgstr[4] "%(num)d lá" #, python-format msgctxt "naturaltime-past" -msgid "%d hour" -msgid_plural "%d hours" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d uair" +msgstr[1] "%(num)d uair an chloig" +msgstr[2] "%(num)d uair an chloig" +msgstr[3] "%(num)d uair an chloig" +msgstr[4] "%(num)d uair an chloig" #, python-format msgctxt "naturaltime-past" -msgid "%d minute" -msgid_plural "%d minutes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d nóiméad" +msgstr[1] "%(num)d nóiméad" +msgstr[2] "%(num)d nóiméad" +msgstr[3] "%(num)d nóiméad" +msgstr[4] "%(num)d nóiméad" #. Translators: 'naturaltime-future' strings will be included in '%(delta)s #. from now' #, python-format msgctxt "naturaltime-future" -msgid "%d year" -msgid_plural "%d years" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d bhliain" +msgstr[1] "%(num)d bliain" +msgstr[2] "%(num)d bliain" +msgstr[3] "%(num)d bliain" +msgstr[4] "%(num)d bliain" #, python-format msgctxt "naturaltime-future" -msgid "%d month" -msgid_plural "%d months" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mí" +msgstr[1] "%(num)d mí" +msgstr[2] "%(num)d mí" +msgstr[3] "%(num)d mí" +msgstr[4] "%(num)d mí" #, python-format msgctxt "naturaltime-future" -msgid "%d week" -msgid_plural "%d weeks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d seachtain" +msgstr[1] "%(num)d seachtain" +msgstr[2] "%(num)d seachtain" +msgstr[3] "%(num)d seachtain" +msgstr[4] "%(num)d seachtain" #, python-format msgctxt "naturaltime-future" -msgid "%d day" -msgid_plural "%d days" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d lá" +msgstr[1] "%(num)d lá" +msgstr[2] "%(num)d lá" +msgstr[3] "%(num)d lá" +msgstr[4] "%(num)d lá" #, python-format msgctxt "naturaltime-future" -msgid "%d hour" -msgid_plural "%d hours" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d uair" +msgstr[1] "%(num)d uair an chloig" +msgstr[2] "%(num)d uair an chloig" +msgstr[3] "%(num)d uair an chloig" +msgstr[4] "%(num)d uair an chloig" #, python-format msgctxt "naturaltime-future" -msgid "%d minute" -msgid_plural "%d minutes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d nóiméad" +msgstr[1] "%(num)d nóiméad" +msgstr[2] "%(num)d nóiméad" +msgstr[3] "%(num)d nóiméad" +msgstr[4] "%(num)d nóiméad" diff --git a/django/contrib/postgres/locale/cs/LC_MESSAGES/django.mo b/django/contrib/postgres/locale/cs/LC_MESSAGES/django.mo index a56d0b4e2967881539ab5e0f5016c11f037509c2..c8e64ab39fffeb2efacf44c386dd64ac32f057bf 100644 GIT binary patch delta 713 zcmaLTO=uHA6bJCPiHZI46F+LI?V}>3BpWtqEu<8cp0p}dsApM|vDtPzv+PU~?Ijn% zg9u^{ReSOxUKC+39<-NcFXCPBrr^nw2l3#={}Sm%bYS?+E;IjmZ{FrUhEM>q>l?<2zb-EpYvS!07}hYn(9 zyAQ0169=%ueS}A#Va()3ah#5HV{4`$*jH^4@=ev0bym07Gz5pPToLSPmdda%w8mdo zcJnDN32p|#fA_D1!Zp~D9EnWoUV5o~)^^Hvxynv;u2LyD7(-WFZR}-SqhO`sJcW}1MyxB?WhgyHkvF&@^@Xx_!*QU-sUrT-&^<0jh5>-#gs15-)Si4 R-(juZ@Rr$)i_!zt%x}35rI!Ez delta 683 zcmajbKWI}y90%~t``z7_%)881p}t5& z-z}o+u#_M=2_M5D_za$gd+-eW1P9?a$nY1;!)%i16y=~ei#>!3SRcZ;&_E}V4f8Mqm*IJ6V0`gyn1gR% z0e*%x)a~dZ((pldyWfwVtL+zz949)5gE!$t=)<_c7L0%9Eu4m_ULxdE4`w{lk!uZg z^&vWenT(!V!)N1t^rKUlcxdZKkxuiQDKQ& zv3p0}<7>+B%xpBD&L(TMT4OzJTlGb`9=Od9&7Ff?F00#tGJ->OUyE{u{ffr!>cM-% z)sHVs>r5b56%JGb!J|3P^2X4>>SlB2f3, 2024 # Tomáš Ehrlich , 2015 # Vláďa Macek , 2015-2019 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-05-11 20:56+0200\n" -"PO-Revision-Date: 2020-05-12 20:01+0000\n" -"Last-Translator: Transifex Bot <>\n" -"Language-Team: Czech (http://www.transifex.com/django/django/language/cs/)\n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2024-10-07 09:22+0000\n" +"Last-Translator: Jiří Podhorecký , 2024\n" +"Language-Team: Czech (http://app.transifex.com/django/django/language/cs/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -109,11 +110,10 @@ msgstr "Byly zadány neznámé klíče: %(keys)s" #, python-format msgid "" -"Ensure that this range is completely less than or equal to %(limit_value)s." -msgstr "Nejvyšší hodnota rozsahu musí být menší nebo rovna %(limit_value)s." +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "Ujistěte se, že horní hranice rozsahu není větší než %(limit_value)s." #, python-format msgid "" -"Ensure that this range is completely greater than or equal to " -"%(limit_value)s." -msgstr "Nejnižší hodnota rozsahu musí být větší nebo rovna %(limit_value)s." +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "Ujistěte se, že spodní hranice rozsahu není menší než %(limit_value)s." diff --git a/django/contrib/postgres/locale/ga/LC_MESSAGES/django.mo b/django/contrib/postgres/locale/ga/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..0f8fe8b46f669265fee0f5df008205f3a9d567eb GIT binary patch literal 3652 zcmeHJOKco97&cH|OL-Lvg%X+os8`Qz60C~`~dg_a2fa{@N3{6 z;0+)F{{Zd>?z@Yz&wyuup8|gYJ_r182V+CPFMzv&KLQE(8*mu7=WfQ115W}E0^bI{ z2U(VZe*MI~jGYHw0!{?21xk72z(a!F3`*MIWPi#5BwE;cii8@ z-)oH3G5_;U=nUNZAY)GhF97|%0_f%W2zVO!4bao?euy!!S!s`A1QUb?lF%S}Xi$+o zf__i$cjXHe*kkArfq@-+7#-pa#=|C);!NkF>E)oD!bin zS*1pB2a2t@g|!7usx0P&2?q?OaHdSW2BP6)A+}iCWI71DZhj%txmZ18LUl_=MQI() z3F3WI$=FG)xLK^T2`38Zu3R>3NvdEWZVX?f1R{A82jL)Ei%m+fiM4WEDvM1v(+hoj zB_zS<0KSA-@0~s!SWriJCv0Mur2f}D?SH{^3!a7U#m>#q@K5C2hUXOT`k=JVNR=WC z^N9K-y8zfZ@zKm<8c14y>aD}K^F49;-n2iH_xGw(HBMRqKPDW1IYq?T9jNw=IYu7 z(bdL9Q#O@Jbh1osG^<-wn?4_15cATLMz8vCrO}b*;b^28HILHB(bnkb{t>j=B)2Y_ zMG>$$ciOb*gj9)<)peTUF`bq=&pC~2sSbd_=poRnwB)IXW(6-=G-0I8Xee{8+iEm; zw_A6fm+Xkk^;j2;o{$5``$##OA7;LRg*(ya*DqLkOB^V0ATXoIr=pw{-oRyF_IAy@OXII$0sFuu1J-65)c*;$S%?9hP ztJr~*2Vdk86@(uM-Y|$g;Zr@;gqw;daOO5nLVZ#SNxnIMfkloA=4HQq2p$&y19RPq zJ2uawe_4s!hul(%Y-_H`>KZPN*jHmp!c&2#nZd8}`HZsH|LZ?7#<+A@M8sS+Xa fI`3&22t)Z?F^9i~a9`l%K`67mlD+PsQfGex!f(HZ literal 0 HcmV?d00001 diff --git a/django/contrib/postgres/locale/ga/LC_MESSAGES/django.po b/django/contrib/postgres/locale/ga/LC_MESSAGES/django.po new file mode 100644 index 0000000000..45babc89a3 --- /dev/null +++ b/django/contrib/postgres/locale/ga/LC_MESSAGES/django.po @@ -0,0 +1,125 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aindriú Mac Giolla Eoin, 2024 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2024-10-07 09:22+0000\n" +"Last-Translator: Aindriú Mac Giolla Eoin, 2024\n" +"Language-Team: Irish (http://app.transifex.com/django/django/language/ga/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ga\n" +"Plural-Forms: nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : " +"4);\n" + +msgid "PostgreSQL extensions" +msgstr "Eisínteachtaí PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Níor bhailíochtaigh mír %(nth)s san eagar:" + +msgid "Nested arrays must have the same length." +msgstr "Caithfidh an fad céanna a bheith ag eagair neadaithe." + +msgid "Map of strings to strings/nulls" +msgstr "Léarscáil de theaghráin go teaghráin/nulls" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Ní teaghrán nó null é luach “%(key)s”." + +msgid "Could not load JSON data." +msgstr "Níorbh fhéidir sonraí JSON a lódáil." + +msgid "Input must be a JSON dictionary." +msgstr "Ní mór gur foclóir JSON é an t-ionchur." + +msgid "Enter two valid values." +msgstr "Cuir isteach dhá luach bhailí." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Ní fhéadfaidh tús an raoin a bheith níos mó ná deireadh an raoin." + +msgid "Enter two whole numbers." +msgstr "Cuir isteach dhá slánuimhir." + +msgid "Enter two numbers." +msgstr "Cuir isteach dhá uimhir." + +msgid "Enter two valid date/times." +msgstr "Cuir isteach dhá dháta bhailí." + +msgid "Enter two valid dates." +msgstr "Cuir isteach dhá dháta bhailí." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Tá %(show_value)d mír ar an liosta, níor cheart go mbeadh níos mó ná " +"%(limit_value)d ann." +msgstr[1] "" +"Tá %(show_value)d míreanna ar an liosta, níor cheart go mbeadh níos mó ná " +"%(limit_value)d ann." +msgstr[2] "" +"Tá %(show_value)d míreanna ar an liosta, níor cheart go mbeadh níos mó ná " +"%(limit_value)d ann." +msgstr[3] "" +"Tá %(show_value)d míreanna ar an liosta, níor cheart go mbeadh níos mó ná " +"%(limit_value)d ann." +msgstr[4] "" +"Tá %(show_value)d míreanna ar an liosta, níor cheart go mbeadh níos mó ná " +"%(limit_value)d ann." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Tá %(show_value)d mír ar an liosta, níor cheart go mbeadh níos lú ná " +"%(limit_value)d ann." +msgstr[1] "" +"Tá %(show_value)d míreanna ar an liosta, níor cheart go mbeadh níos lú ná " +"%(limit_value)d ann." +msgstr[2] "" +"Tá %(show_value)d míreanna ar an liosta, níor cheart go mbeadh níos lú ná " +"%(limit_value)d ann." +msgstr[3] "" +"Tá %(show_value)d míreanna ar an liosta, níor cheart go mbeadh níos lú ná " +"%(limit_value)d ann." +msgstr[4] "" +"Tá %(show_value)d míreanna ar an liosta, níor cheart go mbeadh níos lú ná " +"%(limit_value)d ann." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Bhí roinnt eochracha ar iarraidh: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Soláthraíodh roinnt eochracha anaithnid: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" +"Cinntigh nach bhfuil teorainn uachtarach an raoin níos mó ná %(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" +"Cinntigh nach bhfuil teorainn íochtair an raoin níos lú ná %(limit_value)s." diff --git a/django/contrib/redirects/locale/ga/LC_MESSAGES/django.mo b/django/contrib/redirects/locale/ga/LC_MESSAGES/django.mo index 52e3967c426ca7364afe554f64ab32e39166cb20..0ed0c01435cf3c5f0e0da499adc37b204ad2e3eb 100644 GIT binary patch delta 528 zcmZ9|J4?e*6bJCz)>ly%LEP#Y75a=Fq>B#_7hQZHqKJnWn~Qmoo9f`u&Vrx>bWx$B zbGPD_%@5!vh~VVd)xm#S6*c7KmwR*WIXAa8beF!!){le`?}#15Rzip&*n*?*0S?1Q zn1)ZV55B;2#2aD+W0exZhYe`K4vg#UBRQ@k;TSxDalJD*2(S8tCQw5RATZZm1Vj=M zC&X8OkM1+xMC$T+dy+}%rePbTYPw0R=(TZU27#w4g~Ds&Hk?Z=k7KG}92-uc3d&$# zH@jc16Q`pyxnen|m8mpanbE?@VNwMdJ z_2fsrTJuSFRn&Ayy0#S?-IFq0nzGp^4x%OnW{uS}IZ=x?*H(V=xJm(5w#mZA_2^#O z6ffDWX~mNMz5VX!ATJh~@QdsR^rz#-@0MArvO~Co981ThL*(NHQxr9&Z?J9VX`OA) Q;>uT>e@D{m7IsqepUqK^Pyhe` delta 445 zcmZY4KTE?v7zXg`AGOsw=m*eu>rk82AcY1Mbc(6Fc?H<$, 2011 # Luke Blaney , 2019 # Michael Thornhill , 2015 @@ -8,10 +9,10 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-10-09 17:42+0200\n" -"PO-Revision-Date: 2019-06-22 21:46+0000\n" -"Last-Translator: Luke Blaney \n" -"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2024-10-07 18:32+0000\n" +"Last-Translator: Aindriú Mac Giolla Eoin, 2024\n" +"Language-Team: Irish (http://app.transifex.com/django/django/language/ga/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -29,17 +30,21 @@ msgid "redirect from" msgstr "atreoraigh ó" msgid "" -"This should be an absolute path, excluding the domain name. Example: '/" -"events/search/'." -msgstr "Teastaíonn dearbhchosán gan ainm fearainn. Sampla '/events/search/'." +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Ba cheart gur cosán iomlán é seo, gan an t-ainm fearainn a áireamh. Sampla: " +"\\u201c/events/search/\\u201d." msgid "redirect to" msgstr "atreoraigh go dtí" msgid "" -"This can be either an absolute path (as above) or a full URL starting with " -"'http://'." -msgstr "Is féidir dearbhchosán nó URL lán ag tosnú le 'http://'." +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Is féidir gur cosán iomlán é seo (mar atá thuas) nó URL iomlán ag tosú le " +"scéim mar \\u201chttps://\\u201d." msgid "redirect" msgstr "athsheol" diff --git a/django/contrib/redirects/locale/ko/LC_MESSAGES/django.mo b/django/contrib/redirects/locale/ko/LC_MESSAGES/django.mo index d0a6f6da360d08ce619b3b0a4bf64f5e98080260..82d36159c1562adf610c192837bafd0e1f92e274 100644 GIT binary patch delta 249 zcmaFI(ZD$&#Wj?Xf#E3-^D{6oSTi#)Gy!REARP{*&jD$WxEc!sgBXxD1JV*e+80QJ z#M6K@Cy*}NxN7Mgu-o&?4XT0v30yMV;D5DS>NNQrPm4bJEQEFnI zf<{J3Nr9EVetCKMl+xO5SwOc{6X~+o>~NcTG`vGqdH*f|j>a=O}~*`6#?z ywc_=}2|z6kue+AMox1XMcgO4QC3+06`&(YGobqPw4xnQv-(ogpTrgRHr2qi6X>I2K diff --git a/django/contrib/redirects/locale/ko/LC_MESSAGES/django.po b/django/contrib/redirects/locale/ko/LC_MESSAGES/django.po index 2f2e380551..4209b98700 100644 --- a/django/contrib/redirects/locale/ko/LC_MESSAGES/django.po +++ b/django/contrib/redirects/locale/ko/LC_MESSAGES/django.po @@ -2,6 +2,7 @@ # # Translators: # Jiyoon, Ha , 2016 +# Hyeonho Kang, 2024 # Jannis Leidel , 2011 # Jay Oh , 2020 # JunGu Kang , 2015 @@ -13,9 +14,9 @@ msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-15 09:00+0100\n" -"PO-Revision-Date: 2021-12-24 18:32+0000\n" -"Last-Translator: 정훈 이\n" -"Language-Team: Korean (http://www.transifex.com/django/django/language/ko/)\n" +"PO-Revision-Date: 2024-10-07 18:32+0000\n" +"Last-Translator: Hyeonho Kang, 2024\n" +"Language-Team: Korean (http://app.transifex.com/django/django/language/ko/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -36,7 +37,7 @@ msgid "" "events/search/”." msgstr "" "도메인 이름을 제외한 절대 경로여야 합니다.\n" -"예제: \"/events/search/\"." +"예시: \"/events/search/\"." msgid "redirect to" msgstr "(으)로 리다이렉트" @@ -45,8 +46,8 @@ msgid "" "This can be either an absolute path (as above) or a full URL starting with a " "scheme such as “https://”." msgstr "" -"(위와 같은) 절대경로 혹은 \"https://\" 같은 식으로 시작하는 완전한 URL 모두 " -"가능합니다." +"이것은 절대 경로 (위와 같이) 이거나 “https://”와 같은 체계로 시작하는 전체 " +"URL 일 수 있습니다." msgid "redirect" msgstr "리다이렉트" diff --git a/django/contrib/sessions/locale/ko/LC_MESSAGES/django.mo b/django/contrib/sessions/locale/ko/LC_MESSAGES/django.mo index 144d87c19142f2a13f50df615ee9b1163dca53ca..02949db3ad09bf3ea12dca011239263a9b9aea1f 100644 GIT binary patch delta 166 zcmdnP+RHj2#59zVf#C-O0|Ofn`!O*v@B-;jAPwRtL-|=inhVIU0MeX5x_M&fVo%+m z)UwRt%=|oEm&B4(D+MD1Lt|Y76I~+{1w#ufBQtFSAmH*zEH2RvDN4*M&PgoEFS1hb zs7%ez%g9&oPRvW!0ctWbnY@Bgo;k6gVDc%(eeAE7_q<-*qcFLTNtfmIV*v@$T)HZU|W;0o~94N5J`EJjghu4`ba zYiOxpXl7+%pltvITt11#CAuL+iFw62i6!|(RtnA;MFzRX3O31LS}(iEAw4%SGe<8u jKi3YZdU6G$40CyT`Q+)0``F&hS@3q&ipeodx{M3}{MtA< diff --git a/django/contrib/sessions/locale/ko/LC_MESSAGES/django.po b/django/contrib/sessions/locale/ko/LC_MESSAGES/django.po index 74c622c3f9..b49ff0e67e 100644 --- a/django/contrib/sessions/locale/ko/LC_MESSAGES/django.po +++ b/django/contrib/sessions/locale/ko/LC_MESSAGES/django.po @@ -1,16 +1,17 @@ # This file is distributed under the same license as the Django package. # # Translators: +# Hyeonho Kang, 2024 # Jannis Leidel , 2011 -# Chr0m3 , 2015 +# JunGu Kang , 2015 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-01-17 11:07+0100\n" -"PO-Revision-Date: 2017-09-19 16:40+0000\n" -"Last-Translator: Chr0m3 \n" -"Language-Team: Korean (http://www.transifex.com/django/django/language/ko/)\n" +"PO-Revision-Date: 2024-10-07 18:26+0000\n" +"Last-Translator: Hyeonho Kang, 2024\n" +"Language-Team: Korean (http://app.transifex.com/django/django/language/ko/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -27,10 +28,10 @@ msgid "session data" msgstr "세션 날짜" msgid "expire date" -msgstr "유효날짜" +msgstr "만료 날짜" msgid "session" msgstr "세션" msgid "sessions" -msgstr "세션" +msgstr "세션들" diff --git a/django/contrib/sites/locale/ga/LC_MESSAGES/django.mo b/django/contrib/sites/locale/ga/LC_MESSAGES/django.mo index c15ebefd56238c5ebf598c73db7df0c6d0ae6c9e..b828e40e41b5117cb26d5ce6456241f900b68de4 100644 GIT binary patch delta 420 zcmXwzy-EW?6on_hf<{ma3lX{4YQnlEAn6oD0%~J=x!K*2fz8aaGYY9v+Gruc2ME}R zL@fO&EcQKo2C=l!GYKB}IG33-bI)VxsXY8#Dc%Wa4y=PVSOC|+=>?R)EAYVwsDN+a za=)PH=G-i|1it~Rz}?^Hg=oQ_;mhzJ_#(VgnC={kH4HAe3CA0Odr=0iko(xl75Eoo zGo48r8PV=V6zV=pMT+|o1+0{|6li7L8LI)AgoDVCPRVk|)I=yv67yi1zkNSH*sXf? zs$Zv_y{6aL@}T)+Hn!SMS(%uvPMfqZRhY``jZQeABdOz<=}=3xO}^*XN8Q{;fsFV~R%c^_MocOjQxIRUG}%NU!6|j5?GaO_7r6m3LgPMlBTg}>+UPRh F_yb4ZU~B*Y delta 276 zcmZ3-wwks6o)F7a1|VPqVi_Rz0b*_-t^r~YSOLVWK)e!&d4PC55QF6R05J;?p8#Tz z{8=EL&d9)U8AyZVvzZte1c7upkmd!_oj{r$NKXgSAo=+~8mL^K0Z4-l06Bmeh(Q2k zFa`+DEJ-b%_%X-FQrEyt*T_i0$k58fOxpkmxO@_eOLRku67!045=-)ntQ34ovr`qE xauV}WD-~=?KoXg0sTB@6K;a~?s9tiuUTL=7$1OO)OF(Ci| diff --git a/django/contrib/sites/locale/ga/LC_MESSAGES/django.po b/django/contrib/sites/locale/ga/LC_MESSAGES/django.po index 095d08db92..2b1c9bf9ad 100644 --- a/django/contrib/sites/locale/ga/LC_MESSAGES/django.po +++ b/django/contrib/sites/locale/ga/LC_MESSAGES/django.po @@ -1,6 +1,7 @@ # This file is distributed under the same license as the Django package. # # Translators: +# Aindriú Mac Giolla Eoin, 2024 # Jannis Leidel , 2011 # Luke Blaney , 2019 msgid "" @@ -8,9 +9,9 @@ msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-01-17 11:07+0100\n" -"PO-Revision-Date: 2019-06-22 21:46+0000\n" -"Last-Translator: Luke Blaney \n" -"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"PO-Revision-Date: 2024-10-07 18:05+0000\n" +"Last-Translator: Aindriú Mac Giolla Eoin, 2024\n" +"Language-Team: Irish (http://app.transifex.com/django/django/language/ga/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -22,7 +23,7 @@ msgid "Sites" msgstr "Suíomhanna" msgid "The domain name cannot contain any spaces or tabs." -msgstr "" +msgstr "Ní féidir spásanna ná cluaisíní ar bith a bheith san ainm fearainn." msgid "domain name" msgstr "ainm fearainn" diff --git a/django/contrib/sites/locale/ko/LC_MESSAGES/django.mo b/django/contrib/sites/locale/ko/LC_MESSAGES/django.mo index e697676e25e344ab3036795c84fb257802265841..6cd41462af87aed7b33204355a034c5693cd8b60 100644 GIT binary patch delta 143 zcmZ3^_JVanh*>Bj1A`b4b22b6KG_mWzFxNIPG%(-_@YfAWEz2xMQD?4e zV5w_psbFYkWn!Rh00dk6j, 2016 +# Hyeonho Kang, 2024 # Jannis Leidel , 2011 # Le Tartuffe , 2014 -# Chr0m3 , 2015 +# JunGu Kang , 2015 msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-01-17 11:07+0100\n" -"PO-Revision-Date: 2017-09-19 16:40+0000\n" -"Last-Translator: Jiyoon, Ha \n" -"Language-Team: Korean (http://www.transifex.com/django/django/language/ko/)\n" +"PO-Revision-Date: 2024-10-07 18:05+0000\n" +"Last-Translator: Hyeonho Kang, 2024\n" +"Language-Team: Korean (http://app.transifex.com/django/django/language/ko/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -23,10 +24,10 @@ msgid "Sites" msgstr "사이트" msgid "The domain name cannot contain any spaces or tabs." -msgstr "도메인 이름은 공백이나 탭을 포함 할 수 없습니다." +msgstr "도메인 이름은 공백이나 탭을 포함할 수 없습니다." msgid "domain name" -msgstr "도메인 명" +msgstr "도메인명" msgid "display name" msgstr "표시명" diff --git a/docs/releases/5.1.2.txt b/docs/releases/5.1.2.txt index 6d2714df85..2727b112dc 100644 --- a/docs/releases/5.1.2.txt +++ b/docs/releases/5.1.2.txt @@ -4,7 +4,8 @@ Django 5.1.2 release notes *Expected October 8, 2024* -Django 5.1.2 fixes several bugs in 5.1.1. +Django 5.1.2 fixes several bugs in 5.1.1. Also, the latest string translations +from Transifex are incorporated. Bugfixes ======== From 862026a8b93febcf20f91479d07fea0e47118836 Mon Sep 17 00:00:00 2001 From: antoliny0919 Date: Tue, 8 Oct 2024 09:27:20 +0200 Subject: [PATCH 11/40] Fixed #35742 -- Removed hardcoded "username" references in admin templates. --- django/contrib/admin/templates/admin/auth/user/add_form.html | 4 +--- django/contrib/admin/templates/admin/login.html | 2 +- .../admin/templates/registration/password_reset_email.html | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/django/contrib/admin/templates/admin/auth/user/add_form.html b/django/contrib/admin/templates/admin/auth/user/add_form.html index 48406f11a2..a13e75e89a 100644 --- a/django/contrib/admin/templates/admin/auth/user/add_form.html +++ b/django/contrib/admin/templates/admin/auth/user/add_form.html @@ -3,9 +3,7 @@ {% block form_top %} {% if not is_popup %} -

{% translate 'First, enter a username and password. Then, you’ll be able to edit more user options.' %}

- {% else %} -

{% translate "Enter a username and password." %}

+

{% translate "After you've created a user, you’ll be able to edit more user options." %}

{% endif %} {% endblock %} {% block extrahead %} diff --git a/django/contrib/admin/templates/admin/login.html b/django/contrib/admin/templates/admin/login.html index 3999dd3703..fa0dcbc01d 100644 --- a/django/contrib/admin/templates/admin/login.html +++ b/django/contrib/admin/templates/admin/login.html @@ -57,7 +57,7 @@ {% url 'admin_password_reset' as password_reset_url %} {% if password_reset_url %} {% endif %}
diff --git a/django/contrib/admin/templates/registration/password_reset_email.html b/django/contrib/admin/templates/registration/password_reset_email.html index 64822091d1..2a428c48ce 100644 --- a/django/contrib/admin/templates/registration/password_reset_email.html +++ b/django/contrib/admin/templates/registration/password_reset_email.html @@ -5,7 +5,7 @@ {% block reset_link %} {{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %} {% endblock %} -{% translate 'Your username, in case you’ve forgotten:' %} {{ user.get_username }} +{% translate 'In case you’ve forgotten, you are:' %} {{ user.get_username }} {% translate "Thanks for using our site!" %} From ef56e1ff6dc71a08154e52a1044892e60c25ad77 Mon Sep 17 00:00:00 2001 From: Mario Munoz <46942991+tataraba@users.noreply.github.com> Date: Tue, 8 Oct 2024 12:13:23 +0200 Subject: [PATCH 12/40] Fixed #35799 -- Fixed the positioning of the inline admin plus icon for RTL languages. --- django/contrib/admin/static/admin/css/forms.css | 2 -- django/contrib/admin/static/admin/js/inlines.js | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/django/contrib/admin/static/admin/css/forms.css b/django/contrib/admin/static/admin/css/forms.css index 302d515751..ae697cf58d 100644 --- a/django/contrib/admin/static/admin/css/forms.css +++ b/django/contrib/admin/static/admin/css/forms.css @@ -460,8 +460,6 @@ body.popup .submit-row { .inline-group div.add-row a, .inline-group .tabular tr.add-row td a { - background: url(../img/icon-addlink.svg) 0 1px no-repeat; - padding-left: 16px; font-size: 0.75rem; } diff --git a/django/contrib/admin/static/admin/js/inlines.js b/django/contrib/admin/static/admin/js/inlines.js index e9a1dfe122..a4246d6e12 100644 --- a/django/contrib/admin/static/admin/js/inlines.js +++ b/django/contrib/admin/static/admin/js/inlines.js @@ -50,11 +50,11 @@ // If forms are laid out as table rows, insert the // "add" button in a new table row: const numCols = $this.eq(-1).children().length; - $parent.append('' + options.addText + ""); + $parent.append('' + options.addText + ""); addButton = $parent.find("tr:last a"); } else { // Otherwise, insert it immediately after the last form: - $this.filter(":last").after('"); + $this.filter(":last").after('"); addButton = $this.filter(":last").next().find("a"); } } From 747b417a220b0412ed806001a383959449aac6da Mon Sep 17 00:00:00 2001 From: Gavin Wahl Date: Wed, 2 Nov 2022 16:29:17 -0600 Subject: [PATCH 13/40] Fixed #35798, Refs #31641 -- Prevented admin navigation sidebar loading flicker. Thank you to Mario Munoz and Thibaud Colas for the testing and review. --- django/contrib/admin/templates/admin/base.html | 1 - django/contrib/admin/templates/admin/nav_sidebar.html | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/django/contrib/admin/templates/admin/base.html b/django/contrib/admin/templates/admin/base.html index 18e3a2a9fc..f4df6b30af 100644 --- a/django/contrib/admin/templates/admin/base.html +++ b/django/contrib/admin/templates/admin/base.html @@ -10,7 +10,6 @@ {% endblock %} {% if not is_popup and is_nav_sidebar_enabled %} - {% endif %} {% block extrastyle %}{% endblock %} {% if LANGUAGE_BIDI %}{% endif %} diff --git a/django/contrib/admin/templates/admin/nav_sidebar.html b/django/contrib/admin/templates/admin/nav_sidebar.html index a413e23754..37cdac2184 100644 --- a/django/contrib/admin/templates/admin/nav_sidebar.html +++ b/django/contrib/admin/templates/admin/nav_sidebar.html @@ -1,4 +1,4 @@ -{% load i18n %} +{% load i18n static %} + From 679d57816d716cbc7cff3b364ae265d70444ebd9 Mon Sep 17 00:00:00 2001 From: nessita <124304+nessita@users.noreply.github.com> Date: Tue, 8 Oct 2024 10:01:28 -0300 Subject: [PATCH 14/40] Fixed #35809 -- Set background color for selected rows in the admin's form select widget. Regression in b47bdb4cd9149ee2a39bf1cc9996a36a940bd7d9. Thank you Giannis Terzopoulos for the review, and Tom Carrick and Sarah Boyce for the review. --- .../contrib/admin/static/admin/css/forms.css | 4 ++ docs/releases/5.1.2.txt | 4 ++ tests/admin_views/tests.py | 59 +++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/django/contrib/admin/static/admin/css/forms.css b/django/contrib/admin/static/admin/css/forms.css index ae697cf58d..c6ce78833e 100644 --- a/django/contrib/admin/static/admin/css/forms.css +++ b/django/contrib/admin/static/admin/css/forms.css @@ -169,6 +169,10 @@ form .aligned select + div.help { padding-left: 10px; } +form .aligned select option:checked { + background-color: var(--selected-row); +} + form .aligned ul li { list-style: none; } diff --git a/docs/releases/5.1.2.txt b/docs/releases/5.1.2.txt index 2727b112dc..a7293654df 100644 --- a/docs/releases/5.1.2.txt +++ b/docs/releases/5.1.2.txt @@ -16,3 +16,7 @@ Bugfixes * Fixed a regression in Django 5.1 that caused a crash of ``JSONObject()`` when using server-side binding with PostgreSQL 16+ (:ticket:`35734`). + +* Fixed a regression in Django 5.1 that made selected items in multi-select + widgets indistinguishable from non-selected items in the admin dark theme + (:ticket:`35809`). diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index 16d76f5da2..f63a9ca56f 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -6175,6 +6175,65 @@ class SeleniumTests(AdminSeleniumTestCase): ) self.take_screenshot("selectbox-non-collapsible") + @screenshot_cases(["desktop_size", "mobile_size", "rtl", "dark", "high_contrast"]) + def test_selectbox_selected_rows(self): + from selenium.webdriver import ActionChains + from selenium.webdriver.common.by import By + from selenium.webdriver.common.keys import Keys + + self.admin_login( + username="super", password="secret", login_url=reverse("admin:index") + ) + # Create a new user to ensure that no extra permissions have been set. + user = User.objects.create_user(username="new", password="newuser") + url = self.live_server_url + reverse("admin:auth_user_change", args=[user.id]) + self.selenium.get(url) + + # Scroll to the User permissions section. + user_permissions = self.selenium.find_element( + By.CSS_SELECTOR, "#id_user_permissions_from" + ) + ActionChains(self.selenium).move_to_element(user_permissions).perform() + self.take_screenshot("selectbox-available-perms-none-selected") + + # Select multiple permissions from the "Available" list. + ct = ContentType.objects.get_for_model(Permission) + perms = list(Permission.objects.filter(content_type=ct)) + for perm in perms: + elem = self.selenium.find_element( + By.CSS_SELECTOR, f"#id_user_permissions_from option[value='{perm.id}']" + ) + ActionChains(self.selenium).key_down(Keys.CONTROL).click(elem).key_up( + Keys.CONTROL + ).perform() + + # Move focus to other element. + self.selenium.find_element( + By.CSS_SELECTOR, "#id_user_permissions_input" + ).click() + self.take_screenshot("selectbox-available-perms-some-selected") + + # Move permissions to the "Chosen" list, but none is selected yet. + self.selenium.find_element( + By.CSS_SELECTOR, "#id_user_permissions_add_link" + ).click() + self.take_screenshot("selectbox-chosen-perms-none-selected") + + # Select some permissions from the "Chosen" list. + for perm in [perms[0], perms[-1]]: + elem = self.selenium.find_element( + By.CSS_SELECTOR, f"#id_user_permissions_to option[value='{perm.id}']" + ) + ActionChains(self.selenium).key_down(Keys.CONTROL).click(elem).key_up( + Keys.CONTROL + ).perform() + + # Move focus to other element. + self.selenium.find_element( + By.CSS_SELECTOR, "#id_user_permissions_selected_input" + ).click() + self.take_screenshot("selectbox-chosen-perms-some-selected") + @screenshot_cases(["desktop_size", "mobile_size", "rtl", "dark", "high_contrast"]) def test_first_field_focus(self): """JavaScript-assisted auto-focus on first usable form field.""" From 5bb433e99bc24625295e05448fdf173dc72028ad Mon Sep 17 00:00:00 2001 From: Natalia <124304+nessita@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:37:30 -0300 Subject: [PATCH 15/40] Added release date for 5.1.2. --- docs/releases/5.1.2.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/releases/5.1.2.txt b/docs/releases/5.1.2.txt index a7293654df..c6140adcb0 100644 --- a/docs/releases/5.1.2.txt +++ b/docs/releases/5.1.2.txt @@ -2,7 +2,7 @@ Django 5.1.2 release notes ========================== -*Expected October 8, 2024* +*October 8, 2024* Django 5.1.2 fixes several bugs in 5.1.1. Also, the latest string translations from Transifex are incorporated. From 4d11402932eca570850bdfa58a71eb59fc62275a Mon Sep 17 00:00:00 2001 From: Natalia <124304+nessita@users.noreply.github.com> Date: Tue, 8 Oct 2024 12:02:53 -0300 Subject: [PATCH 16/40] Added stub release notes for 5.1.3. --- docs/releases/5.1.3.txt | 12 ++++++++++++ docs/releases/index.txt | 1 + 2 files changed, 13 insertions(+) create mode 100644 docs/releases/5.1.3.txt diff --git a/docs/releases/5.1.3.txt b/docs/releases/5.1.3.txt new file mode 100644 index 0000000000..9cb48dc2f3 --- /dev/null +++ b/docs/releases/5.1.3.txt @@ -0,0 +1,12 @@ +========================== +Django 5.1.3 release notes +========================== + +*Expected November 5, 2024* + +Django 5.1.3 fixes several bugs in 5.1.2. + +Bugfixes +======== + +* ... diff --git a/docs/releases/index.txt b/docs/releases/index.txt index 689044cfe3..a38053c2a9 100644 --- a/docs/releases/index.txt +++ b/docs/releases/index.txt @@ -32,6 +32,7 @@ versions of the documentation contain the release notes for any later releases. .. toctree:: :maxdepth: 1 + 5.1.3 5.1.2 5.1.1 5.1 From 22e21ec641c6c533d31bef0db876c53207d14920 Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Tue, 8 Oct 2024 22:58:53 +0200 Subject: [PATCH 17/40] Bumped versions in pre-commit and npm configurations. --- .pre-commit-config.yaml | 10 +++++----- package.json | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a1a734accf..5f20568b34 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,15 +1,15 @@ repos: - repo: https://github.com/psf/black-pre-commit-mirror - rev: 24.4.2 + rev: 24.10.0 hooks: - id: black exclude: \.py-tpl$ - repo: https://github.com/adamchainz/blacken-docs - rev: 1.18.0 + rev: 1.19.0 hooks: - id: blacken-docs additional_dependencies: - - black==24.4.2 + - black==24.10.0 files: 'docs/.*\.txt$' args: ["--rst-literal-block"] - repo: https://github.com/PyCQA/isort @@ -17,10 +17,10 @@ repos: hooks: - id: isort - repo: https://github.com/PyCQA/flake8 - rev: 7.1.0 + rev: 7.1.1 hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-eslint - rev: v9.7.0 + rev: v9.12.0 hooks: - id: eslint diff --git a/package.json b/package.json index 0e6bb80f1c..b3bc782c40 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,8 @@ "npm": ">=1.3.0" }, "devDependencies": { - "eslint": "^9.7.0", - "puppeteer": "^22.13.1", + "eslint": "^9.12.0", + "puppeteer": "^23.5.1", "globals": "^15.8.0", "grunt": "^1.6.1", "grunt-cli": "^1.5.0", From f07eeff3a2d7ff0955410bf7e3f1ff197ef1ecf7 Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Tue, 8 Oct 2024 08:10:06 +0200 Subject: [PATCH 18/40] Refs #34900 -- Added Python 3.12 to classifiers and tox.ini, and used it in GitHub actions. --- .github/workflows/docs.yml | 4 ++-- .github/workflows/linters.yml | 4 ++-- .github/workflows/schedule_tests.yml | 10 +++++----- .github/workflows/selenium.yml | 4 ++-- .github/workflows/tests.yml | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 9b88b9be93..f61692ef79 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -30,7 +30,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13' cache: 'pip' cache-dependency-path: 'docs/requirements.txt' - run: python -m pip install -r docs/requirements.txt @@ -48,7 +48,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13' - run: python -m pip install blacken-docs - name: Build docs run: | diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 3875e755f9..7c64dc98ff 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -27,7 +27,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13' - run: python -m pip install flake8 - name: flake8 # Pinned to v3.0.0. @@ -44,7 +44,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13' - run: python -m pip install isort - name: isort # Pinned to v3.0.0. diff --git a/.github/workflows/schedule_tests.yml b/.github/workflows/schedule_tests.yml index 2cf62493c3..f99ef218aa 100644 --- a/.github/workflows/schedule_tests.yml +++ b/.github/workflows/schedule_tests.yml @@ -19,7 +19,7 @@ jobs: - '3.10' - '3.11' - '3.12' - - '3.13-dev' + - '3.13' name: Windows, SQLite, Python ${{ matrix.python-version }} continue-on-error: true steps: @@ -46,7 +46,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13' cache: 'pip' - name: Install libmemcached-dev for pylibmc run: sudo apt-get install libmemcached-dev @@ -145,7 +145,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13' cache: 'pip' cache-dependency-path: 'tests/requirements/py3.txt' - name: Install libmemcached-dev for pylibmc @@ -181,7 +181,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13' cache: 'pip' cache-dependency-path: 'tests/requirements/py3.txt' - name: Install libmemcached-dev for pylibmc @@ -226,7 +226,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13' cache: 'pip' cache-dependency-path: 'tests/requirements/py3.txt' - name: Install libmemcached-dev for pylibmc diff --git a/.github/workflows/selenium.yml b/.github/workflows/selenium.yml index 7e46e0cfb1..14a95f3b66 100644 --- a/.github/workflows/selenium.yml +++ b/.github/workflows/selenium.yml @@ -24,7 +24,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13' cache: 'pip' cache-dependency-path: 'tests/requirements/py3.txt' - name: Install libmemcached-dev for pylibmc @@ -61,7 +61,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13' cache: 'pip' cache-dependency-path: 'tests/requirements/py3.txt' - name: Install libmemcached-dev for pylibmc diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index abe7c78a25..5de554721d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -23,7 +23,7 @@ jobs: strategy: matrix: python-version: - - '3.12' + - '3.13' name: Windows, SQLite, Python ${{ matrix.python-version }} steps: - name: Checkout From 2e3bc59fd3760de87952ec8fd6cd3694e8d9dc1c Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Tue, 8 Oct 2024 08:14:54 +0200 Subject: [PATCH 19/40] Refs #34900 -- Doc'd Python 3.13 compatibility. --- docs/faq/install.txt | 2 +- docs/howto/windows.txt | 4 ++-- docs/intro/reusable-apps.txt | 1 + docs/releases/5.1.3.txt | 3 ++- docs/releases/5.1.txt | 5 +++-- pyproject.toml | 1 + tox.ini | 2 +- 7 files changed, 11 insertions(+), 7 deletions(-) diff --git a/docs/faq/install.txt b/docs/faq/install.txt index ddb84d6d9c..4623e288fb 100644 --- a/docs/faq/install.txt +++ b/docs/faq/install.txt @@ -52,7 +52,7 @@ Django version Python versions ============== =============== 4.2 3.8, 3.9, 3.10, 3.11, 3.12 (added in 4.2.8) 5.0 3.10, 3.11, 3.12 -5.1 3.10, 3.11, 3.12 +5.1 3.10, 3.11, 3.12, 3.13 (added in 5.1.3) 5.2 3.10, 3.11, 3.12, 3.13 ============== =============== diff --git a/docs/howto/windows.txt b/docs/howto/windows.txt index 83aa8d0655..235b18a24f 100644 --- a/docs/howto/windows.txt +++ b/docs/howto/windows.txt @@ -2,7 +2,7 @@ How to install Django on Windows ================================ -This document will guide you through installing Python 3.12 and Django on +This document will guide you through installing Python 3.13 and Django on Windows. It also provides instructions for setting up a virtual environment, which makes it easier to work on Python projects. This is meant as a beginner's guide for users working on Django projects and does not reflect how Django @@ -18,7 +18,7 @@ Install Python ============== Django is a Python web framework, thus requiring Python to be installed on your -machine. At the time of writing, Python 3.12 is the latest version. +machine. At the time of writing, Python 3.13 is the latest version. To install Python on your machine go to https://www.python.org/downloads/. The website should offer you a download button for the latest Python version. diff --git a/docs/intro/reusable-apps.txt b/docs/intro/reusable-apps.txt index 98f21c9d91..e2c25f3525 100644 --- a/docs/intro/reusable-apps.txt +++ b/docs/intro/reusable-apps.txt @@ -237,6 +237,7 @@ this. For a small app like polls, this process isn't too difficult. "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", ] diff --git a/docs/releases/5.1.3.txt b/docs/releases/5.1.3.txt index 9cb48dc2f3..5541a8824a 100644 --- a/docs/releases/5.1.3.txt +++ b/docs/releases/5.1.3.txt @@ -4,7 +4,8 @@ Django 5.1.3 release notes *Expected November 5, 2024* -Django 5.1.3 fixes several bugs in 5.1.2. +Django 5.1.3 fixes several bugs in 5.1.2 and adds compatibility with Python +3.13. Bugfixes ======== diff --git a/docs/releases/5.1.txt b/docs/releases/5.1.txt index bc868fddda..037c76fd54 100644 --- a/docs/releases/5.1.txt +++ b/docs/releases/5.1.txt @@ -18,8 +18,9 @@ project. Python compatibility ==================== -Django 5.1 supports Python 3.10, 3.11, and 3.12. We **highly recommend** and -only officially support the latest release of each series. +Django 5.1 supports Python 3.10, 3.11, 3.12, and 3.13 (as of 5.1.3). We +**highly recommend** and only officially support the latest release of each +series. .. _whats-new-5.1: diff --git a/pyproject.toml b/pyproject.toml index 540bc47439..86ea7393ec 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,7 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Internet :: WWW/HTTP :: WSGI", diff --git a/tox.ini b/tox.ini index c635a129b2..7a76693f21 100644 --- a/tox.ini +++ b/tox.ini @@ -26,7 +26,7 @@ setenv = PYTHONDONTWRITEBYTECODE=1 deps = -e . - py{3,310,311,312,py3}: -rtests/requirements/py3.txt + py{3,310,311,312,313,py3}: -rtests/requirements/py3.txt postgres: -rtests/requirements/postgres.txt mysql: -rtests/requirements/mysql.txt oracle: -rtests/requirements/oracle.txt From d2c74cfb48a3d29159732fb98e3c28a53572067f Mon Sep 17 00:00:00 2001 From: Meta Date: Wed, 7 Aug 2024 16:07:22 -0300 Subject: [PATCH 20/40] Fixed #35502 -- Removed duplication of "mysite" directory name in intro docs. Reorganized intro docs when explaining `django-admin startproject` to prevent confusion when using "mysite" as both the top-level directory and the Django project directory name. Co-authored-by: Natalia <124304+nessita@users.noreply.github.com> Co-authored-by: Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> Co-authored-by: Carlton Gibson --- docs/intro/overview.txt | 14 +++++++------- docs/intro/reusable-apps.txt | 14 +++++++------- docs/intro/tutorial01.txt | 32 +++++++++++++++++--------------- docs/intro/tutorial05.txt | 2 +- docs/intro/tutorial07.txt | 8 ++++---- docs/spelling_wordlist | 1 + 6 files changed, 37 insertions(+), 34 deletions(-) diff --git a/docs/intro/overview.txt b/docs/intro/overview.txt index 8314b3d351..0c41446d01 100644 --- a/docs/intro/overview.txt +++ b/docs/intro/overview.txt @@ -26,7 +26,7 @@ representing your models -- so far, it's been solving many years' worth of database-schema problems. Here's a quick example: .. code-block:: python - :caption: ``mysite/news/models.py`` + :caption: ``news/models.py`` from django.db import models @@ -151,7 +151,7 @@ a website that lets authenticated users add, change and delete objects. The only step required is to register your model in the admin site: .. code-block:: python - :caption: ``mysite/news/models.py`` + :caption: ``news/models.py`` from django.db import models @@ -163,7 +163,7 @@ only step required is to register your model in the admin site: reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE) .. code-block:: python - :caption: ``mysite/news/admin.py`` + :caption: ``news/admin.py`` from django.contrib import admin @@ -195,7 +195,7 @@ Here's what a URLconf might look like for the ``Reporter``/``Article`` example above: .. code-block:: python - :caption: ``mysite/news/urls.py`` + :caption: ``news/urls.py`` from django.urls import path @@ -235,7 +235,7 @@ and renders the template with the retrieved data. Here's an example view for ``year_archive`` from above: .. code-block:: python - :caption: ``mysite/news/views.py`` + :caption: ``news/views.py`` from django.shortcuts import render @@ -265,7 +265,7 @@ Let's say the ``news/year_archive.html`` template was found. Here's what that might look like: .. code-block:: html+django - :caption: ``mysite/news/templates/news/year_archive.html`` + :caption: ``news/templates/news/year_archive.html`` {% extends "base.html" %} @@ -306,7 +306,7 @@ Here's what the "base.html" template, including the use of :doc:`static files `, might look like: .. code-block:: html+django - :caption: ``mysite/templates/base.html`` + :caption: ``templates/base.html`` {% load static %} diff --git a/docs/intro/reusable-apps.txt b/docs/intro/reusable-apps.txt index e2c25f3525..a9c0768e3b 100644 --- a/docs/intro/reusable-apps.txt +++ b/docs/intro/reusable-apps.txt @@ -57,7 +57,7 @@ After the previous tutorials, our project should look like this: .. code-block:: text - mysite/ + djangotutorial/ manage.py mysite/ __init__.py @@ -90,12 +90,12 @@ After the previous tutorials, our project should look like this: admin/ base_site.html -You created ``mysite/templates`` in :doc:`Tutorial 7 `, -and ``polls/templates`` in :doc:`Tutorial 3 `. Now perhaps -it is clearer why we chose to have separate template directories for the -project and application: everything that is part of the polls application is in -``polls``. It makes the application self-contained and easier to drop into a -new project. +You created ``djangotutorial/templates`` in :doc:`Tutorial 7 +`, and ``polls/templates`` in +:doc:`Tutorial 3 `. Now perhaps it is clearer why we chose +to have separate template directories for the project and application: +everything that is part of the polls application is in ``polls``. It makes the +application self-contained and easier to drop into a new project. The ``polls`` directory could now be copied into a new Django project and immediately reused. It's not quite ready to be published though. For that, we diff --git a/docs/intro/tutorial01.txt b/docs/intro/tutorial01.txt index d45fa6bcb6..041da0a404 100644 --- a/docs/intro/tutorial01.txt +++ b/docs/intro/tutorial01.txt @@ -48,14 +48,21 @@ including database configuration, Django-specific options and application-specific settings. From the command line, ``cd`` into a directory where you'd like to store your -code, then run the following command: +code and create a new directory named ``djangotutorial``. (This directory name +doesn't matter to Django; you can rename it to anything you like.) .. console:: - $ django-admin startproject mysite + $ mkdir djangotutorial -This will create a ``mysite`` directory in your current directory. If it didn't -work, see :ref:`troubleshooting-django-admin`. +Then, run the following command to bootstrap a new Django project: + +.. console:: + + $ django-admin startproject mysite djangotutorial + +This will create a project called ``mysite`` inside the ``djangotutorial`` +directory. If it didn't work, see :ref:`troubleshooting-django-admin`. .. note:: @@ -68,7 +75,7 @@ Let's look at what :djadmin:`startproject` created: .. code-block:: text - mysite/ + djangotutorial/ manage.py mysite/ __init__.py @@ -79,14 +86,11 @@ Let's look at what :djadmin:`startproject` created: These files are: -* The outer :file:`mysite/` root directory is a container for your project. Its - name doesn't matter to Django; you can rename it to anything you like. - * :file:`manage.py`: A command-line utility that lets you interact with this Django project in various ways. You can read all the details about :file:`manage.py` in :doc:`/ref/django-admin`. -* The inner :file:`mysite/` directory is the actual Python package for your +* :file:`mysite/`: A directory that is the actual Python package for your project. Its name is the Python package name you'll need to use to import anything inside it (e.g. ``mysite.urls``). @@ -111,8 +115,8 @@ These files are: The development server ====================== -Let's verify your Django project works. Change into the outer :file:`mysite` directory, if -you haven't already, and run the following commands: +Let's verify your Django project works. Change into the :file:`djangotutorial` +directory, if you haven't already, and run the following commands: .. console:: @@ -182,10 +186,8 @@ rather than creating directories. configuration and apps for a particular website. A project can contain multiple apps. An app can be in multiple projects. -Your apps can live anywhere on your :ref:`Python path `. In -this tutorial, we'll create our poll app in the same directory as your -:file:`manage.py` file so that it can be imported as its own top-level module, -rather than a submodule of ``mysite``. +Your apps can live anywhere in your :ref:`Python path `. In +this tutorial, we'll create our poll app inside the ``djangotutorial`` folder. To create your app, make sure you're in the same directory as :file:`manage.py` and type this command: diff --git a/docs/intro/tutorial05.txt b/docs/intro/tutorial05.txt index 5f501ce92f..28a634b8c3 100644 --- a/docs/intro/tutorial05.txt +++ b/docs/intro/tutorial05.txt @@ -216,7 +216,7 @@ and you'll see something like: FAIL: test_was_published_recently_with_future_question (polls.tests.QuestionModelTests) ---------------------------------------------------------------------- Traceback (most recent call last): - File "/path/to/mysite/polls/tests.py", line 16, in test_was_published_recently_with_future_question + File "/path/to/djangotutorial/polls/tests.py", line 16, in test_was_published_recently_with_future_question self.assertIs(future_question.was_published_recently(), False) AssertionError: True is not False diff --git a/docs/intro/tutorial07.txt b/docs/intro/tutorial07.txt index 60a5c43bb3..a8d5e61b81 100644 --- a/docs/intro/tutorial07.txt +++ b/docs/intro/tutorial07.txt @@ -306,10 +306,10 @@ powered by Django itself, and its interfaces use Django's own template system. Customizing your *project's* templates -------------------------------------- -Create a ``templates`` directory in your project directory (the one that -contains ``manage.py``). Templates can live anywhere on your filesystem that -Django can access. (Django runs as whatever user your server runs.) However, -keeping your templates within the project is a good convention to follow. +Create a ``templates`` directory in your ``djangotutorial`` directory. +Templates can live anywhere on your filesystem that Django can access. (Django +runs as whatever user your server runs.) However, keeping your templates within +the project is a good convention to follow. Open your settings file (:file:`mysite/settings.py`, remember) and add a :setting:`DIRS ` option in the :setting:`TEMPLATES` setting: diff --git a/docs/spelling_wordlist b/docs/spelling_wordlist index d715e62e05..d30f2ce440 100644 --- a/docs/spelling_wordlist +++ b/docs/spelling_wordlist @@ -141,6 +141,7 @@ Disqus distro django djangoproject +djangotutorial dm docstring docstrings From fc1119e8be705766b0277a0ebf8ad637f9d068c2 Mon Sep 17 00:00:00 2001 From: Natalia <124304+nessita@users.noreply.github.com> Date: Wed, 7 Aug 2024 16:08:21 -0300 Subject: [PATCH 21/40] Refs #35502 -- Clarified models.py file path in docs/topics/db/queries.txt. --- docs/topics/db/queries.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/topics/db/queries.txt b/docs/topics/db/queries.txt index 45c6183103..7e3338eaea 100644 --- a/docs/topics/db/queries.txt +++ b/docs/topics/db/queries.txt @@ -62,7 +62,8 @@ class represents a particular record in the database table. To create an object, instantiate it using keyword arguments to the model class, then call :meth:`~django.db.models.Model.save` to save it to the database. -Assuming models live in a file ``mysite/blog/models.py``, here's an example: +Assuming models live in a ``models.py`` file inside a ``blog`` Django app, here +is an example: .. code-block:: pycon From 470f4c2436e00873a31673a5992c5260b2de4e97 Mon Sep 17 00:00:00 2001 From: nessita <124304+nessita@users.noreply.github.com> Date: Wed, 9 Oct 2024 10:19:12 -0300 Subject: [PATCH 22/40] Added GitHub Action workflow to test all Python versions listed in the project config file. --- .github/workflows/python_matrix.yml | 52 +++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .github/workflows/python_matrix.yml diff --git a/.github/workflows/python_matrix.yml b/.github/workflows/python_matrix.yml new file mode 100644 index 0000000000..ab48c2be83 --- /dev/null +++ b/.github/workflows/python_matrix.yml @@ -0,0 +1,52 @@ +name: Python Matrix from config file + +on: + pull_request: + types: [labeled, synchronize, opened, reopened] + paths-ignore: + - 'docs/**' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + define-matrix: + if: contains(github.event.pull_request.labels.*.name, 'python-matrix') + runs-on: ubuntu-latest + outputs: + python_versions_output: ${{ steps.set-matrix.outputs.python_versions }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + - id: set-matrix + run: | + python_versions=$(sed -n "s/^.*Programming Language :: Python :: \([[:digit:]]\+\.[[:digit:]]\+\).*$/'\1', /p" pyproject.toml | tr -d '\n' | sed 's/, $//g') + echo "Supported Python versions: $python_versions" + echo "python_versions=[$python_versions]" >> "$GITHUB_OUTPUT" + python: + runs-on: ubuntu-latest + needs: define-matrix + strategy: + matrix: + python-version: ${{ fromJson(needs.define-matrix.outputs.python_versions_output) }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: 'pip' + cache-dependency-path: 'tests/requirements/py3.txt' + - name: Install libmemcached-dev for pylibmc + run: sudo apt-get install libmemcached-dev + - name: Install and upgrade packaging tools + run: python -m pip install --upgrade pip setuptools wheel + - run: python -m pip install -r tests/requirements/py3.txt -e . + - name: Run tests + run: python tests/runtests.py -v2 From d4e4520efb553d2bfcc68ac8cf007c0c402d4845 Mon Sep 17 00:00:00 2001 From: Bona Fide IT GmbH <137388433+BonaFideIT@users.noreply.github.com> Date: Sat, 28 Sep 2024 11:36:38 +0200 Subject: [PATCH 23/40] Fixed #35792 -- Simplified ModelBackend._get_group_permissions(). --- django/contrib/auth/backends.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/django/contrib/auth/backends.py b/django/contrib/auth/backends.py index f14fb3e96f..8352530665 100644 --- a/django/contrib/auth/backends.py +++ b/django/contrib/auth/backends.py @@ -99,9 +99,7 @@ class ModelBackend(BaseBackend): return user_obj.user_permissions.all() def _get_group_permissions(self, user_obj): - user_groups_field = get_user_model()._meta.get_field("groups") - user_groups_query = "group__%s" % user_groups_field.related_query_name() - return Permission.objects.filter(**{user_groups_query: user_obj}) + return Permission.objects.filter(group__in=user_obj.groups.all()) def _get_permissions(self, user_obj, obj, from_name): """ From 40a60d589e1d0d290c3b79c7e97d9cd0c94e52e3 Mon Sep 17 00:00:00 2001 From: Chiara Mezzavilla <2512470+samurang87@users.noreply.github.com> Date: Wed, 9 Oct 2024 16:46:26 +0200 Subject: [PATCH 24/40] Explained exception to using include() within urlpatterns in tutorial 1. --- docs/intro/tutorial01.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/intro/tutorial01.txt b/docs/intro/tutorial01.txt index 041da0a404..c5ac5a1107 100644 --- a/docs/intro/tutorial01.txt +++ b/docs/intro/tutorial01.txt @@ -293,7 +293,8 @@ app will still work. .. admonition:: When to use :func:`~django.urls.include()` You should always use ``include()`` when you include other URL patterns. - ``admin.site.urls`` is the only exception to this. + The only exception is ``admin.site.urls``, which is a pre-built URLconf + provided by Django for the default admin site. You have now wired an ``index`` view into the URLconf. Verify it's working with the following command: From 6db89aa6c4b81838e2158e17f0a53c13711d3a52 Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Wed, 9 Oct 2024 20:46:25 +0200 Subject: [PATCH 25/40] Fixed typo in docs/releases/5.2.txt. --- docs/releases/5.2.txt | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/releases/5.2.txt b/docs/releases/5.2.txt index 9aa232b902..5c5020a3f4 100644 --- a/docs/releases/5.2.txt +++ b/docs/releases/5.2.txt @@ -52,29 +52,29 @@ Minor features * The default iteration count for the PBKDF2 password hasher is increased from 870,000 to 1,000,000. -* The following new asynchronous methods on are now provided, using an ``a`` +* The following new asynchronous methods are now provided, using an ``a`` prefix: * :meth:`.UserManager.acreate_user` * :meth:`.UserManager.acreate_superuser` * :meth:`.BaseUserManager.aget_by_natural_key` - * :meth:`.User.aget_user_permissions()` - * :meth:`.User.aget_all_permissions()` - * :meth:`.User.aget_group_permissions()` - * :meth:`.User.ahas_perm()` - * :meth:`.User.ahas_perms()` - * :meth:`.User.ahas_module_perms()` - * :meth:`.User.aget_user_permissions()` - * :meth:`.User.aget_group_permissions()` - * :meth:`.User.ahas_perm()` - * :meth:`.ModelBackend.aauthenticate()` - * :meth:`.ModelBackend.aget_user_permissions()` - * :meth:`.ModelBackend.aget_group_permissions()` - * :meth:`.ModelBackend.aget_all_permissions()` - * :meth:`.ModelBackend.ahas_perm()` - * :meth:`.ModelBackend.ahas_module_perms()` - * :meth:`.RemoteUserBackend.aauthenticate()` - * :meth:`.RemoteUserBackend.aconfigure_user()` + * :meth:`.User.aget_user_permissions` + * :meth:`.User.aget_all_permissions` + * :meth:`.User.aget_group_permissions` + * :meth:`.User.ahas_perm` + * :meth:`.User.ahas_perms` + * :meth:`.User.ahas_module_perms` + * :meth:`.User.aget_user_permissions` + * :meth:`.User.aget_group_permissions` + * :meth:`.User.ahas_perm` + * :meth:`.ModelBackend.aauthenticate` + * :meth:`.ModelBackend.aget_user_permissions` + * :meth:`.ModelBackend.aget_group_permissions` + * :meth:`.ModelBackend.aget_all_permissions` + * :meth:`.ModelBackend.ahas_perm` + * :meth:`.ModelBackend.ahas_module_perms` + * :meth:`.RemoteUserBackend.aauthenticate` + * :meth:`.RemoteUserBackend.aconfigure_user` * Auth backends can now provide async implementations which are used when calling async auth functions (e.g. From 1979b1403adeb437831a1a8885353e158ec9ad55 Mon Sep 17 00:00:00 2001 From: Baptiste Mispelon Date: Wed, 9 Oct 2024 11:33:32 +0200 Subject: [PATCH 26/40] Fixed docstring for django.core.exceptions module. --- django/core/exceptions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/django/core/exceptions.py b/django/core/exceptions.py index 31c18ee7e1..7a02aa19df 100644 --- a/django/core/exceptions.py +++ b/django/core/exceptions.py @@ -1,5 +1,5 @@ """ -Global Django exception and warning classes. +Global Django exception classes. """ import operator From e970bb7ca71c00594b42a024a15a8ac007cc2c7a Mon Sep 17 00:00:00 2001 From: gabn88 Date: Thu, 11 Jan 2024 17:43:52 +0100 Subject: [PATCH 27/40] Fixed #35103 -- Used provided error code and message when fields is set without a condition on UniqueConstraint. --- django/db/models/constraints.py | 16 +++++++--- docs/ref/models/constraints.txt | 52 +++++++++++++++++++++++---------- docs/releases/5.2.txt | 5 ++++ tests/constraints/models.py | 4 +-- tests/constraints/tests.py | 35 ++++++++++++++++++++++ 5 files changed, 89 insertions(+), 23 deletions(-) diff --git a/django/db/models/constraints.py b/django/db/models/constraints.py index 3859a60e2f..788e2b635b 100644 --- a/django/db/models/constraints.py +++ b/django/db/models/constraints.py @@ -690,11 +690,19 @@ class UniqueConstraint(BaseConstraint): queryset = queryset.exclude(pk=model_class_pk) if not self.condition: if queryset.exists(): - if self.fields: - # When fields are defined, use the unique_error_message() for - # backward compatibility. + if ( + self.fields + and self.violation_error_message + == self.default_violation_error_message + ): + # When fields are defined, use the unique_error_message() as + # a default for backward compatibility. + validation_error_message = instance.unique_error_message( + model, self.fields + ) raise ValidationError( - instance.unique_error_message(model, self.fields), + validation_error_message, + code=validation_error_message.code, ) raise ValidationError( self.get_violation_error_message(), diff --git a/docs/ref/models/constraints.txt b/docs/ref/models/constraints.txt index 7dfc3b7d28..c1f140c265 100644 --- a/docs/ref/models/constraints.txt +++ b/docs/ref/models/constraints.txt @@ -282,27 +282,47 @@ PostgreSQL 15+. .. attribute:: UniqueConstraint.violation_error_code -The error code used when ``ValidationError`` is raised during -:ref:`model validation `. Defaults to ``None``. +The error code used when a ``ValidationError`` is raised during +:ref:`model validation `. -This code is *not used* for :class:`UniqueConstraint`\s with -:attr:`~UniqueConstraint.fields` and without a -:attr:`~UniqueConstraint.condition`. Such :class:`~UniqueConstraint`\s have the -same error code as constraints defined with :attr:`.Field.unique` or in -:attr:`Meta.unique_together `. +Defaults to :attr:`.BaseConstraint.violation_error_code`, when either +:attr:`.UniqueConstraint.condition` is set or :attr:`.UniqueConstraint.fields` +is not set. + +If :attr:`.UniqueConstraint.fields` is set without a +:attr:`.UniqueConstraint.condition`, defaults to the :attr:`Meta.unique_together +` error code when there are multiple +fields, and to the :attr:`.Field.unique` error code when there is a single +field. + +.. versionchanged:: 5.2 + + In older versions, the provided + :attr:`.UniqueConstraint.violation_error_code` was not used when + :attr:`.UniqueConstraint.fields` was set without a + :attr:`.UniqueConstraint.condition`. ``violation_error_message`` --------------------------- .. attribute:: UniqueConstraint.violation_error_message -The error message used when ``ValidationError`` is raised during -:ref:`model validation `. Defaults to -:attr:`.BaseConstraint.violation_error_message`. +The error message used when a ``ValidationError`` is raised during +:ref:`model validation `. -This message is *not used* for :class:`UniqueConstraint`\s with -:attr:`~UniqueConstraint.fields` and without a -:attr:`~UniqueConstraint.condition`. Such :class:`~UniqueConstraint`\s show the -same message as constraints defined with -:attr:`.Field.unique` or in -:attr:`Meta.unique_together `. +Defaults to :attr:`.BaseConstraint.violation_error_message`, when either +:attr:`.UniqueConstraint.condition` is set or :attr:`.UniqueConstraint.fields` +is not set. + +If :attr:`.UniqueConstraint.fields` is set without a +:attr:`.UniqueConstraint.condition`, defaults to the :attr:`Meta.unique_together +` error message when there are +multiple fields, and to the :attr:`.Field.unique` error message when there is a +single field. + +.. versionchanged:: 5.2 + + In older versions, the provided + :attr:`.UniqueConstraint.violation_error_message` was not used when + :attr:`.UniqueConstraint.fields` was set without a + :attr:`.UniqueConstraint.condition`. diff --git a/docs/releases/5.2.txt b/docs/releases/5.2.txt index 5c5020a3f4..eabc27c277 100644 --- a/docs/releases/5.2.txt +++ b/docs/releases/5.2.txt @@ -358,6 +358,11 @@ Miscellaneous * ``HttpRequest.accepted_types`` is now sorted by the client's preference, based on the request's ``Accept`` header. +* :attr:`.UniqueConstraint.violation_error_code` and + :attr:`.UniqueConstraint.violation_error_message` are now always used when + provided. Previously, these were ignored when :attr:`.UniqueConstraint.fields` + were set without a :attr:`.UniqueConstraint.condition`. + * The :func:`~django.template.context_processors.debug` context processor is no longer included in the default project template. diff --git a/tests/constraints/models.py b/tests/constraints/models.py index 829f671cdd..95a29ffa4d 100644 --- a/tests/constraints/models.py +++ b/tests/constraints/models.py @@ -72,15 +72,13 @@ class GeneratedFieldVirtualProduct(models.Model): class UniqueConstraintProduct(models.Model): name = models.CharField(max_length=255) color = models.CharField(max_length=32, null=True) + age = models.IntegerField(null=True) class Meta: constraints = [ models.UniqueConstraint( fields=["name", "color"], name="name_color_uniq", - # Custom message and error code are ignored. - violation_error_code="custom_code", - violation_error_message="Custom message", ) ] diff --git a/tests/constraints/tests.py b/tests/constraints/tests.py index e1c431956f..9047710098 100644 --- a/tests/constraints/tests.py +++ b/tests/constraints/tests.py @@ -953,6 +953,41 @@ class UniqueConstraintTests(TestCase): ChildUniqueConstraintProduct(name=self.p1.name, color=self.p1.color), ) + def test_validate_unique_custom_code_and_message(self): + product = UniqueConstraintProduct.objects.create( + name="test", color="red", age=42 + ) + code = "custom_code" + message = "Custom message" + multiple_fields_constraint = models.UniqueConstraint( + fields=["color", "age"], + name="color_age_uniq", + violation_error_code=code, + violation_error_message=message, + ) + single_field_constraint = models.UniqueConstraint( + fields=["color"], + name="color_uniq", + violation_error_code=code, + violation_error_message=message, + ) + + with self.assertRaisesMessage(ValidationError, message) as cm: + multiple_fields_constraint.validate( + UniqueConstraintProduct, + UniqueConstraintProduct( + name="new-test", color=product.color, age=product.age + ), + ) + self.assertEqual(cm.exception.code, code) + + with self.assertRaisesMessage(ValidationError, message) as cm: + single_field_constraint.validate( + UniqueConstraintProduct, + UniqueConstraintProduct(name="new-test", color=product.color), + ) + self.assertEqual(cm.exception.code, code) + @skipUnlessDBFeature("supports_table_check_constraints") def test_validate_fields_unattached(self): Product.objects.create(price=42) From 68cee15a8fd65bd6ee2329d80331f87cadd97ff5 Mon Sep 17 00:00:00 2001 From: ekinertac Date: Sun, 6 Oct 2024 15:29:35 +0300 Subject: [PATCH 28/40] Fixed #35789 -- Improved the error message raised when the tag must be first in the template. --- django/template/base.py | 6 +++++- tests/template_tests/test_extends.py | 18 ++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/django/template/base.py b/django/template/base.py index ee2e145c04..b974495c9c 100644 --- a/django/template/base.py +++ b/django/template/base.py @@ -533,9 +533,13 @@ class Parser: def extend_nodelist(self, nodelist, node, token): # Check that non-text nodes don't appear before an extends tag. if node.must_be_first and nodelist.contains_nontext: + if self.origin.template_name: + origin = repr(self.origin.template_name) + else: + origin = "the template" raise self.error( token, - "%r must be the first tag in the template." % node, + "{%% %s %%} must be the first tag in %s." % (token.contents, origin), ) if not isinstance(node, TextNode): nodelist.contains_nontext = True diff --git a/tests/template_tests/test_extends.py b/tests/template_tests/test_extends.py index ce1838654b..0d2a93468c 100644 --- a/tests/template_tests/test_extends.py +++ b/tests/template_tests/test_extends.py @@ -1,9 +1,9 @@ import os -from django.template import Context, Engine, TemplateDoesNotExist +from django.template import Context, Engine, TemplateDoesNotExist, TemplateSyntaxError from django.test import SimpleTestCase -from .utils import ROOT +from .utils import ROOT, setup RECURSIVE = os.path.join(ROOT, "recursive_templates") @@ -181,3 +181,17 @@ class ExtendsBehaviorTests(SimpleTestCase): ) template = engine.get_template("base.html") self.assertEqual(template.render(Context({})), "12AB") + + @setup( + {"index.html": "{% block content %}B{% endblock %}{% extends 'base.html' %}"} + ) + def test_extends_not_first_tag_in_extended_template(self): + msg = "{% extends 'base.html' %} must be the first tag in 'index.html'." + with self.assertRaisesMessage(TemplateSyntaxError, msg): + self.engine.get_template("index.html") + + def test_extends_not_first_tag_in_extended_template_from_string(self): + template_string = "{% block content %}B{% endblock %}{% extends 'base.html' %}" + msg = "{% extends 'base.html' %} must be the first tag in the template." + with self.assertRaisesMessage(TemplateSyntaxError, msg): + Engine().from_string(template_string) From cee95e6172f2ea3dbf8cfd4214562cfc92f95392 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Thu, 29 Aug 2024 18:52:31 +0100 Subject: [PATCH 29/40] Fixed #35717 -- Reduced Create/RemoveCollation operations when optimizing migrations. --- django/contrib/postgres/operations.py | 5 +++++ tests/postgres_tests/test_operations.py | 20 +++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/django/contrib/postgres/operations.py b/django/contrib/postgres/operations.py index 1ee5fbc2e2..84360febf9 100644 --- a/django/contrib/postgres/operations.py +++ b/django/contrib/postgres/operations.py @@ -237,6 +237,11 @@ class CreateCollation(CollationOperation): def migration_name_fragment(self): return "create_collation_%s" % self.name.lower() + def reduce(self, operation, app_label): + if isinstance(operation, RemoveCollation) and self.name == operation.name: + return [] + return super().reduce(operation, app_label) + class RemoveCollation(CollationOperation): """Remove a collation.""" diff --git a/tests/postgres_tests/test_operations.py b/tests/postgres_tests/test_operations.py index f344d4ae74..322f38148b 100644 --- a/tests/postgres_tests/test_operations.py +++ b/tests/postgres_tests/test_operations.py @@ -318,7 +318,7 @@ class CreateExtensionTests(PostgreSQLTestCase): @unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL specific tests.") -class CreateCollationTests(PostgreSQLTestCase): +class CreateCollationTests(OptimizerTestBase, PostgreSQLTestCase): app_label = "test_allow_create_collation" @override_settings(DATABASE_ROUTERS=[NoMigrationRouter()]) @@ -459,6 +459,24 @@ class CreateCollationTests(PostgreSQLTestCase): "),", ) + def test_reduce_create_remove(self): + self.assertOptimizesTo( + [ + CreateCollation( + "sample_collation", + "und-u-ks-level2", + provider="icu", + deterministic=False, + ), + RemoveCollation( + "sample_collation", + # Different locale + "de-u-ks-level1", + ), + ], + [], + ) + @unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL specific tests.") class RemoveCollationTests(PostgreSQLTestCase): From 9423f8b47673779049f603a7da271d183de7dc1d Mon Sep 17 00:00:00 2001 From: Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:47:10 +0200 Subject: [PATCH 30/40] Fixed #35612 -- Added documentation on how the security team evaluates reports. Co-authored-by: Joshua Olatunji --- docs/internals/security.txt | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/docs/internals/security.txt b/docs/internals/security.txt index 55300b01e1..6aac9a6b66 100644 --- a/docs/internals/security.txt +++ b/docs/internals/security.txt @@ -38,6 +38,41 @@ action to be taken, you may receive further followup emails. .. _our public Trac instance: https://code.djangoproject.com/query +.. _security-report-evaluation: + +How does Django evaluate a report +================================= + +These are criteria used by the security team when evaluating whether a report +requires a security release: + +* The vulnerability is within a :ref:`supported version ` of + Django. + +* The vulnerability applies to a production-grade Django application. This means + the following do not require a security release: + + * Exploits that only affect local development, for example when using + :djadmin:`runserver`. + * Exploits which fail to follow security best practices, such as failure to + sanitize user input. For other examples, see our :ref:`security + documentation `. + * Exploits in AI generated code that do not adhere to security best practices. + +The security team may conclude that the source of the vulnerability is within +the Python standard library, in which case the reporter will be asked to report +the vulnerability to the Python core team. For further details see the `Python +security guidelines `_. + +On occasion, a security release may be issued to help resolve a security +vulnerability within a popular third-party package. These reports should come +from the package maintainers. + +If you are unsure whether your finding meets these criteria, please still report +it :ref:`privately by emailing security@djangoproject.com +`. The security team will review your report and +recommend the correct course of action. + .. _security-support: Supported versions From 263f7319192b217c4e3b1eea0ea7809836392bbc Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Fri, 11 Oct 2024 13:50:51 +0200 Subject: [PATCH 31/40] Fixed docs build on Sphinx 8.1+. Sphinx 8.1 added :cve: role, so there is no need to define it in Django: - https://github.com/sphinx-doc/sphinx/pull/11781 This also changes used URL to the one used by Python and soonish to be used by Sphinx itself: - https://github.com/sphinx-doc/sphinx/pull/13006 --- docs/conf.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index b72b1afcf5..9289e821fa 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -13,6 +13,8 @@ import functools import sys from os.path import abspath, dirname, join +from sphinx import version_info as sphinx_version + # Workaround for sphinx-build recursion limit overflow: # pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL) # RuntimeError: maximum recursion depth exceeded while pickling an object @@ -138,13 +140,15 @@ django_next_version = "5.2" extlinks = { "bpo": ("https://bugs.python.org/issue?@action=redirect&bpo=%s", "bpo-%s"), "commit": ("https://github.com/django/django/commit/%s", "%s"), - "cve": ("https://nvd.nist.gov/vuln/detail/CVE-%s", "CVE-%s"), "pypi": ("https://pypi.org/project/%s/", "%s"), # A file or directory. GitHub redirects from blob to tree if needed. "source": ("https://github.com/django/django/blob/main/%s", "%s"), "ticket": ("https://code.djangoproject.com/ticket/%s", "#%s"), } +if sphinx_version < (8, 1): + extlinks["cve"] = ("https://www.cve.org/CVERecord?id=CVE-%s", "CVE-%s") + # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # language = None From 97c05a64ca87253e9789ebaab4b6d20a1b2370cf Mon Sep 17 00:00:00 2001 From: Bendeguz Csirmaz Date: Fri, 27 Sep 2024 00:04:33 +0800 Subject: [PATCH 32/40] Refs #373 -- Added additional validations to tuple lookups. --- django/db/models/fields/tuple_lookups.py | 36 ++++++- tests/foreign_object/test_tuple_lookups.py | 110 ++++++++++++++++++++- 2 files changed, 139 insertions(+), 7 deletions(-) diff --git a/django/db/models/fields/tuple_lookups.py b/django/db/models/fields/tuple_lookups.py index eb2d80b20f..a94582db95 100644 --- a/django/db/models/fields/tuple_lookups.py +++ b/django/db/models/fields/tuple_lookups.py @@ -2,7 +2,7 @@ import itertools from django.core.exceptions import EmptyResultSet from django.db.models import Field -from django.db.models.expressions import Func, Value +from django.db.models.expressions import ColPairs, Func, Value from django.db.models.lookups import ( Exact, GreaterThan, @@ -28,17 +28,32 @@ class Tuple(Func): class TupleLookupMixin: def get_prep_lookup(self): + self.check_rhs_is_tuple_or_list() self.check_rhs_length_equals_lhs_length() return self.rhs + def check_rhs_is_tuple_or_list(self): + if not isinstance(self.rhs, (tuple, list)): + lhs_str = self.get_lhs_str() + raise ValueError( + f"{self.lookup_name!r} lookup of {lhs_str} must be a tuple or a list" + ) + def check_rhs_length_equals_lhs_length(self): len_lhs = len(self.lhs) if len_lhs != len(self.rhs): + lhs_str = self.get_lhs_str() raise ValueError( - f"'{self.lookup_name}' lookup of '{self.lhs.field.name}' field " - f"must have {len_lhs} elements" + f"{self.lookup_name!r} lookup of {lhs_str} must have {len_lhs} elements" ) + def get_lhs_str(self): + if isinstance(self.lhs, ColPairs): + return repr(self.lhs.field.name) + else: + names = ", ".join(repr(f.name) for f in self.lhs) + return f"({names})" + def get_prep_lhs(self): if isinstance(self.lhs, (tuple, list)): return Tuple(*self.lhs) @@ -196,14 +211,25 @@ class TupleLessThanOrEqual(TupleLookupMixin, LessThanOrEqual): class TupleIn(TupleLookupMixin, In): def get_prep_lookup(self): + self.check_rhs_is_tuple_or_list() + self.check_rhs_is_collection_of_tuples_or_lists() self.check_rhs_elements_length_equals_lhs_length() - return super(TupleLookupMixin, self).get_prep_lookup() + return self.rhs # skip checks from mixin + + def check_rhs_is_collection_of_tuples_or_lists(self): + if not all(isinstance(vals, (tuple, list)) for vals in self.rhs): + lhs_str = self.get_lhs_str() + raise ValueError( + f"{self.lookup_name!r} lookup of {lhs_str} " + "must be a collection of tuples or lists" + ) def check_rhs_elements_length_equals_lhs_length(self): len_lhs = len(self.lhs) if not all(len_lhs == len(vals) for vals in self.rhs): + lhs_str = self.get_lhs_str() raise ValueError( - f"'{self.lookup_name}' lookup of '{self.lhs.field.name}' field " + f"{self.lookup_name!r} lookup of {lhs_str} " f"must have {len_lhs} elements each" ) diff --git a/tests/foreign_object/test_tuple_lookups.py b/tests/foreign_object/test_tuple_lookups.py index e2561676f3..06182d3bb5 100644 --- a/tests/foreign_object/test_tuple_lookups.py +++ b/tests/foreign_object/test_tuple_lookups.py @@ -1,3 +1,4 @@ +import itertools import unittest from django.db import NotSupportedError, connection @@ -129,6 +130,37 @@ class TupleLookupsTests(TestCase): (self.contact_1, self.contact_2, self.contact_5), ) + def test_tuple_in_rhs_must_be_collection_of_tuples_or_lists(self): + test_cases = ( + (1, 2, 3), + ((1, 2), (3, 4), None), + ) + + for rhs in test_cases: + with self.subTest(rhs=rhs): + with self.assertRaisesMessage( + ValueError, + "'in' lookup of ('customer_code', 'company_code') " + "must be a collection of tuples or lists", + ): + TupleIn((F("customer_code"), F("company_code")), rhs) + + def test_tuple_in_rhs_must_have_2_elements_each(self): + test_cases = ( + ((),), + ((1,),), + ((1, 2, 3),), + ) + + for rhs in test_cases: + with self.subTest(rhs=rhs): + with self.assertRaisesMessage( + ValueError, + "'in' lookup of ('customer_code', 'company_code') " + "must have 2 elements each", + ): + TupleIn((F("customer_code"), F("company_code")), rhs) + def test_lt(self): c1, c2, c3, c4, c5, c6 = ( self.contact_1, @@ -358,8 +390,8 @@ class TupleLookupsTests(TestCase): ) def test_lookup_errors(self): - m_2_elements = "'%s' lookup of 'customer' field must have 2 elements" - m_2_elements_each = "'in' lookup of 'customer' field must have 2 elements each" + m_2_elements = "'%s' lookup of 'customer' must have 2 elements" + m_2_elements_each = "'in' lookup of 'customer' must have 2 elements each" test_cases = ( ({"customer": 1}, m_2_elements % "exact"), ({"customer": (1, 2, 3)}, m_2_elements % "exact"), @@ -381,3 +413,77 @@ class TupleLookupsTests(TestCase): self.assertRaisesMessage(ValueError, message), ): Contact.objects.get(**kwargs) + + def test_tuple_lookup_names(self): + test_cases = ( + (TupleExact, "exact"), + (TupleGreaterThan, "gt"), + (TupleGreaterThanOrEqual, "gte"), + (TupleLessThan, "lt"), + (TupleLessThanOrEqual, "lte"), + (TupleIn, "in"), + (TupleIsNull, "isnull"), + ) + + for lookup_class, lookup_name in test_cases: + with self.subTest(lookup_name): + self.assertEqual(lookup_class.lookup_name, lookup_name) + + def test_tuple_lookup_rhs_must_be_tuple_or_list(self): + test_cases = itertools.product( + ( + TupleExact, + TupleGreaterThan, + TupleGreaterThanOrEqual, + TupleLessThan, + TupleLessThanOrEqual, + TupleIn, + ), + ( + 0, + 1, + None, + True, + False, + {"foo": "bar"}, + ), + ) + + for lookup_cls, rhs in test_cases: + lookup_name = lookup_cls.lookup_name + with self.subTest(lookup_name=lookup_name, rhs=rhs): + with self.assertRaisesMessage( + ValueError, + f"'{lookup_name}' lookup of ('customer_code', 'company_code') " + "must be a tuple or a list", + ): + lookup_cls((F("customer_code"), F("company_code")), rhs) + + def test_tuple_lookup_rhs_must_have_2_elements(self): + test_cases = itertools.product( + ( + TupleExact, + TupleGreaterThan, + TupleGreaterThanOrEqual, + TupleLessThan, + TupleLessThanOrEqual, + ), + ( + [], + [1], + [1, 2, 3], + (), + (1,), + (1, 2, 3), + ), + ) + + for lookup_cls, rhs in test_cases: + lookup_name = lookup_cls.lookup_name + with self.subTest(lookup_name=lookup_name, rhs=rhs): + with self.assertRaisesMessage( + ValueError, + f"'{lookup_name}' lookup of ('customer_code', 'company_code') " + "must have 2 elements", + ): + lookup_cls((F("customer_code"), F("company_code")), rhs) From 53ea4cce2fd08e84b9cdb6363267ccb9525f7060 Mon Sep 17 00:00:00 2001 From: Simon Charette Date: Mon, 14 Oct 2024 19:21:48 -0400 Subject: [PATCH 33/40] Fixed #35744 -- Relabelled external aliases of combined queries. Just like normal queries, combined queries' outer references might fully resolve before their reference is assigned its final alias. Refs #29338. Thanks Antony_K for the report and example, and thanks Mariusz Felisiak for the review. --- django/db/models/sql/query.py | 10 +++++++++ tests/queries/test_qs_combinators.py | 32 +++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index aef3f48f10..b7b93c235a 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -1021,11 +1021,21 @@ class Query(BaseExpression): if alias == old_alias: table_aliases[pos] = new_alias break + + # 3. Rename the direct external aliases and the ones of combined + # queries (union, intersection, difference). self.external_aliases = { # Table is aliased or it's being changed and thus is aliased. change_map.get(alias, alias): (aliased or alias in change_map) for alias, aliased in self.external_aliases.items() } + for combined_query in self.combined_queries: + external_change_map = { + alias: aliased + for alias, aliased in change_map.items() + if alias in combined_query.external_aliases + } + combined_query.change_aliases(external_change_map) def bump_prefix(self, other_query, exclude=None): """ diff --git a/tests/queries/test_qs_combinators.py b/tests/queries/test_qs_combinators.py index ad1017c8af..2f6e93cde8 100644 --- a/tests/queries/test_qs_combinators.py +++ b/tests/queries/test_qs_combinators.py @@ -14,7 +14,16 @@ from django.db.models.functions import Mod from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature from django.test.utils import CaptureQueriesContext -from .models import Author, Celebrity, ExtraInfo, Number, ReservedName +from .models import ( + Annotation, + Author, + Celebrity, + ExtraInfo, + Note, + Number, + ReservedName, + Tag, +) @skipUnlessDBFeature("supports_select_union") @@ -450,6 +459,27 @@ class QuerySetSetOperationTests(TestCase): [8, 1], ) + @skipUnlessDBFeature("supports_select_intersection") + def test_intersection_in_nested_subquery(self): + tag = Tag.objects.create(name="tag") + note = Note.objects.create(tag=tag) + annotation = Annotation.objects.create(tag=tag) + tags = Tag.objects.order_by() + tags = tags.filter(id=OuterRef("tag_id")).intersection( + tags.filter(id=OuterRef(OuterRef("tag_id"))) + ) + qs = Note.objects.filter( + Exists( + Annotation.objects.filter( + Exists(tags), + notes__in=OuterRef("pk"), + ) + ) + ) + self.assertIsNone(qs.first()) + annotation.notes.add(note) + self.assertEqual(qs.first(), note) + def test_union_in_subquery_related_outerref(self): e1 = ExtraInfo.objects.create(value=7, info="e3") e2 = ExtraInfo.objects.create(value=5, info="e2") From 80c3697e96f5a0cbeac043dd5a67f26c076a4279 Mon Sep 17 00:00:00 2001 From: Ben Cail Date: Mon, 14 Oct 2024 09:12:56 -0400 Subject: [PATCH 34/40] Refs #35782 -- Documented the get_help_text methods in password validators. --- docs/topics/auth/passwords.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/topics/auth/passwords.txt b/docs/topics/auth/passwords.txt index 68f5453d54..e8a662e239 100644 --- a/docs/topics/auth/passwords.txt +++ b/docs/topics/auth/passwords.txt @@ -600,6 +600,11 @@ Django includes four validators: Validates that the password is of a minimum length. The minimum length can be customized with the ``min_length`` parameter. + .. method:: get_help_text() + + A hook for customizing the validator's help text. Defaults to ``"Your + password must contain at least characters."`` + .. class:: UserAttributeSimilarityValidator(user_attributes=DEFAULT_USER_ATTRIBUTES, max_similarity=0.7) Validates that the password is sufficiently different from certain @@ -617,6 +622,11 @@ Django includes four validators: ``user_attributes``, whereas a value of 1.0 rejects only passwords that are identical to an attribute's value. + .. method:: get_help_text() + + A hook for customizing the validator's help text. Defaults to ``"Your + password can’t be too similar to your other personal information."`` + .. class:: CommonPasswordValidator(password_list_path=DEFAULT_PASSWORD_LIST_PATH) Validates that the password is not a common password. This converts the @@ -628,10 +638,20 @@ Django includes four validators: common passwords. This file should contain one lowercase password per line and may be plain text or gzipped. + .. method:: get_help_text() + + A hook for customizing the validator's help text. Defaults to ``"Your + password can’t be a commonly used password."`` + .. class:: NumericPasswordValidator() Validate that the password is not entirely numeric. + .. method:: get_help_text() + + A hook for customizing the validator's help text. Defaults to ``"Your + password can’t be entirely numeric."`` + Integrating validation ---------------------- From dc626fbe3ae0225b765df71d08fab02971dc6c6f Mon Sep 17 00:00:00 2001 From: Yash Date: Wed, 4 Sep 2024 20:10:27 +0530 Subject: [PATCH 35/40] Fixed #35682 -- Updated docstrings for base view classes which require a response mixin. --- django/views/generic/dates.py | 44 +++++++++++++++++++++++++++------- django/views/generic/detail.py | 6 ++++- django/views/generic/edit.py | 6 ++--- django/views/generic/list.py | 6 ++++- 4 files changed, 49 insertions(+), 13 deletions(-) diff --git a/django/views/generic/dates.py b/django/views/generic/dates.py index d2b776c122..12ec4104cd 100644 --- a/django/views/generic/dates.py +++ b/django/views/generic/dates.py @@ -300,7 +300,11 @@ class DateMixin: class BaseDateListView(MultipleObjectMixin, DateMixin, View): - """Abstract base class for date-based views displaying a list of objects.""" + """ + Base class for date-based views displaying a list of objects. + + This requires subclassing to provide a response mixin. + """ allow_empty = False date_list_period = "year" @@ -388,7 +392,9 @@ class BaseDateListView(MultipleObjectMixin, DateMixin, View): class BaseArchiveIndexView(BaseDateListView): """ - Base class for archives of date-based items. Requires a response mixin. + Base view for archives of date-based items. + + This requires subclassing to provide a response mixin. """ context_object_name = "latest" @@ -411,7 +417,11 @@ class ArchiveIndexView(MultipleObjectTemplateResponseMixin, BaseArchiveIndexView class BaseYearArchiveView(YearMixin, BaseDateListView): - """List of objects published in a given year.""" + """ + Base view for a list of objects published in a given year. + + This requires subclassing to provide a response mixin. + """ date_list_period = "month" make_object_list = False @@ -463,7 +473,11 @@ class YearArchiveView(MultipleObjectTemplateResponseMixin, BaseYearArchiveView): class BaseMonthArchiveView(YearMixin, MonthMixin, BaseDateListView): - """List of objects published in a given month.""" + """ + Base view for a list of objects published in a given month. + + This requires subclassing to provide a response mixin. + """ date_list_period = "day" @@ -505,7 +519,11 @@ class MonthArchiveView(MultipleObjectTemplateResponseMixin, BaseMonthArchiveView class BaseWeekArchiveView(YearMixin, WeekMixin, BaseDateListView): - """List of objects published in a given week.""" + """ + Base view for a list of objects published in a given week. + + This requires subclassing to provide a response mixin. + """ def get_dated_items(self): """Return (date_list, items, extra_context) for this request.""" @@ -563,7 +581,11 @@ class WeekArchiveView(MultipleObjectTemplateResponseMixin, BaseWeekArchiveView): class BaseDayArchiveView(YearMixin, MonthMixin, DayMixin, BaseDateListView): - """List of objects published on a given day.""" + """ + Base view for a list of objects published on a given day. + + This requires subclassing to provide a response mixin. + """ def get_dated_items(self): """Return (date_list, items, extra_context) for this request.""" @@ -610,7 +632,11 @@ class DayArchiveView(MultipleObjectTemplateResponseMixin, BaseDayArchiveView): class BaseTodayArchiveView(BaseDayArchiveView): - """List of objects published today.""" + """ + Base view for a list of objects published today. + + This requires subclassing to provide a response mixin. + """ def get_dated_items(self): """Return (date_list, items, extra_context) for this request.""" @@ -625,8 +651,10 @@ class TodayArchiveView(MultipleObjectTemplateResponseMixin, BaseTodayArchiveView class BaseDateDetailView(YearMixin, MonthMixin, DayMixin, DateMixin, BaseDetailView): """ - Detail view of a single object on a single date; this differs from the + Base detail view for a single object on a single date; this differs from the standard DetailView by accepting a year/month/day in the URL. + + This requires subclassing to provide a response mixin. """ def get_object(self, queryset=None): diff --git a/django/views/generic/detail.py b/django/views/generic/detail.py index e4428c8036..a5f604bf1a 100644 --- a/django/views/generic/detail.py +++ b/django/views/generic/detail.py @@ -102,7 +102,11 @@ class SingleObjectMixin(ContextMixin): class BaseDetailView(SingleObjectMixin, View): - """A base view for displaying a single object.""" + """ + Base view for displaying a single object. + + This requires subclassing to provide a response mixin. + """ def get(self, request, *args, **kwargs): self.object = self.get_object() diff --git a/django/views/generic/edit.py b/django/views/generic/edit.py index 97934f58cb..ebd071cf00 100644 --- a/django/views/generic/edit.py +++ b/django/views/generic/edit.py @@ -170,7 +170,7 @@ class BaseCreateView(ModelFormMixin, ProcessFormView): """ Base view for creating a new object instance. - Using this base class requires subclassing to provide a response mixin. + This requires subclassing to provide a response mixin. """ def get(self, request, *args, **kwargs): @@ -194,7 +194,7 @@ class BaseUpdateView(ModelFormMixin, ProcessFormView): """ Base view for updating an existing object. - Using this base class requires subclassing to provide a response mixin. + This requires subclassing to provide a response mixin. """ def get(self, request, *args, **kwargs): @@ -242,7 +242,7 @@ class BaseDeleteView(DeletionMixin, FormMixin, BaseDetailView): """ Base view for deleting an object. - Using this base class requires subclassing to provide a response mixin. + This requires subclassing to provide a response mixin. """ form_class = Form diff --git a/django/views/generic/list.py b/django/views/generic/list.py index 830a8df630..8ed92920c4 100644 --- a/django/views/generic/list.py +++ b/django/views/generic/list.py @@ -148,7 +148,11 @@ class MultipleObjectMixin(ContextMixin): class BaseListView(MultipleObjectMixin, View): - """A base view for displaying a list of objects.""" + """ + Base view for displaying a list of objects. + + This requires subclassing to provide a response mixin. + """ def get(self, request, *args, **kwargs): self.object_list = self.get_queryset() From 06bf06a911695c5c84f746742f764c040e237ece Mon Sep 17 00:00:00 2001 From: leondaz Date: Mon, 9 Sep 2024 19:15:40 +0300 Subject: [PATCH 36/40] Fixed #35656 -- Added an autodetector attribute to the makemigrations and migrate commands. --- django/core/checks/__init__.py | 1 + django/core/checks/commands.py | 28 +++++++++ django/core/checks/registry.py | 1 + .../management/commands/makemigrations.py | 5 +- django/core/management/commands/migrate.py | 3 +- docs/ref/checks.txt | 9 +++ docs/releases/5.2.txt | 4 ++ .../management/commands/makemigrations.py | 7 +++ tests/check_framework/test_commands.py | 25 ++++++++ tests/migrations/test_commands.py | 63 ++++++++++++++++++- 10 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 django/core/checks/commands.py create mode 100644 tests/check_framework/custom_commands_app/management/commands/makemigrations.py create mode 100644 tests/check_framework/test_commands.py diff --git a/django/core/checks/__init__.py b/django/core/checks/__init__.py index 998ab9dee2..2502450cdf 100644 --- a/django/core/checks/__init__.py +++ b/django/core/checks/__init__.py @@ -16,6 +16,7 @@ from .registry import Tags, register, run_checks, tag_exists # Import these to force registration of checks import django.core.checks.async_checks # NOQA isort:skip import django.core.checks.caches # NOQA isort:skip +import django.core.checks.commands # NOQA isort:skip import django.core.checks.compatibility.django_4_0 # NOQA isort:skip import django.core.checks.database # NOQA isort:skip import django.core.checks.files # NOQA isort:skip diff --git a/django/core/checks/commands.py b/django/core/checks/commands.py new file mode 100644 index 0000000000..eee1e937e8 --- /dev/null +++ b/django/core/checks/commands.py @@ -0,0 +1,28 @@ +from django.core.checks import Error, Tags, register + + +@register(Tags.commands) +def migrate_and_makemigrations_autodetector(**kwargs): + from django.core.management import get_commands, load_command_class + + commands = get_commands() + + make_migrations = load_command_class(commands["makemigrations"], "makemigrations") + migrate = load_command_class(commands["migrate"], "migrate") + + if make_migrations.autodetector is not migrate.autodetector: + return [ + Error( + "The migrate and makemigrations commands must have the same " + "autodetector.", + hint=( + f"makemigrations.Command.autodetector is " + f"{make_migrations.autodetector.__name__}, but " + f"migrate.Command.autodetector is " + f"{migrate.autodetector.__name__}." + ), + id="commands.E001", + ) + ] + + return [] diff --git a/django/core/checks/registry.py b/django/core/checks/registry.py index 146b28f65e..3139fc3ef4 100644 --- a/django/core/checks/registry.py +++ b/django/core/checks/registry.py @@ -12,6 +12,7 @@ class Tags: admin = "admin" async_support = "async_support" caches = "caches" + commands = "commands" compatibility = "compatibility" database = "database" files = "files" diff --git a/django/core/management/commands/makemigrations.py b/django/core/management/commands/makemigrations.py index a4e4d520e6..d5d3466201 100644 --- a/django/core/management/commands/makemigrations.py +++ b/django/core/management/commands/makemigrations.py @@ -24,6 +24,7 @@ from django.db.migrations.writer import MigrationWriter class Command(BaseCommand): + autodetector = MigrationAutodetector help = "Creates new migration(s) for apps." def add_arguments(self, parser): @@ -209,7 +210,7 @@ class Command(BaseCommand): log=self.log, ) # Set up autodetector - autodetector = MigrationAutodetector( + autodetector = self.autodetector( loader.project_state(), ProjectState.from_apps(apps), questioner, @@ -461,7 +462,7 @@ class Command(BaseCommand): # If they still want to merge it, then write out an empty # file depending on the migrations needing merging. numbers = [ - MigrationAutodetector.parse_number(migration.name) + self.autodetector.parse_number(migration.name) for migration in merge_migrations ] try: diff --git a/django/core/management/commands/migrate.py b/django/core/management/commands/migrate.py index 5e6b19c095..fa420ee6e3 100644 --- a/django/core/management/commands/migrate.py +++ b/django/core/management/commands/migrate.py @@ -15,6 +15,7 @@ from django.utils.text import Truncator class Command(BaseCommand): + autodetector = MigrationAutodetector help = ( "Updates database schema. Manages both apps with migrations and those without." ) @@ -329,7 +330,7 @@ class Command(BaseCommand): self.stdout.write(" No migrations to apply.") # If there's changes that aren't in migrations yet, tell them # how to fix it. - autodetector = MigrationAutodetector( + autodetector = self.autodetector( executor.loader.project_state(), ProjectState.from_apps(apps), ) diff --git a/docs/ref/checks.txt b/docs/ref/checks.txt index d78a6f76b2..2308a854c7 100644 --- a/docs/ref/checks.txt +++ b/docs/ref/checks.txt @@ -77,6 +77,7 @@ Django's system checks are organized using the following tags: * ``async_support``: Checks asynchronous-related configuration. * ``caches``: Checks cache related configuration. * ``compatibility``: Flags potential problems with version upgrades. +* ``commands``: Checks custom management commands related configuration. * ``database``: Checks database-related configuration issues. Database checks are not run by default because they do more than static code analysis as regular checks do. They are only run by the :djadmin:`migrate` command or if @@ -428,6 +429,14 @@ Models * **models.W047**: ```` does not support unique constraints with nulls distinct. +Management Commands +------------------- + +The following checks verify custom management commands are correctly configured: + +* **commands.E001**: The ``migrate`` and ``makemigrations`` commands must have + the same ``autodetector``. + Security -------- diff --git a/docs/releases/5.2.txt b/docs/releases/5.2.txt index eabc27c277..78c96688cf 100644 --- a/docs/releases/5.2.txt +++ b/docs/releases/5.2.txt @@ -230,6 +230,10 @@ Management Commands setting the :envvar:`HIDE_PRODUCTION_WARNING` environment variable to ``"true"``. +* The :djadmin:`makemigrations` and :djadmin:`migrate` commands have a new + ``Command.autodetector`` attribute for subclasses to override in order to use + a custom autodetector class. + Migrations ~~~~~~~~~~ diff --git a/tests/check_framework/custom_commands_app/management/commands/makemigrations.py b/tests/check_framework/custom_commands_app/management/commands/makemigrations.py new file mode 100644 index 0000000000..a6494cba4c --- /dev/null +++ b/tests/check_framework/custom_commands_app/management/commands/makemigrations.py @@ -0,0 +1,7 @@ +from django.core.management.commands.makemigrations import ( + Command as MakeMigrationsCommand, +) + + +class Command(MakeMigrationsCommand): + autodetector = int diff --git a/tests/check_framework/test_commands.py b/tests/check_framework/test_commands.py new file mode 100644 index 0000000000..a51db77402 --- /dev/null +++ b/tests/check_framework/test_commands.py @@ -0,0 +1,25 @@ +from django.core import checks +from django.core.checks import Error +from django.test import SimpleTestCase +from django.test.utils import isolate_apps, override_settings, override_system_checks + + +@isolate_apps("check_framework.custom_commands_app", attr_name="apps") +@override_settings(INSTALLED_APPS=["check_framework.custom_commands_app"]) +@override_system_checks([checks.commands.migrate_and_makemigrations_autodetector]) +class CommandCheckTests(SimpleTestCase): + def test_migrate_and_makemigrations_autodetector_different(self): + expected_error = Error( + "The migrate and makemigrations commands must have the same " + "autodetector.", + hint=( + "makemigrations.Command.autodetector is int, but " + "migrate.Command.autodetector is MigrationAutodetector." + ), + id="commands.E001", + ) + + self.assertEqual( + checks.run_checks(app_configs=self.apps.get_app_configs()), + [expected_error], + ) diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py index cab2906ed1..724c88a28f 100644 --- a/tests/migrations/test_commands.py +++ b/tests/migrations/test_commands.py @@ -9,6 +9,10 @@ from unittest import mock from django.apps import apps from django.core.management import CommandError, call_command +from django.core.management.commands.makemigrations import ( + Command as MakeMigrationsCommand, +) +from django.core.management.commands.migrate import Command as MigrateCommand from django.db import ( ConnectionHandler, DatabaseError, @@ -19,10 +23,11 @@ from django.db import ( ) from django.db.backends.base.schema import BaseDatabaseSchemaEditor from django.db.backends.utils import truncate_name +from django.db.migrations.autodetector import MigrationAutodetector from django.db.migrations.exceptions import InconsistentMigrationHistory from django.db.migrations.recorder import MigrationRecorder from django.test import TestCase, override_settings, skipUnlessDBFeature -from django.test.utils import captured_stdout, extend_sys_path +from django.test.utils import captured_stdout, extend_sys_path, isolate_apps from django.utils import timezone from django.utils.version import get_docs_version @@ -3296,3 +3301,59 @@ class OptimizeMigrationTests(MigrationTestBase): msg = "Cannot find a migration matching 'nonexistent' from app 'migrations'." with self.assertRaisesMessage(CommandError, msg): call_command("optimizemigration", "migrations", "nonexistent") + + +class CustomMigrationCommandTests(MigrationTestBase): + @override_settings( + MIGRATION_MODULES={"migrations": "migrations.test_migrations"}, + INSTALLED_APPS=["migrations.migrations_test_apps.migrated_app"], + ) + @isolate_apps("migrations.migrations_test_apps.migrated_app") + def test_makemigrations_custom_autodetector(self): + class CustomAutodetector(MigrationAutodetector): + def changes(self, *args, **kwargs): + return [] + + class CustomMakeMigrationsCommand(MakeMigrationsCommand): + autodetector = CustomAutodetector + + class NewModel(models.Model): + class Meta: + app_label = "migrated_app" + + out = io.StringIO() + command = CustomMakeMigrationsCommand(stdout=out) + call_command(command, "migrated_app", stdout=out) + self.assertIn("No changes detected", out.getvalue()) + + @override_settings(INSTALLED_APPS=["migrations.migrations_test_apps.migrated_app"]) + @isolate_apps("migrations.migrations_test_apps.migrated_app") + def test_migrate_custom_autodetector(self): + class CustomAutodetector(MigrationAutodetector): + def changes(self, *args, **kwargs): + return [] + + class CustomMigrateCommand(MigrateCommand): + autodetector = CustomAutodetector + + class NewModel(models.Model): + class Meta: + app_label = "migrated_app" + + out = io.StringIO() + command = CustomMigrateCommand(stdout=out) + + out = io.StringIO() + try: + call_command(command, verbosity=0) + call_command(command, stdout=out, no_color=True) + command_stdout = out.getvalue().lower() + self.assertEqual( + "operations to perform:\n" + " apply all migrations: migrated_app\n" + "running migrations:\n" + " no migrations to apply.\n", + command_stdout, + ) + finally: + call_command(command, "migrated_app", "zero", verbosity=0) From ec7d69035a408b357f1803ca05a7c991cc358cfa Mon Sep 17 00:00:00 2001 From: Ben Cail Date: Thu, 26 Sep 2024 10:11:41 -0400 Subject: [PATCH 37/40] Fixed #35782 -- Allowed overriding password validation error messages. --- django/contrib/auth/password_validation.py | 36 ++++++----- docs/releases/5.2.txt | 4 ++ docs/topics/auth/passwords.txt | 39 ++++++++++-- tests/auth_tests/test_validators.py | 70 ++++++++++++++++++++++ 4 files changed, 131 insertions(+), 18 deletions(-) diff --git a/django/contrib/auth/password_validation.py b/django/contrib/auth/password_validation.py index 06f8fcc4e8..d24e69e0ce 100644 --- a/django/contrib/auth/password_validation.py +++ b/django/contrib/auth/password_validation.py @@ -106,17 +106,16 @@ class MinimumLengthValidator: def validate(self, password, user=None): if len(password) < self.min_length: - raise ValidationError( - ngettext( - "This password is too short. It must contain at least " - "%(min_length)d character.", - "This password is too short. It must contain at least " - "%(min_length)d characters.", - self.min_length, - ), - code="password_too_short", - params={"min_length": self.min_length}, - ) + raise ValidationError(self.get_error_message(), code="password_too_short") + + def get_error_message(self): + return ngettext( + "This password is too short. It must contain at least %d character." + % self.min_length, + "This password is too short. It must contain at least %d characters." + % self.min_length, + self.min_length, + ) def get_help_text(self): return ngettext( @@ -203,11 +202,14 @@ class UserAttributeSimilarityValidator: except FieldDoesNotExist: verbose_name = attribute_name raise ValidationError( - _("The password is too similar to the %(verbose_name)s."), + self.get_error_message(), code="password_too_similar", params={"verbose_name": verbose_name}, ) + def get_error_message(self): + return _("The password is too similar to the %(verbose_name)s.") + def get_help_text(self): return _( "Your password can’t be too similar to your other personal information." @@ -242,10 +244,13 @@ class CommonPasswordValidator: def validate(self, password, user=None): if password.lower().strip() in self.passwords: raise ValidationError( - _("This password is too common."), + self.get_error_message(), code="password_too_common", ) + def get_error_message(self): + return _("This password is too common.") + def get_help_text(self): return _("Your password can’t be a commonly used password.") @@ -258,9 +263,12 @@ class NumericPasswordValidator: def validate(self, password, user=None): if password.isdigit(): raise ValidationError( - _("This password is entirely numeric."), + self.get_error_message(), code="password_entirely_numeric", ) + def get_error_message(self): + return _("This password is entirely numeric.") + def get_help_text(self): return _("Your password can’t be entirely numeric.") diff --git a/docs/releases/5.2.txt b/docs/releases/5.2.txt index 78c96688cf..806abfa26d 100644 --- a/docs/releases/5.2.txt +++ b/docs/releases/5.2.txt @@ -82,6 +82,10 @@ Minor features improves performance. See :ref:`adding an async interface ` for more details. +* The :ref:`password validator classes ` + now have a new method ``get_error_message()``, which can be overridden in + subclasses to customize the error messages. + :mod:`django.contrib.contenttypes` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/topics/auth/passwords.txt b/docs/topics/auth/passwords.txt index e8a662e239..8efd2bdebf 100644 --- a/docs/topics/auth/passwords.txt +++ b/docs/topics/auth/passwords.txt @@ -590,6 +590,8 @@ has no settings. The help texts and any errors from password validators are always returned in the order they are listed in :setting:`AUTH_PASSWORD_VALIDATORS`. +.. _included-password-validators: + Included validators ------------------- @@ -600,10 +602,18 @@ Django includes four validators: Validates that the password is of a minimum length. The minimum length can be customized with the ``min_length`` parameter. + .. method:: get_error_message() + + .. versionadded:: 5.2 + + A hook for customizing the ``ValidationError`` error message. Defaults + to ``"This password is too short. It must contain at least + characters."``. + .. method:: get_help_text() A hook for customizing the validator's help text. Defaults to ``"Your - password must contain at least characters."`` + password must contain at least characters."``. .. class:: UserAttributeSimilarityValidator(user_attributes=DEFAULT_USER_ATTRIBUTES, max_similarity=0.7) @@ -622,10 +632,17 @@ Django includes four validators: ``user_attributes``, whereas a value of 1.0 rejects only passwords that are identical to an attribute's value. + .. method:: get_error_message() + + .. versionadded:: 5.2 + + A hook for customizing the ``ValidationError`` error message. Defaults + to ``"The password is too similar to the ."``. + .. method:: get_help_text() A hook for customizing the validator's help text. Defaults to ``"Your - password can’t be too similar to your other personal information."`` + password can’t be too similar to your other personal information."``. .. class:: CommonPasswordValidator(password_list_path=DEFAULT_PASSWORD_LIST_PATH) @@ -638,19 +655,33 @@ Django includes four validators: common passwords. This file should contain one lowercase password per line and may be plain text or gzipped. + .. method:: get_error_message() + + .. versionadded:: 5.2 + + A hook for customizing the ``ValidationError`` error message. Defaults + to ``"This password is too common."``. + .. method:: get_help_text() A hook for customizing the validator's help text. Defaults to ``"Your - password can’t be a commonly used password."`` + password can’t be a commonly used password."``. .. class:: NumericPasswordValidator() Validate that the password is not entirely numeric. + .. method:: get_error_message() + + .. versionadded:: 5.2 + + A hook for customizing the ``ValidationError`` error message. Defaults + to ``"This password is entirely numeric."``. + .. method:: get_help_text() A hook for customizing the validator's help text. Defaults to ``"Your - password can’t be entirely numeric."`` + password can’t be entirely numeric."``. Integrating validation ---------------------- diff --git a/tests/auth_tests/test_validators.py b/tests/auth_tests/test_validators.py index 506c85c0ae..d7e4968951 100644 --- a/tests/auth_tests/test_validators.py +++ b/tests/auth_tests/test_validators.py @@ -144,6 +144,20 @@ class MinimumLengthValidatorTest(SimpleTestCase): "Your password must contain at least 8 characters.", ) + def test_custom_error(self): + class CustomMinimumLengthValidator(MinimumLengthValidator): + def get_error_message(self): + return "Your password must be %d characters long" % self.min_length + + expected_error = "Your password must be %d characters long" + + with self.assertRaisesMessage(ValidationError, expected_error % 8) as cm: + CustomMinimumLengthValidator().validate("1234567") + self.assertEqual(cm.exception.error_list[0].code, "password_too_short") + + with self.assertRaisesMessage(ValidationError, expected_error % 3) as cm: + CustomMinimumLengthValidator(min_length=3).validate("12") + class UserAttributeSimilarityValidatorTest(TestCase): def test_validate(self): @@ -213,6 +227,42 @@ class UserAttributeSimilarityValidatorTest(TestCase): "Your password can’t be too similar to your other personal information.", ) + def test_custom_error(self): + class CustomUserAttributeSimilarityValidator(UserAttributeSimilarityValidator): + def get_error_message(self): + return "The password is too close to the %(verbose_name)s." + + user = User.objects.create_user( + username="testclient", + password="password", + email="testclient@example.com", + first_name="Test", + last_name="Client", + ) + + expected_error = "The password is too close to the %s." + + with self.assertRaisesMessage(ValidationError, expected_error % "username"): + CustomUserAttributeSimilarityValidator().validate("testclient", user=user) + + def test_custom_error_verbose_name_not_used(self): + class CustomUserAttributeSimilarityValidator(UserAttributeSimilarityValidator): + def get_error_message(self): + return "The password is too close to a user attribute." + + user = User.objects.create_user( + username="testclient", + password="password", + email="testclient@example.com", + first_name="Test", + last_name="Client", + ) + + expected_error = "The password is too close to a user attribute." + + with self.assertRaisesMessage(ValidationError, expected_error): + CustomUserAttributeSimilarityValidator().validate("testclient", user=user) + class CommonPasswordValidatorTest(SimpleTestCase): def test_validate(self): @@ -247,6 +297,16 @@ class CommonPasswordValidatorTest(SimpleTestCase): "Your password can’t be a commonly used password.", ) + def test_custom_error(self): + class CustomCommonPasswordValidator(CommonPasswordValidator): + def get_error_message(self): + return "This password has been used too much." + + expected_error = "This password has been used too much." + + with self.assertRaisesMessage(ValidationError, expected_error): + CustomCommonPasswordValidator().validate("godzilla") + class NumericPasswordValidatorTest(SimpleTestCase): def test_validate(self): @@ -264,6 +324,16 @@ class NumericPasswordValidatorTest(SimpleTestCase): "Your password can’t be entirely numeric.", ) + def test_custom_error(self): + class CustomNumericPasswordValidator(NumericPasswordValidator): + def get_error_message(self): + return "This password is all digits." + + expected_error = "This password is all digits." + + with self.assertRaisesMessage(ValidationError, expected_error): + CustomNumericPasswordValidator().validate("42424242") + class UsernameValidatorsTests(SimpleTestCase): def test_unicode_validator(self): From 4a685bc0dca5298a7d5a4e162120a90cac7fd1a4 Mon Sep 17 00:00:00 2001 From: SaJH Date: Wed, 11 Sep 2024 21:23:23 +0900 Subject: [PATCH 38/40] Fixed #35727 -- Added HttpResponse.text property. Signed-off-by: SaJH --- django/http/response.py | 12 ++++++++++++ docs/ref/request-response.txt | 10 ++++++++++ docs/releases/5.2.txt | 3 +++ tests/httpwrappers/tests.py | 23 +++++++++++++++++++++++ 4 files changed, 48 insertions(+) diff --git a/django/http/response.py b/django/http/response.py index abe71718f2..1dbaf46add 100644 --- a/django/http/response.py +++ b/django/http/response.py @@ -21,6 +21,7 @@ from django.http.cookie import SimpleCookie from django.utils import timezone from django.utils.datastructures import CaseInsensitiveMapping from django.utils.encoding import iri_to_uri +from django.utils.functional import cached_property from django.utils.http import content_disposition_header, http_date from django.utils.regex_helper import _lazy_re_compile @@ -408,6 +409,11 @@ class HttpResponse(HttpResponseBase): content = self.make_bytes(value) # Create a list of properly encoded bytestrings to support write(). self._container = [content] + self.__dict__.pop("text", None) + + @cached_property + def text(self): + return self.content.decode(self.charset or "utf-8") def __iter__(self): return iter(self._container) @@ -460,6 +466,12 @@ class StreamingHttpResponse(HttpResponseBase): "`streaming_content` instead." % self.__class__.__name__ ) + @property + def text(self): + raise AttributeError( + "This %s instance has no `text` attribute." % self.__class__.__name__ + ) + @property def streaming_content(self): if self.is_async: diff --git a/docs/ref/request-response.txt b/docs/ref/request-response.txt index 31111a435a..afebd00d8b 100644 --- a/docs/ref/request-response.txt +++ b/docs/ref/request-response.txt @@ -833,6 +833,13 @@ Attributes A bytestring representing the content, encoded from a string if necessary. +.. attribute:: HttpResponse.text + + .. versionadded:: 5.2 + + A string representation of :attr:`HttpResponse.content`, decoded using the + response's :attr:`HttpResponse.charset` (defaulting to ``UTF-8`` if empty). + .. attribute:: HttpResponse.cookies A :py:obj:`http.cookies.SimpleCookie` object holding the cookies included @@ -1272,6 +1279,9 @@ with the following notable differences: :attr:`~StreamingHttpResponse.streaming_content` attribute. This can be used in middleware to wrap the response iterable, but should not be consumed. +* It has no ``text`` attribute, as it would require iterating the response + object. + * You cannot use the file-like object ``tell()`` or ``write()`` methods. Doing so will raise an exception. diff --git a/docs/releases/5.2.txt b/docs/releases/5.2.txt index 806abfa26d..9090f8b70a 100644 --- a/docs/releases/5.2.txt +++ b/docs/releases/5.2.txt @@ -268,6 +268,9 @@ Models Requests and Responses ~~~~~~~~~~~~~~~~~~~~~~ +* The new :attr:`.HttpResponse.text` property provides the string representation + of :attr:`.HttpResponse.content`. + * The new :meth:`.HttpRequest.get_preferred_type` method can be used to query the preferred media type the client accepts. diff --git a/tests/httpwrappers/tests.py b/tests/httpwrappers/tests.py index 2197c6f7ea..154e9517fe 100644 --- a/tests/httpwrappers/tests.py +++ b/tests/httpwrappers/tests.py @@ -530,6 +530,22 @@ class HttpResponseTests(SimpleTestCase): headers={"Content-Type": "text/csv"}, ) + def test_text_updates_when_content_updates(self): + response = HttpResponse("Hello, world!") + self.assertEqual(response.text, "Hello, world!") + response.content = "Updated content" + self.assertEqual(response.text, "Updated content") + + def test_text_charset(self): + for content_type, content in [ + (None, b"Ol\xc3\xa1 Mundo"), + ("text/plain; charset=utf-8", b"Ol\xc3\xa1 Mundo"), + ("text/plain; charset=iso-8859-1", b"Ol\xe1 Mundo"), + ]: + with self.subTest(content_type=content_type): + response = HttpResponse(content, content_type=content_type) + self.assertEqual(response.text, "Olá Mundo") + class HttpResponseSubclassesTests(SimpleTestCase): def test_redirect(self): @@ -756,6 +772,13 @@ class StreamingHttpResponseTests(SimpleTestCase): with self.assertWarnsMessage(Warning, msg): self.assertEqual(b"hello", await anext(aiter(r))) + def test_text_attribute_error(self): + r = StreamingHttpResponse(iter(["hello", "world"])) + msg = "This %s instance has no `text` attribute." % r.__class__.__name__ + + with self.assertRaisesMessage(AttributeError, msg): + r.text + class FileCloseTests(SimpleTestCase): def setUp(self): From 0c8177551500e960d2dc04bc4b0fa7060f9172ae Mon Sep 17 00:00:00 2001 From: SaJH Date: Wed, 16 Oct 2024 01:11:46 +0900 Subject: [PATCH 39/40] Refs #35727 -- Updated response.content.decode calls to use the HttpResponse.text property. Signed-off-by: SaJH --- django/test/client.py | 4 +- tests/admin_views/test_autocomplete_view.py | 20 +++++----- tests/admin_views/tests.py | 18 ++++----- tests/auth_tests/test_views.py | 4 +- tests/csrf_tests/tests.py | 6 ++- tests/httpwrappers/tests.py | 12 +++--- tests/serializers/tests.py | 2 +- tests/sitemaps_tests/test_generic.py | 6 +-- tests/sitemaps_tests/test_http.py | 42 ++++++++++----------- tests/sitemaps_tests/test_https.py | 8 ++-- tests/view_tests/tests/test_i18n.py | 4 +- tests/view_tests/tests/test_json.py | 2 +- 12 files changed, 63 insertions(+), 65 deletions(-) diff --git a/django/test/client.py b/django/test/client.py index a755aae05c..85d91b0c44 100644 --- a/django/test/client.py +++ b/django/test/client.py @@ -947,9 +947,7 @@ class ClientMixin: 'Content-Type header is "%s", not "application/json"' % response.get("Content-Type") ) - response._json = json.loads( - response.content.decode(response.charset), **extra - ) + response._json = json.loads(response.text, **extra) return response._json def _follow_redirect( diff --git a/tests/admin_views/test_autocomplete_view.py b/tests/admin_views/test_autocomplete_view.py index dc3789fc5b..d9595cdb28 100644 --- a/tests/admin_views/test_autocomplete_view.py +++ b/tests/admin_views/test_autocomplete_view.py @@ -102,7 +102,7 @@ class AutocompleteJsonViewTests(AdminViewBasicTestCase): request.user = self.superuser response = AutocompleteJsonView.as_view(**self.as_view_args)(request) self.assertEqual(response.status_code, 200) - data = json.loads(response.content.decode("utf-8")) + data = json.loads(response.text) self.assertEqual( data, { @@ -120,7 +120,7 @@ class AutocompleteJsonViewTests(AdminViewBasicTestCase): request.user = self.superuser response = AutocompleteJsonView.as_view(**self.as_view_args)(request) self.assertEqual(response.status_code, 200) - data = json.loads(response.content.decode("utf-8")) + data = json.loads(response.text) self.assertEqual( data, { @@ -150,7 +150,7 @@ class AutocompleteJsonViewTests(AdminViewBasicTestCase): request.user = self.superuser response = AutocompleteJsonView.as_view(**self.as_view_args)(request) self.assertEqual(response.status_code, 200) - data = json.loads(response.content.decode("utf-8")) + data = json.loads(response.text) self.assertEqual( data, { @@ -184,7 +184,7 @@ class AutocompleteJsonViewTests(AdminViewBasicTestCase): request.user = self.superuser response = AutocompleteJsonView.as_view(**self.as_view_args)(request) self.assertEqual(response.status_code, 200) - data = json.loads(response.content.decode("utf-8")) + data = json.loads(response.text) self.assertEqual( data, { @@ -205,7 +205,7 @@ class AutocompleteJsonViewTests(AdminViewBasicTestCase): request.user = self.superuser response = AutocompleteJsonView.as_view(**self.as_view_args)(request) self.assertEqual(response.status_code, 200) - data = json.loads(response.content.decode("utf-8")) + data = json.loads(response.text) self.assertEqual( data, { @@ -250,7 +250,7 @@ class AutocompleteJsonViewTests(AdminViewBasicTestCase): request.user = self.superuser response = AutocompleteJsonView.as_view(**self.as_view_args)(request) self.assertEqual(response.status_code, 200) - data = json.loads(response.content.decode("utf-8")) + data = json.loads(response.text) self.assertEqual( data, { @@ -306,7 +306,7 @@ class AutocompleteJsonViewTests(AdminViewBasicTestCase): with model_admin(Question, DistinctQuestionAdmin): response = AutocompleteJsonView.as_view(**self.as_view_args)(request) self.assertEqual(response.status_code, 200) - data = json.loads(response.content.decode("utf-8")) + data = json.loads(response.text) self.assertEqual(len(data["results"]), 3) def test_missing_search_fields(self): @@ -335,7 +335,7 @@ class AutocompleteJsonViewTests(AdminViewBasicTestCase): with model_admin(Question, PKOrderingQuestionAdmin): response = AutocompleteJsonView.as_view(**self.as_view_args)(request) self.assertEqual(response.status_code, 200) - data = json.loads(response.content.decode("utf-8")) + data = json.loads(response.text) self.assertEqual( data, { @@ -352,7 +352,7 @@ class AutocompleteJsonViewTests(AdminViewBasicTestCase): with model_admin(Question, PKOrderingQuestionAdmin): response = AutocompleteJsonView.as_view(**self.as_view_args)(request) self.assertEqual(response.status_code, 200) - data = json.loads(response.content.decode("utf-8")) + data = json.loads(response.text) self.assertEqual( data, { @@ -380,7 +380,7 @@ class AutocompleteJsonViewTests(AdminViewBasicTestCase): request ) self.assertEqual(response.status_code, 200) - data = json.loads(response.content.decode("utf-8")) + data = json.loads(response.text) self.assertEqual( data, { diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index f63a9ca56f..17174ff5e0 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -296,9 +296,7 @@ class AdminViewBasicTestCase(TestCase): self.assertLess( response.content.index(text1.encode()), response.content.index(text2.encode()), - (failing_msg or "") - + "\nResponse:\n" - + response.content.decode(response.charset), + (failing_msg or "") + "\nResponse:\n" + response.text, ) @@ -3603,7 +3601,7 @@ class AdminViewDeletedObjectsTest(TestCase): response = self.client.get( reverse("admin:admin_views_villain_delete", args=(self.v1.pk,)) ) - self.assertRegex(response.content.decode(), pattern) + self.assertRegex(response.text, pattern) def test_cyclic(self): """ @@ -8266,7 +8264,7 @@ class AdminKeepChangeListFiltersTests(TestCase): # Check the `change_view` link has the correct querystring. detail_link = re.search( '{}'.format(self.joepublicuser.username), - response.content.decode(), + response.text, ) self.assertURLEqual(detail_link[1], self.get_change_url()) @@ -8278,7 +8276,7 @@ class AdminKeepChangeListFiltersTests(TestCase): # Check the form action. form_action = re.search( '
', - response.content.decode(), + response.text, ) self.assertURLEqual( form_action[1], "?%s" % self.get_preserved_filters_querystring() @@ -8286,13 +8284,13 @@ class AdminKeepChangeListFiltersTests(TestCase): # Check the history link. history_link = re.search( - 'History', response.content.decode() + 'History', response.text ) self.assertURLEqual(history_link[1], self.get_history_url()) # Check the delete link. delete_link = re.search( - 'Delete', response.content.decode() + 'Delete', response.text ) self.assertURLEqual(delete_link[1], self.get_delete_url()) @@ -8332,7 +8330,7 @@ class AdminKeepChangeListFiltersTests(TestCase): self.client.force_login(viewuser) response = self.client.get(self.get_change_url()) close_link = re.search( - 'Close', response.content.decode() + 'Close', response.text ) close_link = close_link[1].replace("&", "&") self.assertURLEqual(close_link, self.get_changelist_url()) @@ -8350,7 +8348,7 @@ class AdminKeepChangeListFiltersTests(TestCase): # Check the form action. form_action = re.search( '', - response.content.decode(), + response.text, ) self.assertURLEqual( form_action[1], "?%s" % self.get_preserved_filters_querystring() diff --git a/tests/auth_tests/test_views.py b/tests/auth_tests/test_views.py index 97d0448ab1..98fdfe79b7 100644 --- a/tests/auth_tests/test_views.py +++ b/tests/auth_tests/test_views.py @@ -1521,7 +1521,7 @@ class ChangelistTests(MessagesTestMixin, AuthViewsTestCase): # Test the link inside password field help_text. rel_link = re.search( r'Reset password', - response.content.decode(), + response.text, )[1] self.assertEqual(urljoin(user_change_url, rel_link), password_change_url) @@ -1617,7 +1617,7 @@ class ChangelistTests(MessagesTestMixin, AuthViewsTestCase): # Test the link inside password field help_text. rel_link = re.search( r'Set password', - response.content.decode(), + response.text, )[1] self.assertEqual(urljoin(user_change_url, rel_link), password_change_url) diff --git a/tests/csrf_tests/tests.py b/tests/csrf_tests/tests.py index b736276534..956cff11d9 100644 --- a/tests/csrf_tests/tests.py +++ b/tests/csrf_tests/tests.py @@ -1481,9 +1481,11 @@ class CsrfInErrorHandlingViewsTests(CsrfFunctionTestMixin, SimpleTestCase): response = self.client.get("/does not exist/") # The error handler returns status code 599. self.assertEqual(response.status_code, 599) - token1 = response.content.decode("ascii") + response.charset = "ascii" + token1 = response.text response = self.client.get("/does not exist/") self.assertEqual(response.status_code, 599) - token2 = response.content.decode("ascii") + response.charset = "ascii" + token2 = response.text secret2 = _unmask_cipher_token(token2) self.assertMaskedSecretCorrect(token1, secret2) diff --git a/tests/httpwrappers/tests.py b/tests/httpwrappers/tests.py index 154e9517fe..3774ff2d67 100644 --- a/tests/httpwrappers/tests.py +++ b/tests/httpwrappers/tests.py @@ -630,7 +630,7 @@ class JsonResponseTests(SimpleTestCase): def test_json_response_non_ascii(self): data = {"key": "łóżko"} response = JsonResponse(data) - self.assertEqual(json.loads(response.content.decode()), data) + self.assertEqual(json.loads(response.text), data) def test_json_response_raises_type_error_with_default_setting(self): with self.assertRaisesMessage( @@ -642,16 +642,16 @@ class JsonResponseTests(SimpleTestCase): def test_json_response_text(self): response = JsonResponse("foobar", safe=False) - self.assertEqual(json.loads(response.content.decode()), "foobar") + self.assertEqual(json.loads(response.text), "foobar") def test_json_response_list(self): response = JsonResponse(["foo", "bar"], safe=False) - self.assertEqual(json.loads(response.content.decode()), ["foo", "bar"]) + self.assertEqual(json.loads(response.text), ["foo", "bar"]) def test_json_response_uuid(self): u = uuid.uuid4() response = JsonResponse(u, safe=False) - self.assertEqual(json.loads(response.content.decode()), str(u)) + self.assertEqual(json.loads(response.text), str(u)) def test_json_response_custom_encoder(self): class CustomDjangoJSONEncoder(DjangoJSONEncoder): @@ -659,11 +659,11 @@ class JsonResponseTests(SimpleTestCase): return json.dumps({"foo": "bar"}) response = JsonResponse({}, encoder=CustomDjangoJSONEncoder) - self.assertEqual(json.loads(response.content.decode()), {"foo": "bar"}) + self.assertEqual(json.loads(response.text), {"foo": "bar"}) def test_json_response_passing_arguments_to_json_dumps(self): response = JsonResponse({"foo": "bar"}, json_dumps_params={"indent": 2}) - self.assertEqual(response.content.decode(), '{\n "foo": "bar"\n}') + self.assertEqual(response.text, '{\n "foo": "bar"\n}') class StreamingHttpResponseTests(SimpleTestCase): diff --git a/tests/serializers/tests.py b/tests/serializers/tests.py index 6ca0c15e04..420246db0b 100644 --- a/tests/serializers/tests.py +++ b/tests/serializers/tests.py @@ -155,7 +155,7 @@ class SerializersTestBase: if isinstance(stream, StringIO): self.assertEqual(string_data, stream.getvalue()) else: - self.assertEqual(string_data, stream.content.decode()) + self.assertEqual(string_data, stream.text) def test_serialize_specific_fields(self): obj = ComplexModel(field1="first", field2="second", field3="third") diff --git a/tests/sitemaps_tests/test_generic.py b/tests/sitemaps_tests/test_generic.py index dc998eec93..f0cd14699b 100644 --- a/tests/sitemaps_tests/test_generic.py +++ b/tests/sitemaps_tests/test_generic.py @@ -45,7 +45,7 @@ class GenericViewsSitemapTests(SitemapTestsBase): "%s\n" "" ) % expected - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) def test_generic_sitemap_lastmod(self): test_model = TestModel.objects.first() @@ -61,7 +61,7 @@ class GenericViewsSitemapTests(SitemapTestsBase): self.base_url, test_model.pk, ) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) self.assertEqual( response.headers["Last-Modified"], "Wed, 13 Mar 2013 10:00:00 GMT" ) @@ -89,4 +89,4 @@ class GenericViewsSitemapTests(SitemapTestsBase): http://example.com/simple/sitemap-generic.xml2013-03-13T10:00:00 """ - self.assertXMLEqual(response.content.decode("utf-8"), expected_content) + self.assertXMLEqual(response.text, expected_content) diff --git a/tests/sitemaps_tests/test_http.py b/tests/sitemaps_tests/test_http.py index 74d183a7b0..6ae7e0d7c4 100644 --- a/tests/sitemaps_tests/test_http.py +++ b/tests/sitemaps_tests/test_http.py @@ -29,7 +29,7 @@ class HTTPSitemapTests(SitemapTestsBase): self.base_url, date.today(), ) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) def test_sitemap_not_callable(self): """A sitemap may not be callable.""" @@ -42,7 +42,7 @@ class HTTPSitemapTests(SitemapTestsBase): self.base_url, date.today(), ) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) def test_paged_sitemap(self): """A sitemap may have multiple pages.""" @@ -54,7 +54,7 @@ class HTTPSitemapTests(SitemapTestsBase): """.format( self.base_url, date.today() ) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) @override_settings( TEMPLATES=[ @@ -76,7 +76,7 @@ class HTTPSitemapTests(SitemapTestsBase): self.base_url, date.today(), ) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) def test_simple_sitemap_section(self): "A simple sitemap section can be rendered" @@ -92,7 +92,7 @@ class HTTPSitemapTests(SitemapTestsBase): self.base_url, date.today(), ) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) def test_no_section(self): response = self.client.get("/simple/sitemap-simple2.xml") @@ -126,7 +126,7 @@ class HTTPSitemapTests(SitemapTestsBase): self.base_url, date.today(), ) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) @override_settings( TEMPLATES=[ @@ -148,7 +148,7 @@ class HTTPSitemapTests(SitemapTestsBase): self.base_url, date.today(), ) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) def test_sitemap_last_modified(self): "Last-Modified header is set correctly" @@ -268,7 +268,7 @@ class HTTPSitemapTests(SitemapTestsBase): "never0.5\n" "" ) % date.today() - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) def test_sitemap_get_urls_no_site_1(self): """ @@ -316,7 +316,7 @@ class HTTPSitemapTests(SitemapTestsBase): self.base_url, date.today(), ) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) def test_x_robots_sitemap(self): response = self.client.get("/simple/index.xml") @@ -346,7 +346,7 @@ class HTTPSitemapTests(SitemapTestsBase): "never0.5\n" "" ).format(self.base_url, self.i18n_model.pk) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) @override_settings(LANGUAGES=(("en", "English"), ("pt", "Portuguese"))) def test_alternate_i18n_sitemap_index(self): @@ -374,7 +374,7 @@ class HTTPSitemapTests(SitemapTestsBase): f"{expected_urls}\n" f"" ) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) @override_settings( LANGUAGES=(("en", "English"), ("pt", "Portuguese"), ("es", "Spanish")) @@ -404,7 +404,7 @@ class HTTPSitemapTests(SitemapTestsBase): f"{expected_urls}\n" f"" ) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) @override_settings(LANGUAGES=(("en", "English"), ("pt", "Portuguese"))) def test_alternate_i18n_sitemap_xdefault(self): @@ -434,7 +434,7 @@ class HTTPSitemapTests(SitemapTestsBase): f"{expected_urls}\n" f"" ) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) @override_settings(LANGUAGES=(("en", "English"), ("pt", "Portuguese"))) def test_language_for_item_i18n_sitemap(self): @@ -460,7 +460,7 @@ class HTTPSitemapTests(SitemapTestsBase): f"{expected_urls}\n" f"" ) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) @override_settings(LANGUAGES=(("en", "English"), ("pt", "Portuguese"))) def test_alternate_language_for_item_i18n_sitemap(self): @@ -500,7 +500,7 @@ class HTTPSitemapTests(SitemapTestsBase): f"{expected_urls}\n" f"" ) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) def test_sitemap_without_entries(self): response = self.client.get("/sitemap-without-entries/sitemap.xml") @@ -510,7 +510,7 @@ class HTTPSitemapTests(SitemapTestsBase): 'xmlns:xhtml="http://www.w3.org/1999/xhtml">\n\n' "" ) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) def test_callable_sitemod_partial(self): """ @@ -535,8 +535,8 @@ class HTTPSitemapTests(SitemapTestsBase): "http://example.com/location/\n" "" ) - self.assertXMLEqual(index_response.content.decode(), expected_content_index) - self.assertXMLEqual(sitemap_response.content.decode(), expected_content_sitemap) + self.assertXMLEqual(index_response.text, expected_content_index) + self.assertXMLEqual(sitemap_response.text, expected_content_sitemap) def test_callable_sitemod_full(self): """ @@ -566,8 +566,8 @@ class HTTPSitemapTests(SitemapTestsBase): "2014-03-13\n" "" ) - self.assertXMLEqual(index_response.content.decode(), expected_content_index) - self.assertXMLEqual(sitemap_response.content.decode(), expected_content_sitemap) + self.assertXMLEqual(index_response.text, expected_content_index) + self.assertXMLEqual(sitemap_response.text, expected_content_sitemap) def test_callable_sitemod_no_items(self): index_response = self.client.get("/callable-lastmod-no-items/index.xml") @@ -577,4 +577,4 @@ class HTTPSitemapTests(SitemapTestsBase): http://example.com/simple/sitemap-callable-lastmod.xml """ - self.assertXMLEqual(index_response.content.decode(), expected_content_index) + self.assertXMLEqual(index_response.text, expected_content_index) diff --git a/tests/sitemaps_tests/test_https.py b/tests/sitemaps_tests/test_https.py index 2eae71e4cc..a5369869f9 100644 --- a/tests/sitemaps_tests/test_https.py +++ b/tests/sitemaps_tests/test_https.py @@ -20,7 +20,7 @@ class HTTPSSitemapTests(SitemapTestsBase): self.base_url, date.today(), ) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) def test_secure_sitemap_section(self): "A secure sitemap section can be rendered" @@ -36,7 +36,7 @@ class HTTPSSitemapTests(SitemapTestsBase): self.base_url, date.today(), ) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) @override_settings(SECURE_PROXY_SSL_HEADER=False) @@ -54,7 +54,7 @@ class HTTPSDetectionSitemapTests(SitemapTestsBase): self.base_url.replace("http://", "https://"), date.today(), ) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) def test_sitemap_section_with_https_request(self): "A sitemap section requested in HTTPS is rendered with HTTPS links" @@ -70,4 +70,4 @@ class HTTPSDetectionSitemapTests(SitemapTestsBase): self.base_url.replace("http://", "https://"), date.today(), ) - self.assertXMLEqual(response.content.decode(), expected_content) + self.assertXMLEqual(response.text, expected_content) diff --git a/tests/view_tests/tests/test_i18n.py b/tests/view_tests/tests/test_i18n.py index 93e91bcc83..229ce68bfc 100644 --- a/tests/view_tests/tests/test_i18n.py +++ b/tests/view_tests/tests/test_i18n.py @@ -295,7 +295,7 @@ class I18NViewTests(SimpleTestCase): """ with override("de"): response = self.client.get("/jsoni18n/") - data = json.loads(response.content.decode()) + data = json.loads(response.text) self.assertIn("catalog", data) self.assertIn("formats", data) self.assertEqual( @@ -329,7 +329,7 @@ class I18NViewTests(SimpleTestCase): """ with self.settings(LANGUAGE_CODE="es"), override("en-us"): response = self.client.get("/jsoni18n/") - data = json.loads(response.content.decode()) + data = json.loads(response.text) self.assertIn("catalog", data) self.assertIn("formats", data) self.assertIn("plural", data) diff --git a/tests/view_tests/tests/test_json.py b/tests/view_tests/tests/test_json.py index 145e6e05a4..b314510f3c 100644 --- a/tests/view_tests/tests/test_json.py +++ b/tests/view_tests/tests/test_json.py @@ -10,7 +10,7 @@ class JsonResponseTests(SimpleTestCase): self.assertEqual(response.status_code, 200) self.assertEqual(response.headers["content-type"], "application/json") self.assertEqual( - json.loads(response.content.decode()), + json.loads(response.text), { "a": [1, 2, 3], "foo": {"bar": "baz"}, From 438fc42ac667653488200578a47e59f6608f2b0b Mon Sep 17 00:00:00 2001 From: Maryam Yusuf Date: Tue, 13 Aug 2024 00:21:49 +0100 Subject: [PATCH 40/40] Expanded contributor docs on getting feedback from the wider community. --- .../writing-code/submitting-patches.txt | 63 ++++++++++++++++--- docs/spelling_wordlist | 1 + 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/docs/internals/contributing/writing-code/submitting-patches.txt b/docs/internals/contributing/writing-code/submitting-patches.txt index cac6848d04..799292e3fd 100644 --- a/docs/internals/contributing/writing-code/submitting-patches.txt +++ b/docs/internals/contributing/writing-code/submitting-patches.txt @@ -114,7 +114,7 @@ requirements: feature, the change should also contain documentation. When you think your work is ready to be reviewed, send :doc:`a GitHub pull -request `. +request `. If you can't send a pull request for some reason, you can also use patches in Trac. When using this style, follow these guidelines. @@ -140,20 +140,63 @@ Regardless of the way you submit your work, follow these steps. .. _ticket tracker: https://code.djangoproject.com/ .. _Development dashboard: https://dashboard.djangoproject.com/ -Non-trivial contributions -========================= +Contributions which require community feedback +============================================== -A "non-trivial" contribution is one that is more than a small bug fix. It's a -change that introduces new Django functionality and makes some sort of design -decision. +A wider community discussion is required when a patch introduces new Django +functionality and makes some sort of design decision. This is especially +important if the approach involves a :ref:`deprecation ` +or introduces breaking changes. -If you provide a non-trivial change, include evidence that alternatives have -been discussed on the `Django Forum`_ or |django-developers| list. +The following are different approaches for gaining feedback from the community. -If you're not sure whether your contribution should be considered non-trivial, -ask on the ticket for opinions. +The Django Forum or django-developers mailing list +-------------------------------------------------- + +You can propose a change on the `Django Forum`_ or |django-developers| mailing +list. You should explain the need for the change, go into details of the +approach and discuss alternatives. + +Please include a link to such discussions in your contributions. + +Third party package +------------------- + +Django does not accept experimental features. All features must follow our +:ref:`deprecation policy `. Hence, it can +take months or years for Django to iterate on an API design. + +If you need user feedback on a public interface, it is better to create a +third-party package first. You can iterate on the public API much faster, while +also validating the need for the feature. + +Once this package becomes stable and there are clear benefits of incorporating +aspects into Django core, starting a discussion on the `Django Forum`_ or +|django-developers| mailing list would be the next step. + +Django Enhancement Proposal (DEP) +--------------------------------- + +Similar to Python’s PEPs, Django has `Django Enhancement Proposals`_ or DEPs. A +DEP is a design document which provides information to the Django community, or +describes a new feature or process for Django. They provide concise technical +specifications of features, along with rationales. DEPs are also the primary +mechanism for proposing and collecting community input on major new features. + +Before considering writing a DEP, it is recommended to first open a discussion +on the `Django Forum`_ or |django-developers| mailing list. This allows the +community to provide feedback and helps refine the proposal. Once the DEP is +ready the :ref:`Steering Council ` votes on whether to accept +it. + +Some examples of DEPs that have been approved and fully implemented: + +* `DEP 181: ORM Expressions `_ +* `DEP 182: Multiple Template Engines `_ +* `DEP 201: Simplified routing syntax `_ .. _Django Forum: https://forum.djangoproject.com/ +.. _Django Enhancement Proposals: https://github.com/django/deps .. _deprecating-a-feature: diff --git a/docs/spelling_wordlist b/docs/spelling_wordlist index d30f2ce440..747a712a62 100644 --- a/docs/spelling_wordlist +++ b/docs/spelling_wordlist @@ -123,6 +123,7 @@ deduplicates deduplication deepcopy deferrable +DEP deprecations deserialization deserialize