Cambia lingua facendo clic su un pulsante


21

L'obiettivo è offrire un pulsante / selezionare il menu a discesa o simile per cambiare la lingua dell'interfaccia pubblica 1) al volo.

Quello che sto cercando

  • Plugin o codice tema ...
  • ... o Idee
  • L'uso di una soluzione load_textdomain()alternativa sarebbe gradito per lasciare la traduzione in file .po / .mo
  • Idee su come analizzare le stringhe nell'interfaccia (es. Ajax / plain php / ini, json, file xml) quando non si fa affidamento su alcune funzioni di textdomain

Nota:

1) Non si tratta di pubblicare in lingue diverse.

2) Non ho bisogno di codice per creare il menu a discesa / pulsante / qualunque cosa. Si tratta solo del codice / sistema che fornisce le stringhe per l'interfaccia utente.

Grazie!


1
Se puoi accontentarti di un aggiornamento della pagina, ridefinire la WPLANGcostante potrebbe essere un'opzione. Lo sto facendo su due siti con contenuti multilingue in cui il plug-in multilingue non riesce ad attivare la traduzione dell'interfaccia utente. Se deve essere una soluzione AJAX / JSON, non saprei aiutare.
Johannes Pille,

@JohannesPille In quale punto / hook si passa? Btw: potresti spostarlo in una risposta. Merita già un voto positivo. Grazie.
Kaiser,

Lo sto facendo in un plugin, senza hook coinvolti. È una soluzione piuttosto sporca e non ne sono così orgoglioso, ma ha fatto il lavoro in quel momento. Puoi vedere il codice del plugin in questo pastebin . Quello che fa è autoesplicativo. Il sito da cui ho copiato questo utilizza l'ultima versione gratuita di WPML. Fair enuff, lo ha spostato in una risposta.
Johannes Pille,

L'URL pastebin sembra essere morto.
PapaFreud,

@JohannesPille Ti dispiacerebbe pubblicare il tuo codice come aggiornamento nella tua Q o aggiungere un pastebin che non sta scadendo?
Kaiser

Risposte:


15

Di gran lunga il modo migliore (più semplice) è usare il filtro locale (all'interno get_locale()).

Innanzitutto imposta una funzione rapida per recuperare una lingua diversa da utilizzare sul localefiltro.

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

L'ho lasciato come una funzione globale, potrebbe essere utile ...? Il resto del plug-in l'ho inserito in una classe.

Crea un menu a discesa delle lingue possibili da cui è possibile selezionare.

svantaggi

  • Cerca i wp-content/languagesfile del modulo xx_xx.mo. Se non è di quel tipo (non tutti i file .mo sono) il plug-in non lo raccoglierà!
  • Il menu a discesa fornisce un elenco delle impostazioni locali trovate tra cui scegliere, ma queste vengono visualizzate nel formato 'xx_xx` delle impostazioni locali, non in un modo amico dell'uomo - qualche idea ??
  • Fa $localealtro che la lingua? In tal caso è ancora possibile ottenere le impostazioni internazionali allo stesso modo, ma fornire traduzioni alternative. È molto più disordinato però ...

Il codice

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

1
Voto fatto (ridendo anche di tutti i commenti in linea). Bounty è pronto e ti verrà assegnato non appena mi sarà permesso (23 ore a sinistra - indicamelo se dimentico).
Kaiser,

2
Aggiornato per riflettere la risposta a questa domanda .
Stephen Harris,

N1ce one. Segnalibro. +1
Johannes Pille,

Ho notato che solo l'inclusione 'wp-admin/includes/ms.php'innesca un avviso di amministratore per l'aggiornamento dei siti di rete (quando sei un singolo sito!). Potrebbe essere format_code_lang()necessario duplicarlo all'interno di una funzione personalizzata.
Stephen Harris,

Ho aggiunto un Gist con la mia pulizia - non ho avuto tempo di testarlo, dato che sto scherzando con le cartelle dei plugin attualmente e questo significa che nessun altro plugin funziona. Spero che tu possa lavorare con l'essenza fornita e forse fork / aggiornamento. Posso assegnare la taglia in mezz'ora, ma devo partire adesso, quindi la spedirò domani. Grazie per tutto il tuo lavoro - dovrebbe essere in qualsiasi installazione predefinita :)
kaiser

