first commit
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
class WPML_Custom_Field_Editor_Settings {
|
||||
/** @var WPML_Custom_Field_Setting_Factory */
|
||||
private $settings_factory;
|
||||
|
||||
public function __construct( WPML_Custom_Field_Setting_Factory $settingsFactory ) {
|
||||
$this->settings_factory = $settingsFactory;
|
||||
}
|
||||
|
||||
public function filter_name( $fieldType, $default ) {
|
||||
return $this->settings_factory->post_meta_setting( $this->extractTypeName( $fieldType ) )->get_editor_label() ?: $default;
|
||||
}
|
||||
|
||||
public function filter_style( $fieldType, $default ) {
|
||||
$filtered_style = $this->settings_factory->post_meta_setting( $this->extractTypeName( $fieldType ) )->get_editor_style();
|
||||
switch ( $filtered_style ) {
|
||||
case 'line':
|
||||
return 0;
|
||||
case 'textarea':
|
||||
return 1;
|
||||
case 'visual':
|
||||
return 2;
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
public function get_group( $fieldType ) {
|
||||
return $this->settings_factory->post_meta_setting( $this->extractTypeName( $fieldType ) )->get_editor_group();
|
||||
}
|
||||
|
||||
private function extractTypeName( $fieldType ) {
|
||||
return substr( $fieldType, strlen( 'field_' ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
class WPML_Editor_UI_Job {
|
||||
|
||||
private $fields = array();
|
||||
protected $job_id;
|
||||
private $job_type;
|
||||
private $job_type_title;
|
||||
private $title;
|
||||
private $view_link;
|
||||
private $source_lang;
|
||||
private $target_lang;
|
||||
private $translation_complete;
|
||||
private $duplicate;
|
||||
private $note = '';
|
||||
|
||||
function __construct(
|
||||
$job_id,
|
||||
$job_type,
|
||||
$job_type_title,
|
||||
$title,
|
||||
$view_link,
|
||||
$source_lang,
|
||||
$target_lang,
|
||||
$translation_complete,
|
||||
$duplicate
|
||||
) {
|
||||
|
||||
$this->job_id = $job_id;
|
||||
$this->job_type = $job_type;
|
||||
$this->job_type_title = $job_type_title;
|
||||
$this->title = $title;
|
||||
$this->view_link = $view_link;
|
||||
$this->source_lang = $source_lang;
|
||||
$this->target_lang = $target_lang;
|
||||
$this->translation_complete = $translation_complete;
|
||||
$this->duplicate = $duplicate;
|
||||
|
||||
}
|
||||
|
||||
public function add_field( $field ) {
|
||||
$this->fields[] = $field;
|
||||
}
|
||||
|
||||
public function add_note( $note ) {
|
||||
$this->note = $note;
|
||||
}
|
||||
|
||||
public function get_all_fields() {
|
||||
$fields = array();
|
||||
/** @var WPML_Editor_UI_Field $field */
|
||||
foreach ( $this->fields as $field ) {
|
||||
$child_fields = $field->get_fields();
|
||||
/** @var WPML_Editor_UI_Field $child_field */
|
||||
foreach ( $child_fields as $child_field ) {
|
||||
$fields[] = $child_field;
|
||||
}
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function get_layout_of_fields() {
|
||||
$layout = array();
|
||||
/** @var WPML_Editor_UI_Field $field */
|
||||
foreach ( $this->fields as $field ) {
|
||||
$layout[] = $field->get_layout();
|
||||
}
|
||||
|
||||
return $layout;
|
||||
}
|
||||
|
||||
public function get_target_language() {
|
||||
return $this->target_lang;
|
||||
}
|
||||
|
||||
public function is_translation_complete() {
|
||||
return $this->translation_complete;
|
||||
}
|
||||
|
||||
public function save( $data ) {
|
||||
$translations = array();
|
||||
|
||||
foreach ( $data['fields'] as $id => $field ) {
|
||||
$translations[ $this->convert_id_to_translation_key( $id ) ] = $field['data'];
|
||||
}
|
||||
|
||||
try {
|
||||
$this->save_translations( $translations );
|
||||
|
||||
return new WPML_Ajax_Response( true, true );
|
||||
} catch ( Exception $e ) {
|
||||
return new WPML_Ajax_Response( false, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
private function convert_id_to_translation_key( $id ) {
|
||||
// This is to support the old api for saving translations.
|
||||
return md5( $id );
|
||||
}
|
||||
|
||||
public function requires_translation_complete_for_each_field() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function display_hide_completed_switcher() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function is_hide_empty_fields() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function save_translations( $translations ) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Editor_Job_Save {
|
||||
|
||||
public function save( $data ) {
|
||||
/** @var WPML_Translation_Job_Factory $wpml_translation_job_factory */
|
||||
global $wpml_translation_job_factory;
|
||||
|
||||
$factory = new WPML_TM_Job_Action_Factory( $wpml_translation_job_factory );
|
||||
$action = new WPML_TM_Editor_Save_Ajax_Action( $factory, $data );
|
||||
|
||||
return $action->run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Editor_Save_Ajax_Action extends WPML_TM_Job_Action {
|
||||
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* WPML_TM_Editor_Save_Ajax_Action constructor.
|
||||
*
|
||||
* @param WPML_TM_Job_Action_Factory $job_action_factory
|
||||
* @param array $data
|
||||
*/
|
||||
public function __construct( &$job_action_factory, array $data ) {
|
||||
parent::__construct( $job_action_factory );
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function run() {
|
||||
try {
|
||||
return new WPML_Ajax_Response(
|
||||
true,
|
||||
$this->job_action_factory->save_action( $this->data )->save_translation()
|
||||
);
|
||||
} catch ( Exception $e ) {
|
||||
return new WPML_Ajax_Response( false, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
class WPML_TM_Field_Type_Sanitizer {
|
||||
|
||||
|
||||
/**
|
||||
* Get elements custom field `field_type`.
|
||||
* Removes last character if it's number.
|
||||
* ex. field-custom_field-0 => field-custom_field
|
||||
*
|
||||
* @param $element
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function sanitize( $custom_field_type ) {
|
||||
$element_field_type_parts = explode( '-', $custom_field_type );
|
||||
$last_part = array_pop( $element_field_type_parts );
|
||||
|
||||
if ( empty( $element_field_type_parts ) ) {
|
||||
return $custom_field_type;
|
||||
}
|
||||
|
||||
// Re-create field.
|
||||
$field_type = implode( '-', $element_field_type_parts );
|
||||
if ( is_numeric( $last_part ) ) {
|
||||
return $field_type;
|
||||
} else {
|
||||
return $custom_field_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
class WPML_Translation_Editor_Header {
|
||||
|
||||
private $job_instance;
|
||||
|
||||
public function __construct( $job_instance ) {
|
||||
$this->job_instance = $job_instance;
|
||||
}
|
||||
|
||||
public function get_model() {
|
||||
$type_title = esc_html( $this->job_instance->get_type_title() );
|
||||
$title = esc_html( $this->job_instance->get_title() );
|
||||
$data = array();
|
||||
$data['title'] = sprintf( __( '%1$s translation: %2$s', 'wpml-translation-management' ), $type_title, '<strong>' . $title . '</strong>' );
|
||||
$data['link_url'] = $this->job_instance->get_url( true );
|
||||
$data['link_text'] = $this->job_instance instanceof WPML_External_Translation_Job ? '' : sprintf( __( 'View %s', 'wpml-translation-management' ), $type_title );
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
class WPML_Translation_Editor_Languages extends WPML_SP_User {
|
||||
|
||||
private $job;
|
||||
|
||||
/**
|
||||
* @param SitePress $sitepress
|
||||
*/
|
||||
public function __construct( &$sitepress, $job ) {
|
||||
parent::__construct( $sitepress );
|
||||
$this->job = $job;
|
||||
}
|
||||
|
||||
public function get_model() {
|
||||
$source_lang = $this->sitepress->get_language_details( $this->job->source_language_code );
|
||||
$target_lang = $this->sitepress->get_language_details( $this->job->language_code );
|
||||
|
||||
$data = array(
|
||||
'source' => $this->job->source_language_code,
|
||||
'target' => $this->job->language_code,
|
||||
'source_lang' => $source_lang['display_name'],
|
||||
'target_lang' => $target_lang['display_name'],
|
||||
);
|
||||
$data['img'] = array(
|
||||
'source_url' => $this->sitepress->get_flag_url( $this->job->source_language_code ),
|
||||
'target_url' => $this->sitepress->get_flag_url( $this->job->language_code ),
|
||||
);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,335 @@
|
||||
<?php
|
||||
|
||||
use \WPML\TM\Jobs\FieldId;
|
||||
|
||||
class WPML_Translation_Editor_UI {
|
||||
const MAX_ALLOWED_SINGLE_LINE_LENGTH = 50;
|
||||
|
||||
/** @var SitePress $sitepress */
|
||||
private $sitepress;
|
||||
/** @var WPDB $wpdb */
|
||||
private $wpdb;
|
||||
|
||||
/** @var array */
|
||||
private $all_translations;
|
||||
/**
|
||||
* @var WPML_Translation_Editor
|
||||
*/
|
||||
private $editor_object;
|
||||
private $job;
|
||||
private $original_post;
|
||||
private $rtl_original;
|
||||
private $rtl_original_attribute_object;
|
||||
private $rtl_translation;
|
||||
private $rtl_translation_attribute;
|
||||
private $is_duplicate = false;
|
||||
/**
|
||||
* @var TranslationManagement
|
||||
*/
|
||||
private $tm_instance;
|
||||
|
||||
/** @var WPML_Element_Translation_Job|WPML_External_Translation_Job */
|
||||
private $job_instance;
|
||||
|
||||
private $job_factory;
|
||||
private $job_layout;
|
||||
/** @var array */
|
||||
private $fields;
|
||||
|
||||
function __construct( wpdb $wpdb, SitePress $sitepress, TranslationManagement $iclTranslationManagement, WPML_Element_Translation_Job $job_instance, WPML_TM_Job_Action_Factory $job_factory, WPML_TM_Job_Layout $job_layout ) {
|
||||
$this->sitepress = $sitepress;
|
||||
$this->wpdb = $wpdb;
|
||||
|
||||
$this->tm_instance = $iclTranslationManagement;
|
||||
$this->job_instance = $job_instance;
|
||||
$this->job = $job_instance->get_basic_data();
|
||||
$this->job_factory = $job_factory;
|
||||
$this->job_layout = $job_layout;
|
||||
if ( $job_instance->get_translator_id() <= 0 ) {
|
||||
$job_instance->assign_to( $sitepress->get_wp_api()->get_current_user_id() );
|
||||
}
|
||||
}
|
||||
|
||||
function render() {
|
||||
list( $this->rtl_original, $this->rtl_translation ) = $this->init_rtl_settings();
|
||||
|
||||
require_once ABSPATH . 'wp-admin/includes/image.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/media.php';
|
||||
|
||||
?>
|
||||
<div class="wrap icl-translation-editor wpml-dialog-translate">
|
||||
<h1 id="wpml-translation-editor-header" class="wpml-translation-title"></h1>
|
||||
<?php
|
||||
do_action( 'icl_tm_messages' );
|
||||
do_action( 'wpml_tm_editor_messages' );
|
||||
$this->init_original_post();
|
||||
$this->init_editor_object();
|
||||
|
||||
$this->output_model();
|
||||
$this->output_ate_notice();
|
||||
$this->output_gutenberg_notice();
|
||||
$this->output_wysiwyg_editors();
|
||||
$this->output_copy_all_dialog();
|
||||
if ( $this->is_duplicate ) {
|
||||
$this->output_edit_independently_dialog();
|
||||
}
|
||||
$this->output_editor_form();
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function init_rtl_settings() {
|
||||
$this->rtl_original = $this->sitepress->is_rtl( $this->job->source_language_code );
|
||||
$this->rtl_translation = $this->sitepress->is_rtl( $this->job->language_code );
|
||||
$this->rtl_original_attribute_object = $this->rtl_original ? ' dir="rtl"' : ' dir="ltr"';
|
||||
$this->rtl_translation_attribute = $this->rtl_translation ? ' dir="rtl"' : ' dir="ltr"';
|
||||
|
||||
return array( $this->rtl_original, $this->rtl_translation );
|
||||
}
|
||||
|
||||
private function init_original_post() {
|
||||
// we do not need the original document of the job here
|
||||
// but the document with the same trid and in the $this->job->source_language_code
|
||||
$this->all_translations = $this->sitepress->get_element_translations( $this->job->trid, $this->job->original_post_type );
|
||||
$this->original_post = false;
|
||||
foreach ( (array) $this->all_translations as $t ) {
|
||||
if ( $t->language_code === $this->job->source_language_code ) {
|
||||
$this->original_post = $this->tm_instance->get_post( $t->element_id, $this->job->element_type_prefix );
|
||||
// if this fails for some reason use the original doc from which the trid originated
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( ! $this->original_post ) {
|
||||
$this->original_post = $this->tm_instance->get_post( $this->job_instance->get_original_element_id(), $this->job->element_type_prefix );
|
||||
}
|
||||
|
||||
if ( isset( $this->all_translations[ $this->job->language_code ] ) ) {
|
||||
$post_status = new WPML_Post_Status( $this->wpdb, $this->sitepress->get_wp_api() );
|
||||
$this->is_duplicate = $post_status->is_duplicate( $this->all_translations[ $this->job->language_code ]->element_id );
|
||||
}
|
||||
|
||||
return $this->original_post;
|
||||
}
|
||||
|
||||
private function init_editor_object() {
|
||||
global $wpdb;
|
||||
|
||||
$this->editor_object = new WPML_Translation_Editor( $this->sitepress, $wpdb, $this->job_instance );
|
||||
}
|
||||
|
||||
private function output_model() {
|
||||
|
||||
$model = array(
|
||||
'requires_translation_complete_for_each_field' => true,
|
||||
'hide_empty_fields' => true,
|
||||
'translation_is_complete' => ICL_TM_COMPLETE === (int) $this->job->status,
|
||||
'show_media_button' => false,
|
||||
'is_duplicate' => $this->is_duplicate,
|
||||
'display_hide_completed_switcher' => true,
|
||||
);
|
||||
|
||||
if ( ! empty( $_GET['return_url'] ) ) {
|
||||
$model['return_url'] = filter_var( $_GET['return_url'], FILTER_SANITIZE_URL );
|
||||
} else {
|
||||
$model['return_url'] = 'admin.php?page=' . WPML_TM_FOLDER . '/menu/translations-queue.php';
|
||||
}
|
||||
|
||||
$languages = new WPML_Translation_Editor_Languages( $this->sitepress, $this->job );
|
||||
$model['languages'] = $languages->get_model();
|
||||
|
||||
$header = new WPML_Translation_Editor_Header( $this->job_instance );
|
||||
$model['header'] = $header->get_model();
|
||||
|
||||
$model['note'] = $this->sitepress->get_wp_api()->get_post_meta(
|
||||
$this->job_instance->get_original_element_id(),
|
||||
WPML_TM_Translator_Note::META_FIELD_KEY,
|
||||
true
|
||||
);
|
||||
|
||||
$this->fields = $this->job_factory->field_contents( (int) $this->job_instance->get_id() )->run();
|
||||
$this->fields = $this->add_titles_and_adjust_styles( $this->fields );
|
||||
$this->fields = $this->add_rtl_attributes( $this->fields );
|
||||
$model['fields'] = $this->fields;
|
||||
$model['layout'] = $this->job_layout->run( $model['fields'], $this->tm_instance );
|
||||
$model['rtl_original'] = $this->rtl_original;
|
||||
$model['rtl_translation'] = $this->rtl_translation;
|
||||
$model['translation_memory'] = (bool) $this->sitepress->get_setting( 'translation_memory', 1 );
|
||||
|
||||
$model = $this->filter_the_model( $model );
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
var WpmlTmEditorModel = <?php echo wp_json_encode( $model ); ?>;
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function output_ate_notice() {
|
||||
|
||||
$html_fields = array_filter(
|
||||
$this->fields,
|
||||
function ( $field ) {
|
||||
return $field['field_style'] === '1' && strpos( $field['field_data'], '<' ) !== false;
|
||||
}
|
||||
);
|
||||
|
||||
if ( count( $html_fields ) > 0 ) {
|
||||
$link = 'https://wpml.org/documentation/translating-your-contents/advanced-translation-editor/#html-markers';
|
||||
$notice_text = esc_html__( 'We see you\'re translating content that contains HTML. Switch to the Advanced Translation Editor to translate content without the risk of breaking your HTML code.', 'wpml-translation-management' );
|
||||
echo '<div class="notice notice-info">
|
||||
<p>' . $notice_text . ' <a href="' . $link . '" class="wpml-external-link" target="_blank" rel="noopener">' . esc_html__( 'Read more...', 'wpml-translation-management' ) . '</a></p>
|
||||
</div>';
|
||||
}
|
||||
}
|
||||
|
||||
private function output_gutenberg_notice() {
|
||||
$has_gutenberg_block = false;
|
||||
|
||||
foreach ( $this->fields as $field ) {
|
||||
if ( preg_match( '#<!-- wp:#', $field['field_data'] ) ) {
|
||||
$has_gutenberg_block = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $has_gutenberg_block ) {
|
||||
echo '<div class="notice notice-info">
|
||||
<p>' . esc_html__( 'This content came from the Block editor and you need to translate it carefully so that formatting is not broken.', 'wpml-translation-management' ) . '</p>
|
||||
<p><a href="https://wpml.org/documentation/getting-started-guide/translating-content-created-using-gutenberg-editor/?utm_source=wpmlplugin&utm_campaign=gutenberg&utm_medium=translation-editor&utm_term=translating-content-created-using-gutenberg-editor" class="wpml-external-link" target="_blank" rel="noopener">' . esc_html__( 'Learn how to translate content that comes from Block editor', 'wpml-translation-management' ) . '</a></p>
|
||||
</div>';
|
||||
}
|
||||
}
|
||||
|
||||
private function output_wysiwyg_editors() {
|
||||
echo '<div style="display: none">';
|
||||
|
||||
foreach ( $this->fields as $field ) {
|
||||
if ( 2 === (int) $field['field_style'] ) {
|
||||
$this->editor_object->output_editors( $field );
|
||||
}
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
private function output_copy_all_dialog() {
|
||||
?>
|
||||
<div id="wpml-translation-editor-copy-all-dialog" class="wpml-dialog" style="display:none"
|
||||
title="<?php echo esc_attr__( 'Copy all fields from original', 'wpml-translation-management' ); ?>">
|
||||
<p class="wpml-dialog-cols-icon">
|
||||
<i class="otgs-ico-copy wpml-dialog-icon-xl"></i>
|
||||
</p>
|
||||
|
||||
<div class="wpml-dialog-cols-content">
|
||||
<p>
|
||||
<strong><?php echo esc_html__( 'Some fields in translation are already filled!', 'wpml-translation-management' ); ?></strong>
|
||||
<br/>
|
||||
<?php echo esc_html__( 'You have two ways to copy content from the original language:', 'wpml-translation-management' ); ?>
|
||||
</p>
|
||||
<ul>
|
||||
<li><?php echo esc_html__( 'copy to empty fields only', 'wpml-translation-management' ); ?></li>
|
||||
<li><?php echo esc_html__( 'copy and overwrite all fields', 'wpml-translation-management' ); ?></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="wpml-dialog-footer">
|
||||
<div class="alignleft">
|
||||
<button
|
||||
class="cancel wpml-dialog-close-button js-copy-cancel"><?php echo esc_html__( 'Cancel', 'wpml-translation-management' ); ?></button>
|
||||
</div>
|
||||
<div class="alignright">
|
||||
<button
|
||||
class="button-secondary js-copy-not-translated"><?php echo esc_html__( 'Copy to empty fields only', 'wpml-translation-management' ); ?></button>
|
||||
<button
|
||||
class="button-secondary js-copy-overwrite"><?php echo esc_html__( 'Copy & Overwrite all fields', 'wpml-translation-management' ); ?></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function output_edit_independently_dialog() {
|
||||
?>
|
||||
<div id="wpml-translation-editor-edit-independently-dialog" class="wpml-dialog" style="display:none"
|
||||
title="<?php echo esc_attr__( 'Edit independently', 'wpml-translation-management' ); ?>">
|
||||
<p class="wpml-dialog-cols-icon">
|
||||
<i class="otgs-ico-unlink wpml-dialog-icon-xl"></i>
|
||||
</p>
|
||||
|
||||
<div class="wpml-dialog-cols-content">
|
||||
<p><?php esc_html_e( 'This document is a duplicate of:', 'wpml-translation-management' ); ?>
|
||||
<span class="wpml-duplicated-post-title">
|
||||
<img class="wpml-title-flag" src="<?php echo esc_attr( $this->sitepress->get_flag_url( $this->job->source_language_code ) ); ?>">
|
||||
<?php echo esc_html( $this->job_instance->get_title() ); ?>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<?php echo esc_html( sprintf( __( 'WPML will no longer synchronize this %s with the original content.', 'wpml-translation-management' ), $this->job_instance->get_type_title() ) ); ?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="wpml-dialog-footer">
|
||||
<div class="alignleft">
|
||||
<button class="cancel wpml-dialog-close-button js-edit-independently-cancel"><?php echo esc_html__( 'Cancel', 'wpml-translation-management' ); ?></button>
|
||||
</div>
|
||||
<div class="alignright">
|
||||
<button class="button-secondary js-edit-independently"><?php echo esc_html__( 'Edit independently', 'wpml-translation-management' ); ?></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function output_editor_form() {
|
||||
?>
|
||||
<form id="icl_tm_editor" method="post" action="">
|
||||
<input type="hidden" name="job_post_type" value="<?php echo esc_attr( $this->job->original_post_type ); ?>"/>
|
||||
<input type="hidden" name="job_post_id" value="<?php echo esc_attr( $this->job->original_doc_id ); ?>"/>
|
||||
<input type="hidden" name="job_id" value="<?php echo esc_attr( $this->job_instance->get_id() ); ?>"/>
|
||||
|
||||
<div id="wpml-translation-editor-wrapper"></div>
|
||||
</form>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function add_titles_and_adjust_styles( array $fields ) {
|
||||
return apply_filters( 'wpml_tm_adjust_translation_fields', $fields, $this->job, $this->original_post );
|
||||
}
|
||||
|
||||
private function add_rtl_attributes( array $fields ) {
|
||||
foreach ( $fields as &$field ) {
|
||||
$field['original_direction'] = $this->rtl_original ? 'dir="rtl"' : 'dir="ltr"';
|
||||
$field['translation_direction'] = $this->rtl_translation ? 'dir="rtl"' : 'dir="ltr"';
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
private function filter_the_model( array $model ) {
|
||||
$job_details = array(
|
||||
'job_type' => $this->job->original_post_type,
|
||||
'job_id' => $this->job->original_doc_id,
|
||||
'target' => $model['languages']['target'],
|
||||
);
|
||||
$job = apply_filters( 'wpml-translation-editor-fetch-job', null, $job_details );
|
||||
if ( $job ) {
|
||||
$model['requires_translation_complete_for_each_field'] = $job->requires_translation_complete_for_each_field();
|
||||
$model['hide_empty_fields'] = $job->is_hide_empty_fields();
|
||||
$model['show_media_button'] = $job->show_media_button();
|
||||
$model['display_hide_completed_switcher'] = $job->display_hide_completed_switcher();
|
||||
|
||||
$model['fields'] = $this->add_rtl_attributes( $job->get_all_fields() );
|
||||
$this->fields = $model['fields'];
|
||||
|
||||
$model['layout'] = $job->get_layout_of_fields();
|
||||
}
|
||||
|
||||
return $model;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
if ( ! class_exists( '_WP_Editors', false ) ) {
|
||||
require ABSPATH . WPINC . '/class-wp-editor.php';
|
||||
}
|
||||
|
||||
class WPML_Translation_Editor extends WPML_WPDB_And_SP_User {
|
||||
|
||||
/**
|
||||
* @var WPML_Element_Translation_Job $job
|
||||
*/
|
||||
private $job;
|
||||
|
||||
/**
|
||||
* @param SitePress $sitepress
|
||||
* @param wpdb $wpdb
|
||||
* @param WPML_Element_Translation_Job $job
|
||||
*/
|
||||
public function __construct(
|
||||
&$sitepress,
|
||||
&$wpdb,
|
||||
$job
|
||||
) {
|
||||
parent::__construct( $wpdb, $sitepress );
|
||||
$this->job = $job;
|
||||
|
||||
$this->add_hooks();
|
||||
$this->enqueue_js();
|
||||
}
|
||||
|
||||
public function add_hooks() {
|
||||
add_filter( 'tiny_mce_before_init', [ $this, 'filter_original_editor_buttons' ], 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues the JavaScript used by the TM editor.
|
||||
*/
|
||||
public function enqueue_js() {
|
||||
wp_enqueue_script( 'wpml-tm-editor-scripts' );
|
||||
wp_localize_script(
|
||||
'wpml-tm-editor-scripts',
|
||||
'tmEditorStrings',
|
||||
$this->get_translation_editor_strings()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function get_translation_editor_strings() {
|
||||
|
||||
$translation_memory_endpoint = apply_filters( 'wpml_st_translation_memory_endpoint', '' );
|
||||
|
||||
return array(
|
||||
'dontShowAgain' => __(
|
||||
"Don't show this again.",
|
||||
'wpml-translation-management'
|
||||
),
|
||||
'learnMore' => __(
|
||||
'<p>The administrator has disabled term translation from the translation editor. </p>
|
||||
<p>If your access permissions allow you can change this under "Translation Management" - "Multilingual Content Setup" - "Block translating taxonomy terms that already got translated". </p>
|
||||
<p>Please note that editing terms from the translation editor will affect all posts that have the respective terms associated.</p>',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
'warning' => __(
|
||||
"Please be advised that editing this term's translation here will change the value of the term in general. The changes made here, will not only affect this post!",
|
||||
'wpml-translation-management'
|
||||
),
|
||||
'title' => __(
|
||||
'Terms translation is disabled',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
'confirm' => __(
|
||||
'You have unsaved work. Are you sure you want to close without saving?',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
'cancel' => __(
|
||||
'Cancel',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
'save' => __(
|
||||
'Save',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
'hide_translated' => __(
|
||||
'Hide completed',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
'save_and_close' => __(
|
||||
'Save & Close',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
'loading_url' => ICL_PLUGIN_URL . '/res/img/ajax-loader.gif',
|
||||
'saving' => __(
|
||||
'Saving...',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
'translation_complete' => __(
|
||||
'Translation is complete',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
'contentNonce' => wp_create_nonce( 'wpml_save_job_nonce' ),
|
||||
'translationMemoryNonce' => \WPML\LIB\WP\Nonce::create( $translation_memory_endpoint ),
|
||||
'translationMemoryEndpoint' => $translation_memory_endpoint,
|
||||
'source_lang' => __(
|
||||
'Original',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
'target_lang' => __(
|
||||
'Translation to',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
'copy_all' => __(
|
||||
'Copy all fields from original',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
'resign' => __(
|
||||
'Resign',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
'resign_translation' => __(
|
||||
'Are you sure you want to resign from this job?',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
'resign_url' => admin_url( 'admin.php?page=' . WPML_TM_FOLDER . '/menu/translations-queue.php&icl_tm_action=save_translation&resign=1&job_id=' . $this->job->get_id() ),
|
||||
'confirmNavigate' => __(
|
||||
'You have unsaved changes!',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
'copy_from_original' => __(
|
||||
'Copy from original',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
'show_diff' => __( 'Show differences', 'wpml-translation-management' ),
|
||||
);
|
||||
}
|
||||
|
||||
public function filter_original_editor_buttons( $config, $editor_id ) {
|
||||
if ( strpos( $editor_id, '_original' ) > 0 ) {
|
||||
$config['toolbar1'] = ' ';
|
||||
$config['toolbar2'] = ' ';
|
||||
$config['readonly'] = '1';
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
public function output_editors( $field ) {
|
||||
echo '<div id="' . $field['field_type'] . '_original_editor" class="original_value mce_editor_origin">';
|
||||
wp_editor(
|
||||
$field['field_data'],
|
||||
$field['field_type'] . '_original',
|
||||
array(
|
||||
'textarea_rows' => 4,
|
||||
'editor_class' => 'wpml_content_tr original_value mce_editor_origin',
|
||||
'media_buttons' => false,
|
||||
'quicktags' => array( 'buttons' => 'empty' ),
|
||||
)
|
||||
);
|
||||
echo '</div>';
|
||||
echo '<div id="' . $field['field_type'] . '_translated_editor" class="mce_editor translated_value">';
|
||||
wp_editor(
|
||||
$field['field_data_translated'],
|
||||
$field['field_type'],
|
||||
array(
|
||||
'textarea_rows' => 4,
|
||||
'editor_class' => 'wpml_content_tr translated_value',
|
||||
'media_buttons' => true,
|
||||
'textarea_name' => 'fields[' . $field['field_type'] . '][data]',
|
||||
)
|
||||
);
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
class WPML_Editor_UI_Field_Group extends WPML_Editor_UI_Fields {
|
||||
|
||||
private $title;
|
||||
private $divider;
|
||||
|
||||
function __construct( $title = '', $divider = true ) {
|
||||
$this->title = $title;
|
||||
$this->divider = $divider;
|
||||
|
||||
}
|
||||
|
||||
public function get_layout() {
|
||||
$data = array(
|
||||
'title' => $this->title,
|
||||
'divider' => $this->divider,
|
||||
'field_type' => 'tm-group',
|
||||
);
|
||||
|
||||
$data['fields'] = parent::get_layout();
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
class WPML_Editor_UI_Field_Image extends WPML_Editor_UI_Fields {
|
||||
|
||||
private $image_id;
|
||||
private $divider;
|
||||
private $group;
|
||||
|
||||
function __construct( $id, $image_id, $data, $divider = true ) {
|
||||
|
||||
$this->image_id = $image_id;
|
||||
$this->divider = $divider;
|
||||
$this->group = new WPML_Editor_UI_Field_Group( '', false );
|
||||
|
||||
$this->group->add_field( new WPML_Editor_UI_Single_Line_Field( $id . '-title', __( 'Title', 'wpml-translation-management' ), $data, false ) );
|
||||
$this->group->add_field( new WPML_Editor_UI_Single_Line_Field( $id . '-caption', __('Caption', 'wpml-translation-management' ), $data, false ) );
|
||||
$this->group->add_field( new WPML_Editor_UI_Single_Line_Field( $id . '-alt-text', __('Alt Text', 'wpml-translation-management' ), $data, false ) );
|
||||
$this->group->add_field( new WPML_Editor_UI_Single_Line_Field( $id . '-description', __('Description', 'wpml-translation-management' ), $data, false ) );
|
||||
|
||||
$this->add_field( $this->group );
|
||||
}
|
||||
|
||||
public function get_layout() {
|
||||
$image = wp_get_attachment_image_src( $this->image_id, array( 100, 100 ) );
|
||||
$data = array(
|
||||
'field_type' => 'wcml-image',
|
||||
'divider' => $this->divider,
|
||||
'image_src' => isset( $image[0] ) ? $image[0] : '',
|
||||
);
|
||||
|
||||
$data['fields'] = parent::get_layout();
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
class WPML_Editor_UI_Field_Section extends WPML_Editor_UI_Fields {
|
||||
|
||||
private $title;
|
||||
private $sub_title;
|
||||
|
||||
function __construct( $title = '', $sub_title = '' ) {
|
||||
$this->title = $title;
|
||||
$this->sub_title = $sub_title;
|
||||
}
|
||||
|
||||
public function get_layout() {
|
||||
$data = array(
|
||||
'empty_message' => '',
|
||||
'empty' => false,
|
||||
'title' => $this->title,
|
||||
'sub_title' => $this->sub_title,
|
||||
'field_type' => 'tm-section',
|
||||
);
|
||||
|
||||
$data['fields'] = parent::get_layout();
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
class WPML_Editor_UI_Field {
|
||||
|
||||
protected $id;
|
||||
protected $title;
|
||||
protected $original;
|
||||
protected $translation;
|
||||
private $requires_complete;
|
||||
protected $is_complete;
|
||||
|
||||
function __construct( $id, $title, $data, $requires_complete = false ) {
|
||||
|
||||
$this->id = $id;
|
||||
$this->title = $title ? $title : '';
|
||||
$this->original = $data[ $id ]['original'];
|
||||
$this->translation = isset( $data[ $id ]['translation'] ) ? $data[ $id ]['translation'] : '';
|
||||
$this->requires_complete = $requires_complete;
|
||||
$this->is_complete = isset( $data[ $id ]['is_complete'] ) ? $data[ $id ]['is_complete'] : false;
|
||||
|
||||
}
|
||||
|
||||
public function get_fields() {
|
||||
$field = array();
|
||||
$field['field_type'] = $this->id;
|
||||
$field['field_data'] = $this->original;
|
||||
$field['field_data_translated'] = $this->translation;
|
||||
$field['title'] = $this->title;
|
||||
$field['field_finished'] = $this->is_complete ? '1' : '0';
|
||||
$field['tid'] = '0';
|
||||
|
||||
return $field;
|
||||
}
|
||||
|
||||
public function get_layout() {
|
||||
// This is a field with no sub fields so just return the id
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
class WPML_Editor_UI_Fields {
|
||||
|
||||
private $fields = array();
|
||||
|
||||
public function add_field( $field ) {
|
||||
$this->fields[] = $field;
|
||||
}
|
||||
|
||||
public function get_fields() {
|
||||
$fields = array();
|
||||
/** @var WPML_Editor_UI_Field $field */
|
||||
foreach ( $this->fields as $field ) {
|
||||
$child_fields = $field->get_fields();
|
||||
foreach ( $child_fields as $child_field ) {
|
||||
$fields[] = $child_field;
|
||||
}
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function get_layout() {
|
||||
$layout = array();
|
||||
/** @var WPML_Editor_UI_Field $field */
|
||||
foreach ( $this->fields as $field ) {
|
||||
$layout[] = $field->get_layout();
|
||||
}
|
||||
|
||||
return $layout;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
class WPML_Editor_UI_Single_Line_Field extends WPML_Editor_UI_Field {
|
||||
|
||||
private $include_copy_button;
|
||||
|
||||
function __construct( $id, $title, $data, $include_copy_button, $requires_complete = false ) {
|
||||
parent::__construct( $id, $title, $data, $requires_complete );
|
||||
|
||||
$this->include_copy_button = $include_copy_button;
|
||||
}
|
||||
|
||||
public function get_fields() {
|
||||
$field = parent::get_fields();
|
||||
$field['field_style'] = '0';
|
||||
|
||||
return array( $field );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
class WPML_Editor_UI_TextArea_Field extends WPML_Editor_UI_Field {
|
||||
|
||||
private $include_copy_button;
|
||||
|
||||
function __construct( $id, $title, $data, $include_copy_button, $requires_complete = false ) {
|
||||
parent::__construct( $id, $title, $data, $requires_complete );
|
||||
|
||||
$this->include_copy_button = $include_copy_button;
|
||||
}
|
||||
|
||||
public function get_fields() {
|
||||
$field = parent::get_fields();
|
||||
$field['field_style'] = '1';
|
||||
|
||||
return array( $field );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
class WPML_Editor_UI_WYSIWYG_Field extends WPML_Editor_UI_Field {
|
||||
|
||||
private $include_copy_button;
|
||||
|
||||
function __construct( $id, $title, $data, $include_copy_button, $requires_complete = false ) {
|
||||
parent::__construct( $id, $title, $data, $requires_complete );
|
||||
|
||||
$this->include_copy_button = $include_copy_button;
|
||||
}
|
||||
|
||||
public function get_fields() {
|
||||
$field = parent::get_fields();
|
||||
$field['field_style'] = '2';
|
||||
|
||||
return array( $field );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user