Code development platform for open source projects from the European Union institutions :large_blue_circle: EU Login authentication by SMS has been phased out. To see alternatives please check here

Skip to content
Snippets Groups Projects
Commit d6154fa4 authored by Davis Ragels's avatar Davis Ragels
Browse files

EMW WordPress plugin Beta version

parent e5258970
Branches
Tags
No related merge requests found
Showing
with 759 additions and 248 deletions
......@@ -251,19 +251,16 @@ a.etm-recommended-learn-more{
width: 200px;
}
#tab_title__wrap {
#tab_title {
padding-left: 12px;
display: flex;
align-items: center;
}
#tab_title__wrap h1 {
padding-left: 12px;
}
#tab_title__logo {
width: 60px;
content:url('../images/icon_128.png');
margin-right: 12px;
}
@media only screen and (min-width: 1024px) {
......
......@@ -98,10 +98,13 @@ jQuery( function() {
function update_domains() {
if (domains) {
var languages = [];
var langcodes = [];
var selected_language = jQuery( '#etm-default-language').val();
var source = get_lang_from_code(selected_language);
jQuery('input.etm-translation-published').each(function() {
languages.push(get_lang_from_code(jQuery(this).val()));
var langcode = jQuery(this).val();
langcodes.push(langcode);
languages.push(get_lang_from_code(langcode));
});
var domainFields = jQuery('select.etm-translation-language-domain');
for (var i = 0; i < domainFields.length; i++) {
......@@ -110,9 +113,17 @@ jQuery( function() {
var previousDomain = jQuery(domainFields[i]).val();
jQuery(domainFields[i]).empty();
var domainKeys = Object.keys(supportedDomains);
domainKeys.forEach(key => {
jQuery(domainFields[i]).append('<option value="' + key + '">' + supportedDomains[key] + '</option>');
});
var selected_index = null;
for (var j = 0; j < domainKeys.length; j++) {
var key = domainKeys[j];
var langcode = langcodes[i];
jQuery(domainFields[i]).append(`<option value='${key}'>${supportedDomains[key]}</option>`);
if (selected_domains && selected_domains[langcode] && selected_domains[langcode] == key) {
selected_index = j;
}
}
domainFields[i].disabled = false;
var defaultDomain = 'GEN';
if (domainKeys.includes(previousDomain)) {
jQuery(domainFields[i]).val(previousDomain);
......@@ -120,6 +131,10 @@ jQuery( function() {
jQuery(domainFields[i]).val(defaultDomain);
} else if (domainKeys.length == 0) {
jQuery(domainFields[i]).append('<option value="-" selected>-</option>');
domainFields[i].disabled = true;
}
if (selected_index != null) {
domainFields[i].selectedIndex = selected_index;
}
}
}
......@@ -127,6 +142,17 @@ jQuery( function() {
function get_supported_domains(source, target, domains) {
var result = {}
if (Object.keys(domains).includes("languageDirections")) {
// generic mt domain data format
domains.languageDirections.forEach(direction => {
if (direction.srcLang == source && direction.trgLang == target) {
var key = direction.domain;
var name = `${direction.domain} (${direction.vendor})`;
result[key] = name;
}
});
} else {
// etranslation domain data format
var searchValue = source + "-" + target;
Object.keys(domains).forEach(key => {
langPairs = domains[key].languagePairs.map(p => p.substring(0, 5).toLowerCase());
......@@ -134,6 +160,7 @@ jQuery( function() {
result[key] = domains[key].name;
}
});
}
return result;
}
......@@ -157,6 +184,11 @@ jQuery( function() {
return url_slugs;
};
this.onsubmit = function (event){
_this.check_unique_url_slugs(event);
jQuery('select.etm-translation-language-domain').removeAttr('disabled');
};
this.check_unique_url_slugs = function (event){
var url_slugs = _this.get_existing_url_slugs();
if ( has_duplicates(url_slugs)){
......@@ -184,13 +216,14 @@ jQuery( function() {
duplicate_url_error_message = etm_url_slugs_info['error_message_duplicate_slugs'];
iso_codes = etm_url_slugs_info['iso_codes'];
domains = etm_url_slugs_info['domains'];
selected_domains = etm_url_slugs_info['selected_domains'];
update_domains();
jQuery( '#etm-sortable-languages' ).sortable({ handle: '.etm-sortable-handle' });
jQuery( '#etm-add-language' ).click( _this.add_language );
jQuery( '.etm-remove-language' ).click( _this.remove_language );
jQuery( '#etm-default-language' ).on( 'change', _this.update_default_language );
jQuery( "form[action='options.php']").on ( 'submit', _this.check_unique_url_slugs );
jQuery( "form[action='options.php']").on ( 'submit', _this.onsubmit );
jQuery( '#etm-languages-table' ).on( 'change', '.etm-translation-language', _this.update_url_slug_and_status );
};
......
......@@ -108,6 +108,8 @@ class ETM_Machine_Translation_Tab {
include_once ETM_PLUGIN_DIR . 'includes/etranslation/class-etranslation-query.php';
include_once ETM_PLUGIN_DIR . 'includes/etranslation/class-etranslation-machine-translator.php';
include_once ETM_PLUGIN_DIR . 'includes/etranslation/functions.php';
include_once ETM_PLUGIN_DIR . 'includes/other-mt-provider/class-other-machine-translator.php';
include_once ETM_PLUGIN_DIR . 'includes/other-mt-provider/functions.php';
}
......@@ -119,7 +121,8 @@ class ETM_Machine_Translation_Tab {
$value = $default;
else {
$existing_engines = apply_filters('etm_automatic_translation_engines_classes', array(
'etranslation' => 'ETM_eTranslation_Machine_Translator'
'etranslation' => 'ETM_eTranslation_Machine_Translator',
'othermt' => 'ETM_Other_Machine_Translator',
));
$value = $existing_engines[$this->settings['etm_machine_translation_settings']['translation-engine']];
......
......@@ -13,6 +13,12 @@ class ETM_Machine_Translator {
protected $machine_translation_codes;
protected $etm_languages;
protected $correct_api_key = null;
private $html_wrapper_prefix = '<div>';
private $html_wrapper_suffix = '</div>';
private $punt_preceding_space = array( ', ', '. ', '; ', ') ', ': ', '? ', '! ' );
public $translation_delimiter = '__EMW__';
/**
* ETM_Machine_Translator constructor.
*
......@@ -263,7 +269,7 @@ class ETM_Machine_Translator {
private function get_placeholders( $count ) {
$placeholders = array();
for ( $i = 1; $i <= $count; $i++ ) {
$placeholders[] = '1TP' . $i . 'T';
$placeholders[] = "<x id=\"@$i\"/>";
}
return $placeholders;
}
......@@ -278,45 +284,274 @@ class ETM_Machine_Translator {
*/
public function translate( $strings, $target_language_code, $source_language_code = null, $is_gettext = false ) {
if ( ! empty( $strings ) && is_array( $strings ) && method_exists( $this, 'translate_array' ) && apply_filters( 'etm_disable_automatic_translations_due_to_error', false ) === false ) {
$prepare_response = $this->prepare_strings_for_translation( $strings );
if ( $this->settings['etm_machine_translation_settings']['translation-engine'] === 'etranslation' ) {
$xml_machine_strings = $this->translate_array( $prepare_response->xml_strings, $prepare_response->original_strings, $target_language_code, $source_language_code, $is_gettext );
} else {
$xml_machine_strings = $this->translate_array( $prepare_response->xml_strings, $target_language_code, $source_language_code );
}
$machine_strings_return_array = array();
if ( ! empty( $xml_machine_strings ) ) {
$decoded_translations = $this->process_xml_translations( $prepare_response, $xml_machine_strings );
foreach ( $decoded_translations as $key => $machine_string ) {
$machine_strings_return_array[ $prepare_response->original_strings[ $key ] ] = $machine_string;
}
}
return $machine_strings_return_array;
} else {
return array();
}
}
public function prepare_strings_for_translation( $source_strings ) {
/*
google (and eTranslation) has a problem translating this characters ( '%', '$', '#' )...for some reasons it puts spaces after them so we need to 'encode' them and decode them back. hopefully it won't break anything important */
/* we put '%s' before '%' because google seems to transform %s into % in strings for some languages which causes a 500 Fatal Error in PHP 8*/
$imploded_strings = implode( ' ', $strings );
$etm_exclude_words_from_automatic_translation = apply_filters( 'etm_exclude_words_from_automatic_translation', array( '%s', '%d', '%', '$', '#', "\n" ), $imploded_strings );
MT providers have a problem translating these characters ( '%', '$', '#' )...for some reasons it puts spaces after them so we need to 'encode' them and decode them back. Otherwise it break the page
*/
$imploded_strings = implode( ' ', $source_strings );
$etm_exclude_words_from_automatic_translation = apply_filters( 'etm_exclude_words_from_automatic_translation', $this->get_strings_to_encode_before_translation(), $imploded_strings );
$placeholders = $this->get_placeholders( count( $etm_exclude_words_from_automatic_translation ) );
$shortcode_tags_to_execute = apply_filters( 'etm_do_these_shortcodes_before_automatic_translation', array( 'etm_language' ) );
$strings = array_unique( $strings );
$original_strings = $strings;
$strings = array_unique( $source_strings );
$original_strings = array_values( $strings );
$xml_strings = $this->translatable_values_to_xml( $strings );
foreach ( $strings as $key => $string ) {
foreach ( $xml_strings as $key => $string ) {
/*
html_entity_decode is needed before replacing the character "#" from the list because characters like &#8220; (8220 utf8)
* will get an extra space after '&' which will break the character, rendering it like this: & #8220;
*/
$strings[ $key ] = str_replace( $etm_exclude_words_from_automatic_translation, $placeholders, html_entity_decode( $string ) );
$strings[ $key ] = etm_do_these_shortcodes( $strings[ $key ], $shortcode_tags_to_execute );
$xml_strings[ $key ] = str_replace( $etm_exclude_words_from_automatic_translation, $placeholders, $string );
$xml_strings[ $key ] = etm_do_these_shortcodes( $xml_strings[ $key ], $shortcode_tags_to_execute );
}
$response = new stdClass();
$response->xml_strings = $xml_strings;
$response->original_strings = $original_strings;
$response->placeholders = $placeholders;
$response->encoded_words = $etm_exclude_words_from_automatic_translation;
return $response;
}
if ( $this->settings['etm_machine_translation_settings']['translation-engine'] === 'etranslation' ) {
$machine_strings = $this->translate_array( $strings, $original_strings, $target_language_code, $source_language_code, $is_gettext );
public function process_xml_translations( $prepare_response, $xml_translations ) {
// workaround for space inserted inside placeholder tags.
$normalized_xmls = str_replace( ' />', '/>', $xml_translations );
// restore spaces around placeholders removed by MT.
$normalized_xmls = $this->restore_spaces_around_placeholders( $prepare_response->xml_strings, $normalized_xmls, $prepare_response->placeholders );
// replace placeholders with original values.
$decoded_xmls = str_replace( $prepare_response->placeholders, $prepare_response->encoded_words, $normalized_xmls );
// convert XML translations back to string array.
$string_translations = $this->decode_xml_translations( $prepare_response->original_strings, $decoded_xmls );
// restore any removed spaces around words.
$result = $this->arr_restore_spaces_after_translation( $prepare_response->original_strings, $string_translations );
return $result;
}
private function translatable_values_to_xml( $values ) {
$xmls = array();
$count = 1;
foreach ( $values as $v ) {
$html_string = $this->wrap_as_html( $v );
$dom = $this->loadHtml( $html_string );
$body = $dom->getElementsByTagName( 'body' )[0];
$nodes = array( $body->firstChild );
while ( $node = array_shift( $nodes ) ) {
if ( $node instanceof \DOMElement ) {
// replace each non-text node with <g> node (or x tag if self-closing), also removing all attributes.
$newTag = $dom->createElement( $node->hasChildNodes() ? 'g' : 'x' );
// set id for each <g> or <x> node.
$newTag->setAttribute( 'id', $count++ );
// replace node.
$node->parentNode->replaceChild( $newTag, $node );
// move all children nodes to new node.
while ( $node->hasChildNodes() ) {
$newTag->appendChild( $node->firstChild );
}
// process children nodes next.
$nodes = array_merge( iterator_to_array( $newTag->childNodes ), $nodes );
}
}
$xmls[] = $dom->saveXML( $body->firstChild );
}
return $xmls;
}
private function decode_xml_translations( $source_values, $translated_values ) {
$translation_count = count( $translated_values );
$decoded_translations = array();
for ( $i = 0; $i < $translation_count; $i++ ) {
// retrieve source and translated values.
$source = $source_values[ $i ];
$translation = $translated_values[ $i ];
// load source as html document.
$html_source = $this->wrap_as_html( $source );
$html_dom = $this->loadHtml( $html_source );
$html_wrapper = $html_dom->getElementsByTagName( 'body' )[0]->firstChild;
// load translation as xml document.
$xml = simplexml_load_string( $translation );
$xml_dom = dom_import_simplexml( $xml )->ownerDocument;
$xml_wrapper = $xml_dom->firstChild;
// replace text nodes in source html with matching text nodes from translation xml.
$new_node = $this->replace_text_nodes_bottom_up( $html_wrapper, $xml_wrapper );
// save as XML instead of HTML to avoid url encoding.
$text_xml = $html_dom->saveXML( $new_node );
// remove XML tag.
$text_value = preg_replace( '/\<\?xml(.*?)\?\>/', '', $text_xml );
// remove wrapper.
$html_prefix_len = strlen( $this->html_wrapper_prefix );
$decoded_translation = substr( $text_value, $html_prefix_len, strlen( $text_value ) - $html_prefix_len - strlen( $this->html_wrapper_suffix ) );
$decoded_translations[] = $decoded_translation;
}
return $decoded_translations;
}
private function replace_text_nodes_bottom_up( $original_node, $encoded_node ) {
// Recursively call this function on each child node.
$original_child_node = $original_node->lastChild;
$encoded_child_node = $encoded_node->lastChild;
while ( $original_child_node && $encoded_child_node ) {
$this->replace_text_nodes_bottom_up( $original_child_node, $encoded_child_node );
$original_child_node = $original_child_node->previousSibling;
$encoded_child_node = $encoded_child_node->previousSibling;
// workaround for extra spaces inserted by MT between <g> tags like: '</g> <g>'.
while ( $original_child_node && $encoded_child_node && XML_TEXT_NODE === $encoded_child_node->nodeType && empty( trim( $encoded_child_node->nodeValue ) ) && XML_TEXT_NODE !== $original_child_node->nodeType ) {
$textNode = $original_node->ownerDocument->createTextNode( $encoded_child_node->nodeValue );
$original_node->insertBefore( $textNode, $original_child_node->nextSibling );
$encoded_child_node = $encoded_child_node->previousSibling;
}
}
// Process the current node.
if ( XML_TEXT_NODE === $original_node->nodeType ) {
$original_node->nodeValue = $encoded_node->nodeValue;
}
return $original_node;
}
private function restore_spaces_around_placeholders( $original_xml_values, $translated_xml_values, $placeholders ) {
$original_xml = implode( $this->translation_delimiter, $original_xml_values );
$translated_xml = implode( $this->translation_delimiter, $translated_xml_values );
foreach ( $placeholders as $key ) {
$original_pos = strpos( $original_xml, $key );
$translation_pos = strpos( $translated_xml, $key );
if ( $original_pos > -1 && $translation_pos > -1 ) {
$original_char_before = substr( $original_xml, $original_pos - 1, 1 );
$translation_char_before = substr( $translated_xml, $translation_pos - 1, 1 );
if ( ctype_space( $original_char_before ) && ! ctype_space( $translation_char_before ) ) {
$translated_xml = str_replace( $key, $original_char_before . $key, $translated_xml );
$translation_pos++;
}
$original_char_after = substr( $original_xml, $original_pos + strlen( $key ), 1 );
$translation_char_after = substr( $translated_xml, $translation_pos + strlen( $key ), 1 );
if ( ctype_space( $original_char_after ) && ! ctype_space( $translation_char_after ) ) {
$translated_xml = str_replace( $key, $key . $original_char_after, $translated_xml );
}
$translation_char_after = substr( $translated_xml, $translation_pos + strlen( $key ), 1 );
$original_two_chars_after = substr( $original_xml, $original_pos + strlen( $key ), 2 );
$translation_two_chars_after = substr( $translated_xml, $translation_pos + strlen( $key ), 2 );
if ( in_array( $original_two_chars_after, $this->punt_preceding_space, true ) && ! in_array( $translation_two_chars_after, $this->punt_preceding_space, true ) && ! ctype_space( $translation_char_after ) ) {
if ( trim( $original_two_chars_after ) === $translation_char_after ) {
$translated_xml = str_replace( $key . $translation_char_after, $key . $original_two_chars_after, $translated_xml );
} else {
$machine_strings = $this->translate_array( $strings, $target_language_code, $source_language_code, $is_gettext );
$translated_xml = str_replace( $key, $key . $original_two_chars_after, $translated_xml );
}
}
}
}
return explode( $this->translation_delimiter, $translated_xml );
}
$machine_strings_return_array = array();
if ( ! empty( $machine_strings ) ) {
foreach ( $machine_strings as $key => $machine_string ) {
$machine_strings_return_array[ $original_strings[ $key ] ] = str_ireplace( $placeholders, $etm_exclude_words_from_automatic_translation, $machine_string );
private function wrap_as_html( $string ) {
return $this->html_wrapper_prefix . $string . $this->html_wrapper_suffix;
}
private function str_restore_spaces_after_translation( $original, $translation ) {
$space = ' ';
$result = $translation;
if ( strlen( $original ) > 0 && strlen( $translation ) > 0 ) {
if ( $original[0] == $space && $translation[0] != $space ) {
$result = $space . $translation;
}
return $machine_strings_return_array;
} else {
return array();
if ( str_ends_with( $original, $space ) && ! str_ends_with( $translation, $space ) ) {
$result = $result . $space;
}
if ( in_array( substr( $original, 0, 2 ), $this->punt_preceding_space ) && ! in_array( substr( $translation, 0, 2 ), $this->punt_preceding_space ) ) {
$result = substr( $original, 0, 2 ) . ltrim( $translation );
}
}
return $result;
}
private function arr_restore_spaces_after_translation( $originals, $translations ): array {
$results = array();
for ( $i = 0; $i < count( $originals ); $i++ ) {
$res = $this->str_restore_spaces_after_translation( $originals[ $i ], $translations[ $i ] );
$results[] = $res;
}
return $results;
}
private function loadHtml( $html ) {
$document = <<<EOD
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
<body>!html</body>
</html>
EOD;
// PHP's \DOMDocument::saveXML() encodes carriage returns as &#13; so
// normalize all newlines to line feeds.
$html = str_replace(
array(
"\r\n",
"\r",
),
"\n",
$html
);
// PHP's \DOMDocument serialization adds extra whitespace when the markup
// of the wrapping document contains newlines, so ensure we remove all
// newlines before injecting the actual HTML body to be processed.
$document = strtr(
$document,
array(
"\n" => '',
'!html' => $html,
)
);
$dom = new \DOMDocument();
// Ignore warnings during HTML soup loading.
@$dom->loadHTML( $document, LIBXML_NOBLANKS );
return $dom;
}
public static function get_strings_to_encode_before_translation(): array {
$result = array();
$letters = array( 's', 'd', 'f', 'u' );
foreach ( $letters as $l ) {
$result[] = "%$l";
for ( $i = 1; $i < 10; $i++ ) {
$result[] = "%$i\$$l";
}
}
return array_merge( $result, array( '%', '$', '#' ) );
}
/**
* @param $etm_exclude_words_from_automatic_translation
......@@ -360,4 +595,57 @@ class ETM_Machine_Translator {
return $array;
}
public function get_all_domains() {
$engine_name = $this->settings['etm_machine_translation_settings']['translation-engine'];
$option_name = "etm_mt_domains_$engine_name";
$stored_domains = get_option( $option_name );
if ( $stored_domains && ! empty( $stored_domains ) ) {
return $stored_domains;
} else {
$response = $this->get_domain_list();
if ( $response['response'] == 200 ) {
$domains = $response['body'];
update_option( $option_name, $domains );
return $domains;
}
}
return array();
}
}
add_filter( 'http_request_timeout', 'wp9838c_timeout_extend' );
function wp9838c_timeout_extend( $time ) {
if ( is_engine_etranslation() ) {
return ETM_HTTP_REQUEST_TIMEOUT;
} else {
return ETM_HTTP_TRANSLATION_TIMEOUT;
}
}
// Setting custom option values for cURL. Using a high value for priority to ensure the function runs after any other added to the same action hook.
add_action( 'http_api_curl', 'etm_custom_curl_opts', 9999, 1 );
function etm_custom_curl_opts( $handle ) {
if ( is_engine_etranslation() ) {
curl_setopt( $handle, CURLOPT_CONNECTTIMEOUT, ETM_HTTP_REQUEST_TIMEOUT );
curl_setopt( $handle, CURLOPT_TIMEOUT, ETM_HTTP_REQUEST_TIMEOUT );
curl_setopt( $handle, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $handle, CURLOPT_FOLLOWLOCATION, true );
}
}
// Setting custom timeout in HTTP request args
add_filter( 'http_request_args', 'etm_custom_http_request_args', 9999, 1 );
function etm_custom_http_request_args( $r ) {
if ( is_engine_etranslation() ) {
$r['timeout'] = ETM_HTTP_REQUEST_TIMEOUT;
}
return $r;
}
function is_engine_etranslation() {
$etm = ETM_eTranslation_Multilingual::get_etm_instance();
$settings = $etm->get_component( 'settings' )->get_settings();
return 'etranslation' === $settings['etm_machine_translation_settings']['translation-engine'];
}
......@@ -17,7 +17,7 @@ class ETM_MT_Notice {
public function enqueue_mt_notice_scripts() {
$show = $this->settings['etm_machine_translation_settings']['show-mt-notice'];
$mt_enabled = $this->settings['etm_machine_translation_settings']['machine-translation'];
$mt_enabled = $this->settings['etm_machine_translation_settings']['machine-translation'] ?? false;
if ($show == 'yes' && $mt_enabled == 'yes') {
global $ETM_LANGUAGE;
$default = $this->settings['default-language'];
......
......@@ -77,7 +77,7 @@ Class ETM_Plugin_Notifications {
private static $_instance = null;
private $prefix = 'etm';
private $menu_slug = 'options-general.php';
public $pluginPages = array( 'etranslation-multilingual', 'etm_addons_page', 'etm_advanced_page', 'etm_machine_translation', 'etm_test_machine_api' );
public $pluginPages = array( 'etranslation-multilingual', 'etm_addons_page', 'etm_advanced_page', 'etm_machine_translation', 'etm_test_machine_api', 'etm_about' );
protected function __construct() {
add_action( 'admin_init', array( $this, 'dismiss_admin_notifications' ), 200 );
......
......@@ -484,8 +484,10 @@ class ETM_Settings {
$all_language_codes = $this->etm_languages->get_all_language_codes();
$iso_codes = $this->etm_languages->get_iso_codes( $all_language_codes, false );
$domains = array();
$selected_domains = $this->settings['translation-languages-domain-parameter'] ?? null;
$machine_translator = $etm->get_component( 'machine_translator' );
if ( $machine_translator->is_available() && $machine_translator instanceof ETM_eTranslation_Machine_Translator && $machine_translator->credentials_set() ) {
if ( $machine_translator->is_available() && $machine_translator->credentials_set() ) {
$domains = $machine_translator->get_all_domains();
}
......@@ -497,6 +499,7 @@ class ETM_Settings {
'error_message_duplicate_slugs' => __( 'Error! Duplicate URL slug values.', 'etranslation-multilingual' ),
'message_please_login_first' => __( 'Please enable automatic translation and enter valid eTranslation credentials first!', 'etranslation-multilingual' ),
'domains' => $domains,
'selected_domains' => $selected_domains,
)
);
......@@ -642,8 +645,7 @@ class ETM_Settings {
$machine_translator = $etm->get_component( 'machine_translator' );
return count( $this->settings['translation-languages'] ) > 1 ||
( $machine_translator->is_available() && $machine_translator instanceof ETM_eTranslation_Machine_Translator
&& $machine_translator->credentials_set() && ! $machine_translator->check_api_key_validity()['error'] );
( $machine_translator->is_available() && $machine_translator->credentials_set() && ! $machine_translator->check_api_key_validity()['error'] );
}
public function login_redirect() {
......
......@@ -170,7 +170,7 @@ class ETM_Ajax {
}
$dictionary_by_original = etm_sort_dictionary_by_original( $dictionaries, 'regular', 'dynamicstrings', null, null );
emt_safe_json_send( $dictionary_by_original );
echo json_encode( $dictionary_by_original );
}
}
......
......@@ -7,15 +7,21 @@ if ( ! defined( 'ABSPATH' ) ) {
class ETM_eTranslation_Machine_Translator extends ETM_Machine_Translator {
private $db_query_interval = 0.1; // 100ms
private $db_query_interval = 100 * 1000; // 100ms
private $etranslation_service;
public $etranslation_query;
// XML variables.
private $segment_opening = '<segment>';
private $segment_closing = '</segment>';
private $delimiter;
public function __construct( $settings ) {
parent::__construct( $settings );
$this->etranslation_service = new eTranslation_Service( $this->get_app_name(), $this->get_password() );
$this->etranslation_query = new eTranslation_Query();
$this->delimiter = $this->segment_closing . $this->segment_opening;
}
private function check_document( $id, $start_timestamp ): string {
......@@ -27,7 +33,7 @@ class ETM_eTranslation_Machine_Translator extends ETM_Machine_Translator {
if ( $translation != null ) {
return $translation;
}
sleep( $this->db_query_interval );
usleep( $this->db_query_interval );
$last_checked = microtime( true );
}
......@@ -41,7 +47,6 @@ class ETM_eTranslation_Machine_Translator extends ETM_Machine_Translator {
}
public function translate_document( $source_language_code, $target_language_code, $strings_array, $original_strings, $start_timestamp, $is_gettext ): array {
$delimiter = "\n";
$id_prefix = $is_gettext ? 'g-' : 'r-';
$id = $id_prefix . uniqid();
......@@ -49,40 +54,45 @@ class ETM_eTranslation_Machine_Translator extends ETM_Machine_Translator {
$target_language = $this->machine_translation_codes[ $target_language_code ];
$domain = $this->settings['translation-languages-domain-parameter'][ $target_language_code ] ?? 'GEN';
$content = implode( $delimiter, $strings_array );
$document = $this->string_to_base64_data( $content );
$xml_prefix = '<?xml version="1.0" encoding="utf-8" standalone="yes" ?><root>' . $this->segment_opening;
$xml_suffix = $this->segment_closing . '</root>';
$content = $xml_prefix . implode( $this->delimiter, $strings_array ) . $xml_suffix;
$original_string_content = implode( $this->translation_delimiter, $original_strings );
$temp_entry = $this->etranslation_query->insert_translation_entry( $id, strtolower( $source_language_code ), strtolower( $target_language_code ), implode( $delimiter, $original_strings ) );
$temp_entry = $this->etranslation_query->insert_translation_entry( $id, strtolower( $source_language_code ), strtolower( $target_language_code ), $original_string_content );
if ( $temp_entry ) {
$response = $this->etranslation_service->send_translate_document_request( $source_language, $target_language, $document, $domain, $id );
$response = $this->etranslation_service->send_translate_document_request( $source_language, $target_language, $content, $domain, $id );
$request_id = isset( $response['body'] ) && is_numeric( $response['body'] ) ? (int) $response['body'] : null;
if ( $response['response'] != 200 || $request_id < 0 ) {
return array();
}
$translation = $this->check_document( $id, $start_timestamp );
if ( empty( $translation ) ) {
$response = $this->check_document( $id, $start_timestamp );
if ( empty( $response ) ) {
return array();
}
$result = explode( $delimiter, $translation );
$result = $this->xml_document_to_string_array( $response );
$original_count = count( $strings_array );
$translation_count = count( $result );
if ( $translation_count != $original_count && ! ( $translation_count == $original_count + 1 && end( $result ) == '' ) ) {
error_log( 'Original string list size differs from translation list size (' . count( $strings_array ) . ' != ' . count( $result ) . ") [ID=$id]" );
}
return ETM_eTranslation_Utils::arr_restore_spaces_after_translation( array_values( $strings_array ), $result );
return $result;
} else {
return array();
}
}
private function string_to_base64_data( $string ) {
$base64_string = base64_encode( $string );
return array(
'content' => $base64_string,
'format' => 'txt',
'filename' => 'translateMe',
);
public function xml_document_to_string_array( $response ) {
// extract strings.
$segment_tag_length = strlen( $this->segment_opening );
$first_segment_pos = strpos( $response, $this->segment_opening );
$data_start_pos = $first_segment_pos + $segment_tag_length;
$data_end_pos = strrpos( $response, $this->segment_closing );
$segment_string = substr( $response, $data_start_pos, $data_end_pos - $data_start_pos );
$translations = explode( $this->delimiter, $segment_string );
return $translations;
}
/**
......@@ -157,7 +167,7 @@ class ETM_eTranslation_Machine_Translator extends ETM_Machine_Translator {
* Send a test request to verify if the functionality is working
*/
public function test_request() {
return $this->etranslation_service->send_translate_document_request( 'en', 'lv', $this->string_to_base64_data( 'about' ) );
return $this->etranslation_service->send_domain_request();
}
public function get_app_name() {
......@@ -187,20 +197,8 @@ class ETM_eTranslation_Machine_Translator extends ETM_Machine_Translator {
return strtolower( explode( '-', $lang_pair_str )[0] );
}
public function get_all_domains() {
$option_name = 'etm_etranslation_domains';
$stored_domains = get_option( $option_name );
if ( $stored_domains && ! empty( $stored_domains ) ) {
return $stored_domains;
} else {
$response = $this->etranslation_service->get_available_domain_language_pairs();
if ( $response['response'] == 200 ) {
$domains = $response['body'];
update_option( $option_name, $domains );
return $domains;
}
}
return array();
public function get_domain_list() {
return $this->etranslation_service->get_available_domain_language_pairs();
}
public function get_engine_specific_language_codes( $languages ) {
......@@ -234,7 +232,7 @@ class ETM_eTranslation_Machine_Translator extends ETM_Machine_Translator {
$return_message = __( 'Please enter your eTranslation credentials.', 'etranslation-multilingual' );
} else {
$response = $machine_translator->test_request();
$code = $response['response'];
$code = wp_remote_retrieve_response_code( $response );
if ( 200 !== $code ) {
$is_error = true;
$translate_response = etm_etranslation_response_codes( $code );
......
......@@ -168,16 +168,18 @@ class eTranslation_Query {
}
}
private function update_translation_manually( $details_row, $translations ) {
private function update_translation_manually( $details_row, $response_body ) {
$etm = ETM_eTranslation_Multilingual::get_etm_instance();
$etm_query = $etm->get_component( 'query' );
$machine_translator = $etm->get_component( 'machine_translator' );
if ( $details_row->from && $details_row->to && $details_row->from != $details_row->to ) {
$is_gettext = str_starts_with( $details_row->id, 'g-' );
$delimiter = "\n";
$original_strings = explode( $delimiter, $details_row->original );
$decoded_translations = self::decode_untranslated_symbols( explode( $delimiter, $translations ), $original_strings );
$translation_strings = ETM_eTranslation_Utils::arr_restore_spaces_after_translation( $original_strings, $decoded_translations );
$original_strings = explode( $machine_translator->translation_delimiter, $details_row->original );
$translation_prepare_response = $machine_translator->prepare_strings_for_translation( $original_strings );
$xml_translations = $machine_translator->xml_document_to_string_array( $response_body );
$translation_strings = $machine_translator->process_xml_translations( $translation_prepare_response, $xml_translations );
if ( $is_gettext ) {
$dict_table = $etm_query->get_gettext_table_name( $details_row->to );
......@@ -242,40 +244,6 @@ class eTranslation_Query {
}
}
private function decode_untranslated_symbols( $translations, $originals ) {
$excluded_words_from_automatic_translation = apply_filters( 'etm_exclude_words_from_automatic_translation', ETM_eTranslation_Utils::get_strings_to_encode_before_translation(), implode( ' ', $originals ) );
for ( $i = 0; $i < count( $translations ); $i++ ) {
$translation = $translations[ $i ];
// check if decoding needed
if ( str_contains( $translation, '1TP' ) ) {
$original = $originals[ $i ];
$replacements = array();
foreach ( $excluded_words_from_automatic_translation as $s ) {
$replacements += self::strpos_all( $original, $s );
}
ksort( $replacements );
$translations[ $i ] = preg_replace_callback(
'/1TP[0-9]+T/',
function( $matches ) use ( &$replacements ) {
return array_shift( $replacements );
},
$translations[ $i ]
);
}
}
return $translations;
}
private static function strpos_all( $haystack, $needle ) {
$offset = 0;
$allpos = array();
while ( ( $pos = strpos( $haystack, $needle, $offset ) ) !== false ) {
$offset = $pos + 1;
$allpos[ $pos ] = $needle;
}
return $allpos;
}
private function get_incomplete_db_entry( $id ) {
return $this->db->get_row( "SELECT * FROM $this->jobs_table WHERE id = '$id' AND status IN ('TRANSLATING', 'TIMEOUT')" );
}
......
......@@ -74,9 +74,9 @@ class eTranslation_Service {
$this->password = $password;
}
public function send_translate_document_request( $sourceLanguage, $targetLanguage, $document, $domain = 'GEN', $id = '' ) {
public function send_translate_document_request( $sourceLanguage, $targetLanguage, $content, $domain = 'GEN', $id = '' ) {
$translationRequest = array(
'documentToTranslateBase64' => $document,
'documentToTranslateBase64' => $this->string_to_base64_data( $content ),
'sourceLanguage' => strtoupper( $sourceLanguage ),
'targetLanguages' => array(
strtoupper( $targetLanguage ),
......@@ -120,8 +120,12 @@ class eTranslation_Service {
);
}
public function send_domain_request() {
return $this->send_etranslation_request( self::$api_url . 'get-domains', 'GET' );
}
public function get_available_domain_language_pairs() {
$response = $this->send_etranslation_request( self::$api_url . 'get-domains', 'GET' );
$response = $this->send_domain_request();
$http_status = wp_remote_retrieve_response_code( $response );
$body = wp_remote_retrieve_body( $response );
......@@ -135,6 +139,15 @@ class eTranslation_Service {
);
}
private function string_to_base64_data( $string ) {
$base64_string = base64_encode( $string );
return array(
'content' => $base64_string,
'format' => 'xml',
'filename' => 'translateMe',
);
}
private function send_etranslation_request( $url, $method, $body = null, $headers = array() ) {
$auth_value = $this->get_digest_auth_header_value( $url, $method );
if ( $auth_value ) {
......
......@@ -2,38 +2,11 @@
class ETM_eTranslation_Utils {
public static $punt_preceding_space = [", ", ". ", "; ", ") ", ": ", "? ", "! "];
private function __construct() {}
public static function str_restore_spaces_after_translation($original, $translation) {
$space = " ";
$result = $translation;
if (strlen($original) > 0 && strlen($translation) > 0) {
if ($original[0] == $space && $translation[0] != $space) {
$result = $space . $translation;
}
if (str_ends_with($original, $space) && !str_ends_with($translation, $space)) {
$result = $result . $space;
}
if (in_array(substr($original, 0, 2), self::$punt_preceding_space) && !in_array(substr($translation, 0, 2), self::$punt_preceding_space)) {
$result = substr($original, 0, 2) . ltrim($translation);
}
}
return $result;
}
public static function arr_restore_spaces_after_translation($originals, $translations): array {
$results = [];
for ($i = 0; $i < count($originals); $i++) {
$res = self::str_restore_spaces_after_translation($originals[$i], $translations[$i]);
$results[] = $res;
}
return $results;
}
public static function encrypt_password( $plaintext ) {
$parsedUrl = parse_url( get_site_url() );
$method = "AES-256-CBC";
$method = 'AES-256-CBC';
$key = hash( 'sha256', $parsedUrl['host'], true );
$iv = openssl_random_pseudo_bytes( 16 );
......@@ -45,27 +18,17 @@ class ETM_eTranslation_Utils {
public static function decrypt_password( $base64cipher ) {
$parsedUrl = parse_url( get_site_url() );
$method = "AES-256-CBC";
$method = 'AES-256-CBC';
$ivHashCiphertext = base64_decode( $base64cipher );
$iv = substr( $ivHashCiphertext, 0, 16 );
$hash = substr( $ivHashCiphertext, 16, 32 );
$ciphertext = substr( $ivHashCiphertext, 48 );
$key = hash( 'sha256', $parsedUrl['host'], true );
if (!hash_equals(hash_hmac('sha256', $ciphertext . $iv, $key, true), $hash)) return null;
return openssl_decrypt($ciphertext, $method, $key, OPENSSL_RAW_DATA, $iv);
if ( ! hash_equals( hash_hmac( 'sha256', $ciphertext . $iv, $key, true ), $hash ) ) {
return null;
}
public static function get_strings_to_encode_before_translation(): array {
$result = array();
$letters = array("s", "d", "f", "u");
foreach ($letters as $l) {
$result[] = "%$l";
for ($i = 1; $i < 10; $i++) {
$result[] = "%$i\$$l";
}
}
return array_merge($result, array('%', '$', '#', "\r\n", "\n"));
return openssl_decrypt( $ciphertext, $method, $key, OPENSSL_RAW_DATA, $iv );
}
}
......@@ -104,24 +104,3 @@ add_filter( 'pre_update_option_etm_machine_translation_settings', function( $new
return $new_value;
}, 10, 2);
add_filter( 'http_request_timeout', 'wp9838c_timeout_extend' );
function wp9838c_timeout_extend( $time ) {
return ETM_HTTP_REQUEST_TIMEOUT;
}
// Setting custom option values for cURL. Using a high value for priority to ensure the function runs after any other added to the same action hook.
add_action( 'http_api_curl', 'etm_custom_curl_opts', 9999, 1 );
function etm_custom_curl_opts( $handle ) {
curl_setopt( $handle, CURLOPT_CONNECTTIMEOUT, ETM_HTTP_REQUEST_TIMEOUT );
curl_setopt( $handle, CURLOPT_TIMEOUT, ETM_HTTP_REQUEST_TIMEOUT );
curl_setopt( $handle, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $handle, CURLOPT_FOLLOWLOCATION, true );
}
// Setting custom timeout in HTTP request args
add_filter( 'http_request_args', 'etm_custom_http_request_args', 9999, 1 );
function etm_custom_http_request_args( $r ) {
$r['timeout'] = ETM_HTTP_REQUEST_TIMEOUT;
return $r;
}
\ No newline at end of file
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class ETM_Other_Machine_Translator extends ETM_Machine_Translator {
public function __construct( $settings ) {
parent::__construct( $settings );
}
/**
* Send request to Generic MT API
*
* @param string $source_language Translate from language
* @param string $language_code Translate to language
* @param array $strings_array Array of string to translate
*
* @return array|WP_Error Response
*/
public function send_translation_request( $source_language, $target_language, $strings_array, $domain = null ) {
$data = (object) array();
$data->srcLang = $source_language;
$data->trgLang = $target_language;
$data->text = array_values( $strings_array );
if ( $domain ) {
$data->domain = $domain;
}
$response = wp_remote_post(
$this->get_api_url() . '/text',
array(
'headers' => array(
'Content-Type' => 'application/json',
'accept' => 'text/plain',
'X-API-KEY' => $this->get_api_key(),
'timeout' => 45,
),
'body' => json_encode( $data, JSON_UNESCAPED_SLASHES ),
)
);
return $response;
}
/**
* Returns an array with the API provided translations of the $new_strings array.
*
* @param array $new_strings array with the strings that need translation. The keys are the node number in the DOM so we need to preserve them
* @param string $target_language_code language code of the language that we will be translating to. Not equal to the google language code
* @param string $source_language_code language code of the language that we will be translating from. Not equal to the google language code
* @return array array with the translation strings and the preserved keys or an empty array if something went wrong
*/
public function translate_array( $new_strings, $target_language_code, $source_language_code = null ) {
if ( $source_language_code === null ) {
$source_language_code = $this->settings['default-language'];
}
if ( empty( $new_strings ) || ! $this->verify_request_parameters( $target_language_code, $source_language_code ) ) {
return array();
}
$source_language = $this->machine_translation_codes[ $source_language_code ];
$target_language = $this->machine_translation_codes[ $target_language_code ];
$domain = $this->settings['translation-languages-domain-parameter'][ $target_language_code ];
$translated_strings = array();
/* split our strings that need translation in chunks of maximum 40 strings */
$new_strings_chunks = array_chunk( $new_strings, 40, true );
/* if there are more than 40 strings we make multiple requests */
foreach ( $new_strings_chunks as $new_strings_chunk ) {
$i = 0;
$response = $this->send_translation_request( $source_language, $target_language, $new_strings_chunk, $domain );
// this is run only if "Log machine translation queries." is set to Yes.
$this->machine_translator_logger->log(
array(
'strings' => serialize( $new_strings_chunk ),
'response' => serialize( $response ),
'lang_source' => $source_language,
'lang_target' => $target_language,
)
);
/* analyze the response */
if ( is_array( $response ) && ! is_wp_error( $response ) && isset( $response['response'] ) &&
isset( $response['response']['code'] ) && $response['response']['code'] === 200 ) {
$this->machine_translator_logger->count_towards_quota( $new_strings_chunk );
$translation_response = json_decode( $response['body'] );
$translations = array_map(
function( $item ) {
return stripslashes( $item->translation );
},
$translation_response->translations
);
foreach ( $new_strings_chunk as $key => $old_string ) {
if ( isset( $translations[ $i ] ) ) {
$translated_strings[ $key ] = $translations[ $i ];
} else {
$translated_strings[ $key ] = $old_string;
}
$i++;
}
if ( $this->machine_translator_logger->quota_exceeded() ) {
break;
}
} else {
error_log( 'Error on translation: ' . print_r( $response, true ) );
}
}
// will have the same indexes as $new_string or it will be an empty array if something went wrong.
return $translated_strings;
}
private function send_lang_direction_request() {
$response = wp_remote_get(
$this->get_api_url() . '/language-directions',
array(
'headers' => array(
'Content-Type' => 'application/json',
'accept' => 'text/plain',
'X-API-KEY' => $this->get_api_key(),
'timeout' => 45,
),
)
);
return $response;
}
/**
* Send a test request to verify if the functionality is working
*/
public function test_request() {
return $this->send_lang_direction_request();
}
public function credentials_set() {
return ! empty( $this->get_api_url() ) && ! empty( $this->get_api_key() );
}
public function get_api_url() {
return isset( $this->settings['etm_machine_translation_settings'], $this->settings['etm_machine_translation_settings']['other-mt-url'] ) ? $this->settings['etm_machine_translation_settings']['other-mt-url'] : '';
}
public function get_api_key() {
return isset( $this->settings['etm_machine_translation_settings'], $this->settings['etm_machine_translation_settings']['other-mt-key'] ) ? $this->settings['etm_machine_translation_settings']['other-mt-key'] : '';
}
public function get_supported_languages() {
$response = $this->send_lang_direction_request();
$source_language_code = $this->settings['default-language'];
$source_language = $this->machine_translation_codes[ $source_language_code ];
$supported_languages = array();
if ( is_array( $response ) && ! is_wp_error( $response ) && isset( $response['response'] ) &&
isset( $response['response']['code'] ) && $response['response']['code'] === 200 ) {
$decoded_response = json_decode( $response['body'] );
foreach ( $decoded_response->languageDirections as $direction ) {
if ( $direction->srcLang === $source_language ) {
$supported_languages[] = $direction->srcLang;
$supported_languages[] = $direction->trgLang;
}
}
}
return array_values( array_unique( $supported_languages ) );
}
public function get_domain_list() {
$response = $this->send_lang_direction_request();
$http_status = wp_remote_retrieve_response_code( $response );
$body = wp_remote_retrieve_body( $response );
if ( $http_status != 200 ) {
error_log( "Error retrieving language directions from MT provider: $body [status: $http_status]" );
}
return array(
'response' => $http_status,
'body' => json_decode( $body ),
);
}
public function get_engine_specific_language_codes( $languages ) {
return $this->etm_languages->get_iso_codes( $languages );
}
public function check_api_key_validity() {
$is_error = false;
$return_message = '';
if ( isset( $this->correct_api_key ) && $this->correct_api_key != null ) {
return $this->correct_api_key;
}
if ( ! $this->credentials_set() ) {
$is_error = true;
$return_message = __( 'Please enter your Custom provider Base URL & API key.', 'etranslation-multilingual' );
} else {
$response = $this->test_request();
$code = wp_remote_retrieve_response_code( $response );
if ( 200 !== $code ) {
$is_error = true;
$translate_response = etm_othermt_response_codes( $code );
$return_message = $translate_response['message'] ? $translate_response['message'] : __( 'Error on Custom provider HTTP request', 'etranslation-multilingual' );
error_log( 'Error on Custom provider request: ' . print_r( $response, true ) );
}
}
$this->correct_api_key = array(
'message' => $return_message,
'error' => $is_error,
);
return $this->correct_api_key;
}
}
......@@ -2,32 +2,94 @@
add_filter( 'etm_machine_translation_engines', 'etm_othermt_add_engine', 6 );
function etm_othermt_add_engine( $engines ){
$engines[] = array( 'value' => 'othermt', 'label' => __( 'Other MT Provider', 'etranslation-multilingual' ) );
$engines[] = array( 'value' => 'othermt', 'label' => __( 'Custom provider', 'etranslation-multilingual' ) );
return $engines;
}
add_action( 'etm_machine_translation_extra_settings_middle', 'etm_othermt_add_settings' );
function etm_othermt_add_settings( $mt_settings ){
$etm = ETM_eTranslation_Multilingual::get_etm_instance();
$machine_translator = $etm->get_component( 'machine_translator' );
$translation_engine = isset( $mt_settings['translation-engine'] ) ? $mt_settings['translation-engine'] : '';
$othermt_engine = 'othermt';
// Check for errors.
$error_message = '';
$show_errors = false;
if ( isset( $mt_settings['other-mt-url'] ) && ! filter_var( $mt_settings['other-mt-url'], FILTER_VALIDATE_URL ) ) {
$error_message = wp_kses( __( 'Please enter a valid URL' ), array() );
$show_errors = true;
} else {
// Check for API errors only if $translation_engine is 'othermt'.
if ( $othermt_engine === $translation_engine ) {
$api_check = $machine_translator->check_api_key_validity();
}
if ( isset( $api_check ) && true === $api_check['error'] ) {
$error_message = $api_check['message'];
$show_errors = true;
}
}
$text_input_classes = array(
'etm-text-input',
);
if ( $show_errors && $othermt_engine === $translation_engine ) {
$text_input_classes[] = 'etm-text-input-error';
}
?>
<tr>
<th scope="row"><?php esc_html_e( 'API URL', 'etranslation-multilingual' ); ?> </th>
<th scope="row"><?php esc_html_e( 'Base URL', 'etranslation-multilingual' ); ?> </th>
<td class="other-mt-fields">
<?php
// Display an error message above the input.
if ( $show_errors && $othermt_engine === $translation_engine ) {
?>
<p class="etm-error-inline">
<?php echo wp_kses_post( $error_message ); ?>
</p>
<?php
}
?>
<input type="text" class="<?php echo esc_html( implode( ' ', $text_input_classes ) ); ?>" name="etm_machine_translation_settings[other-mt-url]" value="<?php if( !empty( $mt_settings['other-mt-url'] ) ) echo esc_attr( $mt_settings['other-mt-url']);?>"/>
</td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'API KEY', 'etranslation-multilingual' ); ?> </th>
<th scope="row"><?php esc_html_e( 'API key', 'etranslation-multilingual' ); ?> </th>
<td class="other-mt-fields">
<input type="text" class="<?php echo esc_html( implode( ' ', $text_input_classes ) ); ?>" name="etm_machine_translation_settings[other-mt-key]" value="<?php if( !empty( $mt_settings['other-mt-key'] ) ) echo esc_attr( $mt_settings['other-mt-key']);?>"/>
<?php
// Only show errors if eTranslation is active.
if ( $machine_translator->is_available() && $othermt_engine === $translation_engine && function_exists( 'etm_output_svg' ) ) {
$machine_translator->automatic_translation_svg_output( $show_errors );
}
?>
<p class="description">
Ask your MT provider for its API URL & Key
<?php echo wp_kses( __( 'Ask your MT provider for its Base URL & API key' ), array() ); ?>
</p>
</td>
</tr>
<?php
}
function etm_othermt_response_codes( $code ) {
$is_error = false;
$code = intval( $code );
$return_message = '';
if ( preg_match( '/4\d\d/', $code ) || preg_match( '/5\d\d/', $code ) ) {
$is_error = true;
$return_message = esc_html__( 'There was an error with your Custom provider configuration. Click on "Test API credentials" button for more details. ', 'etranslation-multilingual' );
}
return array(
'message' => $return_message,
'error' => $is_error,
);
}
\ No newline at end of file
......@@ -86,6 +86,7 @@ function etranslation_query_action($action, $arg) {
defined('DEFAULT_ETRANSLATION_TIMEOUT') or define('DEFAULT_ETRANSLATION_TIMEOUT', 7);
defined('ETM_HTTP_REQUEST_TIMEOUT') or define('ETM_HTTP_REQUEST_TIMEOUT', 30);
defined('ETM_HTTP_TRANSLATION_TIMEOUT') or define('ETM_HTTP_TRANSLATION_TIMEOUT', 120);
function etm_enable_etranslation_multilingual(){
$enable_etranslation_multilingual = true;
......
<div id="etm-advanced-settings" class="wrap">
<form method="post" action="options.php">
<?php settings_fields( 'etm_advanced_settings' ); ?>
<div id="tab_title__wrap">
<h1 id="tab_title">
<img id="tab_title__logo" />
<h1> <?php esc_html_e( 'eTranslation Multilingual Advanced Settings', 'etranslation-multilingual' ); ?></h1>
</div>
<?php esc_html_e( 'eTranslation Multilingual Advanced Settings', 'etranslation-multilingual' ); ?>
</h1>
<?php do_action( 'etm_settings_navigation_tabs' ); ?>
<?php do_action( 'etm_before_output_advanced_settings_options' ); ?>
......
<div id="etm-about" class="wrap">
<div id="tab_title__wrap">
<h1 id="tab_title">
<img id="tab_title__logo" />
<h1> <?php esc_html_e( 'eTranslation Multilingual About', 'etranslation-multilingual' ); ?></h1>
</div>
<?php esc_html_e( 'eTranslation Multilingual About', 'etranslation-multilingual' ); ?>
</h1>
<?php do_action( 'etm_settings_navigation_tabs' ); ?>
<div class="grid feat-header">
......
<div id="etm-main-settings" class="wrap">
<form method="post" action="options.php">
<?php settings_fields( 'etm_machine_translation_settings' ); ?>
<div id="tab_title__wrap">
<h1 id="tab_title">
<img id="tab_title__logo" />
<h1> <?php esc_html_e( 'eTranslation Multilingual Automatic Translation', 'etranslation-multilingual' ); ?></h1>
</div>
<?php esc_html_e( 'eTranslation Multilingual Automatic Translation', 'etranslation-multilingual' ); ?>
</h1>
<?php do_action( 'etm_settings_navigation_tabs' ); ?>
<table id="etm-options" class="form-table etm-machine-translation-options">
......@@ -29,7 +29,7 @@
<?php foreach ( $translation_engines as $engine ) : ?>
<label for="etm-translation-engine-<?php echo esc_attr( $engine['value'] ); ?>" style="margin-right:10px;">
<input type="radio" class="etm-translation-engine etm-radio" id="etm-translation-engine-<?php echo esc_attr( $engine['value'] ); ?>" name="etm_machine_translation_settings[translation-engine]" value="<?php echo esc_attr( $engine['value'] ); ?>" <?php checked( $this->settings['etm_machine_translation_settings']['translation-engine'], $engine['value'] ); ?> <?php disabled( 'othermt', $engine['value'] ); ?>>
<input type="radio" class="etm-translation-engine etm-radio" id="etm-translation-engine-<?php echo esc_attr( $engine['value'] ); ?>" name="etm_machine_translation_settings[translation-engine]" value="<?php echo esc_attr( $engine['value'] ); ?>" <?php checked( $this->settings['etm_machine_translation_settings']['translation-engine'], $engine['value'] ); ?>>
<?php echo esc_html( $engine['label'] ); ?>
</label>
<?php endforeach; ?>
......
......@@ -11,16 +11,6 @@
</tr>
</thead>
<tbody id="etm-sortable-languages" class="etm-language-selector-limited">
<?php
$domain_array = array();
$etm = ETM_eTranslation_Multilingual::get_etm_instance();
$machine_translator = $etm->get_component( 'machine_translator' );
if ( $machine_translator instanceof ETM_eTranslation_Machine_Translator && $machine_translator->is_available() && $machine_translator->credentials_set() ) {
$domain_array = $machine_translator->get_all_domains();
}
?>
<?php
foreach ( $this->settings['translation-languages'] as $key => $selected_language_code ) {
$default_language = ( $selected_language_code == $this->settings['default-language'] );
......@@ -42,15 +32,7 @@
<?php } ?>
</td>
<td>
<select name="etm_settings[translation-languages-domain][]" class="etm-translation-language-domain" <?php disabled( empty( $domain_array ), true ); ?>>
<?php
foreach ( $domain_array as $key => $value ) {
?>
<option value="<?php echo esc_attr( $key ); ?>" <?php echo ( isset( $this->settings['translation-languages-domain-parameter'][ $selected_language_code ] ) && $key == $this->settings['translation-languages-domain-parameter'][ $selected_language_code ] ) ? 'selected' : ''; ?>><?php echo esc_html( $value->name ); ?></option>
<?php
}
?>
</select>
<select name="etm_settings[translation-languages-domain][]" class="etm-translation-language-domain"></select>
</td>
<td>
<input class="etm-language-code etm-code-slug" type="text" disabled value="<?php echo esc_attr( $selected_language_code ); ?>">
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment