Локализация "слагов" темы (пользовательские типы записей, таксономии)

2 окт. 2011 г., 14:02:29
Просмотры: 24.4K
Голосов: 17

В моей теме я хочу определить несколько пользовательских типов записей и пользовательских таксономий, каждая из которых имеет свой настроенный слаг; базовый язык моей темы - английский, поэтому слаги будут на английском языке

например, при определении слага для аргументов пользовательского типа записи "product":

'rewrite' => array( 'slug' => 'product' ),

есть ли способ перевести "слаг" через po/mo файлы? могу ли я написать это как:

'rewrite' => array( 'slug' => __('product', 'mytextdomain') )

или это не будет работать? какая текущая практика локализации слагов?

4
Комментарии

Не знаю, сталкиваемся ли мы с той же проблемой, но похоже, что да. Чтобы лучше проиллюстрировать, вот ссылка на оригинальную страницу index для пользовательского типа записи под названием prensa с установленным слагом prensa. Используя WPML, слаг переведенной страницы - press, так как он не может быть снова prensa: /en/press/, которая ничего не отображает (обратите внимание, что сейчас нажатие на ссылку ES не возвращает вас к /prensa/). НО если вы перейдете по /en/prensa/, то всё работает...

Naoise Golden Naoise Golden
10 окт. 2011 г. 19:45:59

Я решил перенаправить страницы с /en/press на /en/prensa, поэтому упомянутая ссылка, скорее всего, больше не будет работать. Жаль, что не удалось использовать локализованный слаг, но работоспособность вовремя лучше, чем дружелюбные к локализации URL.

Naoise Golden Naoise Golden
10 окт. 2011 г. 20:00:05

Посмотрите мой ответ, Naoise, думаю, он даст вам рабочее решение.

chrisguitarguy chrisguitarguy
10 окт. 2011 г. 20:31:07

Я мучился с этой проблемой несколько часов. В итоге нашел решение: https://github.com/stouch/wp-plugin-polylang-localized-taxonomy-slug/blob/master/functions.php С уважением.

Sylvain Tch Sylvain Tch
14 июл. 2019 г. 15:12:04
Все ответы на вопрос 6
7
21

Я бы не рекомендовал локализовать ваши слаги. Вместо этого, почему бы не дать пользователям возможность изменять их, добавив дополнительное поле на страницу настроек постоянных ссылок?

Подключитесь к хуку load-options-permalink.php и настройте обработку данных $_POST для сохранения вашего слага. Также добавьте поле настроек на страницу.

<?php
add_action( 'load-options-permalink.php', 'wpse30021_load_permalinks' );
function wpse30021_load_permalinks()
{
    if( isset( $_POST['wpse30021_cpt_base'] ) )
    {
        update_option( 'wpse30021_cpt_base', sanitize_title_with_dashes( $_POST['wpse30021_cpt_base'] ) );
    }

    // Добавляем поле настроек на страницу постоянных ссылок
    add_settings_field( 'wpse30021_cpt_base', __( 'База CPT' ), 'wpse30021_field_callback', 'permalink', 'optional' );
}

Затем callback-функция для поля настроек:

<?php
function wpse30021_field_callback()
{
    $value = get_option( 'wpse30021_cpt_base' );    
    echo '<input type="text" value="' . esc_attr( $value ) . '" name="wpse30021_cpt_base" id="wpse30021_cpt_base" class="regular-text" />';
}

При регистрации типа записи получайте слаг через get_option. Если его нет, используйте значение по умолчанию.

<?php
add_action( 'init', 'wpse30021_register_post_type' );
function wpse30021_register_post_type()
{
    $slug = get_option( 'wpse30021_cpt_base' );
    if( ! $slug ) $slug = 'ваш-слаг-по-умолчанию';

    // Регистрируем тип записи, используя $slug для rewrite
    $args['rewrite'] = array( 'slug' => $slug );

    // Очевидно, вам понадобится больше параметров, чем один...
    register_post_type( 'wpse30021_pt', $args );
}

