I. Introduction
Reference: Practical guide to blog tag translation | 8,060 tags, full workflow implemented via a PHP script. I used a custom PHP script to batch iterate through Chinese tags and automatically sync missing English translation tags. This script ran stably on WordPress 6.9 with zero errors and zero data anomalies, perfectly achieving a 1:1 alignment between Chinese and English tags.
After recently upgrading the site to WordPress 7.0, the script suddenly malfunctioned: it ran without errors but could not populate the missing English tags, resulting in a mismatch between the number of Chinese and English tags. After half a day of comprehensive troubleshooting, multiple code rewrites, database repairs, and trial-and-error testing, I finally identified the core issue and resolved it perfectly. This article documents the entire troubleshooting process, source code, execution logs, root cause, and final solution.
II. Initial Environment and Basic Configuration
– Site application: WordPress 7.0 (originally stable version 6.9)
– Multilingual plugin: Polylang latest stable version
– Cache plugin: W3 Total Cache
– Runtime environment: Linux, PHP 8.1, Alibaba Cloud RDS MySQL
– Script functionality: Only reads Chinese tags, automatically detects missing English tags, and only adds new English tags; it does not modify or delete any original Chinese data
III. Issue Symptoms (After upgrading to WP 7.0)
After upgrading the site to WP 7.0, I added 3 new Chinese tags (360, Sitemap, 站点地图). The backend Chinese and English tag data was as follows:
– Total Chinese tags: 8,274
– Total English tags: 8,271
– Data difference: 3 missing English translation tags
– Anomaly: Backend English tags not synced
I executed the sync script that originally worked on WP 6.9. The execution log is below; the script determined there were no tags to process and completely failed:
[root@iZ23wv7v5ggZ www.shuijingwanwq.com]# php polylang-batch-zh-to-en-tags.php
🚀 开始批量处理所有zh标签,自动添加en翻译(分页模式)...
📊 正在处理第 1 - 1000 个标签...
🔰 正在处理: 360 (ID: 36603)
📊 正在处理第 1001 - 2000 个标签...
📊 正在处理第 2001 - 3000 个标签...
📊 正在处理第 3001 - 4000 个标签...
📊 正在处理第 4001 - 5000 个标签...
🔰 正在处理: Sitemap (ID: 36607)
📊 正在处理第 5001 - 6000 个标签...
📊 正在处理第 6001 - 7000 个标签...
📊 正在处理第 7001 - 8000 个标签...
🔰 正在处理: 站点地图 (ID: 36604)
📊 正在处理第 8001 - 8274 个标签...
🎉 全部处理完成!
📊 统计:
已处理新标签: 0
已跳过已有翻译: 8271
✅ 所有标签都已经处理完毕,和手动添加的完全一样!
Core anomaly: The script detected that 8,271 tags already had translations and 0 were newly added, but 3 English tags were actually missing. This was a false positive where the script incorrectly determined they were already translated.
IV. Multiple Rounds of Troubleshooting and Pitfall Records
1. Pitfall 1: Assuming WP 7.0 underlying API incompatibility
I initially suspected that WordPress 7.0 had refactored the underlying logic for terms and tags, causing the old Polylang API to fail. I tried modifying the script: replacing the native Polylang translation binding method, switching to $wpdb for direct underlying writes, manually adding language assignment fields, and binding translation group IDs.
This caused a new issue: tags written directly to the database could not have their language identified by Polylang. They all became dirty data with no language assigned, the backend English list did not count them, and the all-languages view showed a large number of duplicate tags, further aggravating the problem.
2. Pitfall 2: Adding dirty data cleanup logic caused the script to hang and corrupt data
To solve the duplicate dirty tags issue, I added SQL logic to batch query and delete tags with no assigned language. Because the site had over 8,000 tags in total, the heavy operation of looping joined queries and deleting records one by one caused the script to hang with no output.
After forcibly terminating the script, catastrophic data anomalies occurred: the total number of English tags plummeted from 8,000+ to 2 (see Figure 1), a large number of normal English tags were mistakenly deleted, and redundant Chinese tags were added (see Figure 2), completely corrupting the data.


