WPML 可變產品翻譯後價格異常:WooCommerce Variation 無法顯示的根因與修法 - Mr. 蔡大痣數位轉型顧問 - WordPress 及 SEO 專家

文章分類/

WPML 可變產品翻譯後價格異常:WooCommerce Variation 無法顯示的根因與修法

0 瀏覽

當你在 WPML 環境下使用 WooCommerce 可變產品(Variable Product),並只為特定語言建立翻譯商品時,常會遇到一個讓人困惑的狀況:後台明明已建立好各語言的 variation,前台卻顯示「This product is currently out of stock and unavailable.」或是價格完全不顯示。本文記錄這個問題的排查過程與解決方案。

問題背景

站台基底語言為繁體中文(zh-hant),商品只在英文(en)語言下建立,並在 WPML WooCommerce Multilingual 中使用「Set prices in other currencies manually」手動設定 USD 價格。

自製 WooCommerce 產品規格列表 Shortcode 嘗試讀取 variation 清單,卻持續回傳空結果,debug log 顯示:

No available variations found for product ID: 1407

排查過程:找出 _price 為何是空的

第一步先確認 variation 子文章是否存在,改用 get_children() 直接取得子項 ID,再逐一印出所有價格相關 meta:

$children = $product->get_children();
foreach ($children as $child_id) {
    $all_meta = get_post_meta($child_id);
    // 篩出含 price / wcml / currency 的 key
}

log 輸出如下:

Variation 1670 | status: publish | stock_status: instock | purchasable: no | price:  | parent: 1407
Variation 1670 price meta: {
  "_wcml_custom_prices_status": "1",
  "_price_USD": "49",
  "_sale_price_USD": "49",
  "_regular_price_USD": "",
  "_price": "49",
  "_regular_price": "",
  "_sale_price": "49"
}

關鍵在這裡:_price 雖然有值(49),但 _regular_price 是空的。WooCommerce 的 is_purchasable() 內部會同時檢查 price 與 regular_price 是否合法,當 regular_price 為空時,WooCommerce 某些版本會判定為不可購買,進而讓 get_available_variations() 過濾掉這個 variation。

根本原因:WPML 手動多幣別價格不回寫 _regular_price

WPML WooCommerce Multilingual 在「Set prices in other currencies manually」模式下,只會將價格寫入 _price_USD_sale_price_USD 等幣別專屬 meta,並不會同步回 WooCommerce 原生的 _regular_price。這導致:

  • get_available_variations():因 is_purchasable() 失敗而回傳空陣列
  • Elementor 加入購物車按鈕:顯示「out of stock and unavailable」
  • get_price_html():因 WooCommerce 認為 price 無效而回傳空字串

解決方案:改用 get_children() + 直接讀取 WCML meta

繞過 get_available_variations() 的 purchasable 檢查,改用 get_children() 取得所有 variation 子文章,再依序嘗試讀取價格 meta:

// 取得所有 variation(不依賴 is_purchasable)
$children = $product->get_children();

foreach ($children as $child_id) {
    $variation = wc_get_product($child_id);
    if (!$variation || get_post_status($child_id) !== 'publish') {
        continue;
    }

    // 優先用 WooCommerce 標準格式
    $price_html = $variation->get_price_html();

    if (!$price_html) {
        // 退回讀 WCML 幣別 meta
        $price = get_wcml_price($child_id);
        echo $price ? wc_price($price) : '—';
    }
}

function get_wcml_price(int $variation_id): string {
    $currency = get_woocommerce_currency();

    $keys = [
        '_price_' . $currency,
        '_sale_price_' . $currency,
        '_regular_price_' . $currency,
        '_price',
        '_sale_price',
        '_regular_price',
    ];

    foreach ($keys as $key) {
        $val = get_post_meta($variation_id, $key, true);
        if ($val !== '' && $val !== false) {
            return (string) $val;
        }
    }
    return '';
}

補充:WPML 語言切換對查詢的影響

排查過程中也嘗試過幾個常見建議,包括 wpml_switch_language('all') 或切換到預設語言再查詢,但效果有限。問題核心不在於語言過濾,而在於 variation 本身的 meta 資料不完整,導致 WooCommerce 認定不可購買。

如果你的站台是「有中文商品、再翻譯英文」的架構,WPML 會自動同步 variation,通常不會有這個問題。這個 bug 只出現在只建英文商品、沒有中文對應商品的特殊架構下。

常見問題 FAQ

為什麼 WPML 翻譯的 variation 沒有價格?

WPML WooCommerce Multilingual 在手動多幣別模式下,只會將價格存入幣別專屬 meta(如 _price_USD),不會同步回 WooCommerce 的 _regular_price。當你的商品只建立在翻譯語言(如英文)而沒有基底語言版本時,這個問題特別容易出現。

Elementor 加入購物車按鈕顯示缺貨,但庫存明明有設定?

這通常代表 WooCommerce 的 is_purchasable() 回傳 false。常見原因是 variation 的 _regular_price 為空,即使 _price 有值也會失敗。解法是直接在後台各 variation 手動填入售價,或透過程式讀取 WCML 幣別 meta 繞過這個限制。

get_available_variations() 和 get_children() 有什麼差別?

get_available_variations() 會過濾掉不可購買(is_purchasable() = false)的 variation,通常用於前台購買流程。get_children() 則直接回傳所有子文章 ID,不做任何過濾,適合用於展示列表(如規格表)而不需要觸發購買流程的場景。

▧ 文章分類

▧ 熱門文章

▧ 最新文章

✦ 虎鯨 OrcaBiz SEO 優化專業團隊 ✦

專業 SEO 公司幫助你將流量累積成看得見的業績,成為長期有效的最強業務!

[orca_infinite_scroll]