Changer de langue en cliquant sur un bouton

21

L'objectif est d'offrir un bouton / sélectionner une liste déroulante ou similaire pour changer la langue de l' interface publique 1) à la volée.

Ce que je recherche

  • Code du plugin ou du thème ...
  • ... ou des idées
  • L'utilisation d'une solution de contournement avec load_textdomain()serait appréciée pour laisser la traduction aux fichiers .po / .mo
  • Des idées sur la façon d'analyser les chaînes dans l'interface (par exemple, les fichiers ajax / plain php / ini, json, xml) lorsque vous ne comptez pas sur une fonction de domaine de texte

Remarque:

1) Il ne s'agit pas de publier dans différentes langues.

2) Je n'ai pas besoin de code pour créer la liste déroulante / le bouton / quoi que ce soit. Il s'agit uniquement du code / système fournissant les chaînes pour l'interface utilisateur.

Merci!

kaiser
la source
1
Si vous pouvez vous contenter d'une actualisation de page, la redéfinition de la WPLANGconstante pourrait être une option. Je le fais sur deux sites avec un contenu multilingue où le plugin multilingue ne parvient pas à déclencher la traduction de l'interface utilisateur. S'il devait s'agir d'une solution AJAX / JSON, je ne saurais pas comment aider.
Johannes Pille
@JohannesPille À quel point / crochet à changer? Btw: Pourriez-vous déplacer cela vers une réponse. Ça vaut déjà un vote positif. Merci.
kaiser
Je le fais dans un plugin, aucun crochet impliqué. C'est une solution assez sale et je n'en suis pas si fier, mais cela a fait le travail à l'époque. Vous pouvez voir le code du plugin dans cette boîte à pâte . Ce qu'il fait est explicite. Le site à partir duquel j'ai copié utilise la dernière version gratuite de WPML. Assez bien, il a proposé une réponse.
Johannes Pille
L'URL pastebin semble être morte.
PapaFreud
@JohannesPille Pourriez-vous publier votre code en tant que mise à jour de votre Q, ou ajouter une boîte à pâte qui n'expire pas?
kaiser

Réponses:

15

De loin, la meilleure façon (la plus simple) est d'utiliser le filtre de paramètres régionaux (à l'intérieur get_locale()).

Configurez d'abord une fonction rapide pour récupérer une langue différente à utiliser sur le localefiltre.

