Importing translation string with script without reinstall in Drupal 8

Posted on Friday, September 15, 2017
Importing translation string with script without reinstall in Drupal 8

Drupal 8 supports multilingual out of the box now and provides translation interface to added translated strings in different languages. But it's not always feasible to added translation through this translation interface as translation strings might be a lot in numbers.

To tackle the bulk translation strings import we use .po files for each language. You can put .po files in modules translation directory and translations will be imported at the time of module install. But one of the problems with this approach is you need to alway reinstall the module to import new translations strings if they are added later.

One way to tackle this issue is to import translations with a script which can be used with hook_install(), hook_update() or with any other custom interface as well. 

An array of translation strings can be passed to the function with respective language within.
<?php
  $strings 
= [
    
'First name' => [
      
'ar' => 'الاسم الأول',
    ],
    
'Log in' => [
      
'de' => 'Anmeldung',
      
'ar' => 'تسجيل الدخول',
    ],
    
'Log out' => [
      
'de' => 'Ausloggen',
      
'ar' => 'تسجيل الخروج',
    ],
  ];
  
my_module_import_translations($strings);
?>
<?php
function my_module_import_translations($strings) {
  
/** @var \Drupal\locale\StringDatabaseStorage $locale_storage */
  
$locale_storage = \Drupal::service('locale.storage');

  
// Loop through each string for translation.
  
foreach ($strings as $source => $translations) {
    
// Translation context.
    
$context = !empty($translations['context']) ? $translations['context'] : '';
    
// Removing key so to create no problem in looping.
    
unset($translations['context']);
    
// First create the translation source entry.
    
$source_param = [
      
'source' => $source,
      
'version' => \Drupal::VERSION,
    ];
    
// If context is available.
    
if (!empty($context)) {
      
$source_param += ['context' => $context];
    }

    if (!
$locale_storage->findString($source_param)) {
      
$locale_storage->createString($source_param)->save();
    }

    
// Loop through all translations and save them.
    
foreach ($translations as $langcode => $translation) {
      
$conditions = ['source' => $source];
      
// If context is available.
      
if (!empty($context)) {
        
$conditions += ['context' => $context];
      }
      
$options = ['translated' => FALSE'untranslated' => TRUE];

      
// Look for existing translation sources.
      
$data $locale_storage->getTranslations($conditions$options);
      foreach (
$data as $key => $value) {
        if (isset(
$value->source) && $value->source == $source) {
          
// Save translation.
          
$params = [
            
'lid' => $value->lid,
            
'language' => $langcode,
          ];
          
// If context is available.
          
if (!empty($context)) {
            
$params += ['context' => $context];
          }

          try {
            try {
              if (
$target $locale_storage->findTranslation($params)) {
                
$target->delete();
              }
            }
            catch (\
Exception $e) {
              
// This is fine, it's ok if a text is not present.
            
}

            
$target $locale_storage->createTranslation($params);

            
$target->setPlurals([$translation])
              ->
setCustomized()
              ->
save();
          }
          catch (\
Exception $e) {
            \
Drupal::logger('my_module')
              ->
critical('Error occurred while saving translation for @string in @langcode', [
                
'@string' => $translation,
                
'@langcode' => $langcode,
              ]);
          }
        }
      }
    }
  }
}
?>

This script can also be used with a custom interface where admin can upload .csv file with translations in a particular format and import them. If you are planning to do this make sure to test the script and make appropriate changes in it to make it work perfectly.

Disqus Comments