├── README.md ├── include ├── post-type.php └── taxonomy.php └── polylang-translate-rewrite-slugs.php /README.md: -------------------------------------------------------------------------------- 1 | Polylang - Translate URL Rewrite Slugs 2 | =============================================================================== 3 | WordPress plugin that add rewrite url slugs translation feature to Polylang. 4 | 5 | Work in progress ;) 6 | 7 | Upgrade notice < 0.3.0 8 | ------------------------------------------------------------------------------- 9 | If you used a version prior to 0.3.0, the plugin will probably crash as the structure of the param for the "pll_translated_post_type_rewrite_slugs" filter has changed. 10 | 11 | Translate Post Type URLs 12 | ------------------------------------------------------------------------------- 13 | Translate rewrite slugs for post types by doing 5 things: 14 | - Remove original extra rewrite rules and permastruct for these post types; 15 | - Translate the extra rewrite rules and permastruct for these post types; 16 | - Stop Polylang from translating rewrite rules for these post types; 17 | - Fix "get_permalink" for these post types. 18 | - Fix "get_post_type_archive_link" for these post types. 19 | 20 | To translate a post type rewrite slug, add the filter "pll_translated_post_type_rewrite_slugs" to your functions.php file or your plugin and add the "has_archive" and "rewrite" key has you normally do for the params of the "register_post_type" Wordpress function but add it for each post type and language you want. 21 | 22 | Example 23 | ~~~php 24 | array( 29 | 'fr' => array( 30 | 'has_archive' => true, 31 | 'rewrite' => array( 32 | 'slug' => 'produit', 33 | ), 34 | ), 35 | 'en' => array( 36 | 'has_archive' => true, 37 | 'rewrite' => array( 38 | 'slug' => 'product', 39 | ), 40 | ), 41 | ), 42 | ); 43 | return $post_type_translated_slugs; 44 | }); 45 | ?> 46 | ~~~ -------------------------------------------------------------------------------- /include/post-type.php: -------------------------------------------------------------------------------- 1 | replace_extra_rules_top. 7 | */ 8 | class PLL_TRS_Post_Type { 9 | // The post type object. 10 | public $post_type_object; 11 | // The translated rewrite slugs. 12 | public $translated_slugs; 13 | 14 | /** 15 | * Contructor. 16 | */ 17 | public function __construct($post_type_object, $translated_slugs) { 18 | $this->post_type_object = $post_type_object; 19 | $this->translated_slugs = $this->sanitize_translated_slugs($translated_slugs); 20 | 21 | // Replace "extra_rules_top", for archive. 22 | $this->replace_extra_rules_top(); 23 | // Replace "permastruct", for single. 24 | $this->replace_permastruct(); 25 | } 26 | 27 | private function sanitize_translated_slugs($translated_slugs) { 28 | $post_type = $this->post_type_object->name; 29 | 30 | // Add defaults to translated_slugs. 31 | $defaults = array( 32 | 'has_archive' => false, 33 | 'rewrite' => true, 34 | ); 35 | 36 | foreach ($translated_slugs as $lang => $translated_slug) { 37 | $args = wp_parse_args( $translated_slug, $defaults ); 38 | $args = (object) $args; 39 | 40 | if ( false !== $args->rewrite && ( is_admin() || '' != get_option( 'permalink_structure' ) ) ) { 41 | if ( ! is_array( $args->rewrite ) ) 42 | $args->rewrite = array(); 43 | if ( empty( $args->rewrite['slug'] ) ) 44 | $args->rewrite['slug'] = $post_type; 45 | if ( ! isset( $args->rewrite['with_front'] ) ) 46 | $args->rewrite['with_front'] = true; 47 | if ( ! isset( $args->rewrite['pages'] ) ) 48 | $args->rewrite['pages'] = true; 49 | if ( ! isset( $args->rewrite['feeds'] ) || ! $args->has_archive ) 50 | $args->rewrite['feeds'] = (bool) $args->has_archive; 51 | if ( ! isset( $args->rewrite['ep_mask'] ) ) { 52 | if ( isset( $args->permalink_epmask ) ) 53 | $args->rewrite['ep_mask'] = $args->permalink_epmask; 54 | else 55 | $args->rewrite['ep_mask'] = EP_PERMALINK; 56 | } 57 | } 58 | 59 | $translated_slugs[$lang] = $args; 60 | } 61 | 62 | return $translated_slugs; 63 | } 64 | 65 | /** 66 | * Replace "extra_rules_top", for archive. 67 | * 68 | * This code simulate the code used in WordPress function "register_post_type" 69 | * and execute it for each language. After that, Polylang will consider these 70 | * rules like "individual" post types (one by lang) and will create the appropriated 71 | * rules. 72 | * 73 | * @see Extra rules from WordPress (wp-include/post.php, register_post_type()). 74 | */ 75 | private function replace_extra_rules_top() { 76 | global $polylang, $wp_rewrite; 77 | 78 | $post_type = $this->post_type_object->name; 79 | 80 | // Remove the original extra rules. 81 | if ( $this->post_type_object->has_archive ) { 82 | $archive_slug = $this->post_type_object->has_archive === true ? $this->post_type_object->rewrite['slug'] : $this->post_type_object->has_archive; 83 | if ( $this->post_type_object->rewrite['with_front'] ) 84 | $archive_slug = substr( $wp_rewrite->front, 1 ) . $archive_slug; 85 | else 86 | $archive_slug = $wp_rewrite->root . $archive_slug; 87 | 88 | unset($wp_rewrite->extra_rules_top["{$archive_slug}/?$"]); 89 | if ( $this->post_type_object->rewrite['feeds'] && $wp_rewrite->feeds ) { 90 | $feeds = '(' . trim( implode( '|', $wp_rewrite->feeds ) ) . ')'; 91 | unset($wp_rewrite->extra_rules_top["{$archive_slug}/feed/$feeds/?$"]); 92 | unset($wp_rewrite->extra_rules_top["{$archive_slug}/$feeds/?$"]); 93 | } 94 | if ( $this->post_type_object->rewrite['pages'] ) 95 | unset($wp_rewrite->extra_rules_top["{$archive_slug}/{$wp_rewrite->pagination_base}/([0-9]{1,})/?$"]); 96 | } 97 | 98 | // Add the translated extra rules for each languages. 99 | foreach ($this->translated_slugs as $lang => $translated_slug) { 100 | if ($translated_slug->has_archive) { 101 | $archive_slug = $translated_slug->has_archive === true ? $translated_slug->rewrite['slug'] : $translated_slug->has_archive; 102 | if ( $translated_slug->rewrite['with_front'] ) 103 | $archive_slug = substr( $wp_rewrite->front, 1 ) . $archive_slug; 104 | else 105 | $archive_slug = $wp_rewrite->root . $archive_slug; 106 | 107 | add_rewrite_rule( "{$archive_slug}/?$", "index.php?post_type=$post_type", 'top' ); 108 | if ( $translated_slug->rewrite['feeds'] && $wp_rewrite->feeds ) { 109 | $feeds = '(' . trim( implode( '|', $wp_rewrite->feeds ) ) . ')'; 110 | add_rewrite_rule( "{$archive_slug}/feed/$feeds/?$", "index.php?post_type=$post_type" . '&feed=$matches[1]', 'top' ); 111 | add_rewrite_rule( "{$archive_slug}/$feeds/?$", "index.php?post_type=$post_type" . '&feed=$matches[1]', 'top' ); 112 | } 113 | if ( $translated_slug->rewrite['pages'] ) 114 | add_rewrite_rule( "{$archive_slug}/{$wp_rewrite->pagination_base}/([0-9]{1,})/?$", "index.php?post_type=$post_type" . '&paged=$matches[1]', 'top' ); 115 | } 116 | } 117 | } 118 | 119 | /** 120 | * Replace "permastruct", for single. 121 | * 122 | * This code simulate the code used in WordPress function "register_post_type" 123 | * and execute it for each language. 124 | * 125 | * @see Permstruct from WordPress (wp-include/post.php, register_post_type()). 126 | */ 127 | private function replace_permastruct() { 128 | global $polylang, $wp_rewrite; 129 | 130 | $post_type = $this->post_type_object->name; 131 | 132 | // Remove the original permastructs. 133 | unset($wp_rewrite->extra_permastructs[$post_type]); 134 | 135 | // Add the translated permastructs for each languages. 136 | foreach ($this->translated_slugs as $lang => $translated_slug) { 137 | $args = $translated_slug; 138 | 139 | if ( false !== $args->rewrite && ( is_admin() || '' != get_option( 'permalink_structure' ) ) ) { 140 | $permastruct_args = $args->rewrite; 141 | $permastruct_args['feed'] = $permastruct_args['feeds']; 142 | // Set the walk_dirs to false to avoid conflict with has_archive = false and the %language% 143 | // in the rewrite directive. Without it the archive page redirect to the frontpage if has_archive is false. 144 | $permastruct_args['walk_dirs'] = false; 145 | 146 | // If "Hide URL language information for default language" option is 147 | // set to true the rules has to be different for the default language. 148 | if ($polylang->options['hide_default'] && $lang == pll_default_language()) { 149 | add_permastruct( $post_type.'_'.$lang, "{$args->rewrite['slug']}/%$post_type%", $permastruct_args ); 150 | } else { 151 | add_permastruct( $post_type.'_'.$lang, "%language%/{$args->rewrite['slug']}/%$post_type%", $permastruct_args ); 152 | } 153 | } 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /include/taxonomy.php: -------------------------------------------------------------------------------- 1 | taxonomy_object = $taxonomy_object; 18 | $this->translated_slugs = $translated_slugs; 19 | $this->translated_struct = $translated_struct; 20 | 21 | // Translate the rewrite rules of the post type. 22 | add_filter($this->taxonomy_object->name.'_rewrite_rules', array($this, 'taxonomy_rewrite_rules_filter')); 23 | } 24 | 25 | /** 26 | * Translate the rewrite rules. 27 | */ 28 | public function taxonomy_rewrite_rules_filter($rewrite_rules) { 29 | global $polylang, $wp_rewrite; 30 | 31 | $translated_rules = array(); 32 | 33 | // For each lang. 34 | foreach ($this->translated_slugs as $lang => $translated_slug) { 35 | // If "Hide URL language information for default language" option is 36 | // set to true the rules has to be different for the default language. 37 | if ($polylang->options['hide_default'] && $lang == pll_default_language()) { 38 | // For each rule. 39 | foreach ($rewrite_rules as $rule_key => $rule_value) { 40 | // Only translate the rewrite slug. 41 | $translated_rules[str_replace(trim($this->taxonomy_object->rewrite['slug'], '/'), $translated_slug, $rule_key)] = $rule_value; 42 | } 43 | } else { 44 | // For each rule. 45 | foreach ($rewrite_rules as $rule_key => $rule_value) { 46 | $taxonomy_rewrite_slug = $this->taxonomy_object->rewrite['slug']; 47 | 48 | // Replace the rewrite tags in slugs. 49 | foreach ($wp_rewrite->rewritecode as $position => $code) { 50 | $taxonomy_rewrite_slug = str_replace($code, $wp_rewrite->rewritereplace[$position], $taxonomy_rewrite_slug); 51 | $translated_slug = str_replace($code, $wp_rewrite->rewritereplace[$position], $translated_slug); 52 | } 53 | 54 | // Shift the matches up cause "lang" will be the first. 55 | $translated_rules['('.$lang.')/'.str_replace(trim($taxonomy_rewrite_slug, '/'), $translated_slug, $rule_key)] = str_replace( 56 | array('[8]', '[7]', '[6]', '[5]', '[4]', '[3]', '[2]', '[1]'), 57 | array('[9]', '[8]', '[7]', '[6]', '[5]', '[4]', '[3]', '[2]'), 58 | $rule_value 59 | ); 60 | } 61 | } 62 | } 63 | 64 | return $translated_rules; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /polylang-translate-rewrite-slugs.php: -------------------------------------------------------------------------------- 1 | array( 49 | * 'fr' => array( 50 | * 'has_archive' => true, 51 | * 'rewrite' => array( 52 | * 'slug' => 'produit', 53 | * ), 54 | * ), 55 | * 'en' => array( 56 | * 'has_archive' => true, 57 | * 'rewrite' => array( 58 | * 'slug' => 'product', 59 | * ), 60 | * ), 61 | * ), 62 | * ); 63 | * return $post_type_translated_slugs; 64 | * }); 65 | * add_filter('pll_translated_taxonomy_rewrite_slugs', function($taxonomy_translated_slugs) { 66 | * // Add translation for "color" taxonomy. 67 | * $taxonomy_translated_slugs = array( 68 | * 'color' => array( 69 | * 'fr' => 'couleur' 70 | * 'en' => 'color', 71 | * ), 72 | * ); 73 | * return $taxonomy_translated_slugs; 74 | * }); 75 | */ 76 | class Polylang_Translate_Rewrite_Slugs { 77 | // Array of custom post types handle by "Polylang - Translate URL Rewrite Slugs". 78 | public $post_types; 79 | // Array of taxonomies handle by "Polylang - Translate URL Rewrite Slugs". 80 | public $taxonomies; 81 | 82 | /** 83 | * Contructor. 84 | */ 85 | public function __construct() { 86 | // Initiate the array that will contain the "PLL_TRS_Post_Type" object. 87 | $this->post_types = array(); 88 | // Initiate the array that will contain the... 89 | $this->taxonomies = array(); 90 | 91 | // If the Polylang plugin is active... 92 | include_once( ABSPATH . 'wp-admin/includes/plugin.php' ); 93 | if (is_plugin_active('polylang/polylang.php')) { 94 | add_action('init', array($this, 'init_action'), 20); 95 | } 96 | } 97 | 98 | /** 99 | * Trigger on "init" action. 100 | */ 101 | public function init_action() { 102 | // Post types to handle. 103 | require_once(PLL_TRS_INC . '/post-type.php'); 104 | $post_type_translated_slugs = apply_filters('pll_translated_post_type_rewrite_slugs', array()); 105 | foreach ($post_type_translated_slugs as $post_type => $translated_slugs) { 106 | $this->add_post_type($post_type, $translated_slugs); 107 | } 108 | // Taxonomies to handle. 109 | require_once(PLL_TRS_INC . '/taxonomy.php'); 110 | $taxonomy_translated_slugs = apply_filters('pll_translated_taxonomy_rewrite_slugs', array()); 111 | foreach ($taxonomy_translated_slugs as $taxonomy => $translated_slugs) { 112 | $this->add_taxonomy($taxonomy, $translated_slugs); 113 | } 114 | // Fix "get_permalink" for these post types. 115 | add_filter('post_type_link', array($this, 'post_type_link_filter'), 10, 4); 116 | // Fix "get_post_type_archive_link" for these post types. 117 | add_filter('post_type_archive_link', array($this, 'post_type_archive_link_filter'), 25, 2); 118 | // Fix "get_term_link" for taxonomies. 119 | add_filter('term_link', array($this, 'term_link_filter'), 10, 3); 120 | 121 | // Fix "PLL_Frontend_Links->get_translation_url". 122 | add_filter('pll_translation_url', array($this, 'pll_translation_url_filter'), 10, 2); 123 | // Stop Polylang from translating rewrite rules for these post types. 124 | add_filter('pll_rewrite_rules', array($this, 'pll_rewrite_rules_filter')); 125 | } 126 | 127 | /** 128 | * Create a "PLL_TRS_Post_Type" and add it to the handled post type list. 129 | */ 130 | public function add_post_type($post_type, $translated_slugs) { 131 | global $polylang; 132 | 133 | $languages = $polylang->model->get_languages_list(); 134 | $post_type_object = get_post_type_object($post_type); 135 | if (!is_null($post_type_object)) { 136 | foreach ($languages as $language) { 137 | // Add non specified slug translation to post type default. 138 | if (!array_key_exists($language->slug, $translated_slugs)) { 139 | $translated_slugs[$language->slug] = array(); 140 | } 141 | // Trim "/" of the slug. 142 | if (isset($translated_slugs[$language->slug]['rewrite']['slug'])) { 143 | $translated_slugs[$language->slug]['rewrite']['slug'] = trim($translated_slugs[$language->slug]['rewrite']['slug'], '/'); 144 | } 145 | } 146 | $this->post_types[$post_type] = new PLL_TRS_Post_Type($post_type_object, $translated_slugs); 147 | } 148 | } 149 | 150 | /** 151 | * ... 152 | */ 153 | public function add_taxonomy($taxonomy, $translated_slugs) { 154 | global $polylang; 155 | 156 | $languages = $polylang->model->get_languages_list(); 157 | $taxonomy_object = get_taxonomy($taxonomy); 158 | if (!is_null($taxonomy_object)) { 159 | $translated_struct = array(); 160 | foreach ($languages as $language) { 161 | // Add non specified slug translation to taxonomy default. 162 | if (!array_key_exists($language->slug, $translated_slugs)) { 163 | $translated_slugs[$language->slug] = $taxonomy_object->rewrite['slug']; 164 | } 165 | // Trim "/". 166 | $translated_slugs[$language->slug] = trim($translated_slugs[$language->slug], '/'); 167 | // Generate "struct" with "slug" as WordPress would do. 168 | $translated_struct[$language->slug] = $translated_slugs[$language->slug] . "/%{$taxonomy_object->name}%"; 169 | } 170 | $this->taxonomies[$taxonomy] = new PLL_TRS_Taxonomy($taxonomy_object, $translated_slugs, $translated_struct); 171 | } 172 | } 173 | 174 | /** 175 | * Fix "get_permalink" for this post type. 176 | */ 177 | public function post_type_link_filter($post_link, $post, $leavename, $sample) { 178 | global $polylang; 179 | 180 | // We always check for the post language. Otherwise, the current language. 181 | $post_language = $polylang->model->get_post_language($post->ID); 182 | if ($post_language) { 183 | $lang = $post_language->slug; 184 | } else { 185 | $lang = pll_default_language(); 186 | } 187 | 188 | // Check if the post type is handle. 189 | if (isset($this->post_types[$post->post_type])) { 190 | // Build URL. Lang prefix is already handle. 191 | return home_url('/'.$this->post_types[$post->post_type]->translated_slugs[$lang]->rewrite['slug'].'/'.($leavename?"%$post->post_type%":get_page_uri( $post->ID ))); 192 | } 193 | 194 | return $post_link; 195 | } 196 | 197 | /** 198 | * Fix "get_post_type_archive_link" for this post type. 199 | */ 200 | public function post_type_archive_link_filter($link, $archive_post_type) { 201 | if (is_admin()) { 202 | global $polylang; 203 | $lang = $polylang->pref_lang->slug; 204 | } else { 205 | $lang = pll_current_language(); 206 | } 207 | 208 | // Check if the post type is handle. 209 | if (isset($this->post_types[$archive_post_type])) { 210 | return $this->get_post_type_archive_link($archive_post_type, $lang); 211 | } 212 | 213 | return $link; 214 | } 215 | 216 | /** 217 | * Reproduce "get_post_type_archive_link" WordPress function. 218 | * 219 | * @see wp-include/link-template.php, get_post_type_archive_link(). 220 | */ 221 | private function get_post_type_archive_link($post_type, $lang) { 222 | global $wp_rewrite, $polylang; 223 | 224 | // If the post type is handle, let the "$this->get_post_type_archive_link" 225 | // function handle this. 226 | if (isset($this->post_types[$post_type])) { 227 | $translated_slugs = $this->post_types[$post_type]->translated_slugs; 228 | $translated_slug = $translated_slugs[$lang]; 229 | 230 | if ( ! $translated_slug->has_archive ) 231 | return false; 232 | 233 | if ( get_option( 'permalink_structure' ) && is_array( $translated_slug->rewrite ) ) { 234 | $struct = ( true === $translated_slug->has_archive ) ? $translated_slug->rewrite['slug'] : $translated_slug->has_archive; 235 | 236 | if ( 237 | // If the "URL modifications" is set to "The language is set from the directory name in pretty permalinks". 238 | $polylang->options['force_lang'] == 1 239 | // If NOT ("Hide URL language information for default language" option is 240 | // set to true and the $lang is the default language.) 241 | && !($polylang->options['hide_default'] && $lang == pll_default_language()) 242 | ) { 243 | $struct = $lang . '/' . $struct; 244 | } 245 | 246 | if ( $translated_slug->rewrite['with_front'] ) 247 | $struct = $wp_rewrite->front . $struct; 248 | else 249 | $struct = $wp_rewrite->root . $struct; 250 | $link = home_url( user_trailingslashit( $struct, 'post_type_archive' ) ); 251 | } else { 252 | $link = home_url( '?post_type=' . $post_type ); 253 | } 254 | } 255 | 256 | return $link; 257 | } 258 | 259 | /** 260 | * Fix "get_term_link" for this taxonomy. 261 | */ 262 | public function term_link_filter($termlink, $term, $taxonomy) { 263 | // Check if the post type is handle. 264 | if (isset($this->taxonomies[$taxonomy])) { 265 | global $wp_rewrite, $polylang; 266 | 267 | if ( !is_object($term) ) { 268 | if ( is_int($term) ) { 269 | $term = get_term($term, $taxonomy); 270 | } else { 271 | $term = get_term_by('slug', $term, $taxonomy); 272 | } 273 | } 274 | 275 | if ( !is_object($term) ) 276 | $term = new WP_Error('invalid_term', __('Empty Term')); 277 | 278 | if ( is_wp_error( $term ) ) 279 | return $term; 280 | 281 | // Get the term language. 282 | $term_language = $polylang->model->get_term_language($term->term_id); 283 | if ($term_language) { 284 | $lang = $term_language->slug; 285 | } else { 286 | $lang = pll_default_language(); 287 | } 288 | // Check if the language is handle. 289 | if (isset($this->taxonomies[$taxonomy]->translated_slugs[$lang])) { 290 | $taxonomy = $term->taxonomy; 291 | 292 | $termlink = $this->taxonomies[$taxonomy]->translated_struct[$lang]; 293 | 294 | $slug = $term->slug; 295 | $t = get_taxonomy($taxonomy); 296 | 297 | if ( empty($termlink) ) { 298 | if ( 'category' == $taxonomy ) 299 | $termlink = '?cat=' . $term->term_id; 300 | elseif ( $t->query_var ) 301 | $termlink = "?$t->query_var=$slug"; 302 | else 303 | $termlink = "?taxonomy=$taxonomy&term=$slug"; 304 | $termlink = home_url($termlink); 305 | } else { 306 | if ( $t->rewrite['hierarchical'] ) { 307 | $hierarchical_slugs = array(); 308 | $ancestors = get_ancestors($term->term_id, $taxonomy); 309 | foreach ( (array)$ancestors as $ancestor ) { 310 | $ancestor_term = get_term($ancestor, $taxonomy); 311 | $hierarchical_slugs[] = $ancestor_term->slug; 312 | } 313 | $hierarchical_slugs = array_reverse($hierarchical_slugs); 314 | $hierarchical_slugs[] = $slug; 315 | $termlink = str_replace("%$taxonomy%", implode('/', $hierarchical_slugs), $termlink); 316 | } else { 317 | $termlink = str_replace("%$taxonomy%", $slug, $termlink); 318 | } 319 | $termlink = home_url( user_trailingslashit($termlink, 'category') ); 320 | } 321 | // Back Compat filters. 322 | if ( 'post_tag' == $taxonomy ) 323 | $termlink = apply_filters( 'tag_link', $termlink, $term->term_id ); 324 | elseif ( 'category' == $taxonomy ) 325 | $termlink = apply_filters( 'category_link', $termlink, $term->term_id ); 326 | } 327 | } 328 | 329 | return $termlink; 330 | } 331 | 332 | /** 333 | * Fix "PLL_Frontend_Links->get_translation_url()". 334 | */ 335 | public function pll_translation_url_filter($url, $lang) { 336 | global $wp_query, $polylang; 337 | 338 | if (is_category()) { 339 | $term = get_category_by_slug($wp_query->get('category_name')); 340 | $translated_term = get_term(pll_get_term($term->term_id, $lang), $term->taxonomy); 341 | return home_url('/'.$lang.'/'.$translated_term->slug); 342 | } 343 | elseif (is_archive()) { 344 | $post_type = $wp_query->query_vars['post_type']; 345 | // If the post type is handle, let the "$this->get_post_type_archive_link" 346 | // function handle this. 347 | if (isset($this->post_types[$post_type])) { 348 | return $this->get_post_type_archive_link($post_type, $lang); 349 | } 350 | } 351 | 352 | return $url; 353 | } 354 | 355 | /** 356 | * Stop Polylang from translating rewrite rules for these post types. 357 | */ 358 | public function pll_rewrite_rules_filter($rules) { 359 | // We don't want Polylang to take care of these rewrite rules groups. 360 | foreach (array_keys($this->post_types) as $post_type) { 361 | $rule_key = array_search($post_type, $rules); 362 | if ($rule_key) { 363 | unset($rules[$rule_key]); 364 | } 365 | } 366 | foreach (array_keys($this->taxonomies) as $taxonomy) { 367 | $rule_key = array_search($taxonomy, $rules); 368 | if ($rule_key) { 369 | unset($rules[$rule_key]); 370 | } 371 | } 372 | 373 | return $rules; 374 | } 375 | } 376 | new Polylang_Translate_Rewrite_Slugs(); 377 | --------------------------------------------------------------------------------