Lingotek Translation - Version 1.2.9

Version Description

(2017-6-15) =

  • Fixed a bug that displayed an error upon installing the plugin.
  • Fixed a bug that was breaking the String Groups page.
  • The real-time status updater has been fixed.
  • Statuses are saved correctly when callbacks are received quickly.
Download this release

Release Info

Developer robertdhanna
Plugin Icon 128x128 Lingotek Translation
Version 1.2.9
Comparing to
See all releases

Code changes from version 1.2.8 to 1.2.9

Files changed (79) hide show
  1. admin/actions.php +17 -1
  2. admin/admin.php +34 -17
  3. admin/content-table.php +0 -0
  4. admin/custom-fields-table.php +0 -0
  5. admin/filters-columns.php +3 -0
  6. admin/filters-media.php +0 -0
  7. admin/filters-post.php +0 -0
  8. admin/filters-term.php +0 -0
  9. admin/manage/view-content.php +1 -1
  10. admin/manage/view-custom-fields.php +0 -0
  11. admin/manage/view-edit-profile.php +0 -0
  12. admin/manage/view-profiles.php +0 -0
  13. admin/manage/view-string-groups.php +2 -1
  14. admin/manage/view-strings.php +0 -0
  15. admin/post-actions.php +0 -0
  16. admin/profiles-table.php +0 -0
  17. admin/settings.php +0 -0
  18. admin/settings/connect-account.php +0 -0
  19. admin/settings/view-account.php +0 -0
  20. admin/settings/view-defaults.php +0 -0
  21. admin/settings/view-preferences.php +0 -0
  22. admin/settings/view-utilities.php +0 -0
  23. admin/string-actions.php +0 -0
  24. admin/strings-table.php +0 -0
  25. admin/table-string.php +0 -0
  26. admin/term-actions.php +0 -0
  27. admin/tutorial/content.php +0 -0
  28. admin/tutorial/credits.php +5 -0
  29. admin/tutorial/faq.php +0 -0
  30. admin/tutorial/features.php +0 -0
  31. admin/tutorial/img/add-languages.png +0 -0
  32. admin/tutorial/img/add-page.png +0 -0
  33. admin/tutorial/img/add-page2.png +0 -0
  34. admin/tutorial/img/automatic-translation.gif +0 -0
  35. admin/tutorial/img/automatic-translation.png +0 -0
  36. admin/tutorial/img/check-status.png +0 -0
  37. admin/tutorial/img/content-types.png +0 -0
  38. admin/tutorial/img/dashboard.png +0 -0
  39. admin/tutorial/img/polylang-compatible.png +0 -0
  40. admin/tutorial/img/pro-translation.png +0 -0
  41. admin/tutorial/img/professional-translation.png +0 -0
  42. admin/tutorial/img/ready-to-upload.png +0 -0
  43. admin/tutorial/img/request-translations.png +0 -0
  44. admin/tutorial/img/translation-profiles.png +0 -0
  45. admin/tutorial/img/translation-services.png +0 -0
  46. admin/tutorial/img/translations-downloaded.png +0 -0
  47. admin/tutorial/img/translations-ready-for-download.png +0 -0
  48. admin/tutorial/img/translations-underway.png +0 -0
  49. admin/tutorial/img/workbench-full.png +0 -0
  50. admin/tutorial/img/workbench.png +0 -0
  51. admin/utilities.php +0 -0
  52. admin/view-dashboard.php +0 -0
  53. admin/view-manage.php +0 -0
  54. admin/view-network.php +0 -0
  55. admin/view-tutorial.php +0 -0
  56. admin/wp-import.php +0 -0
  57. css/admin.css +0 -0
  58. img/lingotek-chevrons-blue.png +0 -0
  59. img/lingotek-icon.png +0 -0
  60. img/lingotek-white.png +0 -0
  61. include/api.php +0 -0
  62. include/callback.php +3 -3
  63. include/dashboard.php +0 -0
  64. include/group-post.php +0 -0
  65. include/group-string.php +0 -0
  66. include/group-term.php +0 -0
  67. include/group.php +44 -7
  68. include/http.php +0 -0
  69. include/model.php +2 -2
  70. include/plugins-compat.php +0 -0
  71. include/pointer.php +0 -0
  72. js/defaults.js +0 -0
  73. js/progress.js +0 -0
  74. js/updater.js +0 -0
  75. languages/wp-lingotek-fr_FR.mo +0 -0
  76. languages/wp-lingotek-fr_FR.po +0 -0
  77. lingotek.php +75 -47
  78. readme.txt +9 -2
  79. uninstall.php +0 -0
