2013-12-24 2 views
7

Я пытаюсь сделать следующее:Wordpress add_rewrite_tag(), add_rewrite_rule(), и POST_LINK()

Перепишите структуру URL моей установки WordPress, так что поле языка там. Например. http://www.mydomain.com/lang/

Я хочу, чтобы затем взять данные из/lang/и использовать его для отображения соответствующего содержимого. Например. если lang is 'en', я возьму пользовательские поля на английском языке и покажу тему на английском языке.

Вот то, что я до сих пор:

<?php 
function add_directory_rewrite() { 
    global $wp_rewrite; 
    add_rewrite_tag('%lang%', '(.+)'); 
    add_rewrite_rule('^/(.+)/', 'index.php?p=$matches[1]&lang=$matches[2]', 'top'); 
    add_permastruct('lang', '%lang%'); 

    } 
    add_action('init', 'add_directory_rewrite'); 
?> 

Это работает по мере получения языка, но проблема я обращенную теперь the_permalink() имеет «/% Ланг% /», где/ен/должен быть или/fr/или/de/или любым другим языком. Чтобы добавить более подробно, моя структура постоянной ссылки равна /% lang% /% category% /% postname%/и позволяет сказать, что у меня есть категория, называемая пищей, и сообщение с названием chicken, the_permalink будет генерировать http://www.mydomain.com/%lang%/food/chicken/

Любая идея, что я «Неправильно? Приветствия.

ответ

6

Вам также необходимо добавить функцию, которая займет постоянную ссылку, которая содержит ошибочный сегмент «/% lang% /», и заменит его соответствующим языком по умолчанию для сообщения. Как правило, вы можете сделать это либо с помощью фильтра 'pre_post_link', либо фильтра 'post_link'. Если вы используете первое, вы создадите постоянную ссылку с нуля (полностью настраиваемые URL-адреса, которые не используют ничего, что может предложить основной WP). Если последний используется, вы можете отфильтровать постоянную ссылку после WP сделал это волшебство, но прежде, чем он будет использоваться на сайте. Вот пример:

function lou_rewrite_lang_in_permalink($permalink, $post, $leavename) { 
    // find the default post language via a function you have created to 
    // determine the default language url. this could be based on the current 
    // language the user has selected on the frontend, or based on the current 
    // url, or based on the post itself. it is up to you 
    $default_post_language = get_default_post_lang($post); 

    // once you have the default language, it is a simple search and replace 
    return str_replace('%lang%', $lang, $permalink); 
} 
add_filter('post_link', 'lou_rewrite_lang_in_permalink', 11, 3); 

Вы не упомянули об этом, поэтому я это сделаю. С вашей оригинальной сольной функцией, вы, gunna, нелегко, если она одинока. Причина в том, что, хотя вы сказали переписывать, что новый сегмент URL существует, вы не сказали WordPress ожидать его как параметр url. Таким образом, несмотря на то, что у вас есть модный код, чтобы переписать URL-адрес и рассказать WordPress о причудливом параметре lang, WordPress не знает, что он должен его искать, и таким образом игнорирует его. Вам нужно добавить что-то вроде этого, чтобы исправить это:

function lou_add_lang_query_var($vars) { 
    // tell WP to expect the lang query_var, which you can then later use 
    $vars[] = 'lang'; 

    // return the new list of query vars, which includes our lang param 
    return array_unique($vars); 
} 
add_filter('query_vars', 'lou_add_lang_query_var', 10, 1); 

Это скажет WP() класс, он должен принять 'lang' вместо того, чтобы просто пропуская над ним. Позже вы можете сделать что-то вроде этого, чтобы выяснить, что текущая страница передается как это язык:

function lou_somefunction() { 
    // do stuff 
    ... 

    // access the $wp object 
    global $wp; 

    // determine the language from the query_vars of the current page 
    $lang = $wp->query_var['lang']; 

    // do other stuff with $lang 
    ... 
} 

Надеется, что это помогает.

EDIT

Прежде всего я хочу сказать, что это абсолютная пародия, что язык URLs не изначально поддерживается WordPress. Я честно никогда не должен был сделать это, но большинство моих клиентов не являются международными компаниями с международными потребностями. Я буду отправлять что-то в WordPress в виде кода, чтобы решить эту проблему в более поздней версии, но на данный момент вам понадобится плагин, подобный тому, который я создал ниже.

