Make WordPress Core

Changeset 39330


Ignore:
Timestamp:
11/21/2016 04:06:38 PM (7 years ago)
Author:
ocean90
Message:

I18N: Add an additional caching layer for _load_textdomain_just_in_time().

Previously, if no translation files exist for a text domain, _load_textdomain_just_in_time() went through the entire process each time it was called. This results in an increased call to get_locale() and its locale filter.
This change splits the logic into _get_path_to_translation() and _get_path_to_translation_from_lang_dir(). The former, which is used by _load_textdomain_just_in_time(), caches the result of the latter. It also removes some non-working code from WP_Locale_Switcher::load_translations().

Props jrf, swissspidy, sharkomatic, ocean90.
Fixes #37997.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-locale-switcher.php

    r38961 r39330  
    203203            }
    204204
    205             $mofile = $l10n[ $domain ]->get_filename();
    206 
    207205            unload_textdomain( $domain );
    208 
    209             if ( $mofile ) {
    210                 load_textdomain( $domain, $mofile );
    211             }
    212 
    213206            get_translations_for_domain( $domain );
    214207        }
     
    229222     */
    230223    private function change_locale( $locale ) {
     224        // Reset translation availability information.
     225        _get_path_to_translation( null, true );
     226
    231227        $this->load_translations( $locale );
    232228
  • trunk/src/wp-includes/l10n.php

    r39244 r39330  
    828828 * to call load_plugin_texdomain() or load_theme_texdomain().
    829829 *
    830  * Holds a cached list of available .mo files to improve performance.
    831  *
    832830 * @since 4.6.0
    833831 * @access private
     
    843841
    844842    $l10n_unloaded = (array) $l10n_unloaded;
    845 
    846     static $cached_mofiles = null;
    847843
    848844    // Short-circuit if domain is 'default' which is reserved for core.
     
    850846        return false;
    851847    }
     848
     849    $translation_path = _get_path_to_translation( $domain );
     850    if ( false === $translation_path ) {
     851        return false;
     852    }
     853
     854    return load_textdomain( $domain, $translation_path );
     855}
     856
     857/**
     858 * Gets the path to a translation file for loading a textdomain just in time.
     859 *
     860 * Caches the retrieved results internally.
     861 *
     862 * @since 4.7.0
     863 * @access private
     864 *
     865 * @see _load_textdomain_just_in_time()
     866 *
     867 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
     868 * @param bool   $reset  Whether to reset the internal cache. Used by the switch to locale functionality.
     869 * @return string|false The path to the translation file or false if no translation file was found.
     870 */
     871function _get_path_to_translation( $domain, $reset = false ) {
     872    static $available_translations = array();
     873
     874    if ( true === $reset ) {
     875        $available_translations = array();
     876    }
     877
     878    if ( ! isset( $available_translations[ $domain ] ) ) {
     879        $available_translations[ $domain ] = _get_path_to_translation_from_lang_dir( $domain );
     880    }
     881
     882    return $available_translations[ $domain ];
     883}
     884
     885/**
     886 * Gets the path to a translation file in the languages directory for the current locale.
     887 *
     888 * Holds a cached list of available .mo files to improve performance.
     889 *
     890 * @since 4.7.0
     891 * @access private
     892 *
     893 * @see _get_path_to_translation()
     894 *
     895 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
     896 * @return string|false The path to the translation file or false if no translation file was found.
     897 */
     898function _get_path_to_translation_from_lang_dir( $domain ) {
     899    static $cached_mofiles = null;
    852900
    853901    if ( null === $cached_mofiles ) {
     
    870918    $mofile = "{$domain}-{$locale}.mo";
    871919
    872     if ( in_array( WP_LANG_DIR . '/plugins/' . $mofile, $cached_mofiles ) ) {
    873         return load_textdomain( $domain, WP_LANG_DIR . '/plugins/' . $mofile );
    874     }
    875 
    876     if ( in_array( WP_LANG_DIR . '/themes/' . $mofile, $cached_mofiles ) ) {
    877         return load_textdomain( $domain, WP_LANG_DIR . '/themes/' . $mofile );
     920    $path = WP_LANG_DIR . '/plugins/' . $mofile;
     921    if ( in_array( $path, $cached_mofiles ) ) {
     922        return $path;
     923    }
     924
     925    $path = WP_LANG_DIR . '/themes/' . $mofile;
     926    if ( in_array( $path, $cached_mofiles ) ) {
     927        return $path;
    878928    }
    879929
  • trunk/tests/phpunit/tests/l10n/loadTextdomainJustInTime.php

    r39127 r39330  
    99    protected $theme_root;
    1010    protected static $user_id;
     11    private $locale_count;
    1112
    1213    public static function wpSetUpBeforeClass( $factory ) {
     
    2223        $this->theme_root = DIR_TESTDATA . '/themedir1';
    2324        $this->orig_theme_dir = $GLOBALS['wp_theme_directories'];
     25        $this->locale_count = 0;
    2426
    2527        // /themes is necessary as theme.php functions assume /themes is the root if there is only one root.
     
    3234        unset( $GLOBALS['l10n'] );
    3335        unset( $GLOBALS['l10n_unloaded'] );
     36        _get_path_to_translation( null, true );
    3437    }
    3538
     
    4346        unset( $GLOBALS['l10n'] );
    4447        unset( $GLOBALS['l10n_unloaded'] );
     48        _get_path_to_translation( null, true );
    4549
    4650        parent::tearDown();
     
    161165
    162166        $this->assertSame( 'Das ist ein Dummy Plugin', $expected );
     167    }
     168
     169    /**
     170     * @ticket 37997
     171     */
     172    public function test_plugin_translation_after_switching_locale_twice() {
     173        require_once DIR_TESTDATA . '/plugins/internationalized-plugin.php';
     174
     175        switch_to_locale( 'de_DE' );
     176        $expected_de_DE = i18n_plugin_test();
     177
     178        switch_to_locale( 'es_ES' );
     179        $expected_es_ES = i18n_plugin_test();
     180
     181        restore_current_locale();
     182
     183        $this->assertSame( 'Das ist ein Dummy Plugin', $expected_de_DE );
     184        $this->assertSame( 'This is a dummy plugin', $expected_es_ES );
    163185    }
    164186
     
    213235        $this->assertSame( 'Das ist ein Dummy Theme', $expected );
    214236    }
     237
     238    /**
     239     * @ticket 37997
     240     */
     241    public function test_get_locale_is_called_only_once_per_textdomain() {
     242        $textdomain = 'foo-bar-baz';
     243
     244        add_filter( 'locale', array( $this, '_filter_locale_count' ) );
     245
     246        __( 'Foo', $textdomain );
     247        __( 'Bar', $textdomain );
     248        __( 'Baz', $textdomain );
     249        __( 'Foo Bar', $textdomain );
     250        __( 'Foo Bar Baz', $textdomain );
     251
     252        remove_filter( 'locale', array( $this, '_filter_locale_count' ) );
     253
     254        $this->assertFalse( is_textdomain_loaded( $textdomain ) );
     255        $this->assertSame( 1, $this->locale_count );
     256    }
     257
     258    public function _filter_locale_count( $locale ) {
     259        ++$this->locale_count;
     260
     261        return $locale;
     262    }
    215263}
  • trunk/tests/phpunit/tests/l10n/localeSwitcher.php

    r38961 r39330  
    2525        unset( $GLOBALS['l10n'] );
    2626        unset( $GLOBALS['l10n_unloaded'] );
     27        _get_path_to_translation( null, true );
    2728    }
    2829
     
    3031        unset( $GLOBALS['l10n'] );
    3132        unset( $GLOBALS['l10n_unloaded'] );
     33        _get_path_to_translation( null, true );
    3234
    3335        parent::tearDown();
Note: See TracChangeset for help on using the changeset viewer.