多言語サイトでは、仕様により一部の動作が異なります。デフォルト言語の用語をキーとするWordPress関数、WordPressがローカライズできない日付の接尾辞、高度な翻訳エディタが自動生成しないスラッグなどがその例です。サポートのご質問ではこれらがバグとして報告されることがありますが、バグではありません。このページでは、どうなるか、その理由、および代わりの対処法について説明します。
翻訳された投稿でのhas_category()およびその他の条件分岐タグ
WordPressコアのhas_category()は、意図的にWPMLによるフィルタリングの対象外となっています。翻訳では、カテゴリは翻訳された用語となり独自のスラッグを持つため、フランス語の投稿がフランス語の「news」カテゴリに含まれていても、has_category('news')はフランス語の投稿ではfalseになります。has_term()、in_category()、およびデフォルト言語のスラッグや用語IDを比較するすべてのコードについても同様です。翻訳されたスラッグを使用して条件分岐を呼び出すか、最初にwpml_object_idフィルターを介して用語IDを解決してください。
発生する現象
WordPressのネイティブ関数であるhas_categoryが、翻訳された投稿で機能しません。
この例は以下のとおりです。
- 英語のスラッグ「test」と、そのフランス語翻訳「test-fr」を持つカテゴリがあります。
- このカテゴリが投稿に割り当てられています。
- テーマのsingle.phpファイルのループ内で
has_category("test")を呼び出すと、デフォルト言語ではtrueを返しますが、翻訳ではfalseを返します。
対処法
テーマのfunctions.phpファイルで新しいフィルターを定義します。
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);has_category関数をこの新しいフィルターに置き換えます。
apply_filters( 'wp_has_category', 'test' )
このフィルターは、元の名前に基づいて翻訳されたカテゴリを取得し、その翻訳されたカテゴリが投稿に割り当てられているかどうかを確認します。
参照:wpmlcore-3024。
日付の接尾辞(1st、2nd、3rd)の翻訳不可
これはWPMLではなくWordPressコアの制限です。接尾辞はPHPの日付フォーマットから取得されるため、翻訳関数を通過することはありません。
発生する現象
一部のテーマやプラグインでは、日付を表示するためにWordPress関数のwp_date()またはdate_i18n()を使用します。選択したパラメータによっては、これらの日付に1stや26thのような接尾辞が使用される場合があります。
現在、WordPressコアの長期にわたる既知の制限により、日付の接尾辞を翻訳することはできません。
対処法
回避策として、wp_dateフィルターを使用して日付を取得し、ページにレンダリングされる前に接尾辞を変更できます。続行する前にサイトの完全なバックアップを作成し、以下の手順に従ってください。
- テーマのfunctions.phpに小さな
wp_dateフィルターを追加し、各接尾辞を文字列として登録(icl_register_string)して、英語の接尾辞の代わりにその翻訳(icl_t)を返すようにします。 - 日付が表示されるページを開きます。これにより、追加したフィルターが実行されます。
- WPML → 文字列翻訳に移動し、日付を翻訳します。
- 言語によって変わる可能性があるため、各接尾辞(例:1st、2ndなど)を個別に翻訳する必要があります。
参照:compsupp-5773。
高度な翻訳エディタがスラッグを自動生成しない仕様
エディタは、スラッグフィールドに入力した場合はそれを翻訳し、空のままにした場合は元のスラッグを保持します。翻訳されたタイトルから独自にスラッグを派生させることはありません。
発生する現象
高度な翻訳エディタを使用して投稿を翻訳する場合、スラッグフィールドは自動的に入力されません。スラッグフィールドを空のままにすると、翻訳された投稿には元の言語のスラッグが読み込まれます。
参照:wpmlsupp-8574。
WooCommerce商品の短い説明におけるページビルダーのショートコード
短い説明は投稿の抜粋であり、WordPressの定義ではプレーンテキストフィールドです。そのため、WPMLはコンテンツ内で行うようにはページビルダーのショートコードを解析しません。WooCommerceが偶然それらをレンダリングするため、この不一致がユーザーを驚かせる原因となっています。
発生する現象
WooCommerce商品の短い説明は投稿の抜粋フィールドに基づいており、これは通常、ショートコードを処理しないシンプルなテキストフィールドです。そのため、投稿の抜粋にページビルダーのショートコードを貼り付けても機能することは想定されておらず、投稿の抜粋を翻訳する際にWPMLはそのようなショートコードを処理しようとしません。
しかし、WooCommerceはこれらの「抜粋」を少し異なる方法で処理するためショートコードが機能しますが、WPMLは依然として機能しないものとして動作します。そのため、ショートコードに翻訳が必要な属性や自動的に処理されるべき内部リンクが含まれている場合、それらを簡単に処理することはできません。
対処法
この機能を提供するために、プラグインとして追加できるコードを用意しました。以下のコードをコピーして、wpmlpb-excerpts.phpなどの名前を付けたファイルに貼り付け、wp-content/plugins/ディレクトリに保存してから、プラグインを有効化してください。
<?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,
]
);
}
}
}
}
}
参照:wpmlpb-686。
WordPress.comホスティングでの言語ごとの異なるドメイン
WordPress.comは1つのドメインを1つのサイトにマッピングします。「言語ごとに異なるドメイン」のURLフォーマットでは、すべての言語ドメインが同じWordPressに到達する必要がありますが、このホスティングはその機能を提供していません。
発生する現象
WordPress.comでのドメインマッピングの仕組みの制限により、サイトがそこでホストされている場合、言語URL設定で「言語ごとに異なるドメイン」を使用することを選択できません。
対処法
「言語ごとに異なるドメイン」の代わりに、「ディレクトリごとの異なる言語」または「パラメータとして追加された言語名」のいずれかの言語URLオプションを使用できます。
言語ごとに異なるドメインが必須の要件である場合は、別のホストが必要になります。
参照:wpmltriage-2045。
インポートされた翻訳と翻訳エディタ
インポートでは完了した翻訳が書き込まれますが、翻訳ジョブは作成されません。一方、エディタはジョブに基づいて機能します。フロントエンドでは翻訳が完了していますが、高度な翻訳エディタやクラシック翻訳エディタでは編集できないだけです。
発生する現象
WP All ImportおよびWPML All Importアドオンを使用してコンテンツをインポートすると、フロントエンドではインポートされた投稿の翻訳が完全に表示されます。ただし、WPMLの翻訳エディタを使用してそれらを更新しようとすると、問題が発生します。
- クラシック翻訳エディタでは、インポートされた翻訳の代わりにデフォルト言語でコンテンツが表示される
- 高度な翻訳エディタでは、空白の翻訳が表示される
これは、多言語コンテンツをインポートする際、文字列のセグメンテーションに必要な翻訳ジョブがWPMLによって作成されないためです。
対処法
インポートされた翻訳を編集または更新するには、ネイティブのWordPressエディタに切り替えて手動翻訳を使用してください。
参照:WPMLAI-168。