8

Is there a way to programmatically add translations for strings (user interface translation), for example in hook_update_N()?

With Drupal 7, I could use the following code.

/**
 * Helper to manually add a single translation string.
 *
 * After adding strings use locale_clear_cache() for clearing caches.
 */
function locale_add_translation($source, $langcode, $translation, $context = '', $textgroup = 'default') {
  require_once DRUPAL_ROOT . '/includes/locale.inc';
 
  $report = &drupal_static(__FUNCTION__, array('additions' => 0, 'updates' => 0, 'deletes' => 0, 'skips' => 0));
  _locale_import_one_string_db($report, $langcode, $context, $source, $translation, $textgroup, 'Manual import via helper ' . __FUNCTION__ .'().', LOCALE_IMPORT_OVERWRITE);
}
 
/**
 * Helper to clear the locale cache.
 */
function locale_clear_cache() {
  require_once DRUPAL_ROOT . '/includes/locale.inc';
  // Clear locale cache.
  _locale_invalidate_js();
  cache_clear_all('locale:', 'cache', TRUE);
}

3 Answers 3

14

Put the following helper function in your custom module.

use \Drupal\locale\SourceString;

function mymodule_add_translation($source_string, $translated_string, $langcode) {
  // Find the existing source string.
  $storage = \Drupal::service('locale.storage');
  $string = $storage->findString(array('source' => $source_string));
  if (is_null($string)) {
    $string = new SourceString();
    $string->setString($source_string);
    $string->setStorage($storage);
    $string->save();
  }
  // Create the translation. If it already exists, it will be replaced.
  $storage->createTranslation(array(
    'lid' => $string->lid,
    'language' => $langcode,
    'translation' => $translated_string,
  ))->save();
}
0
1

Here is a function to create plural translations.

use Drupal\Component\Gettext\PoItem;
use Drupal\locale\SourceString;

function mymodule_add_plural_translation(array $source_strings, array $translated_strings, string $langcode): void {
  /** @var \Drupal\locale\StringStorageInterface $storage */
  $storage = \Drupal::service('locale.storage');

  $source_string = implode(PoItem::DELIMITER, $source_strings);

  $string = $storage->findString(['source' => $source_string]);

  // If the string is not yet translated, create a new source string.
  if (is_null($string)) {
    $string = new SourceString();
    $string->setString($source_string);
    $string->setStorage($storage);
    $string->save();
  }

  // Create translation. If one already exists, it will be replaced.
  $translation = $storage->createTranslation([
    'lid' => $string->lid,
    'language' => $langcode,
  ]);
  $translation->setPlurals($translated_strings);
  $translation->save();
}

Use it like this:

$source_strings = [
  'Discounted product',  // Singular string first.
  'Discounted products', // Plural string second.
];
$translated_strings = [
  'Reduziertes Produkt', // Singular string first.
  'Reduzierte Produkte', // Plural string second.
];
$langcode = 'de';

mymodule_add_plural_translation($source_strings, $translated_strings, $langcode);
1
  • 1
    Sorry for the accidental roll-back of your edit to the other answer, I wasn't seeing at first that the $context was optional and was afraid this answer wouldn't work anymore when people use it without context. Then saw it and immediately rolled the roll-back back.
    – leymannx
    Jan 31 at 14:43
0

Another sample with string context, like from $this->t('Weight', [], ['context' => 'Physical weight']).

use Drupal\locale\SourceString;

/**
 * Fix "weight" translation.
 */
function MYMODULE_update_N(&$sandbox) {
  $source_string = 'Weight';
  $context = 'Physical weight';
  $langcode = 'de';
  $translated_string = 'Gewicht';

  // Find existing source string. If it doesn't exist, it will be created.
  $storage = \Drupal::service('locale.storage');
  $string = $storage->findString(['source' => $source_string, 'context' => $context]);
  if (is_null($string)) {
    $string = new SourceString();
    $string
      ->setString($source_string)
      ->setValues(['context' => $context])
      ->setStorage($storage)
      ->save();
  }

  // Create translation. If one already exists, it will be replaced.
  $translation = $storage->createTranslation([
    'lid' => $string->getId(),
    'language' => $langcode,
    'translation' => $translated_string,
    'context' => $context,
  ])->save();
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.