没有不值得去解决的问题,也没有不值得去学习的技术!

Troubleshooting and Fixing Accuracy Issues in the WP Tag Batch Translation Script

The script shows 8324 tags processed

作者:

在

Problem Background

While using the Polylang plugin to synchronize Chinese and English tags, I found that the batch translation script had an intermittent counting inaccuracy issue. The script showed that it processed 8324 tags, but there were actually 8328 Chinese tags in the backend, and the results were inconsistent with each execution.

The script shows 8324 tags processed

Symptoms

Plaintext
Total source language tags: 8328 Accurate
New tags processed: 0 Inaccurate (theoretically should be 4)
Existing translations skipped: 9000 Inaccurate (should be 8324)
Processing rate: 108.07%

Troubleshooting Process

First Investigation: Pagination Method Issue

Initially, I used the offset parameter for pagination:

PHP
$terms = get_terms([
    'taxonomy' => 'post_tag',
    'lang' => $source_lang,
    'number' => $per_page,
    'offset' => $offset,
]);

Problem Analysis: When using offset for pagination, creating new target language tags during processing changes the number of records in the database, causing subsequent pagination offsets to be inaccurate.

Fix Attempt: Switched to the paged parameter instead of offset:

PHP
$terms = get_terms([
    'taxonomy' => 'post_tag',
    'lang' => $source_lang,
    'number' => $per_page,
    'paged' => $page,
]);

Second Investigation: Database Table Does Not Exist

After the modification, a new error occurred:

Plaintext
WordPress database error Table 'wp_polylang_terms' doesn't exist

Problem Analysis: I directly queried a non-existent Polylang database table. I should have used the API functions provided by Polylang.

Fix Attempt: Referring to the existing merge-tags.php file in the project, I switched to using get_terms() with the lang parameter to retrieve the tag list.

Third Investigation: Counting Still Inaccurate

Even when using the paged parameter, the count was still inaccurate:

Plaintext
Existing translations skipped: 9000

Problem Analysis: When using get_terms() for paginated queries, the newly created English tags were fetched by subsequent queries, causing the skipped count to be incorrect.

Root Cause: The English tags created during the loop processing were captured by subsequent get_terms() queries because the query conditions only restricted the language, but the newly created English tags might have been cached or re-indexed.

Final Solution

Core Idea: First, retrieve the ID list of all source language tags at once, and then process based on this static list to prevent subsequent queries from being affected by the newly created data.

PHP
// 先一次性获取所有源语言标签的ID列表
$source_term_ids = get_terms([
    'taxonomy' => 'post_tag',
    'lang' => $source_lang,
    'hide_empty' => false,
    'fields' => 'ids',
]);

// 使用 array_chunk 分批处理
foreach (array_chunk($source_term_ids, $per_page) as $batch) {
    foreach ($batch as $term_id) {
        // 处理每个标签...
    }
}

Key Improvements:

  1. Static List: Retrieve the complete source language tag ID list in advance to prevent subsequent queries from being polluted by new data
  2. Array Chunking: Use array_chunk() for memory-friendly batch processing
  3. Accurate Counting: Count based on the static list to ensure statistical accuracy

Complete Optimized Code

PHP
<?php
if (php_sapi_name() !== 'cli') {
    die("❌ 请在命令行运行\n");
}

require __DIR__ . '/wp-config.php';
global $wpdb, $polylang;

$per_page = 1000;
$source_lang = 'zh';
$target_lang = 'en';

$processed = 0;
$skipped = 0;

// 先一次性获取所有源语言标签的ID列表
$source_term_ids = get_terms([
    'taxonomy' => 'post_tag',
    'lang' => $source_lang,
    'hide_empty' => false,
    'fields' => 'ids',
]);

$total_terms = count($source_term_ids);

// 分批处理
foreach (array_chunk($source_term_ids, $per_page) as $batch) {
    foreach ($batch as $term_id) {
        $term = get_term($term_id, 'post_tag');

        // 检查是否已有翻译
        $target_id = pll_get_term($term_id, $target_lang);
        if ($target_id) {
            $skipped++;
            continue;
        }

        // 创建翻译标签...
        $processed++;
    }
}

// 验证阶段
$untranslated_count = 0;
foreach ($source_term_ids as $term_id) {
    if (!pll_get_term($term_id, $target_lang)) {
        $untranslated_count++;
    }
}

Fix Results

Execution results after the fix:

Plaintext
Total source language tags: 8328 ✅
New tags processed: 4 ✅
Existing translations skipped: 8324 ✅
Processing rate: 100.00% ✅
Execution results after the fix:

Lessons Learned

  1. Avoid Dynamic Pagination Pitfalls: In scenarios where data is modified during processing, avoid using dynamic paginated queries
  2. Use Static Datasets: Retrieve the complete ID list in advance to ensure processing stability
  3. Rely on Official APIs: Prioritize using API functions provided by the plugin to avoid directly operating on database tables
  4. Add Verification Steps: Perform verification after processing is complete to ensure all data is processed correctly

References


This article documents the troubleshooting process of the batch tag translation script, from discovering the issue to the final resolution, in hopes of helping developers who encounter similar problems.

系列导航

关于作者 · 持续学习与技术实践

我是一名拥有 15 年以上开发经验的技术从业者,自 2013 年起持续运营个人技术博客,记录工作与个人项目中遇到的真实问题,以及解决问题过程中的探索、实践和思考。

除了技术写作,我也在持续开发和维护自己的独立项目,探索新技术和新工具在实际场景中的应用。我始终相信,没有不值得去解决的问题,也没有不值得去学习的技术。

如果这篇文章对你有所帮助,欢迎浏览博客中的其他文章,也欢迎交流技术经验与想法。

关于我  ·  GitHub  ·  邮件联系