Змініть мову, натиснувши кнопку


21

Мета - запропонувати кнопку / вибір випадаючого меню або подібну для перемикання мови публічного інтерфейсу 1) .

Що я шукаю

  • Плагін або код теми ...
  • ... або Ідеї
  • Використовуючи обхід із load_textdomain()програмою, було б вдячно залишити переклад у файли .po / .mo
  • Ідеї ​​про те, як проаналізувати рядки в інтерфейсі (наприклад, ajax / plain php / ini, json, xml-файли), не покладаючись на якусь функцію textdomain

Примітка:

1) Не йдеться про публікацію різними мовами.

2) Мені не потрібен код, щоб зробити фактичне спадне меню / кнопку / все, що завгодно. Йдеться лише про код / ​​систему, що доставляє рядки для інтерфейсу користувача.

Спасибі!


1
Якщо ви можете влаштуватись на оновлення сторінки, переозначення WPLANGконстанти може бути варіантом. Я роблю це на двох сайтах з багатомовним вмістом, де плагін багатомовності не може запустити трансляцію інтерфейсу. Якщо це повинно бути рішенням AJAX / JSON, я не знаю, як допомогти.
Йоганнес Піл

@JohannesPille У який момент / гачок потрібно переключитися? Btw: Чи можете ви перенести це на відповідь. Вже варто голосувати. Спасибі.
кайзер

Я роблю це в плагіні, без гачків. Це досить брудне виправлення, і я не все так пишаюсь цим, але в цей час це було зроблено. Код плагіна можна побачити на цій пасті . Те, що вона робить, є самоосмислювальним. Сайт, з якого я скопіював це, використовує останню безкоштовну версію WPML. Справедливий енюфф, перемістив його на відповідь.
Йоганнес Піл

URL-адреса пастина, здається, мертва.
PapaFreud

@JohannesPille Чи ви не хочете опублікувати свій код як оновлення до свого Q або додати пастебін, який не закінчується?
кайзер

Відповіді:


15

На сьогодні найкращим (найпростішим) способом є використання локального фільтра (всередині get_locale()).

Спочатку встановіть швидку функцію пошуку іншої мови для використання у localeфільтрі.

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

Я залишив це як глобальну функцію, може бути зручно ...? Решту плагіна я загорнув всередину класу.

Він створює спадне меню можливих мов, з яких ви можете вибрати.

Недоліки

  • Пошук wp-content/languagesфайлів форми xx_xx.mo. Якщо він не такої форми (не всі .mo файли є), плагін не буде зніматися на ньому!
  • У спадному списку подається список знайдених локалів на вибір, але вони відображаються у форматі "xx_xx" локалів, а не дружньому для людини способі - будь-які ідеї ??
  • Чи $localeробить щось, крім мови? Якщо так, то все-таки можна отримати той самий локал, але надайте альтернативні переклади. Хоча це набагато сильніше ...

Кодекс

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
Upvote зроблено (сміється і над усіма вбудованими коментарями). Баунті встановлений і буде присуджений вам якнайшвидше, як мені дозволено (23 години зліва - вкажіть мені на це, якщо я забуду).
кайзер

2
Оновлено, щоб відобразити відповідь на це питання .
Стівен Харріс

N1ce один. Закладка. +1
Йоганнес Піл

Я помітив, що лише включення 'wp-admin/includes/ms.php'запускає повідомлення адміністратора для оновлення ваших мережевих сайтів (коли ви один сайт!). Можливо, format_code_lang()потрібно буде дублювати всередині спеціальної функції.
Стівен Харріс

Я додав історію з моїм очищенням - не мав часу тестувати її, оскільки я зараз возиюся з папками плагінів, і це означає, що жоден інший плагін не працює. Сподіваюся, ви можете працювати з наданим суттю і, можливо, вилкою / оновленням. Я можу нагородити нагороду за півгодини, але зараз треба піти, тому я надішлю її завтра. Дякую за всю вашу роботу - має бути в будь-якій установці за замовчуванням :)
kaiser

5