Итак, я сделал много исследований, чтобы это произошло. После короткой беседы с вопрошающим, если выяснилось, что мое решение было неполным. Естественно, я начал рыть. Похоже, что это должно быть иначе посредственная задача, оказалась ОЧЕНЬ-не-посредственной задачей.В короткой версии WordPress просто не хочет, чтобы вы вставляли дополнительные части URL-адреса, в середине или в начале URL-адреса, на каждом URL-адресе. Вы можете легко сделать это с помощью почтовых URL ТОЛЬКО с приведенным выше кодом, но что-нибудь еще (страницы, вложения, страницы авторов и т. Д.) Вы должны сделать что-то особенное. Вы также можете добавлять детали в конец URL-адреса (конечные точки), но даже это сложно.

Я работал с переписчиком WordPress в прошлом и настоящем, и у меня есть то, что считается экспертным знанием по этой теме. Несмотря на это, мне все же потребовалось 4-5 часов, чтобы написать что-то, что позволит вам добавить индикатор языка ко всем URL-адресам, который затем может быть использован для определения того, на каком языке должна отображаться страница, независимо от типа страницы. Существует один улов, который я считаю приемлемым. Вы должны знать и точно указать, какие языковые префиксы вы хотите поддерживать. Я не предвижу это как проблему для тех, кто будет использовать это, но, тем не менее, это ограничение, просто из-за того, как работает механизм перезаписи.

Наконец, вот плагин, который вы можете использовать для достижения этого. Я работаю на barebone WP install, с WooTheme в качестве темы. Если у вас установлены другие сторонние плагины, есть вероятность, что это не сработает для всех их URL-адресов, в зависимости от того, как они добавили свои правила перезаписи. В краткосрочной перспективе я, вероятно, буду преобразовывать это в плагин для WP и получать его на Wordpress.org, но это, по крайней мере, на несколько дней. Вот рабочий прототип кода в форме плагина. Создайте новый каталог в своей папке плагинов (что-то вроде/wp-content/plugins/lou-lang), а затем вставьте этот код в php-файл внутри этой папки (что-то вроде/wp-content/plugins/lou-lang/lou -lang.php). Затем активируйте плагин через панель управления admin, которая будет помечена как «URL-адреса языка Loushou».

КОД:

<?php (__FILE__ == $_SERVER['SCRIPT_FILENAME']) ? die(header('Location: /')) : null; 
/** 
* Plugin Name: Loushou Language URLs 
* Plugin URI: http://quadshot.com/ 
* Description: Adding the ability to have language support in your frontend urls. 
* Version:  0.1-beta 
* Author:  Loushou 
* Author URI: http://quadshot.com/ 
*/ 

class lou_rewrite_takeover { 
    protected static $add_rules = array(); 

    public static function pre_init() { 
    // debug 
    add_action('admin_footer-options-permalink.php', array(__CLASS__, 'qsart_rewrite_debug')); 

    // add rw tag 
    add_action('init', array(__CLASS__, 'add_directory_rewrite')); 

    // rw rule adds 
    add_filter(is_admin() ? 'setup_theme' : 'do_parse_request', array(__CLASS__, 'do_parse_request'), 0); 
    add_filter('post_rewrite_rules', array(__CLASS__, 'post_rewrite_rules')); 
    add_filter('date_rewrite_rules', array(__CLASS__, 'date_rewrite_rules')); 
    add_filter('root_rewrite_rules', array(__CLASS__, 'root_rewrite_rules')); 
    add_filter('comments_rewrite_rules', array(__CLASS__, 'comments_rewrite_rules')); 
    add_filter('search_rewrite_rules', array(__CLASS__, 'search_rewrite_rules')); 
    add_filter('author_rewrite_rules', array(__CLASS__, 'author_rewrite_rules')); 
    add_filter('page_rewrite_rules', array(__CLASS__, 'page_rewrite_rules')); 
    add_filter('rewrite_rules_array', array(__CLASS__, 'final_rules_correction'), PHP_INT_MAX, 1); 

    // query vars 
    add_filter('query_vars', array(__CLASS__, 'add_lang_query_var'), 10, 1); 
    add_filter('request', array(__CLASS__, 'default_language'), 9); 

    // fix permalinks 
    $link_filters_needing_rewrite = array(
     'post_link', 
     'post_type_link', 
     'page_link', 
     'attachment_link', 
     'search_link', 
     'post_type_archive_link', 
     'year_link', 
     'month_link', 
     'day_link', 
     'feed_link', 
     'author_link', 
     'term_link', 
     'category_feed_link', 
     'term_feed_link', 
     'taxonomy_feed_link', 
     'author_feed_link', 
     'search_feed_link', 
     'post_type_archive_feed_link', 
    ); 
    add_filter('pre_post_link', array(__CLASS__, 'change_permalink_structure'), 10, 3); 
    foreach ($link_filters_needing_rewrite as $link_filter) 
     add_filter($link_filter, array(__CLASS__, 'rewrite_lang_in_permalink'), 11, 3); 
    } 

