Alterar idioma clicando em um botão

21

O objetivo é oferecer um botão / selecionar suspenso ou similar para alternar o idioma da interface pública 1) em tempo real.

O que estou procurando

  • Código do plug-in ou do tema ...
  • ... ou idéias
  • É recomendável usar uma load_textdomain()solução alternativa para deixar a tradução em arquivos .po / .mo
  • Ideias sobre como analisar as seqüências de caracteres na interface (por exemplo, arquivos ajax / php simples / ini, json, xml) quando não depender de alguma função do domínio de texto

Nota:

1) Não se trata de publicar em idiomas diferentes.

2) Não preciso de código para fazer o menu suspenso / botão / o que for. É apenas sobre o código / sistema que entrega as strings para a interface do usuário.

Obrigado!

kaiser
fonte
1
Se você pode aceitar uma atualização da página, redefinir a WPLANGconstante pode ser uma opção. Estou fazendo isso em dois sites com conteúdo multilíngue, em que o plug-in multilíngue falha ao disparar a tradução da interface do usuário. Se tivesse que ser uma solução AJAX / JSON, não saberia como ajudar.
Johannes Pille 5/12
@JohannesPille Em que ponto / gancho você alterna? Btw: Você poderia passar isso para uma resposta. Já vale uma votação. Obrigado.
Kaiser
Estou fazendo isso em um plugin, sem ganchos envolvidos. É uma correção bastante suja e não tenho tanto orgulho disso, mas ele fez o trabalho na época. Você pode ver o código do plug-in nesta pasta . O que ele faz é auto-explicativo. O site do qual copiei utiliza a última versão gratuita do WPML. Fair enuff, mudou-se para uma resposta.
Johannes Pille
O URL do pastebin parece estar morto.
PapaFreud 20/03/12
@JohannesPille Você se importaria de publicar seu código como uma atualização para o seu Q ou adicionar uma pasta que não esteja expirando?
kaiser

Respostas:

15

De longe, a melhor (mais fácil) maneira é usar o filtro de localidade (interno get_locale()).

Primeiro, configure uma função rápida para recuperar um idioma diferente para usar no 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;
}

Eu deixei isso como uma função global, pode ser útil ...? O resto do plug-in que envolvi em uma classe.

Ele cria uma lista suspensa de possíveis idiomas a partir dos quais você pode selecionar.

Desvantagens

  • Procura wp-content/languagespor arquivos do formulário xx_xx.mo. Se não tiver esse formato (nem todos os arquivos .mo), o plug-in não será utilizado!
  • O menu suspenso fornece uma lista dos locais encontrados para escolher, mas eles são exibidos no formato 'xx_xx` de locais, não de uma forma amigável para o ser humano - alguma idéia?
  • Faz $localealgo diferente de idioma? Nesse caso, ainda é possível obter a localidade da mesma forma, mas forneça traduções alternativas. É muito mais bagunçado ...

O 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
fonte
1
Upvote feito (falando sobre todos os comentários em linha também). A recompensa está definida e será concedida a você o mais breve possível, quando me restarem 23 horas - me indique se eu esquecer.
Kaiser
2
Atualizado para refletir a resposta a esta pergunta .
Stephen Harris
N1ce one. Marcado como favorito. +1
Johannes Pille
Percebi que apenas incluir 'wp-admin/includes/ms.php'aciona um aviso de administrador para atualizar os sites da sua rede (quando você é um único site!). Pode ser que format_code_lang()seja necessário duplicar dentro de uma função personalizada.
Stephen Harris
Eu adicionei um Gist com minha limpeza - não tive tempo de testá-lo, pois estou mexendo com as pastas de plug-in atualmente e isso significa que nenhum outro plug-in funciona. Espero que você possa trabalhar com a essência fornecida e talvez com o fork / atualização. Posso conceder a recompensa em meia hora, mas tenho que sair agora, então enviarei amanhã. Obrigado por todo o seu trabalho - deve ser em qualquer instalação padrão :)
kaiser
5

