Изменить язык, нажав кнопку

21

Цель состоит в том, чтобы предложить кнопку / выбрать раскрывающийся список или аналогичный для переключения общедоступного интерфейса 1) язык на лету.

Что я ищу

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

Заметка:

1) Речь не о публикации на разных языках.

2) Мне не нужен код, чтобы сделать реальный раскрывающийся список / кнопку / что угодно. Речь идет только о коде / системе, предоставляющей строки для пользовательского интерфейса.

Благодарность!

кайзер
источник
1
Если вы можете согласиться на обновление страницы, переопределение WPLANGконстанты может быть вариантом. Я делаю это на двух сайтах с многоязычным контентом, где плагин многоязычия не запускает перевод интерфейса. Если бы это было решение AJAX / JSON, я бы не знал, как помочь.
Йоханнес Пилле
@JohannesPille В какой момент / крюк вы переключаетесь? Кстати: не могли бы вы переместить это в ответ. Уже стоит голосовать. Спасибо.
Кайзер
Я делаю это в плагине, без зацепок. Это довольно грязное исправление, и я не всем этим горжусь, но в то время он выполнил свою работу. Вы можете увидеть код плагина в этой папке . То, что он делает, говорит само за себя. Сайт, с которого я это скопировал, использует последнюю бесплатную версию 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()это нужно будет дублировать внутри пользовательской функции.
Стивен Харрис
Я добавил Gist с моей очисткой - у меня не было времени на его тестирование, так как я сейчас возился с папками плагинов, и это означает, что никакой другой плагин не работает. Надеюсь, что вы можете работать с предоставленной сущностью и, возможно, форк / обновление. Я могу назначить награду через полчаса, но мне нужно уйти сейчас, поэтому я пришлю ее завтра. Спасибо за всю вашу работу - должна быть в любой установке по умолчанию :)
kaiser
5

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

Йоханнес Пилле
источник
Хм ... вы можете использовать ajax для замены основного текста или всего HTML-тэга страницы в этом отношении после выполнения приведенного выше кода (в том же запросе ajax), щелчка по кнопке или чего-то в этом роде.
Джошуа Абеназер
+1. Просто посмотрел на вашу пастинку. Это значит, что ваши настройки http://example.com/language/whatever/правильные?
Кайзер
@kaiser Да, это настройка на сайте, откуда приходит код. Если вы заботитесь только о языке пользовательского интерфейса, передайте строку запроса URL-адреса или задайте $_SESSIONпеременную для запуска переопределения WPLANGпри следующей загрузке страницы. Если вы захотите повторить это на многоязычном сайте, обратите внимание, что, как говорится в комментарии со вставкой, код в нем работает с WPML, последней бесплатной версией. Его нельзя реплицировать 1 к 1 с помощью qTranslate, потому что эти URI не являются физическими, а переписываются через mod_rewriteмодуль apache. Я уверен, что это можно настроить, но не будет работать "как есть".
Йоханнес Пилле
Я не буду использовать qTranslate или WPML. Это действительно только о языке пользовательского интерфейса. Ad $_SESSION) Моя проблема в том, что на самом деле они довольно сложны в обращении, и вещи между глобалами и массивом могут быть легко перепутаны. Поэтому, если я попытаюсь найти способ измениться WPLANG, мне нужно найти надежный способ передать его из одного запроса в другой. Может быть, add_query_arg/get_query_varдобьется цели ...
Кайзер
Я просто снова думал об этом (решение до сих пор не встроено в проект): не могли бы вы обернуть это в какой-нибудь ajax? Я думаю, что это был бы лучший способ обойти это. Я хочу закрыть Q и отметить его как решение :) Спасибо.
Кайзер
2

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

это то, что вам нужно ...

Редактировать я - после комментария. Первое - спасибо всем, кто внес вклад в торренты downvotes. (это то, что происходит, когда человек не посещает достаточно часто: -))

now - Функция, которая обрабатывает коммутатор, находится в 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, из-за того, что недавно была введена новая структура div (с вкладками) - но все же она должна работать. (Я обещаю вернуться к этому позже, если у меня будет время)

Если бы у меня было больше времени (и нового кода WordPress здесь), я бы, вероятно, интегрировал это в новую админ-бар с add_action( 'admin_bar_menu', 'k99_add_language_menu_2', 1000 );(я уже обещал вернуться к этому)

2 - у вас должны быть файлы перечисленных языков в папке «languages» в wp-content (лучше ??) или wp-include. Что касается этого пункта - код является только доказательством концепции - и, конечно, если у вас есть больше времени, меню должно быть построено динамически, а не как здесь.

3 - ваш WPLANG в конфиге должен быть пустым. Я не уверен, что он будет работать на более новых версиях 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 в смесь для хранения языков.

РЕДАКТИРОВАТЬ 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 на рабочую версию панели меню администратора (по крайней мере, на моем wp 3.4)

так как у меня не было рабочей установки 3.4 - и теперь я вернулся, и я возвращаюсь - я отредактировал решение Edit III - и оно работает для меня.

Про упущения мне наплевать. И мне не нужны никакие «щедрости» (какими бы они ни были ...). Только для упражнения вы, возможно, дадите его автору qTranslate. :-) Несмотря на то, что это не ООП - это гениальный плагин, у которого есть чему поучиться во многих областях. учитывая «когда» этого выпуска плагина, это даже удивительно. стоит неописуемых усилий по чтению кода без ООП - даже если это не так - ООП. И даже если это не правильно с отступом (боже мой!).

krembo99
источник
3
Может быть, есть решение, скрытое в глубине этого кода, но почти невозможно разобраться во всем, так как оно не написано в ООП. Если вы знаете, где именно находится определение языка (в браузере) и как оно фильтрует строки gettext, пожалуйста, дайте мне знать.
Кайзер
1
@kaiser - см. edit I для "материала браузера".
krembo99
1
@kaiser ... и см. edit II для более подробной информации о браузере - и edit III о том, как включить "материал браузера" в "браузер (материал)".
krembo99
Хорошо, я проголосовал за это (не понизить, чтобы вернуться сюда), за ваши усилия. Идея использования куки, хороша. В любом случае, вот некоторые замечания: Edit II выдаст ошибку после require(). Вы не можете использовать define()одну и ту же строку дважды. Edit III имеет некоторые проблемы с языками. Выбор en_USничего не сделает (?), Но de_DEустановит его на English;). Подводя итог: я присуждаю награды и выдаю их (например, Стивену Харрису) за полный и рабочий ответ. Если вы получили что-то подобное, обновите ваш ответ (интересный подход с использованием cookie), и я могу добавить и наградить вас за вознаграждение.
Кайзер
Пожалуйста, не оставляйте комментарии для меня. Внесите изменения в свой ответ, чтобы каждый мог прочитать ваши идеи. Примечание: внешний код imho всегда должен добавляться как Plugin / MU-Plugin / Theme / DropIn, чтобы сделать его подвижным.
Кайзер