From 27715e88ab371e4f55803c0406f0bcf1faff1ccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Amieiro?= <1667814+amieiro@users.noreply.github.com> Date: Mon, 4 Nov 2024 11:26:31 +0100 Subject: [PATCH 1/8] Add the check for the leading and trailing spaces --- WordPress/Sniffs/WP/I18nSniff.php | 44 +++++++++++++++++++++ WordPress/Tests/WP/I18nUnitTest.1.inc | 23 +++++++++++ WordPress/Tests/WP/I18nUnitTest.1.inc.fixed | 23 +++++++++++ WordPress/Tests/WP/I18nUnitTest.php | 22 +++++++++++ 4 files changed, 112 insertions(+) diff --git a/WordPress/Sniffs/WP/I18nSniff.php b/WordPress/Sniffs/WP/I18nSniff.php index bf9b9936ec..7bc449a793 100644 --- a/WordPress/Sniffs/WP/I18nSniff.php +++ b/WordPress/Sniffs/WP/I18nSniff.php @@ -380,6 +380,7 @@ public function process_parameters( $stackPtr, $group_name, $matched_content, $p $has_content = $this->check_string_has_translatable_content( $matched_content, $param_name, $param_info ); if ( true === $has_content ) { $this->check_string_has_no_html_wrapper( $matched_content, $param_name, $param_info ); + $this->check_string_has_no_leading_trailing_spaces( $matched_content, $param_name, $param_info ); } } } @@ -804,6 +805,49 @@ private function check_string_has_no_html_wrapper( $matched_content, $param_name } } + /** + * Check if a translatable string has leading or trailing spaces. + * + * @since 3.2.0 + * + * @param string $matched_content The token content (function name) which was matched + * in lowercase. + * @param string $param_name The name of the parameter being examined. + * @param array|false $param_info Parameter info array for an individual parameter, + * as received from the PassedParameters class. + * + * @return void + */ + private function check_string_has_no_leading_trailing_spaces( $matched_content, $param_name, $param_info ) { + // Strip surrounding quotes. + $content_without_quotes = TextStrings::stripQuotes( $param_info['clean'] ); + $first_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, $param_info['start'], ( $param_info['end'] + 1 ), true ); + + if ( ltrim( $content_without_quotes ) !== $content_without_quotes ) { + $this->phpcsFile->addError( + 'Translatable string should not have leading spaces. Found: %s', + $first_non_empty, + 'NoLeadingTrailingSpaces', + array( $param_info['clean'] ) + ); + } + if ( rtrim( $content_without_quotes ) !== $content_without_quotes ) { + $this->phpcsFile->addError( + 'Translatable string should not have trailing spaces. Found: %s', + $first_non_empty, + 'NoLeadingTrailingSpaces', + array( $param_info['clean'] ) + ); + } + + if ('cadena' == $param_info['raw']) { + fwrite(STDERR, "\n" . '$matched_content: ' . print_r($matched_content, TRUE)); + fwrite(STDERR, "\n" . '$param_name: ' . print_r($param_name, TRUE)); + fwrite(STDERR, "\n" . '$param_info: ' . print_r($param_info, TRUE)); + exit(1); + } + } + /** * Check for inconsistencies in the placeholders between single and plural form of the translatable text string. * diff --git a/WordPress/Tests/WP/I18nUnitTest.1.inc b/WordPress/Tests/WP/I18nUnitTest.1.inc index 6256e6d84a..d5d80f8e70 100644 --- a/WordPress/Tests/WP/I18nUnitTest.1.inc +++ b/WordPress/Tests/WP/I18nUnitTest.1.inc @@ -317,4 +317,27 @@ esc_html_e( 'foo', '' ); // Bad: text-domain can not be empty. // PHP 8.0+: safeguard handling of newly introduced placeholders. __( 'There are %1$h monkeys in the %H', 'my-slug' ); // Bad: multiple arguments should be numbered. +__( ' string', 'my-slug' ); // Bad: leading space. +_e( 'string ', 'my-slug' ); // Bad: trailing space. +_x( ' string ', 'context', 'my-slug' ); // Bad: leading and trailing spaces. +_ex( ' string', 'context', 'my-slug' ); // Bad: leading spaces. +_n( ' There is %1$d monkey in the %2$s', 'In the %2$s there are %1$d monkeys', $number, 'my-slug' ); // Bad: leading space. +_n( 'There is %1$d monkey in the %2$s', 'In the %2$s there are %1$d monkeys ', $number, 'my-slug' ); // Bad: trailing space. +_n( ' There is %1$d monkey in the %2$s', 'In the %2$s there are %1$d monkeys ', $number, 'my-slug' ); // Bad: leading and trailing spaces. +_nx( ' I have %d cat.', 'I have %d cats.', $number, 'Not really.', 'my-slug' ); // Bad: leading spaces. +_nx( 'I have %d cat.', 'I have %d cats. ', $number, 'Not really.', 'my-slug' ); // Bad: trailing spaces. +_nx( ' I have %d cat.', 'I have %d cats. ', $number, 'Not really.', 'my-slug' ); // Bad: leading and trailing spaces. +_n_noop( ' I have %d cat.', 'I have %d cats.', 'my-slug' ); // Bad: leading space. +_n_noop( 'I have %d cat.', 'I have %d cats. ', 'my-slug' ); // Bad: trailing space. +_n_noop( ' I have %d cat.', 'I have %d cats. ', 'my-slug' ); // Bad: leading and trailing spaces. +_nx_noop( ' I have %d cat.', 'I have %d cats.', 'Not really.', 'my-slug' ); // Bad: leading spaces. +_nx_noop( 'I have %d cat.', 'I have %d cats. ', 'Not really.', 'my-slug' ); // Bad: trailing spaces. +_nx_noop( ' I have %d cat.', 'I have %d cats. ', 'Not really.', 'my-slug' ); // Bad: leading and trailing spaces. +esc_html__( ' string', 'my-slug' ); // Bad: leading space. +esc_html_e( 'string ', 'my-slug' ); // Bad: trailing space. +esc_html_x( ' string ', 'context', 'my-slug' ); // Bad: leading and trailing spaces. +esc_attr__( ' string', 'my-slug' ); // Bad: leading space. +esc_attr_e( 'string ', 'my-slug' ); // Bad: trailing space. +esc_attr_x( ' string ', 'context', 'my-slug' ); // Bad: leading and trailing spaces. + // phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment diff --git a/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed b/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed index b23e9b6192..c884f83963 100644 --- a/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed +++ b/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed @@ -317,4 +317,27 @@ esc_html_e( 'foo', '' ); // Bad: text-domain can not be empty. // PHP 8.0+: safeguard handling of newly introduced placeholders. __( 'There are %1$h monkeys in the %H', 'my-slug' ); // Bad: multiple arguments should be numbered. +__( ' string', 'my-slug' ); // Bad: leading space. +_e( 'string ', 'my-slug' ); // Bad: trailing space. +_x( ' string ', 'context', 'my-slug' ); // Bad: leading and trailing spaces. +_ex( ' string', 'context', 'my-slug' ); // Bad: leading spaces. +_n( ' There is %1$d monkey in the %2$s', 'In the %2$s there are %1$d monkeys', $number, 'my-slug' ); // Bad: leading space. +_n( 'There is %1$d monkey in the %2$s', 'In the %2$s there are %1$d monkeys ', $number, 'my-slug' ); // Bad: trailing space. +_n( ' There is %1$d monkey in the %2$s', 'In the %2$s there are %1$d monkeys ', $number, 'my-slug' ); // Bad: leading and trailing spaces. +_nx( ' I have %d cat.', 'I have %d cats.', $number, 'Not really.', 'my-slug' ); // Bad: leading spaces. +_nx( 'I have %d cat.', 'I have %d cats. ', $number, 'Not really.', 'my-slug' ); // Bad: trailing spaces. +_nx( ' I have %d cat.', 'I have %d cats. ', $number, 'Not really.', 'my-slug' ); // Bad: leading and trailing spaces. +_n_noop( ' I have %d cat.', 'I have %d cats.', 'my-slug' ); // Bad: leading space. +_n_noop( 'I have %d cat.', 'I have %d cats. ', 'my-slug' ); // Bad: trailing space. +_n_noop( ' I have %d cat.', 'I have %d cats. ', 'my-slug' ); // Bad: leading and trailing spaces. +_nx_noop( ' I have %d cat.', 'I have %d cats.', 'Not really.', 'my-slug' ); // Bad: leading spaces. +_nx_noop( 'I have %d cat.', 'I have %d cats. ', 'Not really.', 'my-slug' ); // Bad: trailing spaces. +_nx_noop( ' I have %d cat.', 'I have %d cats. ', 'Not really.', 'my-slug' ); // Bad: leading and trailing spaces. +esc_html__( ' string', 'my-slug' ); // Bad: leading space. +esc_html_e( 'string ', 'my-slug' ); // Bad: trailing space. +esc_html_x( ' string ', 'context', 'my-slug' ); // Bad: leading and trailing spaces. +esc_attr__( ' string', 'my-slug' ); // Bad: leading space. +esc_attr_e( 'string ', 'my-slug' ); // Bad: trailing space. +esc_attr_x( ' string ', 'context', 'my-slug' ); // Bad: leading and trailing spaces. + // phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment diff --git a/WordPress/Tests/WP/I18nUnitTest.php b/WordPress/Tests/WP/I18nUnitTest.php index 3834eb189f..f88102c710 100644 --- a/WordPress/Tests/WP/I18nUnitTest.php +++ b/WordPress/Tests/WP/I18nUnitTest.php @@ -148,6 +148,28 @@ public function getErrorList( $testFile = '' ) { 311 => 1, 315 => 1, 318 => 1, + 320 => 1, + 321 => 1, + 322 => 2, + 323 => 1, + 324 => 1, + 325 => 1, + 326 => 2, + 327 => 1, + 328 => 1, + 329 => 2, + 330 => 1, + 331 => 1, + 332 => 2, + 333 => 1, + 334 => 1, + 335 => 2, + 336 => 1, + 337 => 1, + 338 => 2, + 339 => 1, + 340 => 1, + 341 => 2, ); case 'I18nUnitTest.2.inc': From 436cd2506d7a21e22bff1738280a099bcd0e243c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Amieiro?= <1667814+amieiro@users.noreply.github.com> Date: Mon, 4 Nov 2024 11:33:27 +0100 Subject: [PATCH 2/8] Remove a debug code --- WordPress/Sniffs/WP/I18nSniff.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/WordPress/Sniffs/WP/I18nSniff.php b/WordPress/Sniffs/WP/I18nSniff.php index 7bc449a793..268d49be93 100644 --- a/WordPress/Sniffs/WP/I18nSniff.php +++ b/WordPress/Sniffs/WP/I18nSniff.php @@ -839,13 +839,6 @@ private function check_string_has_no_leading_trailing_spaces( $matched_content, array( $param_info['clean'] ) ); } - - if ('cadena' == $param_info['raw']) { - fwrite(STDERR, "\n" . '$matched_content: ' . print_r($matched_content, TRUE)); - fwrite(STDERR, "\n" . '$param_name: ' . print_r($param_name, TRUE)); - fwrite(STDERR, "\n" . '$param_info: ' . print_r($param_info, TRUE)); - exit(1); - } } /** From 7f311cb55e6f5356bf55edff8aa449263bef6061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Amieiro?= <1667814+amieiro@users.noreply.github.com> Date: Mon, 4 Nov 2024 11:50:33 +0100 Subject: [PATCH 3/8] Lint --- WordPress/Sniffs/WP/I18nSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/Sniffs/WP/I18nSniff.php b/WordPress/Sniffs/WP/I18nSniff.php index 268d49be93..3d7303307b 100644 --- a/WordPress/Sniffs/WP/I18nSniff.php +++ b/WordPress/Sniffs/WP/I18nSniff.php @@ -821,7 +821,7 @@ private function check_string_has_no_html_wrapper( $matched_content, $param_name private function check_string_has_no_leading_trailing_spaces( $matched_content, $param_name, $param_info ) { // Strip surrounding quotes. $content_without_quotes = TextStrings::stripQuotes( $param_info['clean'] ); - $first_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, $param_info['start'], ( $param_info['end'] + 1 ), true ); + $first_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, $param_info['start'], ( $param_info['end'] + 1 ), true ); if ( ltrim( $content_without_quotes ) !== $content_without_quotes ) { $this->phpcsFile->addError( From b18f6d4fe92a88556567af54d02211d552f2c7d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Amieiro?= <1667814+amieiro@users.noreply.github.com> Date: Tue, 10 Jun 2025 19:10:05 +0200 Subject: [PATCH 4/8] Add tabs to the checks --- WordPress/Tests/WP/I18nUnitTest.1.inc | 5 +++++ WordPress/Tests/WP/I18nUnitTest.1.inc.fixed | 5 +++++ WordPress/Tests/WP/I18nUnitTest.php | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/WordPress/Tests/WP/I18nUnitTest.1.inc b/WordPress/Tests/WP/I18nUnitTest.1.inc index d5d80f8e70..75782d6aea 100644 --- a/WordPress/Tests/WP/I18nUnitTest.1.inc +++ b/WordPress/Tests/WP/I18nUnitTest.1.inc @@ -339,5 +339,10 @@ esc_html_x( ' string ', 'context', 'my-slug' ); // Bad: leading and trailing spa esc_attr__( ' string', 'my-slug' ); // Bad: leading space. esc_attr_e( 'string ', 'my-slug' ); // Bad: trailing space. esc_attr_x( ' string ', 'context', 'my-slug' ); // Bad: leading and trailing spaces. +__( ' string', 'my-slug' ); // Bad: leading tab. +__( 'string ', 'my-slug' ); // Bad: trailing tab. +__( ' string ', 'my-slug' ); // Bad: leading and trailing tabs. +__( ' string', 'my-slug' ); // Bad: two leading tabs. +__( 'string ', 'my-slug' ); // Bad: two trailing tabs. // phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment diff --git a/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed b/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed index c884f83963..ae94daf740 100644 --- a/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed +++ b/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed @@ -339,5 +339,10 @@ esc_html_x( ' string ', 'context', 'my-slug' ); // Bad: leading and trailing spa esc_attr__( ' string', 'my-slug' ); // Bad: leading space. esc_attr_e( 'string ', 'my-slug' ); // Bad: trailing space. esc_attr_x( ' string ', 'context', 'my-slug' ); // Bad: leading and trailing spaces. +__( ' string', 'my-slug' ); // Bad: leading tab. +__( 'string ', 'my-slug' ); // Bad: trailing tab. +__( ' string ', 'my-slug' ); // Bad: leading and trailing tabs. +__( ' string', 'my-slug' ); // Bad: two leading tabs. +__( 'string ', 'my-slug' ); // Bad: two trailing tabs. // phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment diff --git a/WordPress/Tests/WP/I18nUnitTest.php b/WordPress/Tests/WP/I18nUnitTest.php index f88102c710..a486e60d7f 100644 --- a/WordPress/Tests/WP/I18nUnitTest.php +++ b/WordPress/Tests/WP/I18nUnitTest.php @@ -170,6 +170,11 @@ public function getErrorList( $testFile = '' ) { 339 => 1, 340 => 1, 341 => 2, + 342 => 1, + 343 => 1, + 344 => 2, + 345 => 1, + 346 => 1, ); case 'I18nUnitTest.2.inc': From 70dfe78ff3a6d7915db8056ca421ed8a76820eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Amieiro?= <1667814+amieiro@users.noreply.github.com> Date: Tue, 10 Jun 2025 19:35:44 +0200 Subject: [PATCH 5/8] Add new lines to the checks --- WordPress/Sniffs/WP/I18nSniff.php | 4 ++-- WordPress/Tests/WP/I18nUnitTest.1.inc | 13 +++++++++++++ WordPress/Tests/WP/I18nUnitTest.1.inc.fixed | 13 +++++++++++++ WordPress/Tests/WP/I18nUnitTest.php | 5 +++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/WordPress/Sniffs/WP/I18nSniff.php b/WordPress/Sniffs/WP/I18nSniff.php index 3d7303307b..d6b12f32dc 100644 --- a/WordPress/Sniffs/WP/I18nSniff.php +++ b/WordPress/Sniffs/WP/I18nSniff.php @@ -825,7 +825,7 @@ private function check_string_has_no_leading_trailing_spaces( $matched_content, if ( ltrim( $content_without_quotes ) !== $content_without_quotes ) { $this->phpcsFile->addError( - 'Translatable string should not have leading spaces. Found: %s', + 'Translatable string should not have leading spaces, tabs, or new lines. Found: %s', $first_non_empty, 'NoLeadingTrailingSpaces', array( $param_info['clean'] ) @@ -833,7 +833,7 @@ private function check_string_has_no_leading_trailing_spaces( $matched_content, } if ( rtrim( $content_without_quotes ) !== $content_without_quotes ) { $this->phpcsFile->addError( - 'Translatable string should not have trailing spaces. Found: %s', + 'Translatable string should not have trailing spaces, tabs, or new lines. Found: %s', $first_non_empty, 'NoLeadingTrailingSpaces', array( $param_info['clean'] ) diff --git a/WordPress/Tests/WP/I18nUnitTest.1.inc b/WordPress/Tests/WP/I18nUnitTest.1.inc index 75782d6aea..2a0feeed05 100644 --- a/WordPress/Tests/WP/I18nUnitTest.1.inc +++ b/WordPress/Tests/WP/I18nUnitTest.1.inc @@ -344,5 +344,18 @@ __( 'string ', 'my-slug' ); // Bad: trailing tab. __( ' string ', 'my-slug' ); // Bad: leading and trailing tabs. __( ' string', 'my-slug' ); // Bad: two leading tabs. __( 'string ', 'my-slug' ); // Bad: two trailing tabs. +__( ' +string', 'my-slug' ); // Bad: leading new line. +__( 'string +', 'my-slug' ); // Bad: trailing new line. +__( ' +string +', 'my-slug' ); // Bad: leading and trailing new line. +__( ' + +string', 'my-slug' ); // Bad: two leading new lines. +__( 'string + +', 'my-slug' ); // Bad: two trailing new lines. // phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment diff --git a/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed b/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed index ae94daf740..f411a07e38 100644 --- a/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed +++ b/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed @@ -344,5 +344,18 @@ __( 'string ', 'my-slug' ); // Bad: trailing tab. __( ' string ', 'my-slug' ); // Bad: leading and trailing tabs. __( ' string', 'my-slug' ); // Bad: two leading tabs. __( 'string ', 'my-slug' ); // Bad: two trailing tabs. +__( ' +string', 'my-slug' ); // Bad: leading new line. +__( 'string +', 'my-slug' ); // Bad: trailing new line. +__( ' +string +', 'my-slug' ); // Bad: leading and trailing new line. +__( ' + +string', 'my-slug' ); // Bad: two leading new lines. +__( 'string + +', 'my-slug' ); // Bad: two trailing new lines. // phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment diff --git a/WordPress/Tests/WP/I18nUnitTest.php b/WordPress/Tests/WP/I18nUnitTest.php index a486e60d7f..7e6e700155 100644 --- a/WordPress/Tests/WP/I18nUnitTest.php +++ b/WordPress/Tests/WP/I18nUnitTest.php @@ -175,6 +175,11 @@ public function getErrorList( $testFile = '' ) { 344 => 2, 345 => 1, 346 => 1, + 347 => 1, + 349 => 1, + 351 => 2, + 354 => 1, + 357 => 1, ); case 'I18nUnitTest.2.inc': From 8d8b411f2f89dc4d2e2969c8f5225b8603ad507e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Amieiro?= <1667814+amieiro@users.noreply.github.com> Date: Wed, 11 Jun 2025 06:55:54 +0200 Subject: [PATCH 6/8] Refactor the method to have different error messages for each check --- WordPress/Sniffs/WP/I18nSniff.php | 63 ++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/WordPress/Sniffs/WP/I18nSniff.php b/WordPress/Sniffs/WP/I18nSniff.php index c21de0f285..a53dff255b 100644 --- a/WordPress/Sniffs/WP/I18nSniff.php +++ b/WordPress/Sniffs/WP/I18nSniff.php @@ -823,19 +823,70 @@ private function check_string_has_no_leading_trailing_spaces( $matched_content, $content_without_quotes = TextStrings::stripQuotes( $param_info['clean'] ); $first_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, $param_info['start'], ( $param_info['end'] + 1 ), true ); - if ( ltrim( $content_without_quotes ) !== $content_without_quotes ) { + // Define regex patterns. + $pattern_leading_spaces = '/^[ ]+/u'; + $pattern_trailing_spaces = '/[ ]+$/u'; + $pattern_leading_tabs = '/^\t+/u'; + $pattern_trailing_tabs = '/\t+$/u'; + $pattern_leading_newlines = '/^[\r\n]+/u'; + $pattern_trailing_newlines = '/[\r\n]+$/u'; + + // Check for leading spaces. + if ( preg_match( $pattern_leading_spaces, $content_without_quotes ) ) { $this->phpcsFile->addError( - 'Translatable string should not have leading spaces, tabs, or new lines. Found: %s', + 'Translatable string should not have leading spaces. Found: %s', $first_non_empty, - 'NoLeadingTrailingSpaces', + 'LeadingSpaces', array( $param_info['clean'] ) ); } - if ( rtrim( $content_without_quotes ) !== $content_without_quotes ) { + + // Check for trailing spaces. + if ( preg_match( $pattern_trailing_spaces, $content_without_quotes ) ) { $this->phpcsFile->addError( - 'Translatable string should not have trailing spaces, tabs, or new lines. Found: %s', + 'Translatable string should not have trailing spaces. Found: %s', $first_non_empty, - 'NoLeadingTrailingSpaces', + 'TrailingSpaces', + array( $param_info['clean'] ) + ); + } + + // Check for leading tabs. + if ( preg_match( $pattern_leading_tabs, $content_without_quotes ) ) { + $this->phpcsFile->addError( + 'Translatable string should not have leading tabs. Found: %s', + $first_non_empty, + 'LeadingTabs', + array( $param_info['clean'] ) + ); + } + + // Check for trailing tabs. + if ( preg_match( $pattern_trailing_tabs, $content_without_quotes ) ) { + $this->phpcsFile->addError( + 'Translatable string should not have trailing tabs. Found: %s', + $first_non_empty, + 'TrailingTabs', + array( $param_info['clean'] ) + ); + } + + // Check for leading new lines. + if ( preg_match( $pattern_leading_newlines, $content_without_quotes ) ) { + $this->phpcsFile->addError( + 'Translatable string should not have leading new lines. Found: %s', + $first_non_empty, + 'LeadingNewLines', + array( $param_info['clean'] ) + ); + } + + // Check for trailing new lines. + if ( preg_match( $pattern_trailing_newlines, $content_without_quotes ) ) { + $this->phpcsFile->addError( + 'Translatable string should not have trailing new lines. Found: %s', + $first_non_empty, + 'TrailingNewLines', array( $param_info['clean'] ) ); } From 8be3ea1ca9624f4fb86db2c969e1969160161878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Amieiro?= <1667814+amieiro@users.noreply.github.com> Date: Wed, 11 Jun 2025 07:25:27 +0200 Subject: [PATCH 7/8] Add vertical tabs to the checks --- WordPress/Sniffs/WP/I18nSniff.php | 22 +++++++++++++++++++++ WordPress/Tests/WP/I18nUnitTest.1.inc | 5 +++++ WordPress/Tests/WP/I18nUnitTest.1.inc.fixed | 5 +++++ WordPress/Tests/WP/I18nUnitTest.php | 5 +++++ 4 files changed, 37 insertions(+) diff --git a/WordPress/Sniffs/WP/I18nSniff.php b/WordPress/Sniffs/WP/I18nSniff.php index a53dff255b..c3829d2c13 100644 --- a/WordPress/Sniffs/WP/I18nSniff.php +++ b/WordPress/Sniffs/WP/I18nSniff.php @@ -830,6 +830,8 @@ private function check_string_has_no_leading_trailing_spaces( $matched_content, $pattern_trailing_tabs = '/\t+$/u'; $pattern_leading_newlines = '/^[\r\n]+/u'; $pattern_trailing_newlines = '/[\r\n]+$/u'; + $pattern_leading_vtabs = '/^\x0B+/u'; + $pattern_trailing_vtabs = '/\x0B+$/u'; // Check for leading spaces. if ( preg_match( $pattern_leading_spaces, $content_without_quotes ) ) { @@ -890,6 +892,26 @@ private function check_string_has_no_leading_trailing_spaces( $matched_content, array( $param_info['clean'] ) ); } + + // Check for leading vertical tabs. + if ( preg_match( $pattern_leading_vtabs, $content_without_quotes ) ) { + $this->phpcsFile->addError( + 'Translatable string should not have leading vertical tabs. Found: %s', + $first_non_empty, + 'LeadingVTabs', + array( $param_info['clean'] ) + ); + } + + // Check for trailing vertical tabs. + if ( preg_match( $pattern_trailing_vtabs, $content_without_quotes ) ) { + $this->phpcsFile->addError( + 'Translatable string should not have trailing vertical tabs. Found: %s', + $first_non_empty, + 'TrailingVTabs', + array( $param_info['clean'] ) + ); + } } /** diff --git a/WordPress/Tests/WP/I18nUnitTest.1.inc b/WordPress/Tests/WP/I18nUnitTest.1.inc index 2a0feeed05..272d2157fb 100644 --- a/WordPress/Tests/WP/I18nUnitTest.1.inc +++ b/WordPress/Tests/WP/I18nUnitTest.1.inc @@ -357,5 +357,10 @@ string', 'my-slug' ); // Bad: two leading new lines. __( 'string ', 'my-slug' ); // Bad: two trailing new lines. +__( " String with leading vertical tab", 'my-slug' ); // Bad, has leading vertical tab. +__( "String with trailing vertical tab ", 'my-slug' ); // Bad, has trailing vertical tab. +__( " String with leading and trailing vertical tabs ", 'my-slug' ); // Bad, has both leading and trailing vertical tabs. +__( " String with 2 leading vertical tabs", 'my-slug' ); // Bad, has 2 leading vertical tabs. +__( "String with 2 trailing vertical tabs ", 'my-slug' ); // Bad, has 2 trailing vertical tabs. // phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment diff --git a/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed b/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed index f411a07e38..2e4621092f 100644 --- a/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed +++ b/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed @@ -357,5 +357,10 @@ string', 'my-slug' ); // Bad: two leading new lines. __( 'string ', 'my-slug' ); // Bad: two trailing new lines. +__( " String with leading vertical tab", 'my-slug' ); // Bad, has leading vertical tab. +__( "String with trailing vertical tab ", 'my-slug' ); // Bad, has trailing vertical tab. +__( " String with leading and trailing vertical tabs ", 'my-slug' ); // Bad, has both leading and trailing vertical tabs. +__( " String with 2 leading vertical tabs", 'my-slug' ); // Bad, has 2 leading vertical tabs. +__( "String with 2 trailing vertical tabs ", 'my-slug' ); // Bad, has 2 trailing vertical tabs. // phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment diff --git a/WordPress/Tests/WP/I18nUnitTest.php b/WordPress/Tests/WP/I18nUnitTest.php index 7e6e700155..7e042dd21f 100644 --- a/WordPress/Tests/WP/I18nUnitTest.php +++ b/WordPress/Tests/WP/I18nUnitTest.php @@ -180,6 +180,11 @@ public function getErrorList( $testFile = '' ) { 351 => 2, 354 => 1, 357 => 1, + 360 => 1, + 361 => 1, + 362 => 2, + 363 => 1, + 364 => 1, ); case 'I18nUnitTest.2.inc': From fe679bdd86909ddbbffdcd3d8dd74ae3f32c94ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Amieiro?= <1667814+amieiro@users.noreply.github.com> Date: Fri, 13 Jun 2025 19:29:41 +0200 Subject: [PATCH 8/8] Change the regexs to use hex codes and reorganize some code --- WordPress/Sniffs/WP/I18nSniff.php | 46 ++++++++++----------- WordPress/Tests/WP/I18nUnitTest.1.inc | 10 ++--- WordPress/Tests/WP/I18nUnitTest.1.inc.fixed | 10 ++--- WordPress/Tests/WP/I18nUnitTest.php | 16 +++---- 4 files changed, 41 insertions(+), 41 deletions(-) diff --git a/WordPress/Sniffs/WP/I18nSniff.php b/WordPress/Sniffs/WP/I18nSniff.php index c3829d2c13..e0a96580bb 100644 --- a/WordPress/Sniffs/WP/I18nSniff.php +++ b/WordPress/Sniffs/WP/I18nSniff.php @@ -824,14 +824,14 @@ private function check_string_has_no_leading_trailing_spaces( $matched_content, $first_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, $param_info['start'], ( $param_info['end'] + 1 ), true ); // Define regex patterns. - $pattern_leading_spaces = '/^[ ]+/u'; - $pattern_trailing_spaces = '/[ ]+$/u'; - $pattern_leading_tabs = '/^\t+/u'; - $pattern_trailing_tabs = '/\t+$/u'; - $pattern_leading_newlines = '/^[\r\n]+/u'; - $pattern_trailing_newlines = '/[\r\n]+$/u'; + $pattern_leading_spaces = '/^[\x20]+/u'; + $pattern_trailing_spaces = '/[\x20]+$/u'; + $pattern_leading_tabs = '/^\x09+/u'; + $pattern_trailing_tabs = '/\x09+$/u'; $pattern_leading_vtabs = '/^\x0B+/u'; $pattern_trailing_vtabs = '/\x0B+$/u'; + $pattern_leading_newlines = '/^\x0A+/u'; + $pattern_trailing_newlines = '/\x0A+$/u'; // Check for leading spaces. if ( preg_match( $pattern_leading_spaces, $content_without_quotes ) ) { @@ -873,42 +873,42 @@ private function check_string_has_no_leading_trailing_spaces( $matched_content, ); } - // Check for leading new lines. - if ( preg_match( $pattern_leading_newlines, $content_without_quotes ) ) { + // Check for leading vertical tabs. + if ( preg_match( $pattern_leading_vtabs, $content_without_quotes ) ) { $this->phpcsFile->addError( - 'Translatable string should not have leading new lines. Found: %s', + 'Translatable string should not have leading vertical tabs. Found: %s', $first_non_empty, - 'LeadingNewLines', + 'LeadingVTabs', array( $param_info['clean'] ) ); } - // Check for trailing new lines. - if ( preg_match( $pattern_trailing_newlines, $content_without_quotes ) ) { + // Check for trailing vertical tabs. + if ( preg_match( $pattern_trailing_vtabs, $content_without_quotes ) ) { $this->phpcsFile->addError( - 'Translatable string should not have trailing new lines. Found: %s', + 'Translatable string should not have trailing vertical tabs. Found: %s', $first_non_empty, - 'TrailingNewLines', + 'TrailingVTabs', array( $param_info['clean'] ) ); } - - // Check for leading vertical tabs. - if ( preg_match( $pattern_leading_vtabs, $content_without_quotes ) ) { + + // Check for leading new lines. + if ( preg_match( $pattern_leading_newlines, $content_without_quotes ) ) { $this->phpcsFile->addError( - 'Translatable string should not have leading vertical tabs. Found: %s', + 'Translatable string should not have leading new lines. Found: %s', $first_non_empty, - 'LeadingVTabs', + 'LeadingNewLines', array( $param_info['clean'] ) ); } - // Check for trailing vertical tabs. - if ( preg_match( $pattern_trailing_vtabs, $content_without_quotes ) ) { + // Check for trailing new lines. + if ( preg_match( $pattern_trailing_newlines, $content_without_quotes ) ) { $this->phpcsFile->addError( - 'Translatable string should not have trailing vertical tabs. Found: %s', + 'Translatable string should not have trailing new lines. Found: %s', $first_non_empty, - 'TrailingVTabs', + 'TrailingNewLines', array( $param_info['clean'] ) ); } diff --git a/WordPress/Tests/WP/I18nUnitTest.1.inc b/WordPress/Tests/WP/I18nUnitTest.1.inc index 272d2157fb..3e10d4db49 100644 --- a/WordPress/Tests/WP/I18nUnitTest.1.inc +++ b/WordPress/Tests/WP/I18nUnitTest.1.inc @@ -344,6 +344,11 @@ __( 'string ', 'my-slug' ); // Bad: trailing tab. __( ' string ', 'my-slug' ); // Bad: leading and trailing tabs. __( ' string', 'my-slug' ); // Bad: two leading tabs. __( 'string ', 'my-slug' ); // Bad: two trailing tabs. +__( " String with leading vertical tab", 'my-slug' ); // Bad: leading vertical tab. +__( "String with trailing vertical tab ", 'my-slug' ); // Bad: trailing vertical tab. +__( " String with leading and trailing vertical tabs ", 'my-slug' ); // Bad: leading and trailing vertical tabs. +__( " String with 2 leading vertical tabs", 'my-slug' ); // Bad: 2 leading vertical tabs. +__( "String with 2 trailing vertical tabs ", 'my-slug' ); // Bad: 2 trailing vertical tabs. __( ' string', 'my-slug' ); // Bad: leading new line. __( 'string @@ -357,10 +362,5 @@ string', 'my-slug' ); // Bad: two leading new lines. __( 'string ', 'my-slug' ); // Bad: two trailing new lines. -__( " String with leading vertical tab", 'my-slug' ); // Bad, has leading vertical tab. -__( "String with trailing vertical tab ", 'my-slug' ); // Bad, has trailing vertical tab. -__( " String with leading and trailing vertical tabs ", 'my-slug' ); // Bad, has both leading and trailing vertical tabs. -__( " String with 2 leading vertical tabs", 'my-slug' ); // Bad, has 2 leading vertical tabs. -__( "String with 2 trailing vertical tabs ", 'my-slug' ); // Bad, has 2 trailing vertical tabs. // phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment diff --git a/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed b/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed index 2e4621092f..17558228da 100644 --- a/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed +++ b/WordPress/Tests/WP/I18nUnitTest.1.inc.fixed @@ -344,6 +344,11 @@ __( 'string ', 'my-slug' ); // Bad: trailing tab. __( ' string ', 'my-slug' ); // Bad: leading and trailing tabs. __( ' string', 'my-slug' ); // Bad: two leading tabs. __( 'string ', 'my-slug' ); // Bad: two trailing tabs. +__( " String with leading vertical tab", 'my-slug' ); // Bad: leading vertical tab. +__( "String with trailing vertical tab ", 'my-slug' ); // Bad: trailing vertical tab. +__( " String with leading and trailing vertical tabs ", 'my-slug' ); // Bad: leading and trailing vertical tabs. +__( " String with 2 leading vertical tabs", 'my-slug' ); // Bad: 2 leading vertical tabs. +__( "String with 2 trailing vertical tabs ", 'my-slug' ); // Bad: 2 trailing vertical tabs. __( ' string', 'my-slug' ); // Bad: leading new line. __( 'string @@ -357,10 +362,5 @@ string', 'my-slug' ); // Bad: two leading new lines. __( 'string ', 'my-slug' ); // Bad: two trailing new lines. -__( " String with leading vertical tab", 'my-slug' ); // Bad, has leading vertical tab. -__( "String with trailing vertical tab ", 'my-slug' ); // Bad, has trailing vertical tab. -__( " String with leading and trailing vertical tabs ", 'my-slug' ); // Bad, has both leading and trailing vertical tabs. -__( " String with 2 leading vertical tabs", 'my-slug' ); // Bad, has 2 leading vertical tabs. -__( "String with 2 trailing vertical tabs ", 'my-slug' ); // Bad, has 2 trailing vertical tabs. // phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment diff --git a/WordPress/Tests/WP/I18nUnitTest.php b/WordPress/Tests/WP/I18nUnitTest.php index 7e042dd21f..131acc2cb4 100644 --- a/WordPress/Tests/WP/I18nUnitTest.php +++ b/WordPress/Tests/WP/I18nUnitTest.php @@ -176,15 +176,15 @@ public function getErrorList( $testFile = '' ) { 345 => 1, 346 => 1, 347 => 1, - 349 => 1, - 351 => 2, + 348 => 1, + 349 => 2, + 350 => 1, + 351 => 1, + 352 => 1, 354 => 1, - 357 => 1, - 360 => 1, - 361 => 1, - 362 => 2, - 363 => 1, - 364 => 1, + 356 => 2, + 359 => 1, + 362 => 1, ); case 'I18nUnitTest.2.inc':