PATH:
home
/
lab2454c
/
public_html
/
wp-content
/
plugins
/
translatepress-multilingual
/
includes
/
gettext
<?php /** * Class TRP_Gettext_Manager * * Handles Gettext strings */ class TRP_Gettext_Manager { protected $settings; /** @var TRP_Query */ protected $trp_query; /** @var TRP_Process_Gettext */ protected $process_gettext; /** @var TRP_Plural_Forms */ protected $plural_forms; protected $machine_translator; protected $url_converter; protected $is_admin_request = null; /** * TRP_Gettext_Manager constructor. * * @param array $settings Settings option. */ public function __construct( $settings ) { $this->settings = $settings; $this->plural_forms = new TRP_Plural_Forms( $this->settings ); $this->process_gettext = new TRP_Process_Gettext( $this->settings, $this->plural_forms ); } public function get_gettext_component( $component ) { return $this->$component; } /** * Create a global with the gettext strings that exist in the database */ public function create_gettext_translated_global() { global $trp_translated_gettext_texts, $trp_translated_gettext_texts_language; if ( $this->processing_gettext_is_needed() ) { $language = get_locale(); if ( in_array( $language, $this->settings['translation-languages'] ) ) { $trp_translated_gettext_texts_language = $language; global $wpdb, $trp_wpdb_prefix; $trp_wpdb_prefix = $wpdb->get_blog_prefix(); $trp = TRP_Translate_Press::get_trp_instance(); if ( ! $this->trp_query ) { $this->trp_query = $trp->get_component( 'query' ); } $strings = $this->trp_query->get_all_gettext_strings( $language ); if ( ! empty( $strings ) ) { $trp_translated_gettext_texts = $strings; $trp_strings = array(); foreach ( $trp_translated_gettext_texts as $key => $value ) { $context = ( $value['context'] ) ? $value['context'] : 'trp_context'; $plural_form = ( $value['plural_form'] ) ? $value['plural_form'] : 0; $domain = ( $value['domain'] ) ? $value['domain'] : $value['tt_domain']; $original = ( $value['original'] ) ? $value['original'] : $value['tt_original']; // trp_context::0::domain::original $trp_strings[ $context . '::' . $plural_form . '::' . $domain . '::' . $original ] = $value; } $trp_translated_gettext_texts = $trp_strings; } } } } /** * function that applies the gettext filter on frontend on different hooks depending on what we need */ public function initialize_gettext_processing() { $is_ajax_on_frontend = $this::is_ajax_on_frontend(); /* on ajax hooks from frontend that have the init hook ( we found WooCommerce has it ) apply it earlier */ if ( $is_ajax_on_frontend || apply_filters( 'trp_apply_gettext_early', false ) ) { add_action( 'wp_loaded', array( $this, 'apply_gettext_filter' ) ); } else {//otherwise start from the wp_head hook add_action( 'wp_head', array( $this, 'apply_gettext_filter' ), 100 ); } //if we have woocommerce installed and it is not an ajax request add a gettext hook starting from wp_loaded and remove it on wp_head if ( class_exists( 'WooCommerce' ) && ! $is_ajax_on_frontend && ! apply_filters( 'trp_apply_gettext_early', false ) ) { // WooCommerce launches some ajax calls before wp_head, so we need to apply_gettext_filter earlier to catch them add_action( 'wp_loaded', array( $this, 'apply_woocommerce_gettext_filter' ), 19 ); } } /* apply the gettext filter here */ public function apply_gettext_filter() { //if we have wocommerce installed remove te hook that was added on wp_loaded if ( class_exists( 'WooCommerce' ) ) { // WooCommerce launches some ajax calls before wp_head, so we need to apply_gettext_filter earlier to catch them remove_action( 'wp_loaded', array( $this, 'apply_woocommerce_gettext_filter' ), 19 ); } $this->call_gettext_filters(); } public function apply_woocommerce_gettext_filter() { $this->call_gettext_filters( 'woocommerce_' ); } public function processing_gettext_is_needed() { global $pagenow; if ( ! $this->url_converter ) { $trp = TRP_Translate_Press::get_trp_instance(); $this->url_converter = $trp->get_component( 'url_converter' ); } if ( $this->is_admin_request === null ) { $this->is_admin_request = $this->url_converter->is_admin_request(); } // Do not process gettext strings on wp-login pages. Do not process strings in admin area except for when when is_ajax_on_frontend. Do not process gettext strings when is rest api from admin url referer. Do not process gettext on xmlrpc.pho return ( ( $pagenow != 'wp-login.php' ) && ( ! is_admin() || $this::is_ajax_on_frontend() ) && ! $this->is_admin_request && $pagenow != 'xmlrpc.php' ); } public function call_gettext_filters( $prefix = '' ) { if ( $this->processing_gettext_is_needed() ) { add_filter( 'gettext', array( $this->process_gettext, $prefix . 'process_gettext_strings_no_context' ), 100, 3 ); add_filter( 'gettext_with_context', array( $this->process_gettext, $prefix . 'process_gettext_strings_with_context' ), 100, 4 ); add_filter( 'ngettext', array( $this->process_gettext, $prefix . 'process_ngettext_strings' ), 100, 5 ); add_filter( 'ngettext_with_context', array( $this->process_gettext, $prefix . 'process_ngettext_strings_with_context' ), 100, 6 ); do_action( 'trp_call_gettext_filters' ); } } public function is_domain_loaded_in_locale( $domain, $locale ) { $localemo = $locale . '.mo'; $length = strlen( $localemo ); global $l10n; if ( isset( $l10n[ $domain ] ) && is_object( $l10n[ $domain ] ) && method_exists( $l10n[ $domain ], 'get_filename' ) ) { $mo_filename = $l10n[ $domain ]->get_filename(); if ( is_string($mo_filename) ) { // $mo_filename does not end with string $locale if ( substr( strtolower( $mo_filename ), -$length ) == strtolower( $localemo ) ) { return true; } else { return false; } } return true; } // if something is not as expected, return true so that we do not interfere return true; } public function verify_locale_of_loaded_textdomain() { global $l10n; if ( ! empty( $l10n ) && is_array( $l10n ) ) { $reload_domains = array(); $locale = get_locale(); foreach ( $l10n as $domain => $item ) { if ( ! $this->is_domain_loaded_in_locale( $domain, $locale ) ) { $reload_domains[] = $domain; } } foreach ( $reload_domains as $domain ) { if ( isset( $l10n[ $domain ] ) && is_object( $l10n[ $domain ] ) ) { $path = $l10n[ $domain ]->get_filename(); $new_path = preg_replace( '/' . $domain . '-(.*).mo$/i', $domain . '-' . $locale . '.mo', $path ); if ( $new_path !== $path ) { unset( $l10n[ $domain ] ); load_textdomain( $domain, $new_path ); } } } } // do this function only once per execution. The init hook can be called more than once remove_action( 'trp_call_gettext_filters', array( $this, 'verify_locale_of_loaded_textdomain' ) ); } /** * Function that determines if an ajax request came from the frontend * @return bool */ static function is_ajax_on_frontend() { /* for our own actions return false */ if ( isset( $_REQUEST['action'] ) && strpos( sanitize_text_field( $_REQUEST['action'] ), 'trp_' ) === 0 ) { return false; } $trp = TRP_Translate_Press::get_trp_instance(); $url_converter = $trp->get_component( "url_converter" ); //check here for wp ajax or woocommerce ajax if ( ( defined( 'DOING_AJAX' ) && DOING_AJAX ) || ( defined( 'WC_DOING_AJAX' ) && WC_DOING_AJAX ) ) { $referer = ''; if ( ! empty( $_REQUEST['_wp_http_referer'] ) ) { // this one is actually REQUEST_URI from the previous page. It's set by the wp_nonce_field() and wp_referer_field() // confusingly enough, wp_get_referer() basically returns $_SERVER['REQUEST_URL'] from the prev page (not a full URL) or // $_SERVER['HTTP_REFERER'] that's setup by the client/browser as a full URL (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer) $referer_uri = wp_unslash( esc_url_raw( $_REQUEST['_wp_http_referer'] ) ); $req_uri = $referer_uri; // req_uri is a relative path which might wrongfully contain the subdirectory (in case WordPress is installed in a subdirectory) // We remove that part from req_uri, in case it's found $parsed_home_path = parse_url( $url_converter->get_abs_home(), PHP_URL_PATH ); $home_path = trim( $parsed_home_path ?: '', '/' ); $home_path_regex = sprintf( '|^%s|i', preg_quote( $home_path, '|' ) ); // Trim path info from the end and the leading home path from the front. $req_uri = ltrim( $req_uri, '/' ); $req_uri = preg_replace( $home_path_regex, '', $req_uri ); $req_uri = trim( $url_converter->get_abs_home(), '/' ) . '/' . ltrim( $req_uri, '/' ); $referer = $req_uri; } elseif ( ! empty( $_SERVER['HTTP_REFERER'] ) ) { // this one is an actual URL that the browser sets. $referer = wp_unslash( esc_url_raw( $_SERVER['HTTP_REFERER'] ) ); } //if the request did not come from the admin set propper variables for the request (being processed in ajax they got lost) and return true if ( ( strpos( $referer, admin_url() ) === false ) ) { TRP_Gettext_Manager::set_vars_in_frontend_ajax_request( $referer ); return true; } } return false; } /** * Function that sets the needed vars in the ajax request. Beeing ajax the globals got reset and also the REQUEST globals * * @param $referer */ static function set_vars_in_frontend_ajax_request( $referer ) { /* for our own actions don't do nothing */ if ( isset( $_REQUEST['action'] ) && strpos( sanitize_text_field( $_REQUEST['action'] ), 'trp_' ) === 0 ) { return; } /* if the request came from preview mode make sure to keep it */ if ( strpos( $referer, 'trp-edit-translation=preview' ) !== false && ! isset( $_REQUEST['trp-edit-translation'] ) ) { $_REQUEST['trp-edit-translation'] = 'preview'; } if ( strpos( $referer, 'trp-edit-translation=preview' ) !== false && strpos( $referer, 'trp-view-as=' ) !== false && strpos( $referer, 'trp-view-as-nonce=' ) !== false ) { $parts = parse_url( $referer ); parse_str( $parts['query'], $query ); $_REQUEST['trp-view-as'] = $query['trp-view-as']; $_REQUEST['trp-view-as-nonce'] = $query['trp-view-as-nonce']; } global $TRP_LANGUAGE; $trp = TRP_Translate_Press::get_trp_instance(); $url_converter = $trp->get_component( 'url_converter' ); $TRP_LANGUAGE = $url_converter->get_lang_from_url_string( $referer ); if ( empty( $TRP_LANGUAGE ) ) { $settings_obj = new TRP_Settings(); $settings = $settings_obj->get_settings(); $TRP_LANGUAGE = $settings["default-language"]; } } /** * function that machine translates gettext strings */ public function machine_translate_gettext() { /* @todo set the original language to detect and also decide if we automatically translate for the default language */ global $TRP_LANGUAGE, $trp_gettext_strings_for_machine_translation; if ( ! empty( $trp_gettext_strings_for_machine_translation ) ) { if ( ! $this->machine_translator ) { $trp = TRP_Translate_Press::get_trp_instance(); $this->machine_translator = $trp->get_component( 'machine_translator' ); } // Gettext strings are considered by default to be in the English language $source_language = apply_filters( 'trp_gettext_source_language', 'en_US', $TRP_LANGUAGE, array(), $trp_gettext_strings_for_machine_translation ); // machine translate new strings if ( $this->machine_translator->is_available( array( $source_language, $TRP_LANGUAGE ) ) ) { /* Transform associative array into ordered numeric array. We need to keep keys numeric and ordered because $new_strings and $machine_strings depend on it. * Array was constructed as associative with db ids as keys to avoid duplication. */ $trp_gettext_strings_for_machine_translation = array_values( $trp_gettext_strings_for_machine_translation ); $new_strings = array(); foreach ( $trp_gettext_strings_for_machine_translation as $trp_gettext_string_for_machine_translation ) { $new_strings[] = ( $trp_gettext_string_for_machine_translation['original_plural'] && (int)$trp_gettext_string_for_machine_translation['plural_form'] > 0 ) ? $trp_gettext_string_for_machine_translation['original_plural'] : $trp_gettext_string_for_machine_translation['original']; } if ( apply_filters( 'trp_gettext_allow_machine_translation', true, $source_language, $TRP_LANGUAGE, $new_strings, $trp_gettext_strings_for_machine_translation ) ) { $machine_strings = $this->machine_translator->translate( $new_strings, $TRP_LANGUAGE, $source_language ); } else { $machine_strings = apply_filters( 'trp_gettext_machine_translate_strings', array(), $new_strings, $TRP_LANGUAGE, $trp_gettext_strings_for_machine_translation ); } if ( ! empty( $machine_strings ) ) { foreach ( $new_strings as $key => $new_string ) { if ( isset( $machine_strings[ $new_string ] ) ) { $trp_gettext_strings_for_machine_translation[ $key ]['translated'] = $machine_strings[ $new_string ]; } } if ( ! $this->trp_query ) { $trp = TRP_Translate_Press::get_trp_instance(); $this->trp_query = $trp->get_component( 'query' ); } $gettext_insert_update = $this->trp_query->get_query_component( 'gettext_insert_update' ); $gettext_insert_update->update_gettext_strings( $trp_gettext_strings_for_machine_translation, $TRP_LANGUAGE ); } } } } /** * make sure we remove the trp-gettext wrap from the format the date_i18n receives * ideally if in the gettext filter we would know 100% that a string is a valid date format then we would not wrap it but it seems that it is not easy to determine that ( explore further in the future $d = DateTime::createFromFormat('Y', date('y a') method); ) */ public function handle_date_i18n_function_for_gettext( $j, $dateformatstring, $unixtimestamp, $gmt ) { /* remove trp-gettext wrap */ $dateformatstring = preg_replace( '/#!trpst#trp-gettext (.*?)#!trpen#/i', '', $dateformatstring ); $dateformatstring = preg_replace( '/#!trpst#(.?)\/trp-gettext#!trpen#/i', '', $dateformatstring ); global $wp_locale; $i = $unixtimestamp; if ( false === $i ) { $i = current_time( 'timestamp', $gmt ); } if ( ( ! empty( $wp_locale->month ) ) && ( ! empty( $wp_locale->weekday ) ) ) { $datemonth = $wp_locale->get_month( date( 'm', $i ) ); $datemonth_abbrev = $wp_locale->get_month_abbrev( $datemonth ); $dateweekday = $wp_locale->get_weekday( date( 'w', $i ) ); $dateweekday_abbrev = $wp_locale->get_weekday_abbrev( $dateweekday ); $datemeridiem = $wp_locale->get_meridiem( date( 'a', $i ) ); $datemeridiem_capital = $wp_locale->get_meridiem( date( 'A', $i ) ); $dateformatstring = ' ' . $dateformatstring; $dateformatstring = preg_replace( "/([^\\\])D/", "\\1" . backslashit( $dateweekday_abbrev ), $dateformatstring ); $dateformatstring = preg_replace( "/([^\\\])F/", "\\1" . backslashit( $datemonth ), $dateformatstring ); $dateformatstring = preg_replace( "/([^\\\])l/", "\\1" . backslashit( $dateweekday ), $dateformatstring ); $dateformatstring = preg_replace( "/([^\\\])M/", "\\1" . backslashit( $datemonth_abbrev ), $dateformatstring ); $dateformatstring = preg_replace( "/([^\\\])a/", "\\1" . backslashit( $datemeridiem ), $dateformatstring ); $dateformatstring = preg_replace( "/([^\\\])A/", "\\1" . backslashit( $datemeridiem_capital ), $dateformatstring ); $dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) - 1 ); } $timezone_formats = array( 'P', 'I', 'O', 'T', 'Z', 'e' ); $timezone_formats_re = implode( '|', $timezone_formats ); if ( preg_match( "/$timezone_formats_re/", $dateformatstring ) ) { $timezone_string = get_option( 'timezone_string' ); if ( $timezone_string ) { $timezone_object = timezone_open( $timezone_string ); //date_create( null, $timezone_object ); //date_create() passing null to parameter #1 ($datetime) of type string is deprecated, from what I found online the null should be replaced with '' $date_object = date_create( '', $timezone_object ); foreach ( $timezone_formats as $timezone_format ) { if ( false !== strpos( $dateformatstring, $timezone_format ) ) { $formatted = date_format( $date_object, $timezone_format ); $dateformatstring = ' ' . $dateformatstring; $dateformatstring = preg_replace( "/([^\\\])$timezone_format/", "\\1" . backslashit( $formatted ), $dateformatstring ); $dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) - 1 ); } } } } $j = @date( $dateformatstring, $i ); return $j; } /** * Strip gettext tags from urls that were parsed by esc_url * * Esc_url() replaces spaces with %20. This is why it is not automatically stripped like the rest of the urls. * * @param $good_protocol_url * @param $original_url * @param $_context * * @return mixed * @since 1.3.8 * */ public function trp_strip_gettext_tags_from_esc_url( $good_protocol_url, $original_url, $_context ) { if ( strpos( $good_protocol_url, '%20data-trpgettextoriginal=' ) !== false ) { // first replace %20 with space so that gettext tags can be stripped. $good_protocol_url = str_replace( '%20data-trpgettextoriginal=', ' data-trpgettextoriginal=', $good_protocol_url ); $good_protocol_url = TRP_Gettext_Manager::strip_gettext_tags( $good_protocol_url ); } return $good_protocol_url; } /** * Filter sanitize_title() to use our own remove_accents() function so it's based on the default language, not current locale. * * Also removes trp gettext tags before running the filter because it strip # and ! and / making it impossible to strip the #trpst later * * @param string $title * @param string $raw_title * @param string $context * * @return string * @since 1.3.1 * */ public function trp_sanitize_title( $title, $raw_title, $context ) { // remove trp_tags before sanitization, because otherwise some characters (#,!,/, spaces ) are stripped later, and it becomes impossible to strip trp-gettext later $raw_title = TRP_Gettext_Manager::strip_gettext_tags( $raw_title ); if ( 'save' == $context ) { $title = trp_remove_accents( $raw_title ); } remove_filter( 'sanitize_title', array( $this, 'trp_sanitize_title' ), 1 ); $title = apply_filters( 'sanitize_title', $title, $raw_title, $context ); add_filter( 'sanitize_title', array( $this, 'trp_sanitize_title' ), 1, 3 ); return $title; } /** * function that strips the gettext tags from a string * * @param $string * * @return mixed */ static function strip_gettext_tags( $string ) { if ( is_string( $string ) && strpos( $string, 'data-trpgettextoriginal=' ) !== false ) { // final 'i' is for case insensitive. same for the 'i' in str_ireplace $string = preg_replace( '/ data-trpgettextoriginal=\d+#!trpen#/i', '', $string ); $string = preg_replace( '/data-trpgettextoriginal=\d+#!trpen#/i', '', $string );//sometimes it can be without space $string = str_ireplace( '#!trpst#trp-gettext', '', $string ); $string = str_ireplace( '#!trpst#/trp-gettext', '', $string ); $string = str_ireplace( '#!trpst#\/trp-gettext', '', $string ); $string = str_ireplace( '#!trpen#', '', $string ); } return $string; } /** * Function that inserts in db translation from language files for specified original string ids for a specific language * This requests changes locale from the very beginning so all the active plugins/theme load their textdomain translations * * Also creates plural entries for all plural forms so we have an id * * @param $dictionary * @param $language * * @return void */ public function add_missing_language_file_translations( $dictionary, $language ) { $trp_plural_forms = $this->get_gettext_component( 'plural_forms' ); if ( ! $this->trp_query ) { $trp = TRP_Translate_Press::get_trp_instance(); $this->trp_query = $trp->get_component( 'query' ); } $insert_gettext_strings = array(); $update_gettext_strings = array(); $number_of_plural_forms = $trp_plural_forms->get_number_of_plural_forms( $language ); if ( ! empty( $dictionary ) ) { foreach ( $dictionary as $current_key => $current_string ) { $translations = get_translations_for_domain( $current_string['domain'] ); $context = ( $current_string['context'] === 'trp_context' ) ? null : $current_string['context']; $translated = ''; if ( $current_string['original_plural'] ) { /* For some domains in some languages, $translations object is not of type Translations * (but of type WP_Translations) on WP version 6.5+. So it doesn't have this method. * Todo: find an alternative to access plural forms for these cases */ if ( !method_exists( $translations, 'translate_entry' ) ) { continue; } // Insert translation for all other plural forms than the current one for ( $plural_form_i = 0; $plural_form_i < $number_of_plural_forms; $plural_form_i ++ ) { if ( $plural_form_i == $current_string['plural_form'] ) { continue; } $translation_exists_for_plural_form = false; $plural_form_id_translation_table = null; foreach ( $dictionary as $secondary_key => $secondary_string ) { if ( $secondary_key == $current_key ) { continue; } if ( $current_string['ot_id'] === $secondary_string['ot_id'] && $secondary_string['plural_form'] == $plural_form_i ) { if ( $secondary_string['status'] == 0 ) { $plural_form_id_translation_table = $secondary_string['id']; } else { $translation_exists_for_plural_form = true; } break; } } if ( ! $translation_exists_for_plural_form ) { $translated = $trp_plural_forms->translate_plural( $current_string['original'], $current_string['original_plural'], $plural_form_i, $context, $translations ); if ( $translated && $translated != $current_string['original'] && $translated != $current_string['original_plural'] ) { $status = 2; }else { $translated = ''; $status = 0; } if ( $plural_form_id_translation_table ) { if ( $translated ) { $update_gettext_strings[] = array( 'id' => $plural_form_id_translation_table, 'translated' => $translated ); } } else { $insert_gettext_strings[] = array( 'original_id' => $current_string['ot_id'], 'original' => $current_string['original'], 'translated' => $translated, 'domain' => $current_string['domain'], 'plural_form' => $plural_form_i, 'status' => $status, 'context' => $current_string['context'], 'original_plural' => $current_string['original_plural'] ); } } } // Insert translation for this current string if ( $current_string['status'] == 0 ) { $translated = $trp_plural_forms->translate_plural( $current_string['original'], $current_string['original_plural'], (int) $current_string['plural_form'], $context, $translations ); } } else { if ( $current_string['status'] == 0 && empty( $current_string['translated'] ) ) { $translated = $translations->translate( $current_string['original'] ); } } if ( $current_string['status'] == 0 && empty( $current_string['translated'] ) ) { if ( $translated && $translated != $current_string['original'] && $translated != $current_string['original_plural'] ) { $status = 2; } else { $translated = ''; $status = 0; } if ( $current_string['id'] ) { if ( $translated ) { $update_gettext_strings[] = array( 'id' => $current_string['id'], 'translated' => $translated, 'status' => 2 ); } } else { $insert_gettext_strings[] = array( 'original_id' => $current_string['ot_id'], 'original' => $current_string['original'], 'translated' => $translated, 'domain' => $current_string['domain'], 'plural_form' => (int) $current_string['plural_form'], 'status' => $status, 'context' => $current_string['context'], 'original_plural' => $current_string['original_plural'] ); } } } $gettext_insert_update = $this->trp_query->get_query_component( 'gettext_insert_update' ); $gettext_insert_update->insert_gettext_strings($insert_gettext_strings, $language); $gettext_insert_update->update_gettext_strings($update_gettext_strings, $language, array('translated', 'id', 'status')); } } }
[+]
..
[-] class-process-gettext.php
[edit]
[-] class-plural-forms.php
[edit]
[-] class-gettext-manager.php
[edit]