Cambiare lingua cliccando un pulsante

5 dic 2011, 20:53:52
Visualizzazioni: 14.2K
Voti: 22

L'obiettivo è offrire un pulsante/select a tendina o simile per cambiare la lingua dell'interfaccia pubblica1) al volo.

Cosa sto cercando:

  • Plugin oppure codice per il tema...
  • ... oppure idee
  • Sarebbe apprezzato un work-around con load_textdomain() per mantenere le traduzioni nei file .po/.mo
  • Idee su come parsare le stringhe nell'interfaccia (es. ajax/php plain/ini, json, file xml) quando non si utilizza una funzione textdomain

Nota:

1) Non si tratta di pubblicare in lingue diverse.

2) Non mi serve codice per creare il menu a tendina/pulsante/altro. Serve solo il codice/sistema che fornisca le stringhe per l'UI.

Grazie!

5
Commenti

Se puoi accontentarti di un refresh della pagina, ridefinire la costante WPLANG potrebbe essere un'opzione. Io lo sto facendo su due siti con contenuti multilingue dove il plugin di multilingua non riesce a attivare la traduzione dell'interfaccia. Se invece deve essere una soluzione AJAX/JSON, non saprei come aiutarti.

Johannes Pille Johannes Pille
5 dic 2011 21:01:45

@JohannesPille In quale punto/hook effettui lo switch? A proposito: potresti spostarlo in una risposta. Già meritevole di un voto positivo. Grazie.

kaiser kaiser
5 dic 2011 21:04:22

Lo sto facendo in un plugin, nessun hook coinvolto. È una soluzione piuttosto sporca e non ne sono particolarmente orgoglioso, ma al momento ha risolto il problema. Puoi vedere il codice del plugin in questo pastebin. Quello che fa è autoesplicativo. Il sito da cui ho copiato questo codice utilizza l'ultima versione gratuita di WPML. Va bene, l'ho spostato in una risposta.

Johannes Pille Johannes Pille
5 dic 2011 21:33:59

L'URL di pastebin sembra non essere più disponibile.

PapaFreud PapaFreud
20 mar 2012 16:04:48

@JohannesPille Potresti pubblicare il tuo codice come aggiornamento alla tua domanda, o aggiungere un pastebin che non scada?

kaiser kaiser
20 mar 2012 16:59:56
Tutte le risposte alla domanda 3
5
15

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

Per prima cosa, imposta una funzione rapida per recuperare una lingua diversa da utilizzare sul filtro locale.

/**
 * Una funzione che restituisce la locale selezionata dall'utente, se memorizzata. 
 */
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;
}

Ho lasciato questa come funzione globale, potrebbe essere utile...? Il resto del plugin l'ho racchiuso in una classe.

Crea un menu a discesa delle lingue disponibili tra cui puoi selezionare.

Svantaggi

  • Cerca nella cartella wp-content/languages i file nel formato xx_xx.mo. Se non è in quel formato (non tutti i file .mo lo sono), il plugin non li rileverà!
  • Il menu a discesa mostra un elenco delle locale trovate tra cui scegliere, ma queste vengono visualizzate nel formato 'xx_xx' delle locale, non in un modo amichevole per l'utente - qualche idea??
  • $locale fa qualcosa oltre alla lingua? Se sì, è comunque possibile ottenere la stessa locale, ma fornire traduzioni alternative. Tuttavia, è molto più complicato...

Il codice

class SH_Pick_Lang{
    /**
     * Un nome univoco per questo plugin
     */
    static $name ='sh_pick_lang';

