TranslatePress – Translate Multilingual sites - Version 1.1.5

Version Description

Added support for translation blocks using the css class .translation-block. Added possibility to choose a different language as default language seen by website visitors. Updated add-ons settings page with the missing add-ons, added Language by GET parameter addon Fixed issue with the [language-switcher] in a post or page that broke saving the page when Yoast SEO plugin is active Added a plugin notification class and a notification for pretty permalinks Added WooCommerce compatibility tag Small css improvements

Download this release

Release Info

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

Code changes from version 1.1.4 to 1.1.5

assets/css/trp-back-end-style.css CHANGED
@@ -55,6 +55,31 @@ span.select2-container{
55
 
56
  }
57
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
59
  /* PRO */
60
  /*
55
 
56
  }
57
 
58
+ /**************************************************/
59
+ /* Extra styling for admin notices
60
+ /**************************************************/
61
+ div.trp-notice {
62
+ position: relative;
63
+ }
64
+
65
+ div.trp-notice:after {
66
+ display: block;
67
+ content: '';
68
+ clear: both;
69
+ }
70
+
71
+ div.trp-notice.trp-narrow {
72
+ max-width: 825px;
73
+ }
74
+
75
+ div.trp-notice .notice-dismiss {
76
+ text-decoration: none;
77
+ }
78
+
79
+ .wrap div.trp-admin-notice {
80
+ margin-bottom: 0;
81
+ }
82
+
83
 
84
  /* PRO */
