diff --git a/flags.info.yml b/flags.info.yml
index b6a5b58..0125c23 100644
--- a/flags.info.yml
+++ b/flags.info.yml
@@ -1,5 +1,5 @@
 name: Flags
 type: module
 description: Provides flags for countries and languages along with simple API.
-core_version_requirement: ^9 || ^10 || ^11
+core_version_requirement: ^11.4 || ^12
 package: Flags
diff --git a/flags.module b/flags.module
index 829af05..841f47d 100644
--- a/flags.module
+++ b/flags.module
@@ -1,22 +1,19 @@
 <?php
 
+/**
+ * @file
+ */
+
+use Drupal\Core\Hook\Attribute\LegacyHook;
+use Drupal\flags\Hook\FlagsHooks;
 use Drupal\Core\Template\Attribute;
-use Drupal\flags\Mapping\FlagMappingInterface;
 
 /**
  * Implements hook_theme().
  */
+#[LegacyHook]
 function flags_theme($existing, $type, $theme, $path) {
-  return [
-    'flags' => [
-      'variables' => [
-        'code' => null,
-        'source' => $type,
-        'tag' => 'span',
-        'attributes' => []
-      ],
-    ],
-  ];
+  return \Drupal::service(FlagsHooks::class)->theme($existing, $type, $theme, $path);
 }
 
 /**
@@ -27,13 +24,13 @@ function flags_theme($existing, $type, $theme, $path) {
 function template_preprocess_flags(array &$variables) {
   $flag = $variables['code'];
   // Use mapping service to allow others to provide their own mappings.
-
   // Try to invoke source specific service if it exists.
   $serviceName = 'flags.mapping.' . $variables['source'];
   if (\Drupal::hasService($serviceName)) {
     $flag = \Drupal::service($serviceName)->map($flag);
     $extra = \Drupal::service($serviceName)->getExtraClasses();
-  } else {
+  }
+  else {
     throw new \InvalidArgumentException(sprintf('Service %s to map source "%s" is not defined.', $serviceName, $variables['source']));
   }
 
@@ -44,7 +41,7 @@ function template_preprocess_flags(array &$variables) {
   }
 
   if (empty($variables['attributes']['class'])) {
-    $variables['attributes']['class'] = array();
+    $variables['attributes']['class'] = [];
   }
 
   $variables['attributes']['class'][] = 'flag';
diff --git a/flags.services.yml b/flags.services.yml
index a3223bd..f5413af 100644
--- a/flags.services.yml
+++ b/flags.services.yml
@@ -14,3 +14,7 @@ services:
   flags.manager:
     class: Drupal\flags\Flags\FlagsManager
     arguments: ['@module_handler']
+
+  Drupal\flags\Hook\FlagsHooks:
+    class: Drupal\flags\Hook\FlagsHooks
+    autowire: true
diff --git a/flags_country/flags_country.info.yml b/flags_country/flags_country.info.yml
index f969085..9988c3b 100644
--- a/flags_country/flags_country.info.yml
+++ b/flags_country/flags_country.info.yml
@@ -1,7 +1,7 @@
 name: Flags Country
 type: module
 description: Provides flag icons in widgets and formatters for country fields.
-core_version_requirement: ^9 || ^10 || ^11
+core_version_requirement: ^11.4 || ^12
 package: Flags
 dependencies:
   - flags:flags
diff --git a/flags_language/flags_language.info.yml b/flags_language/flags_language.info.yml
index 2a570d0..7b7c7e1 100644
--- a/flags_language/flags_language.info.yml
+++ b/flags_language/flags_language.info.yml
@@ -1,7 +1,7 @@
 name: Flags Language (Core)
 type: module
 description: Provides flags icons for language switchers.
-core_version_requirement: ^9 || ^10 || ^11
+core_version_requirement: ^11.4 || ^12
 package: Flags
 dependencies:
   - flags:flags
diff --git a/flags_language/flags_language.module b/flags_language/flags_language.module
index a4ca5bd..dae2aab 100644
--- a/flags_language/flags_language.module
+++ b/flags_language/flags_language.module
@@ -1,41 +1,25 @@
 <?php
 
-use \Drupal\flags\Mapping\FlagMappingInterface;
-use \Drupal\Core\Block\BlockPluginInterface;
+/**
+ * @file
+ */
+
+use Drupal\Core\Hook\Attribute\LegacyHook;
+use Drupal\flags_language\Hook\FlagsLanguageHooks;
+use Drupal\Core\Block\BlockPluginInterface;
 
 /**
  * Implements hook_language_switch_links_alter().
  *
  * Implemented to add flags to the language switcher links.
  *
- * @param array  $links
+ * @param array $links
  * @param string $type
  * @param string $path
  */
