WordPress.org

Make WordPress Core

Ticket #26511: 26511.diff

File 26511.diff, 10.9 KB (added by swissspidy, 21 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..d36db2b
    - +  
     1<?php
     2/**
     3 * Locale switcher object.
     4 *
     5 * @package    WordPress
     6 * @subpackage i18n
     7 * @since      4.7.0
     8 */
     9
     10/**
     11 * Class 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         * @var string[]
     21         */
     22        private $locales = array();
     23
     24        /**
     25         * Original locale.
     26         *
     27         * @since 4.7.0
     28         * @var string
     29         */
     30        private $original_locale;
     31
     32        /**
     33         * Translation objects.
     34         *
     35         * @since 4.7.0
     36         * @var NOOP_Translations[][]
     37         */
     38        private $translations = array();
     39
     40        /**
     41         * Holds all available languages.
     42         * @var array An array of language codes (file names without the .mo extension)
     43         */
     44        private $available_languages = array();
     45
     46        /**
     47         * Constructor.
     48         *
     49         * Stores the original locale.
     50         *
     51         * @since 4.7.0
     52         */
     53        public function __construct() {
     54                $this->original_locale = get_locale();
     55                $this->available_languages = get_available_languages();
     56
     57                add_filter( 'locale', array( $this, 'filter_locale' ) );
     58        }
     59
     60        /**
     61         * Switches the translations according to the given locale.
     62         *
     63         * @since 4.7.0
     64         *
     65         * @global Mo[]      $l10n      An array of available translations.
     66         * @global WP_Locale $wp_locale The WordPress date and time locale object.
     67         *
     68         * @param string $locale The locale.
     69         * @return bool True on success, false on failure.
     70         */
     71        public function switch_to_locale( $locale ) {
     72                global $l10n;
     73
     74                $current_locale = get_locale();
     75
     76                if ( $current_locale === $locale ) {
     77                        return false;
     78                }
     79
     80                if ( ! in_array( $locale, $this->available_languages ) ) {
     81                        return false;
     82                }
     83
     84                $GLOBALS['wp_locale'] = new WP_Locale();
     85
     86                $this->locales[] = $locale;
     87
     88                if ( null === $l10n ) {
     89                        $l10n = array();
     90                }
     91
     92                if ( empty( $l10n ) ) {
     93                        load_default_textdomain();
     94                }
     95
     96                if ( ! $this->has_translations_for_locale( $current_locale ) ) {
     97                        foreach ( array_keys( $l10n ) as $textdomain ) {
     98                                $this->translations[ $current_locale ][ $textdomain ] = get_translations_for_domain( $textdomain );
     99                        }
     100                }
     101
     102                if ( $this->has_translations_for_locale( $locale ) ) {
     103                        foreach ( array_keys( $l10n ) as $textdomain ) {
     104                                if ( isset( $this->translations[ $locale ][ $textdomain ] ) ) {
     105                                        $l10n[ $textdomain ] = $this->translations[ $locale ][ $textdomain ];
     106                                }
     107                        }
     108                } else {
     109                        /* @var MO $mo */
     110                        foreach ( $l10n as $textdomain => $mo ) {
     111                                if ( 'default' === $textdomain ) {
     112                                        load_default_textdomain();
     113
     114                                        continue;
     115                                }
     116
     117                                unload_textdomain( $textdomain );
     118
     119                                if ( $mofile = $mo->get_filename() ) {
     120                                        load_textdomain( $textdomain, $mofile );
     121                                }
     122
     123                                $this->translations[ $locale ][ $textdomain ] = get_translations_for_domain( $textdomain );
     124                        }
     125                }
     126
     127                /**
     128                 * Fires when the locale is switched.
     129                 *
     130                 * @since 4.7.0
     131                 *
     132                 * @param string $locale The new locale.
     133                 */
     134                do_action( 'switch_locale', $locale );
     135
     136                return true;
     137        }
     138
     139        /**
     140         * Restores the translations according to the previous locale.
     141         *
     142         * @since 4.7.0
     143         *
     144         * @global Mo[]      $l10n      An array of available translations.
     145         * @global WP_Locale $wp_locale The WordPress date and time locale object.
     146         *
     147         * @return string|false Locale on success, false on failure.
     148         */
     149        public function restore_locale() {
     150                global $l10n;
     151
     152                $previous_locale = end( $this->locales );
     153
     154                if ( ! array_pop( $this->locales ) ) {
     155                        // The stack is empty, bail.
     156                        return false;
     157                }
     158
     159                if ( null === $l10n ) {
     160                        $l10n = array();
     161                }
     162
     163                $locale = end( $this->locales );
     164
     165                if ( ! $locale ) {
     166                        // There's nothing left in the stack: go back to the original locale.
     167                        $locale = $this->original_locale;
     168                }
     169
     170                foreach ( array_keys( $l10n ) as $textdomain ) {
     171                        if ( isset( $this->translations[ $locale ][ $textdomain ] ) ) {
     172                                $l10n[ $textdomain ] = $this->translations[ $locale ][ $textdomain ];
     173                        }
     174                }
     175
     176                $GLOBALS['wp_locale'] = new WP_Locale();
     177
     178                /**
     179                 * Fires when the locale is restored to the previous one.
     180                 *
     181                 * @since 4.7.0
     182                 *
     183                 * @param string $locale The new locale.
     184                 * @param string $previous_locale The previous locale.
     185                 */
     186                do_action( 'restore_locale', $locale, $previous_locale );
     187
     188                return $locale;
     189        }
     190
     191        /**
     192         * Filters the WordPress install's locale.
     193         *
     194         * @param string $locale The WordPress install's locale.
     195         * @return string The locale currently being switched to.
     196         */
     197        public function filter_locale( $locale ) {
     198                $switched_locale = end( $this->locales );
     199
     200                if ( $switched_locale ) {
     201                        return $switched_locale;
     202                }
     203
     204                return $locale;
     205        }
     206
     207        /**
     208         * Checks if there are cached translations for the given locale.
     209         *
     210         * @since 4.7.0
     211         *
     212         * @param string $locale The locale.
     213         * @return bool True if there are cached translations for the given locale, false otherwise.
     214         */
     215        private function has_translations_for_locale( $locale ) {
     216                return ! empty( $this->translations[ $locale ] );
     217        }
     218}
  • src/wp-includes/l10n.php

    diff --git src/wp-includes/l10n.php src/wp-includes/l10n.php
    index aaa7611..d253fa6 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_locale() {
     1180        /* @var WP_Locale_Switcher $wp_locale_switcher */
     1181        global $wp_locale_switcher;
     1182
     1183        return $wp_locale_switcher->restore_locale();
     1184}
  • src/wp-includes/load.php

    diff --git src/wp-includes/load.php src/wp-includes/load.php
    index ae32c7a..6084c00 100644
    function wp_load_translations_early() { 
    868868        require_once ABSPATH . WPINC . '/pomo/mo.php';
    869869        require_once ABSPATH . WPINC . '/l10n.php';
    870870        require_once ABSPATH . WPINC . '/class-wp-locale.php';
     871        require_once ABSPATH . WPINC . '/class-wp-locale-switcher.php';
    871872
    872873        // General libraries
    873874        require_once ABSPATH . WPINC . '/plugin.php';
  • src/wp-includes/pomo/mo.php

    diff --git src/wp-includes/pomo/mo.php src/wp-includes/pomo/mo.php
    index 6bc44d6..6188a7a 100644
    class MO extends Gettext_Translations { 
    1616        var $_nplurals = 2;
    1717
    1818        /**
     19         * Loaded MO file.
     20         *
     21         * @since 4.7.0
     22         * @var string
     23         */
     24        private $filename = '';
     25
     26        /**
     27         * Returns the loaded MO file.
     28         *
     29         * @since 4.7.0
     30         *
     31         * @return string The loaded MO file.
     32         */
     33        public function get_filename() {
     34                return $this->filename;
     35        }
     36
     37        /**
    1938         * Fills up with the entries from MO file $filename
    2039         *
    2140         * @param string $filename MO file to load
    2241         */
    2342        function import_from_file($filename) {
    24                 $reader = new POMO_FileReader($filename);
    25                 if (!$reader->is_resource())
     43                $reader = new POMO_FileReader( $filename );
     44
     45                if ( ! $reader->is_resource() ) {
    2646                        return false;
    27                 return $this->import_from_reader($reader);
     47                }
     48
     49                $this->filename = (string) $filename;
     50
     51                return $this->import_from_reader( $reader );
    2852        }
    2953
    3054        /**
    class MO extends Gettext_Translations { 
    299323                return $this->_nplurals;
    300324        }
    301325}
    302 endif;
    303  No newline at end of file
     326endif;
  • src/wp-settings.php

    diff --git src/wp-settings.php src/wp-settings.php
    index 80f556c..ccf0396 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
     394 */
     395$GLOBALS['wp_locale_switcher'] = new WP_Locale_Switcher();
     396
    387397// Load the functions for the active theme, for both parent and child theme if applicable.
    388398if ( ! wp_installing() || 'wp-activate.php' === $pagenow ) {
    389399        if ( TEMPLATEPATH !== STYLESHEETPATH && file_exists( STYLESHEETPATH . '/functions.php' ) )
  • 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..30fc24d
    - +  
     1<?php
     2
     3/**
     4 * @group l10n
     5 * @group i18n
     6 */
     7class Tests_Locale_Switcher extends WP_UnitTestCase {
     8        function test_switch_to_non_existent_locale_returns_false() {
     9                $this->assertFalse( switch_to_locale( 'de_DE' ) );
     10        }
     11
     12        function test_switch_to_non_existent_locale_does_not_change_locale() {
     13                switch_to_locale( 'de_DE' );
     14
     15                $this->assertSame( 'en_US', get_locale() );
     16        }
     17
     18        function test_switch_to_locale_returns_true() {
     19                $expected = switch_to_locale( 'en_GB' );
     20
     21                // Cleanup.
     22                restore_locale();
     23
     24                $this->assertTrue( $expected );
     25        }
     26
     27        function test_switch_to_locale_changes_the_locale() {
     28                switch_to_locale( 'en_GB' );
     29
     30                $locale = get_locale();
     31
     32                // Cleanup.
     33                restore_locale();
     34
     35                $this->assertSame( 'en_GB', $locale );
     36        }
     37
     38        function test_switch_to_locale_loads_translation() {
     39                switch_to_locale( 'es_ES' );
     40
     41                $actual = __( 'Invalid parameter.' );
     42
     43                // Cleanup.
     44                restore_locale();
     45
     46                $this->assertSame( 'Parámetro no válido. ', $actual );
     47        }
     48
     49        function test_restore_locale_without_switching() {
     50                $this->assertFalse( restore_locale() );
     51        }
     52
     53        function test_restore_locale_changes_the_locale_back() {
     54                switch_to_locale( 'en_GB' );
     55
     56                // Cleanup.
     57                restore_locale();
     58
     59                $this->assertSame( 'en_US', get_locale() );
     60        }
     61
     62        function test_switch_to_locale_multiple_times() {
     63                switch_to_locale( 'en_GB' );
     64                switch_to_locale( 'es_ES' );
     65                $locale = get_locale();
     66
     67                // Cleanup.
     68                restore_locale();
     69                restore_locale();
     70
     71                $this->assertSame( 'es_ES', $locale );
     72        }
     73
     74        function test_restore_locale_after_switching_multiple_times() {
     75                switch_to_locale( 'en_GB' );
     76                switch_to_locale( 'es_ES' );
     77                restore_locale();
     78
     79                $locale = get_locale();
     80
     81                // Cleanup.
     82                restore_locale();
     83
     84                $this->assertSame( 'en_GB', $locale );
     85        }
     86
     87        function test_restore_locale_restores_translation() {
     88                switch_to_locale( 'es_ES' );
     89                restore_locale();
     90
     91                $actual = __( 'Invalid parameter.' );
     92
     93                $this->assertSame( 'Invalid parameter.', $actual );
     94        }
     95}