根据URL动态重定向页面?

时间:2017-04-10 作者:Victor Marchuk

我正在为我的网站制作一个翻译系统,我在URL重写方面遇到了问题。每个页面都被翻译成多种语言,并且每种语言应有不同的URL,例如:

/en/best-restaurants-in-tokyo

/it/migliori-ristoranti-a-tokyo

/fr/meilleurs-restaurants-à-tokyo
等等。

所有这些链接都应该打开同一个帖子。所有与翻译相关的信息(包括slug)都存储在一个单独的表中。根据所选语言更改帖子的内容是微不足道的,但我无法想出有效的URL重写方法。

理想情况下,我希望有这样的代码:

$languageShortNames = join(\'|\', $languageShortNames);
add_rewrite_rule(\'(\'.$languageShortNames.\')/(.*)/?\', \'index.php?p=4015&language=$matches[1]\', \'top\');
但不是p 作为一个集合数,它应该由某个回调函数动态确定。

我偶然发现的一个有效解决方案是add_rewrite_rule 在每个语言的每个现有帖子的循环中。问题是,我的网站有数千篇帖子,所以我认为性能会非常糟糕。如果我可以简单地通过在翻译表中搜索带有slug的post ID来选择要在回调中呈现的post ID,那就更有意义了。

2 个回复
SO网友:jgraup

假设你坚持add_rewrite_rule(), 如果语言和标题设置为/en/ 发布后,您可以将搜索简化为WP_Meta_Query() 对于/:lang/:title/ 然后把翻译后帖子的实际ID拉到那里。

的翻译/en/best-restaurants-in-tokyo:

  • "/it/migliori-ristoranti-a-tokyo" => 4016
  • "/fr/meilleurs-restaurants-à-tokyo" => 4017

SO网友:Jess Mann

有几种方法可以做到这一点。我将建议以下方法:

使用add\\u rewrite\\u tag来标识语言,添加一个pre\\u get\\u posts操作来根据标签提取翻译内容,使用全局变量将主帖子更改为上面标识的帖子

The Code

我尚未对其进行测试,但以下代码应大致满足您的需要:

// Create translation endpoint
// This changes the url, by adding a few variables
function translation_endpoint()
{
        // Add variables to populate from the url
        // match any two-digit lowercase letter combo
        add_rewrite_tag(\'%tr_language%\', \'([a-z]{2})\' );
        // match any unicode alphanumeric. See: http://php.net/manual/en/regexp.reference.unicode.php
        add_rewrite_tag(\'%tr_title%\', \'([\\pL_-]+)\' );

        // Add the rewrite rule. This sets the "tr_language" and "tr_title" variables 
        add_rewrite_rule(\'^([a-z]{2})/([^/]+)/?\', \'index.php?tr_language=$matches[1]&tr_title=$matches[2]\', \'top\');
}
// Hook into init, so we modify the url early on
add_action( \'init\', \'translation_endpoint\' );

// This checks if our variables are set, and changes our query appropriately
function translation_redirect()
{
        global $wp_query, $wpdb;

        // If not the main query, don\'t change anything.
        if ( !$wp_query->is_main_query() )
                return;

        // Get our variables
        $language = $wp_query->get(\'tr_language\');
        $title = $wp_query->get(\'tr_title\');

        // If tr_language is NOT set, then continue on without changing anything
        if (!$language)
                return;

        // Grab the post id
        // wpdb->prepare is important when working with untrusted data
        $select = $wpdb->prepare(\'SELECT post_id FROM my_custom_table WHERE language = %s AND title = %s LIMIT 1\', $language, $title);
        // Grab just one result as an obj
        $result = $wpdb->get_row($select);

        // Can\'t find anything. So, return the default post.
        if (!$result)
                return;

        // Set the new post id
        $query->set(\'page_id\',$result->post_id);
}
// Hook into pre_get_posts, so we modify the query before the post data is retrieved
add_action( \'pre_get_posts\', \'translation_redirect\' );

REGEX

最后一点注意:尽量使您的正则表达式尽可能具体。从字符串的开头用胡萝卜(^)匹配,并且只匹配您要查找的内容。代码中的(*)将匹配所有内容,包括斜杠。您的查询可能适用于大多数情况,但它也符合以下条件:

示例。com/my\\u new\\u插头in/events/January/2017

--(语言=>“in”,标题=>“events/Jan…”

示例。通信/存档es/123

--(语言=>“es”,标题=>“123”)

示例。通信/电话en/

--(语言=>“en”,标题=>“”)

我给出了一些以上更具体查询的示例。

  • ^ 匹配字符串的开头[\\pL] 匹配unicode字母数字(a-zA-Z),但不匹配符号
  • [^/] 匹配除斜杠以外的任何内容[a-z]{2} 正好匹配2个小写字母[a-z]+ 匹配一个或多个字母,因此首选[a-z]*
,希望这将有助于构建适合您的内容。

祝你好运

相关推荐

如何读取WordPress$Query关联数组(散列)键的值

WordPress编程新手(来自更为传统的环境),并试图了解其一些“独特”特性。我们的网站上有一个目录页,此代码驻留在functions.php, 如果条件为true,则调整结果。if( $query->is_post_type_archive( \'directory\' ) ){ ...//do stuff } 我想知道如何获取is_post_type_archive 这就是“目录”当我对值使用测试时。。。var_dumb($query->is_post