Opened 10 years ago

Closed 6 years ago

Last modified 6 years ago

#21408 closed Bug (fixed)

Fallback to timesince produces erroneous translations in naturaltime

Reported by: 676c7473@… Owned by: Maximilian Merz
Component: Internationalization Version: dev
Severity: Normal Keywords: i18n l10n translation
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

The naturaltime filter in django.contrib.humanize composes strings for days, weeks, months, and years from the words "ago" and "in" and the output of the built-in timesince filter. See here, where delta is to be supplied by timesince:

#: templatetags/humanize.py:190
#, python-format
msgctxt "naturaltime"
msgid "%(delta)s ago"
msgstr "vor %(delta)s"

This produces erroneous translations in German (and probably other inflectional languages, too).

"3 days, 12 hours ago" is translated by Django as

vor 3 Tage, 12 Stunden

but the correct translation is (with dative inflection)

vor 3 Tagen, 12 Stunden

"3 Tage" is correct for timesince, but for naturaltime it must become "3 Tagen". Unfortunately, the assumption that these translations can simply be pieced together from translated bits in timesince.py is mistaken.

I apologise if this isn't the right channel. I'd be glad to help, but so far I haven't seen a good way to avoid duplicating translations.

Change History (14)

comment:1 by Claude Paroz, 10 years ago

Component: TranslationsInternationalization
Triage Stage: UnreviewedAccepted
Version: 1.6master

Surely, this will need duplication of translatable strings. One solution would be to make the django.utils.timesince utility to accept a new optional argument containing a set of translatable strings. Then, naturaltime will be able to provide its own set of npgettext_lazy (with context) strings.

comment:2 by 676c7473@…, 10 years ago

Thank you for your answer. Slightly off-topic: I noticed a minor error in the docs for npgettext_lazy and have fixed it in https://github.com/django/django/pull/1895.

comment:3 by 676c7473@…, 10 years ago

I'm running into some difficulties with the code and the translations. Could it be that the .po files are out of sync with the code?

in humanize.py, line 204, there are bits like this one:

    return ungettext(
        # Translators: \\u00a0 is non-breaking space
        'a second ago', '%(count)s\u00a0seconds ago', delta.seconds
    ) % {'count': delta.seconds}

There is a corresponding entry in the "en" locale, but in the "de" locale it looks different:

#. Translators: \\u00a0 is non-breaking space
#: templatetags/humanize.py:198
#, python-format
msgid "a second ago"
msgid_plural "%(count)s\\u00a0seconds ago"
msgstr[0] ""
msgstr[1] ""
#: templatetags/humanize.py:196
#, python-format
msgid "a second ago"
msgid_plural "%(count)s seconds ago"
msgstr[0] "vor einer Sekunde"
msgstr[1] "vor %(count)s Sekunden"

I guess the translation is still found because the msgid is the same, but the German translation doesn't have the non-breaking space.

Also, these gettext messages in timesince.py, line 24,

    chunks = (
        (60 * 60 * 24 * 365, ungettext_lazy('%d year', '%d years')),
        (60 * 60 * 24 * 30, ungettext_lazy('%d month', '%d months')),
        ...

don't exist in the "de" translations. As far as I can tell, the msgid "year" will not match "%d year".

#: utils/timesince.py:23
#, python-format
msgid "%d year"
msgid_plural "%d years"
msgstr[0] ""
msgstr[1] ""
#: utils/timesince.py:22
msgid "year"
msgid_plural "years"
msgstr[0] "Jahr"
msgstr[1] "Jahre"

I'm not sure what's happening here. I'll experiment some more, maybe things will become clearer soon. If you want to share some advice, please do! Thanks.

comment:4 by Claude Paroz, 10 years ago

You might find more up-to-date translations in the 1.6.x branch. We've still not updated master with the more recent translations.

comment:5 by 676c7473@…, 10 years ago

Yes, @claudep, thank you, unfortunately there are no unit tests for those, and consequently the bug they introduced was overlooked: ticket:21415 Sorry for not noticing this earlier.

David

comment:6 by Markus Bertheau, 7 years ago

Bug still exists in 1.8.

A workaround for German for intervals into the future is to manually replace 'in' with 'noch', resulting in 'noch 2 Tage, 3 Stunden', which is correct.

comment:7 by Maximilian Merz, 6 years ago

Owner: changed from nobody to Maximilian Merz
Status: newassigned

comment:8 by Maximilian Merz, 6 years ago

comment:9 by Tim Graham, 6 years ago

Has patch: set

comment:10 by Claude Paroz, 6 years ago

Patch needs improvement: set

comment:11 by Carlton Gibson, 6 years ago

Patch needs improvement: unset
Triage Stage: AcceptedReady for checkin

comment:12 by Claude Paroz <claude@…>, 6 years ago

Resolution: fixed
Status: assignedclosed

In 78912ccd:

Fixed #21408 — German Translation for “3 days ago”

The problem:
“3 days ago” should translate to “vor 3 Tagen” in German, while “3 days” translates to “3 Tage”. #21408 describes that django always translated to “Tage”, even when the dative “Tagen” was correct. The same applies to months (“Monate”/“Monaten”) and years (“Jahre”/“Jahren”).

The solution:
Let timesince caller provide the string dict to use for the time-related strings.

comment:13 by Carlton Gibson <carlton.gibson@…>, 6 years ago

In ddcb9e80:

Refs #21408 -- Updated naturaltime translation test.

Upcoming German translations will not differ for past and future naturaltime
translations. Using Czech language instead.

comment:14 by Carlton Gibson <carlton.gibson@…>, 6 years ago

In 7b444bf:

[2.1.x] Refs #21408 -- Updated naturaltime translation test.

Upcoming German translations will not differ for past and future naturaltime
translations. Using Czech language instead.
Backport of ddcb9e806275114c91bbed90bc917374ba08a9ae from master

Note: See TracTickets for help on using tickets.
Back to Top