Вот часть с полем настроек в виде плагина: https://gist.github.com/1275867

РЕДАКТИРОВАНИЕ: Другой вариант

Вы также можете изменять слаг на основе константы WPLANG.

Просто создайте функцию с данными...

<?php
function wpse30021_get_slug()
{
    // Возвращаем слаг по умолчанию
    if( ! defined( 'WPLANG' ) || ! WPLANG || 'en_US' == WPLANG ) return 'press';

    // Массив соответствий языков и слагов
    $slugs = array( 
        'fr_FR' => 'presse',
        'es_ES' => 'prensa'
        // и т.д.
    );

    return $slugs[WPLANG];
}

Затем получайте слаг при регистрации типа записи.

<?php
add_action( 'init', 'wpse30021_register_post_type' );
function wpse30021_register_post_type()
{
    $slug = wpse30021_get_slug();

    // Регистрируем тип записи, используя $slug для rewrite
    $args['rewrite'] = array( 'slug' => $slug );

    // Очевидно, вам понадобится больше параметров, чем один...
    register_post_type( 'wpse30021_pt', $args );
}

Лучший вариант, на мой взгляд, - это предоставить пользователю выбор и установить разумные значения по умолчанию:

<?php
add_action( 'init', 'wpse30021_register_post_type' );
function wpse30021_register_post_type()
{
    $slug = get_option( 'wpse30021_cpt_base' );
    // Если пользователь не установил опцию, получаем значение по умолчанию
    if( ! $slug ) $slug = wpse30021_get_slug();

    // Регистрируем тип записи, используя $slug для rewrite
    $args['rewrite'] = array( 'slug' => $slug );

    // Очевидно, вам понадобится больше параметров, чем один...
    register_post_type( 'wpse30021_pt', $args );
}
10 окт. 2011 г. 20:27:57
Комментарии

+1 за плагин на gist и хорошо документированный код. Однако в моем случае это противоречит цели, которая заключается в том, чтобы не давать пользователю возможность изменять, а создавать SEO-дружественные URL с учетом локализации для пользовательских типов записей

Naoise Golden Naoise Golden
11 окт. 2011 г. 20:01:06

Не совсем понимаю, зачем вам нужно лишать пользователя этой опции. Более того, пропуск слага через фильтр перевода дает им ту же возможность: изменить слаг. Просто без красивого поля формы для заполнения.

chrisguitarguy chrisguitarguy
12 окт. 2011 г. 19:05:00

просто из любопытства, почему wpse30021?

Naoise Golden Naoise Golden
17 окт. 2011 г. 12:29:04

Похоже, что эта опция предназначена для локализации на основе WPLANG. Но что делать, если вы работаете с многоязычным сайтом? (например, с плагином WPML). Вопрос скорее о том, как отображать разный slug в зависимости от локализации клиента, а не о возможности задать slug произвольного типа записи из настроек сервера.

Naoise Golden Naoise Golden
17 окт. 2011 г. 12:33:18

wpse = WordPress stack exchange. 30021 — это номер из URL. Удачи в ваших поисках; я дал свой ответ. Дополнительная сложность, которую вы добавляете, и кажущееся полное изменение первоначального вопроса — изначально о slug'ах CPT, только подтверждает аргумент в пользу разрешения конечному пользователю выбирать собственный slug.

chrisguitarguy chrisguitarguy
17 окт. 2011 г. 16:27:13

Вопрос спрашивает, можно ли использовать функцию __() со slug'ами, и "какова практика локализации slug'ов". Это можно интерпретировать как перевод slug'а, подобно переводу строки при просмотре темы на определенном языке, независимо от его использования в CPT. Именно поэтому изначально была установлена награда.

Naoise Golden Naoise Golden
18 окт. 2011 г. 16:38:41

