Zmień język, klikając przycisk

21

Celem jest zaoferowanie przycisku / menu rozwijanego lub podobnego do przełączania języka interfejsu publicznego 1) w locie.

Czego szukam

  • Wtyczka lub kod motywu ...
  • ... lub Pomysły
  • load_textdomain()Docenione byłoby obejście problemu z pozostawieniem tłumaczenia do plików .po / .mo
  • Pomysły, jak parsować ciągi znaków w interfejsie (np. Pliki ajax / plain php / ini, json, xml), gdy nie polegasz na niektórych funkcjach textdomain

Uwaga:

1) Nie chodzi o publikowanie w różnych językach.

2) Nie potrzebuję kodu, aby zrobić rzeczywistą listę rozwijaną / przycisk / cokolwiek innego. Dotyczy tylko kodu / systemu dostarczającego ciągi dla interfejsu użytkownika.

Dzięki!

kajzer
źródło
1
Jeśli możesz zadowolić się odświeżeniem strony, WPLANGopcją może być ponowne zdefiniowanie stałej. Robię to na dwóch stronach z treściami wielojęzycznymi, gdzie wtyczka wielojęzyczności nie uruchamia tłumaczenia interfejsu użytkownika. Gdyby to miało być rozwiązanie AJAX / JSON, nie wiedziałbym, jak pomóc.
Johannes Pille,
@JohannesPille W którym momencie / haku chcesz się przełączyć? Btw: Czy możesz przenieść to do odpowiedzi. Już warte głosowania. Dzięki.
kaiser
Robię to we wtyczce, bez żadnych haczyków. Jest to dość nieprzyjemna poprawka i nie jestem z tego aż tak dumny, ale wtedy wykonała swoją pracę. Kod wtyczki można zobaczyć w tym pastebinie . To, co robi, jest oczywiste. Witryna, z której to skopiowałem, wykorzystuje ostatnią bezpłatną wersję WPML. Fair enuff, przeniosłem go na odpowiedź.
Johannes Pille,
Adres URL pastebin wydaje się być martwy.
PapaFreud,
@JohannesPille Czy mógłbyś opublikować swój kod jako aktualizację swojego Q lub dodać pastebin, który nie wygasa?
kaiser

Odpowiedzi:

15

Zdecydowanie najlepszym (najprostszym) sposobem jest użycie filtru ustawień regionalnych (wewnątrz get_locale()).

Najpierw skonfiguruj szybką funkcję wyszukiwania innego języka do użycia w localefiltrze.

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

Zostawiłem to jako funkcję globalną, może się przydać ...? Resztę wtyczki zapakowałem do klasy.

Tworzy listę możliwych języków, z których możesz wybierać.

Wady

  • Wyszukuje wp-content/languagespliki formularza xx_xx.mo. Jeśli nie ma takiej postaci (nie wszystkie pliki .mo są), wtyczka nie będzie go odbierać!
  • Lista rozwijana zawiera listę znalezionych ustawień narodowych do wyboru, ale są one wyświetlane w formacie ustawień regionalnych „xx_xx”, a nie w sposób przyjazny dla człowieka - jakieś pomysły?
  • Czy $localerobi coś innego niż język? Jeśli tak, nadal można uzyskać takie same ustawienia regionalne, ale podać alternatywne tłumaczenia. Jest jednak znacznie bardziej bałagan ...

Kod

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
źródło
1
Upvote zrobione (lough również na temat wszystkich wbudowanych komentarzy). Nagroda jest ustawiona i zostanie Ci przyznana, gdy tylko pozwolę (pozostało 23 godziny - wskaż mi ją, jeśli zapomnę).
kaiser
2
Zaktualizowano w celu odzwierciedlenia odpowiedzi na to pytanie .
Stephen Harris,
N1ce one. Zakładka +1
Johannes Pille,
Zauważyłem, że samo włączenie 'wp-admin/includes/ms.php'powoduje wyświetlenie powiadomienia administratora o aktualizacji witryn sieciowych (gdy jesteś jedną witryną!). Może być format_code_lang()konieczne skopiowanie go w ramach funkcji niestandardowej.
Stephen Harris,
Dodałem Gist z moim czyszczeniem - nie miałem czasu go testować, ponieważ bawię się obecnie folderami wtyczek, a to oznacza, że ​​żadna inna wtyczka nie działa. Mam nadzieję, że możesz pracować z dostarczoną funkcją i być może rozwidleniem / aktualizacją. Mogę przyznać nagrodę za pół godziny, ale muszę teraz wyjść, więc wyślę ją jutro. Dzięki za całą twoją pracę - powinna być w domyślnej instalacji :)
kaiser
5

