Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
b30a367
Initial plan
Copilot Nov 2, 2025
cb2df63
Add new i18n audit command with multiple output formats
Copilot Nov 2, 2025
33ffb82
Fix debug context from 'make-pot' to 'audit' in AuditCommand
Copilot Nov 2, 2025
16e72a9
Improve code quality: add helper method and documentation
Copilot Nov 2, 2025
242d6aa
Refactor AuditCommand to extend MakePotCommand and eliminate code dup…
Copilot Nov 2, 2025
83d45cd
Suppress log and summary messages in non-plaintext output formats
Copilot Nov 3, 2025
baa2210
Fix --ignore-domain flag to properly extract all strings regardless o…
Copilot Nov 3, 2025
56333d7
Lint fixes
swissspidy Nov 3, 2025
ddba9bf
Remove unused line
swissspidy Nov 3, 2025
336153e
Return false
swissspidy Nov 3, 2025
8e1d8a0
Return false
swissspidy Nov 3, 2025
ee82ee7
Merge branch 'main' into copilot/add-i18n-audit-command
swissspidy Dec 19, 2025
ab7d23c
Fix file data access
swissspidy Dec 19, 2025
c311f0e
Merge branch 'main' into copilot/add-i18n-audit-command
swissspidy Jan 20, 2026
4c3a823
Update src/AuditCommand.php
swissspidy Jan 20, 2026
4ea4b9b
Remove unnecessary quote-stripping regex as gettext already provides …
Copilot Jan 20, 2026
9b1ee8e
Refactor code for better readability: simplify unique comments and th…
Copilot Jan 20, 2026
b5563fa
Update src/AuditCommand.php
swissspidy Jan 20, 2026
1753a81
Fix FileDataExtractor data access to check ['value'] key consistently…
Copilot Jan 20, 2026
cc037ba
Merge branch 'main' into copilot/add-i18n-audit-command
swissspidy Jan 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"bundled": true,
"commands": [
"i18n",
"i18n audit",
"i18n make-pot",
"i18n make-json",
"i18n make-mo",
Expand Down
258 changes: 258 additions & 0 deletions features/audit.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
Feature: Audit strings in a WordPress project

Background:
Given a WP install

Scenario: Audits a plugin for translation issues
Given an empty foo-plugin directory
And a foo-plugin/foo-plugin.php file:
"""
<?php
/**
* Plugin Name: Foo Plugin
* Text Domain: foo-plugin
*/

__( 'Hello %s', 'foo-plugin' );
"""

When I try `wp i18n audit foo-plugin`
Then STDERR should contain:
"""
Warning: foo-plugin.php:7: The string "Hello %s" contains placeholders but has no "translators:" comment to clarify their meaning.
"""
And STDERR should contain:
"""
Warning: Found 1 issue.
"""
And the return code should be 0

Scenario: Audits a plugin and finds no issues
Given an empty foo-plugin directory
And a foo-plugin/foo-plugin.php file:
"""
<?php
/**
* Plugin Name: Foo Plugin
* Text Domain: foo-plugin
*/

__( 'Hello World', 'foo-plugin' );
"""

When I run `wp i18n audit foo-plugin`
Then STDOUT should contain:
"""
Success: No issues found.
"""
And STDERR should be empty

Scenario: Outputs audit results as JSON
Given an empty foo-plugin directory
And a foo-plugin/foo-plugin.php file:
"""
<?php
/**
* Plugin Name: Foo Plugin
* Text Domain: foo-plugin
*/

__( 'Hello %s', 'foo-plugin' );
"""

When I run `wp i18n audit foo-plugin --format=json`
Then STDOUT should contain:
"""
"file": "foo-plugin.php"
"""
And STDOUT should contain:
"""
"line": 7
"""
And STDOUT should contain:
"""
"message": "The string \"Hello %s\" contains placeholders but has no \"translators:\" comment to clarify their meaning."
"""
And STDOUT should contain:
"""
"code": "missing-translator-comment"
"""

Scenario: Outputs audit results in GitHub Actions format
Given an empty foo-plugin directory
And a foo-plugin/foo-plugin.php file:
"""
<?php
/**
* Plugin Name: Foo Plugin
* Text Domain: foo-plugin
*/

__( 'Hello %s', 'foo-plugin' );
"""

When I run `wp i18n audit foo-plugin --format=github-actions`
Then STDOUT should contain:
"""
::warning file=foo-plugin.php,line=7::The string "Hello %s" contains placeholders but has no "translators:" comment to clarify their meaning.
"""

Scenario: Detects multiple unordered placeholders
Given an empty foo-plugin directory
And a foo-plugin/foo-plugin.php file:
"""
<?php
/**
* Plugin Name: Foo Plugin
* Text Domain: foo-plugin
*/

__( 'Hello %s %s', 'foo-plugin' );
"""

When I try `wp i18n audit foo-plugin`
Then STDERR should contain:
"""
Warning: foo-plugin.php:7: Multiple placeholders should be ordered.
"""

Scenario: Detects strings without translatable content
Given an empty foo-plugin directory
And a foo-plugin/foo-plugin.php file:
"""
<?php
/**
* Plugin Name: Foo Plugin
* Text Domain: foo-plugin
*/

__( '%s', 'foo-plugin' );
"""

When I try `wp i18n audit foo-plugin`
Then STDERR should contain:
"""
Warning: foo-plugin.php:7: Found string without translatable content.
"""

Scenario: Detects multiple translator comments
Given an empty foo-plugin directory
And a foo-plugin/foo-plugin.php file:
"""
<?php
/**
* Plugin Name: Foo Plugin
* Text Domain: foo-plugin
*/

/* translators: Comment 1 */
__( 'Hello World', 'foo-plugin' );

/* translators: Comment 2 */
__( 'Hello World', 'foo-plugin' );
"""

When I try `wp i18n audit foo-plugin`
Then STDERR should contain:
"""
Warning: foo-plugin.php:
"""
And STDERR should contain:
"""
different translator comments
"""

Scenario: Detects missing singular placeholder
Given an empty foo-plugin directory
And a foo-plugin/foo-plugin.php file:
"""
<?php
/**
* Plugin Name: Foo Plugin
* Text Domain: foo-plugin
*/

_n( 'One comment', '%s Comments', $count, 'foo-plugin' );
"""

When I try `wp i18n audit foo-plugin`
Then STDERR should contain:
"""
Warning: foo-plugin.php:7: Missing singular placeholder, needed for some languages.
"""

Scenario: Detects mismatched placeholders in plural strings
Given an empty foo-plugin directory
And a foo-plugin/foo-plugin.php file:
"""
<?php
/**
* Plugin Name: Foo Plugin
* Text Domain: foo-plugin
*/

_n( '%s Comment', '%d Comments', $count, 'foo-plugin' );
"""

When I try `wp i18n audit foo-plugin`
Then STDERR should contain:
"""
Warning: foo-plugin.php:7: Mismatched placeholders for singular and plural string.
"""

Scenario: Respects --ignore-domain flag
Given an empty foo-plugin directory
And a foo-plugin/foo-plugin.php file:
"""
<?php
/**
* Plugin Name: Foo Plugin
* Text Domain: foo-plugin
*/

__( 'Hello %s', 'different-domain' );
"""

When I try `wp i18n audit foo-plugin --ignore-domain`
Then STDERR should contain:
"""
Warning: foo-plugin.php:7: The string "Hello %s" contains placeholders but has no "translators:" comment to clarify their meaning.
"""

Scenario: Respects --skip-php flag
Given an empty foo-plugin directory
And a foo-plugin/foo-plugin.php file:
"""
<?php
/**
* Plugin Name: Foo Plugin
* Text Domain: foo-plugin
*/

__( 'Hello %s', 'foo-plugin' );
"""

When I run `wp i18n audit foo-plugin --skip-php`
Then STDOUT should contain:
"""
Success: No issues found.
"""

Scenario: Shows file before warning message in plaintext format
Given an empty foo-plugin directory
And a foo-plugin/foo-plugin.php file:
"""
<?php
/**
* Plugin Name: Foo Plugin
* Text Domain: foo-plugin
*/

__( 'Hello %s', 'foo-plugin' );
"""

When I try `wp i18n audit foo-plugin --format=plaintext`
Then STDERR should contain:
"""
Warning: foo-plugin.php:7: The string "Hello %s" contains placeholders but has no "translators:" comment to clarify their meaning.
"""
12 changes: 12 additions & 0 deletions i18n-command.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,15 @@
WP_CLI::add_command( 'i18n make-php', '\WP_CLI\I18n\MakePhpCommand' );

WP_CLI::add_command( 'i18n update-po', '\WP_CLI\I18n\UpdatePoCommand' );

WP_CLI::add_command(
'i18n audit',
'\WP_CLI\I18n\AuditCommand',
array(
'before_invoke' => static function () {
if ( ! function_exists( 'mb_ereg' ) ) {
WP_CLI::error( 'The mbstring extension is required for string extraction to work reliably.' );
}
},
)
);
Loading