…e translations
naturaltime() composes naturaldelta() output with format strings like
'%s ago' / '%s from now'. Languages such as German require different
grammatical cases depending on the surrounding preposition (e.g.
nominative 'eine Stunde' vs dative 'einer Stunde' after 'vor').
The two-step composition (naturaldelta → wrap) made it impossible for
translators to provide case-correct forms because naturaldelta had no
knowledge of the context in which its result would be used.
Changes:
- Add _npgettext() to humanize.i18n (plural + context gettext).
- Add an optional 'context' parameter to naturaldelta(). When set,
all internal gettext/ngettext calls are replaced with their
pgettext/npgettext counterparts, keyed by the supplied context.
- naturaltime() now passes 'naturaltime-past' or 'naturaltime-future'
as context so translators can provide case-aware forms via msgctxt
entries in .po files.
The change is fully backward-compatible: without a context (or without
matching msgctxt translations), output is identical to before.
Fixes python-humanize#263
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fixes #263
Problem
naturaltime() composes naturaldelta() output with format strings like %s ago / %s from now. Languages such as German require different grammatical cases depending on the surrounding preposition (e.g. nominative eine Stunde vs dative einer Stunde after vor). The two-step composition made it impossible for translators to provide case-correct forms because naturaldelta had no knowledge of the tense context in which its result would be used.
Root cause
naturaldelta() uses _ngettext() / _() for all its translation strings. naturaltime() then wraps the result with _("%s ago"). There is no mechanism for translators to supply alternate grammatical forms of the time-unit strings depending on context.
Fix
How translators use this
German translators can now add msgctxt entries like:
`po
msgctxt "naturaltime-past"
msgid "a second"
msgstr "einer Sekunde"
msgctxt "naturaltime-future"
msgid "a second"
msgstr "einer Sekunde"
`
Without matching msgctxt translations, output is identical to before (full backward compatibility).
Validation