Support » Plugin: Polylang » Permalinks migration

  • Hi.
    I’ve been using polylang for a while now, it’s an amazing tool! But i’m facing a problem.
    Until now, I’ve been using “index.php?p=number” permalink structure. Now I’d link to use “%postname%”, but when I switch from the old structure to the new one, everything goes 404 :'(

    Could you help?

    Thanks a lot 😉

Viewing 14 replies - 1 through 14 (of 14 total)
  • BTW, my website is

    Hi, I think I found the issue.

    I also like the Polylang module and I also ran into 404 errors when using %postname% pretty permalinks. Because I did not find a solution to this on Internet, just a couple of similar reports, I had to sit down and debuge the module myself and I think I found it.

    The issue is caused by rewrite rules added for language category, tag = “language_rewrite_rules”.
    Even though they ARE processed (removed) by the Polylang module (polylang.php, function rewrite_rules, lines 371-372: if (($current_filter = current_filter()) == 'language_rewrite_rules') return array();), this processing is too late and it is not executed when the language-related rewrite rules are being created (wp-includes/rewrite.php, function rewrite_rules, line 1580: $rules = apply_filters($permastructname . '_rewrite_rules', $rules);).

    This is because the Polylang prepare_rewrite_rules() function that actually adds the filter, is called too late (Polylang constructor, line 88, add_action('wp_loaded', array(&$this, 'prepare_rewrite_rules'), 20);)

    So my suggested quick fix is to move the add_filter(“language_rewrite_rules”) to the end of the init method (Polylang::init(), line 335: add this line: add_filter('language_rewrite_rules', array(&$this, 'rewrite_rules'));

    Then redundant adding in prepare_rewrite_rules() can be removed, so the enumeration on line 359 can be changed to:

    foreach ($types as $type)
      if ($type != 'language')
        add_filter($type . '_rewrite_rules', array(&$this, 'rewrite_rules'));

    Works for me.

    Some more experiments revealed, that most probably the whole Polylang::prepare_rewrite_rules() must be called from init(), otherwise localized homepage (and other pages requiring language code) will not work.

    So the final fix suggestion is to add the mentioned call at the end of the init() function of the Polylang object, so the tail should look like:

    add_permastruct('language', $options['rewrite'] ? '%language%' : 'language/%language%', version_compare($GLOBALS['wp_version'], '3.4' , '<') ? false : array('with_front' => false));

    @zuffap, I tested your fix and it works but it breaks somehow custom post types, I will inspect more later but just to let you know.

    Might be, I’m pretty new to WordPress and the site I’m working on has no custom post types, so I haven’t noticed it does not work.
    Probably the rewrite rules creation must be split – some of them must be created earlier (like the language_rewrite_rules) and some laters, especially rules related to custom post types as these are most probably not yet initialized in the init() phase.
    Please, try to investigate and let me know.

    Wow zuffap, you did an amazing job debugging the whole thing, thanks a lot!

    Plugin Author Chouby


    In WordPress rewrite rules are not created each time WordPress loads because it is a very expensive task. Instead, they are created on demand and stored in the database.

    So it is a priori not possible to know when the rewrite rules are created but there are good practices to follow.

    Typically, the rules are created when you change your permalinks structure. Some plugins (as Polylang) need to modify the rewrite rules and so do this at plugin activation and de-activation. Other (or same) plugins need to modify these rules per user action (typically if you create a custom post type or a custom taxonomy with a plugin, or if you change some ‘url’ options in Polylang).

    In all these cases, Polylang should work well.

    However some plugins “flush rewrite rules” in an “init” action each time WordPress loads. This is very bad practice as stated in the codex. And such plugins will break Polylang (and probably other plugins which need to act on rewrite rules).

    So I would be interested to know if you can detect if your problem is the result of a conflict with a plugin (or maybe the theme).

    Well, this issue occurred each time I manually triggered the rebuild of rewrite rules (via Permalinks -> Save), meaning the incorrect language_rewrite_rules breaking the %postname% permalink rewrite rule was stored in the database, so I assume it’s not the problem of flushing rewrite rules in init of any m module, but I can have a look.

    Perhaps better tuning of order of calls to add_filter can be done to get the desired result.

    Have you been able to reproduce the issue?

    Plugin Author Chouby


    No I don’t reproduce. But I mentionned above a known issue. I can’t apply your proposal because it will break compatibility with plugins which register custom post types and taxonomies. That’s why I am interested to know if you are able to identify a conflict with another plugin or your theme.

    I found the the guilty module – it’s WordPress e-commerce (!
    There, in the file marketplace.php on line 300 there is:
    add_action( 'init', array(&$this, 'flush_rewrite'), 999 );
    Commenting out this line made the Polylang work smoothly without any (my) additional intervention. Now the question is, if this flushing is needed for the e-commerce module to work, or not, but that’s a question for different forum, different topic.

    On the other hand – now that we know there are such “treacherous” modules out there doing such things, could you think about amending the Polylang module to survive in such environment? I find it very helpful (great job Chouby, BTW!) and more people could use in combination with not-that-codex-compliant modules…

    Plugin Author Chouby


    I did not find this file and this instruction in the latest version of wp-ecommerce. So maybe, updating could solve your issue.

    Back to the original problem!

    Updating didn’t solve anything. Migrating permalinks to %postname% makes redirect to, which leads to a 404.

    do you want me to send you the list of the plugins I use beside polylang? In this case please send me an email at [deadbird99 %at%].

    try to search for a construct like this: $wp_rewrite->flush_rules(); in all plugins and the current theme source code and if you find it, try to disable it, just as I did in the wp-e-commerce plugin.
    And, by the way, I’m using it’s Lite version ( which is unfortunately up to date (no update is possible) and CONTAINS this rules flushing…

    Plugin Author Chouby


    Before diving into the code, the best is to de-activate all plugins but Polylang and then activate them one by one to detect the conflict. The conflict may alos come from the theme. Then if you come with a plugin name that we can download, we should be able to help.

Viewing 14 replies - 1 through 14 (of 14 total)
  • The topic ‘Permalinks migration’ is closed to new replies.