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 () имеет «/% lang% /», где / en / должно быть или / fr / или / de / или на любом языке. Чтобы добавить более подробно, моя структура постоянной ссылки равна /% lang% /% category% /% postname% / и позволяет сказать, что у меня есть категория, называемая пищей, и сообщение с курицей заголовка, the_permalink будет генерировать http://www.mydomain.com /% Ланг% / еда / курица /

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

Вам также необходимо добавить функцию, которая займет постоянную ссылку, которая содержит ошибочный сегмент «/% lang% /», и заменит его соответствующим языком по умолчанию для сообщения. Обычно вы можете сделать это либо с 'pre_post_link' фильтра '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 ... } 

Надеюсь это поможет.

РЕДАКТИРОВАТЬ

Сначала я хочу сказать, что это абсолютная пародия на то, что языковые ссылки не поддерживаются 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.

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

Поэтому я более подробно рассмотрел плагин qTranslate и после того, как понял, что он использует очень простое и элегантное решение:

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

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

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

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

Вопрос старый, но .. Я работал над легким решением для многоязычного сайта, и я столкнулся с той же проблемой. Нет простого способа сделать это со встроенными функциями 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/([az]{2})/%", $_SERVER['REQUEST_URI'], $matches) ){ $lang = $matches[1]; $_SERVER['REQUEST_URI'] = preg_replace("%\A/[az]{2}/%", '/', $_SERVER['REQUEST_URI'] ); } else $lang = 'en'; // your default language } add_action( 'plugins_loaded', 'localization_uri_process' ); 

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