WordPress.org

Make WordPress Core

Ticket #39210: 39210.2.diff

File 39210.2.diff, 33.2 KB (added by swissspidy, 2 years ago)
  • src/wp-includes/class-wp-locale-switcher.php

    diff --git src/wp-includes/class-wp-locale-switcher.php src/wp-includes/class-wp-locale-switcher.php
    index e111892871..fa1f4bc41a 100644
    class WP_Locale_Switcher { 
    194194                load_default_textdomain( $locale );
    195195
    196196                foreach ( $domains as $domain ) {
    197                         if ( 'default' === $domain ) {
    198                                 continue;
    199                         }
    200 
    201197                        unload_textdomain( $domain );
    202198                        get_translations_for_domain( $domain );
    203199                }
    class WP_Locale_Switcher { 
    211207         *
    212208         * @since 4.7.0
    213209         *
    214          * @global WP_Locale $wp_locale The WordPress date and time locale object.
     210         * @global WP_Locale              $wp_locale              The WordPress date and time locale object.
     211         * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry.
    215212         *
    216213         * @param string $locale The locale to change to.
    217214         */
    218215        private function change_locale( $locale ) {
     216                global $wp_locale, $wp_textdomain_registry;
     217
    219218                // Reset translation availability information.
    220                 _get_path_to_translation( null, true );
     219                $wp_textdomain_registry->reset();
    221220
    222221                $this->load_translations( $locale );
    223222
    224                 $GLOBALS['wp_locale'] = new WP_Locale();
     223                $wp_locale = new WP_Locale();
    225224
    226225                /**
    227226                 * Fires when the locale is switched to or restored.
  • new file src/wp-includes/class-wp-textdomain-registry.php

    diff --git src/wp-includes/class-wp-textdomain-registry.php src/wp-includes/class-wp-textdomain-registry.php
    new file mode 100644
    index 0000000000..03b1d032f6
    - +  
     1<?php
     2/**
     3 * Locale API: WP_Textdomain_Registry class
     4 *
     5 * @package    WordPress
     6 * @subpackage i18n
     7 * @since      5.0.0
     8 */
     9
     10/**
     11 * Core class used for registering textdomains
     12 *
     13 * @since 5.0.0
     14 */
     15class WP_Textdomain_Registry {
     16        /**
     17         * List of domains and their language directory paths.
     18         *
     19         * @since 5.0.0
     20         *
     21         * @var array
     22         */
     23        protected $domains = array();
     24
     25        /**
     26         * Holds a cached list of available .mo files to improve performance.
     27         *
     28         * @since 5.0.0
     29         *
     30         * @var array
     31         */
     32        protected $cached_mofiles;
     33
     34        /**
     35         * Returns the MO file path for a specific domain.
     36         *
     37         * @since 5.0.0
     38         * @access public
     39         *
     40         * @param string $domain Text domain.
     41         *
     42         * @return string|false|null MO file path or false if there is none available.
     43         *                           Null if none have been fetched yet.
     44         */
     45        public function get( $domain ) {
     46                return isset( $this->domains[ $domain ] ) ? $this->domains[ $domain ] : null;
     47        }
     48
     49        /**
     50         * Sets the MO file path for a specific domain.
     51         *
     52         * @since 5.0.0
     53         * @access public
     54         *
     55         * @param string $domain Text domain.
     56         * @param string $path Language directory path.
     57         */
     58        public function set( $domain, $path ) {
     59                $this->domains[ $domain ] = $path;
     60        }
     61
     62        /**
     63         * Resets the registry state.
     64         *
     65         * @since 5.0.0
     66         * @access public
     67         */
     68        public function reset( ) {
     69                $this->cached_mofiles = null;
     70                $this->domains = array();
     71        }
     72
     73        /**
     74         * Gets the path to a translation file in the languages directory for the current locale.
     75         *
     76         * @since 5.0.0
     77         * @access public
     78         *
     79         * @see _get_path_to_translation_from_lang_dir()
     80         *
     81         * @param string $domain Text domain.
     82         */
     83        public function get_translation_from_lang_dir( $domain ) {
     84                if ( null === $this->cached_mofiles ) {
     85                        $this->cached_mofiles = array();
     86
     87                        $this->fetch_available_mofiles();
     88                }
     89
     90                $locale = is_admin() ? get_user_locale() : get_locale();
     91                $mofile = "{$domain}-{$locale}.mo";
     92
     93                $path = WP_LANG_DIR . '/plugins/' . $mofile;
     94                if ( in_array( $path, $this->cached_mofiles, true ) ) {
     95                        $this->set( $domain, WP_LANG_DIR . '/plugins/' );
     96
     97                        return;
     98                }
     99
     100                $path = WP_LANG_DIR . '/themes/' . $mofile;
     101                if ( in_array( $path, $this->cached_mofiles, true ) ) {
     102                        $this->set( $domain, WP_LANG_DIR . '/themes/' );
     103
     104                        return;
     105                }
     106
     107                $this->set( $domain, false );
     108        }
     109
     110        /**
     111         * Fetches all available MO files from the plugins and themes language directories.
     112         *
     113         * @since 5.0.0
     114         * @access protected
     115         *
     116         * @see _get_path_to_translation_from_lang_dir()
     117         */
     118        protected function fetch_available_mofiles() {
     119                $locations = array(
     120                        WP_LANG_DIR . '/plugins',
     121                        WP_LANG_DIR . '/themes',
     122                );
     123
     124                foreach ( $locations as $location ) {
     125                        $mofiles = glob( $location . '/*.mo' );
     126
     127                        if ( $mofiles ) {
     128                                $this->cached_mofiles = array_merge( $this->cached_mofiles, $mofiles );
     129                        }
     130                }
     131        }
     132}
  • src/wp-includes/deprecated.php

    diff --git src/wp-includes/deprecated.php src/wp-includes/deprecated.php
    index 06ecd4b518..21b2e34a0e 100644
    function wp_ajax_press_this_add_category() { 
    39443944                wp_send_json_error( array( 'errorMessage' => __( 'The Press This plugin is required.' ) ) );
    39453945        }
    39463946}
     3947
     3948/**
     3949 * Gets the path to a translation file for loading a textdomain just in time.
     3950 *
     3951 * Caches the retrieved results internally.
     3952 *
     3953 * @since 4.7.0
     3954 * @deprecated 5.0.0
     3955 * @access private
     3956 *
     3957 * @see _load_textdomain_just_in_time()
     3958 *
     3959 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
     3960 * @param bool   $reset  Whether to reset the internal cache. Used by the switch to locale functionality.
     3961 * @return string|false The path to the translation file or false if no translation file was found.
     3962 */
     3963function _get_path_to_translation( $domain, $reset = false ) {
     3964        _deprecated_function( __FUNCTION__, '3.1.0', 'WP_Textdomain_Registry' );
     3965
     3966        static $available_translations = array();
     3967
     3968        if ( true === $reset ) {
     3969                $available_translations = array();
     3970        }
     3971
     3972        if ( ! isset( $available_translations[ $domain ] ) ) {
     3973                $available_translations[ $domain ] = _get_path_to_translation_from_lang_dir( $domain );
     3974        }
     3975
     3976        return $available_translations[ $domain ];
     3977}
     3978
     3979/**
     3980 * Gets the path to a translation file in the languages directory for the current locale.
     3981 *
     3982 * Holds a cached list of available .mo files to improve performance.
     3983 *
     3984 * @since 4.7.0
     3985 * @deprecated 5.0.0
     3986 * @access private
     3987 *
     3988 * @see _get_path_to_translation()
     3989 *
     3990 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
     3991 * @return string|false The path to the translation file or false if no translation file was found.
     3992 */
     3993function _get_path_to_translation_from_lang_dir( $domain ) {
     3994        _deprecated_function( __FUNCTION__, '3.1.0', 'WP_Textdomain_Registry' );
     3995
     3996        static $cached_mofiles = null;
     3997
     3998        if ( null === $cached_mofiles ) {
     3999                $cached_mofiles = array();
     4000
     4001                $locations = array(
     4002                        WP_LANG_DIR . '/plugins',
     4003                        WP_LANG_DIR . '/themes',
     4004                );
     4005
     4006                foreach ( $locations as $location ) {
     4007                        $mofiles = glob( $location . '/*.mo' );
     4008                        if ( $mofiles ) {
     4009                                $cached_mofiles = array_merge( $cached_mofiles, $mofiles );
     4010                        }
     4011                }
     4012        }
     4013
     4014        $locale = is_admin() ? get_user_locale() : get_locale();
     4015        $mofile = "{$domain}-{$locale}.mo";
     4016
     4017        $path = WP_LANG_DIR . '/plugins/' . $mofile;
     4018        if ( in_array( $path, $cached_mofiles ) ) {
     4019                return $path;
     4020        }
     4021
     4022        $path = WP_LANG_DIR . '/themes/' . $mofile;
     4023        if ( in_array( $path, $cached_mofiles ) ) {
     4024                return $path;
     4025        }
     4026
     4027        return false;
     4028}
  • src/wp-includes/l10n.php

    diff --git src/wp-includes/l10n.php src/wp-includes/l10n.php
    index 72bb406bc3..858dbcc276 100644
    function translate_nooped_plural( $nooped_plural, $count, $domain = 'default' ) 
    532532 *
    533533 * @since 1.5.0
    534534 *
    535  * @global array $l10n          An array of all currently loaded text domains.
    536  * @global array $l10n_unloaded An array of all text domains that have been unloaded again.
     535 * @global array                  $l10n                   An array of all currently loaded text domains.
     536 * @global array                  $l10n_unloaded          An array of all text domains that have been unloaded again.
     537 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry.
    537538 *
    538539 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
    539540 * @param string $mofile Path to the .mo file.
    540541 * @return bool True on success, false on failure.
    541542 */
    542543function load_textdomain( $domain, $mofile ) {
    543         global $l10n, $l10n_unloaded;
     544        global $l10n, $l10n_unloaded, $wp_textdomain_registry;
    544545
    545546        $l10n_unloaded = (array) $l10n_unloaded;
    546547
    function load_textdomain( $domain, $mofile ) { 
    581582         */
    582583        $mofile = apply_filters( 'load_textdomain_mofile', $mofile, $domain );
    583584
    584         if ( !is_readable( $mofile ) ) return false;
     585        if ( ! is_readable( $mofile ) ) {
     586                return false;
     587        }
    585588
    586         $mo = new MO();
    587         if ( !$mo->import_from_file( $mofile ) ) return false;
     589        unset( $l10n_unloaded[ $domain ] );
     590
     591        if ( isset( $l10n[$domain] ) ) {
     592                $mo = new MO();
     593
     594                if ( ! $mo->import_from_file( $mofile ) ) {
     595                        return false;
     596                }
    588597
    589         if ( isset( $l10n[$domain] ) )
    590598                $mo->merge_with( $l10n[$domain] );
    591599
    592         unset( $l10n_unloaded[ $domain ] );
     600                return true;
     601        }
    593602
    594         $l10n[$domain] = &$mo;
     603        /* @var WP_Textdomain_Registry $wp_textdomain_registry */
     604        $wp_textdomain_registry->set( $domain, dirname( $mofile ) );
    595605
    596606        return true;
    597607}
    function load_textdomain( $domain, $mofile ) { 
    601611 *
    602612 * @since 3.0.0
    603613 *
    604  * @global array $l10n          An array of all currently loaded text domains.
    605  * @global array $l10n_unloaded An array of all text domains that have been unloaded again.
     614 * @global array                  $l10n                   An array of all currently loaded text domains.
     615 * @global array                  $l10n_unloaded          An array of all text domains that have been unloaded again.
     616 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry.
    606617 *
    607618 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
    608619 * @return bool Whether textdomain was unloaded.
    609620 */
    610621function unload_textdomain( $domain ) {
    611         global $l10n, $l10n_unloaded;
     622        global $l10n, $l10n_unloaded, $wp_textdomain_registry;
    612623
    613624        $l10n_unloaded = (array) $l10n_unloaded;
    614625
    function unload_textdomain( $domain ) { 
    637648         */
    638649        do_action( 'unload_textdomain', $domain );
    639650
    640         if ( isset( $l10n[$domain] ) ) {
    641                 unset( $l10n[$domain] );
     651        if ( isset( $l10n[ $domain ] ) ) {
     652                unset( $l10n[ $domain ] );
     653        }
    642654
     655        /* @var WP_Textdomain_Registry $wp_textdomain_registry */
     656        if ( null !== $wp_textdomain_registry->get( $domain ) ) {
    643657                $l10n_unloaded[ $domain ] = true;
    644658
    645659                return true;
    function load_default_textdomain( $locale = null ) { 
    696710 * @since 1.5.0
    697711 * @since 4.6.0 The function now tries to load the .mo file from the languages directory first.
    698712 *
     713 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry.
     714 *
    699715 * @param string $domain          Unique identifier for retrieving translated strings
    700716 * @param string $deprecated      Optional. Use the $plugin_rel_path parameter instead. Default false.
    701717 * @param string $plugin_rel_path Optional. Relative path to WP_PLUGIN_DIR where the .mo file resides.
    function load_default_textdomain( $locale = null ) { 
    703719 * @return bool True when textdomain is successfully loaded, false otherwise.
    704720 */
    705721function load_plugin_textdomain( $domain, $deprecated = false, $plugin_rel_path = false ) {
     722        global $wp_textdomain_registry;
     723
    706724        /**
    707725         * Filters a plugin's locale.
    708726         *
    function load_plugin_textdomain( $domain, $deprecated = false, $plugin_rel_path 
    729747                $path = WP_PLUGIN_DIR;
    730748        }
    731749
     750        /* @var WP_Textdomain_Registry $wp_textdomain_registry */
     751        $wp_textdomain_registry->set( $domain, $path );
     752
    732753        return load_textdomain( $domain, $path . '/' . $mofile );
    733754}
    734755
    function load_plugin_textdomain( $domain, $deprecated = false, $plugin_rel_path 
    738759 * @since 3.0.0
    739760 * @since 4.6.0 The function now tries to load the .mo file from the languages directory first.
    740761 *
     762 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry.
     763 *
    741764 * @param string $domain             Text domain. Unique identifier for retrieving translated strings.
    742765 * @param string $mu_plugin_rel_path Optional. Relative to `WPMU_PLUGIN_DIR` directory in which the .mo
    743766 *                                   file resides. Default empty string.
    744767 * @return bool True when textdomain is successfully loaded, false otherwise.
    745768 */
    746769function load_muplugin_textdomain( $domain, $mu_plugin_rel_path = '' ) {
     770        global $wp_textdomain_registry;
     771
    747772        /** This filter is documented in wp-includes/l10n.php */
    748773        $locale = apply_filters( 'plugin_locale', is_admin() ? get_user_locale() : get_locale(), $domain );
    749774
    function load_muplugin_textdomain( $domain, $mu_plugin_rel_path = '' ) { 
    756781
    757782        $path = WPMU_PLUGIN_DIR . '/' . ltrim( $mu_plugin_rel_path, '/' );
    758783
     784        /* @var WP_Textdomain_Registry $wp_textdomain_registry */
     785        $wp_textdomain_registry->set( $domain, $path );
     786
    759787        return load_textdomain( $domain, $path . '/' . $mofile );
    760788}
    761789
    function load_muplugin_textdomain( $domain, $mu_plugin_rel_path = '' ) { 
    770798 * @since 1.5.0
    771799 * @since 4.6.0 The function now tries to load the .mo file from the languages directory first.
    772800 *
     801 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry.
     802 *
    773803 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
    774804 * @param string $path   Optional. Path to the directory containing the .mo file.
    775805 *                       Default false.
    776806 * @return bool True when textdomain is successfully loaded, false otherwise.
    777807 */
    778808function load_theme_textdomain( $domain, $path = false ) {
     809        global $wp_textdomain_registry;
     810
    779811        /**
    780812         * Filters a theme's locale.
    781813         *
    function load_theme_textdomain( $domain, $path = false ) { 
    797829                $path = get_template_directory();
    798830        }
    799831
     832        /* @var WP_Textdomain_Registry $wp_textdomain_registry */
     833        $wp_textdomain_registry->set( $domain, $path );
     834
    800835        return load_textdomain( $domain, $path . '/' . $locale . '.mo' );
    801836}
    802837
    function load_child_theme_textdomain( $domain, $path = false ) { 
    832867 * @access private
    833868 *
    834869 * @see get_translations_for_domain()
    835  * @global array $l10n_unloaded An array of all text domains that have been unloaded again.
     870 *
     871 * @global array                  $l10n                   An array of all currently loaded text domains.
     872 * @global array                  $l10n_unloaded          An array of all text domains that have been unloaded again.
     873 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry.
    836874 *
    837875 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
    838876 * @return bool True when the textdomain is successfully loaded, false otherwise.
    839877 */
    840878function _load_textdomain_just_in_time( $domain ) {
    841         global $l10n_unloaded;
     879        global $l10n, $l10n_unloaded, $wp_textdomain_registry;
    842880
    843881        $l10n_unloaded = (array) $l10n_unloaded;
    844882
    845         // Short-circuit if domain is 'default' which is reserved for core.
    846         if ( 'default' === $domain || isset( $l10n_unloaded[ $domain ] ) ) {
     883        if ( isset( $l10n_unloaded[ $domain ] ) ) {
    847884                return false;
    848885        }
    849886
    850         $translation_path = _get_path_to_translation( $domain );
    851         if ( false === $translation_path ) {
    852                 return false;
     887        /* @var WP_Textdomain_Registry $wp_textdomain_registry */
     888        if ( null === $wp_textdomain_registry->get( $domain ) ) {
     889                $wp_textdomain_registry->get_translation_from_lang_dir( $domain );
    853890        }
    854891
    855         return load_textdomain( $domain, $translation_path );
    856 }
     892        $path = $wp_textdomain_registry->get( $domain );
    857893
    858 /**
    859  * Gets the path to a translation file for loading a textdomain just in time.
    860  *
    861  * Caches the retrieved results internally.
    862  *
    863  * @since 4.7.0
    864  * @access private
    865  *
    866  * @see _load_textdomain_just_in_time()
    867  *
    868  * @param string $domain Text domain. Unique identifier for retrieving translated strings.
    869  * @param bool   $reset  Whether to reset the internal cache. Used by the switch to locale functionality.
    870  * @return string|false The path to the translation file or false if no translation file was found.
    871  */
    872 function _get_path_to_translation( $domain, $reset = false ) {
    873         static $available_translations = array();
    874 
    875         if ( true === $reset ) {
    876                 $available_translations = array();
    877         }
    878 
    879         if ( ! isset( $available_translations[ $domain ] ) ) {
    880                 $available_translations[ $domain ] = _get_path_to_translation_from_lang_dir( $domain );
     894        if ( false === $path ) {
     895                return false;
    881896        }
    882897
    883         return $available_translations[ $domain ];
    884 }
    885 
    886 /**
    887  * Gets the path to a translation file in the languages directory for the current locale.
    888  *
    889  * Holds a cached list of available .mo files to improve performance.
    890  *
    891  * @since 4.7.0
    892  * @access private
    893  *
    894  * @see _get_path_to_translation()
    895  *
    896  * @param string $domain Text domain. Unique identifier for retrieving translated strings.
    897  * @return string|false The path to the translation file or false if no translation file was found.
    898  */
    899 function _get_path_to_translation_from_lang_dir( $domain ) {
    900         static $cached_mofiles = null;
    901 
    902         if ( null === $cached_mofiles ) {
    903                 $cached_mofiles = array();
     898        $locale = is_admin() ? get_user_locale() : get_locale();
     899        $mofile = "{$path}/{$domain}-{$locale}.mo";
    904900
    905                 $locations = array(
    906                         WP_LANG_DIR . '/plugins',
    907                         WP_LANG_DIR . '/themes',
    908                 );
     901        if ( 'default' === $domain ) {
     902                $mofile = "{$path}/{$locale}.mo";
     903        }
    909904
    910                 foreach ( $locations as $location ) {
    911                         $mofiles = glob( $location . '/*.mo' );
    912                         if ( $mofiles ) {
    913                                 $cached_mofiles = array_merge( $cached_mofiles, $mofiles );
    914                         }
    915                 }
     905        if ( ! is_readable( $mofile ) ) {
     906                return false;
    916907        }
    917908
    918         $locale = is_admin() ? get_user_locale() : get_locale();
    919         $mofile = "{$domain}-{$locale}.mo";
     909        $mo = new MO();
    920910
    921         $path = WP_LANG_DIR . '/plugins/' . $mofile;
    922         if ( in_array( $path, $cached_mofiles ) ) {
    923                 return $path;
     911        if ( ! $mo->import_from_file( $mofile ) ) {
     912                return false;
    924913        }
    925914
    926         $path = WP_LANG_DIR . '/themes/' . $mofile;
    927         if ( in_array( $path, $cached_mofiles ) ) {
    928                 return $path;
     915        if ( isset( $l10n[ $domain ] ) ) {
     916                $mo->merge_with( $l10n[ $domain ] );
    929917        }
    930918
    931         return false;
     919        unset( $l10n_unloaded[ $domain ] );
     920
     921        $l10n[ $domain ] = &$mo;
     922
     923        return true;
    932924}
    933925
    934926/**
    function get_translations_for_domain( $domain ) { 
    962954 *
    963955 * @since 3.0.0
    964956 *
    965  * @global array $l10n
     957 * @global array                  $l10n                   An array of all currently loaded text domains.
     958 * @global array                  $l10n_unloaded          An array of all text domains that have been unloaded again.
     959 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry.
    966960 *
    967961 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
    968962 * @return bool Whether there are translations.
    969963 */
    970964function is_textdomain_loaded( $domain ) {
    971         global $l10n;
    972         return isset( $l10n[ $domain ] );
     965        global $l10n, $l10n_unloaded, $wp_textdomain_registry;
     966
     967        /** @var WP_Textdomain_Registry $wp_textdomain_registry */
     968        return isset( $l10n[ $domain ] ) || ( ! isset( $l10n_unloaded[ $domain ] ) && $wp_textdomain_registry->get( $domain ) );
    973969}
    974970
    975971/**
  • src/wp-settings.php

    diff --git src/wp-settings.php src/wp-settings.php
    index 3d4c210338..1b04180505 100644
    if ( SHORTINIT ) 
    133133
    134134// Load the L10n library.
    135135require_once( ABSPATH . WPINC . '/l10n.php' );
     136require_once( ABSPATH . WPINC . '/class-wp-textdomain-registry.php' );
    136137require_once( ABSPATH . WPINC . '/class-wp-locale.php' );
    137138require_once( ABSPATH . WPINC . '/class-wp-locale-switcher.php' );
    138139
    require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-user-meta-fields.php' 
    242243
    243244$GLOBALS['wp_embed'] = new WP_Embed();
    244245
     246/**
     247 * WordPress Textdomain Registry object.
     248 *
     249 * Used to support just-in-time translations for manually loaded textdomains.
     250 *
     251 * @since 5.0.0
     252 *
     253 * @global WP_Locale_Switcher $wp_locale_switcher WordPress Textdomain Registry.
     254 */
     255$GLOBALS['wp_textdomain_registry'] = new WP_Textdomain_Registry();
     256
    245257// Load multisite-specific files.
    246258if ( is_multisite() ) {
    247259        require( ABSPATH . WPINC . '/ms-functions.php' );
    unset( $locale_file ); 
    407419$GLOBALS['wp_locale'] = new WP_Locale();
    408420
    409421/**
    410  *  WordPress Locale Switcher object for switching locales.
     422 * WordPress Locale Switcher object for switching locales.
    411423 *
    412424 * @since 4.7.0
    413425 *
  • new file tests/phpunit/data/plugins/custom-internationalized-plugin/custom-internationalized-plugin.php

    diff --git tests/phpunit/data/plugins/custom-internationalized-plugin/custom-internationalized-plugin.php tests/phpunit/data/plugins/custom-internationalized-plugin/custom-internationalized-plugin.php
    new file mode 100644
    index 0000000000..6889deca6a
    - +  
     1<?php
     2/*
     3Plugin Name: Custom Dummy Plugin
     4Plugin URI: https://wordpress.org/
     5Description: For testing purposes only.
     6Version: 1.0.0
     7Text Domain: custom-internationalized-plugin
     8*/
     9
     10load_plugin_textdomain( 'custom-internationalized-plugin', false, basename( dirname( __FILE__ ) ) . '/languages' );
     11
     12function custom_i18n_plugin_test() {
     13        return __( 'This is a dummy plugin', 'custom-internationalized-plugin' );
     14}
  • new file tests/phpunit/data/plugins/custom-internationalized-plugin/languages/custom-internationalized-plugin-de_DE.po

    diff --git tests/phpunit/data/plugins/custom-internationalized-plugin/languages/custom-internationalized-plugin-de_DE.mo tests/phpunit/data/plugins/custom-internationalized-plugin/languages/custom-internationalized-plugin-de_DE.mo
    new file mode 100644
    index 0000000000..a9f2de4915
    Binary files /dev/null and tests/phpunit/data/plugins/custom-internationalized-plugin/languages/custom-internationalized-plugin-de_DE.mo differ
    diff --git tests/phpunit/data/plugins/custom-internationalized-plugin/languages/custom-internationalized-plugin-de_DE.po tests/phpunit/data/plugins/custom-internationalized-plugin/languages/custom-internationalized-plugin-de_DE.po
    new file mode 100644
    index 0000000000..1bf9084bed
    - +  
     1msgid ""
     2msgstr ""
     3"Project-Id-Version: \n"
     4"POT-Creation-Date: 2015-12-31 16:31+0100\n"
     5"PO-Revision-Date: 2017-10-02 22:34+0200\n"
     6"Language: de_DE\n"
     7"MIME-Version: 1.0\n"
     8"Content-Type: text/plain; charset=UTF-8\n"
     9"Content-Transfer-Encoding: 8bit\n"
     10"X-Generator: Poedit 2.0.2\n"
     11"X-Poedit-Basepath: .\n"
     12"Plural-Forms: nplurals=2; plural=(n != 1);\n"
     13"X-Poedit-KeywordsList: __;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;"
     14"_nx_noop:1,2,3c;esc_attr__;esc_html__;esc_attr_e;esc_html_e;esc_attr_x:1,2c;"
     15"esc_html_x:1,2c\n"
     16"X-Textdomain-Support: yes\n"
     17"Last-Translator: Pascal Birchler <swissspidy@chat.wordpress.org>\n"
     18"Language-Team: \n"
     19"X-Poedit-SearchPath-0: .\n"
     20
     21#: internationalized-plugin.php:11
     22msgid "This is a dummy plugin"
     23msgstr "Das ist ein Dummy Plugin"
  • new file tests/phpunit/data/plugins/custom-internationalized-plugin/languages/custom-internationalized-plugin-en_GB.po

    diff --git tests/phpunit/data/plugins/custom-internationalized-plugin/languages/custom-internationalized-plugin-en_GB.mo tests/phpunit/data/plugins/custom-internationalized-plugin/languages/custom-internationalized-plugin-en_GB.mo
    new file mode 100644
    index 0000000000..a0395710ca
    Binary files /dev/null and tests/phpunit/data/plugins/custom-internationalized-plugin/languages/custom-internationalized-plugin-en_GB.mo differ
    diff --git tests/phpunit/data/plugins/custom-internationalized-plugin/languages/custom-internationalized-plugin-en_GB.po tests/phpunit/data/plugins/custom-internationalized-plugin/languages/custom-internationalized-plugin-en_GB.po
    new file mode 100644
    index 0000000000..7fe6a51b68
    - +  
     1msgid ""
     2msgstr ""
     3"Project-Id-Version: \n"
     4"POT-Creation-Date: 2015-12-31 16:31+0100\n"
     5"PO-Revision-Date: 2017-10-02 22:34+0200\n"
     6"Language: en_GB\n"
     7"MIME-Version: 1.0\n"
     8"Content-Type: text/plain; charset=UTF-8\n"
     9"Content-Transfer-Encoding: 8bit\n"
     10"X-Generator: Poedit 2.0.2\n"
     11"X-Poedit-Basepath: .\n"
     12"Plural-Forms: nplurals=2; plural=(n != 1);\n"
     13"X-Poedit-KeywordsList: __;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;"
     14"_nx_noop:1,2,3c;esc_attr__;esc_html__;esc_attr_e;esc_html_e;esc_attr_x:1,2c;"
     15"esc_html_x:1,2c\n"
     16"X-Textdomain-Support: yes\n"
     17"Last-Translator: Pascal Birchler <swissspidy@chat.wordpress.org>\n"
     18"Language-Team: \n"
     19"X-Poedit-SearchPath-0: .\n"
     20
     21#: internationalized-plugin.php:11
     22msgid "This is a dummy plugin"
     23msgstr "This is a wally plugin"
  • tests/phpunit/tests/l10n/loadTextdomain.php

    diff --git tests/phpunit/tests/l10n/loadTextdomain.php tests/phpunit/tests/l10n/loadTextdomain.php
    index a44f09a7fd..0d500e4296 100644
    class Tests_L10n_loadTextdomain extends WP_UnitTestCase { 
    2222
    2323                add_filter( 'plugin_locale', array( $this, 'store_locale' ) );
    2424                add_filter( 'theme_locale', array( $this, 'store_locale' ) );
     25
     26                /* @var WP_Textdomain_Registry $wp_textdomain_registry */
     27                global $wp_textdomain_registry;
     28
     29                $wp_textdomain_registry->reset();
    2530        }
    2631
    2732        public function tearDown() {
    2833                remove_filter( 'plugin_locale', array( $this, 'store_locale' ) );
    2934                remove_filter( 'theme_locale', array( $this, 'store_locale' ) );
    3035
     36                /* @var WP_Textdomain_Registry $wp_textdomain_registry */
     37                global $wp_textdomain_registry;
     38
     39                $wp_textdomain_registry->reset();
     40
    3141                parent::tearDown();
    3242        }
    3343
    class Tests_L10n_loadTextdomain extends WP_UnitTestCase { 
    114124        /**
    115125         * @ticket 21319
    116126         */
    117         function test_is_textdomain_is_not_loaded_after_gettext_call_with_no_translations() {
     127        public function test_is_textdomain_is_not_loaded_after_gettext_call_with_no_translations() {
    118128                $this->assertFalse( is_textdomain_loaded( 'wp-tests-domain' ) );
    119129                __( 'just some string', 'wp-tests-domain' );
    120130                $this->assertFalse( is_textdomain_loaded( 'wp-tests-domain' ) );
    121131        }
    122132
    123         function test_override_load_textdomain_noop() {
     133        public function test_override_load_textdomain_noop() {
    124134                add_filter( 'override_load_textdomain', '__return_true' );
    125135                $load_textdomain = load_textdomain( 'wp-tests-domain', DIR_TESTDATA . '/non-existent-file' );
    126136                remove_filter( 'override_load_textdomain', '__return_true' );
    class Tests_L10n_loadTextdomain extends WP_UnitTestCase { 
    129139                $this->assertFalse( is_textdomain_loaded( 'wp-tests-domain' ) );
    130140        }
    131141
    132         function test_override_load_textdomain_non_existent_mofile() {
     142        public function test_override_load_textdomain_non_existent_mofile() {
    133143                add_filter( 'override_load_textdomain', array( $this, '_override_load_textdomain_filter' ), 10, 3 );
    134144                $load_textdomain = load_textdomain( 'wp-tests-domain', WP_LANG_DIR . '/non-existent-file.mo' );
    135145                remove_filter( 'override_load_textdomain', array( $this, '_override_load_textdomain_filter' ) );
    class Tests_L10n_loadTextdomain extends WP_UnitTestCase { 
    143153                $this->assertFalse( $is_textdomain_loaded_after );
    144154        }
    145155
    146         function test_override_load_textdomain_custom_mofile() {
     156        public function test_override_load_textdomain_custom_mofile() {
     157                global $l10n, $l10n_unloaded, $wp_textdomain_registry;
    147158                add_filter( 'override_load_textdomain', array( $this, '_override_load_textdomain_filter' ), 10, 3 );
    148159                $load_textdomain = load_textdomain( 'wp-tests-domain', WP_LANG_DIR . '/plugins/internationalized-plugin-de_DE.mo' );
    149160                remove_filter( 'override_load_textdomain', array( $this, '_override_load_textdomain_filter' ) );
    class Tests_L10n_loadTextdomain extends WP_UnitTestCase { 
    163174         * @param string $file     Path to the MO file.
    164175         * @return bool
    165176         */
    166         function _override_load_textdomain_filter( $override, $domain, $file ) {
     177        public function _override_load_textdomain_filter( $override, $domain, $file ) {
    167178                global $l10n;
    168179
    169180                if ( ! is_readable( $file ) ) {
  • tests/phpunit/tests/l10n/loadTextdomainJustInTime.php

    diff --git tests/phpunit/tests/l10n/loadTextdomainJustInTime.php tests/phpunit/tests/l10n/loadTextdomainJustInTime.php
    index fc2b84aa3a..0e8e364a3d 100644
    class Tests_L10n_loadTextdomainJustInTime extends WP_UnitTestCase { 
    3030                add_filter( 'stylesheet_root', array( $this, 'filter_theme_root' ) );
    3131                add_filter( 'template_root', array( $this, 'filter_theme_root' ) );
    3232                wp_clean_themes_cache();
    33                 unset( $GLOBALS['wp_themes'] );
    34                 unset( $GLOBALS['l10n'] );
    35                 unset( $GLOBALS['l10n_unloaded'] );
    36                 _get_path_to_translation( null, true );
     33                unset( $GLOBALS['wp_themes'], $GLOBALS['l10n'], $GLOBALS['l10n_unloaded'] );
     34
     35                /* @var WP_Textdomain_Registry $wp_textdomain_registry */
     36                global $wp_textdomain_registry;
     37
     38                $wp_textdomain_registry->reset();
    3739        }
    3840
    3941        public function tearDown() {
    class Tests_L10n_loadTextdomainJustInTime extends WP_UnitTestCase { 
    4244                remove_filter( 'stylesheet_root', array( $this, 'filter_theme_root' ) );
    4345                remove_filter( 'template_root', array( $this, 'filter_theme_root' ) );
    4446                wp_clean_themes_cache();
    45                 unset( $GLOBALS['wp_themes'] );
    46                 unset( $GLOBALS['l10n'] );
    47                 unset( $GLOBALS['l10n_unloaded'] );
    48                 _get_path_to_translation( null, true );
     47                unset( $GLOBALS['wp_themes'], $GLOBALS['l10n'], $GLOBALS['l10n_unloaded'] );
     48
     49                /* @var WP_Textdomain_Registry $wp_textdomain_registry */
     50                global $wp_textdomain_registry;
     51
     52                $wp_textdomain_registry->reset();
    4953
    5054                parent::tearDown();
    5155        }
    class Tests_L10n_loadTextdomainJustInTime extends WP_UnitTestCase { 
    111115                remove_filter( 'override_load_textdomain', '__return_true' );
    112116                remove_filter( 'locale', array( $this, 'filter_set_locale_to_german' ) );
    113117
    114                 $this->assertTrue( $translations instanceof NOOP_Translations );
     118                $this->assertNotNull( 'NOOP_Translations', $translations );
    115119        }
    116120
    117121        /**
  • tests/phpunit/tests/l10n/localeSwitcher.php

    diff --git tests/phpunit/tests/l10n/localeSwitcher.php tests/phpunit/tests/l10n/localeSwitcher.php
    index 41492bdb45..640aa34df2 100644
    class Tests_Locale_Switcher extends WP_UnitTestCase { 
    2222                $this->locale = '';
    2323                $this->previous_locale = '';
    2424
    25                 unset( $GLOBALS['l10n'] );
    26                 unset( $GLOBALS['l10n_unloaded'] );
    27                 _get_path_to_translation( null, true );
     25                unset( $GLOBALS['l10n'], $GLOBALS['l10n_unloaded'] );
     26
     27                /* @var WP_Textdomain_Registry $wp_textdomain_registry */
     28                global $wp_textdomain_registry;
     29
     30                $wp_textdomain_registry->reset();
    2831        }
    2932
    3033        public function tearDown() {
    31                 unset( $GLOBALS['l10n'] );
    32                 unset( $GLOBALS['l10n_unloaded'] );
    33                 _get_path_to_translation( null, true );
     34                unset( $GLOBALS['l10n'], $GLOBALS['l10n_unloaded'] );
     35
     36                /* @var WP_Textdomain_Registry $wp_textdomain_registry */
     37                global $wp_textdomain_registry;
     38
     39                $wp_textdomain_registry->reset();
    3440
    3541                parent::tearDown();
    3642        }
    class Tests_Locale_Switcher extends WP_UnitTestCase { 
    251257
    252258                $site_locale = get_locale();
    253259
    254                 $user_id = $this->factory()->user->create( array(
     260                $user_id = static::factory()->user->create( array(
    255261                        'role'   => 'administrator',
    256262                        'locale' => 'de_DE',
    257263                ) );
    class Tests_Locale_Switcher extends WP_UnitTestCase { 
    269275                $this->assertSame( 'de_DE', $user_locale );
    270276
    271277                load_default_textdomain( $user_locale );
     278                get_translations_for_domain( 'default' );
    272279                $language_header_before_switch = $l10n['default']->headers['Language']; // de_DE
    273280
    274281                $locale_switched_user_locale = switch_to_locale( $user_locale ); // False.
    class Tests_Locale_Switcher extends WP_UnitTestCase { 
    300307
    301308                $site_locale = get_locale();
    302309
    303                 $user_id = $this->factory()->user->create( array(
     310                $user_id = static::factory()->user->create( array(
    304311                        'role'   => 'administrator',
    305312                        'locale' => 'de_DE',
    306313                ) );
    class Tests_Locale_Switcher extends WP_UnitTestCase { 
    318325                $this->assertSame( 'de_DE', $user_locale );
    319326
    320327                load_default_textdomain( $user_locale );
     328                get_translations_for_domain( 'default' );
    321329                $language_header_before_switch = $l10n['default']->headers['Language']; // de_DE
    322330
    323331                $locale_switched_user_locale = switch_to_locale( $user_locale ); // False.
    324332                $locale_switched_site_locale = switch_to_locale( $site_locale ); // True.
    325333                $site_locale_after_switch = get_locale();
     334                load_default_textdomain( get_locale() );
     335                get_translations_for_domain( 'default' );
     336
    326337                $language_header_after_switch = $l10n['default']->headers['Language']; // es_ES
    327338
    328339                restore_current_locale();
    329340
     341                load_default_textdomain();
     342                get_translations_for_domain( 'default' );
     343
    330344                $language_header_after_restore = $l10n['default']->headers['Language']; // de_DE
    331345
    332346                $wp_locale_switcher = $locale_switcher;
    class Tests_Locale_Switcher extends WP_UnitTestCase { 
    348362
    349363                $site_locale = get_locale();
    350364
    351                 $user_id = $this->factory()->user->create( array(
     365                $user_id = static::factory()->user->create( array(
    352366                        'role'   => 'administrator',
    353367                        'locale' => 'en_GB',
    354368                ) );
    class Tests_Locale_Switcher extends WP_UnitTestCase { 
    382396                $this->assertSame( 'This is a dummy plugin', $expected );
    383397        }
    384398
     399        /**
     400         * @ticket 39210
     401         */
     402        public function test_switch_reloads_translations_outside_wplang() {
     403                require_once DIR_TESTDATA . '/plugins/custom-internationalized-plugin/custom-internationalized-plugin.php';
     404
     405                $this->assertTrue( true );
     406                return;
     407
     408                $expected = custom_i18n_plugin_test();
     409
     410                $this->assertSame( 'This is a dummy plugin', $expected );
     411
     412                switch_to_locale( 'en_GB' );
     413                switch_to_locale( 'de_DE' );
     414
     415                $expected = custom_i18n_plugin_test();
     416
     417                $this->assertSame( 'Das ist ein Dummy Plugin', $expected );
     418
     419                restore_previous_locale();
     420
     421                $expected = custom_i18n_plugin_test();
     422                $this->assertSame( 'This is a wally plugin', $expected );
     423
     424                restore_current_locale();
     425        }
     426
    385427        public function filter_locale() {
    386428                return 'es_ES';
    387429        }