85
  /*
assets/css/trp-editor-style.css CHANGED
@@ -478,6 +478,10 @@ spin {
478
  z-index: 1051;
479
  }
480
 
 
 
 
 
481
  .select2-container--default .select2-results > .select2-results__options,
482
  .select2-container--default .select2-results > .select2-results__options,
483
  .select2-results{
478
  z-index: 1051;
479
  }
480
 
481
+ #trp-view-as .select2-container{
482
+ z-index: 999;
483
+ }
484
+
485
  .select2-container--default .select2-results > .select2-results__options,
486
  .select2-container--default .select2-results > .select2-results__options,
487
  .select2-results{
assets/images/get_param_addon.jpg ADDED
Binary file
assets/images/menu_based_on_lang.png ADDED
Binary file
assets/images/view-as-addon.png ADDED
Binary file
class-translate-press.php CHANGED
@@ -39,7 +39,7 @@ class TRP_Translate_Press{
39
  define( 'TRP_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
40
  define( 'TRP_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
41
  define( 'TRP_PLUGIN_SLUG', 'translatepress-multilingual' );
42
- define( 'TRP_PLUGIN_VERSION', '1.1.4' );
43
 
44
  $this->load_dependencies();
45
  $this->initialize_components();
@@ -72,6 +72,7 @@ class TRP_Translate_Press{
72
  require_once TRP_PLUGIN_DIR . 'includes/class-machine-translator.php';
73
  require_once TRP_PLUGIN_DIR . 'includes/class-query.php';
74
  require_once TRP_PLUGIN_DIR . 'includes/class-url-converter.php';
 
75
  require_once TRP_PLUGIN_DIR . 'includes/functions.php';
76
  require_once TRP_PLUGIN_DIR . 'assets/lib/simplehtmldom/simple_html_dom.php';
77
  require_once TRP_PLUGIN_DIR . 'includes/shortcodes.php';
@@ -90,6 +91,7 @@ class TRP_Translate_Press{
90
  $this->query = new TRP_Query( $this->settings->get_settings() );
91
  $this->machine_translator = new TRP_Machine_Translator( $this->settings->get_settings() );
92
  $this->translation_manager = new TRP_Translation_Manager( $this->settings->get_settings() );
 
93
  }
94
 
95
  /**
39
  define( 'TRP_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
40
  define( 'TRP_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
41
  define( 'TRP_PLUGIN_SLUG', 'translatepress-multilingual' );
42
+ define( 'TRP_PLUGIN_VERSION', '1.1.5' );
43
 
44
  $this->load_dependencies();
45
  $this->initialize_components();
72
  require_once TRP_PLUGIN_DIR . 'includes/class-machine-translator.php';
73
  require_once TRP_PLUGIN_DIR . 'includes/class-query.php';
74
  require_once TRP_PLUGIN_DIR . 'includes/class-url-converter.php';
75
+ require_once TRP_PLUGIN_DIR . 'includes/class-plugin-notices.php';
76
  require_once TRP_PLUGIN_DIR . 'includes/functions.php';
77
  require_once TRP_PLUGIN_DIR . 'assets/lib/simplehtmldom/simple_html_dom.php';
78
  require_once TRP_PLUGIN_DIR . 'includes/shortcodes.php';
91
  $this->query = new TRP_Query( $this->settings->get_settings() );
92
  $this->machine_translator = new TRP_Machine_Translator( $this->settings->get_settings() );
93
  $this->translation_manager = new TRP_Translation_Manager( $this->settings->get_settings() );
94
+ $this->notifications = new TRP_Trigger_Plugin_Notifications();
95
  }
96
 
97
  /**
includes/class-language-switcher.php CHANGED
@@ -49,6 +49,10 @@ class TRP_Language_Switcher{
49
  }
50
  $published_languages = $this->trp_languages->get_language_names( $this->settings['publish-languages'] );
51
 
 
 
 
 
52
  $ls_options = $this->trp_settings_object->get_language_switcher_options();
53
  $shortcode_settings = $ls_options[$this->settings['shortcode-options']];
54
 
@@ -70,8 +74,11 @@ class TRP_Language_Switcher{
70
  if ( $lang_from_url != null ){
71
  return $lang_from_url;
72
  }
73
-
74
- return $this->settings['default-language'];
 
 
 
75
  }
76
 
77
  /**
49
  }
50
  $published_languages = $this->trp_languages->get_language_names( $this->settings['publish-languages'] );
51
 
52
+ if( ! $this->trp_settings_object ) {
53
+ $trp = TRP_Translate_Press::get_trp_instance();
54
+ $this->trp_settings_object = $trp->get_component( 'settings' );
55
+ }
56
  $ls_options = $this->trp_settings_object->get_language_switcher_options();
57
  $shortcode_settings = $ls_options[$this->settings['shortcode-options']];
58
 
74
  if ( $lang_from_url != null ){
75
  return $lang_from_url;
76
  }
77
+ if ( $this->settings['add-subdirectory-to-default-language'] == 'yes' && isset( $this->settings['translation-languages'][0] ) ) {
78
+ return $this->settings['translation-languages'][0];
79
+ }else{
80
+ return $this->settings['default-language'];
81
+ }
82
  }
83
 
84
  /**
includes/class-plugin-notices.php ADDED
@@ -0,0 +1,289 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class that adds a misc notice
4
+ *
5
+ * @since v.2.0
6
+ *
7
+ * @return void
8
+ */
9
+ class TRP_Add_General_Notices{
10
+ public $notificationId = '';
11
+ public $notificationMessage = '';
12
+ public $notificationClass = '';
13
+ public $startDate = '';
14
+ public $endDate = '';
15
+
16
+ function __construct( $notificationId, $notificationMessage, $notificationClass = 'updated' , $startDate = '', $endDate = '' ){
17
+ $this->notificationId = $notificationId;
18
+ $this->notificationMessage = $notificationMessage;
19
+ $this->notificationClass = $notificationClass;
20
+
21
+ if( !empty( $startDate ) && time() < strtotime( $startDate ) )
22
+ return;
23
+
24
+ if( !empty( $endDate ) && time() > strtotime( $endDate ) )
25
+ return;
26
+
27
+ add_action( 'admin_notices', array( $this, 'add_admin_notice' ) );
28
+ add_action( 'admin_init', array( $this, 'dismiss_notification' ) );
29
+ }
30
+
31
+
32
+ // Display a notice that can be dismissed in case the serial number is inactive
33
+ function add_admin_notice() {
34
+ global $current_user ;
35
+ global $pagenow;
36
+
37
+ $user_id = $current_user->ID;
38
+ do_action( $this->notificationId.'_before_notification_displayed', $current_user, $pagenow );
39
+
40
+ if ( current_user_can( 'manage_options' ) ){
41
+ // Check that the user hasn't already clicked to ignore the message
42
+ if ( ! get_user_meta($user_id, $this->notificationId.'_dismiss_notification' ) ) {
43
+ echo $finalMessage = apply_filters($this->notificationId.'_notification_message','<div class="'. $this->notificationClass .'" >'.$this->notificationMessage.'</div>', $this->notificationMessage);
44
+ }
45
+ do_action( $this->notificationId.'_notification_displayed', $current_user, $pagenow );
46
+ }
47
+ do_action( $this->notificationId.'_after_notification_displayed', $current_user, $pagenow );
48
+ }
49
+
50
+ function dismiss_notification() {
51
+ global $current_user;
52
+
53
+ $user_id = $current_user->ID;
54
+
55
+ do_action( $this->notificationId.'_before_notification_dismissed', $current_user );
56
+
57
+ // If user clicks to ignore the notice, add that to their user meta
58
+ if ( isset( $_GET[$this->notificationId.'_dismiss_notification']) && '0' == $_GET[$this->notificationId.'_dismiss_notification'] )
59
+ add_user_meta( $user_id, $this->notificationId.'_dismiss_notification', 'true', true );
60
+
61
+ do_action( $this->notificationId.'_after_notification_dismissed', $current_user );
62
+ }
63
+ }
64
+
65
+ Class TRP_Plugin_Notifications {
66
+
67
+ public $notifications = array();
68
+ private static $_instance = null;
69
+ private $prefix = 'trp';
70
+ private $menu_slug = 'options-general.php';
71
+ public $pluginPages = array( 'translate-press', 'trp_addons_page' );
72
+
73
+ protected function __construct() {
74
+ add_action( 'admin_init', array( $this, 'dismiss_admin_notifications' ), 200 );
75
+ add_action( 'admin_init', array( $this, 'add_admin_menu_notification_counts' ), 1000 );
76
+ }
77
+
78
+
79
+ function dismiss_admin_notifications() {
80
+ if( ! empty( $_GET[$this->prefix.'_dismiss_admin_notification'] ) ) {
81
+ $notifications = self::get_instance();
82
+ $notifications->dismiss_notification( sanitize_text_field( $_GET[$this->prefix.'_dismiss_admin_notification'] ) );
83
+ }
84
+
85
+ }
86
+
87
+ function add_admin_menu_notification_counts() {
88
+
89
+ global $menu, $submenu;
90
+
91
+ $notifications = TRP_Plugin_Notifications::get_instance();
92
+
93
+ if( ! empty( $menu ) ) {
94
+ foreach( $menu as $menu_position => $menu_data ) {
95
+ if( ! empty( $menu_data[2] ) && $menu_data[2] == $this->menu_slug ) {
96
+ $menu_count = $notifications->get_count_in_menu();
97
+ if( ! empty( $menu_count ) )
98
+ $menu[$menu_position][0] .= '<span class="update-plugins '.$this->prefix.'-update-plugins"><span class="plugin-count">' . $menu_count . '</span></span>';
99
+ }
100
+ }
101
+ }
102
+
103
+ if( ! empty( $submenu[$this->menu_slug] ) ) {
104
+ foreach( $submenu[$this->menu_slug] as $menu_position => $menu_data ) {
105
+ $menu_count = $notifications->get_count_in_submenu( $menu_data[2] );
106
+ if( ! empty( $menu_count ) )
107
+ $submenu[$this->menu_slug][$menu_position][0] .= '<span class="update-plugins '.$this->prefix.'-update-plugins"><span class="plugin-count">' . $menu_count . '</span></span>';
108
+ }
109
+ }
110
+ }
111
+
112
+ /**
113
+ *
114
+ *
115
+ */
116
+ public static function get_instance() {
117
+ if( is_null( self::$_instance ) )
118
+ self::$_instance = new TRP_Plugin_Notifications();
119
+
120
+ return self::$_instance;
121
+ }
122
+
123
+
124
+ /**
125
+ *
126
+ *
127
+ */
128
+ public function add_notification( $notification_id = '', $notification_message = '', $notification_class = 'update-nag', $count_in_menu = true, $count_in_submenu = array() ) {
129
+
130
+ if( empty( $notification_id ) )
131
+ return;
132
+
133
+ if( empty( $notification_message ) )
134
+ return;
135
+
136
+ global $current_user;
137
+
138
+ if( get_user_meta( $current_user->ID, $notification_id . '_dismiss_notification' ) )
139
+ return;
140
+
141
+ $this->notifications[$notification_id] = array(
142
+ 'id' => $notification_id,
143
+ 'message' => $notification_message,
144
+ 'class' => $notification_class,
145
+ 'count_in_menu' => $count_in_menu,
146
+ 'count_in_submenu' => $count_in_submenu
147
+ );
148
+
149
+
150
+ if( $this->is_plugin_page() ) {
151
+ new TRP_Add_General_Notices( $notification_id, $notification_message, $notification_class );
152
+ }
153
+
154
+ }
155
+
156
+
157
+ /**
158
+ *
159
+ *
160
+ */
161
+ public function get_notifications() {
162
+ return $this->notifications;
163
+ }
164
+
165
+
166
+ /**
167
+ *
168
+ *
169
+ */
170
+ public function get_notification( $notification_id = '' ) {
171
+
172
+ if( empty( $notification_id ) )
173
+ return null;
174
+
175
+ $notifications = $this->get_notifications();
176
+
177
+ if( ! empty( $notifications[$notification_id] ) )
178
+ return $notifications[$notification_id];
179
+ else
180
+ return null;
181
+
182
+ }
183
+
184
+
185
+ /**
186
+ *
187
+ *
188
+ */
189
+ public function dismiss_notification( $notification_id = '' ) {
190
+ global $current_user;
191
+ add_user_meta( $current_user->ID, $notification_id . '_dismiss_notification', 'true', true );
192
+ }
193
+
194
+
195
+ /**
196
+ *
197
+ *
198
+ */
199
+ public function get_count_in_menu() {
200
+ $count = 0;
201
+
202
+ foreach( $this->notifications as $notification ) {
203
+ if( ! empty( $notification['count_in_menu'] ) )
204
+ $count++;
205
+ }
206
+
207
+ return $count;
208
+ }
209
+
210
+
211
+ /**
212
+ *
213
+ *
214
+ */
215
+ public function get_count_in_submenu( $submenu = '' ) {
216
+
217
+ if( empty( $submenu ) )
218
+ return 0;
219
+
220
+ $count = 0;
221
+
222
+ foreach( $this->notifications as $notification ) {
223
+ if( empty( $notification['count_in_submenu'] ) )
224
+ continue;
225
+
226
+ if( ! is_array( $notification['count_in_submenu'] ) )
227
+ continue;
228
+
229
+ if( ! in_array( $submenu, $notification['count_in_submenu'] ) )
230
+ continue;
231
+
232
+ $count++;
233
+ }
234
+
235
+ return $count;
236
+
237
+ }
238
+
239
+
240
+ /**
241
+ *
242
+ *
243
+ */
244
+ protected function is_plugin_page() {
245
+ if( !empty( $this->pluginPages ) ){
246
+ foreach ( $this->pluginPages as $pluginPage ){
247
+ if( ! empty( $_GET['page'] ) && false !== strpos( $_GET['page'], $pluginPage ) )
248
+ return true;
249
+
250
+ if( ! empty( $_GET['post_type'] ) && false !== strpos( $_GET['post_type'], $pluginPage ) )
251
+ return true;
252
+
253
+ if( ! empty( $_GET['post'] ) && false !== strpos( get_post_type( (int)$_GET['post'] ), $pluginPage ) )
254
+ return true;
255
+ }
256
+ }
257
+
258
+ return false;
259
+ }
260
+
261
+ }
262
+
263
+
264
+ class TRP_Trigger_Plugin_Notifications{
265
+
266
+ function __construct() {
267
+ add_action( 'admin_init', array( $this, 'add_plugin_notifications' ) );
268
+ }
269
+
270
+ function add_plugin_notifications() {
271
+
272
+ $notifications = TRP_Plugin_Notifications::get_instance();
273
+
274
+ /* only show this notice if there isn't a pretty permalink structure enabled */
275
+ if( !get_option('permalink_structure') ) {
276
+ /* this must be unique */
277
+ $notification_id = 'trp_new_add_on_invoices';
278
+
279
+ $message = '<img style="float: left; margin: 10px 12px 10px 0; max-width: 80px;" src="' . TRP_PLUGIN_URL . 'assets/images/get_param_addon.jpg" />';
280
+ $message .= '<p style="margin-top: 16px;padding-right:30px;">' . sprintf( __('You are not using a permalink structure! Please <a href="%s">enable</a> one or install our <a href="%s">"Language by GET parameter"</a> addon so TranslatePress can function properly.', 'translatepress-multilingual' ), admin_url('options-permalink.php'),admin_url('admin.php?page=trp_addons_page#language-by-get-parameter') ) . '</p>';
281
+ //make sure to use the trp_dismiss_admin_notification arg
282
+ $message .= '<a href="' . add_query_arg(array('trp_dismiss_admin_notification' => $notification_id)) . '" type="button" class="notice-dismiss"><span class="screen-reader-text">' . __('Dismiss this notice.', 'translatepress-multilingual') . '</span></a>';
283
+
284
+ $notifications->add_notification($notification_id, $message, 'trp-notice trp-narrow notice notice-info', true, array('translate-press'));
285
+ }
286
+
287
+ }
288
+
289
+ }
includes/class-settings.php CHANGED
@@ -407,13 +407,11 @@ class TRP_Settings{
407
  'page' => 'trp_license_key'
408
  );
