WPIntell

Source evidence

Woocommerce attribute issue

Cyr-To-Lat · support · 2026-02-08T07:52:00+00:00

complaintsentiment
highseverity
0.83relevance
17replies
Evidence linked to opportunitycommercial context

Proof Health

Open evidence

Commercial opportunities need traceable source links before they are treated as build-worthy.

5 / 47 rows with source links

10.6% of this page's analysis has direct source links.

0 build-decision rows missing links

0 rows here require auditable proof before promotion.

42 rows with no attached evidence

0 rows have source counts but still need direct links.

Conversation

support
uxtora resolved
Привет. Данный плагин супер, но есть один минус в плане работы с WooCommerce и любыми языками кроме англ. Дело в том, что он автоматом таки переводит ВНУТРЕННИЕ атрибуты в товаре, ровно как и глобальные. Хотя не должен этого делать, ибо тогда ломается стандартный вывод вариантов товара в корзине. Т.е допустим я добавил внутренний(!) атрибут “Цвет”. По итогу он будет выводить его как tsvet. Хотя из коробки WooCommerce выводит так, как написали, ибо это не сущность. Почему is_wc_attribute() ВСЕГДА возвращает false для внутренних атрибутов: is_wc_attribute_taxonomy() → проверяет глобальные атрибуты WooCommerce Внутренний атрибут “цвет” → НЕ глобальный → false is_wc_product_not_converted_attribute() → сломанная логика: php protected function is_wc_product_not_converted_attribute( string $title ): bool { global $product; // ← ПРОБЛЕМА 1: часто NULL if ( ! is_a( $product, 'WC_Product' ) ) { return false; // ← Часто срабатывает здесь } $attributes = (array) get_post_meta( $product->get_id(), '_product_attributes', true ); // ... проверяет уже сохранённые атрибуты } Почему global $product часто NULL: При сохранении товара из админки WooCommerce не всегда устанавливает эту глобальную переменную. При AJAX-обработке атрибутов она точно не установлена Метод вызывается из контекста sanitize_title(), а не из страницы товара Итог: is_wc_attribute_taxonomy(“цвет”) → false is_wc_product_not_converted_attribute(“цвет”) → false (потому что global $product = NULL) is_wc_attribute(“цвет”) → false transliterate(“цвет”) → “tsvet” Ошибка в коде: Метод is_wc_product_not_converted_attribute() пытается определить атрибут по уже сохранённым данным, но не учитывает, что: НОВЫЙ атрибут ещё не сохранён Глобальная переменная $product не установлена в нужном контексте Надо проверять не метаполя, а $_POST данные или контекст сохранения товара Да, проблема известная. Спасибо за более подробное описание. Постараемся найти время и пофиксить. Я поправил. Посмотрите 6.7.0-RC1 – решает вашу проблему? https://github.com/mihdan/cyr2lat/releases/download/v6.7.0-RC1/cyr2lat.6.7.0-RC1.zip Похоже, что не решает… Вижу сам. Вернусь к этой теме позже. Твой фикс ловит только woocommerce_save_attributes . Это AJAX-сохранение внутри карточки “сохранить атрибуты”, там вроде всё ок. Но основная проблема — при полном сохранении товара. Когда жмёшь «Опубликовать» или «Обновить», WooCommerce не вызывает этот экшн. Атрибуты приходят в $_POST['attribute_names'] и сохраняются напрямую в _product_attributes . + у массового редактирования… Расширить метод is_local_attribute() ? protected function is_local_attribute( string $title ): bool { // 1. Глобальные атрибуты — не трогаем, это не локальные if ( 0 === strpos( $title, 'pa_' ) ) { return false; } // 2. Сохранение через карточку товара (редактирование атрибутов) $action = isset( $_POST['action'] ) ? sanitize_text_field( wp_unslash( $_POST['action'] ) ) : ''; if ( 'woocommerce_save_attributes' === $action ) { $data = isset( $_POST['data'] ) ? filter_input( INPUT_POST, 'data', FILTER_SANITIZE_URL ) : ''; wp_parse_str( urldecode( $data ), $attributes ); $attribute_names = $attributes['attribute_names'] ?? []; return in_array( $title, $attribute_names, true ); } // 3. Полное сохранение товара (кнопка «Обновить») if ( doing_action( 'save_post' ) || doing_action( 'wp_insert_post' ) ) { if ( isset( $_POST['attribute_names'] ) && is_array( $_POST['attribute_names'] ) ) { return in_array( $title, $_POST['attribute_names'], true ); } } return false; } Как считаешь, это решит проблему полностью? По-хорошему нужно вообще тотально вырезать работу с внутренними атрибутами и вообще их не трогать ровно как и глобальные. Это не в “политике” плагина. ну или protected function is_local_attribute( string $title ): bool { // ВСЁ ЧТО НЕ pa_ — ЭТО ВНУТРЕННИЙ АТРИБУТ, НЕ ТРОГАЕМ if ( 0 !== strpos( $title, 'pa_' ) ) { return true; } return false; } ? В настройках плагина есть флажок «Товары (product)», но он отключает только фоновую конвертацию существующих слагов. Живая транслитерация при сохранении товара и атрибутов всё равно работает , потому что висит на sanitize_title и не проверяет эту настройку. Предлагаю либо: Сделать, чтобы sanitize_title уважал настройку «Товары (product)», либо Добавить отдельную настройку «Не трогать атрибуты WooCommerce» (+ разделить какие именно не трогать). Я предлагаю вариант 2 — просто исключить всё с префиксом pa_ и всё без pa_ в контексте WooCommerce. Просто например при синхронизации товаров с моим складом ломается абсолютно всё, ибо все синхронизации заточены под ваниль, а не под переведённые Или вовсе так: public function sanitize_title( $title, $raw_title = '', $context = '' ) { global $wpdb; // Не транслитерировать при создании глобальных WC атрибутов if ( function_exists( 'wc_sanitize_taxonomy_name' ) ) { $trace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ); foreach ( $trace as $call ) { if ( isset( $call['function'] ) && $call['function'] === 'wc_sanitize_taxonomy_name' ) { return $title; } } } if ( ! $title || 'query' === $context || ! $this->transliterate_on_pre_term_slug_filter( (string) $title ) ) { return $title; } $title = urldecode( (string) $title ); $pre = apply_filters( 'ctl_pre_sanitize_title', false, $title ); if ( false !== $pre ) { return $pre; } if ( $this->is_term ) { $this->is_term = false; if ( $this->is_frontend && class_exists( SitePress::class ) ) { return $title; } $sql = $wpdb->prepare( "SELECT slug FROM $wpdb->terms t LEFT JOIN $wpdb->term_taxonomy tt ON t.term_id = tt.term_id WHERE t.slug = %s", rawurlencode( $title ) ); if ( $this->taxonomies ) { $sql .= ' AND tt.taxonomy IN (' . $this->prepare_in( $this->taxonomies ) . ')'; } $term = $wpdb->get_var( $sql ); if ( ! empty( $term ) ) { return $term; } } return $this->is_wc_attribute( $title ) ? $title : $this->transliterate( $title ); } } This reply was modified 3 months, 2 weeks ago by uxtora . Я сделал себе “личный cyr-to-lat. Он переводит всё кроме атрибутов. Если интересно – скажи, скину Нет, спасибо. Если есть желание – можно сделать PR на GitHub, с тестами. Я сделаю позже фильтр на WC атрибуты, чтобы закрыть проблему. И более корректную обработку атрибутов. К слову, debug_backtrace – не решение. Это тормоз. нене, я сделал вообще иначе, без debug_backtrace . Твой плагин не трогал. И всё что было в прошлых коммах тоже не использовал. Вот если интересно – https://github.com/uxtora/cyr-to-lat-wp-personal-.git Проверил, работает. Что думаешь? Если поможет в фиксе – буду рад. This reply was modified 3 months, 2 weeks ago by uxtora . This reply was modified 3 months, 2 weeks ago by uxtora . Дополнил Привет. Нашёл ещё одну очень сильную проблему. Возможно она появилась после обновлений – хз. Если сохранить страницу и потом поменять слаг напрямую – он возвращает старый после сохранения. Т,е допустим ты создал страницу “Главная”, он создал ей слаг “glavnaya”. Нажал сохранить. Страница сохранилась. Потом ты решил поменять слаг вручную на “home”. Идешь редачить, AJAX улетает, вроде всё окей, но при сохранении получаешь опять старый слаг. Т.е пост нейм у него почему-то пустой. Я проверил несколько плагинов и везде такая же проблема. + тестировал, просто делал ключи+санитайз = та же проблема. Я решил лишь при прямой перезаписи в БД, но это не совсем правильно т.к обходятся стандартные хуки и тд. Но вроде как при аяксе пофигу… Не знаю. Там есть дебаг файлы, попробуй убери $wpdb->update и поменяй на ванилу, тебе вернёт старый слаг. Короче вп.. https://github.com/uxtora/cyr-to-lat-wp-personal-/blob/main/record%20to%20DB%20AJAX This reply was modified 3 months, 1 week ago by uxtora . This reply was modified 3 months, 1 week ago by uxtora . Спасибо за детали. По основной теме — я вернусь к этому вопросу позже. Что касается предложенного решения через кастомный плагин: спасибо, что поделились, но я не могу разбирать и отлаживать сторонний/самописный код. Это выходит за рамки поддержки нашего плагина. Привет. Поправили? Мы выпустили новую версию 6.7.0. Посмотрите, решает ли она проблему. Нет, в версии 6.7.0 проблема с русскими кастомными Ву-атрибутами сохраняется. Плагин Cyr-to-lat вмешивается в названия кастомных кириллических атрибутов уже при вычитке из БД. Отключем Cyr-to-lat Создаем пользовательский атрибут с кириллческими буквами . На этом шаге Ву сразу создает вариации, если атрибут сделали вариативным. Давайте после активации плагина Cyr-to-lat попробуем выбрать для вариации значение по умолчанию. Включаем плагин. Затем только обновляем страницу редактора товарной карточки и на вкладке Вариации значения атрибутов name в HTML-элементах select уже транслитерировались. В БД в сериализованном представлении объектов атрибутов хранятся URL-кодированные ключи: %d… , но до SELECT’ов доезжают уже преобразованные в латиницу значения 🙂 В текущей версии остается только определять контекст вызова функции sanitize_title() и вешатся на хук 'ctl_pre_sanitize_title' , чтобы вместо false вернуть оригинальную строку и тем заставить плагин оставить в покое строки, которые Ву отправил в sanitize_title() 🙂 This reply was modified 1 month ago by Mikhail Alferov . Спасибо за подробное описание. Похоже, что это уже другой сценарий, не тот, который изначально обсуждался в этом тикете. В версии 6.7.0 мы исправляли обработку WooCommerce-атрибутов в сценарии, когда Cyr2Lat уже активен и атрибуты создаются/сохраняются после этого. Сценарий, когда WooCommerce-атрибуты были созданы и сохранены до включения Cyr2Lat, а затем плагин был активирован на уже существующем магазине, сейчас не поддерживается. В таком случае данные уже могут быть сохранены WooCommerce в одном формате, а после активации Cyr2Lat часть значений может проходить через стандартные механизмы sanitize_title() / обработки slug’ов и отображаться иначе. Мы не можем гарантировать корректное восстановление или автоматическую совместимость для атрибутов, сохранённых до включения плагина. Иными словами: новые WooCommerce-атрибуты, создаваемые при активном Cyr2Lat, должны обрабатываться корректно; но существующие атрибуты, сохранённые до активации Cyr2Lat, могут потребовать ручной корректировки или отдельной миграции данных. Такой migration scenario сейчас находится вне рамок поддержки плагина. Если сможете воспроизвести проблему на чистой установке, где Cyr2Lat активен до создания атрибутов, пожалуйста, опишите точные шаги в новом тикете — тогда это будет уже баг в поддерживаемом сценарии.

Comments

17 shown
kaggdesign 2026-02-08T07:54:00+00:00

Да, проблема известная. Спасибо за более подробное описание. Постараемся найти время и пофиксить.

kaggdesign 2026-02-08T12:26:00+00:00

Я поправил. Посмотрите 6.7.0-RC1 – решает вашу проблему? https://github.com/mihdan/cyr2lat/releases/download/v6.7.0-RC1/cyr2lat.6.7.0-RC1.zip

kaggdesign 2026-02-08T19:36:00+00:00

Похоже, что не решает… Вижу сам. Вернусь к этой теме позже.

uxtora 2026-02-11T17:11:00+00:00

Твой фикс ловит только woocommerce_save_attributes . Это AJAX-сохранение внутри карточки “сохранить атрибуты”, там вроде всё ок. Но основная проблема — при полном сохранении товара. Когда жмёшь «Опубликовать» или «Обновить», WooCommerce не вызывает этот экшн. Атрибуты приходят в $_POST['attribute_names'] и сохраняются напрямую в _product_attributes . + у массового редактирования… Расширить метод is_local_attribute() ? protected function is_local_attribute( string $title ): bool { // 1. Глобальные атрибуты — не трогаем, это не локальные if ( 0 === strpos( $title, 'pa_' ) ) { return false; } // 2. Сохранение через карточку товара (редактирование атрибутов) $action = isset( $_POST['action'] ) ? sanitize_text_field( wp_unslash( $_POST['action'] ) ) : ''; if ( 'woocommerce_save_attributes' === $action ) { $data = isset( $_POST['data'] ) ? filter_input( INPUT_POST, 'data', FILTER_SANITIZE_URL ) : ''; wp_parse_str( urldecode( $data ), $attributes ); $attribute_names = $attributes['attribute_names'] ?? []; return in_array( $title, $attribute_names, true ); } // 3. Полное сохранение товара (кнопка «Обновить») if ( doing_action( 'save_post' ) || doing_action( 'wp_insert_post' ) ) { if ( isset( $_POST['attribute_names'] ) && is_array( $_POST['attribute_names'] ) ) { return in_array( $title, $_POST['attribute_names'], true ); } } return false; } Как считаешь, это решит проблему полностью? По-хорошему нужно вообще тотально вырезать работу с внутренними атрибутами и вообще их не трогать ровно как и глобальные. Это не в “политике” плагина.

uxtora 2026-02-11T17:14:00+00:00

ну или protected function is_local_attribute( string $title ): bool { // ВСЁ ЧТО НЕ pa_ — ЭТО ВНУТРЕННИЙ АТРИБУТ, НЕ ТРОГАЕМ if ( 0 !== strpos( $title, 'pa_' ) ) { return true; } return false; } ?

uxtora 2026-02-11T17:27:00+00:00

В настройках плагина есть флажок «Товары (product)», но он отключает только фоновую конвертацию существующих слагов. Живая транслитерация при сохранении товара и атрибутов всё равно работает , потому что висит на sanitize_title и не проверяет эту настройку. Предлагаю либо: Сделать, чтобы sanitize_title уважал настройку «Товары (product)», либо Добавить отдельную настройку «Не трогать атрибуты WooCommerce» (+ разделить какие именно не трогать). Я предлагаю вариант 2 — просто исключить всё с префиксом pa_ и всё без pa_ в контексте WooCommerce. Просто например при синхронизации товаров с моим складом ломается абсолютно всё, ибо все синхронизации заточены под ваниль, а не под переведённые

uxtora 2026-02-11T17:49:00+00:00

Или вовсе так: public function sanitize_title( $title, $raw_title = '', $context = '' ) { global $wpdb; // Не транслитерировать при создании глобальных WC атрибутов if ( function_exists( 'wc_sanitize_taxonomy_name' ) ) { $trace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ); foreach ( $trace as $call ) { if ( isset( $call['function'] ) && $call['function'] === 'wc_sanitize_taxonomy_name' ) { return $title; } } } if ( ! $title || 'query' === $context || ! $this->transliterate_on_pre_term_slug_filter( (string) $title ) ) { return $title; } $title = urldecode( (string) $title ); $pre = apply_filters( 'ctl_pre_sanitize_title', false, $title ); if ( false !== $pre ) { return $pre; } if ( $this->is_term ) { $this->is_term = false; if ( $this->is_frontend && class_exists( SitePress::class ) ) { return $title; } $sql = $wpdb->prepare( "SELECT slug FROM $wpdb->terms t LEFT JOIN $wpdb->term_taxonomy tt ON t.term_id = tt.term_id WHERE t.slug = %s", rawurlencode( $title ) ); if ( $this->taxonomies ) { $sql .= ' AND tt.taxonomy IN (' . $this->prepare_in( $this->taxonomies ) . ')'; } $term = $wpdb->get_var( $sql ); if ( ! empty( $term ) ) { return $term; } } return $this->is_wc_attribute( $title ) ? $title : $this->transliterate( $title ); } } This reply was modified 3 months, 2 weeks ago by uxtora .

uxtora 2026-02-12T10:08:00+00:00

Я сделал себе “личный cyr-to-lat. Он переводит всё кроме атрибутов. Если интересно – скажи, скину

kaggdesign 2026-02-12T12:09:00+00:00

Нет, спасибо. Если есть желание – можно сделать PR на GitHub, с тестами. Я сделаю позже фильтр на WC атрибуты, чтобы закрыть проблему. И более корректную обработку атрибутов. К слову, debug_backtrace – не решение. Это тормоз.

uxtora 2026-02-12T14:24:00+00:00

нене, я сделал вообще иначе, без debug_backtrace . Твой плагин не трогал. И всё что было в прошлых коммах тоже не использовал. Вот если интересно – https://github.com/uxtora/cyr-to-lat-wp-personal-.git Проверил, работает. Что думаешь? Если поможет в фиксе – буду рад. This reply was modified 3 months, 2 weeks ago by uxtora . This reply was modified 3 months, 2 weeks ago by uxtora .

uxtora 2026-02-13T08:28:00+00:00

Дополнил

uxtora 2026-02-15T14:24:00+00:00

Привет. Нашёл ещё одну очень сильную проблему. Возможно она появилась после обновлений – хз. Если сохранить страницу и потом поменять слаг напрямую – он возвращает старый после сохранения. Т,е допустим ты создал страницу “Главная”, он создал ей слаг “glavnaya”. Нажал сохранить. Страница сохранилась. Потом ты решил поменять слаг вручную на “home”. Идешь редачить, AJAX улетает, вроде всё окей, но при сохранении получаешь опять старый слаг. Т.е пост нейм у него почему-то пустой. Я проверил несколько плагинов и везде такая же проблема. + тестировал, просто делал ключи+санитайз = та же проблема. Я решил лишь при прямой перезаписи в БД, но это не совсем правильно т.к обходятся стандартные хуки и тд. Но вроде как при аяксе пофигу… Не знаю. Там есть дебаг файлы, попробуй убери $wpdb->update и поменяй на ванилу, тебе вернёт старый слаг. Короче вп.. https://github.com/uxtora/cyr-to-lat-wp-personal-/blob/main/record%20to%20DB%20AJAX This reply was modified 3 months, 1 week ago by uxtora . This reply was modified 3 months, 1 week ago by uxtora .

kaggdesign 2026-02-15T15:30:00+00:00

Спасибо за детали. По основной теме — я вернусь к этому вопросу позже. Что касается предложенного решения через кастомный плагин: спасибо, что поделились, но я не могу разбирать и отлаживать сторонний/самописный код. Это выходит за рамки поддержки нашего плагина.

uxtora 2026-02-28T09:46:00+00:00

Привет. Поправили?

kaggdesign 2026-04-01T21:13:00+00:00

Мы выпустили новую версию 6.7.0. Посмотрите, решает ли она проблему.

Mikhail Alferov 2026-04-24T14:58:00+00:00

Нет, в версии 6.7.0 проблема с русскими кастомными Ву-атрибутами сохраняется. Плагин Cyr-to-lat вмешивается в названия кастомных кириллических атрибутов уже при вычитке из БД. Отключем Cyr-to-lat Создаем пользовательский атрибут с кириллческими буквами . На этом шаге Ву сразу создает вариации, если атрибут сделали вариативным. Давайте после активации плагина Cyr-to-lat попробуем выбрать для вариации значение по умолчанию. Включаем плагин. Затем только обновляем страницу редактора товарной карточки и на вкладке Вариации значения атрибутов name в HTML-элементах select уже транслитерировались. В БД в сериализованном представлении объектов атрибутов хранятся URL-кодированные ключи: %d… , но до SELECT’ов доезжают уже преобразованные в латиницу значения 🙂 В текущей версии остается только определять контекст вызова функции sanitize_title() и вешатся на хук 'ctl_pre_sanitize_title' , чтобы вместо false вернуть оригинальную строку и тем заставить плагин оставить в покое строки, которые Ву отправил в sanitize_title() 🙂 This reply was modified 1 month ago by Mikhail Alferov .

kaggdesign 2026-05-03T16:10:00+00:00

Спасибо за подробное описание. Похоже, что это уже другой сценарий, не тот, который изначально обсуждался в этом тикете. В версии 6.7.0 мы исправляли обработку WooCommerce-атрибутов в сценарии, когда Cyr2Lat уже активен и атрибуты создаются/сохраняются после этого. Сценарий, когда WooCommerce-атрибуты были созданы и сохранены до включения Cyr2Lat, а затем плагин был активирован на уже существующем магазине, сейчас не поддерживается. В таком случае данные уже могут быть сохранены WooCommerce в одном формате, а после активации Cyr2Lat часть значений может проходить через стандартные механизмы sanitize_title() / обработки slug’ов и отображаться иначе. Мы не можем гарантировать корректное восстановление или автоматическую совместимость для атрибутов, сохранённых до включения плагина. Иными словами: новые WooCommerce-атрибуты, создаваемые при активном Cyr2Lat, должны обрабатываться корректно; но существующие атрибуты, сохранённые до активации Cyr2Lat, могут потребовать ручной корректировки или отдельной миграции данных. Такой migration scenario сейчас находится вне рамок поддержки плагина. Если сможете воспроизвести проблему на чистой установке, где Cyr2Lat активен до создания атрибутов, пожалуйста, опишите точные шаги в новом тикете — тогда это будет уже баг в поддерживаемом сценарии.