admin/actions.php CHANGED
@@ -221,6 +221,7 @@ abstract class Lingotek_Actions {
221
  * @param string $additional parameters to add (js, target)
222
  */
223
  public static function display_icon( $name, $link, $additional = '' ) {
 
224
  return sprintf('<a class="lingotek-color dashicons dashicons-%s" title="%s" href="%s"%s></a>',
225
  self::$icons[ $name ]['icon'], self::$icons[ $name ]['title'], esc_url( $link ), $additional);
226
  }
@@ -249,6 +250,7 @@ abstract class Lingotek_Actions {
249
  public function upload_icon( $object_id, $confirm = false ) {
250
  $args = array( $this->type => $object_id, 'action' => 'lingotek-upload', 'noheader' => true );
251
  $link = wp_nonce_url( defined( 'DOING_AJAX' ) && DOING_AJAX ? add_query_arg( $args, wp_get_referer() ) : add_query_arg( $args ), 'lingotek-upload' );
 
252
  return self::display_icon( 'upload', $link, $confirm ? self::$confirm_message : '' );
253
  }
254
 
@@ -262,6 +264,7 @@ abstract class Lingotek_Actions {
262
  public function copy_icon( $object_id, $target, $confirm = false ) {
263
  $args = array( $this->type => $object_id, 'target' => $target, 'action' => 'lingotek-copy', 'noheader' => true );
264
  $link = wp_nonce_url( defined( 'DOING_AJAX' ) && DOING_AJAX ? add_query_arg( $args, wp_get_referer() ) : add_query_arg( $args ), 'lingotek-copy' );
 
265
  return self::display_icon( 'copy', $link, $confirm ? self::$confirm_message : '' );
266
  }
267
 
@@ -275,6 +278,7 @@ abstract class Lingotek_Actions {
275
  public static function importing_icon( $document ) {
276
  $args = array( 'document_id' => $document->document_id, 'action' => 'lingotek-status', 'noheader' => true );
277
  $link = wp_nonce_url( defined( 'DOING_AJAX' ) && DOING_AJAX ? add_query_arg( $args, wp_get_referer() ) : add_query_arg( $args ), 'lingotek-status' );
 
278
  return self::display_icon( 'importing', $link );
279
  }
280
 
@@ -290,14 +294,17 @@ abstract class Lingotek_Actions {
290
  if ( isset( $document->translations[ $language->locale ] ) ) {
291
  if ( 'ready' === $document->translations[ $language->locale ] ) {
292
  $link = wp_nonce_url( add_query_arg( array( 'document_id' => $document->document_id, 'locale' => $language->locale, 'action' => 'lingotek-download', 'noheader' => true ) ), 'lingotek-download' );
 
293
  return self::display_icon( $document->translations[ $language->locale ], $link );
294
  } elseif ( 'not-current' === $document->translations[ $language->locale ] ) {
295
  return '<div class="lingotek-color dashicons dashicons-no"></div>';
296
  } else {
 
297
  $link = self::workbench_link( $document->document_id, $language->lingotek_locale );
298
  return self::display_icon( $document->translations[ $language->locale ], $link, ' target="_blank"' );
299
  }
300
  } else {
 
301
  $link = wp_nonce_url( add_query_arg( array( 'document_id' => $document->document_id, 'locale' => $language->locale, 'action' => 'lingotek-request', 'noheader' => true ) ), 'lingotek-request' );
302
  return self::display_icon( 'request', $link );
303
  }
@@ -316,16 +323,25 @@ abstract class Lingotek_Actions {
316
  $action = $args['action'];
317
  $args['action'] = 'lingotek-' . $action;
318
  $args['noheader'] = true;
 
 
319
 
320
  return sprintf(
321
  '<a class="lingotek-color" title="%s" href="%s"%s>%s</a>',
322
  self::$actions[ $action ]['description'],
323
- wp_nonce_url( defined( 'DOING_AJAX' ) && DOING_AJAX ? add_query_arg( $args, wp_get_referer() ) : add_query_arg( $args ), 'lingotek-' . $action ),
324
  empty( $warning ) ? '' : self::$confirm_message,
325
  self::$actions[ $action ]['action']
326
  );
327
  }
328
 
 
 
 
 
 
 
 
329
  /**
330
  * Adds a row action link
331
  *
221
  * @param string $additional parameters to add (js, target)
222
  */
223
  public static function display_icon( $name, $link, $additional = '' ) {
224
+ self::link_to_settings_if_not_connected($link);
225
  return sprintf('<a class="lingotek-color dashicons dashicons-%s" title="%s" href="%s"%s></a>',
226
  self::$icons[ $name ]['icon'], self::$icons[ $name ]['title'], esc_url( $link ), $additional);
227
  }
250
  public function upload_icon( $object_id, $confirm = false ) {
251
  $args = array( $this->type => $object_id, 'action' => 'lingotek-upload', 'noheader' => true );
252
  $link = wp_nonce_url( defined( 'DOING_AJAX' ) && DOING_AJAX ? add_query_arg( $args, wp_get_referer() ) : add_query_arg( $args ), 'lingotek-upload' );
253
+ self::link_to_settings_if_not_connected($link);
254
  return self::display_icon( 'upload', $link, $confirm ? self::$confirm_message : '' );
255
  }
256
 
264
  public function copy_icon( $object_id, $target, $confirm = false ) {
265
  $args = array( $this->type => $object_id, 'target' => $target, 'action' => 'lingotek-copy', 'noheader' => true );
266
  $link = wp_nonce_url( defined( 'DOING_AJAX' ) && DOING_AJAX ? add_query_arg( $args, wp_get_referer() ) : add_query_arg( $args ), 'lingotek-copy' );
267
+ self::link_to_settings_if_not_connected($link);
268
  return self::display_icon( 'copy', $link, $confirm ? self::$confirm_message : '' );
269
  }
270
 
278
  public static function importing_icon( $document ) {
279
  $args = array( 'document_id' => $document->document_id, 'action' => 'lingotek-status', 'noheader' => true );
280
  $link = wp_nonce_url( defined( 'DOING_AJAX' ) && DOING_AJAX ? add_query_arg( $args, wp_get_referer() ) : add_query_arg( $args ), 'lingotek-status' );
281
+ self::link_to_settings_if_not_connected($link);
282
  return self::display_icon( 'importing', $link );
283
  }
284
 
294
  if ( isset( $document->translations[ $language->locale ] ) ) {
295
  if ( 'ready' === $document->translations[ $language->locale ] ) {
296
  $link = wp_nonce_url( add_query_arg( array( 'document_id' => $document->document_id, 'locale' => $language->locale, 'action' => 'lingotek-download', 'noheader' => true ) ), 'lingotek-download' );
297
+ self::link_to_settings_if_not_connected($link);
298
  return self::display_icon( $document->translations[ $language->locale ], $link );
299
  } elseif ( 'not-current' === $document->translations[ $language->locale ] ) {
300
  return '<div class="lingotek-color dashicons dashicons-no"></div>';
301
  } else {
302
+ self::link_to_settings_if_not_connected($link);
303
  $link = self::workbench_link( $document->document_id, $language->lingotek_locale );
304
  return self::display_icon( $document->translations[ $language->locale ], $link, ' target="_blank"' );
305
  }
306
  } else {
307
+ self::link_to_settings_if_not_connected($link);
308
  $link = wp_nonce_url( add_query_arg( array( 'document_id' => $document->document_id, 'locale' => $language->locale, 'action' => 'lingotek-request', 'noheader' => true ) ), 'lingotek-request' );
309
  return self::display_icon( 'request', $link );
310
  }
323
  $action = $args['action'];
324
  $args['action'] = 'lingotek-' . $action;
325
  $args['noheader'] = true;
326
+ $link = wp_nonce_url( defined( 'DOING_AJAX' ) && DOING_AJAX ? add_query_arg( $args, wp_get_referer() ) : add_query_arg( $args ), 'lingotek-' . $action );
327
+ self::link_to_settings_if_not_connected($link);
328
 
329
  return sprintf(
330
  '<a class="lingotek-color" title="%s" href="%s"%s>%s</a>',
331
  self::$actions[ $action ]['description'],
332
+ $link,
333
  empty( $warning ) ? '' : self::$confirm_message,
334
  self::$actions[ $action ]['action']
335
  );
336
  }
337
 
338
+ private static function link_to_settings_if_not_connected(&$link)
339
+ {
340
+ if (! get_option('lingotek_token') || ! get_option('lingotek_community')) {
341
+ $link = get_site_url(null, '/wp-admin/admin.php?page=lingotek-translation_settings');
342
+ }
343
+ }
344
+
345
  /**
346
  * Adds a row action link
347
  *
admin/admin.php CHANGED
@@ -45,11 +45,12 @@ class Lingotek_Admin {
45
  $lgtm = &$GLOBALS['wp_lingotek']->model;
46
  $pllm = $GLOBALS['polylang']->model;
47
  $languages = pll_languages_list( array( 'fields' => 'locale' ) );
48
- $object_ids = filter_input( INPUT_POST, 'check_ids' );
 
49
  if ( null === $object_ids ) {
50
  return;
51
  }
52
- $terms_translations = filter_input( INPUT_POST, 'terms_translations' );
53
  $terms = ! empty( $terms_translations );
54
 
55
  // The main array consists of ids and nonces. Each id has a source language, languages with statuses, and a workbench link.
@@ -57,10 +58,10 @@ class Lingotek_Admin {
57
  foreach ( $object_ids as $object_id ) {
58
  $id = $object_id;
59
  $type = $terms ? 'term' : 'post';
60
- $taxonomy = filter_input( INPUT_POST, 'taxonomy' );
61
  if ( ! empty( $taxonomy ) ) {
62
  if ( strpos( $taxonomy, '&' ) ) {
63
- $taxonomy = strstr( filter_input( INPUT_POST, 'taxonomy' ), '&', true );
64
  }
65
  } else {
66
  $taxonomy = get_post_type( $id );
@@ -73,9 +74,9 @@ class Lingotek_Admin {
73
  'source_status' => null,
74
  );
75
 
76
- $document = $lgtm->get_group( $type, $object_id );
77
  if ( $document && ! isset( $document->source ) && count( $document->desc_array ) >= 3 ) {
78
- $content_metadata[ $id ]['existing_trans'] = true;
79
  }
80
  if ( $document && isset( $document->source ) && isset( $document->document_id ) && isset( $document->status ) && isset( $document->translations ) ) {
81
  if ( $document->source !== (int) $object_id ) {
@@ -89,12 +90,12 @@ class Lingotek_Admin {
89
  if ( count( $existing_translations ) > 1 ) {
90
  $content_metadata[ $id ]['existing_trans'] = true;
91
  }
92
- $content_metadata[ $id ]['source'] = $source_language;
93
- $content_metadata[ $id ]['doc_id'] = $document->document_id;
94
- $content_metadata[ $id ]['source_id'] = $document->source;
95
- $content_metadata[ $id ]['source_status'] = $document->status;
96
- $target_status = 'edited' === $document->status || null === $document->status ? 'edited' : 'current';
97
- $content_metadata[ $id ][ $source_language ]['status'] = $document->source === $object_id ? $document->status : $target_status;
98
 
99
  if ( is_array( $document->translations ) ) {
100
  foreach ( $document->translations as $locale => $translation_status ) {
@@ -122,10 +123,10 @@ class Lingotek_Admin {
122
  }
123
  }
124
 
125
- $language = 'post' === $type ? pll_get_post_language( $id ) : pll_get_term_language( $id );
126
- $language = $pllm->get_language( $language );
127
  if ( $language ) {
128
- $profile = Lingotek_Model::get_profile( $taxonomy, $language, $id );
129
  if ( 'disabled' === $profile['profile'] && false === $content_metadata[ $id ]['source'] ) {
130
  $content_metadata[ $id ]['source'] = 'disabled';
131
  }
@@ -352,6 +353,15 @@ class Lingotek_Admin {
352
  $resources = get_option( 'lingotek_community_resources' );
353
  $options = array(
354
  'manual' => __( 'Manual', 'lingotek-translation' ),
 
 
 
 
 
 
 
 
 
355
  'automatic' => __( 'Automatic', 'lingotek-translation' ),
356
  );
357
 
@@ -363,7 +373,7 @@ class Lingotek_Admin {
363
  ),
364
  'download' => array(
365
  'label' => __( 'Download translations', 'lingotek-translation' ),
366
- 'options' => $options,
367
  'description' => __( 'How should completed translations be downloaded to WordPress?', 'lingotek-translation' ),
368
  ),
369
  'project_id' => array(
@@ -493,7 +503,7 @@ class Lingotek_Admin {
493
  $primary_filter_id = array_search( 'okf_json@with-html-subfilter.fprm', $filters, true );
494
  $secondary_filter_id = array_search( 'okf_html@wordpress.fprm', $filters, true );
495
  $defaults = get_option( 'lingotek_defaults' );
496
- if ( null === $defaults ) {
497
  $defaults['primary_filter_id'] = $primary_filter_id;
498
  $defaults['secondary_filter_id'] = $secondary_filter_id;
499
  update_option( 'lingotek_defaults', $defaults );
@@ -559,11 +569,18 @@ class Lingotek_Admin {
559
  * @since 0.1.0
560
  */
561
  public function display_manage_page() {
 
 
 
 
 
 
562
  if ( self::has_token_details() ) {
563
  include( LINGOTEK_ADMIN_INC . '/view-manage.php' );
564
  } else {
565
  $this->display_settings_page();
566
  }
 
567
  }
568
 
569
  /**
45
  $lgtm = &$GLOBALS['wp_lingotek']->model;
46
  $pllm = $GLOBALS['polylang']->model;
47
  $languages = pll_languages_list( array( 'fields' => 'locale' ) );
48
+ $post_vars = filter_input_array(INPUT_POST);
49
+ $object_ids = $post_vars['check_ids'];
50
  if ( null === $object_ids ) {
51
  return;
52
  }
53
+ $terms_translations = $post_vars['terms_translations'];
54
  $terms = ! empty( $terms_translations );
55
 
56
  // The main array consists of ids and nonces. Each id has a source language, languages with statuses, and a workbench link.
58
  foreach ( $object_ids as $object_id ) {
59
  $id = $object_id;
60
  $type = $terms ? 'term' : 'post';
61
+ $taxonomy = $post_vars['taxonomy'];
62
  if ( ! empty( $taxonomy ) ) {
63
  if ( strpos( $taxonomy, '&' ) ) {
64
+ $taxonomy = strstr( $taxonomy, '&', true );
65
  }
66
  } else {
67
  $taxonomy = get_post_type( $id );
74
  'source_status' => null,
75
  );
76
 
77
+ $document = $lgtm->get_group( $type, $object_id );
78
  if ( $document && ! isset( $document->source ) && count( $document->desc_array ) >= 3 ) {
79
+ $content_metadata[ $id ]['existing_trans'] = true;
80
  }
81
  if ( $document && isset( $document->source ) && isset( $document->document_id ) && isset( $document->status ) && isset( $document->translations ) ) {
82
  if ( $document->source !== (int) $object_id ) {
90
  if ( count( $existing_translations ) > 1 ) {
91
  $content_metadata[ $id ]['existing_trans'] = true;
92
  }
93
+ $content_metadata[ $id ]['source'] = $source_language;
94
+ $content_metadata[ $id ]['doc_id'] = $document->document_id;
95
+ $content_metadata[ $id ]['source_id'] = $document->source;
96
+ $content_metadata[ $id ]['source_status'] = $document->status;
97
+ $target_status = 'edited' === $document->status || null === $document->status ? 'edited' : $document->status;
98
+ $content_metadata[ $id ][ $source_language ]['status'] = $document->source === $object_id ? $document->status : $target_status;
99
 
100
  if ( is_array( $document->translations ) ) {
101
  foreach ( $document->translations as $locale => $translation_status ) {
123
  }
124
  }
125
 
126
+ $language = 'post' === $type ? pll_get_post_language( $id ) : pll_get_term_language( $id );
127
+ $language = $pllm->get_language( $language );
128
  if ( $language ) {
129
+ $profile = Lingotek_Model::get_profile( $taxonomy, $language, $id );
130
  if ( 'disabled' === $profile['profile'] && false === $content_metadata[ $id ]['source'] ) {
131
  $content_metadata[ $id ]['source'] = 'disabled';
132
  }
353
  $resources = get_option( 'lingotek_community_resources' );
354
  $options = array(
355
  'manual' => __( 'Manual', 'lingotek-translation' ),
356
+ );
357
+
358
+
359
+ if (/**get_option('lingotek_automatic_enabled')*/ true) {
360
+ $options['automatic'] = __( 'Automatic', 'lingotek-translation' );
361
+ }
362
+
363
+ $download_options = array(
364
+ 'manual' => __( 'Manual', 'lingotek-translation' ),
365
  'automatic' => __( 'Automatic', 'lingotek-translation' ),
366
  );
367
 
373
  ),
374
  'download' => array(
375
  'label' => __( 'Download translations', 'lingotek-translation' ),
376
+ 'options' => $download_options,
377
  'description' => __( 'How should completed translations be downloaded to WordPress?', 'lingotek-translation' ),
378
  ),
379
  'project_id' => array(
503
  $primary_filter_id = array_search( 'okf_json@with-html-subfilter.fprm', $filters, true );
504
  $secondary_filter_id = array_search( 'okf_html@wordpress.fprm', $filters, true );
505
  $defaults = get_option( 'lingotek_defaults' );
506
+ if ( !$defaults ) {
507
  $defaults['primary_filter_id'] = $primary_filter_id;
508
  $defaults['secondary_filter_id'] = $secondary_filter_id;
509
  update_option( 'lingotek_defaults', $defaults );
569
  * @since 0.1.0
570
  */
571
  public function display_manage_page() {
572
+
573
+ /**
574
+ * If we need to perform a redirect we don't want to get the Cannot Modify Headers error so we write
575
+ * our data to the output buffer and before performing any sort of redirection we can flush the output buffer.
576
+ */
577
+ ob_start();
578
  if ( self::has_token_details() ) {
579
  include( LINGOTEK_ADMIN_INC . '/view-manage.php' );
580
  } else {
581
  $this->display_settings_page();
582
  }
583
+ ob_end_flush();
584
  }
585
 
586
  /**
admin/content-table.php CHANGED
File without changes
admin/custom-fields-table.php CHANGED
File without changes
admin/filters-columns.php CHANGED
@@ -178,6 +178,7 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
178
  'href' => array(),
179
  'class' => array(),
180
  'title' => array(),
 
181
  ),
182
  'div' => array(
183
  'class' => array(),
@@ -221,6 +222,7 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
221
  'href' => array(),
222
  'class' => array(),
223
  'title' => array(),
 
224
  ),
225
  'div' => array(
226
  'class' => array(),
@@ -271,6 +273,7 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
271
  'href' => array(),
272
  'class' => array(),
273
  'title' => array(),
 
274
  ),
275
  );
276
  echo wp_kses( Lingotek_Actions::display_error_icon( 'error', $api_error ), $allowed_html );
178
  'href' => array(),
179
  'class' => array(),
180
  'title' => array(),
181
+ 'target' => array()
182
  ),
183
  'div' => array(
184
  'class' => array(),
222
  'href' => array(),
223
  'class' => array(),
224
  'title' => array(),
225
+ 'target' => array()
226
  ),
227
  'div' => array(
228
  'class' => array(),
273
  'href' => array(),
274
  'class' => array(),
275
  'title' => array(),
276
+ 'target' => array()
277
  ),
278
  );
279
  echo wp_kses( Lingotek_Actions::display_error_icon( 'error', $api_error ), $allowed_html );
admin/filters-media.php CHANGED
File without changes
admin/filters-post.php CHANGED
File without changes
admin/filters-term.php CHANGED
File without changes
admin/manage/view-content.php CHANGED
@@ -78,7 +78,7 @@ else {
78
 
79
  foreach ($data as $key => $item) {
80
  // default profile is manual except for post
81
- $data[$key]['profile'] = empty($content_types[$key]['profile']) ? ('post' === $key ? 'automatic' : ('page' === $key ? 'manual' : 'disabled')) : $content_types[$key]['profile'];
82
  $data[$key]['sources'] = empty($content_types[$key]['sources']) ? array() : $content_types[$key]['sources'];
83
  if (!empty($content_types[$key]['fields']))
84
  $data[$key]['fields']['value'] = $content_types[$key]['fields'];
78
 
79
  foreach ($data as $key => $item) {
80
  // default profile is manual except for post
81
+ $data[$key]['profile'] = empty($content_types[$key]['profile']) ? ('post' === $key || 'page' === $key ? 'manual' : 'disabled') : $content_types[$key]['profile'];
82
  $data[$key]['sources'] = empty($content_types[$key]['sources']) ? array() : $content_types[$key]['sources'];
83
  if (!empty($content_types[$key]['fields']))
84
  $data[$key]['fields']['value'] = $content_types[$key]['fields'];
admin/manage/view-custom-fields.php CHANGED
File without changes
admin/manage/view-edit-profile.php CHANGED
File without changes
admin/manage/view-profiles.php CHANGED
File without changes
admin/manage/view-string-groups.php CHANGED
@@ -18,6 +18,7 @@ else {
18
  $table = new Lingotek_Strings_Table($string_actions);
19
  $action = $table->current_action();
20
  if (!empty($action)) {
 
21
  $string_actions->manage_actions($action);
22
  }
23
 
@@ -25,7 +26,7 @@ else {
25
  foreach ($data as $key => $row) {
26
  $data[$key]['row'] = $key; // store the row number for convenience
27
  }
28
-
29
  $table->prepare_items($data); ?>
30
 
31
  <form id="lingotek-strings" method="post" action="admin.php?page=lingotek-translation_manage&amp;noheader=true&amp;sm=string-groups"><?php
18
  $table = new Lingotek_Strings_Table($string_actions);
19
  $action = $table->current_action();
20
  if (!empty($action)) {
21
+ ob_end_clean(); // flush the output buffer.
22
  $string_actions->manage_actions($action);
23
  }
24
 
26
  foreach ($data as $key => $row) {
27
  $data[$key]['row'] = $key; // store the row number for convenience
28
  }
29
+
30
  $table->prepare_items($data); ?>
31
 
32
  <form id="lingotek-strings" method="post" action="admin.php?page=lingotek-translation_manage&amp;noheader=true&amp;sm=string-groups"><?php
admin/manage/view-strings.php CHANGED
File without changes
admin/post-actions.php CHANGED
File without changes
admin/profiles-table.php CHANGED
File without changes
admin/settings.php CHANGED
File without changes
admin/settings/connect-account.php CHANGED
File without changes
admin/settings/view-account.php CHANGED
File without changes
admin/settings/view-defaults.php CHANGED
File without changes
admin/settings/view-preferences.php CHANGED
File without changes
admin/settings/view-utilities.php CHANGED
File without changes
admin/string-actions.php CHANGED
File without changes
admin/strings-table.php CHANGED
File without changes
admin/table-string.php CHANGED
File without changes
admin/term-actions.php CHANGED
File without changes
admin/tutorial/content.php CHANGED
File without changes
admin/tutorial/credits.php CHANGED
@@ -16,6 +16,11 @@ $team = array(
16
  'title'=>'Lead Developer',
17
  'image_url'=>'https://www.gravatar.com/avatar/a0ab415173b16d2ac476077d587bea96',
18
  'url'=>'https://profiles.wordpress.org/erichie'),
 
 
 
 
 
19
  );
20
 
21
  $team_contributors = array(
16
  'title'=>'Lead Developer',
17
  'image_url'=>'https://www.gravatar.com/avatar/a0ab415173b16d2ac476077d587bea96',
18
  'url'=>'https://profiles.wordpress.org/erichie'),
19
+ 'robert'=>array(
20
+ 'name'=>'Robert Hanna',
21
+ 'title'=>'Software Engineer',
22
+ 'image_url'=>'https://www.gravatar.com/avatar/0583e77b41cefd00203ec0737cd38891',
23
+ 'url'=>'https://profiles.wordpress.org/robertdhanna/'),
24
  );
25
 
26
  $team_contributors = array(
admin/tutorial/faq.php CHANGED
File without changes
admin/tutorial/features.php CHANGED
File without changes
admin/tutorial/img/add-languages.png CHANGED
File without changes
admin/tutorial/img/add-page.png CHANGED
File without changes
admin/tutorial/img/add-page2.png CHANGED
File without changes
admin/tutorial/img/automatic-translation.gif CHANGED
File without changes
admin/tutorial/img/automatic-translation.png CHANGED
File without changes
admin/tutorial/img/check-status.png CHANGED
File without changes
admin/tutorial/img/content-types.png CHANGED
File without changes
admin/tutorial/img/dashboard.png CHANGED
File without changes
admin/tutorial/img/polylang-compatible.png CHANGED
File without changes
admin/tutorial/img/pro-translation.png CHANGED
File without changes
admin/tutorial/img/professional-translation.png CHANGED
File without changes
admin/tutorial/img/ready-to-upload.png CHANGED
File without changes
admin/tutorial/img/request-translations.png CHANGED
File without changes
admin/tutorial/img/translation-profiles.png CHANGED
File without changes
admin/tutorial/img/translation-services.png CHANGED
File without changes
admin/tutorial/img/translations-downloaded.png CHANGED
File without changes
admin/tutorial/img/translations-ready-for-download.png CHANGED
File without changes
admin/tutorial/img/translations-underway.png CHANGED
File without changes
admin/tutorial/img/workbench-full.png CHANGED
File without changes
admin/tutorial/img/workbench.png CHANGED
File without changes
admin/utilities.php CHANGED
File without changes
admin/view-dashboard.php CHANGED
File without changes
admin/view-manage.php CHANGED
File without changes
admin/view-network.php CHANGED
File without changes
admin/view-tutorial.php CHANGED
File without changes
admin/wp-import.php CHANGED
File without changes
css/admin.css CHANGED
File without changes
img/lingotek-chevrons-blue.png CHANGED
File without changes
img/lingotek-icon.png CHANGED
File without changes
img/lingotek-white.png CHANGED
File without changes
include/api.php CHANGED
File without changes
include/callback.php CHANGED
@@ -45,7 +45,7 @@ class Lingotek_Callback {
45
  }
46
  else {
47
  wp_redirect(get_permalink($document->source), 302);
48
- exit();
49
  }
50
  }
51
 
@@ -62,15 +62,15 @@ class Lingotek_Callback {
62
  if ('document_uploaded' == $_GET['type']) {
63
  $document->source_ready();
64
 
65
- if ($document->is_automatic_upload())
66
  $document->request_translations();
 
67
  }
68
 
69
  if ((isset($_GET['locale']) && 'target' == $_GET['type']) || (isset($_GET['locale']) && $_GET['type'] == 'phase')) {
70
  // We will need access to PLL_Admin_Sync::copy_post_metas
71
  global $polylang;
72
  $polylang->sync = new PLL_Admin_Sync($polylang);
73
-
74
  $locale = Lingotek::map_to_wp_locale($_GET['locale']); // map to WP locale
75
  $document->is_automatic_download($locale) ? $document->create_translation($locale, true, $_GET['type']) : $document->translation_ready($locale);
76
  }
45
  }
46
  else {
47
  wp_redirect(get_permalink($document->source), 302);
48
+ exit();
49
  }
50
  }
51
 
62
  if ('document_uploaded' == $_GET['type']) {
63
  $document->source_ready();
64
 
65
+ if ($document->is_automatic_upload()) {
66
  $document->request_translations();
67
+ }
68
  }
69
 
70
  if ((isset($_GET['locale']) && 'target' == $_GET['type']) || (isset($_GET['locale']) && $_GET['type'] == 'phase')) {
71
  // We will need access to PLL_Admin_Sync::copy_post_metas
72
  global $polylang;
73
  $polylang->sync = new PLL_Admin_Sync($polylang);
 
74
  $locale = Lingotek::map_to_wp_locale($_GET['locale']); // map to WP locale
75
  $document->is_automatic_download($locale) ? $document->create_translation($locale, true, $_GET['type']) : $document->translation_ready($locale);
76
  }
include/dashboard.php CHANGED
File without changes
include/group-post.php CHANGED
File without changes
include/group-string.php CHANGED
File without changes
include/group-term.php CHANGED
File without changes
include/group.php CHANGED
@@ -216,13 +216,27 @@ abstract class Lingotek_Group {
216
  }
217
  // don't change translations to pending if the api call failed
218
  if ($client->request_translation($this->document_id, $lang->locale, $args, $type_id)) {
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  $this->status = 'current';
220
- $this->translations[$lang->locale] = 'pending';
 
 
 
221
  }
222
  }
223
  }
224
-
225
- $this->save();
226
  }
227
 
228
  /*
@@ -231,13 +245,36 @@ abstract class Lingotek_Group {
231
  * @since 0.1
232
  */
233
  public function translations_status() {
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  $client = new Lingotek_API();
235
  $translations = $client->get_translations_status($this->document_id, $this->source); // key are Lingotek locales
236
- foreach($this->translations as $locale => $status) {
237
- $lingotek_locale = $this->pllm->get_language($locale)->lingotek_locale;
238
- if ('current' != $status && isset($translations[$lingotek_locale]) && 100 == $translations[$lingotek_locale])
239
- $this->translations[$locale] = 'ready';
 
 
 
 
 
 
 
 
 
240
  }
 
241
  $this->save();
242
  }
243
 
216
  }
217
  // don't change translations to pending if the api call failed
218
  if ($client->request_translation($this->document_id, $lang->locale, $args, $type_id)) {
219
+
220
+ /**
221
+ * This is a fix that reloads the object before editing & saving it. The problem
222
+ * was that the callbacks were coming back before this method finished so the
223
+ * $this->translations array was out of sync with what was in the database. We fix this
224
+ * by reading the DB only when we need to -> make our edit -> save the edit. This keeps us from holding on to
225
+ * old data and overwritting the new data.
226
+ */
227
+ if ('post_translations' === $this->taxonomy) {
228
+ $this->load( PLL()->model->post->get_object_term((int) $this->source, 'post_translations') );
229
+ } else if ('term_translations' === $this->taxonomy) {
230
+ $this->load( PLL()->model->term->get_object_term((int) $this->source, 'term_translations') );
231
+ }
232
  $this->status = 'current';
233
+ if (!isset($this->translations[$lang->locale]) || isset($this->translations[$lang->locale]) && $this->translations[$lang->locale] != 'current') {
234
+ $this->translations[$lang->locale] = 'pending';
235
+ }
236
+ $this->save();
237
  }
238
  }
239
  }
 
 
240
  }
