WordPress.org

Make WordPress Core

Ticket #26511: 26511.6.diff

File 26511.6.diff, 16.5 KB (added by swissspidy, 16 months ago)
  • new file 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
    new file mode 100644
    index 0000000..57c9e0c
    - +  
     1<?php 
     2/** 
     3 * Locale API: WP_Locale_Switcher class 
     4 * 
     5 * @package WordPress 
     6 * @subpackage i18n 
     7 * @since 4.7.0 
     8 */ 
     9 
     10/** 
     11 * Core class used for switching locales. 
     12 * 
     13 * @since 4.7.0 
     14 */ 
     15class WP_Locale_Switcher { 
     16        /** 
     17         * Locale stack. 
     18         * 
     19         * @since 4.7.0 
     20         * @access private 
     21         * @var string[] 
     22         */ 
     23        private $locales = array(); 
     24 
     25        /** 
     26         * Original locale. 
     27         * 
     28         * @since 4.7.0 
     29         * @access private 
     30         * @var string 
     31         */ 
     32        private $original_locale; 
     33 
     34        /** 
     35         * Holds all available languages. 
     36         * 
     37         * @since 4.7.0 
     38         * @access private 
     39         * @var array An array of language codes (file names without the .mo extension). 
     40         */ 
     41        private $available_languages = array(); 
     42 
     43        /** 
     44         * Constructor. 
     45         * 
     46         * Stores the original locale as well as a list of all available languages. 
     47         * 
     48         * @since 4.7.0 
     49         */ 
     50        public function __construct() { 
     51                $this->original_locale     = get_locale(); 
     52                $this->available_languages = get_available_languages(); 
     53        } 
     54 
     55        /** 
     56         * Initializes the locale switcher. 
     57         * 
     58         * Hooks into the {@see 'locale'} filter to change the locale on the fly. 
     59         */ 
     60        public function init() { 
     61                add_filter( 'locale', array( $this, 'filter_locale' ) ); 
     62        } 
     63 
     64        /** 
     65         * Switches the translations according to the given locale. 
     66         * 
     67         * @since 4.7.0 
     68         * 
     69         * @param string $locale The locale to switch to. 
     70         * @return bool True on success, false on failure. 
     71         */ 
     72        public function switch_to_locale( $locale ) { 
     73                if ( $locale === get_locale() ) { 
     74                        return false; 
     75                } 
     76 
     77                if ( ! in_array( $locale, $this->available_languages ) ) { 
     78                        return false; 
     79                } 
     80 
     81                $this->locales[] = $locale; 
     82 
     83                $this->change_locale( $locale ); 
     84 
     85                /** 
     86                 * Fires when the locale is switched. 
     87                 * 
     88                 * @since 4.7.0 
     89                 * 
     90                 * @param string $locale The new locale. 
     91                 */ 
     92                do_action( 'switch_locale', $locale ); 
     93 
     94                return true; 
     95        } 
     96 
     97        /** 
     98         * Restores the translations according to the previous locale. 
     99         * 
     100         * @since 4.7.0 
     101         * 
     102         * @return string|false Locale on success, false on failure. 
     103         */ 
     104        public function restore_previous_locale() { 
     105                $previous_locale = array_pop( $this->locales ); 
     106 
     107                if ( null === $previous_locale ) { 
     108                        // The stack is empty, bail. 
     109                        return false; 
     110                } 
     111 
     112                $locale = end( $this->locales ); 
     113 
     114                if ( ! $locale ) { 
     115                        // There's nothing left in the stack: go back to the original locale. 
     116                        $locale = $this->original_locale; 
     117                } 
     118 
     119                $this->change_locale( $locale ); 
     120 
     121                /** 
     122                 * Fires when the locale is restored to the previous one. 
     123                 * 
     124                 * @since 4.7.0 
     125                 * 
     126                 * @param string $locale          The new locale. 
     127                 * @param string $previous_locale The previous locale. 
     128                 */ 
     129                do_action( 'restore_previous_locale', $locale, $previous_locale ); 
     130 
     131                return $locale; 
     132        } 
     133 
     134        /** 
     135         * Restores the translations according to the original locale. 
     136         * 
     137         * @since 4.7.0 
     138         * 
     139         * @return string|false Locale on success, false on failure. 
     140         */ 
     141        public function restore_current_locale() { 
     142                $this->locales = array( $this->original_locale ); 
     143 
     144                return $this->restore_previous_locale(); 
     145        } 
     146 
     147        /** 
     148         * Filters the WordPress install's locale. 
     149         * 
     150         * @since 4.7.0 
     151         * 
     152         * @param string $locale The WordPress install's locale. 
     153         * @return string The locale currently being switched to. 
     154         */ 
     155        public function filter_locale( $locale ) { 
     156                $switched_locale = end( $this->locales ); 
     157 
     158                if ( $switched_locale ) { 
     159                        return $switched_locale; 
     160                } 
     161 
     162                return $locale; 
     163        } 
     164 
     165        /** 
     166         * Load translations for a given locale. 
     167         * 
     168         * When switching to a locale, translations for this locale must be loaded from scratch. 
     169         * 
     170         * @since 4.7.0 
     171         * @access private 
     172         * 
     173         * @global Mo[] $l10n An array of all currently loaded text domains. 
     174         * 
     175         * @param string $locale The locale to load translations for. 
     176         */ 
     177        private function load_translations( $locale ) { 
     178                global $l10n; 
     179 
     180                if ( ! $l10n ) { 
     181                        $l10n = array(); 
     182                } 
     183 
     184                load_default_textdomain( $locale ); 
     185 
     186                /* @var MO $mo */ 
     187                foreach ( $l10n as $domain => $mo ) { 
     188                        if ( 'default' === $domain ) { 
     189                                continue; 
     190                        } 
     191 
     192                        unload_textdomain( $domain ); 
     193 
     194                        if ( $mo->get_filename() ) { 
     195                                load_textdomain( $domain, $mo->get_filename() ); 
     196                        } 
     197 
     198                        get_translations_for_domain( $domain ); 
     199                } 
     200        } 
     201 
     202        /** 
     203         * Changes the site's locale to the given one. 
     204         * 
     205         * Loads the translations, changes the global `$wp_locale` object and updates 
     206         * all post type labels. 
     207         * 
     208         * @since 4.7.0 
     209         * @access private 
     210         * 
     211         * @global WP_Locale $wp_locale The WordPress date and time locale object. 
     212         * 
     213         * @param string $locale The locale to change to. 
     214         */ 
     215        private function change_locale( $locale ) { 
     216                $this->load_translations( $locale ); 
     217 
     218                $GLOBALS['wp_locale'] = new WP_Locale(); 
     219 
     220                foreach ( get_post_types( array(), 'objects' ) as $post_type ) { 
     221                        $post_type->labels = array(); 
     222                        $post_type->labels = get_post_type_labels( $post_type ); 
     223                        $post_type->label  = $post_type->labels->name; 
     224                } 
     225        } 
     226} 
  • src/wp-includes/l10n.php

    diff --git src/wp-includes/l10n.php src/wp-includes/l10n.php
    index aaa7611..e551d6a 100644
    function is_rtl() { 
    11481148                return false; 
    11491149        } 
    11501150        return $wp_locale->is_rtl(); 
    1151 } 
    1152  No newline at end of file 
     1151} 
     1152 
     1153/** 
     1154 * Switches the translations according to the given locale. 
     1155 * 
     1156 * @since 4.7.0 
     1157 * 
     1158 * @global WP_Locale_Switcher $wp_locale_switcher 
     1159 * 
     1160 * @param string $locale The locale. 
     1161 * @return bool True on success, false on failure. 
     1162 */ 
     1163function switch_to_locale( $locale ) { 
     1164        /* @var WP_Locale_Switcher $wp_locale_switcher */ 
     1165        global $wp_locale_switcher; 
     1166 
     1167        return $wp_locale_switcher->switch_to_locale( $locale ); 
     1168} 
     1169 
     1170/** 
     1171 * Restores the translations according to the previous locale. 
     1172 * 
     1173 * @since 4.7.0 
     1174 * 
     1175 * @global WP_Locale_Switcher $wp_locale_switcher 
     1176 * 
     1177 * @return string|false Locale on success, false on error. 
     1178 */ 
     1179function restore_previous_locale() { 
     1180        /* @var WP_Locale_Switcher $wp_locale_switcher */ 
     1181        global $wp_locale_switcher; 
     1182 
     1183        return $wp_locale_switcher->restore_previous_locale(); 
     1184} 
     1185 
     1186/** 
     1187 * Restores the translations according to the original locale. 
     1188 * 
     1189 * @since 4.7.0 
     1190 * 
     1191 * @global WP_Locale_Switcher $wp_locale_switcher 
     1192 * 
     1193 * @return string|false Locale on success, false on error. 
     1194 */ 
     1195function restore_current_locale() { 
     1196        /* @var WP_Locale_Switcher $wp_locale_switcher */ 
     1197        global $wp_locale_switcher; 
     1198 
     1199        return $wp_locale_switcher->restore_current_locale(); 
     1200} 
  • src/wp-includes/load.php

    diff --git src/wp-includes/load.php src/wp-includes/load.php
    index 2aa4451..6932f83 100644
    function get_current_network_id() { 
    845845 * @since 3.4.0 
    846846 * @access private 
    847847 * 
    848  * @global string    $text_direction 
    849  * @global WP_Locale $wp_locale      The WordPress date and time locale object. 
     848 * @global string             $text_direction 
     849 * @global WP_Locale          $wp_locale      The WordPress date and time locale object. 
     850 * @global WP_Locale_Switcher $wp_locale_switcher WordPress locale switcher object. 
    850851 * 
    851852 * @staticvar bool $loaded 
    852853 */ 
    853854function wp_load_translations_early() { 
    854         global $text_direction, $wp_locale; 
     855        global $text_direction, $wp_locale, $wp_locale_switcher; 
    855856 
    856857        static $loaded = false; 
    857858        if ( $loaded ) 
    function wp_load_translations_early() { 
    868869        require_once ABSPATH . WPINC . '/pomo/mo.php'; 
    869870        require_once ABSPATH . WPINC . '/l10n.php'; 
    870871        require_once ABSPATH . WPINC . '/class-wp-locale.php'; 
     872        require_once ABSPATH . WPINC . '/class-wp-locale-switcher.php'; 
    871873 
    872874        // General libraries 
    873875        require_once ABSPATH . WPINC . '/plugin.php'; 
    function wp_load_translations_early() { 
    919921        } 
    920922 
    921923        $wp_locale = new WP_Locale(); 
     924        $wp_locale_switcher = new WP_Locale_Switcher(); 
     925        $wp_locale_switcher->init(); 
    922926} 
    923927 
    924928/** 
  • src/wp-includes/pomo/mo.php

    diff --git src/wp-includes/pomo/mo.php src/wp-includes/pomo/mo.php
    index 6bc44d6..47e9b6a 100644
    class MO extends Gettext_Translations { 
    1616        var $_nplurals = 2; 
    1717 
    1818        /** 
     19         * Loaded MO file. 
     20         * 
     21         * @var string 
     22         */ 
     23        private $filename = ''; 
     24 
     25        /** 
     26         * Returns the loaded MO file. 
     27         * 
     28         * @return string The loaded MO file. 
     29         */ 
     30        public function get_filename() { 
     31                return $this->filename; 
     32        } 
     33 
     34        /** 
    1935         * Fills up with the entries from MO file $filename 
    2036         * 
    2137         * @param string $filename MO file to load 
    2238         */ 
    2339        function import_from_file($filename) { 
    24                 $reader = new POMO_FileReader($filename); 
    25                 if (!$reader->is_resource()) 
     40                $reader = new POMO_FileReader( $filename ); 
     41 
     42                if ( ! $reader->is_resource() ) { 
    2643                        return false; 
    27                 return $this->import_from_reader($reader); 
     44                } 
     45 
     46                $this->filename = (string) $filename; 
     47 
     48                return $this->import_from_reader( $reader ); 
    2849        } 
    2950 
    3051        /** 
    class MO extends Gettext_Translations { 
    299320                return $this->_nplurals; 
    300321        } 
    301322} 
    302 endif; 
    303  No newline at end of file 
     323endif; 
  • src/wp-settings.php

    diff --git src/wp-settings.php src/wp-settings.php
    index 80f556c..4292f5c 100644
    if ( SHORTINIT ) 
    131131// Load the L10n library. 
    132132require_once( ABSPATH . WPINC . '/l10n.php' ); 
    133133require_once( ABSPATH . WPINC . '/class-wp-locale.php' ); 
     134require_once( ABSPATH . WPINC . '/class-wp-locale-switcher.php' ); 
    134135 
    135136// Run the installer if WordPress is not installed. 
    136137wp_not_installed(); 
    unset( $locale_file ); 
    384385 */ 
    385386$GLOBALS['wp_locale'] = new WP_Locale(); 
    386387 
     388/** 
     389 *  WordPress Locale Switcher object for switching locales. 
     390 * 
     391 * @since 4.7.0 
     392 * 
     393 * @global WP_Locale_Switcher $wp_locale_switcher WordPress locale switcher object. 
     394 */ 
     395$GLOBALS['wp_locale_switcher'] = new WP_Locale_Switcher(); 
     396$GLOBALS['wp_locale_switcher']->init(); 
     397 
    387398// Load the functions for the active theme, for both parent and child theme if applicable. 
    388399if ( ! wp_installing() || 'wp-activate.php' === $pagenow ) { 
    389400        if ( TEMPLATEPATH !== STYLESHEETPATH && file_exists( STYLESHEETPATH . '/functions.php' ) ) 
  • tests/phpunit/tests/l10n.php

    diff --git tests/phpunit/tests/l10n.php tests/phpunit/tests/l10n.php
    index f1048aa..d7fe894 100644
    class Tests_L10n extends WP_UnitTestCase { 
    8585                $this->assertEmpty( $array ); 
    8686 
    8787                $array = get_available_languages( DIR_TESTDATA . '/languages/' ); 
    88                 $this->assertEquals( array( 'en_GB', 'es_ES' ), $array ); 
     88                $this->assertEquals( array( 'de_DE', 'en_GB', 'es_ES' ), $array ); 
    8989        } 
    9090 
    9191        /** 
  • tests/phpunit/tests/l10n/loadTextdomainJustInTime.php

    diff --git tests/phpunit/tests/l10n/loadTextdomainJustInTime.php tests/phpunit/tests/l10n/loadTextdomainJustInTime.php
    index f73cfd5..1d39868 100644
    class Tests_L10n_loadTextdomainJustInTime extends WP_UnitTestCase { 
    141141                $this->assertSame( 'Das ist ein Dummy Plugin', $expected_output_final ); 
    142142                $this->assertTrue( $is_textdomain_loaded_final ); 
    143143        } 
     144 
     145        /** 
     146         * @ticket 26511 
     147         */ 
     148        public function test_plugin_translation_after_switching_locale() { 
     149                require_once DIR_TESTDATA . '/plugins/internationalized-plugin.php'; 
     150 
     151                switch_to_locale( 'de_DE' ); 
     152                $expected = i18n_plugin_test(); 
     153                restore_previous_locale(); 
     154 
     155                $this->assertSame( 'Das ist ein Dummy Plugin', $expected ); 
     156        } 
     157 
     158        /** 
     159         * @ticket 26511 
     160         */ 
     161        public function test_theme_translation_after_switching_locale() { 
     162                switch_theme( 'internationalized-theme' ); 
     163 
     164                require_once get_stylesheet_directory() . '/functions.php'; 
     165 
     166                switch_to_locale( 'de_DE' ); 
     167                $expected = i18n_theme_test(); 
     168                restore_previous_locale(); 
     169 
     170                $this->assertSame( 'Das ist ein Dummy Theme', $expected ); 
     171        } 
    144172} 
  • new file tests/phpunit/tests/l10n/localeSwitcher.php

    diff --git tests/phpunit/tests/l10n/localeSwitcher.php tests/phpunit/tests/l10n/localeSwitcher.php
    new file mode 100644
    index 0000000..8a714c8
    - +  
     1<?php 
     2 
     3/** 
     4 * @group l10n 
     5 * @group i18n 
     6 * @group 26511 
     7 */ 
     8class Tests_Locale_Switcher extends WP_UnitTestCase { 
     9        /** 
     10         * @var string 
     11         */ 
     12        protected $locale = ''; 
     13 
     14        /** 
     15         * @var string 
     16         */ 
     17        protected $previous_locale = ''; 
     18 
     19        public function setUp() { 
     20                $this->locale = ''; 
     21                $this->previous_locale = ''; 
     22        } 
     23 
     24        public function test_switch_to_non_existent_locale_returns_false() { 
     25                $this->assertFalse( switch_to_locale( 'foo_BAR' ) ); 
     26        } 
     27 
     28        public function test_switch_to_non_existent_locale_does_not_change_locale() { 
     29                switch_to_locale( 'foo_BAR' ); 
     30 
     31                $this->assertSame( 'en_US', get_locale() ); 
     32        } 
     33 
     34        public function test_switch_to_locale_returns_true() { 
     35                $expected = switch_to_locale( 'en_GB' ); 
     36 
     37                // Cleanup. 
     38                restore_previous_locale(); 
     39 
     40                $this->assertTrue( $expected ); 
     41        } 
     42 
     43        public function test_switch_to_locale_changes_the_locale() { 
     44                switch_to_locale( 'en_GB' ); 
     45 
     46                $locale = get_locale(); 
     47 
     48                // Cleanup. 
     49                restore_previous_locale(); 
     50 
     51                $this->assertSame( 'en_GB', $locale ); 
     52        } 
     53 
     54        public function test_switch_to_locale_loads_translation() { 
     55                switch_to_locale( 'es_ES' ); 
     56 
     57                $actual = __( 'Invalid parameter.' ); 
     58 
     59                // Cleanup. 
     60                restore_previous_locale(); 
     61 
     62                $this->assertSame( 'Parámetro no válido. ', $actual ); 
     63        } 
     64 
     65        public function test_switch_to_locale_changes_wp_locale_global() { 
     66                global $wp_locale; 
     67 
     68                $expected = array( 
     69                        'thousands_sep' => '.', 
     70                        'decimal_point' => ',', 
     71                ); 
     72 
     73                switch_to_locale( 'de_DE' ); 
     74 
     75                $wp_locale_de_DE = clone $wp_locale; 
     76 
     77                // Cleanup. 
     78                restore_previous_locale(); 
     79 
     80                $this->assertEqualSetsWithIndex( $expected, $wp_locale_de_DE->number_format ); 
     81        } 
     82 
     83        public function test_switch_to_locale_multiple_times() { 
     84                switch_to_locale( 'en_GB' ); 
     85                switch_to_locale( 'es_ES' ); 
     86                $locale = get_locale(); 
     87 
     88                // Cleanup. 
     89                restore_previous_locale(); 
     90                restore_previous_locale(); 
     91 
     92                $this->assertSame( 'es_ES', $locale ); 
     93        } 
     94 
     95        public function test_switch_to_locale_multiple_times_loads_translation() { 
     96                switch_to_locale( 'en_GB' ); 
     97                switch_to_locale( 'de_DE' ); 
     98                switch_to_locale( 'es_ES' ); 
     99 
     100                $actual = __( 'Invalid parameter.' ); 
     101 
     102                // Cleanup. 
     103                restore_previous_locale(); 
     104                restore_previous_locale(); 
     105                restore_previous_locale(); 
     106 
     107                $this->assertSame( 'Parámetro no válido. ', $actual ); 
     108        } 
     109 
     110        public function test_restore_previous_locale_without_switching() { 
     111                $this->assertFalse( restore_previous_locale() ); 
     112        } 
     113 
     114        public function test_restore_previous_locale_changes_the_locale_back() { 
     115                switch_to_locale( 'en_GB' ); 
     116 
     117                // Cleanup. 
     118                restore_previous_locale(); 
     119 
     120                $this->assertSame( 'en_US', get_locale() ); 
     121        } 
     122 
     123        public function test_restore_previous_locale_after_switching_multiple_times() { 
     124                switch_to_locale( 'en_GB' ); 
     125                switch_to_locale( 'es_ES' ); 
     126                restore_previous_locale(); 
     127 
     128                $locale = get_locale(); 
     129 
     130                // Cleanup. 
     131                restore_previous_locale(); 
     132 
     133                $this->assertSame( 'en_GB', $locale ); 
     134        } 
     135 
     136        public function test_restore_previous_locale_restores_translation() { 
     137                switch_to_locale( 'es_ES' ); 
     138                restore_previous_locale(); 
     139 
     140                $actual = __( 'Invalid parameter.' ); 
     141 
     142                $this->assertSame( 'Invalid parameter.', $actual ); 
     143        } 
     144 
     145        public function test_restore_previous_locale_action_passes_previous_locale() { 
     146                switch_to_locale( 'en_GB' ); 
     147                switch_to_locale( 'es_ES' ); 
     148 
     149                add_action( 'restore_previous_locale', array( $this, 'store_locale' ), 10, 2 ); 
     150 
     151                restore_previous_locale(); 
     152 
     153                $previous_locale = $this->previous_locale; 
     154 
     155                // Cleanup. 
     156                restore_previous_locale(); 
     157 
     158                $this->assertSame( 'es_ES', $previous_locale ); 
     159        } 
     160 
     161        public function test_restore_previous_locale_restores_wp_locale_global() { 
     162                global $wp_locale; 
     163 
     164                $expected = array( 
     165                        'thousands_sep' => ',', 
     166                        'decimal_point' => '.', 
     167                ); 
     168 
     169                switch_to_locale( 'de_DE' ); 
     170                restore_previous_locale(); 
     171 
     172                $this->assertEqualSetsWithIndex( $expected, $wp_locale->number_format ); 
     173        } 
     174 
     175        public function test_restore_current_locale_after_switching_multiple_times() { 
     176                switch_to_locale( 'en_GB' ); 
     177                switch_to_locale( 'nl_NL' ); 
     178                switch_to_locale( 'es_ES' ); 
     179 
     180                restore_current_locale(); 
     181 
     182                $this->assertSame( 'en_US', get_locale() ); 
     183        } 
     184 
     185        public function store_locale( $locale, $previous_locale ) { 
     186                $this->locale = $locale; 
     187                $this->previous_locale = $previous_locale; 
     188        } 
     189} 
  • tests/phpunit/tests/locale.php

    diff --git tests/phpunit/tests/locale.php tests/phpunit/tests/locale.php
    index 1c335f4..79372d6 100644
     
    11<?php 
    22 
    33/** 
    4  * @group locale 
     4 * @group l10n 
    55 * @group i18n 
    66 */ 
    77class Tests_Locale extends WP_UnitTestCase {