true, 'strategy' => 'defer', ) ); } /** * Prints what the script needs: where the note sits, the hreflang tag of the language shown, and * the texts of the note in each other language the page is in, keyed by their hreflang tags. */ public function printData(): void { $offers = self::offers(); if ( ! $offers ) { return; } $data = array( 'position' => Settings::get()['suggest']['position'], 'shown' => swiftling_hreflang_code( swiftling_page_language()['locale'] ), 'offers' => $offers, ); printf( '' . "\n", wp_json_encode( $data, JSON_HEX_TAG | JSON_HEX_AMP ) ); } /** * Prints the script that opens the home page in the browser's language, on the home page when * the Switcher screen asks for it, with what it needs: the languages the page is in, the one * shown, and the hosts of the site, which a visitor coming from the site itself is on. */ public static function printOpening(): void { if ( 'open' !== Settings::get()['suggest']['mode'] || ! is_front_page() || is_paged() ) { return; } $offers = self::offers(); if ( ! $offers ) { return; } $hosts = function_exists( 'swiftling_own_hosts' ) ? swiftling_own_hosts() : array( (string) wp_parse_url( home_url(), PHP_URL_HOST ) ); $data = array( 'offers' => array_keys( $offers ), 'shown' => swiftling_hreflang_code( swiftling_page_language()['locale'] ), 'hosts' => array_values( $hosts ), ); $script = (string) file_get_contents( SWIFTLING_DIR . 'assets/js/suggestion-open.js' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- A file of the plugin, printed inline so it runs before the page paints. // Without its comments and indents: it is printed into every home page. $script = (string) preg_replace( array( '~/\*.*?\*/~s', '~^\s*//.*$~m', '~^\s+~m', '~\n+~' ), array( '', '', '', "\n" ), $script ); wp_print_inline_script_tag( trim( str_replace( 'SWIFTLING_OPENING', (string) wp_json_encode( $data, JSON_HEX_TAG | JSON_HEX_AMP ), $script ) ) ); } /** * Returns the texts of the note in each other language the page being shown is in, when the * note is on. * * @return array * Keyed by hreflang tag, e.g. "de-DE"; empty when the page suggests nothing. */ public static function offers(): array { if ( ! Settings::get()['suggest']['enabled'] ) { return array(); } $links = swiftling_hreflangs(); $shown = swiftling_hreflang_code( swiftling_page_language()['locale'] ); $offers = array(); foreach ( swiftling_ordered_languages() as $language ) { $code = swiftling_hreflang_code( $language['locale'] ); if ( '' !== $code && $code !== $shown && isset( $links[ $code ] ) && ! isset( $offers[ $code ] ) ) { $offers[ $code ] = self::texts( $language ); } } return $offers; } /** * Returns the texts of the note in a language: those the Switcher screen gives, or the defaults. * * @param array $language Language, see swiftling_languages(). * @return array{text: string, show: string, close: string, label: string, lang: string, dir: string} */ public static function texts( array $language ): array { $texts = self::defaults( $language ); $saved = Settings::get()['suggest']['texts']; $own = isset( $saved[ $language['locale'] ] ) && is_array( $saved[ $language['locale'] ] ) ? $saved[ $language['locale'] ] : array(); foreach ( array( 'text', 'show' ) as $field ) { if ( isset( $own[ $field ] ) && is_string( $own[ $field ] ) && '' !== $own[ $field ] ) { $texts[ $field ] = $own[ $field ]; } } return $texts; } /** * Returns the default texts of the note in a language: the plugin's translations in the locale * WordPress runs in for it, read once and kept for a day. * * @param array $language Language, see swiftling_languages(). * @return array{text: string, show: string, close: string, label: string, lang: string, dir: string} */ public static function defaults( array $language ): array { $kept = get_transient( self::CACHE ); $kept = is_array( $kept ) ? $kept : array(); $locale = (string) $language['locale']; if ( isset( $kept[ $locale ] ) && is_array( $kept[ $locale ] ) ) { return $kept[ $locale ]; } // A locale WordPress has no translations for gets the English texts, never the page's. $wanted = (string) $language['wp_locale']; $switched = determine_locale() !== $wanted && ( switch_to_locale( $wanted ) || ( 'en_US' !== determine_locale() && switch_to_locale( 'en_US' ) ) ); try { $texts = array( /* translators: %s: name of a language in that language, e.g. Deutsch. */ 'text' => sprintf( __( 'This page is also in %s.', 'swiftling' ), $language['name'] ), 'show' => _x( 'Show', 'open the page in the language a note suggests', 'swiftling' ), 'close' => __( 'Close', 'swiftling' ), 'label' => __( 'Language suggestion', 'swiftling' ), 'lang' => str_replace( '_', '-', $locale ), 'dir' => null !== $language['rtl'] ? ( $language['rtl'] ? 'rtl' : 'ltr' ) : ( is_rtl() ? 'rtl' : 'ltr' ), ); } finally { if ( $switched ) { restore_previous_locale(); } } $kept[ $locale ] = $texts; set_transient( self::CACHE, $kept, DAY_IN_SECONDS ); return $texts; } /** * Forgets the default texts kept, after the languages or their translations changed. */ public static function forget(): void { delete_transient( self::CACHE ); } }