diff --git a/src/wp-includes/class-wp-locale.php b/src/wp-includes/class-wp-locale.php index ea8b67c987..82a79c3750 100644 --- a/src/wp-includes/class-wp-locale.php +++ b/src/wp-includes/class-wp-locale.php @@ -112,6 +112,16 @@ class WP_Locale { */ public $list_item_separator; + /** + * The word count type of the locale language. + * + * Default is 'words'. + * + * @since 6.2.0 + * @var string + */ + public $word_count_type; + /** * Constructor which calls helper methods to set up object variables. * @@ -236,6 +246,9 @@ class WP_Locale { } elseif ( 'rtl' === _x( 'ltr', 'text direction' ) ) { $this->text_direction = 'rtl'; } + + // Set the word count type. + $this->word_count_type = $this->get_word_count_type(); } /** @@ -396,4 +409,31 @@ class WP_Locale { public function get_list_item_separator() { return $this->list_item_separator; } + + /** + * Retrieves the localized word count type. + * + * Options are 'characters_excluding_spaces', 'characters_including_spaces or 'words'. Defaults to 'words'. + * + * @since 6.2.0 + * + * @return string Localized word count type. + */ + public function get_word_count_type() { + + /* + * translators: If your word count is based on single characters (e.g. East Asian characters), + * enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'. + * Do not translate into your own language. + */ + $word_count_type = is_null( $this->word_count_type ) ? _x( 'words', 'Word count type. Do not translate!' ) : $this->word_count_type; + + // Check for valid types. + if ( 'characters_excluding_spaces' !== $word_count_type && 'characters_including_spaces' !== $word_count_type ) { + // Defaults to 'words'. + $word_count_type = 'words'; + } + + return $word_count_type; + } } diff --git a/src/wp-includes/formatting.php b/src/wp-includes/formatting.php index 2cc27ad069..d598d354d3 100644 --- a/src/wp-includes/formatting.php +++ b/src/wp-includes/formatting.php @@ -3945,12 +3945,7 @@ function wp_trim_words( $text, $num_words = 55, $more = null ) { $text = wp_strip_all_tags( $text ); $num_words = (int) $num_words; - /* - * translators: If your word count is based on single characters (e.g. East Asian characters), - * enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'. - * Do not translate into your own language. - */ - if ( strpos( _x( 'words', 'Word count type. Do not translate!' ), 'characters' ) === 0 && preg_match( '/^utf\-?8$/i', get_option( 'blog_charset' ) ) ) { + if ( str_starts_with( wp_get_word_count_type(), 'characters' ) && preg_match( '/^utf\-?8$/i', get_option( 'blog_charset' ) ) ) { $text = trim( preg_replace( "/[\n\r\t ]+/", ' ', $text ), ' ' ); preg_match_all( '/./u', $text, $words_array ); $words_array = array_slice( $words_array[0], 0, $num_words + 1 ); diff --git a/src/wp-includes/l10n.php b/src/wp-includes/l10n.php index f3dbc282bb..3a620ee3ca 100644 --- a/src/wp-includes/l10n.php +++ b/src/wp-includes/l10n.php @@ -1809,3 +1809,18 @@ function wp_get_list_item_separator() { return $wp_locale->get_list_item_separator(); } + +/** + * Retrieves the word count type based on the locale. + * + * @since 6.2.0 + * + * @global WP_Locale $wp_locale WordPress date and time locale object. + * + * @return string Locale-specific word count type. + */ +function wp_get_word_count_type() { + global $wp_locale; + + return $wp_locale->get_word_count_type(); +} diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index a150dd9474..894c2d7936 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -1831,12 +1831,7 @@ function wp_just_in_time_script_localization() { 'word-count', 'wordCountL10n', array( - /* - * translators: If your word count is based on single characters (e.g. East Asian characters), - * enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'. - * Do not translate into your own language. - */ - 'type' => _x( 'words', 'Word count type. Do not translate!' ), + 'type' => wp_get_word_count_type(), 'shortcodes' => ! empty( $GLOBALS['shortcode_tags'] ) ? array_keys( $GLOBALS['shortcode_tags'] ) : array(), ) ); diff --git a/tests/phpunit/tests/locale.php b/tests/phpunit/tests/locale.php index a3a100547e..b672d08121 100644 --- a/tests/phpunit/tests/locale.php +++ b/tests/phpunit/tests/locale.php @@ -173,6 +173,62 @@ class Tests_Locale extends WP_UnitTestCase { $this->locale->text_direction = 'ltr'; $this->assertFalse( $this->locale->is_rtl() ); } + + /** + * Tests that `WP_Locale::get_word_count_type()` returns + * the appropriate value. + * + * @ticket 56698 + * + * @covers WP_Locale::get_word_count_type + * + * @dataProvider data_get_word_count_type + * + * @param string $word_count_type The word count type. + * @param string $expected The expected return value. + */ + public function test_get_word_count_type( $word_count_type, $expected ) { + if ( is_string( $word_count_type ) ) { + $this->locale->word_count_type = $word_count_type; + + } + + $this->assertSame( $expected, $this->locale->get_word_count_type() ); + } + + /** + * Data provider. + * + * @return array[] + */ + public function data_get_word_count_type() { + return array( + 'default' => array( + 'word_count_type' => null, + 'expected' => 'words', + ), + 'empty string' => array( + 'word_count_type' => '', + 'expected' => 'words', + ), + 'an invalid option - "foo"' => array( + 'word_count_type' => 'foo', + 'expected' => 'words', + ), + 'a valid option - "words"' => array( + 'word_count_type' => 'words', + 'expected' => 'words', + ), + 'a valid option - "characters_excluding_spaces"' => array( + 'word_count_type' => 'characters_excluding_spaces', + 'expected' => 'characters_excluding_spaces', + ), + 'a valid option - "characters_including_spaces"' => array( + 'word_count_type' => 'characters_including_spaces', + 'expected' => 'characters_including_spaces', + ), + ); + } } class Custom_WP_Locale extends WP_Locale {