В этой короткой статье я покажу преимущества функции wirePopulateStringTags.

спринт

Обычно при переводе строки с переменными в ней вы будете использовать функцию sprintf следующим образом:

echo sprintf(__('There are %d %s in the %s'), $count, $items, $place));

Рендеринг чего-то похожего на There are 32 apples in the basket.

Но у этого подхода есть один недостаток. В системе управления переводом будет отображаться что-то вроде There are %d %s in the %s, что означает, что вы должны полагаться на комментарии, чтобы дать больше контекста, чтобы переводчик мог создать правильный перевод.

wirePopulateStringTags

Эта функция доступна в ядре ProcessWire. ( https://github.com/processwire/processwire/blob/master/wire/core/Functions.php#L369).

function wirePopulateStringTags($str, $vars, array $options = array())

Для строки $str и значений $vars замените теги в строке значениями. $vars также может быть объектом, и в этом случае значения будут извлечены как свойства объекта. По умолчанию теги указываются в следующем формате: {first_name}, где first_name - имя переменной, из которой нужно извлечь $vars, ‘{‘ - символ открывающего тега, а ‘}’ - символ закрывающего тега. Парсер тегов также может обрабатывать подполя и теги OR, если $vars - это объект, который это поддерживает. Например, {products.title} - это подполе, а {first_name|title|name} - тег ИЛИ.

Эта замечательная функция позволит более читаемым строкам в управлении переводом.

Используя предыдущий пример:

echo wirePopulateStringTags(
__('There are {count} {items} in the {place}'),
['items' => 'apples', 'count' => 32, 'place' => 'basket']
);

Будет отображено что-то похожее на There are 32 apples in the basket. И переводчик увидит There are {count} {items} in the {place} . На мой взгляд, намного лучше, чем использовать vanillasprintf. Другое преимущество заключается в том, что переводчик может легко изменить порядок и при необходимости повторить значение.

Используя оба

Как насчет того, когда вам нужно вывести форматированные значения ?. Например, используя эту строку The percentage is %1.1f%%. Будет отображено что-то похожее на The percentage is 50.2%.

Смешать обе функции очень просто. Просто примените форматирование перед отправкой параметров функции wirePopulateStringTags.

echo wirePopulateStringTags(
__('The percentage is {percent}'), 
['percent' => sprintf('%1.1f%%', 50.1994)]
);

Используя этот подход, мы отделяем презентацию от реализации. Теперь переводчик мог легко выполнять свою работу, не задумываясь о том, что означает %d или %s.

Сокращенная версия

Это специальная функция, объединяющая wirePopulateStringTags() и __(). Вы можете поместить его в файл ready.php, чтобы он был доступен для всего сайта.

/**
 * Perform a language translation replacing string tags.
 * 
 * Used as an alternative to sprintf in language string that requires variables.
 * uses wirePopulateStringTags function for replacing tags.
 *
 * The $vars may also be an object, in which case values will be pulled as properties of the object. 
 *
 * By default, tags are specified in the format: {first_name} where first_name is the name of the
 * variable to pull from $vars, '{' is the opening tag character, and '}' is the closing tag char.
 *
 * The tag parser can also handle subfields and OR tags, if $vars is an object that supports that.
 * For instance {products.title} is a subfield, and {first_name|title|name} is an OR tag. 
 *
 * @param string $text Text for translation.
 * @param WireData|object|array $vars Object or associative array to pull replacement values from.  
 * @param string $context Name of context
 * @param string $textdomain Textdomain for the text, may be class name, filename, or something made up by you. If omitted, a debug backtrace will attempt to determine automatically.
 * @param array $options Array of optional changes to default behavior, including: 
 *  - tagOpen: The required opening tag character(s), default is '{'
 *  - tagClose: The optional closing tag character(s), default is '}'
 *  - recursive: If replacement value contains tags, populate those too? Default=false. 
 *  - removeNullTags: If a tag resolves to a NULL, remove it? If false, tag will remain. Default=true. 
 *  - entityEncode: Entity encode the values pulled from $vars? Default=false. 
 *  - entityDecode: Entity decode the values pulled from $vars? Default=false.
 * @return string Translated text or original text if translation not available.
 *
 */
function _st($text, $vars, $context = null, $textdomain = null, array $options = array())
{
  return wirePopulateStringTags(__($text, $textdomain, $context), $vars, $options);
}

Пример использования

echo _st('There are {count} {items} in the {place}', 
  ['count' => 5, 'items' => 'oranges', 'place' => 'tree']);

Заключение

ProcessWire реализует множество функций, которые могут облегчить нам жизнь как разработчикам. Функцию wirePopulateStringTags можно использовать для улучшения процесса перевода с использованием именованных заполнителей вместо форматов проверки типов.