Issue #3421017 by mohit_aghera, smustgrave: Convert LanguageNegotiation plugin discovery to attributes

merge-requests/6777/merge
Alex Pott 2024-03-02 10:51:29 +00:00
parent e32a8fd37c
commit 2001751fd9
No known key found for this signature in database
GPG Key ID: BDA67E7EE836E5CE
13 changed files with 167 additions and 92 deletions

View File

@ -0,0 +1,54 @@
<?php
namespace Drupal\language\Attribute;
use Drupal\Component\Plugin\Attribute\Plugin;
use Drupal\Core\StringTranslation\TranslatableMarkup;
/**
* Defines a language negotiation attribute object.
*
* Plugin Namespace: Plugin\LanguageNegotiation
*
* For a working example, see
* \Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationBrowser.
*
* @see \Drupal\language\LanguageNegotiator
* @see \Drupal\language\LanguageNegotiationMethodManager
* @see \Drupal\language\LanguageNegotiationMethodInterface
* @see hook_language_negotiation_info_alter()
* @see plugin_api
*/
#[\Attribute(\Attribute::TARGET_CLASS)]
class LanguageNegotiation extends Plugin {
/**
* Constructs an LanguageNegotiation attribute.
*
* @param string $id
* The language negotiation plugin ID.
* @param \Drupal\Core\StringTranslation\TranslatableMarkup $name
* The human-readable name of the language negotiation plugin.
* @param string[]|null $types
* An array of language types, such as the
* \Drupal\Core\Language\LanguageInterface::TYPE_* constants.
* If a language negotiation plugin does not specify which language types it
* should be used with, it will be available for all the configurable
* language types.
* @param int $weight
* The default weight of the language negotiation plugin.
* @param \Drupal\Core\StringTranslation\TranslatableMarkup|null $description
* The description of the language negotiation plugin.
* @param string|null $config_route_name
* (optional) The route pointing to the plugin's configuration page.
*/
public function __construct(
public readonly string $id,
public readonly TranslatableMarkup $name,
public readonly ?array $types = NULL,
public readonly int $weight = 0,
public readonly ?TranslatableMarkup $description = NULL,
public readonly ?string $config_route_name = NULL,
) {}
}

View File

@ -5,6 +5,7 @@ namespace Drupal\language;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Plugin\DefaultPluginManager;
use Drupal\language\Attribute\LanguageNegotiation;
/**
* Manages language negotiation methods.
@ -23,7 +24,7 @@ class LanguageNegotiationMethodManager extends DefaultPluginManager {
* An object that implements ModuleHandlerInterface
*/
public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
parent::__construct('Plugin/LanguageNegotiation', $namespaces, $module_handler, 'Drupal\language\LanguageNegotiationMethodInterface', 'Drupal\language\Annotation\LanguageNegotiation');
parent::__construct('Plugin/LanguageNegotiation', $namespaces, $module_handler, 'Drupal\language\LanguageNegotiationMethodInterface', LanguageNegotiation::class, 'Drupal\language\Annotation\LanguageNegotiation');
$this->cacheBackend = $cache_backend;
$this->setCacheBackend($cache_backend, 'language_negotiation_plugins');
$this->alterInfo('language_negotiation_info');

View File

