TranslatePress – Translate Multilingual sites - Version 1.7.9

Version Description

  • Fix for various 404 page results
  • Fixed flag spacing in RTL languages
  • Added "Full Language Names No HTML" option to language menu
  • Added possibility to change date format by language
  • Oxygen plugin stylesheet loading time improvement
  • Compatibility with Brizy's editor
  • Added filter to allow https adjustments
  • Improved searching on certain pages
Download this release

Release Info

Developer madalin.ungureanu
Plugin Icon 128x128 TranslatePress – Translate Multilingual sites
Version 1.7.9
Comparing to
See all releases

Code changes from version 1.7.8 to 1.7.9

assets/css/trp-floater-language-switcher.css CHANGED
@@ -115,6 +115,10 @@ body.admin-bar #trp-floater-ls.trp-top-left{
115
  padding: 0;
116
  }
117
 
 
 
 
 
118
  #trp-floater-ls a {
119
  text-decoration: none;
120
  }
115
  padding: 0;
116
  }
117
 
118
+ .trp-flag-image:dir(rtl) {
119
+ margin-left: 5px;
120
+ }
121
+
122
  #trp-floater-ls a {
123
  text-decoration: none;
124
  }
class-translate-press.php CHANGED
@@ -57,7 +57,7 @@ class TRP_Translate_Press{
57
  define( 'TRP_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
58
  define( 'TRP_PLUGIN_BASE', plugin_basename( __DIR__ . '/index.php' ) );
59
  define( 'TRP_PLUGIN_SLUG', 'translatepress-multilingual' );
60
- define( 'TRP_PLUGIN_VERSION', '1.7.8' );
61
 
62
  wp_cache_add_non_persistent_groups(array('trp'));
63
 
@@ -298,6 +298,7 @@ class TRP_Translate_Press{
298
 
299
  $this->loader->add_action( 'trp_translation_manager_footer', $this->translation_manager, 'enqueue_scripts_and_styles' );
300
  $this->loader->add_filter( 'template_include', $this->translation_manager, 'translation_editor', 99999 );
 
301
  $this->loader->add_action( 'wp_enqueue_scripts', $this->translation_manager, 'enqueue_preview_scripts_and_styles' );
302
  $this->loader->add_action( 'admin_bar_menu', $this->translation_manager, 'add_shortcut_to_translation_editor', 90, 1 );
303
  $this->loader->add_action( 'admin_head', $this->translation_manager, 'add_styling_to_admin_bar_button', 10 );
@@ -358,7 +359,8 @@ class TRP_Translate_Press{
358
  */
359
  $this->loader->add_filter( "option_rewrite_rules", $this->url_converter, 'woocommerce_filter_permalinks_on_other_languages' );
360
  $this->loader->add_filter( "option_woocommerce_permalinks", $this->url_converter, 'woocommerce_filter_permalink_option' );
361
- $this->loader->add_filter( "pre_update_option_woocommerce_permalinks", $this->url_converter, 'woocommerce_handle_permalink_option_on_frontend', 10, 2 );
 
362
 
363
  /* add to the body class the current language */
364
  $this->loader->add_filter( "body_class", $this->translation_manager, 'add_language_to_body_class' );
57
  define( 'TRP_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
58
  define( 'TRP_PLUGIN_BASE', plugin_basename( __DIR__ . '/index.php' ) );
59
  define( 'TRP_PLUGIN_SLUG', 'translatepress-multilingual' );
60
+ define( 'TRP_PLUGIN_VERSION', '1.7.9' );
61
 
62
  wp_cache_add_non_persistent_groups(array('trp'));
63
 
298
 
299
  $this->loader->add_action( 'trp_translation_manager_footer', $this->translation_manager, 'enqueue_scripts_and_styles' );
300
  $this->loader->add_filter( 'template_include', $this->translation_manager, 'translation_editor', 99999 );
301
+ $this->loader->add_filter( 'option_date_format', $this->translation_manager, 'filter_the_date' );
302
  $this->loader->add_action( 'wp_enqueue_scripts', $this->translation_manager, 'enqueue_preview_scripts_and_styles' );
303
  $this->loader->add_action( 'admin_bar_menu', $this->translation_manager, 'add_shortcut_to_translation_editor', 90, 1 );
304
  $this->loader->add_action( 'admin_head', $this->translation_manager, 'add_styling_to_admin_bar_button', 10 );
359
  */
360
  $this->loader->add_filter( "option_rewrite_rules", $this->url_converter, 'woocommerce_filter_permalinks_on_other_languages' );
361
  $this->loader->add_filter( "option_woocommerce_permalinks", $this->url_converter, 'woocommerce_filter_permalink_option' );
362
+ $this->loader->add_filter( "pre_update_option_woocommerce_permalinks", $this->url_converter, 'prevent_permalink_update_on_other_languages', 10, 2 );
363
+ $this->loader->add_filter( "pre_update_option_rewrite_rules", $this->url_converter, 'prevent_permalink_update_on_other_languages', 10, 2 );
364
 
365
  /* add to the body class the current language */
366
  $this->loader->add_filter( "body_class", $this->translation_manager, 'add_language_to_body_class' );
includes/advanced-settings/custom-date-format.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Register advanced configuration option for custom date formatting for every translated language
4
+ * The settings uses the 'input_array' advanced setting
5
+ * Saves as a key-value pair
6
+ *
7
+ */
8
+ add_filter( 'trp_register_advanced_settings', 'trp_register_language_date_format', 1105 );
9
+ function trp_register_language_date_format( $settings_array ){
10
+
11
+ $settings_array[] = array(
12
+ 'name' => 'language_date_format',
13
+ 'rows' => trp_get_languages("nodefault"),
14
+ 'default' => '',
15
+ 'type' => 'input_array',
16
+ 'label' => esc_html__( 'Date format', 'translatepress-multilingual' ),
17
+ 'description' => wp_kses( __( 'Customize the date formatting per each translated language.<br/>Leave empty for default WP setting or see more information <a href="https://wordpress.org/support/article/formatting-date-and-time/" title="Formatting Date and Time" target="_blank">here</a>', 'translatepress-multilingual' ), array( 'br' => array(), 'a' => array( 'href' => array(), 'title' => array(), 'target' => array() ) )),
18
+ );
19
+
20
+ return $settings_array;
21
+ }
includes/advanced-settings/enable-hreflang-xdefault.php CHANGED
@@ -13,12 +13,6 @@ function trp_register_enable_hreflang_xdefault( $settings_array ){
13
  }
14
 
15
  function trp_get_lang_for_xdefault(){
16
- $trp_obj = TRP_Translate_Press::get_trp_instance();
17
- $settings_obj = $trp_obj->get_component('settings');
18
- $lang_obj = $trp_obj->get_component( 'languages' );
19
-
20
- $published_lang = $settings_obj->get_setting('publish-languages');
21
- $published_lang_labels = $lang_obj->get_language_names( $published_lang );
22
-
23
  return array_merge(['disabled' => 'Disabled'], $published_lang_labels);
24
  }
13
  }
14
 
15
  function trp_get_lang_for_xdefault(){
16
+ $published_lang_labels = trp_get_languages();
 
 
 
 
 
 
17
  return array_merge(['disabled' => 'Disabled'], $published_lang_labels);
18
  }
includes/class-advanced-tab.php CHANGED
@@ -77,6 +77,14 @@ class TRP_Advanced_Tab {
77
  $settings[ $registered_setting['name'] ] = sanitize_text_field($submitted_settings[ $registered_setting['name'] ]);
78
  break;
79
  }
 
 
 
 
 
 
 
 
80
  case 'number': {
81
  $settings[ $registered_setting['name'] ] = sanitize_text_field(intval($submitted_settings[ $registered_setting['name'] ] ) );
82
  break;
@@ -147,6 +155,7 @@ class TRP_Advanced_Tab {
147
  include_once(TRP_PLUGIN_DIR . 'includes/advanced-settings/disable-dynamic-translation.php');
148
  include_once(TRP_PLUGIN_DIR . 'includes/advanced-settings/enable-auto-translate-slug.php');
149
  include_once(TRP_PLUGIN_DIR . 'includes/advanced-settings/enable-numerals-translation.php');
 
150
  include_once(TRP_PLUGIN_DIR . 'includes/advanced-settings/exclude-dynamic-selectors.php');
151
  include_once(TRP_PLUGIN_DIR . 'includes/advanced-settings/exclude-gettext-strings.php');
152
  include_once(TRP_PLUGIN_DIR . 'includes/advanced-settings/exclude-selectors.php');
@@ -207,6 +216,9 @@ class TRP_Advanced_Tab {
207
  case 'number':
208
  echo $this->input_setting( $setting, 'number' );
209
  break;
 
 
 
210
  case 'select':
211
  echo $this->select_setting( $setting );
212
  break;
@@ -309,6 +321,39 @@ class TRP_Advanced_Tab {
309
  return apply_filters('trp_advanced_setting_input', $html );
310
  }
311
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
  /**
313
  * Return HTML of a input type setting
314
  *
77
  $settings[ $registered_setting['name'] ] = sanitize_text_field($submitted_settings[ $registered_setting['name'] ]);
78
  break;
79
  }
80
+ case 'input_array': {
81
+ foreach ( $registered_setting['rows'] as $row_label => $row_name ) {
82
+ if (isset($submitted_settings[$registered_setting['name']][$row_label])) {
83
+ $settings[$registered_setting['name']][$row_label] = sanitize_text_field($submitted_settings[$registered_setting['name']][$row_label]);
84
+ }
85
+ }
86
+ break;
87
+ }
88
  case 'number': {
89
  $settings[ $registered_setting['name'] ] = sanitize_text_field(intval($submitted_settings[ $registered_setting['name'] ] ) );
90
  break;
155
  include_once(TRP_PLUGIN_DIR . 'includes/advanced-settings/disable-dynamic-translation.php');
156
  include_once(TRP_PLUGIN_DIR . 'includes/advanced-settings/enable-auto-translate-slug.php');
157
  include_once(TRP_PLUGIN_DIR . 'includes/advanced-settings/enable-numerals-translation.php');
158
+ include_once(TRP_PLUGIN_DIR . 'includes/advanced-settings/custom-date-format.php');
159
  include_once(TRP_PLUGIN_DIR . 'includes/advanced-settings/exclude-dynamic-selectors.php');
160
  include_once(TRP_PLUGIN_DIR . 'includes/advanced-settings/exclude-gettext-strings.php');
161
  include_once(TRP_PLUGIN_DIR . 'includes/advanced-settings/exclude-selectors.php');
216
  case 'number':
217
  echo $this->input_setting( $setting, 'number' );
218
  break;
219
+ case 'input_array':
220
+ echo $this->input_array_setting( $setting );
221
+ break;
222
  case 'select':
223
  echo $this->select_setting( $setting );
224
  break;
321
  return apply_filters('trp_advanced_setting_input', $html );
322
  }
323
 
324
+ /**
325
+ * Return HTML of an array type setting
326
+ *
327
+ * @param $setting
328
+ * @param string $type
329
+ *
330
+ * @return 'string'
331
+ */
332
+ public function input_array_setting ($setting, $type = 'text'){
333
+ $adv_option = $this->settings['trp_advanced_settings'];
334
+ $default = ( isset( $setting['default'] )) ? $setting['default'] : '';
335
+
336
+ $html = "
337
+ <tr>
338
+ <th scope='row'>" . $setting['label'] . "</th>
339
+ <td>
340
+ <table class='form-table' style='width:10rem;margin-left:-2rem;margin-top:-1rem'>";
341
+ foreach ($setting['rows'] as $row_label=>$row_name ){
342
+ $value = ( isset( $adv_option[ $setting['name'] ][$row_label] ) ) ? $adv_option[ $setting['name'] ][$row_label] : $default;
343
+
344
+ $html.= "
345
+ <tr>
346
+ <td><label for='{$setting['name']}-{$row_label}'> {$row_name} </label></td><td><input type='{$type}' id='{$setting['name']}-{$row_label}' name='trp_advanced_settings[{$setting['name']}][{$row_label}]' value='{$value}'>
347
+ </td>
348
+ </tr>";
349
+ }
350
+ $html.="</table>
351
+ <p class='description'>{$setting['description']}</p>
352
+ </td>
353
+ </tr>";
354
+ return apply_filters('trp_advanced_setting_input_array', $html );
355
+ }
356
+
357
  /**
358
  * Return HTML of a input type setting
359
  *
includes/class-language-switcher.php CHANGED
@@ -426,21 +426,28 @@ class TRP_Language_Switcher{
426
  }
427
  $language_names = $this->trp_languages->get_language_names( array( $language_code ) );
428
  $language_name = $language_names[$language_code];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
429
 
430
-
431
- $items[$key]->url = $this->url_converter->get_url_for_language( $language_code );
432
- $items[$key]->classes[] = 'trp-language-switcher-container';
433
- $items[$key]->title = '<span data-no-translation>';
434
- if ( $menu_settings['flags'] ) {
435
- $items[$key]->title .= $this->add_flag( $language_code, $language_name );
436
- }
437
- if ( $menu_settings['short_names'] ) {
438
- $items[$key]->title .= '<span class="trp-ls-language-name">' . strtoupper( $this->url_converter->get_url_slug( $language_code, false ) ) . '</span>';
439
  }
440
- if ( $menu_settings['full_names'] ) {
441
- $items[$key]->title .= '<span class="trp-ls-language-name">' . $language_name . '</span>';
442
- }
443
- $items[$key]->title .= '</span>';
444
 
445
  $items[$key]->title = apply_filters( 'trp_menu_language_switcher', $items[$key]->title, $language_name, $language_code, $menu_settings );
446
  }
426
  }
427
  $language_names = $this->trp_languages->get_language_names( array( $language_code ) );
428
  $language_name = $language_names[$language_code];
429
+ $items[$key]->url = $this->url_converter->get_url_for_language( $language_code );
430
+
431
+ // Output of simple text only menu, for compatibility with certain themes/plugins
432
+ if ($menu_settings["no_html"] ){
433
+ $items[$key]->classes[] = '';
434
+ $items[$key]->title = $language_name;
435
+ } else {
436
+ $items[$key]->classes[] = 'trp-language-switcher-container';
437
+ $items[$key]->title = '<span data-no-translation>';
438
+ if ( $menu_settings['flags'] ) {
439
+ $items[$key]->title .= $this->add_flag( $language_code, $language_name );
440
+ }
441
+ if ( $menu_settings['short_names'] ) {
442
+ $items[$key]->title .= '<span class="trp-ls-language-name">' . strtoupper( $this->url_converter->get_url_slug( $language_code, false ) ) . '</span>';
443
+ }
444
+ if ( $menu_settings['full_names'] ) {
445
+ $items[$key]->title .= '<span class="trp-ls-language-name">' . $language_name . '</span>';
446
+ }
447
+ $items[$key]->title .= '</span>';
448
 
 
 
 
 
 
 
 
 
 
449
  }
450
+
 
 
 
451
 
452
  $items[$key]->title = apply_filters( 'trp_menu_language_switcher', $items[$key]->title, $language_name, $language_code, $menu_settings );
453
  }
includes/class-machine-translator.php CHANGED
@@ -160,6 +160,8 @@ class TRP_Machine_Translator {
160
  $placeholders = $this->get_placeholders(count($trp_exclude_words_from_automatic_translation));
161
  $shortcode_tags_to_execute = apply_filters( 'trp_do_these_shortcodes_before_automatic_translation', array('trp_language') );
162
 
 
 
163
  foreach ($strings as $key => $string) {
164
  /* html_entity_decode is needed before replacing the character "#" from the list because characters like &#8220; (8220 utf8)
165
  * will get an extra space after '&' which will break the character, rendering it like this: & #8220;
@@ -175,13 +177,13 @@ class TRP_Machine_Translator {
175
  $machine_strings = $this->translate_array($strings, $target_language_code, $source_language_code);
176
  }
177
 
178
-
179
  if (!empty($machine_strings)) {
180
  foreach ($machine_strings as $key => $machine_string) {
181
- $machine_strings[$key] = str_ireplace( $placeholders, $trp_exclude_words_from_automatic_translation, $machine_string );
182
  }
183
  }
184
- return $machine_strings;
185
  }else {
186
  return array();
187
  }
160
  $placeholders = $this->get_placeholders(count($trp_exclude_words_from_automatic_translation));
161
  $shortcode_tags_to_execute = apply_filters( 'trp_do_these_shortcodes_before_automatic_translation', array('trp_language') );
162
 
163
+ $strings = array_unique($strings);
164
+ $original_strings = $strings;
165
  foreach ($strings as $key => $string) {
166
  /* html_entity_decode is needed before replacing the character "#" from the list because characters like &#8220; (8220 utf8)
167
  * will get an extra space after '&' which will break the character, rendering it like this: & #8220;
177
  $machine_strings = $this->translate_array($strings, $target_language_code, $source_language_code);
178
  }
179
 
180
+ $machine_strings_return_array = array();
181
  if (!empty($machine_strings)) {
182
  foreach ($machine_strings as $key => $machine_string) {
183
+ $machine_strings_return_array[$original_strings[$key]] = str_ireplace( $placeholders, $trp_exclude_words_from_automatic_translation, $machine_string );
184
  }
185
  }
186
+ return $machine_strings_return_array;
187
  }else {
188
  return array();
189
  }
includes/class-query.php CHANGED
@@ -407,6 +407,9 @@ class TRP_Query{
407
  * @return array|object|null
408
  */
409
  public function original_strings_sync( $language_code, $new_strings ){
 
 
 
410
  if ( $this->settings['default-language'] != $language_code ) {
411
 
412
  $originals_table = $this->get_table_name_for_original_strings();
@@ -617,14 +620,14 @@ class TRP_Query{
617
  *
618
  * @param array $update_strings Array of strings to update
619
  * @param string $language_code Language code
620
- * @param array $columns_to_update Array with the name of columns to update id, original, translated, status, block_type
621
  */
622
- public function update_strings( $update_strings, $language_code, $columns_to_update = array('id','original', 'translated', 'status', 'block_type') ) {
623
  if ( count( $update_strings ) == 0 ) {
624
  return;
625
  }
626
 
627
- $placeholder_array_mapping = array( 'id'=>'%d', 'original'=>'%s', 'translated' => '%s', 'status' => '%d', 'block_type'=>'%d' );
628
  $columns_query_part = '';
629
  foreach ( $columns_to_update as $column ) {
630
  $columns_query_part .= $column . ',';
407
  * @return array|object|null
408
  */
409
  public function original_strings_sync( $language_code, $new_strings ){
410
+ if ( count($new_strings ) === 0 ){
411
+ return array();
412
+ }
413
  if ( $this->settings['default-language'] != $language_code ) {
414
 
415
  $originals_table = $this->get_table_name_for_original_strings();
620
  *
621
  * @param array $update_strings Array of strings to update
622
  * @param string $language_code Language code
623
+ * @param array $columns_to_update Array with the name of columns to update id, original, translated, status, block_type, original_id
624
  */
625
+ public function update_strings( $update_strings, $language_code, $columns_to_update = array('id','original', 'translated', 'status', 'block_type', 'original_id') ) {
626
  if ( count( $update_strings ) == 0 ) {
627
  return;
628
  }
629
 
630
+ $placeholder_array_mapping = array( 'id'=>'%d', 'original'=>'%s', 'translated' => '%s', 'status' => '%d', 'block_type'=>'%d', 'original_id'=>'%d' );
631
  $columns_query_part = '';
632
  foreach ( $columns_to_update as $column ) {
633
  $columns_query_part .= $column . ',';
includes/class-search.php CHANGED
@@ -71,7 +71,7 @@ class TRP_Search extends WP_Query{
71
 
72
  $search_result_ids = array();
73
  $trp_search_query = '';
74
- $dictionary_name = $this->trp_query->get_table_name( $TRP_LANGUAGE );
75
  $meta_table_name = $this->trp_query->get_table_name_for_original_meta();
76
 
77
  if( $search_terms_count === 1 ){
71
 
72
  $search_result_ids = array();
73
  $trp_search_query = '';
74
+ $dictionary_name = $this->trp_query->get_table_name( apply_filters( 'trp_change_search_dictionary_language', $TRP_LANGUAGE, $this, $query ) );
75
  $meta_table_name = $this->trp_query->get_table_name_for_original_meta();
76
 
77
  if( $search_terms_count === 1 ){
includes/class-settings.php CHANGED
@@ -23,11 +23,12 @@ class TRP_Settings{
23
  */
24
  public function get_language_switcher_options(){
25
  $ls_options = apply_filters( 'trp_language_switcher_output', array(
26
- 'full-names' => array( 'full_names' => true, 'short_names' => false, 'flags' => false, 'label' => __( 'Full Language Names', 'translatepress-multilingual' ) ),
27
- 'short-names' => array( 'full_names' => false, 'short_names' => true, 'flags' => false, 'label' => __( 'Short Language Names', 'translatepress-multilingual' ) ),
28
- 'flags-full-names' => array( 'full_names' => true, 'short_names' => false, 'flags' => true, 'label' => __( 'Flags with Full Language Names', 'translatepress-multilingual' ) ),
29
- 'flags-short-names' => array( 'full_names' => false, 'short_names' => true, 'flags' => true, 'label' => __( 'Flags with Short Language Names', 'translatepress-multilingual' ) ),
30
- 'only-flags' => array( 'full_names' => false, 'short_names' => false, 'flags' => true, 'label' => __( 'Only Flags', 'translatepress-multilingual' ) ),
 
31
  ) );
32
  return $ls_options;
33
  }
@@ -40,10 +41,15 @@ class TRP_Settings{
40
  */
41
  public function output_language_switcher_select( $ls_type, $ls_setting ){
42
  $ls_options = $this->get_language_switcher_options();
 
 
 
 
43
  $output = '<select id="' . esc_attr( $ls_type ) . '" name="trp_settings[' . esc_attr( $ls_type ) .']" class="trp-select trp-ls-select-option">';
44
  foreach( $ls_options as $key => $ls_option ){
45
  $selected = ( $ls_setting == $key ) ? 'selected' : '';
46
  $output .= '<option value="' . esc_attr( $key ) . '" ' . esc_attr( $selected ) . ' >' . esc_html( $ls_option['label'] ). '</option>';
 
47
  }
48
  $output .= '</select>';
49
 
23
  */
24
  public function get_language_switcher_options(){
25
  $ls_options = apply_filters( 'trp_language_switcher_output', array(
26
+ 'full-names' => array( 'full_names' => true, 'short_names' => false, 'flags' => false, 'no_html' => false, 'label' => __( 'Full Language Names', 'translatepress-multilingual' ) ),
27
+ 'short-names' => array( 'full_names' => false, 'short_names' => true, 'flags' => false, 'no_html' => false, 'label' => __( 'Short Language Names', 'translatepress-multilingual' ) ),
28
+ 'flags-full-names' => array( 'full_names' => true, 'short_names' => false, 'flags' => true, 'no_html' => false, 'label' => __( 'Flags with Full Language Names', 'translatepress-multilingual' ) ),
29
+ 'flags-short-names' => array( 'full_names' => false, 'short_names' => true, 'flags' => true, 'no_html' => false, 'label' => __( 'Flags with Short Language Names', 'translatepress-multilingual' ) ),
30
+ 'only-flags' => array( 'full_names' => false, 'short_names' => false, 'flags' => true, 'no_html' => false, 'label' => __( 'Only Flags', 'translatepress-multilingual' ) ),
31
+ 'full-names-no-html' => array( 'full_names' => false, 'short_names' => false, 'flags' => false, 'no_html' => true, 'label' => __( 'Full Language Names No HTML', 'translatepress-multilingual' ) )
32
  ) );
33
  return $ls_options;
34
  }
41
  */
42
  public function output_language_switcher_select( $ls_type, $ls_setting ){
43
  $ls_options = $this->get_language_switcher_options();
44
+ // Use the full names no HTML option only for the menu - for extra compatibility with certain themes and menus
45
+ if ($ls_type !== 'menu-options'){
46
+ unset($ls_options['full-names-no-html']);
47
+ }
48
  $output = '<select id="' . esc_attr( $ls_type ) . '" name="trp_settings[' . esc_attr( $ls_type ) .']" class="trp-select trp-ls-select-option">';
49
  foreach( $ls_options as $key => $ls_option ){
50
  $selected = ( $ls_setting == $key ) ? 'selected' : '';
51
  $output .= '<option value="' . esc_attr( $key ) . '" ' . esc_attr( $selected ) . ' >' . esc_html( $ls_option['label'] ). '</option>';
52
+
53
  }
54
  $output .= '</select>';
55
 
includes/class-translation-manager.php CHANGED
@@ -5,7 +5,8 @@
5
  *
6
  * Handles Front-end Translation Editor, including Ajax requests.
7
  */
8
- class TRP_Translation_Manager {
 
9
  protected $settings;
10
  /** @var TRP_Translation_Render */
11
  protected $translation_render;
@@ -22,7 +23,8 @@ class TRP_Translation_Manager {
22
  *
23
  * @param array $settings Settings option.
24
  */
25
- public function __construct( $settings ) {
 
26
  $this->settings = $settings;
27
  }
28
 
@@ -34,16 +36,17 @@ class TRP_Translation_Manager {
34
  * @param string $mode 'true' | 'preview'
35
  * @return bool Whether current page is part of the Translation Editor.
36
  */
37
- protected function conditions_met( $mode = 'true' ) {
38
- if ( isset( $_REQUEST['trp-edit-translation'] ) && esc_attr( $_REQUEST['trp-edit-translation'] ) == $mode ) {
39
- if ( current_user_can( apply_filters( 'trp_translating_capability', 'manage_options' ) ) && !is_admin() ) {
 
40
  return true;
41
- } elseif ( esc_attr( $_REQUEST['trp-edit-translation'] ) == "preview" ) {
42
  return true;
43
  } else {
44
  wp_die(
45
- '<h1>' . esc_html__( 'Cheatin&#8217; uh?' ) . '</h1>' .
46
- '<p>' . esc_html__( 'Sorry, you are not allowed to access this page.' ) . '</p>',
47
  403
48
  );
49
  }
@@ -59,190 +62,199 @@ class TRP_Translation_Manager {
59
  * @param string $page_template Current page template.
60
  * @return string Template for translation Editor.
61
  */
62
- public function translation_editor( $page_template ) {
63
- if ( !$this->conditions_met() ) {
 
64
  return $page_template;
65
  }
66
 
67
  return TRP_PLUGIN_DIR . 'partials/translation-manager.php';
68
  }
69
 
70
- public function get_merge_rules() {
 
71
  $localized_text = $this->string_groups();
72
 
73
  $merge_rules = array(
74
- 'top_parents' => array( 'p', 'div', 'li', 'ol', 'ul', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'body', 'footer', 'article', 'main', 'iframe', 'section', 'figure', 'figcaption', 'blockquote', 'cite', 'tr', 'td', 'th', 'table', 'tbody', 'thead', 'tfoot', 'form' ),
75
- 'self_object_type' => array( 'translate-press' ),
76
- 'incompatible_siblings' => array( '[data-trpgettextoriginal]', '[data-trp-node-group="' . $localized_text['dynamicstrings'] . '"]' )
77
  );
78
 
79
- return apply_filters( 'trp_merge_rules', $merge_rules );
80
  }
81
 
82
- public function localized_text() {
83
- $update_seo_add_on = ( class_exists( 'TRP_Seo_Pack' ) && !defined( 'TRP_SP_PLUGIN_VERSION' ) );
 
84
 
85
  return $this->string_groups() + array(
86
  // attribute names
87
- 'src' => esc_html__( 'Image source', 'translatepress-multilingual' ),
88
- 'alt' => esc_html__( 'Alt attribute', 'translatepress-multilingual' ),
89
- 'title' => esc_html__( 'Title attribute', 'translatepress-multilingual' ),
90
- 'href' => esc_html__( 'Anchor link', 'translatepress-multilingual' ),
91
- 'placeholder' => esc_html__( 'Placeholder attribute', 'translatepress-multilingual' ),
92
- 'submit' => esc_html__( 'Submit attribute', 'translatepress-multilingual' ),
93
- 'text' => esc_html__( 'Text', 'translatepress-multilingual' ),
94
-
95
- 'saved' => esc_html__( 'Saved', 'translatepress-multilingual' ),
96
- 'save_translation' => esc_html__( 'Save translation', 'translatepress-multilingual' ),
97
- 'saving_translation' => esc_html__( 'Saving translation...', 'translatepress-multilingual' ),
98
- 'unsaved_changes' => esc_html__( 'You have unsaved changes!', 'translatepress-multilingual' ),
99
- 'discard' => esc_html__( 'Discard changes', 'translatepress-multilingual' ),
100
- 'discard_all' => esc_html__( 'Discard All', 'translatepress-multilingual' ),
101
- 'strings_loading' => esc_attr__( 'Loading Strings...', 'translatepress-multilingual' ),
102
- 'select_string' => esc_attr__( 'Select string to translate...', 'translatepress-multilingual' ),
103
- 'close' => esc_attr__( 'Close Editor', 'translatepress-multilingual' ),
104
- 'from' => esc_html__( 'From', 'translatepress-multilingual' ),
105
- 'to' => esc_html__( 'To', 'translatepress-multilingual' ),
106
- 'next' => esc_html__( 'Next', 'translatepress-multilingual' ),
107
- 'previous' => esc_html__( 'Previous', 'translatepress-multilingual' ),
108
- 'add_media' => esc_html__( 'Add Media', 'translatepress-multilingual' ),
109
- 'other_lang' => esc_html__( 'Other languages', 'translatepress-multilingual' ),
110
- 'view_as' => esc_html__( 'View As', 'translatepress-multilingual' ),
111
- 'view_as_pro' => esc_html__( 'Available in our Pro Versions', 'translatepress-multilingual' ),
112
 
113
  //wp media upload
114
- 'select_or_upload' => esc_html__( 'Select or Upload Media', 'translatepress-multilingual' ),
115
- 'use_this_media' => esc_html__( 'Use this media', 'translatepress-multilingual' ),
116
 
117
  // title attributes
118
- 'edit' => esc_attr__( 'Translate', 'translatepress-multilingual' ),
119
- 'merge' => esc_attr__( 'Translate entire block element', 'translatepress-multilingual' ),
120
- 'split' => esc_attr__( 'Split block to translate strings individually', 'translatepress-multilingual' ),
121
- 'save_title_attr' => esc_attr__( 'Save changes to translation. Shortcut: CTRL(⌘) + S', 'translatepress-multilingual' ),
122
- 'next_title_attr' => esc_attr__( 'Navigate to next string in dropdown list. Shortcut: CTRL(⌘) + ALT + Right Arrow', 'translatepress-multilingual' ),
123
- 'previous_title_attr' => esc_attr__( 'Navigate to previous string in dropdown list. Shortcut: CTRL(⌘) + ALT + Left Arrow', 'translatepress-multilingual' ),
124
- 'discard_all_title_attr' => esc_attr__( 'Discard all changes. Shortcut: CTRL(⌘) + ALT + Z', 'translatepress-multilingual' ),
125
- 'discard_individual_changes_title_attribute' => esc_attr__( 'Discard changes to this text box. To discard changes to all text boxes use shortcut: CTRL(⌘) + ALT + Z', 'translatepress-multilingual' ),
126
- 'dismiss_tooltip_title_attribute' => esc_attr__( 'Dismiss tooltip', 'translatepress-multilingual' ),
127
- 'quick_intro_title_attribute' => esc_attr__( 'Quick Intro', 'translatepress-multilingual' ),
128
-
129
- 'split_confirmation' => esc_js( __( 'Are you sure you want to split this phrase into smaller parts?', 'translatepress-multilingual' ) ),
130
- 'translation_not_loaded_yet' => wp_kses( __( 'This string is not ready for translation yet. <br>Try again in a moment...', 'translatepress-multilingual' ), array( 'br' => array() ) ),
131
-
132
- 'bor_update_notice' => esc_js( __( 'For this option to work, please update the Browse as other role add-on to the latest version.', 'translatepress-multilingual' ) ),
133
- 'seo_update_notice' => ( $update_seo_add_on ) ? esc_js( __( 'To translate slugs, please update the SEO Pack add-on to the latest version.', 'translatepress-multilingual' ) ) : 'seo_pack_update_not_needed',
134
 
135
  //Notice when the user has not defined a secondary language
136
- 'extra_lang_row1' => wp_kses( sprintf( __( 'You can add a new language from <a href="%s">Settings->TranslatePress</a>', 'translatepress-multilingual' ), esc_url( admin_url( 'options-general.php?page=translate-press' ) ) ), array( 'a' => [ 'href' => [] ] ) ),
137
- 'extra_lang_row2' => wp_kses( __( 'However, you can still use TranslatePress to <strong style="background: #f5fb9d;">modify gettext strings</strong> available in your page.', 'translatepress-multilingual' ), array( 'strong' => [ 'style' => [] ] ) ),
138
- 'extra_lang_row3' => esc_html__( 'Strings that are user-created cannot be modified, only those from themes and plugins.', 'translatepress-multilingual' ),
139
  //Pro version upselling
140
- 'extra_upsell_title' => esc_html__( 'Extra Translation Features', 'translatepress-multilingual' ),
141
- 'extra_upsell_row1' => esc_html__( 'Support for 221 Extra Languages', 'translatepress-multilingual' ),
142
- 'extra_upsell_row2' => esc_html__( 'Yoast SEO support', 'translatepress-multilingual' ),
143
- 'extra_upsell_row3' => esc_html__( 'Translate SEO Title, Description, Slug', 'translatepress-multilingual' ),
144
- 'extra_upsell_row4' => esc_html__( 'Publish only when translation is complete', 'translatepress-multilingual' ),
145
- 'extra_upsell_row5' => esc_html__( 'Translate by Browsing as User Role', 'translatepress-multilingual' ),
146
- 'extra_upsell_row6' => esc_html__( 'Different Menu Items for each Language', 'translatepress-multilingual' ),
147
- 'extra_upsell_row7' => esc_html__( 'Automatic User Language Detection', 'translatepress-multilingual' ),
148
- 'extra_upsell_row8' => esc_html__( 'Supported By Real People', 'translatepress-multilingual' ),
149
- 'extra_upsell_button' => wp_kses( sprintf( '<a class="button-primary" target="_blank" href="%s">%s</a>', esc_url( trp_add_affiliate_id_to_link( 'https://translatepress.com/pricing/?utm_source=wpbackend&utm_medium=clientsite&utm_content=tpeditor&utm_campaign=tpfree' ) ), __( 'Find Out More', 'translatepress-multilingual' ) ), array( 'a' => [ 'class' => [], 'target' => [], 'href' => [] ] ) ),
150
  // Translation Memory
151
- 'translation_memory_no_suggestions' => esc_html__( 'No available suggestions', 'translatepress-multilingual' ),
152
- 'translation_memory_suggestions' => esc_html__( 'Suggestions from translation memory', 'translatepress-multilingual' ),
153
- 'translation_memory_click_to_copy' => esc_html__( 'Click to Copy', 'translatepress-multilingual' )
154
  );
155
  }
156
 
157
- public function get_help_panel_content() {
 
158
  $edit_icon = TRP_PLUGIN_URL . 'assets/images/edit-icon.png';
159
- return apply_filters( 'trp_help_panel_content', array(
160
  array(
161
- 'title' => esc_html__( 'Quick Intro', 'translatepress-multilingual' ),
162
- 'content' => wp_kses( sprintf( __( 'Hover any text on the page, click <img src="%s" class="trp-edit-icon-inline">, then modify the translation in the sidebar.', 'translatepress-multilingual' ), $edit_icon ),
163
- array( 'img' => array( 'src' => array(), 'class' => array() ) ) ),
164
- 'event' => 'trp_hover_text_help_panel'
165
  ),
166
  array(
167
- 'title' => esc_html__( 'Quick Intro', 'translatepress-multilingual' ),
168
- 'content' => wp_kses( __( 'Don\'t forget to Save Translation. Use keyboard shortcut CTRL(⌘) + S', 'translatepress-multilingual' ), array() ),
169
- 'event' => 'trp_save_translation_help_panel'
170
  ),
171
  array(
172
- 'title' => esc_html__( 'Quick Intro', 'translatepress-multilingual' ),
173
- 'content' => wp_kses( __( 'Switch language to see the translation changes directly on the page.', 'translatepress-multilingual' ), array() ),
174
- 'event' => 'trp_switch_language_help_panel'
175
  ),
176
  array(
177
- 'title' => esc_html__( 'Quick Intro', 'translatepress-multilingual' ),
178
- 'content' => wp_kses( __( 'Search for any text in this page in the dropdown.', 'translatepress-multilingual' ), array() ),
179
- 'event' => 'trp_search_string_help_panel'
180
  )
181
- ) );
182
  }
183
 
184
- public function get_default_editor_user_meta(){
185
- return apply_filters( 'trp_default_editor_user_meta', array(
186
- 'helpPanelOpened' => false,
187
- 'dismissTooltipSave' => false,
188
- 'dismissTooltipNext' => false,
189
- 'dismissTooltipPrevious' => false,
 
190
  'dismissTooltipDismissAll' => false,
191
- ) );
192
  }
193
 
194
- public function get_editor_user_meta() {
195
- $user_meta = get_user_meta( get_current_user_id(), 'trp_editor_user_meta', true );
196
- $user_meta = wp_parse_args( $user_meta, $this->get_default_editor_user_meta() );
197
- return apply_filters( 'trp_editor_user_meta', $user_meta );
 
198
  }
199
 
200
- public function save_editor_user_meta(){
201
- if ( defined( 'DOING_AJAX' ) && DOING_AJAX && current_user_can( apply_filters( 'trp_translating_capability', 'manage_options' ) ) ) {
202
- check_ajax_referer( 'trp_editor_user_meta', 'security' );
203
- if ( isset( $_POST['action'] ) && $_POST['action'] === 'trp_save_editor_user_meta' && !empty( $_POST['user_meta'] ) ) {
204
- $submitted_user_meta = json_decode(stripslashes($_POST['user_meta']), true);
205
- $existing_user_meta = $this->get_editor_user_meta();
206
- foreach( $existing_user_meta as $key => $existing ){
207
- if ( isset( $submitted_user_meta[$key] ) ) {
208
- $existing_user_meta[ $key ] = (bool)$submitted_user_meta[ $key ];
209
- }
210
- }
211
- update_user_meta(get_current_user_id(), 'trp_editor_user_meta', $existing_user_meta );
 
212
  }
213
  }
214
- echo trp_safe_json_encode( array() );
215
  die();
216
  }
217
 
218
- public function string_groups() {
 
219
  $string_groups = array(
220
- 'slugs' => esc_html__( 'Slugs', 'translatepress-multilingual' ),
221
- 'metainformation' => esc_html__( 'Meta Information', 'translatepress-multilingual' ),
222
- 'stringlist' => esc_html__( 'String List', 'translatepress-multilingual' ),
223
- 'gettextstrings' => esc_html__( 'Gettext Strings', 'translatepress-multilingual' ),
224
- 'images' => esc_html__( 'Images', 'translatepress-multilingual' ),
225
- 'dynamicstrings' => esc_html__( 'Dynamically Added Strings', 'translatepress-multilingual' ),
226
  );
227
- return apply_filters( 'trp_string_groups', $string_groups );
228
  }
229
 
230
- public function editor_nonces() {
 
231
  $nonces = array(
232
- 'gettranslationsnonceregular' => wp_create_nonce( 'get_translations' ),
233
- 'savetranslationsnonceregular' => wp_create_nonce( 'save_translations' ),
234
- 'gettranslationsnoncegettext' => wp_create_nonce( 'gettext_get_translations' ),
235
- 'savetranslationsnoncegettext' => wp_create_nonce( 'gettext_save_translations' ),
236
- 'gettranslationsnoncepostslug' => wp_create_nonce( 'postslug_get_translations' ),
237
- 'savetranslationsnoncepostslug' => wp_create_nonce( 'postslug_save_translations' ),
238
- 'splittbnonce' => wp_create_nonce( 'split_translation_block' ),
239
- 'mergetbnonce' => wp_create_nonce( 'merge_translation_block' ),
240
- 'logged_out' => wp_create_nonce( 'trp_view_aslogged_out' . get_current_user_id() ),
241
- 'getsimilarstring' => wp_create_nonce( 'getsimilarstring' ),
242
- 'trp_editor_user_meta' => wp_create_nonce( 'trp_editor_user_meta' )
243
  );
244
 
245
- return apply_filters( 'trp_editor_nonces', $nonces );
246
  }
247
 
248
  /**
@@ -250,24 +262,25 @@ class TRP_Translation_Manager {
250
  *
251
  * @return array
252
  */
253
- public function get_editors_navigation() {
254
- return apply_filters( 'trp_editors_navigation', array(
 
255
  'show' => false,
256
  'tabs' => array(
257
  array(
258
  'handle' => 'visualeditor',
259
- 'label' => __( 'Visual Editor', 'translatepress-multilingual' ),
260
- 'path' => add_query_arg( 'trp-edit-translation', 'true', home_url() ),
261
  'tooltip' => 'Edit translations by visually selecting them on each site page'
262
  ),
263
  array(
264
  'handle' => 'stringtranslation',
265
- 'label' => __( 'String Translation', 'translatepress-multilingual' ),
266
- 'path' => add_query_arg( 'trp-string-translation', 'true', home_url() ) . '#/slugs/',
267
  'tooltip' => 'Edit url slug translations'
268
  )
269
  )
270
- ) );
271
  }
272
 
273
  /**
@@ -275,15 +288,16 @@ class TRP_Translation_Manager {
275
  *
276
  * hooked to trp_translation_manager_footer
277
  */
278
- public function enqueue_scripts_and_styles() {
279
- wp_enqueue_style( 'trp-editor-style', TRP_PLUGIN_URL . 'assets/css/trp-editor.css', array( 'dashicons', 'buttons' ), TRP_PLUGIN_VERSION );
280
- wp_enqueue_script( 'trp-editor', TRP_PLUGIN_URL . 'assets/js/trp-editor.js', array(), TRP_PLUGIN_VERSION );
 
281
 
282
- wp_localize_script( 'trp-editor', 'trp_editor_data', $this->get_trp_editor_data() );
283
 
284
 
285
  // Show upload media dialog in default language
286
- switch_to_locale( $this->settings['default-language'] );
287
  // Necessary for add media button
288
  wp_enqueue_media();
289
 
@@ -294,12 +308,12 @@ class TRP_Translation_Manager {
294
  // Necessary for translate-dom-changes to have a nonce as the same user as the Editor.
295
  // The Preview iframe (which loads translate-dom-changes script) can load as logged out which sets an different nonce
296
  $nonces = $this->editor_nonces();
297
- wp_add_inline_script( 'trp-editor', 'var trp_dynamic_nonce = "' . $nonces['gettranslationsnonceregular'] . '";' );
298
 
299
- $scripts_to_print = apply_filters( 'trp-scripts-for-editor', array( 'jquery', 'jquery-ui-core', 'jquery-effects-core', 'jquery-ui-resizable', 'trp-editor' ) );
300
- $styles_to_print = apply_filters( 'trp-styles-for-editor', array( 'dashicons', 'trp-editor-style', 'media-views', 'imgareaselect', 'buttons' /*'wp-admin', 'common', 'site-icon', 'buttons'*/ ) );
301
- wp_print_scripts( $scripts_to_print );
302
- wp_print_styles( $styles_to_print );
303
 
304
  // Necessary for add media button
305
  print_footer_scripts();
@@ -311,91 +325,93 @@ class TRP_Translation_Manager {
311
  *
312
  * @return array
313
  */
314
- public function get_trp_editor_data() {
 
315
  global $TRP_LANGUAGE;
316
- $trp = TRP_Translate_Press::get_trp_instance();
317
- $trp_languages = $trp->get_component( 'languages' );
318
- $translation_render = $trp->get_component( 'translation_render' );
319
- $url_converter = $trp->get_component( 'url_converter' );
320
 
321
- $language_names = $trp_languages->get_language_names( $this->settings['translation-languages'] );
322
 
323
  // move the current language to the beginning of the array
324
  $translation_languages = $this->settings['translation-languages'];
325
- if ( $TRP_LANGUAGE != $this->settings['default-language'] ) {
326
- $current_language_key = array_search( $TRP_LANGUAGE, $this->settings['translation-languages'] );
327
- unset( $translation_languages[ $current_language_key ] );
328
- $translation_languages = array_merge( array( $TRP_LANGUAGE ), array_values( $translation_languages ) );
329
  }
330
- $default_language_key = array_search( $this->settings['default-language'], $translation_languages );
331
- unset( $translation_languages[ $default_language_key ] );
332
- $ordered_secondary_languages = array_values( $translation_languages );
333
 
334
- $current_language_published = ( in_array( $TRP_LANGUAGE, $this->settings['publish-languages'] ) );
335
- $current_url = $url_converter->cur_page_url();
336
 
337
- $selectors = $translation_render->get_accessors_array( '-' ); // suffix selectors such as array( '-alt', '-src', '-title', '-content', '-value', '-placeholder', '-href', '-outertext', '-innertext' )
338
- $selectors[] = ''; // empty string suffix added for using just the base attribute data-trp-translate-id (instead of data-trp-translate-id-alt)
339
  $data_attributes = $translation_render->get_base_attribute_selectors();
340
 
341
  //setup view_as roles
342
  $view_as_roles = array(
343
- __( 'Current User', 'translatepress-multilingual' ) => 'current_user',
344
- __( 'Logged Out', 'translatepress-multilingual' ) => 'logged_out'
345
  );
346
- $all_roles = wp_roles()->roles;
347
 
348
- if ( !empty( $all_roles ) ) {
349
- foreach ( $all_roles as $role )
350
- $view_as_roles[ $role['name'] ] = '';
351
  }
352
 
353
- $view_as_roles = apply_filters( 'trp_view_as_values', $view_as_roles );
354
- $string_groups = apply_filters( 'trp_string_group_order', array_values( $this->string_groups() ) );
355
 
356
  $flags_path = array();
357
- foreach ( $this->settings['translation-languages'] as $language_code ) {
358
- $default_path = TRP_PLUGIN_URL . 'assets/images/flags/';
359
- $flags_path[ $language_code ] = apply_filters( 'trp_flags_path', $default_path, $language_code );
360
  }
361
 
362
  $editors_navigation = $this->get_editors_navigation();
363
- $string_types = array( 'regular', 'gettext', 'postslug' );
364
 
365
 
366
  $trp_editor_data = array(
367
- 'trp_localized_strings' => $this->localized_text(),
368
- 'trp_settings' => $this->settings,
369
- 'language_names' => $language_names,
370
  'ordered_secondary_languages' => $ordered_secondary_languages,
371
- 'current_language' => $TRP_LANGUAGE,
372
- 'on_screen_language' => ( isset( $ordered_secondary_languages[0] ) ) ? $ordered_secondary_languages[0] : '',
373
- 'view_as_roles' => $view_as_roles,
374
- 'url_to_load' => add_query_arg( 'trp-edit-translation', 'preview', $current_url ),
375
- 'string_selectors' => $selectors,
376
- 'data_attributes' => $data_attributes,
377
- 'editor_nonces' => $this->editor_nonces(),
378
- 'ajax_url' => apply_filters( 'trp_wp_ajax_url', admin_url( 'admin-ajax.php' ) ),
379
- 'string_types' => apply_filters( 'trp_string_types', $string_types ),
380
- 'string_group_order' => $string_groups,
381
- 'merge_rules' => $this->get_merge_rules(),
382
- 'paid_version' => trp_is_paid_version() ? 'true' : 'false',
383
- 'flags_path' => $flags_path,
384
- 'editors_navigation' => $editors_navigation,
385
- 'help_panel_content' => $this->get_help_panel_content(),
386
- 'user_meta' => $this->get_editor_user_meta(),
387
  );
388
 
389
- return apply_filters( 'trp_editor_data', $trp_editor_data );
390
  }
391
 
392
  /**
393
  * Enqueue scripts and styles for translation Editor preview window.
394
  */
395
- public function enqueue_preview_scripts_and_styles() {
396
- if ( $this->conditions_met( 'preview' ) ) {
397
- wp_enqueue_script( 'trp-translation-manager-preview-script', TRP_PLUGIN_URL . 'assets/js/trp-iframe-preview-script.js', array( 'jquery' ), TRP_PLUGIN_VERSION );
398
- wp_enqueue_style( 'trp-preview-iframe-style', TRP_PLUGIN_URL . 'assets/css/trp-preview-iframe-style.css', array( 'dashicons' ), TRP_PLUGIN_VERSION );
 
399
  }
400
  }
401
 
@@ -406,38 +422,39 @@ class TRP_Translation_Manager {
406
  *
407
  * @param $wp_admin_bar
408
  */
409
- public function add_shortcut_to_translation_editor( $wp_admin_bar ) {
410
- if ( !current_user_can( apply_filters( 'trp_translating_capability', 'manage_options' ) ) ) {
 
411
  return;
412
  }
413
 
414
- if ( is_admin() ) {
415
- $url = add_query_arg( 'trp-edit-translation', 'true', trailingslashit( home_url() ) );
416
 
417
- $title = __( 'Translate Site', 'translatepress-multilingual' );
418
  $url_target = '_blank';
419
  } else {
420
 
421
- if ( !$this->url_converter ) {
422
- $trp = TRP_Translate_Press::get_trp_instance();
423
- $this->url_converter = $trp->get_component( 'url_converter' );
424
  }
425
 
426
  $url = $this->url_converter->cur_page_url();
427
 
428
- $url = apply_filters( 'trp_edit_translation_url', add_query_arg( 'trp-edit-translation', 'true', $url ) );
429
 
430
- $title = __( 'Translate Page', 'translatepress-multilingual' );
431
  $url_target = '';
432
  }
433
 
434
  $wp_admin_bar->add_node(
435
  array(
436
- 'id' => 'trp_edit_translation',
437
  'title' => '<span class="ab-icon"></span><span class="ab-label">' . $title . '</span>',
438
- 'href' => $url,
439
- 'meta' => array(
440
- 'class' => 'trp-edit-translation',
441
  'target' => $url_target
442
  )
443
  )
@@ -445,11 +462,11 @@ class TRP_Translation_Manager {
445
 
446
  $wp_admin_bar->add_node(
447
  array(
448
- 'id' => 'trp_settings_page',
449
- 'title' => __( 'Settings', 'translatepress-multilingual' ),
450
- 'href' => admin_url( 'options-general.php?page=translate-press' ),
451
  'parent' => 'trp_edit_translation',
452
- 'meta' => array(
453
  'class' => 'trp-settings-page'
454
  )
455
  )
@@ -462,7 +479,8 @@ class TRP_Translation_Manager {
462
  *
463
  * hooked to admin_head action
464
  */
465
- public function add_styling_to_admin_bar_button() {
 
466
  echo "<style type='text/css'> #wpadminbar #wp-admin-bar-trp_edit_translation .ab-icon:before { content: '\\f326'; top: 3px;}
467
  #wpadminbar #wp-admin-bar-trp_edit_translation > .ab-item {
468
  text-indent: 0;
@@ -482,9 +500,10 @@ class TRP_Translation_Manager {
482
  * @param bool $show_admin_bar TRUE | FALSE
483
  * @return bool
484
  */
485
- public function hide_admin_bar_when_in_editor( $show_admin_bar ) {
 
486
 
487
- if ( $this->conditions_met( 'preview' ) ) {
488
  return false;
489
  }
490
 
@@ -495,24 +514,25 @@ class TRP_Translation_Manager {
495
  /**
496
  * Create a global with the gettext strings that exist in the database
497
  */
498
- public function create_gettext_translated_global() {
 
499
 
500
 
501
  global $trp_translated_gettext_texts;
502
- if ( !is_admin() || $this::is_ajax_on_frontend() ) {
503
  global $TRP_LANGUAGE;
504
 
505
- if ( !$this->trp_query ) {
506
- $trp = TRP_Translate_Press::get_trp_instance();
507
- $this->trp_query = $trp->get_component( 'query' );
508
  }
509
 
510
- $strings = $this->trp_query->get_all_gettext_strings( $TRP_LANGUAGE );
511
- if ( !empty( $strings ) ) {
512
  $trp_translated_gettext_texts = $strings;
513
 
514
- foreach ( $trp_translated_gettext_texts as $key => $value ) {
515
- $trp_strings[ $value['domain'] . '::' . $value['original'] ] = $value;
516
  }
517
  $trp_translated_gettext_texts = $trp_strings;
518
  }
@@ -522,57 +542,61 @@ class TRP_Translation_Manager {
522
  /**
523
  * function that applies the gettext filter on frontend on different hooks depending on what we need
524
  */
525
- public function initialize_gettext_processing() {
 
526
  $is_ajax_on_frontend = $this::is_ajax_on_frontend();
527
 
528
  /* on ajax hooks from frontend that have the init hook ( we found WooCommerce has it ) apply it earlier */
529
- if ( $is_ajax_on_frontend ) {
530
- add_action( 'wp_loaded', array( $this, 'apply_gettext_filter' ) );
531
  } else {//otherwise start from the wp_head hook
532
- add_action( 'wp_head', array( $this, 'apply_gettext_filter' ), 100 );
533
  }
534
 
535
  //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
536
- if ( class_exists( 'WooCommerce' ) && !$is_ajax_on_frontend ) {
537
  // WooCommerce launches some ajax calls before wp_head, so we need to apply_gettext_filter earlier to catch them
538
- add_action( 'wp_loaded', array( $this, 'apply_woocommerce_gettext_filter' ), 19 );
539
  }
540
  }
541
 
542
  /* apply the gettext filter here */
543
- public function apply_gettext_filter() {
 
544
 
545
  //if we have wocommerce installed remove te hook that was added on wp_loaded
546
- if ( class_exists( 'WooCommerce' ) ) {
547
  // WooCommerce launches some ajax calls before wp_head, so we need to apply_gettext_filter earlier to catch them
548
- remove_action( 'wp_loaded', array( $this, 'apply_woocommerce_gettext_filter' ), 19 );
549
  }
550
 
551
  $this->call_gettext_filters();
552
 
553
  }
554
 
555
- public function apply_woocommerce_gettext_filter() {
556
- $this->call_gettext_filters( 'woocommerce_' );
 
557
  }
558
 
559
- public function call_gettext_filters( $prefix = '' ) {
 
560
  global $pagenow;
561
 
562
- if ( !$this->url_converter ) {
563
- $trp = TRP_Translate_Press::get_trp_instance();
564
- $this->url_converter = $trp->get_component( 'url_converter' );
565
  }
566
- if ( $this->is_admin_request === null ) {
567
  $this->is_admin_request = $this->url_converter->is_admin_request();
568
  }
569
 
570
  // 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
571
- if( ( $pagenow != 'wp-login.php' ) && ( !is_admin() || $this::is_ajax_on_frontend() ) && !$this->is_admin_request && $pagenow != 'xmlrpc.php' ) {
572
- add_filter('gettext', array($this, $prefix.'process_gettext_strings'), 100, 3);
573
- add_filter('gettext_with_context', array($this, $prefix.'process_gettext_strings_with_context'), 100, 4);
574
- add_filter('ngettext', array($this, $prefix.'process_ngettext_strings'), 100, 5);
575
- add_filter('ngettext_with_context', array($this, $prefix.'process_ngettext_strings_with_context'), 100, 6);
576
  }
577
  }
578
 
@@ -580,44 +604,45 @@ class TRP_Translation_Manager {
580
  * Function that determines if an ajax request came from the frontend
581
  * @return bool
582
  */
583
- static function is_ajax_on_frontend() {
 
584
 
585
  /* for our own actions return false */
586
- if ( isset( $_REQUEST['action'] ) && strpos( $_REQUEST['action'], 'trp_' ) === 0 )
587
  return false;
588
 
589
- $trp = TRP_Translate_Press::get_trp_instance();
590
- $url_converter = $trp->get_component( "url_converter" );
591
 
592
  //check here for wp ajax or woocommerce ajax
593
- if ( ( defined( 'DOING_AJAX' ) && DOING_AJAX ) || ( defined( 'WC_DOING_AJAX' ) && WC_DOING_AJAX ) ) {
594
  $referer = '';
595
- if ( !empty( $_REQUEST['_wp_http_referer'] ) ) {
596
  // this one is actually REQUEST_URI from the previous page. It's set by the wp_nonce_field() and wp_referer_field()
597
  // confusingly enough, wp_get_referer() basically returns $_SERVER['REQUEST_URL'] from the prev page (not a full URL) or
598
  // $_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)
599
- $referer_uri = wp_unslash( esc_url_raw( $_REQUEST['_wp_http_referer'] ) );
600
- $req_uri = $referer_uri;
601
 
602
- $home_path = trim( parse_url( $url_converter->get_abs_home(), PHP_URL_PATH ), '/' );
603
- $home_path_regex = sprintf( '|^%s|i', preg_quote( $home_path, '|' ) );
604
 
605
  // Trim path info from the end and the leading home path from the front.
606
- $req_uri = ltrim( $req_uri, '/' );
607
- $req_uri = preg_replace( $home_path_regex, '', $req_uri );
608
- $req_uri = trim( $url_converter->get_abs_home(), '/' ) . '/' . ltrim( $req_uri, '/' );
609
 
610
  $referer = $req_uri;
611
 
612
- } elseif ( !empty( $_SERVER['HTTP_REFERER'] ) ) {
613
  // this one is an actual URL that the browser sets.
614
- $referer = wp_unslash( esc_url_raw( $_SERVER['HTTP_REFERER'] ) );
615
 
616
  }
617
 
618
  //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
619
- if ( ( strpos( $referer, admin_url() ) === false ) ) {
620
- TRP_Translation_Manager::set_vars_in_frontend_ajax_request( $referer );
621
  return true;
622
  }
623
  }
@@ -629,31 +654,32 @@ class TRP_Translation_Manager {
629
  * Function that sets the needed vars in the ajax request. Beeing ajax the globals got reset and also the REQUEST globals
630
  * @param $referer
631
  */
632
- static function set_vars_in_frontend_ajax_request( $referer ) {
 
633
 
634
  /* for our own actions don't do nothing */
635
- if ( isset( $_REQUEST['action'] ) && strpos( $_REQUEST['action'], 'trp_' ) === 0 )
636
  return;
637
 
638
  /* if the request came from preview mode make sure to keep it */
639
- if ( strpos( $referer, 'trp-edit-translation=preview' ) !== false && !isset( $_REQUEST['trp-edit-translation'] ) ) {
640
  $_REQUEST['trp-edit-translation'] = 'preview';
641
  }
642
 
643
- if ( strpos( $referer, 'trp-edit-translation=preview' ) !== false && strpos( $referer, 'trp-view-as=' ) !== false && strpos( $referer, 'trp-view-as-nonce=' ) !== false ) {
644
- $parts = parse_url( $referer );
645
- parse_str( $parts['query'], $query );
646
- $_REQUEST['trp-view-as'] = $query['trp-view-as'];
647
  $_REQUEST['trp-view-as-nonce'] = $query['trp-view-as-nonce'];
648
  }
649
 
650
  global $TRP_LANGUAGE;
651
- $trp = TRP_Translate_Press::get_trp_instance();
652
- $url_converter = $trp->get_component( 'url_converter' );
653
- $TRP_LANGUAGE = $url_converter->get_lang_from_url_string( $referer );
654
- if ( empty( $TRP_LANGUAGE ) ) {
655
  $settings_obj = new TRP_Settings();
656
- $settings = $settings_obj->get_settings();
657
  $TRP_LANGUAGE = $settings["default-language"];
658
  }
659
  }
@@ -667,136 +693,137 @@ class TRP_Translation_Manager {
667
  * @param $domain
668
  * @return string
669
  */
670
- public function process_gettext_strings( $translation, $text, $domain ) {
 
671
  // if we have nested gettexts strip previous ones, and consider only the outermost
672
- $text = TRP_Translation_Manager::strip_gettext_tags( $text );
673
- $translation = TRP_Translation_Manager::strip_gettext_tags( $translation );
674
 
675
  //try here to exclude some strings that do not require translation
676
- $excluded_gettext_strings = array( '', ' ', '&hellip;', '&nbsp;', '&raquo;' );
677
- if ( in_array( trp_full_trim( $text ), $excluded_gettext_strings ) )
678
  return $translation;
679
 
680
  //set a global so we remember the last string we processed and if it is the same with the current one return a result immediately for performance reasons ( this could happen in loops )
681
  global $tp_last_gettext_processed;
682
- if ( isset( $tp_last_gettext_processed[ $text . '::' . $domain ] ) )
683
- return $tp_last_gettext_processed[ $text . '::' . $domain ];
684
 
685
  global $TRP_LANGUAGE;
686
 
687
- if ( ( isset( $_REQUEST['trp-edit-translation'] ) && $_REQUEST['trp-edit-translation'] == 'true' ) || $domain == 'translatepress-multilingual' )
688
  return $translation;
689
 
690
  /* for our own actions don't do nothing */
691
- if ( isset( $_REQUEST['action'] ) && strpos( $_REQUEST['action'], 'trp_' ) === 0 )
692
  return $translation;
693
 
694
  /* get_locale() returns WP Settings Language (WPLANG). It might not be a language in TP so it may not have a TP table. */
695
  $current_locale = get_locale();
696
- if ( !in_array( $current_locale, $this->settings['translation-languages'] ) ) {
697
  return $translation;
698
  }
699
 
700
- if ( apply_filters( 'trp_skip_gettext_processing', false, $translation, $text, $domain ) )
701
  return $translation;
702
 
703
  //use a global for is_ajax_on_frontend() so we don't execute it multiple times
704
  global $tp_gettext_is_ajax_on_frontend;
705
- if ( !isset( $tp_gettext_is_ajax_on_frontend ) )
706
  $tp_gettext_is_ajax_on_frontend = $this::is_ajax_on_frontend();
707
 
708
- if ( !defined( 'DOING_AJAX' ) || $tp_gettext_is_ajax_on_frontend ) {
709
- $db_id = '';
710
- $skip_gettext_querying = apply_filters( 'trp_skip_gettext_querying', false, $translation, $text, $domain );
711
- if ( !$skip_gettext_querying ) {
712
  global $trp_translated_gettext_texts, $trp_all_gettext_texts;
713
 
714
  $found_in_db = false;
715
 
716
  /* initiate trp query object */
717
- if ( !$this->trp_query ) {
718
- $trp = TRP_Translate_Press::get_trp_instance();
719
- $this->trp_query = $trp->get_component( 'query' );
720
  }
721
 
722
- if ( !isset( $trp_all_gettext_texts ) ) {
723
  $trp_all_gettext_texts = array();
724
  }
725
 
726
- if ( !empty( $trp_translated_gettext_texts ) ) {
727
- if ( isset( $trp_translated_gettext_texts[ $domain . '::' . $text ] ) ) {
728
- $trp_translated_gettext_text = $trp_translated_gettext_texts[ $domain . '::' . $text ];
729
 
730
- if ( !empty( $trp_translated_gettext_text['translated'] ) && $translation != $trp_translated_gettext_text['translated'] ) {
731
- $translation = str_replace( trim( $text ), $trp_translated_gettext_text['translated'], $text );
732
  }
733
- $db_id = $trp_translated_gettext_text['id'];
734
  $found_in_db = true;
735
  // update the db if a translation appeared in the po file later
736
- if ( empty( $trp_translated_gettext_text['translated'] ) && $translation != $text ) {
737
- $this->trp_query->update_gettext_strings( array(
738
  array(
739
- 'id' => $db_id,
740
- 'original' => $text,
741
  'translated' => $translation,
742
- 'domain' => $domain,
743
- 'status' => $this->trp_query->get_constant_human_reviewed()
744
  )
745
- ), $current_locale );
746
  }
747
  }
748
  }
749
 
750
- if ( !$found_in_db ) {
751
- if ( !in_array( array(
752
- 'original' => $text,
753
  'translated' => $translation,
754
- 'domain' => $domain
755
- ), $trp_all_gettext_texts )
756
  ) {
757
  $trp_all_gettext_texts[] = array(
758
- 'original' => $text,
759
  'translated' => $translation,
760
- 'domain' => $domain
761
  );
762
- $db_id = $this->trp_query->insert_gettext_strings( array(
763
  array(
764
- 'original' => $text,
765
  'translated' => $translation,
766
- 'domain' => $domain
767
  )
768
- ), $current_locale );
769
  /* insert it in the global of translated because now it is in the database */
770
- $trp_translated_gettext_texts[ $domain . '::' . $text ] = array(
771
- 'id' => $db_id,
772
- 'original' => $text,
773
- 'translated' => ( $translation != $text ) ? $translation : '',
774
- 'domain' => $domain
775
  );
776
  }
777
  }
778
 
779
  $trp = TRP_Translate_Press::get_trp_instance();
780
- if ( !$this->machine_translator ) {
781
- $this->machine_translator = $trp->get_component( 'machine_translator' );
782
  }
783
- if ( !$this->trp_languages ) {
784
- $this->trp_languages = $trp->get_component( 'languages' );
785
  }
786
- $machine_translation_codes = $this->trp_languages->get_iso_codes( $this->settings['translation-languages'] );
787
  /* We assume Gettext strings are in English so don't automatically translate into English */
788
- if ( $machine_translation_codes[ $TRP_LANGUAGE ] != 'en' && $this->machine_translator->is_available() ) {
789
  global $trp_gettext_strings_for_machine_translation;
790
- if ( $text == $translation ) {
791
- foreach ( $trp_translated_gettext_texts as $trp_translated_gettext_text ) {
792
- if ( $trp_translated_gettext_text['id'] == $db_id ) {
793
- if ( $trp_translated_gettext_text['translated'] == '' && !isset( $trp_gettext_strings_for_machine_translation[ $db_id ] ) ) {
794
- $trp_gettext_strings_for_machine_translation[ $db_id ] = array(
795
- 'id' => $db_id,
796
- 'original' => $text,
797
  'translated' => '',
798
- 'domain' => $domain,
799
- 'status' => $this->trp_query->get_constant_machine_translated()
800
  );
801
  }
802
  break;
@@ -806,7 +833,7 @@ class TRP_Translation_Manager {
806
  }
807
  }
808
 
809
- $blacklist_functions = apply_filters( 'trp_gettext_blacklist_functions', array(
810
  'wp_enqueue_script',
811
  'wp_enqueue_scripts',
812
  'wp_editor',
@@ -823,38 +850,38 @@ class TRP_Translation_Manager {
823
  'sanitize_title_with_dashes',
824
  'esc_url',
825
  'wc_get_permalink_structure' // make sure we don't touch the woocommerce permalink rewrite slugs that are translated
826
- ), $text, $translation, $domain );
827
 
828
- if ( version_compare( PHP_VERSION, '5.4.0', '>=' ) ) {
829
- $callstack_functions = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 15 );//set a limit if it is supported to improve performance
830
  } else {
831
- $callstack_functions = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS );
832
  }
833
- if ( !empty( $callstack_functions ) ) {
834
- foreach ( $callstack_functions as $callstack_function ) {
835
- if ( in_array( $callstack_function['function'], $blacklist_functions ) ) {
836
- $tp_last_gettext_processed = array( $text . '::' . $domain => $translation );
837
  return $translation;
838
  }
839
 
840
  /* make sure we don't touch the woocommerce process_payment function in WC_Gateway_Stripe. It does a wp_remote_post() call to stripe with localized parameters */
841
- if ( $callstack_function['function'] == 'process_payment' && $callstack_function['class'] == 'WC_Gateway_Stripe' ) {
842
- $tp_last_gettext_processed = array( $text . '::' . $domain => $translation );
843
  return $translation;
844
  }
845
 
846
  }
847
  }
848
- unset( $callstack_functions );//maybe free up some memory
849
 
850
- if ( did_action( 'init' ) ) {
851
- if ( ( !empty( $TRP_LANGUAGE ) && $this->settings["default-language"] != $TRP_LANGUAGE ) || ( isset( $_REQUEST['trp-edit-translation'] ) && $_REQUEST['trp-edit-translation'] == 'preview' ) ) {
852
  //add special start and end tags so that it does not influence html in any way. we will replace them with < and > at the start of the translate function
853
- $translation = apply_filters( 'trp_process_gettext_tags', '#!trpst#trp-gettext data-trpgettextoriginal=' . $db_id . '#!trpen#' . $translation . '#!trpst#/trp-gettext#!trpen#', $translation, $skip_gettext_querying, $text, $domain );
854
  }
855
  }
856
  }
857
- $tp_last_gettext_processed = array( $text . '::' . $domain => $translation );
858
  return $translation;
859
  }
860
 
@@ -865,9 +892,10 @@ class TRP_Translation_Manager {
865
  * @param $domain
866
  * @return string
867
  */
868
- function woocommerce_process_gettext_strings( $translation, $text, $domain ) {
869
- if ( $domain === 'woocommerce' ) {
870
- $translation = $this->process_gettext_strings( $translation, $text, $domain );
 
871
  }
872
  return $translation;
873
  }
@@ -880,17 +908,19 @@ class TRP_Translation_Manager {
880
  * @param $domain
881
  * @return string
882
  */
883
- function process_gettext_strings_with_context( $translation, $text, $context, $domain ) {
884
- $translation = $this->process_gettext_strings( $translation, $text, $domain );
 
885
  return $translation;
886
  }
887
 
888
  /**
889
  * caller for woocommerce domain texts with context
890
  */
891
- function woocommerce_process_gettext_strings_with_context( $translation, $text, $context, $domain ) {
892
- if ( $domain === 'woocommerce' ) {
893
- $translation = $this->process_gettext_strings_with_context( $translation, $text, $context, $domain );
 
894
  }
895
  return $translation;
896
  }
@@ -904,11 +934,12 @@ class TRP_Translation_Manager {
904
  * @param $domain
905
  * @return string
906
  */
907
- function process_ngettext_strings( $translation, $single, $plural, $number, $domain ) {
908
- if ( $number == 1 )
909
- $translation = $this->process_gettext_strings( $translation, $single, $domain );
 
910
  else
911
- $translation = $this->process_gettext_strings( $translation, $plural, $domain );
912
 
913
  return $translation;
914
  }
@@ -916,9 +947,10 @@ class TRP_Translation_Manager {
916
  /**
917
  * caller for woocommerce domain numeric texts
918
  */
919
- function woocommerce_process_ngettext_strings( $translation, $single, $plural, $number, $domain ) {
920
- if ( $domain === 'woocommerce' ) {
921
- $translation = $this->process_ngettext_strings( $translation, $single, $plural, $number, $domain );
 
922
  }
923
 
924
  return $translation;
@@ -934,17 +966,19 @@ class TRP_Translation_Manager {
934
  * @param $domain
935
  * @return string
936
  */
937
- function process_ngettext_strings_with_context( $translation, $single, $plural, $number, $context, $domain ) {
938
- $translation = $this->process_ngettext_strings( $translation, $single, $plural, $number, $domain );
 
939
  return $translation;
940
  }
941
 
942
  /**
943
  * caller for woocommerce domain numeric texts with context
944
  */
945
- function woocommerce_process_ngettext_strings_with_context( $translation, $single, $plural, $number, $context, $domain ) {
946
- if ( $domain === 'woocommerce' ) {
947
- $translation = $this->process_ngettext_strings_with_context( $translation, $single, $plural, $number, $context, $domain );
 
948
  }
949
  return $translation;
950
  }
@@ -952,47 +986,50 @@ class TRP_Translation_Manager {
952
  /**
953
  * function that machine translates gettext strings
954
  */
955
- function machine_translate_gettext() {
 
956
  /* @todo set the original language to detect and also decide if we automatically translate for the default language */
957
  global $TRP_LANGUAGE, $trp_gettext_strings_for_machine_translation;
958
- if ( !empty( $trp_gettext_strings_for_machine_translation ) ) {
959
- if ( !$this->machine_translator ) {
960
- $trp = TRP_Translate_Press::get_trp_instance();
961
- $this->machine_translator = $trp->get_component( 'machine_translator' );
962
  }
963
 
964
  // machine translate new strings
965
- if ( $this->machine_translator->is_available() ) {
966
 
967
  /* Transform associative array into ordered numeric array. We need to keep keys numeric and ordered because $new_strings and $machine_strings depend on it.
968
  * Array was constructed as associative with db ids as keys to avoid duplication.
969
  */
970
- $trp_gettext_strings_for_machine_translation = array_values( $trp_gettext_strings_for_machine_translation );
971
 
972
  $new_strings = array();
973
- foreach ( $trp_gettext_strings_for_machine_translation as $trp_gettext_string_for_machine_translation ) {
974
  $new_strings[] = $trp_gettext_string_for_machine_translation['original'];
975
  }
976
 
977
  // Gettext strings are considered by default to be in the English language
978
- $source_language = apply_filters( 'trp_gettext_source_language', 'en_US', $TRP_LANGUAGE, $new_strings, $trp_gettext_strings_for_machine_translation );
979
- if ( apply_filters( 'trp_gettext_allow_machine_translation', true, $source_language, $TRP_LANGUAGE, $new_strings, $trp_gettext_strings_for_machine_translation ) ) {
980
- $machine_strings = $this->machine_translator->translate( $new_strings, $TRP_LANGUAGE, $source_language );
981
  } else {
982
- $machine_strings = apply_filters( 'trp_gettext_machine_translate_strings', array(), $new_strings, $TRP_LANGUAGE, $trp_gettext_strings_for_machine_translation );
983
  }
984
 
985
  if ( !empty( $machine_strings ) ) {
986
- foreach ( $machine_strings as $key => $machine_string ) {
987
- $trp_gettext_strings_for_machine_translation[ $key ]['translated'] = $machine_string;
 
 
988
  }
989
 
990
- if ( !$this->trp_query ) {
991
- $trp = TRP_Translate_Press::get_trp_instance();
992
- $this->trp_query = $trp->get_component( 'query' );
993
  }
994
 
995
- $this->trp_query->update_gettext_strings( $trp_gettext_strings_for_machine_translation, $TRP_LANGUAGE );
996
  }
997
  }
998
  }
@@ -1003,55 +1040,56 @@ class TRP_Translation_Manager {
1003
  * make sure we remove the trp-gettext wrap from the format the date_i18n receives
1004
  * 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); )
1005
  */
1006
- function handle_date_i18n_function_for_gettext( $j, $dateformatstring, $unixtimestamp, $gmt ) {
 
1007
 
1008
  /* remove trp-gettext wrap */
1009
- $dateformatstring = preg_replace( '/#!trpst#trp-gettext (.*?)#!trpen#/', '', $dateformatstring );
1010
- $dateformatstring = preg_replace( '/#!trpst#(.?)\/trp-gettext#!trpen#/', '', $dateformatstring );
1011
 
1012
 
1013
  global $wp_locale;
1014
  $i = $unixtimestamp;
1015
 
1016
- if ( false === $i ) {
1017
- $i = current_time( 'timestamp', $gmt );
1018
  }
1019
 
1020
- if ( ( !empty( $wp_locale->month ) ) && ( !empty( $wp_locale->weekday ) ) ) {
1021
- $datemonth = $wp_locale->get_month( date( 'm', $i ) );
1022
- $datemonth_abbrev = $wp_locale->get_month_abbrev( $datemonth );
1023
- $dateweekday = $wp_locale->get_weekday( date( 'w', $i ) );
1024
- $dateweekday_abbrev = $wp_locale->get_weekday_abbrev( $dateweekday );
1025
- $datemeridiem = $wp_locale->get_meridiem( date( 'a', $i ) );
1026
- $datemeridiem_capital = $wp_locale->get_meridiem( date( 'A', $i ) );
1027
- $dateformatstring = ' ' . $dateformatstring;
1028
- $dateformatstring = preg_replace( "/([^\\\])D/", "\\1" . backslashit( $dateweekday_abbrev ), $dateformatstring );
1029
- $dateformatstring = preg_replace( "/([^\\\])F/", "\\1" . backslashit( $datemonth ), $dateformatstring );
1030
- $dateformatstring = preg_replace( "/([^\\\])l/", "\\1" . backslashit( $dateweekday ), $dateformatstring );
1031
- $dateformatstring = preg_replace( "/([^\\\])M/", "\\1" . backslashit( $datemonth_abbrev ), $dateformatstring );
1032
- $dateformatstring = preg_replace( "/([^\\\])a/", "\\1" . backslashit( $datemeridiem ), $dateformatstring );
1033
- $dateformatstring = preg_replace( "/([^\\\])A/", "\\1" . backslashit( $datemeridiem_capital ), $dateformatstring );
1034
-
1035
- $dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) - 1 );
1036
  }
1037
- $timezone_formats = array( 'P', 'I', 'O', 'T', 'Z', 'e' );
1038
- $timezone_formats_re = implode( '|', $timezone_formats );
1039
- if ( preg_match( "/$timezone_formats_re/", $dateformatstring ) ) {
1040
- $timezone_string = get_option( 'timezone_string' );
1041
- if ( $timezone_string ) {
1042
- $timezone_object = timezone_open( $timezone_string );
1043
- $date_object = date_create( null, $timezone_object );
1044
- foreach ( $timezone_formats as $timezone_format ) {
1045
- if ( false !== strpos( $dateformatstring, $timezone_format ) ) {
1046
- $formatted = date_format( $date_object, $timezone_format );
1047
  $dateformatstring = ' ' . $dateformatstring;
1048
- $dateformatstring = preg_replace( "/([^\\\])$timezone_format/", "\\1" . backslashit( $formatted ), $dateformatstring );
1049
- $dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) - 1 );
1050
  }
1051
  }
1052
  }
1053
  }
1054
- $j = @date( $dateformatstring, $i );
1055
 
1056
  return $j;
1057
 
@@ -1070,11 +1108,12 @@ class TRP_Translation_Manager {
1070
  * @since 1.3.8
1071
  *
1072
  */
1073
- function trp_strip_gettext_tags_from_esc_url( $good_protocol_url, $original_url, $_context ) {
1074
- if ( strpos( $good_protocol_url, '%20data-trpgettextoriginal=' ) !== false ) {
 
1075
  // first replace %20 with space so that gettext tags can be stripped.
1076
- $good_protocol_url = str_replace( '%20data-trpgettextoriginal=', ' data-trpgettextoriginal=', $good_protocol_url );
1077
- $good_protocol_url = TRP_Translation_Manager::strip_gettext_tags( $good_protocol_url );
1078
  }
1079
 
1080
  return $good_protocol_url;
@@ -1092,16 +1131,17 @@ class TRP_Translation_Manager {
1092
  * @since 1.3.1
1093
  *
1094
  */
1095
- public function trp_sanitize_title( $title, $raw_title, $context ) {
 
1096
  // remove trp_tags before sanitization, because otherwise some characters (#,!,/, spaces ) are stripped later, and it becomes impossible to strip trp-gettext later
1097
- $raw_title = TRP_Translation_Manager::strip_gettext_tags( $raw_title );
1098
 
1099
- if ( 'save' == $context )
1100
- $title = trp_remove_accents( $raw_title );
1101
 
1102
- remove_filter( 'sanitize_title', array( $this, 'trp_sanitize_title' ), 1 );
1103
- $title = apply_filters( 'sanitize_title', $title, $raw_title, $context );
1104
- add_filter( 'sanitize_title', array( $this, 'trp_sanitize_title' ), 1, 3 );
1105
 
1106
  return $title;
1107
  }
@@ -1112,13 +1152,14 @@ class TRP_Translation_Manager {
1112
  * @param $string
1113
  * @return mixed
1114
  */
1115
- static function strip_gettext_tags( $string ) {
1116
- if ( is_string( $string ) && strpos( $string, ' data-trpgettextoriginal=' ) !== false ) {
1117
- $string = preg_replace( '/ data-trpgettextoriginal=\d+#!trpen#/', '', $string );
1118
- $string = str_replace( '#!trpst#trp-gettext', '', $string );
1119
- $string = str_replace( '#!trpst#/trp-gettext', '', $string );
1120
- $string = str_replace( '#!trpst#\/trp-gettext', '', $string );
1121
- $string = str_replace( '#!trpen#', '', $string );
 
1122
  }
1123
 
1124
  return $string;
@@ -1129,9 +1170,10 @@ class TRP_Translation_Manager {
1129
  * @param $classes
1130
  * @return array
1131
  */
1132
- public function add_language_to_body_class( $classes ) {
 
1133
  global $TRP_LANGUAGE;
1134
- if ( !empty( $TRP_LANGUAGE ) ) {
1135
  $classes[] = 'translatepress-' . $TRP_LANGUAGE;
1136
  }
1137
  return $classes;
@@ -1140,28 +1182,29 @@ class TRP_Translation_Manager {
1140
  /**
1141
  * Function that switches the view of the user to other roles
1142
  */
1143
- public function trp_view_as_user() {
1144
- if ( !is_admin() || $this::is_ajax_on_frontend() ) {
1145
- if ( isset( $_REQUEST['trp-edit-translation'] ) && $_REQUEST['trp-edit-translation'] === 'preview' && isset( $_REQUEST['trp-view-as'] ) && isset( $_REQUEST['trp-view-as-nonce'] ) ) {
 
1146
 
1147
- if ( apply_filters( 'trp_allow_translator_role_to_view_page_as_other_roles', true ) ) {
1148
- $current_user_can_change_roles = current_user_can( apply_filters( 'trp_translating_capability', 'manage_options' ) ) || current_user_can( 'manage_options' );
1149
  } else {
1150
- $current_user_can_change_roles = current_user_can( 'manage_options' );
1151
  }
1152
 
1153
- if ( $current_user_can_change_roles ) {
1154
- if ( !wp_verify_nonce( $_REQUEST['trp-view-as-nonce'], 'trp_view_as' . sanitize_text_field( $_REQUEST['trp-view-as'] ) . get_current_user_id() ) ) {
1155
- wp_die( esc_html__( 'Security check', 'translatepress-multilingual' ) );
1156
  } else {
1157
  global $current_user;
1158
- $view_as = sanitize_text_field( $_REQUEST['trp-view-as'] );
1159
- if ( $view_as === 'current_user' ) {
1160
  return;
1161
- } elseif ( $view_as === 'logged_out' ) {
1162
- $current_user = new WP_User( 0, 'trp_logged_out' );
1163
  } else {
1164
- $current_user = apply_filters( 'trp_temporary_change_current_user_role', $current_user, $view_as );
1165
  }
1166
  }
1167
  }
@@ -1179,7 +1222,8 @@ class TRP_Translation_Manager {
1179
  *
1180
  * @return bool
1181
  */
1182
- public function has_bad_characters( $string ) {
 
1183
  $regex = '/
1184
  (
1185
  (?: [\x00-\x7F] # single-byte sequences 0xxxxxxx
@@ -1196,13 +1240,13 @@ class TRP_Translation_Manager {
1196
  ';
1197
 
1198
 
1199
- $regex .= '){1,40} # ...one or more times
1200
  )
1201
  | . # anything else
1202
  /x';
1203
- $stripped_string = preg_replace( $regex, '$1', $string );
1204
 
1205
- if ( $stripped_string === $string ) {
1206
  return false;
1207
  } else {
1208
  return true;
@@ -1220,14 +1264,15 @@ class TRP_Translation_Manager {
1220
  *
1221
  * @return mixed
1222
  */
1223
- public function display_possible_db_errors( $dictionary, $prepared_query, $strings_array ) {
 
1224
  global $trp_editor_notices;
1225
- if ( trp_is_translation_editor( 'preview' ) && is_array( $dictionary ) && count( $dictionary ) === 0 ) {
1226
- if ( $this->has_bad_characters( $prepared_query ) ) {
1227
- $html = "<div class='trp-notice trp-notice-warning'><p class='trp-bad-encoded-strings'>" . __( '<strong>Warning:</strong> Some strings have possibly incorrectly encoded characters. This may result in breaking the queries, rendering the page untranslated in live mode. Consider revising the following strings or their method of outputting.', 'translatepress-multilingual' ) . "</p>";
1228
  $html .= "<ul class='trp-bad-encoded-strings-list'>";
1229
- foreach ( $strings_array as $string ) {
1230
- if ( $this->has_bad_characters( $string ) ) {
1231
  $html .= "<li>" . $string . "</li>";
1232
  }
1233
  }
@@ -1241,4 +1286,28 @@ class TRP_Translation_Manager {
1241
  return $dictionary;
1242
  }
1243
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1244
  }
5
  *
6
  * Handles Front-end Translation Editor, including Ajax requests.
7
  */
8
+ class TRP_Translation_Manager
9
+ {
10
  protected $settings;
11
  /** @var TRP_Translation_Render */
12
  protected $translation_render;
23
  *
24
  * @param array $settings Settings option.
25
  */
26
+ public function __construct($settings)
27
+ {
28
  $this->settings = $settings;
29
  }
30
 
36
  * @param string $mode 'true' | 'preview'
37
  * @return bool Whether current page is part of the Translation Editor.
38
  */
39
+ protected function conditions_met($mode = 'true')
40
+ {
41
+ if (isset($_REQUEST['trp-edit-translation']) && esc_attr($_REQUEST['trp-edit-translation']) == $mode) {
42
+ if (current_user_can(apply_filters('trp_translating_capability', 'manage_options')) && !is_admin()) {
43
  return true;
44
+ } elseif (esc_attr($_REQUEST['trp-edit-translation']) == "preview") {
45
  return true;
46
  } else {
47
  wp_die(
48
+ '<h1>' . esc_html__('Cheatin&#8217; uh?') . '</h1>' .
49
+ '<p>' . esc_html__('Sorry, you are not allowed to access this page.') . '</p>',
50
  403
51
  );
52
  }
62
  * @param string $page_template Current page template.
63
  * @return string Template for translation Editor.
64
  */
65
+ public function translation_editor($page_template)
66
+ {
67
+ if (!$this->conditions_met()) {
68
  return $page_template;
69
  }
70
 
71
  return TRP_PLUGIN_DIR . 'partials/translation-manager.php';
72
  }
73
 
74
+ public function get_merge_rules()
75
+ {
76
  $localized_text = $this->string_groups();
77
 
78
  $merge_rules = array(
79
+ 'top_parents' => array('p', 'div', 'li', 'ol', 'ul', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'body', 'footer', 'article', 'main', 'iframe', 'section', 'figure', 'figcaption', 'blockquote', 'cite', 'tr', 'td', 'th', 'table', 'tbody', 'thead', 'tfoot', 'form'),
80
+ 'self_object_type' => array('translate-press'),
81
+ 'incompatible_siblings' => array('[data-trpgettextoriginal]', '[data-trp-node-group="' . $localized_text['dynamicstrings'] . '"]')
82
  );
83
 
84
+ return apply_filters('trp_merge_rules', $merge_rules);
85
  }
86
 
87
+ public function localized_text()
88
+ {
89
+ $update_seo_add_on = (class_exists('TRP_Seo_Pack') && !defined('TRP_SP_PLUGIN_VERSION'));
90
 
91
  return $this->string_groups() + array(
92
  // attribute names
93
+ 'src' => esc_html__('Image source', 'translatepress-multilingual'),
94
+ 'alt' => esc_html__('Alt attribute', 'translatepress-multilingual'),
95
+ 'title' => esc_html__('Title attribute', 'translatepress-multilingual'),
96
+ 'href' => esc_html__('Anchor link', 'translatepress-multilingual'),
97
+ 'placeholder' => esc_html__('Placeholder attribute', 'translatepress-multilingual'),
98
+ 'submit' => esc_html__('Submit attribute', 'translatepress-multilingual'),
99
+ 'text' => esc_html__('Text', 'translatepress-multilingual'),
100
+
101
+ 'saved' => esc_html__('Saved', 'translatepress-multilingual'),
102
+ 'save_translation' => esc_html__('Save translation', 'translatepress-multilingual'),
103
+ 'saving_translation' => esc_html__('Saving translation...', 'translatepress-multilingual'),
104
+ 'unsaved_changes' => esc_html__('You have unsaved changes!', 'translatepress-multilingual'),
105
+ 'discard' => esc_html__('Discard changes', 'translatepress-multilingual'),
106
+ 'discard_all' => esc_html__('Discard All', 'translatepress-multilingual'),
107
+ 'strings_loading' => esc_attr__('Loading Strings...', 'translatepress-multilingual'),
108
+ 'select_string' => esc_attr__('Select string to translate...', 'translatepress-multilingual'),
109
+ 'close' => esc_attr__('Close Editor', 'translatepress-multilingual'),
110
+ 'from' => esc_html__('From', 'translatepress-multilingual'),
111
+ 'to' => esc_html__('To', 'translatepress-multilingual'),
112
+ 'next' => esc_html__('Next', 'translatepress-multilingual'),
113
+ 'previous' => esc_html__('Previous', 'translatepress-multilingual'),
114
+ 'add_media' => esc_html__('Add Media', 'translatepress-multilingual'),
115
+ 'other_lang' => esc_html__('Other languages', 'translatepress-multilingual'),
116
+ 'view_as' => esc_html__('View As', 'translatepress-multilingual'),
117
+ 'view_as_pro' => esc_html__('Available in our Pro Versions', 'translatepress-multilingual'),
118
 
119
  //wp media upload
120
+ 'select_or_upload' => esc_html__('Select or Upload Media', 'translatepress-multilingual'),
121
+ 'use_this_media' => esc_html__('Use this media', 'translatepress-multilingual'),
122
 
123
  // title attributes
124
+ 'edit' => esc_attr__('Translate', 'translatepress-multilingual'),
125
+ 'merge' => esc_attr__('Translate entire block element', 'translatepress-multilingual'),
126
+ 'split' => esc_attr__('Split block to translate strings individually', 'translatepress-multilingual'),
127
+ 'save_title_attr' => esc_attr__('Save changes to translation. Shortcut: CTRL(⌘) + S', 'translatepress-multilingual'),
128
+ 'next_title_attr' => esc_attr__('Navigate to next string in dropdown list. Shortcut: CTRL(⌘) + ALT + Right Arrow', 'translatepress-multilingual'),
129
+ 'previous_title_attr' => esc_attr__('Navigate to previous string in dropdown list. Shortcut: CTRL(⌘) + ALT + Left Arrow', 'translatepress-multilingual'),
130
+ 'discard_all_title_attr' => esc_attr__('Discard all changes. Shortcut: CTRL(⌘) + ALT + Z', 'translatepress-multilingual'),
131
+ 'discard_individual_changes_title_attribute' => esc_attr__('Discard changes to this text box. To discard changes to all text boxes use shortcut: CTRL(⌘) + ALT + Z', 'translatepress-multilingual'),
132
+ 'dismiss_tooltip_title_attribute' => esc_attr__('Dismiss tooltip', 'translatepress-multilingual'),
133
+ 'quick_intro_title_attribute' => esc_attr__('Quick Intro', 'translatepress-multilingual'),
134
+
135
+ 'split_confirmation' => esc_js(__('Are you sure you want to split this phrase into smaller parts?', 'translatepress-multilingual')),
136
+ 'translation_not_loaded_yet' => wp_kses(__('This string is not ready for translation yet. <br>Try again in a moment...', 'translatepress-multilingual'), array('br' => array())),
137
+
138
+ 'bor_update_notice' => esc_js(__('For this option to work, please update the Browse as other role add-on to the latest version.', 'translatepress-multilingual')),
139
+ 'seo_update_notice' => ($update_seo_add_on) ? esc_js(__('To translate slugs, please update the SEO Pack add-on to the latest version.', 'translatepress-multilingual')) : 'seo_pack_update_not_needed',
140
 
141
  //Notice when the user has not defined a secondary language
142
+ 'extra_lang_row1' => wp_kses(sprintf(__('You can add a new language from <a href="%s">Settings->TranslatePress</a>', 'translatepress-multilingual'), esc_url(admin_url('options-general.php?page=translate-press'))), array('a' => ['href' => []])),
143
+ 'extra_lang_row2' => wp_kses(__('However, you can still use TranslatePress to <strong style="background: #f5fb9d;">modify gettext strings</strong> available in your page.', 'translatepress-multilingual'), array('strong' => ['style' => []])),
144
+ 'extra_lang_row3' => esc_html__('Strings that are user-created cannot be modified, only those from themes and plugins.', 'translatepress-multilingual'),
145
  //Pro version upselling
146
+ 'extra_upsell_title' => esc_html__('Extra Translation Features', 'translatepress-multilingual'),
147
+ 'extra_upsell_row1' => esc_html__('Support for 221 Extra Languages', 'translatepress-multilingual'),
148
+ 'extra_upsell_row2' => esc_html__('Yoast SEO support', 'translatepress-multilingual'),
149
+ 'extra_upsell_row3' => esc_html__('Translate SEO Title, Description, Slug', 'translatepress-multilingual'),
150
+ 'extra_upsell_row4' => esc_html__('Publish only when translation is complete', 'translatepress-multilingual'),
151
+ 'extra_upsell_row5' => esc_html__('Translate by Browsing as User Role', 'translatepress-multilingual'),
152
+ 'extra_upsell_row6' => esc_html__('Different Menu Items for each Language', 'translatepress-multilingual'),
153
+ 'extra_upsell_row7' => esc_html__('Automatic User Language Detection', 'translatepress-multilingual'),
154
+ 'extra_upsell_row8' => esc_html__('Supported By Real People', 'translatepress-multilingual'),
155
+ 'extra_upsell_button' => wp_kses(sprintf('<a class="button-primary" target="_blank" href="%s">%s</a>', esc_url(trp_add_affiliate_id_to_link('https://translatepress.com/pricing/?utm_source=wpbackend&utm_medium=clientsite&utm_content=tpeditor&utm_campaign=tpfree')), __('Find Out More', 'translatepress-multilingual')), array('a' => ['class' => [], 'target' => [], 'href' => []])),
156
  // Translation Memory
157
+ 'translation_memory_no_suggestions' => esc_html__('No available suggestions', 'translatepress-multilingual'),
158
+ 'translation_memory_suggestions' => esc_html__('Suggestions from translation memory', 'translatepress-multilingual'),
159
+ 'translation_memory_click_to_copy' => esc_html__('Click to Copy', 'translatepress-multilingual')
160
  );
161
  }
162
 
163
+ public function get_help_panel_content()
164
+ {
165
  $edit_icon = TRP_PLUGIN_URL . 'assets/images/edit-icon.png';
166
+ return apply_filters('trp_help_panel_content', array(
167
  array(
168
+ 'title' => esc_html__('Quick Intro', 'translatepress-multilingual'),
169
+ 'content' => wp_kses(sprintf(__('Hover any text on the page, click <img src="%s" class="trp-edit-icon-inline">, then modify the translation in the sidebar.', 'translatepress-multilingual'), $edit_icon),
170
+ array('img' => array('src' => array(), 'class' => array()))),
171
+ 'event' => 'trp_hover_text_help_panel'
172
  ),
173
  array(
174
+ 'title' => esc_html__('Quick Intro', 'translatepress-multilingual'),
175
+ 'content' => wp_kses(__('Don\'t forget to Save Translation. Use keyboard shortcut CTRL(⌘) + S', 'translatepress-multilingual'), array()),
176
+ 'event' => 'trp_save_translation_help_panel'
177
  ),
178
  array(
179
+ 'title' => esc_html__('Quick Intro', 'translatepress-multilingual'),
180
+ 'content' => wp_kses(__('Switch language to see the translation changes directly on the page.', 'translatepress-multilingual'), array()),
181
+ 'event' => 'trp_switch_language_help_panel'
182
  ),
183
  array(
184
+ 'title' => esc_html__('Quick Intro', 'translatepress-multilingual'),
185
+ 'content' => wp_kses(__('Search for any text in this page in the dropdown.', 'translatepress-multilingual'), array()),
186
+ 'event' => 'trp_search_string_help_panel'
187
  )
188
+ ));
189
  }
190
 
191
+ public function get_default_editor_user_meta()
192
+ {
193
+ return apply_filters('trp_default_editor_user_meta', array(
194
+ 'helpPanelOpened' => false,
195
+ 'dismissTooltipSave' => false,
196
+ 'dismissTooltipNext' => false,
197
+ 'dismissTooltipPrevious' => false,
198
  'dismissTooltipDismissAll' => false,
199
+ ));
200
  }
201
 
202
+ public function get_editor_user_meta()
203
+ {
204
+ $user_meta = get_user_meta(get_current_user_id(), 'trp_editor_user_meta', true);
205
+ $user_meta = wp_parse_args($user_meta, $this->get_default_editor_user_meta());
206
+ return apply_filters('trp_editor_user_meta', $user_meta);
207
  }
208
 
209
+ public function save_editor_user_meta()
210
+ {
211
+ if (defined('DOING_AJAX') && DOING_AJAX && current_user_can(apply_filters('trp_translating_capability', 'manage_options'))) {
212
+ check_ajax_referer('trp_editor_user_meta', 'security');
213
+ if (isset($_POST['action']) && $_POST['action'] === 'trp_save_editor_user_meta' && !empty($_POST['user_meta'])) {
214
+ $submitted_user_meta = json_decode(stripslashes($_POST['user_meta']), true);
215
+ $existing_user_meta = $this->get_editor_user_meta();
216
+ foreach ($existing_user_meta as $key => $existing) {
217
+ if (isset($submitted_user_meta[$key])) {
218
+ $existing_user_meta[$key] = (bool)$submitted_user_meta[$key];
219
+ }
220
+ }
221
+ update_user_meta(get_current_user_id(), 'trp_editor_user_meta', $existing_user_meta);
222
  }
223
  }
224
+ echo trp_safe_json_encode(array());
225
  die();
226
  }
227
 
228
+ public function string_groups()
229
+ {
230
  $string_groups = array(
231
+ 'slugs' => esc_html__('Slugs', 'translatepress-multilingual'),
232
+ 'metainformation' => esc_html__('Meta Information', 'translatepress-multilingual'),
233
+ 'stringlist' => esc_html__('String List', 'translatepress-multilingual'),
234
+ 'gettextstrings' => esc_html__('Gettext Strings', 'translatepress-multilingual'),
235
+ 'images' => esc_html__('Images', 'translatepress-multilingual'),
236
+ 'dynamicstrings' => esc_html__('Dynamically Added Strings', 'translatepress-multilingual'),
237
  );
238
+ return apply_filters('trp_string_groups', $string_groups);
239
  }
240
 
241
+ public function editor_nonces()
242
+ {
243
  $nonces = array(
244
+ 'gettranslationsnonceregular' => wp_create_nonce('get_translations'),
245
+ 'savetranslationsnonceregular' => wp_create_nonce('save_translations'),
246
+ 'gettranslationsnoncegettext' => wp_create_nonce('gettext_get_translations'),
247
+ 'savetranslationsnoncegettext' => wp_create_nonce('gettext_save_translations'),
248
+ 'gettranslationsnoncepostslug' => wp_create_nonce('postslug_get_translations'),
249
+ 'savetranslationsnoncepostslug' => wp_create_nonce('postslug_save_translations'),
250
+ 'splittbnonce' => wp_create_nonce('split_translation_block'),
251
+ 'mergetbnonce' => wp_create_nonce('merge_translation_block'),
252
+ 'logged_out' => wp_create_nonce('trp_view_aslogged_out' . get_current_user_id()),
253
+ 'getsimilarstring' => wp_create_nonce('getsimilarstring'),
254
+ 'trp_editor_user_meta' => wp_create_nonce('trp_editor_user_meta')
255
  );
256
 
257
+ return apply_filters('trp_editor_nonces', $nonces);
258
  }
259
 
260
  /**
262
  *
263
  * @return array
264
  */
265
+ public function get_editors_navigation()
266
+ {
267
+ return apply_filters('trp_editors_navigation', array(
268
  'show' => false,
269
  'tabs' => array(
270
  array(
271
  'handle' => 'visualeditor',
272
+ 'label' => __('Visual Editor', 'translatepress-multilingual'),
273
+ 'path' => add_query_arg('trp-edit-translation', 'true', home_url()),
274
  'tooltip' => 'Edit translations by visually selecting them on each site page'
275
  ),
276
  array(
277
  'handle' => 'stringtranslation',
278
+ 'label' => __('String Translation', 'translatepress-multilingual'),
279
+ 'path' => add_query_arg('trp-string-translation', 'true', home_url()) . '#/slugs/',
280
  'tooltip' => 'Edit url slug translations'
281
  )
282
  )
283
+ ));
284
  }
285
 
286
  /**
288
  *
289
  * hooked to trp_translation_manager_footer
290
  */
291
+ public function enqueue_scripts_and_styles()
292
+ {
293
+ wp_enqueue_style('trp-editor-style', TRP_PLUGIN_URL . 'assets/css/trp-editor.css', array('dashicons', 'buttons'), TRP_PLUGIN_VERSION);
294
+ wp_enqueue_script('trp-editor', TRP_PLUGIN_URL . 'assets/js/trp-editor.js', array(), TRP_PLUGIN_VERSION);
295
 
296
+ wp_localize_script('trp-editor', 'trp_editor_data', $this->get_trp_editor_data());
297
 
298
 
299
  // Show upload media dialog in default language
300
+ switch_to_locale($this->settings['default-language']);
301
  // Necessary for add media button
302
  wp_enqueue_media();
303
 
308
  // Necessary for translate-dom-changes to have a nonce as the same user as the Editor.
309
  // The Preview iframe (which loads translate-dom-changes script) can load as logged out which sets an different nonce
310
  $nonces = $this->editor_nonces();
311
+ wp_add_inline_script('trp-editor', 'var trp_dynamic_nonce = "' . $nonces['gettranslationsnonceregular'] . '";');
312
 
313
+ $scripts_to_print = apply_filters('trp-scripts-for-editor', array('jquery', 'jquery-ui-core', 'jquery-effects-core', 'jquery-ui-resizable', 'trp-editor'));
314
+ $styles_to_print = apply_filters('trp-styles-for-editor', array('dashicons', 'trp-editor-style', 'media-views', 'imgareaselect', 'buttons' /*'wp-admin', 'common', 'site-icon', 'buttons'*/));
315
+ wp_print_scripts($scripts_to_print);
316
+ wp_print_styles($styles_to_print);
317
 
318
  // Necessary for add media button
319
  print_footer_scripts();
325
  *
326
  * @return array
327
  */
328
+ public function get_trp_editor_data()
329
+ {
330
  global $TRP_LANGUAGE;
331
+ $trp = TRP_Translate_Press::get_trp_instance();
332
+ $trp_languages = $trp->get_component('languages');
333
+ $translation_render = $trp->get_component('translation_render');
334
+ $url_converter = $trp->get_component('url_converter');
335
 
336
+ $language_names = $trp_languages->get_language_names($this->settings['translation-languages']);
337
 
338
  // move the current language to the beginning of the array
339
  $translation_languages = $this->settings['translation-languages'];
340
+ if ($TRP_LANGUAGE != $this->settings['default-language']) {
341
+ $current_language_key = array_search($TRP_LANGUAGE, $this->settings['translation-languages']);
342
+ unset($translation_languages[$current_language_key]);
343
+ $translation_languages = array_merge(array($TRP_LANGUAGE), array_values($translation_languages));
344
  }
345
+ $default_language_key = array_search($this->settings['default-language'], $translation_languages);
346
+ unset($translation_languages[$default_language_key]);
347
+ $ordered_secondary_languages = array_values($translation_languages);
348
 
349
+ $current_language_published = (in_array($TRP_LANGUAGE, $this->settings['publish-languages']));
350
+ $current_url = $url_converter->cur_page_url();
351
 
352
+ $selectors = $translation_render->get_accessors_array('-'); // suffix selectors such as array( '-alt', '-src', '-title', '-content', '-value', '-placeholder', '-href', '-outertext', '-innertext' )
353
+ $selectors[] = ''; // empty string suffix added for using just the base attribute data-trp-translate-id (instead of data-trp-translate-id-alt)
354
  $data_attributes = $translation_render->get_base_attribute_selectors();
355
 
356
  //setup view_as roles
357
  $view_as_roles = array(
358
+ __('Current User', 'translatepress-multilingual') => 'current_user',
359
+ __('Logged Out', 'translatepress-multilingual') => 'logged_out'
360
  );
361
+ $all_roles = wp_roles()->roles;
362
 
363
+ if (!empty($all_roles)) {
364
+ foreach ($all_roles as $role)
365
+ $view_as_roles[$role['name']] = '';
366
  }
367
 
368
+ $view_as_roles = apply_filters('trp_view_as_values', $view_as_roles);
369
+ $string_groups = apply_filters('trp_string_group_order', array_values($this->string_groups()));
370
 
371
  $flags_path = array();
372
+ foreach ($this->settings['translation-languages'] as $language_code) {
373
+ $default_path = TRP_PLUGIN_URL . 'assets/images/flags/';
374
+ $flags_path[$language_code] = apply_filters('trp_flags_path', $default_path, $language_code);
375
  }
376
 
377
  $editors_navigation = $this->get_editors_navigation();
378
+ $string_types = array('regular', 'gettext', 'postslug');
379
 
380
 
381
  $trp_editor_data = array(
382
+ 'trp_localized_strings' => $this->localized_text(),
383
+ 'trp_settings' => $this->settings,
384
+ 'language_names' => $language_names,
385
  'ordered_secondary_languages' => $ordered_secondary_languages,
386
+ 'current_language' => $TRP_LANGUAGE,
387
+ 'on_screen_language' => (isset($ordered_secondary_languages[0])) ? $ordered_secondary_languages[0] : '',
388
+ 'view_as_roles' => $view_as_roles,
389
+ 'url_to_load' => add_query_arg('trp-edit-translation', 'preview', $current_url),
390
+ 'string_selectors' => $selectors,
391
+ 'data_attributes' => $data_attributes,
392
+ 'editor_nonces' => $this->editor_nonces(),
393
+ 'ajax_url' => apply_filters('trp_wp_ajax_url', admin_url('admin-ajax.php')),
394
+ 'string_types' => apply_filters('trp_string_types', $string_types),
395
+ 'string_group_order' => $string_groups,
396
+ 'merge_rules' => $this->get_merge_rules(),
397
+ 'paid_version' => trp_is_paid_version() ? 'true' : 'false',
398
+ 'flags_path' => $flags_path,
399
+ 'editors_navigation' => $editors_navigation,
400
+ 'help_panel_content' => $this->get_help_panel_content(),
401
+ 'user_meta' => $this->get_editor_user_meta(),
402
  );
403
 
404
+ return apply_filters('trp_editor_data', $trp_editor_data);
405
  }
406
 
407
  /**
408
  * Enqueue scripts and styles for translation Editor preview window.
409
  */
410
+ public function enqueue_preview_scripts_and_styles()
411
+ {
412
+ if ($this->conditions_met('preview')) {
413
+ wp_enqueue_script('trp-translation-manager-preview-script', TRP_PLUGIN_URL . 'assets/js/trp-iframe-preview-script.js', array('jquery'), TRP_PLUGIN_VERSION);
414
+ wp_enqueue_style('trp-preview-iframe-style', TRP_PLUGIN_URL . 'assets/css/trp-preview-iframe-style.css', array('dashicons'), TRP_PLUGIN_VERSION);
415
  }
416
  }
417
 
422
  *
423
  * @param $wp_admin_bar
424
  */
425
+ public function add_shortcut_to_translation_editor($wp_admin_bar)
426
+ {
427
+ if (!current_user_can(apply_filters('trp_translating_capability', 'manage_options'))) {
428
  return;
429
  }
430
 
431
+ if (is_admin()) {
432
+ $url = add_query_arg('trp-edit-translation', 'true', trailingslashit(home_url()));
433
 
434
+ $title = __('Translate Site', 'translatepress-multilingual');
435
  $url_target = '_blank';
436
  } else {
437
 
438
+ if (!$this->url_converter) {
439
+ $trp = TRP_Translate_Press::get_trp_instance();
440
+ $this->url_converter = $trp->get_component('url_converter');
441
  }
442
 
443
  $url = $this->url_converter->cur_page_url();
444
 
445
+ $url = apply_filters('trp_edit_translation_url', add_query_arg('trp-edit-translation', 'true', $url));
446
 
447
+ $title = __('Translate Page', 'translatepress-multilingual');
448
  $url_target = '';
449
  }
450
 
451
  $wp_admin_bar->add_node(
452
  array(
453
+ 'id' => 'trp_edit_translation',
454
  'title' => '<span class="ab-icon"></span><span class="ab-label">' . $title . '</span>',
455
+ 'href' => $url,
456
+ 'meta' => array(
457
+ 'class' => 'trp-edit-translation',
458
  'target' => $url_target
459
  )
460
  )
462
 
463
  $wp_admin_bar->add_node(
464
  array(
465
+ 'id' => 'trp_settings_page',
466
+ 'title' => __('Settings', 'translatepress-multilingual'),
467
+ 'href' => admin_url('options-general.php?page=translate-press'),
468
  'parent' => 'trp_edit_translation',
469
+ 'meta' => array(
470
  'class' => 'trp-settings-page'
471
  )
472
  )
479
  *
480
  * hooked to admin_head action
481
  */
482
+ public function add_styling_to_admin_bar_button()
483
+ {
484
  echo "<style type='text/css'> #wpadminbar #wp-admin-bar-trp_edit_translation .ab-icon:before { content: '\\f326'; top: 3px;}
485
  #wpadminbar #wp-admin-bar-trp_edit_translation > .ab-item {
486
  text-indent: 0;
500
  * @param bool $show_admin_bar TRUE | FALSE
501
  * @return bool
502
  */
503
+ public function hide_admin_bar_when_in_editor($show_admin_bar)
504
+ {
505
 
506
+ if ($this->conditions_met('preview')) {
507
  return false;
508
  }
509
 
514
  /**
515
  * Create a global with the gettext strings that exist in the database
516
  */
517
+ public function create_gettext_translated_global()
518
+ {
519
 
520
 
521
  global $trp_translated_gettext_texts;
522
+ if (!is_admin() || $this::is_ajax_on_frontend()) {
523
  global $TRP_LANGUAGE;
524
 
525
+ if (!$this->trp_query) {
526
+ $trp = TRP_Translate_Press::get_trp_instance();
527
+ $this->trp_query = $trp->get_component('query');
528
  }
529
 
530
+ $strings = $this->trp_query->get_all_gettext_strings($TRP_LANGUAGE);
531
+ if (!empty($strings)) {
532
  $trp_translated_gettext_texts = $strings;
533
 
534
+ foreach ($trp_translated_gettext_texts as $key => $value) {
535
+ $trp_strings[$value['domain'] . '::' . $value['original']] = $value;
536
  }
537
  $trp_translated_gettext_texts = $trp_strings;
538
  }
542
  /**
543
  * function that applies the gettext filter on frontend on different hooks depending on what we need
544
  */
545
+ public function initialize_gettext_processing()
546
+ {
547
  $is_ajax_on_frontend = $this::is_ajax_on_frontend();
548
 
549
  /* on ajax hooks from frontend that have the init hook ( we found WooCommerce has it ) apply it earlier */
550
+ if ($is_ajax_on_frontend) {
551
+ add_action('wp_loaded', array($this, 'apply_gettext_filter'));
552
  } else {//otherwise start from the wp_head hook
553
+ add_action('wp_head', array($this, 'apply_gettext_filter'), 100);
554
  }
555
 
556
  //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
557
+ if (class_exists('WooCommerce') && !$is_ajax_on_frontend) {
558
  // WooCommerce launches some ajax calls before wp_head, so we need to apply_gettext_filter earlier to catch them
559
+ add_action('wp_loaded', array($this, 'apply_woocommerce_gettext_filter'), 19);
560
  }
561
  }
562
 
563
  /* apply the gettext filter here */
564
+ public function apply_gettext_filter()
565
+ {
566
 
567
  //if we have wocommerce installed remove te hook that was added on wp_loaded
568
+ if (class_exists('WooCommerce')) {
569
  // WooCommerce launches some ajax calls before wp_head, so we need to apply_gettext_filter earlier to catch them
570
+ remove_action('wp_loaded', array($this, 'apply_woocommerce_gettext_filter'), 19);
571
  }
572
 
573
  $this->call_gettext_filters();
574
 
575
  }
576
 
577
+ public function apply_woocommerce_gettext_filter()
578
+ {
579
+ $this->call_gettext_filters('woocommerce_');
580
  }
581
 
582
+ public function call_gettext_filters($prefix = '')
583
+ {
584
  global $pagenow;
585
 
586
+ if (!$this->url_converter) {
587
+ $trp = TRP_Translate_Press::get_trp_instance();
588
+ $this->url_converter = $trp->get_component('url_converter');
589
  }
590
+ if ($this->is_admin_request === null) {
591
  $this->is_admin_request = $this->url_converter->is_admin_request();
592
  }
593
 
594
  // 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
595
+ if (($pagenow != 'wp-login.php') && (!is_admin() || $this::is_ajax_on_frontend()) && !$this->is_admin_request && $pagenow != 'xmlrpc.php') {
596
+ add_filter('gettext', array($this, $prefix . 'process_gettext_strings'), 100, 3);
597
+ add_filter('gettext_with_context', array($this, $prefix . 'process_gettext_strings_with_context'), 100, 4);
598
+ add_filter('ngettext', array($this, $prefix . 'process_ngettext_strings'), 100, 5);
599
+ add_filter('ngettext_with_context', array($this, $prefix . 'process_ngettext_strings_with_context'), 100, 6);
600
  }
601
  }
602
 
604
  * Function that determines if an ajax request came from the frontend
605
  * @return bool
606
  */
607
+ static function is_ajax_on_frontend()
608
+ {
609
 
610
  /* for our own actions return false */
611
+ if (isset($_REQUEST['action']) && strpos($_REQUEST['action'], 'trp_') === 0)
612
  return false;
613
 
614
+ $trp = TRP_Translate_Press::get_trp_instance();
615
+ $url_converter = $trp->get_component("url_converter");
616
 
617
  //check here for wp ajax or woocommerce ajax
618
+ if ((defined('DOING_AJAX') && DOING_AJAX) || (defined('WC_DOING_AJAX') && WC_DOING_AJAX)) {
619
  $referer = '';
620
+ if (!empty($_REQUEST['_wp_http_referer'])) {
621
  // this one is actually REQUEST_URI from the previous page. It's set by the wp_nonce_field() and wp_referer_field()
622
  // confusingly enough, wp_get_referer() basically returns $_SERVER['REQUEST_URL'] from the prev page (not a full URL) or
623
  // $_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)
624
+ $referer_uri = wp_unslash(esc_url_raw($_REQUEST['_wp_http_referer']));
625
+ $req_uri = $referer_uri;
626
 
627
+ $home_path = trim(parse_url($url_converter->get_abs_home(), PHP_URL_PATH), '/');
628
+ $home_path_regex = sprintf('|^%s|i', preg_quote($home_path, '|'));
629
 
630
  // Trim path info from the end and the leading home path from the front.
631
+ $req_uri = ltrim($req_uri, '/');
632
+ $req_uri = preg_replace($home_path_regex, '', $req_uri);
633
+ $req_uri = trim($url_converter->get_abs_home(), '/') . '/' . ltrim($req_uri, '/');
634
 
635
  $referer = $req_uri;
636
 
637
+ } elseif (!empty($_SERVER['HTTP_REFERER'])) {
638
  // this one is an actual URL that the browser sets.
639
+ $referer = wp_unslash(esc_url_raw($_SERVER['HTTP_REFERER']));
640
 
641
  }
642
 
643
  //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
644
+ if ((strpos($referer, admin_url()) === false)) {
645
+ TRP_Translation_Manager::set_vars_in_frontend_ajax_request($referer);
646
  return true;
647
  }
648
  }
654
  * Function that sets the needed vars in the ajax request. Beeing ajax the globals got reset and also the REQUEST globals
655
  * @param $referer
656
  */
657
+ static function set_vars_in_frontend_ajax_request($referer)
658
+ {
659
 
660
  /* for our own actions don't do nothing */
661
+ if (isset($_REQUEST['action']) && strpos($_REQUEST['action'], 'trp_') === 0)
662
  return;
663
 
664
  /* if the request came from preview mode make sure to keep it */
665
+ if (strpos($referer, 'trp-edit-translation=preview') !== false && !isset($_REQUEST['trp-edit-translation'])) {
666
  $_REQUEST['trp-edit-translation'] = 'preview';
667
  }
668
 
669
+ if (strpos($referer, 'trp-edit-translation=preview') !== false && strpos($referer, 'trp-view-as=') !== false && strpos($referer, 'trp-view-as-nonce=') !== false) {
670
+ $parts = parse_url($referer);
671
+ parse_str($parts['query'], $query);
672
+ $_REQUEST['trp-view-as'] = $query['trp-view-as'];
673
  $_REQUEST['trp-view-as-nonce'] = $query['trp-view-as-nonce'];
674
  }
675
 
676
  global $TRP_LANGUAGE;
677
+ $trp = TRP_Translate_Press::get_trp_instance();
678
+ $url_converter = $trp->get_component('url_converter');
679
+ $TRP_LANGUAGE = $url_converter->get_lang_from_url_string($referer);
680
+ if (empty($TRP_LANGUAGE)) {
681
  $settings_obj = new TRP_Settings();
682
+ $settings = $settings_obj->get_settings();
683
  $TRP_LANGUAGE = $settings["default-language"];
684
  }
685
  }
693
  * @param $domain
694
  * @return string
695
  */
696
+ public function process_gettext_strings($translation, $text, $domain)
697
+ {
698
  // if we have nested gettexts strip previous ones, and consider only the outermost
699
+ $text = TRP_Translation_Manager::strip_gettext_tags($text);
700
+ $translation = TRP_Translation_Manager::strip_gettext_tags($translation);
701
 
702
  //try here to exclude some strings that do not require translation
703
+ $excluded_gettext_strings = array('', ' ', '&hellip;', '&nbsp;', '&raquo;');
704
+ if (in_array(trp_full_trim($text), $excluded_gettext_strings))
705
  return $translation;
706
 
707
  //set a global so we remember the last string we processed and if it is the same with the current one return a result immediately for performance reasons ( this could happen in loops )
708
  global $tp_last_gettext_processed;
709
+ if (isset($tp_last_gettext_processed[$text . '::' . $domain]))
710
+ return $tp_last_gettext_processed[$text . '::' . $domain];
711
 
712
  global $TRP_LANGUAGE;
713
 
714
+ if ((isset($_REQUEST['trp-edit-translation']) && $_REQUEST['trp-edit-translation'] == 'true') || $domain == 'translatepress-multilingual')
715
  return $translation;
716
 
717
  /* for our own actions don't do nothing */
718
+ if (isset($_REQUEST['action']) && strpos($_REQUEST['action'], 'trp_') === 0)
719
  return $translation;
720
 
721
  /* get_locale() returns WP Settings Language (WPLANG). It might not be a language in TP so it may not have a TP table. */
722
  $current_locale = get_locale();
723
+ if (!in_array($current_locale, $this->settings['translation-languages'])) {
724
  return $translation;
725
  }
726
 
727
+ if (apply_filters('trp_skip_gettext_processing', false, $translation, $text, $domain))
728
  return $translation;
729
 
730
  //use a global for is_ajax_on_frontend() so we don't execute it multiple times
731
  global $tp_gettext_is_ajax_on_frontend;
732
+ if (!isset($tp_gettext_is_ajax_on_frontend))
733
  $tp_gettext_is_ajax_on_frontend = $this::is_ajax_on_frontend();
734
 
735
+ if (!defined('DOING_AJAX') || $tp_gettext_is_ajax_on_frontend) {
736
+ $db_id = '';
737
+ $skip_gettext_querying = apply_filters('trp_skip_gettext_querying', false, $translation, $text, $domain);
738
+ if (!$skip_gettext_querying) {
739
  global $trp_translated_gettext_texts, $trp_all_gettext_texts;
740
 
741
  $found_in_db = false;
742
 
743
  /* initiate trp query object */
744
+ if (!$this->trp_query) {
745
+ $trp = TRP_Translate_Press::get_trp_instance();
746
+ $this->trp_query = $trp->get_component('query');
747
  }
748
 
749
+ if (!isset($trp_all_gettext_texts)) {
750
  $trp_all_gettext_texts = array();
751
  }
752
 
753
+ if (!empty($trp_translated_gettext_texts)) {
754
+ if (isset($trp_translated_gettext_texts[$domain . '::' . $text])) {
755
+ $trp_translated_gettext_text = $trp_translated_gettext_texts[$domain . '::' . $text];
756
 
757
+ if (!empty($trp_translated_gettext_text['translated']) && $translation != $trp_translated_gettext_text['translated']) {
758
+ $translation = str_replace(trim($text), $trp_translated_gettext_text['translated'], $text);
759
  }
760
+ $db_id = $trp_translated_gettext_text['id'];
761
  $found_in_db = true;
762
  // update the db if a translation appeared in the po file later
763
+ if (empty($trp_translated_gettext_text['translated']) && $translation != $text) {
764
+ $this->trp_query->update_gettext_strings(array(
765
  array(
766
+ 'id' => $db_id,
767
+ 'original' => $text,
768
  'translated' => $translation,
769
+ 'domain' => $domain,
770
+ 'status' => $this->trp_query->get_constant_human_reviewed()
771
  )
772
+ ), $current_locale);
773
  }
774
  }
775
  }
776
 
777
+ if (!$found_in_db) {
778
+ if (!in_array(array(
779
+ 'original' => $text,
780
  'translated' => $translation,
781
+ 'domain' => $domain
782
+ ), $trp_all_gettext_texts)
783
  ) {
784
  $trp_all_gettext_texts[] = array(
785
+ 'original' => $text,
786
  'translated' => $translation,
787
+ 'domain' => $domain
788
  );
789
+ $db_id = $this->trp_query->insert_gettext_strings(array(
790
  array(
791
+ 'original' => $text,
792
  'translated' => $translation,
793
+ 'domain' => $domain
794
  )
795
+ ), $current_locale);
796
  /* insert it in the global of translated because now it is in the database */
797
+ $trp_translated_gettext_texts[$domain . '::' . $text] = array(
798
+ 'id' => $db_id,
799
+ 'original' => $text,
800
+ 'translated' => ($translation != $text) ? $translation : '',
801
+ 'domain' => $domain
802
  );
803
  }
804
  }
805
 
806
  $trp = TRP_Translate_Press::get_trp_instance();
807
+ if (!$this->machine_translator) {
808
+ $this->machine_translator = $trp->get_component('machine_translator');
809
  }
810
+ if (!$this->trp_languages) {
811
+ $this->trp_languages = $trp->get_component('languages');
812
  }
813
+ $machine_translation_codes = $this->trp_languages->get_iso_codes($this->settings['translation-languages']);
814
  /* We assume Gettext strings are in English so don't automatically translate into English */
815
+ if ($machine_translation_codes[$TRP_LANGUAGE] != 'en' && $this->machine_translator->is_available()) {
816
  global $trp_gettext_strings_for_machine_translation;
817
+ if ($text == $translation) {
818
+ foreach ($trp_translated_gettext_texts as $trp_translated_gettext_text) {
819
+ if ($trp_translated_gettext_text['id'] == $db_id) {
820
+ if ($trp_translated_gettext_text['translated'] == '' && !isset($trp_gettext_strings_for_machine_translation[$db_id])) {
821
+ $trp_gettext_strings_for_machine_translation[$db_id] = array(
822
+ 'id' => $db_id,
823
+ 'original' => $text,
824
  'translated' => '',
825
+ 'domain' => $domain,
826
+ 'status' => $this->trp_query->get_constant_machine_translated()
827
  );
828
  }
829
  break;
833
  }
834
  }
835
 
836
+ $blacklist_functions = apply_filters('trp_gettext_blacklist_functions', array(
837
  'wp_enqueue_script',
838
  'wp_enqueue_scripts',
839
  'wp_editor',
850
  'sanitize_title_with_dashes',
851
  'esc_url',
852
  'wc_get_permalink_structure' // make sure we don't touch the woocommerce permalink rewrite slugs that are translated
853
+ ), $text, $translation, $domain);
854
 
855
+ if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
856
+ $callstack_functions = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 15);//set a limit if it is supported to improve performance
857
  } else {
858
+ $callstack_functions = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
859
  }
860
+ if (!empty($callstack_functions)) {
861
+ foreach ($callstack_functions as $callstack_function) {
862
+ if (in_array($callstack_function['function'], $blacklist_functions)) {
863
+ $tp_last_gettext_processed = array($text . '::' . $domain => $translation);
864
  return $translation;
865
  }
866
 
867
  /* make sure we don't touch the woocommerce process_payment function in WC_Gateway_Stripe. It does a wp_remote_post() call to stripe with localized parameters */
868
+ if ($callstack_function['function'] == 'process_payment' && $callstack_function['class'] == 'WC_Gateway_Stripe') {
869
+ $tp_last_gettext_processed = array($text . '::' . $domain => $translation);
870
  return $translation;
871
  }
872
 
873
  }
874
  }
875
+ unset($callstack_functions);//maybe free up some memory
876
 
877
+ if (did_action('init')) {
878
+ if ((!empty($TRP_LANGUAGE) && $this->settings["default-language"] != $TRP_LANGUAGE) || (isset($_REQUEST['trp-edit-translation']) && $_REQUEST['trp-edit-translation'] == 'preview')) {
879
  //add special start and end tags so that it does not influence html in any way. we will replace them with < and > at the start of the translate function
880
+ $translation = apply_filters('trp_process_gettext_tags', '#!trpst#trp-gettext data-trpgettextoriginal=' . $db_id . '#!trpen#' . $translation . '#!trpst#/trp-gettext#!trpen#', $translation, $skip_gettext_querying, $text, $domain);
881
  }
882
  }
883
  }
884
+ $tp_last_gettext_processed = array($text . '::' . $domain => $translation);
885
  return $translation;
886
  }
887
 
892
  * @param $domain
893
  * @return string
894
  */
895
+ function woocommerce_process_gettext_strings($translation, $text, $domain)
896
+ {
897
+ if ($domain === 'woocommerce') {
898
+ $translation = $this->process_gettext_strings($translation, $text, $domain);
899
  }
900
  return $translation;
901
  }
908
  * @param $domain
909
  * @return string
910
  */
911
+ function process_gettext_strings_with_context($translation, $text, $context, $domain)
912
+ {
913
+ $translation = $this->process_gettext_strings($translation, $text, $domain);
914
  return $translation;
915
  }
916
 
917
  /**
918
  * caller for woocommerce domain texts with context
919
  */
920
+ function woocommerce_process_gettext_strings_with_context($translation, $text, $context, $domain)
921
+ {
922
+ if ($domain === 'woocommerce') {
923
+ $translation = $this->process_gettext_strings_with_context($translation, $text, $context, $domain);
924
  }
925
  return $translation;
926
  }
934
  * @param $domain
935
  * @return string
936
  */
937
+ function process_ngettext_strings($translation, $single, $plural, $number, $domain)
938
+ {
939
+ if ($number == 1)
940
+ $translation = $this->process_gettext_strings($translation, $single, $domain);
941
  else
942
+ $translation = $this->process_gettext_strings($translation, $plural, $domain);
943
 
944
  return $translation;
945
  }
947
  /**
948
  * caller for woocommerce domain numeric texts
949
  */
950
+ function woocommerce_process_ngettext_strings($translation, $single, $plural, $number, $domain)
951
+ {
952
+ if ($domain === 'woocommerce') {
953
+ $translation = $this->process_ngettext_strings($translation, $single, $plural, $number, $domain);
954
  }
955
 
956
  return $translation;
966
  * @param $domain
967
  * @return string
968
  */
969
+ function process_ngettext_strings_with_context($translation, $single, $plural, $number, $context, $domain)
970
+ {
971
+ $translation = $this->process_ngettext_strings($translation, $single, $plural, $number, $domain);
972
  return $translation;
973
  }
974
 
975
  /**
976
  * caller for woocommerce domain numeric texts with context
977
  */
978
+ function woocommerce_process_ngettext_strings_with_context($translation, $single, $plural, $number, $context, $domain)
979
+ {
980
+ if ($domain === 'woocommerce') {
981
+ $translation = $this->process_ngettext_strings_with_context($translation, $single, $plural, $number, $context, $domain);
982
  }
983
  return $translation;
984
  }
986
  /**
987
  * function that machine translates gettext strings
988
  */
989
+ function machine_translate_gettext()
990
+ {
991
  /* @todo set the original language to detect and also decide if we automatically translate for the default language */
992
  global $TRP_LANGUAGE, $trp_gettext_strings_for_machine_translation;
993
+ if (!empty($trp_gettext_strings_for_machine_translation)) {
994
+ if (!$this->machine_translator) {
995
+ $trp = TRP_Translate_Press::get_trp_instance();
996
+ $this->machine_translator = $trp->get_component('machine_translator');
997
  }
998
 
999
  // machine translate new strings
1000
+ if ($this->machine_translator->is_available()) {
1001
 
1002
  /* Transform associative array into ordered numeric array. We need to keep keys numeric and ordered because $new_strings and $machine_strings depend on it.
1003
  * Array was constructed as associative with db ids as keys to avoid duplication.
1004
  */
1005
+ $trp_gettext_strings_for_machine_translation = array_values($trp_gettext_strings_for_machine_translation);
1006
 
1007
  $new_strings = array();
1008
+ foreach ($trp_gettext_strings_for_machine_translation as $trp_gettext_string_for_machine_translation) {
1009
  $new_strings[] = $trp_gettext_string_for_machine_translation['original'];
1010
  }
1011
 
1012
  // Gettext strings are considered by default to be in the English language
1013
+ $source_language = apply_filters('trp_gettext_source_language', 'en_US', $TRP_LANGUAGE, $new_strings, $trp_gettext_strings_for_machine_translation);
1014
+ if (apply_filters('trp_gettext_allow_machine_translation', true, $source_language, $TRP_LANGUAGE, $new_strings, $trp_gettext_strings_for_machine_translation)) {
1015
+ $machine_strings = $this->machine_translator->translate($new_strings, $TRP_LANGUAGE, $source_language);
1016
  } else {
1017
+ $machine_strings = apply_filters('trp_gettext_machine_translate_strings', array(), $new_strings, $TRP_LANGUAGE, $trp_gettext_strings_for_machine_translation);
1018
  }
1019
 
1020
  if ( !empty( $machine_strings ) ) {
1021
+ foreach ( $new_strings as $key => $new_string ) {
1022
+ if (isset($machine_strings[ $new_string ])) {
1023
+ $trp_gettext_strings_for_machine_translation[ $key ]['translated'] = $machine_strings[ $new_string ];
1024
+ }
1025
  }
1026
 
1027
+ if (!$this->trp_query) {
1028
+ $trp = TRP_Translate_Press::get_trp_instance();
1029
+ $this->trp_query = $trp->get_component('query');
1030
  }
1031
 
1032
+ $this->trp_query->update_gettext_strings($trp_gettext_strings_for_machine_translation, $TRP_LANGUAGE);
1033
  }
1034
  }
1035
  }
1040
  * make sure we remove the trp-gettext wrap from the format the date_i18n receives
1041
  * 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); )
1042
  */
1043
+ function handle_date_i18n_function_for_gettext($j, $dateformatstring, $unixtimestamp, $gmt)
1044
+ {
1045
 
1046
  /* remove trp-gettext wrap */
1047
+ $dateformatstring = preg_replace('/#!trpst#trp-gettext (.*?)#!trpen#/', '', $dateformatstring);
1048
+ $dateformatstring = preg_replace('/#!trpst#(.?)\/trp-gettext#!trpen#/', '', $dateformatstring);
1049
 
1050
 
1051
  global $wp_locale;
1052
  $i = $unixtimestamp;
1053
 
1054
+ if (false === $i) {
1055
+ $i = current_time('timestamp', $gmt);
1056
  }
1057
 
1058
+ if ((!empty($wp_locale->month)) && (!empty($wp_locale->weekday))) {
1059
+ $datemonth = $wp_locale->get_month(date('m', $i));
1060
+ $datemonth_abbrev = $wp_locale->get_month_abbrev($datemonth);
1061
+ $dateweekday = $wp_locale->get_weekday(date('w', $i));
1062
+ $dateweekday_abbrev = $wp_locale->get_weekday_abbrev($dateweekday);
1063
+ $datemeridiem = $wp_locale->get_meridiem(date('a', $i));
1064
+ $datemeridiem_capital = $wp_locale->get_meridiem(date('A', $i));
1065
+ $dateformatstring = ' ' . $dateformatstring;
1066
+ $dateformatstring = preg_replace("/([^\\\])D/", "\\1" . backslashit($dateweekday_abbrev), $dateformatstring);
1067
+ $dateformatstring = preg_replace("/([^\\\])F/", "\\1" . backslashit($datemonth), $dateformatstring);
1068
+ $dateformatstring = preg_replace("/([^\\\])l/", "\\1" . backslashit($dateweekday), $dateformatstring);
1069
+ $dateformatstring = preg_replace("/([^\\\])M/", "\\1" . backslashit($datemonth_abbrev), $dateformatstring);
1070
+ $dateformatstring = preg_replace("/([^\\\])a/", "\\1" . backslashit($datemeridiem), $dateformatstring);
1071
+ $dateformatstring = preg_replace("/([^\\\])A/", "\\1" . backslashit($datemeridiem_capital), $dateformatstring);
1072
+
1073
+ $dateformatstring = substr($dateformatstring, 1, strlen($dateformatstring) - 1);
1074
  }
1075
+ $timezone_formats = array('P', 'I', 'O', 'T', 'Z', 'e');
1076
+ $timezone_formats_re = implode('|', $timezone_formats);
1077
+ if (preg_match("/$timezone_formats_re/", $dateformatstring)) {
1078
+ $timezone_string = get_option('timezone_string');
1079
+ if ($timezone_string) {
1080
+ $timezone_object = timezone_open($timezone_string);
1081
+ $date_object = date_create(null, $timezone_object);
1082
+ foreach ($timezone_formats as $timezone_format) {
1083
+ if (false !== strpos($dateformatstring, $timezone_format)) {
1084
+ $formatted = date_format($date_object, $timezone_format);
1085
  $dateformatstring = ' ' . $dateformatstring;
1086
+ $dateformatstring = preg_replace("/([^\\\])$timezone_format/", "\\1" . backslashit($formatted), $dateformatstring);
1087
+ $dateformatstring = substr($dateformatstring, 1, strlen($dateformatstring) - 1);
1088
  }
1089
  }
1090
  }
1091
  }
1092
+ $j = @date($dateformatstring, $i);
1093
 
1094
  return $j;
1095
 
1108
  * @since 1.3.8
1109
  *
1110
  */
1111
+ function trp_strip_gettext_tags_from_esc_url($good_protocol_url, $original_url, $_context)
1112
+ {
1113
+ if (strpos($good_protocol_url, '%20data-trpgettextoriginal=') !== false) {
1114
  // first replace %20 with space so that gettext tags can be stripped.
1115
+ $good_protocol_url = str_replace('%20data-trpgettextoriginal=', ' data-trpgettextoriginal=', $good_protocol_url);
1116
+ $good_protocol_url = TRP_Translation_Manager::strip_gettext_tags($good_protocol_url);
1117
  }
1118
 
1119
  return $good_protocol_url;
1131
  * @since 1.3.1
1132
  *
1133
  */
1134
+ public function trp_sanitize_title($title, $raw_title, $context)
1135
+ {
1136
  // remove trp_tags before sanitization, because otherwise some characters (#,!,/, spaces ) are stripped later, and it becomes impossible to strip trp-gettext later
1137
+ $raw_title = TRP_Translation_Manager::strip_gettext_tags($raw_title);
1138
 
1139
+ if ('save' == $context)
1140
+ $title = trp_remove_accents($raw_title);
1141
 
1142
+ remove_filter('sanitize_title', array($this, 'trp_sanitize_title'), 1);
1143
+ $title = apply_filters('sanitize_title', $title, $raw_title, $context);
1144
+ add_filter('sanitize_title', array($this, 'trp_sanitize_title'), 1, 3);
1145
 
1146
  return $title;
1147
  }
1152
  * @param $string
1153
  * @return mixed
1154
  */
1155
+ static function strip_gettext_tags($string)
1156
+ {
1157
+ if (is_string($string) && strpos($string, ' data-trpgettextoriginal=') !== false) {
1158
+ $string = preg_replace('/ data-trpgettextoriginal=\d+#!trpen#/', '', $string);
1159
+ $string = str_replace('#!trpst#trp-gettext', '', $string);
1160
+ $string = str_replace('#!trpst#/trp-gettext', '', $string);
1161
+ $string = str_replace('#!trpst#\/trp-gettext', '', $string);
1162
+ $string = str_replace('#!trpen#', '', $string);
1163
  }
1164
 
1165
  return $string;
1170
  * @param $classes
1171
  * @return array
1172
  */
1173
+ public function add_language_to_body_class($classes)
1174
+ {
1175
  global $TRP_LANGUAGE;
1176
+ if (!empty($TRP_LANGUAGE)) {
1177
  $classes[] = 'translatepress-' . $TRP_LANGUAGE;
1178
  }
1179
  return $classes;
1182
  /**
1183
  * Function that switches the view of the user to other roles
1184
  */
1185
+ public function trp_view_as_user()
1186
+ {
1187
+ if (!is_admin() || $this::is_ajax_on_frontend()) {
1188
+ if (isset($_REQUEST['trp-edit-translation']) && $_REQUEST['trp-edit-translation'] === 'preview' && isset($_REQUEST['trp-view-as']) && isset($_REQUEST['trp-view-as-nonce'])) {
1189
 
1190
+ if (apply_filters('trp_allow_translator_role_to_view_page_as_other_roles', true)) {
1191
+ $current_user_can_change_roles = current_user_can(apply_filters('trp_translating_capability', 'manage_options')) || current_user_can('manage_options');
1192
  } else {
1193
+ $current_user_can_change_roles = current_user_can('manage_options');
1194
  }
1195
 
1196
+ if ($current_user_can_change_roles) {
1197
+ if (!wp_verify_nonce($_REQUEST['trp-view-as-nonce'], 'trp_view_as' . sanitize_text_field($_REQUEST['trp-view-as']) . get_current_user_id())) {
1198
+ wp_die(esc_html__('Security check', 'translatepress-multilingual'));
1199
  } else {
1200
  global $current_user;
1201
+ $view_as = sanitize_text_field($_REQUEST['trp-view-as']);
1202
+ if ($view_as === 'current_user') {
1203
  return;
1204
+ } elseif ($view_as === 'logged_out') {
1205
+ $current_user = new WP_User(0, 'trp_logged_out');
1206
  } else {
1207
+ $current_user = apply_filters('trp_temporary_change_current_user_role', $current_user, $view_as);
1208
  }
1209
  }
1210
  }
1222
  *
1223
  * @return bool
1224
  */
1225
+ public function has_bad_characters($string)
1226
+ {
1227
  $regex = '/
1228
  (
1229
  (?: [\x00-\x7F] # single-byte sequences 0xxxxxxx
1240
  ';
1241
 
1242
 
1243
+ $regex .= '){1,40} # ...one or more times
1244
  )
1245
  | . # anything else
1246
  /x';
1247
+ $stripped_string = preg_replace($regex, '$1', $string);
1248
 
1249
+ if ($stripped_string === $string) {
1250
  return false;
1251
  } else {
1252
  return true;
1264
  *
1265
  * @return mixed
1266
  */
1267
+ public function display_possible_db_errors($dictionary, $prepared_query, $strings_array)
1268
+ {
1269
  global $trp_editor_notices;
1270
+ if (trp_is_translation_editor('preview') && is_array($dictionary) && count($dictionary) === 0) {
1271
+ if ($this->has_bad_characters($prepared_query)) {
1272
+ $html = "<div class='trp-notice trp-notice-warning'><p class='trp-bad-encoded-strings'>" . __('<strong>Warning:</strong> Some strings have possibly incorrectly encoded characters. This may result in breaking the queries, rendering the page untranslated in live mode. Consider revising the following strings or their method of outputting.', 'translatepress-multilingual') . "</p>";
1273
  $html .= "<ul class='trp-bad-encoded-strings-list'>";
1274
+ foreach ($strings_array as $string) {
1275
+ if ($this->has_bad_characters($string)) {
1276
  $html .= "<li>" . $string . "</li>";
1277
  }
1278
  }
1286
  return $dictionary;
1287
  }
1288
 
1289
+ /**
1290
+ * Receives and returns the date format in which a date (eg publish date) is presented on the frontend
1291
+ * The format is saved in the advanced settings tab for each language except the default one
1292
+ *
1293
+ * @param $date_format
1294
+ *
1295
+ * @return mixed
1296
+ */
1297
+ public function filter_the_date( $date_format)
1298
+ {
1299
+ global $TRP_LANGUAGE;
1300
+
1301
+ if (!empty($TRP_LANGUAGE) && $this->settings["default-language"] === $TRP_LANGUAGE) {
1302
+ return $date_format;
1303
+ } else {
1304
+ if (isset ($this->settings["trp_advanced_settings"]["language_date_format"][$TRP_LANGUAGE]) && !empty ($this->settings["trp_advanced_settings"]["language_date_format"][$TRP_LANGUAGE]))
1305
+ {
1306
+ return $this->settings["trp_advanced_settings"]["language_date_format"][$TRP_LANGUAGE];
1307
+ } else {
1308
+ return $date_format;
1309
+ }
1310
+ }
1311
+ }
1312
+
1313
  }
includes/class-translation-render.php CHANGED
@@ -548,6 +548,11 @@ class TRP_Translation_Render{
548
  }
549
  }
550
  else{
 
 
 
 
 
551
  $row->outertext = '<trp-wrap class="trp-wrap" data-no-translation';
552
  if (isset($_REQUEST['trp-edit-translation']) && $_REQUEST['trp-edit-translation'] == 'preview') {
553
  $row->outertext .= ' data-trpgettextoriginal="'. $original_gettext_translation_id .'"';
@@ -1265,52 +1270,43 @@ class TRP_Translation_Render{
1265
  }
1266
  }
1267
 
 
 
1268
 
1269
  // machine translate new strings
1270
  if ( $machine_translation_available ) {
1271
  $machine_strings = $this->machine_translator->translate( $machine_translatable_strings, $language_code, $this->settings['default-language'] );
 
 
 
 
 
 
 
 
 
 
 
 
 
1272
  }else{
1273
  $machine_strings = false;
1274
  }
1275
 
1276
  // update existing strings without translation if we have one now. also, do not insert duplicates for existing untranslated strings in db
1277
- $untranslated_list = $this->trp_query->get_untranslated_strings( $new_strings, $language_code );
1278
- $update_strings = array();
1279
  foreach( $new_strings as $i => $string ){
1280
- if ( isset( $untranslated_list[$string] ) ){
1281
- //string exists as not translated, thus need to be updated if we have translation
1282
- if ( isset( $machine_strings[$i] ) ) {
1283
- // we have a translation
1284
- array_push ( $update_strings, array(
1285
- 'id' => $untranslated_list[$string]->id,
1286
- 'original' => trp_sanitize_string($untranslated_list[$string]->original),
1287
- 'translated' => trp_sanitize_string($machine_strings[$i]),
1288
- 'status' => $this->trp_query->get_constant_machine_translated() ) );
1289
- $translated_strings[$i] = $machine_strings[$i];
1290
- }
1291
- unset( $new_strings[$i] );
1292
  }
1293
- }
1294
 
1295
- // insert remaining machine translations into db
1296
- if ( $machine_strings !== false ) {
1297
- foreach ($machine_strings as $i => $string) {
1298
- if ( isset( $translated_strings[$i] ) ){
1299
- continue;
1300
- }else {
1301
- $translated_strings[$i] = $machine_strings[$i];
1302
- array_push ( $update_strings, array(
1303
- 'id' => NULL,
1304
- 'original' => $new_strings[$i],
1305
- 'translated' => trp_sanitize_string($machine_strings[$i]),
1306
- 'status' => $this->trp_query->get_constant_machine_translated() ) );
1307
- unset($new_strings[$i]);
1308
- }
1309
  }
1310
  }
1311
 
1312
  $this->trp_query->insert_strings( $new_strings, $language_code, $block_type );
1313
- $this->trp_query->update_strings( $update_strings, $language_code, array( 'id','original', 'translated', 'status' ) );
1314
 
1315
  return $translated_strings;
1316
  }
548
  }
549
  }
550
  else{
551
+ /* Setting this attribute using setAttribute function actually changes the $html object.
552
+ Important for not detecting this gettext as a regular string in the next lines using find() */
553
+ $row->setAttribute($no_translate_attribute, '');
554
+
555
+ /* Changes made to outertext take place only after saving the html object to a string */
556
  $row->outertext = '<trp-wrap class="trp-wrap" data-no-translation';
557
  if (isset($_REQUEST['trp-edit-translation']) && $_REQUEST['trp-edit-translation'] == 'preview') {
558
  $row->outertext .= ' data-trpgettextoriginal="'. $original_gettext_translation_id .'"';
1270
  }
1271
  }
1272
 
1273
+ $untranslated_list = $this->trp_query->get_untranslated_strings( $new_strings, $language_code );
1274
+ $update_strings = array();
1275
 
1276
  // machine translate new strings
1277
  if ( $machine_translation_available ) {
1278
  $machine_strings = $this->machine_translator->translate( $machine_translatable_strings, $language_code, $this->settings['default-language'] );
1279
+ $unique_original_strings_with_machine_translations = array_keys($machine_strings);
1280
+ $original_inserts = $this->trp_query->original_strings_sync( $language_code, $unique_original_strings_with_machine_translations );
1281
+
1282
+ // insert unique machine translations into db. Only for strings newly discovered
1283
+ foreach ( $unique_original_strings_with_machine_translations as $string ) {
1284
+ $id = ( isset( $untranslated_list[$string] ) ) ? $untranslated_list[$string]->id : NULL;
1285
+ array_push( $update_strings, array(
1286
+ 'id' => $id,
1287
+ 'original_id' => $original_inserts[ $string ]->id,
1288
+ 'original' => trp_sanitize_string( $string ),
1289
+ 'translated' => trp_sanitize_string( $machine_strings[ $string ] ),
1290
+ 'status' => $this->trp_query->get_constant_machine_translated() ) );
1291
+ }
1292
  }else{
1293
  $machine_strings = false;
1294
  }
1295
 
1296
  // update existing strings without translation if we have one now. also, do not insert duplicates for existing untranslated strings in db
 
 
1297
  foreach( $new_strings as $i => $string ){
1298
+
1299
+ if ( !isset($translated_strings[$i]) && isset( $machine_strings[$string] ) ) {
1300
+ $translated_strings[$i] = $machine_strings[$string];
 
 
 
 
 
 
 
 
 
1301
  }
 
1302
 
1303
+ if ( isset( $untranslated_list[$string] ) || isset( $machine_strings[$string] ) ){
1304
+ unset( $new_strings[$i] );
 
 
 
 
 
 
 
 
 
 
 
 
1305
  }
1306
  }
1307
 
1308
  $this->trp_query->insert_strings( $new_strings, $language_code, $block_type );
1309
+ $this->trp_query->update_strings( $update_strings, $language_code, array( 'id','original', 'translated', 'status', 'original_id' ) );
1310
 
1311
  return $translated_strings;
1312
  }
includes/class-url-converter.php CHANGED
@@ -493,13 +493,14 @@ class TRP_Url_Converter {
493
  if( empty($this->absolute_home) ){
494
  $this->absolute_home = get_option("siteurl");
495
  }
496
-
497
- // always return absolute_home based on the http or https version of the current page request. This means no more redirects.
498
- if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') {
499
- $this->absolute_home = str_replace( 'http://', 'https://', $this->absolute_home );
500
- } else {
501
- $this->absolute_home = str_replace( 'https://', 'http://', $this->absolute_home );
502
- }
 
503
 
504
  wp_cache_set( 'get_abs_home', $this->absolute_home, 'trp' );
505
 
@@ -673,12 +674,19 @@ class TRP_Url_Converter {
673
  return $value;
674
  }
675
 
676
- /* don't update the woocommerce_permalink option on the frontend if we are not on the default language */
677
- function woocommerce_handle_permalink_option_on_frontend($value, $old_value){
 
 
 
 
 
 
678
  global $TRP_LANGUAGE;
679
- if( isset($TRP_LANGUAGE) && $TRP_LANGUAGE != $this->settings['default-language'] ){
680
  $value = $old_value;
681
  }
 
682
  return $value;
683
  }
684
 
493
  if( empty($this->absolute_home) ){
494
  $this->absolute_home = get_option("siteurl");
495
  }
496
+ if ( apply_filters('trp_adjust_absolute_home_https_based_on_server_variable', true) ) {
497
+ // always return absolute_home based on the http or https version of the current page request. This means no more redirects.
498
+ if ( !empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] != 'off' ) {
499
+ $this->absolute_home = str_replace( 'http://', 'https://', $this->absolute_home );
500
+ } else {
501
+ $this->absolute_home = str_replace( 'https://', 'http://', $this->absolute_home );
502
+ }
503
+ }
504
 
505
  wp_cache_set( 'get_abs_home', $this->absolute_home, 'trp' );
506
 
674
  return $value;
675
  }
676
 
677
+ /**
678
+ * Prevent the rewrite_rules option to change when we are not on the default language so we don't get translated data in the database
679
+ * Basically update_option for rewrite_rules does nothing
680
+ * @param $value
681
+ * @param $old_value
682
+ * @return mixed
683
+ */
684
+ function prevent_permalink_update_on_other_languages( $value, $old_value ){
685
  global $TRP_LANGUAGE;
686
+ if( isset($TRP_LANGUAGE) && $TRP_LANGUAGE != $this->settings['default-language'] ) {
687
  $value = $old_value;
688
  }
689
+
690
  return $value;
691
  }
692
 
includes/compatibility-functions.php CHANGED
@@ -688,4 +688,36 @@ function trp_opengraph_url( $url ) {
688
  $url = $url_converter->get_url_for_language($TRP_LANGUAGE, $url, '');
689
 
690
  return $url;
691
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
688
  $url = $url_converter->get_url_for_language($TRP_LANGUAGE, $url, '');
689
 
690
  return $url;
691
+ }
692
+
693
+ /**
694
+ * Compatibility with Oxygen plugin
695
+ *
696
+ * Improves stylesheet loading time by disabling gettext and regular text detection for pages loaded with xlink=css
697
+ */
698
+ add_action( 'trp_before_running_hooks', 'trp_oxygen_remove_gettext_hooks', 10, 1 );
699
+ function trp_oxygen_remove_gettext_hooks( $trp_loader ) {
700
+ if ( isset( $_REQUEST['xlink'] ) && $_REQUEST['xlink'] === 'css' ) {
701
+ $trp = TRP_Translate_Press::get_trp_instance();
702
+ $translation_manager = $trp->get_component( 'translation_manager' );
703
+ $translation_render = $trp->get_component( 'translation_render' );
704
+ $trp_loader->remove_hook( 'init', 'create_gettext_translated_global', $translation_manager );
705
+ $trp_loader->remove_hook( 'init', 'initialize_gettext_processing', $translation_manager );
706
+ $trp_loader->remove_hook( 'shutdown', 'machine_translate_gettext', $translation_manager );
707
+ $trp_loader->remove_hook( 'init', 'start_output_buffer', $translation_render );
708
+ $trp_loader->remove_hook( 'the_title', 'wrap_with_post_id', $translation_render );
709
+ $trp_loader->remove_hook( 'the_content', 'wrap_with_post_id', $translation_render );
710
+ }
711
+ }
712
+
713
+ /**
714
+ * Compatibility with Brizy editor
715
+ */
716
+ add_filter( 'trp_enable_dynamic_translation', 'trp_brizy_disable_dynamic_translation' );
717
+ function trp_brizy_disable_dynamic_translation( $enable ){
718
+ if ( isset( $_REQUEST['brizy-edit-iframe'] ) ){
719
+ return false;
720
+ }
721
+ return $enable;
722
+ }
723
+
includes/functions.php CHANGED
@@ -518,3 +518,26 @@ function trp_do_these_shortcodes( $content, $tags_allowed ){
518
 
519
  return $return_content;
520
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
518
 
519
  return $return_content;
520
  }
521
+
522
+ /**
523
+ * Obtains a list of TP languages. Can be without the default one
524
+ * in which case use the parameter nodefault set to 'nodefault'
525
+ *
526
+ * @param string $nodefault param used to return published languages without default one
527
+ * @return mixed array with key/value pairs of published language codes and names
528
+ *
529
+ */
530
+ function trp_get_languages($nodefault=null)
531
+ {
532
+ $trp_obj = TRP_Translate_Press::get_trp_instance();
533
+ $settings_obj = $trp_obj->get_component('settings');
534
+ $lang_obj = $trp_obj->get_component('languages');
535
+
536
+ $default_lang_labels = $settings_obj->get_setting('default-language');
537
+ $published_lang = $settings_obj->get_setting('publish-languages');
538
+ $published_lang_labels = $lang_obj->get_language_names($published_lang);
539
+ if (isset($nodefault) && $nodefault === 'nodefault'){
540
+ unset ($published_lang_labels[$default_lang_labels]);
541
+ }
542
+ return ($published_lang_labels);
543
+ }
includes/trp-ajax.php CHANGED
@@ -102,7 +102,6 @@ class TRP_Ajax{
102
 
103
 
104
  $this->connection = mysqli_connect( $credentials['db_host'], $credentials['db_user'], $credentials['db_password'], $credentials['db_name'] );
105
- mysqli_set_charset ( $this->connection , $credentials['db_charset'] );
106
 
107
  // Check connection
108
  if ( mysqli_connect_errno() ) {
@@ -110,6 +109,7 @@ class TRP_Ajax{
110
  return false;
111
  }
112
 
 
113
  if ( preg_match_all( '/\$table_prefix\s*=\s*[\'"](.*?)[\'"]/', $content, $results ) ) {
114
  $this->table_prefix = end( $results[1] );
115
  }else{
102
 
103
 
104
  $this->connection = mysqli_connect( $credentials['db_host'], $credentials['db_user'], $credentials['db_password'], $credentials['db_name'] );
 
105
 
106
  // Check connection
107
  if ( mysqli_connect_errno() ) {
109
  return false;
110
  }
111
 
112
+ mysqli_set_charset ( $this->connection , $credentials['db_charset'] );
113
  if ( preg_match_all( '/\$table_prefix\s*=\s*[\'"](.*?)[\'"]/', $content, $results ) ) {
114
  $this->table_prefix = end( $results[1] );
115
  }else{
index.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: TranslatePress - Multilingual
4
  Plugin URI: https://translatepress.com/
5
  Description: Experience a better way of translating your WordPress site using a visual front-end translation editor, with full support for WooCommerce and site builders.
6
- Version: 1.7.8
7
  Author: Cozmoslabs, Razvan Mocanu, Madalin Ungureanu, Cristophor Hurduban
8
  Author URI: https://cozmoslabs.com/
9
  Text Domain: translatepress-multilingual
3
  Plugin Name: TranslatePress - Multilingual
4
  Plugin URI: https://translatepress.com/
5
  Description: Experience a better way of translating your WordPress site using a visual front-end translation editor, with full support for WooCommerce and site builders.
6
+ Version: 1.7.9
7
  Author: Cozmoslabs, Razvan Mocanu, Madalin Ungureanu, Cristophor Hurduban
8
  Author URI: https://cozmoslabs.com/
9
  Text Domain: translatepress-multilingual
languages/translatepress-multilingual.catalog.php CHANGED
@@ -73,6 +73,7 @@
73
  <?php __("Flags with Full Language Names", "translatepress-multilingual"); ?>
74
  <?php __("Flags with Short Language Names", "translatepress-multilingual"); ?>
75
  <?php __("Only Flags", "translatepress-multilingual"); ?>
 
76
  <?php __("Bottom Right", "translatepress-multilingual"); ?>
77
  <?php __("Bottom Left", "translatepress-multilingual"); ?>
78
  <?php __("Top Right", "translatepress-multilingual"); ?>
@@ -297,6 +298,8 @@
297
  <?php __("WooCommerce Slugs", "translatepress-multilingual"); ?>
298
  <?php __("WooCommerce Slug", "translatepress-multilingual"); ?>
299
  <?php __("Search WooCommerce Slugs", "translatepress-multilingual"); ?>
 
 
300
  <?php __("Disable dynamic translation", "translatepress-multilingual"); ?>
301
  <?php __("It disables detection of strings displayed dynamically using JavaScript. <br/>Strings loaded via a server side AJAX call will still be translated.", "translatepress-multilingual"); ?>
302
  <?php __("Exclude translated links from sitemap", "translatepress-multilingual"); ?>
73
  <?php __("Flags with Full Language Names", "translatepress-multilingual"); ?>
74
  <?php __("Flags with Short Language Names", "translatepress-multilingual"); ?>
75
  <?php __("Only Flags", "translatepress-multilingual"); ?>
76
+ <?php __("Full Language Names No HTML", "translatepress-multilingual"); ?>
77
  <?php __("Bottom Right", "translatepress-multilingual"); ?>
78
  <?php __("Bottom Left", "translatepress-multilingual"); ?>
79
  <?php __("Top Right", "translatepress-multilingual"); ?>
298
  <?php __("WooCommerce Slugs", "translatepress-multilingual"); ?>
299
  <?php __("WooCommerce Slug", "translatepress-multilingual"); ?>
300
  <?php __("Search WooCommerce Slugs", "translatepress-multilingual"); ?>
301
+ <?php __("Date format", "translatepress-multilingual"); ?>
302
+ <?php __("Customize the date formatting per each translated language.<br/>Leave empty for default WP setting or see more information <a href=\"https://wordpress.org/support/article/formatting-date-and-time/\" title=\"Formatting Date and Time\" target=\"_blank\">here</a>", "translatepress-multilingual"); ?>
303
  <?php __("Disable dynamic translation", "translatepress-multilingual"); ?>
304
  <?php __("It disables detection of strings displayed dynamically using JavaScript. <br/>Strings loaded via a server side AJAX call will still be translated.", "translatepress-multilingual"); ?>
305
  <?php __("Exclude translated links from sitemap", "translatepress-multilingual"); ?>
languages/translatepress-multilingual.pot CHANGED
@@ -13,7 +13,7 @@ msgstr ""
13
  "X-Poedit-SourceCharset: UTF-8\n"
14
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
15
 
16
- #: ../tp-add-on-extra-languages/class-extra-languages.php:57, ../translatepress/includes/class-settings.php:397
17
  msgid "Error! Duplicate URL slug values."
18
  msgstr ""
19
 
@@ -89,7 +89,7 @@ msgstr ""
89
  msgid "Slug"
90
  msgstr ""
91
 
92
- #: ../tp-add-on-extra-languages/partials/language-selector-pro.php:10, ../translatepress/includes/class-install-plugins.php:34, ../translatepress/includes/class-settings.php:136
93
  msgid "Active"
94
  msgstr ""
95
 
@@ -97,7 +97,7 @@ msgstr ""
97
  msgid "Are you sure you want to remove this language?"
98
  msgstr ""
99
 
100
- #: ../tp-add-on-extra-languages/partials/language-selector-pro.php:43, ../translatepress/includes/class-advanced-tab.php:423, ../translatepress/includes/class-advanced-tab.php:433, ../translatepress/partials/main-settings-language-selector.php:40
101
  msgid "Remove"
102
  msgstr ""
103
 
@@ -105,7 +105,7 @@ msgstr ""
105
  msgid "Choose..."
106
  msgstr ""
107
 
108
- #: ../tp-add-on-extra-languages/partials/language-selector-pro.php:58, ../translatepress/includes/class-advanced-tab.php:433, ../translatepress/partials/main-settings-language-selector.php:55
109
  msgid "Add"
110
  msgstr ""
111
 
@@ -121,11 +121,11 @@ msgstr ""
121
  msgid "Advanced"
122
  msgstr ""
123
 
124
- #: ../translatepress/includes/class-advanced-tab.php:242, ../translatepress/includes/class-error-manager.php:155, ../translatepress/partials/machine-translation-settings-page.php:13, ../translatepress/partials/machine-translation-settings-page.php:78, ../translatepress/partials/machine-translation-settings-page.php:111, ../translatepress/partials/main-settings-page.php:41, ../translatepress/partials/main-settings-page.php:54, ../translatepress/partials/main-settings-page.php:67
125
  msgid "Yes"
126
  msgstr ""
127
 
128
- #: ../translatepress/includes/class-advanced-tab.php:423, ../translatepress/includes/class-advanced-tab.php:433
129
  msgid "Are you sure you want to remove this item?"
130
  msgstr ""
131
 
@@ -309,343 +309,347 @@ msgstr ""
309
  msgid "Only Flags"
310
  msgstr ""
311
 
312
- #: ../translatepress/includes/class-settings.php:61
 
 
 
 
313
  msgid "Bottom Right"
314
  msgstr ""
315
 
316
- #: ../translatepress/includes/class-settings.php:62
317
  msgid "Bottom Left"
318
  msgstr ""
319
 
320
- #: ../translatepress/includes/class-settings.php:63
321
  msgid "Top Right"
322
  msgstr ""
323
 
324
- #: ../translatepress/includes/class-settings.php:64
325
  msgid "Top Left"
326
  msgstr ""
327
 
328
- #: ../translatepress/includes/class-settings.php:137
329
  msgid "Install & Activate"
330
  msgstr ""
331
 
332
- #: ../translatepress/includes/class-settings.php:438
333
  msgid "Current Language"
334
  msgstr ""
335
 
336
- #: ../translatepress/includes/class-settings.php:479
337
  msgid "General"
338
  msgstr ""
339
 
340
- #: ../translatepress/includes/class-settings.php:484, ../translatepress/includes/class-translation-manager.php:417
341
  msgid "Translate Site"
342
  msgstr ""
343
 
344
- #: ../translatepress/includes/class-settings.php:489
345
  msgid "Addons"
346
  msgstr ""
347
 
348
- #: ../translatepress/includes/class-settings.php:497
349
  msgid "License"
350
  msgstr ""
351
 
352
- #: ../translatepress/includes/class-settings.php:525, ../translatepress/includes/class-translation-manager.php:449
353
  msgid "Settings"
354
  msgstr ""
355
 
356
- #: ../translatepress/includes/class-settings.php:529
357
  msgid "Pro Features"
358
  msgstr ""
359
 
360
- #: ../translatepress/includes/class-translation-manager.php:87
361
  msgid "Image source"
362
  msgstr ""
363
 
364
- #: ../translatepress/includes/class-translation-manager.php:88
365
  msgid "Alt attribute"
366
  msgstr ""
367
 
368
- #: ../translatepress/includes/class-translation-manager.php:89
369
  msgid "Title attribute"
370
  msgstr ""
371
 
372
- #: ../translatepress/includes/class-translation-manager.php:90
373
  msgid "Anchor link"
374
  msgstr ""
375
 
376
- #: ../translatepress/includes/class-translation-manager.php:91
377
  msgid "Placeholder attribute"
378
  msgstr ""
379
 
380
- #: ../translatepress/includes/class-translation-manager.php:92
381
  msgid "Submit attribute"
382
  msgstr ""
383
 
384
- #: ../translatepress/includes/class-translation-manager.php:93
385
  msgid "Text"
386
  msgstr ""
387
 
388
- #: ../translatepress/includes/class-translation-manager.php:95
389
  msgid "Saved"
390
  msgstr ""
391
 
392
- #: ../translatepress/includes/class-translation-manager.php:96
393
  msgid "Save translation"
394
  msgstr ""
395
 
396
- #: ../translatepress/includes/class-translation-manager.php:97
397
  msgid "Saving translation..."
398
  msgstr ""
399
 
400
- #: ../translatepress/includes/class-translation-manager.php:98
401
  msgid "You have unsaved changes!"
402
  msgstr ""
403
 
404
- #: ../translatepress/includes/class-translation-manager.php:99
405
  msgid "Discard changes"
406
  msgstr ""
407
 
408
- #: ../translatepress/includes/class-translation-manager.php:100
409
  msgid "Discard All"
410
  msgstr ""
411
 
412
- #: ../translatepress/includes/class-translation-manager.php:101
413
  msgid "Loading Strings..."
414
  msgstr ""
415
 
416
- #: ../translatepress/includes/class-translation-manager.php:102
417
  msgid "Select string to translate..."
418
  msgstr ""
419
 
420
- #: ../translatepress/includes/class-translation-manager.php:103
421
  msgid "Close Editor"
422
  msgstr ""
423
 
424
- #: ../translatepress/includes/class-translation-manager.php:104
425
  msgid "From"
426
  msgstr ""
427
 
428
- #: ../translatepress/includes/class-translation-manager.php:105
429
  msgid "To"
430
  msgstr ""
431
 
432
- #: ../translatepress/includes/class-translation-manager.php:106
433
  msgid "Next"
434
  msgstr ""
435
 
436
- #: ../translatepress/includes/class-translation-manager.php:107
437
  msgid "Previous"
438
  msgstr ""
439
 
440
- #: ../translatepress/includes/class-translation-manager.php:108
441
  msgid "Add Media"
442
  msgstr ""
443
 
444
- #: ../translatepress/includes/class-translation-manager.php:109
445
  msgid "Other languages"
446
  msgstr ""
447
 
448
- #: ../translatepress/includes/class-translation-manager.php:110
449
  msgid "View As"
450
  msgstr ""
451
 
452
- #: ../translatepress/includes/class-translation-manager.php:111
453
  msgid "Available in our Pro Versions"
454
  msgstr ""
455
 
456
- #: ../translatepress/includes/class-translation-manager.php:114
457
  msgid "Select or Upload Media"
458
  msgstr ""
459
 
460
- #: ../translatepress/includes/class-translation-manager.php:115
461
  msgid "Use this media"
462
  msgstr ""
463
 
464
- #: ../translatepress/includes/class-translation-manager.php:118
465
  msgid "Translate"
466
  msgstr ""
467
 
468
- #: ../translatepress/includes/class-translation-manager.php:119
469
  msgid "Translate entire block element"
470
  msgstr ""
471
 
472
- #: ../translatepress/includes/class-translation-manager.php:120
473
  msgid "Split block to translate strings individually"
474
  msgstr ""
475
 
476
- #: ../translatepress/includes/class-translation-manager.php:121
477
  msgid "Save changes to translation. Shortcut: CTRL(⌘) + S"
478
  msgstr ""
479
 
480
- #: ../translatepress/includes/class-translation-manager.php:122
481
  msgid "Navigate to next string in dropdown list. Shortcut: CTRL(⌘) + ALT + Right Arrow"
482
  msgstr ""
483
 
484
- #: ../translatepress/includes/class-translation-manager.php:123
485
  msgid "Navigate to previous string in dropdown list. Shortcut: CTRL(⌘) + ALT + Left Arrow"
486
  msgstr ""
487
 
488
- #: ../translatepress/includes/class-translation-manager.php:124
489
  msgid "Discard all changes. Shortcut: CTRL(⌘) + ALT + Z"
490
  msgstr ""
491
 
492
- #: ../translatepress/includes/class-translation-manager.php:125
493
  msgid "Discard changes to this text box. To discard changes to all text boxes use shortcut: CTRL(⌘) + ALT + Z"
494
  msgstr ""
495
 
496
- #: ../translatepress/includes/class-translation-manager.php:126
497
  msgid "Dismiss tooltip"
498
  msgstr ""
499
 
500
- #: ../translatepress/includes/class-translation-manager.php:127, ../translatepress/includes/class-translation-manager.php:161, ../translatepress/includes/class-translation-manager.php:167, ../translatepress/includes/class-translation-manager.php:172, ../translatepress/includes/class-translation-manager.php:177
501
  msgid "Quick Intro"
502
  msgstr ""
503
 
504
- #: ../translatepress/includes/class-translation-manager.php:129
505
  msgid "Are you sure you want to split this phrase into smaller parts?"
506
  msgstr ""
507
 
508
- #: ../translatepress/includes/class-translation-manager.php:130
509
  msgid "This string is not ready for translation yet. <br>Try again in a moment..."
510
  msgstr ""
511
 
512
- #: ../translatepress/includes/class-translation-manager.php:132
513
  msgid "For this option to work, please update the Browse as other role add-on to the latest version."
514
  msgstr ""
515
 
516
- #: ../translatepress/includes/class-translation-manager.php:133
517
  msgid "To translate slugs, please update the SEO Pack add-on to the latest version."
518
  msgstr ""
519
 
520
- #: ../translatepress/includes/class-translation-manager.php:136
521
  msgid "You can add a new language from <a href=\"%s\">Settings->TranslatePress</a>"
522
  msgstr ""
523
 
524
- #: ../translatepress/includes/class-translation-manager.php:137
525
  msgid "However, you can still use TranslatePress to <strong style=\"background: #f5fb9d;\">modify gettext strings</strong> available in your page."
526
  msgstr ""
527
 
528
- #: ../translatepress/includes/class-translation-manager.php:138
529
  msgid "Strings that are user-created cannot be modified, only those from themes and plugins."
530
  msgstr ""
531
 
532
- #: ../translatepress/includes/class-translation-manager.php:140
533
  msgid "Extra Translation Features"
534
  msgstr ""
535
 
536
- #: ../translatepress/includes/class-translation-manager.php:141
537
  msgid "Support for 221 Extra Languages"
538
  msgstr ""
539
 
540
- #: ../translatepress/includes/class-translation-manager.php:142
541
  msgid "Yoast SEO support"
542
  msgstr ""
543
 
544
- #: ../translatepress/includes/class-translation-manager.php:143
545
  msgid "Translate SEO Title, Description, Slug"
546
  msgstr ""
547
 
548
- #: ../translatepress/includes/class-translation-manager.php:144
549
  msgid "Publish only when translation is complete"
550
  msgstr ""
551
 
552
- #: ../translatepress/includes/class-translation-manager.php:145
553
  msgid "Translate by Browsing as User Role"
554
  msgstr ""
555
 
556
- #: ../translatepress/includes/class-translation-manager.php:146
557
  msgid "Different Menu Items for each Language"
558
  msgstr ""
559
 
560
- #: ../translatepress/includes/class-translation-manager.php:147
561
  msgid "Automatic User Language Detection"
562
  msgstr ""
563
 
564
- #: ../translatepress/includes/class-translation-manager.php:148
565
  msgid "Supported By Real People"
566
  msgstr ""
567
 
568
- #: ../translatepress/includes/class-translation-manager.php:149
569
  msgid "Find Out More"
570
  msgstr ""
571
 
572
- #: ../translatepress/includes/class-translation-manager.php:151
573
  msgid "No available suggestions"
574
  msgstr ""
575
 
576
- #: ../translatepress/includes/class-translation-manager.php:152
577
  msgid "Suggestions from translation memory"
578
  msgstr ""
579
 
580
- #: ../translatepress/includes/class-translation-manager.php:153
581
  msgid "Click to Copy"
582
  msgstr ""
583
 
584
- #: ../translatepress/includes/class-translation-manager.php:162
585
  msgid "Hover any text on the page, click <img src=\"%s\" class=\"trp-edit-icon-inline\">, then modify the translation in the sidebar."
586
  msgstr ""
587
 
588
- #: ../translatepress/includes/class-translation-manager.php:168
589
  msgid "Don't forget to Save Translation. Use keyboard shortcut CTRL(⌘) + S"
590
  msgstr ""
591
 
592
- #: ../translatepress/includes/class-translation-manager.php:173
593
  msgid "Switch language to see the translation changes directly on the page."
594
  msgstr ""
595
 
596
- #: ../translatepress/includes/class-translation-manager.php:178
597
  msgid "Search for any text in this page in the dropdown."
598
  msgstr ""
599
 
600
- #: ../translatepress/includes/class-translation-manager.php:220, ../tp-add-on-seo-pack/includes/string-translation/class-string-translation-seo.php:12
601
  msgid "Slugs"
602
  msgstr ""
603
 
604
- #: ../translatepress/includes/class-translation-manager.php:221
605
  msgid "Meta Information"
606
  msgstr ""
607
 
608
- #: ../translatepress/includes/class-translation-manager.php:222
609
  msgid "String List"
610
  msgstr ""
611
 
612
- #: ../translatepress/includes/class-translation-manager.php:223
613
  msgid "Gettext Strings"
614
  msgstr ""
615
 
616
- #: ../translatepress/includes/class-translation-manager.php:224
617
  msgid "Images"
618
  msgstr ""
619
 
620
- #: ../translatepress/includes/class-translation-manager.php:225
621
  msgid "Dynamically Added Strings"
622
  msgstr ""
623
 
624
- #: ../translatepress/includes/class-translation-manager.php:259
625
  msgid "Visual Editor"
626
  msgstr ""
627
 
628
- #: ../translatepress/includes/class-translation-manager.php:265
629
  msgid "String Translation"
630
  msgstr ""
631
 
632
- #: ../translatepress/includes/class-translation-manager.php:343
633
  msgid "Current User"
634
  msgstr ""
635
 
636
- #: ../translatepress/includes/class-translation-manager.php:344
637
  msgid "Logged Out"
638
  msgstr ""
639
 
640
- #: ../translatepress/includes/class-translation-manager.php:430
641
  msgid "Translate Page"
642
  msgstr ""
643
 
644
- #: ../translatepress/includes/class-translation-manager.php:1155
645
  msgid "Security check"
646
  msgstr ""
647
 
648
- #: ../translatepress/includes/class-translation-manager.php:1227
649
  msgid "<strong>Warning:</strong> Some strings have possibly incorrectly encoded characters. This may result in breaking the queries, rendering the page untranslated in live mode. Consider revising the following strings or their method of outputting."
650
  msgstr ""
651
 
@@ -1205,6 +1209,14 @@ msgstr ""
1205
  msgid "Search WooCommerce Slugs"
1206
  msgstr ""
1207
 
 
 
 
 
 
 
 
 
1208
  #: ../translatepress/includes/advanced-settings/disable-dynamic-translation.php:8
1209
  msgid "Disable dynamic translation"
1210
  msgstr ""
13
  "X-Poedit-SourceCharset: UTF-8\n"
14
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
15
 
16
+ #: ../tp-add-on-extra-languages/class-extra-languages.php:57, ../translatepress/includes/class-settings.php:403
17
  msgid "Error! Duplicate URL slug values."
18
  msgstr ""
19
 
89
  msgid "Slug"
90
  msgstr ""
91
 
92
+ #: ../tp-add-on-extra-languages/partials/language-selector-pro.php:10, ../translatepress/includes/class-install-plugins.php:34, ../translatepress/includes/class-settings.php:142
93
  msgid "Active"
94
  msgstr ""
95
 
97
  msgid "Are you sure you want to remove this language?"
98
  msgstr ""
99
 
100
+ #: ../tp-add-on-extra-languages/partials/language-selector-pro.php:43, ../translatepress/includes/class-advanced-tab.php:468, ../translatepress/includes/class-advanced-tab.php:478, ../translatepress/partials/main-settings-language-selector.php:40
101
  msgid "Remove"
102
  msgstr ""
103
 
105
  msgid "Choose..."
106
  msgstr ""
107
 
108
+ #: ../tp-add-on-extra-languages/partials/language-selector-pro.php:58, ../translatepress/includes/class-advanced-tab.php:478, ../translatepress/partials/main-settings-language-selector.php:55
109
  msgid "Add"
110
  msgstr ""
111
 
121
  msgid "Advanced"
122
  msgstr ""
123
 
124
+ #: ../translatepress/includes/class-advanced-tab.php:254, ../translatepress/includes/class-error-manager.php:155, ../translatepress/partials/machine-translation-settings-page.php:13, ../translatepress/partials/machine-translation-settings-page.php:78, ../translatepress/partials/machine-translation-settings-page.php:111, ../translatepress/partials/main-settings-page.php:41, ../translatepress/partials/main-settings-page.php:54, ../translatepress/partials/main-settings-page.php:67
125
  msgid "Yes"
126
  msgstr ""
127
 
128
+ #: ../translatepress/includes/class-advanced-tab.php:468, ../translatepress/includes/class-advanced-tab.php:478
129
  msgid "Are you sure you want to remove this item?"
130
  msgstr ""
131
 
309
  msgid "Only Flags"
310
  msgstr ""
311
 
312
+ #: ../translatepress/includes/class-settings.php:31
313
+ msgid "Full Language Names No HTML"
314
+ msgstr ""
315
+
316
+ #: ../translatepress/includes/class-settings.php:67
317
  msgid "Bottom Right"
318
  msgstr ""
319
 
320
+ #: ../translatepress/includes/class-settings.php:68
321
  msgid "Bottom Left"
322
  msgstr ""
323
 
324
+ #: ../translatepress/includes/class-settings.php:69
325
  msgid "Top Right"
326
  msgstr ""
327
 
328
+ #: ../translatepress/includes/class-settings.php:70
329
  msgid "Top Left"
330
  msgstr ""
331
 
332
+ #: ../translatepress/includes/class-settings.php:143
333
  msgid "Install & Activate"
334
  msgstr ""
335
 
336
+ #: ../translatepress/includes/class-settings.php:444
337
  msgid "Current Language"
338
  msgstr ""
339
 
340
+ #: ../translatepress/includes/class-settings.php:485
341
  msgid "General"
342
  msgstr ""
343
 
344
+ #: ../translatepress/includes/class-settings.php:490, ../translatepress/includes/class-translation-manager.php:434
345
  msgid "Translate Site"
346
  msgstr ""
347
 
348
+ #: ../translatepress/includes/class-settings.php:495
349
  msgid "Addons"
350
  msgstr ""
351
 
352
+ #: ../translatepress/includes/class-settings.php:503
353
  msgid "License"
354
  msgstr ""
355
 
356
+ #: ../translatepress/includes/class-settings.php:531, ../translatepress/includes/class-translation-manager.php:466
357
  msgid "Settings"
358
  msgstr ""
359
 
360
+ #: ../translatepress/includes/class-settings.php:535
361
  msgid "Pro Features"
362
  msgstr ""
363
 
364
+ #: ../translatepress/includes/class-translation-manager.php:93
365
  msgid "Image source"
366
  msgstr ""
367
 
368
+ #: ../translatepress/includes/class-translation-manager.php:94
369
  msgid "Alt attribute"
370
  msgstr ""
371
 
372
+ #: ../translatepress/includes/class-translation-manager.php:95
373
  msgid "Title attribute"
374
  msgstr ""
375
 
376
+ #: ../translatepress/includes/class-translation-manager.php:96
377
  msgid "Anchor link"
378
  msgstr ""
379
 
380
+ #: ../translatepress/includes/class-translation-manager.php:97
381
  msgid "Placeholder attribute"
382
  msgstr ""
383
 
384
+ #: ../translatepress/includes/class-translation-manager.php:98
385
  msgid "Submit attribute"
386
  msgstr ""
387
 
388
+ #: ../translatepress/includes/class-translation-manager.php:99
389
  msgid "Text"
390
  msgstr ""
391
 
392
+ #: ../translatepress/includes/class-translation-manager.php:101
393
  msgid "Saved"
394
  msgstr ""
395
 
396
+ #: ../translatepress/includes/class-translation-manager.php:102
397
  msgid "Save translation"
398
  msgstr ""
399
 
400
+ #: ../translatepress/includes/class-translation-manager.php:103
401
  msgid "Saving translation..."
402
  msgstr ""
403
 
404
+ #: ../translatepress/includes/class-translation-manager.php:104
405
  msgid "You have unsaved changes!"
406
  msgstr ""
407
 
408
+ #: ../translatepress/includes/class-translation-manager.php:105
409
  msgid "Discard changes"
410
  msgstr ""
411
 
412
+ #: ../translatepress/includes/class-translation-manager.php:106
413
  msgid "Discard All"
414
  msgstr ""
415
 
416
+ #: ../translatepress/includes/class-translation-manager.php:107
417
  msgid "Loading Strings..."
418
  msgstr ""
419
 
420
+ #: ../translatepress/includes/class-translation-manager.php:108
421
  msgid "Select string to translate..."
422
  msgstr ""
423
 
424
+ #: ../translatepress/includes/class-translation-manager.php:109
425
  msgid "Close Editor"
426
  msgstr ""
427
 
428
+ #: ../translatepress/includes/class-translation-manager.php:110
429
  msgid "From"
430
  msgstr ""
431
 
432
+ #: ../translatepress/includes/class-translation-manager.php:111
433
  msgid "To"
434
  msgstr ""
435
 
436
+ #: ../translatepress/includes/class-translation-manager.php:112
437
  msgid "Next"
438
  msgstr ""
439
 
440
+ #: ../translatepress/includes/class-translation-manager.php:113
441
  msgid "Previous"
442
  msgstr ""
443
 
444
+ #: ../translatepress/includes/class-translation-manager.php:114
445
  msgid "Add Media"
446
  msgstr ""
447
 
448
+ #: ../translatepress/includes/class-translation-manager.php:115
449
  msgid "Other languages"
450
  msgstr ""
451
 
452
+ #: ../translatepress/includes/class-translation-manager.php:116
453
  msgid "View As"
454
  msgstr ""
455
 
456
+ #: ../translatepress/includes/class-translation-manager.php:117
457
  msgid "Available in our Pro Versions"
458
  msgstr ""
459
 
460
+ #: ../translatepress/includes/class-translation-manager.php:120
461
  msgid "Select or Upload Media"
462
  msgstr ""
463
 
464
+ #: ../translatepress/includes/class-translation-manager.php:121
465
  msgid "Use this media"
466
  msgstr ""
467
 
468
+ #: ../translatepress/includes/class-translation-manager.php:124
469
  msgid "Translate"
470
  msgstr ""
471
 
472
+ #: ../translatepress/includes/class-translation-manager.php:125
473
  msgid "Translate entire block element"
474
  msgstr ""
475
 
476
+ #: ../translatepress/includes/class-translation-manager.php:126
477
  msgid "Split block to translate strings individually"
478
  msgstr ""
479
 
480
+ #: ../translatepress/includes/class-translation-manager.php:127
481
  msgid "Save changes to translation. Shortcut: CTRL(⌘) + S"
482
  msgstr ""
483
 
484
+ #: ../translatepress/includes/class-translation-manager.php:128
485
  msgid "Navigate to next string in dropdown list. Shortcut: CTRL(⌘) + ALT + Right Arrow"
486
  msgstr ""
487
 
488
+ #: ../translatepress/includes/class-translation-manager.php:129
489
  msgid "Navigate to previous string in dropdown list. Shortcut: CTRL(⌘) + ALT + Left Arrow"
490
  msgstr ""
491
 
492
+ #: ../translatepress/includes/class-translation-manager.php:130
493
  msgid "Discard all changes. Shortcut: CTRL(⌘) + ALT + Z"
494
  msgstr ""
495
 
496
+ #: ../translatepress/includes/class-translation-manager.php:131
497
  msgid "Discard changes to this text box. To discard changes to all text boxes use shortcut: CTRL(⌘) + ALT + Z"
498
  msgstr ""
499
 
500
+ #: ../translatepress/includes/class-translation-manager.php:132
501
  msgid "Dismiss tooltip"
502
  msgstr ""
503
 
504
+ #: ../translatepress/includes/class-translation-manager.php:133, ../translatepress/includes/class-translation-manager.php:168, ../translatepress/includes/class-translation-manager.php:174, ../translatepress/includes/class-translation-manager.php:179, ../translatepress/includes/class-translation-manager.php:184
505
  msgid "Quick Intro"
506
  msgstr ""
507
 
508
+ #: ../translatepress/includes/class-translation-manager.php:135
509
  msgid "Are you sure you want to split this phrase into smaller parts?"
510
  msgstr ""
511
 
512
+ #: ../translatepress/includes/class-translation-manager.php:136
513
  msgid "This string is not ready for translation yet. <br>Try again in a moment..."
514
  msgstr ""
515
 
516
+ #: ../translatepress/includes/class-translation-manager.php:138
517
  msgid "For this option to work, please update the Browse as other role add-on to the latest version."
518
  msgstr ""
519
 
520
+ #: ../translatepress/includes/class-translation-manager.php:139
521
  msgid "To translate slugs, please update the SEO Pack add-on to the latest version."
522
  msgstr ""
523
 
524
+ #: ../translatepress/includes/class-translation-manager.php:142
525
  msgid "You can add a new language from <a href=\"%s\">Settings->TranslatePress</a>"
526
  msgstr ""
527
 
528
+ #: ../translatepress/includes/class-translation-manager.php:143
529
  msgid "However, you can still use TranslatePress to <strong style=\"background: #f5fb9d;\">modify gettext strings</strong> available in your page."
530
  msgstr ""
531
 
532
+ #: ../translatepress/includes/class-translation-manager.php:144
533
  msgid "Strings that are user-created cannot be modified, only those from themes and plugins."
534
  msgstr ""
535
 
536
+ #: ../translatepress/includes/class-translation-manager.php:146
537
  msgid "Extra Translation Features"
538
  msgstr ""
539
 
540
+ #: ../translatepress/includes/class-translation-manager.php:147
541
  msgid "Support for 221 Extra Languages"
542
  msgstr ""
543
 
544
+ #: ../translatepress/includes/class-translation-manager.php:148
545
  msgid "Yoast SEO support"
546
  msgstr ""
547
 
548
+ #: ../translatepress/includes/class-translation-manager.php:149
549
  msgid "Translate SEO Title, Description, Slug"
550
  msgstr ""
551
 
552
+ #: ../translatepress/includes/class-translation-manager.php:150
553
  msgid "Publish only when translation is complete"
554
  msgstr ""
555
 
556
+ #: ../translatepress/includes/class-translation-manager.php:151
557
  msgid "Translate by Browsing as User Role"
558
  msgstr ""
559
 
560
+ #: ../translatepress/includes/class-translation-manager.php:152
561
  msgid "Different Menu Items for each Language"
562
  msgstr ""
563
 
564
+ #: ../translatepress/includes/class-translation-manager.php:153
565
  msgid "Automatic User Language Detection"
566
  msgstr ""
567
 
568
+ #: ../translatepress/includes/class-translation-manager.php:154
569
  msgid "Supported By Real People"
570
  msgstr ""
571
 
572
+ #: ../translatepress/includes/class-translation-manager.php:155
573
  msgid "Find Out More"
574
  msgstr ""
575
 
576
+ #: ../translatepress/includes/class-translation-manager.php:157
577
  msgid "No available suggestions"
578
  msgstr ""
579
 
580
+ #: ../translatepress/includes/class-translation-manager.php:158
581
  msgid "Suggestions from translation memory"
582
  msgstr ""
583
 
584
+ #: ../translatepress/includes/class-translation-manager.php:159
585
  msgid "Click to Copy"
586
  msgstr ""
587
 
588
+ #: ../translatepress/includes/class-translation-manager.php:169
589
  msgid "Hover any text on the page, click <img src=\"%s\" class=\"trp-edit-icon-inline\">, then modify the translation in the sidebar."
590
  msgstr ""
591
 
592
+ #: ../translatepress/includes/class-translation-manager.php:175
593
  msgid "Don't forget to Save Translation. Use keyboard shortcut CTRL(⌘) + S"
594
  msgstr ""
595
 
596
+ #: ../translatepress/includes/class-translation-manager.php:180
597
  msgid "Switch language to see the translation changes directly on the page."
598
  msgstr ""
599
 
600
+ #: ../translatepress/includes/class-translation-manager.php:185
601
  msgid "Search for any text in this page in the dropdown."
602
  msgstr ""
603
 
604
+ #: ../translatepress/includes/class-translation-manager.php:231, ../tp-add-on-seo-pack/includes/string-translation/class-string-translation-seo.php:12
605
  msgid "Slugs"
606
  msgstr ""
607
 
608
+ #: ../translatepress/includes/class-translation-manager.php:232
609
  msgid "Meta Information"
610
  msgstr ""
611
 
612
+ #: ../translatepress/includes/class-translation-manager.php:233
613
  msgid "String List"
614
  msgstr ""
615
 
616
+ #: ../translatepress/includes/class-translation-manager.php:234
617
  msgid "Gettext Strings"
618
  msgstr ""
619
 
620
+ #: ../translatepress/includes/class-translation-manager.php:235
621
  msgid "Images"
622
  msgstr ""
623
 
624
+ #: ../translatepress/includes/class-translation-manager.php:236
625
  msgid "Dynamically Added Strings"
626
  msgstr ""
627
 
628
+ #: ../translatepress/includes/class-translation-manager.php:272
629
  msgid "Visual Editor"
630
  msgstr ""
631
 
632
+ #: ../translatepress/includes/class-translation-manager.php:278
633
  msgid "String Translation"
634
  msgstr ""
635
 
636
+ #: ../translatepress/includes/class-translation-manager.php:358
637
  msgid "Current User"
638
  msgstr ""
639
 
640
+ #: ../translatepress/includes/class-translation-manager.php:359
641
  msgid "Logged Out"
642
  msgstr ""
643
 
644
+ #: ../translatepress/includes/class-translation-manager.php:447
645
  msgid "Translate Page"
646
  msgstr ""
647
 
648
+ #: ../translatepress/includes/class-translation-manager.php:1198
649
  msgid "Security check"
650
  msgstr ""
651
 
652
+ #: ../translatepress/includes/class-translation-manager.php:1272
653
  msgid "<strong>Warning:</strong> Some strings have possibly incorrectly encoded characters. This may result in breaking the queries, rendering the page untranslated in live mode. Consider revising the following strings or their method of outputting."
654
  msgstr ""
655
 
1209
  msgid "Search WooCommerce Slugs"
1210
  msgstr ""
1211
 
1212
+ #: ../translatepress/includes/advanced-settings/custom-date-format.php:16
1213
+ msgid "Date format"
1214
+ msgstr ""
1215
+
1216
+ #: ../translatepress/includes/advanced-settings/custom-date-format.php:17
1217
+ msgid "Customize the date formatting per each translated language.<br/>Leave empty for default WP setting or see more information <a href=\"https://wordpress.org/support/article/formatting-date-and-time/\" title=\"Formatting Date and Time\" target=\"_blank\">here</a>"
1218
+ msgstr ""
1219
+
1220
  #: ../translatepress/includes/advanced-settings/disable-dynamic-translation.php:8
1221
  msgid "Disable dynamic translation"
1222
  msgstr ""
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: translate, translation, multilingual, automatic translation, bilingual, fr
5
  Requires at least: 3.1.0
6
  Tested up to: 5.4.2
7
  Requires PHP: 5.6.20
8
- Stable tag: 1.7.8
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -138,6 +138,16 @@ For more information please check out our [documentation](https://translatepress
138
 
139
 
140
  == Changelog ==
 
 
 
 
 
 
 
 
 
 
141
  = 1.7.8 =
142
  * Added possibility to exclude hreflang from an original URL
143
  * Fixed translating json inside json. It ensures compatibility with Brizy
5
  Requires at least: 3.1.0
6
  Tested up to: 5.4.2
7
  Requires PHP: 5.6.20
8
+ Stable tag: 1.7.9
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
138
 
139
 
140
  == Changelog ==
141
+ = 1.7.9 =
142
+ * Fix for various 404 page results
143
+ * Fixed flag spacing in RTL languages
144
+ * Added "Full Language Names No HTML" option to language menu
145
+ * Added possibility to change date format by language
146
+ * Oxygen plugin stylesheet loading time improvement
147
+ * Compatibility with Brizy's editor
148
+ * Added filter to allow https adjustments
149
+ * Improved searching on certain pages
150
+
151
  = 1.7.8 =
152
  * Added possibility to exclude hreflang from an original URL
153
  * Fixed translating json inside json. It ensures compatibility with Brizy