409
  }
410
- else{
411
- $tabs[] = array(
412
- 'name' => __( 'Addons', 'translatepress-multilingual' ),
413
- 'url' => admin_url( 'admin.php?page=trp_addons_page' ),
414
- 'page' => 'trp_addons_page'
415
- );
416
- }
417
 
418
  $active_tab = 'translate-press';
419
  if ( isset( $_GET['page'] ) ){
@@ -422,6 +420,5 @@ class TRP_Settings{
422
 
423
  require ( TRP_PLUGIN_DIR . 'partials/settings-navigation-tabs.php');
424
  }
425
-
426
  }
427
 
407
  'page' => 'trp_license_key'
408
  );
409
  }
410
+ $tabs[] = array(
411
+ 'name' => __( 'Addons', 'translatepress-multilingual' ),
412
+ 'url' => admin_url( 'admin.php?page=trp_addons_page' ),
413
+ 'page' => 'trp_addons_page'
414
+ );
 
 
415
 
416
  $active_tab = 'translate-press';
417
  if ( isset( $_GET['page'] ) ){
420
 
421
  require ( TRP_PLUGIN_DIR . 'partials/settings-navigation-tabs.php');
422
  }
 
423
  }
424
 
includes/class-translation-manager.php CHANGED
@@ -416,7 +416,7 @@ class TRP_Translation_Manager{
416
  }
