#34853: [Date Input Localization] Accept-Language Header Takes Precedence Over
Language Set With Cookie
-------------------------------------+-------------------------------------
     Reporter:  blue-hexagon         |                    Owner:  nobody
         Type:  Bug                  |                   Status:  new
    Component:                       |                  Version:  4.1
  Internationalization               |
     Severity:  Normal               |               Resolution:
     Keywords:  l10n localization    |             Triage Stage:
  form input                         |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Description changed by blue-hexagon:

Old description:

> = Accept-Language Header takes precedence over language set with cookie =
>
> The input localization follows the browsers locale.
>
> In the first image below, my browsers locale is 'da' (Danish/Dansk) while
> Django language is en-GB - the form inputs should be localized to en-GB
> and *not* danish!
>
> In the second image, my browsers locale is 'en-GB' and Django language is
> 'da' (Danish) - the form inputs should be localized to danish and not en-
> GB!
>
> The images clearly shows the error.
>
> I have provided every relevant piece of information I can think of below
> the images.
>
> Nowhere in the Django docs, does it mention that form inputs should be
> localized to the browsers locale.
>
> [[Image(https://i.imgur.com/twLMfDc.png)]]
> [[Image(https://i.imgur.com/HnE2HgC.png)]]
>
> == Middleware ==
> {{{
> #!python
> MIDDLEWARE = [
>     "django.middleware.security.SecurityMiddleware",
>     "django.middleware.gzip.GZipMiddleware",
>     "django.contrib.sessions.middleware.SessionMiddleware",
>     'django.middleware.locale.LocaleMiddleware',
>     "django.middleware.common.CommonMiddleware",
>     "django.middleware.csrf.CsrfViewMiddleware",
>     "django.contrib.auth.middleware.AuthenticationMiddleware",
>     "django.contrib.messages.middleware.MessageMiddleware",
>     "django.middleware.clickjacking.XFrameOptionsMiddleware",
>     "django.middleware.common.BrokenLinkEmailsMiddleware",
> ]
> }}}
>
> == I18N / L10N ==
> {{{
> #!python
> TIME_ZONE = "UTC"
> LANGUAGE_CODE = "en"
> LANGUAGES = [
>     ('en', _('English')),
>     ('en-gb', _('English')),
>     ('da', _('Danish')),
> ]
>
> USE_I18N = True
> LANGUAGE_COOKIE_AGE = 31_536_000  # 1 year.
>
> USE_L10N = True
> USE_THOUSAND_SEPARATOR = True
> USE_TZ = True
>
> LOCALE_PATHS = [
>     BASE_DIR / 'locale/',
> ]
> }}}
>
> == Loan View ==
> {{{
> #!python
> @login_required(login_url="/accounts/login/")
> def loan_create(request, institution_id: int):
>     if request.POST:
>         form = LoanForm(request.POST)
>         if form.is_valid():
>             form.save()
>             messages.add_message(request, messages.SUCCESS, _("Loan
> created successfully."))
>             return redirect(request.META.get("HTTP_REFERER",
> request.path_info))
>         else:
>             messages.add_message(request, messages.ERROR, _("An error
> occured."))
>             return redirect(request.META.get("HTTP_REFERER",
> request.path_info))
>     form = LoanFormCreate(
>         institution_id=institution_id,
>         initial={
>             "staff": request.user.id,
>             "reminder_has_been_sent": 0,
>             "is_returned": False,
>         },
>     )
>     return render(
>         request,
>         template_name="crud/loan/create.html",
>         context={
>             "form": form,
>         },
>     )
> }}}
>
> == Modelforms for Loan ==
> {{{
> #!python
> class LoanForm(ModelForm):
>     def __init__(self, *args, **kwargs):
>         super().__init__(*args, **kwargs)
>
>     class Meta:
>         model = Loan
>         fields = "__all__"
>

> class LoanFormBase(ModelForm):
>     def __init__(self, *args, **kwargs):
>         super().__init__(*args, **kwargs)
>
>     class Meta:
>         localized_fields = [
>             "borrowed_from_date",
>             "borrowed_to_date",
>             "deposit"
>         ]
>         model = Loan
>         fields = [
>             "id",
>             "borrower_user",
>             "staff_user",
>             "item",
>             "borrowed_from_date",
>             "borrowed_to_date",
>             "reminder_has_been_sent",
>             "is_returned",
>             "extra_information",
>             "deposit",
>         ]
>         widgets = {
>             "id": forms.NumberInput(),
>             "staff_user": forms.Select(attrs={"class": "form-control"}),
>             "borrower_user": forms.Select(attrs={"class": "form-
> control"}),
>             "item": forms.Select(attrs={"class": "form-control", "data-
> live-search": True}),
>             "borrowed_from_date": forms.DateInput(
>                 attrs={"class": "form-control", "type": "date"},
> format=locale_format
>             ),
>             "borrowed_to_date": forms.DateInput(attrs={"class": "form-
> control", "type": "date"}),
>             "reminder_has_been_sent": forms.NumberInput(attrs={"class":
> "form-control "}),
>             "is_returned": forms.CheckboxInput(attrs={"class": "form-
> control"}),
>             "extra_information": forms.Textarea(attrs={"class": "form-
> control", "rows": 4}),
>             "deposit": forms.TextInput(attrs={"class": "form-control"}),
>         }
>         labels = {
>             "staff_user": _("Lender"),
>             "borrower_user": _("Borrower"),
>             "item": _("Loaned Asset"),
>             "borrowed_from_date": _("Loaned From"),
>             "borrowed_to_date": _("Loaned To"),
>             "is_returned": _("Returned"),
>             "extra_information": _("Comments"),
>             "deposit": _("Deposit"),
>             "reminder_has_been_sent": _("Reminder Sent"),
>         }
>
>         help_texts = {
>             "staff_user": _("Select the person responsible for lending
> the asset to the borrower."),
>             "borrower_user": _("Select the person who borrowed the
> asset."),
>             "item": _("Select the asset that has been loaned out."),
>             "borrowed_from_date": _("Pick the date when the asset was
> borrowed."),
>             "borrowed_to_date": _("Pick the expected return date for the
> asset."),
>             "is_returned": _("Check this box when the asset has been
> returned."),
>             "extra_information": _("Add any relevant comments or
> additional information about the loan here."),
>             "deposit": _("Enter the deposit amount, if applicable."),
>             "reminder_has_been_sent": _("Check if a reminder has been
> sent for this loan."),
>         }
>

> class LoanFormCreate(LoanFormBase):
>     def __init__(self, institution_id: int, *args, **kwargs):
>         super().__init__(*args, **kwargs)
>         # Items shall belong to the institution
>         self.fields["item"].queryset =
> Item.objects.filter(item_group__institution_id=institution_id)
>
>         # Borrower users shall belong to the institution
>         self.fields["borrower_user"].queryset = User.objects.filter()
>         institution_staff_ids =
> StaffInstitution.objects.filter().values_list("staff_id")
>         self.fields["staff_user"].queryset =
> User.objects.filter().exclude()
>
>     class Meta(LoanFormBase.Meta):
>         localized_fields = [
>             "borrowed_from_date",
>             "borrowed_to_date",
>             "deposit"
>         ]
>         exclude = ["id", "is_returned"]
>         widgets = {
>             "extra_information": forms.Textarea(attrs={"class": "form-
> control", "rows": 4}),
>             "borrowed_from_date": forms.DateInput(
>                 attrs={"class": "form-control", "type": "date"},
>             ),
>             "borrowed_to_date": forms.DateInput(
>                 attrs={"class": "form-control", "type": "date"},
>             ),
>             "item": forms.Select(
>                 attrs={
>                     "class": "form-control selectpicker border",
>                     "data-live-search": "true",
>                     "data-show-subtext": "true",
>                     "data-style": "form-control",
>                 }
>             ),
>             "borrower_user": forms.Select(
>                 attrs={
>                     "class": "form-control selectpicker border",
>                     "data-live-search": "true",
>                     "data-show-subtext": "true",
>                     "data-style": "form-control",
>                 }
>             ),
>             "staff_user": forms.Select(
>                 attrs={
>                     "class": "form-control selectpicker border ",
>                     "data-live-search": "true",
>                     "data-show-subtext": "true",
>                     "data-style": "form-control",
>                     "": "",
>                 }
>             ),
>             "reminder_has_been_sent": forms.NumberInput(attrs={"hidden":
> None}),
>         }
> }}}
>
> == Input Dates in Images from HTML file ==
> {{{
> #!jinja
> {# ---------------------------------------------------- #}
> {# --- Trying out with and without filters and tags --- #}
> {{ form.borrowed_to_date }}
> {{ form.borrowed_to_date|localize }}
> {% localize off %}
> {{ form.borrowed_to_date }}
> {% endlocalize %}
> {% localize on %}
> {{ form.borrowed_to_date }}
> {% endlocalize %}
> {# ---------------------------------------------------- #}
> }}}

New description:

 = Accept-Language Header takes precedence over language set with cookie =

 The input localization follows the browsers locale.

 In the first image below, my browsers locale is 'da' (Danish/Dansk) while
 Django language is en-GB - the form inputs should be localized to en-GB
 and *not* danish!

 In the second image, my browsers locale is 'en-GB' and Django language is
 'da' (Danish) - the form inputs should be localized to danish and not en-
 GB!

 The images clearly shows the error.

 I have provided every relevant piece of information I can think of below
 the images.

 Nowhere in the Django docs, does it mention that form inputs should be
 localized to the browsers locale.

 **Image 1**
 [[Image(https://i.imgur.com/twLMfDc.png)]]

 **Image 2**
 [[Image(https://i.imgur.com/HnE2HgC.png)]]

 == Middleware ==
 {{{
 #!python
 MIDDLEWARE = [
     "django.middleware.security.SecurityMiddleware",
     "django.middleware.gzip.GZipMiddleware",
     "django.contrib.sessions.middleware.SessionMiddleware",
     'django.middleware.locale.LocaleMiddleware',
     "django.middleware.common.CommonMiddleware",
     "django.middleware.csrf.CsrfViewMiddleware",
     "django.contrib.auth.middleware.AuthenticationMiddleware",
     "django.contrib.messages.middleware.MessageMiddleware",
     "django.middleware.clickjacking.XFrameOptionsMiddleware",
     "django.middleware.common.BrokenLinkEmailsMiddleware",
 ]
 }}}

 == I18N / L10N ==
 {{{
 #!python
 TIME_ZONE = "UTC"
 LANGUAGE_CODE = "en"
 LANGUAGES = [
     ('en', _('English')),
     ('en-gb', _('English')),
     ('da', _('Danish')),
 ]

 USE_I18N = True
 LANGUAGE_COOKIE_AGE = 31_536_000  # 1 year.

 USE_L10N = True
 USE_THOUSAND_SEPARATOR = True
 USE_TZ = True

 LOCALE_PATHS = [
     BASE_DIR / 'locale/',
 ]
 }}}

 == Loan View ==
 {{{
 #!python
 @login_required(login_url="/accounts/login/")
 def loan_create(request, institution_id: int):
     if request.POST:
         form = LoanForm(request.POST)
         if form.is_valid():
             form.save()
             messages.add_message(request, messages.SUCCESS, _("Loan
 created successfully."))
             return redirect(request.META.get("HTTP_REFERER",
 request.path_info))
         else:
             messages.add_message(request, messages.ERROR, _("An error
 occured."))
             return redirect(request.META.get("HTTP_REFERER",
 request.path_info))
     form = LoanFormCreate(
         institution_id=institution_id,
         initial={
             "staff": request.user.id,
             "reminder_has_been_sent": 0,
             "is_returned": False,
         },
     )
     return render(
         request,
         template_name="crud/loan/create.html",
         context={
             "form": form,
         },
     )
 }}}

 == Modelforms for Loan ==
 {{{
 #!python
 class LoanForm(ModelForm):
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)

     class Meta:
         model = Loan
         fields = "__all__"


 class LoanFormBase(ModelForm):
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)

     class Meta:
         localized_fields = [
             "borrowed_from_date",
             "borrowed_to_date",
             "deposit"
         ]
         model = Loan
         fields = [
             "id",
             "borrower_user",
             "staff_user",
             "item",
             "borrowed_from_date",
             "borrowed_to_date",
             "reminder_has_been_sent",
             "is_returned",
             "extra_information",
             "deposit",
         ]
         widgets = {
             "id": forms.NumberInput(),
             "staff_user": forms.Select(attrs={"class": "form-control"}),
             "borrower_user": forms.Select(attrs={"class": "form-
 control"}),
             "item": forms.Select(attrs={"class": "form-control", "data-
 live-search": True}),
             "borrowed_from_date": forms.DateInput(
                 attrs={"class": "form-control", "type": "date"},
 format=locale_format
             ),
             "borrowed_to_date": forms.DateInput(attrs={"class": "form-
 control", "type": "date"}),
             "reminder_has_been_sent": forms.NumberInput(attrs={"class":
 "form-control "}),
             "is_returned": forms.CheckboxInput(attrs={"class": "form-
 control"}),
             "extra_information": forms.Textarea(attrs={"class": "form-
 control", "rows": 4}),
             "deposit": forms.TextInput(attrs={"class": "form-control"}),
         }
         labels = {
             "staff_user": _("Lender"),
             "borrower_user": _("Borrower"),
             "item": _("Loaned Asset"),
             "borrowed_from_date": _("Loaned From"),
             "borrowed_to_date": _("Loaned To"),
             "is_returned": _("Returned"),
             "extra_information": _("Comments"),
             "deposit": _("Deposit"),
             "reminder_has_been_sent": _("Reminder Sent"),
         }

         help_texts = {
             "staff_user": _("Select the person responsible for lending the
 asset to the borrower."),
             "borrower_user": _("Select the person who borrowed the
 asset."),
             "item": _("Select the asset that has been loaned out."),
             "borrowed_from_date": _("Pick the date when the asset was
 borrowed."),
             "borrowed_to_date": _("Pick the expected return date for the
 asset."),
             "is_returned": _("Check this box when the asset has been
 returned."),
             "extra_information": _("Add any relevant comments or
 additional information about the loan here."),
             "deposit": _("Enter the deposit amount, if applicable."),
             "reminder_has_been_sent": _("Check if a reminder has been sent
 for this loan."),
         }


 class LoanFormCreate(LoanFormBase):
     def __init__(self, institution_id: int, *args, **kwargs):
         super().__init__(*args, **kwargs)
         # Items shall belong to the institution
         self.fields["item"].queryset =
 Item.objects.filter(item_group__institution_id=institution_id)

         # Borrower users shall belong to the institution
         self.fields["borrower_user"].queryset = User.objects.filter()
         institution_staff_ids =
 StaffInstitution.objects.filter().values_list("staff_id")
         self.fields["staff_user"].queryset =
 User.objects.filter().exclude()

     class Meta(LoanFormBase.Meta):
         localized_fields = [
             "borrowed_from_date",
             "borrowed_to_date",
             "deposit"
         ]
         exclude = ["id", "is_returned"]
         widgets = {
             "extra_information": forms.Textarea(attrs={"class": "form-
 control", "rows": 4}),
             "borrowed_from_date": forms.DateInput(
                 attrs={"class": "form-control", "type": "date"},
             ),
             "borrowed_to_date": forms.DateInput(
                 attrs={"class": "form-control", "type": "date"},
             ),
             "item": forms.Select(
                 attrs={
                     "class": "form-control selectpicker border",
                     "data-live-search": "true",
                     "data-show-subtext": "true",
                     "data-style": "form-control",
                 }
             ),
             "borrower_user": forms.Select(
                 attrs={
                     "class": "form-control selectpicker border",
                     "data-live-search": "true",
                     "data-show-subtext": "true",
                     "data-style": "form-control",
                 }
             ),
             "staff_user": forms.Select(
                 attrs={
                     "class": "form-control selectpicker border ",
                     "data-live-search": "true",
                     "data-show-subtext": "true",
                     "data-style": "form-control",
                     "": "",
                 }
             ),
             "reminder_has_been_sent": forms.NumberInput(attrs={"hidden":
 None}),
         }
 }}}

 == Input Dates in Images from HTML file ==
 {{{
 #!jinja
 {# ---------------------------------------------------- #}
 {# --- Trying out with and without filters and tags --- #}
 {{ form.borrowed_to_date }}
 {{ form.borrowed_to_date|localize }}
 {% localize off %}
 {{ form.borrowed_to_date }}
 {% endlocalize %}
 {% localize on %}
 {{ form.borrowed_to_date }}
 {% endlocalize %}
 {# ---------------------------------------------------- #}
 }}}

--

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34853#comment:2>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/0107018aae23e81e-59b7f596-00bf-46a2-a74a-51cb80029a2d-000000%40eu-central-1.amazonses.com.

Reply via email to