term_id function translate_or_mirror($c, $lang, &$cache) { $key = $c . '|' . $lang; if (isset($cache[$key])) return $cache[$key]; $t = pll_get_term($c, $lang); if (!$t) { $term = get_term($c, 'category'); if (!$term || is_wp_error($term)) { return $cache[$key] = $c; } $slug = sanitize_title($term->name) . '-' . $lang . '-' . $c; $res = wp_insert_term($term->name, 'category', ['slug' => $slug]); if (is_wp_error($res)) { $ex = $res->get_error_data(); if (!$ex) { return $cache[$key] = $c; } $t = is_array($ex) ? ($ex['term_id'] ?? 0) : (int) $ex; } else { $t = $res['term_id']; } if ($t) { pll_set_term_language($t, $lang); $tr = pll_get_term_translations($c); $tr[$lang] = $t; pll_save_term_translations($tr); } else { $t = $c; } } return $cache[$key] = (int) $t; } $langs = $only_lang ? [$only_lang] : ['en','fr','it','pt']; $done = 0; $changed = 0; $mirrors = 0; $start_mirror_terms = count($mirror_cache); foreach ($langs as $lang) { $args = ['lang'=>$lang,'post_type'=>'post','post_status'=>['publish','draft'], 'fields'=>'ids','posts_per_page'=> $limit ?: -1,'no_found_rows'=>true, 'meta_query'=>[['key'=>'_cats_reasignadas','compare'=>'NOT EXISTS']]]; $ids = get_posts($args); foreach ($ids as $pid) { // Fuente de verdad = categorías del ES original (las del post traducido // pueden estar incompletas). Se traducen al idioma del post. $es = pll_get_post($pid, 'es'); $source = ($es && $es != $pid) ? wp_get_post_categories($es) : wp_get_post_categories($pid); $new = []; foreach ($source as $c) { $clang = pll_get_term_language($c); $new[] = ($clang === $lang) ? $c : translate_or_mirror($c, $lang, $mirror_cache); } $new = array_values(array_unique($new)); $cur = wp_get_post_categories($pid); sort($cur); $cmp = $new; sort($cmp); if ($cur !== $cmp && $new) { wp_set_post_categories($pid, $new); $changed++; } update_post_meta($pid, '_cats_reasignadas', 1); $done++; } } echo "procesados: $done | con cambios: $changed | términos espejo en caché: " . count($mirror_cache) . "\n";