Якщо ви можете влаштуватись на оновлення сторінки, переозначення WPLANGконстанти може бути варіантом. Я роблю це на двох сайтах з багатомовним вмістом, де плагін багатомовності не може запустити трансляцію інтерфейсу.


Хм .. Ви можете використовувати ajax для заміни корпусу або цілого HTML-тегу сторінки для цього питання, виконавши вищевказаний код (у тому самому запиті на ajax), натиснути кнопку або щось подібне.
Джошуа Абеназер

+1. Просто подивився на свій пастебін. Це означає, що ваша установка є http://example.com/language/whatever/, правда?
кайзер

@kaiser Yup, це налаштування на сайті, з якого походить код. Якщо ви переймаєтесь лише мовою інтерфейсу користувача, потрібно виконати рядок запиту URL-адреси або встановити $_SESSIONзмінну, щоб викликати переосмислення WPLANGнаступного завантаження сторінки. Якщо ви хочете скопіювати це на багатомовному сайті, зауважте, що, як йдеться в коментарі до пастіна, код у ньому працює з WPML, останньою безкоштовною версією. Його не можна повторити 1 на 1 за допомогою qTranslate, тому що ці URI не є фізичними, а переписані через mod_rewriteмодуль apache. Я впевнений, що це можна відрегулювати, але не буде працювати так, як є.
Йоганнес Піл

Я не буду використовувати qTranslate або WPML. Це дійсно лише про мову інтерфейсу. Оголошення $_SESSION) Моя проблема полягає в тому, що в afaik вони досить важкі в обробці, а речі між глобальними мережами та масивом можна легко перемішати. Отже, якщо я б спробував знайти спосіб змінити WPLANG, тоді мені потрібно знайти надійний спосіб передати його від одного запиту до іншого. Можливо add_query_arg/get_query_var, зробить трюк ...
кайзер

Я лише знову замислювався над цим питанням (рішення все ще не вбудоване в проект): Не могли б ви загорнути це в якийсь аякс? Я думаю, що це був би найкращий спосіб обійти це. Я хочу закрити Q і позначити його як рішення :) Дякую.
кайзер

2

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

це те, що вам потрібно ...

Редагувати I - після коментаря. Перший - дякую всім, хто сприяв поточному потоку. (це відбувається, коли людина не відвідує досить часто: -))

тепер - Функція, яка обробляє комутатор, знаходиться в qtranslate-core. (Починається з 80 або більше рядка - залежить від потрібної версії.)

Оскільки ви не можете заглянути в код NOT OOP, і мені зараз нічого більше не потрібно - мені знадобилося 10 хвилин, щоб синтезувати, перефразовувати компіляцію, що не є OOp, і ще одним не-OOP кодом для вас.

(вибачте - тут примітивний старий скол)

Якщо припустити, що я зрозумів питання && Припустимо, що ви хочете, щоб цей код був для адміністратора &&, припускаючи, що ви знаєте, як перенести його до переднього кінця, якщо ви хочете &&, якщо ви розумієте, що код не є оптимальним:

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

ЗАМОВЛЕННЯ:

1 - Це було побудовано за 10 хв. на місцевій машині, перебуваючи в аеропорту. Причина, чому я говорю це, полягає в тому, що єдина доступна інсталяція Wordpress, яка у мене тут, є досить старою. (2.9 я думаю).

Це означає, що, ймовірно, меню мови з’явиться під контекстним довідником через те, що нещодавно була введена нова структура div (з вкладками) - але все-таки вона повинна працювати. (Обіцяю повернутися до цього пізніше, якщо встигну)

