PATH:
home
/
sparklp6
/
public_html
/
website_356c8563
/
wp-content
/
plugins
/
translatepress-multilingual
/
includes
<?php if ( ! defined( 'ABSPATH' ) ) { exit; } /** * Class that renders the Vue-configured language switchers. * * Relies on the config stored in $this->settings['language-switcher']: * floater (array) – settings for the floating switcher * shortcode (array) – settings for [language-switcher] shortcode * menu (array) – settings for menu items */ class TRP_Language_Switcher_V2 { private array $settings; private array $config; private TRP_Translate_Press $trp; private TRP_Url_Converter $url_converter; private TRP_Languages $languages; private TRP_Language_Switcher_Tab $language_switcher_tab; private ?string $current_lang = null; private static ?self $instance = null; /** * @var 'desktop' | 'mobile' */ private string $viewport; /** * Get singleton instance. * * @param null $settings * @param null $trp * @return self */ public static function instance( $settings = null, $trp = null ): self { if ( self::$instance === null ) { if ( $settings === null || $trp === null ) throw new RuntimeException( 'TRP_Language_Switcher_V2::instance() requires $settings and $trp when called manually.' ); self::$instance = new self( $settings, $trp ); } return self::$instance; } /** * @param array $settings TRP settings. * @param TRP_Translate_Press $trp TRP root instance. */ private function __construct( array $settings, TRP_Translate_Press $trp ) { $this->settings = $settings; $this->url_converter = $trp->get_component( 'url_converter' ); $this->languages = $trp->get_component( 'languages' ); $this->language_switcher_tab = $trp->get_component( 'language_switcher_tab' ); $this->trp = $trp; $this->viewport = wp_is_mobile() ? 'mobile' : 'desktop'; // In case it's not yet initialized, we initialize it here $this->config = $this->language_switcher_tab->get_initial_config(); /** * Add the shortcode here instead of init, so we can run the render_shortcode function on pages excluded from translation * Needed because otherwise the shortcode wouldn't be processed at all and [language-switcher] text would appear on excluded pages */ add_shortcode( 'language-switcher', [ $this, 'render_shortcode' ] ); add_action( 'plugins_loaded', array( $this, 'resolve_language_context' ), 3 ); // Trigger on plugins loaded with higher priority for compat with Multiple Domains } /** * Initialize language switcher functionalities * * Hooked on init 1 * * @return void */ public function init() { add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_assets' ] ); add_action( 'wp_footer', [ $this, 'render_floater' ], 99 ); add_filter( 'wp_get_nav_menu_items', [ $this, 'filter_menu_items' ], 10, 3 ); $this->register_ls_menu_switcher(); add_filter( 'get_user_option_metaboxhidden_nav-menus', [ $this, 'cpt_always_visible_in_menus' ] ); } public function enqueue_assets(): void { wp_enqueue_style( 'trp-language-switcher-v2', trailingslashit( TRP_PLUGIN_URL ) . 'assets/css/trp-language-switcher-v2.css', [], TRP_PLUGIN_VERSION ); wp_enqueue_script( 'trp-language-switcher-js-v2', trailingslashit( TRP_PLUGIN_URL ) . 'assets/js/trp-frontend-language-switcher.js', [], TRP_PLUGIN_VERSION ); } /** Make LS CPT available in Menus */ public function register_ls_menu_switcher() : void { register_post_type('language_switcher', [ 'exclude_from_search' => true, 'publicly_queryable' => false, 'show_ui' => true, 'show_in_nav_menus' => true, 'show_in_menu' => false, 'show_in_admin_bar' => false, 'can_export' => false, 'public' => false, 'label' => 'Language Switcher', ]); } /** * Establishes language context for the request and schedules a canonical redirect if needed. * Sets $current_lang/$needed_lang TRP globals; redirects on missing/mismatched language or slug mismatch. * * @return void */ public function resolve_language_context(): void { $lang_from_url = $this->url_converter->get_lang_from_url_string(); // may be null $needed_lang = $this->determine_needed_language($lang_from_url, $this->trp); $this->current_lang = $lang_from_url ?? $needed_lang; global $TRP_LANGUAGE, $TRP_NEEDED_LANGUAGE; $TRP_LANGUAGE = $needed_lang; $allow = apply_filters('trp_allow_language_redirect', true, $needed_lang, $this->url_converter->cur_page_url()); if ( !$allow || trp_dntcp_is_current_url_excluded() ) return; $missing_in_url = ($lang_from_url === null); $add_subdir = ($this->settings['add-subdirectory-to-default-language'] ?? 'no') === 'yes'; $default = $this->settings['default-language'] ?? ''; if ( ( $missing_in_url && $add_subdir ) || ( $missing_in_url && $needed_lang !== $default ) || ( !$missing_in_url && $needed_lang !== $lang_from_url ) ) { $TRP_NEEDED_LANGUAGE = $needed_lang; add_action('template_redirect', [ $this, 'redirect_to_correct_language' ], 10); } } private function determine_needed_language( ?string $lang_from_url, TRP_Translate_Press $trp ): string { if ( $lang_from_url === null ) { if ( ($this->settings['add-subdirectory-to-default-language'] ?? 'no') === 'yes' && isset( $this->settings['publish-languages'][0] ) ) { $needed_language = $this->settings['publish-languages'][0]; } else { $needed_language = $this->settings['default-language']; } } else { $needed_language = $lang_from_url; } return apply_filters( 'trp_needed_language', $needed_language, $lang_from_url, $this->settings, $trp ); } public function redirect_to_correct_language(): void { if ((defined('DOING_AJAX') && DOING_AJAX) || is_customize_preview()) return; if ($this->url_converter->is_sitemap_path()) return; global $TRP_NEEDED_LANGUAGE; $currLang = $this->url_converter->get_lang_from_url_string(); if ( $currLang === $TRP_NEEDED_LANGUAGE ) return; $dest = esc_url_raw((string) apply_filters( 'trp_link_to_redirect_to', $this->url_converter->get_url_for_language($TRP_NEEDED_LANGUAGE, null, ''), $TRP_NEEDED_LANGUAGE )); $should_add_subdir = ( $this->settings['add-subdirectory-to-default-language'] ?? 'no' ) === 'yes'; $status = ( $should_add_subdir && $TRP_NEEDED_LANGUAGE === ( $this->settings['default-language'] ?? '' ) ) ? (int) apply_filters('trp_redirect_status', 301, 'redirect_to_add_subdirectory_to_default_language') : (int) apply_filters('trp_redirect_status', 302, 'redirect_to_a_different_language_according_to_url_slug'); wp_safe_redirect( $dest, $status ); exit; } /** Keep LS box visible in the Menus screen */ public function cpt_always_visible_in_menus( $result ) { if ( is_array( $result ) && in_array( 'add-post-type-language_switcher', $result, true ) ) { $result = array_diff( $result, ['add-post-type-language_switcher'] ); } return $result; } /** * Floating switcher – inserted in footer. */ public function render_floater(): void { if ( !$this->floater_enabled() ) return; $config = $this->config['floater']; $layout = $config['layoutCustomizer'][ $this->viewport ] ?? $config['layoutCustomizer']['desktop']; $name_type = $layout['languageNames'] ?? 'full'; $positionClass = 'trp-switcher-position-' . ( strpos( $layout['position'], 'top' ) !== false ? 'top' : 'bottom' ); $is_opposite = (bool) $config['oppositeLanguage']; $list = $this->get_language_items( $name_type, $is_opposite ); $current_language = $list[0]; global $TRP_LANGUAGE; /** We do this in order to keep the language order consistent. Currently selected language is always first. */ if ( $config['type'] === 'side-by-side' && $TRP_LANGUAGE !== $this->settings['default-language'] ) $list = array_reverse( $list ); $styles = $this->build_floater_style_attr( $config, $layout ); $viewport = $this->viewport; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo apply_filters( 'trp_floater_ls_html_v2', $this->get_template( $this->template_path( "floating-switcher.php" ), compact( 'list', 'styles', 'config', 'viewport', 'positionClass', 'is_opposite', 'current_language' ), true ) ); if ( !empty( $config['enableCustomCss'] ) && !empty( $config['customCss'] ) && is_string( $config['customCss'] ) ) { $css = str_ireplace( '</style', '', $config['customCss'] ); echo '<style id="trp-language-switcher-custom-css">' . $css . '</style>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } } /** * Shortcode switcher. * * Usage: [language-switcher] * * Reads settings from $this->config['shortcode'] and renders * a dropdown switcher with first item as the current language. * * @param array $atts Shortcode attributes (currently unused). * @return string */ public function render_shortcode( $atts = [] ): string { $loader = $this->trp->get_component( 'loader' ); if ( apply_filters( 'trp_allow_tp_to_run', true, $loader ) === false ) return ''; $atts = shortcode_atts( [ 'is_editor' => 'false', ], $atts, 'language-switcher' ); /** @var bool $is_editor is Gutenberg editor the place of render */ $is_editor = filter_var( $atts['is_editor'], FILTER_VALIDATE_BOOLEAN ); $config = ( isset( $this->config['shortcode'] ) && is_array( $this->config['shortcode'] ) ) ? $this->config['shortcode'] : []; $viewport = $this->viewport; $layout = $config['layoutCustomizer'][ $viewport ] ?? ( $config['layoutCustomizer']['desktop'] ?? [] ); $name_type = $layout['languageNames'] ?? 'full'; $flag_position = $layout['flagIconPosition'] ?? 'before'; $flag_shape = $config['flagShape'] ?? 'rect'; $open_on_click = ! empty( $config['clickLanguage'] ); $flag_ratio = ( $flag_shape === 'square' ) ? 'square' : 'rect'; $is_opposite = (bool) $config['oppositeLanguage']; $list = $this->get_language_items( $name_type, $is_opposite ); if ( empty( $list ) || !isset( $list[0]['code'] ) ) return ''; // nothing to render $item_has_label = $name_type !== 'none'; foreach ( $list as &$item ) { $url = wp_doing_ajax() ? wp_get_referer() : null; $code = $item['code']; $item['url'] = $this->url_converter->get_url_for_language( $code, $url ); $item['flag'] = $this->get_flag_html( $code, $flag_ratio, $item_has_label ); $item['name'] = isset( $item['name'] ) && is_string( $item['name'] ) ? $item['name'] : ''; } unset( $item ); $style_value = $this->build_shortcode_style_value( $config, $layout ); // Render the partial (string), then allow filtering of the final HTML $html = $this->get_template( $this->template_path( 'shortcode-switcher.php' ), compact( 'list', 'config', 'style_value', 'flag_position', 'open_on_click', 'is_editor', 'is_opposite' ), true ); $html = apply_filters( 'trp_shortcode_ls_html_v2', $html, $list, $config, $layout ); if ( ! empty( $config['enableCustomCss'] ) && ! empty( $config['customCss'] ) && is_string( $config['customCss'] ) ) { $css = str_ireplace( '</style', '', $config['customCss'] ); $html .= '<style id="trp-language-switcher-shortcode-custom-css">' . $css . '</style>'; } return $html; } /** * Menu language switcher items. * * @param array $items Menu items. * @param WP_Term $menu Menu term. * @param stdClass $args Nav menu args. * @return array */ public function filter_menu_items( array $items, $menu, $args ): array { if ( empty( $this->config['menu'] ) || !is_array( $this->config['menu'] ) ) { return $items; } $cfg = $this->config['menu']; $layout = $cfg['layoutCustomizer'][ $this->viewport ] ?? ( $cfg['layoutCustomizer']['desktop'] ?? [] ); $flagPos = in_array( ( $layout['flagIconPosition'] ?? 'before' ), [ 'before', 'after', 'hide' ], true ) ? $layout['flagIconPosition'] : 'before'; $nameOpt = in_array( ( $layout['languageNames'] ?? 'full' ), [ 'full', 'short', 'none' ], true ) ? $layout['languageNames'] : 'full'; $shape = in_array( ( $layout['flagShape'] ?? 'rect' ), [ 'rect', 'square', 'rounded' ], true ) ? $layout['flagShape'] : 'rect'; $has_label = $nameOpt !== 'none'; // Used by get_flag_html to choose whether to display alt text or not $user_labels = []; foreach ( $items as $it ) { if ( $it->object !== 'language_switcher' ) continue; $ls_id = $it->object_id ?: get_post_meta( $it->ID ?? 0, '_menu_item_object_id', true ); $ls_post = $ls_id ? get_post( $ls_id ) : null; if ( !$ls_post || $ls_post->post_type !== 'language_switcher' ) continue; $token = $ls_post->post_content; if ( isset( $it->post_title ) && $it->post_title !== '' ) { $user_labels[ $token ] = $it->post_title; } } // Cache display names $published_codes = $this->settings['publish-languages'] ?? []; $full_names = $this->languages->get_language_names( $published_codes ); $current_present = false; // did we see the pseudo 'current_language'? $real_current_indexes = []; // collect real items that equal current language foreach ( $items as $i => $item ) { if ( $item->object !== 'language_switcher' ) continue; $ls_id = $item->object_id ?: get_post_meta( $item->ID ?? 0, '_menu_item_object_id', true ); $ls_post = $ls_id ? get_post( $ls_id ) : null; if ( !$ls_post || $ls_post->post_type !== 'language_switcher' ) continue; $orig = $ls_post->post_content; $code = $orig; if ( $orig === 'current_language' ) { $current_present = true; $code = $this->current_lang; } elseif ( $orig === 'opposite_language' ) { $code = $this->get_opposite_language(); } if ( $orig !== 'current_language' && $code === $this->current_lang && !is_admin() ) { $real_current_indexes[] = $i; } $label_html = !empty( $user_labels[ $orig ] ) && $has_label ? $user_labels[ $orig ] : null; if ( $label_html === null ) { $label_html = $this->build_menu_item_label_viewport( $code, [ 'flagPosition' => $flagPos, 'nameOption' => $nameOpt, 'flagShape' => $shape, ], $full_names ); } else { // Allow flags around a plain user label if configured if ( $flagPos !== 'hide' ) { $flag_html = $this->get_flag_html( $code, $shape, $has_label ); $label_html = ( $flagPos === 'before' ) ? '<span data-no-translation>' . $flag_html . ' <span class="trp-ls-language-name">' . wp_kses_post( $label_html ) . '</span></span>' : '<span data-no-translation><span class="trp-ls-language-name">' . wp_kses_post( $label_html ) . '</span> ' . $flag_html . '</span>'; } else { $label_html = '<span class="trp-ls-language-name" data-no-translation>' . wp_kses_post( $label_html ) . '</span>'; } } $item->url = esc_url( $this->url_converter->get_url_for_language( $code ) ); $item->title = $label_html; $item->classes = array_values( array_unique( array_merge( $item->classes ?? [], [ 'trp-language-switcher-container', 'trp-menu-ls-item', 'trp-menu-ls-' . esc_attr( $this->viewport ), ] ) ) ); if ( $code === $this->current_lang ) $item->classes[] = 'current-language-menu-item'; } if ( $current_present && $real_current_indexes ) { foreach ( array_reverse( $real_current_indexes ) as $idx ) { if ( isset( $items[ $idx ] ) ) { unset( $items[ $idx ] ); } } $items = array_values( $items ); } return $items; } /** * Build one menu item label based on viewport-scoped config: * - flagPosition: 'before'|'after'|'hide' * - nameOption : 'full'|'short'|'none' * - flagShape : 'rect'|'square'|'rounded' * * @param string $code * @param array $opts * @param array $full_names map[code => full name] * @return string HTML */ private function build_menu_item_label_viewport( string $code, array $opts, array $full_names ): string { $flagPos = $opts['flagPosition'] ?? 'before'; $nameOpt = $opts['nameOption'] ?? 'full'; $shape = $opts['flagShape'] ?? 'rect'; $has_label = $nameOpt !== 'none'; $flag_html = $flagPos === 'hide' ? '' : $this->get_flag_html( $code, $shape, $has_label ); $name = ''; if ( $nameOpt === 'full' ) { $name = $full_names[ $code ] ?? $code; } elseif ( $nameOpt === 'short' ) { $name = strtoupper( $this->url_converter->get_url_slug( $code, false ) ); } // 'none' stays as empty string $name_html = $name !== '' ? '<span class="trp-ls-language-name">' . esc_html( $name ) . '</span>' : ''; // Compose order $inner = ($flagPos === 'before') ? trim($flag_html . ' ' . $name_html) : trim($name_html . ' ' . $flag_html); return '<span class="trp-menu-ls-label" data-no-translation title="' . esc_html( $name ) . '">' . $inner . '</span>'; } /** * Language list. * * @param string $language_name_option * @param bool $opposite_only Whether to return only current + opposite language. * @return array */ private function get_language_items( string $language_name_option = 'full', bool $opposite_only = false ): array { $codes = current_user_can( apply_filters( 'trp_translating_capability', 'manage_options' ) ) ? ($this->settings['translation-languages'] ?? []) : ($this->settings['publish-languages'] ?? []); // Guard: establish a safe "current" $current = $this->current_lang ?: ($this->settings['default-language'] ?? null); if ( !$current || !in_array( $current, $codes, true ) ) { $current = $codes[0] ?? ($this->settings['default-language'] ?? ''); } $name_resolvers = [ 'short' => function () use ( $codes ) { return array_combine( $codes, array_map( fn( $code ) => esc_html( strtoupper( $this->url_converter->get_url_slug( $code, false ) ) ), $codes ) ); }, 'full' => fn() => $this->languages->get_language_names( $codes ), 'none' => fn() => array_fill_keys( $codes, '' ) ]; // Default to 'full' if the option is invalid or missing $resolver = $name_resolvers[ $language_name_option ] ?? $name_resolvers['full']; $names = $resolver(); if ( $opposite_only ) { $opp_code = $this->get_opposite_language(); return [[ 'code' => $opp_code, 'name' => $names[$opp_code] ?? '' ]]; } $list = [ [ 'code' => $current, 'name' => $names[ $current ] ?? '', ] ]; foreach ( $names as $code => $name ) { if ( $code !== $current ) $list[] = [ 'code' => $code, 'name' => $name ]; } return $list; } private function get_opposite_language(): string { foreach ( $this->settings['publish-languages'] as $code ) { if ( $code !== $this->current_lang ) { return $code; } } return $this->current_lang; } /** * Build inline style attribute with CSS variables. * * @param array $cfg Floater config. * @param array $layout Layout settings based on the current viewport. * * @return string */ private function build_floater_style_attr( array $cfg, array $layout ): string { $position = $layout['position'] ?? 'bottom-right'; $largeFont = $cfg['size'] === 'large'; $edgeMap = [ 'bottom-right' => [ '--bottom' => '0px', '--right' => '10vw' ], 'bottom-left' => [ '--bottom' => '0px', '--left' => '10vw' ], 'top-right' => [ '--top' => '0px', '--right' => '10vw' ], 'top-left' => [ '--top' => '0px', '--left' => '10vw' ], ]; $positionVars = $edgeMap[$position] ?? []; $vars = apply_filters( 'trp_floating_language_switcher_style_vars', array_merge( [ '--bg' => $cfg['bgColor'] ?: 'transparent', '--bg-hover' => $cfg['bgHoverColor'] ?: 'transparent', '--text' => $cfg['textColor'] ?: '#000', '--text-hover' => $cfg['textHoverColor'] ?: '#000', '--border' => $cfg['borderWidth'] ? "{$cfg['borderWidth']}px solid {$cfg['borderColor']}" : 'none', '--border-radius' => $cfg['borderRadius'] ? $this->build_radius( $cfg['borderRadius'] ) : '8px 8px 0 0', '--flag-radius' => isset( $cfg['flagRadius'] ) ? "{$cfg['flagRadius']}px" : '2px', '--flag-size' => $largeFont ? '20px' : '18px', '--aspect-ratio' => $cfg['flagShape'] === 'rect' ? '4/3' : '1', '--font-size' => $largeFont ? '16px' : '14px', '--switcher-width' => ( $layout['width'] === 'custom' ? ( $layout['customWidth'] ?? 216 ) . 'px' : 'auto' ), '--switcher-padding' => ( $layout['padding'] === 'custom' ? ( $layout['customPadding'] ?? 0 ). 'px' : '10px 0' ), '--transition-duration' => $cfg['enableTransitions'] ? '0.2s' : '0s' ], $positionVars ) ); $pairs = array(); foreach ( $vars as $k => $v ) { if ( ! is_string( $k ) || ! preg_match( '/^--[a-z0-9-]+$/i', $k ) ) { continue; } $pairs[] = $k . ':' . $v; } return implode( ';', $pairs ); } /** * Build inline style attribute with CSS variables for the shortcode switcher. * * @param array $cfg Shortcode config. * @param array $layout Layout settings based on current viewport. * @return string style="--var: value; ..." */ private function build_shortcode_style_value( array $cfg, array $layout ): string { $large_font = isset( $cfg['size'] ) && $cfg['size'] === 'large'; $font_size = $large_font ? '16px' : '14px'; $flag_size = $large_font ? '20px' : '18px'; // Scalar border radius (shortcode config uses int) $radius_scalar = isset( $cfg['borderRadius'] ) && is_numeric( $cfg['borderRadius'] ) ? (int) $cfg['borderRadius'] : 5; $border_width = isset( $cfg['borderWidth'] ) ? (int) $cfg['borderWidth'] : 0; $border_color = isset( $cfg['borderColor'] ) ? (string) $cfg['borderColor'] : '#1438521a'; $border = $border_width > 0 ? sprintf( '%dpx solid %s', $border_width, $border_color ) : 'none'; $vars = [ '--bg' => isset( $cfg['bgColor'] ) ? (string) $cfg['bgColor'] : '#ffffff', '--bg-hover' => isset( $cfg['bgHoverColor'] ) ? (string) $cfg['bgHoverColor'] : '#0000000d', '--text' => isset( $cfg['textColor'] ) ? (string) $cfg['textColor'] : '#a9adb0', '--text-hover' => isset( $cfg['textHoverColor'] ) ? (string) $cfg['textHoverColor'] : '#1d2327', // Support both a single --border var and split width/color vars (if your CSS uses either). '--border' => $border, '--border-width' => $border_width . 'px', '--border-color' => $border_color, '--border-radius' => $radius_scalar . 'px', '--flag-radius' => isset( $cfg['flagRadius'] ) ? (int) $cfg['flagRadius'] . 'px' : '2px', '--flag-size' => $flag_size, '--aspect-ratio' => ( isset( $cfg['flagShape'] ) && $cfg['flagShape'] === 'rect' ) ? '4/3' : '1', '--font-size' => $font_size, '--transition-duration' => ( $cfg['enableTransitions'] ?? true ) ? '0.2s' : '0s' ]; $pairs = []; foreach ( $vars as $k => $v ) { $pairs[] = $k . ':' . $v; } return implode( ';', $pairs ); } private function build_radius( array $r ): string { return implode( ' ', array_map( static fn( $v ) => intval( $v ) . 'px', $r ) ); } private function template_path( string $file ): string { return trailingslashit( TRP_PLUGIN_DIR ) . 'partials/' . $file; } /** * Tiny templating helper. * * @param string $path Absolute path. * @param array $vars Vars to extract. * @param bool $return Return string or echo. * @return string */ private function get_template( string $path, array $vars = [], bool $return = false ): string { if ( !file_exists( $path ) ) { return ''; } ob_start(); extract( $vars, EXTR_SKIP ); include $path; $content = ob_get_clean(); if ( $return ) { return $content; } // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Template HTML, values escaped in template. echo $content; return ''; } /** * Determine if the floater should render. * * @return bool */ private function floater_enabled(): bool { return !empty( $this->config['floater']['enabled'] ); } /** * Returns the HTML element that shows a flag using the * lipis/flag-icons CSS classes. * * @param string $language_code Either “en”, “en_US”, “pt-BR”, etc. * @param string $shape Flag shape * @param bool $has_label Whether the language item already has a label or not. We use it in order to display alt text on flags only display mode. * @return string <span class="fi fi-xx">…</span> */ public function get_flag_html( string $language_code, string $shape, bool $has_label = false ): string { global $TRP_LANGUAGE; // Allow override via filter (custom flag URL) $flag_path = apply_filters( 'trp_flags_path', '', $language_code ); $name = $this->languages->get_language_names( [ $language_code ] )[ $language_code ] ?? $language_code; $is_current = $language_code === $TRP_LANGUAGE; // Alt logic $alt = $has_label || $is_current ? '' : sprintf( __( 'Change language to %s', 'translatepress-multilingual' ), $name ); $role = $has_label || $is_current ? ' role="presentation"' : ''; $classes = [ 'trp-flag-image' ]; if ( $shape === 'rounded' ) { $classes[] = 'trp-flag-rounded'; } if ( $shape === 'square' ) { $classes[] = 'trp-flag-square'; } if ( filter_var( $flag_path, FILTER_VALIDATE_URL ) ) { $classes[] = 'trp-custom-flag'; $html = sprintf( '<img src="%s" class="%s" alt="%s" loading="lazy" decoding="async" width="18" height="14" />', esc_url( $flag_path ), esc_attr( implode( ' ', $classes ) ), esc_attr( $name ) ); return apply_filters( 'trp_flag_html', $html, $language_code, $flag_path ); } // Decide folder: square/rounded use 1x1, default is 4x3 $ratio = ( $shape === 'square' || $shape === 'rounded' ) ? '1x1' : '4x3'; // Locale-based filename (hyphen → underscore) $locale_file = str_replace( '-', '_', trim( $language_code ) ) . '.svg'; // Absolute URL & path $url = trailingslashit( TRP_PLUGIN_URL ) . 'assets/flags/' . $ratio . '/' . rawurlencode( $locale_file ); $path = trailingslashit( TRP_PLUGIN_DIR ) . 'assets/flags/' . $ratio . '/' . $locale_file; // If missing, output nothing if ( !is_readable( $path ) ) { return ''; } $html = sprintf( '<img src="%s" class="%s" alt="%s"%s loading="lazy" decoding="async" width="18" height="14" />', esc_url( $url ), esc_attr( implode( ' ', $classes ) ), esc_attr( $alt ), $role ); return apply_filters( 'trp_flag_html', $html, $language_code, $url ); } /** * Legacy function to add flag * @important This function is used in WP Rocket plugin. Please don't remove it or change its signature. * * @param $language_code * @param $language_name * @param $location * @return string * @deprecated */ public function add_flag( $language_code, $language_name, $location = NULL ) { $flags_path = TRP_PLUGIN_URL . 'assets/images/flags/'; $flags_path = apply_filters( 'trp_flags_path', $flags_path, $language_code ); $flag_file_name = $language_code . '.png'; if ( $location == 'ls_shortcode' ) { $flag_url = $flags_path . $flag_file_name; return esc_url( $flag_url ); } return $this->get_flag_html( $language_code, 'rect' ); } /** * Legacy function for rendering shortcode LS * * @param $atts * @return void * @deprecated */ public function language_switcher( $atts ){ return $this->render_shortcode(); } /** * Legacy function for rendering floater LS * */ public function add_floater_language_switcher(){ return $this->render_floater(); } /** * Legacy function used in older versions of Automatic Language Detection Add-on * */ public function add_shortcode_preferences( $settings, $language_code, $language_name ) { if ( $settings['flags'] ){ $flag = $this->add_flag($language_code, $language_name); } else { $flag = ''; } if ( $settings['full_names'] ){ $full_name = $language_name; } else { $full_name = ''; } if ( $settings['short_names'] ){ $short_name = strtoupper( $this->url_converter->get_url_slug( $language_code, false ) ); } else { $short_name = ''; } return $flag . ' ' . esc_html( $short_name . $full_name ); } }
[-] class-plugin-notices.php
[edit]
[-] class-editor-api-gettext-strings.php
[edit]
[-] class-machine-translator-logger.php
[edit]
[-] functions.php
[edit]
[-] class-check-invalid-text.php
[edit]
[+]
google-translate
[-] .htaccess
[edit]
[-] class-error-manager.php
[edit]
[+]
gutenberg-blocks
[-] external-functions.php
[edit]
[+]
string-translation
[-] class-upgrade.php
[edit]
[-] class-editor-api-regular-strings.php
[edit]
[-] class-translation-manager.php
[edit]
[+]
queries
[-] class-elementor-language-for-blocks.php
[edit]
[-] class-advanced-tab.php
[edit]
[-] class-search.php
[edit]
[-] class-hooks-loader.php
[edit]
[+]
gettext
[-] class-ai-words-notification.php
[edit]
[-] class-reviews.php
[edit]
[-] class-plugin-optin.php
[edit]
[-] class-translation-memory.php
[edit]
[-] class-machine-translation-tab.php
[edit]
[-] class-support-chat.php
[edit]
[-] shortcodes.php
[edit]
[-] class-preferred-user-language.php
[edit]
[+]
onboarding
[-] class-language-switcher.php
[edit]
[-] class-languages.php
[edit]
[+]
upgrade
[+]
advanced-settings
[-] trp-ajax.php
[edit]
[-] class-onboarding.php
[edit]
[-] class-wp-bakery-language-for-blocks.php
[edit]
[-] class-rewrite-rules.php
[edit]
[-] class-language-switcher-tab.php
[edit]
[-] class-language-switcher-v2.php
[edit]
[-] compatibility-functions.php
[edit]
[-] class-woocommerce-emails.php
[edit]
[-] class-translation-render.php
[edit]
[-] class-install-plugins.php
[edit]
[-] class-edd-sl-plugin-updater.php
[edit]
[-] class-machine-translator.php
[edit]
[-] custom-language.php
[edit]
[-] class-settings.php
[edit]
[-] class-uri.php
[edit]
[-] class-url-converter.php
[edit]
[+]
mtapi
[+]
..