When you register custom post types manually, WordPress allows you to set a distinct archive slug. How you configure this determines if the slug will be translated into your secondary language or not.
When registering custom post types manually, you can set a set a distinct archive slug using the has_archive function.
WPML allows has_archive to be set to a string. However, if the string value is set to something other than rewrite['slug'], or the custom post type name slug is not set, the archive slug will not be translatable.
Setting a translatable slug
In this code example, we set 'has_archive' => true. Assuming that the slug book has been translated to libro in Spanish, the archive links are in the following:
- English (default language): http://mydomain.tld/book/
- Spanish (second language): http://mydomain.tld/es/libro/
add_action( 'init', 'create_post_type' );
function create_post_type() {
register_post_type( 'book',
array(
'labels' => array(
'name' => __( 'Books', 'textdomain' ),
'singular_name' => __( 'Book', 'textdomain' )
),
'public' => true,
'has_archive' => true,
'publicly_queryable' => true,
'exclude_from_search' => false,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => array('slug' => 'book'),
'supports' => array('title','editor', 'custom-fields','thumbnail')
)
);
}
Setting the same slug in default and secondary languages
In this code example, we set a specific string for the parameter 'has_archive' => 'my-books'. Now the archive links are as follows:
- English (default language): http://mydomain.tld/my-books/
- Spanish (second language): http://mydomain.tld/es/my-books/
add_action( 'init', 'create_post_type' );
function create_post_type() {
register_post_type( 'book',
array(
'labels' => array(
'name' => __( 'Books', 'textdomain' ),
'singular_name' => __( 'Book', 'textdomain' )
),
'public' => true,
'has_archive' => 'my-books', // Do not use the gettext functions for this parameter
'publicly_queryable' => true,
'exclude_from_search' => false,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => array('slug' => 'book'),
'supports' => array('title','editor', 'custom-fields','thumbnail')
)
);
}
Troubleshooting customizable slugs
Some themes and plugins allow the site administrator to set custom slugs for their custom post types and custom taxonomies.
If your translated custom slugs are returning a 404 error, please check the following:
- The custom type should be always registered with the same slug across all requests: per language, frontend, backend, AJAX, heartbeat, etc. So in
'rewrite' => [ 'slug' => $my_custom_slug ],the value of$my_custom_slugshould not change from one request to another even if it comes from an option (or any custom setting). - WPML supports only custom slug translation (when the custom type is registered) but not custom permalink structure.
- If the custom slug is stored as an option, it should not be registered as an
admin-textsin thewpml-config.xmlfile. - After updating the value of a custom slug, the theme/plugin should also flush the rewrite rules (by calling
flush_rewrite_rules();).