Учитывая, что начиная с WordPress 4.7 пользователи могут установить предпочитаемый язык для своего профиля, использование опции из базы данных фактически является предпочтительным решением. Если пользователь выбрал язык, отличный от языка сайта, и инициирует сброс постоянных ссылок, например, посетив настройки постоянных ссылок, то перевод слага записи изменится на язык пользователя, чего вам не хотелось бы.

Gchtr Gchtr
30 июл. 2020 г. 18:56:16
Показать остальные 2 комментариев
0

Я реализую именно такой подход в теме, которую мы разрабатываем. Она поддерживает 5 различных языков, и для каждого языка есть переведённый набор категорий. Первый компонент URL в теме анализируется для определения используемого языка в формате страна-язык:

/uk-en
/fr-fr
/it-it

А затем переведённые категории обрабатываются как последующие компоненты URL.

URL анализируется на фазе parse_request:

function my_parse_request( $wp ) {
    $path = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );

    $components = preg_split('|/|', $path, null, PREG_SPLIT_NO_EMPTY );

    // Определяем язык из $components[0]
    $language = array_shift( $components );
    ...

    // Загружаем файл перевода...
    $mofile = get_stylesheet_directory()."/$language.mo";

    load_textdomain( 'mydomain', $mofile );

    ...

    // Определяем категорию из $components[0]
    if( __( 'some-category', 'mydomain' ) == $components[0] )
      $wp->query_vars['category'] = 'some-category';

    ...
}
add_action( 'parse_request', 'my_parse_request' );

В этом примере опущены необходимые проверки, он предназначен только для демонстрации.

Конечно, у такого подхода есть недостатки, но он позволяет использовать естественные URL на всех языках. Основные недостатки, которые я вижу:

1) Он не использует механизм постоянных ссылок. Это можно расширить, чтобы генерировались правильные правила постоянных ссылок для всех языков и parse_request не понадобится, но для всех языков это потребует загрузки одного MO-файла за другим в цикле, и я не знаю, насколько хорошо это поддерживается.

2) Если переводчик изменит ярлык (slug), то ссылки становятся недействительными.

13 окт. 2011 г. 22:46:59
5

Если это не работает, почему бы просто не сделать:

$post_slug = __('product', 'mytextdomain');
'rewrite' => array( 'slug' => $post_slug );
10 окт. 2011 г. 17:53:23
Комментарии

у меня это не сработало

Naoise Golden Naoise Golden
10 окт. 2011 г. 19:41:22

это практически тот же код, но в другом стиле

Naoise Golden Naoise Golden
10 окт. 2011 г. 19:47:37

Вы добавили правильный текстовый домен? <?php load_theme_textdomain(my_text_domain);?> ?

chifliiiii chifliiiii
10 окт. 2011 г. 21:37:40

Это, безусловно, лучшее решение.

Al Rosado Al Rosado
20 апр. 2017 г. 09:44:18

Будьте осторожны! Начиная с WordPress 4.7, пользователи могут установить предпочитаемый язык для своего профиля. Если у пользователя язык отличается от языка сайта и он инициирует сброс постоянных ссылок (например, посетив настройки постоянных ссылок), то перевод слага записи изменится на язык пользователя! Вот почему принятый ответ, который использует опцию, загружаемую из базы данных, на самом деле является гораздо более надежным и безопасным решением.

Gchtr Gchtr
30 июл. 2020 г. 18:53:53
0

У меня действительно была такая проблема, вот мое решение, которое работает, когда вы заранее знаете языки своего сайта. Допустим, у вас есть пользовательский тип записи (CPT) под названием "movie", и ваш сайт поддерживает 3 языка. Вам нужно переписать постоянные ссылки для этого CPT для каждого языка. Это также можно сделать динамически.