3. Pitfall 3: Polylang version API parameter error
I tried using the new official Polylang function pll_save_term_translations() to bind translation relationships, but running it directly threw a PHP fatal error: parameter type mismatch. This proved that the AI-adapted new version code had compatibility bugs and was not universally applicable.
V. Identifying the Core Root Cause (The Final Truth)
All code rewrites and underlying adaptations were ineffective. Ultimately, by restoring the environment and clearing the cache for testing, I pinpointed the true cause of the failure:
After the WordPress 7.0 upgrade, W3 Total Cache retained residual cache from the old Polylang translation relationships.
This residual cache caused the pll_get_term() function to read cached data instead of the actual database data, falsely determining that the 3 missing tags already had English translations and directly skipping the creation logic, which caused the script to fail.
This failure was unrelated to the code version or the WP underlying API; it was purely a data determination distortion caused by residual cache.
VI. Final Solution (Perfect fix with zero modifications to the original script)
1. Prerequisite repair operations
1. Restored the database to a clean backup from before the WP 7.0 upgrade via Alibaba Cloud RDS, reverting all corrupted tag data;
2. Logged into the WordPress backend → Performance (W3 Total Cache) → Dashboard → Empty All Caches, thoroughly clearing the residual translation relationship cache and term cache;
3. Kept the original working script from WP 6.9 without making any code modifications.
2. Final working original script (compatible with both WP 6.9 and 7.0)
polylang-batch-zh-to-en-tags.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';
echo "🚀 开始批量处理所有{$source_lang}标签,自动添加{$target_lang}翻译(分页模式)...\n\n";
$processed = 0;
$skipped = 0;
$offset = 0;
while (true) {
// 分页拿源语言标签
$terms = get_terms([
'taxonomy' => 'post_tag',
'lang' => $source_lang,
'hide_empty' => false,
'number' => $per_page,
'offset' => $offset,
]);
if (is_wp_error($terms) || empty($terms)) {
break;
}
$current_count = count($terms);
echo "📊 正在处理第 " . ($offset + 1) . " - " . ($offset + $current_count) . " 个标签...\n";
foreach ($terms as $term) {
$source_id = $term->term_id;
$name = $term->name;
$slug = $term->slug;
// 检查是不是已经有目标语言的翻译了
$target_id = pll_get_term($source_id, $target_lang);
if ($target_id) {
$skipped++;
continue;
}
echo "🔰 正在处理: {$name} (ID: {$source_id})\n";
// 创建目标语言标签,绕过slug重复检查
$wpdb->insert($wpdb->terms, [
'name' => $name,
'slug' => $slug,
'term_group' => 0
]);
$new_target_id = $wpdb->insert_id;
// 目标语言标签的taxonomy
$wpdb->insert($wpdb->term_taxonomy, [
'term_id' => $new_target_id,
'taxonomy' => 'post_tag',
'description' => '',
'parent' => 0,
'count' => 0
]);
// 设置目标语言
$polylang->model->term->set_language($new_target_id, $target_lang);
// 绑定翻译
$polylang->model->term->save_translations($source_id, [
$target_lang => $new_target_id
]);
$processed++;
}
$offset += $per_page;
unset($terms);
gc_collect_cycles();
}
echo "\n🎉 全部处理完成!\n";
echo "📊 统计:\n";
echo " 已处理新标签: {$processed}\n";
echo " 已跳过已有翻译: {$skipped}\n";
echo "\n✅ 所有标签都已经处理完毕,和手动添加的完全一样!\n";3. Final successful execution log
[root@iZ23wv7v5ggZ www.shuijingwanwq.com]# php polylang-batch-zh-to-en-tags.php
🚀 开始批量处理所有zh标签,自动添加en翻译(分页模式)...
📊 正在处理第 1 - 1000 个标签...
🔰 正在处理: 360 (ID: 36603)
📊 正在处理第 1001 - 2000 个标签...
📊 正在处理第 2001 - 3000 个标签...
📊 正在处理第 3001 - 4000 个标签...
📊 正在处理第 4001 - 5000 个标签...
🔰 正在处理: Sitemap (ID: 36607)
📊 正在处理第 5001 - 6000 个标签...
📊 正在处理第 6001 - 7000 个标签...
📊 正在处理第 7001 - 8000 个标签...
🔰 正在处理: 站点地图 (ID: 36604)
📊 正在处理第 8001 - 8274 个标签...
🎉 全部处理完成!
📊 统计:
已处理新标签: 3
已跳过已有翻译: 8271
✅ 所有标签都已经处理完毕,和手动添加的完全一样!
VII. Final Repair Results
– Total Chinese tags: 8,274 (no additions or deletions, original data intact)
– Total English tags: 8,274 (successfully populated 3 missing tags)
– No dirty tags without a language, no duplicate tags
– Perfect 1:1 alignment between Chinese and English tags, with translation relationships correctly bound
VIII. Summary and Lessons Learned
1. After a major WP version upgrade, prioritize clearing the site-wide cache and plugin caches before testing existing custom scripts; do not blindly assume code incompatibility;
2. For Polylang multilingual sites, translation relationships and term determinations rely heavily on cache. Residual cache will cause functions to make false determinations;
3. Prioritize keeping original, stably running scripts. Do not blindly rewrite them to adapt to new versions, as most “compatibility issues” are caused by caching;
4. Never add full-database loop deletion logic in batch scripts. Under large data volumes, this can easily cause the script to hang and mistakenly delete normal data.