/**
 * 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;
}

J'ai laissé cela comme une fonction globale, pourrait être utile ...? Le reste du plug-in que j'ai enveloppé dans une classe.

Il crée une liste déroulante des langues possibles parmi lesquelles vous pouvez sélectionner.

Désavantages

  • Recherche les wp-content/languagesfichiers du formulaire xx_xx.mo. S'il n'est pas de cette forme (tous les fichiers .mo ne le sont pas), le plug-in ne le détectera pas!
  • La liste déroulante donne une liste des paramètres régionaux trouvés parmi lesquels choisir, mais ceux-ci sont affichés au format «xx_xx» des paramètres régionaux, pas d'une manière conviviale pour l'homme - des idées ??
  • Fait $localeautre chose que la langue? Si c'est le cas, il est toujours possible d'obtenir les mêmes paramètres régionaux, mais fournissez des traductions alternatives. C'est beaucoup plus compliqué cependant ...

Le 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();
Stephen Harris
la source
1
Upvote done (loughing sur tous les commentaires en ligne aussi). Le Bounty est fixé et vous sera attribué dès que je serai autorisé (23h à gauche - pointez-moi si j'oublie).
kaiser
2
Mis à jour pour refléter la réponse à cette question .
Stephen Harris
N1ce one. Signet. +1
Johannes Pille
J'ai remarqué que le simple fait d'inclure 'wp-admin/includes/ms.php'déclenche un avis administrateur pour la mise à jour de vos sites réseau (lorsque vous êtes un seul site!). Il se peut que format_code_lang()cela doive être dupliqué dans une fonction personnalisée.
Stephen Harris
J'ai ajouté un Gist avec mon nettoyage - je n'ai pas eu le temps de le tester, car je joue avec les dossiers de plugins actuellement et cela signifie qu'aucun autre plugin ne fonctionne. J'espère que vous pourrez travailler avec l'essentiel fourni et peut-être fork / update. Je peux attribuer la prime dans une demi-heure, mais je dois partir maintenant, donc je vais l'envoyer demain. Merci pour tout votre travail - devrait être dans n'importe quelle installation par défaut :)
kaiser
5

Si vous pouvez vous contenter d'une actualisation de page, la redéfinition de la WPLANGconstante pourrait être une option. Je le fais sur deux sites avec un contenu multilingue où le plugin multilingue ne parvient pas à déclencher la traduction de l'interface utilisateur.

Johannes Pille
la source
Hmm .. vous pouvez utiliser ajax pour remplacer le corps ou la balise html entière de la page d'ailleurs, après avoir exécuté le code ci-dessus (dans la même demande ajax), un clic sur votre bouton ou quelque chose comme ça.
Joshua Abenazer
+1. Je viens de regarder votre boîte à pâte. Cela signifie que votre configuration est http://example.com/language/whatever/, non?
kaiser
@kaiser Yup, c'est la configuration sur le site d'où vient le code. Si vous ne vous souciez que de la langue de l'interface utilisateur, le passage d'une chaîne de requête URL ou la définition d'une $_SESSIONvariable pour déclencher la redéfinition de WPLANGla prochaine charge de page devrait suffire. Si vous souhaitez reproduire cela sur un site multilingue, notez que, comme le dit le commentaire avec le pastebin, le code qu'il contient fonctionne avec WPML, dernière version gratuite. Il ne peut pas être répliqué 1 à 1 avec qTranslate, car ces URI ne sont pas physiques mais réécrits via le mod_rewritemodule apache. Je suis sûr qu'il peut être ajusté, mais ne fonctionnera pas "tel quel".
Johannes Pille
Je n'utiliserai pas qTranslate ou WPML. Il s'agit vraiment uniquement de la langue de l'interface utilisateur. Ad $_SESSION) Mon problème est que, afaik, ils sont assez difficiles à gérer et que les trucs entre les globaux et le tableau peuvent se mélanger facilement. Donc, si j'essayais de trouver un moyen de changer WPLANG, alors je dois trouver un moyen solide de le faire d'une demande à l'autre. Peut add_query_arg/get_query_var- être fera l'affaire ...
kaiser
J'y repensais juste (la solution n'est toujours pas intégrée au projet): Pourriez-vous envelopper cela dans de l'ajax? Je pense que ce serait la meilleure façon de contourner cela. Je veux fermer le Q et le marquer comme solution :) Merci.
kaiser
2

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

est ce dont vous avez besoin ...

Edit I - après commentaire. Tout d'abord - merci pour tous ceux qui ont contribué au torrent downvotes. (c'est ce qui arrive quand on ne visite pas assez souvent: -))

now - La fonction qui gère le commutateur est dans qtranslate-core. (commence à la ligne 80 plus ou moins - dépend de la version que vous voulez.)

Puisque vous ne pouvez pas regarder dans un code NOT OOP, et que je n'ai plus rien d'autre à faire - j'ai pris 10 minutes pour synthétiser, paraphraser compiler ce non-OOp avec encore un autre code non-OOP pour vous.

(désolé, - vieille école primitive ici)

En supposant que j'ai compris la question && En supposant que vous vouliez que le code soit pour l'administrateur && en supposant que vous saurez comment le porter sur le front-end si vous voulez && en supposant que vous compreniez que le code n'est pas 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.
?>

REMARQUES :

1 - Il a été construit en 10 min. sur la machine locale à l'aéroport. La raison pour laquelle je dis cela est que la seule installation wordpress disponible disponible que j'ai ici est assez ancienne. (2.9 je pense).

Cela signifie que le menu de langue apparaîtra probablement sous la division d'aide contextuelle, car une nouvelle structure de div a été récemment introduite (avec des onglets) - mais cela devrait quand même fonctionner. (Je promets d'y revenir plus tard si j'ai le temps)

Si j'avais plus de temps (et un nouveau code wordpress ici), j'intégrerais probablement cela dans la nouvelle barre d'administration avec add_action( 'admin_bar_menu', 'k99_add_language_menu_2', 1000 );(j'ai déjà promis d'y revenir)

2 - vous devriez avoir les fichiers de langues listés dans le dossier "languages" dans wp-content (mieux ??) ou wp-include. sur ce point - le code n'est qu'une preuve de concept - et bien sûr si on a plus de temps le menu doit être construit de manière dynamique et pas comme ici.

3 - votre WPLANG dans la configuration doit être vide. Je ne suis pas sûr que cela fonctionnera sur les versions wp plus récentes si une langue est déjà définie.

4 - il s'agit d'une simple preuve de concept synthétisée et paraphrasée construite sur ce qui a été vu dans le code de traduction (également ancienne version) - donc la plupart des choses se font de manière "rapide", pas nécessairement de la "bonne" façon (comme l'ajout de JS , pas de domaine texte dédié etc.).

EDIT II

quelqu'un a de la chance aujourd'hui! (Retard de vol)

Puisque vous recherchiez des "idées" d'approches, en voici une autre célèbre.

Il ne rentrera pas dans un plugin, ni dans aucun autre environnement non exclusif, mais il pourrait vous donner une autre direction sur la façon de gérer les "trucs du navigateur".

Cela permettra d'obtenir la langue avec un GET comme: <a href="index.php?lang=de">German</a>ou<a href="whatever.php?lang=ml">my Language</a>

Pour l'utiliser, vous pouvez créer un code (appelons-le 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', '');
        }
    }
 }

maintenant, dans wp-config, juste avant la constante WPLANG, nous devons inclure notre code.

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

Maintenant - il serait évidemment préférable d'ajouter des cookies au mélange pour stocker les langues.

EDIT III

J'ai promis d'y revenir plus tard - voici comment (d'une manière très incorrecte et primitive) il pourrait être intégré à la barre d'administration (au lieu du menu d'aide contextuelle)

 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 );

Remplacez simplement cette fonction (ou ajoutez) à l'ancien code (le non-plugin NON-OOP d'origine).

Comme je l'ai dit, je n'ai pas de nouvelle installation wordpress ici sur local qui dispose d'une barre d'administration - mais cela devrait fonctionner.

(et encore une fois, cela pourrait ne pas fonctionner ... mais je suis sûr que vous pouvez résoudre ce problème si vous le voulez vraiment - même si ce n'est pas OOP) :-)

dois courir maintenant. j'espère que cela aide en quelque sorte.

EDIT IV - changé edit III en verion de travail pour la barre de menu admin (au moins sur mon wp 3.4)

puisque je n'avais pas d'installation de 3.4 en état de fonctionnement - et maintenant je suis revenu et je le fais - j'ai édité la solution Edit III - et cela fonctionne pour moi.

Concernant les votes positifs, je m'en fichais. Et je n'ai pas besoin de "primes" (quelles qu'elles soient ..) C'est juste pour le plaisir de l'exercice que vous devriez peut-être le donner à l'auteur de qTranslate. :-) malgré le fait qu'il ne s'agit pas de POO - c'est un plugin génial avec beaucoup à apprendre dans de nombreux domaines. compte tenu du "quand" de cette version du plugin, c'est même incroyable. vaut l'effort indescriptible de lire un code NON OOP - même s'il ne l'est pas - OOP. Et même s'il n'est pas correctement en retrait (bon dieu!).

krembo99
la source
3
Peut-être y a-t-il une solution enfouie dans la profondeur de ce code, mais il est presque impossible de comprendre tous les moyens, car il n'est pas écrit en POO. Si vous savez où se situe exactement la détection de la langue (le navigateur) et comment elle filtre les chaînes gettext, faites-le moi savoir.
kaiser
1
@kaiser - voir edit I pour "navigateur".
krembo99
1
@kaiser ..et voir éditer II pour plus de "trucs de navigateur" - et éditer III pour savoir comment incorporer les "trucs de navigateur" dans le "navigateur (trucs)".
krembo99
Ok, j'ai voté (pas downvote pour revenir ici), pour votre effort. L'idée d'utiliser un cookie, c'est sympa. Quoi qu'il en soit, voici quelques notes: Edit II générera une erreur après le require(). Vous ne pouvez pas utiliser define()deux fois la même chaîne. Edit III a quelques problèmes avec les langues. La sélection en_USne ferait rien (?), Mais la de_DEréglerait sur English;). Pour résumer: j'attribue des primes et je les remets à (par exemple StephenHarris) pour une réponse complète et fonctionnelle. Si vous avez quelque chose comme ça, veuillez mettre à jour votre réponse (approche par cookie intéressante) et je peux ajouter et vous récompenser une prime.
kaiser
Veuillez ne pas laisser de commentaires pour moi. Modifiez votre réponse pour que tout le monde puisse lire vos idées. Sidenote: le code externe à mon humble avis doit toujours être ajouté en tant que plugin / plugin MU / thème / DropIn pour le rendre mobile.
kaiser