Своя обёртка для переводов

Звать Lang::get() из сотни шаблонов — значит вписать имя модуля в сотню мест. Если модуль когда-нибудь заменят, менять придётся всё.

Обёртка решает это одной функцией:

namespace App;

use mrLexndr\Translate\Lang;

function t(string $code, array $replace = [], ?string $fallback = null): string
{
    return Lang::get($code, $replace, false, $fallback);
}

Дальше шаблоны зовут App\t('CODE', [], 'Заглушка'), и о существовании модуля знает один файл.

Имя App\t здесь для примера — назовите как принято у вас на проекте.

Обязательный второй шаг

Индексатор ищет в файлах известные ему вызовы. Вашу обёртку он не знает, и все фразы, выведенные через неё, будут числиться неиспользуемыми — то есть попадут в кандидаты на удаление в «Мусорщике».

Поэтому добавьте её в список образцов, по которым идёт поиск:

protected function getPassAPatterns(): array
{
    $base = [
        // …существующие…
        "#\bApp\\t\s*\(\s*'([A-Z0-9_\-\.]{1,250})'\s*(?:[,\)])#m",
    ];

    return $base;
}

Это CodeScanner, точка расширения индексатора. Подробнее — Индексатор использования фраз.

Без этого шага обёртка работает, но словарь постепенно наполняется фразами, которые считаются мусором, и разбор «Мусорщика» превращается в угадайку.

Чего обёртка не должна делать

Не прячьте третий аргумент. Сырой режим нужен в атрибутах, в заголовке страницы и в JSON — если обёртка его не пробрасывает, в этих местах разметка разъедется у администратора с включённым режимом правки. Либо пробрасывайте параметр, либо заведите вторую функцию для сырого вывода.

Не подставляйте фиксированный язык. Язык берётся из текущей страницы Битрикса, и обёртка, которая передаёт его явно, сломается на второй языковой версии.