Problem/Motivation

In a .po file, gettext identifies an entry by its context (msgctxt) and its source text (msgid). For a plural entry, the msgid is the singular text only.

On the other hand Drupal identifies and stores a plural string with its singular and its plural text together, so for Drupal, a plural string and another string with the same text as the singular are two different strings. But in a .po file, they are two entries with the same key, and gettext tools reject the file:

msgid "1 minute"
msgstr ""

msgid "1 minute"
msgid_plural "@count minutes"
msgstr[0] ""
msgstr[1] ""
  • msgfmt -c stops with "duplicate message definition".
  • msguniq merges the two entries into one fuzzy entry, without the plural. Poedit runs msguniq on such files when it opens them.

Currently, the translatable strings of Drupal core have five such duplicates.

Text Plural string Other string with the same text
"1 minute" core/misc/time-diff.js: Drupal.formatPlural(units, '1 minute', '@count minutes') $this->t('1 minute') in TimestampFormatter::getRefreshIntervals(), and in the time increments of DateTimeDatelistWidget and DateRangeDatelistWidget
"1 second" time-diff.js: Drupal.formatPlural(units, '1 second', '@count seconds') $this->t('1 second') in TimestampFormatter::getRefreshIntervals()
"Display" views-ui-view-info.html.twig: {% trans %}Display{% plural displays %}Displays{% endtrans %} $this->t('Display') in several places
"@count item" The Some pager of Views: "@count item" / "@count items" The Full pager of Views: "@count item" / "Paged, @count items"
"@count item, skip @skip" The Some pager: "@count item, skip @skip" / "@count items, skip @skip" The Full pager: "@count item, skip @skip" / "Paged, @count items, skip @skip"

This problem has been raised many times with potential outside solutions such as #556498: Singular string being the same as the msgid of a plural string is invalid Gettext but Drupal relies on it anyway, but we can also just fix the five strings that are misusing source strings anyway. Some of these strings even have other problems:

  • The refresh intervals and the time increments currently use t() with a number, like $this->t('@count minutes', ['@count' => 5]). With t(), a language has one translation for 5, 10, 15 and 30, but some languages need different plural forms for these numbers: Arabic, for example, uses one form for 5 and 10, and another one for 15 and 30. #3378675: Remove hardcoded "X minutes" translatable strings noted that a plural string would be better for translators.
  • time-diff.js currently uses "1 minute" as the singular, but DateFormatter::formatInterval() uses "@count minute" since #2712603: Counts for singulars in DateFormatter::formatInterval() are hardcoded to 1, as in some languages, the singular form is also used for 21, 31 and so on. So currently, the PHP and the JavaScript code have different plural strings for the same time units, and translators translate both.
  • The summary of the Full pager is currently "1 item" for one item, but "Paged, 5 items" for five.

Proposed resolution

The source strings should be changed so that no plural string has the same singular as another string:

  1. Time units in JavaScript: time-diff.js should reuse the existing plural strings of DateFormatter::formatInterval(): "@count year" / "@count years", and the same for months, weeks, days, hours, minutes and seconds.
  2. Time units in PHP: TimestampFormatter::getRefreshIntervals(), and the time increments of DateTimeDatelistWidget and DateRangeDatelistWidget, should use formatPlural() with the same strings, for example $this->formatPlural(5, '@count minute', '@count minutes') in place of $this->t('@count minutes', ['@count' => 5]).
  3. Views pagers: the Full pager should use "Paged, @count item" and "Paged, @count item, skip @skip" as the singulars.
  4. Views UI: the "Display" / "Displays" plural of views-ui-view-info.html.twig should have a context, for example {% trans with {'context': 'View displays'} %}. On 11.x, the copy of the template in the stable9 theme should have the same change.

Testing for the criteria of "no source strings have the singular as the same as a standalone string or another singular" would only be possible if potx would be integrated in core testing. I don't think that should be solved in this issue, but it could be a followup if desired. That would make core testing noticeably slower though, so not sure it is worth it.

Remaining tasks

  • Review.

User interface changes

The summary of a Full pager of one item will be "Paged, 1 item" in place of "1 item". The other English text will not change.

Introduced terminology

None.

API changes

None.

Data model changes

None.

Release notes snippet

Not applicable.

LLM disclosure

LLM was used to draft this issue with human review.

Issue fork drupal-3631439

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

gábor hojtsy created an issue. See original summary.

gábor hojtsy’s picture

Status: Active » Needs review
gábor hojtsy’s picture

There is the more general #3122231: Singular variant for plural string must contain @count, otherwise Drupal displays wrong data for untranslated strings which sets up a new practice to avoid this in the future. That intentionally avoids changing these strings though, so the two issues can work together.

kingdutch’s picture

Status: Needs review » Reviewed & tested by the community

Approving this based on reviewing the MR and matching that against my experience with translations of our own product and the translation tooling we use that builds on POTX.

The text changes are as expected.

fmb’s picture

Also looks good to me.

quietone’s picture

Title: Fix Drupal core plural strings with the same singular as another string (makes the translation files of core invalid for gettext and other tools) » Fix plural strings with the same singular as another string

Updated title, I remove 'Drupal core' since this is the core queue and removed the explanation, which can stay in the issue summary.

gábor hojtsy’s picture

Issue tags: +Plural handling
alexpott’s picture

Version: main » 12.0.x-dev
Status: Reviewed & tested by the community » Fixed

Committed and pushed 89df3a065de to main and 69ead8f8540 to 12.0.x. Thanks!

Backported to 12.0.x as allowed changes to strings before release.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

  • alexpott committed 69ead8f8 on 12.0.x
    fix: #3631439 Fix plural strings with the same singular as another...

  • alexpott committed 89df3a06 on main
    fix: #3631439 Fix plural strings with the same singular as another...
gábor hojtsy’s picture