5

Se puoi accontentarti di un aggiornamento della pagina, ridefinire la WPLANGcostante potrebbe essere un'opzione. Lo sto facendo su due siti con contenuti multilingue in cui il plug-in multilingue non riesce ad attivare la traduzione dell'interfaccia utente.


Hmm .. potresti usare ajax per sostituire il corpo o l'intero tag html della pagina, dopo aver eseguito il codice sopra (nella stessa richiesta ajax), facendo clic sul tuo pulsante o qualcosa del genere.
Joshua Abenazer,

+1. Ho appena guardato il tuo pastebin. Questo significa che la tua configurazione è http://example.com/language/whatever/, giusto?
Kaiser

@kaiser Yup, questa è l'installazione sul sito da cui proviene il codice. Se ti interessa solo la lingua dell'interfaccia utente, dovrebbe essere necessario passare una stringa di query URL o impostare una $_SESSIONvariabile per attivare la ridefinizione WPLANGal successivo pageload. Se ti interessa replicare questo su un sito multilingue, nota che, come dice il commento con il pastebin, il codice in esso funziona con WPML, ultima versione gratuita. Non può essere replicato 1 a 1 con qTranslate, perché quegli URI non sono fisici ma riscritti tramite il mod_rewritemodulo apache. Sono sicuro che può essere regolato, ma non funzionerà "così com'è".
Johannes Pille,

Non userò qTranslate o WPML. Si tratta davvero solo della lingua dell'interfaccia utente. Annuncio $_SESSION) Il mio problema è che afaik sono piuttosto difficili da gestire e le cose tra i globi e l'array possono confondersi facilmente. Quindi, se provassi a trovare un modo per cambiare WPLANG, allora ho bisogno di trovare un modo solido per dare da una richiesta all'altra. Forse add_query_arg/get_query_varfarà il trucco ...
Kaiser

Ci stavo solo pensando di nuovo (soluzione non ancora integrata nel progetto): potresti metterlo in un po 'di ajax? Penso che questo sarebbe il modo migliore per aggirare questo. Voglio chiudere la Q e contrassegnarla come soluzione :) Grazie.
Kaiser

2

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

è quello che ti serve ...

Modifica I - dopo il commento. Innanzitutto, grazie per tutti coloro che hanno contribuito al downvotes torrent. (questo è ciò che accade quando non si visita abbastanza frequentemente: -))

now - La funzione che gestisce l'interruttore è in qtranslate-core. (inizia alla riga 80 più o meno - dipende dalla versione desiderata.)

Dal momento che non puoi cercare un codice NOT OOP, e ora non ho nient'altro da fare - ho impiegato 10 minuti per sintetizzare, parafrasando compilando quel non-OOp con l'ennesimo codice non-OOP per te.

(scusa, - vecchia skool primitiva qui)

Supponendo di aver compreso la domanda && Supponendo che si desideri che il codice sia destinato all'amministratore && supponendo che si saprà portarlo al front-end se si desidera && supponendo di aver compreso che il codice non è ottimale:

<?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.
?>

OSSERVAZIONI:

1 - Costruito in 10 minuti. sulla macchina locale mentre all'aeroporto. Il motivo per cui dico questo è che l'unica installazione wordpress disponibile disponibile che ho qui è piuttosto vecchia. (2.9 Penso).

Ciò significa che probabilmente il menu della lingua apparirà SOTTO il div della guida contestuale, a causa del fatto che una nuova struttura div è stata recentemente introdotta (con schede) - ma dovrebbe comunque funzionare. (Prometto di tornarci più tardi se avrò tempo)

Se avessi più tempo (e un nuovo codice wordpress qui) probabilmente lo integrerei nella nuova barra di amministrazione con add_action( 'admin_bar_menu', 'k99_add_language_menu_2', 1000 );(ho già promesso di tornare a questo)

2 - dovresti avere i file delle lingue elencati nella cartella "lingue" in wp-content (meglio ??) o wp-include. riguardo a questo punto - il codice è solo una prova di concetto - e ovviamente se si ha più tempo il menu dovrebbe essere costruito in modo dinamico e non come fatto qui.

