Opened 4 days ago

Last modified 4 days ago

#36279 new Bug

translatable path without a name attribute does not translate in django.urls.base.translate_url

Reported by: Rami Boutassghount Owned by:
Component: Core (URLs) Version: 5.1
Severity: Normal Keywords: set_language, i18n, translate_url, url, translation, url path
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Rami Boutassghount)

Dear all,

I was trying to mark a URL path for translation in the urlpatterns list object and I found an unexpected behavior when I try to change the language via set_language view (django.view.i18n.views.set_language).

A path must have a name attribute (for instance name="translate-url") in order to make the redirect work after a language change (set_language view). Otherwise, we get 404. This behavior may be a little bug in django (django.urls.base.translate_url), since the framework does not force the developer to use name in the url paths.

To put simple, I will explain it with code.

  • This will work (by 'work' I mean that we will get a translated url in the browser):
path(_('translate-this-url'), translate_this_url_view, name="translate-url"),
  • This will not work (we will get a 404 error)
path(_('translate-this-url'), translate_this_url_view,),

I dig a bit in the code and I found out that the function django.urls.base.translate_url may be missing a check (verify if the url_name attribute of the matched urlpath object is None or not). Check the following snippet:

# django.urls.base.translate_url
def translate_url(url, lang_code):
    parsed = urlsplit(url)
    try:
        # URL may be encoded.
        match = resolve(unquote(parsed.path))
    except Resolver404:
        pass
    else:
        
        # TODO: here we should do something (if url_name is None: do something else)
        
        to_be_reversed = (
            "%s:%s" % (match.namespace, match.url_name)
            if match.namespace
            else match.url_name
        )

        with override(lang_code):
            try:
                url = reverse(to_be_reversed, args=match.args, kwargs=match.kwargs)
            except NoReverseMatch:
                pass
            else:
                url = urlunsplit(
                    (parsed.scheme, parsed.netloc, url, parsed.query, parsed.fragment)
                )
    return url

Many thanks for having a look a the ticket!

According to the ticket's flags, the next step(s) to move this issue forward are:

  • To provide a patch by sending a pull request. Claim the ticket when you start working so that someone else doesn't duplicate effort. Before sending a pull request, review your work against the patch review checklist. Check the "Has patch" flag on the ticket after sending a pull request and include a link to the pull request in the ticket comment when making that update. The usual format is: [https://github.com/django/django/pull/#### PR].

Change History (3)

comment:1 by Rami Boutassghount, 4 days ago

Component: UncategorizedCore (URLs)
Type: UncategorizedBug

comment:2 by Sarah Boyce, 4 days ago

Easy pickings: unset
Summary: Maybe a little Bug in `django.urls.base.translate_url`translatable path without a name attribute does not translate in django.urls.base.translate_url
Triage Stage: UnreviewedAccepted

Thank you, replicated

  • TabularUnified tests/i18n/patterns/tests.py

    a b class URLTranslationTests(URLTestCaseBase):  
    186186                translate_url("/en/account/register-as-path/", "nl"),
    187187                "/nl/profiel/registreren-als-pad/",
    188188            )
     189            self.assertEqual(
     190                translate_url("/en/register-as-path/", "nl"),
     191                "/nl/registreren-als-pad/",
     192            )
    189193            self.assertEqual(translation.get_language(), "en")
    190194            # re_path() URL with parameters.
    191195            self.assertEqual(
  • TabularUnified tests/i18n/patterns/urls/default.py

    diff --git a/tests/i18n/patterns/urls/default.py b/tests/i18n/patterns/urls/default.py
    index 090b92eeca..0563394013 100644
    a b urlpatterns += i18n_patterns(  
    3535    re_path(
    3636        _(r"^account/"), include("i18n.patterns.urls.namespace", namespace="account")
    3737    ),
     38    path(_("register-as-path/"), view),
    3839)

comment:3 by Rami Boutassghount, 4 days ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.
Back to Top