    /**
     * Aggancia le funzioni
     */
    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') );
    }

    /**
     * Aggiorna l'opzione dell'utente appena in tempo! Solo una volta però...
     */
    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;
    }

    /**
     * Aggiunge un menu a discesa dall'aspetto orribile che sono sicuro Kaiser renderà fantastico.
     */
    function admin_bar(){
        global $wp_admin_bar;

        $wp_admin_bar->add_menu( array(
            'id'        => 'shlangpick',
            'title'     => $this->wpse_language_dropown(),
        ) );
    }

    /**
     * Genera un elenco delle locale disponibili.
     * Cerca nella cartella wp-content/languages i file nel formato xx_xx.mo
     * 
     * TODO Non tutte le locale sono nel formato xx_xx.mo - potremmo perderne alcune.
     * TODO Un modo migliore per ottenere la cartella wp-content/languages senza una costante?
     */
    function wpse_language_dropown(){
         $name = self::$name;
         $locale = get_locale();
         $langs = get_available_languages();
         $langs[] = 'en_US';

         //Per le etichette (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('Cambia Lingua','secondary', 'submit', true);
         $html .= "</form >";

         return $html;
    }

} // Fine Classe

//Inizializza...
$sh_pick_lang = new SH_Pick_Lang();
5 lug 2012 16:21:51
Commenti

Upvote fatto (mi diverto anche con tutti i commenti inline). Il bounty è impostato e ti verrà assegnato non appena mi sarà permesso (mancano 23h - fammi un fischio se mi dimentico).

kaiser kaiser
6 lug 2012 14:36:16

Aggiornato per riflettere la risposta a questa domanda.

Stephen Harris Stephen Harris
6 lug 2012 14:57:16

Ottimo lavoro. Aggiunto ai preferiti. +1

Johannes Pille Johannes Pille
6 lug 2012 19:50:13

Ho notato che semplicemente includendo 'wp-admin/includes/ms.php' viene attivato un avviso di amministrazione per aggiornare i siti della rete (quando si tratta di un singolo sito!). Potrebbe essere necessario duplicare format_code_lang() all'interno di una funzione personalizzata.

Stephen Harris Stephen Harris
6 lug 2012 19:54:46

Ho aggiunto un Gist con la mia pulizia - non ho avuto tempo di testarlo, dato che sto pasticciando con le cartelle dei plugin al momento e questo significa che nessun altro plugin funziona. Spero che tu possa lavorare con il gist fornito e magari forkarlo/aggiornarlo. Posso assegnare la bounty tra mezz'ora, ma devo andare ora, quindi la invierò domani. Grazie per tutto il tuo lavoro - dovrebbe essere incluso in qualsiasi installazione predefinita :)

kaiser kaiser
7 lug 2012 14:15:46
5

Se puoi accontentarti di un refresh della pagina, ridefinire la costante WPLANG potrebbe essere un'opzione. Lo sto facendo su due siti con contenuti multilingue dove il plugin di multilingua non riesce ad attivare la traduzione dell'interfaccia utente.

5 dic 2011 21:23:47
Commenti

Hmm.. potresti usare ajax per sostituire il body o l'intero tag html della pagina, dopo aver eseguito il codice sopra (nella stessa richiesta ajax), al click del tuo pulsante o qualcosa del genere.

Joshua Abenazer Joshua Abenazer
5 dic 2011 21:44:46

+1. Ho appena visto il tuo pastebin. Questo significa che il tuo setup è http://example.com/lingua/qualcosa/, giusto?

kaiser kaiser
5 dic 2011 23:18:07

@kaiser Sì, questo è il setup nel sito da cui proviene il codice. Se ti interessa solo la lingua dell'interfaccia utente, passare una query string nell'URL o impostare una variabile $_SESSION per attivare la ridefinizione di WPLANG al prossimo caricamento della pagina dovrebbe funzionare. Se invece vuoi replicare questo su un sito multilingua, 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 modulo apache mod_rewrite. Sono sicuro che può essere adattato, ma non funzionerà "così com'è".

Johannes Pille Johannes Pille
6 dic 2011 00:40:40

Non utilizzerò qTranslate o WPML. Si tratta davvero solo della lingua dell'interfaccia utente. Riguardo a $_SESSION), il mio problema è che, per quanto ne so, sono piuttosto difficili da gestire e i dati tra globali e l'array possono mescolarsi facilmente. Quindi, se cercassi un modo per cambiare WPLANG, dovrei trovare un metodo solido per passarlo da una richiesta all'altra. Forse add_query_arg/get_query_var potrebbe fare al caso mio...

kaiser kaiser
6 dic 2011 03:19:00

