Re: [Django] #36279: translatable path without a name attribute does not translate in django.urls.base.translate_url

2 views
Skip to first unread message

Django

unread,
Mar 27, 2025, 12:43:20 PM (5 days ago) Mar 27
to django-...@googlegroups.com
#36279: translatable path without a name attribute does not translate in
django.urls.base.translate_url
-------------------------------------+-------------------------------------
Reporter: Rami | Owner: (none)
Type: Bug | Status: new
Component: Core (URLs) | Version: 5.1
Severity: Normal | Resolution:
Keywords: set_language, i18n, | Triage Stage: Accepted
translate_url, url, translation, |
url path |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Description changed by Rami:

Old description:

> 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"),
> the redirect works once 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!

New description:

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!

--
--
Ticket URL: <https://code.djangoproject.com/ticket/36279#comment:3>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
Reply all
Reply to author
Forward
0 new messages