diff --git a/features/updatepo.feature b/features/updatepo.feature index 789f4652..87c0cd18 100644 --- a/features/updatepo.feature +++ b/features/updatepo.feature @@ -488,6 +488,10 @@ Feature: Update existing PO files from a POT file #: foo-plugin.php:1 msgid "Some string" msgstr "" + + #: foo-plugin.php:2 + msgid "Some other string" + msgstr "" """ And a foo-plugin/foo-plugin-de_DE.po file: """ @@ -527,3 +531,55 @@ Feature: Update existing PO files from a POT file """ "PO-Revision-Date: 2018-05-02T22:06:24+00:00\n" """ + + Scenario: Keeps POT file order of translations + Given an empty foo-plugin directory + And a foo-plugin/foo-plugin.pot file: + """ + # Copyright (C) 2018 Foo Plugin + # This file is distributed under the same license as the Foo Plugin package. + msgid "" + msgstr "" + "Project-Id-Version: Foo Plugin\n" + "Content-Type: text/plain; charset=UTF-8\n" + "X-Domain: foo-plugin\n" + + #: foo-plugin.php:1 + msgid "First string" + msgstr "" + + #: foo-plugin.php:10 + msgid "Second string" + msgstr "" + + #: foo-plugin.php:20 + msgid "Third string" + msgstr "" + """ + And a foo-plugin/foo-plugin-de_DE.po file: + """ + # Copyright (C) 2018 Foo Plugin + # This file is distributed under the same license as the Foo Plugin package. + msgid "" + msgstr "" + "Project-Id-Version: Foo Plugin\n" + "Content-Type: text/plain; charset=UTF-8\n" + "Language: de_DE\n" + "X-Domain: foo-plugin\n" + + #: foo-plugin.php:20 + msgid "Third string" + msgstr "Dritte Zeichenfolge" + + #: foo-plugin.php:1 + msgid "First string" + msgstr "Erste Zeichenfolge" + """ + + When I run `wp i18n update-po foo-plugin/foo-plugin.pot foo-plugin/foo-plugin-de_DE.po` + Then STDOUT should be: + """ + Success: Updated 1 file. + """ + And STDERR should be empty + And the contents of the foo-plugin/foo-plugin-de_DE.po file should match /First string.*Second string.*Third string/s diff --git a/src/UpdatePoCommand.php b/src/UpdatePoCommand.php index 4fec1706..9cb2aae8 100644 --- a/src/UpdatePoCommand.php +++ b/src/UpdatePoCommand.php @@ -91,7 +91,10 @@ public function __invoke( $args, $assoc_args ) { // Uses gmdate() for consistency across different server timezones. $po_translations->setHeader( 'PO-Revision-Date', gmdate( 'Y-m-d\TH:i:sP' ) ); - if ( ! $po_translations->toPoFile( $file->getPathname() ) ) { + // Reorder translations to match POT file order. + $ordered_translations = $this->reorder_translations( $po_translations, $pot_translations ); + + if ( ! $ordered_translations->toPoFile( $file->getPathname() ) ) { WP_CLI::warning( sprintf( 'Could not update file %s', $file->getPathname() ) ); continue; } @@ -101,4 +104,31 @@ public function __invoke( $args, $assoc_args ) { WP_CLI::success( sprintf( 'Updated %d %s.', $result_count, Utils\pluralize( 'file', $result_count ) ) ); } + + /** + * Reorder translations to match the POT file order. + * + * @param Translations $po_translations The merged PO translations. + * @param Translations $pot_translations The POT translations (source of truth for order). + * + * @return Translations Translations object with entries in POT file order. + */ + private function reorder_translations( Translations $po_translations, Translations $pot_translations ) { + $ordered = new Translations(); + + // Copy headers from the merged PO translations. + foreach ( $po_translations->getHeaders() as $name => $value ) { + $ordered->setHeader( $name, $value ); + } + + // Add translations in POT file order. + foreach ( $pot_translations as $pot_entry ) { + $po_entry = $po_translations->find( $pot_entry ); + if ( $po_entry ) { + $ordered[] = $po_entry->getClone(); + } + } + + return $ordered; + } }