Se você pode aceitar uma atualização da página, redefinir a WPLANGconstante pode ser uma opção. Estou fazendo isso em dois sites com conteúdo multilíngue, em que o plug-in multilíngue falha ao disparar a tradução da interface do usuário.

Johannes Pille
fonte
Hmm .. você pode usar o ajax para substituir o corpo ou a tag html inteira da página, depois de executar o código acima (na mesma solicitação do ajax), clicar no botão ou algo assim.
Joshua Abenazer 5/12
+1. Apenas olhei para o seu pastebin. Isso significa que sua configuração é http://example.com/language/whatever/, certo?
Kaiser
@kaiser Sim, essa é a configuração no site de onde o código vem. Se você se preocupa apenas com o idioma da interface do usuário, deve passar uma cadeia de consulta de URL ou definir uma $_SESSIONvariável para acionar a redefinição WPLANGno próximo carregamento de página. Se você deseja replicar isso em um site multilíngue, observe que, como diz o comentário com o pastebin, o código nele funciona com o WPML, última versão gratuita. Ele não pode ser replicado 1 para 1 com qTranslate, porque esses URIs não são físicos, mas são reescritos através do mod_rewritemódulo apache. Tenho certeza de que pode ser ajustado, mas não funcionará "como está".
Johannes Pille
Não usarei qTranslate ou WPML. É realmente apenas sobre o idioma da interface do usuário. Anúncio $_SESSION) Meu problema é que eles são muito difíceis de manusear e coisas entre globais e a matriz podem se misturar facilmente. Portanto, se eu tentar encontrar uma maneira de mudar WPLANG, preciso encontrar uma maneira sólida de fazer isso de uma solicitação para outra. Talvez add_query_arg/get_query_varfará o truque ...
kaiser
Eu estava pensando sobre isso novamente (a solução ainda não foi incorporada ao projeto): Você poderia colocar isso em algum ajax? Eu acho que essa seria a melhor maneira de contornar isso. Quero fechar o Q e marcá-lo como solução :) Obrigado.
Kaiser
2

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

é o que você precisa ...

Editar I - após o comentário. Primeiro - obrigado por todos os que contribuíram no downvotes torrent. (é o que acontece quando não se visita com frequência suficiente: -))

now - A função que lida com o switch está no qtranslate-core. (começa na linha 80 mais ou menos - depende da versão que você deseja).

Como você não pode procurar um código NOT OOP, e agora não tenho mais nada a fazer - levei 10 minutos para sintetizar, parafraseando a compilação desse non-OOp com outro código não-OOP.

(desculpe, - skool antigo primitivo aqui)

Supondo que eu entendi a pergunta && Supondo que você queira que o código seja para admin && assumindo que você saberá como portá-lo para o front-end se quiser && assumindo que entende que o código não é o ideal:

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

OBSERVAÇÕES:

1 - Este foi construído em 10 min. na máquina local enquanto estiver no aeroporto. A razão pela qual digo isso é que a única instalação pronta disponível do wordpress disponível aqui é bastante antiga. (2,9 eu acho).

Isso significa que provavelmente o menu de idiomas aparecerá SOB a ajuda contextual div, devido ao fato de uma nova estrutura div ter sido introduzida recentemente (com guias) - mas ainda assim deve funcionar. (Eu prometo voltar a isso mais tarde, se tiver tempo)

Se eu tivesse mais tempo (e um novo código wordpress aqui), provavelmente integraria isso na nova barra de administração com add_action( 'admin_bar_menu', 'k99_add_language_menu_2', 1000 );(eu já prometi voltar a isso)

2 - você deve ter os arquivos de idiomas listados dentro da pasta "languages" em wp-content (better ??) ou wp-include. sobre esse ponto - o código é apenas uma prova de conceito - e, claro, se houver mais tempo, o menu deve ser construído de forma dinâmica e não como aqui.

3 - seu WPLANG na configuração deve estar vazio. Não tenho certeza se funcionará em versões mais recentes do wp se um idioma já estiver definido.