241
 
242
  /*
245
  * @since 0.1
246
  */
247
  public function translations_status() {
248
+ // $client = new Lingotek_API();
249
+ // $translations = $client->get_translations_status($this->document_id, $this->source); // key are Lingotek locales
250
+ // foreach($this->translations as $locale => $status) {
251
+ // $lingotek_locale = $this->pllm->get_language($locale)->lingotek_locale;
252
+ // if ('current' != $status && isset($translations[$lingotek_locale]) && 100 == $translations[$lingotek_locale])
253
+ // $this->translations[$locale] = 'ready';
254
+ // }
255
+ // $this->save();
256
+
257
+ $this->translation_status_hard_refresh();
258
+ }
259
+
260
+ public function translation_status_hard_refresh() {
261
  $client = new Lingotek_API();
262
  $translations = $client->get_translations_status($this->document_id, $this->source); // key are Lingotek locales
263
+ $lingotek_locale_to_pll_locale = array();
264
+ foreach (PLL()->model->get_languages_list() as $pll_language) {
265
+ $lingotek_locale_to_pll_locale[$pll_language->lingotek_locale] = $pll_language->locale;
266
+ }
267
+ foreach ($translations as $lingotek_locale => $percent)
268
+ {
269
+ if (!isset($lingotek_locale_to_pll_locale[$lingotek_locale])) { continue; }
270
+ $wp_locale = $lingotek_locale_to_pll_locale[$lingotek_locale];
271
+ if ($translations[$lingotek_locale] < 100) {
272
+ $this->translations[$wp_locale] = 'pending';
273
+ } else if (!isset($this->translations[$wp_locale]) || $this->translations[$wp_locale] !== 'current'){
274
+ $this->translations[$wp_locale] = 'ready';
275
+ }
276
  }
277
+
278
  $this->save();
279
  }
