Make WordPress Core


Ignore:
Timestamp:
01/30/2023 10:25:53 AM (2 years ago)
Author:
swissspidy
Message:

I18N: Introduce switch_to_user_locale().

This new function makes it easier to switch to a specific user’s locale by reducing duplicate code and storing the user’s ID as additional context for plugins to consume. Existing usage of switch_to_locale() in core has been replaced with switch_to_user_locale() where appropriate.

Also, this change ensures WP_Locale_Switcher properly filters determine_locale so that anyyone using the determine_locale() function will get the correct locale information when switching is in effect.

Props costdev.
Fixes #57123.
See #26511.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/l10n/wpLocaleSwitcher.php

    r55010 r55161  
    1717    protected $previous_locale = '';
    1818
    19     public function set_up() {
    20         parent::set_up();
    21 
    22         $this->locale          = '';
    23         $this->previous_locale = '';
    24 
    25         unset( $GLOBALS['l10n'], $GLOBALS['l10n_unloaded'] );
    26 
    27         global $wp_textdomain_registry, $wp_locale_switcher;
    28 
    29         $wp_textdomain_registry = new WP_Textdomain_Registry();
    30 
    31         remove_filter( 'locale', array( $wp_locale_switcher, 'filter_locale' ) );
    32         $wp_locale_switcher = new WP_Locale_Switcher();
    33         $wp_locale_switcher->init();
    34     }
    35 
    36     public function tear_down() {
    37         unset( $GLOBALS['l10n'], $GLOBALS['l10n_unloaded'] );
    38 
    39         global $wp_textdomain_registry, $wp_locale_switcher;
    40 
    41         $wp_textdomain_registry = new WP_Textdomain_Registry();
    42 
    43         remove_filter( 'locale', array( $wp_locale_switcher, 'filter_locale' ) );
    44         $wp_locale_switcher = new WP_Locale_Switcher();
    45         $wp_locale_switcher->init();
    46 
    47         parent::tear_down();
    48     }
    49 
    50     /**
    51      * @covers ::switch_to_locale
    52      */
    53     public function test_switch_to_non_existent_locale_returns_false() {
    54         $this->assertFalse( switch_to_locale( 'foo_BAR' ) );
    55     }
    56 
    57     /**
    58      * @covers ::switch_to_locale
    59      */
    60     public function test_switch_to_non_existent_locale_does_not_change_locale() {
    61         switch_to_locale( 'foo_BAR' );
    62 
    63         $this->assertSame( 'en_US', get_locale() );
    64     }
    65 
    66     /**
    67      * @covers ::switch_to_locale
    68      */
    69     public function test_switch_to_locale_returns_true() {
    70         $expected = switch_to_locale( 'en_GB' );
    71 
    72         // Cleanup.
    73         restore_previous_locale();
    74 
    75         $this->assertTrue( $expected );
    76     }
    77 
    78     /**
    79      * @covers ::switch_to_locale
    80      */
    81     public function test_switch_to_locale_changes_the_locale() {
    82         switch_to_locale( 'en_GB' );
    83 
    84         $locale = get_locale();
    85 
    86         // Cleanup.
    87         restore_previous_locale();
    88 
    89         $this->assertSame( 'en_GB', $locale );
    90     }
    91 
    92     /**
    93      * @covers ::switch_to_locale
    94      * @covers ::translate
    95      * @covers ::__
    96      */
    97     public function test_switch_to_locale_loads_translation() {
    98         switch_to_locale( 'es_ES' );
    99 
    100         $actual = __( 'Invalid parameter.' );
    101 
    102         // Cleanup.
    103         restore_previous_locale();
    104 
    105         $this->assertSame( 'Parámetro no válido. ', $actual );
    106     }
    107 
    108     /**
    109      * @covers ::switch_to_locale
    110      */
    111     public function test_switch_to_locale_changes_wp_locale_global() {
    112         global $wp_locale;
    113 
    114         $expected = array(
    115             'thousands_sep' => '.',
    116             'decimal_point' => ',',
    117         );
    118 
    119         switch_to_locale( 'de_DE' );
    120 
    121         $wp_locale_de_de = clone $wp_locale;
    122 
    123         // Cleanup.
    124         restore_previous_locale();
    125 
    126         $this->assertSameSetsWithIndex( $expected, $wp_locale_de_de->number_format );
    127     }
    128 
    129     /**
    130      * @covers ::switch_to_locale
    131      */
    132     public function test_switch_to_locale_en_US() {
    133         switch_to_locale( 'en_GB' );
    134         $locale_en_gb = get_locale();
    135         switch_to_locale( 'en_US' );
    136         $locale_en_us = get_locale();
    137 
    138         // Cleanup.
    139         restore_current_locale();
    140 
    141         $this->assertSame( 'en_GB', $locale_en_gb );
    142         $this->assertSame( 'en_US', $locale_en_us );
    143     }
    144 
    145     /**
    146      * @covers ::switch_to_locale
    147      */
    148     public function test_switch_to_locale_multiple_times() {
    149         switch_to_locale( 'en_GB' );
    150         switch_to_locale( 'es_ES' );
    151         $locale = get_locale();
    152 
    153         // Cleanup.
    154         restore_previous_locale();
    155         restore_previous_locale();
    156 
    157         $this->assertSame( 'es_ES', $locale );
    158     }
    159 
    160     /**
    161      * @covers ::switch_to_locale
    162      * @covers ::__
    163      * @covers ::translate
    164      */
    165     public function test_switch_to_locale_multiple_times_loads_translation() {
    166         switch_to_locale( 'en_GB' );
    167         switch_to_locale( 'de_DE' );
    168         switch_to_locale( 'es_ES' );
    169 
    170         $actual = __( 'Invalid parameter.' );
    171 
    172         // Cleanup.
    173         restore_previous_locale();
    174         restore_previous_locale();
    175         restore_previous_locale();
    176 
    177         $this->assertSame( 'Parámetro no válido. ', $actual );
    178     }
    179 
    180     /**
    181      * @covers ::restore_previous_locale
    182      */
    183     public function test_restore_previous_locale_without_switching() {
    184         $this->assertFalse( restore_previous_locale() );
    185     }
    186 
    187     /**
    188      * @covers ::restore_previous_locale
    189      */
    190     public function test_restore_previous_locale_changes_the_locale_back() {
    191         switch_to_locale( 'en_GB' );
    192 
    193         // Cleanup.
    194         restore_previous_locale();
    195 
    196         $this->assertSame( 'en_US', get_locale() );
    197     }
    198 
    199     /**
    200      * @covers ::restore_previous_locale
    201      */
    202     public function test_restore_previous_locale_after_switching_multiple_times() {
    203         switch_to_locale( 'en_GB' );
    204         switch_to_locale( 'es_ES' );
    205         restore_previous_locale();
    206 
    207         $locale = get_locale();
    208 
    209         // Cleanup.
    210         restore_previous_locale();
    211 
    212         $this->assertSame( 'en_GB', $locale );
    213     }
    214 
    215     /**
    216      * @covers ::restore_previous_locale
    217      * @covers ::__
    218      * @covers ::translate
    219      */
    220     public function test_restore_previous_locale_restores_translation() {
    221         switch_to_locale( 'es_ES' );
    222         restore_previous_locale();
    223 
    224         $actual = __( 'Invalid parameter.' );
    225 
    226         $this->assertSame( 'Invalid parameter.', $actual );
    227     }
    228 
    229     /**
    230      * @covers ::restore_previous_locale
    231      */
    232     public function test_restore_previous_locale_action_passes_previous_locale() {
    233         switch_to_locale( 'en_GB' );
    234         switch_to_locale( 'es_ES' );
    235 
    236         add_action( 'restore_previous_locale', array( $this, 'store_locale' ), 10, 2 );
    237 
    238         restore_previous_locale();
    239 
    240         $previous_locale = $this->previous_locale;
    241 
    242         // Cleanup.
    243         restore_previous_locale();
    244 
    245         $this->assertSame( 'es_ES', $previous_locale );
    246     }
    247 
    248     /**
    249      * @covers ::restore_previous_locale
    250      */
    251     public function test_restore_previous_locale_restores_wp_locale_global() {
    252         global $wp_locale;
    253 
    254         $expected = array(
    255             'thousands_sep' => ',',
    256             'decimal_point' => '.',
    257         );
    258 
    259         switch_to_locale( 'de_DE' );
    260         restore_previous_locale();
    261 
    262         $this->assertSameSetsWithIndex( $expected, $wp_locale->number_format );
    263     }
    264 
    265     /**
    266      * @covers ::restore_current_locale
    267      */
    268     public function test_restore_current_locale_without_switching() {
    269         $this->assertFalse( restore_current_locale() );
    270     }
    271 
    272     /**
    273      * @covers ::restore_previous_locale
    274      */
    275     public function test_restore_current_locale_after_switching_multiple_times() {
    276         switch_to_locale( 'en_GB' );
    277         switch_to_locale( 'nl_NL' );
    278         switch_to_locale( 'es_ES' );
    279 
    280         restore_current_locale();
    281 
    282         $this->assertSame( 'en_US', get_locale() );
    283     }
    284 
    285     public function store_locale( $locale, $previous_locale ) {
    286         $this->locale          = $locale;
    287         $this->previous_locale = $previous_locale;
    288     }
    289 
    290     /**
    291      * @covers ::is_locale_switched
    292      */
    293     public function test_is_locale_switched_if_not_switched() {
    294         $this->assertFalse( is_locale_switched() );
    295     }
    296 
    297     /**
    298      * @covers ::is_locale_switched
    299      */
    300     public function test_is_locale_switched_original_locale() {
    301         $original_locale = get_locale();
    302 
    303         switch_to_locale( 'en_GB' );
    304         switch_to_locale( $original_locale );
    305 
    306         $is_locale_switched = is_locale_switched();
    307 
    308         restore_current_locale();
    309 
    310         $this->assertTrue( $is_locale_switched );
    311     }
    312 
    313     /**
    314      * @covers ::is_locale_switched
    315      */
    316     public function test_is_locale_switched() {
    317         switch_to_locale( 'en_GB' );
    318         switch_to_locale( 'nl_NL' );
    319 
    320         $is_locale_switched = is_locale_switched();
    321 
    322         restore_current_locale();
    323 
    324         $this->assertTrue( $is_locale_switched );
    325     }
    326 
    327     /**
    328      * @covers ::switch_to_locale
    329      */
    330     public function test_switch_to_site_locale_if_user_locale_is_set() {
    331         global $l10n, $wp_locale_switcher;
    332 
    333         $site_locale = get_locale();
    334 
    335         $user_id = self::factory()->user->create(
     19    /**
     20     * @var int
     21     */
     22    protected static $user_id;
     23
     24    public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
     25        self::$user_id = $factory->user->create(
    33626            array(
    33727                'role'   => 'administrator',
     
    33929            )
    34030        );
    341 
    342         wp_set_current_user( $user_id );
     31    }
     32
     33    public function set_up() {
     34        parent::set_up();
     35
     36        $this->locale          = '';
     37        $this->previous_locale = '';
     38
     39        unset( $GLOBALS['l10n'], $GLOBALS['l10n_unloaded'] );
     40
     41        global $wp_textdomain_registry, $wp_locale_switcher;
     42
     43        $wp_textdomain_registry = new WP_Textdomain_Registry();
     44
     45        remove_filter( 'locale', array( $wp_locale_switcher, 'filter_locale' ) );
     46        $wp_locale_switcher = new WP_Locale_Switcher();
     47        $wp_locale_switcher->init();
     48    }
     49
     50    public function tear_down() {
     51        unset( $GLOBALS['l10n'], $GLOBALS['l10n_unloaded'] );
     52
     53        global $wp_textdomain_registry, $wp_locale_switcher;
     54
     55        $wp_textdomain_registry = new WP_Textdomain_Registry();
     56
     57        remove_filter( 'locale', array( $wp_locale_switcher, 'filter_locale' ) );
     58        $wp_locale_switcher = new WP_Locale_Switcher();
     59        $wp_locale_switcher->init();
     60
     61        parent::tear_down();
     62    }
     63
     64    /**
     65     * @covers ::switch_to_locale
     66     */
     67    public function test_switch_to_non_existent_locale_returns_false() {
     68        $this->assertFalse( switch_to_locale( 'foo_BAR' ) );
     69    }
     70
     71    /**
     72     * @covers ::switch_to_locale
     73     */
     74    public function test_switch_to_non_existent_locale_does_not_change_locale() {
     75        switch_to_locale( 'foo_BAR' );
     76
     77        $this->assertSame( 'en_US', get_locale() );
     78    }
     79
     80    /**
     81     * @covers ::switch_to_locale
     82     */
     83    public function test_switch_to_locale_returns_true() {
     84        $expected = switch_to_locale( 'en_GB' );
     85
     86        // Cleanup.
     87        restore_previous_locale();
     88
     89        $this->assertTrue( $expected );
     90    }
     91
     92    /**
     93     * @covers ::switch_to_locale
     94     */
     95    public function test_switch_to_locale_changes_the_locale() {
     96        switch_to_locale( 'en_GB' );
     97
     98        $locale = get_locale();
     99
     100        // Cleanup.
     101        restore_previous_locale();
     102
     103        $this->assertSame( 'en_GB', $locale );
     104    }
     105
     106    /**
     107     * @ticket 57123
     108     *
     109     * @covers ::switch_to_locale
     110     */
     111    public function test_switch_to_locale_changes_determined_locale() {
     112        switch_to_locale( 'en_GB' );
     113
     114        $locale = determine_locale();
     115
     116        // Cleanup.
     117        restore_previous_locale();
     118
     119        $this->assertSame( 'en_GB', $locale );
     120    }
     121
     122    /**
     123     * @covers ::switch_to_locale
     124     * @covers ::translate
     125     * @covers ::__
     126     */
     127    public function test_switch_to_locale_loads_translation() {
     128        switch_to_locale( 'es_ES' );
     129
     130        $actual = __( 'Invalid parameter.' );
     131
     132        // Cleanup.
     133        restore_previous_locale();
     134
     135        $this->assertSame( 'Parámetro no válido. ', $actual );
     136    }
     137
     138    /**
     139     * @covers ::switch_to_locale
     140     */
     141    public function test_switch_to_locale_changes_wp_locale_global() {
     142        global $wp_locale;
     143
     144        $expected = array(
     145            'thousands_sep' => '.',
     146            'decimal_point' => ',',
     147        );
     148
     149        switch_to_locale( 'de_DE' );
     150
     151        $wp_locale_de_de = clone $wp_locale;
     152
     153        // Cleanup.
     154        restore_previous_locale();
     155
     156        $this->assertSameSetsWithIndex( $expected, $wp_locale_de_de->number_format );
     157    }
     158
     159    /**
     160     * @covers ::switch_to_locale
     161     */
     162    public function test_switch_to_locale_en_US() {
     163        switch_to_locale( 'en_GB' );
     164        $locale_en_gb = get_locale();
     165        switch_to_locale( 'en_US' );
     166        $locale_en_us = get_locale();
     167
     168        // Cleanup.
     169        restore_current_locale();
     170
     171        $this->assertSame( 'en_GB', $locale_en_gb );
     172        $this->assertSame( 'en_US', $locale_en_us );
     173    }
     174
     175    /**
     176     * @covers ::switch_to_locale
     177     */
     178    public function test_switch_to_locale_multiple_times() {
     179        switch_to_locale( 'en_GB' );
     180        switch_to_locale( 'es_ES' );
     181        $locale = get_locale();
     182
     183        // Cleanup.
     184        restore_previous_locale();
     185        restore_previous_locale();
     186
     187        $this->assertSame( 'es_ES', $locale );
     188    }
     189
     190    /**
     191     * @covers ::switch_to_locale
     192     * @covers ::__
     193     * @covers ::translate
     194     */
     195    public function test_switch_to_locale_multiple_times_loads_translation() {
     196        switch_to_locale( 'en_GB' );
     197        switch_to_locale( 'de_DE' );
     198        switch_to_locale( 'es_ES' );
     199
     200        $actual = __( 'Invalid parameter.' );
     201
     202        // Cleanup.
     203        restore_previous_locale();
     204        restore_previous_locale();
     205        restore_previous_locale();
     206
     207        $this->assertSame( 'Parámetro no válido. ', $actual );
     208    }
     209
     210    /**
     211     * @covers ::restore_previous_locale
     212     */
     213    public function test_restore_previous_locale_without_switching() {
     214        $this->assertFalse( restore_previous_locale() );
     215    }
     216
     217    /**
     218     * @covers ::restore_previous_locale
     219     */
     220    public function test_restore_previous_locale_changes_the_locale_back() {
     221        switch_to_locale( 'en_GB' );
     222
     223        // Cleanup.
     224        restore_previous_locale();
     225
     226        $this->assertSame( 'en_US', get_locale() );
     227    }
     228
     229    /**
     230     * @covers ::restore_previous_locale
     231     */
     232    public function test_restore_previous_locale_after_switching_multiple_times() {
     233        switch_to_locale( 'en_GB' );
     234        switch_to_locale( 'es_ES' );
     235        restore_previous_locale();
     236
     237        $locale = get_locale();
     238
     239        // Cleanup.
     240        restore_previous_locale();
     241
     242        $this->assertSame( 'en_GB', $locale );
     243    }
     244
     245    /**
     246     * @covers ::restore_previous_locale
     247     * @covers ::__
     248     * @covers ::translate
     249     */
     250    public function test_restore_previous_locale_restores_translation() {
     251        switch_to_locale( 'es_ES' );
     252        restore_previous_locale();
     253
     254        $actual = __( 'Invalid parameter.' );
     255
     256        $this->assertSame( 'Invalid parameter.', $actual );
     257    }
     258
     259    /**
     260     * @covers ::restore_previous_locale
     261     */
     262    public function test_restore_previous_locale_action_passes_previous_locale() {
     263        switch_to_locale( 'en_GB' );
     264        switch_to_locale( 'es_ES' );
     265
     266        add_action( 'restore_previous_locale', array( $this, 'store_locale' ), 10, 2 );
     267
     268        restore_previous_locale();
     269
     270        $previous_locale = $this->previous_locale;
     271
     272        // Cleanup.
     273        restore_previous_locale();
     274
     275        $this->assertSame( 'es_ES', $previous_locale );
     276    }
     277
     278    /**
     279     * @covers ::restore_previous_locale
     280     */
     281    public function test_restore_previous_locale_restores_wp_locale_global() {
     282        global $wp_locale;
     283
     284        $expected = array(
     285            'thousands_sep' => ',',
     286            'decimal_point' => '.',
     287        );
     288
     289        switch_to_locale( 'de_DE' );
     290        restore_previous_locale();
     291
     292        $this->assertSameSetsWithIndex( $expected, $wp_locale->number_format );
     293    }
     294
     295    /**
     296     * @covers ::restore_current_locale
     297     */
     298    public function test_restore_current_locale_without_switching() {
     299        $this->assertFalse( restore_current_locale() );
     300    }
     301
     302    /**
     303     * @covers ::restore_previous_locale
     304     */
     305    public function test_restore_current_locale_after_switching_multiple_times() {
     306        switch_to_locale( 'en_GB' );
     307        switch_to_locale( 'nl_NL' );
     308        switch_to_locale( 'es_ES' );
     309
     310        restore_current_locale();
     311
     312        $this->assertSame( 'en_US', get_locale() );
     313    }
     314
     315    public function store_locale( $locale, $previous_locale ) {
     316        $this->locale          = $locale;
     317        $this->previous_locale = $previous_locale;
     318    }
     319
     320    /**
     321     * @covers ::is_locale_switched
     322     */
     323    public function test_is_locale_switched_if_not_switched() {
     324        $this->assertFalse( is_locale_switched() );
     325    }
     326
     327    /**
     328     * @covers ::is_locale_switched
     329     */
     330    public function test_is_locale_switched_original_locale() {
     331        $original_locale = get_locale();
     332
     333        switch_to_locale( 'en_GB' );
     334        switch_to_locale( $original_locale );
     335
     336        $is_locale_switched = is_locale_switched();
     337
     338        restore_current_locale();
     339
     340        $this->assertTrue( $is_locale_switched );
     341    }
     342
     343    /**
     344     * @covers ::is_locale_switched
     345     */
     346    public function test_is_locale_switched() {
     347        switch_to_locale( 'en_GB' );
     348        switch_to_locale( 'nl_NL' );
     349
     350        $is_locale_switched = is_locale_switched();
     351
     352        restore_current_locale();
     353
     354        $this->assertTrue( $is_locale_switched );
     355    }
     356
     357    /**
     358     * @covers ::switch_to_locale
     359     */
     360    public function test_switch_to_site_locale_if_user_locale_is_set() {
     361        global $l10n, $wp_locale_switcher;
     362
     363        $site_locale = get_locale();
     364
     365        wp_set_current_user( self::$user_id );
    343366        set_current_screen( 'dashboard' );
    344367
     
    383406        $site_locale = get_locale();
    384407
    385         $user_id = self::factory()->user->create(
    386             array(
    387                 'role'   => 'administrator',
    388                 'locale' => 'de_DE',
    389             )
    390         );
    391 
    392         wp_set_current_user( $user_id );
     408        wp_set_current_user( self::$user_id );
    393409        set_current_screen( 'dashboard' );
    394410
     
    431447        $site_locale = get_locale();
    432448
    433         $user_id = self::factory()->user->create(
    434             array(
    435                 'role'   => 'administrator',
    436                 'locale' => 'en_GB',
    437             )
    438         );
    439 
    440         wp_set_current_user( $user_id );
     449        wp_set_current_user( self::$user_id );
     450        update_user_meta( self::$user_id, 'locale', 'en_GB' );
    441451        set_current_screen( 'dashboard' );
    442452
     
    584594    }
    585595
     596    /**
     597     * @ticket 57123
     598     *
     599     * @covers ::switch_to_locale
     600     * @covers ::switch_to_user_locale
     601     * @covers WP_Locale_Switcher::get_current_locale
     602     * @covers WP_Locale_Switcher::get_current_user_id
     603     */
     604    public function test_returns_current_locale_and_user_after_switching() {
     605        global $wp_locale_switcher;
     606
     607        $user_2 = self::factory()->user->create(
     608            array(
     609                'role'   => 'administrator',
     610                'locale' => 'es_ES',
     611            )
     612        );
     613
     614        $locale_1  = $wp_locale_switcher->get_current_locale();
     615        $user_id_1 = $wp_locale_switcher->get_current_user_id();
     616
     617        switch_to_user_locale( self::$user_id );
     618
     619        $locale_2  = $wp_locale_switcher->get_current_locale();
     620        $user_id_2 = $wp_locale_switcher->get_current_user_id();
     621
     622        switch_to_locale( 'en_GB' );
     623
     624        $locale_3  = $wp_locale_switcher->get_current_locale();
     625        $user_id_3 = $wp_locale_switcher->get_current_user_id();
     626
     627        switch_to_user_locale( $user_2 );
     628
     629        $locale_4  = $wp_locale_switcher->get_current_locale();
     630        $user_id_4 = $wp_locale_switcher->get_current_user_id();
     631
     632        restore_current_locale();
     633
     634        $locale_5  = $wp_locale_switcher->get_current_locale();
     635        $user_id_5 = $wp_locale_switcher->get_current_user_id();
     636
     637        $this->assertFalse( $locale_1, 'Locale should be false before switching' );
     638        $this->assertFalse( $user_id_1, 'User ID should be false before switching' );
     639
     640        $this->assertSame( 'de_DE', $locale_2, 'The locale was not changed to de_DE' );
     641        $this->assertSame( self::$user_id, $user_id_2, 'User ID should match the main admin ID' );
     642
     643        $this->assertSame( 'en_GB', $locale_3, 'The locale was not changed to en_GB' );
     644        $this->assertFalse( $user_id_3, 'User ID should be false after normal locale switching' );
     645
     646        $this->assertSame( 'es_ES', $locale_4, 'The locale was not changed to es_ES' );
     647        $this->assertSame( $user_2, $user_id_4, 'User ID should match the second admin ID' );
     648
     649        $this->assertFalse( $locale_5, 'Locale should be false after restoring' );
     650        $this->assertFalse( $user_id_5, 'User ID should be false after restoring' );
     651
     652    }
     653
    586654    public function filter_locale() {
    587655        return 'es_ES';
Note: See TracChangeset for help on using the changeset viewer.