Lingotek Translation - Version 1.1

Version Description

(2015-08-28) =

  • Added the option to set a Translation Profile per Post/Page which will override the Content Type default Translation Profile
  • The selected Translation Profile is now displayed on bulk display of Posts/Pages
  • Minor fixes for real-time translation status updates
  • Fixed a bug that prevented updating of content
  • Custom fields enhancements and fixes
  • Moved Content Type Configuration, Translation Profiles, and Custom Fields tabs from the Settings Page to the Manage Page
  • Fixed Lingotek Dashboard counting error
Download this release

Release Info

Developer erichie
Plugin Icon 128x128 Lingotek Translation
Version 1.1
Comparing to
See all releases

Code changes from version 1.0.9 to 1.1

admin/actions.php CHANGED
@@ -394,6 +394,11 @@ abstract class Lingotek_Actions {
394
  case 'lingotek-delete':
395
  check_admin_referer('lingotek-delete');
396
  $document->disassociate();
 
 
 
 
 
397
  break;
398
 
399
  default:
394
  case 'lingotek-delete':
395
  check_admin_referer('lingotek-delete');
396
  $document->disassociate();
397
+ if (isset($_GET['lingotek_redirect']) && $_GET['lingotek_redirect'] == true) {
398
+ $site_id = get_current_blog_id();
399
+ wp_redirect(get_site_url($site_id, '/wp-admin/edit.php?post_type=page'));
400
+ exit();
401
+ }
402
  break;
403
 
404
  default:
admin/admin.php CHANGED
@@ -48,8 +48,18 @@ class Lingotek_Admin {
48
  $content_metadata = array();
49
  foreach($object_ids as $object_id) {
50
  $id = $object_id;
 
 
 
 
 
 
 
 
 
 
51
  $document = $lgtm->get_group($taxonomy, $object_id);
52
- if ($document) {
53
  if($document->source !== $object_id){
54
  $document = $lgtm->get_group($taxonomy, $document->source);
55
  }
@@ -57,7 +67,7 @@ class Lingotek_Admin {
57
  $source_language = $terms ? pll_get_term_language($document->source, 'locale')
58
  : pll_get_post_language($document->source, 'locale');
59
  $existing_translations = $pllm->get_translations($taxonomy, $source_id);
60
- $content_metadata[$id]['existing_trans'] = false;
61
  if(count($existing_translations) > 1){
62
  $content_metadata[$id]['existing_trans'] = true;
63
  }
@@ -67,6 +77,18 @@ class Lingotek_Admin {
67
  $content_metadata[$id]['source_status'] = $document->status;
68
  $target_status = $document->status == 'edited' || $document->status == null ? 'edited' : 'current';
69
  $content_metadata[$id][$source_language]['status'] = $document->source == $object_id ? $document->status : $target_status;
 
 
 
 
 
 
 
 
 
 
 
 
70
  if(is_array($document->translations)){
71
  foreach($document->translations as $locale => $translation_status) {
72
  $content_metadata[$id][$locale]['status'] = $translation_status;
@@ -75,15 +97,17 @@ class Lingotek_Admin {
75
  }
76
  }
77
  }
 
 
 
 
 
 
 
 
 
78
  }
79
- //fills in missing languages to be able to update all the ones listed on Wordpress
80
- foreach($languages as $language){
81
- foreach($content_metadata as $group => $status){
82
- if(!isset($status[$language])){
83
- $content_metadata[$group][$language]['status'] = "none";
84
- }
85
- }
86
- }
87
  //get the nonces associated with the different actions
88
  $content_metadata['request_nonce'] = $this->lingotek_get_matching_nonce('lingotek-request');
89
  $content_metadata['download_nonce'] = $this->lingotek_get_matching_nonce('lingotek-download');
@@ -293,14 +317,17 @@ class Lingotek_Admin {
293
  'workflow_id' => array(
294
  'label' => $defaults ? __('Default Workflow', 'wp-lingotek') : __('Workflow', 'wp-lingotek'),
295
  'options' => $resources['workflows'],
 
296
  ),
297
  'primary_filter_id' => array(
298
  'label' => $defaults ? __('Primary Filter', 'wp-lingotek') : __('Primary Filter', 'wp-lingotek'),
299
  'options' => $resources['filters'],
 
300
  ),
301
  'secondary_filter_id' => array(
302
  'label' => $defaults ? __('Secondary Filter', 'wp-lingotek') : __('Secondary Filter', 'wp-lingotek'),
303
  'options' => $resources['filters'],
 
304
  ),
305
  );
306
  }
@@ -351,7 +378,10 @@ class Lingotek_Admin {
351
 
352
  $api_data = $client->get_projects($community_id);
353
  $projects = array();
354
- if ($api_data && $api_data != 'empty') {
 
 
 
355
  foreach ($api_data->entities as $project) {
356
  $projects[$project->properties->id] = $project->properties->title;
357
  }
@@ -363,9 +393,6 @@ class Lingotek_Admin {
363
  natcasesort($projects); //order by title (case-insensitive)
364
  $refresh_success['projects'] = TRUE;
365
  }
366
- else if ($api_data == 'empty') {
367
- add_settings_error('lingotek_community_resources', 'error', __('Your Community currently has no projects.', 'wp-lingotek'), 'error');
368
- }
369
  else {
370
  add_settings_error('lingotek_community_resources', 'error', __('Projects could not be refreshed', 'wp-lingotek'), 'error');
371
  }
48
  $content_metadata = array();
49
  foreach($object_ids as $object_id) {
50
  $id = $object_id;
51
+ if ($taxonomy == 'post') {
52
+ $content_metadata[$id] = array(
53
+ 'existing_trans' => false,
54
+ 'source' => false,
55
+ 'doc_id' => null,
56
+ 'source_id' => null,
57
+ 'source_status' => null,
58
+ );
59
+ }
60
+
61
  $document = $lgtm->get_group($taxonomy, $object_id);
62
+ if ($document && isset($document->source) && isset($document->document_id) && isset($document->status) && isset($document->translations)) {
63
  if($document->source !== $object_id){
64
  $document = $lgtm->get_group($taxonomy, $document->source);
65
  }
67
  $source_language = $terms ? pll_get_term_language($document->source, 'locale')
68
  : pll_get_post_language($document->source, 'locale');
69
  $existing_translations = $pllm->get_translations($taxonomy, $source_id);
70
+
71
  if(count($existing_translations) > 1){
72
  $content_metadata[$id]['existing_trans'] = true;
73
  }
77
  $content_metadata[$id]['source_status'] = $document->status;
78
  $target_status = $document->status == 'edited' || $document->status == null ? 'edited' : 'current';
79
  $content_metadata[$id][$source_language]['status'] = $document->source == $object_id ? $document->status : $target_status;
80
+
81
+ //fills in missing languages to be able to update all the ones listed on Wordpress
82
+ foreach ($languages as $language) {
83
+ foreach ($content_metadata as $group => $status) {
84
+ if (!isset($status[$language])) {
85
+ $content_metadata[$group][$language]['status'] = "none";
86
+ if ($document->is_disabled_target($pllm->get_language($language))) {
87
+ $content_metadata[$group][$language]['status'] = 'disabled';
88
+ }
89
+ }
90
+ }
91
+ }
92
  if(is_array($document->translations)){
93
  foreach($document->translations as $locale => $translation_status) {
94
  $content_metadata[$id][$locale]['status'] = $translation_status;
97
  }
98
  }
99
  }
100
+ $language = pll_get_post_language($id);
101
+ $post_language = $pllm->get_language($language);
102
+ $taxonomy = get_post_type($id);
103
+ if ($post_language) {
104
+ $profile = Lingotek_Model::get_profile($taxonomy, $post_language, $id);
105
+ if ($profile['profile'] == 'disabled') {
106
+ $content_metadata[$id]['source'] = 'disabled';
107
+ }
108
+ }
109
  }
110
+
 
 
 
 
 
 
 
111
  //get the nonces associated with the different actions
112
  $content_metadata['request_nonce'] = $this->lingotek_get_matching_nonce('lingotek-request');
113
  $content_metadata['download_nonce'] = $this->lingotek_get_matching_nonce('lingotek-download');
317
  'workflow_id' => array(
318
  'label' => $defaults ? __('Default Workflow', 'wp-lingotek') : __('Workflow', 'wp-lingotek'),
319
  'options' => $resources['workflows'],
320
+ 'description' => __('Changes will affect new entities only', 'wp-lingotek')
321
  ),
322
  'primary_filter_id' => array(
323
  'label' => $defaults ? __('Primary Filter', 'wp-lingotek') : __('Primary Filter', 'wp-lingotek'),
324
  'options' => $resources['filters'],
325
+ 'description' => __('Changes will affect new entities only', 'wp-lingotek')
326
  ),
327
  'secondary_filter_id' => array(
328
  'label' => $defaults ? __('Secondary Filter', 'wp-lingotek') : __('Secondary Filter', 'wp-lingotek'),
329
  'options' => $resources['filters'],
330
+ 'description' => __('Changes will affect new entities only', 'wp-lingotek')
331
  ),
332
  );
333
  }
378
 
379
  $api_data = $client->get_projects($community_id);
380
  $projects = array();
381
+ if (empty($api_data)) {
382
+ add_settings_error('lingotek_community_resources', 'error', __('Your Community currently has no projects.', 'wp-lingotek'), 'error');
383
+ }
384
+ else if ($api_data !== FALSE) {
385
  foreach ($api_data->entities as $project) {
386
  $projects[$project->properties->id] = $project->properties->title;
387
  }
393
  natcasesort($projects); //order by title (case-insensitive)
394
  $refresh_success['projects'] = TRUE;
395
  }
 
 
 
396
  else {
397
  add_settings_error('lingotek_community_resources', 'error', __('Projects could not be refreshed', 'wp-lingotek'), 'error');
398
  }
admin/custom-fields-table.php CHANGED
@@ -104,6 +104,12 @@ class Lingotek_Custom_Fields_Table extends WP_List_Table {
104
  if (!empty($_REQUEST['orderby'])) // no sort by default
105
  usort($data, 'usort_reorder');
106
 
 
107
  $this->items = $data;
 
 
 
 
 
108
  }
109
  }
104
  if (!empty($_REQUEST['orderby'])) // no sort by default
105
  usort($data, 'usort_reorder');
106
 
107
+ $total_items = count($data);
108
  $this->items = $data;
109
+
110
+ $this->set_pagination_args(array(
111
+ 'total_items' => $total_items,
112
+ 'per_page' => count($data),
113
+ ));
114
  }
115
  }
admin/filters-columns.php CHANGED
@@ -37,7 +37,8 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
37
  * @return array modified list of columns
38
  */
39
  protected function add_column($columns, $before) {
40
- if ($n = array_search($before, array_keys($columns))) {
 
41
  $end = array_slice($columns, $n);
42
  $columns = array_slice($columns, 0, $n);
43
  }
@@ -98,7 +99,7 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
98
  // FIXME not very clean
99
  $actions = 'post' == $type ? $GLOBALS['wp_lingotek']->post_actions : $GLOBALS['wp_lingotek']->term_actions;
100
 
101
- $profile = Lingotek_Model::get_profile($this->content_type, $language);
102
  $disabled = 'disabled' == $profile['profile'];
103
 
104
  // post ready for upload
37
  * @return array modified list of columns
38
  */
39
  protected function add_column($columns, $before) {
40
+ $n = array_search($before, array_keys($columns));
41
+ if ($n) {
42
  $end = array_slice($columns, $n);
43
  $columns = array_slice($columns, 0, $n);
44
  }
99
  // FIXME not very clean
100
  $actions = 'post' == $type ? $GLOBALS['wp_lingotek']->post_actions : $GLOBALS['wp_lingotek']->term_actions;
101
 
102
+ $profile = Lingotek_Model::get_profile($this->content_type, $language, $object_id);
103
  $disabled = 'disabled' == $profile['profile'];
104
 
105
  // post ready for upload
admin/filters-post.php CHANGED
@@ -9,6 +9,7 @@
9
  */
10
  class Lingotek_Filters_Post extends PLL_Admin_Filters_Post {
11
  public $lgtm; // Lingotek model
 
12
 
13
  /*
14
  * Constructor
@@ -19,6 +20,7 @@ class Lingotek_Filters_Post extends PLL_Admin_Filters_Post {
19
  parent::__construct($polylang);
20
 
21
  $this->lgtm = &$GLOBALS['wp_lingotek']->model;
 
22
 
23
  // automatic upload
24
  add_action('post_updated', array(&$this, 'post_updated'), 10, 3);
@@ -26,6 +28,12 @@ class Lingotek_Filters_Post extends PLL_Admin_Filters_Post {
26
  // trash sync
27
  add_action('trashed_post', array(&$this, 'trash_post'));
28
  add_action('untrashed_post', array(&$this, 'untrash_post'));
 
 
 
 
 
 
29
  }
30
 
31
  /*
@@ -37,11 +45,75 @@ class Lingotek_Filters_Post extends PLL_Admin_Filters_Post {
37
  global $post_ID;
38
  if ($this->model->is_translated_post_type($post_type)) {
39
  $document = $this->lgtm->get_group('post', $post_ID);
40
- if (empty($document->source))
41
  parent::add_meta_boxes($post_type);
 
 
 
 
42
  }
43
  }
44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  /*
46
  * uploads a post when saved for the first time
47
  *
@@ -52,13 +124,25 @@ class Lingotek_Filters_Post extends PLL_Admin_Filters_Post {
52
  * @param bool $update whether it is an update or not
53
  */
54
  public function save_post($post_id, $post, $update) {
 
 
 
 
 
 
 
 
 
 
 
 
55
  if (!$this->model->is_translated_post_type($post->post_type))
56
  return;
57
-
58
  if (!isset($_REQUEST['import'])) {
59
  parent::save_post($post_id, $post, $update);
60
 
61
- if (!wp_is_post_revision($post_id) && 'auto-draft' != $post->post_status && Lingotek_Group_Post::is_valid_auto_upload_post_status($post->post_status) && 'automatic' == Lingotek_Model::get_profile_option('upload', $post->post_type, $this->model->get_post_language($post_id)) && !(isset($_POST['action']) && 'heartbeat' == $_POST['action']) && $this->lgtm->can_upload('post', $post_id)) {
62
  $this->lgtm->upload_post($post_id);
63
  }
64
  }
@@ -99,17 +183,6 @@ class Lingotek_Filters_Post extends PLL_Admin_Filters_Post {
99
  * @param object $post_before
100
  */
101
  public function post_updated($post_id, $post_after, $post_before) {
102
- if ($this->can_save_post_data($post_id, $post_after, true)) {
103
- $document = $this->lgtm->get_group('post', $post_id);
104
-
105
- if ($document && $post_id == $document->source && md5(Lingotek_Group_Post::get_content($post_after)) != md5(Lingotek_Group_Post::get_content($post_before))) {
106
- $document->source_edited();
107
-
108
- if ($document->is_automatic_upload() && Lingotek_Group_Post::is_valid_auto_upload_post_status($post_after->post_status)) {
109
- $this->lgtm->upload_post($post_id);
110
- }
111
- }
112
- }
113
  }
114
 
115
  /*
@@ -157,6 +230,18 @@ class Lingotek_Filters_Post extends PLL_Admin_Filters_Post {
157
  }
158
  $this->lgtm->delete_post($post_id);
159
  }
 
 
 
 
 
 
 
 
 
 
 
 
160
  }
161
 
162
  /*
@@ -182,4 +267,55 @@ class Lingotek_Filters_Post extends PLL_Admin_Filters_Post {
182
  foreach ($this->get_translations_to_sync($post_id) as $tr_id)
183
  wp_untrash_post($tr_id);
184
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  }
9
  */
10
  class Lingotek_Filters_Post extends PLL_Admin_Filters_Post {
11
  public $lgtm; // Lingotek model
12
+ public $pllm;
13
 
14
  /*
15
  * Constructor
20
  parent::__construct($polylang);
21
 
22
  $this->lgtm = &$GLOBALS['wp_lingotek']->model;
23
+ $this->pllm = &$GLOBALS['polylang']->model;
24
 
25
  // automatic upload
26
  add_action('post_updated', array(&$this, 'post_updated'), 10, 3);
28
  // trash sync
29
  add_action('trashed_post', array(&$this, 'trash_post'));
30
  add_action('untrashed_post', array(&$this, 'untrash_post'));
31
+
32
+ add_filter('manage_posts_columns', array(&$this, 'add_profile_column'));
33
+ add_action('manage_posts_custom_column', array(&$this, 'add_profile_column_data'), 10, 3);
34
+
35
+ add_filter('manage_pages_columns', array(&$this, 'add_profile_column'));
36
+ add_action('manage_pages_custom_column', array(&$this, 'add_profile_column_data'), 10, 3);
37
  }
38
 
39
  /*
45
  global $post_ID;
46
  if ($this->model->is_translated_post_type($post_type)) {
47
  $document = $this->lgtm->get_group('post', $post_ID);
48
+ if (empty($document->source)) {
49
  parent::add_meta_boxes($post_type);
50
+ }
51
+ else {
52
+ add_action( 'edit_form_top', array( &$this, 'edit_form_top' ) );
53
+ }
54
  }
55
  }
56
 
57
+ /*
58
+ * adds a column to display the post or page translation profile
59
+ *
60
+ * @since 1.1
61
+ */
62
+ public function add_profile_column($columns) {
63
+ $n = array_search('date', array_keys($columns));
64
+ if ($n) {
65
+ $end = array_slice($columns, $n);
66
+ $columns = array_slice($columns, 0, $n);
67
+ }
68
+
69
+ $columns['profile'] = 'Profile';
70
+ return isset($end) ? array_merge($columns, $end) : $columns;
71
+ }
72
+
73
+ /*
74
+ * finds the translation profile for a post or page and if not set then displays the content type default profile
75
+ *
76
+ * @since 1.1
77
+ */
78
+ public function add_profile_column_data($column_name, $post_id) {
79
+ if ($column_name == 'profile') {
80
+ $document = $this->lgtm->get_group('post', $post_id);
81
+ if (isset($document->source)) {
82
+ $post_id = $document->source;
83
+ }
84
+ $profiles = Lingotek::get_profiles();
85
+ $content_profiles = get_option('lingotek_content_type');
86
+ $post_profile = Lingotek_Post_actions::get_post_profile($post_id);
87
+ $post_language = $this->pllm->get_post_language($post_id);
88
+ $post_type = 'post';
89
+ if (isset($_REQUEST['post_type'])) {
90
+ $post_type = $_REQUEST['post_type'];
91
+ }
92
+
93
+ if (isset($content_profiles[$post_type]['sources'][$post_language->slug])) {
94
+ $profile = $content_profiles[$post_type]['sources'][$post_language->slug];
95
+ echo $profiles[$profile]['name'];
96
+ }
97
+ else if ($post_profile) {
98
+ echo $profiles[$post_profile->description]['name'] . sprintf('<a title="%s">%s</a>', __('Not set to the content default profile', 'wp-lingotek'), '*');
99
+ }
100
+ else {
101
+ echo $profiles[$content_profiles[$post_type]['profile']]['name'];
102
+ }
103
+ }
104
+ }
105
+
106
+ /*
107
+ * outputs hidden fields so that Polylang get correct information when its metabox is removed
108
+ *
109
+ * @since 1.10
110
+ */
111
+ public function edit_form_top() {
112
+ global $post_ID;
113
+ printf( '<input type="hidden" id="post_lang_choice" name="post_lang_choice" value="%s" />', pll_get_post_language( $post_ID ) );
114
+ wp_nonce_field('pll_language', '_pll_nonce');
115
+ }
116
+
117
  /*
118
  * uploads a post when saved for the first time
119
  *
124
  * @param bool $update whether it is an update or not
125
  */
126
  public function save_post($post_id, $post, $update) {
127
+ if ($this->can_save_post_data($post_id, $post, true)) {
128
+ $document = $this->lgtm->get_group('post', $post_id);
129
+ // updated post
130
+ if ($document && $post_id == $document->source && $this->post_hash_has_changed($post)) {
131
+ $document->source_edited();
132
+
133
+ if ($document->is_automatic_upload() && Lingotek_Group_Post::is_valid_auto_upload_post_status($post->post_status)) {
134
+ $this->lgtm->upload_post($post_id);
135
+ }
136
+ }
137
+ }
138
+
139
  if (!$this->model->is_translated_post_type($post->post_type))
140
  return;
141
+ // new post
142
  if (!isset($_REQUEST['import'])) {
143
  parent::save_post($post_id, $post, $update);
144
 
145
+ if (!wp_is_post_revision($post_id) && 'auto-draft' != $post->post_status && Lingotek_Group_Post::is_valid_auto_upload_post_status($post->post_status) && 'automatic' == Lingotek_Model::get_profile_option('upload', $post->post_type, $this->model->get_post_language($post_id), false, $post_id) && !(isset($_POST['action']) && 'heartbeat' == $_POST['action']) && $this->lgtm->can_upload('post', $post_id)) {
146
  $this->lgtm->upload_post($post_id);
147
  }
148
  }
183
  * @param object $post_before
184
  */
185
  public function post_updated($post_id, $post_after, $post_before) {
 
 
 
 
 
 
 
 
 
 
 
186
  }
187
 
188
  /*
230
  }
231
  $this->lgtm->delete_post($post_id);
232
  }
233
+ // delete lingotek_profile term upon post deletion
234
+ $terms = wp_get_object_terms($post_id, 'lingotek_profile');
235
+ $term = array_pop($terms);
236
+ if ($term) {
237
+ wp_delete_term($term->term_id, 'lingotek_profile');
238
+ }
239
+ //delete lingotek_hash term upon post deletion
240
+ $hash_terms = wp_get_object_terms($post_id, 'lingotek_hash');
241
+ $hash_term = array_pop($hash_terms);
242
+ if ($hash_term) {
243
+ wp_delete_term($hash_term->term_id, 'lingotek_hash');
244
+ }
245
  }
246
 
247
  /*
267
  foreach ($this->get_translations_to_sync($post_id) as $tr_id)
268
  wp_untrash_post($tr_id);
269
  }
270
+
271
+ /*
272
+ * checks stored hash against current hash to report change
273
+ *
274
+ * @since 1.0
275
+ *
276
+ * @param wp_post $post_after
277
+ */
278
+ protected function post_hash_has_changed($post_after) {
279
+ if ($post_after->post_status === 'trash') {
280
+ return false;
281
+ }
282
+ $document_id = 'lingotek_hash_' . $post_after->ID;
283
+ $new_hash = md5(Lingotek_Group_Post::get_content($post_after));
284
+ $old_term = $this->get_post_hash($post_after->ID);
285
+ $old_hash = $old_term->description;
286
+
287
+ // new or updated page
288
+ if ($old_hash === null || strcmp($new_hash, $old_hash)) {
289
+ if (empty($old_term)) {
290
+ wp_insert_term($document_id, 'lingotek_hash', array('description' => $new_hash));
291
+ }
292
+ else {
293
+ wp_update_term((int) $old_term->term_id, 'lingotek_hash', array('description' => $new_hash));
294
+ }
295
+
296
+ wp_set_object_terms($post_after->ID, $document_id, 'lingotek_hash');
297
+ return true;
298
+ }
299
+ else {
300
+ return false;
301
+ }
302
+ }
303
+
304
+ /*
305
+ * returns a lingotek post hash if it exists
306
+ *
307
+ * @since 1.0
308
+ *
309
+ * @param int $post_id
310
+ */
311
+ protected function get_post_hash($post_id) {
312
+ if (taxonomy_exists('lingotek_hash')) {
313
+ $terms = wp_get_object_terms($post_id, 'lingotek_hash');
314
+ $term = array_pop($terms);
315
+ return $term;
316
+ }
317
+ else {
318
+ return null;
319
+ }
320
+ }
321
  }
admin/{settings → manage}/view-content.php RENAMED
@@ -81,7 +81,7 @@ foreach ($data as $key => $item) {
81
  <h3><?php _e('Content Type Configuration', 'wp-lingotek'); ?></h3>
82
  <p class="description"><?php _e('Content types can be configured to use any translation profile. Additionally, translation profiles can be set based on the language the content was authored in.', 'wp-lingotek'); ?></p>
83
 
84
- <form id="lingotek-content-types" method="post" action="admin.php?page=wp-lingotek_settings&amp;sm=content" class="validate"><?php
85
  wp_nonce_field('lingotek-content-types', '_wpnonce_lingotek-content-types');
86
 
87
  $table = new Lingotek_Content_Table($content_types);
81
  <h3><?php _e('Content Type Configuration', 'wp-lingotek'); ?></h3>
82
  <p class="description"><?php _e('Content types can be configured to use any translation profile. Additionally, translation profiles can be set based on the language the content was authored in.', 'wp-lingotek'); ?></p>
83
 
84
+ <form id="lingotek-content-types" method="post" action="admin.php?page=wp-lingotek_manage&amp;sm=content" class="validate"><?php
85
  wp_nonce_field('lingotek-content-types', '_wpnonce_lingotek-content-types');
86
 
87
  $table = new Lingotek_Content_Table($content_types);
admin/{settings → manage}/view-custom-fields.php RENAMED
@@ -6,12 +6,18 @@ $items = array();
6
 
7
  if (!empty($_POST)) {
8
  check_admin_referer('lingotek-custom-fields', '_wpnonce_lingotek-custom-fields');
9
- $arr = empty($_POST['settings']) ? array() : $_POST['settings'];
10
- update_option('lingotek_custom_fields', $arr);
 
 
 
 
11
 
12
  if (!empty($_POST['refresh'])) {
13
- $items = Lingotek_Group_Post::get_updated_meta_values();
 
14
  }
 
15
  }
16
 
17
  $items = Lingotek_Group_Post::get_cached_meta_values();
@@ -19,9 +25,9 @@ $items = Lingotek_Group_Post::get_cached_meta_values();
19
  ?>
20
 
21
  <h3><?php _e('Custom Field Configuration', 'wp-lingotek'); ?></h3>
22
- <p class="description"><?php _e('Custom Fields can be translated, copied, or ignored.', 'wp-lingotek'); ?></p>
23
 
24
- <form id="lingotek-custom-fields" method="post" action="admin.php?page=wp-lingotek_settings&amp;sm=custom-fields" class="validate"><?php
25
  wp_nonce_field('lingotek-custom-fields', '_wpnonce_lingotek-custom-fields');
26
 
27
  $table = new Lingotek_Custom_Fields_Table();
6
 
7
  if (!empty($_POST)) {
8
  check_admin_referer('lingotek-custom-fields', '_wpnonce_lingotek-custom-fields');
9
+
10
+ if (!empty($_POST['submit'])) {
11
+ $arr = empty($_POST['settings']) ? array() : $_POST['settings'];
12
+ update_option('lingotek_custom_fields', $arr);
13
+ add_settings_error('lingotek_custom_fields_save', 'custom_fields', __('Your <i>Custom Fields</i> were sucessfully saved.', 'wp-lingotek'), 'updated');
14
+ }
15
 
16
  if (!empty($_POST['refresh'])) {
17
+ Lingotek_Group_Post::get_updated_meta_values();
18
+ add_settings_error('lingotek_custom_fields_refresh', 'custom_fields', __('Your <i>Custom Fields</i> were sucessfully identified.', 'wp-lingotek'), 'updated');
19
  }
20
+ settings_errors();
21
  }
22
 
23
  $items = Lingotek_Group_Post::get_cached_meta_values();
25
  ?>
26
 
27
  <h3><?php _e('Custom Field Configuration', 'wp-lingotek'); ?></h3>
28
+ <p class="description"><?php _e('Custom Fields can be translated, copied, or ignored. Click "Refresh Custom Fields" to identify and enable your custom fields.', 'wp-lingotek'); ?></p>
29
 
30
+ <form id="lingotek-custom-fields" method="post" action="admin.php?page=wp-lingotek_manage&amp;sm=custom-fields" class="validate"><?php
31
  wp_nonce_field('lingotek-custom-fields', '_wpnonce_lingotek-custom-fields');
32
 
33
  $table = new Lingotek_Custom_Fields_Table();
admin/{settings → manage}/view-edit-profile.php RENAMED
@@ -55,7 +55,7 @@ unset($settings['primary_filter_id']['options'][$secondary_filter_id]);
55
  unset($settings['secondary_filter_id']['options'][$primary_filter_id]);
56
  ?>
57
 
58
- <form id="lingotek-edit-profile" method="post" action="admin.php?page=wp-lingotek_settings&sm=profiles" class="validate">
59
  <?php wp_nonce_field('lingotek-edit-profile', '_wpnonce_lingotek-edit-profile');?>
60
  <input name="profile" type="hidden" value="<?php echo empty($profile['profile']) ? '' : esc_attr($profile['profile']); ?>">
61
 
@@ -63,11 +63,13 @@ unset($settings['secondary_filter_id']['options'][$primary_filter_id]);
63
  <tr>
64
  <th scope="row"><?php printf('<label for="%s">%s</label>', 'name' , __('Profile name', 'wp-lingotek')); ?></th>
65
  <td><?php
66
- $profile_name = $disabled ? __($profile['name'],'wp-lingotek') : $profile['name'];// localize canned profile names
67
- printf('<input name="name" id="name" type="text" value="%s" %s>',
68
- empty($profile['name']) ? '' : esc_attr($profile_name),
69
- $disabled
70
- ); ?>
 
 
71
  </td>
72
  </tr>
73
  </table>
@@ -174,6 +176,9 @@ unset($settings['secondary_filter_id']['options'][$primary_filter_id]);
174
  <td><?php
175
  printf('<select name="%1$s" id="%1$s" %2$s>', $custom_key, in_array($key, array('upload', 'download')) ? $disabled : '');
176
  foreach ($setting['options'] as $id => $title) {
 
 
 
177
  $selected = isset($profile['custom'][$key][$language->slug]) && $profile['custom'][$key][$language->slug] == $id ? 'selected="selected"' : '';
178
  echo "\n\t<option value='" . esc_attr($id) . "' $selected>" . esc_html($title) . '</option>';
179
  } ?>
@@ -195,9 +200,9 @@ unset($settings['secondary_filter_id']['options'][$primary_filter_id]);
195
  if (!empty($profile['profile']) && !in_array($profile['profile'], array('automatic', 'manual', 'disabled')) && empty($profile['usage']))
196
  printf(
197
  '<a href="%s" class="button" onclick = "return confirm(\'%s\');">%s</a>',
198
- esc_url(wp_nonce_url('admin.php?page=wp-lingotek_settings&sm=profiles&lingotek_action=delete-profile&noheader=true&profile='.$profile['profile'], 'delete-profile')),
199
  __('You are about to permanently delete this profile. Are you sure?', 'wp-lingotek'),
200
  __('Delete', 'wp-lingotek')
201
  );
202
- ?> <a href="admin.php?page=wp-lingotek_settings&amp;sm=profiles" class="button"> <?php _e('Cancel', 'wp-lingotek'); ?></a>
203
  </form>
55
  unset($settings['secondary_filter_id']['options'][$primary_filter_id]);
56
  ?>
57
 
58
+ <form id="lingotek-edit-profile" method="post" action="admin.php?page=wp-lingotek_manage&sm=profiles" class="validate">
59
  <?php wp_nonce_field('lingotek-edit-profile', '_wpnonce_lingotek-edit-profile');?>
60
  <input name="profile" type="hidden" value="<?php echo empty($profile['profile']) ? '' : esc_attr($profile['profile']); ?>">
61
 
63
  <tr>
64
  <th scope="row"><?php printf('<label for="%s">%s</label>', 'name' , __('Profile name', 'wp-lingotek')); ?></th>
65
  <td><?php
66
+ if (!empty($profile)) {
67
+ $profile_name = $disabled ? __($profile['name'],'wp-lingotek') : $profile['name']; // localize canned profile names
68
+ }
69
+ printf('<input name="name" id="name" type="text" value="%s" %s>',
70
+ empty($profile['name']) ? '' : esc_attr($profile_name),
71
+ $disabled
72
+ ); ?>
73
  </td>
74
  </tr>
75
  </table>
176
  <td><?php
177
  printf('<select name="%1$s" id="%1$s" %2$s>', $custom_key, in_array($key, array('upload', 'download')) ? $disabled : '');
178
  foreach ($setting['options'] as $id => $title) {
179
+ if ($id === 'default' && $key === 'workflow_id') {
180
+ $id = $defaults['workflow_id'];
181
+ }
182
  $selected = isset($profile['custom'][$key][$language->slug]) && $profile['custom'][$key][$language->slug] == $id ? 'selected="selected"' : '';
183
  echo "\n\t<option value='" . esc_attr($id) . "' $selected>" . esc_html($title) . '</option>';
184
  } ?>
200
  if (!empty($profile['profile']) && !in_array($profile['profile'], array('automatic', 'manual', 'disabled')) && empty($profile['usage']))
201
  printf(
202
  '<a href="%s" class="button" onclick = "return confirm(\'%s\');">%s</a>',
203
+ esc_url(wp_nonce_url('admin.php?page=wp-lingotek_manage&sm=profiles&lingotek_action=delete-profile&noheader=true&profile='.$profile['profile'], 'delete-profile')),
204
  __('You are about to permanently delete this profile. Are you sure?', 'wp-lingotek'),
205
  __('Delete', 'wp-lingotek')
206
  );
207
+ ?> <a href="admin.php?page=wp-lingotek_manage&amp;sm=profiles" class="button"> <?php _e('Cancel', 'wp-lingotek'); ?></a>
208
  </form>
admin/{settings → manage}/view-profiles.php RENAMED
@@ -14,7 +14,7 @@ if (isset($_GET['lingotek_action']) && 'delete-profile' == $_GET['lingotek_actio
14
  update_option('lingotek_profiles', $profiles);
15
  add_settings_error('lingotek_profile', 'default', __('Your translation profile was sucessfully deleted.', 'wp-lingotek'), 'updated');
16
  set_transient('settings_errors', get_settings_errors(), 30);
17
- wp_redirect(admin_url('admin.php?page=wp-lingotek_settings&sm=profiles&settings-updated=1'));
18
  exit;
19
  }
20
  }
@@ -89,7 +89,7 @@ $table->prepare_items($profiles);
89
  $table->display();
90
  printf(
91
  '<a href="%s" class="button button-primary">%s</a>',
92
- admin_url('admin.php?page=wp-lingotek_settings&sm=edit-profile'),
93
  __('Add New Profile', 'wp-lingotek')
94
  );
95
 
14
  update_option('lingotek_profiles', $profiles);
15
  add_settings_error('lingotek_profile', 'default', __('Your translation profile was sucessfully deleted.', 'wp-lingotek'), 'updated');
16
  set_transient('settings_errors', get_settings_errors(), 30);
17
+ wp_redirect(admin_url('admin.php?page=wp-lingotek_manage&sm=profiles&settings-updated=1'));
18
  exit;
19
  }
20
  }
89
  $table->display();
90
  printf(
91
  '<a href="%s" class="button button-primary">%s</a>',
92
+ admin_url('admin.php?page=wp-lingotek_manage&sm=edit-profile'),
93
  __('Add New Profile', 'wp-lingotek')
94
  );
95
 
admin/post-actions.php CHANGED
@@ -29,6 +29,10 @@ class Lingotek_Post_actions extends Lingotek_Actions {
29
  // manage bulk actions, row actions and icon actions
30
  add_action('load-edit.php', array(&$this, 'manage_actions'));
31
  add_action('load-upload.php', array(&$this, 'manage_actions'));
 
 
 
 
32
  }
33
 
34
  /*
@@ -69,7 +73,7 @@ class Lingotek_Post_actions extends Lingotek_Actions {
69
 
70
  $language = $this->pllm->get_post_language($post->ID);
71
  if (!empty($language)) {
72
- $profile = Lingotek_Model::get_profile($post->post_type, $language);
73
  if ('disabled' == $profile['profile'])
74
  unset($actions['lingotek-upload']);
75
  }
@@ -190,4 +194,125 @@ class Lingotek_Post_actions extends Lingotek_Actions {
190
  $this->lgtm->upload_post((int) $_POST['id']);
191
  die();
192
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
  }
29
  // manage bulk actions, row actions and icon actions
30
  add_action('load-edit.php', array(&$this, 'manage_actions'));
31
  add_action('load-upload.php', array(&$this, 'manage_actions'));
32
+
33
+ // add meta box on post and page edit pages, and hook on save
34
+ add_action('add_meta_boxes', array(&$this, 'lingotek_add_meta_boxes'));
35
+ add_action('save_post', array(&$this, 'lingotek_save_meta_boxes'));
36
  }
37
 
38
  /*
73
 
74
  $language = $this->pllm->get_post_language($post->ID);
75
  if (!empty($language)) {
76
+ $profile = Lingotek_Model::get_profile($post->post_type, $language, $post->ID);
77
  if ('disabled' == $profile['profile'])
78
  unset($actions['lingotek-upload']);
79
  }
194
  $this->lgtm->upload_post((int) $_POST['id']);
195
  die();
196
  }
197
+
198
+ /*
199
+ * adds the lingotek profile meta box on edit pages
200
+ *
201
+ * @since 0.1
202
+ */
203
+ public function lingotek_add_meta_boxes() {
204
+ global $post;
205
+ $lgtm = new Lingotek_Model();
206
+ $group = $lgtm->get_group($post->post_type, $post->ID);
207
+
208
+ // if it's a new page, $group will be null, so don't check if it's a source page
209
+ if ($group) {
210
+ $desc_array = $group->desc_array;
211
+ $source_id = $desc_array['lingotek']['source'];
212
+ // only display the meta box if it's a source
213
+ if (isset($desc_array['lingotek']['source']) && $post->ID != $source_id) {
214
+ return;
215
+ }
216
+ }
217
+
218
+ add_meta_box('lingotek_post_meta_box', __('Lingotek Translation', 'wp-lingotek'), array( __CLASS__, 'lingotek_edit_meta_box_html'), 'post', 'side', 'default');
219
+ add_meta_box('lingotek_page_meta_box', __('Lingotek Translation', 'wp-lingotek'), array( __CLASS__, 'lingotek_edit_meta_box_html'), 'page', 'side', 'default');
220
+ }
221
+
222
+ /*
223
+ * builds the html for the edit post and edit page meta boxes
224
+ *
225
+ * @since 0.1
226
+ */
227
+ public static function lingotek_edit_meta_box_html() {
228
+ global $post;
229
+ $post_type = get_post_type($post->ID);
230
+ $lgtm = new Lingotek_Model();
231
+ $group = $lgtm->get_group('post', $post->ID);
232
+ $profiles = Lingotek::get_profiles();
233
+ $content_profiles = get_option('lingotek_content_type');
234
+ $content_default_profile = array('default' => array(
235
+ 'name' => __('Content Default (', 'wp-lingotek') . $profiles[$content_profiles[$post->post_type]['profile']]['name'] . ')', // Adds in the name of the content type default profile
236
+ ));
237
+ $profiles = array_merge($content_default_profile, $profiles);
238
+ $post_profile = self::get_post_profile($post->ID);
239
+ if (isset($post_profile)) {
240
+ $selected[$post_profile->description] = $profiles[$post_profile->description];
241
+ unset($profiles[$post_profile->description]);
242
+ $profiles = array_merge($selected, $profiles);
243
+ }
244
+
245
+ if (isset($group->source)) { // Disables selection of a different profile if content has been uploaded to Lingotek
246
+ $args = array(
247
+ 'document_id' => $group->document_id,
248
+ 'action' => 'lingotek-delete',
249
+ 'noheader' => true,
250
+ );
251
+ if ($post_type == 'page') {
252
+ $args['lingotek_redirect'] = true;
253
+ }
254
+ $site_id = get_current_blog_id();
255
+ $url = $post_type == 'page' ? get_site_url($site_id, '/wp-admin/edit.php?post_type=page') : get_site_url($site_id, '/wp-admin/edit.php');
256
+ $disassociate_url = wp_nonce_url(add_query_arg($args, $url), 'lingotek-delete');
257
+ $remove_post = 'post=' . $post->ID;
258
+ $disassociate_url = str_replace($remove_post, '', $disassociate_url);
259
+ $prefs = Lingotek_Model::get_prefs();
260
+ $confirm_message = isset($prefs['delete_document_from_tms']) === false ? __('Are you sure you want to do this?', 'wp-lingotek') : __('Are you sure you want to do this? The document will be deleted from Lingotek TMS.', 'wp-lingotek');
261
+ $confirm_message = sprintf(' onclick = "return confirm(\'%s\');"', $confirm_message);
262
+ printf('<strong>%s</strong><br><br>', __('Translation Profile', 'wp-lingotek'));
263
+ printf('<em>%s</em><br>', __('Disassociate this content to change the Translation Profile', 'wp-lingotek'));
264
+ printf(('<a class="button button-small" href="%s" %s>%s</a><br><br>'), esc_url($disassociate_url), $confirm_message, __('Disassociate', 'wp-lingotek'));
265
+ printf('<select disabled class="custom-field-setting" name="%1$s" id="%1$s">', 'lingotek_profile_meta');
266
+ }
267
+ else {
268
+ printf('<strong>%s</strong><br><br>', __('Translation Profile', 'wp-lingotek'));
269
+ printf('<select class="custom-field-setting" name="%1$s" id="%1$s">', 'lingotek_profile_meta');
270
+ }
271
+
272
+ foreach ($profiles as $key => $profile) {
273
+ echo "\n\t<option value=" . esc_attr($key) . ">" . esc_attr($profile['name']) . '</option>';
274
+ }
275
+ echo '</select>';
276
+ }
277
+
278
+ public function lingotek_save_meta_boxes() {
279
+ if (!isset($_POST['lingotek_profile_meta'])) {
280
+ return;
281
+ }
282
+
283
+ global $post;
284
+ $profile_choice = $_POST['lingotek_profile_meta'];
285
+ $document_id = 'lingotek_profile_' . $post->ID;
286
+ $term = self::get_post_profile($post->ID);
287
+ $post_language = $this->get_language($post->ID);
288
+ $content_profiles = get_option('lingotek_content_type');
289
+
290
+ if ($profile_choice == 'default' && isset($content_profiles[$post->post_type]['sources'][$post_language->slug])) {
291
+ $profile_choice = $content_profiles[$post->post_type]['sources'][$post_language->slug];
292
+ }
293
+ if ($profile_choice == 'default' && !empty($term)) {
294
+ wp_delete_term((int) $term->term_id, 'lingotek_profile');
295
+ }
296
+ elseif ($profile_choice != 'default') {
297
+ if (empty($term)) {
298
+ wp_insert_term($document_id, 'lingotek_profile', array('description' => $profile_choice));
299
+ }
300
+ else {
301
+ wp_update_term((int) $term->term_id, 'lingotek_profile', array('description' => $profile_choice));
302
+ }
303
+
304
+ wp_set_object_terms($post->ID, $document_id, 'lingotek_profile');
305
+ }
306
+ }
307
+
308
+ public static function get_post_profile($post_id) {
309
+ if (taxonomy_exists('lingotek_profile')) {
310
+ $terms = wp_get_object_terms($post_id, 'lingotek_profile');
311
+ $term = array_pop($terms);
312
+ return $term;
313
+ }
314
+ else {
315
+ return 'false';
316
+ }
317
+ }
318
  }
admin/profiles-table.php CHANGED
@@ -59,14 +59,14 @@ class Lingotek_Profiles_Table extends WP_List_Table {
59
  if ('disabled' != $item['profile'])
60
  $actions[] = sprintf(
61
  '<a href=%s>%s</a>',
62
- esc_url(admin_url('admin.php?page=wp-lingotek_settings&sm=edit-profile&profile='.$item['profile'])),
63
  __('Edit', 'wp-lingotek')
64
  );
65
 
66
  if (!in_array($item['profile'], array('automatic', 'manual', 'disabled')) && empty($item['usage']))
67
  $actions[] = sprintf(
68
  '<a href="%s" onclick = "return confirm(\'%s\');">%s</a>',
69
- esc_url(wp_nonce_url('admin.php?page=wp-lingotek_settings&sm=profiles&lingotek_action=delete-profile&noheader=true&profile='.$item['profile'], 'delete-profile')),
70
  __('You are about to permanently delete this profile. Are you sure?', 'wp-lingotek'),
71
  __('Delete', 'wp-lingotek')
72
  );
59
  if ('disabled' != $item['profile'])
60
  $actions[] = sprintf(
61
  '<a href=%s>%s</a>',
62
+ esc_url(admin_url('admin.php?page=wp-lingotek_manage&sm=edit-profile&profile='.$item['profile'])),
63
  __('Edit', 'wp-lingotek')
64
  );
65
 
66
  if (!in_array($item['profile'], array('automatic', 'manual', 'disabled')) && empty($item['usage']))
67
  $actions[] = sprintf(
68
  '<a href="%s" onclick = "return confirm(\'%s\');">%s</a>',
69
+ esc_url(wp_nonce_url('admin.php?page=wp-lingotek_manage&sm=profiles&lingotek_action=delete-profile&noheader=true&profile='.$item['profile'], 'delete-profile')),
70
  __('You are about to permanently delete this profile. Are you sure?', 'wp-lingotek'),
71
  __('Delete', 'wp-lingotek')
72
  );
admin/settings.php CHANGED
@@ -13,9 +13,6 @@
13
 
14
  $community_required_menu_items = array(
15
  'defaults' => __('Defaults', 'wp-lingotek'),
16
- 'profiles' => __('Translation Profiles', 'wp-lingotek'),
17
- 'content' => __('Content Type Configuration', 'wp-lingotek'),
18
- 'custom-fields' => __('Custom Fields', 'wp-lingotek'),
19
  'preferences' => __('Preferences', 'wp-lingotek'),
20
  //'advanced' => __('Advanced', 'wp-lingotek'),
21
  //'logging' => __('Logging', 'wp-lingotek'),
13
 
14
  $community_required_menu_items = array(
15
  'defaults' => __('Defaults', 'wp-lingotek'),
 
 
 
16
  'preferences' => __('Preferences', 'wp-lingotek'),
17
  //'advanced' => __('Advanced', 'wp-lingotek'),
18
  //'logging' => __('Logging', 'wp-lingotek'),
admin/settings/view-defaults.php CHANGED
@@ -103,9 +103,8 @@ unset($settings['secondary_filter_id']['options'][$primary_filter_id]);
103
  </select><?php
104
  if ('project_id' == $key) { ?>
105
  <?php
106
- $client = new Lingotek_API();
107
 
108
- if ($client->get_projects($community_id) == 'empty') { ?>
109
  <script> document.getElementById('project_id').style.display = 'none';</script>
110
  <input type="text" name="new_project" id="new_project" placeholder="<?php _e('Enter new project name', 'wp-lingotek') ?>" />
111
  <?php }
103
  </select><?php
104
  if ('project_id' == $key) { ?>
105
  <?php
 
106
 
107
+ if (empty($setting['options'])) { ?>
108
  <script> document.getElementById('project_id').style.display = 'none';</script>
109
  <input type="text" name="new_project" id="new_project" placeholder="<?php _e('Enter new project name', 'wp-lingotek') ?>" />
110
  <?php }
admin/tutorial/features.php CHANGED
@@ -21,12 +21,12 @@
21
 
22
  <div class="changelog feature-section three-col">
23
  <div>
24
- <a href="admin.php?page=wp-lingotek_settings&amp;sm=profiles"><img src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/translation-profiles.png'; ?>"></a>
25
  <h3><?php _e( 'Use translation profiles', 'wp-lingotek'); ?></h3>
26
  <p><?php _e( 'One of the most time-consuming activities of any multilingual web-site project is managing the ongoing flow of changes and additions to site content and configurations. Translation profiles were created to allow you to create and save and re-use your translation settings.', 'wp-lingotek'); ?></p>
27
  </div>
28
  <div>
29
- <a href="admin.php?page=wp-lingotek_settings&amp;sm=content"><img src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/content-types.png'; ?>"></a>
30
  <h3><?php _e( 'Content type profiles', 'wp-lingotek'); ?></h3>
31
  <p><?php _e( 'Content type profiles. Manually choosing which content to upload and download is rarely what a content administrator wants to do, and automating the upload of every change is not workable because there are various types of content. Each type of translatable content can be assigned to a customizable profile. For example, by default, we like to have Posts use an <i>Automatic</i> profile so that content will automatically be uploaded for translation and the resulting translations automatically be downloaded back into WordPress.', 'wp-lingotek'); ?></p>
32
  </div>
@@ -41,7 +41,7 @@
41
 
42
  <div class="changelog feature-section three-col">
43
  <div>
44
- <a href="admin.php?page=wp-lingotek_settings&amp;sm=profiles"><img src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/translation-services.png'; ?>"></a>
45
  <h3><?php _e( 'Need Extra Services?', 'wp-lingotek'); ?></h3>
46
  <p><?php _e( 'Start the process of getting extra services.', 'wp-lingotek'); ?></p>
47
  <ul style="list-style-type: circle;">
21
 
22
  <div class="changelog feature-section three-col">
23
  <div>
24
+ <a href="admin.php?page=wp-lingotek_manage&amp;sm=profiles"><img src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/translation-profiles.png'; ?>"></a>
25
  <h3><?php _e( 'Use translation profiles', 'wp-lingotek'); ?></h3>
26
  <p><?php _e( 'One of the most time-consuming activities of any multilingual web-site project is managing the ongoing flow of changes and additions to site content and configurations. Translation profiles were created to allow you to create and save and re-use your translation settings.', 'wp-lingotek'); ?></p>
27
  </div>
28
  <div>
29
+ <a href="admin.php?page=wp-lingotek_manage&amp;sm=content"><img src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/content-types.png'; ?>"></a>
30
  <h3><?php _e( 'Content type profiles', 'wp-lingotek'); ?></h3>
31
  <p><?php _e( 'Content type profiles. Manually choosing which content to upload and download is rarely what a content administrator wants to do, and automating the upload of every change is not workable because there are various types of content. Each type of translatable content can be assigned to a customizable profile. For example, by default, we like to have Posts use an <i>Automatic</i> profile so that content will automatically be uploaded for translation and the resulting translations automatically be downloaded back into WordPress.', 'wp-lingotek'); ?></p>
32
  </div>
41
 
42
  <div class="changelog feature-section three-col">
43
  <div>
44
+ <a href="admin.php?page=wp-lingotek_manage&amp;sm=profiles"><img src="<?php echo LINGOTEK_URL . '/admin/tutorial/img/translation-services.png'; ?>"></a>
45
  <h3><?php _e( 'Need Extra Services?', 'wp-lingotek'); ?></h3>
46
  <p><?php _e( 'Start the process of getting extra services.', 'wp-lingotek'); ?></p>
47
  <ul style="list-style-type: circle;">
admin/view-dashboard.php CHANGED
@@ -3,7 +3,7 @@
3
  <script>
4
  var cms_data = <?php echo json_encode($cms_data); ?>
5
  </script>
6
- <link rel="stylesheet" href="http://gmc.lingotek.com/v2/styles/ltk.css">
7
- <script src="http://gmc.lingotek.com/v2/ltk.min.js"></script>
8
  <div ltk-dashboard ng-app="LingotekApp" style="margin-top: -15px;"></div>
9
  </div>
3
  <script>
4
  var cms_data = <?php echo json_encode($cms_data); ?>
5
  </script>
6
+ <link rel="stylesheet" href="https://gmc.lingotek.com/v2/styles/ltk.css">
7
+ <script src="https://gmc.lingotek.com/v2/ltk.min.js"></script>
8
  <div ltk-dashboard ng-app="LingotekApp" style="margin-top: -15px;"></div>
9
  </div>
admin/view-manage.php CHANGED
@@ -4,6 +4,9 @@
4
  <?php
5
 
6
  $menu_items = array(
 
 
 
7
  'string-groups' => __('String Groups', 'wp-lingotek'),
8
  'strings' => __('Strings', 'wp-lingotek'),
9
  );
@@ -36,4 +39,4 @@
36
  echo "TO-DO: create <i>" . 'manage/view-' . $submenu . ".php</i>";
37
  ?>
38
 
39
- </div>
4
  <?php
5
 
6
  $menu_items = array(
7
+ 'content' => __('Content Type Configuration', 'wp-lingotek'),
8
+ 'profiles' => __('Translation Profiles', 'wp-lingotek'),
9
+ 'custom-fields' => __('Custom Fields', 'wp-lingotek'),
10
  'string-groups' => __('String Groups', 'wp-lingotek'),
11
  'strings' => __('Strings', 'wp-lingotek'),
12
  );
39
  echo "TO-DO: create <i>" . 'manage/view-' . $submenu . ".php</i>";
40
  ?>
41
 
42
+ </div>
include/api.php CHANGED
@@ -265,7 +265,7 @@ class Lingotek_API extends Lingotek_HTTP {
265
  public function get_projects($community_id) {
266
  $response = $this->get(add_query_arg(array('community_id' => $community_id, 'limit' => 100), $this->api_url . '/project'));
267
  if (wp_remote_retrieve_response_code($response) == 204) {
268
- return 'empty';
269
  }
270
  return !is_wp_error($response) && 200 == wp_remote_retrieve_response_code($response) ? json_decode(wp_remote_retrieve_body($response)) : false;
271
  }
265
  public function get_projects($community_id) {
266
  $response = $this->get(add_query_arg(array('community_id' => $community_id, 'limit' => 100), $this->api_url . '/project'));
267
  if (wp_remote_retrieve_response_code($response) == 204) {
268
+ return array();// there are currently no projects
269
  }
270
  return !is_wp_error($response) && 200 == wp_remote_retrieve_response_code($response) ? json_decode(wp_remote_retrieve_body($response)) : false;
271
  }
include/group-post.php CHANGED
@@ -28,7 +28,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
28
  ),
29
  $language->slug => $object_id // for Polylang
30
  );
31
-
32
  self::_create($object_id, $document_id, $data, 'post_translations');
33
  }
34
 
@@ -107,6 +107,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
107
  */
108
  static public function get_custom_fields_from_wp_postmeta($post_ID = NULL) {
109
  $custom_fields = get_option('lingotek_custom_fields', array());
 
110
  $arr = array();
111
  $keys = array();
112
 
@@ -128,14 +129,11 @@ class Lingotek_Group_Post extends Lingotek_Group {
128
 
129
  foreach ($posts as $post) {
130
  $metadata = has_meta($post->ID);
131
- foreach ($metadata as $key => $value) {
132
- if ($value['meta_key'] === '_encloseme' || $value['meta_key'] === '_edit_last' || $value['meta_key'] === '_edit_lock' || $value['meta_key'] === '_wp_trash_meta_status' || $value['meta_key'] === '_wp_trash_meta_time') {
133
- unset($metadata[$key]);
134
- }
135
- if (in_array($value['meta_key'], $keys)) {
136
  unset($metadata[$key]);
137
  }
138
- $keys [] = $value['meta_key'];
139
  }
140
  $arr = array_merge($arr, $metadata);
141
  }
@@ -143,6 +141,17 @@ class Lingotek_Group_Post extends Lingotek_Group {
143
  return apply_filters('lingotek_post_custom_fields', $arr);
144
  }
145
 
 
 
 
 
 
 
 
 
 
 
 
146
  /*
147
  * updates meta (custom) fields values in the lingotek_custom_fields option
148
  *
@@ -158,41 +167,33 @@ class Lingotek_Group_Post extends Lingotek_Group {
158
  $items = array();
159
 
160
  foreach ($custom_fields_from_postmeta as $cf) {
 
 
 
 
 
 
161
  // no lingotek setting
162
  if (!array_key_exists($cf['meta_key'], $custom_fields_from_lingotek)) {
163
  // no lingotek setting, but there's a wpml setting
164
  if (array_key_exists($cf['meta_key'], $custom_fields_from_wpml)) {
165
  $custom_fields[$cf['meta_key']] = $custom_fields_from_wpml[$cf['meta_key']];
166
- $arr = array(
167
- 'meta_key' => $cf['meta_key'],
168
- 'setting' => $custom_fields_from_wpml[$cf['meta_key']],
169
- );
170
  }
171
  // no lingotek setting, no wpml setting, so save default setting of ignore
172
  else {
173
- $custom_fields[$cf['meta_key']] = 'ignore';
174
- $arr = array(
175
- 'meta_key' => $cf['meta_key'],
176
- 'setting' => 'ignore',
177
- );
178
  }
179
- }
180
  // lingotek already has this field setting saved
181
  else {
182
- $custom_fields[$cf['meta_key']] = $custom_fields_from_lingotek[$cf['meta_key']];
183
- $arr = array(
184
- 'meta_key' => $cf['meta_key'],
185
- 'setting' => $custom_fields_from_lingotek[$cf['meta_key']],
186
- );
187
  }
188
- $items [] = $arr;
189
- }
190
 
191
  if ($post_ID) {
192
  $custom_fields = array_merge($custom_fields_from_lingotek, $custom_fields);
193
  }
194
  update_option('lingotek_custom_fields', $custom_fields);
195
- return $items;
196
  }
197
 
198
  /*
@@ -209,6 +210,9 @@ class Lingotek_Group_Post extends Lingotek_Group {
209
 
210
  if (is_array($custom_fields_from_lingotek)) {
211
  foreach ($custom_fields_from_lingotek as $key => $setting) {
 
 
 
212
  $arr = array(
213
  'meta_key' => $key,
214
  'setting' => $setting,
@@ -305,25 +309,14 @@ class Lingotek_Group_Post extends Lingotek_Group {
305
  $tr_post['ID'] = $tr_id;
306
 
307
  // copy or ignore metas
308
- $custom_fields = get_option('lingotek_custom_fields', array());
309
- foreach ($custom_fields as $key => $setting) {
310
- if ('copy' === $setting) {
311
- $source_meta = current(get_post_meta($post->ID, $key)) ;
312
- update_post_meta($tr_id, $key, $source_meta);
313
- }
314
- elseif ('ignore' === $setting) {
315
- delete_post_meta($tr_id, $key);
316
- }
317
- }
318
 
319
  // translate metas
320
- if (!empty($translation['metas'])) {
321
- foreach ($translation['metas'] as $key => $meta)
322
- update_post_meta($tr_id, $key, $meta);
323
  }
324
 
325
  wp_update_post($tr_post);
326
-
327
  $this->safe_translation_status_update($locale, 'current');
328
  }
329
 
@@ -348,7 +341,6 @@ class Lingotek_Group_Post extends Lingotek_Group {
348
  if ($tr_id) {
349
  $tr_lang = $this->pllm->get_language($locale);
350
  $this->pllm->set_post_language($tr_id, $tr_lang);
351
-
352
  $this->safe_translation_status_update($locale, 'current', array($tr_lang->slug => $tr_id));
353
  wp_set_object_terms($tr_id, $this->term_id, 'post_translations');
354
 
@@ -356,21 +348,11 @@ class Lingotek_Group_Post extends Lingotek_Group {
356
  $GLOBALS['polylang']->sync->copy_post_metas($this->source, $tr_id, $tr_lang->slug);
357
 
358
  // copy or ignore metas
359
- $custom_fields = get_option('lingotek_custom_fields', array());
360
- foreach ($custom_fields as $key => $setting) {
361
- if ('copy' === $setting) {
362
- $source_meta = current(get_post_meta($post->ID, $key)) ;
363
- update_post_meta($tr_id, $key, $source_meta);
364
- }
365
- elseif ('ignore' === $setting) {
366
- delete_post_meta($tr_id, $key);
367
- }
368
- }
369
 
370
  // translate metas
371
- if (!empty($translation['metas'])) {
372
- foreach ($translation['metas'] as $key => $meta)
373
- update_post_meta($tr_id, $key, $meta);
374
  }
375
  }
376
  }
@@ -382,6 +364,38 @@ class Lingotek_Group_Post extends Lingotek_Group {
382
  add_filter('content_filtered_save_pre', 'wp_filter_post_kses');
383
  }
384
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
385
  /*
386
  * checks if content should be automatically uploaded
387
  *
@@ -390,7 +404,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
390
  * @return bool
391
  */
392
  public function is_automatic_upload() {
393
- return 'automatic' == Lingotek_Model::get_profile_option('upload', get_post_type($this->source), $this->get_source_language());
394
  }
395
 
396
  /*
@@ -403,4 +417,18 @@ class Lingotek_Group_Post extends Lingotek_Group {
403
  public function get_source_language() {
404
  return $this->pllm->get_post_language($this->source);
405
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
406
  }
28
  ),
29
  $language->slug => $object_id // for Polylang
30
  );
31
+ self::save_hash_on_upload($object_id);
32
  self::_create($object_id, $document_id, $data, 'post_translations');
33
  }
34
 
107
  */
108
  static public function get_custom_fields_from_wp_postmeta($post_ID = NULL) {
109
  $custom_fields = get_option('lingotek_custom_fields', array());
110
+ $meta_black_list = array('_encloseme', '_edit_last', '_edit_lock', '_wp_trash_meta_status', '_wp_trash_meta_time');
111
  $arr = array();
112
  $keys = array();
113
 
129
 
130
  foreach ($posts as $post) {
131
  $metadata = has_meta($post->ID);
132
+ foreach ($metadata as $key => $meta) {
133
+ if (in_array($meta['meta_key'], $meta_black_list) || in_array($meta['meta_key'], $keys)) {
 
 
 
134
  unset($metadata[$key]);
135
  }
136
+ $keys [] = $meta['meta_key'];
137
  }
138
  $arr = array_merge($arr, $metadata);
139
  }
141
  return apply_filters('lingotek_post_custom_fields', $arr);
142
  }
143
 
144
+ /*
145
+ * tests whether a meta belongs to the Advanced Custom Fields plugin
146
+ *
147
+ * @since 0.2
148
+ *
149
+ * @return bool
150
+ */
151
+ protected static function is_advanced_custom_fields_meta($key, $value) {
152
+ return ((substr($key, 0, strlen('_')) === '_') && (substr($value, 0, strlen('field_')) === 'field_' )) ? TRUE : FALSE;
153
+ }
154
+
155
  /*
156
  * updates meta (custom) fields values in the lingotek_custom_fields option
157
  *
167
  $items = array();
168
 
169
  foreach ($custom_fields_from_postmeta as $cf) {
170
+ // hide-copy means hide from user, and always copy to translations (Advanced Custom Fields plugin)
171
+ if (self::is_advanced_custom_fields_meta($cf['meta_key'], $cf['meta_value'])) {
172
+ $custom_fields[$cf['meta_key']] = 'hide-copy';
173
+ continue;
174
+ }
175
+
176
  // no lingotek setting
177
  if (!array_key_exists($cf['meta_key'], $custom_fields_from_lingotek)) {
178
  // no lingotek setting, but there's a wpml setting
179
  if (array_key_exists($cf['meta_key'], $custom_fields_from_wpml)) {
180
  $custom_fields[$cf['meta_key']] = $custom_fields_from_wpml[$cf['meta_key']];
 
 
 
 
181
  }
182
  // no lingotek setting, no wpml setting, so save default setting of ignore
183
  else {
184
+ $custom_fields[$cf['meta_key']] = 'ignore';
 
 
 
 
185
  }
186
+ }
187
  // lingotek already has this field setting saved
188
  else {
189
+ $custom_fields[$cf['meta_key']] = $custom_fields_from_lingotek[$cf['meta_key']];
 
 
 
 
190
  }
191
+ }
 
192
 
193
  if ($post_ID) {
194
  $custom_fields = array_merge($custom_fields_from_lingotek, $custom_fields);
195
  }
196
  update_option('lingotek_custom_fields', $custom_fields);
 
197
  }
198
 
199
  /*
210
 
211
  if (is_array($custom_fields_from_lingotek)) {
212
  foreach ($custom_fields_from_lingotek as $key => $setting) {
213
+ if ($setting === 'hide-copy') {
214
+ continue;
215
+ }
216
  $arr = array(
217
  'meta_key' => $key,
218
  'setting' => $setting,
309
  $tr_post['ID'] = $tr_id;
310
 
311
  // copy or ignore metas
312
+ self::copy_or_ignore_metas($post->ID, $tr_id);
 
 
 
 
 
 
 
 
 
313
 
314
  // translate metas
315
+ if (isset($translation['metas'])) {
316
+ self::copy_translated_metas($translation['metas'], $tr_id);
 
317
  }
318
 
319
  wp_update_post($tr_post);
 
320
  $this->safe_translation_status_update($locale, 'current');
321
  }
322
 
341
  if ($tr_id) {
342
  $tr_lang = $this->pllm->get_language($locale);
343
  $this->pllm->set_post_language($tr_id, $tr_lang);
 
344
  $this->safe_translation_status_update($locale, 'current', array($tr_lang->slug => $tr_id));
345
  wp_set_object_terms($tr_id, $this->term_id, 'post_translations');
346
 
348
  $GLOBALS['polylang']->sync->copy_post_metas($this->source, $tr_id, $tr_lang->slug);
349
 
350
  // copy or ignore metas
351
+ self::copy_or_ignore_metas($post->ID, $tr_id);
 
 
 
 
 
 
 
 
 
352
 
353
  // translate metas
354
+ if (isset($translation['metas'])) {
355
+ self::copy_translated_metas($translation['metas'], $tr_id);
 
356
  }
357
  }
358
  }
364
  add_filter('content_filtered_save_pre', 'wp_filter_post_kses');
365
  }
366
 
367
+ /*
368
+ * copies source meta strings to translations or deletes meta if set to ignore
369
+ *
370
+ * @since 1.0.9
371
+ */
372
+
373
+ protected static function copy_or_ignore_metas($post_id, $tr_id) {
374
+ // copy or ignore metas
375
+ $custom_fields = get_option('lingotek_custom_fields', array());
376
+ foreach ($custom_fields as $key => $setting) {
377
+ if ('copy' === $setting || 'hide-copy' === $setting) {
378
+ $source_meta = current(get_post_meta($post_id, $key)) ;
379
+ update_post_meta($tr_id, $key, $source_meta);
380
+ }
381
+ elseif ('ignore' === $setting) {
382
+ delete_post_meta($tr_id, $key);
383
+ }
384
+ }
385
+ }
386
+
387
+ /*
388
+ * inserts translated meta values into translations
389
+ *
390
+ * @since 1.0.9
391
+ */
392
+ protected static function copy_translated_metas($translation_metas, $tr_id) {
393
+ if (!empty($translation_metas)) {
394
+ foreach ($translation_metas as $key => $meta)
395
+ update_post_meta($tr_id, $key, $meta);
396
+ }
397
+ }
398
+
399
  /*
400
  * checks if content should be automatically uploaded
401
  *
404
  * @return bool
405
  */
406
  public function is_automatic_upload() {
407
+ return 'automatic' == Lingotek_Model::get_profile_option('upload', get_post_type($this->source), $this->get_source_language(), false, $this->source);
408
  }
409
 
410
  /*
417
  public function get_source_language() {
418
  return $this->pllm->get_post_language($this->source);
419
  }
420
+
421
+ /*
422
+ * creates hash for lingotek_hash term
423
+ *
424
+ * @since 1.0.9
425
+ */
426
+ protected static function save_hash_on_upload($object_id) {
427
+ $post = get_post($object_id);
428
+ $document_id = 'lingotek_hash_' . $post->ID;
429
+ $new_hash = md5(Lingotek_Group_Post::get_content($post));
430
+
431
+ wp_insert_term($document_id, 'lingotek_hash', array('description' => $new_hash));
432
+ wp_set_object_terms($post->ID, $document_id, 'lingotek_hash');
433
+ }
434
  }
include/group.php CHANGED
@@ -177,7 +177,7 @@ abstract class Lingotek_Group {
177
  public function request_translation($locale) {
178
  $client = new Lingotek_API();
179
  $language = $this->pllm->get_language($locale);
180
- $workflow = Lingotek_Model::get_profile_option('workflow_id', $this->type, $this->get_source_language(), $language);
181
  $args = $workflow ? array('workflow_id' => $workflow) : array();
182
 
183
  if (!$this->is_disabled_target($language) && empty($this->translations[$language->locale])) {
@@ -200,7 +200,7 @@ abstract class Lingotek_Group {
200
 
201
  foreach ($this->pllm->get_languages_list() as $lang) {
202
  if ($source_language->slug != $lang->slug && !$this->is_disabled_target($lang) && empty($this->translations[$lang->locale])) {
203
- $workflow = Lingotek_Model::get_profile_option('workflow_id', $this->type, $source_language, $lang);
204
  $args = $workflow ? array('workflow_id' => $workflow) : array();
205
  $client->request_translation($this->document_id, $lang->lingotek_locale, $args);
206
  $this->status = 'current';
@@ -283,7 +283,7 @@ abstract class Lingotek_Group {
283
  * @return bool
284
  */
285
  public function is_automatic_download($locale) {
286
- return 'automatic' == Lingotek_Model::get_profile_option('download', $this->type, $this->get_source_language(), $this->pllm->get_language($locale));
287
  }
288
 
289
  /*
@@ -295,7 +295,7 @@ abstract class Lingotek_Group {
295
  * @param object $language
296
  */
297
  public function is_disabled_target($language) {
298
- $profile = Lingotek_Model::get_profile($this->type, $language);
299
  return isset($profile['targets'][$language->slug]) && 'disabled' == $profile['targets'][$language->slug];
300
  }
301
  }
177
  public function request_translation($locale) {
178
  $client = new Lingotek_API();
179
  $language = $this->pllm->get_language($locale);
180
+ $workflow = Lingotek_Model::get_profile_option('workflow_id', $this->type, $this->get_source_language(), $language, $this->source);
181
  $args = $workflow ? array('workflow_id' => $workflow) : array();
182
 
183
  if (!$this->is_disabled_target($language) && empty($this->translations[$language->locale])) {
200
 
201
  foreach ($this->pllm->get_languages_list() as $lang) {
202
  if ($source_language->slug != $lang->slug && !$this->is_disabled_target($lang) && empty($this->translations[$lang->locale])) {
203
+ $workflow = Lingotek_Model::get_profile_option('workflow_id', $this->type, $source_language, $lang, $this->source);
204
  $args = $workflow ? array('workflow_id' => $workflow) : array();
205
  $client->request_translation($this->document_id, $lang->lingotek_locale, $args);
206
  $this->status = 'current';
283
  * @return bool
284
  */
285
  public function is_automatic_download($locale) {
286
+ return 'automatic' == Lingotek_Model::get_profile_option('download', $this->type, $this->get_source_language(), $this->pllm->get_language($locale), $this->source);
287
  }
288
 
289
  /*
295
  * @param object $language
296
  */
297
  public function is_disabled_target($language) {
298
+ $profile = Lingotek_Model::get_profile($this->type, $language, $this->source);
299
  return isset($profile['targets'][$language->slug]) && 'disabled' == $profile['targets'][$language->slug];
300
  }
301
  }
include/model.php CHANGED
@@ -16,6 +16,9 @@ class Lingotek_Model {
16
  */
17
  public function __construct() {
18
  $this->pllm = $GLOBALS['polylang']->model;
 
 
 
19
  }
20
 
21
  /*
@@ -109,10 +112,21 @@ class Lingotek_Model {
109
  * @param object $language
110
  * @return array
111
  */
112
- static public function get_profile($type, $language) {
113
  $content_types = get_option('lingotek_content_type');
114
  $profiles = get_option('lingotek_profiles');
115
 
 
 
 
 
 
 
 
 
 
 
 
116
  // default profile is manual except for post
117
  $default = 'post' == $type ? 'automatic' : 'manual';
118
 
@@ -152,8 +166,8 @@ class Lingotek_Model {
152
  * @param object $target_language optional, needed to get custom target informations 'workflow_id' | 'download'
153
  * @return string | bool either the option or false if the translation is disabled
154
  */
155
- static public function get_profile_option($item, $type, $source_language, $target_language = false) {
156
- $profile = self::get_profile($type, $source_language);
157
  if ('disabled' == $profile['profile'])
158
  return false;
159
 
@@ -180,7 +194,7 @@ class Lingotek_Model {
180
  if (empty($post) || empty($language))
181
  return;
182
 
183
- $profile = self::get_profile($post->post_type, $language);
184
  if ('disabled' == $profile['profile'])
185
  return;
186
 
@@ -191,17 +205,17 @@ class Lingotek_Model {
191
  'title' => $post->post_title,
192
  'content' => Lingotek_Group_Post::get_content($post),
193
  'locale_code' => $language->lingotek_locale,
194
- 'project_id' => self::get_profile_option('project_id', $post->post_type, $language),
195
- 'workflow_id' => self::get_profile_option('workflow_id', $post->post_type, $language),
196
  'external_url' => $external_url,
197
  );
198
 
199
  $filter_ids = array();
200
- if (self::get_profile_option('primary_filter_id', $post->post_type, $language)) {
201
- $filter_ids['fprm_id'] = self::get_profile_option('primary_filter_id',$post->post_type, $language);
202
  }
203
- if (self::get_profile_option('secondary_filter_id', $post->post_type, $language)) {
204
- $filter_ids['fprm_subfilter_id'] = self::get_profile_option('secondary_filter_id',$post->post_type, $language);
205
  }
206
  $params = array_merge($params, $filter_ids);
207
 
@@ -567,8 +581,11 @@ class Lingotek_Model {
567
  $group = unserialize($group);
568
  if (isset($group['lingotek']['translations'])) {
569
  foreach ($group['lingotek']['translations'] as $locale => $status) {
570
- if (('pending' == $status || 'ready' == $status) && $language = $this->pllm->get_language($locale))
571
- $sources[$language->slug]--;
 
 
 
572
  }
573
  }
574
  }
16
  */
17
  public function __construct() {
18
  $this->pllm = $GLOBALS['polylang']->model;
19
+
20
+ register_taxonomy('lingotek_profile', null , array('label' => false, 'public' => false, 'query_var' => false, 'rewrite' => false));
21
+ register_taxonomy('lingotek_hash', null , array('label' => false, 'public' => false, 'query_var' => false, 'rewrite' => false));
22
  }
23
 
24
  /*
112
  * @param object $language
113
  * @return array
114
  */
115
+ static public function get_profile($type, $language, $post_id = null) {
116
  $content_types = get_option('lingotek_content_type');
117
  $profiles = get_option('lingotek_profiles');
118
 
119
+ // If a profile is set for a specific post/page get that first
120
+ if ($post_id) {
121
+ $terms = get_terms('lingotek_profile', 'orderby=count&hide_empty=0');
122
+ foreach ($terms as $term) {
123
+ $extracted_post_id = str_replace('lingotek_profile_', '', $term->name);
124
+ if ($extracted_post_id == $post_id) {
125
+ return $profiles[$term->description];
126
+ }
127
+ }
128
+ }
129
+
130
  // default profile is manual except for post
131
  $default = 'post' == $type ? 'automatic' : 'manual';
132
 
166
  * @param object $target_language optional, needed to get custom target informations 'workflow_id' | 'download'
167
  * @return string | bool either the option or false if the translation is disabled
168
  */
169
+ static public function get_profile_option($item, $type, $source_language, $target_language = false, $post_id = null) {
170
+ $profile = self::get_profile($type, $source_language, $post_id);
171
  if ('disabled' == $profile['profile'])
172
  return false;
173
 
194
  if (empty($post) || empty($language))
195
  return;
196
 
197
+ $profile = self::get_profile($post->post_type, $language, $post_id);
198
  if ('disabled' == $profile['profile'])
199
  return;
200
 
205
  'title' => $post->post_title,
206
  'content' => Lingotek_Group_Post::get_content($post),
207
  'locale_code' => $language->lingotek_locale,
208
+ 'project_id' => self::get_profile_option('project_id', $post->post_type, $language, false, $post_id),
209
+ 'workflow_id' => self::get_profile_option('workflow_id', $post->post_type, $language, false, $post_id),
210
  'external_url' => $external_url,
211
  );
212
 
213
  $filter_ids = array();
214
+ if (self::get_profile_option('primary_filter_id', $post->post_type, $language, false, $post_id)) {
215
+ $filter_ids['fprm_id'] = self::get_profile_option('primary_filter_id',$post->post_type, $language, false, $post_id);
216
  }
217
+ if (self::get_profile_option('secondary_filter_id', $post->post_type, $language, false, $post_id)) {
218
+ $filter_ids['fprm_subfilter_id'] = self::get_profile_option('secondary_filter_id',$post->post_type, $language, false, $post_id);
219
  }
220
  $params = array_merge($params, $filter_ids);
221
 
581
  $group = unserialize($group);
582
  if (isset($group['lingotek']['translations'])) {
583
  foreach ($group['lingotek']['translations'] as $locale => $status) {
584
+ if (('pending' == $status || 'ready' == $status) && $language = $this->pllm->get_language($locale)) {
585
+ if ($sources[$language->slug] > 0) {
586
+ $sources[$language->slug]--;
587
+ }
588
+ }
589
  }
590
  }
591
  }
js/updater.js CHANGED
@@ -96,6 +96,9 @@ jQuery(document).ready(function($) {
96
  $(td).find('.pll_icon_edit').remove();
97
  updateUploadIndicator(td, data, key, locale);
98
  }
 
 
 
99
  else if ($(td).find('.pll_icon_add').length > 0 && data[key][data[key]['source']]['status'] === 'none'){
100
  break;
101
  }
96
  $(td).find('.pll_icon_edit').remove();
97
  updateUploadIndicator(td, data, key, locale);
98
  }
99
+ else if (data[key][locale]['status'] === 'disabled' || data[key]['source'] === 'disabled') {
100
+ $(td).find('.lingotek-color').remove();
101
+ }
102
  else if ($(td).find('.pll_icon_add').length > 0 && data[key][data[key]['source']]['status'] === 'none'){
103
  break;
104
  }
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.0.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.
@@ -15,7 +15,7 @@ GitHub Plugin URI: https://github.com/lingotek/wp-lingotek
15
  if (!function_exists('add_action'))
16
  exit();
17
 
18
- define('LINGOTEK_VERSION', '1.0.9'); // plugin version (should match above meta)
19
  define('LINGOTEK_MIN_PLL_VERSION', '1.7.4.2');
20
  define('LINGOTEK_BASENAME', plugin_basename(__FILE__)); // plugin name as known by WP
21
  define('LINGOTEK_PLUGIN_SLUG', 'wp-lingotek');// plugin slug (should match above meta: Text Domain)
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.1
6
  Author: Lingotek and Frédéric Demarle
7
  Author uri: http://lingotek.com
8
  Description: Lingotek offers convenient cloud-based localization and translation.
15
  if (!function_exists('add_action'))
16
  exit();
17
 
18
+ define('LINGOTEK_VERSION', '1.1'); // plugin version (should match above meta)
19
  define('LINGOTEK_MIN_PLL_VERSION', '1.7.4.2');
20
  define('LINGOTEK_BASENAME', plugin_basename(__FILE__)); // plugin name as known by WP
21
  define('LINGOTEK_PLUGIN_SLUG', 'wp-lingotek');// plugin slug (should match above meta: Text Domain)
readme.txt CHANGED
@@ -4,7 +4,7 @@ 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.3
7
- Stable tag: 1.0.9
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -58,7 +58,7 @@ Wherever third party code has been used, credit has been given in the code’s c
58
 
59
  = Do you like Lingotek? =
60
 
61
- Don't hesitate to [give your feedback](http://wordpress.org/support/view/plugin-reviews/lingotek#postform). It will help make the plugin better. Other [contributions](http://lingotek.wordpress.com/documentation/contribute/) (helping other users on the support forum) are welcome!
62
 
63
  == Installation ==
64
 
@@ -115,6 +115,16 @@ For more, visit the [Lingotek documentation site](https://lingotek.atlassian.net
115
 
116
  == Changelog ==
117
 
 
 
 
 
 
 
 
 
 
 
118
  = 1.0.9 (2015-08-19) =
119
 
120
  * Fixed error with YouTube videos not displaying in translations
4
  Tags: automation, bilingual, international, language, Lingotek, localization, multilanguage, multilingual, translate, translation
5
  Requires at least: 3.8
6
  Tested up to: 4.3
7
+ Stable tag: 1.1
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
58
 
59
  = Do you like Lingotek? =
60
 
61
+ Don't hesitate to [give your feedback](https://wordpress.org/support/view/plugin-reviews/lingotek-translation). It will help make the plugin better. Other [contributions](https://wordpress.org/support/plugin/lingotek-translation) (helping other users on the support forum) are welcome!
62
 
63
  == Installation ==
64
 
115
 
116
  == Changelog ==
117
 
118
+ = 1.1 (2015-08-28) =
119
+
120
+ * Added the option to set a Translation Profile per Post/Page which will override the Content Type default Translation Profile
121
+ * The selected Translation Profile is now displayed on bulk display of Posts/Pages
122
+ * Minor fixes for real-time translation status updates
123
+ * Fixed a bug that prevented updating of content
124
+ * Custom fields enhancements and fixes
125
+ * Moved Content Type Configuration, Translation Profiles, and Custom Fields tabs from the Settings Page to the Manage Page
126
+ * Fixed Lingotek Dashboard counting error
127
+
128
  = 1.0.9 (2015-08-19) =
129
 
130
  * Fixed error with YouTube videos not displaying in translations