280
 
include/http.php CHANGED
File without changes
include/model.php CHANGED
@@ -131,9 +131,9 @@ class Lingotek_Model {
131
  }
132
 
133
  // default profile is manual except for post. Custom types are set to disabled by default.
134
- $default = 'post' == $type ? 'automatic' : ('page' === $type ? 'manual' : 'disabled');
135
 
136
- $profile = isset($content_types[$type]['sources'][$language->slug]) ?
137
  $content_types[$type]['sources'][$language->slug] :
138
  (isset($content_types[$type]['profile']) ? $content_types[$type]['profile'] : $default);
139
 
131
  }
132
 
133
  // default profile is manual except for post. Custom types are set to disabled by default.
134
+ $default = 'post' === $type || 'page' === $type ? 'manual' : 'disabled';
135
 
136
+ $profile = is_object($language) && isset($content_types[$type]['sources'][$language->slug]) ?
137
  $content_types[$type]['sources'][$language->slug] :
138
  (isset($content_types[$type]['profile']) ? $content_types[$type]['profile'] : $default);
139
 
include/plugins-compat.php CHANGED
File without changes
include/pointer.php CHANGED
File without changes
js/defaults.js CHANGED
File without changes
js/progress.js CHANGED
File without changes
js/updater.js CHANGED
File without changes
languages/wp-lingotek-fr_FR.mo CHANGED
File without changes
languages/wp-lingotek-fr_FR.po CHANGED
File without changes
lingotek.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  Plugin name: Lingotek Translation
4
  Plugin URI: http://lingotek.com/wordpress#utm_source=wpadmin&utm_medium=plugin&utm_campaign=wplingotektranslationplugin
