__(): Что делать, если нужно передать переменную?

26 янв. 2014 г., 11:10:50
Просмотры: 21.7K
Голосов: 7

В документации для функции перевода __( $text, $domain ) указано, что нужно помещать строку непосредственно вместо $text, и нельзя делать что-то хитрое вроде __( $my_text, 'text-domain' );.

Однако я пишу метод, который принимает строку и должен как-то передать её в __( ... ). Есть ли способ обойти это, например, с помощью printf или sprintf?

Что-то вроде...

function print_description( $text ) {
    echo '<p>' . __( printf( '%s', $text ), 'text-domain' ) . '</p>';
}
0
Все ответы на вопрос 6
0
21

Вы можете сделать это с помощью функции printf().

Например:

printf( __( 'Мы удалили %d спам-сообщений.', 'my-text-domain' ), $count );
15 янв. 2016 г. 10:09:09
1

Для перевода строк в WordPress, как и в большинстве CMS, использующих PHP, необходимо обернуть строку в функцию перевода GetText (например, __(), _e(), _n(), _x() и т.д.).

Строка также должна быть включена в PO-файл (GetText Portable Object files, стандарт индустрии для многоязычных сайтов на PHP — https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html). Этот файл содержит пары строк: одна строка на исходном языке, а другая — её перевод на целевой язык.

Для создания этих PO-файлов для каждого языка (например, my-text-domain-es_ES.po для испанского, my-text-domain-fr_FR.po для французского и т.д.), в которые нужно перевести плагин или тему, переводчик использует POT-файл (PO-шаблон), содержащий все строки для перевода на исходном языке, и добавляет перевод для каждой из них. PO-файлы компилируются в двоичные MO-файлы, которые обрабатываются гораздо быстрее.

Во время выполнения строки для перевода извлекаются через MO-файлы и заменяются их переводом.

POT-файлы обычно генерируются с помощью специальных инструментов, которые анализируют исходные файлы кода и извлекают переводимые строки.

Если мы напишем код так:

    $translated_text = __( $text, 'my_text_domain');

Когда код анализируется специальными инструментами, значение строки для перевода ($text) ещё не определено и поэтому отсутствует в коде. В результате автоматические инструменты поиска не включат эту строку в POT-файл, и она не попадёт в PO- и MO-файлы.

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

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

Вариант 1: Вручную отредактировать POT-файл, добавив записи с возможными значениями $text. Этот вариант прост и легко реализуем. Любой текстовый редактор и минимальные знания формата POT будут достаточны. Но у него есть один недостаток: каждый раз, когда мы используем автоматические инструменты поиска для обновления переводов после изменения нашего кода, внесённые нами правки будут потеряны, и нам придётся добавлять их снова вручную.

Вариант 2: Включить в наш код все возможные значения $text, обёрнутые функциями перевода. Рассмотрим пример. Предположим, что $text может принимать значения: apple, orange, banana, peach и pear. Нам нужно написать следующий код:

    // эта переменная используется только для включения в качестве параметров в 
    // функции перевода всех возможных значений $text
    $locale = __('apple', 'my_text_domain') .
              __('orange', 'my_text_domain') .
              __('banana', 'my_text_domain') .
              __('peach', 'my_text_domain') .
              __('pear', 'my_text_domain');

    $translated_text = __( $text, 'my_text_domain');

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

Если в нашей теме или плагине есть несколько переменных, которые мы хотим перевести, и у них ограниченный набор известных возможных значений, мы можем включить их все в отдельный файл, который должен находиться в корневой папке или подпапке (например, папки 'includes' или 'assets') темы или плагина, как показано ниже:

    <?php
    //значения переменных для перевода
    $locale_var1 = __('text-of-var1_val1', 'my_text_domain') .
                   __('text-of-var1_val2', 'my_text_domain') .
                   __('text-of-var1_val3', 'my_text_domain') .
                   .......
                   __('text-of-var1_valn', 'my_text_domain');

    $locale_var2 = __('text-of-var2_val1', 'my_text_domain') .
                   __('text-of-var2_val2', 'my_text_domain') .
                   .......
                   __('text-of-var2_valn', 'my_text_domain');

    .............

    $locale_varn = __('text-of-varn_val1', 'my_text_domain') .
                   __('text-of-varn_val2', 'my_text_domain') .
                   .......
                   __('text-of-varn_valn', 'my_text_domain');

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

6 февр. 2019 г. 03:32:13
Комментарии

Спасибо за это, @Juan Guerrero. Я не уверен, почему этот ответ не получил несколько лайков - мне кажется, ваша идея с файлом ресурсов для предсказуемых наборов строк очень хороша - как вы сказали, это "чистый и поддерживаемый" подход. Я буду использовать его.

Nikkorian Nikkorian
20 февр. 2020 г. 03:25:13
0

Нет

Инструменты, помогающие в генерации перевода, не могут проанализировать ваш код и определить, какие строки требуют перевода, когда строки, передаваемые в функции перевода, полностью динамические.

В вашем примере правильный способ написать эту функцию:

function print_description( $text ) {
    echo '<p>' . $text . '</p>';
}

И вызывать её так:

print_description(__('конкретное описание','text_domain'));
26 янв. 2014 г. 11:20:07
0

Нет, потому что нельзя перевести текст, если вы на самом деле не знаете, что это за текст.

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

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

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

26 янв. 2014 г. 20:09:44
3

По какой-то причине у меня работает передача переменных в _e():

$string = 'ciao';
_e($string, 'textdomain'); // укажите свой textdomain..
// выведет 'ciao' или 'hello', в зависимости от текущего языка

Очевидно, вам нужно сначала создать свой textdomain, желательно в yourtheme/functions.php:

add_action( 'after_setup_theme', 'theme_setup' );
function theme_setup() {
  load_theme_textdomain( 'yourtextdomain', TEMPLATEPATH . '/languages' );
  // [...] другой код инициализации
}

Если я переведу слово 'ciao' в .po файле, оно будет корректно переведено во фронтенде. Используйте Poedit или аналоги для компиляции .mo. Оба файла .po и .mo должны быть размещены в /wp-content/yourtheme/languages (согласно коду выше).

#. Тестовый en_EN.po
msgid "ciao"
msgstr "hello"

Не уверен, почему это работает, но это действительно так - выводит 'ciao' на итальянском и 'hello' на английском.

3 дек. 2016 г. 14:03:30
Комментарии

Это работает только потому, что вы вручную добавляете перевод. Если вы используете инструмент, который ищет строки для перевода в вашем коде, он не сможет найти правильную строку.

Milo Milo
3 дек. 2016 г. 18:49:44

Да, конечно, но я думаю, что это не проблема исходного вопроса

Luca Reghellin Luca Reghellin
3 дек. 2016 г. 19:11:34

Ну, ваша переменная не совсем переменная, она фиксирована - $string не меняется в вашем примере, и вы сами добавили строку для перевода. Это не рабочее решение.

Milo Milo
3 дек. 2016 г. 19:18:22
0

Как я упомянул здесь http://www.westofwonder.com/2013/12/whats-with-all-the-double-underscores-everywhere/ (прошу прощения за тему, я внес улучшения, просто еще не опубликовал их), одним из возможных решений этой проблемы является создание функции для текста:

function yourtheme_thisisthetext() {
    return __( 'Это текст.', 'yourthemetextdomain' );
}

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

(Разрешено ли так делать? Ссылаться на свой блог в прямом ответе на вопрос? Если нет, приношу извинения и больше не буду.)

26 янв. 2014 г. 19:15:38