*/ private const REGIONAL_LOCALES = array( 'en_us' => 'us', 'en_gb' => 'gb', 'pt_br' => 'br', 'pt_pt' => 'pt', 'zh_cn' => 'cn', 'zh_tw' => 'tw', ); /** * Resolve a validated flag code for the given language. * * A saved SiteLang flag is authoritative. Regional locale lookup is only a * fallback, and never turns an arbitrary language code into a country code. * * @param array $language Language row. * @return string Empty string means use the neutral language globe. */ public static function resolve_code( array $language ) { $flag = isset( $language['flag'] ) ? strtolower( sanitize_key( (string) $language['flag'] ) ) : ''; if ( in_array( $flag, self::FLAGS, true ) && is_file( SITELANG_PATH . 'assets/flags/rectangular/' . $flag . '.svg' ) ) { return $flag; } $locale = isset( $language['wp_locale'] ) ? strtolower( str_replace( '-', '_', sanitize_text_field( (string) $language['wp_locale'] ) ) ) : ''; if ( isset( self::REGIONAL_LOCALES[ $locale ] ) ) { $regional_flag = self::REGIONAL_LOCALES[ $locale ]; if ( is_file( SITELANG_PATH . 'assets/flags/rectangular/' . $regional_flag . '.svg' ) ) { return $regional_flag; } } return ''; } /** * Render one decorative, locally hosted flag image. * * @param array $language Language row. * @param string $shape rectangular or circular. * @param string $context switcher or admin. * @param string $size menu, card, trigger, chip, or preview. * @return string */ public static function render( array $language, $shape = 'rectangular', $context = 'switcher', $size = 'menu' ) { $shape = in_array( $shape, array( 'rectangular', 'circular' ), true ) ? $shape : 'rectangular'; $context = 'admin' === $context ? 'admin' : 'switcher'; $size = in_array( $size, array( 'menu', 'card', 'trigger', 'chip', 'preview' ), true ) ? $size : 'menu'; $code = self::resolve_code( $language ); $asset = $code ? 'assets/flags/' . $shape . '/' . $code . '.svg' : ( 'circular' === $shape ? 'assets/flags/language-globe-circle.svg' : 'assets/flags/language-globe.svg' ); $width = 'circular' === $shape ? ( 'trigger' === $size ? 28 : ( 'chip' === $size ? 21 : 23 ) ) : 20; $height = 'circular' === $shape ? $width : 15; $class = 'admin' === $context ? 'sitelang-admin-flag' : 'sitelang-switcher__flag'; $class .= 'circular' === $shape ? ' sitelang-flag--circle' : ' sitelang-flag--rectangular'; $loading = in_array( $size, array( 'trigger', 'chip', 'preview' ), true ) ? 'eager' : 'lazy'; return sprintf( '', esc_attr( $class ), esc_url( SITELANG_URL . $asset ), absint( $width ), absint( $height ), esc_attr( $loading ), esc_attr( $code ) ); } /** * Build a safe URL map for the admin's live preview. * * @return array> */ public static function preview_map() { $map = array(); foreach ( self::FLAGS as $flag ) { $map[ $flag ] = array( 'rectangular' => esc_url_raw( SITELANG_URL . 'assets/flags/rectangular/' . $flag . '.svg' ), 'circular' => esc_url_raw( SITELANG_URL . 'assets/flags/circular/' . $flag . '.svg' ), ); } $map['fallback'] = array( 'rectangular' => esc_url_raw( SITELANG_URL . 'assets/flags/language-globe.svg' ), 'circular' => esc_url_raw( SITELANG_URL . 'assets/flags/language-globe-circle.svg' ), ); return $map; } }