3 - il tuo WPLANG in config dovrebbe essere vuoto. Non sono sicuro che funzionerà con le nuove versioni di wp se è già impostata una lingua.

4 - è una semplice dimostrazione sintetizzata e parafrasata del concetto basata su ciò che è stato visto nel codice qtranslate (anche versione precedente) - quindi la maggior parte delle cose sono fatte nel modo "rapido", non necessariamente nel modo "giusto" (come l'aggiunta di JS , nessun textdomain dedicato ecc.).

EDIT II

qualcuno è fortunato oggi! (Ritardo del volo )

Dato che stavi cercando "idee" per approcci, eccone un'altra famosa.

Non si adatta a un plug-in o in realtà a qualsiasi altro ambiente non esclusivo, ma potrebbe darti un'altra direzione su come gestire le "cose ​​del browser".

Ciò consentirà di ottenere la lingua con un GET come: <a href="index.php?lang=de">German</a>o<a href="whatever.php?lang=ml">my Language</a>

Per usare, puoi creare un codice (chiamiamolo 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', '');
        }
    }
 }

ora, in wp-config, appena prima della costante WPLANG, dobbiamo includere il nostro codice.

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

Ora, ovviamente, sarebbe meglio aggiungere alcuni cookie al mix per memorizzare le lingue.

EDIT III

Ho promesso di tornare a questo in seguito - ecco come (in un modo molto non corretto e primitivo) potrebbe essere integrato all'interno della barra di amministrazione (invece del menu di aiuto contestuale)

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

Basta sostituire questa funzione (o aggiungere) al vecchio codice (il non plugin originale NON - OOP).

Come ho detto, non ho una nuova installazione di wordpress qui su local che presenta la barra di amministrazione - ma dovrebbe funzionare.

(e poi di nuovo, potrebbe non funzionare ... ma sono sicuro che potresti risolverlo se vuoi davvero - anche se pensavo che non fosse OOP) :-)

devo correre ora. spero che aiuti in qualche modo.

EDIT IV - cambiato edit III in versione funzionante per la barra dei menu dell'amministratore (almeno sul mio wp 3.4)

dal momento che non avevo un'installazione funzionante di 3.4 - e ora sono tornato e lo faccio - ho modificato la soluzione Edit III - e funziona per me.

A proposito dei voti, non me ne può fregare di meno. E non ho bisogno di "doni" (qualunque essi siano ..) Era solo per il bene dell'esercizio che potresti darlo all'autore di qTranslate. :-) nonostante non sia OOP - è un plugin geniale con molto da cui imparare in molte aree. considerando il "quando" di questa versione del plugin, è persino sorprendente. vale la pena indescrivibile di leggere un codice NON OOP - anche se non lo è - OOP. E anche se non è correttamente rientrato (buon dio!).


3
Forse c'è una soluzione nascosta nella profondità di questo codice, ma è quasi impossibile capire tutte le vie, poiché non è scritta in OOP. Se sai dove si trova esattamente il rilevamento della lingua (roba del browser) e come filtra le stringhe gettext, per favore fammi sapere.
Kaiser

1
@kaiser - vedi modifica I per "roba del browser".
krembo99,

1
@kaiser ..e vedi modifica II per ulteriori "elementi del browser" - e modifica III per come incorporare "elementi del browser" all'interno di "browser (elementi)".
krembo99,

Ok, l'ho votato (non votato per tornare qui), per il tuo sforzo. L'idea che utilizza un cookie è buona. Comunque, ecco alcune note: Edit II genererà un errore dopo il require(). Non è possibile utilizzare define()due volte sulla stessa stringa. Modifica III ha alcuni problemi con le lingue. La selezione en_USnon farebbe nulla (?), Ma de_DElo imposterà su English;). Per riassumere: premio i doni e li do a (ad esempio StephenHarris) per una risposta completa e funzionante. Se hai qualcosa del genere, ti preghiamo di aggiornare la tua risposta (approccio ai cookie interessante) e potrei aggiungere e premiarti una ricompensa.
Kaiser

Per favore, non lasciare commenti per me. Apporta modifiche alla tua risposta, in modo che tutti possano leggere le tue idee. Nota a margine: codice esterno imho deve sempre essere aggiunto come Plugin / MU-Plugin / Theme / DropIn per renderlo mobile.
Kaiser,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.