Make WordPress Core

Changeset 59157


Ignore:
Timestamp:
10/02/2024 01:42:11 PM (6 months 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.