Jeśli możesz zadowolić się odświeżeniem strony, WPLANGopcją może być ponowne zdefiniowanie stałej. Robię to na dwóch stronach z treściami wielojęzycznymi, gdzie wtyczka wielojęzyczności nie uruchamia tłumaczenia interfejsu użytkownika.

Johannes Pille
źródło
Hmm .. możesz użyć ajax do zastąpienia treści lub całego tagu HTML strony po tym, po wykonaniu powyższego kodu (w tym samym żądaniu ajax), po kliknięciu przycisku lub coś w tym rodzaju.
Joshua Abenazer,
+1. Właśnie spojrzałem na twoją pastebin. Oznacza to, że twoja konfiguracja jest http://example.com/language/whatever/, prawda?
kaiser
@kaiser Tak, to konfiguracja w witrynie, z której pochodzi kod. Jeśli zależy Ci tylko na języku interfejsu użytkownika, powinno wystarczyć przekazanie ciągu zapytania do adresu URL lub ustawienie $_SESSIONzmiennej wyzwalającej przedefiniowanie WPLANGprzy następnym ładowaniu strony. Jeśli chcesz powielić to na stronie wielojęzycznej, zwróć uwagę, że jak mówi komentarz do pastebin, kod w nim działa z WPML, ostatnią darmową wersją. Nie można go replikować 1 do 1 za pomocą qTranslate, ponieważ te identyfikatory URI nie są fizyczne, ale przepisywane za pośrednictwem mod_rewritemodułu apache. Jestem pewien, że można to zmienić, ale nie będzie działać „tak jak jest”.
Johannes Pille,
Nie będę używać qTranslate ani WPML. To tak naprawdę tylko język interfejsu użytkownika. Ad $_SESSION) Mój problem polega na tym, że afaik jest dość trudny w obsłudze, a rzeczy między globalsami a tablicą mogą łatwo się pomieszać. Tak więc, jeśli spróbuję znaleźć sposób na zmianę WPLANG, to muszę znaleźć solidny sposób na przekazanie jej z jednej prośby do drugiej. Może add_query_arg/get_query_var
załatwi sprawę
Właśnie pomyślałem o tym ponownie (rozwiązanie nadal nie jest wbudowane w projekt): Czy możesz zawinąć to w jakieś ajax? Myślę, że byłby to najlepszy sposób na obejście tego. Chcę zamknąć Q i oznaczyć jako rozwiązanie :) Dzięki.
kaiser
2

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

jest to czego potrzebujesz ...

Edytuj I - po komentarzu. Po pierwsze - dziękuję wszystkim, którzy wnieśli swój wkład w torrent downvotes. (tak się dzieje, gdy nie odwiedza się wystarczająco często: -))

teraz - funkcja obsługująca przełącznik znajduje się w rdzeniu qtranslate. (zaczyna się mniej więcej od linii 80 - zależy od wybranej wersji).

Ponieważ nie możesz zajrzeć do kodu NOT OOP, a teraz nie mam już nic innego do roboty - syntezowanie zajęło 10 minut, parafrazując skompiluj ten non-OOp z jeszcze innym kodem innym niż OOP.

(przepraszam, - prymitywny stary skool tutaj)

Zakładając, że rozumiem pytanie i& Zakładając, że chcesz, aby kod był dla administratora i&, zakładając, że będziesz wiedział, jak przenieść go do interfejsu, jeśli chcesz i&, zakładając, że rozumiesz, że kod nie jest optymalny:

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

UWAGI:

1 - Zbudowano go w 10 minut. na lokalnej maszynie podczas pobytu na lotnisku. Powodem, dla którego to mówię, jest to, że jedyna dostępna instalacja Wordpress, którą mam tutaj, jest dość stara. (Myślę, że 2.9).

Oznacza to, że prawdopodobnie menu języka pojawi się pod kontekstowym div pomocy, ponieważ ostatnio wprowadzono nową strukturę div (z zakładkami) - ale nadal powinna działać. (Obiecuję, że wrócę do tego później, jeśli będę miał czas)

Gdybym miał więcej czasu (i nowy kod Wordpress tutaj), prawdopodobnie zintegrowałbym to z nowym paskiem administracyjnym z add_action( 'admin_bar_menu', 'k99_add_language_menu_2', 1000 );(już obiecałem wrócić do tego)

2 - powinieneś mieć wymienione pliki językowe w folderze „languages” w wp-content (lepiej ??) lub wp-include. jeśli chodzi o ten punkt - kod jest tylko dowodem koncepcji - i oczywiście, jeśli ktoś ma więcej czasu, menu powinno być budowane w sposób dynamiczny, a nie jak tutaj.

3 - Twój WPLANG w konfiguracji powinien być pusty. Nie jestem pewien, czy będzie działać na nowszych wersjach wp, jeśli język jest już ustawiony.

