Bilingual WP site: How to achieve different URL sturcture rule based on its language?

The question:

A wordpress website with bilingual setup, with three languages:

  • English (“primary language”) : “en”
  • Traditional Chinese : “zh-hant”
  • Simplified Chinese : “zh-hans”

The bilingual setup is currently achieved with the polylang plugin.

I would like to have different URL structure based on the post’s language.

For English,

example.com/blog/%category%/%postname%/

And the above permalink sturcture is my current set up in the WP permalink setting page.
(custom structure, /blog/%category%/%postname%/)

But for non-English blog post URL, I would like to use post id instead of postname:

example.com/zh-hant/blog/%category%/%post_id%

The polylang plugin does not allow me to have different permalink setting per language, so I think I need a custom function solution to this.

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

Try the following steps:

  1. Add the rewrite rules for the <language>/blog/%category%/%post_id% structure.

    I used the post_rewrite_rules hook to add the rewrite rules, but for generating the rewrite rules, I used WP_Rewrite::generate_rewrite_rules() the same way WordPress core used it to generate the rewrite rules for the default permalink structure (that you set via the Permalink Settings page).

    add_filter( 'post_rewrite_rules', 'my_post_rewrite_rules' );
    function my_post_rewrite_rules( $post_rewrite ) {
        global $wp_rewrite;
    
        // Generate the rewrite rules for example.com/<language>/blog/<category slug or path>/<post ID>/
        $post_rewrite2 = $wp_rewrite->generate_rewrite_rules(
            '^zh-han[st]/blog/%category%/%post_id%',
            EP_PERMALINK
        );
    
        // Combine the rules, with the new ones at the top.
        return array_merge( $post_rewrite2, $post_rewrite );
    }
    
  2. The above step ensures that the URLs do not result in a 404 error, and now, we need to filter the permalink URL generated via get_permalink() so that the URL uses the correct structure.

    Normally, one would use the post_link hook to replace the rewrite tag (%post_id% in your case), but %post_id% is a core rewrite/structure tag in WordPress, so we can simply use the pre_post_link hook to set the structure to /blog/%category%/%post_id%/ if the post language (slug) is zh-hans or zh-hant. I.e. We just need to set the structure and the tag will be replaced by WordPress.

    Note: pll_get_post_language() is a Polylang function; see here for further details.

    add_filter( 'pre_post_link', 'my_pre_post_link', 10, 3 );
    function my_pre_post_link( $permalink, $post, $leavename ) {
        if ( ! $leavename && is_object( $post ) &&
            preg_match( '#^zh-han[st]$#', pll_get_post_language( $post->ID ) )
        ) {
            $permalink = '/blog/%category%/%post_id%/';
        }
    
        return $permalink;
    }
    
  3. Be sure to flush the rewrite rules after you’ve added the above functions to your theme/plugin — just visit the Permalink Settings page without having to click on the Save Changes button.

Additionally, the RegEx pattern ^zh-han[st] will match both zh-hans and zh-hant. You can test it here.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment