Update Composer, update everything

This commit is contained in:
Oliver Davies 2018-11-23 12:29:20 +00:00
parent ea3e94409f
commit dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions

View file

@ -75,7 +75,7 @@ class LanguageConfigFactoryOverride extends ConfigFactoryOverrideBase implements
$this->baseStorage = $storage;
$this->eventDispatcher = $event_dispatcher;
$this->typedConfigManager = $typed_config;
// Prior to negiotiation the override language should be the default
// Prior to negotiation the override language should be the default
// language.
$this->language = $default_language->get();
}

View file

@ -426,7 +426,12 @@ class ConfigurableLanguageManager extends LanguageManager implements Configurabl
}
/**
* {@inheritdoc}
* Sets the configuration override language.
*
* @param \Drupal\Core\Language\LanguageInterface $language
* The language to override configuration with.
*
* @return $this
*/
public function setConfigOverrideLanguage(LanguageInterface $language = NULL) {
$this->configFactoryOverride->setLanguage($language);

View file

@ -16,6 +16,13 @@ use Drupal\language\ConfigurableLanguageInterface;
* @ConfigEntityType(
* id = "configurable_language",
* label = @Translation("Language"),
* label_collection = @Translation("Languages"),
* label_singular = @Translation("language"),
* label_plural = @Translation("languages"),
* label_count = @PluralTranslation(
* singular = "@count language",
* plural = "@count languages",
* ),
* handlers = {
* "list_builder" = "Drupal\language\LanguageListBuilder",
* "access" = "Drupal\language\LanguageAccessControlHandler",
@ -139,6 +146,14 @@ class ConfigurableLanguage extends ConfigEntityBase implements ConfigurableLangu
// Install any available language configuration overrides for the language.
\Drupal::service('language.config_factory_override')->installLanguageOverrides($this->id());
}
if (!$this->isLocked() && !$update) {
// Add language to the list of language domains.
$config = \Drupal::configFactory()->getEditable('language.negotiation');
$domains = $config->get('url.domains');
$domains[$this->id()] = '';
$config->set('url.domains', $domains)->save();
}
}
/**
@ -173,6 +188,12 @@ class ConfigurableLanguage extends ConfigEntityBase implements ConfigurableLangu
if (!\Drupal::languageManager()->isMultilingual()) {
ConfigurableLanguageManager::rebuildServices();
}
// Remove language from language prefix and domain list.
$config = \Drupal::configFactory()->getEditable('language.negotiation');
$config->clear('url.prefixes.' . $entity->id());
$config->clear('url.domains.' . $entity->id());
$config->save();
}
/**

View file

@ -14,6 +14,13 @@ use Drupal\language\ContentLanguageSettingsInterface;
* @ConfigEntityType(
* id = "language_content_settings",
* label = @Translation("Content Language Settings"),
* label_collection = @Translation("Content Language Settings"),
* label_singular = @Translation("content language setting"),
* label_plural = @Translation("content languages settings"),
* label_count = @PluralTranslation(
* singular = "@count content language setting",
* plural = "@count content languages settings",
* ),
* admin_permission = "administer languages",
* config_prefix = "content_settings",
* entity_keys = {

View file

@ -81,7 +81,7 @@ class ConfigSubscriber implements EventSubscriberInterface {
* then this event must be changed to work with both the old and new schema
* definition so this event is update safe.
*
* @param ConfigCrudEvent $event
* @param \Drupal\Core\Config\ConfigCrudEvent $event
* The configuration event.
*/
public function onConfigSave(ConfigCrudEvent $event) {

View file

@ -2,6 +2,7 @@
namespace Drupal\language\EventSubscriber;
use Drupal\Core\DrupalKernelInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\Translator\TranslatorInterface;
use Drupal\language\ConfigurableLanguageManagerInterface;
@ -33,14 +34,14 @@ class LanguageRequestSubscriber implements EventSubscriberInterface {
/**
* The translation service.
*
* @var \Drupal\Core\StringTranslation\Translator\TranslatorInterface;
* @var \Drupal\Core\StringTranslation\Translator\TranslatorInterface
*/
protected $translation;
/**
* The current active user.
*
* @return \Drupal\Core\Session\AccountInterface
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
@ -51,7 +52,7 @@ class LanguageRequestSubscriber implements EventSubscriberInterface {
* The language manager service.
* @param \Drupal\language\LanguageNegotiatorInterface $negotiator
* The language negotiator.
* @param \Drupal\Core\StringTranslation\Translator\TranslatorInterface $translation;
* @param \Drupal\Core\StringTranslation\Translator\TranslatorInterface $translation
* The translation service.
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current active user.
@ -64,25 +65,39 @@ class LanguageRequestSubscriber implements EventSubscriberInterface {
}
/**
* Sets the default language and initializes configuration overrides.
* Initializes the language manager at the beginning of the request.
*
* @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
* The Event to process.
*/
public function onKernelRequestLanguage(GetResponseEvent $event) {
if ($event->getRequestType() == HttpKernelInterface::MASTER_REQUEST) {
$this->negotiator->setCurrentUser($this->currentUser);
if ($this->languageManager instanceof ConfigurableLanguageManagerInterface) {
$this->languageManager->setNegotiator($this->negotiator);
$this->languageManager->setConfigOverrideLanguage($this->languageManager->getCurrentLanguage());
}
// After the language manager has initialized, set the default langcode
// for the string translations.
$langcode = $this->languageManager->getCurrentLanguage()->getId();
$this->translation->setDefaultLangcode($langcode);
$this->setLanguageOverrides();
}
}
/**
* Initializes config overrides whenever the service container is rebuilt.
*/
public function onContainerInitializeSubrequestFinished() {
$this->setLanguageOverrides();
}
/**
* Sets the language for config overrides on the language manager.
*/
private function setLanguageOverrides() {
$this->negotiator->setCurrentUser($this->currentUser);
if ($this->languageManager instanceof ConfigurableLanguageManagerInterface) {
$this->languageManager->setNegotiator($this->negotiator);
$this->languageManager->setConfigOverrideLanguage($this->languageManager->getCurrentLanguage());
}
// After the language manager has initialized, set the default langcode for
// the string translations.
$langcode = $this->languageManager->getCurrentLanguage()->getId();
$this->translation->setDefaultLangcode($langcode);
}
/**
* Registers the methods in this class that should be listeners.
*
@ -91,6 +106,7 @@ class LanguageRequestSubscriber implements EventSubscriberInterface {
*/
public static function getSubscribedEvents() {
$events[KernelEvents::REQUEST][] = ['onKernelRequestLanguage', 255];
$events[DrupalKernelInterface::CONTAINER_INITIALIZE_SUBREQUEST_FINISHED][] = ['onContainerInitializeSubrequestFinished', 255];
return $events;
}

View file

@ -11,6 +11,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Configure the content language settings for this site.
*
* @internal
*/
class ContentLanguageSettingsForm extends FormBase {
@ -155,7 +157,7 @@ class ContentLanguageSettingsForm extends FormBase {
->save();
}
}
drupal_set_message($this->t('Settings successfully updated.'));
$this->messenger()->addStatus($this->t('Settings successfully updated.'));
}
}

View file

@ -9,6 +9,8 @@ use Drupal\language\Entity\ConfigurableLanguage;
/**
* Controller for language addition forms.
*
* @internal
*/
class LanguageAddForm extends LanguageFormBase {
@ -86,12 +88,12 @@ class LanguageAddForm extends LanguageFormBase {
$t_args = ['%language' => $this->entity->label(), '%langcode' => $this->entity->id()];
$this->logger('language')->notice('The %language (%langcode) language has been created.', $t_args);
drupal_set_message($this->t('The language %language has been created and can now be used.', $t_args));
$this->messenger()->addStatus($this->t('The language %language has been created and can now be used.', $t_args));
if ($this->moduleHandler->moduleExists('block')) {
// Tell the user they have the option to add a language switcher block
// to their theme so they can switch between the languages.
drupal_set_message($this->t('Use one of the language switcher blocks to allow site visitors to switch between languages. You can enable these blocks on the <a href=":block-admin">block administration page</a>.', [':block-admin' => $this->url('block.admin_display')]));
$this->messenger()->addStatus($this->t('Use one of the language switcher blocks to allow site visitors to switch between languages. You can enable these blocks on the <a href=":block-admin">block administration page</a>.', [':block-admin' => $this->url('block.admin_display')]));
}
$form_state->setRedirectUrl($this->entity->urlInfo('collection'));
}

View file

@ -6,6 +6,8 @@ use Drupal\Core\Entity\EntityDeleteForm;
/**
* Defines a confirmation form for deleting a language entity.
*
* @internal
*/
class LanguageDeleteForm extends EntityDeleteForm {

View file

@ -6,6 +6,8 @@ use Drupal\Core\Form\FormStateInterface;
/**
* Controller for language edit forms.
*
* @internal
*/
class LanguageEditForm extends LanguageFormBase {

View file

@ -50,11 +50,11 @@ abstract class LanguageFormBase extends EntityForm {
$form['langcode_view'] = [
'#type' => 'item',
'#title' => $this->t('Language code'),
'#markup' => $language->id()
'#markup' => $language->id(),
];
$form['langcode'] = [
'#type' => 'value',
'#value' => $language->id()
'#value' => $language->id(),
];
}
else {

View file

@ -9,6 +9,8 @@ use Drupal\Core\Url;
/**
* Defines a confirmation form for deleting a browser language negotiation mapping.
*
* @internal
*/
class NegotiationBrowserDeleteForm extends ConfirmFormBase {
use ConfigFormBaseTrait;
@ -27,7 +29,6 @@ class NegotiationBrowserDeleteForm extends ConfirmFormBase {
return ['language.mappings'];
}
/**
* {@inheritdoc}
*/
@ -74,7 +75,7 @@ class NegotiationBrowserDeleteForm extends ConfirmFormBase {
$this->logger('language')->notice('The browser language detection mapping for the %browser browser language code has been deleted.', $args);
drupal_set_message($this->t('The mapping for the %browser browser language code has been deleted.', $args));
$this->messenger()->addStatus($this->t('The mapping for the %browser browser language code has been deleted.', $args));
$form_state->setRedirect('language.negotiation_browser');
}

View file

@ -11,6 +11,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Configure the browser language negotiation method for this site.
*
* @internal
*/
class NegotiationBrowserForm extends ConfigFormBase {
@ -23,11 +25,8 @@ class NegotiationBrowserForm extends ConfigFormBase {
/**
* {@inheritdoc}
*
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler
*/
public function __construct(ConfigFactoryInterface $config_factory, ConfigurableLanguageManagerInterface $language_manager ) {
public function __construct(ConfigFactoryInterface $config_factory, ConfigurableLanguageManagerInterface $language_manager) {
parent::__construct($config_factory);
$this->languageManager = $language_manager;
}

View file

@ -3,7 +3,6 @@
namespace Drupal\language\Form;
use Drupal\Core\Block\BlockManagerInterface;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Extension\ThemeHandlerInterface;
@ -17,6 +16,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Configure the selected language negotiation method for this site.
*
* @internal
*/
class NegotiationConfigureForm extends ConfigFormBase {
@ -202,7 +203,7 @@ class NegotiationConfigureForm extends ConfigFormBase {
$this->blockManager->clearCachedDefinitions();
$form_state->setRedirect('language.negotiation');
drupal_set_message($this->t('Language detection configuration saved.'));
$this->messenger()->addStatus($this->t('Language detection configuration saved.'));
}
/**
@ -213,7 +214,7 @@ class NegotiationConfigureForm extends ConfigFormBase {
* @param string $type
* The language type to generate the table for.
*/
protected function configureFormTable(array &$form, $type) {
protected function configureFormTable(array &$form, $type) {
$info = $form['#language_types_info'][$type];
$table_form = [
@ -234,7 +235,7 @@ class NegotiationConfigureForm extends ConfigFormBase {
'#attributes' => ['class' => ['language-customization-checkbox']],
'#attached' => [
'library' => [
'language/drupal.language.admin'
'language/drupal.language.admin',
],
],
];
@ -274,7 +275,7 @@ class NegotiationConfigureForm extends ConfigFormBase {
$table_form['weight'][$method_id] = [
'#type' => 'weight',
'#title' => $this->t('Weight for @title language detection method', ['@title' => Unicode::strtolower($method_name)]),
'#title' => $this->t('Weight for @title language detection method', ['@title' => mb_strtolower($method_name)]),
'#title_display' => 'invisible',
'#default_value' => $weight,
'#attributes' => ['class' => ["language-method-weight-$type"]],
@ -285,7 +286,7 @@ class NegotiationConfigureForm extends ConfigFormBase {
$table_form['enabled'][$method_id] = [
'#type' => 'checkbox',
'#title' => $this->t('Enable @title language detection method', ['@title' => Unicode::strtolower($method_name)]),
'#title' => $this->t('Enable @title language detection method', ['@title' => mb_strtolower($method_name)]),
'#title_display' => 'invisible',
'#default_value' => $enabled,
];

View file

@ -8,6 +8,8 @@ use Drupal\Core\Form\ConfigFormBase;
/**
* Configure the selected language negotiation method for this site.
*
* @internal
*/
class NegotiationSelectedForm extends ConfigFormBase {

View file

@ -7,6 +7,8 @@ use Drupal\Core\Form\FormStateInterface;
/**
* Configure the session language negotiation method for this site.
*
* @internal
*/
class NegotiationSessionForm extends ConfigFormBase {

View file

@ -12,6 +12,8 @@ use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl;
/**
* Configure the URL language negotiation method for this site.
*
* @internal
*/
class NegotiationUrlForm extends ConfigFormBase {

View file

@ -60,7 +60,6 @@ class PathProcessorLanguage implements InboundPathProcessorInterface, OutboundPa
*/
protected $configSubscriber;
/**
* Constructs a PathProcessorLanguage object.
*
@ -147,7 +146,7 @@ class PathProcessorLanguage implements InboundPathProcessorInterface, OutboundPa
// Sort the processors list, so that their functions are called in the
// order specified by the weight of the methods.
uksort($this->processors[$scope], function ($method_id_a, $method_id_b) use($weights) {
uksort($this->processors[$scope], function ($method_id_a, $method_id_b) use ($weights) {
$a_weight = $weights[$method_id_a];
$b_weight = $weights[$method_id_b];

View file

@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
@ -37,6 +38,13 @@ class LanguageListBuilder extends DraggableListBuilder {
*/
protected $configFactory;
/**
* The messenger.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* {@inheritdoc}
*/
@ -45,7 +53,8 @@ class LanguageListBuilder extends DraggableListBuilder {
$entity_type,
$container->get('entity.manager')->getStorage($entity_type->id()),
$container->get('language_manager'),
$container->get('config.factory')
$container->get('config.factory'),
$container->get('messenger')
);
}
@ -60,11 +69,14 @@ class LanguageListBuilder extends DraggableListBuilder {
* The language manager.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The factory for configuration objects.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger.
*/
public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, LanguageManagerInterface $language_manager, ConfigFactoryInterface $config_factory) {
public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, LanguageManagerInterface $language_manager, ConfigFactoryInterface $config_factory, MessengerInterface $messenger) {
parent::__construct($entity_type, $storage);
$this->languageManager = $language_manager;
$this->configFactory = $config_factory;
$this->messenger = $messenger;
}
/**
@ -154,7 +166,7 @@ class LanguageListBuilder extends DraggableListBuilder {
$this->languageManager->updateLockedLanguageWeights();
}
drupal_set_message(t('Configuration saved.'));
$this->messenger->addStatus($this->t('Configuration saved.'));
// Force the redirection to the page with the language we have just
// selected as default.
$form_state->setRedirectUrl($this->entities[$new_id]->urlInfo('collection', ['language' => $this->entities[$new_id]]));

View file

@ -28,7 +28,7 @@ abstract class LanguageNegotiationMethodBase implements LanguageNegotiationMetho
/**
* The current active user.
*
* @return \Drupal\Core\Session\AccountInterface
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;

View file

@ -24,7 +24,7 @@ interface LanguageNegotiationMethodInterface {
/**
* Injects the configuration factory.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* @param \Drupal\Core\Config\ConfigFactoryInterface $config
* The configuration factory.
*/
public function setConfig(ConfigFactoryInterface $config);

View file

@ -38,7 +38,7 @@ class LanguageNegotiator implements LanguageNegotiatorInterface {
/**
* The settings instance.
*
* @return \Drupal\Core\Site\Settings
* @var \Drupal\Core\Site\Settings
*/
protected $settings;
@ -52,7 +52,7 @@ class LanguageNegotiator implements LanguageNegotiatorInterface {
/**
* The current active user.
*
* @return \Drupal\Core\Session\AccountInterface
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
@ -74,7 +74,7 @@ class LanguageNegotiator implements LanguageNegotiatorInterface {
* Constructs a new LanguageNegotiator object.
*
* @param \Drupal\language\ConfigurableLanguageManagerInterface $language_manager
* The language manager.
* The language manager.
* @param \Drupal\Component\Plugin\PluginManagerInterface $negotiator_manager
* The language negotiation methods plugin manager
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory

View file

@ -91,7 +91,6 @@ use Drupal\Core\Session\AccountInterface;
* }
* }
* }
* ?>
* @endcode
*
* For more information, see

View file

@ -70,7 +70,7 @@ class LanguageServiceProvider extends ServiceProviderBase {
// and caching. This might prove difficult as this is called before the
// container has finished building.
$config_storage = BootstrapConfigStorageFactory::get();
$config_ids = array_filter($config_storage->listAll($prefix), function($config_id) use ($prefix) {
$config_ids = array_filter($config_storage->listAll($prefix), function ($config_id) use ($prefix) {
return $config_id != $prefix . LanguageInterface::LANGCODE_NOT_SPECIFIED && $config_id != $prefix . LanguageInterface::LANGCODE_NOT_APPLICABLE;
});
return count($config_ids) > 1;

View file

@ -57,7 +57,6 @@ class LanguageBlock extends BlockBase implements ContainerFactoryPluginInterface
$this->pathMatcher = $path_matcher;
}
/**
* {@inheritdoc}
*/
@ -71,7 +70,6 @@ class LanguageBlock extends BlockBase implements ContainerFactoryPluginInterface
);
}
/**
* {@inheritdoc}
*/

View file

@ -104,7 +104,7 @@ class Language extends ConditionPluginBase implements ContainerFactoryPluginInte
$language_list = $this->languageManager->getLanguages(LanguageInterface::STATE_ALL);
$selected = $this->configuration['langcodes'];
// Reduce the language list to an array of language names.
$language_names = array_reduce($language_list, function(&$result, $item) use ($selected) {
$language_names = array_reduce($language_list, function (&$result, $item) use ($selected) {
// If the current item of the $language_list array is one of the selected
// languages, add it to the $results array.
if (!empty($selected[$item->getId()])) {

View file

@ -20,7 +20,7 @@ class LanguageDomains extends ArrayBuild {
* {@inheritdoc}
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
if ($row->getSourceProperty('domain_negotiation')) {
if ($row->getSourceProperty('domain_negotiation_used')) {
global $base_url;
foreach ($value as $old_key => $old_value) {

View file

@ -8,7 +8,7 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* @MigrateSource(
* id = "language",
* source_provider = "locale"
* source_module = "locale"
* )
*/
class Language extends DrupalSqlBase {
@ -66,7 +66,7 @@ class Language extends DrupalSqlBase {
// when the 'language_negotiation' variable is set to '3', and in D7, when
// the 'locale_language_negotiation_url_part' variable is set to '1'.
if ($this->variableGet('language_negotiation', 0) == 3 || $this->variableGet('locale_language_negotiation_url_part', 0) == 1) {
$row->setSourceProperty('domain_negotiation', TRUE);
$row->setSourceProperty('domain_negotiation_used', TRUE);
}
}

View file

@ -10,6 +10,7 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
*
* @MigrateSource(
* id = "d6_language_content_settings",
* source_module = "locale"
* )
*/
class LanguageContentSettings extends DrupalSqlBase {

View file

@ -0,0 +1,65 @@
<?php
namespace Drupal\language\Plugin\migrate\source\d6;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* Drupal 6 i18n vocabularies source from database.
*
* @MigrateSource(
* id = "d6_language_content_settings_taxonomy_vocabulary",
* source_module = "taxonomy"
* )
*/
class LanguageContentSettingsTaxonomyVocabulary extends DrupalSqlBase {
/**
* {@inheritdoc}
*/
public function query() {
return $this->select('vocabulary', 'v')
->fields('v', ['vid', 'language']);
}
/**
* {@inheritdoc}
*/
public function fields() {
return [
'vid' => $this->t('The vocabulary ID.'),
'language' => $this->t('The default language for new terms.'),
'state' => $this->t('The i18n taxonomy translation setting.'),
];
}
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
// Get the i18n taxonomy translation setting for this vocabulary.
// 0 - No multilingual options
// 1 - Localizable terms. Run through the localization system.
// 2 - Predefined language for a vocabulary and its terms.
// 3 - Per-language terms, translatable (referencing terms with different
// languages) but not localizable.
$i18ntaxonomy_vocabulary = $this->variableGet('i18ntaxonomy_vocabulary', NULL);
$vid = $row->getSourceProperty('vid');
$state = FALSE;
if (array_key_exists($vid, $i18ntaxonomy_vocabulary)) {
$state = $i18ntaxonomy_vocabulary[$vid];
}
$row->setSourceProperty('state', $state);
return parent::prepareRow($row);
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['vid']['type'] = 'integer';
return $ids;
}
}

View file

@ -10,6 +10,7 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
*
* @MigrateSource(
* id = "d7_language_content_settings",
* source_module = "locale"
* )
*/
class LanguageContentSettings extends DrupalSqlBase {

View file

@ -1,50 +0,0 @@
<?php
namespace Drupal\language\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests entity type without language support.
*
* This is to ensure that an entity type without language support can not
* enable the language select from the content language settings page.
*
* @group language
*/
class EntityTypeWithoutLanguageFormTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = [
'language',
'language_test',
];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Create and log in administrative user.
$admin_user = $this->drupalCreateUser([
'administer languages',
]);
$this->drupalLogin($admin_user);
}
/**
* Tests configuration options with an entity without language definition.
*/
public function testEmptyLangcode() {
// Assert that we can not enable language select from
// content language settings page.
$this->drupalGet('admin/config/regional/content-language');
$this->assertNoField('entity_types[no_language_entity_test]');
}
}

View file

@ -1,253 +0,0 @@
<?php
namespace Drupal\language\Tests;
use Drupal\Core\Language\LanguageInterface;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\language\Entity\ContentLanguageSettings;
use Drupal\simpletest\WebTestBase;
use Drupal\taxonomy\Entity\Vocabulary;
/**
* Tests the features of the language configuration element field.
*
* @group language
*/
class LanguageConfigurationElementTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['taxonomy', 'node', 'language', 'language_elements_test', 'field_ui'];
protected function setUp() {
parent::setUp();
$user = $this->drupalCreateUser(['access administration pages', 'administer languages', 'administer content types']);
$this->drupalLogin($user);
}
/**
* Tests the language settings have been saved.
*/
public function testLanguageConfigurationElement() {
$this->drupalGet('language-tests/language_configuration_element');
$edit['lang_configuration[langcode]'] = 'current_interface';
$edit['lang_configuration[language_alterable]'] = FALSE;
$this->drupalPostForm(NULL, $edit, 'Save');
$lang_conf = ContentLanguageSettings::loadByEntityTypeBundle('entity_test', 'some_bundle');
// Check that the settings have been saved.
$this->assertEqual($lang_conf->getDefaultLangcode(), 'current_interface');
$this->assertFalse($lang_conf->isLanguageAlterable());
$this->drupalGet('language-tests/language_configuration_element');
$this->assertOptionSelected('edit-lang-configuration-langcode', 'current_interface');
$this->assertNoFieldChecked('edit-lang-configuration-language-alterable');
// Reload the page and save again.
$this->drupalGet('language-tests/language_configuration_element');
$edit['lang_configuration[langcode]'] = 'authors_default';
$edit['lang_configuration[language_alterable]'] = TRUE;
$this->drupalPostForm(NULL, $edit, 'Save');
$lang_conf = ContentLanguageSettings::loadByEntityTypeBundle('entity_test', 'some_bundle');
// Check that the settings have been saved.
$this->assertEqual($lang_conf->getDefaultLangcode(), 'authors_default');
$this->assertTrue($lang_conf->isLanguageAlterable());
$this->drupalGet('language-tests/language_configuration_element');
$this->assertOptionSelected('edit-lang-configuration-langcode', 'authors_default');
$this->assertFieldChecked('edit-lang-configuration-language-alterable');
// Test if content type settings have been saved.
$edit = [
'name' => 'Page',
'type' => 'page',
'language_configuration[langcode]' => 'authors_default',
'language_configuration[language_alterable]' => TRUE,
];
$this->drupalPostForm('admin/structure/types/add', $edit, 'Save and manage fields');
// Make sure the settings are saved when creating the content type.
$this->drupalGet('admin/structure/types/manage/page');
$this->assertOptionSelected('edit-language-configuration-langcode', 'authors_default');
$this->assertFieldChecked('edit-language-configuration-language-alterable');
}
/**
* Tests that the language_get_default_langcode() returns the correct values.
*/
public function testDefaultLangcode() {
// Add some custom languages.
foreach (['aa', 'bb', 'cc'] as $language_code) {
ConfigurableLanguage::create([
'id' => $language_code,
'label' => $this->randomMachineName(),
])->save();
}
// Fixed language.
ContentLanguageSettings::loadByEntityTypeBundle('entity_test', 'custom_bundle')
->setLanguageAlterable(TRUE)
->setDefaultLangcode('bb')
->save();
$langcode = language_get_default_langcode('entity_test', 'custom_bundle');
$this->assertEqual($langcode, 'bb');
// Current interface.
ContentLanguageSettings::loadByEntityTypeBundle('entity_test', 'custom_bundle')
->setLanguageAlterable(TRUE)
->setDefaultLangcode('current_interface')
->save();
$langcode = language_get_default_langcode('entity_test', 'custom_bundle');
$language_interface = \Drupal::languageManager()->getCurrentLanguage();
$this->assertEqual($langcode, $language_interface->getId());
// Site's default.
$old_default = \Drupal::languageManager()->getDefaultLanguage();
// Ensure the language entity default value is correct.
$configurable_language = ConfigurableLanguage::load($old_default->getId());
$this->assertTrue($configurable_language->isDefault(), 'The en language entity is flagged as the default language.');
$this->config('system.site')->set('default_langcode', 'cc')->save();
ContentLanguageSettings::loadByEntityTypeBundle('entity_test', 'custom_bundle')
->setLanguageAlterable(TRUE)
->setDefaultLangcode(LanguageInterface::LANGCODE_SITE_DEFAULT)
->save();
$langcode = language_get_default_langcode('entity_test', 'custom_bundle');
$this->assertEqual($langcode, 'cc');
// Ensure the language entity default value is correct.
$configurable_language = ConfigurableLanguage::load($old_default->getId());
$this->assertFalse($configurable_language->isDefault(), 'The en language entity is not flagged as the default language.');
$configurable_language = ConfigurableLanguage::load('cc');
// Check calling the
// \Drupal\language\ConfigurableLanguageInterface::isDefault() method
// directly.
$this->assertTrue($configurable_language->isDefault(), 'The cc language entity is flagged as the default language.');
// Check the default value of a language field when authors preferred option
// is selected.
// Create first an user and assign a preferred langcode to him.
$some_user = $this->drupalCreateUser();
$some_user->preferred_langcode = 'bb';
$some_user->save();
$this->drupalLogin($some_user);
ContentLanguageSettings::create([
'target_entity_type_id' => 'entity_test',
'target_bundle' => 'some_bundle',
])->setLanguageAlterable(TRUE)
->setDefaultLangcode('authors_default')
->save();
$this->drupalGet('language-tests/language_configuration_element_test');
$this->assertOptionSelected('edit-langcode', 'bb');
}
/**
* Tests that the configuration is retained when the node type is updated.
*/
public function testNodeTypeUpdate() {
// Create the article content type first if the profile used is not the
// standard one.
if ($this->profile != 'standard') {
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
}
$admin_user = $this->drupalCreateUser(['administer content types']);
$this->drupalLogin($admin_user);
$edit = [
'language_configuration[langcode]' => 'current_interface',
'language_configuration[language_alterable]' => TRUE,
];
$this->drupalPostForm('admin/structure/types/manage/article', $edit, t('Save content type'));
// Check the language default configuration for the articles.
$configuration = ContentLanguageSettings::loadByEntityTypeBundle('node', 'article');
$uuid = $configuration->uuid();
$this->assertEqual($configuration->getDefaultLangcode(), 'current_interface', 'The default language configuration has been saved on the Article content type.');
$this->assertTrue($configuration->isLanguageAlterable(), 'The alterable language configuration has been saved on the Article content type.');
// Update the article content type by changing the title label.
$edit = [
'title_label' => 'Name'
];
$this->drupalPostForm('admin/structure/types/manage/article', $edit, t('Save content type'));
// Check that we still have the settings for the updated node type.
$configuration = ContentLanguageSettings::loadByEntityTypeBundle('node', 'article');
$this->assertEqual($configuration->getDefaultLangcode(), 'current_interface', 'The default language configuration has been kept on the updated Article content type.');
$this->assertTrue($configuration->isLanguageAlterable(), 'The alterable language configuration has been kept on the updated Article content type.');
$this->assertEqual($configuration->uuid(), $uuid, 'The language configuration uuid has been kept on the updated Article content type.');
}
/**
* Tests the language settings are deleted on bundle delete.
*/
public function testNodeTypeDelete() {
// Create the article content type first if the profile used is not the
// standard one.
if ($this->profile != 'standard') {
$this->drupalCreateContentType([
'type' => 'article',
'name' => 'Article'
]);
}
$admin_user = $this->drupalCreateUser(['administer content types']);
$this->drupalLogin($admin_user);
// Create language configuration for the articles.
$edit = [
'language_configuration[langcode]' => 'authors_default',
'language_configuration[language_alterable]' => TRUE,
];
$this->drupalPostForm('admin/structure/types/manage/article', $edit, t('Save content type'));
// Check the language default configuration for articles is present.
$configuration = \Drupal::entityManager()->getStorage('language_content_settings')->load('node.article');
$this->assertTrue($configuration, 'The language configuration is present.');
// Delete 'article' bundle.
$this->drupalPostForm('admin/structure/types/manage/article/delete', [], t('Delete'));
// Check that the language configuration has been deleted.
\Drupal::entityManager()->getStorage('language_content_settings')->resetCache();
$configuration = \Drupal::entityManager()->getStorage('language_content_settings')->load('node.article');
$this->assertFalse($configuration, 'The language configuration was deleted after bundle was deleted.');
}
/**
* Tests that the configuration is retained when a vocabulary is updated.
*/
public function testTaxonomyVocabularyUpdate() {
$vocabulary = Vocabulary::create([
'name' => 'Country',
'vid' => 'country',
]);
$vocabulary->save();
$admin_user = $this->drupalCreateUser(['administer taxonomy']);
$this->drupalLogin($admin_user);
$edit = [
'default_language[langcode]' => 'current_interface',
'default_language[language_alterable]' => TRUE,
];
$this->drupalPostForm('admin/structure/taxonomy/manage/country', $edit, t('Save'));
// Check the language default configuration.
$configuration = ContentLanguageSettings::loadByEntityTypeBundle('taxonomy_term', 'country');
$uuid = $configuration->uuid();
$this->assertEqual($configuration->getDefaultLangcode(), 'current_interface', 'The default language configuration has been saved on the Country vocabulary.');
$this->assertTrue($configuration->isLanguageAlterable(), 'The alterable language configuration has been saved on the Country vocabulary.');
// Update the vocabulary.
$edit = [
'name' => 'Nation'
];
$this->drupalPostForm('admin/structure/taxonomy/manage/country', $edit, t('Save'));
// Check that we still have the settings for the updated vocabulary.
$configuration = ContentLanguageSettings::loadByEntityTypeBundle('taxonomy_term', 'country');
$this->assertEqual($configuration->getDefaultLangcode(), 'current_interface', 'The default language configuration has been kept on the updated Country vocabulary.');
$this->assertTrue($configuration->isLanguageAlterable(), 'The alterable language configuration has been kept on the updated Country vocabulary.');
$this->assertEqual($configuration->uuid(), $uuid, 'The language configuration uuid has been kept on the updated Country vocabulary.');
}
}

View file

@ -1,221 +0,0 @@
<?php
namespace Drupal\language\Tests;
use Drupal\Core\Language\LanguageInterface;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\simpletest\WebTestBase;
/**
* Adds and configures languages to check negotiation changes.
*
* @group language
*/
class LanguageConfigurationTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['language'];
/**
* Functional tests for adding, editing and deleting languages.
*/
public function testLanguageConfiguration() {
// Ensure the after installing the language module the weight of the English
// language is still 0.
$this->assertEqual(ConfigurableLanguage::load('en')->getWeight(), 0, 'The English language has a weight of 0.');
// User to add and remove language.
$admin_user = $this->drupalCreateUser(['administer languages', 'access administration pages']);
$this->drupalLogin($admin_user);
// Check if the Default English language has no path prefix.
$this->drupalGet('admin/config/regional/language/detection/url');
$this->assertFieldByXPath('//input[@name="prefix[en]"]', '', 'Default English has no path prefix.');
// Check that Add language is a primary button.
$this->drupalGet('admin/config/regional/language/add');
$this->assertFieldByXPath('//input[contains(@class, "button--primary")]', 'Add language', 'Add language is a primary button');
// Add predefined language.
$edit = [
'predefined_langcode' => 'fr',
];
$this->drupalPostForm(NULL, $edit, 'Add language');
$this->assertText('French');
$this->assertUrl(\Drupal::url('entity.configurable_language.collection', [], ['absolute' => TRUE]), [], 'Correct page redirection.');
// Langcode for Languages is always 'en'.
$language = $this->config('language.entity.fr')->get();
$this->assertEqual($language['langcode'], 'en');
// Check if the Default English language has no path prefix.
$this->drupalGet('admin/config/regional/language/detection/url');
$this->assertFieldByXPath('//input[@name="prefix[en]"]', '', 'Default English has no path prefix.');
// Check if French has a path prefix.
$this->drupalGet('admin/config/regional/language/detection/url');
$this->assertFieldByXPath('//input[@name="prefix[fr]"]', 'fr', 'French has a path prefix.');
// Check if we can change the default language.
$this->drupalGet('admin/config/regional/language');
$this->assertFieldChecked('edit-site-default-language-en', 'English is the default language.');
// Change the default language.
$edit = [
'site_default_language' => 'fr',
];
$this->drupalPostForm(NULL, $edit, t('Save configuration'));
$this->rebuildContainer();
$this->assertFieldChecked('edit-site-default-language-fr', 'Default language updated.');
$this->assertUrl(\Drupal::url('entity.configurable_language.collection', [], ['absolute' => TRUE, 'langcode' => 'fr']), [], 'Correct page redirection.');
// Check if a valid language prefix is added after changing the default
// language.
$this->drupalGet('admin/config/regional/language/detection/url');
$this->assertFieldByXPath('//input[@name="prefix[en]"]', 'en', 'A valid path prefix has been added to the previous default language.');
// Check if French still has a path prefix.
$this->drupalGet('admin/config/regional/language/detection/url');
$this->assertFieldByXPath('//input[@name="prefix[fr]"]', 'fr', 'French still has a path prefix.');
// Check that prefix can be changed.
$edit = [
'prefix[fr]' => 'french',
];
$this->drupalPostForm(NULL, $edit, t('Save configuration'));
$this->assertFieldByXPath('//input[@name="prefix[fr]"]', 'french', 'French path prefix has changed.');
// Check that the prefix can be removed.
$edit = [
'prefix[fr]' => '',
];
$this->drupalPostForm(NULL, $edit, t('Save configuration'));
$this->assertNoText(t('The prefix may only be left blank for the selected detection fallback language.'), 'The path prefix can be removed for the default language');
// Change default negotiation language.
$this->config('language.negotiation')->set('selected_langcode', 'fr')->save();
// Check that the prefix of a language that is not the negotiation one
// cannot be changed to empty string.
$edit = [
'prefix[en]' => '',
];
$this->drupalPostForm(NULL, $edit, t('Save configuration'));
$this->assertText(t('The prefix may only be left blank for the selected detection fallback language.'));
// Check that prefix cannot be changed to contain a slash.
$edit = [
'prefix[en]' => 'foo/bar',
];
$this->drupalPostForm(NULL, $edit, t('Save configuration'));
$this->assertText(t('The prefix may not contain a slash.'), 'English prefix cannot be changed to contain a slash.');
// Remove English language and add a new Language to check if langcode of
// Language entity is 'en'.
$this->drupalPostForm('admin/config/regional/language/delete/en', [], t('Delete'));
$this->rebuildContainer();
$this->assertRaw(t('The %language (%langcode) language has been removed.', ['%language' => 'English', '%langcode' => 'en']));
// Ensure that French language has a weight of 1 after being created through
// the UI.
$french = ConfigurableLanguage::load('fr');
$this->assertEqual($french->getWeight(), 1, 'The French language has a weight of 1.');
// Ensure that French language can now have a weight of 0.
$french->setWeight(0)->save();
$this->assertEqual($french->getWeight(), 0, 'The French language has a weight of 0.');
// Ensure that new languages created through the API get a weight of 0.
$afrikaans = ConfigurableLanguage::createFromLangcode('af');
$afrikaans->save();
$this->assertEqual($afrikaans->getWeight(), 0, 'The Afrikaans language has a weight of 0.');
// Ensure that a new language can be created with any weight.
$arabic = ConfigurableLanguage::createFromLangcode('ar');
$arabic->setWeight(4)->save();
$this->assertEqual($arabic->getWeight(), 4, 'The Arabic language has a weight of 0.');
$edit = [
'predefined_langcode' => 'de',
];
$this->drupalPostForm('admin/config/regional/language/add', $edit, 'Add language');
$language = $this->config('language.entity.de')->get();
$this->assertEqual($language['langcode'], 'fr');
// Ensure that German language has a weight of 5 after being created through
// the UI.
$french = ConfigurableLanguage::load('de');
$this->assertEqual($french->getWeight(), 5, 'The German language has a weight of 5.');
}
/**
* Functional tests for setting system language weight on adding, editing and deleting languages.
*/
public function testLanguageConfigurationWeight() {
// User to add and remove language.
$admin_user = $this->drupalCreateUser(['administer languages', 'access administration pages']);
$this->drupalLogin($admin_user);
$this->checkConfigurableLanguageWeight();
// Add predefined language.
$edit = [
'predefined_langcode' => 'fr',
];
$this->drupalPostForm('admin/config/regional/language/add', $edit, 'Add language');
$this->checkConfigurableLanguageWeight('after adding new language');
// Re-ordering languages.
$edit = [
'languages[en][weight]' => $this->getHighestConfigurableLanguageWeight() + 1,
];
$this->drupalPostForm('admin/config/regional/language', $edit, 'Save configuration');
$this->checkConfigurableLanguageWeight('after re-ordering');
// Remove predefined language.
$edit = [
'confirm' => 1,
];
$this->drupalPostForm('admin/config/regional/language/delete/fr', $edit, 'Delete');
$this->checkConfigurableLanguageWeight('after deleting a language');
}
/**
* Validates system languages are ordered after configurable languages.
*
* @param string $state
* (optional) A string for customizing assert messages, containing the
* description of the state of the check, for example: 'after re-ordering'.
* Defaults to 'by default'.
*/
protected function checkConfigurableLanguageWeight($state = 'by default') {
// Reset language list.
\Drupal::languageManager()->reset();
$max_configurable_language_weight = $this->getHighestConfigurableLanguageWeight();
$replacements = ['@event' => $state];
foreach (\Drupal::languageManager()->getLanguages(LanguageInterface::STATE_LOCKED) as $locked_language) {
$replacements['%language'] = $locked_language->getName();
$this->assertTrue($locked_language->getWeight() > $max_configurable_language_weight, format_string('System language %language has higher weight than configurable languages @event', $replacements));
}
}
/**
* Helper to get maximum weight of configurable (unlocked) languages.
*
* @return int
* Maximum weight of configurable languages.
*/
protected function getHighestConfigurableLanguageWeight(){
$max_weight = 0;
$storage = $this->container->get('entity_type.manager')
->getStorage('configurable_language');
$storage->resetCache();
/* @var $languages \Drupal\Core\Language\LanguageInterface[] */
$languages = $storage->loadMultiple();
foreach ($languages as $language) {
if (!$language->isLocked()) {
$max_weight = max($max_weight, $language->getWeight());
}
}
return $max_weight;
}
}

View file

@ -1,101 +0,0 @@
<?php
namespace Drupal\language\Tests;
use Drupal\simpletest\WebTestBase;
use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageInterface;
/**
* Adds and configures custom languages.
*
* @group language
*/
class LanguageCustomLanguageConfigurationTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['language'];
/**
* Functional tests for adding, editing and deleting languages.
*/
public function testLanguageConfiguration() {
// Create user with permissions to add and remove languages.
$admin_user = $this->drupalCreateUser(['administer languages', 'access administration pages']);
$this->drupalLogin($admin_user);
// Add custom language.
$edit = [
'predefined_langcode' => 'custom',
];
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language'));
// Test validation on missing values.
$this->assertText(t('@name field is required.', ['@name' => t('Language code')]));
$this->assertText(t('@name field is required.', ['@name' => t('Language name')]));
$empty_language = new Language();
$this->assertFieldChecked('edit-direction-' . $empty_language->getDirection(), 'Consistent usage of language direction.');
$this->assertUrl(\Drupal::url('language.add', [], ['absolute' => TRUE]), [], 'Correct page redirection.');
// Test validation of invalid values.
$edit = [
'predefined_langcode' => 'custom',
'langcode' => 'white space',
'label' => '<strong>evil markup</strong>',
'direction' => LanguageInterface::DIRECTION_LTR,
];
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language'));
$this->assertRaw(t('%field must be a valid language tag as <a href=":url">defined by the W3C</a>.', [
'%field' => t('Language code'),
':url' => 'http://www.w3.org/International/articles/language-tags/',
]));
$this->assertRaw(t('%field cannot contain any markup.', ['%field' => t('Language name')]));
$this->assertUrl(\Drupal::url('language.add', [], ['absolute' => TRUE]), [], 'Correct page redirection.');
// Test adding a custom language with a numeric region code.
$edit = [
'predefined_langcode' => 'custom',
'langcode' => 'es-419',
'label' => 'Latin American Spanish',
'direction' => LanguageInterface::DIRECTION_LTR,
];
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language'));
$this->assertRaw(t(
'The language %language has been created and can now be used.',
['%language' => $edit['label']]
));
$this->assertUrl(\Drupal::url('entity.configurable_language.collection', [], ['absolute' => TRUE]), [], 'Correct page redirection.');
// Test validation of existing language values.
$edit = [
'predefined_langcode' => 'custom',
'langcode' => 'de',
'label' => 'German',
'direction' => LanguageInterface::DIRECTION_LTR,
];
// Add the language the first time.
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language'));
$this->assertRaw(t(
'The language %language has been created and can now be used.',
['%language' => $edit['label']]
));
$this->assertUrl(\Drupal::url('entity.configurable_language.collection', [], ['absolute' => TRUE]), [], 'Correct page redirection.');
// Add the language a second time and confirm that this is not allowed.
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language'));
$this->assertRaw(t(
'The language %language (%langcode) already exists.',
['%language' => $edit['label'], '%langcode' => $edit['langcode']]
));
$this->assertUrl(\Drupal::url('language.add', [], ['absolute' => TRUE]), [], 'Correct page redirection.');
}
}

View file

@ -1,209 +0,0 @@
<?php
namespace Drupal\language\Tests;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\simpletest\WebTestBase;
use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageInterface;
/**
* Adds a new language and tests changing its status and the default language.
*
* @group language
*/
class LanguageListTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['language'];
/**
* Functional tests for adding, editing and deleting languages.
*/
public function testLanguageList() {
// User to add and remove language.
$admin_user = $this->drupalCreateUser(['administer languages', 'access administration pages']);
$this->drupalLogin($admin_user);
// Get the weight of the last language.
$languages = \Drupal::service('language_manager')->getLanguages();
$last_language_weight = end($languages)->getWeight();
// Add predefined language.
$edit = [
'predefined_langcode' => 'fr',
];
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
$this->assertText('French', 'Language added successfully.');
$this->assertUrl(\Drupal::url('entity.configurable_language.collection', [], ['absolute' => TRUE]));
// Get the weight of the last language and check that the weight is one unit
// heavier than the last configurable language.
$this->rebuildContainer();
$languages = \Drupal::service('language_manager')->getLanguages();
$last_language = end($languages);
$this->assertEqual($last_language->getWeight(), $last_language_weight + 1);
$this->assertEqual($last_language->getId(), $edit['predefined_langcode']);
// Add custom language.
$langcode = 'xx';
$name = $this->randomMachineName(16);
$edit = [
'predefined_langcode' => 'custom',
'langcode' => $langcode,
'label' => $name,
'direction' => Language::DIRECTION_LTR,
];
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language'));
$this->assertUrl(\Drupal::url('entity.configurable_language.collection', [], ['absolute' => TRUE]));
$this->assertRaw('"edit-languages-' . $langcode . '-weight"', 'Language code found.');
$this->assertText(t($name), 'Test language added.');
$language = \Drupal::service('language_manager')->getLanguage($langcode);
$english = \Drupal::service('language_manager')->getLanguage('en');
// Check if we can change the default language.
$path = 'admin/config/regional/language';
$this->drupalGet($path);
$this->assertFieldChecked('edit-site-default-language-en', 'English is the default language.');
// Change the default language.
$edit = [
'site_default_language' => $langcode,
];
$this->drupalPostForm(NULL, $edit, t('Save configuration'));
$this->rebuildContainer();
$this->assertNoFieldChecked('edit-site-default-language-en', 'Default language updated.');
$this->assertUrl(\Drupal::url('entity.configurable_language.collection', [], ['absolute' => TRUE, 'language' => $language]));
// Ensure we can't delete the default language.
$this->drupalGet('admin/config/regional/language/delete/' . $langcode);
$this->assertResponse(403, 'Failed to delete the default language.');
// Ensure 'Edit' link works.
$this->drupalGet('admin/config/regional/language');
$this->clickLink(t('Edit'));
$this->assertTitle(t('Edit language | Drupal'), 'Page title is "Edit language".');
// Edit a language.
$name = $this->randomMachineName(16);
$edit = [
'label' => $name,
];
$this->drupalPostForm('admin/config/regional/language/edit/' . $langcode, $edit, t('Save language'));
$this->assertRaw($name, 'The language has been updated.');
$this->assertUrl(\Drupal::url('entity.configurable_language.collection', [], ['absolute' => TRUE, 'language' => $language]));
// Change back the default language.
$edit = [
'site_default_language' => 'en',
];
$this->drupalPostForm($path, $edit, t('Save configuration'));
$this->rebuildContainer();
// Ensure 'delete' link works.
$this->drupalGet('admin/config/regional/language');
$this->clickLink(t('Delete'));
$this->assertText(t('Are you sure you want to delete the language'), '"Delete" link is correct.');
// Delete a language.
$this->drupalGet('admin/config/regional/language/delete/' . $langcode);
// First test the 'cancel' link.
$this->clickLink(t('Cancel'));
$this->assertUrl(\Drupal::url('entity.configurable_language.collection', [], ['absolute' => TRUE, 'language' => $english]));
$this->assertRaw($name, 'The language was not deleted.');
// Delete the language for real. This a confirm form, we do not need any
// fields changed.
$this->drupalPostForm('admin/config/regional/language/delete/' . $langcode, [], t('Delete'));
// We need raw here because %language and %langcode will add HTML.
$t_args = ['%language' => $name, '%langcode' => $langcode];
$this->assertRaw(t('The %language (%langcode) language has been removed.', $t_args), 'The test language has been removed.');
$this->assertUrl(\Drupal::url('entity.configurable_language.collection', [], ['absolute' => TRUE, 'language' => $english]));
// Verify that language is no longer found.
$this->drupalGet('admin/config/regional/language/delete/' . $langcode);
$this->assertResponse(404, 'Language no longer found.');
// Delete French.
$this->drupalPostForm('admin/config/regional/language/delete/fr', [], t('Delete'));
// Make sure the "language_count" state has been updated correctly.
$this->rebuildContainer();
// We need raw here because %language and %langcode will add HTML.
$t_args = ['%language' => 'French', '%langcode' => 'fr'];
$this->assertRaw(t('The %language (%langcode) language has been removed.', $t_args), 'The French language has been removed.');
$this->assertUrl(\Drupal::url('entity.configurable_language.collection', [], ['absolute' => TRUE]));
// Verify that language is no longer found.
$this->drupalGet('admin/config/regional/language/delete/fr');
$this->assertResponse(404, 'Language no longer found.');
// Make sure the "language_count" state has not changed.
// Ensure we can delete the English language. Right now English is the only
// language so we must add a new language and make it the default before
// deleting English.
$langcode = 'xx';
$name = $this->randomMachineName(16);
$edit = [
'predefined_langcode' => 'custom',
'langcode' => $langcode,
'label' => $name,
'direction' => Language::DIRECTION_LTR,
];
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language'));
$this->assertUrl(\Drupal::url('entity.configurable_language.collection', [], ['absolute' => TRUE]));
$this->assertText($name, 'Name found.');
// Check if we can change the default language.
$path = 'admin/config/regional/language';
$this->drupalGet($path);
$this->assertFieldChecked('edit-site-default-language-en', 'English is the default language.');
// Change the default language.
$edit = [
'site_default_language' => $langcode,
];
$this->drupalPostForm(NULL, $edit, t('Save configuration'));
$this->rebuildContainer();
$this->assertNoFieldChecked('edit-site-default-language-en', 'Default language updated.');
$this->assertUrl(\Drupal::url('entity.configurable_language.collection', [], ['absolute' => TRUE, 'language' => $language]));
$this->drupalPostForm('admin/config/regional/language/delete/en', [], t('Delete'));
// We need raw here because %language and %langcode will add HTML.
$t_args = ['%language' => 'English', '%langcode' => 'en'];
$this->assertRaw(t('The %language (%langcode) language has been removed.', $t_args), 'The English language has been removed.');
$this->rebuildContainer();
// Ensure we can't delete a locked language.
$this->drupalGet('admin/config/regional/language/delete/und');
$this->assertResponse(403, 'Can not delete locked language');
// Ensure that NL cannot be set default when it's not available.
$this->drupalGet('admin/config/regional/language');
$extra_values = '&site_default_language=nl';
$this->drupalPostForm(NULL, [], t('Save configuration'), [], [], NULL, $extra_values);
$this->assertText(t('Selected default language no longer exists.'));
$this->assertNoFieldChecked('edit-site-default-language-xx', 'The previous default language got deselected.');
}
/**
* Functional tests for the language states (locked or configurable).
*/
public function testLanguageStates() {
// Add some languages, and also lock some of them.
ConfigurableLanguage::create(['label' => $this->randomMachineName(), 'id' => 'l1'])->save();
ConfigurableLanguage::create(['label' => $this->randomMachineName(), 'id' => 'l2', 'locked' => TRUE])->save();
ConfigurableLanguage::create(['label' => $this->randomMachineName(), 'id' => 'l3'])->save();
ConfigurableLanguage::create(['label' => $this->randomMachineName(), 'id' => 'l4', 'locked' => TRUE])->save();
$expected_locked_languages = ['l4' => 'l4', 'l2' => 'l2', 'und' => 'und', 'zxx' => 'zxx'];
$expected_all_languages = ['l4' => 'l4', 'l3' => 'l3', 'l2' => 'l2', 'l1' => 'l1', 'en' => 'en', 'und' => 'und', 'zxx' => 'zxx'];
$expected_conf_languages = ['l3' => 'l3', 'l1' => 'l1', 'en' => 'en'];
$locked_languages = $this->container->get('language_manager')->getLanguages(LanguageInterface::STATE_LOCKED);
$this->assertEqual(array_diff_key($expected_locked_languages, $locked_languages), [], 'Locked languages loaded correctly.');
$all_languages = $this->container->get('language_manager')->getLanguages(LanguageInterface::STATE_ALL);
$this->assertEqual(array_diff_key($expected_all_languages, $all_languages), [], 'All languages loaded correctly.');
$conf_languages = $this->container->get('language_manager')->getLanguages();
$this->assertEqual(array_diff_key($expected_conf_languages, $conf_languages), [], 'Configurable languages loaded correctly.');
}
}

View file

@ -1,73 +0,0 @@
<?php
namespace Drupal\language\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Adds a new language with translations and tests language list order.
*
* @group language
*/
class LanguageLocaleListTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['language', 'locale'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Add a default locale storage for all these tests.
$this->storage = $this->container->get('locale.storage');
}
/**
* Tests adding, editing, and deleting languages.
*/
public function testLanguageLocaleList() {
// User to add and remove language.
$admin_user = $this->drupalCreateUser(['administer languages', 'access administration pages']);
$this->drupalLogin($admin_user);
// Add predefined language.
$edit = [
'predefined_langcode' => 'fr',
];
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
$this->assertText('The language French has been created and can now be used');
$this->assertUrl(\Drupal::url('entity.configurable_language.collection', [], ['absolute' => TRUE]));
$this->rebuildContainer();
// Translate Spanish language to French (Espagnol).
$source = $this->storage->createString([
'source' => 'Spanish',
'context' => '',
])->save();
$this->storage->createTranslation([
'lid' => $source->lid,
'language' => 'fr',
'translation' => 'Espagnol',
])->save();
// Get language list displayed in select list.
$this->drupalGet('fr/admin/config/regional/language/add');
$select = $this->xpath('//select[@id="edit-predefined-langcode"]');
$select_element = (array) end($select);
$options = $select_element['option'];
// Remove the 'Custom language...' option form the end.
array_pop($options);
// Order language list.
$options_ordered = $options;
natcasesort($options_ordered);
// Check the language list displayed is ordered.
$this->assertTrue($options === $options_ordered, 'Language list is ordered.');
}
}

View file

@ -1,88 +0,0 @@
<?php
namespace Drupal\language\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests the content translation settings language selector options.
*
* @group language
*/
class LanguageSelectorTranslatableTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = [
'language',
'content_translation',
'node',
'comment',
'field_ui',
'entity_test',
'locale',
];
/**
* The user with administrator privileges.
*
* @var \Drupal\user\Entity\User;
*/
public $administrator;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Create user and set permissions.
$this->administrator = $this->drupalCreateUser($this->getAdministratorPermissions(), 'administrator');
$this->drupalLogin($this->administrator);
}
/**
* Returns an array of permissions needed for the translator.
*/
protected function getAdministratorPermissions() {
return array_filter(
['translate interface',
'administer content translation',
'create content translations',
'update content translations',
'delete content translations',
'administer languages',
]
);
}
/**
* Tests content translation language selectors are correctly translated.
*/
public function testLanguageStringSelector() {
// Add another language.
$edit = ['predefined_langcode' => 'es'];
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
// Translate the string English in Spanish (Inglés). Override config entity.
$name_translation = 'Inglés';
\Drupal::languageManager()
->getLanguageConfigOverride('es', 'language.entity.en')
->set('label', $name_translation)
->save();
// Check content translation overview selector.
$path = 'es/admin/config/regional/content-language';
$this->drupalGet($path);
// Get en language from selector.
$elements = $this->xpath('//select[@id=:id]//option[@value=:option]', [':id' => 'edit-settings-user-user-settings-language-langcode', ':option' => 'en']);
// Check that the language text is translated.
$this->assertEqual((string) $elements[0], $name_translation, 'Checking the option string English is translated to Spanish.');
}
}

View file

@ -1,457 +0,0 @@
<?php
namespace Drupal\language\Tests;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl;
use Drupal\menu_link_content\Entity\MenuLinkContent;
use Drupal\Core\Language\LanguageInterface;
use Drupal\simpletest\WebTestBase;
/**
* Functional tests for the language switching feature.
*
* @group language
*/
class LanguageSwitchingTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['locale', 'locale_test', 'language', 'block', 'language_test', 'menu_ui'];
protected function setUp() {
parent::setUp();
// Create and log in user.
$admin_user = $this->drupalCreateUser(['administer blocks', 'administer languages', 'access administration pages']);
$this->drupalLogin($admin_user);
}
/**
* Functional tests for the language switcher block.
*/
public function testLanguageBlock() {
// Add language.
$edit = [
'predefined_langcode' => 'fr',
];
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
// Set the native language name.
$this->saveNativeLanguageName('fr', 'français');
// Enable URL language detection and selection.
$edit = ['language_interface[enabled][language-url]' => '1'];
$this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
// Enable the language switching block.
$block = $this->drupalPlaceBlock('language_block:' . LanguageInterface::TYPE_INTERFACE, [
'id' => 'test_language_block',
// Ensure a 2-byte UTF-8 sequence is in the tested output.
'label' => $this->randomMachineName(8) . '×',
]);
$this->doTestLanguageBlockAuthenticated($block->label());
$this->doTestLanguageBlockAnonymous($block->label());
}
/**
* For authenticated users, the "active" class is set by JavaScript.
*
* @param string $block_label
* The label of the language switching block.
*
* @see testLanguageBlock()
*/
protected function doTestLanguageBlockAuthenticated($block_label) {
// Assert that the language switching block is displayed on the frontpage.
$this->drupalGet('');
$this->assertText($block_label, 'Language switcher block found.');
// Assert that each list item and anchor element has the appropriate data-
// attributes.
list($language_switcher) = $this->xpath('//div[@id=:id]', [':id' => 'block-test-language-block']);
$list_items = [];
$anchors = [];
$labels = [];
foreach ($language_switcher->ul->li as $list_item) {
$classes = explode(" ", (string) $list_item['class']);
list($langcode) = array_intersect($classes, ['en', 'fr']);
$list_items[] = [
'langcode_class' => $langcode,
'data-drupal-link-system-path' => (string) $list_item['data-drupal-link-system-path'],
];
$anchors[] = [
'hreflang' => (string) $list_item->a['hreflang'],
'data-drupal-link-system-path' => (string) $list_item->a['data-drupal-link-system-path'],
];
$labels[] = (string) $list_item->a;
}
$expected_list_items = [
0 => ['langcode_class' => 'en', 'data-drupal-link-system-path' => 'user/2'],
1 => ['langcode_class' => 'fr', 'data-drupal-link-system-path' => 'user/2'],
];
$this->assertIdentical($list_items, $expected_list_items, 'The list items have the correct attributes that will allow the drupal.active-link library to mark them as active.');
$expected_anchors = [
0 => ['hreflang' => 'en', 'data-drupal-link-system-path' => 'user/2'],
1 => ['hreflang' => 'fr', 'data-drupal-link-system-path' => 'user/2'],
];
$this->assertIdentical($anchors, $expected_anchors, 'The anchors have the correct attributes that will allow the drupal.active-link library to mark them as active.');
$settings = $this->getDrupalSettings();
$this->assertIdentical($settings['path']['currentPath'], 'user/2', 'drupalSettings.path.currentPath is set correctly to allow drupal.active-link to mark the correct links as active.');
$this->assertIdentical($settings['path']['isFront'], FALSE, 'drupalSettings.path.isFront is set correctly to allow drupal.active-link to mark the correct links as active.');
$this->assertIdentical($settings['path']['currentLanguage'], 'en', 'drupalSettings.path.currentLanguage is set correctly to allow drupal.active-link to mark the correct links as active.');
$this->assertIdentical($labels, ['English', 'français'], 'The language links labels are in their own language on the language switcher block.');
}
/**
* For anonymous users, the "active" class is set by PHP.
*
* @param string $block_label
* The label of the language switching block.
*
* @see testLanguageBlock()
*/
protected function doTestLanguageBlockAnonymous($block_label) {
$this->drupalLogout();
// Assert that the language switching block is displayed on the frontpage
// and ensure that the active class is added when query params are present.
$this->drupalGet('', ['query' => ['foo' => 'bar']]);
$this->assertText($block_label, 'Language switcher block found.');
// Assert that only the current language is marked as active.
list($language_switcher) = $this->xpath('//div[@id=:id]', [':id' => 'block-test-language-block']);
$links = [
'active' => [],
'inactive' => [],
];
$anchors = [
'active' => [],
'inactive' => [],
];
$labels = [];
foreach ($language_switcher->ul->li as $link) {
$classes = explode(" ", (string) $link['class']);
list($langcode) = array_intersect($classes, ['en', 'fr']);
if (in_array('is-active', $classes)) {
$links['active'][] = $langcode;
}
else {
$links['inactive'][] = $langcode;
}
$anchor_classes = explode(" ", (string) $link->a['class']);
if (in_array('is-active', $anchor_classes)) {
$anchors['active'][] = $langcode;
}
else {
$anchors['inactive'][] = $langcode;
}
$labels[] = (string) $link->a;
}
$this->assertIdentical($links, ['active' => ['en'], 'inactive' => ['fr']], 'Only the current language list item is marked as active on the language switcher block.');
$this->assertIdentical($anchors, ['active' => ['en'], 'inactive' => ['fr']], 'Only the current language anchor is marked as active on the language switcher block.');
$this->assertIdentical($labels, ['English', 'français'], 'The language links labels are in their own language on the language switcher block.');
}
/**
* Test language switcher links for domain based negotiation.
*/
public function testLanguageBlockWithDomain() {
// Add the Italian language.
ConfigurableLanguage::createFromLangcode('it')->save();
// Rebuild the container so that the new language is picked up by services
// that hold a list of languages.
$this->rebuildContainer();
$languages = $this->container->get('language_manager')->getLanguages();
// Enable browser and URL language detection.
$edit = [
'language_interface[enabled][language-url]' => TRUE,
'language_interface[weight][language-url]' => -10,
];
$this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
// Do not allow blank domain.
$edit = [
'language_negotiation_url_part' => LanguageNegotiationUrl::CONFIG_DOMAIN,
'domain[en]' => '',
];
$this->drupalPostForm('admin/config/regional/language/detection/url', $edit, t('Save configuration'));
$this->assertText(t('The domain may not be left blank for English'), 'The form does not allow blank domains.');
// Change the domain for the Italian language.
$edit = [
'language_negotiation_url_part' => LanguageNegotiationUrl::CONFIG_DOMAIN,
'domain[en]' => \Drupal::request()->getHost(),
'domain[it]' => 'it.example.com',
];
$this->drupalPostForm('admin/config/regional/language/detection/url', $edit, t('Save configuration'));
$this->assertText(t('The configuration options have been saved'), 'Domain configuration is saved.');
// Enable the language switcher block.
$this->drupalPlaceBlock('language_block:' . LanguageInterface::TYPE_INTERFACE, ['id' => 'test_language_block']);
$this->drupalGet('');
/** @var \Drupal\Core\Routing\UrlGenerator $generator */
$generator = $this->container->get('url_generator');
// Verify the English URL is correct
list($english_link) = $this->xpath('//div[@id=:id]/ul/li/a[@hreflang=:hreflang]', [
':id' => 'block-test-language-block',
':hreflang' => 'en',
]);
$english_url = $generator->generateFromRoute('entity.user.canonical', ['user' => 2], ['language' => $languages['en']]);
$this->assertEqual($english_url, (string) $english_link['href']);
// Verify the Italian URL is correct
list($italian_link) = $this->xpath('//div[@id=:id]/ul/li/a[@hreflang=:hreflang]', [
':id' => 'block-test-language-block',
':hreflang' => 'it',
]);
$italian_url = $generator->generateFromRoute('entity.user.canonical', ['user' => 2], ['language' => $languages['it']]);
$this->assertEqual($italian_url, (string) $italian_link['href']);
}
/**
* Test active class on links when switching languages.
*/
public function testLanguageLinkActiveClass() {
// Add language.
$edit = [
'predefined_langcode' => 'fr',
];
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
// Enable URL language detection and selection.
$edit = ['language_interface[enabled][language-url]' => '1'];
$this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
$this->doTestLanguageLinkActiveClassAuthenticated();
$this->doTestLanguageLinkActiveClassAnonymous();
}
/**
* Check the path-admin class, as same as on default language.
*/
public function testLanguageBodyClass() {
$searched_class = 'path-admin';
// Add language.
$edit = [
'predefined_langcode' => 'fr',
];
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
// Enable URL language detection and selection.
$edit = ['language_interface[enabled][language-url]' => '1'];
$this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
// Check if the default (English) admin/config page has the right class.
$this->drupalGet('admin/config');
$class = $this->xpath('//body[contains(@class, :class)]', [':class' => $searched_class]);
$this->assertTrue(isset($class[0]), t('The path-admin class appears on default language.'));
// Check if the French admin/config page has the right class.
$this->drupalGet('fr/admin/config');
$class = $this->xpath('//body[contains(@class, :class)]', [':class' => $searched_class]);
$this->assertTrue(isset($class[0]), t('The path-admin class same as on default language.'));
// The testing profile sets the user/login page as the frontpage. That
// redirects authenticated users to their profile page, so check with an
// anonymous user instead.
$this->drupalLogout();
// Check if the default (English) frontpage has the right class.
$this->drupalGet('<front>');
$class = $this->xpath('//body[contains(@class, :class)]', [':class' => 'path-frontpage']);
$this->assertTrue(isset($class[0]), 'path-frontpage class found on the body tag');
// Check if the French frontpage has the right class.
$this->drupalGet('fr');
$class = $this->xpath('//body[contains(@class, :class)]', [':class' => 'path-frontpage']);
$this->assertTrue(isset($class[0]), 'path-frontpage class found on the body tag with french as the active language');
}
/**
* For authenticated users, the "active" class is set by JavaScript.
*
* @see testLanguageLinkActiveClass()
*/
protected function doTestLanguageLinkActiveClassAuthenticated() {
$function_name = '#type link';
$path = 'language_test/type-link-active-class';
// Test links generated by the link generator on an English page.
$current_language = 'English';
$this->drupalGet($path);
// Language code 'none' link should be active.
$langcode = 'none';
$links = $this->xpath('//a[@id = :id and @data-drupal-link-system-path = :path]', [':id' => 'no_lang_link', ':path' => $path]);
$this->assertTrue(isset($links[0]), t('A link generated by :function to the current :language page with langcode :langcode has the correct attributes that will allow the drupal.active-link library to mark it as active.', [':function' => $function_name, ':language' => $current_language, ':langcode' => $langcode]));
// Language code 'en' link should be active.
$langcode = 'en';
$links = $this->xpath('//a[@id = :id and @hreflang = :lang and @data-drupal-link-system-path = :path]', [':id' => 'en_link', ':lang' => 'en', ':path' => $path]);
$this->assertTrue(isset($links[0]), t('A link generated by :function to the current :language page with langcode :langcode has the correct attributes that will allow the drupal.active-link library to mark it as active.', [':function' => $function_name, ':language' => $current_language, ':langcode' => $langcode]));
// Language code 'fr' link should not be active.
$langcode = 'fr';
$links = $this->xpath('//a[@id = :id and @hreflang = :lang and @data-drupal-link-system-path = :path]', [':id' => 'fr_link', ':lang' => 'fr', ':path' => $path]);
$this->assertTrue(isset($links[0]), t('A link generated by :function to the current :language page with langcode :langcode has the correct attributes that will allow the drupal.active-link library to NOT mark it as active.', [':function' => $function_name, ':language' => $current_language, ':langcode' => $langcode]));
// Verify that drupalSettings contains the correct values.
$settings = $this->getDrupalSettings();
$this->assertIdentical($settings['path']['currentPath'], $path, 'drupalSettings.path.currentPath is set correctly to allow drupal.active-link to mark the correct links as active.');
$this->assertIdentical($settings['path']['isFront'], FALSE, 'drupalSettings.path.isFront is set correctly to allow drupal.active-link to mark the correct links as active.');
$this->assertIdentical($settings['path']['currentLanguage'], 'en', 'drupalSettings.path.currentLanguage is set correctly to allow drupal.active-link to mark the correct links as active.');
// Test links generated by the link generator on a French page.
$current_language = 'French';
$this->drupalGet('fr/language_test/type-link-active-class');
// Language code 'none' link should be active.
$langcode = 'none';
$links = $this->xpath('//a[@id = :id and @data-drupal-link-system-path = :path]', [':id' => 'no_lang_link', ':path' => $path]);
$this->assertTrue(isset($links[0]), t('A link generated by :function to the current :language page with langcode :langcode has the correct attributes that will allow the drupal.active-link library to mark it as active.', [':function' => $function_name, ':language' => $current_language, ':langcode' => $langcode]));
// Language code 'en' link should not be active.
$langcode = 'en';
$links = $this->xpath('//a[@id = :id and @hreflang = :lang and @data-drupal-link-system-path = :path]', [':id' => 'en_link', ':lang' => 'en', ':path' => $path]);
$this->assertTrue(isset($links[0]), t('A link generated by :function to the current :language page with langcode :langcode has the correct attributes that will allow the drupal.active-link library to NOT mark it as active.', [':function' => $function_name, ':language' => $current_language, ':langcode' => $langcode]));
// Language code 'fr' link should be active.
$langcode = 'fr';
$links = $this->xpath('//a[@id = :id and @hreflang = :lang and @data-drupal-link-system-path = :path]', [':id' => 'fr_link', ':lang' => 'fr', ':path' => $path]);
$this->assertTrue(isset($links[0]), t('A link generated by :function to the current :language page with langcode :langcode has the correct attributes that will allow the drupal.active-link library to mark it as active.', [':function' => $function_name, ':language' => $current_language, ':langcode' => $langcode]));
// Verify that drupalSettings contains the correct values.
$settings = $this->getDrupalSettings();
$this->assertIdentical($settings['path']['currentPath'], $path, 'drupalSettings.path.currentPath is set correctly to allow drupal.active-link to mark the correct links as active.');
$this->assertIdentical($settings['path']['isFront'], FALSE, 'drupalSettings.path.isFront is set correctly to allow drupal.active-link to mark the correct links as active.');
$this->assertIdentical($settings['path']['currentLanguage'], 'fr', 'drupalSettings.path.currentLanguage is set correctly to allow drupal.active-link to mark the correct links as active.');
}
/**
* For anonymous users, the "active" class is set by PHP.
*
* @see testLanguageLinkActiveClass()
*/
protected function doTestLanguageLinkActiveClassAnonymous() {
$function_name = '#type link';
$this->drupalLogout();
// Test links generated by the link generator on an English page.
$current_language = 'English';
$this->drupalGet('language_test/type-link-active-class');
// Language code 'none' link should be active.
$langcode = 'none';
$links = $this->xpath('//a[@id = :id and contains(@class, :class)]', [':id' => 'no_lang_link', ':class' => 'is-active']);
$this->assertTrue(isset($links[0]), t('A link generated by :function to the current :language page with langcode :langcode is marked active.', [':function' => $function_name, ':language' => $current_language, ':langcode' => $langcode]));
// Language code 'en' link should be active.
$langcode = 'en';
$links = $this->xpath('//a[@id = :id and contains(@class, :class)]', [':id' => 'en_link', ':class' => 'is-active']);
$this->assertTrue(isset($links[0]), t('A link generated by :function to the current :language page with langcode :langcode is marked active.', [':function' => $function_name, ':language' => $current_language, ':langcode' => $langcode]));
// Language code 'fr' link should not be active.
$langcode = 'fr';
$links = $this->xpath('//a[@id = :id and not(contains(@class, :class))]', [':id' => 'fr_link', ':class' => 'is-active']);
$this->assertTrue(isset($links[0]), t('A link generated by :function to the current :language page with langcode :langcode is NOT marked active.', [':function' => $function_name, ':language' => $current_language, ':langcode' => $langcode]));
// Test links generated by the link generator on a French page.
$current_language = 'French';
$this->drupalGet('fr/language_test/type-link-active-class');
// Language code 'none' link should be active.
$langcode = 'none';
$links = $this->xpath('//a[@id = :id and contains(@class, :class)]', [':id' => 'no_lang_link', ':class' => 'is-active']);
$this->assertTrue(isset($links[0]), t('A link generated by :function to the current :language page with langcode :langcode is marked active.', [':function' => $function_name, ':language' => $current_language, ':langcode' => $langcode]));
// Language code 'en' link should not be active.
$langcode = 'en';
$links = $this->xpath('//a[@id = :id and not(contains(@class, :class))]', [':id' => 'en_link', ':class' => 'is-active']);
$this->assertTrue(isset($links[0]), t('A link generated by :function to the current :language page with langcode :langcode is NOT marked active.', [':function' => $function_name, ':language' => $current_language, ':langcode' => $langcode]));
// Language code 'fr' link should be active.
$langcode = 'fr';
$links = $this->xpath('//a[@id = :id and contains(@class, :class)]', [':id' => 'fr_link', ':class' => 'is-active']);
$this->assertTrue(isset($links[0]), t('A link generated by :function to the current :language page with langcode :langcode is marked active.', [':function' => $function_name, ':language' => $current_language, ':langcode' => $langcode]));
}
/**
* Tests language switcher links for session based negotiation.
*/
public function testLanguageSessionSwitchLinks() {
// Add language.
$edit = [
'predefined_langcode' => 'fr',
];
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
// Enable session language detection and selection.
$edit = [
'language_interface[enabled][language-url]' => FALSE,
'language_interface[enabled][language-session]' => TRUE,
];
$this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
// Enable the language switching block.
$this->drupalPlaceBlock('language_block:' . LanguageInterface::TYPE_INTERFACE, [
'id' => 'test_language_block',
]);
// Enable the main menu block.
$this->drupalPlaceBlock('system_menu_block:main', [
'id' => 'test_menu',
]);
// Add a link to the homepage.
$link = MenuLinkContent::create([
'title' => 'Home',
'menu_name' => 'main',
'bundle' => 'menu_link_content',
'link' => [['uri' => 'entity:user/2']],
]);
$link->save();
// Go to the homepage.
$this->drupalGet('');
// Click on the French link.
$this->clickLink(t('French'));
// There should be a query parameter to set the session language.
$this->assertUrl('user/2', ['query' => ['language' => 'fr']]);
// Click on the 'Home' Link.
$this->clickLink(t('Home'));
// There should be no query parameter.
$this->assertUrl('user/2');
// Click on the French link.
$this->clickLink(t('French'));
// There should be no query parameter.
$this->assertUrl('user/2');
}
/**
* Saves the native name of a language entity in configuration as a label.
*
* @param string $langcode
* The language code of the language.
* @param string $label
* The native name of the language.
*/
protected function saveNativeLanguageName($langcode, $label) {
\Drupal::service('language.config_factory_override')
->getOverride($langcode, 'language.entity.' . $langcode)->set('label', $label)->save();
}
}

View file

@ -1,62 +0,0 @@
<?php
namespace Drupal\language\Tests;
use Drupal\tour\Tests\TourTestBase;
/**
* Tests tour functionality.
*
* @group tour
*/
class LanguageTourTest extends TourTestBase {
/**
* An admin user with administrative permissions for views.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['block', 'language', 'tour'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->adminUser = $this->drupalCreateUser(['administer languages', 'access tour']);
$this->drupalLogin($this->adminUser);
$this->drupalPlaceBlock('local_actions_block');
}
/**
* Tests language tour tip availability.
*/
public function testLanguageTour() {
$this->drupalGet('admin/config/regional/language');
$this->assertTourTips();
}
/**
* Go to add language page and check the tour tooltips.
*/
public function testLanguageAddTour() {
$this->drupalGet('admin/config/regional/language/add');
$this->assertTourTips();
}
/**
* Go to edit language page and check the tour tooltips.
*/
public function testLanguageEditTour() {
$this->drupalGet('admin/config/regional/language/edit/en');
$this->assertTourTips();
}
}

View file

@ -1,536 +0,0 @@
<?php
namespace Drupal\language\Tests;
use Drupal\Core\Url;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationBrowser;
use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationSelected;
use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationSession;
use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl;
use Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUser;
use Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUserAdmin;
use Drupal\simpletest\WebTestBase;
use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageInterface;
use Symfony\Component\HttpFoundation\Request;
use Drupal\language\LanguageNegotiatorInterface;
use Drupal\block\Entity\Block;
/**
* Tests the language UI for language switching.
*
* The uses cases that get tested, are:
* - URL (path) > default: Test that the URL prefix setting gets precedence over
* the default language. The browser language preference does not have any
* influence.
* - URL (path) > browser > default: Test that the URL prefix setting gets
* precedence over the browser language preference, which in turn gets
* precedence over the default language.
* - URL (domain) > default: Tests that the URL domain setting gets precedence
* over the default language.
*
* The paths that are used for each of these, are:
* - admin/config: Tests the UI using the precedence rules.
* - zh-hans/admin/config: Tests the UI in Chinese.
* - blah-blah/admin/config: Tests the 404 page.
*
* @group language
*/
class LanguageUILanguageNegotiationTest extends WebTestBase {
/**
* Modules to enable.
*
* We marginally use interface translation functionality here, so need to use
* the locale module instead of language only, but the 90% of the test is
* about the negotiation process which is solely in language module.
*
* @var array
*/
public static $modules = ['locale', 'language_test', 'block', 'user', 'content_translation'];
protected function setUp() {
parent::setUp();
$admin_user = $this->drupalCreateUser(['administer languages', 'translate interface', 'access administration pages', 'administer blocks']);
$this->drupalLogin($admin_user);
}
/**
* Tests for language switching by URL path.
*/
public function testUILanguageNegotiation() {
// A few languages to switch to.
// This one is unknown, should get the default lang version.
$langcode_unknown = 'blah-blah';
// For testing browser lang preference.
$langcode_browser_fallback = 'vi';
// For testing path prefix.
$langcode = 'zh-hans';
// For setting browser language preference to 'vi'.
$http_header_browser_fallback = ["Accept-Language: $langcode_browser_fallback;q=1"];
// For setting browser language preference to some unknown.
$http_header_blah = ["Accept-Language: blah;q=1"];
// Setup the site languages by installing two languages.
// Set the default language in order for the translated string to be registered
// into database when seen by t(). Without doing this, our target string
// is for some reason not found when doing translate search. This might
// be some bug.
$default_language = \Drupal::languageManager()->getDefaultLanguage();
ConfigurableLanguage::createFromLangcode($langcode_browser_fallback)->save();
$this->config('system.site')->set('default_langcode', $langcode_browser_fallback)->save();
ConfigurableLanguage::createFromLangcode($langcode)->save();
// We will look for this string in the admin/config screen to see if the
// corresponding translated string is shown.
$default_string = 'Hide descriptions';
// First visit this page to make sure our target string is searchable.
$this->drupalGet('admin/config');
// Now the t()'ed string is in db so switch the language back to default.
// This will rebuild the container so we need to rebuild the container in
// the test environment.
$this->config('system.site')->set('default_langcode', $default_language->getId())->save();
$this->config('language.negotiation')->set('url.prefixes.en', '')->save();
$this->rebuildContainer();
// Translate the string.
$language_browser_fallback_string = "In $langcode_browser_fallback In $langcode_browser_fallback In $langcode_browser_fallback";
$language_string = "In $langcode In $langcode In $langcode";
// Do a translate search of our target string.
$search = [
'string' => $default_string,
'langcode' => $langcode_browser_fallback,
];
$this->drupalPostForm('admin/config/regional/translate', $search, t('Filter'));
$textarea = current($this->xpath('//textarea'));
$lid = (string) $textarea[0]['name'];
$edit = [
$lid => $language_browser_fallback_string,
];
$this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations'));
$search = [
'string' => $default_string,
'langcode' => $langcode,
];
$this->drupalPostForm('admin/config/regional/translate', $search, t('Filter'));
$textarea = current($this->xpath('//textarea'));
$lid = (string) $textarea[0]['name'];
$edit = [
$lid => $language_string,
];
$this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations'));
// Configure selected language negotiation to use zh-hans.
$edit = ['selected_langcode' => $langcode];
$this->drupalPostForm('admin/config/regional/language/detection/selected', $edit, t('Save configuration'));
$test = [
'language_negotiation' => [LanguageNegotiationSelected::METHOD_ID],
'path' => 'admin/config',
'expect' => $language_string,
'expected_method_id' => LanguageNegotiationSelected::METHOD_ID,
'http_header' => $http_header_browser_fallback,
'message' => 'SELECTED: UI language is switched based on selected language.',
];
$this->doRunTest($test);
// An invalid language is selected.
$this->config('language.negotiation')->set('selected_langcode', NULL)->save();
$test = [
'language_negotiation' => [LanguageNegotiationSelected::METHOD_ID],
'path' => 'admin/config',
'expect' => $default_string,
'expected_method_id' => LanguageNegotiatorInterface::METHOD_ID,
'http_header' => $http_header_browser_fallback,
'message' => 'SELECTED > DEFAULT: UI language is switched based on selected language.',
];
$this->doRunTest($test);
// No selected language is available.
$this->config('language.negotiation')->set('selected_langcode', $langcode_unknown)->save();
$test = [
'language_negotiation' => [LanguageNegotiationSelected::METHOD_ID],
'path' => 'admin/config',
'expect' => $default_string,
'expected_method_id' => LanguageNegotiatorInterface::METHOD_ID,
'http_header' => $http_header_browser_fallback,
'message' => 'SELECTED > DEFAULT: UI language is switched based on selected language.',
];
$this->doRunTest($test);
$tests = [
// Default, browser preference should have no influence.
[
'language_negotiation' => [LanguageNegotiationUrl::METHOD_ID, LanguageNegotiationSelected::METHOD_ID],
'path' => 'admin/config',
'expect' => $default_string,
'expected_method_id' => LanguageNegotiatorInterface::METHOD_ID,
'http_header' => $http_header_browser_fallback,
'message' => 'URL (PATH) > DEFAULT: no language prefix, UI language is default and the browser language preference setting is not used.',
],
// Language prefix.
[
'language_negotiation' => [LanguageNegotiationUrl::METHOD_ID, LanguageNegotiationSelected::METHOD_ID],
'path' => "$langcode/admin/config",
'expect' => $language_string,
'expected_method_id' => LanguageNegotiationUrl::METHOD_ID,
'http_header' => $http_header_browser_fallback,
'message' => 'URL (PATH) > DEFAULT: with language prefix, UI language is switched based on path prefix',
],
// Default, go by browser preference.
[
'language_negotiation' => [LanguageNegotiationUrl::METHOD_ID, LanguageNegotiationBrowser::METHOD_ID],
'path' => 'admin/config',
'expect' => $language_browser_fallback_string,
'expected_method_id' => LanguageNegotiationBrowser::METHOD_ID,
'http_header' => $http_header_browser_fallback,
'message' => 'URL (PATH) > BROWSER: no language prefix, UI language is determined by browser language preference',
],
// Prefix, switch to the language.
[
'language_negotiation' => [LanguageNegotiationUrl::METHOD_ID, LanguageNegotiationBrowser::METHOD_ID],
'path' => "$langcode/admin/config",
'expect' => $language_string,
'expected_method_id' => LanguageNegotiationUrl::METHOD_ID,
'http_header' => $http_header_browser_fallback,
'message' => 'URL (PATH) > BROWSER: with language prefix, UI language is based on path prefix',
],
// Default, browser language preference is not one of site's lang.
[
'language_negotiation' => [LanguageNegotiationUrl::METHOD_ID, LanguageNegotiationBrowser::METHOD_ID, LanguageNegotiationSelected::METHOD_ID],
'path' => 'admin/config',
'expect' => $default_string,
'expected_method_id' => LanguageNegotiatorInterface::METHOD_ID,
'http_header' => $http_header_blah,
'message' => 'URL (PATH) > BROWSER > DEFAULT: no language prefix and browser language preference set to unknown language should use default language',
],
];
foreach ($tests as $test) {
$this->doRunTest($test);
}
// Unknown language prefix should return 404.
$definitions = \Drupal::languageManager()->getNegotiator()->getNegotiationMethods();
// Enable only methods, which are either not limited to a specific language
// type or are supporting the interface language type.
$language_interface_method_definitions = array_filter($definitions, function ($method_definition) {
return !isset($method_definition['types']) || (isset($method_definition['types']) && in_array(LanguageInterface::TYPE_INTERFACE, $method_definition['types']));
});
$this->config('language.types')
->set('negotiation.' . LanguageInterface::TYPE_INTERFACE . '.enabled', array_flip(array_keys($language_interface_method_definitions)))
->save();
$this->drupalGet("$langcode_unknown/admin/config", [], $http_header_browser_fallback);
$this->assertResponse(404, "Unknown language path prefix should return 404");
// Set preferred langcode for user to NULL.
$account = $this->loggedInUser;
$account->preferred_langcode = NULL;
$account->save();
$test = [
'language_negotiation' => [LanguageNegotiationUser::METHOD_ID, LanguageNegotiationSelected::METHOD_ID],
'path' => 'admin/config',
'expect' => $default_string,
'expected_method_id' => LanguageNegotiatorInterface::METHOD_ID,
'http_header' => [],
'message' => 'USER > DEFAULT: no preferred user language setting, the UI language is default',
];
$this->doRunTest($test);
// Set preferred langcode for user to unknown language.
$account = $this->loggedInUser;
$account->preferred_langcode = $langcode_unknown;
$account->save();
$test = [
'language_negotiation' => [LanguageNegotiationUser::METHOD_ID, LanguageNegotiationSelected::METHOD_ID],
'path' => 'admin/config',
'expect' => $default_string,
'expected_method_id' => LanguageNegotiatorInterface::METHOD_ID,
'http_header' => [],
'message' => 'USER > DEFAULT: invalid preferred user language setting, the UI language is default',
];
$this->doRunTest($test);
// Set preferred langcode for user to non default.
$account->preferred_langcode = $langcode;
$account->save();
$test = [
'language_negotiation' => [LanguageNegotiationUser::METHOD_ID, LanguageNegotiationSelected::METHOD_ID],
'path' => 'admin/config',
'expect' => $language_string,
'expected_method_id' => LanguageNegotiationUser::METHOD_ID,
'http_header' => [],
'message' => 'USER > DEFAULT: defined preferred user language setting, the UI language is based on user setting',
];
$this->doRunTest($test);
// Set preferred admin langcode for user to NULL.
$account->preferred_admin_langcode = NULL;
$account->save();
$test = [
'language_negotiation' => [LanguageNegotiationUserAdmin::METHOD_ID, LanguageNegotiationSelected::METHOD_ID],
'path' => 'admin/config',
'expect' => $default_string,
'expected_method_id' => LanguageNegotiatorInterface::METHOD_ID,
'http_header' => [],
'message' => 'USER ADMIN > DEFAULT: no preferred user admin language setting, the UI language is default',
];
$this->doRunTest($test);
// Set preferred admin langcode for user to unknown language.
$account->preferred_admin_langcode = $langcode_unknown;
$account->save();
$test = [
'language_negotiation' => [LanguageNegotiationUserAdmin::METHOD_ID, LanguageNegotiationSelected::METHOD_ID],
'path' => 'admin/config',
'expect' => $default_string,
'expected_method_id' => LanguageNegotiatorInterface::METHOD_ID,
'http_header' => [],
'message' => 'USER ADMIN > DEFAULT: invalid preferred user admin language setting, the UI language is default',
];
$this->doRunTest($test);
// Set preferred admin langcode for user to non default.
$account->preferred_admin_langcode = $langcode;
$account->save();
$test = [
'language_negotiation' => [LanguageNegotiationUserAdmin::METHOD_ID, LanguageNegotiationSelected::METHOD_ID],
'path' => 'admin/config',
'expect' => $language_string,
'expected_method_id' => LanguageNegotiationUserAdmin::METHOD_ID,
'http_header' => [],
'message' => 'USER ADMIN > DEFAULT: defined preferred user admin language setting, the UI language is based on user setting',
];
$this->doRunTest($test);
// Go by session preference.
$language_negotiation_session_param = $this->randomMachineName();
$edit = ['language_negotiation_session_param' => $language_negotiation_session_param];
$this->drupalPostForm('admin/config/regional/language/detection/session', $edit, t('Save configuration'));
$tests = [
[
'language_negotiation' => [LanguageNegotiationSession::METHOD_ID],
'path' => "admin/config",
'expect' => $default_string,
'expected_method_id' => LanguageNegotiatorInterface::METHOD_ID,
'http_header' => $http_header_browser_fallback,
'message' => 'SESSION > DEFAULT: no language given, the UI language is default',
],
[
'language_negotiation' => [LanguageNegotiationSession::METHOD_ID],
'path' => 'admin/config',
'path_options' => ['query' => [$language_negotiation_session_param => $langcode]],
'expect' => $language_string,
'expected_method_id' => LanguageNegotiationSession::METHOD_ID,
'http_header' => $http_header_browser_fallback,
'message' => 'SESSION > DEFAULT: language given, UI language is determined by session language preference',
],
];
foreach ($tests as $test) {
$this->doRunTest($test);
}
}
protected function doRunTest($test) {
$test += ['path_options' => []];
if (!empty($test['language_negotiation'])) {
$method_weights = array_flip($test['language_negotiation']);
$this->container->get('language_negotiator')->saveConfiguration(LanguageInterface::TYPE_INTERFACE, $method_weights);
}
if (!empty($test['language_negotiation_url_part'])) {
$this->config('language.negotiation')
->set('url.source', $test['language_negotiation_url_part'])
->save();
}
if (!empty($test['language_test_domain'])) {
\Drupal::state()->set('language_test.domain', $test['language_test_domain']);
}
$this->container->get('language_manager')->reset();
$this->drupalGet($test['path'], $test['path_options'], $test['http_header']);
$this->assertText($test['expect'], $test['message']);
$this->assertText(t('Language negotiation method: @name', ['@name' => $test['expected_method_id']]));
}
/**
* Test URL language detection when the requested URL has no language.
*/
public function testUrlLanguageFallback() {
// Add the Italian language.
$langcode_browser_fallback = 'it';
ConfigurableLanguage::createFromLangcode($langcode_browser_fallback)->save();
$languages = $this->container->get('language_manager')->getLanguages();
// Enable the path prefix for the default language: this way any unprefixed
// URL must have a valid fallback value.
$edit = ['prefix[en]' => 'en'];
$this->drupalPostForm('admin/config/regional/language/detection/url', $edit, t('Save configuration'));
// Enable browser and URL language detection.
$edit = [
'language_interface[enabled][language-browser]' => TRUE,
'language_interface[enabled][language-url]' => TRUE,
'language_interface[weight][language-browser]' => -8,
'language_interface[weight][language-url]' => -10,
];
$this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
$this->drupalGet('admin/config/regional/language/detection');
// Enable the language switcher block.
$this->drupalPlaceBlock('language_block:' . LanguageInterface::TYPE_INTERFACE, ['id' => 'test_language_block']);
// Log out, because for anonymous users, the "active" class is set by PHP
// (which means we can easily test it here), whereas for authenticated users
// it is set by JavaScript.
$this->drupalLogout();
// Place a site branding block in the header region.
$this->drupalPlaceBlock('system_branding_block', ['region' => 'header']);
// Access the front page without specifying any valid URL language prefix
// and having as browser language preference a non-default language.
$http_header = ["Accept-Language: $langcode_browser_fallback;q=1"];
$language = new Language(['id' => '']);
$this->drupalGet('', ['language' => $language], $http_header);
// Check that the language switcher active link matches the given browser
// language.
$args = [':id' => 'block-test-language-block', ':url' => \Drupal::url('<front>') . $langcode_browser_fallback];
$fields = $this->xpath('//div[@id=:id]//a[@class="language-link is-active" and starts-with(@href, :url)]', $args);
$this->assertTrue($fields[0] == $languages[$langcode_browser_fallback]->getName(), 'The browser language is the URL active language');
// Check that URLs are rewritten using the given browser language.
$fields = $this->xpath('//div[@class="site-name"]/a[@rel="home" and @href=:url]', $args);
$this->assertTrue($fields[0] == 'Drupal', 'URLs are rewritten using the browser language.');
}
/**
* Tests URL handling when separate domains are used for multiple languages.
*/
public function testLanguageDomain() {
global $base_url;
// Get the current host URI we're running on.
$base_url_host = parse_url($base_url, PHP_URL_HOST);
// Add the Italian language.
ConfigurableLanguage::createFromLangcode('it')->save();
$languages = $this->container->get('language_manager')->getLanguages();
// Enable browser and URL language detection.
$edit = [
'language_interface[enabled][language-url]' => TRUE,
'language_interface[weight][language-url]' => -10,
];
$this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
// Do not allow blank domain.
$edit = [
'language_negotiation_url_part' => LanguageNegotiationUrl::CONFIG_DOMAIN,
'domain[en]' => '',
];
$this->drupalPostForm('admin/config/regional/language/detection/url', $edit, t('Save configuration'));
$this->assertText('The domain may not be left blank for English', 'The form does not allow blank domains.');
$this->rebuildContainer();
// Change the domain for the Italian language.
$edit = [
'language_negotiation_url_part' => LanguageNegotiationUrl::CONFIG_DOMAIN,
'domain[en]' => $base_url_host,
'domain[it]' => 'it.example.com',
];
$this->drupalPostForm('admin/config/regional/language/detection/url', $edit, t('Save configuration'));
$this->assertText('The configuration options have been saved', 'Domain configuration is saved.');
$this->rebuildContainer();
// Try to use an invalid domain.
$edit = [
'language_negotiation_url_part' => LanguageNegotiationUrl::CONFIG_DOMAIN,
'domain[en]' => $base_url_host,
'domain[it]' => 'it.example.com/',
];
$this->drupalPostForm('admin/config/regional/language/detection/url', $edit, t('Save configuration'));
$this->assertRaw(t('The domain for %language may only contain the domain name, not a trailing slash, protocol and/or port.', ['%language' => 'Italian']));
// Build the link we're going to test.
$link = 'it.example.com' . rtrim(base_path(), '/') . '/admin';
// Test URL in another language: http://it.example.com/admin.
// Base path gives problems on the testbot, so $correct_link is hard-coded.
// @see UrlAlterFunctionalTest::assertUrlOutboundAlter (path.test).
$italian_url = Url::fromRoute('system.admin', [], ['language' => $languages['it']])->toString();
$url_scheme = \Drupal::request()->isSecure() ? 'https://' : 'http://';
$correct_link = $url_scheme . $link;
$this->assertEqual($italian_url, $correct_link, format_string('The right URL (@url) in accordance with the chosen language', ['@url' => $italian_url]));
// Test HTTPS via options.
$italian_url = Url::fromRoute('system.admin', [], ['https' => TRUE, 'language' => $languages['it']])->toString();
$correct_link = 'https://' . $link;
$this->assertTrue($italian_url == $correct_link, format_string('The right HTTPS URL (via options) (@url) in accordance with the chosen language', ['@url' => $italian_url]));
// Test HTTPS via current URL scheme.
$request = Request::create('', 'GET', [], [], [], ['HTTPS' => 'on']);
$this->container->get('request_stack')->push($request);
$italian_url = Url::fromRoute('system.admin', [], ['language' => $languages['it']])->toString();
$correct_link = 'https://' . $link;
$this->assertTrue($italian_url == $correct_link, format_string('The right URL (via current URL scheme) (@url) in accordance with the chosen language', ['@url' => $italian_url]));
}
/**
* Tests persistence of negotiation settings for the content language type.
*/
public function testContentCustomization() {
// Customize content language settings from their defaults.
$edit = [
'language_content[configurable]' => TRUE,
'language_content[enabled][language-url]' => FALSE,
'language_content[enabled][language-session]' => TRUE,
];
$this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
// Check if configurability persisted.
$config = $this->config('language.types');
$this->assertTrue(in_array('language_interface', $config->get('configurable')), 'Interface language is configurable.');
$this->assertTrue(in_array('language_content', $config->get('configurable')), 'Content language is configurable.');
// Ensure configuration was saved.
$this->assertFalse(array_key_exists('language-url', $config->get('negotiation.language_content.enabled')), 'URL negotiation is not enabled for content.');
$this->assertTrue(array_key_exists('language-session', $config->get('negotiation.language_content.enabled')), 'Session negotiation is enabled for content.');
}
/**
* Tests if the language switcher block gets deleted when a language type has been made not configurable.
*/
public function testDisableLanguageSwitcher() {
$block_id = 'test_language_block';
// Enable the language switcher block.
$this->drupalPlaceBlock('language_block:' . LanguageInterface::TYPE_CONTENT, ['id' => $block_id]);
// Check if the language switcher block has been created.
$block = Block::load($block_id);
$this->assertTrue($block, 'Language switcher block was created.');
// Make sure language_content is not configurable.
$edit = [
'language_content[configurable]' => FALSE,
];
$this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
$this->assertResponse(200);
// Check if the language switcher block has been removed.
$block = Block::load($block_id);
$this->assertFalse($block, 'Language switcher block was removed.');
}
}

View file

@ -1,159 +0,0 @@
<?php
namespace Drupal\language\Tests;
use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Url;
use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl;
use Drupal\simpletest\WebTestBase;
use Symfony\Component\HttpFoundation\Request;
/**
* Tests that URL rewriting works as expected.
*
* @group language
*/
class LanguageUrlRewritingTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['language', 'language_test'];
/**
* An user with permissions to administer languages.
*
* @var \Drupal\user\UserInterface
*/
protected $webUser;
protected function setUp() {
parent::setUp();
// Create and log in user.
$this->webUser = $this->drupalCreateUser(['administer languages', 'access administration pages']);
$this->drupalLogin($this->webUser);
// Install French language.
$edit = [];
$edit['predefined_langcode'] = 'fr';
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
// Enable URL language detection and selection.
$edit = ['language_interface[enabled][language-url]' => 1];
$this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
// Check that drupalSettings contains path prefix.
$this->drupalGet('fr/admin/config/regional/language/detection');
$this->assertRaw('"pathPrefix":"fr\/"', 'drupalSettings path prefix contains language code.');
}
/**
* Check that non-installed languages are not considered.
*/
public function testUrlRewritingEdgeCases() {
// Check URL rewriting with a non-installed language.
$non_existing = new Language(['id' => $this->randomMachineName()]);
$this->checkUrl($non_existing, 'Path language is ignored if language is not installed.', 'URL language negotiation does not work with non-installed languages');
// Check that URL rewriting is not applied to subrequests.
$this->drupalGet('language_test/subrequest');
$this->assertText($this->webUser->getUsername(), 'Page correctly retrieved');
}
/**
* Check URL rewriting for the given language.
*
* The test is performed with a fixed URL (the default front page) to simply
* check that language prefixes are not added to it and that the prefixed URL
* is actually not working.
*
* @param \Drupal\Core\Language\LanguageInterface $language
* The language object.
* @param string $message1
* Message to display in assertion that language prefixes are not added.
* @param string $message2
* The message to display confirming prefixed URL is not working.
*/
private function checkUrl(LanguageInterface $language, $message1, $message2) {
$options = ['language' => $language, 'script' => ''];
$base_path = trim(base_path(), '/');
$rewritten_path = trim(str_replace($base_path, '', \Drupal::url('<front>', [], $options)), '/');
$segments = explode('/', $rewritten_path, 2);
$prefix = $segments[0];
$path = isset($segments[1]) ? $segments[1] : $prefix;
// If the rewritten URL has not a language prefix we pick a random prefix so
// we can always check the prefixed URL.
$prefixes = language_negotiation_url_prefixes();
$stored_prefix = isset($prefixes[$language->getId()]) ? $prefixes[$language->getId()] : $this->randomMachineName();
if ($this->assertNotEqual($stored_prefix, $prefix, $message1)) {
$prefix = $stored_prefix;
}
$this->drupalGet("$prefix/$path");
$this->assertResponse(404, $message2);
}
/**
* Check URL rewriting when using a domain name and a non-standard port.
*/
public function testDomainNameNegotiationPort() {
global $base_url;
$language_domain = 'example.fr';
// Get the current host URI we're running on.
$base_url_host = parse_url($base_url, PHP_URL_HOST);
$edit = [
'language_negotiation_url_part' => LanguageNegotiationUrl::CONFIG_DOMAIN,
'domain[en]' => $base_url_host,
'domain[fr]' => $language_domain
];
$this->drupalPostForm('admin/config/regional/language/detection/url', $edit, t('Save configuration'));
// Rebuild the container so that the new language gets picked up by services
// that hold the list of languages.
$this->rebuildContainer();
// Enable domain configuration.
$this->config('language.negotiation')
->set('url.source', LanguageNegotiationUrl::CONFIG_DOMAIN)
->save();
// Reset static caching.
$this->container->get('language_manager')->reset();
// In case index.php is part of the URLs, we need to adapt the asserted
// URLs as well.
$index_php = strpos(\Drupal::url('<front>', [], ['absolute' => TRUE]), 'index.php') !== FALSE;
$request = Request::createFromGlobals();
$server = $request->server->all();
$request = $this->prepareRequestForGenerator(TRUE, ['HTTP_HOST' => $server['HTTP_HOST'] . ':88']);
// Create an absolute French link.
$language = \Drupal::languageManager()->getLanguage('fr');
$url = Url::fromRoute('<front>', [], [
'absolute' => TRUE,
'language' => $language,
])->toString();
$expected = ($index_php ? 'http://example.fr:88/index.php' : 'http://example.fr:88') . rtrim(base_path(), '/') . '/';
$this->assertEqual($url, $expected, 'The right port is used.');
// If we set the port explicitly, it should not be overridden.
$url = Url::fromRoute('<front>', [], [
'absolute' => TRUE,
'language' => $language,
'base_url' => $request->getBaseUrl() . ':90',
])->toString();
$expected = $index_php ? 'http://example.fr:90/index.php' : 'http://example.fr:90' . rtrim(base_path(), '/') . '/';
$this->assertEqual($url, $expected, 'A given port is not overridden.');
}
}