Skip to content

Commit 511666d

Browse files
authored
Merge pull request #461 from wp-cli/copilot/fix-1570774-111592377-8d1e68ec-3eae-4dfa-abd4-ecdb9fb7198f
2 parents c602513 + c969bfb commit 511666d

File tree

2 files changed

+230
-4
lines changed

2 files changed

+230
-4
lines changed

features/updatepo.feature

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,3 +583,142 @@ Feature: Update existing PO files from a POT file
583583
"""
584584
And STDERR should be empty
585585
And the contents of the foo-plugin/foo-plugin-de_DE.po file should match /First string.*Second string.*Third string/s
586+
587+
Scenario: Reports unchanged files when POT hasn't changed
588+
Given an empty foo-plugin directory
589+
And a foo-plugin/foo-plugin.pot file:
590+
"""
591+
# Copyright (C) 2018 Foo Plugin
592+
# This file is distributed under the same license as the Foo Plugin package.
593+
msgid ""
594+
msgstr ""
595+
"Project-Id-Version: Foo Plugin\n"
596+
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/foo-plugin\n"
597+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
598+
"Language-Team: LANGUAGE <LL@li.org>\n"
599+
"MIME-Version: 1.0\n"
600+
"Content-Type: text/plain; charset=UTF-8\n"
601+
"Content-Transfer-Encoding: 8bit\n"
602+
"POT-Creation-Date: 2018-05-02T22:06:24+00:00\n"
603+
"PO-Revision-Date: 2018-05-02T22:06:24+00:00\n"
604+
"X-Domain: foo-plugin\n"
605+
606+
#: foo-plugin.php:1
607+
msgid "Some string"
608+
msgstr ""
609+
"""
610+
And a foo-plugin/foo-plugin-de_DE.po file:
611+
"""
612+
# Copyright (C) 2018 Foo Plugin
613+
# This file is distributed under the same license as the Foo Plugin package.
614+
msgid ""
615+
msgstr ""
616+
"Project-Id-Version: Foo Plugin\n"
617+
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/foo-plugin\n"
618+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
619+
"Language-Team: LANGUAGE <LL@li.org>\n"
620+
"Language: de_DE\n"
621+
"MIME-Version: 1.0\n"
622+
"Content-Type: text/plain; charset=UTF-8\n"
623+
"Content-Transfer-Encoding: 8bit\n"
624+
"POT-Creation-Date: 2018-05-02T22:06:24+00:00\n"
625+
"PO-Revision-Date: 2018-05-02T22:06:24+00:00\n"
626+
"X-Domain: foo-plugin\n"
627+
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
628+
629+
#: foo-plugin.php:1
630+
msgid "Some string"
631+
msgstr "Some translated string"
632+
"""
633+
634+
When I run `wp i18n update-po foo-plugin/foo-plugin.pot`
635+
Then STDOUT should be:
636+
"""
637+
Success: Updated 0 files. 1 file unchanged.
638+
"""
639+
And STDERR should be empty
640+
641+
Scenario: Reports both updated and unchanged files
642+
Given an empty foo-plugin directory
643+
And a foo-plugin/foo-plugin.pot file:
644+
"""
645+
# Copyright (C) 2018 Foo Plugin
646+
# This file is distributed under the same license as the Foo Plugin package.
647+
msgid ""
648+
msgstr ""
649+
"Project-Id-Version: Foo Plugin\n"
650+
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/foo-plugin\n"
651+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
652+
"Language-Team: LANGUAGE <LL@li.org>\n"
653+
"MIME-Version: 1.0\n"
654+
"Content-Type: text/plain; charset=UTF-8\n"
655+
"Content-Transfer-Encoding: 8bit\n"
656+
"POT-Creation-Date: 2018-05-02T22:06:24+00:00\n"
657+
"PO-Revision-Date: 2018-05-02T22:06:24+00:00\n"
658+
"X-Domain: foo-plugin\n"
659+
660+
#: foo-plugin.php:1
661+
msgid "Some string"
662+
msgstr ""
663+
664+
#: foo-plugin.php:15
665+
msgid "Another new string"
666+
msgstr ""
667+
"""
668+
And a foo-plugin/foo-plugin-de_DE.po file:
669+
"""
670+
# Copyright (C) 2018 Foo Plugin
671+
# This file is distributed under the same license as the Foo Plugin package.
672+
msgid ""
673+
msgstr ""
674+
"Project-Id-Version: Foo Plugin\n"
675+
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/foo-plugin\n"
676+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
677+
"Language-Team: LANGUAGE <LL@li.org>\n"
678+
"Language: de_DE\n"
679+
"MIME-Version: 1.0\n"
680+
"Content-Type: text/plain; charset=UTF-8\n"
681+
"Content-Transfer-Encoding: 8bit\n"
682+
"POT-Creation-Date: 2018-05-02T22:06:24+00:00\n"
683+
"PO-Revision-Date: 2018-05-02T22:06:24+00:00\n"
684+
"X-Domain: foo-plugin\n"
685+
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
686+
687+
#: foo-plugin.php:10
688+
msgid "Some string"
689+
msgstr "Some translated string"
690+
"""
691+
And a foo-plugin/foo-plugin-es_ES.po file:
692+
"""
693+
# Copyright (C) 2018 Foo Plugin
694+
# This file is distributed under the same license as the Foo Plugin package.
695+
msgid ""
696+
msgstr ""
697+
"Project-Id-Version: Foo Plugin\n"
698+
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/foo-plugin\n"
699+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
700+
"Language-Team: LANGUAGE <LL@li.org>\n"
701+
"Language: es_ES\n"
702+
"MIME-Version: 1.0\n"
703+
"Content-Type: text/plain; charset=UTF-8\n"
704+
"Content-Transfer-Encoding: 8bit\n"
705+
"POT-Creation-Date: 2018-05-02T22:06:24+00:00\n"
706+
"PO-Revision-Date: 2018-05-02T22:06:24+00:00\n"
707+
"X-Domain: foo-plugin\n"
708+
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
709+
710+
#: foo-plugin.php:1
711+
msgid "Some string"
712+
msgstr "Some translated string"
713+
714+
#: foo-plugin.php:15
715+
msgid "Another new string"
716+
msgstr "Otra nueva cadena"
717+
"""
718+
719+
When I run `wp i18n update-po foo-plugin/foo-plugin.pot`
720+
Then STDOUT should be:
721+
"""
722+
Success: Updated 1 file. 1 file unchanged.
723+
"""
724+
And STDERR should be empty

src/UpdatePoCommand.php

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ class UpdatePoCommand extends WP_CLI_Command {
4141
* $ wp i18n update-po example-plugin.pot languages
4242
* Success: Updated 2 files.
4343
*
44+
* # Shows message when some files don't need updating.
45+
* $ wp i18n update-po example-plugin.pot languages
46+
* Success: Updated 2 files. 1 file unchanged.
47+
*
4448
* @when before_wp_load
4549
*
4650
* @throws WP_CLI\ExitException
@@ -69,7 +73,8 @@ public function __invoke( $args, $assoc_args ) {
6973

7074
$pot_translations = Translations::fromPoFile( $source );
7175

72-
$result_count = 0;
76+
$updated_count = 0;
77+
$unchanged_count = 0;
7378
/** @var DirectoryIterator $file */
7479
foreach ( $files as $file ) {
7580
if ( 'po' !== $file->getExtension() ) {
@@ -81,12 +86,17 @@ public function __invoke( $args, $assoc_args ) {
8186
continue;
8287
}
8388

84-
$po_translations = Translations::fromPoFile( $file->getPathname() );
89+
$po_translations = Translations::fromPoFile( $file->getPathname() );
90+
$original_translations = clone $po_translations;
91+
8592
$po_translations->mergeWith(
8693
$pot_translations,
8794
Merge::ADD | Merge::REMOVE | Merge::COMMENTS_THEIRS | Merge::EXTRACTED_COMMENTS_THEIRS | Merge::REFERENCES_THEIRS | Merge::DOMAIN_OVERRIDE
8895
);
8996

97+
// Check if the translations actually changed by comparing the objects.
98+
$has_changes = $this->translations_differ( $original_translations, $po_translations );
99+
90100
// Update PO-Revision-Date to current date and time in UTC.
91101
// Uses gmdate() for consistency across different server timezones.
92102
$po_translations->setHeader( 'PO-Revision-Date', gmdate( 'Y-m-d\TH:i:sP' ) );
@@ -99,10 +109,87 @@ public function __invoke( $args, $assoc_args ) {
99109
continue;
100110
}
101111

102-
++$result_count;
112+
if ( $has_changes ) {
113+
++$updated_count;
114+
} else {
115+
++$unchanged_count;
116+
}
117+
}
118+
119+
// Build the success message.
120+
$message_parts = array();
121+
$message_parts[] = sprintf( 'Updated %d %s', $updated_count, Utils\pluralize( 'file', $updated_count ) );
122+
if ( $unchanged_count > 0 ) {
123+
$message_parts[] = sprintf( '%d %s unchanged', $unchanged_count, Utils\pluralize( 'file', $unchanged_count ) );
124+
}
125+
126+
WP_CLI::success( implode( '. ', $message_parts ) . '.' );
127+
}
128+
129+
/**
130+
* Check if two Translations objects differ.
131+
*
132+
* @param Translations $original Original translations.
133+
* @param Translations $updated Updated translations.
134+
* @return bool True if translations differ, false otherwise.
135+
*/
136+
private function translations_differ( Translations $original, Translations $updated ) {
137+
// Quick check: if counts differ, they're different.
138+
if ( count( $original ) !== count( $updated ) ) {
139+
return true;
140+
}
141+
142+
// Compare each translation entry.
143+
foreach ( $original as $translation ) {
144+
$context = $translation->getContext();
145+
$original_str = $translation->getOriginal();
146+
147+
// Find the corresponding translation in the updated set.
148+
$updated_translation = $updated->find( $context, $original_str );
149+
150+
// If translation doesn't exist in updated set, they differ.
151+
if ( ! $updated_translation ) {
152+
return true;
153+
}
154+
155+
// Compare translation strings.
156+
if ( $translation->getTranslation() !== $updated_translation->getTranslation() ) {
157+
return true;
158+
}
159+
160+
// Compare plural translations if they exist.
161+
$original_plurals = $translation->getPluralTranslations();
162+
$updated_plurals = $updated_translation->getPluralTranslations();
163+
164+
if ( $original_plurals !== $updated_plurals ) {
165+
return true;
166+
}
167+
168+
// Compare references (source code locations).
169+
$original_refs = $translation->getReferences();
170+
$updated_refs = $updated_translation->getReferences();
171+
172+
$original_refs_sorted = $original_refs;
173+
$updated_refs_sorted = $updated_refs;
174+
175+
sort( $original_refs_sorted );
176+
sort( $updated_refs_sorted );
177+
178+
if ( $original_refs_sorted !== $updated_refs_sorted ) {
179+
return true;
180+
}
181+
182+
// Compare comments.
183+
if ( $translation->getExtractedComments() !== $updated_translation->getExtractedComments() ) {
184+
return true;
185+
}
186+
187+
if ( $translation->getComments() !== $updated_translation->getComments() ) {
188+
return true;
189+
}
103190
}
104191

105-
WP_CLI::success( sprintf( 'Updated %d %s.', $result_count, Utils\pluralize( 'file', $result_count ) ) );
192+
return false;
106193
}
107194

108195
/**

0 commit comments

Comments
 (0)