The country is rendered in the wrong language when the entity is translatable

Created on 2 June 2020, about 4 years ago
Updated 10 January 2024, 6 months ago

Problem/Motivation

Currently name of country based on the interface translation and not by content translation. It could be reproduced with all current field formatter by following steps:

  1. Enable English (default) and 'Chinese, Traditional' ('zh-hant' langcode) languages
  2. Enable content translation of Article node type (or any other content type)
  3. Add field 'Address' type for translatable node type (and make this field translatable)
  4. Fill in all fields including address field with following values:
    'country' => 'Taiwan',
    'administrative_area' => 'Taipei City',
    'locality' => "Da'an District",
    'address_line1' => 'Sec. 3 Hsin-yi Rd.',
    'postal_code' => '106',
    'organization' => 'Giant Bike Store',
    'given_name' => 'Wu',
    'family_name' => 'Chen',
  5. On save, you should see following values:

    Chen Wu

    Giant Bike Store

    Sec. 3 Hsin-yi Rd.

    Da'an District, Taipei City 106

    Taiwan

  6. So everything is correct and work as expected.

  7. But if we go to the same node in the Chinese language we will see the different output:

    Chen Wu
    Company name
    Sec. 3 Hsin-yi Rd.
    Da'an District, Taipei City 106
    台灣

    As you can see here we have a translation of country to the language of the interface but, not content language (because the content language we still have as English before adding translation).

I think that content language should have higher priority and in this particular step we should have an output like that:

Taiwan

And of course, when we have a translation of this node we should see this formatted address (for the Chinese language):

台灣
106
台北垂倧安區
Sec. 3 Hsin-yi Rd.
Company name
Chen Wu

with translations from Subdivision and Country repositories.

Proposed resolution

In order to improve this behavior, I think it would be useful to use the proposed patch and maybe, if possible to merge it.

🐛 Bug report
Status

Fixed

Version

2.0

Component

Code

Created by

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • First commit to issue fork.
  • Open in Jenkins → Open on Drupal.org →
    Core: 10.0.11 + Environment: PHP 8.1 & MySQL 5.7
    last update 6 months ago
    Patch Failed to Apply
  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 8.2 & MySQL 8
    last update 6 months ago
    Patch Failed to Apply
  • Status changed to Needs work 6 months ago
  • 🇷🇞Serbia bojanz

    It's too late to make a change this big in 8.x-1.x, but it sounds sensible for 2.0.x.

    The patch needs a reroll though.

  • First commit to issue fork.
  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 8.0 & MySQL 5.7
    last update 6 months ago
    29 pass, 2 fail
  • Status changed to Needs review 6 months ago
  • 🇮🇳India ankithashetty Karnataka, India

    Rerolled the patch in #6 as an MR against 2.x, thanks!

  • Status changed to Needs work 6 months ago
  • 🇷🇞Serbia bojanz

    Tests are failing with:

    Error: Class "Drupal\Tests\address\Kernel\Formatter\EntityTest" not found
    

    I think that 2.0.x has an extra test case ("AddressDefaultFormatterTest::testUruguayAddress") which also needs to be converted.

  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 8.0 & MySQL 5.7
    last update 6 months ago
    35 pass
  • 🇷🇞Serbia bojanz

    Let's try to fix the tests.

  • Status changed to Needs review 6 months ago
  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 8.0 & MySQL 5.7
    last update 6 months ago
    33 pass, 2 fail
  • 🇷🇞Serbia bojanz

    The problem here can be narrowed down. The country is rendered in an unexpected language.

    For country and zone fields, the fix is simple, we follow core and use $langcode.
    Address fields are a bit more complex, they have their own getLocale() getter, which returns the locale stored by initializeLocale:

      /**
       * Initializes and returns the langcode property for the current field.
       *
       * Some countries use separate address formats for the local language VS
       * other languages. For example, China uses major-to-minor ordering
       * when the address is entered in Chinese, and minor-to-major when the
       * address is entered in other languages.
       * This means that the address must remember which language it was
       * entered in, to ensure consistent formatting later on.
       *
       * - For translatable entities this information comes from the field langcode.
       * - Non-translatable entities have no way to provide this information, since
       *   the field langcode never changes. In this case the field must store
       *   the interface language at the time of address creation.
       * - It is also possible to override the used language via field settings,
       *   in case the language is always known (e.g. a field storing the "english
       *   address" on a chinese article).
       *
       * The langcode property is interpreted by getLocale(), and in case it's NULL,
       * the field langcode is returned instead (indicating a non-multilingual site
       * or a translatable parent entity).
       *
       * @return string|null
       *   The langcode, or NULL if the field langcode should be used instead.
       */
      public function initializeLangcode() {
    

    We are already using getLocale() elsewhere in the formatters, we just forgot to use it when fetching the country list.

    Two other problems I noticed:
    1) The Italian test is not needed, we can use the existing Taiwan test instead, which has an additional benefit of also ensuring the field order and subdivision names are selected via the right langcode.
    2) We need to update the used cache contexts.

    So, let's try this.

  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 8.0 & MySQL 5.7
    last update 6 months ago
    34 pass
  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 8.0 & MySQL 5.7
    last update 6 months ago
    34 pass
  • 🇷🇞Serbia bojanz

    Manual testing showed $langcode to be preferable to $address->getLocale() for non-translatable entities. Reverting to the original approach, and adding a comment explaining why.

    $address->getLocale() and $langcode are the same for translatable entities.
    For non-translatable entities $address->getLocale() exists to record the langcode at the time of address creation, so that we can rerender the address the same way (e.g. if it was created in Chinese, when we render, we continue to maintain the major-to-minor field order and the subdivisions in Chinese script). However, if we did the same for countries, then the site admin would be unable to recognize to which country the address belongs to. So we'll maintain old behavior and continue to show the country in the current interface language in that case.

    • bojanz → committed c62afe73 on 2.0.x
      Issue #3144823 by bojanz, Chewie, Upchuk, joevagyok, ieguskiza: The...
  • Status changed to Fixed 6 months ago
  • 🇷🇞Serbia bojanz

    Committed. Thanks to everyone at the European Commission for pushing this fix forward!

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.69.0 2024