WooCommerce Transliterate Slugs | Cododel
CODODELDEV
EN / RU
Back to Deck
[snippet]

WooCommerce Transliterate Slugs

SOURCE PHP
VERSION 1.0
AUTHOR Cododel

A one-time execution PHP snippet for WordPress/WooCommerce that transliterates Cyrillic attribute and term slugs to Latin. Preserves original display names while fixing URL-unsafe slugs.

The Problem

WooCommerce attributes and terms with Cyrillic names create URL-unsafe slugs:

  • Attribute: pa_цвет → Should be pa_cvet
  • Term: красный → Should be krasnyj

This causes issues with:

  • SEO (non-Latin URLs)
  • URL encoding problems
  • Database indexing
  • API compatibility

⚠️ Important Warnings

  1. BACKUP YOUR DATABASE before running this script
  2. This is a one-time execution snippet
  3. It modifies your database directly
  4. Remove the code after execution
  5. Test on staging environment first

Features

  • ✅ Transliterates Cyrillic to Latin for attribute slugs
  • ✅ Updates term slugs while preserving names
  • ✅ One-time execution with option check
  • ✅ Proper WooCommerce API usage
  • ✅ Cache invalidation
  • ✅ Error logging

Usage Instructions

  1. Backup database:

    Terminal window
    # Via wp-cli
    wp db export backup.sql
  2. Add to functions.php:

    // Add the entire code below to your theme's functions.php
  3. Load any page on your WordPress site to trigger execution

  4. Verify results:

    • Check WooCommerce → Attributes
    • Verify product attribute URLs
  5. Remove the code from functions.php after execution

Example Transformations

BeforeAfter
pa_цветpa_cvet
pa_размерpa_razmer
красныйkrasnyj
большойbolshoy

Source Code

update-wc-attributes-terms-slugs.php

<?php
function update_woocommerce_attributes_and_terms() {
// Получаем все атрибуты WooCommerce
$attributes = wc_get_attribute_taxonomies();
if (empty($attributes)) {
return;
}
foreach ($attributes as $attribute) {
$old_taxonomy = wc_attribute_taxonomy_name($attribute->attribute_name);
$new_attribute_name = cyr_to_lat_sanitize($attribute->attribute_name);
$new_taxonomy = wc_attribute_taxonomy_name($new_attribute_name);
// Если slug атрибута нужно обновить
if ($new_attribute_name !== $attribute->attribute_name) {
// Обновляем атрибут через WooCommerce
$attribute_data = [
'id' => $attribute->attribute_id,
'name' => $attribute->attribute_label, // Оставляем оригинальное название
'slug' => $new_attribute_name,
'type' => $attribute->attribute_type,
'order_by' => $attribute->attribute_orderby,
'has_archives' => $attribute->attribute_public
];
$result = wc_update_attribute($attribute->attribute_id, $attribute_data);
if (is_wp_error($result)) {
error_log("Failed to update attribute {$attribute->attribute_name}: " . $result->get_error_message());
continue;
}
// Обновляем термины для старой таксономии
$terms = get_terms([
'taxonomy' => $old_taxonomy,
'hide_empty' => false,
]);
if (!is_wp_error($terms)) {
foreach ($terms as $term) {
$new_term_slug = cyr_to_lat_sanitize($term->slug);
if ($new_term_slug !== $term->slug) {
wp_update_term($term->term_id, $new_taxonomy, [
'slug' => $new_term_slug,
// Название термина не меняем
]);
}
}
}
// Удаляем старую таксономию и регистрируем новую
unregister_taxonomy($old_taxonomy);
register_taxonomy(
$new_taxonomy,
'product',
[
'label' => $attribute->attribute_label,
'public' => (bool) $attribute->attribute_public,
'hierarchical' => false,
'show_ui' => false,
]
);
}
// Обновляем slug терминов даже если атрибут не менялся
$terms = get_terms([
'taxonomy' => $new_taxonomy,
'hide_empty' => false,
]);
if (!is_wp_error($terms)) {
foreach ($terms as $term) {
$new_term_slug = cyr_to_lat_sanitize($term->slug);
if ($new_term_slug !== $term->slug) {
wp_update_term($term->term_id, $new_taxonomy, [
'slug' => $new_term_slug,
// Название термина не меняем
]);
}
}
}
}
// Очищаем кэш
delete_transient('wc_attribute_taxonomies');
WC_Cache_Helper::invalidate_cache_group('woocommerce-attributes');
wp_cache_flush();
}
// Выполняем один раз
add_action('init', function() {
if (get_option('update_wc_attributes_and_terms') !== 'done') {
update_woocommerce_attributes_and_terms();
update_option('update_wc_attributes_and_terms', 'done');
}
});
// Функция транслитерации
function cyr_to_lat_sanitize($text) {
$cyr = [
'а'=>'a', 'б'=>'b', 'в'=>'v', 'г'=>'g', 'д'=>'d', 'е'=>'e', 'ё'=>'yo', 'ж'=>'zh',
'з'=>'z', 'и'=>'i', 'й'=>'y', 'к'=>'k', 'л'=>'l', 'м'=>'m', 'н'=>'n', 'о'=>'o',
'п'=>'p', 'р'=>'r', 'с'=>'s', 'т'=>'t', 'у'=>'u', 'ф'=>'f', 'х'=>'h', 'ц'=>'ts',
'ч'=>'ch', 'ш'=>'sh', 'щ'=>'sht', 'ъ'=>'', 'ы'=>'y', 'ь'=>'', 'э'=>'e', 'ю'=>'yu',
'я'=>'ya',
'А'=>'A', 'Б'=>'B', 'В'=>'V', 'Г'=>'G', 'Д'=>'D', 'Е'=>'E', 'Ё'=>'Yo', 'Ж'=>'Zh',
'З'=>'Z', 'И'=>'I', 'Й'=>'Y', 'К'=>'K', 'Л'=>'L', 'М'=>'M', 'Н'=>'N', 'О'=>'O',
'П'=>'P', 'Р'=>'R', 'С'=>'S', 'Т'=>'T', 'У'=>'U', 'Ф'=>'F', 'Х'=>'H', 'Ц'=>'Ts',
'Ч'=>'Ch', 'Ш'=>'Sh', 'Щ'=>'Sht', 'Ъ'=>'', 'Ы'=>'Y', 'Ь'=>'', 'Э'=>'E', 'Ю'=>'Yu',
'Я'=>'Ya'
];
$text = strtr($text, $cyr);
$text = preg_replace('/[^a-zA-Z0-9\s-]/', '', $text);
return sanitize_title(trim($text));
}
[ ▲ 0 ]