    public static function do_parse_request($cur) { 
    self::get_page_permastruct(); 
    self::get_author_permastruct(); 
    self::correct_extras(); 
    return $cur; 
    } 

    public static function get_supported_langs() { 
    return apply_filters('lou-get-supported-languages', array(
     'en', 
    )); 
    } 

    public static function add_directory_rewrite() { 
    global $wp_rewrite; 
    $supported_languages = self::get_supported_langs(); 
    add_rewrite_tag('%lang%', '('.implode('|', $supported_languages).')'); 
    } 

    public static function unleadingslashit($str) { 
    return ltrim($str, '/'); 
    } 

    public static function final_rules_correction($rules) { 
    global $wp_rewrite; 

    $new_rules = array(); 
    $supported_languages = self::get_supported_langs(); 
    $find = implode('|', $supported_languages); 
    $find_find = '#(?<!\()('.preg_quote($find, '#').')#'; 
    $preg_node = str_replace('%%%', '(\d+)', preg_quote($wp_rewrite->preg_index('%%%'), '#')); 

    foreach ($rules as $k => $v) { 
     if (preg_match($find_find, $k)) { 
     $nk = preg_replace($find_find, '('.$find.')', $k); 
     $parts = explode('?', $v); 
     $index = array_shift($parts); 
     $pv = implode('?', $parts); 
     $pv = preg_replace_callback('#'.$preg_node.'#', function ($matches) use ($wp_rewrite) { 
      return $wp_rewrite->preg_index($matches[1]+1); 
     }, $pv); 
     $nv = $index.'?lang='.$wp_rewrite->preg_index(1).(!empty($pv) ? '&'.$pv : ''); 
     $new_rules[$nk] = $nv; 
     } else { 
     $new_rules[$k] = $v; 
     } 
    } 

    return $new_rules; 
    } 

    public static function change_permalink_structure($struct) { 
    $struct = self::unleadingslashit($struct); 
    $struct = preg_replace('#^%lang%/?#', '', $struct); 
    return '/%lang%/'.$struct; 
    } 

    public static function extras_rewrite_rules($rules, $struct) { 
    global $wp_rewrite; 

    if (is_array($struct)) { 
     if (count($struct) == 2) 
     $new_rules = $wp_rewrite->generate_rewrite_rules(self::change_permalink_structure($struct[0]), $struct[1]); 
     else 
     $new_rules = $wp_rewrite->generate_rewrite_rules(self::change_permalink_structure($struct['struct']), $struct['ep_mask'], $struct['paged'], $struct['feed'], $struct['forcomments'], $struct['walk_dirs'], $struct['endpoints']); 
    } else { 
     $new_rules = $wp_rewrite->generate_rewrite_rules(self::change_permalink_structure($struct)); 
    } 

    return $new_rules + $rules; 
    } 

    public static function post_rewrite_rules($rules) { 
    global $wp_rewrite; 

    // hack to add code for extras type urls (usually created by other plugins) 
    $func = array(__CLASS__, 'extras_rewrite_rules'); 
    foreach ($wp_rewrite->extra_permastructs as $type => $struct) { 
     $filter = ($type == 'post_tag' ? 'tag' : $type).'_rewrite_rules'; 
     add_filter($filter, function ($rules) use ($struct, $func) { return call_user_func_array($func, array($rules, $struct)); }); 
    } 

    return $wp_rewrite->generate_rewrite_rules(self::change_permalink_structure($wp_rewrite->permalink_structure), EP_PERMALINK) + $rules; 
    } 