4 - é uma simples prova de conceito sintetizada e parafraseada, construída com base no que foi visto no código qtranslate (também versão antiga) - para que a maioria das coisas seja feita da maneira "rápida", não necessariamente da maneira "certa" (como adicionar JS , nenhum domínio de texto dedicado etc.).

EDIT II

alguém tem sorte hoje! (Atraso no voo)

Desde que você estava procurando "idéias" para abordagens, aqui está outra famosa.

Ele não se encaixa em um plug-in ou em qualquer outro ambiente não exclusivo, mas pode fornecer outra orientação sobre como lidar com o "material do navegador".

Isso permitirá obter o idioma com um GET como: <a href="index.php?lang=de">German</a>ou<a href="whatever.php?lang=ml">my Language</a>

Para usar, você pode criar um código (vamos chamá-lo de 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', '');
        }
    }
 }

Agora, no wp-config, logo antes da constante WPLANG, precisamos incluir nosso código.

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

Agora - obviamente, seria melhor adicionar alguns cookies à mistura para armazenar os idiomas.

EDIT III

Prometi voltar a isso mais tarde - eis como (de uma maneira muito incorreta e primitiva) ele poderia ser integrado dentro da barra de administração (em vez do menu de ajuda 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 );

Apenas substitua esta função (ou adicione) ao código antigo (o não plug-in NON-OOP original).

Como eu disse, eu não tenho uma nova instalação do wordpress aqui no local que apresenta o admin-bar - mas deve funcionar.

(e, novamente, pode não funcionar ... mas tenho certeza de que você pode corrigir isso se realmente quiser - mesmo que não seja OOP) :-)

tenho que correr agora. espero que ajude de alguma forma.

EDIT IV - alteração da edição III para a versão de trabalho da barra de menus do administrador (pelo menos no meu wp 3.4)

desde que eu não tinha uma instalação funcional do 3.4 - e agora voltei e o faço - editei a solução Edit III - e funciona para mim.

Sobre os votos, eu não poderia me importar menos. E não preciso de "recompensas" (sejam elas quais forem ..) Foi apenas por causa do exercício que talvez você devesse dar ao autor do qTranslate. :-) apesar de não ser OOP - é um plugin genial com muito o que aprender em muitas áreas. considerando o "quando" desta versão do plugin, é ainda incrível. vale o esforço indescritível de ler um código NÃO OOP - mesmo que não seja - OOP. E mesmo que não esteja corretamente recuado (bom Deus!).

krembo99
fonte
3
Talvez haja uma solução escondida na profundidade desse código, mas é quase impossível descobrir todas as maneiras, pois não está escrito em OOP. Se você souber exatamente onde está a detecção de idioma (o material do navegador) e como ela filtra as strings gettext, entre em contato.
Kaiser
1
@ kaiser - veja edit I para "itens do navegador".
krembo99
1
@kaiser ..e veja a edição II para mais "itens do navegador" - e a edição III para saber como incorporar as "coisas do navegador" dentro do "navegador (itens)".
Krembo99
Ok, eu votei (não votei para reverter aqui), pelo seu esforço. A ideia de usar um cookie é boa. Enfim, aqui estão algumas notas: Edit II lançará um erro após o require(). Você não pode usar define()a mesma string duas vezes. O Edit III tem alguns problemas com os idiomas. Selecionar en_USnão faria nada (?), Mas de_DEconfiguraria para English;). Para resumir: concedo recompensas e as dou a (por exemplo, StephenHarris) para obter uma resposta completa e funcional. Se você tiver algo assim, atualize sua resposta (abordagem interessante sobre cookies) e eu posso adicionar e recompensar você.
Kaiser
Por favor, não deixe comentários para mim. Faça edições na sua resposta para que todos possam ler suas idéias. Nota: o código externo imho sempre deve ser adicionado como Plugin / MU-Plugin / Theme / DropIn para torná-lo móvel.
kaiser