In my previous post I showed how to easily access the human-readable value of a ListStringItem field, which is the type that’s used to power fields that are set by dropdowns, radios, and various types of multi-select. However, if you’re running a multi-lingual site, that method falls short, as it will only deliver the human-value in the default language. If you’ve translated these values into a second language (in my examples, French), you have to do something tricker to get the correct value.

In the previous post, MyListStringItem.php looks like this:

<?php
namespace Drupal\mymodule\Plugin\Field\FieldType;
use Drupal\options\Plugin\Field\FieldType\ListStringItem;

// extend the base class
class MyListStringItem extends ListStringItem {
  public function getHumanValue() { // add our custom method
    $allowed_values = $this->getSetting('allowed_values');
    $value = $allowed_values[$this->value];
    return $value;
  }
}

We’re can get the current language using

$lang = \Drupal::languageManager()->getCurrentLanguage()->getId();

We can get the config for a field like this:

$config = \Drupal::languageManager()->getLanguageConfigOverride($lang,'field.storage.field_my_field');

But we want the flexibility for this to work on any field when we getHumanValue. So we’ll need to know which field this is when we call getHumanValue:

$field_id = $this->definition->getFieldDefinition()->getFieldStorageDefinition()->id();

That seems ineligant to me, but it was the way I figured out how to do it. I wish there was a little less object-diving necessary to get the $field_id!

Once we have the translated $config, we can get the translated values from it:

$translated = $config->get('settings.allowed_values');

Unfortunately, they aren’t indexed by the ListStringItem keys, $translated just gives a numerically indexed array that seems to match up with the order of the key|label pairs. Again, we have to do something ineligant to get the translated value, but it works.

Now putting it all together:

namespace Drupal\mymodule\Plugin\Field\FieldType;
use Drupal\options\Plugin\Field\FieldType\ListStringItem;

// extend the base class
class MyListStringItem extends ListStringItem {
  public function getHumanValue() { // add our custom method
    $allowed_values = $this->getSetting('allowed_values');
    $value = $allowed_values[$this->value];

    $field_id = $this->definition->getFieldDefinition()->getFieldStorageDefinition()->id();
    $storage_id = 'field.storage.' . $field_id;

    $lang = \Drupal::languageManager()->getCurrentLanguage()->getId();
    $config = \Drupal::languageManager()->getLanguageConfigOverride($lang, $storage_id);

    // get the numeric index of the value of this field
    $i = array_search($this->value,array_keys($allowed_values));
    $translated = $config->get('settings.allowed_values');
    if (isset($translated[$i]))
      $value = $translated[$i]['label'];

    return $value;
  }
}

Phew! Finally we can get the correctly translated human readable value of a ListStringItem field

$value = $node->field_my_list_string->getHumanValue();

Or in a twig template:

The value is {{ node.field_my_list_string.getHumanValue }}