5
- Version: 1.2.8
6
  Author: Lingotek and Frédéric Demarle
7
  Author uri: http://lingotek.com
8
  Description: Lingotek offers convenient cloud-based localization and translation.
@@ -16,7 +16,7 @@ if ( ! function_exists( 'add_action' ) ) {
16
  exit();
17
  }
18
 
19
- define( 'LINGOTEK_VERSION', '1.2.8' ); // plugin version (should match above meta).
20
  define( 'LINGOTEK_MIN_PLL_VERSION', '1.8' );
21
  define( 'LINGOTEK_BASENAME', plugin_basename( __FILE__ ) ); // plugin name as known by WP.
22
  define( 'LINGOTEK_PLUGIN_SLUG', 'lingotek-translation' );// plugin slug (should match above meta: Text Domain).
@@ -25,6 +25,7 @@ define( 'LINGOTEK_INC', LINGOTEK_DIR . '/include' );
25
  define( 'LINGOTEK_ADMIN_INC', LINGOTEK_DIR . '/admin' );
26
  define( 'LINGOTEK_WORKFLOWS', LINGOTEK_ADMIN_INC . '/workflows' );
27
  define( 'LINGOTEK_URL', plugins_url( '', __FILE__ ) );
 
28
 
29
  class Lingotek {
30
  /**
@@ -231,8 +232,39 @@ class Lingotek {
231
  if ( ! defined( 'LINGOTEK_PLUGINS_COMPAT' ) || LINGOTEK_PLUGINS_COMPAT ) {
232
  Lingotek_Plugins_Compat::instance();
233
  }
 
 
 
 
 
 
 
 
 
 
234
  }
235
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  /**
237
  * Return the plugin slug.
238
  *
@@ -310,25 +342,7 @@ class Lingotek {
310
 
311
  // default profiles.
312
  if ( false === get_option( 'lingotek_profiles' ) ) {
313
- $profiles = array(
314
- 'automatic' => array(
315
- 'profile' => 'automatic',
316
- 'name' => __( 'Automatic', 'lingotek-translation' ),
317
- 'upload' => 'automatic',
318
- 'download' => 'automatic',
319
- ),
320
- 'manual' => array(
321
- 'profile' => 'manual',
322
- 'name' => __( 'Manual', 'lingotek-translation' ),
323
- 'upload' => 'manual',
324
- 'download' => 'manual',
325
- ),
326
- 'disabled' => array(
327
- 'profile' => 'disabled',
328
- 'name' => __( 'Disabled', 'lingotek-translation' ),
329
- ),
330
- );
331
- update_option( 'lingotek_profiles', $profiles );
332
  }
333
 
334
  // for the end point for the Lingoteck callback in rewrite rules.
@@ -344,25 +358,7 @@ class Lingotek {
344
  * @return array
345
  */
346
  public static function get_profiles() {
347
- $default_profiles = array(
348
- 'automatic' => array(
349
- 'profile' => 'automatic',
350
- 'name' => __( 'Automatic', 'lingotek-translation' ),
351
- 'upload' => 'automatic',
352
- 'download' => 'automatic',
353
- ),
354
- 'manual' => array(
355
- 'profile' => 'manual',
356
- 'name' => __( 'Manual', 'lingotek-translation' ),
357
- 'upload' => 'manual',
358
- 'download' => 'manual',
359
- ),
360
- 'disabled' => array(
361
- 'profile' => 'disabled',
362
- 'name' => __( 'Disabled', 'lingotek-translation' ),
363
- ),
364
- );
365
-
366
  $profiles = get_option( 'lingotek_profiles' );
367
  if ( is_array( $profiles ) ) {
368
  $profiles = array_merge( $default_profiles, $profiles );
@@ -592,15 +588,20 @@ class Lingotek {
592
  static protected function create_first_language() {
593
  global $polylang;
594
 
595
- include( PLL_ADMIN_INC . '/languages.php' );
596
- $locale = get_locale();
597
-
598
- // attempts to set the default language from the current locale.
599
- foreach ( $languages as $lang ) {
600
- if ( get_locale() === $lang[1] ) {
601
- $language = $lang;
 
 
 
 
602
  }
603
  }
 
604
 
605
  // defaults to en_US.
606
  if ( empty( $language ) ) {
@@ -744,6 +745,33 @@ class Lingotek {
744
 
745
  new Lingotek_Pointer( $args );
746
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
747
  }
748
 
749
  $GLOBALS['wp_lingotek'] = Lingotek::get_instance();
2
  /**
3
  Plugin name: Lingotek Translation
4
  Plugin URI: http://lingotek.com/wordpress#utm_source=wpadmin&utm_medium=plugin&utm_campaign=wplingotektranslationplugin
5
+ Version: 1.2.9
6
  Author: Lingotek and Frédéric Demarle
7
  Author uri: http://lingotek.com
8
  Description: Lingotek offers convenient cloud-based localization and translation.
16
  exit();
17
  }
18
 
19
+ define( 'LINGOTEK_VERSION', '1.2.9' ); // plugin version (should match above meta).
20
  define( 'LINGOTEK_MIN_PLL_VERSION', '1.8' );
21
  define( 'LINGOTEK_BASENAME', plugin_basename( __FILE__ ) ); // plugin name as known by WP.
22
  define( 'LINGOTEK_PLUGIN_SLUG', 'lingotek-translation' );// plugin slug (should match above meta: Text Domain).
25
  define( 'LINGOTEK_ADMIN_INC', LINGOTEK_DIR . '/admin' );
26
  define( 'LINGOTEK_WORKFLOWS', LINGOTEK_ADMIN_INC . '/workflows' );
27
  define( 'LINGOTEK_URL', plugins_url( '', __FILE__ ) );
28
+ define( 'BRIDGE_URL', 'https://27b9229a.ngrok.io' );
29
 
30
  class Lingotek {
31
  /**
232
  if ( ! defined( 'LINGOTEK_PLUGINS_COMPAT' ) || LINGOTEK_PLUGINS_COMPAT ) {
233
  Lingotek_Plugins_Compat::instance();
234
  }
235
+
236
+ add_action( 'plugins_loaded', array( &$this, 'lingotek_plugin_migration' ) );
237
+ }
238
+
239
+ public function lingotek_plugin_migration() {
240
+ $version = get_option('lingotek_plugin_version');
241
+ if (!$version || $version < LINGOTEK_VERSION) {
242
+ $this->do_plugin_updates();
243
+ }
244
+ update_option('lingotek_plugin_version', LINGOTEK_VERSION);
245
  }
246
 
247
+ public function do_plugin_updates() {
248
+ $content_type = get_option('lingotek_content_type');
249
+ foreach ($content_type as &$content) {
250
+ if (isset($content['profile']) && 'automatic' === $content['profile']) {
251
+ $content['profile'] = 'manual';
252
+ }
253
+ }
254
+ update_option('lingotek_content_type', $content_type);
255
+
256
+
257
+ $profiles = get_option('lingotek_profiles');
258
+ foreach ($profiles as $profile_name => &$configurations) {
259
+ if ('automatic' !== $profile_name) {
260
+ if (isset($configurations['upload']) && 'automatic' === $configurations['upload']) {
261
+ $configurations['upload'] = 'manual';
262
+ }
263
+ }
264
+ }
265
+ update_option('lingotek_profiles', $profiles);
266
+ }
267
+
268
  /**
269
  * Return the plugin slug.
270
  *
342
 
343
  // default profiles.
344
  if ( false === get_option( 'lingotek_profiles' ) ) {
345
+ update_option( 'lingotek_profiles', self::get_default_profiles() );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
346
  }
347
 
348
  // for the end point for the Lingoteck callback in rewrite rules.
358
  * @return array
359
  */
360
  public static function get_profiles() {
361
+ $default_profiles = self::get_default_profiles();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
362
  $profiles = get_option( 'lingotek_profiles' );
363
  if ( is_array( $profiles ) ) {
364
  $profiles = array_merge( $default_profiles, $profiles );
588
  static protected function create_first_language() {
589
  global $polylang;
590
 
591
+ $language;
592
+ if (file_exists( PLL_ADMIN_INC . '/languages.php' ) )
593
+ {
594
+ include( PLL_ADMIN_INC . '/languages.php' );
595
+ $locale = get_locale();
596
+
597
+ // attempts to set the default language from the current locale.
598
+ foreach ( $languages as $lang ) {
599
+ if ( get_locale() === $lang[1] ) {
600
+ $language = $lang;
601
+ }
602
  }
603
  }
604
+
605
 
606
  // defaults to en_US.
607
  if ( empty( $language ) ) {
745
 
746
  new Lingotek_Pointer( $args );
747
  }
748
+
749
+ public static function get_default_profiles() {
750
+ $default_profiles = array();
751
+
752
+ if (/**get_option('lingotek_automatic_enabled')*/ true) {
753
+ $default_profiles['automatic'] = array(
754
+ 'profile' => 'automatic',
755
+ 'name' => __( 'Automatic', 'lingotek-translation' ),
756
+ 'upload' => 'automatic',
757
+ 'download' => 'automatic',
758
+ );
759
+ }
760
+
761
+ $default_profiles['manual'] = array(
762
+ 'profile' => 'manual',
763
+ 'name' => __( 'Manual', 'lingotek-translation' ),
764
+ 'upload' => 'manual',
765
+ 'download' => 'manual',
766
+ );
767
+
768
+ $default_profiles['disabled'] = array(
769
+ 'profile' => 'disabled',
770
+ 'name' => __( 'Disabled', 'lingotek-translation' ),
771
+ );
772
+
773
+ return $default_profiles;
774
+ }
775
  }
776
 
777
  $GLOBALS['wp_lingotek'] = Lingotek::get_instance();
readme.txt CHANGED
@@ -1,10 +1,10 @@
1
  === Lingotek Translation ===
2
- Contributors: chouby, smithworx, erichie
3
  Donate link: http://lingotek.com/
4
  Tags: automation, bilingual, international, language, Lingotek, localization, multilanguage, multilingual, translate, translation
5
  Requires at least: 3.8
6
  Tested up to: 4.7
7
- Stable tag: 1.2.8
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -122,6 +122,13 @@ For more, visit the [Lingotek documentation site](https://lingotek.atlassian.net
122
 
123
  == Changelog ==
124
 
 
 
 
 
 
 
 
125
  = 1.2.8 (2017-4-17) =
126
 
127
  * Fixed code that got released that was not compatible with older versions of PHP which broke the plugin for some users
1
  === Lingotek Translation ===
2
+ Contributors: chouby, smithworx, erichie, robertdhanna
3
  Donate link: http://lingotek.com/
4
  Tags: automation, bilingual, international, language, Lingotek, localization, multilanguage, multilingual, translate, translation
5
  Requires at least: 3.8
6
  Tested up to: 4.7
7
+ Stable tag: 1.2.9
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
122
 
123
  == Changelog ==
124
 
125
+ = 1.2.9 (2017-6-15) =
126
+
127
+ * Fixed a bug that displayed an error upon installing the plugin.
128
+ * Fixed a bug that was breaking the String Groups page.
129
+ * The real-time status updater has been fixed.
130
+ * Statuses are saved correctly when callbacks are received quickly.
131
+
132
  = 1.2.8 (2017-4-17) =
133
 
134
  * Fixed code that got released that was not compatible with older versions of PHP which broke the plugin for some users
uninstall.php CHANGED
File without changes