From 7cdada5da773e51ab52251eda880d7e089df2294 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 3 Nov 2025 13:42:44 +0000 Subject: [PATCH 01/15] Initial plan From 9e2589b13bbe03f5a2e6e8a5089c2dfe62367e9b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 3 Nov 2025 14:08:41 +0000 Subject: [PATCH 02/15] Add --skip-purge flag to preserve obsolete entries and comments Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/UpdatePoCommand.php | 87 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/src/UpdatePoCommand.php b/src/UpdatePoCommand.php index 5af6b996..61be5a91 100644 --- a/src/UpdatePoCommand.php +++ b/src/UpdatePoCommand.php @@ -27,6 +27,11 @@ class UpdatePoCommand extends WP_CLI_Command { * : PO file to update or a directory containing multiple PO files. * Defaults to all PO files in the source directory. * + * [--skip-purge] + * : Prevent removal of obsolete strings and preserve translator comments. + * By default, strings not found in the POT file are removed, and translator comments are replaced with those from the POT file. + * This flag keeps obsolete translations (marked with #~) and preserves existing translator comments like copyright notices. + * * ## EXAMPLES * * # Update all PO files from a POT file in the current directory. @@ -41,6 +46,10 @@ class UpdatePoCommand extends WP_CLI_Command { * $ wp i18n update-po example-plugin.pot languages * Success: Updated 2 files. * + * # Update PO files while keeping obsolete strings and translator comments. + * $ wp i18n update-po example-plugin.pot --skip-purge + * Success: Updated 3 files. + * * @when before_wp_load * * @throws WP_CLI\ExitException @@ -69,6 +78,16 @@ public function __invoke( $args, $assoc_args ) { $pot_translations = Translations::fromPoFile( $source ); + // Build merge flags based on options + $merge_flags = Merge::ADD | Merge::EXTRACTED_COMMENTS_THEIRS | Merge::REFERENCES_THEIRS | Merge::DOMAIN_OVERRIDE; + + $skip_purge = Utils\get_flag_value( $assoc_args, 'skip-purge', false ); + + if ( ! $skip_purge ) { + // By default, remove obsolete entries and replace translator comments + $merge_flags |= Merge::REMOVE | Merge::COMMENTS_THEIRS; + } + $result_count = 0; /** @var DirectoryIterator $file */ foreach ( $files as $file ) { @@ -81,10 +100,16 @@ public function __invoke( $args, $assoc_args ) { continue; } + // Preserve file-level comments when --skip-purge is set + $file_comments = ''; + if ( $skip_purge ) { + $file_comments = $this->extract_file_comments( $file->getPathname() ); + } + $po_translations = Translations::fromPoFile( $file->getPathname() ); $po_translations->mergeWith( $pot_translations, - Merge::ADD | Merge::REMOVE | Merge::COMMENTS_THEIRS | Merge::EXTRACTED_COMMENTS_THEIRS | Merge::REFERENCES_THEIRS | Merge::DOMAIN_OVERRIDE + $merge_flags ); if ( ! $po_translations->toPoFile( $file->getPathname() ) ) { @@ -92,9 +117,69 @@ public function __invoke( $args, $assoc_args ) { continue; } + // Restore file-level comments when --skip-purge is set + if ( $skip_purge && ! empty( $file_comments ) ) { + $this->restore_file_comments( $file->getPathname(), $file_comments ); + } + ++$result_count; } WP_CLI::success( sprintf( 'Updated %d %s.', $result_count, Utils\pluralize( 'file', $result_count ) ) ); } + + /** + * Extract file-level comments from a PO file. + * + * These are comments that appear before the first msgid in the file. + * + * @param string $file_path Path to the PO file. + * @return string The file-level comments. + */ + private function extract_file_comments( $file_path ) { + $content = file_get_contents( $file_path ); + if ( false === $content ) { + return ''; + } + + $lines = explode( "\n", $content ); + $file_comments = []; + $found_msgid = false; + + foreach ( $lines as $line ) { + $trimmed = trim( $line ); + + // Stop when we hit the first msgid + if ( preg_match( '/^msgid\s/', $trimmed ) ) { + $found_msgid = true; + break; + } + + // Collect comment lines + if ( preg_match( '/^#([^.,:~]|$)/', $trimmed ) ) { + $file_comments[] = $line; + } + } + + return $found_msgid && ! empty( $file_comments ) ? implode( "\n", $file_comments ) . "\n" : ''; + } + + /** + * Restore file-level comments to a PO file. + * + * @param string $file_path Path to the PO file. + * @param string $comments The file-level comments to restore. + * @return bool True on success, false on failure. + */ + private function restore_file_comments( $file_path, $comments ) { + $content = file_get_contents( $file_path ); + if ( false === $content ) { + return false; + } + + // Prepend the comments to the file content + $updated_content = $comments . $content; + + return false !== file_put_contents( $file_path, $updated_content ); + } } From af41370a662c86060e8f0b1cd24d27d614acb45d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 3 Nov 2025 14:10:45 +0000 Subject: [PATCH 03/15] Add test scenarios for --skip-purge flag Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/updatepo.feature | 142 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/features/updatepo.feature b/features/updatepo.feature index 6aba5e30..612f98b1 100644 --- a/features/updatepo.feature +++ b/features/updatepo.feature @@ -465,3 +465,145 @@ Feature: Update existing PO files from a POT file """ "X-Domain: foo-plugin\n" """ + + Scenario: Preserves obsolete translations and file-level comments with --skip-purge + 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" + "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/foo-plugin\n" + "Last-Translator: FULL NAME \n" + "Language-Team: LANGUAGE \n" + "MIME-Version: 1.0\n" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" + "POT-Creation-Date: 2018-05-02T22:06:24+00:00\n" + "PO-Revision-Date: 2018-05-02T22:06:24+00:00\n" + "X-Domain: foo-plugin\n" + + #: foo-plugin.php:1 + msgid "Some 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" + "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/foo-plugin\n" + "Last-Translator: FULL NAME \n" + "Language-Team: LANGUAGE \n" + "Language: de_DE\n" + "MIME-Version: 1.0\n" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" + "POT-Creation-Date: 2018-05-02T22:06:24+00:00\n" + "PO-Revision-Date: 2018-05-02T22:06:24+00:00\n" + "X-Domain: foo-plugin\n" + "Plural-Forms: nplurals=2; plural=(n != 1);\n" + + #: foo-plugin.php:1 + msgid "Some string" + msgstr "Some translated string" + + #~ msgid "Obsolete string" + #~ msgstr "Veralteter String" + """ + + When I run `wp i18n update-po foo-plugin/foo-plugin.pot foo-plugin/foo-plugin-de_DE.po --skip-purge` + Then STDOUT should be: + """ + Success: Updated 1 file. + """ + And STDERR should be empty + And the foo-plugin/foo-plugin-de_DE.po file should contain: + """ + # Copyright (C) 2018 Foo Plugin + # This file is distributed under the same license as the Foo Plugin package. + """ + And the foo-plugin/foo-plugin-de_DE.po file should contain: + """ + #~ msgid "Obsolete string" + #~ msgstr "Veralteter String" + """ + And the foo-plugin/foo-plugin-de_DE.po file should contain: + """ + #: foo-plugin.php:1 + msgid "Some string" + msgstr "Some translated string" + """ + + Scenario: Removes obsolete translations and comments without --skip-purge + Given an empty foo-plugin directory + And a foo-plugin/foo-plugin.pot file: + """ + msgid "" + msgstr "" + "Project-Id-Version: Foo Plugin\n" + "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/foo-plugin\n" + "Last-Translator: FULL NAME \n" + "Language-Team: LANGUAGE \n" + "MIME-Version: 1.0\n" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" + "POT-Creation-Date: 2018-05-02T22:06:24+00:00\n" + "PO-Revision-Date: 2018-05-02T22:06:24+00:00\n" + "X-Domain: foo-plugin\n" + + #: foo-plugin.php:1 + msgid "Some 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" + "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/foo-plugin\n" + "Last-Translator: FULL NAME \n" + "Language-Team: LANGUAGE \n" + "Language: de_DE\n" + "MIME-Version: 1.0\n" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" + "POT-Creation-Date: 2018-05-02T22:06:24+00:00\n" + "PO-Revision-Date: 2018-05-02T22:06:24+00:00\n" + "X-Domain: foo-plugin\n" + "Plural-Forms: nplurals=2; plural=(n != 1);\n" + + #: foo-plugin.php:1 + msgid "Some string" + msgstr "Some translated string" + + #~ msgid "Obsolete string" + #~ msgstr "Veralteter String" + """ + + 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 foo-plugin/foo-plugin-de_DE.po file should not contain: + """ + # Copyright (C) 2018 Foo Plugin + """ + And the foo-plugin/foo-plugin-de_DE.po file should not contain: + """ + #~ msgid "Obsolete string" + """ + And the foo-plugin/foo-plugin-de_DE.po file should contain: + """ + #: foo-plugin.php:1 + msgid "Some string" + msgstr "Some translated string" + """ From 765140565234cf68711a6d7beba8204100096d25 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 3 Nov 2025 14:14:30 +0000 Subject: [PATCH 04/15] Fix code review issues: remove trailing whitespace and use atomic file operations Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/UpdatePoCommand.php | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/UpdatePoCommand.php b/src/UpdatePoCommand.php index 61be5a91..72a688d2 100644 --- a/src/UpdatePoCommand.php +++ b/src/UpdatePoCommand.php @@ -80,9 +80,9 @@ public function __invoke( $args, $assoc_args ) { // Build merge flags based on options $merge_flags = Merge::ADD | Merge::EXTRACTED_COMMENTS_THEIRS | Merge::REFERENCES_THEIRS | Merge::DOMAIN_OVERRIDE; - + $skip_purge = Utils\get_flag_value( $assoc_args, 'skip-purge', false ); - + if ( ! $skip_purge ) { // By default, remove obsolete entries and replace translator comments $merge_flags |= Merge::REMOVE | Merge::COMMENTS_THEIRS; @@ -148,7 +148,7 @@ private function extract_file_comments( $file_path ) { foreach ( $lines as $line ) { $trimmed = trim( $line ); - + // Stop when we hit the first msgid if ( preg_match( '/^msgid\s/', $trimmed ) ) { $found_msgid = true; @@ -180,6 +180,19 @@ private function restore_file_comments( $file_path, $comments ) { // Prepend the comments to the file content $updated_content = $comments . $content; - return false !== file_put_contents( $file_path, $updated_content ); + // Use atomic file operation with temporary file + $temp_file = $file_path . '.tmp'; + if ( false === file_put_contents( $temp_file, $updated_content ) ) { + return false; + } + + // Rename is atomic on most filesystems + if ( ! rename( $temp_file, $file_path ) ) { + // Clean up temp file on failure + @unlink( $temp_file ); + return false; + } + + return true; } } From 64b01d38159eb50a20ef1c97d561376cc5ba7d9f Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 3 Nov 2025 18:32:59 +0100 Subject: [PATCH 05/15] Lint fix --- src/UpdatePoCommand.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/UpdatePoCommand.php b/src/UpdatePoCommand.php index 72a688d2..b6846c96 100644 --- a/src/UpdatePoCommand.php +++ b/src/UpdatePoCommand.php @@ -142,9 +142,9 @@ private function extract_file_comments( $file_path ) { return ''; } - $lines = explode( "\n", $content ); - $file_comments = []; - $found_msgid = false; + $lines = explode( "\n", $content ); + $file_comments = []; + $found_msgid = false; foreach ( $lines as $line ) { $trimmed = trim( $line ); From 86fabf42ac818dec1433ab2c932a44b6055a26d2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 3 Nov 2025 20:51:32 +0000 Subject: [PATCH 06/15] Rename flag from --skip-purge to --purge with inverted logic Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/updatepo.feature | 6 +++--- src/UpdatePoCommand.php | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/features/updatepo.feature b/features/updatepo.feature index 612f98b1..d648058b 100644 --- a/features/updatepo.feature +++ b/features/updatepo.feature @@ -466,7 +466,7 @@ Feature: Update existing PO files from a POT file "X-Domain: foo-plugin\n" """ - Scenario: Preserves obsolete translations and file-level comments with --skip-purge + Scenario: Preserves obsolete translations and file-level comments with --no-purge Given an empty foo-plugin directory And a foo-plugin/foo-plugin.pot file: """ @@ -516,7 +516,7 @@ Feature: Update existing PO files from a POT file #~ msgstr "Veralteter String" """ - When I run `wp i18n update-po foo-plugin/foo-plugin.pot foo-plugin/foo-plugin-de_DE.po --skip-purge` + When I run `wp i18n update-po foo-plugin/foo-plugin.pot foo-plugin/foo-plugin-de_DE.po --no-purge` Then STDOUT should be: """ Success: Updated 1 file. @@ -539,7 +539,7 @@ Feature: Update existing PO files from a POT file msgstr "Some translated string" """ - Scenario: Removes obsolete translations and comments without --skip-purge + Scenario: Removes obsolete translations and comments by default Given an empty foo-plugin directory And a foo-plugin/foo-plugin.pot file: """ diff --git a/src/UpdatePoCommand.php b/src/UpdatePoCommand.php index b6846c96..08822311 100644 --- a/src/UpdatePoCommand.php +++ b/src/UpdatePoCommand.php @@ -27,10 +27,10 @@ class UpdatePoCommand extends WP_CLI_Command { * : PO file to update or a directory containing multiple PO files. * Defaults to all PO files in the source directory. * - * [--skip-purge] - * : Prevent removal of obsolete strings and preserve translator comments. + * [--purge] + * : Remove obsolete strings and replace translator comments. Defaults to true. * By default, strings not found in the POT file are removed, and translator comments are replaced with those from the POT file. - * This flag keeps obsolete translations (marked with #~) and preserves existing translator comments like copyright notices. + * Use `--no-purge` to preserve obsolete translations (marked with #~) and existing translator comments like copyright notices. * * ## EXAMPLES * @@ -47,7 +47,7 @@ class UpdatePoCommand extends WP_CLI_Command { * Success: Updated 2 files. * * # Update PO files while keeping obsolete strings and translator comments. - * $ wp i18n update-po example-plugin.pot --skip-purge + * $ wp i18n update-po example-plugin.pot --no-purge * Success: Updated 3 files. * * @when before_wp_load @@ -81,9 +81,9 @@ public function __invoke( $args, $assoc_args ) { // Build merge flags based on options $merge_flags = Merge::ADD | Merge::EXTRACTED_COMMENTS_THEIRS | Merge::REFERENCES_THEIRS | Merge::DOMAIN_OVERRIDE; - $skip_purge = Utils\get_flag_value( $assoc_args, 'skip-purge', false ); + $purge = Utils\get_flag_value( $assoc_args, 'purge', true ); - if ( ! $skip_purge ) { + if ( $purge ) { // By default, remove obsolete entries and replace translator comments $merge_flags |= Merge::REMOVE | Merge::COMMENTS_THEIRS; } @@ -100,9 +100,9 @@ public function __invoke( $args, $assoc_args ) { continue; } - // Preserve file-level comments when --skip-purge is set + // Preserve file-level comments when --no-purge is set $file_comments = ''; - if ( $skip_purge ) { + if ( ! $purge ) { $file_comments = $this->extract_file_comments( $file->getPathname() ); } @@ -117,8 +117,8 @@ public function __invoke( $args, $assoc_args ) { continue; } - // Restore file-level comments when --skip-purge is set - if ( $skip_purge && ! empty( $file_comments ) ) { + // Restore file-level comments when --no-purge is set + if ( ! $purge && ! empty( $file_comments ) ) { $this->restore_file_comments( $file->getPathname(), $file_comments ); } From 9a81a3a23a28443246e4ad1d75f1da213b00ae7a Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 9 Feb 2026 10:44:32 +0100 Subject: [PATCH 07/15] remove unrelated change --- .gemini/settings.json | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .gemini/settings.json diff --git a/.gemini/settings.json b/.gemini/settings.json deleted file mode 100644 index 1fc35b8a..00000000 --- a/.gemini/settings.json +++ /dev/null @@ -1 +0,0 @@ -{ "contextFileName": "AGENTS.md", "advanced": { "bugCommand": { "urlTemplate": "https://github.com/wp-cli/i18n-command/issues/new?template=1-BUG_REPORT.md&title={title}" } } } From f35bd753dd38b3ec30123db224c03fec7cff58f2 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 9 Feb 2026 10:46:55 +0100 Subject: [PATCH 08/15] fix issues after merge --- src/UpdatePoCommand.php | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/UpdatePoCommand.php b/src/UpdatePoCommand.php index 11213c4d..520ce4d7 100644 --- a/src/UpdatePoCommand.php +++ b/src/UpdatePoCommand.php @@ -137,22 +137,23 @@ public function __invoke( $args, $assoc_args ) { // Restore file-level comments when --no-purge is set if ( ! $purge && ! empty( $file_comments ) ) { $this->restore_file_comments( $file->getPathname(), $file_comments ); - if ( $has_changes ) { - ++$updated_count; - } else { - ++$unchanged_count; - } } - // Build the success message. - $message_parts = array(); - $message_parts[] = sprintf( 'Updated %d %s', $updated_count, Utils\pluralize( 'file', $updated_count ) ); - if ( $unchanged_count > 0 ) { - $message_parts[] = sprintf( '%d %s unchanged', $unchanged_count, Utils\pluralize( 'file', $unchanged_count ) ); + if ( $has_changes ) { + ++$updated_count; + } else { + ++$unchanged_count; } + } - WP_CLI::success( implode( '. ', $message_parts ) . '.' ); + // Build the success message. + $message_parts = array(); + $message_parts[] = sprintf( 'Updated %d %s', $updated_count, Utils\pluralize( 'file', $updated_count ) ); + if ( $unchanged_count > 0 ) { + $message_parts[] = sprintf( '%d %s unchanged', $unchanged_count, Utils\pluralize( 'file', $unchanged_count ) ); } + + WP_CLI::success( implode( '. ', $message_parts ) . '.' ); } /** From 195b8e63c069f9e09ed2014a38bc5d6862c69e74 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 17:21:52 +0000 Subject: [PATCH 09/15] Fix test failure: preserve obsolete translations and count file-level comment restoration as change Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/UpdatePoCommand.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/UpdatePoCommand.php b/src/UpdatePoCommand.php index 520ce4d7..8b5cee64 100644 --- a/src/UpdatePoCommand.php +++ b/src/UpdatePoCommand.php @@ -122,6 +122,11 @@ public function __invoke( $args, $assoc_args ) { // Check if the translations actually changed by comparing the objects. $has_changes = $this->translations_differ( $original_translations, $po_translations ); + // When using --no-purge, file-level comments being restored counts as a change. + if ( ! $purge && ! empty( $file_comments ) ) { + $has_changes = true; + } + // Update PO-Revision-Date to current date and time in UTC. // Uses gmdate() for consistency across different server timezones. $po_translations->setHeader( 'PO-Revision-Date', gmdate( 'Y-m-d\TH:i:sP' ) ); @@ -314,6 +319,14 @@ private function reorder_translations( Translations $po_translations, Translatio } } + // Add any remaining translations from PO that aren't in POT (e.g., obsolete/disabled translations). + foreach ( $po_translations as $po_entry ) { + // Check if this entry is already in the ordered set. + if ( ! $ordered->find( $po_entry ) ) { + $ordered[] = $po_entry->getClone(); + } + } + return $ordered; } } From 229cec24d5164d64ab4ced5612a22dd0fd757aaf Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 16 Feb 2026 22:05:46 +0100 Subject: [PATCH 10/15] Update src/UpdatePoCommand.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/UpdatePoCommand.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/UpdatePoCommand.php b/src/UpdatePoCommand.php index 8b5cee64..a19cc744 100644 --- a/src/UpdatePoCommand.php +++ b/src/UpdatePoCommand.php @@ -230,12 +230,12 @@ private function restore_file_comments( $file_path, $comments ) { } /** - * Check if two Translations objects differ . - * - * @param Translations $original Original translations. - * @param Translations $updated Updated translations. - * @return bool true if translations differ, false otherwise. - */ + * Check if two Translations objects differ . + * + * @param Translations $original Original translations. + * @param Translations $updated Updated translations. + * @return bool true if translations differ, false otherwise. + */ private function translations_differ( Translations $original, Translations $updated ) { // Quick check: if counts differ, they're different. if ( count( $original ) !== count( $updated ) ) { From 1428a7dbdd28355067865d3dad525ad9aec9bffa Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 16 Feb 2026 22:06:05 +0100 Subject: [PATCH 11/15] Update src/UpdatePoCommand.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/UpdatePoCommand.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/UpdatePoCommand.php b/src/UpdatePoCommand.php index a19cc744..3197cb23 100644 --- a/src/UpdatePoCommand.php +++ b/src/UpdatePoCommand.php @@ -92,7 +92,6 @@ public function __invoke( $args, $assoc_args ) { $merge_flags |= Merge::REMOVE | Merge::COMMENTS_THEIRS; } - $result_count = 0; $updated_count = 0; $unchanged_count = 0; /** @var DirectoryIterator $file */ From 63fa08a535ccc1c0c1211586fdf212a049ffe186 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 16 Feb 2026 22:06:53 +0100 Subject: [PATCH 12/15] Update src/UpdatePoCommand.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/UpdatePoCommand.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/UpdatePoCommand.php b/src/UpdatePoCommand.php index 3197cb23..6200885a 100644 --- a/src/UpdatePoCommand.php +++ b/src/UpdatePoCommand.php @@ -140,7 +140,9 @@ public function __invoke( $args, $assoc_args ) { // Restore file-level comments when --no-purge is set if ( ! $purge && ! empty( $file_comments ) ) { - $this->restore_file_comments( $file->getPathname(), $file_comments ); + if ( ! $this->restore_file_comments( $file->getPathname(), $file_comments ) ) { + WP_CLI::warning( sprintf( 'Could not restore file-level comments for %s', $file->getPathname() ) ); + } } if ( $has_changes ) { From d014ac416cb458a81d3ae7421511cf1a7f8bbbe8 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 16 Feb 2026 22:07:37 +0100 Subject: [PATCH 13/15] Apply suggestions from code review --- src/UpdatePoCommand.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/UpdatePoCommand.php b/src/UpdatePoCommand.php index 6200885a..a1c8b937 100644 --- a/src/UpdatePoCommand.php +++ b/src/UpdatePoCommand.php @@ -231,11 +231,11 @@ private function restore_file_comments( $file_path, $comments ) { } /** - * Check if two Translations objects differ . + * Check if two Translations objects differ. * * @param Translations $original Original translations. * @param Translations $updated Updated translations. - * @return bool true if translations differ, false otherwise. + * @return bool True if translations differ, false otherwise. */ private function translations_differ( Translations $original, Translations $updated ) { // Quick check: if counts differ, they're different. From bffbcee69cd9af9b65b13b4df3116da84f0af5a6 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 23 Feb 2026 10:10:17 +0100 Subject: [PATCH 14/15] Update src/UpdatePoCommand.php --- src/UpdatePoCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/UpdatePoCommand.php b/src/UpdatePoCommand.php index a1c8b937..632a1743 100644 --- a/src/UpdatePoCommand.php +++ b/src/UpdatePoCommand.php @@ -195,7 +195,7 @@ private function extract_file_comments( $file_path ) { } } - return $found_msgid && ! empty( $file_comments ) ? implode( "\n", $file_comments ) . "\n" : ''; + return ! empty( $file_comments ) ? implode( "\n", $file_comments ) . "\n" : ''; } /** From e21bc5a2c46b08d31ab4030230c9a78a29163cd2 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 23 Feb 2026 11:18:31 +0100 Subject: [PATCH 15/15] Update src/UpdatePoCommand.php --- src/UpdatePoCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/UpdatePoCommand.php b/src/UpdatePoCommand.php index 632a1743..5dae222b 100644 --- a/src/UpdatePoCommand.php +++ b/src/UpdatePoCommand.php @@ -223,7 +223,7 @@ private function restore_file_comments( $file_path, $comments ) { // Rename is atomic on most filesystems if ( ! rename( $temp_file, $file_path ) ) { // Clean up temp file on failure - @unlink( $temp_file ); + unlink( $temp_file ); return false; }