Change language by clicking a button

The goal is to offer a button/select drop-down or similar to switch the public interface1) language on the fly.

What I’m searching for

Read More
  • Plugin or Theme Code…
  • or Ideas
  • Using a work-around with load_textdomain() would be appreciated to leave translation to .po/.mo files
  • Ideas on how to parse the strings into the interface (ex. ajax/plain php/ini, json, xml files) when not relying on some textdomain function

Note:

1) It’s not about publishing in different languages.

2) I don’t need code to make the actual drop-down/button/whatever. It’s only about the code/system delivering the strings for the UI.

Thanks!

Related posts

Leave a Reply

3 comments

  1. By far the best (easiest) way is to use the locale filter (inside get_locale()).

    First set up a quick function for retrieving a different language to use on the locale filter.

    /**
     * A function returns with returns the user's selectd locale, if stored. 
     */
    function wpse35622_get_new_locale($locale=false){
    $new_locale = get_user_meta(get_current_user_id(), 'wpse_locale', true);
        if($new_locale)
            return $new_locale;
    
        return $locale;
    }
    

    I’ve left this as a global function, might be handy…? The rest of the plug-in I’ve wrapped inside a class.

    It creates a drop-down of possible languages from which you can select.

    Drawbacks

    • Searches wp-content/languages for files of the form xx_xx.mo. If it’s not of that form (not all .mo files are) the plug-in won’t pick up on it!
    • The drop down gives a list of the found locales to choose from, but these are displayed in the ‘xx_xx` format of locales, not a human friendly way – any ideas??
    • Does $locale do anything other than language? If so it’s still possible to get the locale the same, but provide alternative translations. It’s a lot messier though…

    The code

    class SH_Pick_Lang{
        /**
         * A unique name for this plug-in
         */
        static $name ='sh_pick_lang';
    
        /**
         * Hook the functions
         */
        public function __construct(){
    
            if( isset($_POST[self::$name]) ){
                add_action('locale',array($this,'update_user'));
            }
            add_filter( 'locale', 'wpse35622_get_new_locale',20 );
            add_action( 'wp_before_admin_bar_render', array( $this, 'admin_bar') );
        }
    
        /**
         * Update the user's option just in time! Only once mind...
         */
        function update_user($locale){
            $save_locale = $_POST[self::$name];
            update_user_meta(get_current_user_id(), 'wpse_locale', $save_locale);
            remove_filter(current_filter(),__FUNCTION__);
            return $locale;
        }
    
        /**
         * Add a really horrible looking dropdown menu that I'm sure Kaiser will make look fantastic.
         */
        function admin_bar(){
            global $wp_admin_bar;
    
            $wp_admin_bar->add_menu( array(
                'id'        => 'shlangpick',
                'title'     => $this->wpse_language_dropown(),
            ) );
        }
    
        /**
         * Generates a list of available locales.
         * Searches the wp-content/languages folder for files of the form xx_xx.mo
         * 
         * TODO Not all locales are of the form xx_xx.mo - we might miss some.
         * TODO Better way of gettin gthe wp-content/languages folder without a constant?
         */
        function wpse_language_dropown(){
             $name = self::$name;
             $locale = get_locale();
             $langs = get_available_languages();
             $langs[] = 'en_US';
    
             //For the labels (format_code_lang)
             require_once( ABSPATH . 'wp-admin/includes/ms.php');
    
             $html = "<form method='post'> ";
             $html .= "<select name='{$name}'>";
             foreach($langs as $lang){
                  $label = format_code_lang( $lang );
                  $html .= "<option ".selected( $lang, $locale, false)." value='{$lang}'>{$label}</option>";
            }
             $html .= "</select>";
             $html .= get_submit_button('Change Language','secondary', 'submit', true);
             $html .= "</form >";
    
             return $html;
        }
    
    } // END Class
    
    //Initiate...
    $sh_pick_lang = new SH_Pick_Lang();
    
  2. If you can settle for a page refresh, redefining the WPLANG constant could be an option. I’m doing that on two sites with multilingual content where the multilinguality plugin fails to trigger UI translation.

  3. http://www.qianqin.de/qtranslate/

    is what you need …

    Edit I – after comment.
    First – thanks for all who contributed in the downvotes torrent.
    (this is what happens when one does not visit frequently enough :- ) )

    now –
    The function that handles the switch is in qtranslate-core.
    (starts at line 80 more or less – depends on the version that you want.)

    Since you can not look into a NOT OOP code , and I am now with nothing else to do – I took 10 minutes to synthesize , paraphrase compile that non-OOp with yet another non-OOP code for you .

    (sorry, – primitive old skool here)

    Assuming that I understood the question && Assuming you want the code to be for admin && assuming you will know how to port it to front end if you want && assuming you understand that the code is not optimal :

    <?php
    /*
    Plugin Name: k99 language switcher
    Plugin URI: http://www.krembo99.com
    Description: Admin Language switcher proof of concept only - do not use in production.
    Version: 0.0.0.0.0.0.0.1
    Author: Krembo99
    Author URI: http://www.krembo99.com
    */ 
    ?>
    <?php function k99_add_language_menu() {
        //  k99_load_ajax_display_functions();
    ?>  
        <div class="mgmb_help_setting">
        <?php _e('Language:','your_text_domain'); ?>
        <select name="mgmb_language_setting_help" id="mgmb_language_setting_help" onChange="mgmb_set_language_cookies(this.value);" >
            <option value="en_US" <?php if($_COOKIE['k99_userLang']=="en_US"){echo "selected";} ?>><?php _e('English','your_text_domain');?></option>
            <option value="de_DE" <?php if($_COOKIE['k99_userLang']=="de_DE"){echo "selected";} ?>><?php _e('German','your_text_domain');?></option>
            <option value="zh_CN" <?php if($_COOKIE['k99_userLang']=="zh_CN"){echo "selected";} ?>><?php _e('Chinese','your_text_domain');?></option>
        </select>
        </div>
    <?php   
    }
    // Now we set that function up to execute when the help action is called
    add_filter('contextual_help', 'k99_add_language_menu');
    
    // I guess this is your mysterious "browser stuff"
    function k99_language_change($lang){ 
     global $locale;
     // wp_cache_set( "language", $lang, 'options' );
        if ( isset($_COOKIE['k99_userLang'])) {
          $lang = $_COOKIE['k99_userLang'];
        }
        define( 'WPLANG', $lang );
     if($locale!= $lang) {
        $locale = $lang;
        load_plugin_textdomain('your_text_domain', false, dirname( plugin_basename(__FILE__) ) . '/lang'); // sample use for plugins textdomain
        load_plugin_textdomain('your_text_domain2', false, dirname( plugin_basename(__FILE__) ) . '/lang');
        load_plugin_textdomain('your_text_domain3', false, dirname( plugin_basename(__FILE__) ) . '/lang');
     }
      return $locale;
    }
    add_filter('locale', 'k99_language_change',99);
    
    ////////// +++++++++++++++  START COOKIES CREATION +++++++++++++++//////////////////
    // Javascript function set the language cookies
    // access external
    // @param lang - language code
    // @return NULL
    // or maybe this is the OP´s mysterious "browser stuff" ??
        function mgmb_print_script() {
        ?>
        <script type="text/javascript" >
        function mgmb_set_language_cookies(lang){   
            var Then = new Date(); 
            Then.setTime(Then.getTime() + 10000*60*60*1000 ); //set cookie expire to 10000 hours cookies (hour*minute*seconds*1000)
            document.cookie = "k99_userLang="+lang+";expires="+ Then.toGMTString();
            window.location.reload();
            } 
            </script>
    <?php
    } 
    add_action('admin_print_scripts', 'mgmb_print_script');  // this is not the right way to do .. but no time now.
    ?>
    

    REMARKS :

    1 – This was built in 10 min. on local machine while at the airport .
    The reason why I say this is that the only ready available wordpress installation that I have here is quite old . (2.9 I think).

    This means that probably the language menu will appear UNDER the contextual help div, due to the fact that a new div structure was recently introduced (with tabs) – but still it should work.
    (I promise to get back to this later if I have time)

    If I had more time (and a new wordpress code here ) i would probably integrate this in the new admin-bar with add_action( 'admin_bar_menu', 'k99_add_language_menu_2', 1000 ); (I already promised to get back to this)

    2 – you should have the listed languages files inside the “languages” folder in wp-content (better??) or wp-include.
    regarding this point – the code is only a proof of concept – and of course if one has more time the menu should be built in a dynamic way and not like done here.

    3 – your WPLANG in config should be empty. I am not sure it will work on newer wp versions if a language is already set.

    4 – it is a simple synthesized and paraphrased proof of concept built on what was seen in qtranslate code (also old version) – so most of the things are done the “quick” way, not necessarily the “right” way (like adding JS, no dedicated textdomain etc..).

    EDIT II

    someone is lucky today ! (Flight Delay )

    Since you were looking for “ideas” for approaches , here is another famous one .

    It will not fit in a plugin, or actually any other non-exclusive environment , but it might give you another direction as how to handle the “Browser stuff”.

    This will allow one to get the language with a GET like : <a href="index.php?lang=de">German</a> or <a href="whatever.php?lang=ml">my Language</a>

    To use , you can create a code (let´s call it wp-langswitch.php )

     session_start();
     if ( isset( $_GET['lang'] ) ) {
        $_SESSION['WPLANG'] = $_GET['lang'];
        define ('WPLANG', $_SESSION[WPLANG]);
     } else {
        if(isset($_SESSION['WPLANG'])) {
            define ('WPLANG', $_SESSION['WPLANG']);
            $_GET['lang'] = $_SESSION['WPLANG'];
        } else {
            if ( isset( $_SERVER["HTTP_ACCEPT_LANGUAGE"] ) ) {
                $languages = strtolower( $_SERVER["HTTP_ACCEPT_LANGUAGE"] );
                 $languages = explode( ",", $languages );
                $_SESSION['WPLANG'] = $languages[0];
                $_SESSION['WPLANG'] = str_replace("-", "_", $_SESSION['WPLANG']);
                $_GET['lang'] = substr($_SESSION['WPLANG'],0,2);
                define ('WPLANG', $_SESSION[WPLANG]);
            } else {
                define ('WPLANG', '');
            }
        }
     }
    

    now, in wp-config, just before the WPLANG constant , we need to include our code .

     require_once(dirname(__FILE__).'/wp-langswitch.php');
     define ('WPLANG', ''); 
    

    Now – obviously it would be better to add some cookies to the mix to store the languages .

    EDIT III

    I promised to get back to this later – here is how (in a very non-correct and primitive way ) it could be integrated inside the admin-bar (instead of the contextual-help-menu)

     function k99_add_language_menu_bar() {
        global $wp_admin_bar, $wpdb;
        if ( !is_super_admin() || !is_admin_bar_showing() )
            return;
    // I am sure you can find a way alone to construct array from reading folder . If not , comment and I will update again.
    
    if($_COOKIE['k99_userLang']=="en_US"){$sel==$_COOKIE['k99_userLang'];} 
    if($_COOKIE['k99_userLang']=="de_DE"){$sel==$_COOKIE['k99_userLang'];}
    if($_COOKIE['k99_userLang']=="zh_CN"){$sel==$_COOKIE['k99_userLang'];}
    
        $k99_lang = '';
        $k99_lang .= '<select name="mgmb_language_setting_help" id="mgmb_language_setting_help" onChange="mgmb_set_language_cookies(this.value);" >';
        $k99_lang .= '<option value="en_US" >English</option>';
        $k99_lang .= '<option value="de_DE" >German</option>';
        $k99_lang .= '<option value="zh_CN" >Chinese</option></select>';
    
        /* Add the main siteadmin menu item */
        $wp_admin_bar->add_menu( array( 'id' => 'Language', 'title' => __( 'language', 'your_text_domain3' ), 'href' => FALSE ) );
        $wp_admin_bar->add_menu( array( 'parent' => 'Language', 'title' => $k99_lang, 'href' => FALSE ) );
    }
    add_action( 'admin_bar_menu', 'k99_add_language_menu_bar', 999 );
    

    Just replace this function (or add) to the old code (the original NON – OOP non-plugin) .

    Like I said, I do not have a new wordpress installation here on local that features admin-bar – but it should work .

    (and then again, it might not work…but I am sure you could fix that if you really want – even thought it is not OOP ) 🙂

    gotta run now . hope it helps somehow.

    EDIT IV – changed edit III to working verion for admin menu bar (at least on my wp 3.4)

    since I had no working install of 3.4 – and now I returned and I do – I have edited the Edit III solution – and it works for me .

    About the upvotes, I could not care less . And I do not need any “bounties” (whatever those may be..) It was just for the sake of the exercise you shlould maybe give it to the author of qTranslate . 🙂 despite of the fact that it is not OOP – it is a genious plugin with a lot to learn from in a lot of areas . considering the “when” of this plugin release , it is even amazing. worth the indescribably effort of reading a NON OOP code – even if it is not – OOP . And even if it is not correctly indented (good god !).