4 - jest to prosty zsyntetyzowany i sparafrazowany dowód koncepcji oparty na tym, co widzieliśmy w kodzie qtranslate (także w starej wersji) - więc większość rzeczy jest wykonywana w „szybki” sposób, niekoniecznie w „właściwy” sposób (jak dodanie JS , brak dedykowanej domeny tekstowej itp.).

EDYCJA II

dzisiaj ktoś ma szczęście! (Opóźnienie lotu )

Ponieważ szukałeś „pomysłów” na podejścia, oto kolejny znany.

Nie zmieści się we wtyczce ani w żadnym innym niewyłącznym środowisku, ale może dać ci inny kierunek, jak radzić sobie z „przeglądarkami”.

Umożliwi to zdobycie języka z GET, takim jak: <a href="index.php?lang=de">German</a>lub<a href="whatever.php?lang=ml">my Language</a>

Aby użyć, możesz utworzyć kod (nazwijmy go 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', '');
        }
    }
 }

teraz w wp-config, tuż przed stałą WPLANG, musimy dołączyć nasz kod.

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

Teraz - oczywiście lepiej byłoby dodać kilka ciasteczek do miksu, aby przechowywać języki.

EDYCJA III

Obiecałem, że wrócę do tego później - oto jak (w bardzo niepoprawny i prymitywny sposób) można go zintegrować z paskiem administratora (zamiast menu pomocy kontekstowej)

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

Po prostu zastąp tę funkcję (lub dodaj) do starego kodu (oryginalna wtyczka NON - OOP).

Tak jak powiedziałem, nie mam tutaj nowej instalacji wordpress na lokalnym, która zawiera pasek administratora - ale powinien działać.

(a potem znowu może nie działać ... ale jestem pewien, że możesz to naprawić, jeśli naprawdę chcesz - nawet myślałem, że to nie jest OOP) :-)

muszę teraz biec. mam nadzieję, że to jakoś pomaga.

EDYCJA IV - zmieniono edycję III na działającą wersję dla paska menu administratora (przynajmniej na moim wp 3.4)

ponieważ nie miałem działającej instalacji 3.4 - a teraz wróciłem i tak zrobiłem - edytowałem rozwiązanie Edit III - i działa dla mnie.

Jeśli chodzi o głosy poparcia, nie obchodzi mnie to mniej. I nie potrzebuję żadnych „nagród” (cokolwiek by to było…) To tylko ze względu na ćwiczenie, które powinieneś być w stanie przekazać autorowi qTranslate. :-) pomimo tego, że nie jest to OOP - jest to genialna wtyczka, z której można się wiele nauczyć w wielu obszarach. biorąc pod uwagę „kiedy” tego wydania wtyczki, jest to nawet niesamowite. warte nieopisanego wysiłku odczytania kodu NON OOP - nawet jeśli nie jest - OOP. I nawet jeśli nie jest poprawnie wcięte (dobry Boże!).

krembo99
źródło
3
Być może istnieje rozwiązanie ukryte w głębi tego kodu, ale jest prawie niemożliwe, aby znaleźć wszystkie wyjścia, ponieważ nie jest napisane w OOP. Jeśli wiesz, gdzie dokładnie znajduje się wykrywanie języka (elementy przeglądarki) i jak filtruje ciągi gettext, daj mi znać.
kaiser
1
@kaiser - patrz edycja I dla „rzeczy z przeglądarki”.
krembo99
1
@kaiser ... i zobacz edit II, aby uzyskać więcej „rzeczy do przeglądarki” - i edytuj III, aby włączyć „rzeczy z przeglądarki” do „przeglądarki (rzeczy)”.
krembo99
Ok, głosowałem za tym (nie głosuj tutaj, żeby wrócić tutaj), dla twojego wysiłku. Pomysł użycia ciasteczka jest fajny. W każdym razie, oto kilka uwag: Edycja II zgłosi błąd po require(). Nie możesz użyć define()tego samego ciągu dwa razy. Edycja III ma pewne problemy z językami. Wybór en_USnie zrobiłby nic (?), Ale de_DEustawiłby na English;). Podsumowując: przyznam nagrody i rozdaję je (na przykład StephenHarris) za kompletną i działającą odpowiedź. Jeśli masz coś takiego, zaktualizuj swoją odpowiedź (ciekawe podejście do plików cookie), a ja mogę dodać i wynagrodzić nagrodę.
kaiser
Nie zostawiaj mi komentarzy. Wprowadź zmiany w swojej odpowiedzi, aby każdy mógł przeczytać Twoje pomysły. Sidenote: imho kod zewnętrzny powinien być zawsze dodawany jako Plugin / MU-Plugin / Temat / DROPIN aby poruszać.
kaiser