Error “Call to a member function switch_to_locale() on null” during insert_with_markers

Having an issue with my plugin updating the htaccess file. The code I used to do that is:

insert_with_markers($htaccess_file, $marker, $lines);

The parameters used in that function have been previously defined properly. There error message is:

    Uncaught Error: Call to a member function switch_to_locale() on null 
in /home2/path/to/site/fstraptest/wp-includes/l10n.php:1582

I tried ensuring that various functions used by switch_to_locale() are loaded:

if (! function_exists('get_home_path')) 
        {include_once(ABSPATH . 'wp-admin/includes/file.php');}
    if (! function_exists('insert_with_markers')) 
        {include_once(ABSPATH . 'wp-admin/includes/misc.php');}
    if (! function_exists('switch_to_locale')) 
        {
        include_once(ABSPATH . 'wp-admin/includes/l10n.php');
        include_once(ABSPATH . 'wp-includes/class-wp-locale-switcher.php');
        }
    if (! function_exists('got_mod_rewrite')) 
        {include_once(ABSPATH . 'wp-admin/includes/misc.php');}
    if (! function_exists('is_multisite')) 
        {include_once(ABSPATH . 'wp-admin/includes/load.php');}

But that didn’t solve the issue.

This is with WP 5.3, PHP 7.3.11 . Similar code has worked before; this may have started with WP 5.3, but not sure.

The googles have not helped with this error. The language for the site is “en-US”. The plugin does not have any language files. Theme has been changed to “Twenty-Thirteen”; error also occurs in other themes, so does not appear theme-dependent.

Additional Code

At the top of the plugin file, this code initializes the settings

add_action( 'admin_init', 'CWPSO_settings_init' );  // does register_setting, add_settings_section add_settings_field, etc

The CWPSO_settings_init() does the register thing, then there are a bunch of add_settings_field() to set up the options. All of those look similar to this:

add_settings_field( 
        'CWPSO_protect_config_file',                    // field name
        __( '', 'CWPSO_namespace' ),    // message before field (not used)
        'CWPSO_protect_config_file_render',         // render function
        'pluginPage',                   // plugin page name
        'CWPSO_pluginPage_section'      // plugin section name
    );  

This code sanitizes that input field:

if (isset($_POST['CWPSO_protect_config_file'])) {
                $new_input['CWPSO_protect_config_file'] = "1";} else { $new_input['CWPSO_protect_config_file'] = "0";}

This code sets up an array of things that might happen to the htaccess file

if (($options['CWPSO_protect_config_file'])  and ($_GET['page'] == 'cellarweb_private_function')) {
     $change_htaccess[] = 'CWPSO_protect_config_file';
 }

This code checks the previous htaccess array, and builds the statements to put in the htaccess

if (in_array('CWPSO_protect_config_file', $change_htaccess) ) {
        $lines[] = '  # protect wp-config.php file from direct access';
        $lines[] = '     <files wp-config.php>';
        $lines[] = '       order allow,deny';
        $lines[] = '       deny from all';
        $lines[] = '     </files>';
    }

This code does the actual htaccess file modification ($marker has been previously set)

$success = insert_with_markers($htaccess_file, $marker, $lines);

And that insert_with_markers() line causes the error. Note that all of the settings that the plugin uses/creates/save work properly. If I comment out the insert_with_markers() line, the plugin settings display/save properly.

2 Answers
2

From your comment:

Those htaccess changes don’t happen as a result of an add_action.
Perhaps they should?

Yes, they should.

And here’s why

insert_with_markers() calls switch_to_locale() which uses $GLOBALS['wp_locale_switcher'] (or $wp_locale_switcher) which is initialized in wp-settings.php, but only after WordPress runs the setup_theme hook.

And looking at the error in question and line #1582 in wp-includes/l10n.php which is return $wp_locale_switcher->switch_to_locale( $locale );, that error occurred most likely because the global variable $wp_locale_switcher has not yet been defined or initialized. Which indicates that you called insert_with_markers() too early.

So if you want to use insert_with_markers(), make sure you use the proper hook; for example, load-{$page_hook} or update_option_{$option}:

// Example 1:
add_action( 'admin_menu', function () {
    $hookname = add_menu_page( ... );
    add_action( 'load-' . $hookname, function () {
        // Call insert_with_markers()
    } );
} );

// Example 2:
add_action( 'update_option_my_field', function ( $old_value, $value ) {
    // Call insert_with_markers()
}, 10, 2 );

Both tried & tested working on WordPress 5.2.4 and 5.3.

But it’s also possible there’s a plugin or custom code which is messing with $wp_locale_switcher, so if using a hook later than setup_theme doesn’t work for you, you can try deactivating plugins..

Leave a Comment