add_action("init", "rewrite_cpt", 10, 0);
function rewrite_cpt(){    
    add_rewrite_rule('^movie/([^/]*)/?', 'index.php?post_type=movie&name=$matches[1]', 'top'); // Английский
    add_rewrite_rule('^film/([^/]*)/?', 'index.php?post_type=movie&name=$matches[1]', 'top');  // Итальянский
    add_rewrite_rule('^фильм/([^/]*)/?', 'index.php?post_type=movie&name=$matches[1]', 'top'); // Русский
}

Теперь вам просто нужно перестроить постоянные ссылки: перейдите в Настройки > Постоянные ссылки и просто нажмите "Сохранить"

Следующая часть — это перезапись URL для вашего CPT. Если у вас есть переведенный CPT, вам нужно получить язык записи. В моем случае я использую Polylang. Важно кодировать иностранные символы в URL.

add_filter("post_type_link", "x_tours_postlink", 10, 2);
function x_tours_postlink($post_link, $post){
    $urls = array(
        "en" => "movie",
        "it" => "film",
        "ru" => "фильм"
    );
    if(get_post_type($post) == "movie")
        $post_link = str_replace("movie", urlencode($urls[pll_get_post_language($post->ID)]), $post_link);
    return $post_link;
}
5 апр. 2020 г. 17:53:13
1

Вы можете попробовать это в вашем functions.php

<?php
add_filter('rewrite_slugs', function($translated_slugs) {
    // возможные переводы для вашего слага 'product'
    $translated_slugs = array(
        'product' => array(
            'pt' => array(
                'has_archive' => true,'rewrite' => array('slug' => 'produto'),
            ),
            'es' => array(
                'has_archive' => true,'rewrite' => array('slug' => 'producto'),
            ),
        ),
    );
    return $translated_slugs;
});
?>

как показано здесь

26 мар. 2015 г. 00:43:22
Комментарии

Фильтр rewrite_slugs действительно существует в самом WordPress, ссылка, которую вы указали, относится к плагину WP Polylang - так что это может помочь пользователям Polylang

jave.web jave.web
16 февр. 2020 г. 15:47:14
4
-1

Я рекомендую не делать слаги переводимыми.

Перевод предназначен для контента сайта, который видят пользователи. Слаги используются внутренне и лишь частично "публичны" через перезапись URL — а URL также не должны переводиться.

Итак: оставьте свои слаги такими, как вы их определили. Переводите только те строки, которые предназначены для публичного использования.

12 окт. 2011 г. 20:06:31
Комментарии

переведенные ЧПУ (человеко-понятные URL) с точки зрения SEO и пользовательского опыта имеют огромное значение...

Naoise Golden Naoise Golden
17 окт. 2011 г. 12:20:45

Я не согласен, что ЧПУ как-то влияют на пользовательский опыт. Если ЧПУ используется как часть ссылки, анкорный текст будет переведен, поэтому пользователь не заметит разницы. А когда начинают разбрасываться терминами вроде "SEO", у меня обычно возникает мысль "разводилово". Я не эксперт по SEO, но в влияние переведенных ЧПУ на SEO я не верю.

Chip Bennett Chip Bennett
17 окт. 2011 г. 14:28:10

Я не согласен, основываясь на опыте. У нас в компании есть иностранные контент-менеджеры, которые прямо утверждают, что ЧПУ должны быть локализованы. Это вопрос создания полностью локального опыта для иностранного пользователя. Для некоторых стран, например Японии, это буквально необходимо для установления подлинного доверия и демонстрации серьезности намерений вести там бизнес.

internetross internetross
15 февр. 2013 г. 01:13:28

URL-адреса должны быть понятными. Поэтому если ярлык (slug) представляет собой (как часто бывает) название сущности или таксономии, перезапись должна учитывать как множественное число, так и переводы. Это не просто опция, а необходимость как для SEO, так и просто хорошая практика по отношению к конечным пользователям.

Luca Reghellin Luca Reghellin
21 дек. 2015 г. 16:11:27