TranslationManager.php

Same filename in this branch
  1. main core/modules/locale/src/TranslationManager.php
Same filename and directory in other branches
  1. 11.x core/lib/Drupal/Core/StringTranslation/TranslationManager.php
  2. 10 core/lib/Drupal/Core/StringTranslation/TranslationManager.php
  3. 9 core/lib/Drupal/Core/StringTranslation/TranslationManager.php
  4. 8.9.x core/lib/Drupal/Core/StringTranslation/TranslationManager.php
  5. 11.x core/modules/locale/src/TranslationManager.php

Namespace

Drupal\Core\StringTranslation

File

core/lib/Drupal/Core/StringTranslation/TranslationManager.php

View source
<?php

namespace Drupal\Core\StringTranslation;

use Drupal\Component\Gettext\PoItem;
use Drupal\Core\Language\LanguageDefault;
use Drupal\Core\StringTranslation\Translator\TranslatorInterface;

/**
 * Defines a chained translation implementation combining multiple translators.
 */
class TranslationManager implements TranslationInterface, TranslatorInterface {
  
  /**
   * An unsorted array of arrays of active translators.
   *
   * An associative array. The keys are integers that indicate priority. Values
   * are arrays of TranslatorInterface objects.
   *
   * @var \Drupal\Core\StringTranslation\Translator\TranslatorInterface[][]
   *
   * @see \Drupal\Core\StringTranslation\TranslationManager::addTranslator()
   * @see \Drupal\Core\StringTranslation\TranslationManager::sortTranslators()
   */
  protected $translators = [];
  
  /**
   * An array of translators, sorted by priority.
   *
   * If this is NULL a rebuild will be triggered.
   *
   * @var null|\Drupal\Core\StringTranslation\Translator\TranslatorInterface[]
   *
   * @see \Drupal\Core\StringTranslation\TranslationManager::addTranslator()
   * @see \Drupal\Core\StringTranslation\TranslationManager::sortTranslators()
   */
  protected $sortedTranslators = NULL;
  
  /**
   * The default langcode used in translations.
   *
   * @var string
   *   A language code.
   */
  protected $defaultLangcode;
  public function __construct(LanguageDefault $default_language) {
    $this->defaultLangcode = $default_language->get()
      ->getId();
  }
  
  /**
   * Appends a translation system to the translation chain.
   *
   * @param \Drupal\Core\StringTranslation\Translator\TranslatorInterface $translator
   *   The translation interface to be appended to the translation chain.
   * @param int $priority
   *   The priority of the logger being added.
   *
   * @return $this
   */
  public function addTranslator(TranslatorInterface $translator, $priority = 0) {
    $this->translators[$priority][] = $translator;
    // Reset sorted translators property to trigger rebuild.
    $this->sortedTranslators = NULL;
    return $this;
  }
  
  /**
   * Sorts translators according to priority.
   *
   * @return \Drupal\Core\StringTranslation\Translator\TranslatorInterface[]
   *   A sorted array of translator objects.
   */
  protected function sortTranslators() {
    krsort($this->translators);
    return array_merge(...$this->translators);
  }
  
  /**
   * {@inheritdoc}
   */
  public function getStringTranslation($langcode, $string, $context) {
    if ($this->sortedTranslators === NULL) {
      $this->sortedTranslators = $this->sortTranslators();
    }
    foreach ($this->sortedTranslators as $translator) {
      $translation = $translator->getStringTranslation($langcode, $string, $context);
      if ($translation !== FALSE) {
        return $translation;
      }
    }
    // No translator got a translation.
    return FALSE;
  }
  
  /**
   * {@inheritdoc}
   */
  public function translate($string, array $args = [], array $options = []) {
    // phpcs:ignore Drupal.Semantics.FunctionT.NotLiteralString
    return new TranslatableMarkup($string, $args, $options, $this);
  }
  
  /**
   * {@inheritdoc}
   */
  public function translateString(TranslatableMarkup $translated_string) {
    return $this->doTranslate($translated_string->getUntranslatedString(), $translated_string->getOptions());
  }
  
  /**
   * {@inheritdoc}
   */
  public function selectPluralForm(int|float $count, string $string, ?string $langcode = NULL) : string {
    $translated_array = explode(PoItem::DELIMITER, $string);
    if ($count == 1 || count($translated_array) == 1) {
      // Singular form.
      return $translated_array[0];
    }
    // Plural formulas are defined over integers, so a fractional count is
    // truncated for the lookup only. The count itself is still displayed as
    // given via the @count placeholder.
    $index = $this->getPluralIndex((int) $count, $langcode);
    // Fallback to second plural form.
    return $translated_array[$index] ?? $translated_array[1];
  }
  
  /**
   * Returns plural form index for a specific number.
   *
   * The base implementation only distinguishes between singular and plural,
   * so it always returns the second (index 1) plural form. Subclasses that
   * know a language's full plural rules should override this method.
   *
   * @param int $count
   *   Number to return plural for.
   * @param string|null $langcode
   *   (optional) Language code to translate to a language other than what is
   *   used to display the page.
   *
   * @return int
   *   The numeric index of the plural variant to use for this $langcode and
   *   $count combination.
   */
  protected function getPluralIndex(int $count, ?string $langcode = NULL) : int {
    return 1;
  }
  
  /**
   * Translates a string to the current language or to a given language.
   *
   * @param string $string
   *   A string containing the English text to translate.
   * @param array $options
   *   An associative array of additional options, with the following elements:
   *   - 'langcode': The language code to translate to a language other than
   *      what is used to display the page.
   *   - 'context': The context the source string belongs to.
   *
   * @return string
   *   The translated string.
   */
  protected function doTranslate($string, array $options = []) {
    // If a NULL langcode has been provided, unset it.
    if (!isset($options['langcode']) && array_key_exists('langcode', $options)) {
      unset($options['langcode']);
    }
    // Merge in options defaults.
    $options = $options + [
      'langcode' => $this->defaultLangcode,
      'context' => '',
    ];
    $translation = $this->getStringTranslation($options['langcode'], $string, $options['context']);
    return $translation === FALSE ? $string : $translation;
  }
  
  /**
   * {@inheritdoc}
   */
  public function formatPlural($count, $singular, $plural, array $args = [], array $options = []) {
    return new PluralTranslatableMarkup($count, $singular, $plural, $args, $options, $this);
  }
  
  /**
   * Sets the default langcode.
   *
   * @param string $langcode
   *   A language code.
   */
  public function setDefaultLangcode($langcode) {
    $this->defaultLangcode = $langcode;
  }
  
  /**
   * {@inheritdoc}
   */
  public function reset() {
    if ($this->sortedTranslators === NULL) {
      $this->sortedTranslators = $this->sortTranslators();
    }
    foreach ($this->sortedTranslators as $translator) {
      $translator->reset();
    }
  }

}

Classes

Title Deprecated Summary
TranslationManager Defines a chained translation implementation combining multiple translators.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.