    public static function date_rewrite_rules($rules) { 
    global $wp_rewrite; 
    return $wp_rewrite->generate_rewrite_rules(self::change_permalink_structure($wp_rewrite->get_date_permastruct()), EP_DATE) + $rules; 
    } 

    public static function root_rewrite_rules($rules) { 
    global $wp_rewrite; 
    return $wp_rewrite->generate_rewrite_rules(self::change_permalink_structure($wp_rewrite->get_date_permastruct()), EP_DATE) + $rules; 
    } 

    public static function comments_rewrite_rules($rules) { 
    global $wp_rewrite; 
    return $wp_rewrite->generate_rewrite_rules(self::change_permalink_structure($wp_rewrite->root . $wp_rewrite->comments_base), EP_COMMENTS, false, true, true, false) + $rules; 
    } 

    public static function search_rewrite_rules($rules) { 
    global $wp_rewrite; 
    return $wp_rewrite->generate_rewrite_rules(self::change_permalink_structure($wp_rewrite->get_search_permastruct()), EP_SEARCH) + $rules; 
    } 

    public static function author_rewrite_rules($rules) { 
    global $wp_rewrite; 
    return $wp_rewrite->generate_rewrite_rules(self::change_permalink_structure($wp_rewrite->get_author_permastruct()), EP_AUTHORS) + $rules; 
    } 

    public static function page_rewrite_rules($rules) { 
    global $wp_rewrite; 
    $page_structure = self::get_page_permastruct(); 
    return $wp_rewrite->generate_rewrite_rules($page_structure, EP_PAGES, true, true, false, false) + $rules; 
    } 

    protected static function get_page_permastruct() { 
    global $wp_rewrite; 

    if (empty($wp_rewrite->permalink_structure)) { 
     $wp_rewrite->page_structure = ''; 
     return false; 
    } 

    $wp_rewrite->page_structure = self::change_permalink_structure($wp_rewrite->root . '%pagename%'); 

    return $wp_rewrite->page_structure; 
    } 

    protected static function get_author_permastruct() { 
    global $wp_rewrite; 

    if (empty($wp_rewrite->permalink_structure)) { 
     $wp_rewrite->author_structure = ''; 
     return false; 
    } 

    $wp_rewrite->author_structure = self::change_permalink_structure($wp_rewrite->front . $wp_rewrite->author_base . '/%author%'); 

    return $wp_rewrite->author_structure; 
    } 

    protected static function correct_extras() { 
    global $wp_rewrite; 

    foreach ($wp_rewrite->extra_permastructs as $k => $v) 
     $wp_rewrite->extra_permastructs[$k]['struct'] = self::change_permalink_structure($v['struct']); 
    } 

    public static function get_default_post_lang($post) { 
    return ($lang = get_query_var('lang')) ? $lang : 'en'; 
    } 

    public static function rewrite_lang_in_permalink($permalink, $post=0, $leavename=false) { 
    // find the default post language via a function you have created to 
    // determine the default language url. this could be based on the current 
    // language the user has selected on the frontend, or based on the current 
    // url, or based on the post itself. it is up to you 
    $lang = self::get_default_post_lang($post); 

    // once you have the default language, it is a simple search and replace 
    return str_replace('%lang%', $lang, $permalink); 
    } 

    public static function add_lang_query_var($vars) { 
    // tell WP to expect the lang query_var, which you can then later use 
    $vars[] = 'lang'; 

    // return the new list of query vars, which includes our lang param 
    return array_unique($vars); 
    } 

    public static function default_language($vars) { 
    if (array_diff(array_keys($vars), array('preview', 'page', 'paged', 'cpage'))) 
     $vars['lang'] = !empty($vars['lang']) ? $vars['lang'] : 'en'; 
    return $vars; 
    } 

    public static function qsart_rewrite_debug() { 
    if (isset($_COOKIE['rwdebug']) && $_COOKIE['rwdebug'] == 1) { 
     global $wp_rewrite; 
     echo '<pre style="background-color:#ffffff; font-size:10px;">'; 
     print_r($wp_rewrite->rules); 
     echo '</pre>'; 
    } 
    } 
} 

if (defined('ABSPATH') && function_exists('add_action')) { 
    lou_rewrite_takeover::pre_init(); 
} 

