From bf38bd326c90fbe0a46ecc2253ee8ad00a8d7b52 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 29 May 2023 08:34:43 +0000 Subject: [PATCH] I18N: Improve `_load_textdomain_just_in_time()` logic when there are no translation files. Fixes a performance issue where the JIT logic is invoked for every translation call if the there are no translations in the current locale. With this change, the information is cached by adding `Noop_Translations` instances to the global `$l10n` array. This way, `get_translations_for_domain()` returns earlier, thus avoiding subsequent `_load_textdomain_just_in_time()` calls. Props swissspidy, johnbillion, ocean90. Fixes #58321. git-svn-id: https://develop.svn.wordpress.org/trunk@55865 602fd350-edb4-49c9-b593-d223f7449a82 --- .../class-wp-textdomain-registry.php | 2 +- src/wp-includes/l10n.php | 10 ++++++++- .../tests/l10n/loadTextdomainJustInTime.php | 21 +++++++++++++++++++ tests/phpunit/tests/l10n/wpLocaleSwitcher.php | 2 +- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/wp-includes/class-wp-textdomain-registry.php b/src/wp-includes/class-wp-textdomain-registry.php index 4564a6c0bf..fc3994ad15 100644 --- a/src/wp-includes/class-wp-textdomain-registry.php +++ b/src/wp-includes/class-wp-textdomain-registry.php @@ -97,7 +97,7 @@ class WP_Textdomain_Registry { */ public function has( $domain ) { return ( - ! empty( $this->current[ $domain ] ) || + isset( $this->current[ $domain ] ) || empty( $this->all[ $domain ] ) || in_array( $domain, $this->domains_with_translations, true ) ); diff --git a/src/wp-includes/l10n.php b/src/wp-includes/l10n.php index 080007b869..a0c7bba903 100644 --- a/src/wp-includes/l10n.php +++ b/src/wp-includes/l10n.php @@ -834,6 +834,12 @@ function unload_textdomain( $domain, $reloadable = false ) { do_action( 'unload_textdomain', $domain, $reloadable ); if ( isset( $l10n[ $domain ] ) ) { + if ( $l10n[ $domain ] instanceof NOOP_Translations ) { + unset( $l10n[ $domain ] ); + + return false; + } + unset( $l10n[ $domain ] ); if ( ! $reloadable ) { @@ -1307,6 +1313,8 @@ function get_translations_for_domain( $domain ) { $noop_translations = new NOOP_Translations(); } + $l10n[ $domain ] = &$noop_translations; + return $noop_translations; } @@ -1322,7 +1330,7 @@ function get_translations_for_domain( $domain ) { */ function is_textdomain_loaded( $domain ) { global $l10n; - return isset( $l10n[ $domain ] ); + return isset( $l10n[ $domain ] ) && ! $l10n[ $domain ] instanceof NOOP_Translations; } /** diff --git a/tests/phpunit/tests/l10n/loadTextdomainJustInTime.php b/tests/phpunit/tests/l10n/loadTextdomainJustInTime.php index 4f29c0c586..3b93d4a975 100644 --- a/tests/phpunit/tests/l10n/loadTextdomainJustInTime.php +++ b/tests/phpunit/tests/l10n/loadTextdomainJustInTime.php @@ -121,6 +121,27 @@ class Tests_L10n_LoadTextdomainJustInTime extends WP_UnitTestCase { $this->assertInstanceOf( 'NOOP_Translations', $translations ); } + /** + * @ticket 58321 + * + * @covers ::get_translations_for_domain + */ + public function test_get_translations_for_domain_get_locale_is_called_only_once() { + $filter_locale = new MockAction(); + add_filter( 'locale', array( $filter_locale, 'filter' ) ); + + get_translations_for_domain( 'internationalized-plugin' ); + get_translations_for_domain( 'internationalized-plugin' ); + get_translations_for_domain( 'internationalized-plugin' ); + $translations = get_translations_for_domain( 'internationalized-plugin' ); + + remove_filter( 'locale', array( $filter_locale, 'filter' ) ); + + $this->assertSame( 1, $filter_locale->get_call_count() ); + $this->assertInstanceOf( 'NOOP_Translations', $translations ); + $this->assertFalse( is_textdomain_loaded( 'internationalized-plugin' ) ); + } + /** * @ticket 37113 * diff --git a/tests/phpunit/tests/l10n/wpLocaleSwitcher.php b/tests/phpunit/tests/l10n/wpLocaleSwitcher.php index 7d61f54d55..1b0b8f796d 100644 --- a/tests/phpunit/tests/l10n/wpLocaleSwitcher.php +++ b/tests/phpunit/tests/l10n/wpLocaleSwitcher.php @@ -384,7 +384,7 @@ class Tests_L10n_wpLocaleSwitcher extends WP_UnitTestCase { $locale_switched_user_locale = switch_to_locale( $user_locale ); // False. $locale_switched_site_locale = switch_to_locale( $site_locale ); // True. $site_locale_after_switch = get_locale(); - $language_header_after_switch = isset( $l10n['default'] ); // en_US + $language_header_after_switch = is_textdomain_loaded( 'default' ); // en_US restore_current_locale();