admin管理员组

文章数量:1023251

I'm currently rewriting a little plugin that shows visitors a small info text. This plugin is German only so far and so I want to add multi language support as I am working on a page that should be in English and German. The text that is displayed to the visitor can be set in the settings interface of the plugin. The given values are stored in a single option in the database. In my modified plugin I store the settings in separate options, each for one language. I've added a $_GET paramter which is used in the setting registration to create a unique name for a language specific option.

My important (stripped-down) parts of my plugin class:

class Privacy_Policies {
    // the language to which the text is translated
    public $translation;
    // the options, stored in the database
    public $options;

    public function __construct() {
        // use the current user locale as a fallback
        $this->translation = isset($_GET['lang']) ? $_GET['lang'] : get_user_locale();
        // if an option already exists, edit it
        // use $this->translation to determine the right language
        $this->options = get_option('privacy_policies_' . $this->translation);
        // call registration when settings page gets loaded
        add_action('admin_init', array($this, 'register_settings');
        // create the settings page
        add_action('admin_menu', array($this, 'add_settings_page');
    }

    // settings validation, called as callback to register settings
    public function validate_settings($value) {
        if (isset($value['checkbox']) && 1 == $value['checkbox']) {
            $value[ 'checkbox' ] = 1;
        } else {
            $value[ 'checkbox' ] = 0;
        }
        $value['notice'] = normalize_whitespace($value['notice' ]);
        $value['error_message'] = normalize_whitespace($value['error_message']);
        $value['style'] = normalize_whitespace($value['style']);

        return $value;
    }

    // register a distinct option name for each language
    // the function is called when the settings page gets loaded
    public function register_settings() {
        register_setting(
            'privacy_notice_settings_group', 
            'privacy_notice_settings_' . $this->translation,
            array( $this, 'validate_settings' )
        );
    }

    // create the html for the settings page
    // stripped down to a simple checkbox
    public function get_settings_page() { ?>
        <h2><?php echo $this->get_plugin_data('Name'); ?></h2>
        <form method="post" action="options.php">
            <?php settings_fields('privacy_notice_settings_group'); ?>
            <table class="form-table">
                <tr valign="top">
                    <td>
                        <!-- important: 'name' must reflect the option name! -->
                        <input type="checkbox" id="privacy_checkbox" name="privacy_notice_settings_<?php echo $this->translation ?>[checkbox]" value="1"
                        <?php if (isset($this->options['checkbox'])) {
                            checked('1', $this->options['checkbox']);
                        } ?> />
                    </td>
                </tr>
            </table>
        </form>
    <?php }

    // add settings page
    // called in the admin_menu hook
    public function add_settings_page() {
        add_options_page(
            'Privacy Policies Settings',
            'Privacy Policies',
            'manage_options',
            'privacy_notice_settings_group',
            array( $this, 'get_settings_page' )
        );
    }
}

The funny thing is that, whatever locale is in $this->locale the setting will always be stored in the database as setting of WP's current locale (get_user_locale()). I.e. a setting's name that has been composed of 'privacy_notice_settings_' . $this->translation gets mysteriously recomposed to 'privacy_notice_settings_' . get_user_locale(). I suspect the secret lies somewhere burried in options.php which the form is calling. But I seem to be unable to debug this.

I'm currently rewriting a little plugin that shows visitors a small info text. This plugin is German only so far and so I want to add multi language support as I am working on a page that should be in English and German. The text that is displayed to the visitor can be set in the settings interface of the plugin. The given values are stored in a single option in the database. In my modified plugin I store the settings in separate options, each for one language. I've added a $_GET paramter which is used in the setting registration to create a unique name for a language specific option.

My important (stripped-down) parts of my plugin class:

class Privacy_Policies {
    // the language to which the text is translated
    public $translation;
    // the options, stored in the database
    public $options;

    public function __construct() {
        // use the current user locale as a fallback
        $this->translation = isset($_GET['lang']) ? $_GET['lang'] : get_user_locale();
        // if an option already exists, edit it
        // use $this->translation to determine the right language
        $this->options = get_option('privacy_policies_' . $this->translation);
        // call registration when settings page gets loaded
        add_action('admin_init', array($this, 'register_settings');
        // create the settings page
        add_action('admin_menu', array($this, 'add_settings_page');
    }

    // settings validation, called as callback to register settings
    public function validate_settings($value) {
        if (isset($value['checkbox']) && 1 == $value['checkbox']) {
            $value[ 'checkbox' ] = 1;
        } else {
            $value[ 'checkbox' ] = 0;
        }
        $value['notice'] = normalize_whitespace($value['notice' ]);
        $value['error_message'] = normalize_whitespace($value['error_message']);
        $value['style'] = normalize_whitespace($value['style']);

        return $value;
    }

    // register a distinct option name for each language
    // the function is called when the settings page gets loaded
    public function register_settings() {
        register_setting(
            'privacy_notice_settings_group', 
            'privacy_notice_settings_' . $this->translation,
            array( $this, 'validate_settings' )
        );
    }

    // create the html for the settings page
    // stripped down to a simple checkbox
    public function get_settings_page() { ?>
        <h2><?php echo $this->get_plugin_data('Name'); ?></h2>
        <form method="post" action="options.php">
            <?php settings_fields('privacy_notice_settings_group'); ?>
            <table class="form-table">
                <tr valign="top">
                    <td>
                        <!-- important: 'name' must reflect the option name! -->
                        <input type="checkbox" id="privacy_checkbox" name="privacy_notice_settings_<?php echo $this->translation ?>[checkbox]" value="1"
                        <?php if (isset($this->options['checkbox'])) {
                            checked('1', $this->options['checkbox']);
                        } ?> />
                    </td>
                </tr>
            </table>
        </form>
    <?php }

    // add settings page
    // called in the admin_menu hook
    public function add_settings_page() {
        add_options_page(
            'Privacy Policies Settings',
            'Privacy Policies',
            'manage_options',
            'privacy_notice_settings_group',
            array( $this, 'get_settings_page' )
        );
    }
}

The funny thing is that, whatever locale is in $this->locale the setting will always be stored in the database as setting of WP's current locale (get_user_locale()). I.e. a setting's name that has been composed of 'privacy_notice_settings_' . $this->translation gets mysteriously recomposed to 'privacy_notice_settings_' . get_user_locale(). I suspect the secret lies somewhere burried in options.php which the form is calling. But I seem to be unable to debug this.

Share Improve this question edited Apr 12, 2019 at 17:59 5tefan asked Apr 10, 2019 at 22:56 5tefan5tefan 213 bronze badges 6
  • And how do you make the site multilanguage? Do you use any ML plugin? – Krzysiek Dróżdż Commented Apr 11, 2019 at 4:10
  • I'm using WPGlobus: wordpress/plugins/wpglobus – 5tefan Commented Apr 11, 2019 at 18:11
  • for the third argument for register_setting you seem to have a validation callback (not included in your code) ... but that would need to be array('sanitize_callback' => array($this->validate_settings)) in any case. developer.wordpress/reference/functions/register_setting – majick Commented Apr 12, 2019 at 7:02
  • @majick - thanks for the tip! I've tried your suggestion but that doesn't seem to solve the problem. $this->validate_settings is invalid (only $this->validate_settings()` executes immediately which isn't what I need here). The particular line you've pointed out comes from the original implementation of the plugin. I'm not sure validate_settings is ever executed properly (I get no error, however). I'll try again later... – 5tefan Commented Apr 12, 2019 at 17:54
  • So, where/how do you actually pass &lang=en to satisfy the isset($_GET['lang']) ? – Anastis Commented Apr 12, 2019 at 20:54
 |  Show 1 more comment

1 Answer 1

Reset to default 0

I haven't yet tried to finally fix my issue but dare to say what's wrong: WP doesn't allow me to use $_GET directly. It expects these variables to get sanitized by first whitelisting them through the query_vars hook and later calling them through a WP_query instance - haven't figured out in detail yet but that seems to make sense to me. Here's a post on the wordpress forum that might explain more: query-string-url-parameter-in-wp-admin-custom-page

I'm currently rewriting a little plugin that shows visitors a small info text. This plugin is German only so far and so I want to add multi language support as I am working on a page that should be in English and German. The text that is displayed to the visitor can be set in the settings interface of the plugin. The given values are stored in a single option in the database. In my modified plugin I store the settings in separate options, each for one language. I've added a $_GET paramter which is used in the setting registration to create a unique name for a language specific option.

My important (stripped-down) parts of my plugin class:

class Privacy_Policies {
    // the language to which the text is translated
    public $translation;
    // the options, stored in the database
    public $options;

    public function __construct() {
        // use the current user locale as a fallback
        $this->translation = isset($_GET['lang']) ? $_GET['lang'] : get_user_locale();
        // if an option already exists, edit it
        // use $this->translation to determine the right language
        $this->options = get_option('privacy_policies_' . $this->translation);
        // call registration when settings page gets loaded
        add_action('admin_init', array($this, 'register_settings');
        // create the settings page
        add_action('admin_menu', array($this, 'add_settings_page');
    }

    // settings validation, called as callback to register settings
    public function validate_settings($value) {
        if (isset($value['checkbox']) && 1 == $value['checkbox']) {
            $value[ 'checkbox' ] = 1;
        } else {
            $value[ 'checkbox' ] = 0;
        }
        $value['notice'] = normalize_whitespace($value['notice' ]);
        $value['error_message'] = normalize_whitespace($value['error_message']);
        $value['style'] = normalize_whitespace($value['style']);

        return $value;
    }

    // register a distinct option name for each language
    // the function is called when the settings page gets loaded
    public function register_settings() {
        register_setting(
            'privacy_notice_settings_group', 
            'privacy_notice_settings_' . $this->translation,
            array( $this, 'validate_settings' )
        );
    }

    // create the html for the settings page
    // stripped down to a simple checkbox
    public function get_settings_page() { ?>
        <h2><?php echo $this->get_plugin_data('Name'); ?></h2>
        <form method="post" action="options.php">
            <?php settings_fields('privacy_notice_settings_group'); ?>
            <table class="form-table">
                <tr valign="top">
                    <td>
                        <!-- important: 'name' must reflect the option name! -->
                        <input type="checkbox" id="privacy_checkbox" name="privacy_notice_settings_<?php echo $this->translation ?>[checkbox]" value="1"
                        <?php if (isset($this->options['checkbox'])) {
                            checked('1', $this->options['checkbox']);
                        } ?> />
                    </td>
                </tr>
            </table>
        </form>
    <?php }

    // add settings page
    // called in the admin_menu hook
    public function add_settings_page() {
        add_options_page(
            'Privacy Policies Settings',
            'Privacy Policies',
            'manage_options',
            'privacy_notice_settings_group',
            array( $this, 'get_settings_page' )
        );
    }
}

The funny thing is that, whatever locale is in $this->locale the setting will always be stored in the database as setting of WP's current locale (get_user_locale()). I.e. a setting's name that has been composed of 'privacy_notice_settings_' . $this->translation gets mysteriously recomposed to 'privacy_notice_settings_' . get_user_locale(). I suspect the secret lies somewhere burried in options.php which the form is calling. But I seem to be unable to debug this.

I'm currently rewriting a little plugin that shows visitors a small info text. This plugin is German only so far and so I want to add multi language support as I am working on a page that should be in English and German. The text that is displayed to the visitor can be set in the settings interface of the plugin. The given values are stored in a single option in the database. In my modified plugin I store the settings in separate options, each for one language. I've added a $_GET paramter which is used in the setting registration to create a unique name for a language specific option.

My important (stripped-down) parts of my plugin class:

class Privacy_Policies {
    // the language to which the text is translated
    public $translation;
    // the options, stored in the database
    public $options;

    public function __construct() {
        // use the current user locale as a fallback
        $this->translation = isset($_GET['lang']) ? $_GET['lang'] : get_user_locale();
        // if an option already exists, edit it
        // use $this->translation to determine the right language
        $this->options = get_option('privacy_policies_' . $this->translation);
        // call registration when settings page gets loaded
        add_action('admin_init', array($this, 'register_settings');
        // create the settings page
        add_action('admin_menu', array($this, 'add_settings_page');
    }

    // settings validation, called as callback to register settings
    public function validate_settings($value) {
        if (isset($value['checkbox']) && 1 == $value['checkbox']) {
            $value[ 'checkbox' ] = 1;
        } else {
            $value[ 'checkbox' ] = 0;
        }
        $value['notice'] = normalize_whitespace($value['notice' ]);
        $value['error_message'] = normalize_whitespace($value['error_message']);
        $value['style'] = normalize_whitespace($value['style']);

        return $value;
    }

    // register a distinct option name for each language
    // the function is called when the settings page gets loaded
    public function register_settings() {
        register_setting(
            'privacy_notice_settings_group', 
            'privacy_notice_settings_' . $this->translation,
            array( $this, 'validate_settings' )
        );
    }

    // create the html for the settings page
    // stripped down to a simple checkbox
    public function get_settings_page() { ?>
        <h2><?php echo $this->get_plugin_data('Name'); ?></h2>
        <form method="post" action="options.php">
            <?php settings_fields('privacy_notice_settings_group'); ?>
            <table class="form-table">
                <tr valign="top">
                    <td>
                        <!-- important: 'name' must reflect the option name! -->
                        <input type="checkbox" id="privacy_checkbox" name="privacy_notice_settings_<?php echo $this->translation ?>[checkbox]" value="1"
                        <?php if (isset($this->options['checkbox'])) {
                            checked('1', $this->options['checkbox']);
                        } ?> />
                    </td>
                </tr>
            </table>
        </form>
    <?php }

    // add settings page
    // called in the admin_menu hook
    public function add_settings_page() {
        add_options_page(
            'Privacy Policies Settings',
            'Privacy Policies',
            'manage_options',
            'privacy_notice_settings_group',
            array( $this, 'get_settings_page' )
        );
    }
}

The funny thing is that, whatever locale is in $this->locale the setting will always be stored in the database as setting of WP's current locale (get_user_locale()). I.e. a setting's name that has been composed of 'privacy_notice_settings_' . $this->translation gets mysteriously recomposed to 'privacy_notice_settings_' . get_user_locale(). I suspect the secret lies somewhere burried in options.php which the form is calling. But I seem to be unable to debug this.

Share Improve this question edited Apr 12, 2019 at 17:59 5tefan asked Apr 10, 2019 at 22:56 5tefan5tefan 213 bronze badges 6
  • And how do you make the site multilanguage? Do you use any ML plugin? – Krzysiek Dróżdż Commented Apr 11, 2019 at 4:10
  • I'm using WPGlobus: wordpress/plugins/wpglobus – 5tefan Commented Apr 11, 2019 at 18:11
  • for the third argument for register_setting you seem to have a validation callback (not included in your code) ... but that would need to be array('sanitize_callback' => array($this->validate_settings)) in any case. developer.wordpress/reference/functions/register_setting – majick Commented Apr 12, 2019 at 7:02
  • @majick - thanks for the tip! I've tried your suggestion but that doesn't seem to solve the problem. $this->validate_settings is invalid (only $this->validate_settings()` executes immediately which isn't what I need here). The particular line you've pointed out comes from the original implementation of the plugin. I'm not sure validate_settings is ever executed properly (I get no error, however). I'll try again later... – 5tefan Commented Apr 12, 2019 at 17:54
  • So, where/how do you actually pass &lang=en to satisfy the isset($_GET['lang']) ? – Anastis Commented Apr 12, 2019 at 20:54
 |  Show 1 more comment

1 Answer 1

Reset to default 0

I haven't yet tried to finally fix my issue but dare to say what's wrong: WP doesn't allow me to use $_GET directly. It expects these variables to get sanitized by first whitelisting them through the query_vars hook and later calling them through a WP_query instance - haven't figured out in detail yet but that seems to make sense to me. Here's a post on the wordpress forum that might explain more: query-string-url-parameter-in-wp-admin-custom-page

本文标签: settings apiplugin development storing language specific options