settings == null ){ $this->set_options(); } return $this->settings; } /** * Returns the value of an individual setting or the default provided. * * @param string $name * @param default mixed * * @return mixed Setting Value */ public function get_setting($name, $default = null){ if( array_key_exists($name, $this->settings ) ){ return maybe_unserialize($this->settings[$name]); } else { return $default; } } /** * Register Settings subpage for Translangated */ public function register_menu_page(){ add_options_page( 'Translangated', 'Translangated', apply_filters( 'translangated_settings_capability', 'manage_options' ), 'translangated', array( $this, 'settings_page_content' ) ); } /** * Settings page content. */ public function settings_page_content(){ if ( ! $this->translangated_languages ){ $trp = Translangated_Plugin::get_translangated_instance(); $this->translangated_languages = $trp->get_component( 'languages' ); } $languages = $this->translangated_languages->get_languages( 'english_name' ); require_once TRANSLANGATED_PLUGIN_DIR . 'partials/main-settings-page.php'; } /** * Register settings option. */ public function register_setting(){ register_setting( 'translangated_settings', 'translangated_settings', array( $this, 'sanitize_settings' ) ); } /** * Sanitizes a settings option after save. * * Updates menu items for languages to be used in Menus. * * @param array $settings Raw settings option. * @return array Sanitized option page. */ public function sanitize_settings( $settings ){ if ( ! $this->translangated_query ) { $trp = Translangated_Plugin::get_translangated_instance(); $this->translangated_query = $trp->get_component( 'query' ); } if ( ! $this->translangated_languages ){ $trp = Translangated_Plugin::get_translangated_instance(); $this->translangated_languages = $trp->get_component( 'languages' ); } if ( !isset ( $settings['default-language'] ) ) { $settings['default-language'] = 'en_US'; } if ( !isset ( $settings['translation-languages'] ) ){ $settings['translation-languages'] = array(); } if ( !isset ( $settings['publish-languages'] ) ){ $settings['publish-languages'] = array(); } $settings['translation-languages'] = array_filter( array_unique( $settings['translation-languages'] ) ); $settings['publish-languages'] = array_filter( array_unique( $settings['publish-languages'] ) ); if ( ! in_array( $settings['default-language'], $settings['translation-languages'] ) ){ array_unshift( $settings['translation-languages'], $settings['default-language'] ); } if ( ! in_array( $settings['default-language'], $settings['publish-languages'] ) ){ array_unshift( $settings['publish-languages'], $settings['default-language'] ); } // check if submitted language codes are valid. Default language is included here too $check_language_codes = array_unique( array_merge($settings['translation-languages'], $settings['publish-languages']) ); foreach($check_language_codes as $check_language_code ){ if ( !translangated_is_valid_language_code($check_language_code) ){ add_settings_error( 'translangated_advanced_settings', 'settings_error', esc_html__('Invalid language code. Please try again.', 'translangated'), 'error' ); return get_option( 'translangated_settings', 'not_set' ); } } if( !empty( $settings['native_or_english_name'] ) ) $settings['native_or_english_name'] = sanitize_text_field( $settings['native_or_english_name'] ); else $settings['native_or_english_name'] = 'english_name'; if( !empty( $settings['add-subdirectory-to-default-language'] ) ) $settings['add-subdirectory-to-default-language'] = sanitize_text_field( $settings['add-subdirectory-to-default-language'] ); else $settings['add-subdirectory-to-default-language'] = 'no'; if( !empty( $settings['force-language-to-custom-links'] ) ) $settings['force-language-to-custom-links'] = sanitize_text_field( $settings['force-language-to-custom-links'] ); else $settings['force-language-to-custom-links'] = 'no'; if ( !empty( $settings['trp-ls-floater'] ) ){ $settings['trp-ls-floater'] = sanitize_text_field( $settings['trp-ls-floater'] ); }else{ $settings['trp-ls-floater'] = 'no'; } if ( ! isset( $settings['floater-position'] ) ){ $settings['floater-position'] = 'bottom-right'; } if ( ! isset( $settings['floater-color'] ) ){ $settings['floater-color'] = 'dark'; } if ( !empty( $settings['trp-ls-show-poweredby'] ) ){ $settings['trp-ls-show-poweredby'] = sanitize_text_field( $settings['trp-ls-show-poweredby'] ); }else{ $settings['trp-ls-show-poweredby'] = 'no'; } if ( ! isset( $settings['url-slugs'] ) ){ $settings['url-slugs'] = $this->translangated_languages->get_iso_codes( $settings['translation-languages'] ); } foreach( $settings['translation-languages'] as $language_code ){ if ( empty ( $settings['url-slugs'][$language_code] ) ){ $settings['url-slugs'][$language_code] = $language_code; }else{ $settings['url-slugs'][$language_code] = sanitize_title( strtolower( $settings['url-slugs'][$language_code] )) ; } } foreach ($settings['translation-languages'] as $value=>$language){ if(isset($settings['translation-languages-formality'][$value])) { if ( $settings['translation-languages-formality'][ $value ] == 'informal' ) { $settings['translation-languages-formality-parameter'][ $language ] = 'informal'; } else { if ( $settings['translation-languages-formality'][ $value ] == 'formal' ) { $settings['translation-languages-formality-parameter'][ $language ] = 'formal'; } else { $settings['translation-languages-formality-parameter'][ $language ] = 'default'; } } } } unset($settings['translation-languages-formality']); $trp = Translangated_Plugin::get_translangated_instance(); $language_switcher_tab = $trp->get_component('language_switcher_tab'); if ( count( $settings['publish-languages'] ) > 2 ) { $ls_settings = $language_switcher_tab->get_initial_config(); $new_ls_settings = $ls_settings; $new_ls_settings['floater']['oppositeLanguage'] = false; $new_ls_settings['shortcode']['oppositeLanguage'] = false; if ( $new_ls_settings !== $ls_settings ){ update_option( 'translangated_language_switcher_settings', $new_ls_settings ); } } // check for duplicates in url slugs $duplicate_exists = false; foreach( $settings['url-slugs'] as $urlslug ) { if ( count ( array_keys( $settings['url-slugs'], $urlslug ) ) > 1 ){ $duplicate_exists = true; break; } } if ( $duplicate_exists ){ foreach( $settings['translation-languages'] as $language_code ) { $settings['url-slugs'][$language_code] = $language_code; } } $this->create_menu_entries( $settings['publish-languages'] ); $gettext_table_creation = $this->translangated_query->get_query_component('gettext_table_creation'); require_once ABSPATH . 'wp-admin/includes/translation-install.php'; // wp_download_language_pack() below foreach ( $settings['translation-languages'] as $language_code ){ if ( $settings['default-language'] != $language_code ) { $this->translangated_query->check_table( $settings['default-language'], $language_code ); } wp_download_language_pack( $language_code ); $gettext_table_creation->check_gettext_table( $language_code ); } //in version 1.6.6 we normalized the original strings and created new tables $this->translangated_query->check_original_table(); $this->translangated_query->check_original_meta_table(); $gettext_table_creation->check_gettext_original_table(); $gettext_table_creation->check_gettext_original_meta_table(); // table used to keep concurrent requests from machine translating the same string at the same time $this->translangated_query->check_machine_translation_lock_table(); // regenerate permalinks in case something changed flush_rewrite_rules(); return apply_filters( 'translangated_extra_sanitize_settings', $this->keep_known_settings( $settings ) ); } /** * Build the stored translangated_settings from the known keys only, each sanitized for its type. * Runs after sanitize_settings() has validated the language codes. * * @param array $settings Settings processed by sanitize_settings(). * @return array */ protected function keep_known_settings( $settings ) { $yes_no = static function ( $value ) { return $value === 'yes' ? 'yes' : 'no'; }; $languages = array_values( (array) $settings['translation-languages'] ); $clean = array( 'default-language' => $settings['default-language'], 'translation-languages' => $languages, 'publish-languages' => array_values( array_intersect( (array) $settings['publish-languages'], $languages ) ), 'native_or_english_name' => $settings['native_or_english_name'] === 'native_name' ? 'native_name' : 'english_name', 'add-subdirectory-to-default-language' => $yes_no( $settings['add-subdirectory-to-default-language'] ), 'force-language-to-custom-links' => $yes_no( $settings['force-language-to-custom-links'] ), 'trp-ls-floater' => $yes_no( $settings['trp-ls-floater'] ), 'trp-ls-show-poweredby' => $yes_no( $settings['trp-ls-show-poweredby'] ), 'url-slugs' => array(), ); // Settings of the previous language switcher, only read to migrate it. foreach ( array( 'shortcode-options', 'menu-options', 'floater-options', 'floater-position', 'floater-color' ) as $key ) { if ( isset( $settings[ $key ] ) && is_string( $settings[ $key ] ) ) { $clean[ $key ] = sanitize_key( $settings[ $key ] ); } } foreach ( $languages as $language_code ) { // An empty slug falls back to the (already validated) language code, kept as is. $slug = $settings['url-slugs'][ $language_code ] ?? $language_code; $clean['url-slugs'][ $language_code ] = ( $slug === $language_code ) ? $language_code : sanitize_title( $slug ); $formality = $settings['translation-languages-formality-parameter'][ $language_code ] ?? null; if ( $formality !== null ) { $clean['translation-languages-formality-parameter'][ $language_code ] = in_array( $formality, array( 'formal', 'informal' ), true ) ? $formality : 'default'; } } // Domain per language, set by the multiple-domains integration. if ( isset( $settings['trp-multiple-domains'] ) && is_array( $settings['trp-multiple-domains'] ) ) { foreach ( $settings['trp-multiple-domains'] as $language_code => $domain ) { if ( in_array( $language_code, $languages, true ) && is_string( $domain ) ) { $clean['trp-multiple-domains'][ $language_code ] = sanitize_text_field( $domain ); } } } return $clean; } /** * Output admin notices after saving settings. */ public function admin_notices(){ settings_errors( 'translangated_settings' ); } /** * Set options array variable to be used across plugin. * * Sets a default option if it does not exist. */ protected function set_options(){ $settings_option = get_option( 'translangated_settings', 'not_set' ); // initialize default settings $default = get_locale(); if ( empty( $default ) ){ $default = 'en_US'; } $default_settings = array( 'default-language' => $default, 'translation-languages' => array( $default ), 'publish-languages' => array( $default ), 'native_or_english_name' => 'english_name', 'add-subdirectory-to-default-language' => 'no', 'force-language-to-custom-links' => 'yes', 'trp-ls-floater' => 'yes', 'shortcode-options' => 'flags-full-names', 'menu-options' => 'flags-full-names', 'floater-options' => 'flags-full-names', 'floater-position' => 'bottom-right', 'floater-color' => 'dark', 'trp-ls-show-poweredby' => 'no', 'url-slugs' => array( 'en_US' => 'en', '' ), ); if ( 'not_set' == $settings_option || is_string($settings_option) ){ if ( is_string( $settings_option ) && 'not_set' !== $settings_option ){ error_log( 'Invalid translangated_settings: ' . wp_json_encode($settings_option) ); } update_option ( 'translangated_settings', $default_settings ); $settings_option = $default_settings; }else{ // Add any missing default option for translangated_setting foreach ( $default_settings as $key_default_setting => $value_default_setting ){ if ( !isset ( $settings_option[$key_default_setting] ) ) { $settings_option[$key_default_setting] = $value_default_setting; } } } // Might have saved invalid language codes in the past so this code protects against SQL Injections using invalid language codes which are used in queries $check_language_codes = array_unique( array_merge($settings_option['translation-languages'], $settings_option['publish-languages']) ); foreach($check_language_codes as $check_language_code ) { if ( !translangated_is_valid_language_code( $check_language_code ) ) { add_filter('plugins_loaded', array($this, 'show_invalid_language_codes_error_notice'), 999999); } } /** * These options (translangated_advanced_settings, translangated_machine_translation_settings, translangated_language_switcher_settings) are not part of the actual translangated_settings DB option. * But they are included in $settings variable across TP */ $settings_option['translangated_advanced_settings'] = get_option('translangated_advanced_settings', array() ); $settings_option['translangated_language_switcher_settings'] = get_option( 'translangated_language_switcher_settings', [] ); // Add any missing default option for translangated_machine_translation_settings $default_translangated_machine_translation_settings = $this->get_default_translangated_machine_translation_settings(); // a client reported a notice where, in wp_options table, the translangated_machine_translation_settings is false // we don't know how ths happened since the setting should be an array, or it shouldn't exist // this couldn't be replicated on a clean instance $translangated_check_if_machine_settings_is_array = get_option( 'translangated_machine_translation_settings', $default_translangated_machine_translation_settings ); if ( is_array( $translangated_check_if_machine_settings_is_array )) { $settings_option['translangated_machine_translation_settings'] = array_merge( $default_translangated_machine_translation_settings, $translangated_check_if_machine_settings_is_array ); }else{ $settings_option[ 'translangated_machine_translation_settings' ] = $default_translangated_machine_translation_settings; } /* @deprecated Setting only used for compatibility with Deepl Add-on 1.0.0 */ if ( $settings_option['translangated_machine_translation_settings']['translation-engine'] === 'deepl' && defined( 'TRANSLANGATED_DL_PLUGIN_VERSION' ) && TRANSLANGATED_DL_PLUGIN_VERSION === '1.0.0' ) { $translangated_languages = new Translangated_Languages(); $settings_option['machine-translate-codes'] = $translangated_languages->get_iso_codes($settings_option['translation-languages']); if ( isset( $settings_option['translangated_machine_translation_settings']['deepl-api-key'] ) ) { $settings_option['deepl-api-key'] = $settings_option['translangated_machine_translation_settings']['deepl-api-key']; } } $this->settings = $settings_option; } public function show_invalid_language_codes_error_notice(){ $trp = Translangated_Plugin::get_translangated_instance(); $error_manager = $trp->get_component( 'error_manager' ); $error_manager->record_error( array( 'message' => esc_html__('Language codes can contain only A-Z a-z 0-9 - _ characters. Check your language codes in Translangated General Settings.', 'translangated'), 'notification_id' => 'translangated_invalid_language_code' ) ); } public function get_default_translangated_machine_translation_settings(){ return apply_filters( 'translangated_get_default_translangated_machine_translation_settings', array( // default settings for translangated_machine_translation_settings 'machine-translation' => 'no', 'translation-engine' => 'google_translate_v2', 'block-crawlers' => 'yes', 'automatically-translate-slug' => 'yes', 'machine_translation_counter_date' => gmdate( "Y-m-d" ), 'machine_translation_limit_enabled' => 'no', 'machine_translation_limit' => 1000000, /* * These settings are merged into the saved DB option. * Be sure to set any checkbox options to 'no' in sanitize_settings. * Unchecked checkboxes don't have a POST value when saving settings, so they will be overwritten by merging. */ )); } /** * Enqueue scripts and styles for settings page. * * @param string $hook Admin page. */ public function enqueue_scripts_and_styles( $hook ) { if( in_array( $hook, [ 'settings_page_translangated', 'admin_page_translangated_advanced_page', 'admin_page_translangated_machine_translation', 'admin_page_translangated_machine_translation_glossary', 'admin_page_translangated_test_machine_api', 'admin_page_translangated_remove_duplicate_rows', 'admin_page_translangated_update_database', 'admin_page_translangated_language_switcher', 'admin_page_translangated-onboarding' ] ) ){ wp_enqueue_style( 'translangated-settings-style', TRANSLANGATED_PLUGIN_URL . 'assets/css/trp-back-end-style.css', array(), TRANSLANGATED_PLUGIN_VERSION ); } if( in_array( $hook, array( 'settings_page_translangated', 'admin_page_translangated_advanced_page', 'admin_page_translangated_machine_translation', 'admin_page_translangated_machine_translation_glossary' ) ) ) { // Base script now handles both free and pro functionality via hooks/filters. // However, we keep loading trp-back-end-script-pro.js for backwords compatibility when TP Free is newer then the Pro Addon. $back_end_script_url = TRANSLANGATED_PLUGIN_URL . 'assets/js/trp-back-end-script.js'; if( defined( 'TRANSLANGATED_IN_EL_PLUGIN_URL' ) && file_exists( TRANSLANGATED_IN_EL_PLUGIN_DIR . 'assets/js/trp-back-end-script-pro.js' ) ) { $back_end_script_url = TRANSLANGATED_IN_EL_PLUGIN_URL . 'assets/js/trp-back-end-script-pro.js'; } wp_enqueue_script( 'translangated-settings-script', $back_end_script_url, array( 'jquery', 'jquery-ui-sortable' ), TRANSLANGATED_PLUGIN_VERSION ); if ( ! $this->translangated_languages ){ $trp = Translangated_Plugin::get_translangated_instance(); $this->translangated_languages = $trp->get_component( 'languages' ); } $all_language_codes = $this->translangated_languages->get_all_language_codes(); $iso_codes = $this->translangated_languages->get_iso_codes( $all_language_codes, false ); $tp_data = get_option('translangated_db_stored_data', array() ); $languages_that_support_formality = isset( $tp_data['translangated_mt_supported_languages'][$this->settings['translangated_machine_translation_settings']['translation-engine']] ) ? $tp_data['translangated_mt_supported_languages'][$this->settings['translangated_machine_translation_settings']['translation-engine']]['formality-supported-languages'] : '' ; wp_localize_script( 'translangated-settings-script', 'translangated_url_slugs_info', array( 'iso_codes' => $iso_codes, 'languages_that_support_formality' => $languages_that_support_formality, 'max_secondary_languages' => apply_filters( 'translangated_secondary_languages', 1 ), 'error_message_duplicate_slugs' => __( 'Error! Duplicate URL slug values.', 'translangated' ), 'error_message_formality' => wp_kses( __( 'You cannot select two languages that have the same iso code but different formalities because doing so will lead to duplicate hreflang tags.', 'translangated' ), [ 'a' => [ 'href' => [], 'class' => [], 'rel' => [], 'target' => [] ] ] ), 'error_message_duplicate_languages' => wp_kses( __( 'Duplicate language detected.
Each language can only be added once to ensure accurate translation management.
Please change the duplicate language entry and try again. ', 'translangated' ), [ 'br' => [] ] ), 'admin-ajax' => admin_url( 'admin-ajax.php' ), ) ); wp_enqueue_script( 'translangated-select2-lib-js', TRANSLANGATED_PLUGIN_URL . 'assets/lib/select2-lib/dist/js/select2.min.js', array( 'jquery' ), '4.1.0' ); wp_enqueue_style( 'translangated-select2-lib-css', TRANSLANGATED_PLUGIN_URL . 'assets/lib/select2-lib/dist/css/select2.min.css', array(), '4.1.0' ); } } /** * Output HTML for Translation Language option. * * Hooked to translangated_language_selector. * * @param array $languages All available languages. */ public function languages_selector( $languages ){ if ( ! $this->url_converter ) { $trp = Translangated_Plugin::get_translangated_instance(); $this->url_converter = $trp->get_component('url_converter'); } $selected_language_code = ''; require_once TRANSLANGATED_PLUGIN_DIR . 'partials/main-settings-language-selector.php'; } /** * Update language switcher menu items. * * @param array $languages Array of language codes to create menu items for. */ public function create_menu_entries( $languages ){ if ( ! $this->translangated_languages ){ $trp = Translangated_Plugin::get_translangated_instance(); $this->translangated_languages = $trp->get_component( 'languages' ); } $published_languages = $this->translangated_languages->get_language_names( $languages, 'english_name' ); $published_languages['current_language'] = __( 'Current Language', 'translangated' ); $languages[] = 'current_language'; $posts = get_posts( array( 'post_type' =>'translangated_ls', 'posts_per_page' => -1 ) ); if ( count( $published_languages ) == 3 ){ $languages[] = 'opposite_language'; $published_languages['opposite_language'] = __( 'Opposite Language', 'translangated' ); } foreach ( $published_languages as $language_code => $language_name ) { $existing_ls = null; foreach( $posts as $post ){ if ( $post->post_content == $language_code ){ $existing_ls = $post; break; } } $ls = array( 'post_title' => $language_name, 'post_content' => $language_code, 'post_status' => 'publish', 'post_type' => 'translangated_ls' ); if ( $existing_ls ){ $ls['ID'] = $existing_ls->ID; wp_update_post( $ls ); }else{ wp_insert_post( $ls ); } } foreach ( $posts as $post ){ if ( ! in_array( $post->post_content, $languages ) ){ wp_delete_post( $post->ID ); } } } /** * Add navigation tabs in settings. * */ public function add_navigation_tabs(){ add_filter( 'translangated_add_language_to_home_url_check_for_admin', '__return_false' ); $translate_site_url = add_query_arg( 'trp-edit-translation', 'true', home_url() ); remove_filter( 'translangated_add_language_to_home_url_check_for_admin', '__return_false' ); $tabs = array( array( 'name' => __( 'General', 'translangated' ), 'url' => admin_url( 'options-general.php?page=translangated' ), 'page' => 'translangated' ), array( 'name' => __( 'Translate Site', 'translangated' ), 'url' => $translate_site_url, 'page' => 'translangated_translation_editor' ), ); $tabs = apply_filters( 'translangated_settings_tabs', $tabs ); $active_tab = 'translangated'; if ( isset( $_GET['page'] ) ){ $active_tab = sanitize_text_field( wp_unslash( $_GET['page'] ) ); } $active_tab = apply_filters( 'translangated_settings_active_tab', $active_tab ); require TRANSLANGATED_PLUGIN_DIR . 'partials/settings-navigation-tabs.php'; } /** * Add SVG icon symbols to use throughout the admin. */ public function add_svg_icons() { ?> %2$s', admin_url( 'options-general.php?page=translangated' ), __( 'Settings', 'translangated' ) ); array_unshift( $links, $settings_link ); return $links; } }