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;
}
}