Some things work differently on a multilingual site by design: a WordPress function keyed on a default-language term, a date suffix WordPress cannot localize, a slug the Advanced Translation Editor does not invent. Support questions raise them as bugs; they are not. This page says what happens, why, and what to do instead.
has_category() and other conditional tags on translated posts
WordPress core's has_category() is not filtered by WPML, on purpose. On a translation the category is the translated term, which has its own slug, so has_category('news') is false on the French post even though the French post is in the French "news" category. The same holds for has_term(), in_category() and any code that compares a default-language slug or term id. Call the conditional with the translated slug, or resolve the term id through the wpml_object_id filter first.
What you see
The native WordPress function has_category does not work for translated posts.
An example of this is as follows:
- We have a category with the English slug “test” and its French translation “test-fr”.
- This category is assigned to posts.
- When you invoke the
has_category("test")inside a loop in your theme’s single.php file, it returns true for the default language but false for the translation.
What to do
Define a new filter in your theme’s functions.php file:
function wp_has_category ($category) {
$category = get_term_by('name', $category, 'category');
return has_category($category);
}
add_filter('wp_has_category', 'wp_has_category', 10, 1);Replace the has_category function with this new filter:
apply_filters( 'wp_has_category', 'test' )
This filter takes the translated category based on the name of original one and checks if the translated category is assigned to a post.
Reference: wpmlcore-3024.
Date suffixes (1st, 2nd, 3rd) are not translatable
This is a limitation of WordPress core, not of WPML: the suffix comes from PHP's date formatting and never passes through a translation function.
What you see
Some themes or plugins use the wp_date() or date_i18n() WordPress functions to display dates. These dates may use a suffix as 1st or 26th, depending on the parameters selected.
Currently, it’s not possible to translate date suffixes because of a longstanding known limitation in WordPress core.
What to do
As a workaround, you can use the wp_date filter to get the date, then modify the suffix before it’s rendered on the page. Please make a full backup of your site before proceeding and follow the steps below:
- Add a small
wp_datefilter to your theme's functions.php that registers each suffix as a string (icl_register_string) and returns its translation (icl_t) in place of the English suffix: - Open the page where the dates are displayed. This will execute the filter added.
- Go to WPML → String Translation and translate the dates.
- You will need to translate each suffix separately (e.g. 1st, 2nd…) because it may change depending on the language.
Reference: compsupp-5773.
The Advanced Translation Editor does not invent a slug
The editor translates the slug field when you fill it and keeps the original slug when you leave it empty. It never derives a slug from the translated title on its own.
What you see
If you translate a post using our Advanced Translation Editor, the slug field is not filled automatically. If you then decided to leave the slug field empty, it loads the original language slug in the translated post.
Reference: wpmlsupp-8574.
Page-builder shortcodes in a WooCommerce product short description
The short description is the post excerpt, a plain-text field by WordPress's definition, so WPML does not parse page-builder shortcodes in it the way it does in the content. WooCommerce happens to render them, which is why the mismatch surprises people.
What you see
The WooCommerce product short description is based on the post excerpt field, and that is ordinarily a simple text field that does not handle shortcodes. As such it is not expected that if you paste page-builder shortcodes into the post excerpt they would work, and when translating post excerpts WPML does not attempt to handle such shortcodes.
But WC handles these “excerpts” a little differently, and shortcodes do work, but WPML still acts as if they do not, and if the shortcode includes attributes that need translating or internal links that should be handled automatically that is not readily possible.
What to do
We have prepared code that can be added as a plugin to provide this functionality. Copy and paste the below code into a file that you might name wpmlpb-excerpts.php and save in your wp-content/plugins/ directory, then activate the plugin.
<?php
/**
* Plugin Name: WPML Page Builders - Proces Excerpts
* Description: Parses shortcode strings in exceprts.
* Version: 1.0
*/
namespace WPMLPB686;
( new Excerpts() )->add_hooks();
class Excerpts {
const SEPARATOR_START = '<!--WPML_EXCERPT_START-->';
const SEPARATOR_END = '<!--WPML_EXCERPT_END-->';
public function add_hooks() {
add_filter( 'wpml_pb_shortcode_content_for_translation', [ $this, 'joinWithContent' ], 10, 2 );
add_filter( 'wpml_tm_translation_job_data', [ $this, 'excludeFromJob' ], 10, 2 );
add_action( 'wpml_pro_translation_completed', [ $this, 'splitFromContent' ], 999 );
}
public function joinWithContent( $content, $id ) {
$post = get_post( $id );
if ( $post && $post->post_excerpt ) {
$content .= self::SEPARATOR_START . $post->post_excerpt . self::SEPARATOR_END;
}
return $content;
}
public function excludeFromJob( $package, $post ) {
if ( preg_match( '/[[^]]+]/', $post->post_excerpt ) ) {
$package['contents']['excerpt']['translate'] = 0;
$package['contents']['excerpt']['data'] = '';
}
return $package;
}
public function splitFromContent( $post_id ) {
$post = get_post( $post_id );
if ( $post && false !== strpos( $post->post_content, self::SEPARATOR_START ) ) {
$start_pos = strpos( $post->post_content, self::SEPARATOR_START );
$end_pos = strpos( $post->post_content, self::SEPARATOR_END, $start_pos );
if ( false !== $end_pos ) {
$content = substr( $post->post_content, 0, $start_pos );
$excerpt = substr( $post->post_content, $start_pos + strlen( self::SEPARATOR_START ), $end_pos - $start_pos - strlen( self::SEPARATOR_START ) );
if ( $excerpt ) {
wp_update_post(
[
'ID' => $post_id,
'post_content' => $content,
'post_excerpt' => $excerpt,
]
);
}
}
}
}
}
Reference: wpmlpb-686.
Different domains per language on WordPress.com hosting
WordPress.com maps one domain to a site; the "different domains per language" URL format needs every language domain to reach the same WordPress, which that hosting does not offer.
What you see
Because of limitations on how domain mapping works with WordPress.com it is not possible to choose the language URLs setting to use different domains per language when sites are hosted with them.
What to do
Either of the other language URL options, with languages in directories or added as a URL parameter, can be used instead of different domains per language.
A different host would be needed if different domains per language were a requirement.
Reference: wpmltriage-2045.
Imported translations and the translation editors
An import writes finished translations; it does not create translation jobs, and the editors work from jobs. The translations are complete on the front end and simply not editable in the Advanced or Classic Translation Editor.
What you see
Whenever you import content using WP All Import and the WPML All Import add-on, you will see the imported post translations perfectly on the front-end. However, you will encounter issues if you try to update them using WPML’s translation editors:
- The Classic Translation Editor displays content in the default language instead of the imported translations
- The Advanced Translation Editor displays blank translations
This is because when you import multilingual content, WPML does not create translation jobs, which are needed for string segmentation.
What to do
To edit or update your imported translations, please switch to the native WordPress editor and use manual translation.
Reference: WPMLAI-168.