Make WordPress Core

Changeset 59157


Ignore:
Timestamp:
10/02/2024 01:42:11 PM (2 years ago)
Author:
swissspidy
Message:

I18N: Do not load translations directly in load_*_textdomain.

In [59127], _doing_it_wrong warnings were added if plugins or themes load translations too early, either through a manual function call or just-in-time loading.

Because many plugins and themes still manually call load_plugin_textdomain(), load_theme_textdomain() or load_muplugin_textdomain(), even though they don't have to anymore, that caused a lot of warnings.

With this new approach, these functions merely register the translations path in the existing WP_Textdomain_Registry and do not immediately try to load the translations anymore. The loading is all handled by the just-in-time functionality.

This way, warnings will only be emitted if triggering the just-in-time loading too early, greatly improving the developer experience and to a degree also performance.

Props swissspidy, sergeybiryukov, mukesh27.
See #44937.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/l10n.php

    r59127 r59157  
    984984 * @since 1.5.0
    985985 * @since 4.6.0 The function now tries to load the .mo file from the languages directory first.
     986 * @since 6.7.0 Translations are no longer immediately loaded, but handed off to the just-in-time loading mechanism.
    986987 *
    987988 * @param string       $domain          Unique identifier for retrieving translated strings
    … …  
    998999        if ( ! is_string( $domain ) ) {
    9991000                return false;
    1000         }
    1001 
    1002         if ( ! doing_action( 'after_setup_theme' ) && ! did_action( 'after_setup_theme' ) ) {
    1003                 _doing_it_wrong(
    1004                         __FUNCTION__,
    1005                         sprintf(
    1006                                 /* translators: 1: The text domain. 2: 'after_setup_theme'. */
    1007                                 __( 'Attempted to load translations for the %1$s domain too early. Translations should be loaded after the %2$s action has fired, to ensure that the current user is already set up.' ),
    1008                                 '<code>' . $domain . '</code>',
    1009                                 '<code>after_setup_theme</code>'
    1010                         ),
    1011                         '6.7.0'
    1012                 );
    1013         }
    1014 
    1015         /**
    1016          * Filters a plugin's locale.
    1017          *
    1018          * @since 3.0.0
    1019          *
    1020          * @param string $locale The plugin's current locale.
    1021          * @param string $domain Text domain. Unique identifier for retrieving translated strings.
    1022          */
    1023         $locale = apply_filters( 'plugin_locale', determine_locale(), $domain );
    1024 
    1025         $mofile = $domain . '-' . $locale . '.mo';
    1026 
    1027         // Try to load from the languages directory first.
    1028         if ( load_textdomain( $domain, WP_LANG_DIR . '/plugins/' . $mofile, $locale ) ) {
    1029                 return true;
    10301001        }
    10311002
    … …  
    10411012        $wp_textdomain_registry->set_custom_path( $domain, $path );
    10421013
    1043         return load_textdomain( $domain, $path . '/' . $mofile, $locale );
     1014        return true;
    10441015}
    10451016
    … …  
    10491020 * @since 3.0.0
    10501021 * @since 4.6.0 The function now tries to load the .mo file from the languages directory first.
     1022 * @since 6.7.0 Translations are no longer immediately loaded, but handed off to the just-in-time loading mechanism.
    10511023 *
    10521024 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry.
    … …  
    10651037        }
    10661038
    1067         if ( ! doing_action( 'after_setup_theme' ) && ! did_action( 'after_setup_theme' ) ) {
    1068                 _doing_it_wrong(
    1069                         __FUNCTION__,
    1070                         sprintf(
    1071                                 /* translators: 1: The text domain. 2: 'after_setup_theme'. */
    1072                                 __( 'Attempted to load translations for the %1$s domain too early. Translations should be loaded after the %2$s action has fired, to ensure that the current user is already set up.' ),
    1073                                 '<code>' . $domain . '</code>',
    1074                                 '<code>after_setup_theme</code>'
    1075                         ),
    1076                         '6.7.0'
    1077                 );
    1078         }
    1079 
    1080         /** This filter is documented in wp-includes/l10n.php */
    1081         $locale = apply_filters( 'plugin_locale', determine_locale(), $domain );
    1082 
    1083         $mofile = $domain . '-' . $locale . '.mo';
    1084 
    1085         // Try to load from the languages directory first.
    1086         if ( load_textdomain( $domain, WP_LANG_DIR . '/plugins/' . $mofile, $locale ) ) {
    1087                 return true;
    1088         }
    1089 
    10901039        $path = WPMU_PLUGIN_DIR . '/' . ltrim( $mu_plugin_rel_path, '/' );
    10911040
    10921041        $wp_textdomain_registry->set_custom_path( $domain, $path );
    10931042
    1094         return load_textdomain( $domain, $path . '/' . $mofile, $locale );
     1043        return true;
    10951044}
    10961045
    … …  
    11051054 * @since 1.5.0
    11061055 * @since 4.6.0 The function now tries to load the .mo file from the languages directory first.
     1056 * @since 6.7.0 Translations are no longer immediately loaded, but handed off to the just-in-time loading mechanism.
    11071057 *
    11081058 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry.
    … …  
    11211071        }
    11221072
    1123         if ( ! doing_action( 'after_setup_theme' ) && ! did_action( 'after_setup_theme' ) ) {
    1124                 _doing_it_wrong(
    1125                         __FUNCTION__,
    1126                         sprintf(
    1127                                 /* translators: 1: The text domain. 2: 'after_setup_theme'. */
    1128                                 __( 'Attempted to load translations for the %1$s domain too early. Translations should be loaded after the %2$s action has fired, to ensure that the current user is already set up.' ),
    1129                                 '<code>' . $domain . '</code>',
    1130                                 '<code>after_setup_theme</code>'
    1131                         ),
    1132                         '6.7.0'
    1133                 );
    1134         }
    1135 
    1136         /**
    1137          * Filters a theme's locale.
    1138          *
    1139          * @since 3.0.0
    1140          *
    1141          * @param string $locale The theme's current locale.
    1142          * @param string $domain Text domain. Unique identifier for retrieving translated strings.
    1143          */
    1144         $locale = apply_filters( 'theme_locale', determine_locale(), $domain );
    1145 
    1146         $mofile = $domain . '-' . $locale . '.mo';
    1147 
    1148         // Try to load from the languages directory first.
    1149         if ( load_textdomain( $domain, WP_LANG_DIR . '/themes/' . $mofile, $locale ) ) {
    1150                 return true;
    1151         }
    1152 
    11531073        if ( ! $path ) {
    11541074                $path = get_template_directory();
    … …  
    11571077        $wp_textdomain_registry->set_custom_path( $domain, $path );
    11581078
    1159         return load_textdomain( $domain, $path . '/' . $locale . '.mo', $locale );
     1079        return true;
    11601080}
    11611081
    … …  
    14261346                        __FUNCTION__,
    14271347                        sprintf(
    1428                                 /* translators: %s: The text domain. */
    1429                                 __( 'Translation loading for the %s domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early.' ),
    1430                                 '<code>' . $domain . '</code>'
     1348                                /* translators: 1: The text domain. 2: 'init'. */
     1349                                __( 'Translation loading for the %1$s domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the %2$s action or later.' ),
     1350                                '<code>' . $domain . '</code>',
     1351                                '<code>init</code>'
    14311352                        ),
    14321353                        '6.7.0'
  • trunk/tests/phpunit/tests/l10n/loadTextdomain.php

    r57925 r59157  
    66 */
    77class Tests_L10n_LoadTextdomain extends WP_UnitTestCase {
    8         protected $locale;
    98        protected static $user_id;
    109
    … …  
    2120                parent::set_up();
    2221
    23                 $this->locale = '';
    24 
    25                 add_filter( 'plugin_locale', array( $this, 'store_locale' ) );
    26                 add_filter( 'theme_locale', array( $this, 'store_locale' ) );
    27 
    2822                /** @var WP_Textdomain_Registry $wp_textdomain_registry */
    2923                global $wp_textdomain_registry;
    … …  
    4034
    4135                parent::tear_down();
    42         }
    43 
    44         public function store_locale( $locale ) {
    45                 $this->locale = $locale;
    46 
    47                 return $locale;
    4836        }
    4937
    … …  
    234222
    235223        /**
    236          * @covers ::load_muplugin_textdomain
    237          */
    238         public function test_load_muplugin_textdomain_site_locale() {
    239                 load_muplugin_textdomain( 'wp-tests-domain' );
    240 
    241                 $this->assertSame( get_locale(), $this->locale );
    242         }
    243 
    244         /**
    245          * @ticket 38485
    246          *
    247          * @covers ::load_muplugin_textdomain
    248          */
    249         public function test_load_muplugin_textdomain_user_locale() {
    250                 set_current_screen( 'dashboard' );
    251                 wp_set_current_user( self::$user_id );
    252 
    253                 load_muplugin_textdomain( 'wp-tests-domain' );
    254 
    255                 $this->assertSame( get_user_locale(), $this->locale );
    256         }
    257 
    258         /**
    259          * @covers ::load_plugin_textdomain
    260          */
    261         public function test_load_plugin_textdomain_site_locale() {
    262                 load_plugin_textdomain( 'wp-tests-domain' );
    263 
    264                 $this->assertSame( get_locale(), $this->locale );
    265         }
    266 
    267         /**
    268          * @ticket 38485
    269          *
    270          * @covers ::load_plugin_textdomain
    271          */
    272         public function test_load_plugin_textdomain_user_locale() {
    273                 set_current_screen( 'dashboard' );
    274                 wp_set_current_user( self::$user_id );
    275 
    276                 load_plugin_textdomain( 'wp-tests-domain' );
    277 
    278                 $this->assertSame( get_user_locale(), $this->locale );
    279         }
    280 
    281         /**
    282          * @covers ::load_theme_textdomain
    283          */
    284         public function test_load_theme_textdomain_site_locale() {
    285                 load_theme_textdomain( 'wp-tests-domain' );
    286 
    287                 $this->assertSame( get_locale(), $this->locale );
    288         }
    289 
    290         /**
    291          * @ticket 38485
    292          *
    293          * @covers ::load_theme_textdomain
    294          */
    295         public function test_load_theme_textdomain_user_locale() {
    296                 set_current_screen( 'dashboard' );
    297                 wp_set_current_user( self::$user_id );
    298 
    299                 load_theme_textdomain( 'wp-tests-domain' );
    300 
    301                 $this->assertSame( get_user_locale(), $this->locale );
    302         }
    303 
    304         /**
    305224         * @ticket 58035
    306225         *
  • trunk/tests/phpunit/tests/rest-api/rest-themes-controller.php

    r58328 r59157  
    583583                $result   = $response->get_data();
    584584                $this->assertArrayHasKey( 'tags', $result[0] );
    585                 $this->assertSame( array( 'holiday', 'custom-menu' ), $result[0]['tags']['raw'] );
    586                 $this->assertSame( 'holiday, custom-menu', $result[0]['tags']['rendered'] );
     585                $this->assertSame( array( 'Holiday', 'custom-menu' ), $result[0]['tags']['raw'] );
     586                $this->assertSame( 'Holiday, custom-menu', $result[0]['tags']['rendered'] );
    587587        }
    588588
Note: See TracChangeset for help on using the changeset viewer.