settings->get()->languages() as $lang ) { if ( '' !== $lang->locale && 'en_US' !== $lang->locale ) { $out[] = $lang->locale; } } return array_values( array_unique( $out ) ); } /** @return string[] */ public function add_locales( mixed $locales ): array { return array_values( array_unique( array_merge( (array) $locales, $this->locales() ) ) ); } /** @return string[] Locales whose core pack is not on the server yet. */ public function missing(): array { return array_values( array_diff( $this->locales(), get_available_languages() ) ); } /** * Install core packs for the locales, then theme and plugin packs. * * @param string[]|null $locales Default: all site locales. * @return array{core: string[], failed: string[], unreachable?: string[], packs: int}|WP_Error */ public function install( ?array $locales = null ): array|WP_Error { $locales = null === $locales ? $this->locales() : array_values( array_diff( $locales, array( 'en_US', '' ) ) ); if ( ! $locales ) { return array( 'core' => array(), 'failed' => array(), 'packs' => 0, ); } require_once ABSPATH . 'wp-admin/includes/file.php'; require_once ABSPATH . 'wp-admin/includes/translation-install.php'; require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; require_once ABSPATH . 'wp-includes/update.php'; if ( ! wp_can_install_language_pack() ) { return new WP_Error( 'blocklingo_langpack_fs', __( 'WordPress cannot write to wp-content/languages here (file permissions or FTP credentials needed). Install the languages in Settings > General > Site Language instead.', 'blocklingo' ) ); } // The list of WordPress translations comes from wordpress.org. Empty = it could not be reached // (wp_download_language_pack() would then fail for every locale as if none existed). $have = get_available_languages(); $available = array_diff( $locales, $have ) ? wp_get_available_translations() : array(); if ( array_diff( $locales, $have ) && ! $available ) { return new WP_Error( 'blocklingo_langpack_offline', __( 'Could not connect to wordpress.org to download translation files. The site may be offline or a firewall may block outgoing connections. Try again later with "Save and install", or install the languages in Settings > General > Site Language.', 'blocklingo' ) ); } $core = array(); $failed = array(); $unreachable = array(); foreach ( $locales as $locale ) { if ( in_array( $locale, $have, true ) ) { continue; } if ( wp_download_language_pack( $locale ) ) { $core[] = $locale; } elseif ( isset( $available[ $locale ] ) ) { $unreachable[] = $locale; // Listed on wordpress.org, but the download failed (SSL, firewall, timeout). } else { $failed[] = $locale; } } // Ask wordpress.org again (our locales are added by the filters above). delete_site_transient( 'update_plugins' ); delete_site_transient( 'update_themes' ); wp_update_plugins(); wp_update_themes(); $updates = array_values( array_filter( wp_get_translation_updates(), static fn( $u ): bool => isset( $u->language ) && in_array( $u->language, $locales, true ) ) ); $packs = 0; if ( $updates ) { $upgrader = new \Language_Pack_Upgrader( new \Automatic_Upgrader_Skin() ); $result = $upgrader->bulk_upgrade( $updates, array( 'clear_update_cache' => true ) ); if ( is_array( $result ) ) { $packs = count( array_filter( $result, static fn( $r ): bool => $r && ! is_wp_error( $r ) ) ); } } return array( 'core' => $core, 'failed' => $failed, 'unreachable' => $unreachable, 'packs' => $packs, ); } /** * One-line summary for an admin notice. * * @param array{core: string[], failed: string[], unreachable?: string[], packs: int}|WP_Error $result */ public static function summary( array|WP_Error $result ): string { if ( is_wp_error( $result ) ) { return $result->get_error_message(); } $parts = array(); if ( $result['core'] ) { $parts[] = sprintf( /* translators: %s: list of locales. */ __( 'WordPress translations installed: %s.', 'blocklingo' ), implode( ', ', $result['core'] ) ); } if ( $result['packs'] > 0 || ( ! $result['core'] && ! $result['failed'] && empty( $result['unreachable'] ) ) ) { $parts[] = sprintf( /* translators: %d: number of files. */ __( 'Theme and plugin translation files installed or updated: %d.', 'blocklingo' ), $result['packs'] ); } if ( ! empty( $result['unreachable'] ) ) { $parts[] = sprintf( /* translators: %s: list of locales. */ __( 'Could not download from wordpress.org: %s. The server may block outgoing connections or fail the SSL check. Try "Save and install" again later.', 'blocklingo' ), implode( ', ', $result['unreachable'] ) ); } if ( $result['failed'] ) { $parts[] = sprintf( /* translators: %s: list of locales. */ __( 'Not available on wordpress.org: %s.', 'blocklingo' ), implode( ', ', $result['failed'] ) ); } return implode( ' ', $parts ); } }