Version Description
(2021-08-05) = * New UI - The source and translation icons have been replaced with chips. This makes it easier to view which stage the translations are in. - Added dropdown actions to the source and target chips. - Added Cancel option for specific targets in the action dropdown. *New Gone status - This will give you a visual indicator when a document or target has been archived or deleted.
Download this release
Release Info
Developer | sowmiya2021 |
Plugin | Lingotek Translation |
Version | 1.5.0 |
Comparing to | |
See all releases |
Code changes from version 1.4.16 to 1.5.0
- admin/action-url.php +49 -0
- admin/actions.php +272 -60
- admin/admin.php +9 -6
- admin/chip-base.php +126 -0
- admin/chip-source.php +115 -0
- admin/chip-target.php +138 -0
- admin/filters-columns.php +132 -6
- admin/post-actions.php +7 -1
- admin/tutorial/content.php +11 -1
- css/actions.css +73 -0
- css/statuses.css +255 -0
- here +0 -0
- img/icon-collapse.svg +4 -0
- include/api.php +61 -43
- include/callback.php +77 -13
- include/group.php +18 -4
- include/model.php +51 -6
- js/actions.js +38 -0
- js/progress.js +3 -0
- js/updater.js +9 -1
- lingotek.php +57 -13
- readme.txt +9 -1
- sanitization.php +33 -0
- tests/test-action-url.php +43 -0
admin/action-url.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Helper class to model an action interacting with Lingotek.
|
5 |
+
*
|
6 |
+
* @since 1.5.0
|
7 |
+
*/
|
8 |
+
class Lingotek_Action_Url {
|
9 |
+
|
10 |
+
/**
|
11 |
+
* The uri.
|
12 |
+
*
|
13 |
+
* @var string
|
14 |
+
*/
|
15 |
+
protected $uri;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* The title.
|
19 |
+
*
|
20 |
+
* @var string
|
21 |
+
*/
|
22 |
+
protected $title;
|
23 |
+
|
24 |
+
public function __construct( $uri, $title ) {
|
25 |
+
$this->uri = $uri;
|
26 |
+
$this->title = $title;
|
27 |
+
}
|
28 |
+
|
29 |
+
public function getTitle() {
|
30 |
+
return $this->title;
|
31 |
+
}
|
32 |
+
|
33 |
+
public function getUri() {
|
34 |
+
return $this->uri;
|
35 |
+
}
|
36 |
+
|
37 |
+
public function render() {
|
38 |
+
return sprintf(
|
39 |
+
'
|
40 |
+
<li>
|
41 |
+
<a href="%s">%s</a>
|
42 |
+
</li>
|
43 |
+
',
|
44 |
+
$this->getUri(),
|
45 |
+
$this->getTitle()
|
46 |
+
);
|
47 |
+
}
|
48 |
+
|
49 |
+
}
|
admin/actions.php
CHANGED
@@ -90,48 +90,56 @@ abstract class Lingotek_Actions {
|
|
90 |
'action' => __( 'Upload to Lingotek', 'lingotek-translation' ),
|
91 |
'progress' => __( 'Uploading...', 'lingotek-translation' ),
|
92 |
'description' => __( 'Upload this item to Lingotek TMS', 'lingotek-translation' ),
|
|
|
93 |
),
|
94 |
|
95 |
'request' => array(
|
96 |
'action' => __( 'Request translations', 'lingotek-translation' ),
|
97 |
'progress' => __( 'Requesting translations...', 'lingotek-translation' ),
|
98 |
'description' => __( 'Request translations of this item to Lingotek TMS', 'lingotek-translation' ),
|
|
|
99 |
),
|
100 |
|
101 |
'status' => array(
|
102 |
'action' => __( 'Update translations status', 'lingotek-translation' ),
|
103 |
'progress' => __( 'Updating translations status...', 'lingotek-translation' ),
|
104 |
'description' => __( 'Update translations status of this item in Lingotek TMS', 'lingotek-translation' ),
|
|
|
105 |
),
|
106 |
|
107 |
'download' => array(
|
108 |
'action' => __( 'Download translations', 'lingotek-translation' ),
|
109 |
'progress' => __( 'Downloading translations...', 'lingotek-translation' ),
|
110 |
'description' => __( 'Download translations of this item from Lingotek TMS', 'lingotek-translation' ),
|
|
|
111 |
),
|
112 |
|
113 |
'cancel' => array(
|
114 |
'action' => __( 'Cancel translations', 'lingotek-translation' ),
|
115 |
'progress' => __( 'Cancelling translations...', 'lingotek-translation' ),
|
116 |
'description' => __( 'Cancel the translations of this item from Lingotek TMS', 'lingotek-translation' ),
|
|
|
117 |
),
|
118 |
|
119 |
'delete' => array(
|
120 |
'action' => __( 'Delete translations', 'lingotek-translation' ),
|
121 |
'progress' => __( 'Deleting translations...', 'lingotek-translation' ),
|
122 |
'description' => __( 'Delete the translations of this item from Lingotek TMS', 'lingotek-translation' ),
|
|
|
123 |
),
|
124 |
|
125 |
'cancel-translation' => array(
|
126 |
'action' => __( 'Cancel translation', 'lingotek-translation' ),
|
127 |
'progress' => __( 'Cancelling translation', 'lingotek-translation' ),
|
128 |
'description' => __( 'Cancel this translation from Lingotek TMS', 'lingotek-translation' ),
|
|
|
129 |
),
|
130 |
|
131 |
'delete-translation' => array(
|
132 |
'action' => __( 'Delete translation', 'lingotek-translation' ),
|
133 |
'progress' => __( 'Deleting translation', 'lingotek-translation' ),
|
134 |
'description' => __( 'Delete this translation from Lingotek TMS', 'lingotek-translation' ),
|
|
|
135 |
),
|
136 |
);
|
137 |
|
@@ -202,6 +210,16 @@ abstract class Lingotek_Actions {
|
|
202 |
'title' => __( 'Translation has been cancelled', 'lingotek-translation' ),
|
203 |
'icon' => 'warning',
|
204 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
205 |
);
|
206 |
|
207 |
$this->type = $type;
|
@@ -215,11 +233,11 @@ abstract class Lingotek_Actions {
|
|
215 |
add_action( 'wp_ajax_get_user_payment_information', array( &$this, 'ajax_get_user_payment_information' ) );
|
216 |
add_action( 'wp_ajax_get_ltk_terms_and_conditions', array( &$this, 'ajax_get_ltk_terms_and_conditions' ) );
|
217 |
|
218 |
-
foreach (
|
219 |
-
if ( strpos( $action, '-translation' ) ) {
|
220 |
continue;
|
221 |
}
|
222 |
-
add_action( 'wp_ajax_lingotek_progress_' . $this->type . '_' . $action, array( &$this, 'ajax_' . $action ) );
|
223 |
}
|
224 |
}
|
225 |
|
@@ -238,6 +256,31 @@ abstract class Lingotek_Actions {
|
|
238 |
return Lingotek_API::PRODUCTION_URL . "/workbench/document/$document_id/locale/$locale";
|
239 |
}
|
240 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
241 |
/**
|
242 |
* Outputs an action icon
|
243 |
*
|
@@ -296,16 +339,8 @@ abstract class Lingotek_Actions {
|
|
296 |
* @param bool $confirm
|
297 |
*/
|
298 |
public function upload_icon( $object_id, $confirm = false ) {
|
299 |
-
$
|
300 |
-
|
301 |
-
'action' => 'lingotek-upload',
|
302 |
-
'noheader' => true,
|
303 |
-
);
|
304 |
-
if ( isset( $args['string'] ) ) {
|
305 |
-
$args['string'] = rawurlencode( $args['string'] );
|
306 |
-
}
|
307 |
-
$link = wp_nonce_url( defined( 'DOING_AJAX' ) && DOING_AJAX ? add_query_arg( $args, wp_get_referer() ) : add_query_arg( $args ), 'lingotek-upload' );
|
308 |
-
self::link_to_settings_if_not_connected( $link );
|
309 |
return self::display_icon( 'upload', $link, $confirm ? self::$confirm_message : '' );
|
310 |
}
|
311 |
|
@@ -384,17 +419,7 @@ abstract class Lingotek_Actions {
|
|
384 |
public static function translation_icon( $document, $language ) {
|
385 |
if ( isset( $document->translations[ $language->locale ] ) ) {
|
386 |
if ( 'ready' === $document->translations[ $language->locale ] ) {
|
387 |
-
$link =
|
388 |
-
add_query_arg(
|
389 |
-
array(
|
390 |
-
'document_id' => $document->document_id,
|
391 |
-
'locale' => $language->locale,
|
392 |
-
'action' => 'lingotek-download',
|
393 |
-
'noheader' => true,
|
394 |
-
)
|
395 |
-
),
|
396 |
-
'lingotek-download'
|
397 |
-
);
|
398 |
self::link_to_settings_if_not_connected( $link );
|
399 |
return self::display_icon( $document->translations[ $language->locale ], $link );
|
400 |
} elseif ( 'not-current' === $document->translations[ $language->locale ] ) {
|
@@ -403,23 +428,17 @@ abstract class Lingotek_Actions {
|
|
403 |
} elseif ( 'current' !== $document->translations[ $language->locale ] && $custom_icon = $document->get_custom_in_progress_icon( $language ) ) {
|
404 |
return $custom_icon;
|
405 |
} else {
|
406 |
-
$link
|
|
|
|
|
|
|
|
|
|
|
407 |
self::link_to_settings_if_not_connected( $link );
|
408 |
-
return self::display_icon( $document->translations[ $language->locale ], $link,
|
409 |
}//end if
|
410 |
} else {
|
411 |
-
$link =
|
412 |
-
add_query_arg(
|
413 |
-
array(
|
414 |
-
'document_id' => $document->document_id,
|
415 |
-
'locale' => $language->locale,
|
416 |
-
'action' => 'lingotek-request',
|
417 |
-
'noheader' => true,
|
418 |
-
),
|
419 |
-
defined( 'DOING_AJAX' ) && DOING_AJAX ? wp_get_referer() : wp_get_referer()
|
420 |
-
),
|
421 |
-
'lingotek-request'
|
422 |
-
);
|
423 |
self::link_to_settings_if_not_connected( $link );
|
424 |
return self::display_icon( 'request', $link );
|
425 |
}//end if
|
@@ -431,17 +450,7 @@ abstract class Lingotek_Actions {
|
|
431 |
* @since 1.4.3
|
432 |
*/
|
433 |
public function failed_import_icon( $name, $object_id ) {
|
434 |
-
$
|
435 |
-
$this->type => $object_id,
|
436 |
-
'action' => 'lingotek-upload',
|
437 |
-
'noheader' => true,
|
438 |
-
);
|
439 |
-
if ( isset( $args['string'] ) ) {
|
440 |
-
$args['string'] = rawurlencode( $args['string'] );
|
441 |
-
}
|
442 |
-
$link = wp_nonce_url( defined( 'DOING_AJAX' ) && DOING_AJAX ? add_query_arg( $args, wp_get_referer() ) : add_query_arg( $args ), 'lingotek-upload' );
|
443 |
-
self::link_to_settings_if_not_connected( $link );
|
444 |
-
|
445 |
return sprintf(
|
446 |
'<a class="%s dashicons dashicons-%s" title="%s" href="%s"></a>',
|
447 |
self::$icons[ $name ]['class'],
|
@@ -652,7 +661,7 @@ abstract class Lingotek_Actions {
|
|
652 |
$actions['lingotek-cancel-translation'] = $this->get_action_link(
|
653 |
array(
|
654 |
'document_id' => $document->document_id,
|
655 |
-
'target_id' => $
|
656 |
'target_locale' => $target_locale,
|
657 |
'action' => 'cancel-translation',
|
658 |
),
|
@@ -680,14 +689,19 @@ abstract class Lingotek_Actions {
|
|
680 |
* @since 0.2
|
681 |
*/
|
682 |
protected function _add_bulk_actions( $bulk_actions ) {
|
683 |
-
foreach ( self::$actions as $action => $
|
684 |
-
if ( strpos( $action, '-translation' ) ) {
|
685 |
continue;
|
686 |
}
|
687 |
// phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain
|
688 |
-
$bulk_actions[ 'bulk-lingotek-' . $action ] = __( $
|
689 |
if ( null !== filter_input( INPUT_GET, 'bulk-lingotek-' . $action ) ) {
|
690 |
-
$text = $
|
|
|
|
|
|
|
|
|
|
|
691 |
}
|
692 |
}
|
693 |
if ( ! empty( $text ) ) {
|
@@ -718,13 +732,16 @@ abstract class Lingotek_Actions {
|
|
718 |
'warning' => null === filter_input( INPUT_GET, 'lingotek_warning' ) ? ( null === filter_input( INPUT_GET, 'lingotek_remove' ) ? '' : __( "You are about to $action_message existing translations from your Lingotek community. Are you sure?", 'lingotek-translation' ) ) : __( 'You are about to overwrite existing translations. Are you sure?', 'lingotek-translation' ),
|
719 |
'nonce' => wp_create_nonce( 'lingotek_progress' ),
|
720 |
);
|
|
|
|
|
|
|
721 |
if ( null !== filter_input( INPUT_GET, 'locales' ) ) {
|
722 |
$data['locales'] = explode( ',', filter_input( INPUT_GET, 'locales' ) );
|
723 |
}
|
724 |
wp_localize_script( 'lingotek_progress', 'lingotek_data', $data );
|
725 |
return;
|
726 |
-
}
|
727 |
-
}
|
728 |
}
|
729 |
|
730 |
/**
|
@@ -817,9 +834,8 @@ abstract class Lingotek_Actions {
|
|
817 |
case 'lingotek-cancel-translation':
|
818 |
check_admin_referer( 'lingotek-cancel-translation' );
|
819 |
$target_locale = filter_input( INPUT_GET, 'target_locale' );
|
820 |
-
$
|
821 |
-
$
|
822 |
-
$document->cancel_translation( $language, $target_id );
|
823 |
if ( null !== filter_input( INPUT_GET, 'lingotek_redirect' ) && filter_input( INPUT_GET, 'lingotek_redirect' ) === true ) {
|
824 |
$site_id = get_current_blog_id();
|
825 |
wp_safe_redirect( get_site_url( $site_id, '/wp-admin/edit.php?post_type=page' ) );
|
@@ -917,11 +933,27 @@ abstract class Lingotek_Actions {
|
|
917 |
$document->cancel();
|
918 |
// phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
|
919 |
} elseif ( $document && $document->source != $id && $language ) {
|
920 |
-
$document->cancel_translation( $
|
921 |
}
|
922 |
die();
|
923 |
}
|
924 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
925 |
/**
|
926 |
* Ajax call to get the price estimation of a given document.
|
927 |
*/
|
@@ -1001,4 +1033,184 @@ abstract class Lingotek_Actions {
|
|
1001 |
|
1002 |
return $api_error;
|
1003 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1004 |
}
|
90 |
'action' => __( 'Upload to Lingotek', 'lingotek-translation' ),
|
91 |
'progress' => __( 'Uploading...', 'lingotek-translation' ),
|
92 |
'description' => __( 'Upload this item to Lingotek TMS', 'lingotek-translation' ),
|
93 |
+
'per_locale' => false,
|
94 |
),
|
95 |
|
96 |
'request' => array(
|
97 |
'action' => __( 'Request translations', 'lingotek-translation' ),
|
98 |
'progress' => __( 'Requesting translations...', 'lingotek-translation' ),
|
99 |
'description' => __( 'Request translations of this item to Lingotek TMS', 'lingotek-translation' ),
|
100 |
+
'per_locale' => false,
|
101 |
),
|
102 |
|
103 |
'status' => array(
|
104 |
'action' => __( 'Update translations status', 'lingotek-translation' ),
|
105 |
'progress' => __( 'Updating translations status...', 'lingotek-translation' ),
|
106 |
'description' => __( 'Update translations status of this item in Lingotek TMS', 'lingotek-translation' ),
|
107 |
+
'per_locale' => false,
|
108 |
),
|
109 |
|
110 |
'download' => array(
|
111 |
'action' => __( 'Download translations', 'lingotek-translation' ),
|
112 |
'progress' => __( 'Downloading translations...', 'lingotek-translation' ),
|
113 |
'description' => __( 'Download translations of this item from Lingotek TMS', 'lingotek-translation' ),
|
114 |
+
'per_locale' => false,
|
115 |
),
|
116 |
|
117 |
'cancel' => array(
|
118 |
'action' => __( 'Cancel translations', 'lingotek-translation' ),
|
119 |
'progress' => __( 'Cancelling translations...', 'lingotek-translation' ),
|
120 |
'description' => __( 'Cancel the translations of this item from Lingotek TMS', 'lingotek-translation' ),
|
121 |
+
'per_locale' => false,
|
122 |
),
|
123 |
|
124 |
'delete' => array(
|
125 |
'action' => __( 'Delete translations', 'lingotek-translation' ),
|
126 |
'progress' => __( 'Deleting translations...', 'lingotek-translation' ),
|
127 |
'description' => __( 'Delete the translations of this item from Lingotek TMS', 'lingotek-translation' ),
|
128 |
+
'per_locale' => false,
|
129 |
),
|
130 |
|
131 |
'cancel-translation' => array(
|
132 |
'action' => __( 'Cancel translation', 'lingotek-translation' ),
|
133 |
'progress' => __( 'Cancelling translation', 'lingotek-translation' ),
|
134 |
'description' => __( 'Cancel this translation from Lingotek TMS', 'lingotek-translation' ),
|
135 |
+
'per_locale' => true,
|
136 |
),
|
137 |
|
138 |
'delete-translation' => array(
|
139 |
'action' => __( 'Delete translation', 'lingotek-translation' ),
|
140 |
'progress' => __( 'Deleting translation', 'lingotek-translation' ),
|
141 |
'description' => __( 'Delete this translation from Lingotek TMS', 'lingotek-translation' ),
|
142 |
+
'per_locale' => false,
|
143 |
),
|
144 |
);
|
145 |
|
210 |
'title' => __( 'Translation has been cancelled', 'lingotek-translation' ),
|
211 |
'icon' => 'warning',
|
212 |
),
|
213 |
+
|
214 |
+
'deleted' => array(
|
215 |
+
'title' => __( 'Translation has been deleted', 'lingotek-translation' ),
|
216 |
+
'icon' => 'remove',
|
217 |
+
),
|
218 |
+
|
219 |
+
'archived' => array(
|
220 |
+
'title' => __( 'Document has been archived', 'lingotek-translation' ),
|
221 |
+
'icon' => 'remove',
|
222 |
+
),
|
223 |
);
|
224 |
|
225 |
$this->type = $type;
|
233 |
add_action( 'wp_ajax_get_user_payment_information', array( &$this, 'ajax_get_user_payment_information' ) );
|
234 |
add_action( 'wp_ajax_get_ltk_terms_and_conditions', array( &$this, 'ajax_get_ltk_terms_and_conditions' ) );
|
235 |
|
236 |
+
foreach ( self::$actions as $action => $action_data ) {
|
237 |
+
if ( strpos( $action, '-translation' ) && ! $action_data['per_locale'] ) {
|
238 |
continue;
|
239 |
}
|
240 |
+
add_action( 'wp_ajax_lingotek_progress_' . $this->type . '_' . $action, array( &$this, 'ajax_' . str_replace( '-', '_', $action ) ) );
|
241 |
}
|
242 |
}
|
243 |
|
256 |
return Lingotek_API::PRODUCTION_URL . "/workbench/document/$document_id/locale/$locale";
|
257 |
}
|
258 |
|
259 |
+
/**
|
260 |
+
* Generates a request target link
|
261 |
+
*
|
262 |
+
* @since 1.4.14
|
263 |
+
*
|
264 |
+
* @param string $document_id
|
265 |
+
* @param string $wp_locale WordPress locale.
|
266 |
+
* @return string Workbench link.
|
267 |
+
*/
|
268 |
+
public static function request_target_link( $document_id, $wp_locale ) {
|
269 |
+
$link = wp_nonce_url(
|
270 |
+
add_query_arg(
|
271 |
+
array(
|
272 |
+
'document_id' => $document_id,
|
273 |
+
'locale' => $wp_locale,
|
274 |
+
'action' => 'lingotek-request',
|
275 |
+
'noheader' => true,
|
276 |
+
),
|
277 |
+
defined( 'DOING_AJAX' ) && DOING_AJAX ? wp_get_referer() : wp_get_referer()
|
278 |
+
),
|
279 |
+
'lingotek-request'
|
280 |
+
);
|
281 |
+
return $link;
|
282 |
+
}
|
283 |
+
|
284 |
/**
|
285 |
* Outputs an action icon
|
286 |
*
|
339 |
* @param bool $confirm
|
340 |
*/
|
341 |
public function upload_icon( $object_id, $confirm = false ) {
|
342 |
+
$link = $this->upload_url( $object_id );
|
343 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
344 |
return self::display_icon( 'upload', $link, $confirm ? self::$confirm_message : '' );
|
345 |
}
|
346 |
|
419 |
public static function translation_icon( $document, $language ) {
|
420 |
if ( isset( $document->translations[ $language->locale ] ) ) {
|
421 |
if ( 'ready' === $document->translations[ $language->locale ] ) {
|
422 |
+
$link = self::request_target_link( $document->document_id, $language->locale );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
423 |
self::link_to_settings_if_not_connected( $link );
|
424 |
return self::display_icon( $document->translations[ $language->locale ], $link );
|
425 |
} elseif ( 'not-current' === $document->translations[ $language->locale ] ) {
|
428 |
} elseif ( 'current' !== $document->translations[ $language->locale ] && $custom_icon = $document->get_custom_in_progress_icon( $language ) ) {
|
429 |
return $custom_icon;
|
430 |
} else {
|
431 |
+
$link = self::workbench_link( $document->document_id, $language->lingotek_locale );
|
432 |
+
$target_blank = ' target="_blank"';
|
433 |
+
if ( 'deleted' === $document->translations[ $language->locale ] ) {
|
434 |
+
$link = self::request_target_link( $document->document_id, $language->locale );
|
435 |
+
$target_blank = '';
|
436 |
+
}
|
437 |
self::link_to_settings_if_not_connected( $link );
|
438 |
+
return self::display_icon( $document->translations[ $language->locale ], $link, $target_blank );
|
439 |
}//end if
|
440 |
} else {
|
441 |
+
$link = self::request_target_link( $document->document_id, $language->locale );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
442 |
self::link_to_settings_if_not_connected( $link );
|
443 |
return self::display_icon( 'request', $link );
|
444 |
}//end if
|
450 |
* @since 1.4.3
|
451 |
*/
|
452 |
public function failed_import_icon( $name, $object_id ) {
|
453 |
+
$link = $this->upload_url( $object_id );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
454 |
return sprintf(
|
455 |
'<a class="%s dashicons dashicons-%s" title="%s" href="%s"></a>',
|
456 |
self::$icons[ $name ]['class'],
|
661 |
$actions['lingotek-cancel-translation'] = $this->get_action_link(
|
662 |
array(
|
663 |
'document_id' => $document->document_id,
|
664 |
+
'target_id' => $id,
|
665 |
'target_locale' => $target_locale,
|
666 |
'action' => 'cancel-translation',
|
667 |
),
|
689 |
* @since 0.2
|
690 |
*/
|
691 |
protected function _add_bulk_actions( $bulk_actions ) {
|
692 |
+
foreach ( self::$actions as $action => $action_data ) {
|
693 |
+
if ( strpos( $action, '-translation' ) && ! $action_data['per_locale'] ) {
|
694 |
continue;
|
695 |
}
|
696 |
// phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain
|
697 |
+
$bulk_actions[ 'bulk-lingotek-' . $action ] = __( $action_data['action'], $action );
|
698 |
if ( null !== filter_input( INPUT_GET, 'bulk-lingotek-' . $action ) ) {
|
699 |
+
$text = $action_data['progress'];
|
700 |
+
}
|
701 |
+
if ( isset( $action_data['per_locale'] ) && true === $action_data['per_locale'] ) {
|
702 |
+
foreach ( PLL()->model->get_languages_list() as $language ) {
|
703 |
+
$bulk_actions[ 'bulk-lingotek-' . $action . ':' . $language->locale ] = __( $action_data['action'] . ' for ' . $language->lingotek_locale, 'lingotek-translation' );
|
704 |
+
}
|
705 |
}
|
706 |
}
|
707 |
if ( ! empty( $text ) ) {
|
732 |
'warning' => null === filter_input( INPUT_GET, 'lingotek_warning' ) ? ( null === filter_input( INPUT_GET, 'lingotek_remove' ) ? '' : __( "You are about to $action_message existing translations from your Lingotek community. Are you sure?", 'lingotek-translation' ) ) : __( 'You are about to overwrite existing translations. Are you sure?', 'lingotek-translation' ),
|
733 |
'nonce' => wp_create_nonce( 'lingotek_progress' ),
|
734 |
);
|
735 |
+
if ( null !== filter_input( INPUT_GET, 'target_locale' ) ) {
|
736 |
+
$data['target_locale'] = filter_input( INPUT_GET, 'target_locale' );
|
737 |
+
}
|
738 |
if ( null !== filter_input( INPUT_GET, 'locales' ) ) {
|
739 |
$data['locales'] = explode( ',', filter_input( INPUT_GET, 'locales' ) );
|
740 |
}
|
741 |
wp_localize_script( 'lingotek_progress', 'lingotek_data', $data );
|
742 |
return;
|
743 |
+
}//end if
|
744 |
+
}//end foreach
|
745 |
}
|
746 |
|
747 |
/**
|
834 |
case 'lingotek-cancel-translation':
|
835 |
check_admin_referer( 'lingotek-cancel-translation' );
|
836 |
$target_locale = filter_input( INPUT_GET, 'target_locale' );
|
837 |
+
$document_id = filter_input( INPUT_GET, 'document_id' );
|
838 |
+
$document->cancel_translation( $document_id, $target_locale );
|
|
|
839 |
if ( null !== filter_input( INPUT_GET, 'lingotek_redirect' ) && filter_input( INPUT_GET, 'lingotek_redirect' ) === true ) {
|
840 |
$site_id = get_current_blog_id();
|
841 |
wp_safe_redirect( get_site_url( $site_id, '/wp-admin/edit.php?post_type=page' ) );
|
933 |
$document->cancel();
|
934 |
// phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
|
935 |
} elseif ( $document && $document->source != $id && $language ) {
|
936 |
+
$document->cancel_translation( $document->document_id, $language->lingotek_locale );
|
937 |
}
|
938 |
die();
|
939 |
}
|
940 |
|
941 |
+
/**
|
942 |
+
* Ajax response cancel only one target and showing progress
|
943 |
+
*
|
944 |
+
* @since 1.5.0
|
945 |
+
*/
|
946 |
+
public function ajax_cancel_translation() {
|
947 |
+
check_ajax_referer( 'lingotek_progress', '_lingotek_nonce' );
|
948 |
+
$id = filter_input( INPUT_POST, 'id' );
|
949 |
+
$target_locale = filter_input( INPUT_POST, 'target_locale' );
|
950 |
+
$document = $this->lgtm->get_group( $this->type, $id );
|
951 |
+
// phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
|
952 |
+
if ( $document && $target_locale ) {
|
953 |
+
$document->cancel_translation( $document->document_id, $target_locale );
|
954 |
+
}
|
955 |
+
die();
|
956 |
+
}
|
957 |
/**
|
958 |
* Ajax call to get the price estimation of a given document.
|
959 |
*/
|
1033 |
|
1034 |
return $api_error;
|
1035 |
}
|
1036 |
+
|
1037 |
+
/**
|
1038 |
+
* Gets the upload url.
|
1039 |
+
*
|
1040 |
+
* @param int $object_id
|
1041 |
+
* @param string|null $locale
|
1042 |
+
*
|
1043 |
+
* @return string
|
1044 |
+
*
|
1045 |
+
* @since 1.5.0
|
1046 |
+
*/
|
1047 |
+
public function upload_url( $object_id, $locale = null ) {
|
1048 |
+
$args = array(
|
1049 |
+
$this->type => $object_id,
|
1050 |
+
'action' => 'lingotek-upload',
|
1051 |
+
'noheader' => true,
|
1052 |
+
);
|
1053 |
+
if ( null !== $locale ) {
|
1054 |
+
$args['locale'] = $locale;
|
1055 |
+
}
|
1056 |
+
if ( isset( $args['string'] ) ) {
|
1057 |
+
$args['string'] = rawurlencode( $args['string'] );
|
1058 |
+
}
|
1059 |
+
$link = wp_nonce_url( defined( 'DOING_AJAX' ) && DOING_AJAX ? add_query_arg( $args, wp_get_referer() ) : add_query_arg( $args ), 'lingotek-upload' );
|
1060 |
+
self::link_to_settings_if_not_connected( $link );
|
1061 |
+
|
1062 |
+
return $link;
|
1063 |
+
}
|
1064 |
+
|
1065 |
+
/**
|
1066 |
+
* Gets the request translation url.
|
1067 |
+
*
|
1068 |
+
* @param int $object_id
|
1069 |
+
* @param object $document
|
1070 |
+
* @param string $ltk_locale
|
1071 |
+
*
|
1072 |
+
* @return string
|
1073 |
+
*
|
1074 |
+
* @since 1.5.0
|
1075 |
+
*/
|
1076 |
+
public function request_translation_url( $object_id, $document, $ltk_locale ) {
|
1077 |
+
$link = wp_nonce_url(
|
1078 |
+
add_query_arg(
|
1079 |
+
array(
|
1080 |
+
'document_id' => $document->document_id,
|
1081 |
+
'locale' => $ltk_locale,
|
1082 |
+
'action' => 'lingotek-request',
|
1083 |
+
'noheader' => true,
|
1084 |
+
),
|
1085 |
+
defined( 'DOING_AJAX' ) && DOING_AJAX ? wp_get_referer() : wp_get_referer()
|
1086 |
+
),
|
1087 |
+
'lingotek-request'
|
1088 |
+
);
|
1089 |
+
return $link;
|
1090 |
+
}
|
1091 |
+
|
1092 |
+
/**
|
1093 |
+
* Gets the check source status url.
|
1094 |
+
*
|
1095 |
+
* @param int $object_id
|
1096 |
+
* @param object $document
|
1097 |
+
* @param string $ltk_locale
|
1098 |
+
*
|
1099 |
+
* @return string
|
1100 |
+
*
|
1101 |
+
* @since 1.5.0
|
1102 |
+
*/
|
1103 |
+
public function check_source_url( $object_id, $document, $ltk_locale ) {
|
1104 |
+
$link = wp_nonce_url(
|
1105 |
+
add_query_arg(
|
1106 |
+
array(
|
1107 |
+
'document_id' => $document->document_id,
|
1108 |
+
'action' => 'lingotek-status',
|
1109 |
+
'noheader' => true,
|
1110 |
+
),
|
1111 |
+
defined( 'DOING_AJAX' ) && DOING_AJAX ? wp_get_referer() : wp_get_referer()
|
1112 |
+
),
|
1113 |
+
'lingotek-status'
|
1114 |
+
);
|
1115 |
+
return $link;
|
1116 |
+
}
|
1117 |
+
|
1118 |
+
/**
|
1119 |
+
* Gets the check translation status url.
|
1120 |
+
*
|
1121 |
+
* @param int $object_id
|
1122 |
+
* @param object $document
|
1123 |
+
* @param string $ltk_locale
|
1124 |
+
*
|
1125 |
+
* @return string
|
1126 |
+
*
|
1127 |
+
* @since 1.5.0
|
1128 |
+
*/
|
1129 |
+
public function check_translation_url( $object_id, $document, $ltk_locale ) {
|
1130 |
+
$link = wp_nonce_url(
|
1131 |
+
add_query_arg(
|
1132 |
+
array(
|
1133 |
+
'document_id' => $document->document_id,
|
1134 |
+
'action' => 'lingotek-status',
|
1135 |
+
'noheader' => true,
|
1136 |
+
),
|
1137 |
+
defined( 'DOING_AJAX' ) && DOING_AJAX ? wp_get_referer() : wp_get_referer()
|
1138 |
+
),
|
1139 |
+
'lingotek-status'
|
1140 |
+
);
|
1141 |
+
return $link;
|
1142 |
+
}
|
1143 |
+
|
1144 |
+
/**
|
1145 |
+
* Gets the cancel translation target url.
|
1146 |
+
*
|
1147 |
+
* @param int $object_id
|
1148 |
+
* @param object $document
|
1149 |
+
* @param string $ltk_locale
|
1150 |
+
*
|
1151 |
+
* @return string
|
1152 |
+
*
|
1153 |
+
* @since 1.5.0
|
1154 |
+
*/
|
1155 |
+
public function cancel_translation_url( $object_id, $document, $ltk_locale ) {
|
1156 |
+
$link = wp_nonce_url(
|
1157 |
+
add_query_arg(
|
1158 |
+
array(
|
1159 |
+
'document_id' => $document->document_id,
|
1160 |
+
'id' => $object_id,
|
1161 |
+
'target_locale' => $ltk_locale,
|
1162 |
+
'action' => 'lingotek-cancel-translation',
|
1163 |
+
'noheader' => true,
|
1164 |
+
),
|
1165 |
+
defined( 'DOING_AJAX' ) && DOING_AJAX ? wp_get_referer() : wp_get_referer()
|
1166 |
+
),
|
1167 |
+
'lingotek-cancel-translation'
|
1168 |
+
);
|
1169 |
+
|
1170 |
+
return $link;
|
1171 |
+
}
|
1172 |
+
|
1173 |
+
/**
|
1174 |
+
* Gets the download translation url.
|
1175 |
+
*
|
1176 |
+
* @param int $object_id
|
1177 |
+
* @param object $document
|
1178 |
+
* @param string $ltk_locale
|
1179 |
+
*
|
1180 |
+
* @return string
|
1181 |
+
*
|
1182 |
+
* @since 1.5.0
|
1183 |
+
*/
|
1184 |
+
public function download_translation_url( $object_id, $document, $ltk_locale ) {
|
1185 |
+
$link = wp_nonce_url(
|
1186 |
+
add_query_arg(
|
1187 |
+
array(
|
1188 |
+
'document_id' => $document->document_id,
|
1189 |
+
'locale' => $ltk_locale,
|
1190 |
+
'action' => 'lingotek-download',
|
1191 |
+
'noheader' => true,
|
1192 |
+
),
|
1193 |
+
defined( 'DOING_AJAX' ) && DOING_AJAX ? wp_get_referer() : wp_get_referer()
|
1194 |
+
),
|
1195 |
+
'lingotek-download'
|
1196 |
+
);
|
1197 |
+
return $link;
|
1198 |
+
}
|
1199 |
+
|
1200 |
+
/**
|
1201 |
+
* Gets the workbench access url.
|
1202 |
+
*
|
1203 |
+
* @param int $object_id
|
1204 |
+
* @param object $document
|
1205 |
+
* @param string $ltk_locale
|
1206 |
+
*
|
1207 |
+
* @return string
|
1208 |
+
*
|
1209 |
+
* @since 1.5.0
|
1210 |
+
*/
|
1211 |
+
public function workbench_url( $object_id, $document, $ltk_locale ) {
|
1212 |
+
$link = self::workbench_link( $document->document_id, $ltk_locale );
|
1213 |
+
self::link_to_settings_if_not_connected( $link );
|
1214 |
+
return $link;
|
1215 |
+
}
|
1216 |
}
|
admin/admin.php
CHANGED
@@ -91,10 +91,10 @@ class Lingotek_Admin {
|
|
91 |
if ( $document->source !== (int) $object_id ) {
|
92 |
$document = $lgtm->get_group( $type, $document->source );
|
93 |
}
|
94 |
-
|
95 |
-
|
96 |
: pll_get_post_language( $document->source, 'locale' );
|
97 |
-
|
98 |
|
99 |
if ( count( $existing_translations ) > 1 ) {
|
100 |
$content_metadata[ $id ]['existing_trans'] = true;
|
@@ -107,9 +107,12 @@ class Lingotek_Admin {
|
|
107 |
$content_metadata[ $id ][ $source_language ]['status'] = $document->source === $object_id ? $document->status : $target_status;
|
108 |
if ( is_array( $document->translations ) ) {
|
109 |
foreach ( $document->translations as $locale => $translation_status ) {
|
110 |
-
$content_metadata[ $id ][ $locale ]['status']
|
111 |
-
|
112 |
-
|
|
|
|
|
|
|
113 |
}
|
114 |
}
|
115 |
|
91 |
if ( $document->source !== (int) $object_id ) {
|
92 |
$document = $lgtm->get_group( $type, $document->source );
|
93 |
}
|
94 |
+
$source_id = null !== $document->source ? $document->source : $object_id;
|
95 |
+
$source_language = $terms ? pll_get_term_language( $document->source, 'locale' )
|
96 |
: pll_get_post_language( $document->source, 'locale' );
|
97 |
+
$existing_translations = ( 'term' === $type ) ? PLL()->model->term->get_translations( $source_id ) : PLL()->model->post->get_translations( $source_id );
|
98 |
|
99 |
if ( count( $existing_translations ) > 1 ) {
|
100 |
$content_metadata[ $id ]['existing_trans'] = true;
|
107 |
$content_metadata[ $id ][ $source_language ]['status'] = $document->source === $object_id ? $document->status : $target_status;
|
108 |
if ( is_array( $document->translations ) ) {
|
109 |
foreach ( $document->translations as $locale => $translation_status ) {
|
110 |
+
$content_metadata[ $id ][ $locale ]['status'] = $translation_status;
|
111 |
+
// If the target was marked as deleted, there's no workbench link.
|
112 |
+
if ( 'deleted' !== $translation_status ) {
|
113 |
+
$workbench_link = Lingotek_Actions::workbench_link( $document->document_id, $locale );
|
114 |
+
$content_metadata[ $id ][ $locale ]['workbench_link'] = $workbench_link;
|
115 |
+
}
|
116 |
}
|
117 |
}
|
118 |
|
admin/chip-base.php
ADDED
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Chip base class for representing a locale (source or target).
|
5 |
+
*
|
6 |
+
* @since 1.5.0
|
7 |
+
*/
|
8 |
+
abstract class Lingotek_Chip_Base {
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Id of the document.
|
12 |
+
*
|
13 |
+
* @var int
|
14 |
+
*/
|
15 |
+
protected $id;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* The document.
|
19 |
+
*
|
20 |
+
* @var object
|
21 |
+
*/
|
22 |
+
protected $document;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Construct the chip.
|
26 |
+
*
|
27 |
+
* @param int $id Id of the document.
|
28 |
+
* @param object $document The document.
|
29 |
+
*/
|
30 |
+
public function __construct( $id, $document ) {
|
31 |
+
$this->id = $id;
|
32 |
+
$this->document = $document;
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Get the url for an action
|
37 |
+
*
|
38 |
+
* @param object $language
|
39 |
+
* @param string $status
|
40 |
+
*
|
41 |
+
* @return Lingotek_Action_Url|null
|
42 |
+
*
|
43 |
+
* @since 1.5.0
|
44 |
+
*/
|
45 |
+
abstract public function get_action_url( $language, $status );
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Get the secondary urls for an action menu.
|
49 |
+
*
|
50 |
+
* @param object $language
|
51 |
+
* @param string $status
|
52 |
+
*
|
53 |
+
* @return Lingotek_Action_Url[]
|
54 |
+
*
|
55 |
+
* @since 1.5.0
|
56 |
+
*/
|
57 |
+
abstract public function get_secondary_action_urls( $language, $status );
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Renders a chip with their primary action and a secondary actions menu.
|
61 |
+
*
|
62 |
+
* @param object $language
|
63 |
+
* @param string $status
|
64 |
+
*
|
65 |
+
* @return string
|
66 |
+
*
|
67 |
+
* @since 1.5.0
|
68 |
+
*/
|
69 |
+
public function render( $language, $status ) {
|
70 |
+
$primary_action_url = $this->get_action_url( $language, $status );
|
71 |
+
$secondary_action_urls = $this->get_secondary_action_urls( $language, $status );
|
72 |
+
|
73 |
+
$output_html = sprintf(
|
74 |
+
'<div class="lingotek-%s-dropdown">' .
|
75 |
+
'<a href="%s" class="language-icon %s-%s" title="%s">%s</a>',
|
76 |
+
$this->type,
|
77 |
+
null !== $primary_action_url ? $primary_action_url->getUri() : '#',
|
78 |
+
$this->type,
|
79 |
+
$status,
|
80 |
+
null !== $primary_action_url ? $primary_action_url->getTitle() : '',
|
81 |
+
$language->lingotek_locale
|
82 |
+
);
|
83 |
+
|
84 |
+
$secondary_actions_code = '';
|
85 |
+
foreach ( $secondary_action_urls as $source_secondary_action ) {
|
86 |
+
$secondary_actions_code .= $source_secondary_action->render();
|
87 |
+
}
|
88 |
+
|
89 |
+
if ( count( $secondary_action_urls ) > 0 ) {
|
90 |
+
$output_html .= sprintf(
|
91 |
+
'
|
92 |
+
<button class="language-icon lingotek-%s-dropdown-toggle %s-%s"><span class="visually-hidden">Toggle Actions</span></button>
|
93 |
+
<ul class="lingotek-%s-actions">
|
94 |
+
%s
|
95 |
+
</ul>',
|
96 |
+
$this->type,
|
97 |
+
$this->type,
|
98 |
+
$status,
|
99 |
+
$this->type,
|
100 |
+
$secondary_actions_code
|
101 |
+
);
|
102 |
+
}
|
103 |
+
|
104 |
+
$output_html .= '</div>';
|
105 |
+
|
106 |
+
return $output_html;
|
107 |
+
}
|
108 |
+
|
109 |
+
public function get_canonical_url( $language ) {
|
110 |
+
if ( is_object( $this->document ) ) {
|
111 |
+
if ( post_type_exists( $this->document->type ) ) {
|
112 |
+
$id = PLL()->model->post->get( $this->document->source, $language->locale );
|
113 |
+
if ( $id ) {
|
114 |
+
return get_permalink( $id );
|
115 |
+
}
|
116 |
+
} elseif ( taxonomy_exists( $this->document->type ) ) {
|
117 |
+
$id = $this->document->pllm->get_term( $this->document->source, $language->locale );
|
118 |
+
if ( $id ) {
|
119 |
+
return get_term_link( $id, $this->document->type );
|
120 |
+
}
|
121 |
+
}
|
122 |
+
}
|
123 |
+
return false;
|
124 |
+
}
|
125 |
+
|
126 |
+
}
|
admin/chip-source.php
ADDED
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Chip class for representing a source locale and its actions.
|
5 |
+
*
|
6 |
+
* @since 1.5.0
|
7 |
+
*/
|
8 |
+
class Lingotek_Chip_Source extends Lingotek_Chip_Base {
|
9 |
+
|
10 |
+
/**
|
11 |
+
* The type of the chip.
|
12 |
+
*
|
13 |
+
* @var string
|
14 |
+
*/
|
15 |
+
protected $type = 'source';
|
16 |
+
|
17 |
+
/**
|
18 |
+
* {@inheritdoc}
|
19 |
+
*/
|
20 |
+
public function get_action_url( $language, $status ) {
|
21 |
+
$url = null;
|
22 |
+
$uri = null;
|
23 |
+
$title = null;
|
24 |
+
$post_actions = $GLOBALS['wp_lingotek']->post_actions;
|
25 |
+
$document_id = $this->document ? $this->document->document_id : false;
|
26 |
+
if ( $document_id ) {
|
27 |
+
if ( in_array( $status, array( 'request', 'deleted', 'untracked' ), true ) ) {
|
28 |
+
$uri = $post_actions->upload_url( $this->id );
|
29 |
+
$title = __( 'Upload', 'lingotek-translation' );
|
30 |
+
}
|
31 |
+
if ( 'deleted' === $status ) {
|
32 |
+
$uri = $post_actions->upload_url( $this->id );
|
33 |
+
$title = sprintf( __( 'This document has been deleted. Reupload the source for translation.', 'lingotek-translation' ) );
|
34 |
+
}
|
35 |
+
if ( 'archived' === $status ) {
|
36 |
+
$uri = $post_actions->upload_url( $this->id );
|
37 |
+
$title = sprintf( __( 'This document has been archived. Reupload the source for translation.', 'lingotek-translation' ) );
|
38 |
+
}
|
39 |
+
if ( 'importing' === $status ) {
|
40 |
+
$uri = $post_actions->check_source_url( $this->id, $this->document, $language->locale );
|
41 |
+
$title = __( 'Check source status', 'lingotek-translation' );
|
42 |
+
}
|
43 |
+
if ( in_array( $status, array( 'current', 'edited', 'failed', 'error' ), true ) ) {
|
44 |
+
$uri = $post_actions->upload_url( $this->id );
|
45 |
+
$title = __( 'Re-Upload', 'lingotek-translation' );
|
46 |
+
}
|
47 |
+
if ( 'disabled' === $status ) {
|
48 |
+
$url = null;
|
49 |
+
}
|
50 |
+
} else {
|
51 |
+
if ( 'deleted' === $status ) {
|
52 |
+
$uri = $post_actions->upload_url( $this->id );
|
53 |
+
$title = sprintf( __( 'This document has been deleted. Reupload the source for translation.', 'lingotek-translation' ) );
|
54 |
+
} elseif ( 'archived' === $status ) {
|
55 |
+
$uri = $post_actions->upload_url( $this->id );
|
56 |
+
$title = sprintf( __( 'This document has been archived. Reupload the source for translation.', 'lingotek-translation' ) );
|
57 |
+
} else {
|
58 |
+
$uri = $post_actions->upload_url( $this->id );
|
59 |
+
$title = __( 'Upload', 'lingotek-translation' );
|
60 |
+
}
|
61 |
+
}//end if
|
62 |
+
if ( null !== $uri && null !== $title ) {
|
63 |
+
$url = new Lingotek_Action_Url( $uri, $title );
|
64 |
+
}
|
65 |
+
return $url;
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* {@inheritdoc}
|
70 |
+
*/
|
71 |
+
public function get_secondary_action_urls( $language, $status ) {
|
72 |
+
$urls = array();
|
73 |
+
$post_actions = $GLOBALS['wp_lingotek']->post_actions;
|
74 |
+
$document_id = $this->document ? $this->document->document_id : false;
|
75 |
+
|
76 |
+
$canonical_url = $this->get_canonical_url( $language );
|
77 |
+
if ( $canonical_url ) {
|
78 |
+
$urls[] = new Lingotek_Action_Url(
|
79 |
+
$canonical_url,
|
80 |
+
'source' === $this->type ? __( 'View', 'lingotek-translation' ) : __( 'View translation', 'lingotek-translation' )
|
81 |
+
);
|
82 |
+
}
|
83 |
+
|
84 |
+
if ( $document_id ) {
|
85 |
+
if ( in_array( $status, array( 'request', 'deleted', 'untracked', 'archived', 'cancelled' ), true ) ) {
|
86 |
+
$urls[] = new Lingotek_Action_Url(
|
87 |
+
$post_actions->upload_url( $this->id ),
|
88 |
+
__( 'Upload', 'lingotek-translation' )
|
89 |
+
);
|
90 |
+
}
|
91 |
+
if ( 'importing' === $status ) {
|
92 |
+
$urls[] = new Lingotek_Action_Url(
|
93 |
+
$post_actions->check_source_url( $this->id, $this->document, $language->locale ),
|
94 |
+
__( 'Check source status', 'lingotek-translation' )
|
95 |
+
);
|
96 |
+
}
|
97 |
+
if ( in_array( $status, array( 'current', 'edited', 'failed', 'error' ), true ) ) {
|
98 |
+
$urls[] = new Lingotek_Action_Url(
|
99 |
+
$post_actions->upload_url( $this->id ),
|
100 |
+
__( 'Re-Upload', 'lingotek-translation' )
|
101 |
+
);
|
102 |
+
}
|
103 |
+
if ( 'disabled' === $status ) {
|
104 |
+
$url = null;
|
105 |
+
}
|
106 |
+
} else {
|
107 |
+
$urls[] = new Lingotek_Action_Url(
|
108 |
+
$post_actions->upload_url( $this->id ),
|
109 |
+
__( 'Upload', 'lingotek-translation' )
|
110 |
+
);
|
111 |
+
}//end if
|
112 |
+
return $urls;
|
113 |
+
}
|
114 |
+
|
115 |
+
}
|
admin/chip-target.php
ADDED
@@ -0,0 +1,138 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Chip class for representing a target locale and its actions.
|
5 |
+
*
|
6 |
+
* @since 1.5.0
|
7 |
+
*/
|
8 |
+
class Lingotek_Chip_Target extends Lingotek_Chip_Base {
|
9 |
+
|
10 |
+
/**
|
11 |
+
* The type of the chip.
|
12 |
+
*
|
13 |
+
* @var string
|
14 |
+
*/
|
15 |
+
protected $type = 'target';
|
16 |
+
|
17 |
+
/**
|
18 |
+
* {@inheritdoc}
|
19 |
+
*/
|
20 |
+
public function get_action_url( $language, $status ) {
|
21 |
+
$url = null;
|
22 |
+
$uri = null;
|
23 |
+
$title = null;
|
24 |
+
$post_actions = $GLOBALS['wp_lingotek']->post_actions;
|
25 |
+
$document_id = $this->document->document_id;
|
26 |
+
if ( $document_id ) {
|
27 |
+
if ( in_array( $status, array( 'request', 'untracked' ), true ) ) {
|
28 |
+
$uri = $post_actions->request_translation_url( $this->id, $this->document, $language->locale );
|
29 |
+
/* translators: %s: The lingotek locale. */
|
30 |
+
$title = sprintf( __( 'Request translation to %s', 'lingotek-translation' ), $language->lingotek_locale );
|
31 |
+
}
|
32 |
+
if ( 'deleted' === $status ) {
|
33 |
+
$uri = $post_actions->request_translation_url( $this->id, $this->document, $language->locale );
|
34 |
+
$canonical_url = $this->get_canonical_url( $language );
|
35 |
+
if ( $canonical_url ) {
|
36 |
+
$title = sprintf( __( 'This target has been deleted and the translation does exist.', 'lingotek-translation' ) );
|
37 |
+
} else {
|
38 |
+
$title = sprintf( __( 'This target has been deleted and the translation does not exist.', 'lingotek-translation' ) );
|
39 |
+
}
|
40 |
+
}
|
41 |
+
if ( 'archived' === $status ) {
|
42 |
+
$uri = $post_actions->request_translation_url( $this->id, $this->document, $language->locale );
|
43 |
+
$canonical_url = $this->get_canonical_url( $language );
|
44 |
+
if ( $canonical_url ) {
|
45 |
+
$title = sprintf( __( 'This target has been archived and the translation does exist.', 'lingotek-translation' ) );
|
46 |
+
} else {
|
47 |
+
$title = sprintf( __( 'This target has been archived and the translation does not exist.', 'lingotek-translation' ) );
|
48 |
+
}
|
49 |
+
}
|
50 |
+
if ( 'pending' === $status ) {
|
51 |
+
$uri = $post_actions->check_translation_url( $this->id, $this->document, $language->locale );
|
52 |
+
/* translators: %s: The lingotek locale. */
|
53 |
+
$title = sprintf( __( 'Check translation status for %s', 'lingotek-translation' ), $language->lingotek_locale );
|
54 |
+
}
|
55 |
+
if ( in_array( $status, array( 'ready', 'error', 'failed' ), true ) ) {
|
56 |
+
$uri = $post_actions->download_translation_url( $this->id, $this->document, $language->locale );
|
57 |
+
/* translators: %s: The lingotek locale. */
|
58 |
+
$title = sprintf( __( 'Download translation for %s', 'lingotek-translation' ), $language->lingotek_locale );
|
59 |
+
}
|
60 |
+
if ( in_array( $status, array( 'current', 'interim', 'intermediate', 'edited' ), true ) ) {
|
61 |
+
$uri = $post_actions->workbench_url( $this->id, $this->document, $language->lingotek_locale );
|
62 |
+
$title = __( 'Open in Lingotek workbench', 'lingotek-translation' );
|
63 |
+
}
|
64 |
+
if ( 'disabled' === $status ) {
|
65 |
+
$url = null;
|
66 |
+
}
|
67 |
+
}//end if
|
68 |
+
if ( null !== $uri && null !== $title ) {
|
69 |
+
$url = new Lingotek_Action_Url( $uri, $title );
|
70 |
+
}
|
71 |
+
return $url;
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* {@inheritdoc}
|
76 |
+
*/
|
77 |
+
public function get_secondary_action_urls( $language, $status ) {
|
78 |
+
$urls = array();
|
79 |
+
$post_actions = $GLOBALS['wp_lingotek']->post_actions;
|
80 |
+
$document_id = $this->document->document_id;
|
81 |
+
|
82 |
+
$canonical_url = $this->get_canonical_url( $language );
|
83 |
+
if ( $canonical_url ) {
|
84 |
+
$urls[] = new Lingotek_Action_Url(
|
85 |
+
$canonical_url,
|
86 |
+
'source' === $this->type ? __( 'View', 'lingotek-translation' ) : __( 'View translation', 'lingotek-translation' )
|
87 |
+
);
|
88 |
+
}
|
89 |
+
|
90 |
+
if ( $document_id ) {
|
91 |
+
if ( in_array( $status, array( 'request', 'deleted', 'untracked' ), true ) ) {
|
92 |
+
$urls[] = new Lingotek_Action_Url(
|
93 |
+
$post_actions->request_translation_url( $this->id, $this->document, $language->locale ),
|
94 |
+
sprintf( __( 'Request translation', 'lingotek-translation' ), $language->locale )
|
95 |
+
);
|
96 |
+
}
|
97 |
+
if ( 'pending' === $status ) {
|
98 |
+
$urls[] = new Lingotek_Action_Url(
|
99 |
+
$post_actions->check_translation_url( $this->id, $this->document, $language->locale ),
|
100 |
+
sprintf( __( 'Check translation status', 'lingotek-translation' ), $language->locale )
|
101 |
+
);
|
102 |
+
$urls[] = new Lingotek_Action_Url(
|
103 |
+
$post_actions->cancel_translation_url( $this->id, $this->document, $language->locale ),
|
104 |
+
sprintf( __( 'Cancel translation', 'lingotek-translation' ), $language->locale )
|
105 |
+
);
|
106 |
+
}
|
107 |
+
if ( in_array( $status, array( 'ready', 'error', 'failed' ), true ) ) {
|
108 |
+
$urls[] = new Lingotek_Action_Url(
|
109 |
+
$post_actions->download_translation_url( $this->id, $this->document, $language->locale ),
|
110 |
+
sprintf( __( 'Download translation', 'lingotek-translation' ), $language->locale )
|
111 |
+
);
|
112 |
+
$urls[] = new Lingotek_Action_Url(
|
113 |
+
$post_actions->cancel_translation_url( $this->id, $this->document, $language->locale ),
|
114 |
+
sprintf( __( 'Cancel translation', 'lingotek-translation' ), $language->locale )
|
115 |
+
);
|
116 |
+
}
|
117 |
+
// I'm not sure if the status is interim or intermediate, so we consider both for now.
|
118 |
+
if ( in_array( $status, array( 'current', 'interim', 'intermediate' ), true ) ) {
|
119 |
+
$urls[] = new Lingotek_Action_Url(
|
120 |
+
$post_actions->download_translation_url( $this->id, $this->document, $language->locale ),
|
121 |
+
sprintf( __( 'Re-Download translation', 'lingotek-translation' ), $language->locale )
|
122 |
+
);
|
123 |
+
}
|
124 |
+
// I'm not sure if the status is error or failed, so we consider both for now.
|
125 |
+
if ( in_array( $status, array( 'pending', 'ready', 'error', 'failed', 'current', 'interim', 'intermediate', 'edited' ), true ) ) {
|
126 |
+
$urls[] = new Lingotek_Action_Url(
|
127 |
+
$post_actions->workbench_url( $this->id, $this->document, $language->lingotek_locale ),
|
128 |
+
__( 'Open in Lingotek workbench', 'lingotek-translation' )
|
129 |
+
);
|
130 |
+
}
|
131 |
+
if ( 'disabled' === $status ) {
|
132 |
+
$url = null;
|
133 |
+
}
|
134 |
+
}//end if
|
135 |
+
return $urls;
|
136 |
+
}
|
137 |
+
|
138 |
+
}
|
admin/filters-columns.php
CHANGED
@@ -26,6 +26,22 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
|
|
26 |
// FIXME remove quick edit and bulk edit for now waiting for a solution to remove it only for uploaded documents.
|
27 |
remove_filter( 'quick_edit_custom_box', array( &$this, 'quick_edit_custom_box' ), 10, 2 );
|
28 |
remove_filter( 'bulk_edit_custom_box', array( &$this, 'quick_edit_custom_box' ), 10, 2 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
}
|
30 |
|
31 |
/**
|
@@ -47,6 +63,8 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
|
|
47 |
}
|
48 |
$this->print_patch_error();
|
49 |
$this->print_cancel_error();
|
|
|
|
|
50 |
foreach ( $this->model->get_languages_list() as $language ) {
|
51 |
$columns[ 'language_' . $language->locale ] = $language->flag ? $language->flag :
|
52 |
sprintf(
|
@@ -127,7 +145,7 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
|
|
127 |
$inline = defined( 'DOING_AJAX' ) && $get_action === $action && ! empty( $inline_lang_choice );
|
128 |
$lang = $inline ? $this->model->get_language( $inline_lang_choice ) : ( 'post' === $type ? PLL()->model->post->get_language( $object_id ) : PLL()->model->term->get_language( $object_id ) );
|
129 |
|
130 |
-
if ( false === strpos( $column, 'language_' ) || ! $lang ) {
|
131 |
if ( $custom_data ) {
|
132 |
return $custom_data;
|
133 |
} else {
|
@@ -136,6 +154,17 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
|
|
136 |
}
|
137 |
|
138 |
$language = $this->model->get_language( substr( $column, 9 ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
139 |
|
140 |
// FIXME should I suppress quick edit?.
|
141 |
// yes for uploaded posts, but I will need js as the field is built for all posts.
|
@@ -149,7 +178,6 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
|
|
149 |
( $language->slug === $lang->slug ? $object_id : 0 ) :
|
150 |
'post' === $type ) ? PLL()->model->post->get( $object_id, $language ) : PLL()->model->term->get( $object_id, $language );
|
151 |
|
152 |
-
$document = $this->lgtm->get_group( $type, $object_id );
|
153 |
if ( isset( $document->source ) ) {
|
154 |
$source_language = 'post' === $type ? PLL()->model->post->get_language( $document->source ) : PLL()->model->term->get_language( $document->source );
|
155 |
$source_profile = Lingotek_Model::get_profile( $this->content_type, $source_language, $document->source );
|
@@ -233,23 +261,39 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
|
|
233 |
* @param int $post_id post id.
|
234 |
*/
|
235 |
public function post_column( $column, $post_id ) {
|
236 |
-
if ( false === strpos( $column, 'language_' ) ) {
|
237 |
return;
|
238 |
}
|
239 |
$this->content_type = get_post_type( $post_id );
|
240 |
|
241 |
$allowed_html = array(
|
242 |
-
'a'
|
243 |
'href' => array(),
|
244 |
'class' => array(),
|
245 |
'title' => array(),
|
246 |
'target' => array(),
|
247 |
),
|
248 |
-
'div'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
249 |
'title' => array(),
|
250 |
'class' => array(),
|
251 |
),
|
252 |
-
'img'
|
253 |
'src' => array(),
|
254 |
),
|
255 |
);
|
@@ -305,6 +349,7 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
|
|
305 |
'class' => array(),
|
306 |
),
|
307 |
'span' => array(
|
|
|
308 |
'class' => array(),
|
309 |
),
|
310 |
'img' => array(
|
@@ -365,4 +410,85 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
|
|
365 |
}
|
366 |
}
|
367 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
368 |
}
|
26 |
// FIXME remove quick edit and bulk edit for now waiting for a solution to remove it only for uploaded documents.
|
27 |
remove_filter( 'quick_edit_custom_box', array( &$this, 'quick_edit_custom_box' ), 10, 2 );
|
28 |
remove_filter( 'bulk_edit_custom_box', array( &$this, 'quick_edit_custom_box' ), 10, 2 );
|
29 |
+
|
30 |
+
add_filter( 'default_hidden_columns', array( &$this, 'hide_pll_list_columns' ), 10, 2 );
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Hide by default the polylang based columns.
|
35 |
+
*
|
36 |
+
* @param array $hidden Hidden columns.
|
37 |
+
* @param \WP_Screen $screen Screen object.
|
38 |
+
* @since 1.15.0
|
39 |
+
*/
|
40 |
+
public function hide_pll_list_columns( $hidden, $screen ) {
|
41 |
+
foreach ( $this->model->get_languages_list() as $language ) {
|
42 |
+
$hidden[] = 'language_' . $language->locale;
|
43 |
+
}
|
44 |
+
return $hidden;
|
45 |
}
|
46 |
|
47 |
/**
|
63 |
}
|
64 |
$this->print_patch_error();
|
65 |
$this->print_cancel_error();
|
66 |
+
$columns ['lingotek_source'] = __( 'Lingotek source', 'lingotek-translation' );
|
67 |
+
$columns ['lingotek_targets'] = __( 'Lingotek translations', 'lingotek-translation' );
|
68 |
foreach ( $this->model->get_languages_list() as $language ) {
|
69 |
$columns[ 'language_' . $language->locale ] = $language->flag ? $language->flag :
|
70 |
sprintf(
|
145 |
$inline = defined( 'DOING_AJAX' ) && $get_action === $action && ! empty( $inline_lang_choice );
|
146 |
$lang = $inline ? $this->model->get_language( $inline_lang_choice ) : ( 'post' === $type ? PLL()->model->post->get_language( $object_id ) : PLL()->model->term->get_language( $object_id ) );
|
147 |
|
148 |
+
if ( ( false === strpos( $column, 'lingotek_' ) && false === strpos( $column, 'language_' ) ) || ! $lang ) {
|
149 |
if ( $custom_data ) {
|
150 |
return $custom_data;
|
151 |
} else {
|
154 |
}
|
155 |
|
156 |
$language = $this->model->get_language( substr( $column, 9 ) );
|
157 |
+
$document = $this->lgtm->get_group( $type, $object_id );
|
158 |
+
|
159 |
+
if ( 0 === strpos( $column, 'lingotek_' ) ) {
|
160 |
+
$source_language = PLL()->model->post->get_language( $object_id );
|
161 |
+
if ( 'lingotek_source' === $column ) {
|
162 |
+
return $this->render_source_status( $object_id, $source_language, $document, $document ? $document->status : 'untracked' );
|
163 |
+
}
|
164 |
+
if ( 'lingotek_targets' === $column ) {
|
165 |
+
return $this->render_target_statuses( $object_id, $source_language, $document );
|
166 |
+
}
|
167 |
+
}
|
168 |
|
169 |
// FIXME should I suppress quick edit?.
|
170 |
// yes for uploaded posts, but I will need js as the field is built for all posts.
|
178 |
( $language->slug === $lang->slug ? $object_id : 0 ) :
|
179 |
'post' === $type ) ? PLL()->model->post->get( $object_id, $language ) : PLL()->model->term->get( $object_id, $language );
|
180 |
|
|
|
181 |
if ( isset( $document->source ) ) {
|
182 |
$source_language = 'post' === $type ? PLL()->model->post->get_language( $document->source ) : PLL()->model->term->get_language( $document->source );
|
183 |
$source_profile = Lingotek_Model::get_profile( $this->content_type, $source_language, $document->source );
|
261 |
* @param int $post_id post id.
|
262 |
*/
|
263 |
public function post_column( $column, $post_id ) {
|
264 |
+
if ( false === strpos( $column, 'language_' ) && false === strpos( $column, 'lingotek_' ) ) {
|
265 |
return;
|
266 |
}
|
267 |
$this->content_type = get_post_type( $post_id );
|
268 |
|
269 |
$allowed_html = array(
|
270 |
+
'a' => array(
|
271 |
'href' => array(),
|
272 |
'class' => array(),
|
273 |
'title' => array(),
|
274 |
'target' => array(),
|
275 |
),
|
276 |
+
'div' => array(
|
277 |
+
'title' => array(),
|
278 |
+
'class' => array(),
|
279 |
+
),
|
280 |
+
'span' => array(
|
281 |
+
'title' => array(),
|
282 |
+
'class' => array(),
|
283 |
+
),
|
284 |
+
'button' => array(
|
285 |
+
'title' => array(),
|
286 |
+
'class' => array(),
|
287 |
+
),
|
288 |
+
'ul' => array(
|
289 |
+
'title' => array(),
|
290 |
+
'class' => array(),
|
291 |
+
),
|
292 |
+
'li' => array(
|
293 |
'title' => array(),
|
294 |
'class' => array(),
|
295 |
),
|
296 |
+
'img' => array(
|
297 |
'src' => array(),
|
298 |
),
|
299 |
);
|
349 |
'class' => array(),
|
350 |
),
|
351 |
'span' => array(
|
352 |
+
'title' => array(),
|
353 |
'class' => array(),
|
354 |
),
|
355 |
'img' => array(
|
410 |
}
|
411 |
}
|
412 |
}
|
413 |
+
|
414 |
+
/**
|
415 |
+
* Renders the source status.
|
416 |
+
*
|
417 |
+
* @param int $id
|
418 |
+
* @param object $source_language
|
419 |
+
* @param object $document
|
420 |
+
*
|
421 |
+
* @return string
|
422 |
+
*
|
423 |
+
* @since 1.5.0
|
424 |
+
*/
|
425 |
+
private function render_source_status( $id, $source_language, $document ) {
|
426 |
+
// If the source was uploaded, we want the group source document locale. If not, the document locale.
|
427 |
+
$source_language = is_object( $document ) && isset( $document->source ) ?
|
428 |
+
PLL()->model->post->get_language( $document->source ) :
|
429 |
+
$source_language;
|
430 |
+
$source_status = is_object( $document ) && $document->status ? $document->status : 'untracked';
|
431 |
+
|
432 |
+
$source_chip = new Lingotek_Chip_Source( $id, $document );
|
433 |
+
return $source_chip->render( $source_language, $source_status );
|
434 |
+
}
|
435 |
+
|
436 |
+
/**
|
437 |
+
* Render target statuses.
|
438 |
+
*
|
439 |
+
* @param int $id
|
440 |
+
* @param object $source_language
|
441 |
+
* @param object $document
|
442 |
+
*
|
443 |
+
* @return string
|
444 |
+
*
|
445 |
+
* @since 1.5.0
|
446 |
+
*/
|
447 |
+
private function render_target_statuses( $id, $source_language, $document ) {
|
448 |
+
$targets_markup = '';
|
449 |
+
$targets = isset( $document->translations ) ? array_keys( $document->translations ) : array();
|
450 |
+
$targets_data = array();
|
451 |
+
// If the source was uploaded, we want the group source document locale. If not, the document locale.
|
452 |
+
$wp_source_locale = is_object( $document ) && isset( $document->source ) ?
|
453 |
+
PLL()->model->post->get_language( $document->source )->locale :
|
454 |
+
$source_language->locale;
|
455 |
+
|
456 |
+
foreach ( $targets as $wp_locale ) {
|
457 |
+
$language = PLL()->model->get_language( $wp_locale );
|
458 |
+
// If we had a translation status but the language was removed/disabled, language is false.
|
459 |
+
if ( $language ) {
|
460 |
+
$status = $document->translations[ $wp_locale ];
|
461 |
+
$targets_data[ $wp_locale ] = array(
|
462 |
+
'id' => $id,
|
463 |
+
'source_language' => $source_language,
|
464 |
+
'document' => $document,
|
465 |
+
'status' => $status,
|
466 |
+
'language' => $language,
|
467 |
+
);
|
468 |
+
}
|
469 |
+
}
|
470 |
+
|
471 |
+
// We need to add the locales that were not requested, so they can be requested, but only when the source
|
472 |
+
// in a valid state for requesting those.
|
473 |
+
if ( is_object( $document ) && isset( $document->status ) && ! in_array( $document->status, array( 'cancelled', 'deleted', 'archived' ), true ) ) {
|
474 |
+
foreach ( PLL()->model->get_languages_list() as $pll_language ) {
|
475 |
+
$status = 'request';
|
476 |
+
if ( ! isset( $targets_data[ $pll_language->locale ] ) && $pll_language->locale !== $wp_source_locale ) {
|
477 |
+
$targets_data[ $pll_language->locale ] = array(
|
478 |
+
'id' => $id,
|
479 |
+
'source_language' => $source_language,
|
480 |
+
'document' => $document,
|
481 |
+
'status' => $status,
|
482 |
+
'language' => $pll_language,
|
483 |
+
);
|
484 |
+
}
|
485 |
+
}
|
486 |
+
}
|
487 |
+
foreach ( $targets_data as $locale => $locale_data ) {
|
488 |
+
$target_chip = new Lingotek_Chip_Target( $locale_data['id'], $locale_data['document'] );
|
489 |
+
$targets_markup .= $target_chip->render( $locale_data['language'], $locale_data['status'] );
|
490 |
+
}
|
491 |
+
return $targets_markup;
|
492 |
+
}
|
493 |
+
|
494 |
}
|
admin/post-actions.php
CHANGED
@@ -157,6 +157,8 @@ class Lingotek_Post_Actions extends Lingotek_Actions {
|
|
157 |
$redirect = admin_url( "edit.php?post_type=$typenow" );
|
158 |
}
|
159 |
|
|
|
|
|
160 |
switch ( $action ) {
|
161 |
case 'bulk-lingotek-upload':
|
162 |
$type = empty( $typenow ) ? 'media' : 'post';
|
@@ -198,6 +200,7 @@ class Lingotek_Post_Actions extends Lingotek_Actions {
|
|
198 |
case 'bulk-lingotek-status':
|
199 |
case 'bulk-lingotek-delete':
|
200 |
case 'bulk-lingotek-cancel':
|
|
|
201 |
if ( empty( $post_ids ) ) {
|
202 |
$type = empty( $typenow ) ? 'media' : 'post';
|
203 |
$filtered_get = filter_input_array( INPUT_GET );
|
@@ -209,11 +212,14 @@ class Lingotek_Post_Actions extends Lingotek_Actions {
|
|
209 |
}
|
210 |
|
211 |
empty( $typenow ) ? check_admin_referer( 'bulk-media' ) : check_admin_referer( 'bulk-posts' );
|
212 |
-
if ( in_array( $action, array( 'bulk-lingotek-cancel', 'bulk-lingotek-delete' ), true ) ) {
|
213 |
$redirect = add_query_arg( 'lingotek_remove', 1, $redirect );
|
214 |
}
|
215 |
$redirect = add_query_arg( $action, 1, $redirect );
|
216 |
$redirect = add_query_arg( 'ids', implode( ',', $post_ids ), $redirect );
|
|
|
|
|
|
|
217 |
break;
|
218 |
|
219 |
case 'lingotek-upload':
|
157 |
$redirect = admin_url( "edit.php?post_type=$typenow" );
|
158 |
}
|
159 |
|
160 |
+
list($action, $locale) = explode( ':', $action, 2 );
|
161 |
+
|
162 |
switch ( $action ) {
|
163 |
case 'bulk-lingotek-upload':
|
164 |
$type = empty( $typenow ) ? 'media' : 'post';
|
200 |
case 'bulk-lingotek-status':
|
201 |
case 'bulk-lingotek-delete':
|
202 |
case 'bulk-lingotek-cancel':
|
203 |
+
case 'bulk-lingotek-cancel-translation':
|
204 |
if ( empty( $post_ids ) ) {
|
205 |
$type = empty( $typenow ) ? 'media' : 'post';
|
206 |
$filtered_get = filter_input_array( INPUT_GET );
|
212 |
}
|
213 |
|
214 |
empty( $typenow ) ? check_admin_referer( 'bulk-media' ) : check_admin_referer( 'bulk-posts' );
|
215 |
+
if ( in_array( $action, array( 'bulk-lingotek-cancel', 'bulk-lingotek-delete' ), true ) && ! $locale ) {
|
216 |
$redirect = add_query_arg( 'lingotek_remove', 1, $redirect );
|
217 |
}
|
218 |
$redirect = add_query_arg( $action, 1, $redirect );
|
219 |
$redirect = add_query_arg( 'ids', implode( ',', $post_ids ), $redirect );
|
220 |
+
if ( $locale ) {
|
221 |
+
$redirect = add_query_arg( 'target_locale', $locale, $redirect );
|
222 |
+
}
|
223 |
break;
|
224 |
|
225 |
case 'lingotek-upload':
|
admin/tutorial/content.php
CHANGED
@@ -107,7 +107,17 @@
|
|
107 |
<th><?php _e( 'Translation Cancelled', 'lingotek-translation' ); ?></th>
|
108 |
<td><?php _e( 'The translation is cancelled. The source cannot be translated into this language again.', 'lingotek-translation' ); ?></td>
|
109 |
</tr>
|
110 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
<td><span class="lingotek-color dashicons dashicons-no"></span></td>
|
112 |
<th><?php _e( 'Out of Sync', 'lingotek-translation' ); ?></th>
|
113 |
<td><?php _e( 'You have made changes to source content. The source must be sent to Lingotek again for additional translation.', 'lingotek-translation' ); ?></td>
|
107 |
<th><?php _e( 'Translation Cancelled', 'lingotek-translation' ); ?></th>
|
108 |
<td><?php _e( 'The translation is cancelled. The source cannot be translated into this language again.', 'lingotek-translation' ); ?></td>
|
109 |
</tr>
|
110 |
+
<tr>
|
111 |
+
<td><span class="lingotek-color dashicons dashicons-remove"></span></td>
|
112 |
+
<th><?php _e( 'Document Archived', 'lingotek-translation' ); ?></th>
|
113 |
+
<td><?php _e( 'The document is archived. The document can be translated again.', 'lingotek-translation' ); ?></td>
|
114 |
+
</tr>
|
115 |
+
<tr>
|
116 |
+
<td><span class="lingotek-color dashicons dashicons-remove"></span></td>
|
117 |
+
<th><?php _e( 'Translation Deleted', 'lingotek-translation' ); ?></th>
|
118 |
+
<td><?php _e( 'The translation is deleted. The source can be translated into this language again.', 'lingotek-translation' ); ?></td>
|
119 |
+
</tr>
|
120 |
+
<tr>
|
121 |
<td><span class="lingotek-color dashicons dashicons-no"></span></td>
|
122 |
<th><?php _e( 'Out of Sync', 'lingotek-translation' ); ?></th>
|
123 |
<td><?php _e( 'You have made changes to source content. The source must be sent to Lingotek again for additional translation.', 'lingotek-translation' ); ?></td>
|
css/actions.css
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.lingotek-source-dropdown-toggle,
|
2 |
+
.lingotek-target-dropdown-toggle {
|
3 |
+
display: inline-block;
|
4 |
+
height: 30px;
|
5 |
+
width: 20px;
|
6 |
+
background: url("../img/icon-collapse.svg") no-repeat center;
|
7 |
+
transform: rotateZ(180deg);
|
8 |
+
background-size: 15px 15px;
|
9 |
+
padding: 0;
|
10 |
+
padding-left: 0;
|
11 |
+
margin-bottom: 2px;
|
12 |
+
float: right;
|
13 |
+
opacity: .8;
|
14 |
+
}
|
15 |
+
|
16 |
+
.lingotek-source-dropdown-toggle:focus,
|
17 |
+
.lingotek-target-dropdown-toggle:focus {
|
18 |
+
outline: none;
|
19 |
+
}
|
20 |
+
|
21 |
+
.lingotek-source-dropdown.open .lingotek-source-dropdown-toggle,
|
22 |
+
.lingotek-target-dropdown.open .lingotek-target-dropdown-toggle {
|
23 |
+
transform: rotateZ(0);
|
24 |
+
}
|
25 |
+
|
26 |
+
.lingotek-source-dropdown.open .lingotek-source-actions,
|
27 |
+
.lingotek-target-dropdown.open .lingotek-target-actions {
|
28 |
+
display: block;
|
29 |
+
}
|
30 |
+
|
31 |
+
.lingotek-source-dropdown,
|
32 |
+
.lingotek-target-dropdown {
|
33 |
+
position: relative;
|
34 |
+
display: inline-block;
|
35 |
+
margin-right: 8px;
|
36 |
+
}
|
37 |
+
|
38 |
+
.lingotek-source-actions,
|
39 |
+
.lingotek-target-actions {
|
40 |
+
display: none;
|
41 |
+
position: absolute;
|
42 |
+
list-style-type: none;
|
43 |
+
margin: 0;
|
44 |
+
padding: 0;
|
45 |
+
background-color: #f9f9f9;
|
46 |
+
min-width: 200px;
|
47 |
+
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
48 |
+
z-index: 1;
|
49 |
+
font-size: 90%;
|
50 |
+
}
|
51 |
+
|
52 |
+
.lingotek-source-actions a,
|
53 |
+
.lingotek-target-actions a {
|
54 |
+
color: black;
|
55 |
+
padding: 12px 16px;
|
56 |
+
text-decoration: none;
|
57 |
+
display: block;
|
58 |
+
font-size: 12px;
|
59 |
+
}
|
60 |
+
|
61 |
+
.lingotek-source-actions a:hover,
|
62 |
+
.lingotek-target-actions a:hover {
|
63 |
+
background-color: #f1f1f1
|
64 |
+
}
|
65 |
+
|
66 |
+
.visually-hidden {
|
67 |
+
position: absolute !important;
|
68 |
+
overflow: hidden;
|
69 |
+
clip: rect(1px, 1px, 1px, 1px);
|
70 |
+
width: 1px;
|
71 |
+
height: 1px;
|
72 |
+
word-wrap: normal;
|
73 |
+
}
|
css/statuses.css
ADDED
@@ -0,0 +1,255 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.language-icon {
|
2 |
+
background-color:#80a49e;
|
3 |
+
border-radius: 1px;
|
4 |
+
margin-right: 0px;
|
5 |
+
padding: 4px;
|
6 |
+
color: #fff;
|
7 |
+
white-space: nowrap;
|
8 |
+
border: 1px solid #fff;
|
9 |
+
border-spacing: 0;
|
10 |
+
width: 40px;
|
11 |
+
height: 20px;
|
12 |
+
}
|
13 |
+
|
14 |
+
.language-icon.source-failed,
|
15 |
+
.language-icon.source-error,
|
16 |
+
.language-icon.target-error {
|
17 |
+
background-color: #B71C1C;
|
18 |
+
border: 1px solid #B71C1C;
|
19 |
+
color: #FFFFFF;
|
20 |
+
}
|
21 |
+
|
22 |
+
.language-icon.source-failed a,
|
23 |
+
.language-icon.source-error a,
|
24 |
+
.language-icon.target-error a {
|
25 |
+
color: #FFFFFF;
|
26 |
+
}
|
27 |
+
|
28 |
+
span.language-icon ,
|
29 |
+
a.language-icon {
|
30 |
+
margin-bottom: 2px;
|
31 |
+
display: inline-block;
|
32 |
+
text-align: center;
|
33 |
+
}
|
34 |
+
|
35 |
+
/** Content statuses v2.0 */
|
36 |
+
.language-icon.source-untracked ,
|
37 |
+
.language-icon.source-request {
|
38 |
+
background-color: #ffffff;
|
39 |
+
border: 1px solid #999999;
|
40 |
+
color: #999999;
|
41 |
+
}
|
42 |
+
.language-icon.source-untracked a ,
|
43 |
+
.language-icon.source-request a {
|
44 |
+
color: #999999;
|
45 |
+
}
|
46 |
+
.language-icon.source-untracked:hover ,
|
47 |
+
.language-icon.source-request:hover {
|
48 |
+
color: #8c8c8c;
|
49 |
+
border: 1px solid #8c8c8c;
|
50 |
+
}
|
51 |
+
|
52 |
+
.language-icon.source-edited {
|
53 |
+
background-color:#ffc107;
|
54 |
+
border: 1px solid #575757;
|
55 |
+
color: #575757;
|
56 |
+
}
|
57 |
+
.language-icon.source-edited a {
|
58 |
+
color: #575757;
|
59 |
+
}
|
60 |
+
.language-icon.source-edited:hover {
|
61 |
+
background-color: #ffb300;
|
62 |
+
}
|
63 |
+
|
64 |
+
.language-icon.source-importing {
|
65 |
+
background-color:#f37f16;
|
66 |
+
border: 1px solid #f37f16;
|
67 |
+
color: #ffffff;
|
68 |
+
}
|
69 |
+
.language-icon.source-importing a {
|
70 |
+
color: #ffffff;
|
71 |
+
}
|
72 |
+
.language-icon.source-importing:hover {
|
73 |
+
background-color: #e67209;
|
74 |
+
}
|
75 |
+
|
76 |
+
.language-icon.source-current {
|
77 |
+
background-color:#5fdc64;
|
78 |
+
border: 1px solid #5fdc64;
|
79 |
+
color: #ffffff;
|
80 |
+
}
|
81 |
+
.language-icon.source-current a {
|
82 |
+
color: #ffffff;
|
83 |
+
}
|
84 |
+
.language-icon.source-current:hover {
|
85 |
+
background-color: #43a047;
|
86 |
+
}
|
87 |
+
|
88 |
+
.language-icon.target-request {
|
89 |
+
background-color:#ffffff;
|
90 |
+
border: 1px solid #f37f16;
|
91 |
+
color: #f37f16;
|
92 |
+
}
|
93 |
+
.language-icon.target-request a {
|
94 |
+
color: #f37f16;
|
95 |
+
}
|
96 |
+
.language-icon.target-request a:hover {
|
97 |
+
color: #e67209;
|
98 |
+
}
|
99 |
+
.language-icon.target-request:hover {
|
100 |
+
color: #e67209;
|
101 |
+
border: 1px solid #e67209;
|
102 |
+
}
|
103 |
+
|
104 |
+
.language-icon.target-pending {
|
105 |
+
background-color:#f37f16;
|
106 |
+
border: 1px solid #f37f16;
|
107 |
+
color: #ffffff;
|
108 |
+
}
|
109 |
+
.language-icon.target-pending a {
|
110 |
+
color: #ffffff;
|
111 |
+
}
|
112 |
+
.language-icon.target-pending:hover {
|
113 |
+
background-color: #e67209;
|
114 |
+
}
|
115 |
+
|
116 |
+
.language-icon.target-ready {
|
117 |
+
background-color:#2196f3;
|
118 |
+
border: 1px solid #2196f3;
|
119 |
+
color: #ffffff;
|
120 |
+
}
|
121 |
+
.language-icon.target-ready a {
|
122 |
+
color: #ffffff;
|
123 |
+
}
|
124 |
+
.language-icon.target-ready:hover {
|
125 |
+
background-color: #1e88e5;
|
126 |
+
}
|
127 |
+
|
128 |
+
.language-icon.target-edited {
|
129 |
+
background-color:#ffc107;
|
130 |
+
border: 1px solid #575757;
|
131 |
+
color: #575757;
|
132 |
+
}
|
133 |
+
.language-icon.target-edited a {
|
134 |
+
color: #575757;
|
135 |
+
}
|
136 |
+
.language-icon.target-edited:hover {
|
137 |
+
background-color: #ffb300;
|
138 |
+
}
|
139 |
+
|
140 |
+
.language-icon.target-current {
|
141 |
+
background-color:#5fdc64;
|
142 |
+
border: 1px solid #5fdc64;
|
143 |
+
color: #ffffff;
|
144 |
+
}
|
145 |
+
.language-icon.target-current a {
|
146 |
+
color: #ffffff;
|
147 |
+
}
|
148 |
+
.language-icon.target-current:hover {
|
149 |
+
background-color: #43a047;
|
150 |
+
}
|
151 |
+
|
152 |
+
.language-icon.target-interim,
|
153 |
+
.language-icon.target-intermediate {
|
154 |
+
background-color: #ffffff;
|
155 |
+
border: 1px solid #4caf50;
|
156 |
+
color: #4caf50;
|
157 |
+
}
|
158 |
+
|
159 |
+
.language-icon.target-interim a,
|
160 |
+
.language-icon.target-intermediate a {
|
161 |
+
color: #4caf50;
|
162 |
+
}
|
163 |
+
|
164 |
+
.language-icon.target-interim a:hover,
|
165 |
+
.language-icon.target-intermediate a:hover {
|
166 |
+
color: #43a047;
|
167 |
+
}
|
168 |
+
|
169 |
+
.language-icon.target-interim:hover,
|
170 |
+
.language-icon.target-intermediate:hover {
|
171 |
+
color: #43a047;
|
172 |
+
}
|
173 |
+
|
174 |
+
.language-icon.target-untracked {
|
175 |
+
background-color:#999999;
|
176 |
+
border: 1px solid #999999;
|
177 |
+
color: #ffffff;
|
178 |
+
}
|
179 |
+
.language-icon.target-untracked a {
|
180 |
+
color: #ffffff;
|
181 |
+
}
|
182 |
+
.language-icon.target-untracked:hover {
|
183 |
+
background-color: #8c8c8c;
|
184 |
+
}
|
185 |
+
|
186 |
+
.language-icon.source-cancelled,
|
187 |
+
.language-icon.target-cancelled {
|
188 |
+
background-color:#ffffff;
|
189 |
+
border: 1px solid #b71c1c;
|
190 |
+
color: #b71c1c;
|
191 |
+
}
|
192 |
+
.language-icon.source-cancelled a,
|
193 |
+
.language-icon.target-cancelled a {
|
194 |
+
color: #b71c1c;
|
195 |
+
}
|
196 |
+
|
197 |
+
.language-icon.source-cancelled:hover,
|
198 |
+
.language-icon.target-cancelled:hover {
|
199 |
+
background-color:#ffffff;
|
200 |
+
color: #9e0303;
|
201 |
+
border: 1px solid #9e0303;
|
202 |
+
}
|
203 |
+
|
204 |
+
.language-icon.source-disabled,
|
205 |
+
.language-icon.target-disabled {
|
206 |
+
background-color:#ffffff;
|
207 |
+
border: 1px solid #999999;
|
208 |
+
color: #999999;
|
209 |
+
text-decoration:line-through;
|
210 |
+
}
|
211 |
+
|
212 |
+
.language-icon.source-disabled a,
|
213 |
+
.language-icon.target-disabled a {
|
214 |
+
color: #999999;
|
215 |
+
}
|
216 |
+
|
217 |
+
.language-icon.source-none,
|
218 |
+
.language-icon.target-none {
|
219 |
+
background-color:#ffffff;
|
220 |
+
border: 1px solid #999999;
|
221 |
+
color: #999999;
|
222 |
+
}
|
223 |
+
|
224 |
+
.language-icon.source-none a,
|
225 |
+
.language-icon.target-none a {
|
226 |
+
color: #999999;
|
227 |
+
}
|
228 |
+
|
229 |
+
.language-icon.source-archived,
|
230 |
+
.language-icon.source-deleted,
|
231 |
+
.language-icon.target-archived,
|
232 |
+
.language-icon.target-deleted {
|
233 |
+
background-color: #ffffff;
|
234 |
+
border: 1px solid #404040;
|
235 |
+
color: #404040;
|
236 |
+
}
|
237 |
+
|
238 |
+
.language-icon.source-archived a,
|
239 |
+
.language-icon.source-deleted a,
|
240 |
+
.language-icon.target-archived a,
|
241 |
+
.language-icon.target-deleted a {
|
242 |
+
color: #404040;
|
243 |
+
}
|
244 |
+
|
245 |
+
.fixed .column-lingotek_source {
|
246 |
+
width: 10%;
|
247 |
+
}
|
248 |
+
|
249 |
+
.fixed .column-lingotek_translations {
|
250 |
+
width: 70%;
|
251 |
+
}
|
252 |
+
|
253 |
+
.fixed .column-profile {
|
254 |
+
width: 10%;
|
255 |
+
}
|
here
DELETED
File without changes
|
img/icon-collapse.svg
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
2 |
+
<path class="icon" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z" fill="#787878"/>
|
3 |
+
<path class="bg" d="M0 0h24v24H0z" fill="none"/>
|
4 |
+
</svg>
|
include/api.php
CHANGED
@@ -226,26 +226,30 @@ class Lingotek_API extends Lingotek_HTTP {
|
|
226 |
return $success;
|
227 |
}//end if
|
228 |
|
229 |
-
if ( $status_code == 410 ) {
|
|
|
230 |
Lingotek_Logger::info(
|
231 |
-
'Document ID was
|
232 |
array(
|
233 |
'old_document_id' => $id,
|
234 |
'wp_id' => $wp_id,
|
235 |
'args' => $args,
|
236 |
)
|
237 |
);
|
238 |
-
$targets
|
239 |
-
$
|
240 |
-
|
241 |
-
|
242 |
-
$document->translations[ $
|
|
|
243 |
}
|
|
|
|
|
244 |
$document->document_id = 'disassociated_' . $document->document_id;
|
245 |
unset( $document->desc_array['lingotek'] );
|
246 |
$document->save();
|
247 |
return $this->upload_document( $unformatted_args, $wp_id );
|
248 |
-
}
|
249 |
if ( $status_code == 402 ) {
|
250 |
Lingotek_Logger::error( 'There was an error updating WordPress item', array( 'error' => $this->get_error_message_from_response( $response ) ) );
|
251 |
$document->source_failed();
|
@@ -282,7 +286,7 @@ class Lingotek_API extends Lingotek_HTTP {
|
|
282 |
|
283 |
private function update_patch_error_message( $response, $status_code, $title ) {
|
284 |
// Do not inform user if call was successful.
|
285 |
-
if ( $status_code == 202 || $status_code == 410 ) {
|
286 |
return;
|
287 |
}
|
288 |
$lingotek_log_errors = get_option( 'lingotek_log_errors', array() );
|
@@ -716,19 +720,20 @@ class Lingotek_API extends Lingotek_HTTP {
|
|
716 |
*
|
717 |
* @since 0.1
|
718 |
*
|
719 |
-
* @param string
|
720 |
-
* @param string $locale Lingotek locale
|
721 |
-
* @param array $args optional arguments (only workflow_id at the moment)
|
722 |
-
* @
|
|
|
723 |
*/
|
724 |
-
public function request_translation(
|
725 |
-
$lgtm
|
726 |
-
$document
|
727 |
-
$
|
728 |
-
$args
|
729 |
-
$args
|
730 |
-
$response
|
731 |
-
$title
|
732 |
if ( $wp_id ) {
|
733 |
$arr = get_option( 'lingotek_log_errors', array() );
|
734 |
$status_code = wp_remote_retrieve_response_code( $response );
|
@@ -737,26 +742,37 @@ class Lingotek_API extends Lingotek_HTTP {
|
|
737 |
if ( 423 === $status_code ) {
|
738 |
$document->document_id = $body->next_document_id;
|
739 |
$document->save();
|
740 |
-
return $this->request_translation( $body->next_document_id, $
|
741 |
}
|
742 |
if ( 402 === $status_code ) {
|
743 |
Lingotek_Logger::error( 'There was an error updating WordPress item', array( 'error' => $this->get_error_message_from_response( $response ) ) );
|
744 |
$document->source_failed();
|
745 |
return false;
|
746 |
}
|
747 |
-
if ( 410 === $status_code ) {
|
748 |
// WP hooks automatically check source status so this might not get called
|
749 |
-
$
|
750 |
-
$
|
751 |
-
|
752 |
-
|
|
|
|
|
753 |
unset( $document->desc_array['lingotek'] );
|
754 |
$document->save();
|
755 |
-
|
756 |
-
|
|
|
|
|
|
|
757 |
}
|
758 |
-
|
759 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
760 |
if ( 400 === $status_code &&
|
761 |
! empty( $body->messages ) &&
|
762 |
strpos( $body->messages[0], 'already exists' ) ) {
|
@@ -766,17 +782,17 @@ class Lingotek_API extends Lingotek_HTTP {
|
|
766 |
if ( 201 === $status_code ) {
|
767 |
if ( isset( $arr[ $wp_id ] ) ) {
|
768 |
unset( $arr[ $wp_id ]['wp_error'] );
|
769 |
-
unset( $arr[ $wp_id ]['request_translation'][ $
|
770 |
if ( empty( $arr[ $wp_id ] ) ) {
|
771 |
unset( $arr[ $wp_id ] );
|
772 |
}
|
773 |
}
|
774 |
} elseif ( is_wp_error( $response ) ) {
|
775 |
$arr[ $wp_id ]['wp_error'] = __( 'Make sure you have internet connectivity', 'lingotek-translation' );
|
776 |
-
} elseif ( 400 == $status_code
|
777 |
-
$arr[ $wp_id ]['request_translation'][ $
|
778 |
__( 'There was an error requesting translation %1$s for WordPress item %2$s', 'lingotek-translation' ),
|
779 |
-
$
|
780 |
$wp_id
|
781 |
);
|
782 |
}
|
@@ -787,8 +803,8 @@ class Lingotek_API extends Lingotek_HTTP {
|
|
787 |
$response,
|
788 |
'RequestTranslation: Error Occurred',
|
789 |
array(
|
790 |
-
'document_id' => $
|
791 |
-
'locale' => $
|
792 |
'args' => $args,
|
793 |
)
|
794 |
);
|
@@ -862,18 +878,20 @@ class Lingotek_API extends Lingotek_HTTP {
|
|
862 |
* cancels a translation
|
863 |
*
|
864 |
* @since 1.4.2
|
|
|
865 |
*
|
866 |
-
* @param string $
|
867 |
* @param string $locale Lingotek locale
|
868 |
*/
|
869 |
-
public function cancel_translation( $
|
870 |
-
$args
|
871 |
array(
|
872 |
'cancelled_reason' => 'CANCELLED_BY_AUTHOR',
|
873 |
'mark_invoiceable' => true,
|
874 |
)
|
875 |
);
|
876 |
-
$
|
|
|
877 |
|
878 |
if ( $wp_id ) {
|
879 |
$arr = get_option( 'lingotek_log_errors' );
|
@@ -886,7 +904,7 @@ class Lingotek_API extends Lingotek_HTTP {
|
|
886 |
$response,
|
887 |
'CancelTranslation: Error occurred',
|
888 |
array(
|
889 |
-
'id' => $
|
890 |
'wordpress_id' => $wp_id,
|
891 |
)
|
892 |
);
|
@@ -895,7 +913,7 @@ class Lingotek_API extends Lingotek_HTTP {
|
|
895 |
Lingotek_Logger::info(
|
896 |
'Target cancelled',
|
897 |
array(
|
898 |
-
'document_id' => $
|
899 |
'wp_id' => $wp_id,
|
900 |
)
|
901 |
);
|
226 |
return $success;
|
227 |
}//end if
|
228 |
|
229 |
+
if ( $status_code == 410 || $status_code == 404 ) {
|
230 |
+
$document_status_string = $status_code == 410 ? 'archived' : 'not found';
|
231 |
Lingotek_Logger::info(
|
232 |
+
'Document ID was ' . $document_status_string . ', reuploading document',
|
233 |
array(
|
234 |
'old_document_id' => $id,
|
235 |
'wp_id' => $wp_id,
|
236 |
'args' => $args,
|
237 |
)
|
238 |
);
|
239 |
+
$targets = array_keys( $document->translations );
|
240 |
+
$lingotek_locales = array();
|
241 |
+
foreach ( $targets as $target ) {
|
242 |
+
// Targets stored in the document translations property are the polylang targets, so we need to get the lingotek locales instead
|
243 |
+
$document->translations[ $target ] = 'pending';
|
244 |
+
$lingotek_locales[] = Lingotek::map_to_lingotek_locale( $target );
|
245 |
}
|
246 |
+
$unformatted_args['translation_locale_code'] = $lingotek_locales;
|
247 |
+
$this->format_args_for_upload( $unformatted_args, $wp_id );
|
248 |
$document->document_id = 'disassociated_' . $document->document_id;
|
249 |
unset( $document->desc_array['lingotek'] );
|
250 |
$document->save();
|
251 |
return $this->upload_document( $unformatted_args, $wp_id );
|
252 |
+
}//end if
|
253 |
if ( $status_code == 402 ) {
|
254 |
Lingotek_Logger::error( 'There was an error updating WordPress item', array( 'error' => $this->get_error_message_from_response( $response ) ) );
|
255 |
$document->source_failed();
|
286 |
|
287 |
private function update_patch_error_message( $response, $status_code, $title ) {
|
288 |
// Do not inform user if call was successful.
|
289 |
+
if ( $status_code == 202 || $status_code == 410 || $status_code == 404 ) {
|
290 |
return;
|
291 |
}
|
292 |
$lingotek_log_errors = get_option( 'lingotek_log_errors', array() );
|
720 |
*
|
721 |
* @since 0.1
|
722 |
*
|
723 |
+
* @param string &$document_id document id.
|
724 |
+
* @param string $locale Lingotek locale.
|
725 |
+
* @param array $args optional arguments (only workflow_id at the moment).
|
726 |
+
* @param object $document the translation term for the post.
|
727 |
+
* @return bool true if the request succeeded.
|
728 |
*/
|
729 |
+
public function request_translation( &$document_id, $locale, $args = array(), $wp_id = null, $document = null ) {
|
730 |
+
$lgtm = $GLOBALS['wp_lingotek']->model;
|
731 |
+
$document = isset( $document ) ? $document : $lgtm->get_group_by_id( $document_id );
|
732 |
+
$lingotek_locale = Lingotek::map_to_lingotek_locale( $locale );
|
733 |
+
$args = $unformatted_args = wp_parse_args( $args, array( 'workflow_id' => $this->get_workflow_id() ) );
|
734 |
+
$args = array_merge( array( 'locale_code' => $lingotek_locale ), $args );
|
735 |
+
$response = $this->post( $this->api_url . '/document/' . $document_id . '/translation', $args );
|
736 |
+
$title = isset( $args['title'] ) ? $args['title'] : $document_id;
|
737 |
if ( $wp_id ) {
|
738 |
$arr = get_option( 'lingotek_log_errors', array() );
|
739 |
$status_code = wp_remote_retrieve_response_code( $response );
|
742 |
if ( 423 === $status_code ) {
|
743 |
$document->document_id = $body->next_document_id;
|
744 |
$document->save();
|
745 |
+
return $this->request_translation( $body->next_document_id, $lingotek_locale, $unformatted_args, $wp_id );
|
746 |
}
|
747 |
if ( 402 === $status_code ) {
|
748 |
Lingotek_Logger::error( 'There was an error updating WordPress item', array( 'error' => $this->get_error_message_from_response( $response ) ) );
|
749 |
$document->source_failed();
|
750 |
return false;
|
751 |
}
|
752 |
+
if ( 410 === $status_code || 404 === $status_code ) {
|
753 |
// WP hooks automatically check source status so this might not get called
|
754 |
+
$polylang_targets = array_keys( $document->translations );
|
755 |
+
if ( ! in_array( $locale, $polylang_targets ) ) {
|
756 |
+
$polylang_targets[] = $locale;
|
757 |
+
}
|
758 |
+
$params = $lgtm->reupload_build_params( $wp_id );
|
759 |
+
$unformatted_args = array_merge( $unformatted_args, $params );
|
760 |
unset( $document->desc_array['lingotek'] );
|
761 |
$document->save();
|
762 |
+
$lingotek_locales = array();
|
763 |
+
foreach ( $polylang_targets as $target ) {
|
764 |
+
$document->translations[ $target ] = 'pending';
|
765 |
+
// Targets stored in the document translations property are the polylang targets, so we need to get the lingotek locales instead
|
766 |
+
$lingotek_locales[] = Lingotek::map_to_lingotek_locale( $target );
|
767 |
}
|
768 |
+
$unformatted_args['translation_locale_code'] = $lingotek_locales;
|
769 |
+
$this->format_args_for_upload( $unformatted_args, $wp_id );
|
770 |
+
$upload_response = $this->upload_document( $unformatted_args, $wp_id );
|
771 |
+
if ( $upload_response ) {
|
772 |
+
$document_id = $upload_response;
|
773 |
+
}
|
774 |
+
return $upload_response;
|
775 |
+
}//end if
|
776 |
if ( 400 === $status_code &&
|
777 |
! empty( $body->messages ) &&
|
778 |
strpos( $body->messages[0], 'already exists' ) ) {
|
782 |
if ( 201 === $status_code ) {
|
783 |
if ( isset( $arr[ $wp_id ] ) ) {
|
784 |
unset( $arr[ $wp_id ]['wp_error'] );
|
785 |
+
unset( $arr[ $wp_id ]['request_translation'][ $lingotek_locale ] );
|
786 |
if ( empty( $arr[ $wp_id ] ) ) {
|
787 |
unset( $arr[ $wp_id ] );
|
788 |
}
|
789 |
}
|
790 |
} elseif ( is_wp_error( $response ) ) {
|
791 |
$arr[ $wp_id ]['wp_error'] = __( 'Make sure you have internet connectivity', 'lingotek-translation' );
|
792 |
+
} elseif ( 400 == $status_code ) {
|
793 |
+
$arr[ $wp_id ]['request_translation'][ $lingotek_locale ] = sprintf(
|
794 |
__( 'There was an error requesting translation %1$s for WordPress item %2$s', 'lingotek-translation' ),
|
795 |
+
$lingotek_locale,
|
796 |
$wp_id
|
797 |
);
|
798 |
}
|
803 |
$response,
|
804 |
'RequestTranslation: Error Occurred',
|
805 |
array(
|
806 |
+
'document_id' => $document_id,
|
807 |
+
'locale' => $lingotek_locale,
|
808 |
'args' => $args,
|
809 |
)
|
810 |
);
|
878 |
* cancels a translation
|
879 |
*
|
880 |
* @since 1.4.2
|
881 |
+
* @since 1.5.0 Changed signature, breaking change.
|
882 |
*
|
883 |
+
* @param string $document_id document id
|
884 |
* @param string $locale Lingotek locale
|
885 |
*/
|
886 |
+
public function cancel_translation( $document_id, $locale, $wp_id = null ) {
|
887 |
+
$args = wp_parse_args(
|
888 |
array(
|
889 |
'cancelled_reason' => 'CANCELLED_BY_AUTHOR',
|
890 |
'mark_invoiceable' => true,
|
891 |
)
|
892 |
);
|
893 |
+
$lingotek_locale = Lingotek::map_to_lingotek_locale( $locale );
|
894 |
+
$response = $this->post( "$this->api_url/document/$document_id/translation/$lingotek_locale/cancel", $args );
|
895 |
|
896 |
if ( $wp_id ) {
|
897 |
$arr = get_option( 'lingotek_log_errors' );
|
904 |
$response,
|
905 |
'CancelTranslation: Error occurred',
|
906 |
array(
|
907 |
+
'id' => $document_id,
|
908 |
'wordpress_id' => $wp_id,
|
909 |
)
|
910 |
);
|
913 |
Lingotek_Logger::info(
|
914 |
'Target cancelled',
|
915 |
array(
|
916 |
+
'document_id' => $document_id,
|
917 |
'wp_id' => $wp_id,
|
918 |
)
|
919 |
);
|
include/callback.php
CHANGED
@@ -44,6 +44,9 @@ class Lingotek_Callback {
|
|
44 |
case 'target_cancelled':
|
45 |
$this->handleTargetCancelled( $document );
|
46 |
break;
|
|
|
|
|
|
|
47 |
case 'document_uploaded':
|
48 |
case 'document_updated':
|
49 |
$this->handleDocumentUploadedOrUpdated( $document );
|
@@ -52,8 +55,10 @@ class Lingotek_Callback {
|
|
52 |
$this->handleImportFailure( $document );
|
53 |
break;
|
54 |
case 'document_archived':
|
|
|
|
|
55 |
case 'document_deleted':
|
56 |
-
$this->
|
57 |
break;
|
58 |
case 'document_cancelled';
|
59 |
$this->handleDocumentCancelled( $document );
|
@@ -152,17 +157,53 @@ class Lingotek_Callback {
|
|
152 |
$document->source_failed();
|
153 |
}
|
154 |
|
155 |
-
public function
|
156 |
$callback_parameters = array(
|
157 |
-
|
158 |
-
|
|
|
|
|
|
|
159 |
);
|
160 |
Lingotek_Logger::info( 'Callback received', array( 'Callback Parameters' => $callback_parameters ) );
|
|
|
161 |
$wp_id = isset( $document->desc_array['lingotek']['source'] ) ? $document->desc_array['lingotek']['source'] : null;
|
162 |
-
|
163 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
164 |
$document->save();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
165 |
wp_remove_object_terms( $wp_id, "lingotek_hash_{$wp_id}", 'lingotek_hash' );
|
|
|
|
|
|
|
|
|
166 |
}
|
167 |
|
168 |
public function handleDocumentCancelled( $document ) {
|
@@ -171,15 +212,16 @@ class Lingotek_Callback {
|
|
171 |
'Type' => isset( $_GET['type'] ) ? $_GET['type'] : null,
|
172 |
);
|
173 |
if ( isset( $document->desc_array['lingotek']['translations'] ) && count( $document->desc_array['lingotek']['translations'] ) > 0 ) {
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
unset( $document->desc_array['lingotek'] );
|
178 |
}
|
179 |
-
$wp_id
|
180 |
-
$document->status = 'cancelled';
|
181 |
-
$document->save();
|
182 |
wp_remove_object_terms( $wp_id, "lingotek_hash_{$wp_id}", 'lingotek_hash' );
|
|
|
|
|
|
|
|
|
183 |
Lingotek_Logger::info( 'Callback Received', array( 'Callback Parameters' => $callback_parameters ) );
|
184 |
}
|
185 |
|
@@ -198,4 +240,26 @@ class Lingotek_Callback {
|
|
198 |
$document->update_translation_status( $locale, 'cancelled' );
|
199 |
Lingotek_Logger::info( 'Callback received', array( 'Callback Parameters' => $callback_parameters ) );
|
200 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
201 |
}
|
44 |
case 'target_cancelled':
|
45 |
$this->handleTargetCancelled( $document );
|
46 |
break;
|
47 |
+
case 'target_deleted':
|
48 |
+
$this->handleTargetDeleted( $document );
|
49 |
+
break;
|
50 |
case 'document_uploaded':
|
51 |
case 'document_updated':
|
52 |
$this->handleDocumentUploadedOrUpdated( $document );
|
55 |
$this->handleImportFailure( $document );
|
56 |
break;
|
57 |
case 'document_archived':
|
58 |
+
$this->handleDocumentArchived( $document );
|
59 |
+
break;
|
60 |
case 'document_deleted':
|
61 |
+
$this->handleDocumentDeleted( $document );
|
62 |
break;
|
63 |
case 'document_cancelled';
|
64 |
$this->handleDocumentCancelled( $document );
|
157 |
$document->source_failed();
|
158 |
}
|
159 |
|
160 |
+
public function handleDocumentArchived( $document ) {
|
161 |
$callback_parameters = array(
|
162 |
+
// As this comes from Lingotek callback we cannot have a nonce.
|
163 |
+
// phpcs:ignore WordPress.Security.NonceVerification.Recommended,
|
164 |
+
'Document ID' => isset( $_GET['document_id'] ) ? sanitize_key( $_GET['document_id'] ) : null,
|
165 |
+
// phpcs:ignore WordPress.Security.NonceVerification.Recommended,
|
166 |
+
'Type' => isset( $_GET['type'] ) ? sanitize_key( $_GET['type'] ) : null,
|
167 |
);
|
168 |
Lingotek_Logger::info( 'Callback received', array( 'Callback Parameters' => $callback_parameters ) );
|
169 |
+
// The removal of the lingotek hash term is needed as it could prevent further uploads.
|
170 |
$wp_id = isset( $document->desc_array['lingotek']['source'] ) ? $document->desc_array['lingotek']['source'] : null;
|
171 |
+
wp_remove_object_terms( $wp_id, "lingotek_hash_{$wp_id}", 'lingotek_hash' );
|
172 |
+
|
173 |
+
if ( isset( $document->desc_array['lingotek']['translations'] ) && count( $document->desc_array['lingotek']['translations'] ) > 0 ) {
|
174 |
+
foreach ( $document->desc_array['lingotek']['translations'] as $target_locale => $target_status ) {
|
175 |
+
$document->desc_array['lingotek']['translations'][ $target_locale ] = 'archived';
|
176 |
+
}
|
177 |
+
}
|
178 |
+
$document->desc_array['lingotek']['document_id'] = 'archived_' . $document->document_id;
|
179 |
+
$document->desc_array['lingotek']['status'] = 'archived';
|
180 |
+
|
181 |
$document->save();
|
182 |
+
}
|
183 |
+
|
184 |
+
public function handleDocumentDeleted( $document ) {
|
185 |
+
$callback_parameters = array(
|
186 |
+
// As this comes from Lingotek callback we cannot have a nonce.
|
187 |
+
// phpcs:ignore WordPress.Security.NonceVerification.Recommended,
|
188 |
+
'Document ID' => isset( $_GET['document_id'] ) ? sanitize_key( $_GET['document_id'] ) : null,
|
189 |
+
// phpcs:ignore WordPress.Security.NonceVerification.Recommended,
|
190 |
+
'Type' => isset( $_GET['type'] ) ? sanitize_key( $_GET['type'] ) : null,
|
191 |
+
);
|
192 |
+
Lingotek_Logger::info( 'Callback received', array( 'Callback Parameters' => $callback_parameters ) );
|
193 |
+
|
194 |
+
if ( isset( $document->desc_array['lingotek']['translations'] ) && count( $document->desc_array['lingotek']['translations'] ) > 0 ) {
|
195 |
+
foreach ( $document->desc_array['lingotek']['translations'] as $target_locale => $target_status ) {
|
196 |
+
$document->desc_array['lingotek']['translations'][ $target_locale ] = 'deleted';
|
197 |
+
}
|
198 |
+
}
|
199 |
+
|
200 |
+
// The removal of the lingotek hash term is needed as it could prevent further uploads.
|
201 |
+
$wp_id = isset( $document->desc_array['lingotek']['source'] ) ? $document->desc_array['lingotek']['source'] : null;
|
202 |
wp_remove_object_terms( $wp_id, "lingotek_hash_{$wp_id}", 'lingotek_hash' );
|
203 |
+
|
204 |
+
$document->desc_array['lingotek']['document_id'] = 'deleted_' . $document->document_id;
|
205 |
+
$document->desc_array['lingotek']['status'] = 'deleted';
|
206 |
+
$document->save();
|
207 |
}
|
208 |
|
209 |
public function handleDocumentCancelled( $document ) {
|
212 |
'Type' => isset( $_GET['type'] ) ? $_GET['type'] : null,
|
213 |
);
|
214 |
if ( isset( $document->desc_array['lingotek']['translations'] ) && count( $document->desc_array['lingotek']['translations'] ) > 0 ) {
|
215 |
+
foreach ( $document->desc_array['lingotek']['translations'] as $target_locale => $target_status ) {
|
216 |
+
$document->desc_array['lingotek']['translations'][ $target_locale ] = 'cancelled';
|
217 |
+
}
|
|
|
218 |
}
|
219 |
+
$wp_id = isset( $document->desc_array['lingotek']['source'] ) ? $document->desc_array['lingotek']['source'] : null;
|
|
|
|
|
220 |
wp_remove_object_terms( $wp_id, "lingotek_hash_{$wp_id}", 'lingotek_hash' );
|
221 |
+
|
222 |
+
$document->desc_array['lingotek']['document_id'] = 'cancelled_' . $document->document_id;
|
223 |
+
$document->desc_array['lingotek']['status'] = 'cancelled';
|
224 |
+
$document->save();
|
225 |
Lingotek_Logger::info( 'Callback Received', array( 'Callback Parameters' => $callback_parameters ) );
|
226 |
}
|
227 |
|
240 |
$document->update_translation_status( $locale, 'cancelled' );
|
241 |
Lingotek_Logger::info( 'Callback received', array( 'Callback Parameters' => $callback_parameters ) );
|
242 |
}
|
243 |
+
|
244 |
+
public function handleTargetDeleted( $document ) {
|
245 |
+
$callback_parameters = array(
|
246 |
+
// As this comes from Lingotek callback we cannot have a nonce.
|
247 |
+
// phpcs:ignore WordPress.Security.NonceVerification.Recommended,
|
248 |
+
'Document ID' => isset( $_GET['document_id'] ) ? sanitize_key( $_GET['document_id'] ) : null,
|
249 |
+
// phpcs:ignore WordPress.Security.NonceVerification.Recommended,
|
250 |
+
'Type' => isset( $_GET['type'] ) ? sanitize_key( $_GET['type'] ) : null,
|
251 |
+
// phpcs:ignore WordPress.Security.NonceVerification.Recommended,
|
252 |
+
'Locale' => isset( $_GET['locale'] ) ? sanitize_lingotek_locale( $_GET['locale'] ) : null,
|
253 |
+
);
|
254 |
+
// Map to WordPress locale.
|
255 |
+
// phpcs:ignore WordPress.Security.NonceVerification.Recommended,
|
256 |
+
$locale = Lingotek::map_to_wp_locale( sanitize_lingotek_locale( $_GET['locale'] ) );
|
257 |
+
if ( ! isset( $document->desc_array['lingotek']['translations'][ $locale ] ) ) {
|
258 |
+
$document->desc_array['lingotek']['translations'][] = $locale;
|
259 |
+
$document->save();
|
260 |
+
}
|
261 |
+
$document->update_translation_status( $locale, 'deleted' );
|
262 |
+
Lingotek_Logger::info( 'Callback received', array( 'Callback Parameters' => $callback_parameters ) );
|
263 |
+
}
|
264 |
+
|
265 |
}
|
include/group.php
CHANGED
@@ -182,10 +182,11 @@ abstract class Lingotek_Group {
|
|
182 |
*
|
183 |
* @param bool $cancel whether to cancel the Lingotek document or not
|
184 |
*/
|
185 |
-
public function cancel_translation( $
|
186 |
$client = new Lingotek_API();
|
187 |
-
if ( $client->cancel_translation( $this->document_id, $
|
188 |
-
$
|
|
|
189 |
$this->save();
|
190 |
} else {
|
191 |
update_option( 'cancel_target_failed', true );
|
@@ -210,6 +211,7 @@ abstract class Lingotek_Group {
|
|
210 |
$this->translations = isset( $this->translations ) ? array_fill_keys( array_keys( $this->translations ), 'pending' ) : null;
|
211 |
$this->save();
|
212 |
}
|
|
|
213 |
}
|
214 |
|
215 |
/**
|
@@ -256,7 +258,8 @@ abstract class Lingotek_Group {
|
|
256 |
}
|
257 |
$args = $workflow ? array( 'workflow_id' => $workflow ) : array();
|
258 |
|
259 |
-
if ( ! $this->is_disabled_target( $language ) &&
|
|
|
260 |
// don't change translations to pending if the api call failed
|
261 |
if ( $client->request_translation( $this->document_id, $language->locale, $args, $this->source ) ) {
|
262 |
$this->status = 'current';
|
@@ -366,6 +369,17 @@ abstract class Lingotek_Group {
|
|
366 |
$this->translations[ $wp_locale ] = 'ready';
|
367 |
}
|
368 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
369 |
|
370 |
$this->save();
|
371 |
}
|
182 |
*
|
183 |
* @param bool $cancel whether to cancel the Lingotek document or not
|
184 |
*/
|
185 |
+
public function cancel_translation( $id, $target_locale ) {
|
186 |
$client = new Lingotek_API();
|
187 |
+
if ( $client->cancel_translation( $this->document_id, $target_locale ) ) {
|
188 |
+
$wp_locale = Lingotek::map_to_wp_locale( $target_locale );
|
189 |
+
$this->desc_array['lingotek']['translations'][ $wp_locale ] = 'cancelled';
|
190 |
$this->save();
|
191 |
} else {
|
192 |
update_option( 'cancel_target_failed', true );
|
211 |
$this->translations = isset( $this->translations ) ? array_fill_keys( array_keys( $this->translations ), 'pending' ) : null;
|
212 |
$this->save();
|
213 |
}
|
214 |
+
return $res;
|
215 |
}
|
216 |
|
217 |
/**
|
258 |
}
|
259 |
$args = $workflow ? array( 'workflow_id' => $workflow ) : array();
|
260 |
|
261 |
+
if ( ! $this->is_disabled_target( $language ) &&
|
262 |
+
( empty( $this->translations[ $language->locale ] ) || 'deleted' === $this->translations[ $language->locale ] ) ) {
|
263 |
// don't change translations to pending if the api call failed
|
264 |
if ( $client->request_translation( $this->document_id, $language->locale, $args, $this->source ) ) {
|
265 |
$this->status = 'current';
|
369 |
$this->translations[ $wp_locale ] = 'ready';
|
370 |
}
|
371 |
}
|
372 |
+
// If there were any cancelled or deleted targets that we didn't update properly,
|
373 |
+
// we didn't get anything, but locally they would keep that status, let's update those here.
|
374 |
+
$pll_locale_to_lingotek_locale = array_flip( $lingotek_locale_to_pll_locale );
|
375 |
+
foreach ( $this->translations as $target_locale => $target_status ) {
|
376 |
+
if ( ! isset( $translations[ $pll_locale_to_lingotek_locale[ $target_locale ] ] ) ) {
|
377 |
+
if ( ! in_array( $this->translations[ $target_locale ], array( 'deleted', 'cancelled' ) ) ) {
|
378 |
+
// Mark is a deleted.
|
379 |
+
$this->translations[ $target_locale ] = 'deleted';
|
380 |
+
}
|
381 |
+
}
|
382 |
+
}
|
383 |
|
384 |
$this->save();
|
385 |
}
|
include/model.php
CHANGED
@@ -391,18 +391,20 @@ class Lingotek_Model {
|
|
391 |
// Returns type string or boolean
|
392 |
$document_id = self::get_document_id( 'post', $post_id );
|
393 |
// Slug can't be empty or duplicated, so we prefix `disassociated` to show the document id is no longer associated with this post
|
394 |
-
if ( is_string( $document_id ) &&
|
395 |
$document_id = false;
|
396 |
}
|
397 |
$content = null;
|
398 |
// If we already uploaded this doc, check if it changed and prevent the upload if it didn't.
|
|
|
399 |
if ( $document_id ) {
|
400 |
$content = Lingotek_Group_Post::get_content( $post );
|
401 |
$hash_terms = wp_get_object_terms( $post->ID, 'lingotek_hash' );
|
402 |
$hash_term = array_pop( $hash_terms );
|
403 |
$new_hash = md5( $content );
|
404 |
if ( ! empty( $hash_term ) ) {
|
405 |
-
|
|
|
406 |
return;
|
407 |
}
|
408 |
}
|
@@ -414,7 +416,6 @@ class Lingotek_Model {
|
|
414 |
$document->pre_upload_to_lingotek( $post_id, $post->post_type, $language, 'post' );
|
415 |
}
|
416 |
|
417 |
-
$client = new Lingotek_API();
|
418 |
$external_url = get_page_link( $post_id );
|
419 |
if ( ! $content ) {
|
420 |
$content = Lingotek_Group_Post::get_content( $post );
|
@@ -431,12 +432,12 @@ class Lingotek_Model {
|
|
431 |
$hash_terms = wp_set_post_terms( $post->ID, 'lingotek_hash_' . $post->ID, 'lingotek_hash' );
|
432 |
$hash_term_id = array_pop( $hash_terms );
|
433 |
} else {
|
434 |
-
$hash_term_id = $hash_term->
|
435 |
}
|
436 |
wp_update_term( $hash_term_id, 'lingotek_hash', array( 'description' => $new_hash ) );
|
437 |
}
|
438 |
return $response;
|
439 |
-
} elseif ( ! Lingotek_Group::$creating_translation && ! self::$copying_post && ( ! $document || $document->status
|
440 |
$document_id = $client->upload_document( $params, $post->ID );
|
441 |
if ( $document_id ) {
|
442 |
Lingotek_Group_Post::create( $post->ID, $language, $document_id );
|
@@ -675,7 +676,7 @@ class Lingotek_Model {
|
|
675 |
$client->cancel_document( $document->document_id, $object_id );
|
676 |
} else {
|
677 |
$lang = PLL()->model->term->get_language( $object_id );
|
678 |
-
PLL()->model->term->cancel_translation( $
|
679 |
PLL()->model->term->delete_translation( $object_id );
|
680 |
$client->cancel_translation( $document->document_id, $lang->lingotek_locale, $object_id );
|
681 |
}
|
@@ -1028,6 +1029,36 @@ class Lingotek_Model {
|
|
1028 |
return $params;
|
1029 |
}
|
1030 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1031 |
private function get_filter_ids( $type, $language, $wp_id ) {
|
1032 |
$filter_ids = array();
|
1033 |
if ( self::get_profile_option( 'primary_filter_id', $type, $language, false, $wp_id ) ) {
|
@@ -1038,4 +1069,18 @@ class Lingotek_Model {
|
|
1038 |
}
|
1039 |
return $filter_ids;
|
1040 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1041 |
}
|
391 |
// Returns type string or boolean
|
392 |
$document_id = self::get_document_id( 'post', $post_id );
|
393 |
// Slug can't be empty or duplicated, so we prefix `disassociated` to show the document id is no longer associated with this post
|
394 |
+
if ( is_string( $document_id ) && $this->is_disassociated_deleted_cancelled_or_archived( $document_id ) ) {
|
395 |
$document_id = false;
|
396 |
}
|
397 |
$content = null;
|
398 |
// If we already uploaded this doc, check if it changed and prevent the upload if it didn't.
|
399 |
+
$client = new Lingotek_API();
|
400 |
if ( $document_id ) {
|
401 |
$content = Lingotek_Group_Post::get_content( $post );
|
402 |
$hash_terms = wp_get_object_terms( $post->ID, 'lingotek_hash' );
|
403 |
$hash_term = array_pop( $hash_terms );
|
404 |
$new_hash = md5( $content );
|
405 |
if ( ! empty( $hash_term ) ) {
|
406 |
+
// If the document hasn't changed and it exists in TMS, don't upload
|
407 |
+
if ( $hash_term->description == $new_hash && $client->get_document_status( $document_id ) ) {
|
408 |
return;
|
409 |
}
|
410 |
}
|
416 |
$document->pre_upload_to_lingotek( $post_id, $post->post_type, $language, 'post' );
|
417 |
}
|
418 |
|
|
|
419 |
$external_url = get_page_link( $post_id );
|
420 |
if ( ! $content ) {
|
421 |
$content = Lingotek_Group_Post::get_content( $post );
|
432 |
$hash_terms = wp_set_post_terms( $post->ID, 'lingotek_hash_' . $post->ID, 'lingotek_hash' );
|
433 |
$hash_term_id = array_pop( $hash_terms );
|
434 |
} else {
|
435 |
+
$hash_term_id = $hash_term->term_id;
|
436 |
}
|
437 |
wp_update_term( $hash_term_id, 'lingotek_hash', array( 'description' => $new_hash ) );
|
438 |
}
|
439 |
return $response;
|
440 |
+
} elseif ( ! Lingotek_Group::$creating_translation && ! self::$copying_post && ( ! $document || in_array( $document->status, array( 'deleted', 'disassociated', 'archived', 'cancelled', null ), true ) ) ) {
|
441 |
$document_id = $client->upload_document( $params, $post->ID );
|
442 |
if ( $document_id ) {
|
443 |
Lingotek_Group_Post::create( $post->ID, $language, $document_id );
|
676 |
$client->cancel_document( $document->document_id, $object_id );
|
677 |
} else {
|
678 |
$lang = PLL()->model->term->get_language( $object_id );
|
679 |
+
PLL()->model->term->cancel_translation( $document->document_id, $lang->lingotek_locale );
|
680 |
PLL()->model->term->delete_translation( $object_id );
|
681 |
$client->cancel_translation( $document->document_id, $lang->lingotek_locale, $object_id );
|
682 |
}
|
1029 |
return $params;
|
1030 |
}
|
1031 |
|
1032 |
+
/**
|
1033 |
+
* Builds the array of parameters for reuploads by getting only the post id.
|
1034 |
+
* Primarily for when handling 410 and 404 response codes
|
1035 |
+
* Return empty array if profile is disabled, or post/language are empty
|
1036 |
+
*
|
1037 |
+
* @since 1.5.0
|
1038 |
+
*
|
1039 |
+
* @param integer $post_id
|
1040 |
+
* @return array
|
1041 |
+
*/
|
1042 |
+
public function reupload_build_params( $post_id ) {
|
1043 |
+
$post = get_post( $post_id );
|
1044 |
+
$language = PLL()->model->post->get_language( $post_id );
|
1045 |
+
$profile = self::get_profile( $post->post_type, $language, $post_id );
|
1046 |
+
if ( 'disabled' === $profile['profile'] || empty( $post ) || empty( $language ) ) {
|
1047 |
+
Lingotek_Logger::info(
|
1048 |
+
'Document cannot be uploaded',
|
1049 |
+
array(
|
1050 |
+
'profile' => $profile['profile'],
|
1051 |
+
'post is empty' => empty( $post ),
|
1052 |
+
'language is empty' => empty( $language ),
|
1053 |
+
)
|
1054 |
+
);
|
1055 |
+
return array();
|
1056 |
+
}
|
1057 |
+
$external_url = get_page_link( $post_id );
|
1058 |
+
$content = Lingotek_Group_Post::get_content( $post );
|
1059 |
+
return $this->build_params( $external_url, $post->post_title, $post->post_type, $content, $language, $profile, $post_id );
|
1060 |
+
}
|
1061 |
+
|
1062 |
private function get_filter_ids( $type, $language, $wp_id ) {
|
1063 |
$filter_ids = array();
|
1064 |
if ( self::get_profile_option( 'primary_filter_id', $type, $language, false, $wp_id ) ) {
|
1069 |
}
|
1070 |
return $filter_ids;
|
1071 |
}
|
1072 |
+
|
1073 |
+
/**
|
1074 |
+
* Checks if a document id is disassociated, cancelled or archived.
|
1075 |
+
*
|
1076 |
+
* @param string $document_id
|
1077 |
+
*
|
1078 |
+
* @return bool
|
1079 |
+
*/
|
1080 |
+
protected function is_disassociated_deleted_cancelled_or_archived( $document_id ) {
|
1081 |
+
return strpos( $document_id, 'disassociated_' ) === 0 ||
|
1082 |
+
strpos( $document_id, 'deleted_' ) === 0 ||
|
1083 |
+
strpos( $document_id, 'cancelled_' ) === 0 ||
|
1084 |
+
strpos( $document_id, 'archived_' ) === 0;
|
1085 |
+
}
|
1086 |
}
|
js/actions.js
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* @file
|
3 |
+
* Lingotek target actions JS code for lingotek target actions button.
|
4 |
+
*/
|
5 |
+
jQuery( document ).ready(
|
6 |
+
function($) {
|
7 |
+
'use strict';
|
8 |
+
var $actionsElement = $( document ).find( '.lingotek-target-dropdown,.lingotek-source-dropdown' );
|
9 |
+
// Attach event handlers to toggle button.
|
10 |
+
$actionsElement.each(
|
11 |
+
function () {
|
12 |
+
var $this = $( this );
|
13 |
+
var $toggle = $this.find( '.lingotek-target-dropdown-toggle,.lingotek-source-dropdown-toggle' );
|
14 |
+
$toggle.on(
|
15 |
+
'click',
|
16 |
+
function (e) {
|
17 |
+
e.preventDefault();
|
18 |
+
$this.toggleClass( 'open' );
|
19 |
+
}
|
20 |
+
);
|
21 |
+
$this.on(
|
22 |
+
'focusout',
|
23 |
+
function (e) {
|
24 |
+
setTimeout(
|
25 |
+
function () {
|
26 |
+
if ($this.has( document.activeElement ).length == 0) {
|
27 |
+
// The focus left the action button group, hide actions.
|
28 |
+
$this.removeClass( 'open' );
|
29 |
+
}
|
30 |
+
},
|
31 |
+
1
|
32 |
+
);
|
33 |
+
}
|
34 |
+
);
|
35 |
+
}
|
36 |
+
);
|
37 |
+
}
|
38 |
+
);
|
js/progress.js
CHANGED
@@ -10,6 +10,9 @@ jQuery(document).ready(function($) {
|
|
10 |
if (lingotek_data.locales){
|
11 |
data.locales = JSON.stringify(lingotek_data.locales);
|
12 |
}
|
|
|
|
|
|
|
13 |
$.post(ajaxurl, data , function(response) {
|
14 |
$("#lingotek-progressbar").progressbar({
|
15 |
value: ++i / lingotek_data.ids.length * 100
|
10 |
if (lingotek_data.locales){
|
11 |
data.locales = JSON.stringify(lingotek_data.locales);
|
12 |
}
|
13 |
+
if (lingotek_data.target_locale){
|
14 |
+
data.target_locale = lingotek_data.target_locale;
|
15 |
+
}
|
16 |
$.post(ajaxurl, data , function(response) {
|
17 |
$("#lingotek-progressbar").progressbar({
|
18 |
value: ++i / lingotek_data.ids.length * 100
|
js/updater.js
CHANGED
@@ -2,7 +2,7 @@ jQuery(document).ready(function($) {
|
|
2 |
$('.edit-php a.submitdelete, .post-php a.submitdelete').click( function( event ) {
|
3 |
if( ! confirm( 'Content that is put into the trash will be cancelled in your Lingotek community. Are you sure you want to proceed?' ) ) {
|
4 |
event.preventDefault();
|
5 |
-
}
|
6 |
});
|
7 |
var current_ids = {};
|
8 |
var post_data = {"check_ids" : current_ids};
|
@@ -108,6 +108,14 @@ jQuery(document).ready(function($) {
|
|
108 |
updateGenericBulkLink(tr, data, key, 'download' , 'Download translations of this item from Lingotek TMS', 'Download translations');
|
109 |
updateIndicator(td, data, key, locale, 'download', 'Ready to download', 'download');
|
110 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
case 'cancelled':
|
112 |
if (locale === data[key]['source']){
|
113 |
updateUploadBulkLink(tr, data, key, 'upload' , 'Upload cancelled item to Lingotek TMS', 'Upload to Lingotek');
|
2 |
$('.edit-php a.submitdelete, .post-php a.submitdelete').click( function( event ) {
|
3 |
if( ! confirm( 'Content that is put into the trash will be cancelled in your Lingotek community. Are you sure you want to proceed?' ) ) {
|
4 |
event.preventDefault();
|
5 |
+
}
|
6 |
});
|
7 |
var current_ids = {};
|
8 |
var post_data = {"check_ids" : current_ids};
|
108 |
updateGenericBulkLink(tr, data, key, 'download' , 'Download translations of this item from Lingotek TMS', 'Download translations');
|
109 |
updateIndicator(td, data, key, locale, 'download', 'Ready to download', 'download');
|
110 |
break;
|
111 |
+
case 'deleted':
|
112 |
+
if (locale === data[key]['source']){
|
113 |
+
updateUploadBulkLink(tr, data, key, 'upload' , 'Upload deleted item to Lingotek TMS', 'Upload to Lingotek');
|
114 |
+
updateIndicator(td, data, key, locale, 'deleted', 'Upload deleted item', 'remove');
|
115 |
+
} else {
|
116 |
+
updateIndicator(td, data, key, locale, 'deleted', 'Target is deleted', 'remove');
|
117 |
+
}
|
118 |
+
break;
|
119 |
case 'cancelled':
|
120 |
if (locale === data[key]['source']){
|
121 |
updateUploadBulkLink(tr, data, key, 'upload' , 'Upload cancelled item to Lingotek TMS', 'Upload to Lingotek');
|
lingotek.php
CHANGED
@@ -2,13 +2,15 @@
|
|
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.
|
6 |
Author: Lingotek and Frédéric Demarle
|
7 |
Author uri: http://lingotek.com
|
8 |
Description: Lingotek offers convenient cloud-based localization and translation.
|
9 |
Text Domain: lingotek-translation
|
10 |
Domain Path: /languages
|
11 |
GitHub Plugin URI: https://github.com/lingotek/lingotek-translation
|
|
|
|
|
12 |
*/
|
13 |
|
14 |
// don't access directly.
|
@@ -17,7 +19,7 @@ if ( ! function_exists( 'add_action' ) ) {
|
|
17 |
}
|
18 |
|
19 |
// Plugin version (should match above meta).
|
20 |
-
define( 'LINGOTEK_VERSION', '1.
|
21 |
define( 'LINGOTEK_MIN_PLL_VERSION', '1.8' );
|
22 |
// Plugin name as known by WordPress.
|
23 |
define( 'LINGOTEK_BASENAME', plugin_basename( __FILE__ ) );
|
@@ -311,24 +313,61 @@ class Lingotek {
|
|
311 |
}
|
312 |
|
313 |
add_action( 'plugins_loaded', array( &$this, 'lingotek_plugin_migration' ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
314 |
}
|
315 |
|
316 |
public function lingotek_plugin_migration() {
|
317 |
-
$
|
318 |
if ( $this->needs_to_run_updates( '1.4.11' ) ) {
|
319 |
// Add the updates introduced in 1.4.11.
|
320 |
$this->update_1_4_11_for_removing_custom_fields_from_postTypes_settings();
|
321 |
$this->update_1_4_11_for_removing_custom_fields_autoload();
|
322 |
$this->update_1_4_11_for_removing_community_resources_autoload();
|
323 |
-
$
|
324 |
}
|
325 |
if ( $this->needs_to_run_updates( '1.4.13' ) ) {
|
326 |
// Add the updates introduced in 1.4.13.
|
327 |
$this->update_1_4_13_for_disabling_autoload_for_all_wpoptions();
|
328 |
-
$
|
329 |
}
|
330 |
// If any update happened, inform the user and update the version.
|
331 |
-
if ( $
|
332 |
update_option( 'lingotek_plugin_version', LINGOTEK_VERSION, false );
|
333 |
add_action(
|
334 |
'admin_notices',
|
@@ -347,18 +386,18 @@ class Lingotek {
|
|
347 |
* It will check that the installed version is newer than the db one, even if we
|
348 |
* had skipped any version, and ensures we don't run any update if we already did.
|
349 |
*
|
350 |
-
* @param $
|
351 |
* The version where these updates were introduced.
|
352 |
* @return bool
|
353 |
* true if needs to run, false otherwise
|
354 |
*
|
355 |
* @since 1.4.11
|
356 |
*/
|
357 |
-
public function needs_to_run_updates( $
|
358 |
$db_version = get_option( 'lingotek_plugin_version' );
|
359 |
return ( $db_version !== false &&
|
360 |
-
version_compare( LINGOTEK_VERSION, $
|
361 |
-
version_compare( $
|
362 |
}
|
363 |
|
364 |
/**
|
@@ -368,9 +407,9 @@ class Lingotek {
|
|
368 |
* @since 1.4.11
|
369 |
*/
|
370 |
public function update_1_4_11_for_removing_custom_fields_from_postTypes_settings() {
|
371 |
-
$settings = get_option( 'lingotek_content_type' );
|
372 |
-
foreach ( $settings as $
|
373 |
-
unset( $
|
374 |
}
|
375 |
update_option( 'lingotek_content_type', $settings, false );
|
376 |
}
|
@@ -697,6 +736,10 @@ class Lingotek {
|
|
697 |
}
|
698 |
|
699 |
wp_enqueue_style( 'lingotek_admin', LINGOTEK_URL . '/css/admin.css', array(), LINGOTEK_VERSION );
|
|
|
|
|
|
|
|
|
700 |
}
|
701 |
|
702 |
/**
|
@@ -971,4 +1014,5 @@ class Lingotek {
|
|
971 |
}
|
972 |
}
|
973 |
|
|
|
974 |
$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.5.0
|
6 |
Author: Lingotek and Frédéric Demarle
|
7 |
Author uri: http://lingotek.com
|
8 |
Description: Lingotek offers convenient cloud-based localization and translation.
|
9 |
Text Domain: lingotek-translation
|
10 |
Domain Path: /languages
|
11 |
GitHub Plugin URI: https://github.com/lingotek/lingotek-translation
|
12 |
+
*
|
13 |
+
* @package Lingotek
|
14 |
*/
|
15 |
|
16 |
// don't access directly.
|
19 |
}
|
20 |
|
21 |
// Plugin version (should match above meta).
|
22 |
+
define( 'LINGOTEK_VERSION', '1.5.0' );
|
23 |
define( 'LINGOTEK_MIN_PLL_VERSION', '1.8' );
|
24 |
// Plugin name as known by WordPress.
|
25 |
define( 'LINGOTEK_BASENAME', plugin_basename( __FILE__ ) );
|
313 |
}
|
314 |
|
315 |
add_action( 'plugins_loaded', array( &$this, 'lingotek_plugin_migration' ) );
|
316 |
+
|
317 |
+
/**
|
318 |
+
* We temporarely inform of the new UI. We might want to remove this after some releases.
|
319 |
+
*
|
320 |
+
* @since 1.15.0
|
321 |
+
*/
|
322 |
+
add_action( 'init', array( &$this, 'lingotek_new_ui' ), 10, 2 );
|
323 |
+
}
|
324 |
+
|
325 |
+
/**
|
326 |
+
* Show the bubble announcing the new UI.
|
327 |
+
*
|
328 |
+
* @since 1.15.0
|
329 |
+
*/
|
330 |
+
public function lingotek_new_ui() {
|
331 |
+
$content = __( 'Lingotek new UI is ready! If you still need the Polylang based columns, customize those in "Screen Options"', 'lingotek-translation' );
|
332 |
+
|
333 |
+
$buttons = array(
|
334 |
+
array(
|
335 |
+
'label' => __( 'Close' ),
|
336 |
+
),
|
337 |
+
);
|
338 |
+
|
339 |
+
$args = array(
|
340 |
+
'pointer' => 'lingotek-new-ui',
|
341 |
+
'id' => 'lingotek_targets',
|
342 |
+
'position' => array(
|
343 |
+
'edge' => 'top',
|
344 |
+
'align' => 'left',
|
345 |
+
),
|
346 |
+
'width' => 380,
|
347 |
+
'title' => __( 'Lingotek New UI', 'lingotek-translation' ),
|
348 |
+
'content' => $content,
|
349 |
+
'buttons' => $buttons,
|
350 |
+
);
|
351 |
+
|
352 |
+
new Lingotek_Pointer( $args );
|
353 |
}
|
354 |
|
355 |
public function lingotek_plugin_migration() {
|
356 |
+
$updates_have_run = false;
|
357 |
if ( $this->needs_to_run_updates( '1.4.11' ) ) {
|
358 |
// Add the updates introduced in 1.4.11.
|
359 |
$this->update_1_4_11_for_removing_custom_fields_from_postTypes_settings();
|
360 |
$this->update_1_4_11_for_removing_custom_fields_autoload();
|
361 |
$this->update_1_4_11_for_removing_community_resources_autoload();
|
362 |
+
$updates_have_run = true;
|
363 |
}
|
364 |
if ( $this->needs_to_run_updates( '1.4.13' ) ) {
|
365 |
// Add the updates introduced in 1.4.13.
|
366 |
$this->update_1_4_13_for_disabling_autoload_for_all_wpoptions();
|
367 |
+
$updates_have_run = true;
|
368 |
}
|
369 |
// If any update happened, inform the user and update the version.
|
370 |
+
if ( $updates_have_run ) {
|
371 |
update_option( 'lingotek_plugin_version', LINGOTEK_VERSION, false );
|
372 |
add_action(
|
373 |
'admin_notices',
|
386 |
* It will check that the installed version is newer than the db one, even if we
|
387 |
* had skipped any version, and ensures we don't run any update if we already did.
|
388 |
*
|
389 |
+
* @param $version_updates
|
390 |
* The version where these updates were introduced.
|
391 |
* @return bool
|
392 |
* true if needs to run, false otherwise
|
393 |
*
|
394 |
* @since 1.4.11
|
395 |
*/
|
396 |
+
public function needs_to_run_updates( $version_updates ) {
|
397 |
$db_version = get_option( 'lingotek_plugin_version' );
|
398 |
return ( $db_version !== false &&
|
399 |
+
version_compare( LINGOTEK_VERSION, $version_updates, '>=' ) &&
|
400 |
+
version_compare( $version_updates, $db_version, '>' ) );
|
401 |
}
|
402 |
|
403 |
/**
|
407 |
* @since 1.4.11
|
408 |
*/
|
409 |
public function update_1_4_11_for_removing_custom_fields_from_postTypes_settings() {
|
410 |
+
$settings = get_option( 'lingotek_content_type', array() );
|
411 |
+
foreach ( $settings as $enabled_post_type => &$enabled_post_type_settings ) {
|
412 |
+
unset( $enabled_post_type_settings['fields']['metas'] );
|
413 |
}
|
414 |
update_option( 'lingotek_content_type', $settings, false );
|
415 |
}
|
736 |
}
|
737 |
|
738 |
wp_enqueue_style( 'lingotek_admin', LINGOTEK_URL . '/css/admin.css', array(), LINGOTEK_VERSION );
|
739 |
+
wp_enqueue_style( 'lingotek_statuses', LINGOTEK_URL . '/css/statuses.css', array(), LINGOTEK_VERSION );
|
740 |
+
|
741 |
+
wp_enqueue_script( 'lingotek_actions', LINGOTEK_URL . '/js/actions.js', array( 'jquery' ), LINGOTEK_VERSION, true );
|
742 |
+
wp_enqueue_style( 'lingotek_actions', LINGOTEK_URL . '/css/actions.css', array(), LINGOTEK_VERSION );
|
743 |
}
|
744 |
|
745 |
/**
|
1014 |
}
|
1015 |
}
|
1016 |
|
1017 |
+
require_once 'sanitization.php';
|
1018 |
$GLOBALS['wp_lingotek'] = Lingotek::get_instance();
|
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: 5.8
|
7 |
-
Stable tag: 1.
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
@@ -122,6 +122,14 @@ For more, visit the [Lingotek documentation site](https://lingotek.atlassian.net
|
|
122 |
5. The Lingotek Translation plugin provides the ability to Copy, Translate, and Ignore each specific custom field. Our plugin supports Wordpress custom fields and advanced custom fields.
|
123 |
|
124 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
= 1.4.16 (2021-07-22) =
|
126 |
* Fixed small whitespace bug
|
127 |
|
4 |
Tags: automation, bilingual, international, language, Lingotek, localization, multilanguage, multilingual, translate, translation
|
5 |
Requires at least: 3.8
|
6 |
Tested up to: 5.8
|
7 |
+
Stable tag: 1.5.0
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
122 |
5. The Lingotek Translation plugin provides the ability to Copy, Translate, and Ignore each specific custom field. Our plugin supports Wordpress custom fields and advanced custom fields.
|
123 |
|
124 |
== Changelog ==
|
125 |
+
= 1.5.0 (2021-08-05) =
|
126 |
+
* New UI
|
127 |
+
- The source and translation icons have been replaced with chips. This makes it easier to view which stage the translations are in.
|
128 |
+
- Added dropdown actions to the source and target chips.
|
129 |
+
- Added Cancel option for specific targets in the action dropdown.
|
130 |
+
*New Gone status
|
131 |
+
- This will give you a visual indicator when a document or target has been archived or deleted.
|
132 |
+
|
133 |
= 1.4.16 (2021-07-22) =
|
134 |
* Fixed small whitespace bug
|
135 |
|
sanitization.php
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Collection of functions that needs to be available everywhere in Lingotek Translation plugin.
|
4 |
+
*
|
5 |
+
* @package Lingotek
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Sanitizes a Lingotek locale.
|
10 |
+
*
|
11 |
+
* Lower and uppercase alphanumeric characters, dashes, and underscores are allowed.
|
12 |
+
*
|
13 |
+
* @since 1.4.14
|
14 |
+
*
|
15 |
+
* @param string $locale String locale.
|
16 |
+
* @return string Sanitized locale.
|
17 |
+
*/
|
18 |
+
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound
|
19 |
+
function sanitize_lingotek_locale( $locale ) {
|
20 |
+
$raw_locale = $locale;
|
21 |
+
$locale = preg_replace( '/[^a-zA-Z0-9_\-]/', '', $locale );
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Filters a sanitized key string.
|
25 |
+
*
|
26 |
+
* @since 1.4.14
|
27 |
+
*
|
28 |
+
* @param string $key Sanitized key.
|
29 |
+
* @param string $raw_key The key prior to sanitization.
|
30 |
+
*/
|
31 |
+
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
|
32 |
+
return apply_filters( 'sanitize_lingotek_locale', $locale, $raw_locale );
|
33 |
+
}
|
tests/test-action-url.php
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class ActionUrlTest
|
4 |
+
*
|
5 |
+
* @package Lingotek_Translation
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Sample test case.
|
10 |
+
*/
|
11 |
+
class ActionUrlTest extends WP_UnitTestCase {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Tests the rendering of an action url.
|
15 |
+
*
|
16 |
+
* @test
|
17 |
+
* @dataProvider actionsDataProvider
|
18 |
+
*
|
19 |
+
* @param string $url The url.
|
20 |
+
* @param string $title The title.
|
21 |
+
* @param string $expected The expected html.
|
22 |
+
*/
|
23 |
+
public function SecondaryActionIsRendered( $url, $title, $expected ) {
|
24 |
+
$action = new Lingotek_Action_Url( $url, $title );
|
25 |
+
$this->assertSame( $url, $action->getUri() );
|
26 |
+
$this->assertSame( $title, $action->getTitle() );
|
27 |
+
$this->assertXmlStringEqualsXmlString( $expected, $action->render() );
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Data provider for actions.
|
32 |
+
*
|
33 |
+
* @see ::SecondaryActionIsRendered
|
34 |
+
*/
|
35 |
+
public function actionsDataProvider() {
|
36 |
+
yield 'secondary action' => array(
|
37 |
+
'https://www.lingotek.com',
|
38 |
+
'Lingotek website',
|
39 |
+
'<li><a href="https://www.lingotek.com">Lingotek website</a></li>',
|
40 |
+
);
|
41 |
+
}
|
42 |
+
|
43 |
+
}
|