Stavo ripensando di nuovo a questo (la soluzione non è ancora stata implementata nel progetto): Potresti racchiuderlo in qualche ajax? Penso che questo sarebbe il modo migliore per aggirare il problema. Voglio chiudere la domanda e contrassegnarla come soluzione :) Grazie.

kaiser kaiser
4 feb 2012 05:21:44
5

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

è quello che ti serve...

Modifica I - dopo il commento. Prima di tutto - grazie a tutti quelli che hanno contribuito al torrente di voti negativi. (questo è ciò che accade quando non si visita frequentemente abbastanza :- ) )

ora - La funzione che gestisce lo switch si trova in qtranslate-core. (inizia più o meno alla linea 80 - dipende dalla versione che vuoi.)

Dato che non puoi guardare in un codice NON OOP, e io ora non ho altro da fare - ho preso 10 minuti per sintetizzare, parafrasare e compilare quel codice non-OOP con un altro codice non-OOP per te.

(scusa, - vecchia scuola primitiva qui)

Supponendo di aver capito la domanda && Supponendo che tu voglia il codice per l'admin && supponendo che tu sappia come portarlo al front end se vuoi && supponendo che tu capisca 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('Lingua:','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('Inglese','your_text_domain');?></option>
        <option value="de_DE" <?php if($_COOKIE['k99_userLang']=="de_DE"){echo "selected";} ?>><?php _e('Tedesco','your_text_domain');?></option>
        <option value="zh_CN" <?php if($_COOKIE['k99_userLang']=="zh_CN"){echo "selected";} ?>><?php _e('Cinese','your_text_domain');?></option>
    </select>
    </div>
<?php   
}
// Ora impostiamo quella funzione per essere eseguita quando viene chiamata l'azione di help
add_filter('contextual_help', 'k99_add_language_menu');

// Immagino che questa sia la tua misteriosa "roba del browser"
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'); // esempio d'uso per il textdomain dei plugin
    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);

////////// +++++++++++++++  INIZIO CREAZIONE COOKIES +++++++++++++++//////////////////
// Funzione Javascript per impostare i cookies della lingua
// accesso esterno
// @param lang - codice lingua
// @return NULL
// o forse questa è la misteriosa "roba del browser" dell'OP ??
    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 ); //imposta la scadenza del cookie a 10000 ore (ora*minuto*secondi*1000)
        document.cookie = "k99_userLang="+lang+";expires="+ Then.toGMTString();
        window.location.reload();
        } 
        </script>
<?php
} 
add_action('admin_print_scripts', 'mgmb_print_script');  // questo non è il modo giusto per farlo.. ma non ho tempo ora.
?>

OSSERVAZIONI:

1 - Questo è stato costruito in 10 min. su una macchina locale mentre ero all'aeroporto. Il motivo per cui lo dico è che l'unica installazione di wordpress pronta che ho qui è piuttosto vecchia. (2.9 credo).

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

Se avessi più tempo (e un nuovo codice wordpress qui) probabilmente integrerei questo nella nuova admin-bar con add_action( 'admin_bar_menu', 'k99_add_language_menu_2', 1000 ); (ho già promesso di tornarci)

2 - dovresti avere i file delle lingue elencate all'interno della cartella "languages" in wp-content (meglio??) o wp-include. riguardo a questo punto - il codice è solo una proof of concept - e ovviamente se uno 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à su versioni più nuove di wp se una lingua è già impostata.

4 - è una semplice proof of concept sintetizzata e parafrasata basata su ciò che è stato visto nel codice di qtranslate (anche versione vecchia) - quindi la maggior parte delle cose sono fatte in modo "veloce", non necessariamente nel modo "giusto" (come aggiungere JS, nessun textdomain dedicato etc..).

MODIFICA II

qualcuno è fortunato oggi! (Volo in ritardo)

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

Non si adatterà a un plugin, o in realtà a qualsiasi altro ambiente non esclusivo, ma potrebbe darti un'altra direzione su come gestire la "roba del browser".

Questo permetterà di ottenere la lingua con un GET come: <a href="index.php?lang=de">Tedesco</a> o <a href="whatever.php?lang=ml">mia Lingua</a>

Per usarlo, 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 qualche cookie al mix per memorizzare le lingue.

MODIFICA III

Ho promesso di tornarci più tardi - ecco come (in un modo molto non corretto e primitivo) potrebbe essere integrato all'interno della admin-bar (invece del contextual-help-menu)

 function k99_add_language_menu_bar() {
    global $wp_admin_bar, $wpdb;
    if ( !is_super_admin() || !is_admin_bar_showing() )
        return;
// Sono sicuro che puoi trovare un modo da solo per costruire l'array leggendo la cartella. Se no, commenta e aggiornerò ancora.

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" >Inglese</option>';
    $k99_lang .= '<option value="de_DE" >Tedesco</option>';
    $k99_lang .= '<option value="zh_CN" >Cinese</option></select>';

    /* Aggiungi la voce principale del menu siteadmin */
    $wp_admin_bar->add_menu( array( 'id' => 'Language', 'title' => __( 'lingua', '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 );

Sostituisci questa funzione (o aggiungi) al vecchio codice (il NON - OOP non-plugin originale).

Come ho detto, non ho una nuova installazione di wordpress qui in locale che abbia la admin-bar - ma dovrebbe funzionare.

(e poi di nuovo, potrebbe non funzionare...ma sono sicuro che potresti sistemarlo se lo vuoi davvero - anche se non è OOP) :-)

devo scappare ora. spero che aiuti in qualche modo.

MODIFICA IV - cambiato edit III alla versione funzionante per la admin menu bar (almeno sul mio wp 3.4)

dato che non avevo un'installazione funzionante di 3.4 - e ora sono tornato e ce l'ho - ho modificato la soluzione della Modifica III - e funziona per me.

Riguardo agli upvotes, non me ne potrebbe fregare di meno. E non ho bisogno di nessun "bounty" (qualunque cosa siano..) Era solo per il gusto dell'esercizio dovresti forse darlo all'autore di qTranslate. :-) nonostante il fatto che non sia OOP - è un plugin geniale con tanto da imparare in tante aree. considerando il "quando" di questo rilascio del plugin, è persino incredibile. vale lo sforzo indescrivibile di leggere un codice NON OOP - anche se non è - OOP. E anche se non è indentato correttamente (santo cielo!).

5 dic 2011 22:30:30
Commenti

Forse c'è una soluzione sepolta nelle profondità di questo codice, ma è quasi impossibile individuare tutti i percorsi, dato che non è scritto in OOP. Se sai esattamente dove si trova il rilevamento della lingua (la parte relativa al browser) e come filtra le stringhe gettext, per favore fammelo sapere.

kaiser kaiser
5 dic 2011 23:24:40

@kaiser - vedi modifica I per la "parte relativa al browser".

krembo99 krembo99
8 lug 2012 12:19:43

@kaiser ..e vedi modifica II per ulteriori dettagli sulla "parte relativa al browser" - e modifica III per come incorporare la "parte relativa al browser" all'interno del "browser (stuff)".

krembo99 krembo99
8 lug 2012 12:49:32

Ok, ho votato positivamente (non negativo per annullare qui), per il tuo sforzo. L'idea di usare un cookie è carina. Comunque, ecco alcune note: Edit II genererà un errore dopo il require(). Non puoi usare define() sulla stessa stringa due volte. Edit III ha alcuni problemi con le lingue. Selezionare en_US non farebbe nulla(?), ma de_DE lo imposterebbe su English ;). Per riassumere: assegno i bounty e li do (per esempio a StephenHarris) per una risposta completa e funzionante. Se hai qualcosa del genere, per favore aggiorna la tua risposta (l'approccio con i cookie è interessante) e potrei aggiungere e premiarti con un bounty.

kaiser kaiser
8 lug 2012 14:45:17

Per favore non lasciare commenti per me. Fai modifiche alla tua risposta, così tutti possono leggere le tue idee. Nota a margine: imho il codice esterno dovrebbe sempre essere aggiunto come Plugin/MU-Plugin/Theme/DropIn per renderlo spostabile.

kaiser kaiser
8 lug 2012 18:40:23