diff --git a/core/lib/Drupal/Component/Gettext/PoStreamReader.php b/core/lib/Drupal/Component/Gettext/PoStreamReader.php index 24e393671dddea689799c0edcd2dc4f3fa4854e8..d2840a6fb622b0530c38821f36e3e696615f181c 100644 --- a/core/lib/Drupal/Component/Gettext/PoStreamReader.php +++ b/core/lib/Drupal/Component/Gettext/PoStreamReader.php @@ -230,6 +230,10 @@ public function getSeek() { */ private function readHeader() { $item = $this->readItem(); + // Handle the case properly when the .po file is empty (0 bytes). + if (!$item) { + return; + } $header = new PoHeader; $header->setFromString(trim($item->getTranslation())); $this->_header = $header; diff --git a/core/modules/locale/lib/Drupal/locale/Gettext.php b/core/modules/locale/lib/Drupal/locale/Gettext.php index 9d3bfb8b57415fb692e83fda0a8b602573cd3c9c..1f42289695cff7c2032a93cd59589c5c97089229 100644 --- a/core/modules/locale/lib/Drupal/locale/Gettext.php +++ b/core/modules/locale/lib/Drupal/locale/Gettext.php @@ -10,6 +10,7 @@ use Drupal\Component\Gettext\PoStreamReader; use Drupal\Component\Gettext\PoMemoryWriter; use Drupal\locale\PoDatabaseWriter; +use Exception; /** * Static class providing Drupal specific Gettext functionality. diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleImportFunctionalTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleImportFunctionalTest.php index 589c555edf0a58911d6f76e7757ca8dc7e15889a..bfab647fa5be94bd3ceeb866f8c0a47a145ac4a2 100644 --- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleImportFunctionalTest.php +++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleImportFunctionalTest.php @@ -76,6 +76,13 @@ function testStandalonePoFile() { $skip_message = format_plural(2, 'A translation string was skipped because of disallowed or malformed HTML. See the log for details.', '@count translation strings were skipped because of disallowed or malformed HTML. See the log for details.', array('@url' => url('admin/reports/dblog'))); $this->assertRaw($skip_message, t('Unsafe strings were skipped.')); + // Try importing a zero byte sized .po file. + $this->importPoFile($this->getEmptyPoFile(), array( + 'langcode' => 'fr', + )); + + // The import should have created 0 string and rejected 0. + $this->assertRaw(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => 0, '%update' => 0, '%delete' => 0)), 'The empty translation file was successfully imported.'); // Try importing a .po file which doesn't exist. $name = $this->randomName(16); @@ -338,6 +345,13 @@ function getPoFile() { EOF; } + /** + * Helper function that returns a empty .po file. + */ + function getEmptyPoFile() { + return ''; + } + /** * Helper function that returns a bad .po file. */ diff --git a/core/modules/locale/locale.bulk.inc b/core/modules/locale/locale.bulk.inc index 5229c0178baf997f3c35f0ec9eeabafa1db4dd6c..8c8d18d9a01939d4067ef8d6741db0f725e5d1fe 100644 --- a/core/modules/locale/locale.bulk.inc +++ b/core/modules/locale/locale.bulk.inc @@ -496,13 +496,17 @@ function locale_translate_batch_finished($success, $results) { $additions = $updates = $deletes = $skips = 0; drupal_set_message(format_plural(count($results['files']), 'One translation file imported.', '@count translation files imported.')); $skipped_files = array(); - foreach ($results['stats'] as $filepath => $report) { - $additions += $report['additions']; - $updates += $report['updates']; - $deletes += $report['deletes']; - $skips += $report['skips']; - if ($report['skips'] > 0) { - $skipped_files[] = $filepath; + // If there are no results and/or no stats (eg. coping with an empty .po + // file), simply do nothing. + if ($results && isset($results['stats'])) { + foreach ($results['stats'] as $filepath => $report) { + $additions += $report['additions']; + $updates += $report['updates']; + $deletes += $report['deletes']; + $skips += $report['skips']; + if ($report['skips'] > 0) { + $skipped_files[] = $filepath; + } } } drupal_set_message(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => $additions, '%update' => $updates, '%delete' => $deletes)));