> $items Строки текущей страницы.
* @param Language $language Целевой язык.
* @return array Идентификатор строки => официальный перевод.
*/
private function officialTranslations( array $items, Language $language ): array {
if ( array() === $items || ! function_exists( 'switch_to_locale' ) || ! function_exists( 'get_translations_for_domain' ) ) {
return array();
}
$switched = switch_to_locale( $language->wpLocale );
$result = array();
$objects = array();
foreach ( $items as $row ) {
$domain = (string) ( $row['domain'] ?? '' );
$domain = '' !== $domain ? $domain : DomainLabel::CORE;
// Объект переводов домена — сами загруженные файлы, без фильтров gettext
// (иначе вместо официального перевода показалось бы наше же переопределение).
$objects[ $domain ] ??= get_translations_for_domain( $domain );
$pluralKey = isset( $row['plural_key'] ) && null !== $row['plural_key'] ? (int) $row['plural_key'] : null;
$translated = OfficialTranslation::lookup(
$objects[ $domain ],
(string) $row['source_text'],
(string) ( $row['gettext_context'] ?? '' ),
$pluralKey
);
if ( null !== $translated ) {
$result[ (int) $row['id'] ] = $translated;
}
}
if ( $switched ) {
restore_previous_locale();
}
return $result;
}
/**
* Карта «домен → человекочитаемое имя» для показанных строк.
*
* @return array
*/
private function domainLabels(): array {
$themes = array();
$plugins = array();
if ( function_exists( 'wp_get_theme' ) ) {
foreach ( wp_get_themes() as $theme ) {
$domain = (string) $theme->get( 'TextDomain' );
if ( '' !== $domain ) {
$themes[ $domain ] = (string) $theme->get( 'Name' );
}
}
}
if ( ! function_exists( 'get_plugins' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
foreach ( get_plugins() as $plugin ) {
$domain = (string) ( $plugin['TextDomain'] ?? '' );
if ( '' !== $domain ) {
$plugins[ $domain ] = (string) ( $plugin['Name'] ?? $domain );
}
}
$labels = array();
foreach ( $this->gettext->domains() as $domain ) {
$labels[ $domain ] = DomainLabel::format( $domain, $themes, $plugins );
}
$labels[ DomainLabel::CORE ] = DomainLabel::format( DomainLabel::CORE );
return $labels;
}
/**
* Фильтры над таблицей.
*
* @param array{domain: string, status: string, search: string, page: int} $filters Текущие фильтры.
* @param int $total Всего строк.
*/
private function renderFilters( Language $language, array $secondary, array $filters, int $total ): void {
$labels = $this->domainLabels();
?>
wpLocale ) {
/*
* Словарь интерфейса общий для всех языков: `msgid` английский
* по определению, и одна строка обслуживает и болгарский, и
* любой другой. Поэтому на английской вкладке видны строки,
* собранные на ДРУГИХ языках, — и у каждой честно написано
* «нет перевода», хотя переводить нечего: оригинал уже
* английский. Без этого объяснения экран выглядит поломанным.
*/
printf(
'
%s
',
esc_html__( 'English is the language of the originals themselves: the interface strings are already written in it and do not need translating. The list below is shared by all languages (it was collected wherever a translation was missing), so the strings show "No translation", which is normal for English. Switch the language to see where a translation is really needed.', 'lingocanvas' )
);
return;
}
if ( $this->packs->isInstalled( $language->wpLocale ) ) {
return;
}
printf(
'
%s
%s
',
esc_html(
sprintf(
/* translators: 1: language label, 2: WordPress locale */
__( 'The language pack for "%1$s" (%2$s) is not installed. Until it is, WordPress serves the English originals for all interface strings, and collecting them into the dictionary is pointless, so this list is not filled for this language.', 'lingocanvas' ),
$language->label,
$language->wpLocale
)
),
wp_kses(
sprintf(
/* translators: %s: link to the languages settings page */
__( 'Install the pack on the %s page; after that, only what it truly lacks will appear here.', 'lingocanvas' ),
'' . esc_html__( 'Multilingual → Languages', 'lingocanvas' ) . ''
),
array( 'a' => array( 'href' => array() ) )
)
);
}
}