Feature: Generate a POT file of a WordPress project Background: Given a WP install Scenario: Bail for invalid source directories When I try `wp i18n make-pot foo bar/baz.pot` Then STDERR should contain: """ Error: Not a valid source directory! """ And the return code should be 1 Scenario: Generates a POT file by default When I run `wp scaffold plugin hello-world` Then the wp-content/plugins/hello-world directory should exist And the wp-content/plugins/hello-world/hello-world.php file should exist When I run `wp i18n make-pot wp-content/plugins/hello-world wp-content/plugins/hello-world/languages/hello-world.pot` Then STDOUT should be: """ Plugin file detected. Success: POT file successfully generated! """ And STDERR should be empty And the wp-content/plugins/hello-world/languages/hello-world.pot file should exist Scenario: Does include file headers. When I run `wp scaffold plugin hello-world --plugin_name="Hello World" --plugin_author="John Doe" --plugin_author_uri="https://example.com" --plugin_uri="https://foo.example.com"` Then the wp-content/plugins/hello-world directory should exist And the wp-content/plugins/hello-world/hello-world.php file should exist When I run `wp i18n make-pot wp-content/plugins/hello-world wp-content/plugins/hello-world/languages/hello-world.pot` Then the wp-content/plugins/hello-world/languages/hello-world.pot file should exist Then STDOUT should be: """ Plugin file detected. Success: POT file successfully generated! """ And STDERR should be empty And the wp-content/plugins/hello-world/languages/hello-world.pot file should exist And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ msgid "Hello World" """ And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ msgid "John Doe" """ And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ msgid "https://example.com" """ And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ msgid "https://foo.example.com" """ Scenario: Does not include empty file headers. When I run `wp scaffold plugin hello-world --plugin_description=""` When I run `wp i18n make-pot wp-content/plugins/hello-world wp-content/plugins/hello-world/languages/hello-world.pot` Then the wp-content/plugins/hello-world/languages/hello-world.pot file should exist And the wp-content/plugins/hello-world/languages/hello-world.pot file should not contain: """ Description of the plugin """ Scenario: Adds copyright comments When I run `wp scaffold plugin hello-world` When I run `date +"%Y"` Then STDOUT should not be empty And save STDOUT as {YEAR} When I run `wp i18n make-pot wp-content/plugins/hello-world wp-content/plugins/hello-world/languages/hello-world.pot` And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ # Copyright (C) {YEAR} YOUR NAME HERE # This file is distributed under the same license as the Hello World plugin. """ Scenario: Use the same license as the plugin Given an empty foo-plugin directory And a foo-plugin/foo-plugin.php file: """ \n" "Language-Team: LANGUAGE \n" """ Scenario: Sets the generator header When I run `wp scaffold plugin hello-world` When I run `wp i18n make-pot wp-content/plugins/hello-world wp-content/plugins/hello-world/languages/hello-world.pot` Then the contents of the wp-content/plugins/hello-world/languages/hello-world.pot file should match /X-Generator:\s/ Scenario: Ignores any other text domain Given an empty foo-plugin directory And a foo-plugin/foo-plugin.php file: """ \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.js:15 msgid "Foo Plugin" msgstr "" """ When I run `wp scaffold plugin hello-world --plugin_name="Hello World" --plugin_author="John Doe" --plugin_author_uri="https://example.com" --plugin_uri="https://foo.example.com"` Then the wp-content/plugins/hello-world directory should exist And the wp-content/plugins/hello-world/hello-world.php file should exist When I run `wp i18n make-pot wp-content/plugins/hello-world wp-content/plugins/hello-world/languages/hello-world.pot --merge=foo-plugin/foo-plugin.pot` Then the wp-content/plugins/hello-world/languages/hello-world.pot file should exist Then STDOUT should be: """ Plugin file detected. Success: POT file successfully generated! """ And STDERR should be empty And the wp-content/plugins/hello-world/languages/hello-world.pot file should exist And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ msgid "Hello World" """ And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ #: foo-plugin.js:15 """ And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ msgid "Foo Plugin" """ Scenario: Merges translations with the ones from multiple existing POT files 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.js:15 msgid "Foo Plugin" msgstr "" """ And a foo-plugin/bar-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" #: bar-plugin.js:15 msgid "Bar Plugin" msgstr "" """ When I run `wp scaffold plugin hello-world --plugin_name="Hello World" --plugin_author="John Doe" --plugin_author_uri="https://example.com" --plugin_uri="https://foo.example.com"` Then the wp-content/plugins/hello-world directory should exist And the wp-content/plugins/hello-world/hello-world.php file should exist When I run `wp i18n make-pot wp-content/plugins/hello-world wp-content/plugins/hello-world/languages/hello-world.pot --merge=foo-plugin/foo-plugin.pot,foo-plugin/bar-plugin.pot` Then the wp-content/plugins/hello-world/languages/hello-world.pot file should exist Then STDOUT should be: """ Plugin file detected. Success: POT file successfully generated! """ And STDERR should be empty And the wp-content/plugins/hello-world/languages/hello-world.pot file should exist And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ msgid "Hello World" """ And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ #: foo-plugin.js:15 """ And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ msgid "Foo Plugin" """ And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ #: bar-plugin.js:15 """ And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ msgid "Bar Plugin" """ Scenario: Merges translations with existing destination file When I run `wp scaffold plugin hello-world --plugin_name="Hello World" --plugin_author="John Doe" --plugin_author_uri="https://example.com" --plugin_uri="https://foo.example.com"` Then the wp-content/plugins/hello-world directory should exist And the wp-content/plugins/hello-world/hello-world.php file should exist Given a wp-content/plugins/hello-world/languages/hello-world.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" #: hello-world.js:15 msgid "Hello World JS" msgstr "" """ When I run `wp i18n make-pot wp-content/plugins/hello-world wp-content/plugins/hello-world/languages/hello-world.pot --merge` Then STDOUT should be: """ Plugin file detected. Success: POT file successfully generated! """ And STDERR should be empty And the wp-content/plugins/hello-world/languages/hello-world.pot file should exist And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ msgid "Hello World" """ And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ #: hello-world.js:15 """ And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ msgid "Hello World JS" """ Scenario: Uses newer file headers when merging 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" "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/foo-plugin\n" "Last-Translator: John Doe \n" "Language-Team: Language Team \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.js:15 msgid "Foo Plugin" msgstr "" """ When I run `wp scaffold plugin hello-world --plugin_name="Hello World" --plugin_author="John Doe" --plugin_author_uri="https://example.com" --plugin_uri="https://foo.example.com"` Then the wp-content/plugins/hello-world directory should exist And the wp-content/plugins/hello-world/hello-world.php file should exist When I run `date +"%Y"` Then save STDOUT as {YEAR} When I run `wp i18n make-pot wp-content/plugins/hello-world wp-content/plugins/hello-world/languages/hello-world.pot --merge=foo-plugin/foo-plugin.pot` Then the wp-content/plugins/hello-world/languages/hello-world.pot file should exist Then STDOUT should be: """ Plugin file detected. Success: POT file successfully generated! """ And STDERR should be empty And the wp-content/plugins/hello-world/languages/hello-world.pot file should exist And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ # Copyright (C) {YEAR} John Doe # This file is distributed under the same license as the Hello World plugin. msgid "" msgstr "" "Project-Id-Version: Hello World 0.1.0\n" "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/hello-world\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" """ And the wp-content/plugins/hello-world/languages/hello-world.pot file should not contain: """ "POT-Creation-Date: 2018-05-02T22:06:24+00:00\n" "PO-Revision-Date: 2018-05-02T22:06:24+00:00\n" """ And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" """ And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ "X-Domain: hello-world\n" """ And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ msgid "Hello World" """ And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ #: foo-plugin.js:15 """ And the wp-content/plugins/hello-world/languages/hello-world.pot file should contain: """ msgid "Foo Plugin" """ Scenario: Extracts functions from JavaScript file Given an empty foo-plugin directory And a foo-plugin/foo-plugin.php file: """ {__( 'Hello JSX', 'foo-plugin' )}, document.getElementById('root') ); wp.i18n.__( 'wp.i18n.__', 'foo-plugin' ); wp.i18n._n( 'wp.i18n._n_single', 'wp.i18n._n_plural', number, 'foo-plugin' ); const translate = wp.i18n; translate.__( 'translate.__', 'foo-plugin' ); Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_7__["__"])( 'webpack.__', 'foo-plugin' ); Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_7__[/* __ */ "a"])( 'webpack.mangle.__', 'foo-plugin' ); Object(u.__)( 'minified.__', 'foo-plugin' ); Object(j._x)( 'minified._x', 'minified._x_context', 'foo-plugin' ); /* translators: babel */ (0, __)( 'babel.__', 'foo-plugin' ); (0, _i18n.__)( 'babel-i18n.__', 'foo-plugin' ); (0, _i18n._x)( 'babel-i18n._x', 'babel-i18n._x_context', 'foo-plugin' ); eval( "__( 'Hello Eval World', 'foo-plugin' );" ); __( `This is a ${ bug }`, 'foo-plugin' ); """ When I run `wp i18n make-pot foo-plugin` Then STDOUT should be: """ Plugin file detected. Success: POT file successfully generated! """ And the foo-plugin/foo-plugin.pot file should exist And the foo-plugin/foo-plugin.pot file should contain: """ msgid "__" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgid "_x" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgctxt "_x_context" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgid "_n_single" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgid_plural "_n_plural" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgid "_nx_single" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgid_plural "_nx_plural" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgctxt "_nx_context" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgid "Hello JSX" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgid "wp.i18n.__" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgid "wp.i18n._n_single" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgid_plural "wp.i18n._n_plural" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgid "translate.__" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgid "webpack.__" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgid "webpack.mangle.__" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgid "minified.__" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgid "minified._x" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgctxt "minified._x_context" """ And the foo-plugin/foo-plugin.pot file should contain: """ #. translators: babel """ And the foo-plugin/foo-plugin.pot file should contain: """ msgid "babel.__" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgid "babel-i18n.__" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgid "babel-i18n._x" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgctxt "babel-i18n._x_context" """ And the foo-plugin/foo-plugin.pot file should contain: """ msgid "Hello Eval World" """ And the foo-plugin/foo-plugin.pot file should not contain: """ msgid "wrong-domain" """ And the foo-plugin/foo-plugin.pot file should not contain: """ msgid "foo-plugin" """ Scenario: Ignores dynamic import in JavaScript file. Given an empty foo-plugin directory And a foo-plugin/foo-plugin.php file: """ console.log(a)) __( '__', 'foo-plugin' ); """ When I run `wp i18n make-pot foo-plugin` Then STDOUT should be: """ Plugin file detected. Success: POT file successfully generated! """ And the foo-plugin/foo-plugin.pot file should exist And the foo-plugin/foo-plugin.pot file should contain: """ msgid "__" """ Scenario: Parse .js and .jsx files for javascript translations Given an empty foo-plugin directory And a foo-plugin/foo-plugin.php file: """ {__( 'Hello JSX', 'foo-plugin' )}, document.getElementById('root') ); // translators: this is wp.i18n wp.i18n.__( 'Hello wp.i18n', 'foo-plugin' ); message = Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_7__["sprintf"])( // translators: this is Webpack Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_7__["__"])('Hello webpack.', 'foo-plugin'), mediaFile.name); """ When I try `wp i18n make-pot foo-plugin` Then STDOUT should be: """ Plugin file detected. Success: POT file successfully generated! """ And the foo-plugin/foo-plugin.pot file should exist And the foo-plugin/foo-plugin.pot file should contain: """ msgid "Foo Plugin" """ And the foo-plugin/foo-plugin.pot file should contain: """ #. translators: Translators 1! """ And the foo-plugin/foo-plugin.pot file should contain: """ #. Translators: Translators 2! """ And the foo-plugin/foo-plugin.pot file should contain: """ msgid "F j, Y g:i a" """ And the foo-plugin/foo-plugin.pot file should contain: """ #. translators: localized date and time format, see https://secure.php.net/date """ And the foo-plugin/foo-plugin.pot file should contain: """ #. translators: let your ears fly! """ And the foo-plugin/foo-plugin.pot file should contain: """ #. Translators: If there are characters in your language that are not supported by Lato, translate this to 'off'. Do not translate into your own language. """ And the foo-plugin/foo-plugin.pot file should contain: """ #. translators: this should get extracted. """ And the foo-plugin/foo-plugin.pot file should contain: """ #. translators: boo """ And the foo-plugin/foo-plugin.pot file should contain: """ #. translators: this should get extracted too. """ And the foo-plugin/foo-plugin.pot file should contain: """ #. translators: this is before the multiline call. """ And the foo-plugin/foo-plugin.pot file should contain: """ #. translators: this is inside the multiline call. """ And the foo-plugin/foo-plugin.pot file should contain: """ #. translators: this is JSX """ And the foo-plugin/foo-plugin.pot file should contain: """ #. translators: this is wp.i18n """ And the foo-plugin/foo-plugin.pot file should contain: """ #. translators: this is Webpack """ Scenario: Extract plural strings with expressions from JavaScript file Given an empty foo-plugin directory And a foo-plugin/foo-plugin.php file: """ {__( 'Hello JSX', 'baz' )}, document.getElementById('root') ); """ When I run `wp i18n make-pot foo-plugin foo-plugin.pot --domain=bar` Then STDOUT should be: """ Plugin file detected. Success: POT file successfully generated! """ And the foo-plugin.pot file should contain: """ msgid "Foo" """ And the foo-plugin.pot file should not contain: """ msgid "Hello World" """ And the foo-plugin.pot file should not contain: """ msgid "bar" """ And the foo-plugin.pot file should not contain: """ msgid "Hello JSX" """ Scenario: Extract strings in template literals in JavaScript file Given an empty foo-plugin directory And a foo-plugin/foo-plugin.php file: """ \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" msgid "Foo Bar" msgstr "" msgid "Bar Baz" msgstr "" msgid "Some other text" msgstr "" """ And a foo-plugin.php file: """ \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" #: bar-plugin.php:2 #: bar-baz-plugin.php:20 msgid "Foo Bar" msgstr "" #: bar-plugin.php:5 #: bar-bar.php:50 msgid "Bar Baz" msgstr "" #: bar-plugin.php:17 #: bar-baz-plugin.php:99 #: foobar/plugin.php:39 msgid "Some other text" msgstr "" """ And a foo-plugin.php file: """ {!! __('Page not found.', 'foo-theme') !!} {!! get_search_form(false) !!} @endif @endsection """ When I try `wp i18n make-pot foo-theme result.pot --ignore-domain --debug` Then STDOUT should be: """ Theme stylesheet detected. Success: POT file successfully generated! """ And the result.pot file should contain: """ msgid "Test" """ And the result.pot file should contain: """ msgid "Page not found." """ And the result.pot file should contain: """ msgid "Another test." """ @blade Scenario: Extract strings from a Blade-PHP file in a theme Given an empty foo-theme directory And a foo-theme/style.css file: """ /* Theme Name: Foo Theme Theme URI: https://example.com Description: Author: Author URI: Version: 0.1.0 License: GPL-2.0+ Text Domain: foo-theme */ """ And a foo-theme/stuff.blade.php file: """ @php __('Test'); @endphp @extends('layouts.app') @php(__('Another test.', 'some-other-domain')) @section('content') @include('partials.page-header') @if (! have_posts()) {!! __('Page not found.', 'foo-theme') !!} {!! get_search_form(false) !!} @endif @endsection """ When I try `wp i18n make-pot foo-theme result.pot --debug` Then STDOUT should be: """ Theme stylesheet detected. Success: POT file successfully generated! """ And the result.pot file should contain: """ msgid "Page not found." """ Scenario: Custom package name Given an empty example-project directory And a example-project/stuff.php file: """