diff --git a/features/makejson.feature b/features/makejson.feature index dc8ab19f..f5314ef5 100644 --- a/features/makejson.feature +++ b/features/makejson.feature @@ -325,15 +325,15 @@ Feature: Split PO files into JSON files. """ "D" """ - And the foo-plugin/foo-plugin-de_DE.po file should not contain: + And the foo-plugin/foo-plugin-de_DE.po file should contain: """ "A" """ - And the foo-plugin/foo-plugin-de_DE.po file should not contain: + And the foo-plugin/foo-plugin-de_DE.po file should contain: """ "B" """ - And the foo-plugin/foo-plugin-de_DE.po file should not contain: + And the foo-plugin/foo-plugin-de_DE.po file should contain: """ "C" """ @@ -377,7 +377,7 @@ Feature: Split PO files into JSON files. msgstr "D" """ - When I run `wp i18n make-json foo-plugin --no-purge` + When I run `wp i18n make-json foo-plugin` Then STDOUT should contain: """ Success: Created 2 files. @@ -437,104 +437,6 @@ Feature: Split PO files into JSON files. "C" """ - Scenario: Does generate or update MO files - Given an empty foo-plugin directory - 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" - - #: a.js:10 - msgid "A" - msgstr "A" - - #: b.js:10 - msgid "B" - msgstr "B" - - #: a.js:10 - #: b.js:10 - msgid "C" - msgstr "C" - - #: foo-plugin.php:10 - msgid "D" - msgstr "D" - """ - - When I run `wp i18n make-json foo-plugin` - Then STDOUT should contain: - """ - Success: Created 2 files. - """ - And the return code should be 0 - - And the foo-plugin/foo-plugin-de_DE-95f0a310f289230d56c3a4949c17963e.json file should exist - And the foo-plugin/foo-plugin-de_DE.mo file should exist - - Scenario: Does not generate or update MO files - Given an empty foo-plugin directory - 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" - - #: a.js:10 - msgid "A" - msgstr "A" - - #: b.js:10 - msgid "B" - msgstr "B" - - #: a.js:10 - #: b.js:10 - msgid "C" - msgstr "C" - - #: foo-plugin.php:10 - msgid "D" - msgstr "D" - """ - - When I run `wp i18n make-json foo-plugin --no-update-mo-files` - Then STDOUT should contain: - """ - Success: Created 2 files. - """ - And the return code should be 0 - - And the foo-plugin/foo-plugin-de_DE-95f0a310f289230d56c3a4949c17963e.json file should exist - And the foo-plugin/foo-plugin-de_DE.mo file should not exist - Scenario: Correctly saves strings with context Given an empty foo-plugin directory And a foo-plugin/foo-plugin-de_DE.po file: diff --git a/features/makemo.feature b/features/makemo.feature index c1bff75d..ae0e2585 100644 --- a/features/makemo.feature +++ b/features/makemo.feature @@ -183,7 +183,7 @@ Feature: Generate MO files from PO files "X-Domain: foo-plugin\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" - #: foo-plugin.js:15 + #: foo-plugin.php:15 msgid "Foo Plugin" msgstr "Bar Plugin" """ @@ -198,3 +198,59 @@ Feature: Generate MO files from PO files """ Bar Plugin """ + + Scenario: Excludes JS-only strings from MO files + Given an empty foo-plugin directory + 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.js:15 + msgid "JS Only String" + msgstr "JS Only Translation" + + #: foo-plugin.php:10 + msgid "PHP String" + msgstr "PHP Translation" + + #: foo-plugin.js:20 + #: foo-plugin.php:15 + msgid "Both JS and PHP" + msgstr "Both Translation" + """ + + When I run `wp i18n make-mo foo-plugin` + Then STDOUT should contain: + """ + Success: Created 1 file. + """ + And the return code should be 0 + And the foo-plugin/foo-plugin-de_DE.mo file should exist + And the foo-plugin/foo-plugin-de_DE.mo file should contain: + """ + PHP Translation + """ + And the foo-plugin/foo-plugin-de_DE.mo file should contain: + """ + Both Translation + """ + And the foo-plugin/foo-plugin-de_DE.mo file should not contain: + """ + JS Only Translation + """ + diff --git a/features/makephp.feature b/features/makephp.feature index d345dea4..66f12711 100644 --- a/features/makephp.feature +++ b/features/makephp.feature @@ -202,7 +202,15 @@ Feature: Generate PHP files from PO files And the return code should be 0 And the foo-plugin/foo-plugin-de_DE.l10n.php file should contain: """ - return ['domain'=>'foo-plugin','plural-forms'=>'nplurals=2; plural=(n != 1);','language'=>'de_DE','project-id-version'=>'Foo Plugin','pot-creation-date'=>'2018-05-02T22:06:24+00:00','po-revision-date'=>'2018-05-02T22:06:24+00:00','messages'=>['Plugin NameFoo Plugin (EN)'=>'Foo Plugin (DE)','Foo Plugin'=>'Bar Plugin','You have %d new message'=>'Sie haben %d neue Nachricht' . "\0" . 'Sie haben %d neue Nachrichten']]; + You have %d new message + """ + And the foo-plugin/foo-plugin-de_DE.l10n.php file should not contain: + """ + Foo Plugin (DE) + """ + And the foo-plugin/foo-plugin-de_DE.l10n.php file should not contain: + """ + Bar Plugin """ Scenario: Excludes strings without translations @@ -300,3 +308,59 @@ Feature: Generate PHP files from PO files """ 'messages' => [ """ + + Scenario: Excludes JS-only strings from PHP files + Given an empty foo-plugin directory + 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.js:15 + msgid "JS Only String" + msgstr "JS Only Translation" + + #: foo-plugin.php:10 + msgid "PHP String" + msgstr "PHP Translation" + + #: foo-plugin.js:20 + #: foo-plugin.php:15 + msgid "Both JS and PHP" + msgstr "Both Translation" + """ + + When I run `wp i18n make-php foo-plugin` + Then STDOUT should contain: + """ + Success: Created 1 file. + """ + And the return code should be 0 + And the foo-plugin/foo-plugin-de_DE.l10n.php file should exist + And the foo-plugin/foo-plugin-de_DE.l10n.php file should contain: + """ + PHP Translation + """ + And the foo-plugin/foo-plugin-de_DE.l10n.php file should contain: + """ + Both Translation + """ + And the foo-plugin/foo-plugin-de_DE.l10n.php file should not contain: + """ + JS Only Translation + """ + diff --git a/src/JsStringFilterTrait.php b/src/JsStringFilterTrait.php new file mode 100644 index 00000000..c1ace362 --- /dev/null +++ b/src/JsStringFilterTrait.php @@ -0,0 +1,46 @@ +getArrayCopy() as $translation ) { + /** @var Translation $translation */ + + if ( ! $translation->hasReferences() ) { + continue; + } + + $has_non_js_reference = false; + foreach ( $translation->getReferences() as $reference ) { + $file = $reference[0]; + $extension = '.' . strtolower( pathinfo( $file, PATHINFO_EXTENSION ) ); + + if ( ! in_array( $extension, static::$js_extensions, true ) ) { + $has_non_js_reference = true; + break; + } + } + + // If all references are JS files, remove this translation. + if ( ! $has_non_js_reference ) { + unset( $translations[ $translation->getId() ] ); + } + } + } +} diff --git a/src/MakeJsonCommand.php b/src/MakeJsonCommand.php index 2076ac57..b52c9a29 100644 --- a/src/MakeJsonCommand.php +++ b/src/MakeJsonCommand.php @@ -3,7 +3,6 @@ namespace WP_CLI\I18n; use Gettext\Extractors\Po as PoExtractor; -use Gettext\Generators\Po as PoGenerator; use Gettext\Translation; use Gettext\Translations; use WP_CLI; @@ -44,13 +43,6 @@ class MakeJsonCommand extends WP_CLI_Command { * [--extensions=] * : Additional custom JS extensions, comma separated list. By default searches for .min.js and .js extensions. * - * [--purge] - * : Whether to purge the strings that were extracted from the original source file. Defaults to true, use `--no-purge` to skip the removal. - * - * [--update-mo-files] - * : Whether MO files should be updated as well after updating PO files. - * Only has an effect when used in combination with `--purge`. - * * [--pretty-print] * : Pretty-print resulting JSON files. * @@ -63,8 +55,8 @@ class MakeJsonCommand extends WP_CLI_Command { * # Create JSON files for all PO files in the languages directory * $ wp i18n make-json languages * - * # Create JSON files for my-plugin-de_DE.po and leave the PO file untouched. - * $ wp i18n make-json my-plugin-de_DE.po /tmp --no-purge + * # Create JSON files for my-plugin-de_DE.po + * $ wp i18n make-json my-plugin-de_DE.po /tmp * * # Create JSON files with mapping * $ wp i18n make-json languages --use-map=build/map.json @@ -80,12 +72,10 @@ class MakeJsonCommand extends WP_CLI_Command { * @throws WP_CLI\ExitException */ public function __invoke( $args, $assoc_args ) { - $assoc_args = Utils\parse_shell_arrays( $assoc_args, array( 'use-map' ) ); - $purge = Utils\get_flag_value( $assoc_args, 'purge', true ); - $update_mo_files = Utils\get_flag_value( $assoc_args, 'update-mo-files', true ); - $map_paths = Utils\get_flag_value( $assoc_args, 'use-map', false ); - $domain = Utils\get_flag_value( $assoc_args, 'domain', '' ); - $extensions = array_map( + $assoc_args = Utils\parse_shell_arrays( $assoc_args, array( 'use-map' ) ); + $map_paths = Utils\get_flag_value( $assoc_args, 'use-map', false ); + $domain = Utils\get_flag_value( $assoc_args, 'domain', '' ); + $extensions = array_map( function ( $extension ) { return trim( $extension, ' .' ); }, @@ -130,25 +120,6 @@ function ( $extension ) { if ( $file->isFile() && $file->isReadable() && 'po' === $file->getExtension() ) { $result = $this->make_json( $file->getRealPath(), $destination, $map, $domain, $extensions ); $result_count += count( $result ); - - if ( $purge ) { - $removed = $this->remove_js_strings_from_po_file( $file->getRealPath() ); - - if ( ! $removed ) { - WP_CLI::warning( sprintf( 'Could not update file %s', basename( $source ) ) ); - continue; - } - - if ( $update_mo_files ) { - $file_basename = basename( $file->getFilename(), '.po' ); - $destination_file = "{$destination}/{$file_basename}.mo"; - - $translations = Translations::fromPoFile( $file->getPathname() ); - if ( ! $translations->toMoFile( $destination_file ) ) { - WP_CLI::warning( "Could not create file {$destination_file}" ); - } - } - } } } @@ -385,37 +356,4 @@ protected function build_json_files( $mapping, $base_file_name, $destination ) { return $result; } - - /** - * Removes strings from PO file that only occur in JavaScript file. - * - * @param string $source_file Path to the PO file. - * @return bool True on success, false otherwise. - */ - protected function remove_js_strings_from_po_file( $source_file ) { - /** @var Translations[] $mapping */ - $translations = new Translations(); - - PoExtractor::fromFile( $source_file, $translations ); - - foreach ( $translations->getArrayCopy() as $translation ) { - /** @var Translation $translation */ - - if ( ! $translation->hasReferences() ) { - continue; - } - - foreach ( $translation->getReferences() as $reference ) { - $file = $reference[0]; - - if ( substr( $file, - 3 ) !== '.js' ) { - continue 2; - } - } - - unset( $translations[ $translation->getId() ] ); - } - - return PoGenerator::toFile( $translations, $source_file ); - } } diff --git a/src/MakeMoCommand.php b/src/MakeMoCommand.php index a13eeabc..89bc9865 100644 --- a/src/MakeMoCommand.php +++ b/src/MakeMoCommand.php @@ -3,6 +3,7 @@ namespace WP_CLI\I18n; use DirectoryIterator; +use Gettext\Translation; use Gettext\Translations; use IteratorIterator; use SplFileInfo; @@ -11,6 +12,8 @@ use WP_CLI_Command; class MakeMoCommand extends WP_CLI_Command { + use JsStringFilterTrait; + /** * Create MO files from PO files. * @@ -88,6 +91,10 @@ public function __invoke( $args, $assoc_args ) { $destination_file = "{$destination}/{$file_name}"; $translations = Translations::fromPoFile( $file->getPathname() ); + + // Remove JS-only strings from MO files to keep them small. + $this->remove_js_only_strings( $translations ); + if ( ! $translations->toMoFile( $destination_file ) ) { WP_CLI::warning( sprintf( 'Could not create file %s', $destination_file ) ); continue; diff --git a/src/MakePhpCommand.php b/src/MakePhpCommand.php index 1e7622e8..adecee2c 100644 --- a/src/MakePhpCommand.php +++ b/src/MakePhpCommand.php @@ -3,6 +3,7 @@ namespace WP_CLI\I18n; use DirectoryIterator; +use Gettext\Translation; use Gettext\Translations; use IteratorIterator; use SplFileInfo; @@ -11,6 +12,8 @@ use WP_CLI_Command; class MakePhpCommand extends WP_CLI_Command { + use JsStringFilterTrait; + /** * Create PHP files from PO files. * @@ -82,7 +85,11 @@ public function __invoke( $args, $assoc_args ) { $destination_file = "{$destination}/{$file_basename}.l10n.php"; $translations = Translations::fromPoFile( $file->getPathname() ); - $options = [ 'prettyPrint' => $pretty_print ]; + + // Remove JS-only strings from PHP files to keep them small. + $this->remove_js_only_strings( $translations ); + + $options = [ 'prettyPrint' => $pretty_print ]; if ( ! PhpArrayGenerator::toFile( $translations, $destination_file, $options ) ) { WP_CLI::warning( sprintf( 'Could not create file %s', $destination_file ) ); continue;