3 namespace Drupal\language\Form;
5 use Drupal\Core\Config\ConfigFactoryInterface;
6 use Drupal\Core\Form\ConfigFormBase;
7 use Drupal\Core\Form\FormStateInterface;
9 use Drupal\language\ConfigurableLanguageManagerInterface;
10 use Symfony\Component\DependencyInjection\ContainerInterface;
13 * Configure the browser language negotiation method for this site.
15 class NegotiationBrowserForm extends ConfigFormBase {
18 * The configurable language manager.
20 * @var \Drupal\language\ConfigurableLanguageManagerInterface
22 protected $languageManager;
27 public function __construct(ConfigFactoryInterface $config_factory, ConfigurableLanguageManagerInterface $language_manager) {
28 parent::__construct($config_factory);
29 $this->languageManager = $language_manager;
35 public static function create(ContainerInterface $container) {
37 $container->get('config.factory'),
38 $container->get('language_manager')
45 public function getFormId() {
46 return 'language_negotiation_configure_browser_form';
52 protected function getEditableConfigNames() {
53 return ['language.mappings'];
59 public function buildForm(array $form, FormStateInterface $form_state) {
62 // Initialize a language list to the ones available, including English.
63 $languages = $this->languageManager->getLanguages();
65 $existing_languages = [];
66 foreach ($languages as $langcode => $language) {
67 $existing_languages[$langcode] = $language->getName();
70 // If we have no languages available, present the list of predefined languages
71 // only. If we do have already added languages, set up two option groups with
72 // the list of existing and then predefined languages.
73 if (empty($existing_languages)) {
74 $language_options = $this->languageManager->getStandardLanguageListWithoutConfigured();
78 (string) $this->t('Existing languages') => $existing_languages,
79 (string) $this->t('Languages not yet added') => $this->languageManager->getStandardLanguageListWithoutConfigured(),
86 $this->t('Browser language code'),
87 $this->t('Site language'),
88 $this->t('Operations'),
90 '#attributes' => ['id' => 'language-negotiation-browser'],
91 '#empty' => $this->t('No browser language mappings available.'),
94 $mappings = $this->language_get_browser_drupal_langcode_mappings();
95 foreach ($mappings as $browser_langcode => $drupal_langcode) {
96 $form['mappings'][$browser_langcode] = [
97 'browser_langcode' => [
98 '#title' => $this->t('Browser language code'),
99 '#title_display' => 'invisible',
100 '#type' => 'textfield',
101 '#default_value' => $browser_langcode,
105 'drupal_langcode' => [
106 '#title' => $this->t('Site language'),
107 '#title_display' => 'invisible',
109 '#options' => $language_options,
110 '#default_value' => $drupal_langcode,
114 // Operations column.
115 $form['mappings'][$browser_langcode]['operations'] = [
116 '#type' => 'operations',
119 $form['mappings'][$browser_langcode]['operations']['#links']['delete'] = [
120 'title' => $this->t('Delete'),
121 'url' => Url::fromRoute('language.negotiation_browser_delete', ['browser_langcode' => $browser_langcode]),
126 $form['new_mapping'] = [
127 '#type' => 'details',
128 '#title' => $this->t('Add a new mapping'),
131 $form['new_mapping']['browser_langcode'] = [
132 '#type' => 'textfield',
133 '#title' => $this->t('Browser language code'),
134 '#description' => $this->t('Use language codes as <a href=":w3ctags">defined by the W3C</a> for interoperability. <em>Examples: "en", "en-gb" and "zh-hant".</em>', [':w3ctags' => 'http://www.w3.org/International/articles/language-tags/']),
137 $form['new_mapping']['drupal_langcode'] = [
139 '#title' => $this->t('Site language'),
140 '#options' => $language_options,
143 return parent::buildForm($form, $form_state);
149 public function validateForm(array &$form, FormStateInterface $form_state) {
150 // Array to check if all browser language codes are unique.
153 // Check all mappings.
154 if ($form_state->hasValue('mappings')) {
155 $mappings = $form_state->getValue('mappings');
156 foreach ($mappings as $key => $data) {
157 // Make sure browser_langcode is unique.
158 if (array_key_exists($data['browser_langcode'], $unique_values)) {
159 $form_state->setErrorByName('mappings][new_mapping][browser_langcode', $this->t('Browser language codes must be unique.'));
161 elseif (preg_match('/[^a-z\-]/', $data['browser_langcode'])) {
162 $form_state->setErrorByName('mappings][new_mapping][browser_langcode', $this->t('Browser language codes can only contain lowercase letters and a hyphen(-).'));
164 $unique_values[$data['browser_langcode']] = $data['drupal_langcode'];
168 // Check new mapping.
169 $data = $form_state->getValue('new_mapping');
170 if (!empty($data['browser_langcode'])) {
171 // Make sure browser_langcode is unique.
172 if (array_key_exists($data['browser_langcode'], $unique_values)) {
173 $form_state->setErrorByName('mappings][' . $key . '][browser_langcode', $this->t('Browser language codes must be unique.'));
175 elseif (preg_match('/[^a-z\-]/', $data['browser_langcode'])) {
176 $form_state->setErrorByName('mappings][' . $key . '][browser_langcode', $this->t('Browser language codes can only contain lowercase letters and a hyphen(-).'));
178 $unique_values[$data['browser_langcode']] = $data['drupal_langcode'];
181 $form_state->set('mappings', $unique_values);
187 public function submitForm(array &$form, FormStateInterface $form_state) {
188 $mappings = $form_state->get('mappings');
189 if (!empty($mappings)) {
190 $config = $this->config('language.mappings');
191 $config->setData(['map' => $mappings]);
195 parent::submitForm($form, $form_state);
199 * Retrieves the browser's langcode mapping configuration array.
202 * The browser's langcode mapping configuration array.
204 protected function language_get_browser_drupal_langcode_mappings() {
205 $config = $this->config('language.mappings');
206 if ($config->isNew()) {
209 return $config->get('map');