Version Description
(2022-03-01) = - ELEMENTOR: Uploading Metadata content - WP: Add 'Ready-Interim' Status - WordPress: Update the "Mailto:" link for subscription terms - ELEMENTOR: Group elementor fields in Custom Field Configuration - ELEMENTOR: Apply hooks for when elementor content is updated - ELEMENTOR: Add support for embedded content - WP: Accept the 20,000 words exceeded response - Wordpress: Transition to Ready to Download
Download this release
Release Info
Developer | sowmiya2021 |
Plugin | Lingotek Translation |
Version | 1.5.3 |
Comparing to | |
See all releases |
Code changes from version 1.5.2 to 1.5.3
- CHANGELOG.md +4 -0
- admin/actions.php +34 -1
- admin/chip-target.php +3 -3
- admin/filters-columns.php +13 -0
- css/admin.css +11 -0
- css/statuses.css +18 -0
- include/api.php +20 -2
- include/callback.php +6 -1
- include/group-post.php +106 -39
- include/group.php +16 -8
- include/metadata-elementor.php +299 -0
- js/updater.js +22 -0
- lingotek.php +2 -2
- readme.txt +13 -2
CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1 |
# Changelog
|
|
|
|
|
|
|
|
|
2 |
## [1.4.16] - 2021-07-22
|
3 |
- Merging hotfix 1.4.16 branch
|
1 |
# Changelog
|
2 |
+
|
3 |
+
## [1.5.4] - 2022-04-12
|
4 |
+
- Merging release 1.5.4 branch
|
5 |
+
|
6 |
## [1.4.16] - 2021-07-22
|
7 |
- Merging hotfix 1.4.16 branch
|
admin/actions.php
CHANGED
@@ -186,6 +186,11 @@ abstract class Lingotek_Actions {
|
|
186 |
'icon' => 'edit',
|
187 |
),
|
188 |
|
|
|
|
|
|
|
|
|
|
|
189 |
'current' => array(
|
190 |
'title' => __( 'Current', 'lingotek-translation' ),
|
191 |
'icon' => 'edit',
|
@@ -301,6 +306,15 @@ abstract class Lingotek_Actions {
|
|
301 |
esc_url( $link ),
|
302 |
$additional
|
303 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
304 |
}
|
305 |
return sprintf(
|
306 |
'<a class="lingotek-color dashicons dashicons-%s dashicons-%s-lingotek" title="%s" href="%s"%s></a>',
|
@@ -568,6 +582,16 @@ abstract class Lingotek_Actions {
|
|
568 |
)
|
569 |
);
|
570 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
571 |
} else {
|
572 |
$actions['lingotek-upload'] = $this->get_action_link(
|
573 |
array(
|
@@ -596,6 +620,15 @@ abstract class Lingotek_Actions {
|
|
596 |
);
|
597 |
}
|
598 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
599 |
//need to request translations?
|
600 |
$language = $this->get_language( $document->source );
|
601 |
$all_locales = array_flip( $this->pllm->get_languages_list( array( 'fields' => 'locale' ) ) );
|
@@ -862,7 +895,7 @@ abstract class Lingotek_Actions {
|
|
862 |
$document = $this->lgtm->get_group( $this->type, filter_input( INPUT_POST, 'id' ) );
|
863 |
if ( $document ) {
|
864 |
foreach ( $document->translations as $locale => $status ) {
|
865 |
-
if ( 'pending' === $status || 'ready' === $status || 'interim' === $status || 'current' === $status ) {
|
866 |
$document->create_translation( $locale );
|
867 |
}
|
868 |
}
|
186 |
'icon' => 'edit',
|
187 |
),
|
188 |
|
189 |
+
'ready-interim' => array(
|
190 |
+
'title' => __( 'Interim Translation Ready to be Downloaded', 'lingotek-translation' ),
|
191 |
+
'icon' => 'edit',
|
192 |
+
),
|
193 |
+
|
194 |
'current' => array(
|
195 |
'title' => __( 'Current', 'lingotek-translation' ),
|
196 |
'icon' => 'edit',
|
306 |
esc_url( $link ),
|
307 |
$additional
|
308 |
);
|
309 |
+
} elseif ( 'ready-interim' === $name) {
|
310 |
+
return sprintf(
|
311 |
+
'<a class="lingotek-ready-interim-color dashicons dashicons-%s dashicons-%s-lingotek" title="%s" href="%s"%s></a>',
|
312 |
+
self::$icons[ $name ]['icon'],
|
313 |
+
self::$icons[ $name ]['icon'],
|
314 |
+
self::$icons[ $name ]['title'],
|
315 |
+
esc_url( $link ),
|
316 |
+
$additional
|
317 |
+
);
|
318 |
}
|
319 |
return sprintf(
|
320 |
'<a class="lingotek-color dashicons dashicons-%s dashicons-%s-lingotek" title="%s" href="%s"%s></a>',
|
582 |
)
|
583 |
);
|
584 |
}
|
585 |
+
|
586 |
+
if ( $document->has_translation_status( 'ready-interim' ) ) {
|
587 |
+
$actions['lingotek-status'] = $this->get_action_link(
|
588 |
+
array(
|
589 |
+
'document_id' => $document->document_id,
|
590 |
+
'action' => 'download',
|
591 |
+
)
|
592 |
+
);
|
593 |
+
}
|
594 |
+
|
595 |
} else {
|
596 |
$actions['lingotek-upload'] = $this->get_action_link(
|
597 |
array(
|
620 |
);
|
621 |
}
|
622 |
|
623 |
+
if ( $document->has_translation_status( 'ready-interim' ) ) {
|
624 |
+
$actions['lingotek-status'] = $this->get_action_link(
|
625 |
+
array(
|
626 |
+
'document_id' => $document->document_id,
|
627 |
+
'action' => 'download',
|
628 |
+
)
|
629 |
+
);
|
630 |
+
}
|
631 |
+
|
632 |
//need to request translations?
|
633 |
$language = $this->get_language( $document->source );
|
634 |
$all_locales = array_flip( $this->pllm->get_languages_list( array( 'fields' => 'locale' ) ) );
|
895 |
$document = $this->lgtm->get_group( $this->type, filter_input( INPUT_POST, 'id' ) );
|
896 |
if ( $document ) {
|
897 |
foreach ( $document->translations as $locale => $status ) {
|
898 |
+
if ( 'pending' === $status || 'ready' === $status || 'interim' === $status || 'current' === $status || 'ready-interim' === $status ) {
|
899 |
$document->create_translation( $locale );
|
900 |
}
|
901 |
}
|
admin/chip-target.php
CHANGED
@@ -52,7 +52,7 @@ class Lingotek_Chip_Target extends Lingotek_Chip_Base {
|
|
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 );
|
@@ -104,7 +104,7 @@ class Lingotek_Chip_Target extends Lingotek_Chip_Base {
|
|
104 |
sprintf( __( 'Cancel translation', 'lingotek-translation' ), $language->locale )
|
105 |
);
|
106 |
}
|
107 |
-
if ( in_array( $status, array( 'ready'), 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 )
|
@@ -128,7 +128,7 @@ class Lingotek_Chip_Target extends Lingotek_Chip_Base {
|
|
128 |
);
|
129 |
}
|
130 |
// I'm not sure if the status is error or failed, so we consider both for now.
|
131 |
-
if ( in_array( $status, array( 'pending', 'ready', 'error', 'failed', 'current', 'interim', 'intermediate', 'edited' ), true ) ) {
|
132 |
$urls[] = new Lingotek_Action_Url(
|
133 |
$post_actions->workbench_url( $this->id, $this->document, $language->lingotek_locale ),
|
134 |
__( 'Open in Lingotek workbench', 'lingotek-translation' )
|
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', 'ready-interim' ), 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 );
|
104 |
sprintf( __( 'Cancel translation', 'lingotek-translation' ), $language->locale )
|
105 |
);
|
106 |
}
|
107 |
+
if ( in_array( $status, array( 'ready', 'ready-interim' ), 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 )
|
128 |
);
|
129 |
}
|
130 |
// I'm not sure if the status is error or failed, so we consider both for now.
|
131 |
+
if ( in_array( $status, array( 'pending', 'ready', 'error', 'failed', 'current', 'interim', 'intermediate', 'edited', 'ready-interim' ), true ) ) {
|
132 |
$urls[] = new Lingotek_Action_Url(
|
133 |
$post_actions->workbench_url( $this->id, $this->document, $language->lingotek_locale ),
|
134 |
__( 'Open in Lingotek workbench', 'lingotek-translation' )
|
admin/filters-columns.php
CHANGED
@@ -63,6 +63,7 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
|
|
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 ) {
|
@@ -120,6 +121,18 @@ class Lingotek_Filters_Columns extends PLL_Admin_Filters_Columns {
|
|
120 |
}//end if
|
121 |
}
|
122 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
123 |
private function print_patch_error() {
|
124 |
$lingotek_log_errors = get_option( 'lingotek_log_errors' );
|
125 |
if ( empty( $lingotek_log_errors['patch_document_error'] ) ) {
|
63 |
}
|
64 |
$this->print_patch_error();
|
65 |
$this->print_cancel_error();
|
66 |
+
$this->print_word_limit_error();
|
67 |
$columns ['lingotek_source'] = __( 'Lingotek source', 'lingotek-translation' );
|
68 |
$columns ['lingotek_targets'] = __( 'Lingotek translations', 'lingotek-translation' );
|
69 |
foreach ( $this->model->get_languages_list() as $language ) {
|
121 |
}//end if
|
122 |
}
|
123 |
|
124 |
+
private function print_word_limit_error() {
|
125 |
+
$lingotek_log_errors = get_option( 'lingotek_log_errors', [] );
|
126 |
+
if ( !isset( $lingotek_log_errors['word_limit_error'] ) && empty( $lingotek_log_errors['word_limit_error'] ) ) {
|
127 |
+
return;
|
128 |
+
}
|
129 |
+
printf( '<div class="notice notice-error is-dismissible"><p>%s</p></div>',
|
130 |
+
__( 'Processed word limit exceeded. Please contact your local administrator or Lingotek Client Success <a href="mailto:sales@lingotek.com">(sales@lingotek.com)</a> for assistance.', 'lingotek-translation' ),
|
131 |
+
);
|
132 |
+
unset( $lingotek_log_errors['word_limit_error'] );
|
133 |
+
update_option( 'lingotek_log_errors', $lingotek_log_errors, false );
|
134 |
+
}
|
135 |
+
|
136 |
private function print_patch_error() {
|
137 |
$lingotek_log_errors = get_option( 'lingotek_log_errors' );
|
138 |
if ( empty( $lingotek_log_errors['patch_document_error'] ) ) {
|
css/admin.css
CHANGED
@@ -56,6 +56,17 @@ a.lingotek-interim-color:hover {
|
|
56 |
color: #dbdbdb;
|
57 |
}
|
58 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
.lingotek-failed-color {
|
60 |
color: #b71c1c;
|
61 |
}
|
56 |
color: #dbdbdb;
|
57 |
}
|
58 |
|
59 |
+
.lingotek-ready-interim-color {
|
60 |
+
color: #b0b0b0;
|
61 |
+
}
|
62 |
+
a.lingotek-ready-interim-color {
|
63 |
+
color: #b0b0b0;
|
64 |
+
}
|
65 |
+
|
66 |
+
a.lingotek-ready-interim-color:hover {
|
67 |
+
color: #dbdbdb;
|
68 |
+
}
|
69 |
+
|
70 |
.lingotek-failed-color {
|
71 |
color: #b71c1c;
|
72 |
}
|
css/statuses.css
CHANGED
@@ -171,6 +171,24 @@ a.language-icon {
|
|
171 |
color: #43a047;
|
172 |
}
|
173 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
.language-icon.target-untracked {
|
175 |
background-color:#999999;
|
176 |
border: 1px solid #999999;
|
171 |
color: #43a047;
|
172 |
}
|
173 |
|
174 |
+
.language-icon.target-ready-interim {
|
175 |
+
background-color: #ffffff;
|
176 |
+
border: 1px solid #2196f3;
|
177 |
+
color: #2196f3;
|
178 |
+
}
|
179 |
+
|
180 |
+
.language-icon.target-ready-interim a {
|
181 |
+
color: #2196f3;
|
182 |
+
}
|
183 |
+
|
184 |
+
.language-icon.target-ready-interim a:hover {
|
185 |
+
color: #2196f3;
|
186 |
+
}
|
187 |
+
|
188 |
+
.language-icon.target-ready-interim:hover {
|
189 |
+
color: #2196f3;
|
190 |
+
}
|
191 |
+
|
192 |
.language-icon.target-untracked {
|
193 |
background-color:#999999;
|
194 |
border: 1px solid #999999;
|
include/api.php
CHANGED
@@ -163,6 +163,10 @@ class Lingotek_API extends Lingotek_HTTP {
|
|
163 |
$this->get_error_message_from_response( $response ) : 'No error message set by Lingotek';
|
164 |
$lingotek_log_errors['patch_document_error'] = __( "Payment required. Message: $error_message", 'lingotek-translation' );
|
165 |
update_option( 'lingotek_log_errors', $lingotek_log_errors, false );
|
|
|
|
|
|
|
|
|
166 |
}
|
167 |
return false;
|
168 |
}
|
@@ -198,6 +202,12 @@ class Lingotek_API extends Lingotek_HTTP {
|
|
198 |
$document->save();
|
199 |
return $this->patch_document( $body->next_document_id, $unformatted_args, $wp_id );
|
200 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
201 |
|
202 |
// We will handle patch errors separately. All we want to do is return the result of the current patch request to the user if payment is required
|
203 |
// (although in theory this will never happen, because the WP model is document count based, and it will not allow them to upload documents until
|
@@ -286,7 +296,7 @@ class Lingotek_API extends Lingotek_HTTP {
|
|
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() );
|
@@ -494,7 +504,7 @@ class Lingotek_API extends Lingotek_HTTP {
|
|
494 |
$response = $this->get( $this->api_url . "/document/$doc_id/translation/$locale" );
|
495 |
if ( ! is_wp_error( $response ) && 200 == wp_remote_retrieve_response_code( $response ) ) {
|
496 |
$b = json_decode( wp_remote_retrieve_body( $response ) );
|
497 |
-
$status = $b->properties->
|
498 |
}
|
499 |
|
500 |
$this->log_error_on_response_failure(
|
@@ -526,6 +536,8 @@ class Lingotek_API extends Lingotek_HTTP {
|
|
526 |
$translations[ $e->properties->locale_code ] = array(
|
527 |
'progress' => $e->properties->status,
|
528 |
'percent_complete' => $e->properties->percent_complete,
|
|
|
|
|
529 |
);
|
530 |
}
|
531 |
}
|
@@ -755,6 +767,12 @@ class Lingotek_API extends Lingotek_HTTP {
|
|
755 |
$document->source_failed();
|
756 |
return false;
|
757 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
758 |
if ( 410 === $status_code || 404 === $status_code ) {
|
759 |
// WP hooks automatically check source status so this might not get called
|
760 |
$polylang_targets = array_keys( $document->translations );
|
163 |
$this->get_error_message_from_response( $response ) : 'No error message set by Lingotek';
|
164 |
$lingotek_log_errors['patch_document_error'] = __( "Payment required. Message: $error_message", 'lingotek-translation' );
|
165 |
update_option( 'lingotek_log_errors', $lingotek_log_errors, false );
|
166 |
+
} elseif ( $code == 429 ) {
|
167 |
+
$lingotek_log_errors = get_option( 'lingotek_log_errors', [] );
|
168 |
+
$lingotek_log_errors['word_limit_error'] = true;
|
169 |
+
update_option( 'lingotek_log_errors', $lingotek_log_errors, false );
|
170 |
}
|
171 |
return false;
|
172 |
}
|
202 |
$document->save();
|
203 |
return $this->patch_document( $body->next_document_id, $unformatted_args, $wp_id );
|
204 |
}
|
205 |
+
if ( $status_code == 429 ) {
|
206 |
+
$lingotek_log_errors = get_option( 'lingotek_log_errors', [] );
|
207 |
+
$lingotek_log_errors['word_limit_error'] = true;
|
208 |
+
update_option( 'lingotek_log_errors', $lingotek_log_errors, false );
|
209 |
+
return false;
|
210 |
+
}
|
211 |
|
212 |
// We will handle patch errors separately. All we want to do is return the result of the current patch request to the user if payment is required
|
213 |
// (although in theory this will never happen, because the WP model is document count based, and it will not allow them to upload documents until
|
296 |
|
297 |
private function update_patch_error_message( $response, $status_code, $title ) {
|
298 |
// Do not inform user if call was successful.
|
299 |
+
if ( $status_code == 202 || $status_code == 410 || $status_code == 404 || $status_code == 429 ) {
|
300 |
return;
|
301 |
}
|
302 |
$lingotek_log_errors = get_option( 'lingotek_log_errors', array() );
|
504 |
$response = $this->get( $this->api_url . "/document/$doc_id/translation/$locale" );
|
505 |
if ( ! is_wp_error( $response ) && 200 == wp_remote_retrieve_response_code( $response ) ) {
|
506 |
$b = json_decode( wp_remote_retrieve_body( $response ) );
|
507 |
+
$status = $b->properties->ready_to_download;
|
508 |
}
|
509 |
|
510 |
$this->log_error_on_response_failure(
|
536 |
$translations[ $e->properties->locale_code ] = array(
|
537 |
'progress' => $e->properties->status,
|
538 |
'percent_complete' => $e->properties->percent_complete,
|
539 |
+
'ready_to_download' => $e->properties->ready_to_download
|
540 |
+
|
541 |
);
|
542 |
}
|
543 |
}
|
767 |
$document->source_failed();
|
768 |
return false;
|
769 |
}
|
770 |
+
if ( 429 === $status_code ) {
|
771 |
+
$lingotek_log_errors = get_option( 'lingotek_log_errors', [] );
|
772 |
+
$lingotek_log_errors['word_limit_error'] = true;
|
773 |
+
update_option( 'lingotek_log_errors', $lingotek_log_errors, false );
|
774 |
+
return false;
|
775 |
+
}
|
776 |
if ( 410 === $status_code || 404 === $status_code ) {
|
777 |
// WP hooks automatically check source status so this might not get called
|
778 |
$polylang_targets = array_keys( $document->translations );
|
include/callback.php
CHANGED
@@ -123,7 +123,12 @@ class Lingotek_Callback {
|
|
123 |
$polylang->sync = new PLL_Admin_Sync( $polylang );
|
124 |
// Map to WordPress locale.
|
125 |
$locale = Lingotek::map_to_wp_locale( $_GET['locale'] );
|
126 |
-
|
|
|
|
|
|
|
|
|
|
|
127 |
}//end if
|
128 |
}
|
129 |
|
123 |
$polylang->sync = new PLL_Admin_Sync( $polylang );
|
124 |
// Map to WordPress locale.
|
125 |
$locale = Lingotek::map_to_wp_locale( $_GET['locale'] );
|
126 |
+
if ($type == 'download_interim_translation') {
|
127 |
+
$document->is_automatic_download( $locale ) ? $document->create_translation( $locale, true, $type ) : $document->translation_ready_interim( $locale );
|
128 |
+
}
|
129 |
+
else {
|
130 |
+
$document->is_automatic_download( $locale ) ? $document->create_translation( $locale, true, $type ) : $document->translation_ready( $locale );
|
131 |
+
}
|
132 |
}//end if
|
133 |
}
|
134 |
|
include/group-post.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
|
4 |
* Translations groups for posts, pages and custom post types
|
5 |
*
|
6 |
* @since 0.2
|
@@ -9,12 +9,12 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
9 |
|
10 |
// Preference constant used for downloaded translations.
|
11 |
const SAME_AS_SOURCE = 'SAME_AS_SOURCE';
|
12 |
-
|
13 |
* set a translation term for an object
|
14 |
*
|
15 |
* @since 0.2
|
16 |
*
|
17 |
-
* @param int
|
18 |
* @param object $language
|
19 |
* @param string $document_id translation term name (Lingotek document id)
|
20 |
*/
|
@@ -33,7 +33,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
33 |
self::_create( $object_id, $document_id, $data, 'post_translations' );
|
34 |
}
|
35 |
|
36 |
-
|
37 |
* returns content type fields
|
38 |
*
|
39 |
* @since 0.2
|
@@ -69,7 +69,11 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
69 |
if ( is_array( $custom_fields ) && ! empty( $custom_fields ) ) {
|
70 |
foreach ( $custom_fields as $cf => $setting ) {
|
71 |
if ( 'translate' == $setting ) {
|
72 |
-
|
|
|
|
|
|
|
|
|
73 |
}
|
74 |
}
|
75 |
}
|
@@ -79,14 +83,14 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
79 |
return apply_filters( 'lingotek_post_content_type_fields', $arr, $post_type );
|
80 |
}
|
81 |
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
public static function get_custom_fields_from_wpml() {
|
91 |
$wpml_config = PLL_WPML_Config::instance();
|
92 |
$arr = array();
|
@@ -103,7 +107,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
103 |
return apply_filters( 'lingotek_post_content_type_fields_from_wpml', $arr );
|
104 |
}
|
105 |
|
106 |
-
|
107 |
* returns meta (custom) fields from the wp-postmeta database table
|
108 |
*
|
109 |
* @since 0.2
|
@@ -111,11 +115,12 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
111 |
* @return array
|
112 |
*/
|
113 |
public static function get_custom_fields_from_wp_postmeta( $post_ID = null ) {
|
114 |
-
$all_acf_fields
|
115 |
-
$
|
116 |
-
$
|
117 |
-
$
|
118 |
-
$
|
|
|
119 |
|
120 |
if ( $post_ID ) {
|
121 |
$p = get_post( $post_ID );
|
@@ -159,16 +164,25 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
159 |
if ( in_array( $meta['meta_key'], $meta_black_list ) || in_array( $meta['meta_key'], $keys ) ) {
|
160 |
unset( $metadata[ $key ] );
|
161 |
}
|
162 |
-
|
|
|
|
|
|
|
|
|
|
|
163 |
}
|
164 |
$arr = array_merge( $arr, $metadata );
|
165 |
}
|
166 |
$arr = array_merge( $arr, $all_acf_fields );
|
|
|
|
|
|
|
|
|
167 |
// allow plugins to modify the fields to translate
|
168 |
return apply_filters( 'lingotek_post_custom_fields', $arr );
|
169 |
}
|
170 |
|
171 |
-
|
172 |
* tests whether a meta belongs to the Advanced Custom Fields plugin
|
173 |
*
|
174 |
* @since 0.2
|
@@ -179,7 +193,36 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
179 |
return ( ( substr( $key, 0, strlen( '_' ) ) === '_' ) && ( substr( $value, 0, strlen( 'field_' ) ) === 'field_' ) ) ? true : false;
|
180 |
}
|
181 |
|
182 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
183 |
* updates meta (custom) fields values in the lingotek_custom_fields option
|
184 |
*
|
185 |
* @since 0.2
|
@@ -228,7 +271,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
228 |
update_option( 'lingotek_custom_fields', $custom_fields, false );
|
229 |
}
|
230 |
|
231 |
-
|
232 |
* returns cached meta (custom) fields values in the lingotek_custom_fields option
|
233 |
*
|
234 |
* @since 0.2
|
@@ -255,7 +298,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
255 |
return $items;
|
256 |
}
|
257 |
|
258 |
-
|
259 |
* returns the content to translate
|
260 |
*
|
261 |
* @since 0.2
|
@@ -275,7 +318,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
275 |
// check for advanced custom fields meta expects a string
|
276 |
// so if array, check first item
|
277 |
$value = is_array( $value ) ? current( $value ) : $value;
|
278 |
-
if ( self::is_advanced_custom_fields_meta( $meta, $value ) || in_array( $meta, $meta_black_list ) ) {
|
279 |
continue;
|
280 |
}
|
281 |
// Get all metas in array format
|
@@ -289,7 +332,16 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
289 |
if ( isset( $fields['metas'][ $acf_empty_string ] ) && function_exists( 'acf_get_field_groups' ) && function_exists( 'acf_get_fields' ) ) {
|
290 |
$arr['metas'][ $acf_empty_string ] = get_post_meta( $post->ID, $acf_empty_string, true );
|
291 |
}
|
292 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
293 |
// send slug for translation only if it has been modified
|
294 |
elseif ( 'post_name' == $key && empty( $content_types[ $post->post_type ]['fields'][ $key ] ) ) {
|
295 |
// Default slug created by WordPress.
|
@@ -310,7 +362,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
310 |
return $valid;
|
311 |
}
|
312 |
|
313 |
-
|
314 |
* requests translations to Lingotek TMS
|
315 |
*
|
316 |
* @since 0.1
|
@@ -322,7 +374,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
322 |
}
|
323 |
}
|
324 |
|
325 |
-
|
326 |
* create a translation downloaded from Lingotek TMS
|
327 |
*
|
328 |
* @since 0.1
|
@@ -334,10 +386,10 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
334 |
// Removes content sanitization so YouTube videos, links, etc don't get removed when inserting translations
|
335 |
remove_filter( 'content_save_pre', 'wp_filter_post_kses' );
|
336 |
remove_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' );
|
337 |
-
$client
|
338 |
-
$
|
339 |
|
340 |
-
if ( $
|
341 |
return;
|
342 |
}
|
343 |
|
@@ -376,7 +428,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
376 |
self::copy_or_ignore_metas( $post->ID, $tr_id );
|
377 |
|
378 |
wp_update_post( $tr_post );
|
379 |
-
if ( $
|
380 |
$this->safe_translation_status_update( $locale, 'interim' );
|
381 |
} else {
|
382 |
$this->safe_translation_status_update( $locale, 'current' );
|
@@ -384,7 +436,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
384 |
}
|
385 |
|
386 |
// create new translation
|
387 |
-
elseif ( ( $this->translations[ $locale ] == 'ready' || $this->translations[ $locale ] == 'pending' ) || $automatic ) {
|
388 |
$content_type_options = get_option( 'lingotek_content_type' );
|
389 |
if ( ! isset( $content_type_options[ $post->post_type ]['fields']['post_name'] ) ) {
|
390 |
// Forces the creation of a new default slug if not translated by Lingotek.
|
@@ -410,7 +462,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
410 |
$tr_lang = $this->pllm->get_language( $locale );
|
411 |
PLL()->model->post->set_language( $tr_id, $tr_lang );
|
412 |
$this->safe_translation_status_update( $locale, 'current', array( $tr_lang->slug => $tr_id ) );
|
413 |
-
if ( $
|
414 |
$this->safe_translation_status_update( $locale, 'interim' );
|
415 |
}
|
416 |
wp_set_object_terms( $tr_id, $this->term_id, 'post_translations' );
|
@@ -461,7 +513,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
461 |
empty( $trimmed_excerpt );
|
462 |
}
|
463 |
|
464 |
-
|
465 |
* copies source meta strings to translations or deletes meta if set to ignore
|
466 |
*
|
467 |
* @since 1.0.9
|
@@ -474,6 +526,14 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
474 |
foreach ( $post_custom_fields as $key => $source_meta ) {
|
475 |
// Set to blank string to ignore if no lingotek setting has been set.
|
476 |
$setting = isset( $custom_fields[ $key ] ) ? $custom_fields[ $key ] : '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
477 |
if ( 'copy' === $setting || 'hide-copy' === $setting ) {
|
478 |
$source_meta = current( get_post_meta( $post_id, $key ) );
|
479 |
update_post_meta( $tr_id, $key, $source_meta );
|
@@ -483,7 +543,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
483 |
}
|
484 |
}
|
485 |
|
486 |
-
|
487 |
* inserts translated meta values into translations
|
488 |
*
|
489 |
* @since 1.0.9
|
@@ -491,12 +551,19 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
491 |
protected static function copy_translated_metas( $translation_metas, $tr_id ) {
|
492 |
if ( ! empty( $translation_metas ) ) {
|
493 |
foreach ( $translation_metas as $key => $meta ) {
|
|
|
|
|
|
|
494 |
update_post_meta( $tr_id, $key, $meta );
|
495 |
}
|
|
|
|
|
|
|
|
|
496 |
}
|
497 |
}
|
498 |
|
499 |
-
|
500 |
* checks if content should be automatically uploaded
|
501 |
*
|
502 |
* @since 0.2
|
@@ -507,7 +574,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
507 |
return 'automatic' == Lingotek_Model::get_profile_option( 'upload', get_post_type( $this->source ), $this->get_source_language(), false, $this->source ) && parent::is_automatic_upload();
|
508 |
}
|
509 |
|
510 |
-
|
511 |
* get the the language of the source post
|
512 |
*
|
513 |
* @since 0.2
|
@@ -518,7 +585,7 @@ class Lingotek_Group_Post extends Lingotek_Group {
|
|
518 |
return PLL()->model->post->get_language( $this->source );
|
519 |
}
|
520 |
|
521 |
-
|
522 |
* creates hash for lingotek_hash term
|
523 |
*
|
524 |
* @since 1.0.9
|
1 |
<?php
|
2 |
|
3 |
+
/**
|
4 |
* Translations groups for posts, pages and custom post types
|
5 |
*
|
6 |
* @since 0.2
|
9 |
|
10 |
// Preference constant used for downloaded translations.
|
11 |
const SAME_AS_SOURCE = 'SAME_AS_SOURCE';
|
12 |
+
/**
|
13 |
* set a translation term for an object
|
14 |
*
|
15 |
* @since 0.2
|
16 |
*
|
17 |
+
* @param int $object_id post id
|
18 |
* @param object $language
|
19 |
* @param string $document_id translation term name (Lingotek document id)
|
20 |
*/
|
33 |
self::_create( $object_id, $document_id, $data, 'post_translations' );
|
34 |
}
|
35 |
|
36 |
+
/**
|
37 |
* returns content type fields
|
38 |
*
|
39 |
* @since 0.2
|
69 |
if ( is_array( $custom_fields ) && ! empty( $custom_fields ) ) {
|
70 |
foreach ( $custom_fields as $cf => $setting ) {
|
71 |
if ( 'translate' == $setting ) {
|
72 |
+
if ( $cf === Lingotek_Metadata_Elementor::$elementor_content ) {
|
73 |
+
$arr['metas'][ Lingotek_Metadata_Elementor::$elementor_data ] = Lingotek_Metadata_Elementor::$elementor_data;
|
74 |
+
} else {
|
75 |
+
$arr['metas'][ $cf ] = $cf;
|
76 |
+
}
|
77 |
}
|
78 |
}
|
79 |
}
|
83 |
return apply_filters( 'lingotek_post_content_type_fields', $arr, $post_type );
|
84 |
}
|
85 |
|
86 |
+
/**
|
87 |
+
* returns custom fields from the wpml-config.xml file
|
88 |
+
*
|
89 |
+
* @since 0.2
|
90 |
+
*
|
91 |
+
* @param string $post_type
|
92 |
+
* @return array
|
93 |
+
*/
|
94 |
public static function get_custom_fields_from_wpml() {
|
95 |
$wpml_config = PLL_WPML_Config::instance();
|
96 |
$arr = array();
|
107 |
return apply_filters( 'lingotek_post_content_type_fields_from_wpml', $arr );
|
108 |
}
|
109 |
|
110 |
+
/**
|
111 |
* returns meta (custom) fields from the wp-postmeta database table
|
112 |
*
|
113 |
* @since 0.2
|
115 |
* @return array
|
116 |
*/
|
117 |
public static function get_custom_fields_from_wp_postmeta( $post_ID = null ) {
|
118 |
+
$all_acf_fields = array();
|
119 |
+
$elementor_field_group = array();
|
120 |
+
$custom_fields = get_option( 'lingotek_custom_fields', array() );
|
121 |
+
$meta_black_list = array( '_encloseme', '_edit_last', '_edit_lock', '_wp_trash_meta_status', '_wp_trash_meta_time' );
|
122 |
+
$arr = array();
|
123 |
+
$keys = array();
|
124 |
|
125 |
if ( $post_ID ) {
|
126 |
$p = get_post( $post_ID );
|
164 |
if ( in_array( $meta['meta_key'], $meta_black_list ) || in_array( $meta['meta_key'], $keys ) ) {
|
165 |
unset( $metadata[ $key ] );
|
166 |
}
|
167 |
+
if ( self::is_elementor_meta( $meta['meta_key'] ) ) {
|
168 |
+
$elementor_field_group[ $meta['meta_key'] ] = $meta['meta_key'];
|
169 |
+
// Remove elementor field
|
170 |
+
unset( $metadata [ $key ] );
|
171 |
+
}
|
172 |
+
$keys[ $meta['meta_key'] ] = $meta['meta_key'];
|
173 |
}
|
174 |
$arr = array_merge( $arr, $metadata );
|
175 |
}
|
176 |
$arr = array_merge( $arr, $all_acf_fields );
|
177 |
+
if ( is_plugin_active( 'elementor/elementor.php' ) && ! empty( $elementor_field_group ) ) {
|
178 |
+
// Set Lingotek elementor field
|
179 |
+
self::group_elementor_fields( $arr, $elementor_field_group );
|
180 |
+
}
|
181 |
// allow plugins to modify the fields to translate
|
182 |
return apply_filters( 'lingotek_post_custom_fields', $arr );
|
183 |
}
|
184 |
|
185 |
+
/**
|
186 |
* tests whether a meta belongs to the Advanced Custom Fields plugin
|
187 |
*
|
188 |
* @since 0.2
|
193 |
return ( ( substr( $key, 0, strlen( '_' ) ) === '_' ) && ( substr( $value, 0, strlen( 'field_' ) ) === 'field_' ) ) ? true : false;
|
194 |
}
|
195 |
|
196 |
+
/**
|
197 |
+
* tests whether a meta belongs to the Elementor plugin
|
198 |
+
*
|
199 |
+
* @since 1.5.1
|
200 |
+
*
|
201 |
+
* @return bool
|
202 |
+
*/
|
203 |
+
protected static function is_elementor_meta( $key ) {
|
204 |
+
return ( is_string( $key ) && 0 === strpos( $key, '_elementor' ) ) ? true : false;
|
205 |
+
}
|
206 |
+
|
207 |
+
/**
|
208 |
+
* Checks if certain elementor fields exist, then groups all elementor metadata keys under one meta key
|
209 |
+
*
|
210 |
+
* @since 1.5.3
|
211 |
+
*
|
212 |
+
* @param array $metas The array of meta keys that users can translate.
|
213 |
+
* @param array $elementor_field_group The array of elementor metadata found in the posts
|
214 |
+
*/
|
215 |
+
public static function group_elementor_fields( &$metas, $elementor_field_group ) {
|
216 |
+
// Create Lingotek elementor meta field if posts exist with elementor content
|
217 |
+
if ( in_array( Lingotek_Metadata_Elementor::$elementor_data, $elementor_field_group ) && in_array( Lingotek_Metadata_Elementor::$elementor_edit_mode, $elementor_field_group ) ) {
|
218 |
+
$metas[] = array(
|
219 |
+
'meta_key' => Lingotek_Metadata_Elementor::$elementor_content,
|
220 |
+
'meta_value' => $elementor_field_group,
|
221 |
+
);
|
222 |
+
}
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
* updates meta (custom) fields values in the lingotek_custom_fields option
|
227 |
*
|
228 |
* @since 0.2
|
271 |
update_option( 'lingotek_custom_fields', $custom_fields, false );
|
272 |
}
|
273 |
|
274 |
+
/**
|
275 |
* returns cached meta (custom) fields values in the lingotek_custom_fields option
|
276 |
*
|
277 |
* @since 0.2
|
298 |
return $items;
|
299 |
}
|
300 |
|
301 |
+
/**
|
302 |
* returns the content to translate
|
303 |
*
|
304 |
* @since 0.2
|
318 |
// check for advanced custom fields meta expects a string
|
319 |
// so if array, check first item
|
320 |
$value = is_array( $value ) ? current( $value ) : $value;
|
321 |
+
if ( self::is_advanced_custom_fields_meta( $meta, $value ) || self::is_elementor_meta( $meta ) || in_array( $meta, $meta_black_list ) ) {
|
322 |
continue;
|
323 |
}
|
324 |
// Get all metas in array format
|
332 |
if ( isset( $fields['metas'][ $acf_empty_string ] ) && function_exists( 'acf_get_field_groups' ) && function_exists( 'acf_get_fields' ) ) {
|
333 |
$arr['metas'][ $acf_empty_string ] = get_post_meta( $post->ID, $acf_empty_string, true );
|
334 |
}
|
335 |
+
|
336 |
+
// Check if elementor data exists in post
|
337 |
+
if ( isset( $fields['metas'][ Lingotek_Metadata_Elementor::$elementor_data ] ) && 'builder' === get_post_meta( $post->ID, Lingotek_Metadata_Elementor::$elementor_edit_mode, true ) ) {
|
338 |
+
$arr['metas'][ Lingotek_Metadata_Elementor::$elementor_data ] = Lingotek_Metadata_Elementor::get_post_metadata_content( $post->ID );
|
339 |
+
// We need to keep the original meta string with the translation
|
340 |
+
$arr['metas'][ Lingotek_Metadata_Elementor::$elementor_data . '_original' ] = get_post_meta( $post->ID, Lingotek_Metadata_Elementor::$elementor_data, true );
|
341 |
+
// Since the elementor data overwrites post_content this prevents duplicating the content sent up for translation.
|
342 |
+
$arr['post']['post_content'] = '';
|
343 |
+
}
|
344 |
+
}//end if
|
345 |
// send slug for translation only if it has been modified
|
346 |
elseif ( 'post_name' == $key && empty( $content_types[ $post->post_type ]['fields'][ $key ] ) ) {
|
347 |
// Default slug created by WordPress.
|
362 |
return $valid;
|
363 |
}
|
364 |
|
365 |
+
/**
|
366 |
* requests translations to Lingotek TMS
|
367 |
*
|
368 |
* @since 0.1
|
374 |
}
|
375 |
}
|
376 |
|
377 |
+
/**
|
378 |
* create a translation downloaded from Lingotek TMS
|
379 |
*
|
380 |
* @since 0.1
|
386 |
// Removes content sanitization so YouTube videos, links, etc don't get removed when inserting translations
|
387 |
remove_filter( 'content_save_pre', 'wp_filter_post_kses' );
|
388 |
remove_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' );
|
389 |
+
$client = new Lingotek_API();
|
390 |
+
$ready_to_download = $client->get_translation_status( $this->document_id, $locale );
|
391 |
|
392 |
+
if ( $ready_to_download === -1 ) {
|
393 |
return;
|
394 |
}
|
395 |
|
428 |
self::copy_or_ignore_metas( $post->ID, $tr_id );
|
429 |
|
430 |
wp_update_post( $tr_post );
|
431 |
+
if ( ! $ready_to_download ) {
|
432 |
$this->safe_translation_status_update( $locale, 'interim' );
|
433 |
} else {
|
434 |
$this->safe_translation_status_update( $locale, 'current' );
|
436 |
}
|
437 |
|
438 |
// create new translation
|
439 |
+
elseif ( ( $this->translations[ $locale ] == 'ready' || $this->translations[ $locale ] == 'pending' ) || $automatic || $this->translations[ $locale ] == 'ready-interim' ) {
|
440 |
$content_type_options = get_option( 'lingotek_content_type' );
|
441 |
if ( ! isset( $content_type_options[ $post->post_type ]['fields']['post_name'] ) ) {
|
442 |
// Forces the creation of a new default slug if not translated by Lingotek.
|
462 |
$tr_lang = $this->pllm->get_language( $locale );
|
463 |
PLL()->model->post->set_language( $tr_id, $tr_lang );
|
464 |
$this->safe_translation_status_update( $locale, 'current', array( $tr_lang->slug => $tr_id ) );
|
465 |
+
if ( ! $ready_to_download ) {
|
466 |
$this->safe_translation_status_update( $locale, 'interim' );
|
467 |
}
|
468 |
wp_set_object_terms( $tr_id, $this->term_id, 'post_translations' );
|
513 |
empty( $trimmed_excerpt );
|
514 |
}
|
515 |
|
516 |
+
/**
|
517 |
* copies source meta strings to translations or deletes meta if set to ignore
|
518 |
*
|
519 |
* @since 1.0.9
|
526 |
foreach ( $post_custom_fields as $key => $source_meta ) {
|
527 |
// Set to blank string to ignore if no lingotek setting has been set.
|
528 |
$setting = isset( $custom_fields[ $key ] ) ? $custom_fields[ $key ] : '';
|
529 |
+
if ( self::is_elementor_meta( $key ) ) {
|
530 |
+
// Use custom lingotek elementor field
|
531 |
+
$setting = isset( $custom_fields [ Lingotek_Metadata_Elementor::$elementor_content ] ) ? $custom_fields[ Lingotek_Metadata_Elementor::$elementor_content ] : '';
|
532 |
+
// If the setting is translate but key is not elementor data, set to copy
|
533 |
+
if ( $setting === 'translate' && $key !== Lingotek_Metadata_Elementor::$elementor_data ) {
|
534 |
+
$setting = 'copy';
|
535 |
+
}
|
536 |
+
}
|
537 |
if ( 'copy' === $setting || 'hide-copy' === $setting ) {
|
538 |
$source_meta = current( get_post_meta( $post_id, $key ) );
|
539 |
update_post_meta( $tr_id, $key, $source_meta );
|
543 |
}
|
544 |
}
|
545 |
|
546 |
+
/**
|
547 |
* inserts translated meta values into translations
|
548 |
*
|
549 |
* @since 1.0.9
|
551 |
protected static function copy_translated_metas( $translation_metas, $tr_id ) {
|
552 |
if ( ! empty( $translation_metas ) ) {
|
553 |
foreach ( $translation_metas as $key => $meta ) {
|
554 |
+
if ( $key === Lingotek_Metadata_Elementor::$elementor_data || $key === Lingotek_Metadata_Elementor::$elementor_data . '_original' ) {
|
555 |
+
continue;
|
556 |
+
}
|
557 |
update_post_meta( $tr_id, $key, $meta );
|
558 |
}
|
559 |
+
|
560 |
+
if ( isset( $translation_metas[ Lingotek_Metadata_Elementor::$elementor_data ], $translation_metas[ Lingotek_Metadata_Elementor::$elementor_data . '_original' ] ) ) {
|
561 |
+
Lingotek_Metadata_Elementor::set_post_metadata_content( $tr_id, $translation_metas[ Lingotek_Metadata_Elementor::$elementor_data . '_original' ], $translation_metas[ Lingotek_Metadata_Elementor::$elementor_data ] );
|
562 |
+
}
|
563 |
}
|
564 |
}
|
565 |
|
566 |
+
/**
|
567 |
* checks if content should be automatically uploaded
|
568 |
*
|
569 |
* @since 0.2
|
574 |
return 'automatic' == Lingotek_Model::get_profile_option( 'upload', get_post_type( $this->source ), $this->get_source_language(), false, $this->source ) && parent::is_automatic_upload();
|
575 |
}
|
576 |
|
577 |
+
/**
|
578 |
* get the the language of the source post
|
579 |
*
|
580 |
* @since 0.2
|
585 |
return PLL()->model->post->get_language( $this->source );
|
586 |
}
|
587 |
|
588 |
+
/**
|
589 |
* creates hash for lingotek_hash term
|
590 |
*
|
591 |
* @since 1.0.9
|
include/group.php
CHANGED
@@ -362,15 +362,13 @@ abstract class Lingotek_Group {
|
|
362 |
}
|
363 |
$wp_locale = $lingotek_locale_to_pll_locale[ $lingotek_locale ];
|
364 |
|
365 |
-
if (
|
366 |
-
|
367 |
-
|
368 |
-
} else {
|
369 |
-
$this->translations[ $wp_locale ] = 'pending';
|
370 |
-
}
|
371 |
-
} elseif ( $this->translations[ $wp_locale ] === 'interim' && $locale_status['percent_complete'] === 100 ) {
|
372 |
$this->translations[ $wp_locale ] = 'ready';
|
373 |
-
} elseif ( (
|
|
|
|
|
374 |
$this->translations[ $wp_locale ] = 'ready';
|
375 |
}
|
376 |
}
|
@@ -399,6 +397,16 @@ abstract class Lingotek_Group {
|
|
399 |
$this->safe_translation_status_update( $locale, 'ready' );
|
400 |
}
|
401 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
402 |
/**
|
403 |
* attempts to create all translations from an object
|
404 |
*
|
362 |
}
|
363 |
$wp_locale = $lingotek_locale_to_pll_locale[ $lingotek_locale ];
|
364 |
|
365 |
+
if ( !$locale_status['ready_to_download'] && ! in_array( $this->translations[ $wp_locale ], array( 'interim', 'ready-interim' ) ) ) {
|
366 |
+
$this->translations[ $wp_locale ] = 'pending';
|
367 |
+
} elseif ( in_array( $this->translations[ $wp_locale ], array( 'interim', 'ready-interim' ) ) && $locale_status['ready_to_download'] ) {
|
|
|
|
|
|
|
|
|
368 |
$this->translations[ $wp_locale ] = 'ready';
|
369 |
+
} elseif ( in_array( $this->translations[ $wp_locale ], array( 'interim', 'ready-interim' ) ) && !$locale_status['ready_to_download'] ) {
|
370 |
+
$this->translations[ $wp_locale ] = $this->translations[ $wp_locale ];
|
371 |
+
} elseif ( ( ! isset( $this->translations[ $wp_locale ] ) ) || ( $this->translations[ $wp_locale ] !== 'current' ) && ! in_array( $this->translations[ $wp_locale ], array( 'interim', 'ready-interim' ) ) ) {
|
372 |
$this->translations[ $wp_locale ] = 'ready';
|
373 |
}
|
374 |
}
|
397 |
$this->safe_translation_status_update( $locale, 'ready' );
|
398 |
}
|
399 |
|
400 |
+
/**
|
401 |
+
* sets translation status to interim
|
402 |
+
*
|
403 |
+
* @since 0.1
|
404 |
+
* @uses Lingotek_Group::safe_translation_status_update() as the status can be automatically set by the TMS callback
|
405 |
+
*/
|
406 |
+
public function translation_ready_interim( $locale ) {
|
407 |
+
$this->safe_translation_status_update( $locale, 'ready-interim' );
|
408 |
+
}
|
409 |
+
|
410 |
/**
|
411 |
* attempts to create all translations from an object
|
412 |
*
|
include/metadata-elementor.php
ADDED
@@ -0,0 +1,299 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Special processing for Elementor metadata content
|
4 |
+
*
|
5 |
+
* @since 1.5.3
|
6 |
+
*/
|
7 |
+
class Lingotek_Metadata_Elementor {
|
8 |
+
/**
|
9 |
+
* Reusable variable of elementor data meta key
|
10 |
+
*
|
11 |
+
* @var string
|
12 |
+
*/
|
13 |
+
public static $elementor_data = '_elementor_data';
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Reusable variable of elementor edit mode meta key. Determines if the elementor data should be applied to the post.
|
17 |
+
*
|
18 |
+
* @var string
|
19 |
+
*/
|
20 |
+
public static $elementor_edit_mode = '_elementor_edit_mode';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Reusable variable of Lingotek custom field for Elementor field group
|
24 |
+
*
|
25 |
+
* @var string
|
26 |
+
*/
|
27 |
+
public static $elementor_content = 'elementor_content';
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Widgets that contain translatable content.
|
31 |
+
*
|
32 |
+
* @var array
|
33 |
+
*/
|
34 |
+
protected static $text_widgets = array(
|
35 |
+
'text-editor',
|
36 |
+
'heading',
|
37 |
+
'button',
|
38 |
+
'call-to-action',
|
39 |
+
'form',
|
40 |
+
'text-path',
|
41 |
+
'blockquote',
|
42 |
+
'forms',
|
43 |
+
'animated-headline',
|
44 |
+
'price-list',
|
45 |
+
'price-table',
|
46 |
+
'table-of-contents',
|
47 |
+
'lottie',
|
48 |
+
'theme-site-title',
|
49 |
+
);
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Widgets that embedded content that need to be handled differently, i.e. images
|
53 |
+
* The values are the translatable fields in the settings of each widget type.
|
54 |
+
*
|
55 |
+
* @var array
|
56 |
+
*/
|
57 |
+
public static $embedded_widgets = array(
|
58 |
+
'image' => array(
|
59 |
+
'caption',
|
60 |
+
),
|
61 |
+
'image-box' => array(
|
62 |
+
'title_text',
|
63 |
+
'description_text',
|
64 |
+
),
|
65 |
+
'hotspot' => array(
|
66 |
+
'hotspot',
|
67 |
+
'hotspot_label',
|
68 |
+
'hotspot_tooltip_content',
|
69 |
+
),
|
70 |
+
'testimonial-carousel' => array(
|
71 |
+
'slides',
|
72 |
+
'content',
|
73 |
+
'name',
|
74 |
+
'title',
|
75 |
+
),
|
76 |
+
'blockquote' => array(
|
77 |
+
'blockquote_content',
|
78 |
+
'tweet_button_label',
|
79 |
+
'author_name',
|
80 |
+
),
|
81 |
+
'posts' => array(
|
82 |
+
'classic_meta_separator',
|
83 |
+
'classic_read_more_text',
|
84 |
+
'cards_meta_separator',
|
85 |
+
'cards_read_more_text',
|
86 |
+
'full_content_meta_separator',
|
87 |
+
'pagination_prev_label',
|
88 |
+
'pagination_next_label',
|
89 |
+
'text',
|
90 |
+
'load_more_no_posts_custom_message',
|
91 |
+
),
|
92 |
+
'gallery' => array(
|
93 |
+
'gallery_title',
|
94 |
+
'show_all_galleries_label',
|
95 |
+
),
|
96 |
+
);
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Get the translatable content from the _elementor_data
|
100 |
+
*
|
101 |
+
* @since 1.5.3
|
102 |
+
*
|
103 |
+
* @param int $post_id The source post id.
|
104 |
+
* @return array list of translatable content, where the indexes are the element ids, and the values are the element content
|
105 |
+
*/
|
106 |
+
public static function get_post_metadata_content( $post_id ) {
|
107 |
+
$content_list = array();
|
108 |
+
$meta_json_string = get_post_meta( $post_id, self::$elementor_data, true );
|
109 |
+
$meta_array = json_decode( $meta_json_string, true );
|
110 |
+
self::get_elements( $meta_array, $content_list );
|
111 |
+
return $content_list;
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Sets the translated content into the copied _elementor_data json string
|
116 |
+
*
|
117 |
+
* @since 1.5.3
|
118 |
+
*
|
119 |
+
* @param int $post_id The translated post id.
|
120 |
+
* @param string $element_json The original json string.
|
121 |
+
* @param array $translation_list The list of translated content.
|
122 |
+
* @return boolean True if the content in the original json string is successfully replaced with the translated content, and the meta field for the translated post is successfully updated, false otherwise.
|
123 |
+
*/
|
124 |
+
public static function set_post_metadata_content( $post_id, $element_json, $translation_list ) {
|
125 |
+
// We need to set the translations in the meta string from the original post
|
126 |
+
$meta_array = json_decode( $element_json, true );
|
127 |
+
if ( ! $meta_array && ! $translation_list ) {
|
128 |
+
// We either don't have the original json string or there is no translated content.
|
129 |
+
return false;
|
130 |
+
}
|
131 |
+
self::set_translations( $meta_array, $translation_list );
|
132 |
+
$updated_meta_json_string = wp_slash( wp_json_encode( $meta_array ) );
|
133 |
+
return update_post_meta( $post_id, self::$elementor_data, $updated_meta_json_string );
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Parse through the list of elements and pull translatable elements into a list
|
138 |
+
*
|
139 |
+
* @since 1.5.3
|
140 |
+
*
|
141 |
+
* @param array $element_list List of elementor elements.
|
142 |
+
* @param array $content_list List of translatable elements.
|
143 |
+
*/
|
144 |
+
public static function get_elements( $element_list, &$content_list ) {
|
145 |
+
foreach ( $element_list as $element ) {
|
146 |
+
$element_in_array = isset( $element['id'], $content_list[ $element['id'] ] ) ? true : false;
|
147 |
+
$element_settings = isset( $element['settings'] ) && ! empty( $element['settings'] ) ? $element['settings'] : false;
|
148 |
+
$element_widget_type = isset( $element['widgetType'] ) ? $element['widgetType'] : false;
|
149 |
+
|
150 |
+
// Check if element has already been stored, and if the widget has translatable text.
|
151 |
+
$widget_editor_type = in_array( $element_widget_type, self::$text_widgets, true );
|
152 |
+
$embedded_widget = isset( self::$embedded_widgets[ $element_widget_type ] ) ? true : false;
|
153 |
+
if ( ! $element_in_array && $widget_editor_type && $element_settings ) {
|
154 |
+
$content_list[ $element['id'] ] = $element_settings;
|
155 |
+
} elseif ( ! $element_in_array && $embedded_widget && $element_settings ) {
|
156 |
+
$translatable_fields = isset( self::$embedded_widgets[ $element_widget_type ] ) ? self::$embedded_widgets[ $element_widget_type ] : array();
|
157 |
+
$content_list[ $element['id'] ] = self::get_translatable_fields( $translatable_fields, $element_settings );
|
158 |
+
}
|
159 |
+
$sub_elements = isset( $element['elements'] ) && ! empty( $element['elements'] ) ? $element['elements'] : false;
|
160 |
+
if ( $sub_elements ) {
|
161 |
+
// Check embedded elements for more translatable content.
|
162 |
+
self::get_elements( $sub_elements, $content_list );
|
163 |
+
}
|
164 |
+
}
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Sets the translated content in the elementor elements in for the translated post
|
169 |
+
*
|
170 |
+
* @since 1.5.3
|
171 |
+
*
|
172 |
+
* @param array $element_list List of elementor elements.
|
173 |
+
* @param array $translation_list List of translated content.
|
174 |
+
*/
|
175 |
+
public static function set_translations( &$element_list, $translation_list ) {
|
176 |
+
foreach ( $element_list as $key => $element ) {
|
177 |
+
$translated_element = isset( $element['id'], $translation_list[ $element['id'] ] ) ? $translation_list[ $element['id'] ] : false;
|
178 |
+
$element_settings = isset( $element['settings'] ) && ! empty( $element['settings'] ) ? $element['settings'] : false;
|
179 |
+
$element_widget_type = isset( $element['widgetType'] ) ? $element['widgetType'] : false;
|
180 |
+
$widget_editor_type = in_array( $element_widget_type, self::$text_widgets, true );
|
181 |
+
$embedded_widget = isset( self::$embedded_widgets[ $element_widget_type ] ) ? true : false;
|
182 |
+
// Check that element translation exists, has a valid editor type, and has a settings key.
|
183 |
+
if ( $translated_element && $widget_editor_type && $element_settings ) {
|
184 |
+
$element['settings'] = $translated_element;
|
185 |
+
} elseif ( $translated_element && $element_settings && $embedded_widget ) {
|
186 |
+
$translatable_fields = isset( self::$embedded_widgets[ $element_widget_type ] ) ? self::$embedded_widgets[ $element_widget_type ] : array();
|
187 |
+
$element['settings'] = self::set_translatable_fields( $translatable_fields, $element_settings, $translated_element );
|
188 |
+
}
|
189 |
+
$sub_elements = isset( $element['elements'] ) && ! empty( $element['elements'] ) ? $element['elements'] : false;
|
190 |
+
if ( $sub_elements ) {
|
191 |
+
// Check if any embedded elements have translations and update them.
|
192 |
+
self::set_translations( $sub_elements, $translation_list );
|
193 |
+
$element['elements'] = $sub_elements;
|
194 |
+
}
|
195 |
+
// Save element to list of elements, along with any changes.
|
196 |
+
$element_list[ $key ] = $element;
|
197 |
+
}//end foreach
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* Gets the translatable fields from embedded content.
|
202 |
+
*
|
203 |
+
* @since 1.5.3
|
204 |
+
*
|
205 |
+
* @param array $translatable_fields Array containing the fields that we want to translate.
|
206 |
+
* @param array $settings Array containing the current widget settings.
|
207 |
+
* @return array
|
208 |
+
*/
|
209 |
+
public static function get_translatable_fields( $translatable_fields, $settings ) {
|
210 |
+
$temp_settings = array();
|
211 |
+
// we only want to translate specific fields, anything not translatable has its key prepended with `_`
|
212 |
+
foreach ( $settings as $setting => $value ) {
|
213 |
+
// if an image exists within a widget setting, we only want to translate the alt text.
|
214 |
+
if ( 'image' === $setting && is_array( $value ) ) {
|
215 |
+
$temp_settings[ $setting ] = self::get_translatable_fields( array( 'alt' ), $value );
|
216 |
+
} elseif ( in_array( $setting, $translatable_fields, true ) ) {
|
217 |
+
// If setting is a translatable field then we save it as is.
|
218 |
+
if ( is_array( $value ) && ! self::has_string_keys( $value ) ) {
|
219 |
+
// If the field is a JSON array and not a JSON object, we go through each item to check that it is translatable.
|
220 |
+
foreach ( $value as $value_key => $value_settings ) {
|
221 |
+
$value[ $value_key ] = self::get_translatable_fields( $translatable_fields, $value_settings );
|
222 |
+
}
|
223 |
+
}
|
224 |
+
$temp_settings[ $setting ] = $value;
|
225 |
+
} else {
|
226 |
+
// Non translatable fields are prepended with `_` to mark them as non translatable.
|
227 |
+
// If the setting is not translatable, but if it is an array, we check if it's a JSON object, or a JSON array.
|
228 |
+
if ( is_array( $value ) ) {
|
229 |
+
$temp_value = array();
|
230 |
+
$has_string_keys = self::has_string_keys( $value );
|
231 |
+
foreach ( $value as $value_key => $value_settings ) {
|
232 |
+
// If it's a JSON object then we check if any of its fields are translatable.
|
233 |
+
if ( $has_string_keys ) {
|
234 |
+
if ( in_array( $value_key, $translatable_fields, true ) ) {
|
235 |
+
$temp_value[ $value_key ] = $value_settings;
|
236 |
+
} else {
|
237 |
+
$temp_value[ '_' . $value_key ] = $value_settings;
|
238 |
+
}
|
239 |
+
} else {
|
240 |
+
// Else we check each item in the array for translatable fields.
|
241 |
+
$temp_value[ $value_key ] = self::get_translatable_fields( $translatable_fields, $value_settings );
|
242 |
+
}
|
243 |
+
}
|
244 |
+
// We save any changes made to the field value.
|
245 |
+
$value = $temp_value;
|
246 |
+
}
|
247 |
+
$temp_settings[ '_' . $setting ] = $value;
|
248 |
+
}//end if
|
249 |
+
}//end foreach
|
250 |
+
return $temp_settings;
|
251 |
+
}
|
252 |
+
|
253 |
+
/**
|
254 |
+
* Sets the translations back in the correct translatable fields
|
255 |
+
*
|
256 |
+
* @since 1.5.3
|
257 |
+
*
|
258 |
+
* @param array $translatable_fields Array of translatable fields for current element type.
|
259 |
+
* @param array $settings Array of the current element settings.
|
260 |
+
* @param array $translation Translated version of the current element settings.
|
261 |
+
* @return array Return the current element settings with the correct translations properly inserted.
|
262 |
+
*/
|
263 |
+
public static function set_translatable_fields( $translatable_fields, $settings, $translation ) {
|
264 |
+
foreach ( $translation as $key => $value ) {
|
265 |
+
// Images are a special case since we only want to translate the alt text, and this is shorter than adding 'alt'
|
266 |
+
// and 'image' to all the content that potentially uses images in their widget
|
267 |
+
if ( 'image' === $key && is_array( $value ) ) {
|
268 |
+
$settings[ $key ] = self::set_translatable_fields( array( 'alt' ), $settings[ $key ], $value );
|
269 |
+
continue;
|
270 |
+
}
|
271 |
+
// If the key is a string and not a translatable field, we assume that an underscore was added to mark it as non-translatable, so it's removed.
|
272 |
+
if ( ! in_array( $key, $translatable_fields, true ) && is_string( $key ) ) {
|
273 |
+
$temp_key = substr( $key, 1 );
|
274 |
+
} else {
|
275 |
+
$temp_key = $key;
|
276 |
+
}
|
277 |
+
// If the current translated value is an array then we have to update each of its
|
278 |
+
// fields individually incase not all of them are translatable.
|
279 |
+
if ( is_array( $value ) ) {
|
280 |
+
$value = self::set_translatable_fields( $translatable_fields, $settings[ $temp_key ], $value );
|
281 |
+
}
|
282 |
+
// Replace current setting value with translated value.
|
283 |
+
$settings[ $temp_key ] = $value;
|
284 |
+
}//end foreach
|
285 |
+
return $settings;
|
286 |
+
}
|
287 |
+
|
288 |
+
/**
|
289 |
+
* Returns true if the array has all string keys, else returns false
|
290 |
+
*
|
291 |
+
* @since 1.5.3
|
292 |
+
*
|
293 |
+
* @param array $array Array to test.
|
294 |
+
* @return boolean
|
295 |
+
*/
|
296 |
+
public static function has_string_keys( array $array ) {
|
297 |
+
return count( array_filter( array_keys( $array ), 'is_string' ) ) > 0;
|
298 |
+
}
|
299 |
+
}
|
js/updater.js
CHANGED
@@ -108,6 +108,10 @@ 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 'deleted':
|
112 |
if (locale === data[key]['source']){
|
113 |
updateUploadBulkLink(tr, data, key, 'upload' , 'Upload deleted item to Lingotek TMS', 'Upload to Lingotek');
|
@@ -224,6 +228,24 @@ jQuery(document).ready(function($) {
|
|
224 |
$(td).prepend(request_link);
|
225 |
}
|
226 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
function updateGenericBulkLink(tr, data, key, action, title, text){
|
228 |
var row_actions = $(tr).find('.row-actions');
|
229 |
if($(row_actions).find('.lingotek-' + action).length === 0){
|
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 'ready-interim':
|
112 |
+
updateGenericBulkLink(tr, data, key, 'status' , 'Update translations status of this item in Lingotek TMS', 'Update translations status ');
|
113 |
+
updateReadyInterimIcon(td, data, key, locale);
|
114 |
+
break;
|
115 |
case 'deleted':
|
116 |
if (locale === data[key]['source']){
|
117 |
updateUploadBulkLink(tr, data, key, 'upload' , 'Upload deleted item to Lingotek TMS', 'Upload to Lingotek');
|
228 |
$(td).prepend(request_link);
|
229 |
}
|
230 |
|
231 |
+
function updateReadyInterimIcon(td, data, key, locale) {
|
232 |
+
$(td).find('.lingotek-color').remove();
|
233 |
+
$(td).find('.lingotek-ready-interim-color').remove();
|
234 |
+
if ($(td).find('dashicons-no').length > 0) {
|
235 |
+
$(td).find('.dashicons-no').remove();
|
236 |
+
} else if ($(td).find('.dashicons-clock').length > 0) {
|
237 |
+
$(td).find('.dashicons-clock').remove();
|
238 |
+
}
|
239 |
+
$(td).find('.lingotek-professional-icon').remove();
|
240 |
+
var icon = 'edit';
|
241 |
+
$(td).find('.lingotek-ready-interim-color').remove();
|
242 |
+
var request_link = $('<a></a>').attr('href', data[key][locale]['workbench_link'])
|
243 |
+
.attr('title', 'Interim Translation Ready to be Downloaded')
|
244 |
+
.attr('target','_blank')
|
245 |
+
.addClass('lingotek-ready-interim-color dashicons dashicons-' + icon + ' dashicons-' + icon + '-lingotek');
|
246 |
+
$(td).prepend(request_link);
|
247 |
+
}
|
248 |
+
|
249 |
function updateGenericBulkLink(tr, data, key, action, title, text){
|
250 |
var row_actions = $(tr).find('.row-actions');
|
251 |
if($(row_actions).find('.lingotek-' + action).length === 0){
|
lingotek.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
/**
|
3 |
Plugin name: Lingotek Translation
|
4 |
Plugin URI: http://lingotek.com/wordpress#utm_source=wpadmin&utm_medium=plugin&utm_campaign=wplingotektranslationplugin
|
5 |
-
Version: 1.5.
|
6 |
Author: Lingotek and Frédéric Demarle
|
7 |
Author uri: http://lingotek.com
|
8 |
Description: Lingotek offers convenient cloud-based localization and translation.
|
@@ -19,7 +19,7 @@ if ( ! function_exists( 'add_action' ) ) {
|
|
19 |
}
|
20 |
|
21 |
// Plugin version (should match above meta).
|
22 |
-
define( 'LINGOTEK_VERSION', '1.5.
|
23 |
define( 'LINGOTEK_MIN_PLL_VERSION', '1.8' );
|
24 |
// Plugin name as known by WordPress.
|
25 |
define( 'LINGOTEK_BASENAME', plugin_basename( __FILE__ ) );
|
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.3
|
6 |
Author: Lingotek and Frédéric Demarle
|
7 |
Author uri: http://lingotek.com
|
8 |
Description: Lingotek offers convenient cloud-based localization and translation.
|
19 |
}
|
20 |
|
21 |
// Plugin version (should match above meta).
|
22 |
+
define( 'LINGOTEK_VERSION', '1.5.3' );
|
23 |
define( 'LINGOTEK_MIN_PLL_VERSION', '1.8' );
|
24 |
// Plugin name as known by WordPress.
|
25 |
define( 'LINGOTEK_BASENAME', plugin_basename( __FILE__ ) );
|
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.5.
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
@@ -123,12 +123,23 @@ For more, visit the [Lingotek documentation site](https://lingotek.atlassian.net
|
|
123 |
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.
|
124 |
|
125 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
= 1.5.2 (2021-11-05) =
|
127 |
- Removed the cancel action from the target dropdown
|
128 |
- Fixed duplicated message "Your Lingotek account has been successfully connected."
|
129 |
- Unable to add language-only locale if same language code already exists
|
130 |
- Fixed Cancel translation for specific targets from bulk action displays an irrelevant message
|
131 |
-
|
132 |
= 1.5.1 (2021-08-19) =
|
133 |
- Compatibility issues with PolyLang 3.1
|
134 |
- Add check for the Document Status
|
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.3
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
123 |
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.
|
124 |
|
125 |
== Changelog ==
|
126 |
+
|
127 |
+
= 1.5.3 (2022-03-01) =
|
128 |
+
- ELEMENTOR: Uploading Metadata content
|
129 |
+
- WP: Add 'Ready-Interim' Status
|
130 |
+
- WordPress: Update the "Mailto:" link for subscription terms
|
131 |
+
- ELEMENTOR: Group elementor fields in Custom Field Configuration
|
132 |
+
- ELEMENTOR: Apply hooks for when elementor content is updated
|
133 |
+
- ELEMENTOR: Add support for embedded content
|
134 |
+
- WP: Accept the 20,000 words exceeded response
|
135 |
+
- Wordpress: Transition to Ready to Download
|
136 |
+
|
137 |
= 1.5.2 (2021-11-05) =
|
138 |
- Removed the cancel action from the target dropdown
|
139 |
- Fixed duplicated message "Your Lingotek account has been successfully connected."
|
140 |
- Unable to add language-only locale if same language code already exists
|
141 |
- Fixed Cancel translation for specific targets from bulk action displays an irrelevant message
|
142 |
+
|
143 |
= 1.5.1 (2021-08-19) =
|
144 |
- Compatibility issues with PolyLang 3.1
|
145 |
- Add check for the Document Status
|