HTML внутри строк перевода __() или _e()
Какой правильный подход к построению строк перевода?
Например,
echo __( 'Hello ' . $first . ' you owe me money.' );
echo __( '<div><p>Top: ' . $t_margin . '</p>' . '<p>Bottom: ' . $b_margin . '</p></div>' )
Правильно ли объединять строки и/или HTML или сначала нужно создать строку, а затем пропустить через перевод, например:
$html = '<div><p>Top: ' . $t_margin . '</p>' . '<p>Bottom: ' . $b_margin . '</p></div>';
echo __( $html );

У функции __()
есть второй аргумент. Он должен быть установлен в домен, который вы используете для своего плагина или темы. В примерах ниже я использую 'text_domain'
. Ваша строка домена должна быть уникальной. Она не должна совпадать с другими строками доменов. Если не использовать аргумент текстового домена, по умолчанию будет использоваться 'default'
— доменное имя WordPress. Подробнее см. по ссылке.
Всегда используйте строку ('text_domain'
). Никогда не используйте переменную, функцию или константу, содержащую эту строку. Большинство (или все?) программ для перевода не увидят её без явного указания строки.
Ваш код:
echo __( 'Hello ' . $first . ' you own me money.' );
Не включайте переменные в строку.
Лучший способ:
echo sprintf( __( 'Hello %s you own me money.', 'text_domain' ), $first );
Или просто:
printf( __( 'Hello %s you own me money.', 'text_domain' ), $first );
Плейсхолдер %s
указывает переводчику, что здесь будет вставлена строка. Используйте %d
для чисел. Также существуют другие плейсхолдеры.
(Это предложение грамматически неверно в английском. Используйте либо 'Hello %s, you owe me money.'
, либо 'Hello %s, you own my money.'
в зависимости от того, какой смысл вы вкладываете.)
Ваш код:
$html = '<div><p>Top: ' . $t_margin . '</p>' . <p>Bottom: ' . $b_margin . '</p></div>';
Не переводите HTML. Он одинаков на любом языке.
Лучший способ:
$html = sprintf( '<div><p>%s</p><p>%s</p></div>', __( 'Top: ', 'text_domain' ) . $t_margin, __( 'Bottom: ', 'text_domain' ) . $b_margin );
Или разбейте на несколько строк:
$html = sprintf(
'<div><p>%s</p><p>%s</p></div>',
__( 'Top: ', 'text_domain' ) . $t_margin,
__( 'Bottom: ', 'text_domain' ) . $b_margin
);
Если не очевидно, что означают Top и Bottom, вы можете использовать функцию _x()
, чтобы объяснить контекст этих терминов.
Другие примеры перевода можно найти здесь: Интернационализация: скорее всего, вы делаете это неправильно

Вы говорите не переводить HTML. Позвольте заметить, что HTML не переводится, а ищется в существующих таблицах предварительно переведенных строк. Наличие HTML в строке не имеет значения, если переводчик их не удалил. Фактически, в некоторых ситуациях это обеспечивает лучшую производительность, чем поиск и замена через регулярные выражения.

Не по теме, но стоит отметить: textdomain
должен быть строковым литералом, он не может быть переменной/константой/свойством.

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

+1 к использованию sprintf()
. Это действительно способ избежать HTML в переводимой строке.

Я не понимаю, как использование sprintf()
помогает, кроме, возможно, более чистого вида. Если у вас есть предложение с HTML внутри, например Некоторый текст с выделенным словом внутри.
, как можно перевести предложение целиком, а не переводить Некоторый текст с
, выделенным
и словом внутри
по отдельности (что не имеет смысла).

Я не буду касаться вопроса переменных в строке, так как это уже было сказано.
Вы хотите, чтобы ваша строка оставалась статичной, то есть её содержимое не будет меняться. Также вы хотите избежать лишнего HTML.
__( '<p>Привет, мир!</p>' );
__( '<h1>Привет, мир!</h1>' );
Вышеприведённый код займёт две строки в вашей таблице для, по сути, одного и того же текста. Их можно переписать так:
'<p>' . __( 'Привет, мир!' ) . '</p>'
'<h1>' . __( 'Привет, мир!' ) . '</h1>'
Это сократит запись до одной строки.
Иногда HTML в тексте неизбежен. Например:
__( 'В настоящее время вы должны <b>%s</b> долларов' );
Поскольку языки грамматически сложны, разделение текста может вызвать проблемы у переводчика.
Общее правило: HTML-теги форматирования внутри предложения допустимы. Предложения, начинающиеся и заканчивающиеся HTML-тегами, просто занимают лишнее место.

В последнем примере вы можете обернуть теги вокруг аргумента, который вставляется "<b>$string</b>"
. Затем можно использовать 'Вы должны %s долларов'
. Но, возможно, это нужно оставить, если вы используете функцию _n()
, которая требует плейсхолдер %d
.
