You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WordPress Polylang插件:复制文章时分类转移异常问题

问题背景与解决方法

问题描述

  • 需求:使用Polylang插件复制文章时,禁止自动创建未翻译的分类,仅将已有目标语言翻译的分类关联到新复制的文章。
  • 当前实现:通过pll_copy_taxonomies钩子拦截默认分类同步逻辑,用pll_get_term判断分类是否有对应翻译,再调用wp_set_object_terms关联已翻译分类,最后取消默认的category同步。
  • 异常现象:虽然实现了仅关联已翻译分类的需求,但删除原文章后,原文章中未翻译的分类会被大量重复创建,slug格式为exampleslug-1、exampleslug-2……这类带递增后缀的形式。

原代码:

add_filter('pll_copy_taxonomies', 'donotsync', 10, 5);
function donotsync($taxonomies, $sync, $from, $to, $lang) {
    //Bail early if not WP built-in posts
    if ('post' !== get_post_type($from)) {
        return $taxonomies;
    }

    //*** Get the post categories and transfer only the ones already translated
    //*** PROBLEM: This seems to work, but when the article with the default language gets eventually deleted, WP starts duplicating hundreds of copys of the categories from that post that don't have translations yet. Without this block of code, the categories aren't transferred and there's no error.
    $post_categories = get_the_category($from);
    foreach ($post_categories as $key => $terms) {
        $category_id = $terms->term_id;
        //Check if Polylang function exists
        if (function_exists('pll_get_term')) {
            //Check if translation for the category already exists and than transfer it to the duplicated post
            $term_translation = pll_get_term($category_id, $lang);
                if (!empty($term_translation)) {
                    wp_set_object_terms($to, $term_translation, 'category', true);
                }
        }
    }

    //Remove taxonomy sync
    unset($taxonomies['category']);
    return $taxonomies;
}

问题根源

原代码在pll_copy_taxonomies钩子执行期间直接调用WordPress原生函数wp_set_object_terms,打乱了Polylang内部的术语关联状态。当删除原文章时,Polylang的术语清理逻辑因状态异常,错误触发了未翻译分类的重复创建流程。

修复方案

改用Polylang提供的pll_post_translated钩子(文章翻译复制完成后触发)延迟处理分类关联,避免干扰Polylang内部执行逻辑:

add_filter('pll_copy_taxonomies', 'sync_only_translated_categories', 10, 5);
function sync_only_translated_categories($taxonomies, $sync, $from, $to, $lang) {
    // 仅处理文章类型
    if ('post' !== get_post_type($from)) {
        return $taxonomies;
    }

    // 先移除默认的category同步,彻底阻止Polylang自动创建未翻译分类
    unset($taxonomies['category']);

    // 延迟到文章翻译完成后再处理分类关联
    if (function_exists('pll_get_term')) {
        add_action('pll_post_translated', function($translated_post_id, $original_post_id, $lang) use ($from) {
            // 确保只处理当前触发的翻译操作
            if ($original_post_id !== $from) {
                return;
            }

            $post_categories = get_the_category($original_post_id);
            $translated_terms = [];

            // 收集所有已有翻译的分类ID
            foreach ($post_categories as $term) {
                $translated_term_id = pll_get_term($term->term_id, $lang);
                if (!empty($translated_term_id)) {
                    $translated_terms[] = $translated_term_id;
                }
            }

            // 批量设置分类,避免重复关联
            if (!empty($translated_terms)) {
                wp_set_object_terms($translated_post_id, $translated_terms, 'category', false);
            }
        }, 10, 3);
    }

    return $taxonomies;
}

关键修改点

  1. 提前移除category的默认同步,彻底阻断Polylang自动创建未翻译分类的逻辑。
  2. 使用pll_post_translated钩子确保在文章翻译流程完全结束后再修改分类关联,符合Polylang的执行顺序。
  3. 批量收集已翻译分类ID后一次性调用wp_set_object_terms(第三个参数设为false,替换而非追加分类),避免重复关联。
  4. 添加判断逻辑,确保只处理当前触发的翻译复制操作,避免误触发其他场景。

内容的提问来源于stack exchange,提问作者Butzke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 12:45:37