По умолчанию, только код языка поддерживает этот плагин 'en'. Очевидно, вам нужно больше, чем просто. Таким образом, как только вы установили плагин, вы можете добавить код в ваш файл <theme>/functions.php, который выглядит примерно так, чтобы добавить остатки.

function more_languages($list) { 
    $my_languages = array(
    'de', 'zh', 'bg', 'fr' 
); 
    return array_unique($list + $my_languages); 
} 
add_filter('lou-get-supported-languages', 'more_languages', 10, 1); 

После того как вы как установлен плагин и определили свои собственные языки, то у вас есть один последний шаг. Вы должны сохранить свои постоянные ссылки. Чтобы сделать это от администратора, перейдите по ссылке: Настройки -> Постоянная ссылка -> Сохранить изменения (кнопка). После всего этого вы должны быть добрыми!

Надеюсь, это поможет кому-то, и, надеюсь, я смогу заблокировать некоторое время, чтобы получить это на wp.org.

+0

Это сработало спасибо! Там проблема - страницы не загружаются, например./en/upload/- это страница, но она идет на index.php. Код ' Функция lou_rewrite_lang_in_permalink ($ permalink, $ post, $ leavename) { global $ wp; $ lang = get_query_var ('lang'); if (! (Strlen ($ lang)> 0)) {$ lang = 'en'; } return str_replace ('% lang%', $ lang, $ permalink); } функция lou_add_lang_query_var ($ вары) {[...]} функция add_directory_rewrite() { глобальной $ wp_rewrite; add_rewrite_tag ('% lang%', '(. +?)', 'Lang ='); add_rewrite_rule ('([\ w] {2}) /?', 'Index.php? Lang = $ matches [1] & p = $ matches [2]', 'bottom'); } ' – salemmarafi

+0

alrighty. этого должно быть достаточно для создания тестового примера и выяснить, где проблема. – loushou

+0

Извините, я все еще привык к переполнению стека, надеюсь, что это ясно? – salemmarafi

2

Я наткнулся на это сообщение, ища решение поставить языковой тег перед URL-адресом. Хотя решение wp_rewrite довольно много, оно вроде как не работает для моей цели (например, не имеет языкового тега перед языком по умолчанию и т. Д.).

Так что я присмотрелся на qTranslate-плагина и после того, как я в то время как я понял, что он использует очень простое и элегантное решение:

В основном это делает две вещи:

  1. (Очевидно). Он изменяет все созданные Wordpress ссылки (например, post_link, post_type_link, page_link и т. Д.), Чтобы включить правильный языковой тег в URL.

  2. Вместо того, чтобы манипулировать сложные правила перезаписи, чтобы WordPress принимать и правильно обрабатывать тег языка, он просто перехватывает в «plugins_loaded» (это прямо перед тем Wordpress пытается разобрать запрос) и манипулирует $_SERVER['REQUEST_URI'] вычищая языковой тег. Итак, если вы, например, звонок www.example.com/ru/myurlpath Wordpress только «видит» www.example.com/myurlpath. $_SERVER['REQUEST_URI'] = "/en/myurlpath" перед манипуляцией. $_SERVER['REQUEST_URI'] = "/myurlpath" после манипуляции.

Таким образом, ваша единственная «задачка» - очистить любые URL-адреса до того, как Wordpress разобрал их.

2

Вопрос старый, но .. Я работал над легким решением для многоязычного сайта, и я столкнулся с той же проблемой. Нет простого способа сделать это со встроенными функциями WordPress. Однако (как упомянуто пользователем1254824) есть очень простой трюк для его достижения.

Вы можете перехватить глобальный var $_SERVER['REQUEST_URI'], извлечь/lang/part и удалить его перед разбором WordPress. WordPress будет служить вам на обычной странице, но теперь у вас есть свой параметр lang в var.

function localization_uri_process() { 

    global $lang; // then you can access $lang value in your theme's files 

    if(preg_match("%\A/([a-z]{2})/%", $_SERVER['REQUEST_URI'], $matches)){ 
    $lang = $matches[1]; 
    $_SERVER['REQUEST_URI'] = preg_replace("%\A/[a-z]{2}/%", '/', $_SERVER['REQUEST_URI']); 
    } 
    else 
    $lang = 'en'; // your default language 
} 
add_action('plugins_loaded', 'localization_uri_process'); 

Затем вы также можете использовать фильтры для автоматической перезаписи всех ваших ссылок.

Смежные вопросы