@ -4,21 +4,22 @@ namespace Drupal\language\Plugin\LanguageNegotiation;
use Drupal\Component\Utility\UserAgent;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\language\Attribute\LanguageNegotiation;
use Drupal\language\LanguageNegotiationMethodBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Class for identifying language from the browser Accept-language HTTP header.
*
* @LanguageNegotiation(
* id = \Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationBrowser::METHOD_ID,
* weight = -2,
* name = @Translation("Browser"),
* description = @Translation("Language from the browser's language settings."),
* config_route_name = "language.negotiation_browser"
* )
*/
#[LanguageNegotiation(
id: LanguageNegotiationBrowser::METHOD_ID,
name: new TranslatableMarkup('Browser'),
weight: -2,
description: new TranslatableMarkup("Language from the browser's language settings."),
config_route_name: 'language.negotiation_browser'
)]
class LanguageNegotiationBrowser extends LanguageNegotiationMethodBase implements ContainerFactoryPluginInterface {
/**

View File

@ -4,10 +4,13 @@ namespace Drupal\language\Plugin\LanguageNegotiation;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Url;
use Drupal\language\Attribute\LanguageNegotiation;
use Drupal\language\LanguageNegotiationMethodBase;
use Drupal\language\LanguageSwitcherInterface;
use Drupal\Core\Routing\RouteObjectInterface;
@ -17,15 +20,14 @@ use Symfony\Component\Routing\Route;
/**
* Class for identifying the content translation language.
*
* @LanguageNegotiation(
* id = Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationContentEntity::METHOD_ID,
* types = {Drupal\Core\Language\LanguageInterface::TYPE_CONTENT},
* weight = -9,
* name = @Translation("Content language"),
* description = @Translation("Determines the content language from the request parameter named 'language_content_entity'."),
* )
*/
#[LanguageNegotiation(
id: LanguageNegotiationContentEntity::METHOD_ID,
name: new TranslatableMarkup('Content language'),
types: [LanguageInterface::TYPE_CONTENT],
weight: -9,
description: new TranslatableMarkup("Determines the content language from the request parameter named 'language_content_entity'.")
)]
class LanguageNegotiationContentEntity extends LanguageNegotiationMethodBase implements OutboundPathProcessorInterface, LanguageSwitcherInterface, ContainerFactoryPluginInterface {
/**

View File

@ -2,20 +2,21 @@
namespace Drupal\language\Plugin\LanguageNegotiation;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\language\Attribute\LanguageNegotiation;
use Drupal\language\LanguageNegotiationMethodBase;
use Symfony\Component\HttpFoundation\Request;
/**
* Class for identifying language from a selected language.
*
* @LanguageNegotiation(
* id = Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationSelected::METHOD_ID,
* weight = 12,
* name = @Translation("Selected language"),
* description = @Translation("Language based on a selected language."),
* config_route_name = "language.negotiation_selected"
* )
*/
#[LanguageNegotiation(
id: LanguageNegotiationSelected::METHOD_ID,
name: new TranslatableMarkup('Selected language'),
weight: 12,
description: new TranslatableMarkup("Language based on a selected language."),
config_route_name: 'language.negotiation_selected'
)]
class LanguageNegotiationSelected extends LanguageNegotiationMethodBase {
/**

View File

@ -6,7 +6,9 @@ use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Url;
use Drupal\language\Attribute\LanguageNegotiation;
use Drupal\language\LanguageNegotiationMethodBase;
use Drupal\language\LanguageSwitcherInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
@ -15,15 +17,14 @@ use Symfony\Component\HttpFoundation\RequestStack;
/**
* Identify language from a request/session parameter.
*
* @LanguageNegotiation(
* id = Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationSession::METHOD_ID,
* weight = -6,
* name = @Translation("Session"),
* description = @Translation("Language from a request/session parameter."),
* config_route_name = "language.negotiation_session"
* )
*/
#[LanguageNegotiation(
id: LanguageNegotiationSession::METHOD_ID,
name: new TranslatableMarkup('Session'),
weight: -6,
description: new TranslatableMarkup("Language from a request/session parameter."),
config_route_name: 'language.negotiation_session'
)]
class LanguageNegotiationSession extends LanguageNegotiationMethodBase implements OutboundPathProcessorInterface, LanguageSwitcherInterface, ContainerFactoryPluginInterface {
/**

View File

@ -2,20 +2,22 @@
namespace Drupal\language\Plugin\LanguageNegotiation;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\language\Attribute\LanguageNegotiation;
use Drupal\language\LanguageNegotiationMethodBase;
use Symfony\Component\HttpFoundation\Request;
/**
* Identifies the language from the interface text language selected for page.
*
* @LanguageNegotiation(
* id = Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUI::METHOD_ID,
* types = {Drupal\Core\Language\LanguageInterface::TYPE_CONTENT},
* weight = 9,
* name = @Translation("Interface"),
* description = @Translation("Use the detected interface language.")
* )
*/
#[LanguageNegotiation(
id: LanguageNegotiationUI::METHOD_ID,
name: new TranslatableMarkup('Interface'),
types: [LanguageInterface::TYPE_CONTENT],
weight: 9,
description: new TranslatableMarkup("Use the detected interface language.")
)]
class LanguageNegotiationUI extends LanguageNegotiationMethodBase {
/**

View File

@ -6,25 +6,27 @@ use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Url;
use Drupal\language\Attribute\LanguageNegotiation;
use Drupal\language\LanguageNegotiationMethodBase;
use Drupal\language\LanguageSwitcherInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Class for identifying language via URL prefix or domain.
*
* @LanguageNegotiation(
* id = \Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl::METHOD_ID,
* types = {\Drupal\Core\Language\LanguageInterface::TYPE_INTERFACE,
* \Drupal\Core\Language\LanguageInterface::TYPE_CONTENT,
* \Drupal\Core\Language\LanguageInterface::TYPE_URL},
* weight = -8,
* name = @Translation("URL"),
* description = @Translation("Language from the URL (Path prefix or domain)."),
* config_route_name = "language.negotiation_url"
* )
*/
#[LanguageNegotiation(
id: LanguageNegotiationUrl::METHOD_ID,
name: new TranslatableMarkup('URL'),
types: [LanguageInterface::TYPE_INTERFACE,
LanguageInterface::TYPE_CONTENT,
LanguageInterface::TYPE_URL,
],
weight: -8,
description: new TranslatableMarkup("Language from the URL (Path prefix or domain)."),
config_route_name: 'language.negotiation_url'
)]
class LanguageNegotiationUrl extends LanguageNegotiationMethodBase implements InboundPathProcessorInterface, OutboundPathProcessorInterface, LanguageSwitcherInterface {
/**

View File

@ -2,6 +2,9 @@
namespace Drupal\language\Plugin\LanguageNegotiation;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\language\Attribute\LanguageNegotiation;
use Drupal\language\LanguageNegotiationMethodBase;
use Symfony\Component\HttpFoundation\Request;
@ -25,15 +28,14 @@ use Symfony\Component\HttpFoundation\Request;
* requested URL having an empty prefix or domain is an anomaly that must be
* fixed. This is done by introducing a prefix or domain in the rendered
* page matching the detected interface language.
*
* @LanguageNegotiation(
* id = Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrlFallback::METHOD_ID,
* types = {Drupal\Core\Language\LanguageInterface::TYPE_URL},
* weight = 8,
* name = @Translation("URL fallback"),
* description = @Translation("Use an already detected language for URLs if none is found.")
* )
*/
#[LanguageNegotiation(
id: LanguageNegotiationUrlFallback::METHOD_ID,
name: new TranslatableMarkup('URL fallback'),
types: [LanguageInterface::TYPE_URL],
weight: 8,
description: new TranslatableMarkup('Use an already detected language for URLs if none is found.'),
)]
class LanguageNegotiationUrlFallback extends LanguageNegotiationMethodBase {
/**

View File

@ -2,21 +2,25 @@
namespace Drupal\language_test\Plugin\LanguageNegotiation;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\language\Attribute\LanguageNegotiation;
use Drupal\language\LanguageNegotiationMethodBase;
use Symfony\Component\HttpFoundation\Request;
/**
* Class for identifying language from a selected language.
*
* @LanguageNegotiation(
* id = "test_language_negotiation_method",
* weight = -10,
* name = @Translation("Test"),
* description = @Translation("This is a test language negotiation method."),
* types = {Drupal\Core\Language\LanguageInterface::TYPE_CONTENT,
* "test_language_type", "fixed_test_language_type"}
* )
*/
#[LanguageNegotiation(
id: LanguageNegotiationTest::METHOD_ID,
name: new TranslatableMarkup('Test'),
types: [LanguageInterface::TYPE_CONTENT,
'test_language_type',
'fixed_test_language_type',
],
weight: -10,
description: new TranslatableMarkup('This is a test language negotiation method.'),
)]
class LanguageNegotiationTest extends LanguageNegotiationMethodBase {
/**

View File

@ -2,17 +2,19 @@
namespace Drupal\language_test\Plugin\LanguageNegotiation;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\language\Attribute\LanguageNegotiation;
/**
* Class for identifying language from a selected language.
*
* @LanguageNegotiation(
* id = "test_language_negotiation_method_ts",
* weight = -10,
* name = @Translation("Type-specific test"),
* description = @Translation("This is a test language negotiation method."),
* types = {"test_language_type"}
* )
*/
#[LanguageNegotiation(
id: LanguageNegotiationTestTs::METHOD_ID,
name: new TranslatableMarkup('Type-specific test'),
types: ['test_language_type'],
weight: -10,
description: new TranslatableMarkup('This is a test language negotiation method.'),
)]
class LanguageNegotiationTestTs extends LanguageNegotiationTest {
/**

View File

@ -2,19 +2,20 @@
namespace Drupal\user\Plugin\LanguageNegotiation;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\language\Attribute\LanguageNegotiation;
use Drupal\language\LanguageNegotiationMethodBase;
use Symfony\Component\HttpFoundation\Request;
/**
* Class for identifying language from the user preferences.
*
* @LanguageNegotiation(
* id = \Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUser::METHOD_ID,
* weight = -4,
* name = @Translation("User"),
* description = @Translation("Follow the user's language preference.")
* )
*/
#[LanguageNegotiation(
id: LanguageNegotiationUser::METHOD_ID,
name: new TranslatableMarkup('User'),
weight: -4,
description: new TranslatableMarkup("Follow the user's language preference.")
)]
class LanguageNegotiationUser extends LanguageNegotiationMethodBase {
/**

View File

@ -2,10 +2,13 @@
namespace Drupal\user\Plugin\LanguageNegotiation;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\PathProcessor\PathProcessorManager;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Routing\AdminContext;
use Drupal\Core\Routing\StackedRouteMatchInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\language\Attribute\LanguageNegotiation;
use Drupal\language\LanguageNegotiationMethodBase;
use Drupal\Core\Routing\RouteObjectInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
@ -16,15 +19,14 @@ use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
/**
* Identifies admin language from the user preferences.
*
* @LanguageNegotiation(
* id = Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUserAdmin::METHOD_ID,
* types = {Drupal\Core\Language\LanguageInterface::TYPE_INTERFACE},
* weight = -10,
* name = @Translation("Account administration pages"),
* description = @Translation("Account administration pages language setting.")
* )
*/
#[LanguageNegotiation(
id: LanguageNegotiationUserAdmin::METHOD_ID,
name: new TranslatableMarkup('Account administration pages'),
types: [LanguageInterface::TYPE_INTERFACE],
weight: -10,
description: new TranslatableMarkup('Account administration pages language setting.')
)]
class LanguageNegotiationUserAdmin extends LanguageNegotiationMethodBase implements ContainerFactoryPluginInterface {
/**