[Resolved] WPML and Custom Slug Translation for a Custom Permalinks Plugin
This thread is resolved. Here is a description of the problem and solution.
Problem: You are using a custom plugin to modify the permalink structure for several custom post types that are linked to a parent post type via JetEngine relationships. The plugin is configured to dynamically include the parent festival’s slug in the child post URLs and uses WPML to translate the base slug. However, visiting the translated URLs results in a 404 Not Found error, suggesting a possible mismatch between the rewrite rules or WPML’s handling of the translated slug. Solution: We recommend not using the register/translate string hook for translating slugs as it is intended for PHP string translation, not slugs. Instead, create a custom post type (CPT) and its slug as outlined in our documentation. You can then easily translate it from WPML > Settings. Here are some helpful links:
If this solution does not apply to your case, or if it seems outdated, we highly recommend checking related known issues at https://wpml.org/known-issues/, verifying the version of the permanent fix, and confirming that you have installed the latest versions of themes and plugins. If further assistance is needed, please open a new support ticket at WPML support forum.
This is the technical support forum for WPML - the multilingual WordPress plugin.
Everyone can read, but only WPML clients can post here. WPML team is replying on the forum 6 days per week, 22 hours per day.
Background of the issue:
I am trying to use a custom plugin (Slicked Custom Permalinks) to modify the permalink structure for several custom post types (lineups, set-times, guides) that are linked to a parent post type (festivals) via JetEngine relationships. The plugin is configured to dynamically include the parent festival’s slug in the child post URLs. The desired URL structure is /translated-festivals-slug/parent-festival-slug/child-post-slug/. The plugin uses WPML to translate the base slug (festivals) into each language dynamically using wpml_register_single_string and wpml_translate_single_string. Here’s a summary of what the plugin does: Registers a Base Slug for Translation: do_action('wpml_register_single_string', 'Custom Permalinks', 'base_slug', 'festivals'); $base_slug = apply_filters('wpml_translate_single_string', 'festivals', 'Custom Permalinks', 'base_slug'); Adds Rewrite Rules: Registers rewrite rules for the translated base slug: add_rewrite_rule('^' . $base_slug . '/([^/]+)/([^/]+)/?$', 'index.php?festival=$matches[1]&name=$matches[2]', 'top'); Query Variable Handling: Adds festival as a query variable and modifies the main query to include the custom post types (lineups, set-times, guides). URL Construction: Modifies permalinks dynamically to include the translated base slug and parent festival slug: return home_url('/' . $base_slug . '/' . $parent_festival->post_name . '/' . $post->post_name . '/'); Link to a page where the issue can be seen: hidden link
Symptoms:
The translation of the base slug (festivals -> festivaluri) works correctly, and the URLs appear as expected in all languages. However, visiting the translated URLs results in a 404 Not Found error, suggesting a possible mismatch between the rewrite rules or WPML’s handling of the translated slug.
Questions:
Does WPML fully integrate with dynamically registered rewrite rules for translated slugs?
Is there a better way to register and handle the translation of the base slug to avoid 404 errors?
Are there additional steps required to ensure compatibility between WPML and JetEngine’s relationships when generating and resolving custom permalinks?
Please note we can not support or debug custom-coded plugins we can only try to advise you, if you need further help I suggest hiring a WPML contractor: https://wpml.org/contractors/
In your case using register / translate string hook, is not recomaned since this is to be used with PHP string translation not slugs. What I can suggest is to create CPT and its slug as suggested in our docs and using rewrite['slug'], then you can easily translate it from WPML > Settings.