Mercurial > hg > cmmr2012-drupal-site
comparison core/modules/content_translation/content_translation.module @ 5:12f9dff5fda9 tip
Update to Drupal core 8.7.1
author | Chris Cannam |
---|---|
date | Thu, 09 May 2019 15:34:47 +0100 |
parents | a9cd425dd02b |
children |
comparison
equal
deleted
inserted
replaced
4:a9cd425dd02b | 5:12f9dff5fda9 |
---|---|
3 /** | 3 /** |
4 * @file | 4 * @file |
5 * Allows entities to be translated into different languages. | 5 * Allows entities to be translated into different languages. |
6 */ | 6 */ |
7 | 7 |
8 use Drupal\Core\Url; | |
8 use Drupal\content_translation\BundleTranslationSettingsInterface; | 9 use Drupal\content_translation\BundleTranslationSettingsInterface; |
9 use Drupal\content_translation\ContentTranslationManager; | 10 use Drupal\content_translation\ContentTranslationManager; |
10 use Drupal\Core\Access\AccessResult; | 11 use Drupal\Core\Access\AccessResult; |
11 use Drupal\Core\Entity\ContentEntityFormInterface; | 12 use Drupal\Core\Entity\ContentEntityFormInterface; |
12 use Drupal\Core\Entity\ContentEntityInterface; | 13 use Drupal\Core\Entity\ContentEntityInterface; |
14 use Drupal\Core\Entity\EntityTypeInterface; | 15 use Drupal\Core\Entity\EntityTypeInterface; |
15 use Drupal\Core\Form\FormStateInterface; | 16 use Drupal\Core\Form\FormStateInterface; |
16 use Drupal\Core\Language\LanguageInterface; | 17 use Drupal\Core\Language\LanguageInterface; |
17 use Drupal\Core\Routing\RouteMatchInterface; | 18 use Drupal\Core\Routing\RouteMatchInterface; |
18 use Drupal\Core\StringTranslation\TranslatableMarkup; | 19 use Drupal\Core\StringTranslation\TranslatableMarkup; |
20 use Drupal\language\ContentLanguageSettingsInterface; | |
19 | 21 |
20 /** | 22 /** |
21 * Implements hook_help(). | 23 * Implements hook_help(). |
22 */ | 24 */ |
23 function content_translation_help($route_name, RouteMatchInterface $route_match) { | 25 function content_translation_help($route_name, RouteMatchInterface $route_match) { |
24 switch ($route_name) { | 26 switch ($route_name) { |
25 case 'help.page.content_translation': | 27 case 'help.page.content_translation': |
26 $output = ''; | 28 $output = ''; |
27 $output .= '<h3>' . t('About') . '</h3>'; | 29 $output .= '<h3>' . t('About') . '</h3>'; |
28 $output .= '<p>' . t('The Content Translation module allows you to translate content, comments, custom blocks, taxonomy terms, users and other <a href=":field_help" title="Field module help, with background on content entities">content entities</a>. Together with the modules <a href=":language">Language</a>, <a href=":config-trans">Configuration Translation</a>, and <a href=":locale">Interface Translation</a>, it allows you to build multilingual websites. For more information, see the <a href=":translation-entity">online documentation for the Content Translation module</a>.', [':locale' => (\Drupal::moduleHandler()->moduleExists('locale')) ? \Drupal::url('help.page', ['name' => 'locale']) : '#', ':config-trans' => (\Drupal::moduleHandler()->moduleExists('config_translation')) ? \Drupal::url('help.page', ['name' => 'config_translation']) : '#', ':language' => \Drupal::url('help.page', ['name' => 'language']), ':translation-entity' => 'https://www.drupal.org/documentation/modules/translation', ':field_help' => \Drupal::url('help.page', ['name' => 'field'])]) . '</p>'; | 30 $output .= '<p>' . t('The Content Translation module allows you to translate content, comments, custom blocks, taxonomy terms, users and other <a href=":field_help" title="Field module help, with background on content entities">content entities</a>. Together with the modules <a href=":language">Language</a>, <a href=":config-trans">Configuration Translation</a>, and <a href=":locale">Interface Translation</a>, it allows you to build multilingual websites. For more information, see the <a href=":translation-entity">online documentation for the Content Translation module</a>.', [':locale' => (\Drupal::moduleHandler()->moduleExists('locale')) ? Url::fromRoute('help.page', ['name' => 'locale'])->toString() : '#', ':config-trans' => (\Drupal::moduleHandler()->moduleExists('config_translation')) ? Url::fromRoute('help.page', ['name' => 'config_translation'])->toString() : '#', ':language' => Url::fromRoute('help.page', ['name' => 'language'])->toString(), ':translation-entity' => 'https://www.drupal.org/documentation/modules/translation', ':field_help' => Url::fromRoute('help.page', ['name' => 'field'])->toString()]) . '</p>'; |
29 $output .= '<h3>' . t('Uses') . '</h3>'; | 31 $output .= '<h3>' . t('Uses') . '</h3>'; |
30 $output .= '<dl>'; | 32 $output .= '<dl>'; |
31 $output .= '<dt>' . t('Enabling translation') . '</dt>'; | 33 $output .= '<dt>' . t('Enabling translation') . '</dt>'; |
32 $output .= '<dd>' . t('In order to translate content, the website must have at least two <a href=":url">languages</a>. When that is the case, you can enable translation for the desired content entities on the <a href=":translation-entity">Content language</a> page. When enabling translation you can choose the default language for content and decide whether to show the language selection field on the content editing forms.', [':url' => \Drupal::url('entity.configurable_language.collection'), ':translation-entity' => \Drupal::url('language.content_settings_page'), ':language-help' => \Drupal::url('help.page', ['name' => 'language'])]) . '</dd>'; | 34 $output .= '<dd>' . t('In order to translate content, the website must have at least two <a href=":url">languages</a>. When that is the case, you can enable translation for the desired content entities on the <a href=":translation-entity">Content language</a> page. When enabling translation you can choose the default language for content and decide whether to show the language selection field on the content editing forms.', [':url' => Url::fromRoute('entity.configurable_language.collection')->toString(), ':translation-entity' => Url::fromRoute('language.content_settings_page')->toString(), ':language-help' => Url::fromRoute('help.page', ['name' => 'language'])->toString()]) . '</dd>'; |
33 $output .= '<dt>' . t('Enabling field translation') . '</dt>'; | 35 $output .= '<dt>' . t('Enabling field translation') . '</dt>'; |
34 $output .= '<dd>' . t('You can define which fields of a content entity can be translated. For example, you might want to translate the title and body field while leaving the image field untranslated. If you exclude a field from being translated, it will still show up in the content editing form, but any changes made to that field will be applied to <em>all</em> translations of that content.') . '</dd>'; | 36 $output .= '<dd>' . t('You can define which fields of a content entity can be translated. For example, you might want to translate the title and body field while leaving the image field untranslated. If you exclude a field from being translated, it will still show up in the content editing form, but any changes made to that field will be applied to <em>all</em> translations of that content.') . '</dd>'; |
35 $output .= '<dt>' . t('Translating content') . '</dt>'; | 37 $output .= '<dt>' . t('Translating content') . '</dt>'; |
36 $output .= '<dd>' . t('If translation is enabled you can translate a content entity via the Translate tab (or Translate link). The Translations page of a content entity gives an overview of the translation status for the current content and lets you add, edit, and delete its translations. This process is similar for every translatable content entity on your site.') . '</dd>'; | 38 $output .= '<dd>' . t('If translation is enabled you can translate a content entity via the Translate tab (or Translate link). The Translations page of a content entity gives an overview of the translation status for the current content and lets you add, edit, and delete its translations. This process is similar for every translatable content entity on your site.') . '</dd>'; |
37 $output .= '<dt>' . t('Changing the source language for a translation') . '</dt>'; | 39 $output .= '<dt>' . t('Changing the source language for a translation') . '</dt>'; |
42 return $output; | 44 return $output; |
43 | 45 |
44 case 'language.content_settings_page': | 46 case 'language.content_settings_page': |
45 $output = ''; | 47 $output = ''; |
46 if (!\Drupal::languageManager()->isMultilingual()) { | 48 if (!\Drupal::languageManager()->isMultilingual()) { |
47 $output .= '<p>' . t('Before you can translate content, there must be at least two languages added on the <a href=":url">languages administration</a> page.', [':url' => \Drupal::url('entity.configurable_language.collection')]) . '</p>'; | 49 $output .= '<p>' . t('Before you can translate content, there must be at least two languages added on the <a href=":url">languages administration</a> page.', [':url' => Url::fromRoute('entity.configurable_language.collection')->toString()]) . '</p>'; |
48 } | 50 } |
49 return $output; | 51 return $output; |
50 } | 52 } |
51 } | 53 } |
52 | 54 |
168 $entity_type->addConstraint('ContentTranslationSynchronizedFields'); | 170 $entity_type->addConstraint('ContentTranslationSynchronizedFields'); |
169 } | 171 } |
170 } | 172 } |
171 | 173 |
172 /** | 174 /** |
175 * Implements hook_ENTITY_TYPE_insert(). | |
176 * | |
177 * Installs Content Translation's field storage definitions for the target | |
178 * entity type, if required. | |
179 * | |
180 * Also clears the bundle information cache so that the bundle's translatability | |
181 * will be set properly. | |
182 * | |
183 * @see content_translation_entity_bundle_info_alter() | |
184 * @see \Drupal\content_translation\ContentTranslationManager::isEnabled() | |
185 */ | |
186 function content_translation_language_content_settings_insert(ContentLanguageSettingsInterface $settings) { | |
187 if ($settings->getThirdPartySetting('content_translation', 'enabled', FALSE)) { | |
188 _content_translation_install_field_storage_definitions($settings->getTargetEntityTypeId()); | |
189 } | |
190 | |
191 \Drupal::service('entity_type.bundle.info')->clearCachedBundles(); | |
192 } | |
193 | |
194 /** | |
195 * Implements hook_ENTITY_TYPE_update(). | |
196 * | |
197 * Installs Content Translation's field storage definitions for the target | |
198 * entity type, if required. | |
199 * | |
200 * Also clears the bundle information cache so that the bundle's translatability | |
201 * will be changed properly. | |
202 * | |
203 * @see content_translation_entity_bundle_info_alter() | |
204 * @see \Drupal\content_translation\ContentTranslationManager::isEnabled() | |
205 */ | |
206 function content_translation_language_content_settings_update(ContentLanguageSettingsInterface $settings) { | |
207 $original_settings = $settings->original; | |
208 if ($settings->getThirdPartySetting('content_translation', 'enabled', FALSE) | |
209 && !$original_settings->getThirdPartySetting('content_translation', 'enabled', FALSE) | |
210 ) { | |
211 _content_translation_install_field_storage_definitions($settings->getTargetEntityTypeId()); | |
212 } | |
213 \Drupal::service('entity_type.bundle.info')->clearCachedBundles(); | |
214 } | |
215 | |
216 /** | |
217 * Installs Content Translation's fields for a given entity type. | |
218 * | |
219 * @param string $entity_type_id | |
220 * The entity type ID. | |
221 * | |
222 * @todo Generalize this code in https://www.drupal.org/node/2346013. | |
223 */ | |
224 function _content_translation_install_field_storage_definitions($entity_type_id) { | |
225 /** @var \Drupal\Core\Entity\EntityFieldManagerInterface $field_manager */ | |
226 $field_manager = \Drupal::service('entity_field.manager'); | |
227 /** @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface $schema_repository */ | |
228 $schema_repository = \Drupal::service('entity.last_installed_schema.repository'); | |
229 $definition_update_manager = \Drupal::entityDefinitionUpdateManager(); | |
230 | |
231 $field_manager->useCaches(FALSE); | |
232 $storage_definitions = $field_manager->getFieldStorageDefinitions($entity_type_id); | |
233 $field_manager->useCaches(TRUE); | |
234 $installed_storage_definitions = $schema_repository->getLastInstalledFieldStorageDefinitions($entity_type_id); | |
235 foreach (array_diff_key($storage_definitions, $installed_storage_definitions) as $storage_definition) { | |
236 /** @var \Drupal\Core\Field\FieldStorageDefinitionInterface $storage_definition */ | |
237 if ($storage_definition->getProvider() == 'content_translation') { | |
238 $definition_update_manager->installFieldStorageDefinition($storage_definition->getName(), $entity_type_id, 'content_translation', $storage_definition); | |
239 } | |
240 } | |
241 } | |
242 | |
243 /** | |
173 * Implements hook_entity_bundle_info_alter(). | 244 * Implements hook_entity_bundle_info_alter(). |
174 */ | 245 */ |
175 function content_translation_entity_bundle_info_alter(&$bundles) { | 246 function content_translation_entity_bundle_info_alter(&$bundles) { |
176 /** @var \Drupal\content_translation\ContentTranslationManagerInterface $content_translation_manager */ | 247 /** @var \Drupal\content_translation\ContentTranslationManagerInterface $content_translation_manager */ |
177 $content_translation_manager = \Drupal::service('content_translation.manager'); | 248 $content_translation_manager = \Drupal::service('content_translation.manager'); |
197 /** @var \Drupal\content_translation\ContentTranslationManagerInterface $manager */ | 268 /** @var \Drupal\content_translation\ContentTranslationManagerInterface $manager */ |
198 $manager = \Drupal::service('content_translation.manager'); | 269 $manager = \Drupal::service('content_translation.manager'); |
199 $entity_type_id = $entity_type->id(); | 270 $entity_type_id = $entity_type->id(); |
200 if ($manager->isSupported($entity_type_id)) { | 271 if ($manager->isSupported($entity_type_id)) { |
201 $definitions = $manager->getTranslationHandler($entity_type_id)->getFieldDefinitions(); | 272 $definitions = $manager->getTranslationHandler($entity_type_id)->getFieldDefinitions(); |
202 $installed_storage_definitions = \Drupal::entityManager()->getLastInstalledFieldStorageDefinitions($entity_type_id); | 273 $installed_storage_definitions = \Drupal::service('entity.last_installed_schema.repository')->getLastInstalledFieldStorageDefinitions($entity_type_id); |
203 // We return metadata storage fields whenever content translation is enabled | 274 // We return metadata storage fields whenever content translation is enabled |
204 // or it was enabled before, so that we keep translation metadata around | 275 // or it was enabled before, so that we keep translation metadata around |
205 // when translation is disabled. | 276 // when translation is disabled. |
206 // @todo Re-evaluate this approach and consider removing field storage | 277 // @todo Re-evaluate this approach and consider removing field storage |
207 // definitions and the related field data if the entity type has no bundle | 278 // definitions and the related field data if the entity type has no bundle |
248 function content_translation_entity_operation(EntityInterface $entity) { | 319 function content_translation_entity_operation(EntityInterface $entity) { |
249 $operations = []; | 320 $operations = []; |
250 if ($entity->hasLinkTemplate('drupal:content-translation-overview') && content_translation_translate_access($entity)->isAllowed()) { | 321 if ($entity->hasLinkTemplate('drupal:content-translation-overview') && content_translation_translate_access($entity)->isAllowed()) { |
251 $operations['translate'] = [ | 322 $operations['translate'] = [ |
252 'title' => t('Translate'), | 323 'title' => t('Translate'), |
253 'url' => $entity->urlInfo('drupal:content-translation-overview'), | 324 'url' => $entity->toUrl('drupal:content-translation-overview'), |
254 'weight' => 50, | 325 'weight' => 50, |
255 ]; | 326 ]; |
256 } | 327 } |
257 return $operations; | 328 return $operations; |
258 } | 329 } |
414 '#access' => $field->getFieldStorageDefinition()->isTranslatable(), | 485 '#access' => $field->getFieldStorageDefinition()->isTranslatable(), |
415 ]; | 486 ]; |
416 | 487 |
417 // Provide helpful pointers for administrators. | 488 // Provide helpful pointers for administrators. |
418 if (\Drupal::currentUser()->hasPermission('administer content translation') && !$bundle_is_translatable) { | 489 if (\Drupal::currentUser()->hasPermission('administer content translation') && !$bundle_is_translatable) { |
419 $toggle_url = \Drupal::url('language.content_settings_page', [], [ | 490 $toggle_url = Url::fromRoute('language.content_settings_page', [], [ |
420 'query' => \Drupal::destination()->getAsArray(), | 491 'query' => \Drupal::destination()->getAsArray(), |
421 ]); | 492 ])->toString(); |
422 $form['translatable']['#description'] = t('To configure translation for this field, <a href=":language-settings-url">enable language support</a> for this type.', [ | 493 $form['translatable']['#description'] = t('To configure translation for this field, <a href=":language-settings-url">enable language support</a> for this type.', [ |
423 ':language-settings-url' => $toggle_url, | 494 ':language-settings-url' => $toggle_url, |
424 ]); | 495 ]); |
425 } | 496 } |
426 | 497 |
436 | 507 |
437 /** | 508 /** |
438 * Implements hook_entity_presave(). | 509 * Implements hook_entity_presave(). |
439 */ | 510 */ |
440 function content_translation_entity_presave(EntityInterface $entity) { | 511 function content_translation_entity_presave(EntityInterface $entity) { |
441 if ($entity instanceof ContentEntityInterface && $entity->isTranslatable() && !$entity->isNew()) { | 512 if ($entity instanceof ContentEntityInterface && $entity->isTranslatable() && !$entity->isNew() && isset($entity->original)) { |
442 /** @var \Drupal\content_translation\ContentTranslationManagerInterface $manager */ | 513 /** @var \Drupal\content_translation\ContentTranslationManagerInterface $manager */ |
443 $manager = \Drupal::service('content_translation.manager'); | 514 $manager = \Drupal::service('content_translation.manager'); |
444 if (!$manager->isEnabled($entity->getEntityTypeId(), $entity->bundle())) { | 515 if (!$manager->isEnabled($entity->getEntityTypeId(), $entity->bundle())) { |
445 return; | 516 return; |
446 } | |
447 // If we are creating a new translation we need to use the source language | |
448 // as original language, since source values are the only ones available to | |
449 // compare against. | |
450 if (!isset($entity->original)) { | |
451 $entity->original = \Drupal::entityTypeManager() | |
452 ->getStorage($entity->entityType())->loadUnchanged($entity->id()); | |
453 } | 517 } |
454 $langcode = $entity->language()->getId(); | 518 $langcode = $entity->language()->getId(); |
455 $source_langcode = !$entity->original->hasTranslation($langcode) ? $manager->getTranslationMetadata($entity)->getSource() : NULL; | 519 $source_langcode = !$entity->original->hasTranslation($langcode) ? $manager->getTranslationMetadata($entity)->getSource() : NULL; |
456 \Drupal::service('content_translation.synchronizer')->synchronizeFields($entity, $langcode, $source_langcode); | 520 \Drupal::service('content_translation.synchronizer')->synchronizeFields($entity, $langcode, $source_langcode); |
457 } | 521 } |
565 $context = $form_state->get(['language', $key]); | 629 $context = $form_state->get(['language', $key]); |
566 $enabled = $form_state->getValue([$key, 'content_translation']); | 630 $enabled = $form_state->getValue([$key, 'content_translation']); |
567 | 631 |
568 if (\Drupal::service('content_translation.manager')->isEnabled($context['entity_type'], $context['bundle']) != $enabled) { | 632 if (\Drupal::service('content_translation.manager')->isEnabled($context['entity_type'], $context['bundle']) != $enabled) { |
569 \Drupal::service('content_translation.manager')->setEnabled($context['entity_type'], $context['bundle'], $enabled); | 633 \Drupal::service('content_translation.manager')->setEnabled($context['entity_type'], $context['bundle'], $enabled); |
570 \Drupal::entityManager()->clearCachedDefinitions(); | 634 \Drupal::entityTypeManager()->clearCachedDefinitions(); |
571 \Drupal::service('router.builder')->setRebuildNeeded(); | 635 \Drupal::service('router.builder')->setRebuildNeeded(); |
572 } | 636 } |
573 } | 637 } |
574 | 638 |
575 /** | 639 /** |