417
 
418
  $url = $this->url_converter->cur_page_url();
419
- $url = add_query_arg( 'trp-edit-translation', 'true', trailingslashit( $url ) );
420
 
421
  $title = __( 'Translate Page', 'translatepress-multilingual' );
422
  $url_target = '';
416
  }
417
 
418
  $url = $this->url_converter->cur_page_url();
419
+ $url = add_query_arg( 'trp-edit-translation', 'true', $url );
420
 
421
  $title = __( 'Translate Page', 'translatepress-multilingual' );
422
  $url_target = '';
includes/class-translation-render.php CHANGED
@@ -28,8 +28,8 @@ class TRP_Translation_Render{
28
  if( TRP_Translation_Manager::is_ajax_on_frontend() ){
29
  //in this case move forward
30
  }else if( is_admin() ||
31
- ( $TRP_LANGUAGE == $this->settings['default-language'] && ( ! isset( $_REQUEST['trp-edit-translation'] ) || ( isset( $_REQUEST['trp-edit-translation'] ) && $_REQUEST['trp-edit-translation'] != 'preview' ) ) ) ||
32
- ( isset( $_REQUEST['trp-edit-translation']) && $_REQUEST['trp-edit-translation'] == 'true' ) ) {
33
  return;
34
  }
35
 
@@ -302,12 +302,13 @@ class TRP_Translation_Render{
302
  }
303
 
304
  /* sort them here ascending by key where the key is the number of children */
 
305
  ksort($trp_rows);
306
  foreach( $trp_rows as $level ){
307
  foreach( $level as $row ){
308
  $original_gettext_translation_id = $row->getAttribute('data-trpgettextoriginal');
309
- /* Parent node has no other children and no other innertext besides the current node */
310
- if( count( $row->parent()->children ) == 1 && $row->parent()->innertext == $row->outertext ){
311
  $row->outertext = $row->innertext();
312
  $row->parent()->setAttribute('data-no-translation', '');
313
  // we are in the editor
@@ -337,9 +338,9 @@ class TRP_Translation_Render{
337
  }
338
 
339
  // convert to a node
340
- $node_from_value = trp_str_get_html(html_entity_decode(htmlspecialchars_decode($attr_value, ENT_QUOTES)));
341
- foreach ($node_from_value->find('trp-gettext') as $nfv_row) {
342
- $nfv_row->outertext = $nfv_row->innertext();
343
  $row->setAttribute($attr_name, $node_from_value->save() );
344
  if( !$row->has_child() ){// if the node doesn't have children set the needed attributes, else it means that there are other nodes inside so probably they are the ones displayed
345
  $row->setAttribute('data-no-translation', '');
@@ -365,15 +366,42 @@ class TRP_Translation_Render{
365
 
366
  $no_translate_selectors = apply_filters( 'trp_no_translate_selectors', array( '#wpadminbar' ), $TRP_LANGUAGE );
367
 
 
 
 
 
368
  foreach ( $no_translate_selectors as $no_translate_selector ){
369
  foreach ( $html->find( $no_translate_selector ) as $k => $row ){
370
  $row->setAttribute( $no_translate_attribute, '' );
371
  }
372
  }
373
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374
  foreach ( $html->find('text') as $k => $row ){
375
- if($this->full_trim($row->outertext)!="" && $row->parent()->tag!="script" && $row->parent()->tag!="style" && !is_numeric($this->full_trim($row->outertext)) && !preg_match('/^\d+%$/',$this->full_trim($row->outertext))
376
- && !$this->has_ancestor_attribute( $row, $no_translate_attribute ) && $row->parent()->tag != 'title' && strpos($row->outertext,'[vc_') === false ){
 
 
 
 
 
 
 
 
377
  array_push( $translateable_strings, $this->full_trim( $row->outertext ) );
378
  if( $row->parent()->tag == 'button') {
379
  array_push($nodes, array('node' => $row, 'type' => 'button'));
@@ -384,17 +412,25 @@ class TRP_Translation_Render{
384
  }
385
 
386
  foreach ( $html->find('input[type=\'submit\'],input[type=\'button\']') as $k => $row ){
387
- if($this->full_trim($row->value)!="" && !is_numeric($this->full_trim($row->value)) && !preg_match('/^\d+%$/',$this->full_trim($row->value))
388
- && !$this->has_ancestor_attribute( $row, $no_translate_attribute )) {
389
- array_push( $translateable_strings, html_entity_decode( $row->value ) );
390
- array_push( $nodes, array('node'=>$row,'type'=>'submit') );
 
 
 
 
391
  }
392
  }
393
  foreach ( $html->find('input[type=\'text\'],input[type=\'password\'],input[type=\'search\'],input[type=\'email\'],input:not([type]),textarea') as $k => $row ){
394
- if($this->full_trim($row->placeholder)!="" && !is_numeric($this->full_trim($row->placeholder)) && !preg_match('/^\d+%$/',$this->full_trim($row->placeholder))
395
- && !$this->has_ancestor_attribute( $row, $no_translate_attribute )){
396
- array_push( $translateable_strings, html_entity_decode ( $row->placeholder ) );
397
- array_push( $nodes, array('node'=>$row,'type'=>'placeholder') );
 
 
 
 
398
  }
399
  }
400
 
@@ -420,6 +456,10 @@ class TRP_Translation_Render{
420
  'accessor' => 'outertext',
421
  'attribute' => false
422
  ),
 
 
 
 
423
  'page_title' => array(
424
  'accessor' => 'outertext',
425
  'attribute' => false
@@ -453,7 +493,7 @@ class TRP_Translation_Render{
453
  foreach ( $nodes as $i => $node ) {
454
  $translation_available = isset( $translated_strings[$i] );
455
  if ( ! ( $translation_available || $preview_mode ) ){
456
- continue;
457
  }
458
  $current_node_accessor = $node_accessor[ $nodes[$i]['type'] ];
459
  $accessor = $current_node_accessor[ 'accessor' ];
@@ -474,9 +514,6 @@ class TRP_Translation_Render{
474
  $nodes[$i]['node']->$accessor = str_replace( $translateable_string, $translated_strings[$i], $nodes[$i]['node']->$accessor );
475
  }
476
 
477
- if ( $nodes[$i]['type'] == 'image_src' && $nodes[$i]['node']->hasAttribute("srcset") && $nodes[$i]['node']->srcset != "" && $translated_strings[$i] != $translateable_strings[$i]) {
478
- $nodes[$i]['node']->srcset = "";
479
- }
480
  }
481
 
482
  if ( $preview_mode ) {
@@ -708,6 +745,26 @@ class TRP_Translation_Render{
708
  return false;
709
  }
710
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
711
  /**
712
  * Enqueue dynamic translation script.
713
  */
@@ -855,8 +912,8 @@ class TRP_Translation_Render{
855
  */
856
  function callback_add_language_to_url(&$item, $key){
857
  if ( filter_var($item, FILTER_VALIDATE_URL) !== FALSE ) {
858
- $form_language_slug = esc_attr($_REQUEST[ 'trp-form-language' ]);
859
- $form_language = array_search($form_language_slug, $this->settings['url-slugs']);
860
  if ( ! $this->url_converter ) {
861
  $trp = TRP_Translate_Press::get_trp_instance();
862
  $this->url_converter = $trp->get_component('url_converter');
@@ -868,7 +925,7 @@ class TRP_Translation_Render{
868
 
869
  /**
870
  * Function that reverses CDATA string replacement from the content because it breaks the renderer
871
- * @param $content
872
  * @return mixed
873
  */
874
  public function handle_cdata( $output ){
28
  if( TRP_Translation_Manager::is_ajax_on_frontend() ){
29
  //in this case move forward
30
  }else if( is_admin() ||
31
+ ( $TRP_LANGUAGE == $this->settings['default-language'] && ( ! isset( $_REQUEST['trp-edit-translation'] ) || ( isset( $_REQUEST['trp-edit-translation'] ) && $_REQUEST['trp-edit-translation'] != 'preview' ) ) ) ||
32
+ ( isset( $_REQUEST['trp-edit-translation']) && $_REQUEST['trp-edit-translation'] == 'true' ) ) {
33
  return;
34
  }
35
 
302
  }
303
 
304
  /* sort them here ascending by key where the key is the number of children */
305
+ /* here we add support for gettext inside gettext */
306
  ksort($trp_rows);
307
  foreach( $trp_rows as $level ){
308
  foreach( $level as $row ){
309
  $original_gettext_translation_id = $row->getAttribute('data-trpgettextoriginal');
310
+ /* Parent node has no other children and no other innertext besides the current node */
311
+ if( count( $row->parent()->children ) == 1 && $row->parent()->innertext == $row->outertext ){
312
  $row->outertext = $row->innertext();
313
  $row->parent()->setAttribute('data-no-translation', '');
314
  // we are in the editor
338
  }
339
 
340
  // convert to a node
341
+ $node_from_value = trp_str_get_html(html_entity_decode(htmlspecialchars_decode($attr_value, ENT_QUOTES)));
342
+ foreach ($node_from_value->find('trp-gettext') as $nfv_row) {
343
+ $nfv_row->outertext = $nfv_row->innertext();
344
  $row->setAttribute($attr_name, $node_from_value->save() );
345
  if( !$row->has_child() ){// if the node doesn't have children set the needed attributes, else it means that there are other nodes inside so probably they are the ones displayed
346
  $row->setAttribute('data-no-translation', '');
366
 
367
  $no_translate_selectors = apply_filters( 'trp_no_translate_selectors', array( '#wpadminbar' ), $TRP_LANGUAGE );
368
 
369
+ /*
370
+ * process the types of strings we can currently have: no-translate, translation-block, text, input, textarea, etc.
371
+ */
372
+
373
  foreach ( $no_translate_selectors as $no_translate_selector ){
374
  foreach ( $html->find( $no_translate_selector ) as $k => $row ){
375
  $row->setAttribute( $no_translate_attribute, '' );
376
  }
377
  }
378
 
379
+ foreach ( $html->find('.translation-block') as $k => $row ){
380
+ if( $this->full_trim($row->outertext)!=""
381
+ && $row->parent()->tag!="script"
382
+ && $row->parent()->tag!="style"
383
+ && !is_numeric($this->full_trim($row->outertext))
384
+ && !preg_match('/^\d+%$/',$this->full_trim($row->outertext))
385
+ && !$this->has_ancestor_attribute( $row, $no_translate_attribute )
386
+ && $row->parent()->tag != 'title'
387
+ && strpos($row->outertext,'[vc_') === false )
388
+ {
389
+ array_push( $translateable_strings, $this->full_trim( $row->innertext ) );
390
+ array_push( $nodes, array('node' => $row, 'type' => 'block'));
391
+ }
392
+ }
393
+
394
  foreach ( $html->find('text') as $k => $row ){
395
+ if( $this->full_trim($row->outertext)!=""
396
+ && $row->parent()->tag!="script"
397
+ && $row->parent()->tag!="style"
398
+ && !is_numeric($this->full_trim($row->outertext))
399
+ && !preg_match('/^\d+%$/',$this->full_trim($row->outertext))
400
+ && !$this->has_ancestor_attribute( $row, $no_translate_attribute )
401
+ && !$this->has_ancestor_class( $row, 'translation-block')
402
+ && $row->parent()->tag != 'title'
403
+ && strpos($row->outertext,'[vc_') === false )
404
+ {
405
  array_push( $translateable_strings, $this->full_trim( $row->outertext ) );
406
  if( $row->parent()->tag == 'button') {
407
  array_push($nodes, array('node' => $row, 'type' => 'button'));
412
  }
413
 
414
  foreach ( $html->find('input[type=\'submit\'],input[type=\'button\']') as $k => $row ){
415
+ if( $this->full_trim($row->value)!=""
416
+ && !is_numeric($this->full_trim($row->value))
417
+ && !preg_match('/^\d+%$/',$this->full_trim($row->value))
418
+ && !$this->has_ancestor_attribute( $row, $no_translate_attribute )
419
+ && !$this->has_ancestor_class( $row, 'translation-block') )
420
+ {
421
+ array_push( $translateable_strings, html_entity_decode( $row->value ) );
422
+ array_push( $nodes, array('node'=>$row,'type'=>'submit') );
423
  }
424
  }
425
  foreach ( $html->find('input[type=\'text\'],input[type=\'password\'],input[type=\'search\'],input[type=\'email\'],input:not([type]),textarea') as $k => $row ){
426
+ if( $this->full_trim($row->placeholder)!=""
427
+ && !is_numeric($this->full_trim($row->placeholder))
428
+ && !preg_match('/^\d+%$/',$this->full_trim($row->placeholder))
429
+ && !$this->has_ancestor_attribute( $row, $no_translate_attribute )
430
+ && !$this->has_ancestor_class( $row, 'translation-block') )
431
+ {
432
+ array_push( $translateable_strings, html_entity_decode ( $row->placeholder ) );
433
+ array_push( $nodes, array('node'=>$row,'type'=>'placeholder') );
434
  }
435
  }
436
 
456
  'accessor' => 'outertext',
457
  'attribute' => false
458
  ),
459
+ 'block' => array(
460
+ 'accessor' => 'innertext',
461
+ 'attribute' => false
462
+ ),
463
  'page_title' => array(
464
  'accessor' => 'outertext',
465
  'attribute' => false
493
  foreach ( $nodes as $i => $node ) {
494
  $translation_available = isset( $translated_strings[$i] );
495
  if ( ! ( $translation_available || $preview_mode ) ){
496
+ continue;
497
  }
498
  $current_node_accessor = $node_accessor[ $nodes[$i]['type'] ];
499
  $accessor = $current_node_accessor[ 'accessor' ];
514
  $nodes[$i]['node']->$accessor = str_replace( $translateable_string, $translated_strings[$i], $nodes[$i]['node']->$accessor );
515
  }
516
 
 
 
 
517
  }
518
 
519
  if ( $preview_mode ) {
745
  return false;
746
  }
747
 
748
+ /**
749
+ * Whether given node has ancestor with given class.
750
+ *
751
+ * @param object $node Html Node.
752
+ * @param string $class class to search for
753
+ * @return bool Whether given node has ancestor with given class.
754
+ */
755
+ public function has_ancestor_class($node, $class) {
756
+ $currentNode = $node;
757
+
758
+ while($currentNode->parent() && $currentNode->parent()->tag!="html") {
759
+ if(isset($currentNode->parent()->class) && strpos($currentNode->parent()->class, $class) !== false) {
760
+ return true;
761
+ } else {
762
+ $currentNode = $currentNode->parent();
763
+ }
764
+ }
765
+ return false;
766
+ }
767
+
768
  /**
769
  * Enqueue dynamic translation script.
770
  */
912
  */
913
  function callback_add_language_to_url(&$item, $key){
914
  if ( filter_var($item, FILTER_VALIDATE_URL) !== FALSE ) {
915
+ $form_language_slug = esc_attr($_REQUEST[ 'trp-form-language' ]);
916
+ $form_language = array_search($form_language_slug, $this->settings['url-slugs']);
917
  if ( ! $this->url_converter ) {
918
  $trp = TRP_Translate_Press::get_trp_instance();
919
  $this->url_converter = $trp->get_component('url_converter');
925
 
926
  /**
927
  * Function that reverses CDATA string replacement from the content because it breaks the renderer
928
+ * @param $output
929
  * @return mixed
930
  */
931
  public function handle_cdata( $output ){
includes/class-url-converter.php CHANGED
@@ -34,7 +34,12 @@ class TRP_Url_Converter {
34
  $lang_from_url = $this->get_lang_from_url_string( $this->cur_page_url() );
35
 
36
  if ( $lang_from_url == null ) {
37
- header( 'Location: ' . $this->get_url_for_language( $this->settings['default-language'] ) );
 
 
 
 
 
38
  exit;
39
  }
40
  }
34
  $lang_from_url = $this->get_lang_from_url_string( $this->cur_page_url() );
35
 
36
  if ( $lang_from_url == null ) {
37
+ $language_to_redirect = $this->settings['default-language'];
38
+ if ( isset( $this->settings['translation-languages'][0] ) ) {
39
+ $language_to_redirect = $this->settings['translation-languages'][0];
40
+ }
41
+ $TRP_LANGUAGE = $this->settings['default-language'];
42
+ header( 'Location: ' . $this->get_url_for_language( $language_to_redirect ) );
43
  exit;
44
  }
45
  }
index.php CHANGED
@@ -3,10 +3,12 @@
3
  Plugin Name: TranslatePress - Multilingual
4
  Plugin URI: https://translatepress.com/
5
  Description: Experience a better way of translating your WordPress site, with full support for WooCommerce and site builders.
6
- Version: 1.1.4
7
  Author: Cozmoslabs, Razvan Mocanu, Madalin Ungureanu, Cristophor Hurduban
8
  Author URI: https://cozmoslabs.com/
9
  License: GPL2
 
 
10
 
11
  == Copyright ==
12
  Copyright 2017 Cozmoslabs (www.cozmoslabs.com)
3
  Plugin Name: TranslatePress - Multilingual
4
  Plugin URI: https://translatepress.com/
5
  Description: Experience a better way of translating your WordPress site, with full support for WooCommerce and site builders.
6
+ Version: 1.1.5
7
  Author: Cozmoslabs, Razvan Mocanu, Madalin Ungureanu, Cristophor Hurduban
8
  Author URI: https://cozmoslabs.com/
9
  License: GPL2
10
+ WC requires at least: 2.5.0
11
+ WC tested up to: 3.3
12
 
13
  == Copyright ==
14
  Copyright 2017 Cozmoslabs (www.cozmoslabs.com)
partials/addons-settings-page.php CHANGED
@@ -14,7 +14,7 @@
14
  <div class="grid-cell" style="overflow:hidden;">
15
  <a href="https://translatepress.com/pricing/" target="_blank"><img src="<?php echo plugins_url('../assets/images/seo_icon_translatepress.png', __FILE__) ?>" alt="SEO" style="float: left; margin: 0 1.5rem 1.5rem 0;"></a>
16
  <h3><a href=" <?php echo trp_add_affiliate_id_to_link('https://translatepress.com/pricing/?utm_source=wpbackend&utm_medium=clientsite&utm_content=addons_tab&utm_campaign=tpfree') ?> " target="_blank"> SEO Pack</a></h3>
17
- <p>SEO support for page slug, page title, description and facebook and twitter social graph information. The HTML lang attribute is properly set.</p>
18
  </div>
19
  </div>
20
 
@@ -27,6 +27,13 @@
27
  </div>
28
  </div>
29
 
 
 
 
 
 
 
 
30
  <div class="grid">
31
  <div class="grid-cell" style="overflow:hidden;">
32
  <a href="https://translatepress.com/pricing/" target="_blank"><img src="<?php echo plugins_url('../assets/images/translator-accounts-addon.png', __FILE__) ?>" alt="Translator Account" style="float: left; margin: 0 1.5rem 1.5rem 0;"></a>
@@ -34,4 +41,35 @@
34
  <p>Create translator accounts for new users or allow existing users <br/>that are not administrators to translate your website.</p>
35
  </div>
36
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  </div>
14
  <div class="grid-cell" style="overflow:hidden;">
15
  <a href="https://translatepress.com/pricing/" target="_blank"><img src="<?php echo plugins_url('../assets/images/seo_icon_translatepress.png', __FILE__) ?>" alt="SEO" style="float: left; margin: 0 1.5rem 1.5rem 0;"></a>
16
  <h3><a href=" <?php echo trp_add_affiliate_id_to_link('https://translatepress.com/pricing/?utm_source=wpbackend&utm_medium=clientsite&utm_content=addons_tab&utm_campaign=tpfree') ?> " target="_blank"> SEO Pack</a></h3>
17
+ <p>SEO support for page slug, page title, description and facebook and twitter social graph information. </br> The HTML lang attribute is properly set.</p>
18
  </div>
19
  </div>
20
 
27
  </div>
28
  </div>
29
 
30
+ <div class="grid feat-header">
31
+ <div class="grid-cell">
32
+ <h2>Pro Addons</h2>
33
+ <p>These addons extend your translation plugin and are available in the Business and Developer plans.</p>
34
+ </div>
35
+ </div>
36
+
37
  <div class="grid">
38
  <div class="grid-cell" style="overflow:hidden;">
39
  <a href="https://translatepress.com/pricing/" target="_blank"><img src="<?php echo plugins_url('../assets/images/translator-accounts-addon.png', __FILE__) ?>" alt="Translator Account" style="float: left; margin: 0 1.5rem 1.5rem 0;"></a>
41
  <p>Create translator accounts for new users or allow existing users <br/>that are not administrators to translate your website.</p>
42
  </div>
43
  </div>
44
+
45
+ <div class="grid">
46
+ <div class="grid-cell" style="overflow:hidden;">
47
+ <a href="https://translatepress.com/pricing/" target="_blank"><img src="<?php echo plugins_url('../assets/images/view-as-addon.png', __FILE__) ?>" alt="Browse As User Role" style="float: left; margin: 0 1.5rem 1.5rem 0;"></a>
48
+ <h3><a href=" <?php echo trp_add_affiliate_id_to_link('https://translatepress.com/pricing/?utm_source=wpbackend&utm_medium=clientsite&utm_content=addons_tab&utm_campaign=tpfree') ?> " target="_blank"> Browse As User Role</a></h3>
49
+ <p>Navigate your website just like a particular user role would. Really useful for dynamic content or hidden content that appears for particular users.</p>
50
+ </div>
51
+ </div>
52
+
53
+ <div class="grid">
54
+ <div class="grid-cell" style="overflow:hidden;">
55
+ <a href="https://translatepress.com/pricing/" target="_blank"><img src="<?php echo plugins_url('../assets/images/menu_based_on_lang.png', __FILE__) ?>" alt="Navigation Based on Language" style="float: left; margin: 0 1.5rem 1.5rem 0;"></a>
56
+ <h3><a href=" <?php echo trp_add_affiliate_id_to_link('https://translatepress.com/pricing/?utm_source=wpbackend&utm_medium=clientsite&utm_content=addons_tab&utm_campaign=tpfree') ?> " target="_blank"> Navigation Based on Language</a></h3>
57
+ <p>Configure different menu items for different languages.</p>
58
+ </div>
59
+ </div>
60
+
61
+ <div class="grid feat-header">
62
+ <div class="grid-cell">
63
+ <h2>Free Addons</h2>
64
+ <p>Extend your translation plugin with these free addons.</p>
65
+ </div>
66
+ </div>
67
+
68
+ <div class="grid">
69
+ <div class="grid-cell" style="overflow:hidden;">
70
+ <a href="https://translatepress.com/docs/addons/language-get-parameter/" target="_blank"><img src="<?php echo plugins_url('../assets/images/get_param_addon.jpg', __FILE__) ?>" alt="Language by GET parameter" style="float: left; margin: 0 1.5rem 1.5rem 0;"></a>
71
+ <h3 id="language-by-get-parameter"><a href=" <?php echo trp_add_affiliate_id_to_link('https://translatepress.com/pricing/?utm_source=wpbackend&utm_medium=clientsite&utm_content=addons_tab&utm_campaign=tpfree') ?> " target="_blank"> Language by GET parameter </a></h3>
72
+ <p>Use GET parameter to encode language in the url, replacing the language directory. </br> Your urls will look like this: www.example.com?lang=en</p>
73
+ </div>
74
+ </div>
75
  </div>
partials/main-settings-page.php CHANGED
@@ -46,7 +46,7 @@
46
  <option value="yes" <?php selected( $this->settings['add-subdirectory-to-default-language'], 'yes' ); ?>><?php _e( 'Yes', 'translatepress-multilingual') ?></option>
47
  </select>
48
  <p class="description">
49
- <?php _e( 'Select Yes if you want to add the subdirectory in the url for the default language.', 'translatepress-multilingual' ); ?>
50
  </p>
51
  </td>
52
  </tr>
46
  <option value="yes" <?php selected( $this->settings['add-subdirectory-to-default-language'], 'yes' ); ?>><?php _e( 'Yes', 'translatepress-multilingual') ?></option>
47
  </select>
48
  <p class="description">
49
+ <?php _e( 'Select Yes if you want to add the subdirectory in the url for the default language.</br>By selecting Yes, the default language seen by website visitors will become the first one in the "Translation Languages" list.', 'translatepress-multilingual' ); ?>
50
  </p>
51
  </td>
52
  </tr>
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: cozmoslabs, razvan.mo, madalin.ungureanu, cristophor
3
  Donate link: https://www.cozmoslabs.com/
4
  Tags: translate, translation, multilingual, automatic translation, front-end translation, google translate, bilingual
5
  Requires at least: 3.1.0
6
- Tested up to: 4.9.2
7
- Stable tag: 1.1.4
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -53,6 +53,10 @@ TranslatePress - Multilingual has a range of premium [Add-ons](https://translate
53
  * [Browse as User Role](https://translatepress.com/docs/addons/browse-as-role/?utm_source=wp.org&utm_medium=tp-description-page&utm_campaign=TPFree) - view and translate content that is visible only to a particular user role
54
  * [Navigation Based on Language](https://translatepress.com/docs/addons/navigate-based-language/?utm_source=wp.org&utm_medium=tp-description-page&utm_campaign=TPFree) - configure and display different menu items for different languages
55
 
 
 
 
 
56
  = Website =
57
 
58
  [translatepress.com](https://translatepress.com/?utm_source=wp.org&utm_medium=tp-description-page&utm_campaign=TPFree)
@@ -108,6 +112,15 @@ For more information please check out [TranslatePress documentation](https://tra
108
  6. Menu Language Switcher
109
 
110
  == Changelog ==
 
 
 
 
 
 
 
 
 
111
  = 1.1.4 =
112
  * Filter to allow adding new language: 'trp_wp_languages'
113
  * Fixed issue with get_permalink() in ajax calls that was not returning the propper language
3
  Donate link: https://www.cozmoslabs.com/
4
  Tags: translate, translation, multilingual, automatic translation, front-end translation, google translate, bilingual
5
  Requires at least: 3.1.0
6
+ Tested up to: 4.9.4
7
+ Stable tag: 1.1.5
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
53
  * [Browse as User Role](https://translatepress.com/docs/addons/browse-as-role/?utm_source=wp.org&utm_medium=tp-description-page&utm_campaign=TPFree) - view and translate content that is visible only to a particular user role
54
  * [Navigation Based on Language](https://translatepress.com/docs/addons/navigate-based-language/?utm_source=wp.org&utm_medium=tp-description-page&utm_campaign=TPFree) - configure and display different menu items for different languages
55
 
56
+ **Free Add-ons**
57
+
58
+ * [Language by GET parameter](https://translatepress.com/docs/addons/language-get-parameter/?utm_source=wp.org&utm_medium=tp-description-page&utm_campaign=TPFree) - enables the language in the URL to be encoded as a GET Parameter
59
+
60
  = Website =
61
 
62
  [translatepress.com](https://translatepress.com/?utm_source=wp.org&utm_medium=tp-description-page&utm_campaign=TPFree)
112
  6. Menu Language Switcher
113
 
114
  == Changelog ==
115
+ = 1.1.5 =
116
+ Added support for translation blocks using the css class .translation-block.
117
+ Added possibility to choose a different language as default language seen by website visitors.
118
+ Updated add-ons settings page with the missing add-ons, added Language by GET parameter addon
119
+ Fixed issue with the [language-switcher] in a post or page that broke saving the page when Yoast SEO plugin is active
120
+ Added a plugin notification class and a notification for pretty permalinks
121
+ Added WooCommerce compatibility tag
122
+ Small css improvements
123
+
124
  = 1.1.4 =
125
  * Filter to allow adding new language: 'trp_wp_languages'
126
  * Fixed issue with get_permalink() in ajax calls that was not returning the propper language