diff --git a/src/wp-admin/includes/dashboard.php b/src/wp-admin/includes/dashboard.php index 9c7f93c430..a622f0e7cf 100644 --- a/src/wp-admin/includes/dashboard.php +++ b/src/wp-admin/includes/dashboard.php @@ -584,6 +584,9 @@ function wp_dashboard_recent_drafts( $drafts = false ) { } echo '
' . $the_content . '
'; } echo "\n"; diff --git a/src/wp-includes/comment-template.php b/src/wp-includes/comment-template.php index 5158a6f8a7..ca0a8de714 100644 --- a/src/wp-includes/comment-template.php +++ b/src/wp-includes/comment-template.php @@ -577,42 +577,35 @@ function comment_date( $d = '', $comment_ID = 0 ) { } /** - * Retrieve the excerpt of the current comment. + * Retrieves the excerpt of the given comment. * - * Will cut each word and only output the first 20 words with '…' at the end. - * If the word count is less than 20, then no truncating is done and no '…' - * will appear. + * Returns a maximum of 20 words with an ellipsis appended if necessary. * * @since 1.5.0 * @since 4.4.0 Added the ability for `$comment_ID` to also accept a WP_Comment object. * * @param int|WP_Comment $comment_ID WP_Comment or ID of the comment for which to get the excerpt. * Default current comment. - * @return string The maybe truncated comment with 20 words or less. + * @return string The possibly truncated comment excerpt. */ function get_comment_excerpt( $comment_ID = 0 ) { $comment = get_comment( $comment_ID ); $comment_text = strip_tags( str_replace( array( "\n", "\r" ), ' ', $comment->comment_content ) ); - $words = explode( ' ', $comment_text ); + + /* translators: Maximum number of words used in a comment excerpt. */ + $comment_excerpt_length = intval( _x( '20', 'comment_excerpt_length' ) ); /** - * Filters the amount of words used in the comment excerpt. + * Filters the maximum number of words used in the comment excerpt. * * @since 4.4.0 * * @param int $comment_excerpt_length The amount of words you want to display in the comment excerpt. */ - $comment_excerpt_length = apply_filters( 'comment_excerpt_length', 20 ); + $comment_excerpt_length = apply_filters( 'comment_excerpt_length', $comment_excerpt_length ); - $use_ellipsis = count( $words ) > $comment_excerpt_length; - if ( $use_ellipsis ) { - $words = array_slice( $words, 0, $comment_excerpt_length ); - } + $excerpt = wp_trim_words( $comment_text, $comment_excerpt_length, '…' ); - $excerpt = trim( join( ' ', $words ) ); - if ( $use_ellipsis ) { - $excerpt .= '…'; - } /** * Filters the retrieved comment excerpt. * diff --git a/src/wp-includes/formatting.php b/src/wp-includes/formatting.php index 51a1388dfd..a76a4927b7 100644 --- a/src/wp-includes/formatting.php +++ b/src/wp-includes/formatting.php @@ -3680,9 +3680,7 @@ function human_time_diff( $from, $to = '' ) { /** * Generates an excerpt from the content, if needed. * - * The excerpt word amount will be 55 words and if the amount is greater than - * that, then the string ' […]' will be appended to the excerpt. If the string - * is less than 55 words, then the content will be returned as is. + * Returns a maximum of 55 words with an ellipsis appended if necessary. * * The 55 word limit can be modified by plugins/themes using the {@see 'excerpt_length'} filter * The ' […]' string can be modified by plugins/themes using the {@see 'excerpt_more'} filter @@ -3707,14 +3705,18 @@ function wp_trim_excerpt( $text = '', $post = null ) { $text = apply_filters( 'the_content', $text ); $text = str_replace( ']]>', ']]>', $text ); + /* translators: Maximum number of words used in a post excerpt. */ + $excerpt_length = intval( _x( '55', 'excerpt_length' ) ); + /** - * Filters the number of words in an excerpt. + * Filters the maximum number of words in a post excerpt. * * @since 2.7.0 * - * @param int $number The number of words. Default 55. + * @param int $number The maximum number of words. Default 55. */ - $excerpt_length = apply_filters( 'excerpt_length', 55 ); + $excerpt_length = apply_filters( 'excerpt_length', $excerpt_length ); + /** * Filters the string in the "more" link displayed after a trimmed excerpt. * @@ -3725,6 +3727,7 @@ function wp_trim_excerpt( $text = '', $post = null ) { $excerpt_more = apply_filters( 'excerpt_more', ' ' . '[…]' ); $text = wp_trim_words( $text, $excerpt_length, $excerpt_more ); } + /** * Filters the trimmed excerpt string. * diff --git a/tests/phpunit/data/languages/ja_JP.mo b/tests/phpunit/data/languages/ja_JP.mo index 1399898aa7..da1681326c 100644 Binary files a/tests/phpunit/data/languages/ja_JP.mo and b/tests/phpunit/data/languages/ja_JP.mo differ diff --git a/tests/phpunit/data/languages/ja_JP.po b/tests/phpunit/data/languages/ja_JP.po index f71a737714..bd9cd17a95 100644 --- a/tests/phpunit/data/languages/ja_JP.po +++ b/tests/phpunit/data/languages/ja_JP.po @@ -40,3 +40,30 @@ msgstr "number_format_thousands_sep" #: wp-includes/script-loader.php:620 msgid "Update %s now" msgstr "今すぐ %s を更新" + +#. 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. +#: wp-includes/formatting.php:3372 wp-includes/script-loader.php:1100 +msgctxt "Word count type. Do not translate!" +msgid "words" +msgstr "characters_including_spaces" + +#. translators: Maximum number of words used in a post excerpt. +#: wp-includes/formatting.php:3640 +msgctxt "excerpt_length" +msgid "55" +msgstr "110" + +#. translators: Maximum number of words used in a comment excerpt. +#: wp-includes/comment-template.ph:599 +msgctxt "comment_excerpt_length" +msgid "20" +msgstr "40" + +#. translators: Maximum number of words used in a preview of a draft on the dashboard. +#: wp-admin/includes/dashboard.php:591 +msgctxt "draft_length" +msgid "10" +msgstr "40" diff --git a/tests/phpunit/tests/formatting/WPTrimWords.php b/tests/phpunit/tests/formatting/WPTrimWords.php index 7f2a27fc05..fab62372f7 100644 --- a/tests/phpunit/tests/formatting/WPTrimWords.php +++ b/tests/phpunit/tests/formatting/WPTrimWords.php @@ -4,6 +4,14 @@ * @group formatting */ class Tests_Formatting_WPTrimWords extends WP_UnitTestCase { + + /** + * Long Dummy Text. + * + * @since 5.0.0 + * + * @var string $long_text + */ private $long_text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce varius lacinia vehicula. Etiam sapien risus, ultricies ac posuere eu, convallis sit amet augue. Pellentesque urna massa, lacinia vel iaculis eget, bibendum in mauris. Aenean eleifend pulvinar ligula, a convallis eros gravida non. Suspendisse potenti. Pellentesque et odio tortor. In vulputate pellentesque libero, sed dapibus velit mollis viverra. Pellentesque id urna euismod dolor cursus sagittis.'; function test_trims_to_55_by_default() { @@ -42,4 +50,27 @@ class Tests_Formatting_WPTrimWords extends WP_UnitTestCase { $text = 'This is some short text.'; $this->assertEquals( $text, wp_trim_words( $text ) ); } + + /** + * @ticket 44541 + */ + function test_trims_to_20_counted_by_chars() { + switch_to_locale( 'ja_JP' ); + $expected = substr( $this->long_text, 0, 20 ) . '…'; + $actual = wp_trim_words( $this->long_text, 20 ); + restore_previous_locale(); + $this->assertEquals( $expected, $actual ); + } + + /** + * @ticket 44541 + */ + function test_trims_to_20_counted_by_chars_with_double_width_chars() { + switch_to_locale( 'ja_JP' ); + $text = str_repeat( 'あ', 100 ); + $expected = str_repeat( 'あ', 19 ) . '…'; + $actual = wp_trim_words( $text, 19 ); + restore_previous_locale(); + $this->assertEquals( $expected, $actual ); + } } diff --git a/tests/phpunit/tests/l10n.php b/tests/phpunit/tests/l10n.php index 45a6008363..7b34d32b4e 100644 --- a/tests/phpunit/tests/l10n.php +++ b/tests/phpunit/tests/l10n.php @@ -6,6 +6,15 @@ */ class Tests_L10n extends WP_UnitTestCase { + /** + * Long Dummy Text. + * + * @since 5.0.0 + * + * @var string $long_text + */ + private $long_text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'; + /** * @ticket 35961 */ @@ -260,4 +269,251 @@ class Tests_L10n extends WP_UnitTestCase { $this->assertNotEmpty( $array['Project-Id-Version'] ); $this->assertNotEmpty( $array['X-Generator'] ); } + + /** + * @ticket 44541 + */ + function test_length_of_excerpt_should_be_counted_by_words() { + global $post; + + switch_to_locale( 'en_US' ); + + $args = array( + 'post_content' => $this->long_text, + 'post_excerpt' => '', + ); + + $post = $this->factory()->post->create_and_get( $args ); + setup_postdata( $post ); + + $expect = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat […]
\n"; + the_excerpt(); + + restore_previous_locale(); + + $this->expectOutputString( $expect ); + } + + /** + * @ticket 44541 + */ + function test_length_of_excerpt_should_be_counted_by_chars() { + global $post; + + switch_to_locale( 'ja_JP' ); + + $args = array( + 'post_content' => $this->long_text, + 'post_excerpt' => '', + ); + + $post = $this->factory()->post->create_and_get( $args ); + setup_postdata( $post ); + + $expect = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore […]
\n"; + the_excerpt(); + + restore_previous_locale(); + + $this->expectOutputString( $expect ); + } + + /** + * @ticket 44541 + */ + function test_length_of_excerpt_should_be_counted_by_chars_in_japanese() { + global $post; + + switch_to_locale( 'ja_JP' ); + + $args = array( + 'post_content' => str_repeat( 'あ', 200 ), + 'post_excerpt' => '', + ); + + $post = $this->factory()->post->create_and_get( $args ); + setup_postdata( $post ); + + $expect = '' . str_repeat( 'あ', 110 ) . " […]
\n"; + the_excerpt(); + + restore_previous_locale(); + + $this->expectOutputString( $expect ); + } + + /** + * @ticket 44541 + */ + function test_length_of_excerpt_rss_should_be_counted_by_words() { + global $post; + + switch_to_locale( 'en_US' ); + + $args = array( + 'post_content' => $this->long_text, + 'post_excerpt' => '', + ); + + $post = $this->factory()->post->create_and_get( $args ); + setup_postdata( $post ); + + $expect = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat […]'; + the_excerpt_rss(); + + restore_previous_locale(); + + $this->expectOutputString( $expect ); + } + + /** + * @ticket 44541 + */ + function test_length_of_excerpt_rss_should_be_counted_by_chars() { + global $post; + + switch_to_locale( 'ja_JP' ); + + $args = array( + 'post_content' => $this->long_text, + 'post_excerpt' => '', + ); + + $post = $this->factory()->post->create_and_get( $args ); + setup_postdata( $post ); + + $expect = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore […]'; + + the_excerpt_rss(); + + restore_previous_locale(); + + $this->expectOutputString( $expect ); + } + + /** + * @ticket 44541 + */ + function test_length_of_draft_should_be_counted_by_words() { + require_once ABSPATH . 'wp-admin/includes/dashboard.php'; + + switch_to_locale( 'en_US' ); + + $args = array( + 'post_content' => $this->long_text, + 'post_excerpt' => '', + 'post_status' => 'draft', + ); + + $this->factory()->post->create( $args ); + + $expect = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do…'; + wp_dashboard_recent_drafts(); + + restore_previous_locale(); + + $this->expectOutputRegex( '/' . $expect . '/' ); + } + + /** + * @ticket 44541 + */ + function test_length_of_draft_should_be_counted_by_chars() { + require_once ABSPATH . 'wp-admin/includes/dashboard.php'; + + switch_to_locale( 'ja_JP' ); + + $args = array( + 'post_content' => $this->long_text, + 'post_excerpt' => '', + 'post_status' => 'draft', + ); + + $post = $this->factory()->post->create( $args ); + + $expect = 'Lorem ipsum dolor sit amet, consectetur …'; + wp_dashboard_recent_drafts(); + + restore_previous_locale(); + + $this->expectOutputRegex( '/' . $expect . '/' ); + } + + /** + * @ticket 44541 + */ + function test_length_of_draft_should_be_counted_by_chars_in_japanese() { + require_once ABSPATH . 'wp-admin/includes/dashboard.php'; + + switch_to_locale( 'ja_JP' ); + + $args = array( + 'post_content' => str_repeat( 'あ', 200 ), + 'post_excerpt' => '', + 'post_status' => 'draft', + ); + + $this->factory()->post->create( $args ); + + $expect = str_repeat( 'あ', 40 ) . '…'; + wp_dashboard_recent_drafts(); + + restore_previous_locale(); + + $this->expectOutputRegex( '/' . $expect . '/' ); + } + + /** + * @ticket 44541 + */ + function test_length_of_comment_excerpt_should_be_counted_by_words() { + switch_to_locale( 'en_US' ); + + $args = array( + 'comment_content' => $this->long_text, + ); + $comment_id = $this->factory()->comment->create( $args ); + $expect = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut…'; + $comment_excerpt = get_comment_excerpt( $comment_id ); + + restore_previous_locale(); + + $this->assertSame( $expect, $comment_excerpt ); + } + + /** + * @ticket 44541 + */ + function test_length_of_comment_excerpt_should_be_counted_by_chars() { + switch_to_locale( 'ja_JP' ); + + $args = array( + 'comment_content' => $this->long_text, + ); + $comment_id = $this->factory()->comment->create( $args ); + $expect = 'Lorem ipsum dolor sit amet, consectetur …'; + $comment_excerpt = get_comment_excerpt( $comment_id ); + + restore_previous_locale(); + + $this->assertSame( $expect, $comment_excerpt ); + } + + /** + * @ticket 44541 + */ + function test_length_of_comment_excerpt_should_be_counted_by_chars_in_Japanese() { + switch_to_locale( 'ja_JP' ); + + $args = array( + 'comment_content' => str_repeat( 'あ', 200 ), + ); + $comment_id = $this->factory()->comment->create( $args ); + $expect = str_repeat( 'あ', 40 ) . '…'; + $comment_excerpt = get_comment_excerpt( $comment_id ); + + restore_previous_locale(); + + $this->assertSame( $expect, $comment_excerpt ); + } }