Commit 256ad918 authored by bojanz's avatar bojanz
Browse files

Issue #2567747: Display the subdivision in the right language

parent 8b4d0735
......@@ -114,6 +114,9 @@ field.value.address:
type: mapping
label: 'Default value'
mapping:
langcode:
type: string
label: 'Language code'
country_code:
type: string
label: 'Country code'
......@@ -159,6 +162,9 @@ field.field_settings.address:
label: 'Used fields'
sequence:
- type: string
langcode_override:
type: string
label: 'Language override'
field.widget.settings.address_default:
type: mapping
......
......@@ -15,6 +15,7 @@ use Drupal\address\LabelHelper;
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\TypedData\DataDefinition;
/**
......@@ -43,6 +44,10 @@ class AddressItem extends FieldItemBase implements AddressInterface {
public static function schema(FieldStorageDefinitionInterface $fieldDefinition) {
return [
'columns' => [
'langcode' => [
'type' => 'varchar',
'length' => 32,
],
'country_code' => [
'type' => 'varchar',
'length' => 2,
......@@ -91,6 +96,9 @@ class AddressItem extends FieldItemBase implements AddressInterface {
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldStorageDefinitionInterface $fieldDefinition) {
$properties = [];
$properties['langcode'] = DataDefinition::create('language')
->setLabel(t('The language code.'));
$properties['country_code'] = DataDefinition::create('string')
->setLabel(t('The two-letter country code.'));
$properties['administrative_area'] = DataDefinition::create('string')
......@@ -122,6 +130,7 @@ class AddressItem extends FieldItemBase implements AddressInterface {
return [
'available_countries' => [],
'fields' => array_values(AddressField::getAll()),
'langcode_override' => '',
] + parent::defaultFieldSettings();
}
......@@ -129,6 +138,15 @@ class AddressItem extends FieldItemBase implements AddressInterface {
* {@inheritdoc}
*/
public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
$languages = \Drupal::languageManager()->getLanguages(LanguageInterface::STATE_ALL);
$languageOptions = [];
foreach ($languages as $langcode => $language) {
// Only list real languages (English, French, but not "Not specified").
if (!$language->isLocked()) {
$languageOptions[$langcode] = $language->getName();
}
}
$element = [];
$element['available_countries'] = [
'#type' => 'select',
......@@ -147,6 +165,15 @@ class AddressItem extends FieldItemBase implements AddressInterface {
'#options' => LabelHelper::getGenericFieldLabels(),
'#required' => TRUE,
];
$element['langcode_override'] = [
'#type' => 'select',
'#title' => $this->t('Language override'),
'#description' => $this->t('Ensures entered addresses are always formatted in the same language.'),
'#options' => $languageOptions,
'#default_value' => $this->getSetting('langcode_override'),
'#empty_option' => $this->t('- No override -'),
'#access' => \Drupal::languageManager()->isMultilingual(),
];
return $element;
}
......@@ -172,6 +199,48 @@ class AddressItem extends FieldItemBase implements AddressInterface {
return static::$availableCountries[$definitionId];
}
/**
* 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 intepreted 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() {
$this->langcode = NULL;
$languageManager = \Drupal::languageManager();
if (!$languageManager->isMultilingual()) {
return;
}
if ($override = $this->getSetting('langcode_override')) {
$this->langcode = $override;
}
elseif (!$this->getEntity()->isTranslatable()) {
$this->langcode = $languageManager->getConfigOverrideLanguage()->getId();
}
return $this->langcode;
}
/**
* {@inheritdoc}
*/
......@@ -198,7 +267,14 @@ class AddressItem extends FieldItemBase implements AddressInterface {
* {@inheritdoc}
*/
public function getLocale() {
return $this->getLangcode();
$langcode = $this->langcode;
if (!$langcode) {
// If no langcode was stored, fallback to the field langcode.
// Documented in initializeLangcode().
$langcode = $this->getLangcode();
}
return $langcode;
}
/**
......
......@@ -251,6 +251,12 @@ class AddressDefaultWidget extends WidgetBase implements ContainerFactoryPluginI
$countryList = $missingElement + $countryList;
}
// Calling initializeLangcode() every time, and not just when the field
// is empty, ensures that the langcode can be changed on subsequent
// edits (because the entity or interface language changed, for example).
$langcode = $item->initializeLangcode();
$element += [
'#type' => 'details',
'#collapsible' => TRUE,
......@@ -271,6 +277,10 @@ class AddressDefaultWidget extends WidgetBase implements ContainerFactoryPluginI
// Pass the id along to other methods.
'#wrapper_id' => $wrapperId,
];
$element['langcode'] = [
'#type' => 'value',
'#value' => $langcode,
];
$element['country_code'] = [
'#type' => 'select',
'#title' => $this->t('Country'),
......
......@@ -164,8 +164,8 @@ class DefaultFormatterTest extends KernelTestBase {
\Drupal::languageManager()->setConfigOverrideLanguage($language);
$entity = EntityTest::create([]);
$translation = $entity->addTranslation('zh-hant', []);
$translation->{$this->fieldName} = [
$entity->{$this->fieldName} = [
'langcode' => 'zh-hant',
'country_code' => 'TW',
'administrative_area' => 'TW-TPE',
'locality' => 'TW-TPE-e3cc33',
......@@ -175,7 +175,7 @@ class DefaultFormatterTest extends KernelTestBase {
'organization' => 'Giant <h2>Bike</h2> Store',
'recipient' => 'Mr. Liu',
];
$this->renderEntityFields($translation, $this->display);
$this->renderEntityFields($entity, $this->display);
$expected = implode('', [
'line1' => '<p translate="no">',
'line2' => '<span class="country">台灣</span><br>' . "\n",
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment