Cambiar idioma haciendo clic en un botón

21

El objetivo es ofrecer un botón / seleccionar desplegable o similar para cambiar la interfaz pública 1) idioma sobre la marcha.

Lo que estoy buscando

  • Plugin o código de tema ...
  • ... o ideas
  • load_textdomain()Se agradecería usar una solución alternativa para dejar la traducción a archivos .po / .mo
  • Ideas sobre cómo analizar las cadenas en la interfaz (por ejemplo, archivos ajax / plain php / ini, json, xml) cuando no confía en alguna función de dominio de texto

Nota:

1) No se trata de publicar en diferentes idiomas.

2) No necesito código para hacer el menú desplegable / botón / lo que sea. Solo se trata del código / sistema que entrega las cadenas para la interfaz de usuario.

¡Gracias!

emperador
fuente
1
Si puede conformarse con una actualización de la página, redefinir la WPLANGconstante podría ser una opción. Lo estoy haciendo en dos sitios con contenido multilingüe donde el complemento multilingüismo no puede activar la traducción de la interfaz de usuario. Si tiene que ser una solución AJAX / JSON, no sabría cómo ayudar.
Johannes Pille
@JohannesPille ¿En qué punto / gancho cambiar? Por cierto: ¿podrías mover eso a una respuesta? Ya vale la pena un voto positivo. Gracias.
kaiser
Lo estoy haciendo en un complemento, sin ganchos involucrados. Es una solución bastante sucia y no estoy tan orgulloso de eso, pero hizo el trabajo en ese momento. Puede ver el código del complemento en este pastebin . Lo que hace se explica por sí mismo. El sitio del que copié esto utiliza la última versión gratuita de WPML. Justo enuff, lo movió a una respuesta.
Johannes Pille
La URL de Pastebin parece estar muerta.
PapaFreud
@JohannesPille ¿Le importaría publicar su código como una actualización de su Q, o agregar un pastebin que no caduque?
kaiser

Respuestas:

15

Con mucho, la mejor manera (más fácil) es usar el filtro de configuración regional (dentro get_locale()).

Primero configure una función rápida para recuperar un idioma diferente para usar en el 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;
}

He dejado esto como una función global, ¿podría ser útil ...? El resto del complemento lo he incluido dentro de una clase.

Crea un menú desplegable de posibles idiomas entre los que puede seleccionar.

Inconvenientes

  • Busca wp-content/languagesarchivos del formulario xx_xx.mo. Si no es de esa forma (no todos los archivos .mo son), ¡el complemento no lo detectará!
  • El menú desplegable proporciona una lista de las configuraciones regionales encontradas para elegir, pero estas se muestran en el formato 'xx_xx` de configuraciones regionales, no de una manera amigable para los humanos: ¿alguna idea?
  • ¿Hace $localealgo más que el idioma? Si es así, todavía es posible obtener la configuración regional igual, pero proporcionar traducciones alternativas. Aunque es mucho más desordenado ...

El código

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
fuente
1
Voto a favor hecho (gustando de todos los comentarios en línea también). La recompensa está establecida y se te otorgará tan pronto como me lo permitan (quedan 23 horas; apúntame si lo olvido).
kaiser
2
Actualizado para reflejar la respuesta a esta pregunta .
Stephen Harris el
N1ce uno. Marcado como favorito +1
Johannes Pille
Me di cuenta de que solo incluir 'wp-admin/includes/ms.php'activa un aviso de administrador para actualizar sus sitios de red (¡cuando es un solo sitio!). Es posible que format_code_lang()deba duplicarse dentro de una función personalizada.
Stephen Harris
Agregué un Gist con mi limpieza , no tuve tiempo de probarlo, ya que actualmente estoy jugando con las carpetas de complementos y esto significa que ningún otro complemento funciona. Espero que pueda trabajar con la esencia proporcionada y tal vez fork / update. Puedo otorgar la recompensa en media hora, pero tengo que irme ahora, así que la enviaré mañana. Gracias por todo su trabajo, debería estar en cualquier instalación predeterminada :)
kaiser
5

Si puede conformarse con una actualización de la página, redefinir la WPLANGconstante podría ser una opción. Lo estoy haciendo en dos sitios con contenido multilingüe donde el complemento multilingüismo no puede activar la traducción de la interfaz de usuario.

Johannes Pille
fuente
Hmm ... podría usar ajax para reemplazar el cuerpo o la etiqueta html completa de la página, después de ejecutar el código anterior (en la misma solicitud de ajax), al hacer clic en su botón o algo así.
Joshua Abenazer
+1. Acabo de mirar tu pastebin. Esto significa que su configuración es http://example.com/language/whatever/, ¿verdad?
kaiser
@kaiser Sí, esa es la configuración en el sitio de donde proviene el código. Si solo le importa el idioma de la interfaz de usuario, debe pasar una cadena de consulta de URL o establecer una $_SESSIONvariable para activar la redefinición WPLANGen la próxima carga de página. Si desea replicar esto en un sitio multilingüe, tenga en cuenta que, como dice el comentario con el pastebin, el código en él funciona con WPML, la última versión gratuita. No se puede replicar 1 a 1 con qTranslate, porque esos URI no son físicos, sino que se reescriben a través del mod_rewritemódulo apache. Estoy seguro de que se puede ajustar, pero no funcionará "como está".
Johannes Pille
No usaré qTranslate o WPML. Realmente se trata solo del lenguaje de la interfaz de usuario. Ad $_SESSION) Mi problema es que afaik son bastante difíciles de manejar y las cosas entre los globales y la matriz se pueden mezclar fácilmente. Entonces, si trato de encontrar una manera de cambiar WPLANG, entonces necesito encontrar una forma sólida de darlo de una solicitud a otra. Quizás add_query_arg/get_query_varhaga el truco ...
kaiser
Estaba pensando en esto nuevamente (la solución aún no está incorporada en el proyecto): ¿Podría envolver esto en algún ajax? Creo que esta sería la mejor manera de evitar esto. Quiero cerrar la Q y marcarla como solución :) Gracias.
kaiser
2

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

es lo que necesitas ...

Editar I - después del comentario. Primero, gracias por todos los que contribuyeron en el torrente de votos negativos. (esto es lo que sucede cuando uno no visita con suficiente frecuencia: -))

ahora: la función que maneja el conmutador está en qtranslate-core. (comienza en la línea 80 más o menos, depende de la versión que desee).

Como no puede buscar un código NOT OOP, y ahora no tengo nada más que hacer, me tomé 10 minutos para sintetizar, parafrasear compilar ese no OOp con otro código no OOP para usted.

(lo siento, primitivo viejo skool aquí)

Suponiendo que entendí la pregunta && Suponiendo que desea que el código sea para el administrador && suponiendo que sabrá cómo portarlo al front-end si lo desea && asumiendo que comprende que el código no es óptimo:

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

OBSERVACIONES

1 - Esto fue construido en 10 min. en la máquina local, mientras que en el aeropuerto. La razón por la que digo esto es que la única instalación de WordPress disponible que tengo aquí es bastante antigua. (2.9 creo).

Esto significa que probablemente el menú de idioma aparecerá BAJO el div de ayuda contextual, debido al hecho de que recientemente se introdujo una nueva estructura div (con pestañas), pero aún así debería funcionar. (Prometo volver a esto más tarde si tengo tiempo)

Si tuviera más tiempo (y un nuevo código de WordPress aquí) probablemente integraría esto en la nueva barra de administración con add_action( 'admin_bar_menu', 'k99_add_language_menu_2', 1000 );(ya prometí volver a esto)

2 - debe tener los archivos de idiomas enumerados dentro de la carpeta "idiomas" en wp-content (mejor ??) o wp-include. con respecto a este punto, el código es solo una prueba de concepto, y, por supuesto, si uno tiene más tiempo, el menú debe construirse de forma dinámica y no como se hace aquí.

3 - tu WPLANG en la configuración debe estar vacío. No estoy seguro de que funcionará en las nuevas versiones de wp si ya se ha configurado un idioma.

4 - es una simple prueba de concepto sintetizada y parafraseada construida sobre lo que se vio en el código qtranslate (también versión anterior) - por lo que la mayoría de las cosas se hacen de la manera "rápida", no necesariamente de la manera "correcta" (como agregar JS , sin dominio de texto dedicado, etc.).

EDITAR II

Alguien tiene suerte hoy! (Vuelo demorado )

Como estaba buscando "ideas" para enfoques, aquí hay otra famosa.

No cabrá en un complemento, o en cualquier otro entorno no exclusivo, pero podría darle otra dirección sobre cómo manejar el "material del navegador".

Esto permitirá obtener el idioma con un GET como: <a href="index.php?lang=de">German</a>o<a href="whatever.php?lang=ml">my Language</a>

Para usar, puede crear un código (vamos a llamarlo 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', '');
        }
    }
 }

ahora, en wp-config, justo antes de la constante WPLANG, necesitamos incluir nuestro código.

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

Ahora, obviamente, sería mejor agregar algunas cookies a la mezcla para almacenar los idiomas.

EDITAR III

Prometí volver a esto más tarde: así es cómo (de una manera muy incorrecta y primitiva) podría integrarse dentro de la barra de administración (en lugar del menú de ayuda contextual)

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

Simplemente reemplace esta función (o agregue) al código anterior (el no plugin original NO - OOP).

Como dije, no tengo una nueva instalación de WordPress aquí en local que incluya la barra de administración, pero debería funcionar.

(y de nuevo, puede que no funcione ... pero estoy seguro de que podría solucionarlo si realmente lo desea, incluso aunque no sea POO) :-)

Tengo que correr ahora. Espero que ayude de alguna manera.

EDITAR IV : cambió la edición III a la versión de trabajo para la barra de menú de administración (al menos en mi wp 3.4)

Como no tenía una instalación funcional de 3.4, y ahora regresé y lo hago, he editado la solución Edit III, y funciona para mí.

Sobre los votos a favor, no podría importarme menos. Y no necesito ninguna "recompensa" (sean las que sean). Fue solo por el ejercicio que tal vez deberías dárselo al autor de qTranslate. :-) a pesar del hecho de que no es OOP, es un plugin genial con mucho que aprender en muchas áreas. considerando el "cuándo" de este lanzamiento de plugin, es incluso sorprendente. Vale la pena el esfuerzo indescriptible de leer un código NO OOP, incluso si no lo es, OOP. E incluso si no está correctamente sangrado (¡Dios mío!).

krembo99
fuente
3
Tal vez hay una solución enterrada en la profundidad de este código, pero es casi imposible de resolver, ya que no está escrito en OOP. Si sabe dónde se encuentra exactamente la detección de idioma (el material del navegador) y cómo filtra las cadenas gettext, hágamelo saber.
kaiser
1
@kaiser - ver edit I para "cosas del navegador".
krembo99
1
@kaiser .. y vea edit II para más "cosas del navegador" - y edit III para saber cómo incorporar las "cosas del navegador" dentro del "browser (cosas)".
krembo99
Ok, lo voté (no lo rechazo para volver aquí), por su esfuerzo. La idea de usar una cookie es buena. De todos modos, aquí hay algunas notas: Edit II arrojará un error después de require(). No se puede usar define()en la misma cadena dos veces. Edit III tiene algunos problemas con los idiomas. Seleccionar en_USno haría nada (?), Pero de_DElo establecería en English;). Para resumir: otorgo recompensas y se las doy (por ejemplo, StephenHarris) para obtener una respuesta completa y funcional. Si tiene algo así, actualice su respuesta (enfoque de cookie interesante) y puedo agregarle y recompensarle una recompensa.
kaiser
Por favor no me dejes comentarios. Modifique su respuesta para que todos puedan leer sus ideas. Nota al margen: el código externo de imho siempre debe agregarse como Plugin / MU-Plugin / Theme / DropIn para que sea movible.
kaiser