В WordPress 6.7 заметно переработали интернационализацию: just-in-time загрузка переводов, новые хелперы, язык писем для администратора и более строгие предупреждения, если textdomain трогают слишком рано. Ниже – что изменилось на практике и как не словить лавину _doing_it_wrong после обновления.
Опора на официальный разбор: i18n improvements in 6.7 (Make/Core).
1. has_translation(): проверка без лишней нагрузки
Появилась функция has_translation(): можно узнать, есть ли перевод для строки, не обязательно «дёргая» тяжёлую логику там, где раньше приходилось угадывать через загрузку домена.
Сигнатура (упрощённо): has_translation( string $singular, string $textdomain = 'default', ?string $locale = null ): bool.
if ( has_translation( 'Settings saved.', 'my-text-domain' ) ) {
echo esc_html__( 'Settings saved.', 'my-text-domain' );
} else {
// fallback / другая ветка UI
}
Первый аргумент – singular-строка (как в __()), второй – textdomain. Не путайте с slug плагина.
2. Письма на языке администратора
С WP 4.7 у пользователей есть свой язык интерфейса. В 6.7 логика уведомлений умнее: если получатель – администратор сайта (в типичном сценарии связанный с admin_email / locale пользователя), письма могут уходить на языке админа, а не на языке фронта сайта.
Пример: сайт на испанском для посетителей, админ читает интерфейс по-английски – служебные письма ближе к языку админа. Для кастомных рассылок через wp_mail() всё равно проверяйте, какой locale активен в момент отправки (switch_to_locale / restore_previous_locale при необходимости).
wp_mail(
get_option( 'admin_email' ),
__( 'Notification', 'my-text-domain' ),
__( 'Hello, this is a site notice.', 'my-text-domain' )
);
3. Откуда грузятся переводы тем и плагинов
Каноничное место для файлов с translate.wordpress.org и ручных .mo/.l10n.php – каталоги под WP_LANG_DIR:
wp-content/languages/plugins/{slug}-{locale}.mo
wp-content/languages/themes/{slug}-{locale}.mo
# плюс современные .l10n.php варианты в тех же деревьях
Пример:
wp-content/languages/themes/your-theme-ru_RU.mo
Явная загрузка по-прежнему возможна, но её лучше вызывать в правильный момент жизненного цикла:
add_action( 'after_setup_theme', function () {
load_theme_textdomain( 'your-theme', get_template_directory() . '/languages' );
} );
// или централизованный каталог:
// load_theme_textdomain( 'your-theme', WP_LANG_DIR . '/themes' );
Для плагинов аналогично: load_plugin_textdomain() / JIT, без вызовов переводимых строк на верхнем уровне файла плагина при подключении.
4. Предупреждения о преждевременной загрузке
6.7 активнее сигналит, если перевод загружается «слишком рано» (до того, как i18n-стек готов). Типичный триггер – вызов __(), esc_html__(), get_plugin_data() с переводом прямо при include файла плагина.
Плохо (часто ловит notice в debug):
// top-level в main plugin file define( 'MYPLUGIN_VERSION', get_plugin_data( __FILE__ )['Version'] );
Лучше отключить перевод в get_plugin_data или отложить чтение:
define(
'MYPLUGIN_VERSION',
get_plugin_data( __FILE__, false /* $translate */, false )['Version']
);
// строки интерфейса - на init / admin_init / after_setup_theme
add_action( 'init', function () {
// load_plugin_textdomain( ... ); если всё ещё нужен явный вызов
} );
Общее правило: не вызывайте переводимые API и не читайте переведённые заголовки плагина до хуков вроде init / after_setup_theme.
5. Как поймать источник _doing_it_wrong
Включите WP_DEBUG / log на staging и повесьте трассировку:
add_action(
'doing_it_wrong_run',
static function ( $function_name ) {
if ( '_load_textdomain_just_in_time' === $function_name ) {
// error_log() / monolog / временный file_put_contents
error_log( wp_debug_backtrace_summary() );
}
}
);
Удобно смотреть стек в Query Monitor (секции Doing It Wrong / Languages). Чаще всего виноват чужой плагин с top-level __() или тема, которая грузит textdomain в конструкторе при подключении functions.php слишком рано.
Чеклист перед/после 6.7
- Нет переводимых вызовов на верхнем уровне main-файла плагина.
get_plugin_data( ..., false ), если нужна только версия/мета без перевода.- .mo/.l10n.php лежат в ожидаемых путях под
languages/. - Staging с
WP_DEBUG_LOG, прогон админки и cron. - Обновление «шумных» плагинов, если backtrace указывает на них.
Итог
i18n в WordPress 6.7 заточен под более позднюю и аккуратную загрузку переводов: быстрее типичные запросы, меньше сюрпризов с locale, зато строже к старому коду. Проверьте свои темы и плагины на premature translation loading, разложите языковые файлы по WP_LANG_DIR и держите debug включённым на staging после апдейта.


