HTML внутри строк перевода __() или _e()

15 сент. 2013 г., 06:19:01
Просмотры: 50.5K
Голосов: 29

Какой правильный подход к построению строк перевода?

Например,

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 ); 
0
Все ответы на вопрос 2
5
49

У функции __() есть второй аргумент. Он должен быть установлен в домен, который вы используете для своего плагина или темы. В примерах ниже я использую '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(), чтобы объяснить контекст этих терминов.


Другие примеры перевода можно найти здесь: Интернационализация: скорее всего, вы делаете это неправильно

15 сент. 2013 г. 07:09:45
Комментарии

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

Twifty Twifty
15 сент. 2013 г. 10:12:32

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

brasofilo brasofilo
15 сент. 2013 г. 13:33:22

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

Charles Clarkson Charles Clarkson
15 сент. 2013 г. 14:27:57

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

helgatheviking helgatheviking
15 сент. 2013 г. 14:31:21

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

phpheini phpheini
3 июн. 2017 г. 19:56:21
2

Я не буду касаться вопроса переменных в строке, так как это уже было сказано.

Вы хотите, чтобы ваша строка оставалась статичной, то есть её содержимое не будет меняться. Также вы хотите избежать лишнего HTML.

__( '<p>Привет, мир!</p>' );
__( '<h1>Привет, мир!</h1>' );

Вышеприведённый код займёт две строки в вашей таблице для, по сути, одного и того же текста. Их можно переписать так:

'<p>' . __( 'Привет, мир!' ) . '</p>'
'<h1>' . __( 'Привет, мир!' ) . '</h1>'

Это сократит запись до одной строки.

Иногда HTML в тексте неизбежен. Например:

__( 'В настоящее время вы должны <b>%s</b> долларов' );

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

Общее правило: HTML-теги форматирования внутри предложения допустимы. Предложения, начинающиеся и заканчивающиеся HTML-тегами, просто занимают лишнее место.

15 сент. 2013 г. 10:43:58
Комментарии

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

Charles Clarkson Charles Clarkson
15 сент. 2013 г. 14:36:15

@CharlesClarkson Хорошее замечание. Возможно, мне следовало убрать %s, чтобы сделать это немного понятнее.

Twifty Twifty
15 сент. 2013 г. 14:52:55