Якби у мене було більше часу (і тут з'явився новий код wordpress), я б, мабуть, інтегрував це в нову панель адміністрування add_action( 'admin_bar_menu', 'k99_add_language_menu_2', 1000 );(я вже пообіцяв повернутися до цього)

2 - ви повинні мати перелічені файли мов всередині папки "languages" у wp-контенті (краще ??) або wp-include. щодо цього моменту - код є лише доказом концепції - і, звичайно, якщо у вас є більше часу, меню має будуватися динамічно, а не так, як це робиться тут.

3 - ваш WPLANG у config повинен бути порожнім. Я не впевнений, що він буде працювати над новішими версіями wp, якщо мова вже встановлена.

4 - це простий синтезований і перефразований доказ концепції, побудованої на тому, що було помічено в коді qtranslate (також стара версія) - тому більшість речей робиться "швидким" способом, не обов'язково "правильним" способом (як додавання JS , немає виділеного текстового домену тощо.).

РЕДАКТ II

комусь пощастило сьогодні! (Затримка польоту)

Оскільки ви шукали «ідеї» для підходів, ось ще одна відома.

Він не впишеться у плагін чи фактично будь-яке інше неексклюзивне середовище, але це може дати вам інший напрямок щодо того, як поводитися з "матеріалами браузера".

Це дозволить отримати мову за допомогою GET типу: <a href="index.php?lang=de">German</a>або<a href="whatever.php?lang=ml">my Language</a>

Для використання можна створити код (назвемо його 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', '');
        }
    }
 }

тепер, у wp-config, безпосередньо перед константою WPLANG, нам потрібно включити наш код.

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

Тепер - очевидно, було б краще додати трохи файлів cookie до суміші, щоб зберігати мови.

EDIT III

Я пообіцяв повернутися до цього пізніше - ось як (дуже не правильним і примітивним способом) він міг бути інтегрований всередині адмін-панелі (замість контекстного довідкового меню)

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

Просто замініть цю функцію (або додайте) на старий код (оригінальний неплагін NON - OOP).

Як я вже сказав, у мене немає нової установки WordPress на локальній, яка має адмін-бар - але вона повинна працювати.

(і знову ж таки, це може не спрацювати ... але я впевнений, що ви могли б це виправити, якщо дуже хочете - навіть подумали, що це не ООП) :-)

зараз треба бігти. сподіваюся, що це якось допомагає.

EDIT IV - змінив редагування III на робочу версію для панелі меню адміністратора (принаймні на моїй версії 3.4)

так як у мене не було робочої установки 3.4 - а тепер я повернувся і це роблю - я відредагував рішення Edit III - і це працює для мене.

Про анотації я міг би не менше піклуватися. І мені не потрібні будь-які «щедроти» (як би там не було ..) Це було просто заради вправи, яку ви, можливо, дасте автору qTranslate. :-) незважаючи на те, що це не OOP - це геніальний плагін, з якого можна багато чому навчитися у багатьох областях. враховуючи "коли" цього випуску плагінів, це навіть дивовижно. Варто невимовно намагатися прочитати код NON OOP - навіть якщо це не так - OOP. І навіть якщо він неправильно відведений (добрий бог!).


3
Можливо, є рішення, поховане в глибині цього коду, але майже неможливо розібратися з усіма способами, оскільки це не написано в OOP. Якщо ви знаєте, де саме знаходиться система виявлення мови (речі браузера) та як вона фільтрує рядки gettext, будь ласка, дайте мені знати.
кайзер

1
@kaiser - див. редагування I для "речей із браузера".
krembo99

1
@kaiser ..і перегляньте редагування II, щоб дізнатися більше про "браузерні речі" - і редагувати III, як включити "браузерні речі" всередині "браузера (речі)".
krembo99

Гаразд, я підтримав це (а не зворотне повернення тут) для ваших зусиль. Ідея, що використовує печиво, приємна. У будь-якому випадку, ось деякі примітки: Edit II видасть помилку після require(). Ви не можете використовувати один і define()той же рядок двічі. У редакції III є деякі проблеми з мовами. Вибір en_USнічого не зробив би (?), Але de_DEвстановив би це English;). Підводячи підсумок: я нагороджую щедростями і віддаю їх (наприклад, СтівенХаррісу) за повну і робочу відповідь. Якщо у вас є щось подібне, будь ласка, оновіть свою відповідь (цікавий підхід до файлів cookie), і я можу додати вам нагороду і нагородити її.
кайзер

Будь ласка, не залишайте для мене коментарів. Внесіть зміни до своєї відповіді, щоб кожен міг прочитати ваші ідеї. Сторінка: зовнішній код imho завжди слід додавати як плагін / MU-плагін / тему / DropIn, щоб зробити його рухомим.
кайзер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.