Change record status: 
Project: 
Introduced in branch: 
8.x
Description: 

Drupal core has support for parsing and generating Gettext Portable Object (.po) files for ages. However, the actual code that was used to process and generate Gettext files was so baked in, there is no practical way to reuse at all. You could only import all strings from a filename (tied together all through from opening the file to parsing and writing to the database); you could only export direct from the database for a HTTP header equipped download. Everything was very tightly coupled.

While solving this problem, we also went on board with the PSR-4 movement to convert functionality in includes/* to classes that are used throughout Drupal.

Therefore we introduced a Drupal/Component/Gettext component with interfaces and some Drupal database independent implementations. Code involving reading and writing to the database is locale module specific, so those implementations live with the locale module. More generic implementations for file parsing and generation and memory based loading (for the installer) reside with the component.

There are separate class implementations for each direction of PO handling (read, write) and each source type combined. This leads to:

  1. PoStreamReader (read PO items from files -- in fact arbitrary PHP streams)
  2. PoStreamWriter (write PO items to files -- in fact arbitrary PHP streams)
  3. PoDatabaseReader (implemented inside Drupal\locale\GetText, because it is locale database specific)
  4. PoDatabaseWriter (implemented inside Drupal\locale\GetText, because it is locale database specific)
  5. PoMemoryWriter (collects items read in memory -- for the installer)

We can then chain a Reader to a Writer to get a job done:

  • PoStreamReader -> PoDatabaseWriter (for importing a translation file in locale module)
  • PoStreamReader -> PoMemoryWriter (for installing Drupal in a foreign language)
  • PoDatabaseReader -> PoStreamWriter (for exporting a translation or creating a translation template file)

The architectural overview of the interfaces and classes introduced is the following:

To ease the matching of readers and writers, there are common core implementations in Drupal\locale\Gettext. See Gettext::filesToArray() and Gettext:fileToDatabase() for the two common import operations.

The changes are only relevant if you work directly with Gettext PO formatted files (for which now you get a generic parser) or source translation data from the database for export. Translation imports for projects and other related services are still automated by Drupal, and if you never handled locale module interface translation data directly or worked with Gettext PO files, then you are not affected.

Where the Drupal 7 code imported a .po file for example, the change is simple:

Drupal 7:

if ($return = _locale_import_po($file, $langcode, $form_state['values']['mode'], $form_state['values']['group']) == FALSE) {
  // Error handling logic.
}

Drupal 8:

try {

   // Try to allocate enough time to parse and import the data.
   drupal_set_time_limit(240);

   $report = GetText::fileToDatabase($file, $language->langcode, $form_state['values']['overwrite_options'], $customized);

} catch (Exception $exc) {
  // Error handling logic.
}

(Drupal 8 also uses more complex overwrite options (previously mode), dropped support for textgroups but added support for tracking custom translations).

For changes in export, see http://api.drupal.org/api/drupal/modules%21locale%21locale.admin.inc/fun..., http://api.drupal.org/api/drupal/includes%21locale.inc/function/_locale_... and http://api.drupal.org/api/drupal/includes%21locale.inc/function/_locale_... compared to http://api.drupal.org/api/drupal/core%21modules%21locale%21locale.bulk.i.... Instead of getting a string list directly from the database and passing a huge array on to export, a database reader is piped into a stream writer and the stream is printed to the HTTP output.

Impacts: 
Module developers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Other updates done