question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

naturaltime: wrong translation with delta >= 2 years

See original GitHub issue

What did you do?

Ran the following code:

import humanize
import datetime as dt

humanize.i18n.activate("fr_FR")
output = humanize.naturaltime(dt.datetime(year=2010, month=1, day=1))
print(output)

What did you expect to happen?

Output to be:

il y a 12 ans

What actually happened?

Output was:

il y a 12 years

What versions are you using?

  • OS: Mac OS
  • Python: 3.8.6
  • Humanize: 4.0.1

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:6 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
carterboxcommented, Jun 20, 2022

The general translation workflow seems to be:

  1. generate possible format strings
  2. translate the unevaluated format strings
  3. evaluate the format strings.

When I added the intcomma feature for years in the time module, I didn’t properly test step 2 (translate the format string). Since the translation works directly on the format string and the translation phrases include the formatters (probably because in some locales the order is changed), switching from %d to %s broke the translation step. This means the translation is broken for all translated languages.

Notably, this translation error does not occur in precisedelta() because the translation and format evaluation occur on multiple lines, so the %d are swapped for %s after translation.

https://github.com/python-humanize/humanize/blob/29d37fb15945433d295b942bd839ae152770eca0/src/humanize/time.py#L564-L567

So the solution would be to match naturaldelta() with precisedelta() and swap the formatter after the translation.

I don’t want to change the translation files or swap the formatters in other places because using %d instead of %s may be used to do rounding or truncation of floating point numbers.

1reaction
hugovkcommented, Jun 17, 2022

Here’s a more direct reproducer. The first three asserts are fine, but the last fails because it get “12 years” not “12 ans”:

import humanize

output = humanize.naturaldelta(1 * 365 * 24 * 60 * 60)
print(output)
assert output == "a year"

output = humanize.naturaldelta(12 * 365 * 24 * 60 * 60)
print(output)
assert output == "12 years"


humanize.i18n.activate("fr_FR")

output = humanize.naturaldelta(1 * 365 * 24 * 60 * 60)
print(output)
assert output == "un an"

output = humanize.naturaldelta(12 * 365 * 24 * 60 * 60)
print(output)  # "12 years"
assert output == "12 ans"

This was introduced in https://github.com/python-humanize/humanize/commit/d1faf1cff76d5add3b4e9849522d8ea9a0f49d0d from PR https://github.com/jmoiron/humanize/pull/246:

Instead of passing an integer to the _ngettext localisation function we’re passing in the results of intcomma(years) which is a string:

-        return _ngettext("%d year", "%d years", years) % years
+        return _ngettext("%s year", "%s years", years) % intcomma(years)

And also I think it can’t find "%s year", "%s years" values because they use %d in the translation files:

https://github.com/python-humanize/humanize/blob/7688f204a994e55f8e607675363178e5d8424523/src/humanize/locale/fr_FR/LC_MESSAGES/humanize.po#L339-L344

Ping @carterbox, please could you have a look at this?

Read more comments on GitHub >

github_iconTop Results From Across the Web

21408 (Fallback to timesince produces erroneous translations ...
"3 Tage" is correct for timesince , but for naturaltime it must become "3 Tagen". Unfortunately, the assumption that these translations can simply...
Read more >
Django Humanize naturaltime templatetag only partly translating
Django Humanize naturaltime templatetag only partly translating ... 0: # Translators: delta will contain a string like '2 months' or '1 ...
Read more >
Issues with the new naturaltime template tag - Google Groups
a chance to translate words generated here by timesince/timeuntil differently. The past form would sound like either "age %(delta)s" or "%(delta)s in the...
Read more >
XCHART Statement
Defining the V-Mask for a Two-Sided Cusum Scheme . ... delta. = 1. /* shift to be detected. */ alpha. = 0.10. /*...
Read more >
TRANSLATION - DTIC
The sentence word order has been partially rearranged for readability. The content of this translation does not indicate editorial accuracy, nor does it ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found