-function flags_language_language_switch_links_alter(
-  array &$links, $type, $path
-) {
-  /** @var FlagMappingInterface $mapper */
-  $mapper = \Drupal::service('flags.mapping.language');
-
-  foreach($links as $langCode => &$link) {
-    $title = $link['title'];
-
-    // If title is a string, then we turn it into renderable array.
-    // Otherwise it probably already is a renderable array.
-    if (is_string($title)) {
-      $title = array('#markup' => $link['title']);
-    }
-
-    $link['title'] = array(
-      'flag' => array(
-        '#theme' => 'flags',
-        '#code' => $mapper->map($langCode),
-        '#source' => 'language'
-      ),
-      'title' => $title,
-    );
-  }
+#[LegacyHook]
+function flags_language_language_switch_links_alter(array &$links, $type, $path) {
+  \Drupal::service(FlagsLanguageHooks::class)->languageSwitchLinksAlter($links, $type, $path);
 }
 
 /**
@@ -43,15 +27,20 @@ function flags_language_language_switch_links_alter(
  *
  * Implemented to attach flags CSS to the language switcher block.
  *
- * @param array                 $build
- * @param BlockPluginInterface  $block
+ * @param array $build
+ * @param \Drupal\Core\Block\BlockPluginInterface $block
  */
+#[LegacyHook]
 function flags_language_block_view_language_block_alter(
-  array &$build, BlockPluginInterface $block
+  array &$build,
+  BlockPluginInterface $block,
 ) {
-  $build['#attached']['library'][] = 'flags/flags';
+  \Drupal::service(FlagsLanguageHooks::class)->blockViewLanguageBlockAlter($build, $block);
 }
 
+/**
+ *
+ */
 function flags_language_field_widget_info_alter(array &$info) {
   // Allow to use widget language_select_menu only when select_icons enabled.
   if (\Drupal::moduleHandler()->moduleExists('select_icons')) {
diff --git a/flags_language/flags_language.services.yml b/flags_language/flags_language.services.yml
new file mode 100644
index 0000000..1896c6b
--- /dev/null
+++ b/flags_language/flags_language.services.yml
@@ -0,0 +1,5 @@
+
+services:
+  Drupal\flags_language\Hook\FlagsLanguageHooks:
+    class: Drupal\flags_language\Hook\FlagsLanguageHooks
+    autowire: true
diff --git a/flags_language/src/Hook/FlagsLanguageHooks.php b/flags_language/src/Hook/FlagsLanguageHooks.php
new file mode 100644
index 0000000..9676260
--- /dev/null
+++ b/flags_language/src/Hook/FlagsLanguageHooks.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace Drupal\flags_language\Hook;
+
+use Drupal\Core\Block\BlockPluginInterface;
+use Drupal\Core\Hook\Attribute\Hook;
+
+/**
+ * Hook implementations for flags_language.
+ */
+class FlagsLanguageHooks {
+
+  /**
+   * Implements hook_language_switch_links_alter().
+   *
+   * Implemented to add flags to the language switcher links.
+   *
+   * @param array $links
+   * @param string $type
+   * @param string $path
+   */
+  #[Hook('language_switch_links_alter')]
+  public static function languageSwitchLinksAlter(array &$links, $type, $path) {
+    /** @var \Drupal\flags\Mapping\FlagMappingInterface $mapper */
+    $mapper = \Drupal::service('flags.mapping.language');
+    foreach ($links as $langCode => &$link) {
+      $title = $link['title'];
+      // If title is a string, then we turn it into renderable array.
+      // Otherwise it probably already is a renderable array.
+      if (is_string($title)) {
+        $title = [
+          '#markup' => $link['title'],
+        ];
+      }
+      $link['title'] = [
+        'flag' => [
+          '#theme' => 'flags',
+          '#code' => $mapper->map($langCode),
+          '#source' => 'language',
+        ],
+        'title' => $title,
+      ];
+    }
+  }
+
+  /**
+   * Implements hook_block_view_BASE_BLOCK_ID_alter().
+   *
+   * Implemented to attach flags CSS to the language switcher block.
+   *
+   * @param array $build
+   * @param \Drupal\Core\Block\BlockPluginInterface $block
+   */
+  #[Hook('block_view_language_block_alter')]
+  public static function blockViewLanguageBlockAlter(array &$build, BlockPluginInterface $block) {
+    $build['#attached']['library'][] = 'flags/flags';
+  }
+
+}
diff --git a/flags_language/src/Plugin/Field/FieldWidget/LanguageSelectMenuWidget.php b/flags_language/src/Plugin/Field/FieldWidget/LanguageSelectMenuWidget.php
index f9c5d9c..e41c9fa 100644
--- a/flags_language/src/Plugin/Field/FieldWidget/LanguageSelectMenuWidget.php
+++ b/flags_language/src/Plugin/Field/FieldWidget/LanguageSelectMenuWidget.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\flags_language\Plugin\Field\FieldWidget;
 
+use Drupal\Component\Utility\DeprecationHelper;
 use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\Plugin\Field\FieldWidget\LanguageSelectWidget;
@@ -40,7 +41,7 @@ class LanguageSelectMenuWidget extends LanguageSelectWidget {
    *   The widget settings.
    * @param array $third_party_settings
    *   Any third party settings.
-   * @param Language $flags_mapping_language
+   * @param \Drupal\flags\Mapping\Language $flags_mapping_language
    *   The flags.mapping.language service.
    */
   public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, Language $flags_mapping_language) {
@@ -64,7 +65,7 @@ class LanguageSelectMenuWidget extends LanguageSelectWidget {
   public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
     $element = parent::formElement($items, $delta, $element, $form, $form_state);
     // Add #options to the $element.
-    $element['value'] = language_process_language_select($element['value']);
+    $element['value'] = DeprecationHelper::backwardsCompatibleCall(\Drupal::VERSION, '11.4.0', fn() => \Drupal::service('Drupal\language\Hook\LanguageHooks')->processLanguageSelect($element['value']), fn() => language_process_language_select($element['value']));
     // Change language select to the out type.
     $element['value']['#type'] = 'select_icons';
 
@@ -72,9 +73,9 @@ class LanguageSelectMenuWidget extends LanguageSelectWidget {
       array_keys($element['value']['#options'])
     );
 
-    $element['value']['#attached'] = array('library' => array('flags/flags'));
+    $element['value']['#attached'] = ['library' => ['flags/flags']];
 
-    // @TODO: check this language_element_info_alter.
+    // @todo check this language_element_info_alter.
     return $element;
   }
 
diff --git a/flags_languagefield/flags_languagefield.info.yml b/flags_languagefield/flags_languagefield.info.yml
index c540ea2..9f87955 100644
--- a/flags_languagefield/flags_languagefield.info.yml
+++ b/flags_languagefield/flags_languagefield.info.yml
@@ -1,7 +1,7 @@
 name: Flags Language Field
 type: module
 description: Provides flag icons in widgets and formatters for language fields.
-core_version_requirement: ^9 || ^10 || ^11
+core_version_requirement: ^11.4 || ^12
 package: Flags
 dependencies:
   - flags:flags
diff --git a/flags_ui/flags_ui.info.yml b/flags_ui/flags_ui.info.yml
index 4663f41..3a43a74 100644
--- a/flags_ui/flags_ui.info.yml
+++ b/flags_ui/flags_ui.info.yml
@@ -1,7 +1,7 @@
 name: Flags UI
 type: module
 description: Provides UI for mapping flags with countries and languages.
-core_version_requirement: ^9 || ^10 || ^11
+core_version_requirement: ^11.4 || ^12
 package: Flags
 dependencies:
   - flags:flags
diff --git a/src/Hook/FlagsHooks.php b/src/Hook/FlagsHooks.php
new file mode 100644
index 0000000..7e6597e
--- /dev/null
+++ b/src/Hook/FlagsHooks.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Drupal\flags\Hook;
+
+use Drupal\Core\Hook\Attribute\Hook;
+
+/**
+ * Hook implementations for flags.
+ */
+class FlagsHooks {
+
+  /**
+   * Implements hook_theme().
+   */
+  #[Hook('theme')]
+  public static function theme($existing, $type, $theme, $path) {
+    return [
+      'flags' => [
+        'variables' => [
+          'code' => NULL,
+          'source' => $type,
+          'tag' => 'span',
+          'attributes' => [],
+        ],
+      ],
+    ];
+  }
+
+}
