first commit

This commit is contained in:
2023-09-12 21:41:04 +02:00
commit 3361a7f053
13284 changed files with 2116755 additions and 0 deletions

View File

@@ -0,0 +1,224 @@
<?php
use WPML\Settings\PostTypesUI;
use function \WPML\Container\make;
if ( ! isset( $wpdb ) ) {
global $wpdb;
}
if ( ! isset( $sitepress_settings ) ) {
global $sitepress_settings;
}
if ( ! isset( $sitepress ) ) {
global $sitepress;
}
if ( ! isset( $iclTranslationManagement ) ) {
global $iclTranslationManagement;
}
global $wp_taxonomies;
if ( ! function_exists( 'prepare_synchronization_needed_warning' ) ) {
function prepare_synchronization_needed_warning( $elements, $type ) {
$notice = '';
if ( $elements ) {
$msg = esc_html( __( "You haven't set your synchronization preferences for these %1\$s: %2\$s. Default value was selected.", 'sitepress' ) );
$notice .= '<div class="updated below-h2"><p>';
$notice .= sprintf( $msg, $type, '<i>' . implode( '</i>, <i>', $elements ) . '</i>' );
$notice .= '</p></div>';
}
return $notice;
}
}
$default_language = $sitepress->get_default_language();
$wpml_post_types = new WPML_Post_Types( $sitepress );
$custom_posts = $wpml_post_types->get_translatable_and_readonly();
$custom_posts_sync_not_set = array();
foreach ( $custom_posts as $k => $custom_post ) {
if ( ! isset( $sitepress_settings['custom_posts_sync_option'][ $k ] ) ) {
$custom_posts_sync_not_set[] = $custom_post->labels->name;
}
}
$custom_taxonomies = array_diff( array_keys( (array) $wp_taxonomies ), array( 'nav_menu', 'link_category', 'post_format' ) );
$tax_sync_not_set = array();
foreach ( $custom_taxonomies as $custom_tax ) {
if ( ! isset( $sitepress_settings['taxonomies_sync_option'][ $custom_tax ] ) ) {
$tax_sync_not_set[] = $wp_taxonomies[ $custom_tax ]->label;
}
}
/** @var PostTypesUI $custom_types_ui */
$custom_post_types_ui = make( PostTypesUI::class );
/** @var WPML_Custom_Types_Translation_UI $custom_types_ui */
$custom_tax_types_ui = make( WPML_Custom_Types_Translation_UI::class );
$CPT_slug_UI = $taxonomy_slug_UI = null;
if ( class_exists( 'WPML_ST_Slug_Translation_UI_Factory' ) ) {
$slug_ui_factory = new WPML_ST_Slug_Translation_UI_Factory();
$CPT_slug_UI = $slug_ui_factory->create( WPML_ST_Slug_Translation_UI_Factory::POST )->init();
$taxonomy_slug_UI = $slug_ui_factory->create( WPML_ST_Slug_Translation_UI_Factory::TAX )->init();
}
if ( $custom_posts ) {
$notice = prepare_synchronization_needed_warning( $custom_posts_sync_not_set, 'custom posts' );
?>
<div class="wpml-section" id="ml-content-setup-sec-7">
<div class="wpml-section-header">
<h3><?php esc_html_e( 'Post Types Translation', 'sitepress' ); ?></h3>
</div>
<div class="wpml-section-content wpml-section-content-wide">
<?php
if ( isset( $notice ) ) {
echo $notice;
}
?>
<form id="icl_custom_posts_sync_options" name="icl_custom_posts_sync_options"
class="js_element_type_sync_options" action="">
<?php wp_nonce_field( 'icl_custom_posts_sync_options_nonce', '_icl_nonce' ); ?>
<div class="wpml-flex-table wpml-translation-setup-table wpml-margin-top-sm">
<?php $custom_post_types_ui->render_custom_types_header_ui( esc_html__( 'Post types', 'sitepress' ) ); ?>
<div class="wpml-flex-table-body">
<?php
foreach ( $custom_posts as $k => $custom_post ) :
$disabled = isset( $iclTranslationManagement->settings['custom-types_readonly_config'][ $k ] );
$translation_mode = WPML_CONTENT_TYPE_DONT_TRANSLATE;
if ( isset( $sitepress_settings['custom_posts_sync_option'][ $k ] ) ) {
$translation_mode = (int) $sitepress_settings['custom_posts_sync_option'][ $k ];
}
$unlocked = false;
if ( isset( $sitepress_settings['custom_posts_unlocked_option'][ $k ] ) ) {
$unlocked = (int) $sitepress_settings['custom_posts_unlocked_option'][ $k ];
}
?>
<div class="wpml-flex-table-row wpml-flex-table-row-wrap js-type-translation-row">
<?php
$custom_post_types_ui->render_row(
esc_html( $custom_post->labels->name ),
'icl_sync_custom_posts',
$k,
$disabled,
$translation_mode,
$unlocked,
esc_html( $custom_post->labels->singular_name )
);
if ( $CPT_slug_UI ) {
?>
<div class="wpml-flex-table-cell-span">
<?php echo $CPT_slug_UI->render( $k, $custom_post ); ?>
</div>
<?php } ?>
</div>
<?php endforeach; ?>
</div>
</div>
<p class="buttons-wrap">
<span class="icl_ajx_response" id="icl_ajx_response_cp"></span>
<input type="submit"
id="wpml_post_type_save_legacy"
class="js_element_type_sync_button button button-primary"
value="<?php esc_attr_e( 'Save', 'sitepress' ); ?>" style="display:none"/>
<span id="wpml_post_type_save" style="display: inline-block"></span>
</p>
</form>
</div> <!-- .wpml-section-content -->
</div> <!-- wpml-section -->
<?php
}
if ( $custom_taxonomies ) {
$notice = prepare_synchronization_needed_warning( $tax_sync_not_set, 'taxonomies' );
?>
<div class="wpml-section" id="ml-content-setup-sec-8">
<div class="wpml-section-header">
<h3><?php esc_html_e( 'Taxonomies Translation', 'sitepress' ); ?></h3>
</div>
<div class="wpml-section-content wpml-section-content-wide">
<?php
if ( isset( $notice ) ) {
echo $notice;
}
?>
<form id="icl_custom_tax_sync_options" name="icl_custom_tax_sync_options"
class="js_element_type_sync_options" action="">
<?php wp_nonce_field( 'icl_custom_tax_sync_options_nonce', '_icl_nonce' ); ?>
<div class="wpml-flex-table wpml-translation-setup-table wpml-margin-top-sm">
<?php $custom_tax_types_ui->render_custom_types_header_ui( esc_html__( 'Taxonomy', 'sitepress' ) ); ?>
<div class="wpml-flex-table-body">
<?php
foreach ( $custom_taxonomies as $ctax ) :
$disabled = isset( $iclTranslationManagement->settings['taxonomies_readonly_config'][ $ctax ] );
$translation_mode = WPML_CONTENT_TYPE_DONT_TRANSLATE;
if ( isset( $sitepress_settings['taxonomies_sync_option'][ $ctax ] ) ) {
$translation_mode = (int) $sitepress_settings['taxonomies_sync_option'][ $ctax ];
}
$unlocked = false;
if ( isset( $sitepress_settings['taxonomies_unlocked_option'][ $ctax ] ) ) {
$unlocked = (int) $sitepress_settings['taxonomies_unlocked_option'][ $ctax ];
}
?>
<div class="wpml-flex-table-row wpml-flex-table-row-wrap js-type-translation-row">
<?php
$custom_tax_types_ui->render_row(
esc_html( $wp_taxonomies[ $ctax ]->label ),
'icl_sync_tax',
$ctax,
$disabled,
$translation_mode,
$unlocked
);
$slug_UI = apply_filters( 'wpml_taxonomy_slug_translation_ui', $taxonomy_slug_UI, $ctax );
if ( $slug_UI ) {
?>
<div class="wpml-flex-table-cell-span">
<?php echo $slug_UI->render( $ctax, $wp_taxonomies[ $ctax ] ); ?>
</div>
<?php } ?>
</div>
<?php endforeach; ?>
</div>
</div>
<p class="buttons-wrap">
<span class="icl_ajx_response" id="icl_ajx_response_ct"></span>
<input type="submit"
class="js_element_type_sync_button button-primary"
value="<?php esc_html_e( 'Save', 'sitepress' ); ?>" />
</p>
</form>
</div> <!-- .wpml-section-content -->
</div> <!-- wpml-section -->
<?php
}

View File

@@ -0,0 +1,72 @@
<?php
global $sitepress, $sitepress_settings;
?>
<div class="wpml-section" id="ml-content-setup-sec-wp-login">
<div class="wpml-section-header">
<h3><?php esc_html_e( 'Login and registration pages', 'sitepress' ); ?></h3>
</div>
<div class="wpml-section-content">
<form id="icl_login_page_translation" name="icl_login_page_translation" action="">
<?php
wp_nonce_field( 'icl_login_page_translation_nonce', '_icl_nonce' );
$login_page_documentation_url = 'https://wpml.org/documentation/getting-started-guide/translating-wordpress-login-and-registration-pages/?utm_source=plugin&utm_medium=gui&utm_campaign=wpmlcore';
?>
<p>
<label>
<input type="checkbox" id="login_page_translation"
name="login_page_translation"
<?php checked( get_option( \WPML\UrlHandling\WPLoginUrlConverter::SETTINGS_KEY, false ) ); ?>
value="1"/>
<?php esc_html_e( 'Allow translating the login and registration pages', 'sitepress' ); ?>
</label>
<br/>
<a href="<?php esc_attr_e( $login_page_documentation_url ); ?>" target="_blank"
class="wpml-external-link">
<?php esc_html_e( 'How to translate login and registration pages', 'sitepress' ); ?>
</a>
<br/>
<p class="sub-section" id="show_login_page_language_switcher_sub_section"
<?php if ( ! get_option( \WPML\UrlHandling\WPLoginUrlConverter::SETTINGS_KEY, false ) ) : ?> style="display: none" <?php endif; ?>
>
<label>
<input type="checkbox" id="show_login_page_language_switcher"
name="show_login_page_language_switcher"
<?php checked( get_option( \WPML\AdminLanguageSwitcher\AdminLanguageSwitcher::LANGUAGE_SWITCHER_KEY, true ) ); ?>
value="1"/>
<?php esc_html_e( 'Show Language Switcher on login and registration pages', 'sitepress' ); ?>
</label>
</p>
</p>
<div class="notice-info notice below-h2">
<p>
<?php
esc_html_e( 'If your site uses nginx, you may need to adjust your server settings. ', 'sitepress' );
$nginx_documentation_url = 'https://wpml.org/documentation/getting-started-guide/translating-wordpress-login-and-registration-pages/?utm_source=plugin&utm_medium=gui&utm_campaign=wpmlcore#server-requirements-for-sites-that-use-nginx';
/* translators: "server requirements for sites that use nginx" is a link added to the end of "Read more about the" */
$link_to_documentation = '<a class="wpml-external-link" target="_blank" href="' . $nginx_documentation_url . '">'
. esc_html__( 'server requirements for sites that use nginx', 'sitepress' )
. '</a>';
/* translators: $s: a link with "server requirements for sites that use nginx" as a text */
echo sprintf( esc_html__( ' Read more about the %s.', 'sitepress' ), $link_to_documentation );
?>
</p>
</div>
<div class="wpml-section-content-inner">
<p class="buttons-wrap">
<span class="icl_ajx_response" id="icl_ajx_response_login"></span>
<input class="button button-primary" name="save" value="<?php esc_attr_e( 'Save', 'sitepress' ); ?>"
type="submit"/>
</p>
</div>
</form>
</div> <!-- wpml-section-content -->
</div> <!-- .wpml-section -->

View File

@@ -0,0 +1,104 @@
<?php
global $sitepress, $sitepress_settings;
?>
<div class="wpml-section" id="ml-content-setup-sec-2">
<div class="wpml-section-header">
<h3><?php esc_html_e( 'Posts and pages synchronization', 'sitepress' ); ?></h3>
</div>
<div class="wpml-section-content">
<form id="icl_page_sync_options" name="icl_page_sync_options" action="">
<?php wp_nonce_field( 'icl_page_sync_options_nonce', '_icl_nonce' ); ?>
<div class="wpml-section-content-inner">
<p>
<label><input type="checkbox" id="icl_sync_page_ordering" name="icl_sync_page_ordering" <?php checked( $sitepress_settings['sync_page_ordering'] ) ?> value="1" />
<?php esc_html_e( 'Synchronize page order for translations', 'sitepress' ) ?></label>
</p>
<p>
<label><input type="checkbox" id="icl_sync_page_parent" name="icl_sync_page_parent" <?php checked( $sitepress_settings['sync_page_parent'] ) ?> value="1" />
<?php esc_html_e( 'Set page parent for translation according to page parent of the original language', 'sitepress' ) ?></label>
</p>
<p>
<label><input type="checkbox" name="icl_sync_page_template" <?php checked( $sitepress_settings['sync_page_template'] ) ?> value="1" />
<?php esc_html_e( 'Synchronize page template', 'sitepress' ) ?></label>
</p>
<p>
<label><input type="checkbox" name="icl_sync_comment_status" <?php checked( $sitepress_settings['sync_comment_status'] ) ?> value="1" />
<?php esc_html_e( 'Synchronize comment status', 'sitepress' ) ?></label>
</p>
<p>
<label><input type="checkbox" name="icl_sync_ping_status" <?php checked( $sitepress_settings['sync_ping_status'] ) ?> value="1" />
<?php esc_html_e( 'Synchronize ping status', 'sitepress' ) ?></label>
</p>
<p>
<label><input type="checkbox" name="icl_sync_sticky_flag" <?php checked( $sitepress_settings['sync_sticky_flag'] ) ?> value="1" />
<?php esc_html_e( 'Synchronize sticky flag', 'sitepress' ) ?></label>
</p>
<p>
<label><input type="checkbox" name="icl_sync_password" <?php checked( $sitepress_settings['sync_password'] ) ?> value="1" />
<?php esc_html_e( 'Synchronize password for password protected posts', 'sitepress' ) ?></label>
</p>
<p>
<label><input type="checkbox" name="icl_sync_private_flag" <?php checked( $sitepress_settings['sync_private_flag'] ) ?> value="1" />
<?php esc_html_e( 'Synchronize private flag', 'sitepress' ) ?></label>
</p>
<p>
<label><input type="checkbox" name="icl_sync_post_format" <?php checked( $sitepress_settings['sync_post_format'] ) ?> value="1" />
<?php esc_html_e( 'Synchronize posts format', 'sitepress' ) ?></label>
</p>
</div>
<div class="wpml-section-content-inner">
<p>
<label><input type="checkbox" name="icl_sync_delete" <?php checked( $sitepress_settings['sync_delete'] ) ?> value="1" />
<?php esc_html_e( 'When deleting a post, delete translations as well', 'sitepress' ) ?></label>
</p>
<p>
<label><input type="checkbox" name="icl_sync_delete_tax" <?php checked( $sitepress_settings['sync_delete_tax'] ) ?> value="1" />
<?php esc_html_e( 'When deleting a taxonomy (category, tag or custom), delete translations as well', 'sitepress' ) ?></label>
</p>
</div>
<div class="wpml-section-content-inner">
<p>
<label><input type="checkbox" name="icl_sync_post_taxonomies" <?php checked( $sitepress_settings['sync_post_taxonomies'] ) ?> value="1" />
<?php esc_html_e( 'Copy taxonomy to translations', 'sitepress' ) ?></label>
</p>
<p>
<label><input type="checkbox" name="icl_sync_post_date" <?php checked( $sitepress_settings['sync_post_date'] ) ?> value="1" />
<?php esc_html_e( 'Copy publishing date to translations', 'sitepress' ) ?></label>
</p>
</div>
<?php if ( defined( 'WPML_TM_VERSION' ) ): ?>
<div class="wpml-section-content-inner">
<p>
<label><input type="checkbox" name="icl_sync_comments_on_duplicates" <?php checked( $sitepress->get_setting( 'sync_comments_on_duplicates' ) ) ?> value="1" />
<?php esc_html_e( 'Synchronize comments on duplicate content', 'sitepress' ) ?></label>
</p>
</div>
<div class="wpml-section-content-inner">
<h4><?php esc_html_e( 'Page builders options', 'sitepress' ) ?></h4>
<?php $wpml_page_builder_options = new WPML_Page_Builder_Settings(); ?>
<label><input type="checkbox" name="wpml_pb_translate_raw_html" <?php checked( $wpml_page_builder_options->is_raw_html_translatable() ); ?> value="1" />
<?php esc_html_e( 'Send to translation the content of raw HTML cells', 'sitepress' ) ?></label>
</p>
</div>
<?php endif; ?>
<div class="wpml-section-content-inner">
<p class="buttons-wrap">
<span class="icl_ajx_response" id="icl_ajx_response_mo"></span>
<input class="button button-primary" name="save" value="<?php esc_attr_e( 'Save', 'sitepress' ) ?>" type="submit" />
</p>
</div>
</form>
</div> <!-- wpml-section-content -->
</div> <!-- .wpml-section -->

View File

@@ -0,0 +1,15 @@
<?php
class WPML_Post_Status_Display_Factory {
/** @var SitePress $sitepress */
private $sitepress;
public function __construct( SitePress $sitepress = null ) {
$this->sitepress = $sitepress ?: $GLOBALS['sitepress'];
}
public function create() {
return new WPML_Post_Status_Display( $this->sitepress->get_active_languages() );
}
}

View File

@@ -0,0 +1,94 @@
<?php
use WPML\TM\API\Basket;
class WPML_Dashboard_Ajax {
/** @var WPML_Super_Globals_Validation $super_globals*/
private $super_globals;
public function __construct( WPML_Super_Globals_Validation $super_globals ) {
$this->super_globals = $super_globals;
}
public function init_ajax_actions() {
add_action( 'wp_ajax_wpml_duplicate_dashboard', array( $this, 'wpml_duplicate_dashboard' ) );
add_action( 'wp_ajax_wpml_need_sync_message', array( $this, 'wpml_need_sync_message' ) );
}
public function enqueue_js() {
wp_register_script(
'wpml-tm-dashboard-scripts',
WPML_TM_URL . '/res/js/tm-dashboard/wpml-tm-dashboard.js',
array( 'jquery', 'backbone', 'wpml-tm-progressbar' ),
WPML_TM_VERSION
);
$wpml_tm_strings = $this->get_wpml_tm_script_js_strings();
wp_localize_script( 'wpml-tm-dashboard-scripts', 'wpml_tm_strings', $wpml_tm_strings );
wp_enqueue_script( 'wpml-tm-dashboard-scripts' );
wp_enqueue_script( OTGS_Assets_Handles::POPOVER_TOOLTIP );
wp_enqueue_style( OTGS_Assets_Handles::POPOVER_TOOLTIP );
}
private function get_wpml_tm_script_js_strings() {
$wpml_tm_strings = array(
'BB_default' => Basket::shouldUse()
? __( 'Add selected content to translation basket', 'wpml-translation-management' )
: __( 'Translate selected content', 'wpml-translation-management' ),
'BB_mixed_actions' => __(
'Add selected content to translation basket / Duplicate',
'wpml-translation-management'
),
'BB_duplicate_all' => __( 'Duplicate', 'wpml-translation-management' ),
'BB_no_actions' => __(
'Choose at least one translation action',
'wpml-translation-management'
),
'duplication_complete' => __(
'Finished Post Duplication',
'wpml-translation-management'
),
'wpml_duplicate_dashboard_nonce' => wp_create_nonce( 'wpml_duplicate_dashboard_nonce' ),
'wpml_need_sync_message_nonce' => wp_create_nonce( 'wpml_need_sync_message_nonce' ),
'duplicating' => __( 'Duplicating', 'wpml-translation-management' ),
'post_parent' => __( 'Post parent', 'wpml-translation-management' ),
'any' => __( 'Any', 'wpml-translation-management' ),
);
return $wpml_tm_strings;
}
public function wpml_duplicate_dashboard() {
if ( ! wpml_is_action_authenticated( 'wpml_duplicate_dashboard' ) ) {
wp_send_json_error( 'Wrong Nonce' );
}
global $sitepress;
$post_ids = filter_var( $_POST['duplicate_post_ids'], FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
$languages = filter_var( $_POST['duplicate_target_languages'], FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
$res = array();
foreach ( $post_ids as $pid ) {
foreach ( $languages as $lang_code ) {
if ( $sitepress->make_duplicate( $pid, $lang_code ) !== false ) {
$res[ $lang_code ] = $pid;
}
}
}
wp_send_json_success( $res );
}
public function wpml_need_sync_message() {
if ( ! wpml_is_action_authenticated( 'wpml_need_sync_message' ) ) {
wp_send_json_error( 'Wrong Nonce' );
return;
}
$post_ids = $this->super_globals->post( 'duplicated_post_ids' );
$post_ids = array_values( array_filter( explode( ',', $post_ids ) ) );
do_action( 'wpml_new_duplicated_terms', $post_ids );
wp_send_json_success();
}
}

View File

@@ -0,0 +1,547 @@
<?php
use WPML\FP\Lst;
use WPML\FP\Obj;
use WPML\LIB\WP\Hooks;
/**
* Class WPML_TM_Dashboard
*/
class WPML_TM_Dashboard {
const LIMIT_RETRIEVED_POSTS_VALUE = 200;
/**
* @var array
*/
private $translatable_post_types = null;
/**
* @var wpdb
*/
private $wpdb;
/**
* @var SitePress
*/
private $sitepress;
/**
* @var int
*/
private $found_documents = 0;
/**
* WPML_TM_Dashboard constructor.
*
* @param wpdb $wpdb
* @param SitePress $sitepress
*/
public function __construct( wpdb $wpdb, SitePress $sitepress ) {
$this->wpdb = $wpdb;
$this->sitepress = $sitepress;
add_filter( 'posts_where', array( $this, 'add_dashboard_filter_conditions' ), 10, 2 );
}
/**
* @param array $args
*
* @return array
*/
public function get_documents( $args = array() ) {
$results = array();
$documents = array();
$defaults = array(
'from_lang' => 'en',
'to_lang' => '',
'tstatus' => - 1,
'sort_by' => 'date',
'sort_order' => 'DESC',
'limit_no' => ICL_TM_DOCS_PER_PAGE,
'parent_type' => 'any',
'parent_id' => false,
'type' => '',
'title' => '',
'status' => array( 'publish', 'pending', 'draft', 'future', 'private', 'inherit' ),
'page' => 0,
);
$args = $this->remove_empty_arguments( $args );
$args = wp_parse_args( $args, $defaults );
$documents = $this->add_string_packages( $documents, $args );
$documents = $this->add_translatable_posts( $documents, $args );
$filtered_documents = apply_filters( 'wpml_tm_dashboard_documents', $documents );
$countAfterFilter = count( $documents ) - count( $filtered_documents );
/**
* Slicing the posts and string packages array according to page number and limit of posts per page.
*
* @see https://onthegosystems.myjetbrains.com/youtrack/issue/wpmldev-616
*/
$filtered_documents = Lst::slice( $args['page'] * $args['limit_no'], $args['limit_no'], $filtered_documents );
$results['documents'] = $filtered_documents;
$results['found_documents'] = $this->found_documents - $countAfterFilter;
return $results;
}
/**
* @param $args
*
* @return array
*/
private function remove_empty_arguments( $args ) {
$output = array();
foreach ( $args as $argument_name => $argument_value ) {
if ( '' !== $argument_value && null !== $argument_value ) {
$output[ $argument_name ] = $argument_value;
}
}
return $output;
}
/**
* Add list of translatable post types to dashboard.
*
* @param array $results
* @param array $args
*
* @return array
*/
private function add_translatable_posts( $results, $args ) {
$dashboardPagination = new WPML_TM_Dashboard_Pagination();
$post_types = $this->get_translatable_post_types();
if ( $this->is_cpt_type( $args ) ) {
$post_types = array( $args['type'] );
} elseif ( ! empty( $args['type'] ) ) {
return $results;
}
/**
* Preparing query arguments without specific pagination args and with 'no_found_rows = true' to avoid extra query for getting total posts number
* That's done because we're already limiting the number of retrieved posts based on number set in self::LIMIT_RETRIEVED_POSTS_VALUE constant
*
* @see https://onthegosystems.myjetbrains.com/youtrack/issue/wpmldev-616
*/
$query_args = [
'post_type' => $post_types,
'orderby' => $args['sort_by'],
'order' => $args['sort_order'],
'post_status' => $args['status'],
'post_language' => $args['from_lang'],
'post_language_to' => $args['to_lang'],
'post_translation_status' => $args['tstatus'],
'suppress_filters' => false,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'no_found_rows' => true,
];
if ( 'any' !== $args['parent_type'] ) {
switch ( $args['parent_type'] ) {
case 'page':
$query_args['post_parent'] = (int) $args['parent_id'];
break;
default:
$query_args['tax_query'] = array(
array(
'taxonomy' => $args['parent_type'],
'field' => 'term_id',
'terms' => (int) $args['parent_id'],
),
);
break;
}
}
if ( isset( $args['translation_priority'] ) ) {
$translation_priorities = new WPML_TM_Translation_Priorities();
if ( $translation_priorities->get_default_value_id() === (int) $args['translation_priority'] ) {
$tax_query = array(
'relation' => 'OR',
array(
'taxonomy' => 'translation_priority',
'operator' => 'NOT EXISTS',
),
);
}
$tax_query[] = array(
'taxonomy' => 'translation_priority',
'field' => 'term_id',
'terms' => $args['translation_priority'],
);
$query_args['tax_query'] = $tax_query;
}
if ( ! empty( $args['title'] ) ) {
$query_args['post_title_like'] = $args['title'];
}
$lang = $this->sitepress->get_admin_language();
$this->sitepress->switch_lang( $args['from_lang'] );
/**
* Callback function that queries and prepares posts documents
*
* @return array
*
* @see https://onthegosystems.myjetbrains.com/youtrack/issue/wpmldev-616
*/
$preparePosts = function () use ( $query_args, $results, $lang ) {
$query = new WPML_TM_WP_Query( $query_args );
$this->sitepress->switch_lang( $lang );
if ( ! empty( $query->posts ) ) {
foreach ( $query->posts as $post ) {
$language_details = $this->sitepress->get_element_language_details( $post->ID, 'post_' . $post->post_type );
$post_obj = new stdClass();
$post_obj->ID = $post->ID;
$post_obj->translation_element_type = 'post_' . $post->post_type;
$post_obj->title = $post->post_title;
$post_obj->is_translation = ( null === $language_details->source_language_code ) ? '0' : '1';
$post_obj->language_code = $language_details->language_code;
$post_obj->trid = $language_details->trid;
$results[] = $post_obj;
}
}
/**
* Setting value of found documents depending on actual number of posts retrieved from database.
*
* @see https://onthegosystems.myjetbrains.com/youtrack/issue/wpmldev-616
*/
$this->found_documents += $query->getPostCount();
return $results;
};
$dashboardPagination->setPostsLimitValue( self::LIMIT_RETRIEVED_POSTS_VALUE );
$results = Hooks::callWithFilter( $preparePosts, 'post_limits', [
$dashboardPagination,
'getPostsLimitQueryValue'
] );
$dashboardPagination->resetPostsLimitValue();
wp_reset_query();
return $results;
}
/**
* Add additional where conditions to support the following query arguments:
* - post_title_like - Allow query posts with SQL LIKE in post title.
* - post_language_to - Allow query posts with language they are translated to.
* - post_translation_status - Allow to query posts by their translation status.
*
* @param string $where
* @param object $wp_query
*
* @return string
*/
public function add_dashboard_filter_conditions( $where, $wp_query ) {
$post_title_like = $wp_query->get( 'post_title_like' );
$post_language = $wp_query->get( 'post_language_to' );
$post_translation_status = $wp_query->get( 'post_translation_status' );
if ( $post_title_like ) {
$where .= $this->wpdb->prepare( " AND {$this->wpdb->posts}.post_title LIKE '%s'", '%' . $this->wpdb->esc_like( $post_title_like ) . '%' );
}
$post_type = $wp_query->get( 'post_type' );
if ( Lst::includes( $post_type[0], $this->get_translatable_post_types() ) ) {
$where .= $this->build_translation_status_where( $post_translation_status, $post_language );
}
return $where;
}
/**
* Add string packages to translation dashboard.
*
* @param array $results
* @param array $args
*
* @return array
*/
private function add_string_packages( $results, $args ) {
$string_packages_table = $this->wpdb->prefix . 'icl_string_packages';
$translations_table = $this->wpdb->prefix . 'icl_translations';
if ( $this->is_cpt_type( $args ) ) {
return array();
}
if ( ! is_plugin_active( 'wpml-string-translation/plugin.php' ) ) {
return $results;
}
// Exit if *icl_string_packages table doesn't exist.
if ( $this->wpdb->get_var( "SHOW TABLES LIKE '$string_packages_table'" ) !== $string_packages_table ) {
return $results;
}
$where = $this->create_string_packages_where( $args );
$postsLimit = self::LIMIT_RETRIEVED_POSTS_VALUE;
$sql = "SELECT DISTINCT
st_table.ID,
st_table.kind_slug,
st_table.title,
wpml_translations.element_type,
wpml_translations.language_code,
wpml_translations.source_language_code,
wpml_translations.trid
FROM {$string_packages_table} AS st_table
LEFT JOIN {$translations_table} AS wpml_translations
ON wpml_translations.element_id=st_table.ID OR wpml_translations.element_id = null
WHERE 1 = 1 {$where}
GROUP BY st_table.ID
ORDER BY st_table.ID ASC
LIMIT {$postsLimit}";
$sql = apply_filters( 'wpml_tm_dashboard_external_type_sql_query', $sql, $args );
$packages = $this->wpdb->get_results( $sql );
foreach ( $packages as $package ) {
$package_obj = new stdClass();
$package_obj->ID = $package->ID;
$package_obj->translation_element_type = WPML_Package_Translation::get_package_element_type( $package->kind_slug );
$package_obj->title = $package->title;
$package_obj->is_translation = ( null === $package->source_language_code ) ? '0' : '1';
$package_obj->language_code = $package->language_code;
$package_obj->trid = $package->trid;
$results[] = $package_obj;
}
/**
* Setting value of found documents depending on actual number of string packages retrieved from database.
*
* @see https://onthegosystems.myjetbrains.com/youtrack/issue/wpmldev-616
*/
$this->found_documents += count( $packages );
return $results;
}
/**
* Create additional where clause for querying string packages based on filters.
*
* @param array $args
*
* @return string
*/
private function create_string_packages_where( $args ) {
$where = " AND wpml_translations.element_type LIKE 'package%' AND st_table.post_id IS NULL";
if ( ! $this->is_cpt_type( $args ) && ! empty( $args['type'] ) ) {
$where .= $this->wpdb->prepare( " AND kind_slug='%s'", $args['type'] );
}
if ( ! empty( $args['title'] ) ) {
$where .= $this->wpdb->prepare( " AND title LIKE '%s'", '%' . $this->wpdb->esc_like( $args['title'] ) . '%' );
}
if ( ! empty( $args['to_lang'] ) ) {
$where .= $this->wpdb->prepare( " AND wpml_translations.language_code='%s'", $args['to_lang'] );
$where .= $this->wpdb->prepare( " AND wpml_translations.source_language_code='%s'", $args['from_lang'] );
} else {
$where .= $this->wpdb->prepare( " AND wpml_translations.language_code='%s'", $args['from_lang'] );
}
if ( $args['tstatus'] >= 0 ) {
$where .= $this->build_translation_status_where( $args['tstatus'] );
}
return $where;
}
/**
* @param string|int $translation_status
* @param string $language
*
* @return string
*/
private function build_translation_status_where( $translation_status, $language = null ) {
if ( $translation_status < 0 && ! $language ) {
return '';
}
if ( $translation_status < 0 && $language ) {
$subquery = $this->only_language_condition( $language );
} else {
switch ( $translation_status ) {
case ICL_TM_NOT_TRANSLATED . '_' . ICL_TM_NEEDS_UPDATE:
$subquery = $this->not_translated_or_needs_update_condition( $language );
break;
case ICL_TM_NOT_TRANSLATED:
$subquery = $this->not_translated_or_needs_update_condition( $language, false );
break;
case ICL_TM_NEEDS_UPDATE:
$subquery = $this->needs_update_condition( $language );
break;
case ICL_TM_IN_PROGRESS:
$subquery = $this->explicit_status_condition(
wpml_prepare_in( [ ICL_TM_IN_PROGRESS, ICL_TM_WAITING_FOR_TRANSLATOR ], '%d' ),
$language
);
break;
case ICL_TM_COMPLETE:
$subquery = $this->explicit_status_condition(
wpml_prepare_in( [ ICL_TM_COMPLETE, ICL_TM_DUPLICATE ], '%d' ),
$language
);
break;
default:
$subquery = '';
}
}
if ( $subquery ) {
return " AND wpml_translations.trid IN ({$subquery})";
}
return '';
}
private function only_language_condition( $language ) {
$query = "
SELECT translations.trid
FROM {$this->wpdb->prefix}icl_translations translations
WHERE translations.language_code = %s
";
return $this->wpdb->prepare( $query, $language );
}
private function explicit_status_condition( $status, $language = null ) {
$prefix = $this->wpdb->prefix;
$query = "
SELECT trid
FROM {$prefix}icl_translations translations
INNER JOIN {$prefix}icl_translation_status translation_status ON translation_status.translation_id = translations.translation_id
WHERE (translation_status.status IN ({$status}) AND translation_status.needs_update = 0)
";
if ( $language ) {
$query .= $this->language_where( $language );
}
return $query;
}
private function needs_update_condition( $language = null ) {
$prefix = $this->wpdb->prefix;
$query = "
SELECT trid
FROM {$prefix}icl_translations translations
INNER JOIN {$prefix}icl_translation_status translation_status ON translation_status.translation_id = translations.translation_id
WHERE translation_status.needs_update = 1
";
if ( $language ) {
$query .= $this->language_where( $language );
}
return $query;
}
private function not_translated_or_needs_update_condition( $language = null, $withNeedsUpdate = true ) {
$prefix = $this->wpdb->prefix;
if ( $withNeedsUpdate ) {
$needsUpdatePart = 'translation_status.needs_update = 1 OR ';
} else {
$needsUpdatePart = '';
}
$query = "
SELECT trid
FROM {$prefix}icl_translations translations
INNER JOIN {$prefix}icl_translation_status translation_status ON translation_status.translation_id = translations.translation_id
WHERE ( $needsUpdatePart translation_status.status = 0 )
";
if ( $language ) {
$query .= $this->language_where( $language );
}
$query .= ' UNION ';
if ( $language ) {
$query .= "
SELECT trid
FROM {$prefix}icl_translations translations
WHERE NOT EXISTS (
SELECT inner_translations.trid
FROM {$prefix}icl_translations inner_translations
WHERE inner_translations.trid = translations.trid AND inner_translations.language_code = %s
)
";
$query = $this->wpdb->prepare( $query, $language );
} else {
$query .= "
SELECT trid
FROM {$prefix}icl_translations translations
WHERE (
SELECT COUNT(inner_translations.trid)
FROM {$prefix}icl_translations inner_translations
WHERE inner_translations.trid = translations.trid
) < %d
";
$query = $this->wpdb->prepare( $query, count( $this->sitepress->get_active_languages() ) );
}
return $query;
}
private function language_where( $language ) {
return $this->wpdb->prepare( ' AND translations.language_code = %s', $language );
}
/**
* @param array $args
* @param string $post_type
*
* @return bool
*/
private function is_cpt_type( $args = array(), $post_type = '' ) {
$is_cpt_type = false;
if ( ! empty( $args ) && '' === $post_type && array_key_exists( 'type', $args ) && ! empty( $args['type'] ) ) {
$post_type = $args['type'];
}
if ( in_array( $post_type, $this->get_translatable_post_types() ) ) {
$is_cpt_type = true;
}
return $is_cpt_type;
}
/**
* @return array
*/
private function get_translatable_post_types() {
if ( null === $this->translatable_post_types ) {
$translatable_post_types = $this->sitepress->get_translatable_documents();
$this->translatable_post_types = array_keys( apply_filters( 'wpml_tm_dashboard_translatable_types', $translatable_post_types ) );
}
return $this->translatable_post_types;
}
}

View File

@@ -0,0 +1,41 @@
<?php
require_once WPML_PLUGIN_PATH . '/inc/functions-debug-information.php';
$debug_info = get_debug_info();
$debug_data = $debug_info->run();
/* DEBUG ACTION */
/**
* @param $term_object
*
* @return callable
*/
?>
<div class="wrap">
<h1><?php echo __( 'Debug information', 'sitepress' ); ?></h1>
<?php
$message = filter_input( INPUT_GET, 'message', FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_NULL_ON_FAILURE );
if ( $message ) {
?>
<div class="updated message fade"><p>
<?php echo esc_html( $message ); ?>
</p></div>
<?php } ?>
<div id="poststuff">
<div id="wpml-debug-info" class="postbox">
<div class="inside">
<p><?php _e( 'This information allows our support team to see the versions of WordPress, plugins and theme on your site. Provide this information if requested in our support forum. No passwords or other confidential information is included.', 'sitepress' ); ?></p>
<br/>
<?php
echo '<textarea style="font-size:10px;width:100%;height:150px;" rows="16" readonly="readonly">';
echo esc_html( $debug_info->do_json_encode( $debug_data ) );
echo '</textarea>';
?>
</div>
</div>
</div>
<?php do_action( 'icl_menu_footer' ); ?>
</div>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,806 @@
<?php
/* var WPML_Language_Switcher $wpml_language_switcher */
global $sitepress, $sitepress_settings, $wpdb, $wpml_language_switcher;
if ( ! is_plugin_active( WPML_PLUGIN_BASENAME ) ) {
?>
<h2><?php esc_html_e( 'Setup WPML', 'sitepress' ); ?></h2>
<div class="updated fade">
<p style="line-height:1.5"><?php esc_html_e( 'The WPML Multilingual CMS plugin is not currently enabled.', 'sitepress' ); ?></p>
<p style="line-height:1.5">
<?php
echo sprintf(
esc_html__( 'Please go to the %1$sPlugins%2$s page and enable the WPML Multilingual CMS plugin before trying to configure the plugin.', 'sitepress' ),
'<a href="plugins.php">',
'</a>'
)
?>
</p>
</div>
<?php
return;
}
if ( isset( $_GET['trop'] ) ) {
require_once dirname( __FILE__ ) . '/edit-languages.php';
global $icl_edit_languages;
$flags_factory = new WPML_Flags_Factory( $wpdb );
$icl_edit_languages = new SitePress_EditLanguages( $flags_factory->create() );
$icl_edit_languages->render();
return;
}
$sitepress_settings = get_option( 'icl_sitepress_settings' );
$active_languages = $sitepress->get_active_languages();
$hidden_languages = $sitepress->get_setting( 'hidden_languages' );
$show_untranslated_blog_posts = $sitepress->get_setting( 'show_untranslated_blog_posts' );
$automatic_redirect = $sitepress->get_setting( 'automatic_redirect' );
$setting_urls = $sitepress->get_setting( 'urls' );
$existing_content_language_verified = $sitepress->get_setting( 'existing_content_language_verified' );
$language_negotiation_type = $sitepress->get_setting( 'language_negotiation_type' );
$seo = $sitepress->get_setting( 'seo' );
$default_language = $sitepress->get_default_language();
$all_languages = $sitepress->get_languages( $sitepress->get_admin_language() );
$sample_lang = false;
$default_language_details = false;
$wp_api = $sitepress->get_wp_api();
$should_hide_admin_language = $wp_api->version_compare_naked( get_bloginfo( 'version' ), '4.7', '>=' );
$encryptor = new WPML_Data_Encryptor();
$inactive_content = null;
if ( ! $existing_content_language_verified ) {
// try to determine the blog language
$blog_current_lang = 0;
if ( $blog_lang = get_option( 'WPLANG' ) ) {
$exp = explode( '_', $blog_lang );
$blog_current_lang = $wpdb->get_var(
$wpdb->prepare(
"SELECT code FROM {$wpdb->prefix}icl_languages WHERE code= %s",
$exp[0]
)
);
}
if ( ! $blog_current_lang && defined( 'WPLANG' ) && WPLANG != '' ) {
$blog_current_lang = $wpdb->get_var( $wpdb->prepare( "SELECT code FROM {$wpdb->prefix}icl_languages WHERE default_locale=%s", WPLANG ) );
if ( ! $blog_current_lang ) {
$blog_lang = WPLANG;
$exp = explode( '_', $blog_lang );
$blog_current_lang = $wpdb->get_var(
$wpdb->prepare(
"SELECT code FROM {$wpdb->prefix}icl_languages WHERE code= %s",
$exp[0]
)
);
}
}
if ( ! $blog_current_lang ) {
$blog_current_lang = 'en';
}
$languages = $sitepress->get_languages( $blog_current_lang, false, true, false, 'display_name' );
} else {
$languages = $sitepress->get_languages( $sitepress->get_admin_language(), false, true, false, 'display_name' );
foreach ( $active_languages as $lang ) {
if ( $lang['code'] != $default_language ) {
$sample_lang = $lang;
break;
}
}
$default_language_details = $sitepress->get_language_details( $default_language );
$inactive_content = new WPML_Inactive_Content( $wpdb, $sitepress->get_current_language() );
}
global $language_switcher_defaults, $language_switcher_defaults_alt;
$theme_wpml_config_file = WPML_Config::get_theme_wpml_config_file();
?>
<?php $sitepress->noscript_notice(); ?>
<div class="wrap wpml-settings-container">
<h2><?php esc_html_e( 'Setup WPML', 'sitepress' ) ?></h2>
<?php
$compatibility_reports_args = array(
'plugin_name' => 'WPML',
'plugin_uri' => 'http://wpml.org',
'plugin_site' => 'wpml.org',
'use_styles' => true,
'privacy_policy_url' => 'https://wpml.org/documentation/privacy-policy-and-gdpr-compliance/?utm_source=plugin&utm_medium=gui&utm_campaign=wpmlcore',
'plugin_repository' => 'wpml',
);
if ( count( $active_languages ) > 1 ): ?>
<p>
<strong><?php esc_html_e( 'This screen contains the language settings for your site.', 'sitepress' ); ?></strong>
</p>
<ul class="wpml-navigation-links js-wpml-navigation-links">
<?php
$navigation_items = array(
'#lang-sec-1' => __( 'Site Languages', 'sitepress' ),
'#lang-sec-2' => __( 'Language URL format', 'sitepress' ),
'#lang-sec-4' => __( 'Admin language', 'sitepress' ),
'#lang-sec-7' => __( 'Hide languages', 'sitepress' ),
'#lang-sec-8' => __( 'Make themes work multilingual', 'sitepress' ),
'#lang-sec-9' => __( 'Browser language redirect', 'sitepress' ),
'#lang-sec-9-5' => __( 'SEO Options', 'sitepress' ),
'#lang-sec-9-6' => __( 'Theme and plugins reporting', 'sitepress' ),
'#cookie' => __( 'Language filtering for AJAX operations', 'sitepress' ),
'#lang-sec-10' => __( 'WPML love', 'sitepress' ),
);
if ( $should_hide_admin_language && array_key_exists( '#lang-sec-4', $navigation_items ) ) {
unset( $navigation_items['#lang-sec-4'] );
}
/**
* @param array $navigation_items
*/
$navigation_items = apply_filters( 'wpml_admin_languages_navigation_items', $navigation_items );
foreach ( $navigation_items as $link => $text ) {
echo '<li><a href="' . esc_attr( $link ) . '">' . esc_html( $text ) . '</a></li>';
}
?>
</ul>
<?php endif; ?>
<div id="lang-sec-1" class="wpml-section wpml-section-languages">
<div class="wpml-section-header">
<h3><?php _e( 'Site Languages', 'sitepress' ); ?></h3>
</div>
<div class="wpml-section-content">
<div class="wpml-section-content-inner">
<h4><?php _e('These languages are enabled for this site:','sitepress'); ?></h4>
<?php do_action( 'wpml_before_active_languages_display' ); ?>
<ul id="icl_enabled_languages" class="enabled-languages">
<?php
foreach ( $active_languages as $lang ) :
$is_default = ( $default_language == $lang['code'] );
?>
<?php
if ( ! empty( $hidden_languages ) && in_array( $lang['code'], $hidden_languages ) ) {
$hidden = '&nbsp<strong style="color:#f00">(' . esc_html__( 'hidden', 'sitepress' ) . ')</strong>';
} else {
$hidden = '';
}
?>
<li
<?php
if ( $is_default ) :
?>
class="selected"<?php endif; ?>>
<input id="default_language_<?php echo esc_attr( $lang['code'] ); ?>"
name="default_language" type="radio"
value="<?php echo esc_attr( $lang['code'] ); ?>" <?php checked( $is_default ); ?> />
<label for="default_language_<?php echo esc_attr( $lang['code'] ); ?>">
<?php echo esc_html( $lang['display_name'] ) . $hidden; ?>
<?php
if ( $is_default ) :
?>
(<?php esc_html_e( 'default', 'sitepress' ); ?>)<?php endif ?>
</label>
</li>
<?php endforeach ?>
</ul>
<?php do_action( 'wpml_after_active_languages_display' ); ?>
<?php wp_nonce_field('wpml_set_default_language', 'set_default_language_nonce'); ?>
<p class="buttons-wrap">
<button id="icl_cancel_default_button" class="button-secondary action"><?php esc_html_e( 'Cancel', 'sitepress' ); ?></button>
<button id="icl_save_default_button" class="button-primary action"><?php esc_html_e( 'Save', 'sitepress' ); ?></button>
</p>
<p>
<button id="icl_change_default_button"
class="button-secondary action <?php if ( count( $active_languages ) < 2 ): ?>hidden<?php endif ?>">
<?php esc_html_e( 'Change default language', 'sitepress' ) ?>
</button>
<button id="icl_add_remove_button" class="button-secondary action">
<?php esc_html_e( 'Add / Remove languages', 'sitepress' ) ?>
</button>
</p>
<p class="icl_ajx_response" id="icl_ajx_response"></p>
<div id="icl_avail_languages_picker" class="hidden">
<ul class="available-languages">
<?php
foreach ( $languages as $lang ) {
$checked = checked( '1', $lang['active'], false );
$disabled = disabled( $default_language, $lang['code'], false );
$language_item_classes = array();
if ( (bool) $lang['active'] ) {
$language_item_classes[] = 'wpml-selected';
}
?>
<li class="<?php echo implode( ' ', $language_item_classes ); ?>">
<label for="wpml-language-<?php echo $lang['code']; ?>">
<input type="checkbox" id="wpml-language-<?php echo esc_attr( $lang['code'] ); ?>"
value="<?php echo esc_attr( $lang['code'] ); ?>" <?php echo $checked . ' ' . $disabled; ?>/>
<?php echo $sitepress->get_flag_image($lang['code']) ?>
<?php echo esc_html( $lang['display_name'] ); ?>
</label>
</li>
<?php
}
?>
</ul>
<div class="buttons-wrap">
<input id="icl_cancel_language_selection" type="button" class="button-secondary action"
value="<?php esc_attr_e( 'Cancel', 'sitepress' ); ?>" />
<input id="icl_save_language_selection" type="button" class="button-primary action"
value="<?php esc_attr_e( 'Save', 'sitepress' ); ?>" style="display:none"/>
<div id="wpml_language_selection_save" style="display: inline-block"></div>
</div>
<?php wp_nonce_field('wpml_set_active_languages', 'set_active_languages_nonce'); ?>
</div>
<p>
<a href="admin.php?page=<?php echo WPML_PLUGIN_FOLDER ?>/menu/languages.php&amp;trop=1">
<?php esc_html_e( 'Edit Languages', 'sitepress' ) ?>
</a>
</p>
</div> <!-- wpml-section-content-inner -->
<?php if ( $inactive_content && $inactive_content->has_entries() ) : ?>
<div class="wpml-section-content-inner">
<?php
$render_inactive_content = new WPML_Inactive_Content_Render(
$inactive_content,
array( WPML_PLUGIN_PATH . '/templates/languages/' )
);
echo $render_inactive_content->render();
?>
</div> <!-- wpml-section-content-inner -->
<?php endif; ?>
</div> <!-- .wcml-section-content -->
</div> <!-- .wpml-section-languages -->
<?php
if ( ! class_exists( 'WP_Http' ) ) {
include_once ABSPATH . WPINC . '/class-http.php';
}
/**
* @var WPML_URL_Converter $wpml_url_converter
* @var WPML_Request $wpml_request_handler
*/
global $wpml_url_converter, $wpml_request_handler;
$validator = wpml_get_langs_in_dirs_val( $wpml_url_converter );
?>
<?php if ( count( $active_languages ) > 1 ) : ?>
<div class="wpml-section wpml-section-url-format" id="lang-sec-2">
<div class="wpml-section-header">
<h3><?php esc_html_e( 'Language URL format', 'sitepress' ); ?></h3>
</div>
<div class="wpml-section-content">
<h4><?php esc_html_e( 'Choose how to determine which language visitors see contents in', 'sitepress' ); ?></h4>
<form id="icl_save_language_negotiation_type" name="icl_save_language_negotiation_type" action="">
<?php wp_nonce_field( 'save_language_negotiation_type', 'save_language_negotiation_type_nonce' ); ?>
<ul>
<?php
$abs_home = $wpml_url_converter->get_abs_home();
$icl_folder_url_enabled = $validator->validate_langs_in_dirs();
?>
<li>
<label>
<input type="radio" name="icl_language_negotiation_type" value="1" <?php checked( 1 == $language_negotiation_type ); ?> />
<?php esc_html_e( 'Different languages in directories', 'sitepress' ); ?>
<span class="explanation-text">
(
<?php
$root = ! empty( $setting_urls['directory_for_default_language'] );
echo $validator->print_explanation( $sample_lang['code'], $root );
?>
)
</span>
</label>
<div id="icl_use_directory_wrap" style="
<?php
if ( $language_negotiation_type != 1 ) :
?>
display:none;<?php endif; ?>" >
<p class="sub-section">
<label>
<input type="checkbox" name="use_directory" id="icl_use_directory" value="1"
<?php checked( ! empty( $setting_urls['directory_for_default_language'] ) ); ?> />
<?php esc_html_e( 'Use directory for default language', 'sitepress' ); ?>
</label>
</p>
<div id="icl_use_directory_details" class="sub-section"
<?php
if ( empty( $setting_urls['directory_for_default_language'] ) ) {
echo ' style="display:none"';}
?>
>
<p><?php esc_html_e( 'What to show for the root url:', 'sitepress' ); ?></p>
<ul>
<li>
<label for="wpml_show_on_root_html_file">
<input id="wpml_show_on_root_html_file" type="radio" name="show_on_root"
value="html_file" <?php checked( 'html_file' === $setting_urls['show_on_root'] ); ?> />
<?php esc_html_e( 'HTML file', 'sitepress' ); ?> &ndash;
<span class="explanation-text">
<?php esc_html_e( 'please enter path: absolute or relative to the WordPress installation folder', 'sitepress' ); ?>
</span>
</label>
<p>
<input type="text" id="root_html_file_path" name="root_html_file_path" value="<?php echo esc_attr( $setting_urls['root_html_file_path'] ); ?>" />
<label class="icl_error_text icl_error_1" for="root_html_file_path" style="display: none;">
<?php esc_html_e( 'Please select what to show for the root url.', 'sitepress' ); ?>
</label>
</p>
</li>
<li>
<label>
<input id="wpml_show_on_root_page" type="radio" name="show_on_root" value="page"
<?php checked( 'page' === $setting_urls['show_on_root'] ); ?>
<?php
if ( $setting_urls['show_on_root'] === 'page' ) :
?>
class="active"<?php endif; ?>
/>
<?php esc_html_e( 'A page', 'sitepress' ); ?>
<span style="display: none;" id="wpml_show_page_on_root_x"><?php esc_html_e( 'Please save the settings first by clicking Save.', 'sitepress' ); ?></span>
<span id="wpml_show_page_on_root_details"
<?php
if ( $setting_urls['show_on_root'] !== 'page' ) :
?>
style="display:none"<?php endif; ?>>
<?php
$rp_exists = false;
if ( ! empty( $setting_urls['root_page'] ) ) {
$rp = get_post( $setting_urls['root_page'] );
if ( $rp && $rp->post_status !== 'trash' ) {
$rp_exists = true;
}
}
?>
<?php if ( $rp_exists ) : ?>
<a href="<?php echo get_edit_post_link( $setting_urls['root_page'] ); ?>">
<?php esc_html_e( 'Edit root page.', 'sitepress' ); ?>
</a>
<?php else : ?>
<a href="<?php echo admin_url( 'post-new.php?post_type=page&wpml_root_page=1' ); ?>">
<?php esc_html_e( 'Create root page.', 'sitepress' ); ?>
</a>
<?php endif; ?>
</span>
<p id="icl_hide_language_switchers" class="sub-section"
<?php
if ( $setting_urls['show_on_root'] !== 'page' ) :
?>
style="display:none"<?php endif; ?>>
<label>
<input type="checkbox" name="hide_language_switchers" id="icl_hide_language_switchers"
value="1" <?php checked( $setting_urls['hide_language_switchers'] ); ?> />
<?php esc_html_e( 'Hide language switchers on the root page', 'sitepress' ); ?>
</label>
</p>
</label>
</li>
</ul>
</div>
</div>
<?php if ( ! $icl_folder_url_enabled ): ?>
<div class="icl_error_text" style="margin:10px;">
<p>
<?php esc_html_e( 'It looks like languages per directories will not function.', 'sitepress' ); ?>
<a href="#" onClick="jQuery(this).parent().parent().next().toggle();return false">
<?php esc_html_e( 'Details', 'sitepress' ); ?>
</a>
</p>
</div>
<div class="icl_error_text" style="display:none;margin:10px;">
<p><?php esc_html_e( 'This can be a result of either:', 'sitepress' ); ?></p>
<ul>
<li>
<?php esc_html_e( "Your server settings do not allow for languages in directories.", 'sitepress' ); ?>
<a href="https://wpml.org/documentation/getting-started-guide/language-setup/cannot-activate-language-directories/?utm_source=plugin&utm_medium=gui&utm_campaign=wpmlcore"><?php esc_html_e( 'Learn more about the required server settings.', 'sitepress'); ?></a>
</li>
<li><?php esc_html_e( 'URL rewriting is not enabled in your web server.', 'sitepress' ); ?></li>
<li><?php esc_html_e( 'The web server cannot write to the .htaccess file', 'sitepress' ); ?></li>
</ul>
<a href="https://wpml.org/?page_id=1010"><?php esc_html_e( 'How to fix', 'sitepress' ); ?></a>
</div>
<?php endif; ?>
</li>
<?php
global $wpmu_version;
if ( isset( $wpmu_version ) || ( function_exists( 'is_multisite' ) && is_multisite() && ( ! defined( 'WPML_SUNRISE_MULTISITE_DOMAINS' ) || ! WPML_SUNRISE_MULTISITE_DOMAINS ) ) ) {
$icl_lnt_disabled = 'disabled="disabled" ';
} else {
$icl_lnt_disabled = '';
}
?>
<li>
<label>
<input <?php echo $icl_lnt_disabled; ?>id="icl_lnt_domains" type="radio" name="icl_language_negotiation_type"
value="2" <?php checked( 2 == $language_negotiation_type ); ?> />
<?php esc_html_e( 'A different domain per language', 'sitepress' ); ?>
<?php if ( $icl_lnt_disabled ) : ?>
<span class="icl_error_text"><?php esc_html_e( 'This option is not yet available for Multisite installs', 'sitepress' ); ?></span>
<?php endif; ?>
<?php if ( defined( 'WPML_SUNRISE_MULTISITE_DOMAINS' ) && WPML_SUNRISE_MULTISITE_DOMAINS ) : ?>
<span class="icl_error_text"><?php esc_html_e( 'Experimental', 'sitepress' ); ?></span>
<?php endif; ?>
</label>
<?php wp_nonce_field( 'language_domains_nonce', '_icl_nonce_ldom', false ); ?>
<?php wp_nonce_field( 'validate_language_domain', 'validate_language_domain_nonce', false ); ?>
<div id="icl_lnt_domains_box">
<?php
if ( (int) $language_negotiation_type === 2 ) :
$domains_box = new WPML_Lang_Domains_Box( $sitepress );
echo $domains_box->render();
endif;
?>
</div>
<div id="language_domain_xdomain_options" class="sub-section"
<?php
if ( $language_negotiation_type != 2 ) {
echo ' style="display:none"';}
?>
>
<p><?php esc_html_e( 'Pass session arguments between domains through the language switcher', 'sitepress' ); ?></p>
<p>
<label>
<input type="radio" name="icl_xdomain_data"
value="<?php echo WPML_XDOMAIN_DATA_GET; ?>"
<?php checked( WPML_XDOMAIN_DATA_GET === (int) $sitepress_settings['xdomain_data'] ); ?>/>
<?php esc_html_e( 'Pass arguments via GET (the url)', 'sitepress' ); ?>
</label>
</p>
<p>
<label>
<input type="radio" name="icl_xdomain_data"
value="<?php echo WPML_XDOMAIN_DATA_POST; ?>"
<?php checked( WPML_XDOMAIN_DATA_POST === (int) $sitepress_settings['xdomain_data'] ); ?>/>
<?php esc_html_e( 'Pass arguments via POST', 'sitepress' ); ?>
</label>
</p>
<p>
<label>
<input type="radio" name="icl_xdomain_data"
value="<?php echo WPML_XDOMAIN_DATA_OFF; ?>"
<?php checked( WPML_XDOMAIN_DATA_OFF === (int) $sitepress_settings['xdomain_data'] ); ?>/>
<?php esc_html_e( 'Disable this feature', 'sitepress' ); ?>
</label>
</p>
<?php $encryptor_library = $encryptor->get_crypt_library(); ?>
<?php if ( $encryptor_library === 'mcrypt' || $encryptor_library === 'openssl' ) : ?>
<p>
<?php
printf(
esc_html__( 'The data will be encrypted with the %s algorithm.', 'sitepress' ),
$encryptor_library === 'mcrypt' ? 'MCRYPT_RIJNDAEL_256' : 'AES-256-CTR'
)
?>
</p>
<?php else : ?>
<p><?php esc_html_e( 'Because encryption is not supported on your host, the data will only have a basic encoding with the bse64 algorithm.', 'sitepress' ); ?></p>
<?php endif; ?>
<p><a href="https://wpml.org/?page_id=693147" target="_blank"><?php esc_html_e( 'Learn more about passing data between domains', 'sitepress' ); ?></a></p>
</div>
</li>
<li>
<label>
<input type="radio" name="icl_language_negotiation_type" value="3" <?php checked( 3 == $language_negotiation_type ); ?> />
<?php esc_html_e( 'Language name added as a parameter', 'sitepress' ); ?>
<span class="explanation-text">
<?php echo sprintf( '(%s?lang=%s - %s)', get_home_url(), esc_html( $sample_lang['code'] ), esc_html( $sample_lang['display_name'] ) ); ?>
</span>
</label>
</li>
</ul>
<div class="wpml-form-message" style="display:none;"></div>
<div class="wpml-form-errors icl_form_errors" style="display: none;"></div>
<p class="buttons-wrap">
<span class="icl_ajx_response" id="icl_ajx_response2"></span>
<input class="button button-primary" name="save" value="<?php esc_html_e( 'Save', 'sitepress' ); ?>" type="submit" />
</p>
</form>
</div>
</div> <!-- .wpml-section-url-format -->
<?php endif; ?>
<?php do_action( 'wpml_admin_after_languages_url_format' ); ?>
<?php if ( count( $all_languages ) > 1 && ! $should_hide_admin_language ): ?>
<div class="wpml-section wpml-section-admin-language" id="lang-sec-4">
<div class="wpml-section-header">
<h3><?php esc_html_e( 'Admin language', 'sitepress' ); ?></h3>
</div>
<div class="wpml-section-content">
<form id="icl_admin_language_options" name="icl_admin_language_options" action="">
<?php wp_nonce_field( 'icl_admin_language_options_nonce', '_icl_nonce' ); ?>
<?php if ( is_admin() ) : ?>
<p>
<label>
<?php _e( 'Default admin language: ', 'sitepress' ); ?>
<?php $default_language_details = $sitepress->get_language_details( $default_language ); ?>
<select name="icl_admin_default_language">
<option value="_default_"><?php printf( esc_html__( 'Default language (currently %s)', 'sitepress' ), $default_language_details['display_name'] ); ?></option>
<?php foreach ( $all_languages as $al ) : ?>
<?php if ( $al['active'] ) : ?>
<option value="<?php echo esc_attr( $al['code'] ); ?>" <?php selected( $sitepress->get_setting( 'admin_default_language' ) == $al['code'] ); ?>>
<?php
echo esc_html( $al['display_name'] );
if ( $sitepress->get_admin_language() != $al['code'] ) {
echo ' (' . esc_html( $al['native_name'] ) . ')';
}
?>
&nbsp;
</option>
<?php endif; ?>
<?php endforeach; ?>
<?php foreach ( $all_languages as $al ) : ?>
<?php if ( ! $al['active'] ) : ?>
<option value="<?php echo esc_attr( $al['code'] ); ?>" <?php selected( $sitepress->get_setting( 'admin_default_language' ) == $al['code'] ); ?>>
<?php
echo esc_html( $al['display_name'] );
if ( $sitepress->get_admin_language() != $al['code'] ) {
echo ' (' . esc_html( $al['native_name'] ) . ')';
}
?>
&nbsp;
</option>
<?php endif; ?>
<?php endforeach; ?>
</select>
</label>
</p>
<?php endif; ?>
<p><?php printf( __( 'Each user can choose the admin language. You can edit your language preferences by visiting your <a href="%s">profile page</a>.', 'sitepress' ), 'profile.php#wpml' ); ?></p>
<p class="buttons-wrap">
<span class="icl_ajx_response" id="icl_ajx_response_al"></span>
<input class="button button-primary" name="save" value="<?php esc_html_e( 'Save', 'sitepress' ); ?>" type="submit" />
</p>
</form>
</div>
</div>
<?php endif; ?>
<?php if ( count( $active_languages ) > 1 ): ?>
<div class="wpml-section wpml-section-hide-languages" id="lang-sec-7">
<div class="wpml-section-header">
<h3><?php esc_html_e( 'Hide languages', 'sitepress' ); ?></h3>
</div>
<div class="wpml-section-content">
<p><?php esc_html_e( 'You can completely hide content in specific languages from visitors and search engines, but still view it yourself. This allows reviewing translations that are in progress.', 'sitepress' ); ?></p>
<form id="icl_hide_languages" name="icl_hide_languages" action="">
<?php wp_nonce_field( 'icl_hide_languages_nonce', '_icl_nonce' ); ?>
<?php foreach ( $active_languages as $l ) : ?>
<?php
if ( $l['code'] == $default_language_details['code'] ) {
continue;}
?>
<p>
<label>
<input type="checkbox" name="icl_hidden_languages[]" value="<?php echo esc_attr( $l['code'] ); ?>"
<?php checked( ! empty( $hidden_languages ) && in_array( $l['code'], $hidden_languages ) ); ?> />
<?php echo esc_html( $l['display_name'] ); ?>
</label>
</p>
<?php endforeach; ?>
<p id="icl_hidden_languages_status">
<?php
if ( ! empty( $hidden_languages ) ) {
// While checking for hidden languages, it cleans any possible leftover from inactive or deleted languages
if ( 1 == count( $hidden_languages ) ) {
if ( isset( $active_languages[ $hidden_languages[0] ] ) ) {
printf( esc_html__( '%s is currently hidden to visitors.', 'sitepress' ), esc_html( $active_languages[ $hidden_languages[0] ]['display_name'] ) );
$hidden_languages[] = $hidden_languages[0];
}
} else {
$_hlngs = array();
foreach ( $hidden_languages as $l ) {
if ( isset( $active_languages[ $l ] ) ) {
$_hlngs[] = $active_languages[ $l ]['display_name'];
}
}
$hlangs = implode( ', ', $_hlngs );
printf( esc_html__( '%s are currently hidden to visitors.', 'sitepress' ), esc_html( $hlangs ) );
}
$hidden_languages = array_unique( $hidden_languages );
$sitepress->set_setting( 'hidden_languages', $hidden_languages );
echo '<p>';
printf( __( 'You can enable its/their display for yourself, in your <a href="%s">profile page</a>.', 'sitepress' ), 'profile.php#wpml' );
echo '</p>';
} else {
esc_html_e( 'All languages are currently displayed.', 'sitepress' );
}
?>
</p>
<p class="buttons-wrap">
<span class="icl_ajx_response" id="icl_ajx_response_hl"></span>
<input class="button button-primary" name="save" value="<?php esc_attr_e( 'Save', 'sitepress' ); ?>" type="submit" />
</p>
</form>
</div>
</div>
<div class="wpml-section wpml-section-ml-themes" id="lang-sec-8">
<div class="wpml-section-header">
<h3><?php esc_html_e( 'Make themes work multilingual', 'sitepress' ); ?></h3>
</div>
<div class="wpml-section-content">
<form id="icl_adjust_ids" name="icl_adjust_ids" action="">
<?php wp_nonce_field( 'icl_adjust_ids_nonce', '_icl_nonce' ); ?>
<p><?php esc_html_e( 'This feature turns themes into multilingual, without having to edit their PHP files.', 'sitepress' ); ?></p>
<p>
<label>
<input type="checkbox" value="1" name="icl_adjust_ids" <?php checked( $sitepress->get_setting( 'auto_adjust_ids' ) ); ?> />
<?php esc_html_e( 'Adjust IDs for multilingual functionality', 'sitepress' ); ?>
</label>
</p>
<p class="buttons-wrap">
<span class="icl_ajx_response" id="icl_ajx_response_ai"></span>
<input class="button button-primary" name="save" value="<?php esc_attr_e( 'Save', 'sitepress' ); ?>" type="submit" />
</p>
</form>
</div>
</div>
<div class="wpml-section wpml-section-redirect" id="lang-sec-9">
<div class="wpml-section-header">
<h3><?php esc_html_e( 'Browser language redirect', 'sitepress' ); ?></h3>
</div>
<div class="wpml-section-content">
<p><?php esc_html_e( 'WPML can automatically redirect visitors according to browser language.', 'sitepress' ); ?></p>
<p class="explanation-text"><?php esc_html_e( "This feature uses Javascript. Make sure that your site doesn't have JS errors.", 'sitepress' ); ?></p>
<form id="icl_automatic_redirect" name="icl_automatic_redirect" action="">
<?php wp_nonce_field( 'icl_automatic_redirect_nonce', '_icl_nonce' ); ?>
<ul>
<li><label>
<input type="radio" value="0" name="icl_automatic_redirect" <?php checked( empty( $automatic_redirect ) ); ?> />
<?php esc_html_e( 'Disable browser language redirect', 'sitepress' ); ?>
</label></li>
<li><label>
<input type="radio" value="1" name="icl_automatic_redirect" <?php checked( 1, $automatic_redirect ); ?> />
<?php esc_html_e( 'Redirect visitors based on browser language only if translations exist', 'sitepress' ); ?>
</label></li>
<li><label>
<input type="radio" value="2" name="icl_automatic_redirect" <?php checked( 2, $automatic_redirect ); ?> />
<?php esc_html_e( 'Always redirect visitors based on browser language (redirect to home page if translations are missing)', 'sitepress' ); ?>
</label></li>
</ul>
<ul>
<li>
<label>
<?php
printf(
esc_html__( "Remember visitors' language preference for %s hours (please enter 24 or multiples of it).", 'sitepress' ),
'<input size="2" type="number" min="24" value="' . (int) $sitepress->get_setting( 'remember_language' ) . '" name="icl_remember_language" /> '
);
global $wpml_request_handler;
if ( ! $wpml_request_handler->get_cookie_lang() ) {
?>
<span class="icl_error_text"><?php esc_html_e( "Your browser doesn't seem to be allowing cookies to be set.", 'sitepress' ); ?></span>
<?php
}
?>
</label>
</li>
</ul>
<div class="wpml-form-message update-nag js-redirect-warning"
<?php
if ( empty( $automatic_redirect ) ) :
?>
style="display: none;"<?php endif; ?>>
<?php
$redirect_warning_1 = esc_html__( "Browser language redirect may affect your site's indexing", 'sitepress' );
$redirect_warning_2 = esc_html__( 'learn more', 'sitepress' );
$url = 'https://wpml.org/documentation/getting-started-guide/language-setup/automatic-redirect-based-on-browser-language/how-browser-language-redirect-affects-google-indexing/?utm_source=plugin&utm_medium=gui&utm_campaign=wpmlcore';
echo $redirect_warning_1 . '- <a href="' . $url . '" target="_blank">' . $redirect_warning_2 . '</a>';
?>
</div>
<p class="buttons-wrap">
<span class="icl_ajx_response" id="icl_ajx_response_ar"></span>
<input class="button button-primary" name="save" value="<?php esc_attr_e( 'Save', 'sitepress' ); ?>" type="submit" />
</p>
</form>
</div>
</div>
<?php endif; ?>
<?php
$request_get_page = filter_input( INPUT_GET, 'page', FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_NULL_ON_FAILURE );
do_action( 'icl_extra_options_' . $request_get_page );
$seo_ui = new WPML_SEO_HeadLangs( $sitepress );
$seo_ui->render_menu();
?>
<div class="wpml-section wpml-section-wpml-theme-and-plugins-reporting" id="lang-sec-9-6">
<div class="wpml-section-header">
<h3><?php esc_html_e( 'Reporting to wpml.org', 'sitepress' ) ?></h3>
</div>
<div class="wpml-section-content">
<?php
$compatibility_reports_after_setup_args = $compatibility_reports_args;
$compatibility_reports_after_setup_args['custom_heading'] = '';
$compatibility_reports_after_setup_args['use_radio'] = false;
do_action( 'otgs_installer_render_local_components_setting', $compatibility_reports_after_setup_args );
?>
</div>
</div>
<div class="wpml-section wpml-section-wpml-love" id="lang-sec-10">
<div class="wpml-section-header">
<h3><?php esc_html_e( 'WPML love', 'sitepress' ) ?></h3>
</div>
<div class="wpml-section-content">
<form id="icl_promote_form" name="icl_promote_form" action="">
<?php wp_nonce_field( 'icl_promote_form_nonce', '_icl_nonce' ); ?>
<p>
<label><input type="checkbox" name="icl_promote" <?php checked( $sitepress->get_setting( 'promote_wpml' ) ) ?> value="1"/>
<?php printf( __( "Tell the world your site is running multilingual with WPML (places a message in your site's footer) - <a href=\"%s\">read more</a>", 'sitepress' ), 'https://wpml.org/?page_id=4560' ); ?>
</label>
</p>
<p class="buttons-wrap">
<span class="icl_ajx_response" id="icl_ajx_response_lv"></span>
<input class="button button-primary" name="save" value="<?php esc_attr_e( 'Save', 'sitepress' ) ?>" type="submit"/>
</p>
</form>
</div>
</div>
<?php
do_action( 'wpml_after_settings', $theme_wpml_config_file );
/**
* @deprecated use `wpml_after_settings` instead
*/
do_action( 'wpml_admin_after_wpml_love', $theme_wpml_config_file );
/**
* @deprecated use `wpml_menu_footer` instead
*/
do_action( 'icl_menu_footer' );
do_action( 'wpml_menu_footer' );
?>
</div> <!-- .wrap -->
<?php
// Save any changed setting
$sitepress->save_settings();

View File

@@ -0,0 +1,288 @@
<?php
global $icl_menus_sync, $sitepress;
/** @var SitePress $sitepress */
/** @var ICLMenusSync $icl_menus_sync */
$active_languages = $sitepress->get_active_languages();
$def_lang_code = $sitepress->get_default_language();
$def_lang = $sitepress->get_language_details( $def_lang_code );
$secondary_languages = array();
foreach ( $active_languages as $code => $lang ) {
if ( $code !== $def_lang_code ) {
$secondary_languages[] = $lang;
}
}
?>
<!--suppress HtmlFormInputWithoutLabel --><!--suppress HtmlUnknownAttribute -->
<div class="wrap">
<h2><?php esc_html_e( 'WP Menus Sync', 'sitepress' ); ?></h2>
<p><?php printf( esc_html__( 'Menu synchronization will sync the menu structure from the default language of %s to the secondary languages.', 'sitepress' ), $def_lang['display_name'] ); ?></p>
<br/>
<?php
if ( $icl_menus_sync->is_preview ) {
?>
<form id="icl_msync_confirm_form" method="post">
<input type="hidden" name="action" value="icl_msync_confirm"/>
<table id="icl_msync_confirm" class="widefat icl_msync">
<thead>
<tr>
<th scope="row" class="menu-check-all"><input type="checkbox"/></th>
<th><?php esc_html_e( 'Language', 'sitepress' ); ?></th>
<th><?php esc_html_e( 'Action', 'sitepress' ); ?></th>
</tr>
</thead>
<tbody>
<?php
$menu_id = null;
if ( empty( $icl_menus_sync->sync_data ) ) {
?>
<tr>
<td align="center" colspan="3"><?php esc_html_e( 'Nothing to sync.', 'sitepress' ); ?></td>
</tr>
<?php
} else {
// Menus
foreach ( $icl_menus_sync->menus as $menu_id => $menu ) {
$menu_sync_display = new WPML_Menu_Sync_Display( $menu_id, $icl_menus_sync );
?>
<tr class="icl_msync_menu_title">
<td colspan="3"><?php echo esc_html( $menu['name'] ); ?></td>
</tr>
<?php
// Display actions per menu
// menu translations
if ( isset( $icl_menus_sync->sync_data['menu_translations'], $icl_menus_sync->sync_data['menu_translations'][ $menu_id ] ) ) {
foreach ( $icl_menus_sync->sync_data['menu_translations'][ $menu_id ] as $language => $name ) {
$lang_details = $sitepress->get_language_details( $language );
?>
<tr>
<th scope="row" class="check-column">
<input type="checkbox"
name="sync[menu_translation][<?php echo esc_attr( $menu_id ); ?>][<?php echo esc_attr( $language ); ?>]"
value="<?php echo esc_attr( $name ); ?>"/>
</th>
<td><?php echo esc_html( $lang_details['display_name'] ); ?></td>
<td><?php printf( esc_html__( 'Add menu translation: %s', 'sitepress' ), '<strong>' . esc_html( $name ) . '</strong>' ); ?> </td>
</tr>
<?php
}
}
foreach (
array(
'add',
'mov',
'del',
'label_changed',
'url_changed',
'label_missing',
'url_missing',
'options_changed',
) as $sync_type
) {
$menu_sync_display->print_sync_field( $sync_type );
}
}
}
?>
</tbody>
</table>
<p class="submit">
<?php
$icl_menu_sync_submit_disabled = '';
if ( empty( $icl_menus_sync->sync_data ) || ( empty( $icl_menus_sync->sync_data['mov'] ) && empty( $icl_menus_sync->sync_data['mov'][ $menu_id ] ) ) ) {
$icl_menu_sync_submit_disabled = 'disabled="disabled"';
}
?>
<input id="icl_msync_submit"
class="button-primary"
type="button"
value="<?php esc_attr_e( 'Apply changes' ); ?>"
data-message="<?php esc_attr_e( 'Syncing menus %1 of %2', 'sitepress' ); ?>"
data-message-complete="<?php esc_attr_e( 'The selected menus have been synchonized.', 'sitepress' ); ?>"
<?php echo $icl_menu_sync_submit_disabled; ?> />&nbsp;
<input id="icl_msync_cancel" class="button-secondary" type="button" value="<?php _e( 'Cancel' ); ?>"/>
<span id="icl_msync_message"></span>
</p>
<?php wp_nonce_field( '_icl_nonce_menu_sync', '_icl_nonce_menu_sync' ); ?>
</form>
<?php
} else {
$need_sync = 0;
?>
<form method="post" action="">
<input type="hidden" name="action" value="icl_msync_preview"/>
<table class="widefat icl_msync">
<thead>
<tr>
<th><?php echo esc_html( $def_lang['display_name'] ); ?></th>
<?php
if ( ! empty( $secondary_languages ) ) {
foreach ( $secondary_languages as $lang ) {
?>
<th><?php echo esc_html( $lang['display_name'] ); ?></th>
<?php
}
}
?>
</tr>
</thead>
<tbody>
<?php
if ( empty( $icl_menus_sync->menus ) ) {
?>
<tr>
<td align="center" colspan="<?php echo count( $active_languages ); ?>"><?php esc_html_e( 'No menus found', 'sitepress' ); ?></td>
</tr>
<?php
} else {
foreach ( $icl_menus_sync->menus as $menu_id => $menu ) {
?>
<tr class="icl_msync_menu_title">
<td><strong><?php echo esc_html( $menu['name'] ); ?></strong></td>
<?php
foreach ( $secondary_languages as $l ) {
$input_name = sprintf( 'sync[menu_options][%s][%s][auto_add]', esc_attr( $menu_id ), esc_attr( $l['code'] ) );
?>
<td>
<?php
if ( isset( $menu['translations'][ $l['code'] ]['name'] ) ) {
echo esc_html( $menu['translations'][ $l['code'] ]['name'] );
} else { // menu is translated in $l[code]
$need_sync++;
?>
<input type="text" class="icl_msync_add"
name="sync[menu_translations][<?php echo esc_attr( $menu_id ); ?>][<?php echo esc_attr( $l['code'] ); ?>]"
value="<?php echo esc_attr( $menu['name'] ) . ' - ' . esc_attr( $l['display_name'] ); ?>"
/>
<small><?php esc_html_e( 'Auto-generated title. Click to edit.', 'sitepress' ); ?></small>
<input type="hidden" value=""
name="<?php echo $input_name; ?>"
/>
<?php
}
if ( isset( $menu['translations'][ $l['code'] ]['auto_add'] ) ) {
?>
<input type="hidden" name="<?php echo $input_name; ?>" value="<?php echo esc_attr( $menu['translations'][ $l['code'] ]['auto_add'] ); ?>"/>
<?php
}
?>
</td>
<?php
} //foreach($secondary_languages as $l):
?>
</tr>
<?php
$need_sync += $icl_menus_sync->render_items_tree_default( $menu_id );
} //foreach( $icl_menus_sync->menus as $menu_id => $menu):
}
?>
</tbody>
</table>
<p class="submit">
<?php
if ( $need_sync ) {
?>
<input id="icl_msync_sync" type="submit" class="button-primary"
value="<?php esc_attr_e( 'Sync', 'sitepress' ); ?>"
<?php disabled( ! $need_sync ); ?>
/>
&nbsp;&nbsp;
<span id="icl_msync_max_input_vars"
style="display:none"
class="icl-admin-message-warning"
data-max_input_vars="
<?php
//phpcs:disable PHPCompatibility.IniDirectives.NewIniDirectives.max_input_varsFound -- It never caused issues, but we should probably fix that
echo ini_get( 'max_input_vars' );
//phpcs:enable PHPCompatibility.IniDirectives.NewIniDirectives.max_input_varsFound
?>
">
<?php
printf(
esc_html__( 'The menus on this page may not sync because it requires more input variables. Please modify the %1$s setting in your php.ini or .htaccess files to %2$s or more.', 'sitepress' ),
'<strong>max_input_vars</strong>',
'<strong>!NUM!</strong>'
)
?>
</span>
<?php
} else {
?>
<input id="icl_msync_sync" type="submit" class="button-primary"
value="<?php esc_attr_e( 'Nothing Sync', 'sitepress' ); ?>"<?php disabled( ! $need_sync ); ?>
/>
<?php
}
?>
</p>
<?php wp_nonce_field( '_icl_nonce_menu_sync', '_icl_nonce_menu_sync' ); ?>
</form>
<?php
if ( ! empty( $icl_menus_sync->operations ) ) {
$show_string_translation_link = false;
foreach ( $icl_menus_sync->operations as $op => $c ) {
if ( $op == 'add' ) {
?>
<span class="icl_msync_item icl_msync_add"><?php esc_html_e( 'Item will be added', 'sitepress' ); ?></span>
<?php
} elseif ( $op == 'del' ) {
?>
<span class="icl_msync_item icl_msync_del"><?php esc_html_e( 'Item will be removed', 'sitepress' ); ?></span>
<?php
} elseif ( $op == 'not' ) {
?>
<span class="icl_msync_item icl_msync_not"><?php esc_html_e( 'Item cannot be added (parent not translated)', 'sitepress' ); ?></span>
<?php
} elseif ( $op == 'mov' ) {
?>
<span class="icl_msync_item icl_msync_mov"><?php esc_html_e( 'Item changed position', 'sitepress' ); ?></span>
<?php
} elseif ( $op == 'copy' ) {
?>
<span class="icl_msync_item icl_msync_copy"><?php esc_html_e( 'Item will be copied', 'sitepress' ); ?></span>
<?php
} elseif ( $op == 'label_changed' ) {
?>
<span class="icl_msync_item icl_msync_label_changed"><?php esc_html_e( 'Strings for menus will be updated', 'sitepress' ); ?></span>
<?php
} elseif ( $op == 'url_changed' ) {
?>
<span class="icl_msync_item icl_msync_url_changed"><?php esc_html_e( 'URLs for menus will be updated', 'sitepress' ); ?></span>
<?php
} elseif ( $op == 'options_changed' ) {
?>
<span class="icl_msync_item icl_msync_options_changed"><?php esc_html_e( 'Menu Options will be updated', 'sitepress' ); ?></span>
<?php
} elseif ( $op == 'label_missing' ) {
?>
<span class="icl_msync_item icl_msync_label_missing">
<?php esc_html_e( 'Untranslated strings for menus', 'sitepress' ); ?>
</span>
<?php
} elseif ( $op == 'url_missing' ) {
?>
<span class="icl_msync_item icl_msync_url_missing">
<?php esc_html_e( 'Untranslated URLs for menus', 'sitepress' ); ?>
</span>
<?php
}
}
}
$icl_menus_sync->display_menu_links_to_string_translation();
}
do_action( 'icl_menu_footer' );
?>
</div>

View File

@@ -0,0 +1,106 @@
<?php
class WPML_Menu_Sync_Display {
private $menu_id;
/** @var ICLMenusSync $icl_ms*/
private $icl_ms;
private $labels;
public function __construct( $menu_id, $icl_ms ) {
$this->menu_id = $menu_id;
$this->icl_ms = $icl_ms;
$this->labels = array(
'del' => array( esc_html__( 'Remove %s', 'sitepress' ), '' ),
'label_changed' => array( esc_html__( 'Rename label to %s', 'sitepress' ), '' ),
'url_changed' => array( esc_html__( 'Update URL to %s', 'sitepress' ), '' ),
'url_missing' => array( esc_html__( 'Untranslated URL %s', 'sitepress' ), '' ),
'mov' => array( esc_html__( 'Change menu order for %s', 'sitepress' ), '' ),
'add' => array( esc_html__( 'Add %s', 'sitepress' ), '' ),
'options_changed' => array( esc_html__( 'Update %1$s menu option to %2$s', 'sitepress' ), '' ),
);
if ( defined( 'WPML_ST_FOLDER' ) ) {
$this->labels['label_missing'] = array(
esc_html__( 'Untranslated string %s', 'sitepress' ),
$this->print_label_missing_text( $icl_ms, $menu_id ),
);
}
}
private function print_label_missing_text( $icl_menus_sync, $menu_id ) {
$context_menu_name = $icl_menus_sync->menus[ $menu_id ]['name'] . ' menu';
$res = '&nbsp;' . sprintf(
esc_html__(
'The selected strings can now be translated using the %1$s string translation %2$s screen',
'sitepress'
),
'<a href="admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php&context=' . $context_menu_name . '"',
'</a>'
);
return $res;
}
public function print_sync_field( $index ) {
global $sitepress;
$icl_menus_sync = $this->icl_ms;
$menu_id = $this->menu_id;
// items translations / del
if ( isset( $icl_menus_sync->sync_data[ $index ][ $menu_id ] ) ) {
foreach ( $icl_menus_sync->sync_data[ $index ][ $menu_id ] as $item_id => $languages ) {
foreach ( $languages as $lang_code => $name ) {
$additional_data = $this->get_additional_data( $index, $name );
$item_name = $this->get_item_name( $index, $name );
$lang_details = $sitepress->get_language_details( $lang_code );
$input_name = esc_attr( sprintf( 'sync[%s][%s][%s][%s]%s', $index, $menu_id, $lang_code, $item_id, $additional_data ) );
?>
<tr>
<th scope="row" class="check-column">
<input type="checkbox"
name="<?php echo $input_name; ?>"
value="<?php echo esc_attr( $item_name ); ?>"/>
</th>
<td><?php echo esc_html( $lang_details['display_name'] ); ?></td>
<td><?php echo $this->get_action_label( $index, $item_name, $item_id ); ?> </td>
</tr>
<?php
}
}
}
}
private function get_action_label( $index, $item_name, $item_id ) {
$labels = $this->labels;
if ( 'options_changed' !== $index ) {
$argument = sprintf( $labels[ $index ][0], '<strong>' . $item_name . '</strong>' );
} else {
$argument = sprintf(
$labels[ $index ][0],
'<strong>' . $item_id . '</strong>',
'<strong>' . ( $item_name ? $item_name : '0' ) . '</strong>'
);
}
return $this->hierarchical_prefix( $index, $item_id ) . $argument . $labels[ $index ][1];
}
private function get_additional_data( $index, $name ) {
return 'mov' === $index ? '[' . key( $name ) . ']' : '';
}
private function get_item_name( $index, $name ) {
return 'mov' === $index ? current( $name ) : $name;
}
private function hierarchical_prefix( $index, $item_id ) {
$prefix = '';
if ( in_array( $index, array( 'mov', 'add' ), true ) ) {
$prefix = str_repeat( ' - ', $this->icl_ms->get_item_depth( $this->menu_id, $item_id ) );
}
return $prefix;
}
}

View File

@@ -0,0 +1,214 @@
<?php
$wp_list_table = _get_list_table( 'WP_MS_Sites_List_Table' );
$pagenum = $wp_list_table->get_pagenum();
$id = isset( $_REQUEST['id'] ) ? intval( $_REQUEST['id'] ) : 0;
$wp_list_table->prepare_items();
$total_pages = $wp_list_table->get_pagination_arg( 'total_pages' );
if ( $pagenum > $total_pages && $total_pages > 0 ) {
wp_redirect( add_query_arg( 'paged', $total_pages ) );
exit;
}
$msg = '';
if ( isset( $_REQUEST['updated'] ) && 'true' === $_REQUEST['updated'] && ! empty( $_REQUEST['action'] ) ) {
switch ( $_REQUEST['action'] ) {
case 'resetwpml':
$msg = esc_html__( 'WPML has been reset for the selected site.', 'sitepress' );
break;
case 'deactivatewpml':
$msg = esc_html__( 'WPML has been deactivated for the selected site.', 'sitepress' );
break;
case 'activatewpml':
$msg = esc_html__( 'WPML has been activated for the selected site.', 'sitepress' );
break;
default:
$msg = false;
}
if ( $msg ) {
$msg = '<div class="updated" id="message"><p>' . $msg . '</p></div>';
}
}
$text = isset( $text ) ? $text : '';
?>
<div class="wrap">
<h2><?php echo esc_html__( 'WPML Network Setup', 'sitepress' ); ?>
<?php
if ( isset( $_REQUEST['s'] ) && $_REQUEST['s'] ) {
printf( '<span class="subtitle">' . esc_html__( 'Search results for &#8220;%s&#8221;' ) . '</span>', filter_var( $_REQUEST['s'], FILTER_SANITIZE_SPECIAL_CHARS ) );
}
?>
</h2>
<form action="" method="get" id="ms-search">
<p class="search-box">
<label class="screen-reader-text" for="icl_ss"><?php echo esc_html( $text ); ?>:</label>
<input type="hidden" name="page" value="<?php echo esc_attr( $_GET['page'] ); ?>"/>
<input type="text" id="icl_ss" name="s" value="<?php _admin_search_query(); ?>"/>
<?php submit_button( __( 'Search', 'sitepress' ), 'button', false, false, array( 'id' => 'search-submit' ) ); ?>
</p>
</form>
<?php echo $msg; ?>
<br/>
<?php if ( empty( $wp_list_table->items ) ) : ?>
<?php $wp_list_table->no_items(); ?>
<?php else : ?>
<div class="tablenav top">
<?php
$wp_list_table->pagination( 'bottom' );
?>
</div>
<table class="wp-list-table widefat">
<thead>
<tr>
<th><?php esc_html_e( 'Site', 'sitepress' ); ?></th>
<th><?php esc_html_e( 'Status', 'sitepress' ); ?></th>
<th>&nbsp;</th>
</tr>
</thead>
<tfoot>
<tr>
<th><?php esc_html_e( 'Site', 'sitepress' ); ?></th>
<th><?php esc_html_e( 'Status', 'sitepress' ); ?></th>
<th>&nbsp;</th>
</tr>
</tfoot>
<tbody>
<?php
$status_list = array(
'archived' => array( 'site-archived', esc_html__( 'Archived' ) ),
'spam' => array( 'site-spammed', esc_html_x( 'Spam', 'site' ) ),
'deleted' => array( 'site-deleted', esc_html__( 'Deleted' ) ),
'mature' => array( 'site-mature', esc_html__( 'Mature' ) ),
);
$class = '';
foreach ( $wp_list_table->items as $blog ) :
if ( class_exists( 'WP_Site' ) && $blog instanceof WP_Site ) {
$blog = object_to_array( $blog );
}
$class = ( 'alternate' == $class ) ? '' : 'alternate';
$blog_states = array();
foreach ( $status_list as $status => $col ) {
if ( 1 === get_blog_status( $blog['blog_id'], $status ) ) {
$class = $col[0];
$blog_states[] = $col[1];
}
}
$blog_state = '';
if ( ! empty( $blog_states ) ) {
$state_count = count( $blog_states );
$i = 0;
$blog_state .= ' - ';
foreach ( $blog_states as $state ) {
++ $i;
( $i == $state_count ) ? $sep = '' : $sep = ', ';
$blog_state .= "<span class='post-state'>" . esc_html( $state . $sep ) . '</span>';
}
}
?>
<tr class="<?php echo esc_attr( $class ); ?>">
<td class='column-blogname blogname'>
<?php
$current_site = get_current_site();
$blog_name = $blog['path'];
if ( ( is_subdomain_install() ) ) {
$blog_name = str_replace( '.' . $current_site->domain, '', $blog['domain'] );
}
?>
<a href="<?php echo esc_url( network_admin_url( 'site-info.php?id=' . $blog['blog_id'] ) ); ?>"
class="edit"><?php echo esc_html( $blog_name ) . $blog_state; ?></a>
<?php
// Preordered.
$actions = array(
'edit' => '',
'backend' => '',
'activate' => '',
'deactivate' => '',
'archive' => '',
'unarchive' => '',
'spam' => '',
'unspam' => '',
'delete' => '',
'visit' => '',
);
$actions['edit'] = '<span class="edit"><a href="' . esc_url( network_admin_url( 'site-info.php?id=' . $blog['blog_id'] ) ) . '">' . esc_html__( 'Edit', 'sitepress' ) . '</a></span>';
$actions['backend'] = "<span class='backend'><a href='" . esc_url( get_admin_url( $blog['blog_id'] ) ) . "' class='edit'>" . esc_html__( 'Dashboard', 'sitepress' ) . '</a></span>';
$actions['visit'] = "<span class='view'><a href='" . esc_url( get_home_url( $blog['blog_id'] ) ) . "' rel='permalink'>" . esc_html__( 'Visit', 'sitepress' ) . '</a></span>';
$actions = apply_filters( 'manage_sites_action_links', array_filter( $actions ), $blog['blog_id'], $blog_name );
echo $wp_list_table->row_actions( $actions );
?>
</td>
<td>
<?php switch_to_blog( $blog['blog_id'] ); ?>
<?php if ( get_option( '_wpml_inactive', false ) ) : ?>
<?php esc_html_e( 'Inactive', 'sitepress' ); ?>
<div class="row-actions">
<a href="<?php echo esc_url( wp_nonce_url( network_admin_url( 'sites.php?action=activatewpml&amp;id=' . (int) $blog['blog_id'] ), 'activatewpml' ) ); ?>"><?php esc_html_e( 'Activate', 'sitepress' ); ?></a>
</div>
<?php else : ?>
<?php esc_html_e( 'Active', 'sitepress' ); ?>
<div class="row-actions">
<?php
global $current_blog;
if ( $blog['blog_id'] != $current_blog->blog_id ) {
?>
<a href="<?php echo esc_url( wp_nonce_url( network_admin_url( 'sites.php?action=deactivatewpml&amp;id=' . (int) $blog['blog_id'] ), 'deactivatewpml' ) ); ?>"><?php esc_html_e( 'Deactivate', 'sitepress' ); ?></a>
<?php
}
?>
</div>
<?php endif; ?>
<?php restore_current_blog(); ?>
</td>
<td><a onclick="WPML_core.network.reset_wpml(this)" href="#"
data-link="<?php echo esc_url( wp_nonce_url( network_admin_url( 'sites.php?action=resetwpml&amp;id=' . (int) $blog['blog_id'] ), 'resetwpml' ) ); ?>"
data-msg="
<?php
echo sprintf( esc_html__( 'You are about to reset WPML for this site: %s.', 'sitepress' ), esc_html( $blog_name ) ) .
' ' . esc_html__( "All translation data will be lost if you reset WPML's data. They cannot be recovered later.", 'sitepress' )
?>
"><?php esc_html_e( 'Reset', 'sitepress' ); ?></a></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="tablenav bottom">
<?php
$wp_list_table->pagination( 'bottom' );
?>
</div>
<?php endif ?>
</div>
<script type="text/javascript">
var WPML_core = WPML_core || {};
WPML_core.network = {};
WPML_core.network.reset_wpml = function (link) {
link = jQuery(link);
if (confirm(link.data('msg'))) {
window.location = link.data('link');
}
}
</script>

View File

@@ -0,0 +1,14 @@
<?php
class WPML_Meta_Boxes_Post_Edit_Ajax_Factory implements IWPML_Backend_Action_Loader, IWPML_AJAX_Action_Loader {
/**
* @return WPML_Meta_Boxes_Post_Edit_Ajax
*/
public function create() {
global $sitepress, $wpml_post_translations;
$post_edit_metabox = new WPML_Meta_Boxes_Post_Edit_HTML( $sitepress, $wpml_post_translations );
return new WPML_Meta_Boxes_Post_Edit_Ajax( $post_edit_metabox, wpml_load_core_tm(), new WPML_Admin_Language_Switcher() );
}
}

View File

@@ -0,0 +1,94 @@
<?php
class WPML_Meta_Boxes_Post_Edit_Ajax implements IWPML_Action {
const ACTION_GET_META_BOXES = 'wpml_get_meta_boxes_html';
const ACTION_GET_ADMIN_LS = 'wpml_get_admin_ls_links';
const ACTION_DUPLICATE = 'make_duplicates';
private $meta_boxes_post_edit_html;
private $translation_management;
private $admin_language_switcher;
public function __construct(
WPML_Meta_Boxes_Post_Edit_HTML $meta_boxes_post_edit_html,
TranslationManagement $iclTranslationManagement,
WPML_Admin_Language_Switcher $admin_language_switcher
) {
$this->translation_management = $iclTranslationManagement;
$this->meta_boxes_post_edit_html = $meta_boxes_post_edit_html;
$this->admin_language_switcher = $admin_language_switcher;
}
public function add_hooks() {
add_action( 'wp_ajax_' . self::ACTION_GET_META_BOXES, array( $this, 'render_meta_boxes_html' ) );
add_action( 'wp_ajax_' . self::ACTION_GET_ADMIN_LS, [ $this, 'get_admin_ls_links' ] );
add_action( 'wp_ajax_' . self::ACTION_DUPLICATE, array( $this, 'duplicate_post' ) );
add_filter( 'wpml_post_edit_can_translate', array( $this, 'force_post_edit_when_refreshing_meta_boxes' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
}
/**
* @param string $hook
*/
public function enqueue_scripts( $hook ) {
if (
in_array( $hook, [ 'post.php', 'post-new.php', 'edit.php' ], true ) ||
apply_filters( 'wpml_enable_language_meta_box', false )
) {
wp_enqueue_script( 'wpml-meta-box', ICL_PLUGIN_URL . '/dist/js/wpml-meta-box/wpml-meta-box.js', [], ICL_SITEPRESS_VERSION, true );
}
}
public function render_meta_boxes_html() {
if ( $this->is_valid_request( self::ACTION_GET_META_BOXES ) ) {
$post_id = (int) $_POST['post_id'];
$this->meta_boxes_post_edit_html->render_languages( get_post( $post_id ) );
wp_die();
}
}
public function get_admin_ls_links() {
if ( $this->is_valid_request( self::ACTION_GET_ADMIN_LS ) ) {
$links = $this->admin_language_switcher->get_languages_links();
wp_send_json_success( $links );
}
}
/**
* @param bool $is_edit_page
*
* @return bool
*/
public function force_post_edit_when_refreshing_meta_boxes( $is_edit_page ) {
return isset( $_POST['action'] ) && self::ACTION_GET_META_BOXES === $_POST['action'] ? true : $is_edit_page;
}
public function duplicate_post() {
if ( $this->is_valid_request( self::ACTION_DUPLICATE ) ) {
$post_id = (int) $_POST['post_id'];
$mdata['iclpost'] = array( $post_id );
$langs = explode( ',', $_POST['langs'] );
foreach ( $langs as $lang ) {
$mdata['duplicate_to'][ $lang ] = 1;
}
$this->translation_management->make_duplicates( $mdata );
do_action( 'wpml_new_duplicated_terms', (array) $mdata['iclpost'], false );
wp_send_json_success();
} else {
wp_send_json_error();
}
}
/**
* @param string $action
* @return bool
*/
private function is_valid_request( $action ) {
$action = $action ? $action : self::ACTION_GET_META_BOXES;
return isset( $_POST['nonce'] ) && wp_verify_nonce( $_POST['nonce'], $action );
}
}

View File

@@ -0,0 +1,880 @@
<?php
/**
* Class WPML_Meta_Boxes_Post_Edit_HTML
*/
class WPML_Meta_Boxes_Post_Edit_HTML {
const FLAG_HAS_MEDIA_OPTIONS = 'wpml_has_media_options';
const TAXONOMIES_PRIORITY = 'translation_priority';
const WRAPPER_ID = 'icl_div';
/** @var SitePress $sitepress */
private $sitepress;
/** @var WPML_Post_Translation $post_translation */
private $post_translation;
private $translation_of_options;
/** @var array $allowed_languages */
private $allowed_languages;
/** @var bool $can_translate_post */
private $can_translate_post;
/** @var bool $is_original */
private $is_original;
/** @var WP_Post $post */
private $post;
/** @var string $post_type_label */
private $post_type_label;
/** @var string $selected_language */
private $selected_language;
/** @var string $source_language */
private $source_language;
/** @var array $translations */
private $translations;
/** @var int $trid */
private $trid;
/**
* @param SitePress $sitepress
* @param WPML_Post_Translation $post_translation
*/
function __construct( SitePress $sitepress, WPML_Post_Translation $post_translation ) {
$this->sitepress = $sitepress;
$this->post_translation = $post_translation;
}
/**
* @param null|WP_Post $post
*/
public function render_languages( $post = null ) {
if ( ! $post || ! is_post_type_translated( $post->post_type ) ) {
return;
}
$this->set_post( $post );
$this->init_post_data();
$this->post_edit_languages_duplicate_of();
ob_start();
$this->post_edit_languages_dropdown();
$this->connect_translations();
$this->translation_priority();
$this->translation_of();
$this->languages_actions();
$this->copy_from_original( $post );
if ( $this->sitepress->is_translated_post_type( 'attachment' ) ) {
$this->media_options( $post );
}
$this->minor_edit();
do_action( 'icl_post_languages_options_after' );
$contents = ob_get_clean();
echo $this->is_a_duplicate() ? '<span style="display:none">' . $contents . '</span>' : $contents;
}
private function post_edit_languages_duplicate_of() {
$duplicate_original_id = $this->is_a_duplicate();
if ( $duplicate_original_id ) {
?>
<div class="icl_cyan_box"><?php
printf( esc_html__( 'This document is a duplicate of %s and it is maintained by WPML.', 'sitepress' ), '<a href="' . esc_url( get_edit_post_link( $duplicate_original_id ) ) . '">' . esc_html( get_the_title( $duplicate_original_id ) ) . '</a>' );
?>
<p><input id="icl_translate_independent" class="button-secondary" type="button" value="<?php esc_html_e( 'Translate independently', 'sitepress' ) ?>"/></p>
<?php wp_nonce_field( 'reset_duplication_nonce', '_icl_nonce_rd' ) ?>
<i><?php printf( esc_html__( 'WPML will no longer synchronize this %s with the original content.', 'sitepress' ), $this->post->post_type ); ?></i>
</div>
<?php
}
}
private function post_edit_languages_dropdown() {
?>
<div id="icl_document_language_dropdown" class="icl_box_paragraph"
data-metabox-refresh-nonce="<?php echo wp_create_nonce( WPML_Meta_Boxes_Post_Edit_Ajax::ACTION_GET_META_BOXES ) ?>"
data-admin-ls-refresh-nonce="<?php echo wp_create_nonce( WPML_Meta_Boxes_Post_Edit_Ajax::ACTION_GET_ADMIN_LS ) ?>">
<p>
<label for="icl_post_language">
<strong><?php printf( esc_html__( 'Language of this %s', 'sitepress' ), esc_html( $this->post_type_label ) ); ?></strong>
</label>
</p>
<?php
$disabled_language = disabled( false, $this->can_translate_post, false );
wp_nonce_field( WPML_Post_Edit_Ajax::AJAX_ACTION_SWITCH_POST_LANGUAGE, 'nonce' );
?>
<select name="icl_post_language" id="icl_post_language" <?php echo $disabled_language; ?>>
<?php
$active_langs = $this->sitepress->get_active_languages();
$active_langs = apply_filters( 'wpml_active_languages_access', $active_langs, array( 'action'=>'edit' ) );
$translations = $this->get_translations();
foreach ( $active_langs as $code => $lang ) {
if ( ( $code != $this->selected_language && ! in_array( $code, $this->allowed_languages ) )
|| ( isset( $translations[ $code ] ) && $translations[ $code ] != $this->post->ID )
) {
continue;
}
?>
<option value="<?php echo esc_attr( $code ); ?>" <?php selected( true, $this->is_selected_lang( $code, $this->selected_language ), true ); ?>>
<?php echo esc_html( $lang['display_name'] ); ?>
</option>
<?php
}
?>
</select>
<input type="hidden" name="icl_trid" value="<?php echo esc_attr( $this->get_trid() ); ?>"/>
</div>
<?php
}
private function translation_priority() {
if ( \WPML\Setup\Option::isTMAllowed() ) {
?>
<div id="icl_translation_priority_dropdown" class="icl_box_paragraph">
<p>
<label for="icl_translation_priority_dropdown">
<strong><?php esc_html_e( 'Translation Priority', 'sitepress' ); ?></strong>
</label>
</p>
<?php
wp_nonce_field( 'wpml_translation_priority', 'nonce' );
wp_dropdown_categories(
array(
'hide_empty' => 0,
'selected' => $this->get_selected_priority(),
'name' => 'icl_translation_priority',
'taxonomy' => self::TAXONOMIES_PRIORITY
)
);
?>
<a href="<?php echo admin_url( 'edit-tags.php?taxonomy=translation_priority' ); ?>"
target="_blank"><?php esc_html_e( 'edit terms', 'sitepress' ); ?></a>
</div>
<?php
}
}
/**
* @param int $element_id
*
* @return WP_Term|null
*/
private function get_term_obj( $element_id ) {
$terms = wp_get_object_terms( $element_id, self::TAXONOMIES_PRIORITY );
if ( is_wp_error( $terms ) ) {
return null;
}
return empty( $terms ) ? null : $terms[0];
}
private function connect_translations() {
if ( 'auto-draft' !== $this->post->post_status ) {
$trid = $this->get_trid();
$current_language = $this->sitepress->get_current_language();
if ( count( $this->get_translations() ) === 1 && count( $this->sitepress->get_orphan_translations( $trid, $this->post->post_type, $current_language ) ) > 0 ) {
$args = array();
$args['language_code'] = $this->selected_language;
$args['display_code'] = $this->sitepress->get_default_language();
$language_name = apply_filters( 'wpml_display_single_language_name', null, $args );
?>
<div id="icl_document_connect_translations_dropdown" class="icl_box_paragraph">
<p>
<a class="js-set-post-as-source" href="#">
<?php esc_html_e( 'Connect with translations', 'sitepress' ); ?>
</a>
</p>
<input type="hidden" id="icl_connect_translations_post_id" name="icl_connect_translations_post_id"
value="<?php echo esc_attr( $this->post->ID ); ?>"/>
<input type="hidden" id="icl_connect_translations_trid" name="icl_connect_translations_trid"
value="<?php echo esc_attr( $trid ); ?>"/>
<input type="hidden" id="icl_connect_translations_post_type"
name="icl_connect_translations_post_type" value="<?php echo esc_attr( $this->post->post_type ); ?>"/>
<input type="hidden"
id="icl_connect_translations_language"
name="icl_connect_translations_language"
value="<?php echo esc_attr( $current_language ); ?>"/>
<?php wp_nonce_field( 'get_orphan_posts_nonce', '_icl_nonce_get_orphan_posts' ); ?>
</div>
<div class="hidden">
<div id="connect_translations_dialog"
title="<?php esc_attr_e( sprintf( 'Choose a %s to assign', get_post_type_object( get_post_type( $this->post ) )->labels->singular_name ), 'sitepress' ); ?>"
data-set_as_source-text="<?php echo esc_attr( sprintf( __( 'Make %s the original language for this %s', 'sitepress' ), $language_name, $this->post->post_type ) ); ?>"
data-alert-text="<?php esc_attr_e( "Please make sure to save your post, if you've made any change, before proceeding with this action!", 'sitepress' ); ?>"
data-cancel-label="<?php esc_attr_e( 'Cancel', 'sitepress' ); ?>"
data-ok-label="<?php esc_attr_e( 'Ok', 'sitepress' ); ?>">
<p class="js-ajax-loader ajax-loader">
<?php esc_html_e( 'Loading', 'sitepress' ); ?>&hellip; <span class="spinner"></span>
</p>
<div class="posts-found js-posts-found">
<label id="post-label" for="post_search">
<?php esc_html_e( 'Type a post title', 'sitepress' ); ?>: </label>
<input id="post_search" type="text">
</div>
<p class="js-no-posts-found no-posts-found"><?php esc_html_e( 'No posts found', 'sitepress' ) ?></p>
<input type="hidden" id="assign_to_trid">
</div>
<div id="connect_translations_dialog_confirm"
title="<?php esc_attr_e( 'Connect this post?', 'sitepress' ); ?>"
data-cancel-label="<?php esc_attr_e( 'Cancel', 'sitepress' ); ?>"
data-assign-label="<?php esc_attr_e( 'Assign', 'sitepress' ); ?>">
<p>
<span class="ui-icon ui-icon-alert"></span> <?php esc_html_e( 'You are about to connect the current post with these following posts', 'sitepress' ); ?>
: </p>
<div id="connect_translations_dialog_confirm_list">
<p class="js-ajax-loader ajax-loader">
<?php esc_html_e( 'Loading', 'sitepress' ); ?>&hellip; <span class="spinner"></span>
</p>
</div> <?php wp_nonce_field( 'get_posts_from_trid_nonce', '_icl_nonce_get_posts_from_trid' ); ?>
<?php wp_nonce_field( 'connect_translations_nonce', '_icl_nonce_connect_translations' ); ?>
</div>
</div>
<?php
}
}
}
private function translation_of() {
?>
<div id="translation_of_wrap">
<?php
if ( 'auto-draft' !== $this->post->post_status && ( $this->is_a_translation() || ! $this->has_translations() ) ) {
$disabled = disabled( false, $this->is_edit_action() && $this->get_trid(), false );
?>
<div id="icl_translation_of_panel" class="icl_box_paragraph">
<label for="icl_translation_of"><?php esc_html_e( 'This is a translation of', 'sitepress' ); ?></label>&nbsp;
<select name="icl_translation_of" id="icl_translation_of" <?php echo $disabled; ?>>
<?php
$this->render_translation_of_options();
?>
</select>
<?php //Add hidden value when the dropdown is hidden ?>
<?php
$source_element_id = SitePress::get_original_element_id_by_trid( $this->get_trid() );
if ( $disabled && ! empty( $source_element_id ) ) {
?>
<input type="hidden" name="icl_translation_of" id="icl_translation_of_hidden" value="<?php echo esc_attr( $source_element_id ); ?>">
<?php
}
?>
</div>
<?php
}
?>
</div><!--//translation_of_wrap--><?php // don't delete this html comment ?>
<br clear="all"/>
<?php
}
private function minor_edit() {
$stacktrace = new WPML\Utils\DebugBackTrace();
if ( $stacktrace->is_function_in_call_stack( 'the_block_editor_meta_boxes' ) ) {
do_action( 'wpml_minor_edit_for_gutenberg' );
}
}
private function languages_actions() {
$status_display = new WPML_Post_Status_Display( $this->sitepress->get_active_languages() );
if ( $this->can_translate() ) {
do_action( 'icl_post_languages_options_before', $this->post->ID );
list( $translated_posts, $untranslated_posts ) = $this->count_untranslated_posts();
?>
<div id="icl_translate_options">
<?php
if ( $untranslated_posts ) {
$this->languages_table( $status_display );
}
if ( $translated_posts > 0 ) {
$this->translation_summary( $status_display );
}
?>
</div>
<?php
}
}
private function is_a_translation() {
return ! $this->is_original && ( $this->selected_language != $this->source_language || ( isset( $_GET[ 'lang' ] ) && $this->source_language !== $_GET[ 'lang' ] ) ) && 'all' !== $this->sitepress->get_current_language();
}
private function has_translations() {
return (bool) $this->get_translations();
}
private function render_translation_of_options() {
$this->init_translation_of_options();
foreach ( $this->translation_of_options as $option_value => $option_data ) {
echo sprintf( '<option value="%s" %s>%s</option>', esc_attr( $option_value ), selected( true, $option_data[ 'selected' ], false ), esc_html( $option_data[ 'label' ] ) );
}
}
/**
* @return bool
*/
private function can_translate() {
$trid = $this->get_trid();
$can_translate_args = array(
'trid' => $trid,
'translations' => $this->get_translations(),
);
$can_translate_aaa = $trid && ( $this->is_edit_action() || apply_filters( 'wpml_post_edit_can_translate', false, $can_translate_args ) );
return $can_translate_aaa;
}
private function count_untranslated_posts() {
$untranslated_found = 0;
$translations_found = 0;
$active_langs = $this->sitepress->get_active_languages();
$translations = $this->get_translations();
foreach ( $active_langs as $lang ) {
if ( $this->selected_language == $lang['code'] ) {
continue;
}
if ( isset( $translations[ $lang['code'] ] ) ) {
$translations_found += 1;
} else {
$untranslated_found += 1;
}
}
return array( $translations_found, $untranslated_found );
}
private function languages_table( $status_display ) {
?>
<p style="clear:both;"><b><?php esc_html_e( 'Translate this Document', 'sitepress' ); ?></b></p>
<?php
/**
* Fire actions before to render the translations tables
*
* @since 4.2.0
*
* @param WP_Post $this->post
*/
do_action( 'wpml_before_post_edit_translations_table', $this->post );
?>
<table width="100%" id="icl_untranslated_table" class="icl_translations_table">
<tr>
<th>&nbsp;</th>
<th align="right"><?php esc_html_e( 'Translate', 'sitepress' ) ?></th>
<th align="right" width="10" style="padding-left:8px;"><?php echo esc_html__( 'Duplicate', 'sitepress' ) ?></th>
</tr>
<?php
$active_langs = $this->sitepress->get_active_languages();
$active_langs = apply_filters( 'wpml_active_languages_access', $active_langs, array( 'action' => 'edit', 'post_type' => $this->post_type_label, 'post_id' => $this->post->ID ) );
foreach ( $active_langs as $lang ) {
$this->translate_option( $lang, $status_display );
}
?>
<tr>
<td colspan="3" align="right">
<input
id="icl_make_duplicates"
type="button"
class="button-secondary"
value="<?php echo esc_attr__( 'Duplicate', 'sitepress' ) ?>"
disabled="disabled"
style="display:none;"
data-action="<?php echo WPML_Meta_Boxes_Post_Edit_Ajax::ACTION_DUPLICATE; ?>"
data-nonce="<?php echo wp_create_nonce( WPML_Meta_Boxes_Post_Edit_Ajax::ACTION_DUPLICATE ); ?>"
data-post-id="<?php echo isset( $this->post->ID ) ? $this->post->ID : 0; ?>"
/>
</td>
</tr>
</table>
<?php
}
/**
* @param WPML_Post_Status_Display $status_display
*/
private function translation_summary( $status_display ) {
$dupes = $this->sitepress->get_duplicates( $this->post->ID );
$not_show_flags = ! apply_filters( 'wpml_setting', false, 'show_translations_flag' );
?>
<div class="icl_box_paragraph">
<p><b><?php esc_html_e( 'Translations', 'sitepress' ) ?></b>
(<a class="icl_toggle_show_translations" href="#" <?php if ( $not_show_flags ) : ?>style="display:none;"<?php endif; ?>><?php esc_html_e( 'hide', 'sitepress' ); ?></a><a class="icl_toggle_show_translations" href="#" <?php if ( ! $not_show_flags ) : ?>style="display:none;"<?php endif; ?>><?php esc_html_e( 'show', 'sitepress' ) ?></a>)
</p>
<?php
/**
* Fire actions before to render the translations summary
*
* @since 4.2.0
*
* @param WP_Post $this->post
*/
do_action( 'wpml_before_post_edit_translations_summary', $this->post );
wp_nonce_field( 'toggle_show_translations_nonce', '_icl_nonce_tst' );
?>
<table width="100%" class="icl_translations_table wpml-margin-bottom-base" id="icl_translations_table"
<?php
if ( $not_show_flags ) : ?>style="display:none;"<?php endif; ?>>
<?php
$odd_even = 1;
$active_langs = $this->sitepress->get_active_languages();
$translations = $this->get_translations();
?>
<?php foreach ( $active_langs as $lang ) :
if ( $this->selected_language === $lang['code'] ) {
continue;
} ?>
<tr <?php if ( $odd_even < 0 ) : ?>class="icl_odd_row"<?php endif; ?>>
<?php if ( isset( $translations[ $lang['code'] ] ) ) : ?>
<?php $odd_even = $odd_even * - 1; ?>
<td style="padding-left: 4px;">
<?php echo esc_html( $lang['display_name'] ); ?>
<?php if ( isset( $dupes[ $lang['code'] ] ) ) {
echo ' (' . esc_html__( 'duplicate', 'sitepress' ) . ')';
} ?>
</td>
<td align="right">
<?php echo $status_display->get_status_html( $this->post->ID, $lang['code'] ); ?>
</td>
<?php endif; ?>
</tr>
<?php endforeach; ?>
</table>
</div>
<?php
}
private function init_translation_of_options() {
$this->translation_of_options = array();
$element_id = null;
if ( $this->trid ) {
$this->fix_source_language();
$element_id = $this->post_translation->get_element_id( $this->source_language, $this->trid );
}
$this->add_translation_of_option( 'none', __( '--None--', 'sitepress' ), false );
if ( $element_id && ! isset( $_GET['icl_ajx'] ) ) {
$element_title = $this->get_element_title( $element_id );
$this->add_translation_of_option( $element_id, $element_title, true );
}
if ( $this->handle_as_original() && apply_filters( 'wpml_language_is_active', null, $this->selected_language )
) {
$untranslated = $this->get_untranslated_posts();
foreach ( $untranslated as $translation_of_id => $translation_of_title ) {
$this->add_translation_of_option( $translation_of_id, $translation_of_title, false );
}
}
}
/**
* @param string $lang
* @param WPML_Post_Status_Display $status_display
*/
private function translate_option( $lang, $status_display ) {
static $row = 0;
if ( $this->selected_language == $lang[ 'code' ] ) {
return;
}
$row_class = 0 === $row % 2 ? 'class="icl_odd_row"' : '';
?>
<tr <?php echo $row_class; ?>>
<?php
$translations = $this->get_translations();
if ( ! isset( $translations[ $lang['code'] ] ) ) {
$row ++;
?>
<td style="padding-left: 4px;">
<?php echo esc_html( $lang['display_name'] ); ?>
</td>
<td align="right">
<?php echo $status_display->get_status_html( $this->post->ID, $lang[ 'code' ] ); ?>
</td>
<td align="right">
<?php
$disabled_duplication = false;
$disabled_duplication_title = esc_attr__( 'Create duplicate', 'sitepress' );
$element_key = array( 'trid' => $this->trid, 'language_code' => $lang['code'] );
$translation_status = apply_filters( 'wpml_tm_translation_status', null, $element_key );
echo PHP_EOL . '<!-- $translation_status = ' . $translation_status . ' -->' . PHP_EOL;
if ( $translation_status && $translation_status < ICL_TM_COMPLETE ) {
$disabled_duplication = true;
if ( ICL_TM_DUPLICATE === (int) $translation_status ) {
$disabled_duplication_title = esc_attr__( 'This post is already duplicated.', 'sitepress' );
} else {
$disabled_duplication_title = esc_attr__( "Can't create a duplicate. A translation is in progress.", 'sitepress' );
}
}
?>
<input<?php disabled( true, $disabled_duplication ); ?> type="checkbox" name="icl_dupes[]" value="<?php echo esc_attr( $lang['code'] ); ?>" title="<?php echo $disabled_duplication_title ?>"/>
</td>
<?php
}
?>
</tr>
<?php
}
private function handle_as_original() {
return $this->is_original || ! $this->source_language || $this->source_language === $this->selected_language;
}
private function add_translation_of_option( $value, $label, $selected ) {
if ( ! isset( $this->translation_of_options[ $value ] ) ) {
if ( trim( $label ) == '' ) {
$label = '{' . __( 'Post without a title', 'sitepress' ) . '}';
}
$this->translation_of_options[ $value ] = array( 'label' => $label, 'selected' => $selected );
}
}
private function fix_source_language() {
if ( ! $this->source_language ) {
if ( $this->post ) {
$this->source_language = $this->post_translation->get_source_lang_code( $this->post->ID );
} else {
$this->source_language = $this->sitepress->get_default_language();
}
}
}
/**
* @return bool
*/
private function is_edit_action() {
return isset( $_GET['action'] ) && 'edit' === $_GET['action'];
}
/**
* Helper function to tell if $lang_code should be marked as selected in post language chooser
*
* @param string $lang_code 2 letters language code
* @param string $selected_language 2 letters language code
*
* @return boolean
*/
private function is_selected_lang( $lang_code, $selected_language ) {
return $lang_code === $selected_language
|| ( ! $this->sitepress->is_active_language( $selected_language )
&& $lang_code === $this->sitepress->get_default_language() );
}
/**
* Renders the "Copy From" and "Overwrite With" buttons on the post edit screen.
*
* @param WP_Post $post
*
* @hook icl_post_languages_options_after
*/
private function copy_from_original( $post ) {
$trid = $this->get_trid();
$source_lang = filter_var( isset( $_GET['source_lang'] ) ? $_GET['source_lang'] : '', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
$source_lang = 'all' === $source_lang ? $this->sitepress->get_default_language() : $source_lang;
$lang = filter_var( isset( $_GET['lang'] ) ? $_GET['lang'] : '', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
$source_lang = ! $source_lang && isset( $_GET['post'] ) && $lang !== $this->sitepress->get_default_language()
? $this->post_translation->get_source_lang_code( $post->ID ) : $source_lang;
if ( $source_lang && $source_lang !== $lang ) {
$_lang_details = $this->sitepress->get_language_details( $source_lang );
$source_lang_name = $_lang_details['display_name'];
$this->display_copy_from_button( $source_lang, $source_lang_name, $post, $trid );
$this->display_set_as_dupl_btn( $post,
$source_lang_name,
$this->post_translation->get_element_id( $source_lang, $trid ),
$lang );
}
}
private function media_options( $post ) {
echo '<br /><br /><strong>' . esc_html__( 'Media attachments', 'sitepress' ) . '</strong>';
$original_post_id = (int) $this->post_translation->get_original_post_ID( $this->trid );
if( ! $original_post_id ){
$settings = get_option( '_wpml_media' );
$content_defaults = $settings['new_content_settings'];
$duplicate_media = $content_defaults['duplicate_media'];
$duplicate_featured = $content_defaults['duplicate_featured'];
} else{
$duplicate_media = get_post_meta( $original_post_id, WPML_Admin_Post_Actions::DUPLICATE_MEDIA_META_KEY, true );
$duplicate_featured = get_post_meta( $original_post_id, WPML_Admin_Post_Actions::DUPLICATE_FEATURED_META_KEY, true );
}
if( ! $original_post_id || (int) $post->ID === $original_post_id ){
$duplicate_media_label = esc_html__('Duplicate uploaded media to translations', 'sitepress');
$duplicate_featured_label = esc_html__('Duplicate featured image to translations', 'sitepress');
} else {
$duplicate_media_label = esc_html__('Duplicate uploaded media from original', 'sitepress');
$duplicate_featured_label = esc_html__('Duplicate featured image from original', 'sitepress');
}
echo '<br /><input name="' . self::FLAG_HAS_MEDIA_OPTIONS . '" type="hidden" value="1"/>';
echo '<br /><label><input name="wpml_duplicate_media" type="checkbox" value="1" ' .
checked( $duplicate_media, true, false ) . '/>&nbsp;' . $duplicate_media_label . '</label>';
echo '<br /><label><input name="wpml_duplicate_featured" type="checkbox" value="1" ' .
checked( $duplicate_featured, true, false ) . '/>&nbsp;' . $duplicate_featured_label . '</label>';
}
/**
* Renders the button for copying the original posts content to the currently edited post on the post edit screen.
*
* @param string $source_lang
* @param string $source_lang_name
* @param WP_Post $post
* @param int $trid
*/
private function display_copy_from_button( $source_lang, $source_lang_name, $post, $trid ) {
$disabled = trim( $post->post_content ) ? ' disabled="disabled"' : '';
wp_nonce_field( 'copy_from_original_nonce', '_icl_nonce_cfo_' . $trid );
echo '<input id="icl_cfo" class="button-secondary" type="button" value="' . sprintf(
esc_html__( 'Copy content from %s', 'sitepress' ),
$source_lang_name
) . '"
onclick="icl_copy_from_original(\'' . esc_js( $source_lang ) . '\', \'' . esc_js( $trid ) . '\')"'
. $disabled . ' />'; ?>
<i class="otgs-ico-help js-otgs-popover-tooltip"
data-tippy-zindex="999999"
title="<?php echo esc_html__("This operation copies the content from the original language onto this translation. It's meant for when you want to start with the original content, but keep translating in this language. This button is only enabled when there's no content in the editor.",'sitepress');?>"></i>
<?php }
/**
* Renders the "Overwrite" button on the post edit screen that allows setting the post as a duplicate of its
* original.
*
* @param WP_Post $post
* @param string $source_lang_name
* @param int $original_post_id
* @param string $post_lang
*/
private function display_set_as_dupl_btn( $post, $source_lang_name, $original_post_id, $post_lang ) {
wp_nonce_field( 'set_duplication_nonce', '_icl_nonce_sd' ) ?>
<input id="icl_set_duplicate" type="button" class="button-secondary"
value="<?php printf( esc_html__( 'Overwrite with %s content.', 'sitepress' ), $source_lang_name ) ?>"
data-wpml_original_post_id="<?php echo absint( $original_post_id ); ?>"
data-post_lang="<?php echo esc_attr( $post_lang ); ?>"/>
<span style="display: none;"><?php echo esc_js(
sprintf(
__(
'The current content of this %s will be permanently lost. WPML will copy the %s content and replace the current content.',
'sitepress'
),
$post->post_type,
esc_html( $source_lang_name )
)
); ?></span>
<i class="otgs-ico-help js-otgs-popover-tooltip"
data-tippy-zindex="999999"
title=" <?php echo esc_html__("This operation will synchronize this translation with the original language. When you edit the original, this translation will update immediately. It's meant when you want the content in this language to always be the same as the content in the original language.",'sitepress') ?>"></i>
<?php
}
private function get_untranslated_posts() {
$untranslated = array();
if ( $this->selected_language != $this->sitepress->get_default_language() ) {
$args['element_type'] = 'post_' . $this->post->post_type;
$args['target_language'] = $this->selected_language;
$args['source_language'] = $this->sitepress->get_default_language();
$untranslated_ids = apply_filters( 'wpml_elements_without_translations', null, $args );
foreach ( $untranslated_ids as $id ) {
$untranslated[ $id ] = get_the_title( $id );
}
}
return $untranslated;
}
/**
* Wrapper for \WPML_Post_Translation::get_element_translations that retrieves all translations of the currently
* edited post.
*
* @uses \WPML_Post_Translation::get_element_translations
*
* @return int[]
*/
private function get_translations() {
return $this->post_translation->get_element_translations( false, $this->get_trid() );
}
/**
* @return int|false
*/
private function get_trid() {
$post_id = isset( $this->post->ID ) ? $this->post->ID : 0;
$post_status = isset( $this->post->post_status ) ? $this->post->post_status : '';
return $this->post_translation->get_save_post_trid( $post_id, $post_status );
}
/**
* Returns the post title for a given post or a placeholder if no title exists
*
* @param int $source_element_id
*
* @return string
*/
private function get_element_title( $source_element_id ) {
$element_title = '';
if ( $source_element_id && $source_element_id != $this->post->ID ) {
$element_title = get_the_title( $source_element_id );
if ( trim( $element_title ) === '' ) {
$element_title = '{' . esc_html__( 'Post without a title', 'sitepress' ) . '}';
}
}
return $element_title;
}
private function init_post_data() {
global $wp_post_types;
$this->init_trid_and_selected_language();
$this->init_source_element_data();
//globalize some variables to make them available through hooks
global $icl_meta_box_globals;
$icl_meta_box_globals = array(
'active_languages' => $this->sitepress->get_active_languages(),
'translations' => $this->get_translations(),
'selected_language' => $this->selected_language
);
$this->post_type_label = wpml_mb_strtolower( $wp_post_types[ $this->post->post_type ]->labels->singular_name
!= "" ? $wp_post_types[ $this->post->post_type ]->labels->singular_name : $wp_post_types[ $this->post->post_type ]->labels->name );
}
/**
* Returns the id of the master post in case the currently edited post is a duplicate.
*
* @return int|bool|false
*/
private function is_a_duplicate() {
return get_post_meta( $this->post->ID, '_icl_lang_duplicate_of', true );
}
private function set_post( &$post ) {
$this->allowed_languages = $this->get_allowed_target_langs( $post );
$this->can_translate_post = ! empty( $this->allowed_languages );
$this->selected_language = null;
$this->source_language = null;
$this->post_type_label = null;
$this->trid = null;
$this->translations = array();
$this->is_original = false;
$this->post = $post;
}
/**
* Returns the languages for which a post is missing translations and can be translated to
*
* @param WP_Post $post
*
* @return string[] language codes
*/
private function get_allowed_target_langs( $post ) {
$active_languages = $this->sitepress->get_active_languages();
$can_translate = array_keys( $active_languages );
$can_translate = array_diff(
$can_translate,
array( $this->post_translation->get_element_lang_code( $post->ID ) )
);
return apply_filters( 'wpml_allowed_target_langs', $can_translate, $post->ID, 'post' );
}
private function init_trid_and_selected_language() {
$current_lang = $this->sitepress->get_current_language();
$this->selected_language = $current_lang;
if ( $this->post->ID && $this->post->post_status !== 'auto-draft' ) {
$this->trid = $this->post_translation->get_element_trid( $this->post->ID );
if ( $this->trid ) {
$this->selected_language = $this->post_translation->get_element_lang_code( $this->post->ID );
} else {
$this->sitepress->set_element_language_details( $this->post->ID,
'post_' . $this->post->post_type,
null,
$current_lang );
$this->trid = $this->post_translation->get_element_trid( $this->post->ID );
$this->selected_language = $current_lang;
}
} else {
$this->trid = isset( $_GET['trid'] ) ? intval( $_GET['trid'] ) : false;
$this->selected_language = isset( $_GET['lang'] ) ? strip_tags( $_GET['lang'] ) : $current_lang;
}
if ( isset( $_GET['lang'] ) ) {
$this->selected_language = strip_tags( $_GET['lang'] );
}
}
private function init_source_element_data() {
$this->source_language = isset( $_GET['source_lang'] ) ? filter_var( $_GET['source_lang'],
FILTER_SANITIZE_FULL_SPECIAL_CHARS ) : false;
$this->is_original = false;
if ( ! $this->source_language ) {
$translations = $this->get_translations();
if ( isset( $translations[ $this->selected_language ] ) ) {
$selected_content_translation = $translations[ $this->selected_language ];
$this->is_original = (bool) $this->post_translation->get_source_lang_code( $selected_content_translation ) === false;
if ( ! $this->is_original ) {
$selected_content_language_details = $this->sitepress->get_element_translations( $selected_content_translation,
'post_' . $this->post->post_type );
if (isset( $selected_content_language_details->source_language_code ) ) {
$this->source_language = $selected_content_language_details->source_language_code;
}
}
}
}
}
/**
* @return bool|int|mixed|void
*/
private function get_selected_priority() {
$selected = null;
if ( $this->is_original ) {
$term_obj = $this->get_term_obj( $this->post->ID );
$selected = $term_obj ? $term_obj->term_id : WPML_TM_Translation_Priorities::get_default_term()->term_id;
} else {
$this->fix_source_language();
$element_id = $this->post_translation->get_element_id( $this->source_language, $this->trid );
$term_obj = $this->get_term_obj( $element_id );
if ( $term_obj ) {
$selected = apply_filters( 'translate_object_id', $term_obj->term_id, self::TAXONOMIES_PRIORITY, false, $this->selected_language );
}
if ( ! $selected ) {
$selected = $term_obj ?
WPML_TM_Translation_Priorities::insert_missing_translation( $term_obj->term_id, $term_obj->name, $this->selected_language ) :
WPML_TM_Translation_Priorities::get_default_term()->term_id;
}
}
return $selected;
}
}

View File

@@ -0,0 +1,57 @@
<?php
class WPML_Sync_Custom_Field_Note extends WPML_SP_User {
/**
* Prints and admins notice if custom fields where copied to a new post.
*
* @param string $source_lang
* @param int[] $translations
*/
public function print_sync_copy_custom_field_note( $source_lang, $translations ) {
$copied_cf = $this->get_copied_custom_fields( $source_lang, $translations );
if ( ! empty( $copied_cf ) ) {
$lang_details = $this->sitepress->get_language_details( $source_lang );
$user_preferences = $this->sitepress->get_user_preferences();
if ( (bool) $copied_cf === true && ( ! isset( $user_preferences['notices']['hide_custom_fields_copy'] ) || ! $user_preferences['notices']['hide_custom_fields_copy'] ) ) {
$ccf_note = '<i class="otgs-ico-warning"></i> ';
$ccf_note .= wp_nonce_field( 'save_user_preferences_nonce', '_icl_nonce_sup', false, false );
$ccf_note .= sprintf(
esc_html__( 'WPML will copy %s from %s when you save this post.', 'sitepress' ),
'<i><strong>' . join( '</strong>, <strong>', $copied_cf ) . '</strong></i>',
$lang_details['display_name']
);
$ccf_note .= '<a class="icl_user_notice_hide notice-dismiss" href="#hide_custom_fields_copy"><span class="screen-reader-text">'. esc_html__( 'Never show this', 'sitepress' ) . '</span></a>';
$this->sitepress->admin_notices( $ccf_note, 'notice notice-info otgs-notice otgs-is-dismissible' );
}
}
}
/**
* @param string $source_lang
* @param array $translations
*
* @return array
*/
private function get_copied_custom_fields( $source_lang, $translations ) {
$tm_settings = $this->sitepress->get_setting( 'translation-management', array() );
$custom_fields_translation = ! empty( $tm_settings['custom_fields_translation'] )
? (array) $tm_settings['custom_fields_translation'] : array();
$copied_cf = array_keys( (array) $custom_fields_translation, 1 );
$source_lang = $source_lang ? $source_lang : $this->sitepress->get_default_language();
if ( isset( $translations[ $source_lang ] ) ) {
$original_custom = $this->sitepress->get_wp_api()->get_post_custom( $translations[ $source_lang ] );
$copied_cf = (bool) $original_custom
? array_intersect( $copied_cf, array_keys( $original_custom ) ) : array();
$copied_cf = apply_filters(
'icl_custom_fields_to_be_copied',
$copied_cf,
$translations[ $source_lang ]
);
} else {
$copied_cf = array();
}
return $copied_cf;
}
}

View File

@@ -0,0 +1,86 @@
<?php
class WPML_Post_Language_Filter extends WPML_Language_Filter_Bar {
private $post_status;
private $post_type;
protected function sanitize_request() {
$request_data = parent::sanitize_request ();
$this->post_type = $request_data[ 'req_ptype' ] ? $request_data[ 'req_ptype' ] : 'post';
$post_statuses = array_keys ( get_post_stati () );
$post_status = get_query_var ( 'post_status' );
if ( is_string ( $post_status ) ) {
$post_status = $post_status ? array( $post_status ) : array();
}
$illegal_status = array_diff ( $post_status, $post_statuses );
$this->post_status = array_diff ( $post_status, $illegal_status );
}
public function register_scripts() {
wp_register_script( 'post-edit-languages', ICL_PLUGIN_URL . '/res/js/post-edit-languages.js', array( 'jquery' ), false, true );
}
public function post_language_filter() {
$this->sanitize_request();
$this->init();
$type = $this->post_type;
if ( !$this->sitepress->is_translated_post_type ( $type ) ) {
return '';
}
$post_edit_languages = array();
$post_edit_languages['language_links'] = $this->language_links( $type );
wp_localize_script( 'post-edit-languages', 'post_edit_languages_data', $post_edit_languages );
wp_enqueue_script( 'post-edit-languages' );
return $post_edit_languages;
}
protected function extra_conditions_snippet(){
$extra_conditions = "";
if ( !empty( $this->post_status ) ) {
$status_snippet = " AND post_status IN (" .wpml_prepare_in($this->post_status) . ") ";
$extra_conditions .= apply_filters( '_icl_posts_language_count_status', $status_snippet );
}
$extra_conditions .= $this->post_status != array( 'trash' ) ? " AND post_status <> 'trash'" : '';
$extra_conditions .= " AND post_status <> 'auto-draft' ";
$extra_conditions .= parent::extra_conditions_snippet();
return $extra_conditions;
}
protected function get_count_data( $type ) {
$extra_conditions = $this->extra_conditions_snippet();
return $this->wpdb->get_results( $this->wpdb->prepare("
SELECT language_code, COUNT(p.ID) AS c
FROM {$this->wpdb->prefix}icl_translations t
JOIN {$this->wpdb->posts} p
ON t.element_id=p.ID
AND t.element_type = CONCAT('post_', p.post_type)
WHERE p.post_type=%s {$extra_conditions}
", $type ) );
}
private function language_links( $type ) {
$lang_links = array();
$languages = $this->get_counts( $type );
$post_status = $this->post_status;
foreach ( $this->active_languages as $code => $lang ) {
$item = array();
$item['type'] = esc_js( $type );
$item['statuses'] = array_map( 'esc_js', $post_status );
$item['code'] = esc_js( $code );
$item['name'] = esc_js( $lang[ 'display_name' ] );
$item['current'] = $code === $this->current_language;
$item['count'] = isset( $languages[ $code ] ) ? esc_js( $languages[ $code ] ) : -1;
$lang_links[ ] = $item;
}
return $lang_links;
}
}

View File

@@ -0,0 +1,10 @@
<?php
\WPML\Setup\Initializer::loadJS();
?>
<div class="wrap wpml-settings-container wpml-wizard">
<h2><?php _e( 'WPML Setup', 'sitepress' ) ?></h2>
<div id="wpml-wizard__content"></div>
</div>

View File

@@ -0,0 +1,16 @@
<?php
/**
* @package wpml-core
*/
if ( ! class_exists( 'WP_List_Table' ) ) {
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}
if ( ! class_exists( 'SitePress_Table' ) ) {
class SitePress_Table extends WP_List_Table {
public function __construct() {
parent::__construct();
}
}
}

View File

@@ -0,0 +1,78 @@
<div class="wrap">
<h2><?php esc_html_e( 'Support', 'sitepress' ) ?></h2>
<p style="margin-top: 20px;">
<?php printf( esc_html__( 'Technical support for clients is available via %sWPML forums%s.', 'sitepress' ), '<a target="_blank" href="https://wpml.org/forums/">', '</a>' ); ?>
</p>
<?php
$wpml_plugins_list = SitePress::get_installed_plugins();
echo '
<table class="widefat" style="width: auto;">
<thead>
<tr>
<th>' . esc_html__( 'Plugin Name', 'sitepress' ) . '</th>
<th style="text-align:right">' . esc_html__( 'Status', 'sitepress' ) . '</th>
<th>' . esc_html__( 'Active', 'sitepress' ) . '</th>
<th>' . esc_html__( 'Version', 'sitepress' ) . '</th>
</tr>
</thead>
<tbody>
';
foreach ( $wpml_plugins_list as $name => $plugin_data ) {
$plugin_name = $name;
$file = $plugin_data['file'];
$dir = dirname( $file );
echo '<tr>';
echo '<td><i class="otgs-ico-' . esc_attr( $plugin_data['slug'] ) . '"></i> ' . esc_html( $plugin_name ) . '</td>';
echo '<td align="right">';
if ( empty( $plugin_data['plugin'] ) ) {
echo esc_html__( 'Not installed', 'sitepress' );
} else {
echo esc_html__( 'Installed', 'sitepress' );
}
echo '</td>';
echo '<td align="center">';
echo isset( $file ) && is_plugin_active( $file ) ? esc_html__( 'Yes', 'sitepress' ) : esc_html__( 'No', 'sitepress' );
echo '</td>';
echo '<td align="right">';
echo isset( $plugin_data['plugin']['Version'] ) ? esc_html( $plugin_data['plugin']['Version'] ) : esc_html__( 'n/a', 'sitepress' );
echo '</td>';
echo '</tr>';
}
echo '
</tbody>
</table>
';
?>
<p style="margin-top: 20px;">
<?php printf( esc_html__( 'For advanced access or to completely uninstall WPML and remove all language information, use the %stroubleshooting%s page.', 'sitepress' ), '<a href="' . esc_url( admin_url( 'admin.php?page=' . WPML_PLUGIN_FOLDER . '/menu/troubleshooting.php' ) ) . '">', '</a>' ); ?>
</p>
<p style="margin-top: 20px;">
<?php printf( esc_html__( 'For retrieving debug information if asked by support person, use the %sdebug information%s page.', 'sitepress' ), '<a href="' . esc_url( admin_url( 'admin.php?page=' . WPML_PLUGIN_FOLDER . '/menu/debug-information.php' ) ) . '">', '</a>' ); ?>
</p>
<?php
$support_info_factory = new WPML_Support_Info_UI_Factory();
$support_info_ui = $support_info_factory->create();
echo $support_info_ui->show();
$xml_config_log_factory = new WPML_XML_Config_Log_Factory();
$xml_config_log_ui = $xml_config_log_factory->create_ui();
echo $xml_config_log_ui->show();
do_action( 'wpml_support_page_after' );
do_action( 'otgs_render_installer_support_link' );
?>
</div>

View File

@@ -0,0 +1,111 @@
<?php
/**
* @var SitePress $sitepress
* @var wpdb $wpdb
*/
global $sitepress, $wpdb;
$sitepress->noscript_notice();
$element_id = isset( $term->term_taxonomy_id ) ? $term->term_taxonomy_id : false;
$element_type = isset( $_GET['taxonomy'] ) ? esc_sql( $_GET['taxonomy'] ) : 'post_tag';
$icl_element_type = 'tax_' . $element_type;
$default_language = $sitepress->get_default_language();
$current_language = $sitepress->get_current_language();
if ( $element_id ) {
$res_prepared = $wpdb->prepare(
"SELECT trid, language_code, source_language_code
FROM {$wpdb->prefix}icl_translations WHERE element_id=%d AND element_type=%s",
array( $element_id, $icl_element_type )
);
/** @var \stdClass $res */
$res = $wpdb->get_row( $res_prepared );
$trid = $res->trid;
if ( $trid ) {
$element_lang_code = $res->language_code;
} else {
$element_lang_code = $current_language;
$translation_id = $sitepress->set_element_language_details( $element_id, $icl_element_type, null, $element_lang_code );
// get trid of $translation_id
$trid = $wpdb->get_var( $wpdb->prepare( "SELECT trid FROM {$wpdb->prefix}icl_translations WHERE translation_id=%d", array( $translation_id ) ) );
}
} else {
$trid = isset( $_GET['trid'] ) ? (int) $_GET['trid'] : false;
$element_lang_code = $current_language;
if ( array_key_exists( 'lang', $_GET ) ) {
$element_lang_code = filter_var( $_GET['lang'], FILTER_SANITIZE_FULL_SPECIAL_CHARS );
}
}
$translations = false;
if ( $trid ) {
$translations = $sitepress->get_element_translations( $trid, $icl_element_type );
}
$terms_translations = empty( $translations ) ? array() : $translations;
$active_languages = $sitepress->get_active_languages();
$selected_language = $element_lang_code ? $element_lang_code : $default_language;
$source_language = isset( $_GET['source_lang'] ) ? strip_tags( filter_input( INPUT_GET, 'source_lang', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) ) : false;
$untranslated_ids = $sitepress->get_elements_without_translations( $icl_element_type, $selected_language, $default_language );
$dropdown = new WPML_Taxonomy_Element_Language_Dropdown();
$dropdown->add_language_selector_to_page(
$active_languages,
$selected_language,
$terms_translations,
$element_id,
$icl_element_type
);
$setup_complete = $sitepress->get_setting( 'setup_complete' );
if ( $setup_complete ) {
require WPML_PLUGIN_PATH . '/menu/wpml-translation-selector.class.php';
$selector = new WPML_Translation_Selector( $sitepress, $default_language, $source_language, $element_id );
$selector->add_translation_of_selector_to_page(
$trid,
$sitepress->get_current_language(),
$selected_language,
$untranslated_ids
);
$sitepress->add_translate_options( $trid, $active_languages, $selected_language, $terms_translations, $icl_element_type );
echo '</div></div></div></div></div>';
if ( $trid && $sitepress->get_wp_api()->is_term_edit_page() ) {
/**
* Extends the translation options for terms
*
* Called after rendering the translation options for terms, after the closing the main container tag
*
* @since 3.8.2
*
* @param array $args {
* Information about the current term and its translations
*
* @type int $trid The translation cluster ID.
* @type array $active_languages All active languages data.
* @type string $selected_language The language of the current term being edited.
* @type array $translations All the available translations (including the current one).
* @type string $type The translation element type (e.g. `tax_category`, `tax_{taxonomy}`.
* }
*/
do_action(
'wpml_translate_options_terms_after',
array(
'trid' => $trid,
'active_languages' => $active_languages,
'selected_language' => $selected_language,
'translations' => $terms_translations,
'type' => $icl_element_type,
)
);
}
}

View File

@@ -0,0 +1,279 @@
<?php
new WPML_Taxonomy_Translation_Sync_Display();
class WPML_Taxonomy_Translation_Table_Display {
private static function get_strings_translation_array() {
$st_plugin = '<a href="' . get_admin_url( null, 'plugins.php' ) . '" target="_blank" class="wpml-external-link">WPML String Translation</a>';
$term_results_cap = defined( 'WPML_TAXONOMY_TRANSLATION_MAX_TERMS_RESULTS_SET' ) ?
WPML_TAXONOMY_TRANSLATION_MAX_TERMS_RESULTS_SET :
WPML_Taxonomy_Translation_Screen_Data::WPML_TAXONOMY_TRANSLATION_MAX_TERMS_RESULTS_SET;
$labels = array(
'Show' => __( 'Show', 'sitepress' ),
'untranslated' => __( 'untranslated', 'sitepress' ),
'all' => __( 'all', 'sitepress' ),
'in' => __( 'in', 'sitepress' ),
'to' => __( 'to', 'sitepress' ),
'of' => __( 'of', 'sitepress' ),
'taxonomy' => __( 'Taxonomy', 'sitepress' ),
'anyLang' => __( 'any language', 'sitepress' ),
'apply' => __( 'Refresh', 'sitepress' ),
'synchronizeBtn' => __( 'Update Taxonomy Hierarchy', 'sitepress' ),
'searchPlaceHolder' => __( 'Search', 'sitepress' ),
'selectParent' => __( 'select parent', 'sitepress' ),
'taxToTranslate' => __( 'Select the taxonomy to translate: ', 'sitepress' ),
'translate' => sprintf( __( '%1$s Translation', 'sitepress' ), '%taxonomy%' ),
'Synchronize' => __( 'Hierarchy Synchronization', 'sitepress' ),
'lowercaseTranslate' => __( 'translate', 'sitepress' ),
'copyToAllLanguages' => __( 'Copy to all languages', 'sitepress' ),
'copyToAllMessage' => sprintf( __( 'Copy this term from original: %1$s to all other languages?' ), '%language%' ),
'copyAllOverwrite' => __( 'Overwrite existing translations', 'sitepress' ),
'willBeRemoved' => __( 'Will be removed', 'sitepress' ),
'willBeAdded' => __( 'Will be added', 'sitepress' ),
'legend' => __( 'Legend:', 'sitepress' ),
'refLang' => sprintf( __( 'Synchronize taxonomy hierarchy according to: %1$s language.', 'sitepress' ), '%language%' ),
'targetLang' => __( 'Target Language', 'sitepress' ),
'termPopupDialogTitle' => __( 'Term translation', 'sitepress' ),
'originalTermPopupDialogTitle' => __( 'Original term', 'sitepress' ),
'labelPopupDialogTitle' => __( 'Label translation', 'sitepress' ),
'copyFromOriginal' => __( 'Copy from original', 'sitepress' ),
'original' => __( 'Original:', 'sitepress' ),
'translationTo' => __( 'Translation to:', 'sitepress' ),
'Name' => __( 'Name', 'sitepress' ),
'Slug' => __( 'Slug', 'sitepress' ),
'Description' => __( 'Description', 'sitepress' ),
'Ok' => __( 'OK', 'sitepress' ),
'save' => __( 'Save', 'sitepress' ),
'Singular' => __( 'Singular', 'sitepress' ),
'Plural' => __( 'Plural', 'sitepress' ),
'changeLanguage' => __( 'Change language', 'sitepress' ),
'cancel' => __( 'Cancel', 'sitepress' ),
'loading' => __( 'loading', 'sitepress' ),
'Save' => __( 'Save', 'sitepress' ),
'currentPage' => __( 'Current page', 'sitepress' ),
'goToPreviousPage' => __( 'Go to previous page', 'sitepress' ),
'goToNextPage' => __( 'Go to the next page', 'sitepress' ),
'goToFirstPage' => __( 'Go to the first page', 'sitepress' ),
'goToLastPage' => __( 'Go to the last page', 'sitepress' ),
'hieraSynced' => __( 'The taxonomy hierarchy is now synchronized.', 'sitepress' ),
'hieraAlreadySynced' => __( 'The taxonomy hierarchy is already synchronized.', 'sitepress' ),
'noTermsFound' => sprintf( __( 'No %1$s found.', 'sitepress' ), '%taxonomy%' ),
'items' => __( 'items', 'sitepress' ),
'item' => __( 'item', 'sitepress' ),
'summaryTerms' => sprintf( __( 'Translation of %1$s', 'sitepress' ), '%taxonomy%' ),
'summaryLabels' => sprintf( __( 'Translations of taxonomy %1$s labels and slug', 'sitepress' ), '%taxonomy%' ),
'activateStringTranslation' => sprintf( __( 'To translate taxonomy labels and slug you need %s plugin.', 'sitepress' ), $st_plugin ),
'preparingTermsData' => __( 'Loading ...', 'sitepress' ),
'firstColumnHeading' => sprintf( __( '%1$s terms (in original language)', 'sitepress' ), '%taxonomy%' ),
'resultsTruncated' => sprintf( __( 'Because too many %1$s were found, only the first %2$s results are listed. You can refine the results using the Search field below.', 'sitepress' ), '%taxonomy%', '<strong>' . $term_results_cap . '</strong>' ),
'wpml_save_term_nonce' => wp_create_nonce( 'wpml_save_term_nonce' ),
'wpml_tt_sync_hierarchy_nonce' => wp_create_nonce( 'wpml_tt_sync_hierarchy_nonce' ),
'wpml_generate_unique_slug_nonce' => wp_create_nonce( 'wpml_generate_unique_slug_nonce' ),
'wpml_taxonomy_translation_nonce' => wp_create_nonce( 'wpml_taxonomy_translation_nonce' ),
'addTranslation' => __( 'Add translation', 'sitepress' ),
'editTranslation' => __( 'Edit translation', 'sitepress' ),
'originalLanguage' => __( 'Original language', 'sitepress' ),
'termMetaLabel' => __( 'This term has additional meta fields:', 'sitepress' ),
);
return $labels;
}
public static function enqueue_taxonomy_table_resources( $sitepress ) {
WPML_Simple_Language_Selector::enqueue_scripts();
wp_enqueue_style( 'translate-taxonomy', ICL_PLUGIN_URL . '/res/css/taxonomy-translation.css', array(), ICL_SITEPRESS_VERSION );
$core_dependencies = array( 'jquery', 'jquery-ui-dialog', 'backbone', 'wpml-underscore-template-compiler' );
wp_register_script(
'templates-compiled',
ICL_PLUGIN_URL . '/res/js/taxonomy-translation/templates-compiled.js',
$core_dependencies,
'1.2.4'
);
$core_dependencies[] = 'templates-compiled';
wp_register_script( 'main-util', ICL_PLUGIN_URL . '/res/js/taxonomy-translation/util.js', $core_dependencies );
wp_register_script( 'main-model', ICL_PLUGIN_URL . '/res/js/taxonomy-translation/main.js', $core_dependencies );
$core_dependencies[] = 'main-model';
$dependencies = $core_dependencies;
wp_register_script(
'term-rows-collection',
ICL_PLUGIN_URL . '/res/js/taxonomy-translation/collections/term-rows.js',
array_merge( $core_dependencies, array( 'term-row-model' ) )
);
$dependencies[] = 'term-rows-collection';
wp_register_script(
'term-model',
ICL_PLUGIN_URL . '/res/js/taxonomy-translation/models/term.js',
$core_dependencies
);
$dependencies[] = 'term-model';
wp_register_script(
'taxonomy-model',
ICL_PLUGIN_URL . '/res/js/taxonomy-translation/models/taxonomy.js',
$core_dependencies
);
$dependencies[] = 'taxonomy-model';
wp_register_script(
'term-row-model',
ICL_PLUGIN_URL . '/res/js/taxonomy-translation/models/term-row.js',
$core_dependencies
);
$dependencies[] = 'term-row-model';
foreach ( array(
'filter-view',
'nav-view',
'table-view',
'taxonomy-view',
'term-popup-view',
'original-term-popup-view',
'label-popup-view',
'term-row-view',
'label-row-view',
'term-rows-view',
'term-view',
'term-original-view',
'copy-all-popup-view',
) as $script ) {
wp_register_script(
$script,
ICL_PLUGIN_URL . '/res/js/taxonomy-translation/views/' . $script . '.js',
$core_dependencies,
'1.2.4'
);
$dependencies[] = $script;
}
wp_localize_script( 'main-model', 'labels', self::get_strings_translation_array() );
wp_localize_script( 'main-model', 'wpml_taxonomies', self::wpml_get_table_taxonomies( $sitepress ) );
$need_enqueue = $dependencies;
$need_enqueue[] = 'main-model';
$need_enqueue[] = 'main-util';
$need_enqueue[] = 'templates';
foreach ( $need_enqueue as $handle ) {
wp_enqueue_script( $handle );
}
wp_register_script( 'taxonomy-hierarchy-sync-message', ICL_PLUGIN_URL . '/res/js/taxonomy-hierarchy-sync-message.js', array( 'jquery' ) );
wp_enqueue_script( 'taxonomy-hierarchy-sync-message' );
}
public static function wpml_get_table_taxonomies( SitePress $sitepress ) {
$taxonomies = $sitepress->get_wp_api()->get_taxonomies( array(), 'objects' );
$result = array(
'taxonomies' => array(),
'activeLanguages' => array(),
'allLanguages' => array(),
);
$sitepress->set_admin_language();
$active_langs = $sitepress->get_active_languages();
$default_lang = $sitepress->get_default_language();
$result['activeLanguages'][ $default_lang ] = array(
'label' => esc_js( $active_langs[ $default_lang ]['display_name'] ),
'flag' => esc_url( $sitepress->get_flag_url( $default_lang ) ),
);
foreach ( $active_langs as $code => $lang ) {
if ( $code !== $default_lang ) {
$result['activeLanguages'][ $code ] = array(
'label' => esc_js( $lang['display_name'] ),
'flag' => esc_url( $sitepress->get_flag_url( $code ) ),
);
}
}
$all_languages = $sitepress->get_languages();
foreach ( $all_languages as $code => $lang ) {
$result['allLanguages'][ $code ] = array(
'label' => esc_js( $lang['display_name'] ),
'flag' => esc_url( $sitepress->get_flag_url( $code ) ),
);
}
foreach ( $taxonomies as $key => $tax ) {
if ( $sitepress->is_translated_taxonomy( $key ) ) {
$result['taxonomies'][ $key ] = array(
'label' => $tax->label,
'singularLabel' => $tax->labels->singular_name,
'hierarchical' => $tax->hierarchical,
'name' => $key,
);
}
}
return $result;
}
public static function wpml_get_terms_and_labels_for_taxonomy_table() {
global $sitepress;
if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'wpml_taxonomy_translation_nonce' ) ) {
wp_send_json_error( __( 'Wrong nonce', 'sitepress' ) );
return;
}
$taxonomy = false;
$request_post_taxonomy = filter_input(
INPUT_POST,
'taxonomy',
FILTER_SANITIZE_FULL_SPECIAL_CHARS,
FILTER_NULL_ON_FAILURE
);
if ( $request_post_taxonomy ) {
$taxonomy = html_entity_decode( $request_post_taxonomy );
}
if ( $taxonomy ) {
$terms_data = new WPML_Taxonomy_Translation_Screen_Data( $sitepress, $taxonomy );
$term_results = $terms_data->terms();
$labels = apply_filters( 'wpml_label_translation_data', false, $taxonomy );
$def_lang = $sitepress->get_default_language();
$bottom_content = apply_filters( 'wpml_taxonomy_translation_bottom', $html = '', $taxonomy, get_taxonomy( $taxonomy ) );
wp_send_json(
array(
'terms' => $term_results['terms'],
'resultsTruncated' => $term_results['truncated'],
'taxLabelTranslations' => $labels,
'defaultLanguage' => $def_lang,
'bottomContent' => $bottom_content,
'taxLangSelector' => self::render_tax_language_selector( $labels, $taxonomy ),
)
);
} else {
wp_send_json_error();
}
}
private static function render_tax_language_selector( $labels, $taxonomy ) {
global $sitepress;
if ( ! isset( $labels['st_default_lang'] ) ) {
return null;
}
$args = array(
'selected' => $labels['st_default_lang'],
'name' => 'string_lang[' . $taxonomy . ']',
'show_please_select' => false,
'echo' => false,
'class' => 'js-tax-lang-selector',
);
$lang_selector = new WPML_Simple_Language_Selector( $sitepress );
return $lang_selector->render( $args );
}
}

View File

@@ -0,0 +1,155 @@
<?php
class WPML_Tax_Menu_Loader {
/** @var SitePress $sitepress */
private $sitepress;
/** @var wpdb $wpdb */
public $wpdb;
/** @var string $taxonomy */
private $taxonomy;
/**
* @param wpdb $wpdb
* @param SitePress $sitepress
* @param string $taxonomy
*/
public function __construct( $wpdb, $sitepress, $taxonomy ) {
$this->sitepress = $sitepress;
$this->wpdb = $wpdb;
$this->taxonomy = $taxonomy;
add_action( 'init', [ $this, 'init' ] );
add_action( 'after-category-table', [ $this, 'category_display_action' ], 1, 0 );
add_filter( 'wp_redirect', [ $this, 'preserve_lang_param' ] );
}
public function get_wpdb() {
return $this->wpdb;
}
public function init() {
$tax_get = filter_input( INPUT_GET, 'taxonomy' );
$trid = filter_input( INPUT_GET, 'trid' );
if ( $trid
&& ( $source_lang = filter_input( INPUT_GET, 'source_lang' ) )
&& get_taxonomy( $tax_get ) !== false
) {
$translations = $this->sitepress->get_element_translations( $trid, 'tax_' . $this->taxonomy );
if ( isset( $translations[ $_GET['lang'] ] ) && ! empty( $translations[ $_GET['lang'] ]->term_id ) ) {
wp_redirect( get_edit_term_link( $translations[ $_GET['lang'] ]->term_id, $tax_get ) );
exit;
} else {
add_action( 'admin_notices', [ $this, '_tax_adding' ] );
}
}
add_action( $this->taxonomy . '_edit_form', [ $this, 'wpml_edit_term_form' ] );
add_action( $this->taxonomy . '_add_form', [ $this, 'wpml_edit_term_form' ] );
add_action( 'admin_print_scripts-edit-tags.php', [ $this, 'js_scripts_tags' ] );
add_action( 'admin_print_scripts-term.php', [ $this, 'js_scripts_tags' ] );
add_filter( 'wp_dropdown_cats', [ $this, 'wp_dropdown_cats_select_parent' ], 10, 2 );
if ( ! $this->sitepress->get_wp_api()->is_term_edit_page() ) {
$term_lang_filter = new WPML_Term_Language_Filter( $this->wpdb, $this->sitepress );
add_action( 'admin_footer', [ $term_lang_filter, 'terms_language_filter' ], 0 );
}
}
/**
* Filters the display of the categories list in order to prevent the default category from being delete-able.
* This is done by printing a hidden div containing a JSON encoded array with all category id's, the checkboxes of which are to be removed.
*/
public function category_display_action() {
/** @var WPML_Term_Translation $wpml_term_translations */
global $wpml_term_translations;
if ( ( $default_category_id = get_option( 'default_category' ) ) ) {
$default_cat_ids = array();
$translations = $wpml_term_translations->get_element_translations( $default_category_id );
foreach ( $translations as $lang => $translation ) {
$default_cat_ids [] = $wpml_term_translations->term_id_in( $default_category_id, $lang );
}
echo '<div id="icl-default-category-ids" style="display: none;">'
. wp_json_encode( $default_cat_ids ) . '</div>';
}
}
public function js_scripts_tags() {
wp_enqueue_script( 'sitepress-tags', ICL_PLUGIN_URL . '/res/js/tags.js', array(), ICL_SITEPRESS_VERSION );
}
function wp_dropdown_cats_select_parent( $html, $args ) {
if ( ( $trid = filter_input( INPUT_GET, 'trid', FILTER_SANITIZE_NUMBER_INT ) ) ) {
$element_type = $taxonomy = isset( $args['taxonomy'] ) ? $args['taxonomy'] : 'post_tag';
$icl_element_type = 'tax_' . $element_type;
$source_lang = isset( $_GET['source_lang'] )
? filter_input( INPUT_GET, 'source_lang', FILTER_SANITIZE_FULL_SPECIAL_CHARS )
: $this->sitepress->get_default_language();
$parent = $this->wpdb->get_var(
$this->wpdb->prepare(
"
SELECT parent
FROM {$this->wpdb->term_taxonomy} tt
JOIN {$this->wpdb->prefix}icl_translations tr ON tr.element_id=tt.term_taxonomy_id
AND tr.element_type=%s AND tt.taxonomy=%s
WHERE trid=%d AND tr.language_code=%s
",
$icl_element_type,
$taxonomy,
$trid,
$source_lang
)
);
if ( $parent ) {
$parent = (int) icl_object_id( $parent, $element_type );
$html = str_replace( 'value="' . $parent . '"', 'value="' . $parent . '" selected="selected"', $html );
}
}
return $html;
}
/**
* @param Object $term
*/
public function wpml_edit_term_form( $term ) {
include WPML_PLUGIN_PATH . '/menu/term-taxonomy-menus/taxonomy-menu.php';
}
function _tax_adding() {
$trid = filter_input( INPUT_GET, 'trid', FILTER_SANITIZE_NUMBER_INT );
$taxonomy = filter_input( INPUT_GET, 'taxonomy' );
$translations = $trid && $taxonomy ?
$this->sitepress->get_element_translations( $trid, 'tax_' . $taxonomy ) : array();
$name = isset( $translations[ $_GET['source_lang'] ] ) ? $translations[ filter_input( INPUT_GET, 'source_lang', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) ]
: false;
$name = isset( $name->name ) ? $name->name : false;
if ( $name !== false ) {
$tax_name = apply_filters( 'the_category', $name );
// translators: %s is replaced by the name of the taxonomy.
echo '<div id="icl_tax_adding_notice" class="updated fade"><p>'
. sprintf( esc_html__( 'Adding translation for: %s.', 'sitepress' ), $tax_name )
. '</p></div>';
}
}
/**
* If user perform bulk taxonomy deletion when displaying non-default
* language taxonomies, after deletion should stay with same language
*
* @param string $location Url where browser will redirect.
* @return string Url where browser will redirect.
*/
public function preserve_lang_param( $location ) {
global $wpml_url_converter;
$get_lang = $wpml_url_converter->get_language_from_url(
(string) filter_input( INPUT_POST, '_wp_http_referer' )
);
$location = $get_lang ? add_query_arg( 'lang', $get_lang, $location ) : $location;
return $location;
}
}

View File

@@ -0,0 +1,71 @@
<?php
class WPML_Taxonomy_Element_Language_Dropdown {
function add_language_selector_to_page( $active_languages, $selected_language, $translations, $element_id, $type ) {
?>
<div id="icl_tax_menu" style="display:none">
<div id="dashboard-widgets" class="metabox-holder">
<div class="postbox-container" style="width: 99%;line-height:normal;">
<div id="icl_<?php echo esc_attr( $type ); ?>_lang" class="postbox" style="line-height:normal;">
<h3 class="hndle">
<span><?php echo esc_html__( 'Language', 'sitepress' ); ?></span>
</h3>
<div class="inside" style="padding: 10px;">
<?php
$active_languages = $this->filter_allowed_languages( $active_languages, $selected_language );
$disabled = count( $active_languages ) === 1 ? ' disabled="disabled" ' : '';
?>
<select name="icl_<?php echo esc_attr( $type ); ?>_language" <?php echo $disabled; ?>>
<?php
echo $this->add_options( $active_languages, $selected_language );
?>
<?php foreach ( $active_languages as $lang ) : ?>
<?php
if ( $lang['code'] === $selected_language || ( isset( $translations[ $lang['code'] ]->element_id ) && $translations[ $lang['code'] ]->element_id != $element_id ) ) {
continue;
}
?>
<option
value="<?php echo esc_attr( $lang['code'] ); ?>"
<?php
if ( $selected_language === $lang['code'] ) :
?>
selected="selected"<?php endif; ?>><?php echo esc_html( $lang['display_name'] ); ?></option>
<?php endforeach; ?>
</select>
<?php if ( $disabled ) { ?>
<input type="hidden" name="icl_<?php echo esc_attr( $type ); ?>_language"
value="<?php echo esc_attr( $selected_language ); ?>"/>
<?php
}
}
private function filter_allowed_languages( $active_languages, $selected_language ) {
global $sitepress;
$wp_api = new WPML_WP_API();
$show_all = $wp_api->is_term_edit_page() || $sitepress->get_current_language() === 'all';
return $show_all ? $active_languages : array( $active_languages[ $selected_language ] );
}
private function add_options( $active_languages, $selected_language ) {
$html = '';
foreach ( $active_languages as $lang ) {
if ( $lang['code'] === $selected_language ) {
$html .= '<option value="' . esc_attr( $selected_language ) . '" selected="selected">' . esc_html( $lang['display_name'] ) . '</option>';
}
}
return $html;
}
}

View File

@@ -0,0 +1,48 @@
<?php
class WPML_Taxonomy_Translation_Sync_Display {
public function __construct() {
add_action( 'wp_ajax_wpml_tt_sync_hierarchy_preview', array( $this, 'ajax_sync_preview' ) );
add_action( 'wp_ajax_wpml_tt_sync_hierarchy_save', array( $this, 'ajax_sync_save' ) );
}
private function get_req_data() {
$taxonomy = isset( $_POST['taxonomy'] ) ? $_POST['taxonomy'] : false;
$ref_lang = isset( $_POST['ref_lang'] ) ? $_POST['ref_lang'] : false;
return array( $taxonomy, $ref_lang );
}
public function ajax_sync_preview() {
global $wpml_language_resolution, $sitepress;
if ( ! wpml_is_action_authenticated( 'wpml_tt_sync_hierarchy' ) ) {
wp_send_json_error( 'Wrong Nonce' );
}
$sync_helper = wpml_get_hierarchy_sync_helper( 'term' );
list( $taxonomy, $ref_lang ) = $this->get_req_data();
if ( $taxonomy ) {
$ref_lang = $wpml_language_resolution->is_language_active( $ref_lang ) || $wpml_language_resolution->is_language_hidden( $ref_lang )
? $ref_lang : $sitepress->get_default_language();
$corrections = $sync_helper->get_unsynced_elements( $taxonomy, $ref_lang );
wp_send_json_success( $corrections );
} else {
wp_send_json_error( 'No taxonomy in request!' );
}
}
public function ajax_sync_save() {
if ( ! wpml_is_action_authenticated( 'wpml_tt_sync_hierarchy' ) ) {
wp_send_json_error( 'Wrong Nonce' );
}
$sync_helper = wpml_get_hierarchy_sync_helper( 'term' );
list( $taxonomy, $ref_lang ) = $this->get_req_data();
if ( $taxonomy ) {
$sync_helper->sync_element_hierarchy( $taxonomy, $ref_lang );
wp_send_json_success( 1 );
} else {
wp_send_json_error( 'No taxonomy in request!' );
}
}
}

View File

@@ -0,0 +1,51 @@
<?php
class WPML_Term_Language_Filter extends WPML_Language_Filter_Bar {
function terms_language_filter( $echo = true ) {
$this->init();
$requested_data = $this->sanitize_request();
$taxonomy = $requested_data['req_tax'] !== '' ? $requested_data['req_tax'] : 'post_tag';
$post_type = $requested_data['req_ptype'] !== '' ? $requested_data['req_ptype'] : '';
$languages = $this->get_counts( $taxonomy );
$languages_links = array();
foreach ( $this->active_languages as $code => $lang ) {
$languages_links[] = $this->lang_element( $languages, $code, $taxonomy, $post_type );
}
$all_languages_links = join( ' | ', $languages_links );
$html = '<span id="icl_subsubsub" class="icl_subsubsub" style="display: none;">' . $all_languages_links . '</span>';
if ( $echo !== false ) {
echo $html;
}
return $html;
}
private function lang_element( $languages, $code, $taxonomy, $post_type ) {
$count = isset( $languages[ $code ] ) ? $languages[ $code ] : 0;
if ( $code === $this->current_language ) {
list($px, $sx) = $this->strong_lang_span_cover( $code, $count );
} else {
$px = '<a href="?taxonomy=' . esc_attr( $taxonomy ) . '&amp;lang=' . esc_attr( $code );
$px .= $post_type !== '' ? '&amp;post_type=' . esc_attr( $post_type ) : '';
$px .= '">';
$sx = '</a>' . $this->lang_span( $code, $count );
}
return $px . esc_html( $this->active_languages[ $code ]['display_name'] ) . $sx;
}
protected function get_count_data( $taxonomy ) {
$res_query = " SELECT language_code, COUNT(tm.term_id) AS c
FROM {$this->wpdb->prefix}icl_translations t
JOIN {$this->wpdb->term_taxonomy} tt
ON t.element_id = tt.term_taxonomy_id
AND t.element_type = CONCAT('tax_', tt.taxonomy)
JOIN {$this->wpdb->terms} tm
ON tt.term_id = tm.term_id
WHERE tt.taxonomy = %s
" . $this->extra_conditions_snippet();
return $this->wpdb->get_results( $this->wpdb->prepare( $res_query, $taxonomy ) );
}
}

View File

@@ -0,0 +1,26 @@
<?php
global $sitepress;
if ( ( ! isset( $sitepress_settings['existing_content_language_verified'] ) ||
! $sitepress_settings['existing_content_language_verified'] ) ||
2 > count( $sitepress->get_active_languages() ) ) {
return;
}
?>
<div class="wrap">
<h2><?php _e( 'Theme and plugins localization', 'sitepress' ); ?></h2>
<div id="wpml-mo-scan-localization-page"></div>
<?php
/** @deprecated use wpml_custom_localization_type instead */
do_action( 'icl_custom_localization_type' );
do_action( 'wpml_custom_localization_type' );
?>
<?php do_action( 'icl_menu_footer' ); ?>
</div>

View File

@@ -0,0 +1,38 @@
<div class="wrap">
<h3><?php _e( 'Theme and Plugins compatibility with WPML', 'sitepress' ); ?></h3>
<p><?php _e( 'Configuration for compatibility between your active plugins and theme is updated automatically on daily basis.', 'sitepress' ); ?></p>
<div id="icl_theme_plugins_compatibility">
<p><?php printf( __( 'Last checked on %s', 'sitepress' ), '<span id="wpml_conf_upd">' . date( 'F j, Y H:i a', get_option( 'wpml_config_index_updated' ) ) . '</span>' ); ?></p>
<input class="button" id="update_wpml_config" value="<?php echo __( 'Update', 'sitepress' ); ?>" type="button" style="float:left;"/>
</div>
</div>
<script type="text/javascript">
jQuery(document).ready(function ($) {
$('#update_wpml_config').click(function () {
var el = $(this);
var ajaxLoader = $('<span class="spinner" style="float:left"></span>');
ajaxLoader.insertAfter(el).show();
el.prop('disabled', true);
jQuery.ajax({
type: "post",
url: ajaxurl,
data: {
action: "update_wpml_config_index",
_icl_nonce: "<?php echo wp_create_nonce( 'icl_theme_plugins_compatibility_nonce' ); ?>"
},
success: function (response) {
if (response)
$('#wpml_conf_upd').html(response);
},
complete: function () {
ajaxLoader.remove();
el.prop('disabled', false);
}
});
});
});
</script>

View File

@@ -0,0 +1,22 @@
<div class="wrap">
<h2><?php echo __( 'Settings', 'sitepress' ); ?></h2>
<br />
<?php
require __DIR__ . '/_posts_sync_options.php';
require __DIR__ . '/_login_translation_options.php';
if ( defined( 'WPML_ST_PATH' ) ) {
include WPML_ST_PATH . '/menu/_slug-translation-options.php';
}
?>
<br clear="all" />
<?php
require __DIR__ . '/_custom_types_translation.php';
do_action( 'icl_tm_menu_mcsetup' );
do_action( 'icl_menu_footer' );
?>
</div>

View File

@@ -0,0 +1,914 @@
<?php
use WPML\API\Sanitize;
require_once WPML_PLUGIN_PATH . '/inc/functions-troubleshooting.php';
global $wpdb;
/* DEBUG ACTION */
/**
* @param \stdClass $term_object
*
* @return int
*/
function get_term_taxonomy_id_from_term_object( $term_object ) {
return $term_object->term_taxonomy_id;
}
function get_ATE_account_data() {
return get_option( WPML_TM_ATE_Authentication::AMS_DATA_KEY, [] );
}
$action = Sanitize::stringProp( 'debug_action', $_GET );
$nonce = Sanitize::stringProp( 'nonce', $_GET );
if ( ! $action ) {
$action = Sanitize::stringProp( 'debug_action', $_POST );
$nonce = Sanitize::stringProp( 'nonce', $_POST );
}
$otgs_twig_cache_disable_key = '_otgs_twig_cache_disabled';
if ( defined( 'WPML_Templates_Factory::OTGS_TWIG_CACHE_DISABLED_KEY' ) ) {
$otgs_twig_cache_disable_key = WPML_Templates_Factory::OTGS_TWIG_CACHE_DISABLED_KEY;
}
if ( wp_verify_nonce( $nonce, $action ) ) {
ob_end_clean();
global $wpdb;
switch ( $action ) {
case 'otgs_twig_cache_enable':
$new_value = false;
if ( array_key_exists( 'new_value', $_POST ) ) {
$new_value = (bool) $_POST['new_value'];
}
update_option( $otgs_twig_cache_disable_key, $new_value, 'no' );
exit;
case 'fix_languages':
SitePress_Setup::fill_languages();
SitePress_Setup::fill_languages_translations();
SitePress_Setup::fill_flags();
icl_cache_clear();
exit;
case 'icl_fix_collation':
repair_el_type_collate();
exit;
case 'cache_clear':
icl_cache_clear();
$cache_directory = new WPML_Cache_Directory( new WPML_WP_API() );
$cache_directory->remove();
exit;
case 'ghost_clean':
// clean the icl_translations table
$orphans = $wpdb->get_col(
"
SELECT t.translation_id, t.element_type
FROM {$wpdb->prefix}icl_translations t
LEFT JOIN {$wpdb->posts} p ON t.element_id = p.ID
WHERE t.element_id IS NOT NULL AND t.element_type LIKE 'post\\_%' AND p.ID IS NULL
"
);
if ( ! empty( $orphans ) ) {
$upgrade_args_set = array();
foreach ( $orphans as $orphan ) {
$upgrade_args = array(
'translation_id' => $orphan,
'context' => 'post',
);
$upgrade_args_set[] = $upgrade_args;
do_action( 'wpml_translation_update', array_merge( $upgrade_args, array( 'type' => 'before_delete' ) ) );
}
$wpdb->query(
"DELETE FROM {$wpdb->prefix}icl_translations
WHERE translation_id IN (" . wpml_prepare_in( $orphans, '%d' ) . ')'
);
foreach ( $upgrade_args_set as $upgrade_args ) {
do_action( 'wpml_translation_update', array_merge( $upgrade_args, array( 'type' => 'after_delete' ) ) );
}
}
$orphans = $wpdb->get_col(
"
SELECT t.translation_id
FROM {$wpdb->prefix}icl_translations t
LEFT JOIN {$wpdb->comments} c ON t.element_id = c.comment_ID
WHERE t.element_type = 'comment' AND c.comment_ID IS NULL "
);
if ( false === $orphans ) {
echo $wpdb->last_result;
}
if ( ! empty( $orphans ) ) {
$upgrade_args_set = array();
foreach ( $orphans as $orphan ) {
$upgrade_args = array(
'translation_id' => $orphan,
'context' => 'comment',
);
$upgrade_args_set[] = $upgrade_args;
do_action( 'wpml_translation_update', array_merge( $upgrade_args, array( 'type' => 'before_delete' ) ) );
}
$wpdb->query(
"DELETE FROM {$wpdb->prefix}icl_translations
WHERE translation_id IN (" . wpml_prepare_in( $orphans, '%d' ) . ')'
);
foreach ( $upgrade_args_set as $upgrade_args ) {
do_action( 'wpml_translation_update', array_merge( $upgrade_args, array( 'type' => 'after_delete' ) ) );
}
}
$orphans = $wpdb->get_col(
"
SELECT t.translation_id
FROM {$wpdb->prefix}icl_translations t
LEFT JOIN {$wpdb->term_taxonomy} p ON t.element_id = p.term_taxonomy_id
WHERE t.element_id IS NOT NULL AND t.element_type LIKE 'tax\\_%' AND p.term_taxonomy_id IS NULL"
);
if ( ! empty( $orphans ) ) {
$upgrade_args_set = array();
foreach ( $orphans as $orphan ) {
$upgrade_args = array(
'translation_id' => $orphan,
'context' => 'tax',
);
$upgrade_args_set[] = $upgrade_args;
do_action( 'wpml_translation_update', $upgrade_args );
}
$wpdb->query(
"DELETE FROM {$wpdb->prefix}icl_translations
WHERE translation_id IN (" . wpml_prepare_in( $orphans, '%d' ) . ')'
);
foreach ( $upgrade_args_set as $upgrade_args ) {
do_action( 'wpml_translation_update', array_merge( $upgrade_args, array( 'type' => 'after_delete' ) ) );
}
}
global $wp_taxonomies;
if ( is_array( $wp_taxonomies ) ) {
foreach ( $wp_taxonomies as $t => $v ) {
$orphans = $wpdb->get_col(
"
SELECT t.translation_id
FROM {$wpdb->prefix}icl_translations t
LEFT JOIN {$wpdb->term_taxonomy} p
ON t.element_id = p.term_taxonomy_id
WHERE t.element_type = 'tax_{$t}'
AND p.taxonomy <> '{$t}'
"
);
if ( ! empty( $orphans ) ) {
$upgrade_args_set = array();
foreach ( $orphans as $orphan ) {
$upgrade_args = array(
'translation_id' => $orphan,
'context' => 'tax',
);
$upgrade_args_set[] = $upgrade_args;
do_action( 'wpml_translation_update', $upgrade_args );
}
$wpdb->query(
"DELETE FROM {$wpdb->prefix}icl_translations
WHERE translation_id IN (" . wpml_prepare_in( $orphans, '%d' ) . ')'
);
foreach ( $upgrade_args_set as $upgrade_args ) {
do_action( 'wpml_translation_update', array_merge( $upgrade_args, array( 'type' => 'after_delete' ) ) );
}
}
}
}
// remove ghost translations
// get unlinked rids
$rids = $wpdb->get_col( "SELECT rid FROM {$wpdb->prefix}icl_translation_status WHERE translation_id NOT IN (SELECT translation_id FROM {$wpdb->prefix}icl_translations)" );
if ( $rids ) {
$jids = $wpdb->get_col( "SELECT job_id FROM {$wpdb->prefix}icl_translate_job WHERE rid IN (" . wpml_prepare_in( $rids, '%d' ) . ')' );
if ( $jids ) {
$wpdb->query( "DELETE FROM {$wpdb->prefix}icl_translate WHERE job_id IN (" . wpml_prepare_in( $jids, '%d' ) . ')' );
$wpdb->query( "DELETE FROM {$wpdb->prefix}icl_translate_job WHERE job_id IN (" . wpml_prepare_in( $jids, '%d' ) . ')' );
$wpdb->query( "DELETE FROM {$wpdb->prefix}icl_translation_status WHERE rid IN (" . wpml_prepare_in( $rids, '%d' ) . ')' );
}
}
// remove any duplicates in icl_translations
$trs = $wpdb->get_results(
"SELECT element_id, GROUP_CONCAT(translation_id) AS tids FROM {$wpdb->prefix}icl_translations
WHERE element_id > 0 AND element_type LIKE 'post\\_%' GROUP BY element_id"
);
foreach ( $trs as $r ) {
$exp = explode( ',', $r->tids );
if ( count( $exp ) > 1 ) {
$maxtid = max( $exp );
foreach ( $exp as $e ) {
if ( $e != $maxtid ) {
$upgrade_args = array(
'translation_id' => $e,
'context' => 'post',
);
do_action( 'wpml_translation_update', array_merge( $upgrade_args, array( 'type' => 'before_delete' ) ) );
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}icl_translations WHERE translation_id=%d", $e ) );
do_action( 'wpml_translation_update', array_merge( $upgrade_args, array( 'type' => 'after_delete' ) ) );
}
}
}
}
exit;
break;
case 'assign_translation_status_to_duplicates':
$updated_items = WPML\Troubleshooting\AssignTranslationStatusToDuplicates::run();
echo json_encode( array( 'updated' => $updated_items ) );
exit;
case 'icl_ts_add_missing_language':
global $iclTranslationManagement;
$iclTranslationManagement->add_missing_language_information();
exit;
case 'link_post_type':
$old_el_type = 'post_' . sanitize_key( filter_input( INPUT_GET, 'old_value' ) );
$new_el_type = 'post_' . sanitize_key( filter_input( INPUT_GET, 'new_value' ) );
$wpdb->update(
$wpdb->prefix . 'icl_translations',
array( 'element_type' => $new_el_type ),
array( 'element_type' => $old_el_type )
);
do_action(
'wpml_translation_update',
array(
'type' => 'element_type_update',
'element_type' => $new_el_type,
'context' => 'post',
)
);
exit;
case 'link_taxonomy':
$new_el_type = 'tax_' . $_GET['new_value'];
$old_el_type = 'tax_' . $_GET['old_value'];
$wpdb->update(
$wpdb->prefix . 'icl_translations',
array( 'element_type' => $new_el_type ),
array( 'element_type' => $old_el_type )
);
do_action(
'wpml_translation_update',
array(
'type' => 'element_type_update',
'element_type' => $new_el_type,
'content' => 'tax',
)
);
exit;
case 'icl_fix_terms_count':
global $sitepress;
$has_get_terms_args_filter = remove_filter( 'get_terms_args', array( $sitepress, 'get_terms_args_filter' ) );
$has_get_term_filter = remove_filter( 'get_term', array( $sitepress, 'get_term_adjust_id' ), 1 );
$has_terms_clauses_filter = remove_filter( 'terms_clauses', array( $sitepress, 'terms_clauses' ) );
foreach ( get_taxonomies( array(), 'names' ) as $taxonomy ) {
$terms_objects = get_terms( $taxonomy, 'hide_empty=0' );
if ( $terms_objects ) {
$term_taxonomy_ids = array_map( 'get_term_taxonomy_id_from_term_object', $terms_objects );
wp_update_term_count( $term_taxonomy_ids, $taxonomy, true );
}
}
if ( $has_terms_clauses_filter ) {
add_filter( 'terms_clauses', array( $sitepress, 'terms_clauses' ), 10, 3 );
}
if ( $has_get_term_filter ) {
add_filter( 'get_term', array( $sitepress, 'get_term_adjust_id' ), 1, 1 );
}
if ( $has_get_terms_args_filter ) {
add_filter( 'get_terms_args', array( $sitepress, 'get_terms_args_filter' ), 10, 2 );
}
exit;
case 'icl_remove_st_db_cache_logs':
delete_option( 'wpml-st-persist-errors' );
exit;
}
}
/* DEBUG ACTION */
global $sitepress;
if ( wp_verify_nonce(
(string) filter_input( INPUT_POST, 'icl_reset_allnonce' ),
'icl_reset_all'
) ) {
if ( $_POST['icl-reset-all'] == 'on' ) {
icl_reset_wpml();
echo '<script type="text/javascript">location.href=\'' . admin_url(
'plugins.php?deactivate=true'
) . '\'</script>';
exit();
}
}
?>
<div class="wrap">
<h2><?php echo __( 'Troubleshooting', 'sitepress' ); ?></h2>
<?php if ( isset( $_GET['message'] ) ) { ?>
<div class="updated message fade"><p>
<?php echo esc_html( $_GET['message'] ); ?>
</p></div>
<?php } ?>
<?php
// phpcs:disable
echo \WPML\ICLToATEMigration\Loader::renderContainerIfNeeded();
// phpcs:enable
echo '<a href="#wpml-settings">' . __( 'WPML Settings', 'sitepress' ) . '</a>';
echo '<br /><hr /><h3 id="wpml-settings"> ' . __( 'WPML settings', 'sitepress' ) . '</h3>';
echo '<textarea style="font-size:10px;width:100%" wrap="off" rows="16" readonly="readonly">';
ob_start();
print_r( $sitepress->get_settings() );
$ob = ob_get_contents();
ob_end_clean();
echo esc_html( $ob );
echo '</textarea>';
?>
<script type="text/javascript">
jQuery(document).ready(function () {
jQuery('#icl_troubleshooting_more_options').submit(iclSaveForm);
})
</script>
<br clear="all"/><br/>
<br/>
<script type="text/javascript">
function wpml_ts_link_post_type(select, old_value) {
if (!select.val()) return;
select.attr('disabled', 'disabled');
select.after(icl_ajxloaderimg);
jQuery.post(WPML_core.sanitize(location.href) + '&debug_action=link_post_type&nonce=<?php echo wp_create_nonce( 'link_post_type' ); ?>&new_value=' + select.val() + '&old_value=' + old_value, function () {
alert('<?php echo esc_js( __( 'Done', 'sitepress' ) ); ?>');
select.next().fadeOut();
location.reload();
});
}
function wpml_ts_link_taxonomy(select, old_value) {
if (!select.val()) return;
select.attr('disabled', 'disabled');
select.after(icl_ajxloaderimg);
jQuery.post(WPML_core.sanitize(location.href) + '&debug_action=link_taxonomy&nonce=<?php echo wp_create_nonce( 'link_taxonomy' ); ?>&new_value=' + select.val() + '&old_value=' + old_value, function () {
alert('<?php echo esc_js( __( 'Done', 'sitepress' ) ); ?>');
select.next().fadeOut();
location.reload();
});
}
function parse_xhr_error(xhr, status, error) {
return xhr.statusText || status || error;
}
jQuery(document).ready(function ($) {
$('#otgs_twig_cache_enable').find('.button-secondary').on('click', function () {
jQuery(this).attr('disabled', 'disabled');
jQuery(this).after(icl_ajxloaderimg);
var value = jQuery(this).parent().find('.otgs_twig_cache_new_value').val();
var key = '<?php echo $otgs_twig_cache_disable_key; ?>';
jQuery.ajax({
type: "POST",
url: WPML_core.sanitize( location.href ),
data: {
'debug_action': 'otgs_twig_cache_enable',
'nonce': '<?php echo wp_create_nonce( 'otgs_twig_cache_enable' ); ?>',
'new_value': value
},
success: function () {
alert('<?php echo esc_js( __( 'Done', 'sitepress' ) ); ?>');
location.reload();
}
});
});
jQuery('#icl_fix_languages').click(function () {
jQuery(this).prop('disabled', true);
jQuery(this).after(icl_ajxloaderimg);
var icl_fix_languages = jQuery('#icl_fix_languages');
jQuery.ajax({
type: 'POST',
contentType: "application/json; charset=utf-8",
url: WPML_core.sanitize(location.href) + '&debug_action=fix_languages&nonce=<?php echo wp_create_nonce( 'fix_languages' ); ?>',
timeout: 60000,
success: function () {
icl_fix_languages.prop('disabled', false);
alert('<?php echo esc_js( __( 'Done', 'sitepress' ) ); ?>');
icl_fix_languages.next().fadeOut();
location.reload();
},
error: function (jqXHR, status, error) {
var parsed_response = parse_xhr_error(jqXHR, status, error);
<?php
$timeout_message = 'The operation timed out, but languages may still get fixed in the background.\n';
$timeout_message .= 'Please wait 5-10 minutes, then refresh or come back to this page.\n';
$timeout_message .= 'If languages are still not fixed, please retry or contact the WPML support.'
?>
if(parsed_response=='timeout') {
alert('<?php echo __( $timeout_message, 'sitepress' ); ?>');
} else {
alert(parsed_response);
}
icl_fix_languages.next().fadeOut();
}
});
});
jQuery('#icl_remove_ghost').click(function () {
var self = jQuery(this);
self.prop('disabled', true);
self.after(icl_ajxloaderimg);
jQuery.post(WPML_core.sanitize(location.href) + '&debug_action=ghost_clean&nonce=<?php echo wp_create_nonce( 'ghost_clean' ); ?>', function () {
self.prop('disabled', false);
alert('<?php echo esc_js( __( 'Done', 'sitepress' ) ); ?>');
self.next().fadeOut();
});
});
// #assign_translation_status_to_duplicates_resp: BEGIN
var assign_translation_status_to_duplicates_loader = jQuery(icl_ajxloaderimg);
var assign_translation_status_to_duplicates_cycles = 0;
var assign_translation_status_to_duplicates_updated = 0;
var response_element = jQuery('#assign_translation_status_to_duplicates_resp');
var assign_translation_status_to_duplicates_element = jQuery('#assign_translation_status_to_duplicates');
assign_translation_status_to_duplicates_element.click(function () {
assign_translation_status_to_duplicates();
});
function assign_translation_status_to_duplicates() {
if (assign_translation_status_to_duplicates_cycles == 0) {
assign_translation_status_to_duplicates_element.prop('disabled', true);
response_element.text('');
response_element.show();
assign_translation_status_to_duplicates_element.after(assign_translation_status_to_duplicates_loader);
}
assign_translation_status_to_duplicates_cycles++;
jQuery.ajax({
type: 'POST',
contentType: "application/json; charset=utf-8",
url: WPML_core.sanitize(location.href) + '&debug_action=assign_translation_status_to_duplicates&nonce=<?php echo wp_create_nonce( 'assign_translation_status_to_duplicates' ); ?>',
dataType: 'json',
success: function (msg) {
assign_translation_status_to_duplicates_updated += msg.updated;
var response_message;
if (msg.updated > 0) {
response_message = assign_translation_status_to_duplicates_updated + ' <?php echo esc_js( _x( 'translation jobs updated', 'Sets the translation status to DUPLICATE in the icl_translation_status table, for posts that are marked as duplicated', 'sitepress' ) ); ?>';
if (assign_translation_status_to_duplicates_cycles >= 50) {
response_message += '. <?php echo esc_js( _x( 'Partially done.', 'Sets the translation status to DUPLICATE in the icl_translation_status table, for posts that are marked as duplicated', 'sitepress' ) ); ?>';
response_message += '. <?php echo esc_js( _x( 'There might be more content to fix: please repeat the process.', 'Sets the translation status to DUPLICATE in the icl_translation_status table, for posts that are marked as duplicated', 'sitepress' ) ); ?>';
response_element.text(response_message);
alert('<?php echo esc_js( _x( 'Partially done', 'Sets the translation status to DUPLICATE in the icl_translation_status table, for posts that are marked as duplicated', 'sitepress' ) ); ?>');
response_element.fadeOut();
assign_translation_status_to_duplicates_loader.fadeOut(function() {
assign_translation_status_to_duplicates_element.remove(assign_translation_status_to_duplicates_loader);
});
assign_translation_status_to_duplicates_element.prop('disabled', false);
//Reset counters
assign_translation_status_to_duplicates_cycles = 0;
assign_translation_status_to_duplicates_updated = 0;
} else {
response_message += ' ...';
response_element.text(response_message);
assign_translation_status_to_duplicates();
}
} else {
response_message = '';
if (assign_translation_status_to_duplicates_updated != 0) {
response_message += assign_translation_status_to_duplicates_updated + '.';
}
response_message += '<?php echo esc_js( __( 'Done', 'sitepress' ) ); ?>';
response_element.text(response_message);
alert('<?php echo esc_js( __( 'Done', 'sitepress' ) ); ?>');
response_element.fadeOut();
assign_translation_status_to_duplicates_loader.fadeOut(function() {
assign_translation_status_to_duplicates_element.remove(assign_translation_status_to_duplicates_loader);
});
assign_translation_status_to_duplicates_element.prop('disabled', false);
}
},
error: function (xhr, status, error) {
var parsed_response = parse_xhr_error(xhr, status, error);
response_element.text('');
response_element.html(parsed_response);
assign_translation_status_to_duplicates_loader.fadeOut(function() {
assign_translation_status_to_duplicates_element.remove(assign_translation_status_to_duplicates_loader);
});
assign_translation_status_to_duplicates_element.attr('disabled', 'disabled');
}
});
}
jQuery('#icl_add_missing_lang').click(function () {
var self = jQuery(this);
self.prop('disabled', true);
self.after(icl_ajxloaderimg);
jQuery.post(WPML_core.sanitize(location.href) + '&debug_action=icl_ts_add_missing_language&nonce=<?php echo wp_create_nonce( 'icl_ts_add_missing_language' ); ?>', function () {
self.prop('disabled', false);
alert('<?php echo esc_js( __( 'Done', 'sitepress' ) ); ?>');
self.next().fadeOut();
});
});
jQuery('#icl_fix_collation').click(function () {
jQuery(this).prop('disabled', true);
jQuery(this).after(icl_ajxloaderimg);
jQuery.post(WPML_core.sanitize(location.href) + '&debug_action=icl_fix_collation&nonce=<?php echo wp_create_nonce( 'icl_fix_collation' ); ?>', function () {
jQuery('#icl_fix_collation').prop('disabled', false);
alert('<?php echo esc_js( __( 'Done', 'sitepress' ) ); ?>');
jQuery('#icl_fix_collation').next().fadeOut();
});
});
jQuery('#icl_fix_terms_count').click(function () {
var self = jQuery(this);
self.prop('disabled', true);
self.after(icl_ajxloaderimg);
jQuery.post(WPML_core.sanitize(location.href) + '&debug_action=icl_fix_terms_count&nonce=<?php echo wp_create_nonce( 'icl_fix_terms_count' ); ?>', function () {
self.prop('disabled', false);
alert('<?php echo esc_js( __( 'Done', 'sitepress' ) ); ?>');
self.next().fadeOut();
});
});
jQuery('#icl_remove_st_db_cache_logs').click(function () {
var self = jQuery(this);
self.prop('disabled', true);
self.after(icl_ajxloaderimg);
jQuery.post(WPML_core.sanitize(location.href) + '&debug_action=icl_remove_st_db_cache_logs&nonce=<?php echo wp_create_nonce( 'icl_remove_st_db_cache_logs' ); ?>', function () {
self.prop('disabled', false);
alert('<?php echo esc_js( __( 'Done', 'sitepress' ) ); ?>');
self.next().fadeOut();
});
});
<?php
$icl_ajax_url = wpml_get_admin_url(
[
'path' => 'admin.php',
'query' => [ 'page' => WPML_PLUGIN_FOLDER . '/menu/languages.php' ],
]
);
?>
jQuery('#icl_reset_languages').click(function () {
var icl_ajx_url = '<?php echo esc_url( $icl_ajax_url ); ?>';
var self = jQuery(this);
self.prop('disabled', true);
self.after(icl_ajxloaderimg);
jQuery.post(icl_ajx_url + "&icl_ajx_action=reset_languages&_icl_nonce=" + jQuery('#_icl_nonce_rl').val(), function () {
self.prop('disabled', false);
alert('<?php echo esc_js( __( 'Done', 'sitepress' ) ); ?>');
self.next().fadeOut();
});
});
})
</script>
<div class="icl_cyan_box">
<h3><?php _e( 'Advanced settings', 'sitepress' ); ?></h3>
<p id="otgs_twig_cache_enable">
<?php
$twig_cache_disabled = (bool) get_option( $otgs_twig_cache_disable_key, false );
$twig_cache_new_value = ! $twig_cache_disabled;
$twig_cache_label = __( 'Disable cache for language switcher templates', 'sitepress' );
if ( $twig_cache_disabled ) {
$twig_cache_label = __( 'Enable cache for language switcher templates', 'sitepress' );
}
?>
<input type="hidden" id="otgs_twig_cache_new_value" class="otgs_twig_cache_new_value" value="<?php echo $twig_cache_new_value; ?>"/>
<input type="button" class="button-secondary" value="<?php echo $twig_cache_label; ?>"/><br/>
</p>
</div><br clear="all"/>
<?php
$registration_data = get_ATE_account_data();
$shared = array_key_exists( 'shared', $registration_data ) ? $registration_data['shared'] : null;
$uuid = get_option( WPML_Site_ID::SITE_ID_KEY . ':' . WPML_TM_ATE::SITE_ID_SCOPE, null );
if ( $shared ) {
?>
<div class="icl_cyan_box">
<h3><?php _e( 'Your Automatic Translation account id is', 'sitepress' ); ?></h3>
<p>
<?php echo $uuid . '#' . $registration_data['shared']; ?>
</p>
</div><br clear="all"/>
<?php
}
?>
<div class="icl_cyan_box">
<h3><?php _e( 'Clean up', 'sitepress' ); ?></h3>
<p class="icl_form_errors" style="padding:6px;"><?php _e( 'Please make backup of your database before using this.', 'sitepress' ); ?></p>
<?php if ( ! SitePress_Setup::languages_complete() ) { ?>
<p>
<br />
<label><input type="checkbox" onchange="if(jQuery(this).prop('checked')){jQuery('#icl_fix_languages').prop('disabled', false);}else{jQuery('#icl_fix_languages').prop('disabled', true);}">
&nbsp;<?php _e( "This operation will reset WPML's language tables and reinstall it. Any custom languages that you added will be removed.", 'sitepress' ); ?></label><br /><br />
<input disabled="disabled" id="icl_fix_languages" type="button" class="button-secondary" value="<?php _e( 'Clear language information and repopulate languages', 'sitepress' ); ?>"/><br/><br />
<small style="margin-left:10px;"><?php _e( "This operation will remove WPML's language table and recreate it. You should use it if you just installed WPML and you're not seeing a complete list of available languages.", 'sitepress' ); ?></small>
<br /><br />
</p>
<?php } ?>
<?php if ( SitePress_Setup::setup_complete() ) { ?>
<?php do_action( 'wpml_troubleshooting_after_setup_complete_cleanup_begin' ); ?>
<?php do_action( 'before_setup_complete_troubleshooting_functions' ); ?>
<p>
<select name="wpml_post_type">
<?php foreach ( $sitepress->get_translatable_documents() as $key => $translatable_document ) : ?>
<option value="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $translatable_document->label ); ?></option>
<?php endforeach; ?>
</select>
<input id="wpml_sync_posts_taxonomies" type="button" class="button-secondary" value="<?php esc_html_e( 'Synchronize posts taxonomies', 'sitepress' ); ?>"/> <span class="wpml-notice"></span><br/>
<small style="margin-left:10px;"><?php esc_html_e( 'This will assign the same taxonomy terms as the source for each post translation.', 'sitepress' ); ?></small>
</p>
<p>
<input id="icl_cache_clear" type="button" class="button-secondary" value="<?php _e( 'Clear the cache in WPML', 'sitepress' ); ?>"/><br/>
<small style="margin-left:10px;"><?php _e( 'This may solve issues like missing languages in the language switcher.', 'sitepress' ); ?></small>
</p>
<p>
<input id="icl_remove_ghost" type="button" class="button-secondary" value="<?php _e( 'Remove ghost entries from the translation tables', 'sitepress' ); ?>"/><br/>
<small style="margin-left:10px;"><?php _e( 'Removes entries from the WPML tables that are not linked properly. Cleans the table off entries left over upgrades, bug fixes or undetermined factors.', 'sitepress' ); ?></small>
</p>
<p>
<input id="icl_fix_collation" type="button" class="button-secondary" value="<?php _e( 'Fix element_type collation', 'sitepress' ); ?>"/><br/>
<small style="margin-left:10px;"><?php _e( 'Fixes the collation of the element_type column in icl_translations in case this setting changed for your posts.post_type column.', 'sitepress' ); ?></small>
</p>
<?php do_action( 'wpml_troubleshooting_after_fix_element_type_collation' ); ?>
<?php do_action( 'wpml_tm_mcs_troubleshooting' ); ?>
<?php if ( class_exists( 'TranslationManagement' ) ) { ?>
<p>
<input id="assign_translation_status_to_duplicates" type="button" class="button-secondary" value="<?php _e( 'Assign translation status to duplicated content', 'sitepress' ); ?>"/><span id="assign_translation_status_to_duplicates_resp"></span><br/>
<small style="margin-left:10px;"><?php _e( 'Sets the translation status to DUPLICATE in the icl_translation_status table, for posts that are marked as duplicated.', 'sitepress' ); ?> </small>
</p>
<?php } ?>
<p>
<input id="icl_add_missing_lang" type="button" class="button-secondary" value="<?php _e( 'Set language information', 'sitepress' ); ?>"/><br/>
<small style="margin-left:10px;"><?php _e( 'Adds language information to posts and taxonomies that are missing this information.', 'sitepress' ); ?></small>
</p>
<p>
<?php wp_nonce_field( 'reset_languages_nonce', '_icl_nonce_rl' ); ?>
<input class="button-secondary" type="button" id="icl_reset_languages" value="<?php esc_html_e( 'Reset languages', 'sitepress' ); ?>"/>
<small style="margin-left:10px;"><?php esc_html_e( 'WPML will reset all language information to its default values. Any languages that you added or edited will be lost.', 'sitepress' ); ?></small>
</p>
<p>
<input id="icl_fix_terms_count" type="button" class="button-secondary" value="<?php _e( 'Fix terms count', 'sitepress' ); ?>"/><br/>
<small style="margin-left:10px;"><?php _e( 'Correct terms count in case something went wrong with translated contents.', 'sitepress' ); ?></small>
</p>
<p>
<input id="icl_fix_post_types" type="button" class="button-secondary" value="<?php _e( 'Fix post type assignment for translations', 'sitepress' ); ?>"/><br/>
<small style="margin-left:10px;"><?php _e( 'Correct post type assignment for translations of custom post types in case something went wrong.', 'sitepress' ); ?></small>
</p>
<?php if ( get_option( 'wpml-st-persist-errors' ) ) { ?>
<p>
<input id="icl_remove_st_db_cache_logs" type="button" class="button-secondary" value="<?php _e( 'Remove debug logs of String Translation cache', 'sitepress' ); ?>"/><br/>
<small style="margin-left:10px;"><?php _e( 'Removes invalid rows stored in option and hide admin notice.', 'sitepress' ); ?></small>
</p>
<?php } ?>
<p>
<br/>
<?php _e( 'Translatable custom posts linking', 'sitepress' ); ?><br/>
<small style="margin-left:10px;"><?php _e( 'Allows linking existing translations after changing custom posts definition (name) ', 'sitepress' ); ?></small>
<?php
$translatable_posts = $sitepress->get_translatable_documents();
$res = $wpdb->get_col(
$wpdb->prepare(
"SELECT DISTINCT element_type FROM {$wpdb->prefix}icl_translations WHERE element_type LIKE %s",
array( wpml_like_escape( 'post_' ) . '%' )
)
);
echo '<table class="widefat" style="width:300px;">';
foreach ( $res as $row ) {
$post_type = preg_replace( '#^post_#', '', $row );
if ( $post_type == 'nav_menu_item' ) {
continue;
}
echo '<tr>';
echo '<td>' . $post_type . '</td>';
if ( isset( $translatable_posts[ $post_type ] ) ) {
echo '<td>' . __( 'linked to: ', 'sitepress' ) . $translatable_posts[ $post_type ]->labels->name . '</td>';
} else {
echo '<td>';
echo '<select onchange="wpml_ts_link_post_type(jQuery(this), \'' . $post_type . '\')">';
echo '<option value="">' . __( '--select--', 'sitepress' ) . '</option>';
foreach ( $translatable_posts as $name => $type ) {
echo '<option value="' . $name . '">' . $type->labels->name . '(' . $name . ')' . '</option>';
}
echo '</select>';
echo '</td>';
}
echo '</tr>';
}
echo '</table>';
echo '<br />';
echo __( 'Note: if you edited the custom post declaration you may need to re-configure WPML to mark it as translatable.', 'sitepress' );
?>
</p>
<p>
<br/>
<?php _e( 'Translatable taxonomies linking', 'sitepress' ); ?><br/>
<small style="margin-left:10px;"><?php _e( 'Allows linking existing translations after changing custom taxonomies definition (name) ', 'sitepress' ); ?></small>
<?php
global $wp_post_types, $wp_taxonomies;
$translatable_taxs = array();
foreach ( $wp_post_types as $name => $post_type ) {
$translatable_taxs = array_merge( $translatable_taxs, $sitepress->get_translatable_taxonomies( true, $name ) );
}
$translatable_taxs = array_unique( $translatable_taxs );
$res = $wpdb->get_col(
$wpdb->prepare(
"SELECT DISTINCT element_type FROM {$wpdb->prefix}icl_translations WHERE element_type LIKE %s",
array( wpml_like_escape( 'tax_' ) . '%' )
)
);
echo '<table class="widefat" style="width:300px;">';
foreach ( $res as $row ) {
$tax = preg_replace( '#^tax_#', '', $row );
if ( $tax == 'link_category' || $tax == 'nav_menu' ) {
continue;
}
echo '<tr>';
echo '<td>' . $tax . '</td>';
if ( in_array( $tax, $translatable_taxs ) ) {
echo '<td>' . __( 'linked to: ', 'sitepress' ) . $wp_taxonomies[ $tax ]->labels->name . '</td>';
} else {
echo '<td>';
echo '<select onchange="wpml_ts_link_taxonomy(jQuery(this), \'' . $tax . '\')">';
echo '<option value="">' . __( '--select--', 'sitepress' ) . '</option>';
foreach ( $translatable_taxs as $name ) {
echo '<option value="' . $name . '">' . $wp_taxonomies[ $name ]->labels->name . '(' . $name . ')' . '</option>';
}
echo '</select>';
echo '</td>';
}
echo '</tr>';
}
echo '</table>';
echo '<br />';
echo __( 'Note: if you edited the custom taxonomy declaration you may need to re-configure WPML to mark it as translatable.', 'sitepress' );
?>
</p>
<?php do_action( 'wpml_troubleshooting_after_setup_complete_cleanup_end' ); ?>
<?php do_action( 'after_setup_complete_troubleshooting_functions' ); ?>
<?php } ?>
</div>
<br clear="all"/>
<?php
// TODO: [WPML 3.3] we should use the new hooks to add elements to the troubleshooting page
echo WPML_Troubleshooting_Terms_Menu::display_terms_with_suffix();
?>
<br clear="all"/>
<div class="icl_cyan_box">
<?php
echo '<h3 id="wpml-settings"> ' . __( 'Reset', 'sitepress' ) . '</h3>';
?>
<?php if ( function_exists( 'is_multisite' ) && is_multisite() ) { ?>
<p><?php _e( 'This function is available through the Network Admin section.', 'sitepress' ); ?></p>
<?php if ( current_user_can( 'manage_sites' ) ) { ?>
<a href="
<?php
echo esc_url(
network_admin_url( 'admin.php?page=' . WPML_PLUGIN_FOLDER . '/menu/network.php' )
)
?>
"><?php _e( 'Go to WPML Network settings.', 'sitepress' ); ?></a>
<p><small><?php _e( 'Note: WPML must be activated on the primary site or must be network activated.', 'sitepress' ); ?></small></p>
<?php } else { ?>
<i><?php _e( 'You are not allowed to manage the WPML Network settings.', 'sitepress' ); ?></i>
<?php } ?>
<?php } else { ?>
<?php
echo '<form method="post" onsubmit="return confirm(\'' . __(
'Are you sure you want to reset all translation and language data? This operation cannot be reversed!',
'sitepress'
) . '\')">';
wp_nonce_field( 'icl_reset_all', 'icl_reset_allnonce' );
echo '<p class="error" style="padding:6px;">';
_e(
"The 'Reset' action will deactivate the WPML plugin after it deletes the WPML tables (tables with the 'icl_' prefix) from the database. The action will NOT delete any content (posts, taxonomy terms etc.). It only affects translation and language information that WPML associates with each content type.",
'sitepress'
);
echo '</p>';
echo '<p class="error" style="padding:6px;">';
_e( "Please note that all translations you have sent to remote translation services will be lost if you reset WPML's data. They cannot be recovered later.", 'sitepress' );
echo '</p>';
echo '<p class="error" style="padding:6px;">';
_e( 'If you are using the Advanced Translation Editor, you will lose the translations that are in progress, as well as the existing translation memory and glossary. You will also lose access to purchases, invoices, and history related to your work with the Advanced Translation Editor.', 'sitepress' );
echo '</p>';
echo '<label><input type="checkbox" name="icl-reset-all" ';
if ( ! function_exists( 'is_super_admin' ) || is_super_admin() ) {
echo 'onchange="if(this.checked) jQuery(\'#reset-all-but\').prop(\'disabled\', false); else jQuery(\'#reset-all-but\').prop(\'disabled\', true);"';
}
echo ' /> ' . __( 'I am about to reset all translation and language data.', 'sitepress' ) . '</label><br /><br />';
echo '<input id="reset-all-but" type="submit" disabled="disabled" class="button-primary" value="' . __(
'Reset and deactivate WPML',
'sitepress'
) . '" />';
echo '</form>';
?>
<?php } ?>
</div>
<?php do_action( 'icl_menu_footer' ); ?>
</div>

View File

@@ -0,0 +1,39 @@
<?php
$upgrade_lines = array(
'3.2' => array(
'message' => __( 'This version of WPML includes major updates and improvements.', 'sitepress' ),
'link' => '<a href="https://wpml.org/version/wpml-3-2/?utm_source=plugin&utm_medium=gui&utm_campaign=wpmlcore">' . __( 'WPML 3.2 release notes', 'sitepress' ) . '</a>',
'dismiss' => false,
),
);
$short_v = implode( '.', array_slice( explode( '.', ICL_SITEPRESS_VERSION ), 0, 3 ) );
if ( ! isset( $upgrade_lines[ $short_v ] ) ) {
return;
}
?>
<div id="icl_update_message" class="updated message fade otgs-is-dismissible">
<p><img src="<?php echo ICL_ICONS_URL . 'icon_adv.png'; ?>" />&nbsp;<?php echo $upgrade_lines[ $short_v ]['message']; ?></p>
<p>
<?php if ( $upgrade_lines[ $short_v ]['link'] ) : ?>
<?php echo $upgrade_lines[ $short_v ]['link']; ?>
<?php else : ?>
<a href="https://wpml.org/?cat=48"><?php _e( 'Learn more', 'sitepress' ); ?></a>
<?php endif; ?>
</p>
<?php
if ( $upgrade_lines[ $short_v ]['dismiss'] ) {
?>
<span title="<?php _e( 'Stop showing this message', 'sitepress' ); ?>" id="icl_dismiss_upgrade_notice" class="notice-dismiss"><span class="screen-reader-text"><?php _e( 'Dismiss', 'sitepress' ); ?></span></span>
<?php
wp_nonce_field( 'dismiss_upgrade_notice_nonce', '_icl_nonce_dun' );
} else {
// set the hide settings so it's shown only one
icl_set_setting( 'hide_upgrade_notice', implode( '.', array_slice( explode( '.', ICL_SITEPRESS_VERSION ), 0, 3 ) ) );
icl_save_settings();
}
?>
</div>

View File

@@ -0,0 +1,278 @@
<?php
use WPML\FP\Obj;
use WPML\UIPage;
class WPML_Admin_Language_Switcher {
private $flag_kses_tags = array(
'img' => array(
'src' => array(),
'class' => array(),
'height' => array(),
'width' => array(),
),
'i' => array(
'class' => array(),
),
);
private $current_language;
function render() {
wp_enqueue_script( OTGS_Assets_Handles::POPOVER_TOOLTIP );
wp_enqueue_style( OTGS_Assets_Handles::POPOVER_TOOLTIP );
$languages_links = $this->get_languages_links();
$this->render_admin_bar_menu( $languages_links, $this->current_language );
}
public function get_languages_links() {
global $wpdb, $pagenow, $mode, $sitepress;
$all_languages_enabled = true;
$current_page = basename( $_SERVER['SCRIPT_NAME'] );
$post_type = false;
$trid = false;
$translations = false;
$languages_links = array();
// individual translations
$is_post = false;
$is_tax = false;
$is_menu = false;
$this->current_language = $sitepress->get_current_language();
$this->current_language = $this->current_language ? $this->current_language : $sitepress->get_default_language();
switch ( $pagenow ) {
case 'post.php':
case 'admin-ajax.php':
$is_post = true;
$post_id = @intval( Obj::propOr( $_GET['post'], 'post_id', $_POST ) );
$post = get_post( $post_id );
$post_language = $sitepress->get_language_for_element( $post_id, 'post_' . get_post_type( $post_id ) );
if ( $post_language && $post_language != $this->current_language ) {
$sitepress->switch_lang( $post_language );
$this->current_language = $sitepress->get_current_language();
}
$trid = $sitepress->get_element_trid( $post_id, 'post_' . $post->post_type );
$translations = $sitepress->get_element_translations( $trid, 'post_' . $post->post_type, true );
break;
case 'post-new.php':
$all_languages_enabled = false;
if ( isset( $_GET['trid'] ) ) {
$trid = intval( $_GET['trid'] );
$post_type = isset( $_GET['post_type'] ) ? $_GET['post_type'] : 'post';
$translations = $sitepress->get_element_translations( $trid, 'post_' . $post_type, true );
$is_post = true;
}
break;
case 'edit-tags.php':
case 'term.php':
$is_tax = true;
if ( $sitepress->get_wp_api()->is_term_edit_page() ) {
$all_languages_enabled = false;
}
$taxonomy = $_GET['taxonomy'];
$term_tax_id = 0;
if ( isset( $_GET['tag_ID'] ) ) {
$term_id = @intval( $_GET['tag_ID'] );
$term_tax_id = $wpdb->get_var( $wpdb->prepare( "SELECT term_taxonomy_id FROM {$wpdb->term_taxonomy} WHERE taxonomy=%s AND term_id=%d", $taxonomy, $term_id ) );
}
if ( $term_tax_id ) {
$trid = $sitepress->get_element_trid( $term_tax_id, 'tax_' . $taxonomy );
}
if ( $trid ) {
$translations = $sitepress->get_element_translations( $trid, 'tax_' . $taxonomy, true );
}
break;
case 'nav-menus.php':
$is_menu = true;
if ( isset( $_GET['menu'] ) && $_GET['menu'] ) {
$menu_id = $_GET['menu'];
$element_id = $wpdb->get_var( $wpdb->prepare( "SELECT term_taxonomy_id FROM {$wpdb->term_taxonomy} WHERE term_id=%d", $menu_id ) );
$trid = $trid = $sitepress->get_element_trid( $element_id, 'tax_nav_menu' );
$translations = $sitepress->get_element_translations( $trid, 'tax_nav_menu', true );
}
$all_languages_enabled = false;
break;
case 'upload.php':
if ( $mode == 'grid' ) {
$all_languages_enabled = false;
}
break;
}
if( UIPage::isTMDashboard( $_GET ) ) {
$all_languages_enabled = false;
}
$active_languages = $sitepress->get_active_languages();
$current_active_language = null;
if ( 'all' !== $this->current_language ) {
$current_active_language = isset( $active_languages[ $this->current_language ] ) ? $active_languages[ $this->current_language ] : null;
}
$active_languages = apply_filters( 'wpml_admin_language_switcher_active_languages', $active_languages );
if ( 'all' !== $this->current_language && ! isset( $active_languages[ $this->current_language ] ) ) {
array_unshift( $active_languages, $current_active_language );
}
foreach ( $active_languages as $lang ) {
$current_page_lang = $current_page;
if ( isset( $_SERVER['QUERY_STRING'] ) ) {
parse_str( $_SERVER['QUERY_STRING'], $query_vars );
unset( $query_vars['lang'], $query_vars['admin_bar'] );
} else {
$query_vars = array();
}
// individual translations
if ( $is_post ) {
if ( isset( $translations[ $lang['code'] ] ) && isset( $translations[ $lang['code'] ]->element_id ) ) {
$query_vars['post'] = $translations[ $lang['code'] ]->element_id;
unset( $query_vars['source_lang'] );
$current_page_lang = 'post.php';
$query_vars['action'] = 'edit';
} else {
$current_page_lang = 'post-new.php';
if ( isset( $post ) ) {
$query_vars['post_type'] = $post->post_type;
$query_vars['source_lang'] = $this->current_language;
} else {
$query_vars['post_type'] = $post_type;
}
$query_vars['trid'] = $trid;
unset( $query_vars['post'], $query_vars['action'] );
}
} elseif ( $is_tax ) {
if ( isset( $translations[ $lang['code'] ] ) && isset( $translations[ $lang['code'] ]->term_id ) ) {
$query_vars['tag_ID'] = $translations[ $lang['code'] ]->term_id;
} else {
$query_vars['trid'] = $trid;
$query_vars['source_lang'] = $this->current_language;
unset( $query_vars['tag_ID'], $query_vars['action'] );
}
} elseif ( $is_menu ) {
if ( ! empty( $menu_id ) ) {
if ( isset( $translations[ $lang['code'] ]->term_id ) ) {
$query_vars['menu'] = $translations[ $lang['code'] ]->term_id;
} else {
$query_vars['menu'] = 0;
$query_vars['trid'] = $trid;
$query_vars['action'] = 'edit';
}
}
}
$query_string = http_build_query( $query_vars );
$query = '?';
if ( ! empty( $query_string ) ) {
$query .= $query_string . '&';
}
$query .= 'lang=' . $lang['code']; // the default language need to specified explicitly yoo in order to set the lang cookie
$link_url = admin_url( $current_page_lang . $query );
$flag = $sitepress->get_flag( $lang['code'] );
if ( $flag ) {
if ( $flag->from_template ) {
$wp_upload_dir = wp_upload_dir();
$flag_url = $wp_upload_dir['baseurl'] . '/flags/' . $flag->flag;
} else {
$flag_url = ICL_PLUGIN_URL . '/res/flags/' . $flag->flag;
}
} else {
$flag_url = ICL_PLUGIN_URL . '/res/flags/';
}
$languages_links[ $lang['code'] ] = array(
'url' => $link_url . '&admin_bar=1',
'current' => $lang['code'] == $this->current_language,
'anchor' => $lang['display_name'],
'flag' => $sitepress->get_flag_image($lang['code'], [], '', [ 'icl_als_iclflag' ] ),
);
}
if ( $all_languages_enabled ) {
$query = '?';
if ( ! empty( $query_string ) ) {
$query .= $query_string . '&';
}
$query .= 'lang=all';
$link_url = admin_url( basename( $_SERVER['SCRIPT_NAME'] ) . $query );
$languages_links['all'] = array(
'url' => $link_url,
'current' => 'all' == $this->current_language,
'anchor' => __( 'All languages', 'sitepress' ),
'flag' => '<i class="otgs-ico-wpml"></i>',
);
} else {
// set the default language as current
if ( 'all' == $this->current_language ) {
$this->current_language = $sitepress->get_default_language();
$languages_links[ $this->current_language ]['current'] = true;
}
}
$current_language_item = isset( $languages_links[ $this->current_language ] ) ? $languages_links[ $this->current_language ] : null;
$languages_links = apply_filters( 'wpml_admin_language_switcher_items', $languages_links );
if ( ! isset( $languages_links[ $this->current_language ] ) ) {
$languages_links = array_merge( array( $this->current_language => $current_language_item ), $languages_links );
}
return $languages_links;
}
private function render_admin_bar_menu( $languages_links, $current_language ) {
/** @var WP_Admin_Bar $wp_admin_bar */
global $wp_admin_bar;
$parent = 'WPML_ALS';
$lang = $languages_links[ $this->current_language ];
$help_tip_text = __( 'This language selector determines which content to display. You can choose items in a specific language or in all languages. To change the language of the WordPress Admin interface, go to your profile.', 'sitepress' );
// Current language
$wp_admin_bar->add_menu(
array(
'parent' => false,
'id' => $parent,
'title' => '<span title="' . __( 'Showing content in:', 'sitepress' ) . ' ' . $lang['anchor'] . '">'
. wp_kses( $lang['flag'], $this->flag_kses_tags ) . '&nbsp;' . esc_html( $lang['anchor'] )
. '</span>'
. '&nbsp;<i class="otgs-ico-help js-otgs-popover-tooltip" data-tippy-zIndex="999999" title="' . $help_tip_text . '" ></i>',
'href' => false,
)
);
if ( $languages_links ) {
foreach ( $languages_links as $code => $lang ) {
if ( $code == $this->current_language ) {
continue;
}
$wp_admin_bar->add_menu(
array(
'parent' => $parent,
'id' => $parent . '_' . $code,
'title' => wp_kses( $lang['flag'], $this->flag_kses_tags ) . '&nbsp;' . esc_html( $lang['anchor'] ),
'href' => $lang['url'],
'meta' => array(
'title' => __( 'Show content in:', 'sitepress' ) . ' ' . $lang['anchor'],
),
)
);
}
}
}
}

View File

@@ -0,0 +1,71 @@
<?php
abstract class WPML_Language_Filter_Bar extends WPML_WPDB_And_SP_User {
protected $active_languages;
protected $current_language;
protected function init() {
if ( ! isset( $this->active_languages['all'] ) ) {
$this->current_language = $this->sitepress->get_current_language();
$this->active_languages = $this->sitepress->get_active_languages();
$this->active_languages['all'] = array( 'display_name' => __( 'All languages', 'sitepress' ) );
}
}
protected function lang_span( $lang_code, $count ) {
return ' (<span class="' . esc_attr( $lang_code ) . '">' . esc_html( $count ) . '</span>)';
}
protected function strong_lang_span_cover( $lang_code, $count ) {
$px = '<strong>';
$sx = $this->lang_span( $lang_code, $count ) . '</strong>';
return array( $px, $sx );
}
private function sanitize_get_input( $index, $parent_array ) {
$value = isset( $_GET[ $index ] ) ? $_GET[ $index ] : false;
return isset( $parent_array[ $value ] ) ? $value : '';
}
protected function sanitize_request() {
global $wp_post_types, $wp_taxonomies;
$taxonomy = $this->sanitize_get_input( 'taxonomy', $wp_taxonomies );
$post_type = $this->sanitize_get_input( 'post_type', $wp_post_types );
return array(
'req_tax' => $taxonomy,
'req_ptype' => $post_type,
);
}
abstract protected function get_count_data( $element_type );
protected function extra_conditions_snippet() {
$sql = ' AND t.language_code IN (' . wpml_prepare_in( array_keys( $this->active_languages ) ) . ')
GROUP BY language_code';
return apply_filters( 'wpml_language_filter_extra_conditions_snippet', $sql );
}
protected function get_counts( $element_type ) {
$counts = $this->get_count_data( $element_type );
$counts = (bool) $counts === true ? $counts : array();
return $this->generate_counts_array( $counts );
}
private function generate_counts_array( array $data ) {
$languages = array( 'all' => 0 );
foreach ( $data as $language_count ) {
$languages[ $language_count->language_code ] = $language_count->c;
$languages['all'] += $language_count->c;
}
return $languages;
}
}

View File

@@ -0,0 +1,256 @@
<?php
class WPML_Post_Status_Display {
const ICON_TRANSLATION_EDIT = 'otgs-ico-edit';
const ICON_TRANSLATION_NEEDS_UPDATE = 'otgs-ico-refresh';
const ICON_TRANSLATION_ADD = 'otgs-ico-add';
const ICON_TRANSLATION_ADD_DISABLED = 'otgs-ico-add-disabled';
const ICON_TRANSLATION_EDIT_DISABLED = 'otgs-ico-edit-disabled';
const ICON_TRANSLATION_IN_PROGRESS = 'otgs-ico-in-progress';
private $active_langs;
public function __construct( $active_languages ) {
$this->active_langs = $active_languages;
}
/**
* Returns the html of a status icon.
*
* @param string $link Link the status icon is to point to.
* @param string $text Hover text for the status icon.
* @param string $css_class
*
* @return string
*/
private function render_status_icon( $link, $text, $css_class ) {
$icon = $this->get_action_icon( $css_class, $text );
if ( strpos( $icon, 'disabled' ) ) {
$link = null;
}
if ( $link ) {
$icon_html = '<a href="' . esc_url( $link ) . '" class="js-wpml-translate-link">';
} else {
$icon_html = '<a class="js-wpml-translate-link">';
}
$icon_html .= $icon;
$icon_html .= $link ? '</a>' : '</span>';
return $icon_html;
}
private function get_action_icon( $css_class, $label ) {
return '<i class="' . $css_class . ' js-otgs-popover-tooltip" title="' . esc_attr( $label ) . '" data-original-title="' . esc_attr( $label ) . '"></i>';
}
/**
* This function takes a post ID and a language as input.
* It will always return the status icon,
* of the version of the input post ID in the language given as the second parameter.
*
* @param int $post_id original post ID
* @param string $lang language of the translation
*
* @return string
*/
public function get_status_html( $post_id, $lang ) {
list( $text, $link, $trid, $css_class, $status ) = $this->get_status_data( $post_id, $lang );
if ( ! did_action( 'wpml_pre_status_icon_display' ) ) {
do_action( 'wpml_pre_status_icon_display' );
}
/**
* Filters the translation edit link.
*
* @param string $link
* @param int $post_id
* @param string $lang
* @param int $trid
* @param string $css_class
* @param int $status
*/
$link = apply_filters( 'wpml_link_to_translation', $link, $post_id, $lang, $trid, $css_class, $status );
/**
* Filters the translation status text.
*
* @param string $text
* @param int $post_id
* @param string $lang
* @param int $trid
* @param string $css_class
* @param int $status
*/
$text = apply_filters( 'wpml_text_to_translation', $text, $post_id, $lang, $trid, $css_class, $status );
/**
* Filter the CSS class for the status icon.
*
* @since 4.2.0
*
* @param string $css_class
* @param int $post_id
* @param string $lang
* @param int $trid
* @param int $status
*/
$css_class = apply_filters( 'wpml_css_class_to_translation', $css_class, $post_id, $lang, $trid, $status );
$css_class = $this->map_old_icon_filter_to_css_class( $css_class, $post_id, $lang, $trid );
/**
* Filter the HTML link to edit the translation
*
* @since 4.2.0
*
* @param string HTML link
* @param int $post_id
* @param string $lang
* @param int $trid
*/
return apply_filters(
'wpml_post_status_display_html',
$this->render_status_icon( $link, $text, $css_class ),
$post_id,
$lang,
$trid
);
}
/**
* @param string $css_class
* @param int $post_id
* @param string $lang
* @param int $trid
*
* @return string
*/
private function map_old_icon_filter_to_css_class( $css_class, $post_id, $lang, $trid ) {
$map = array(
'edit_translation.png' => self::ICON_TRANSLATION_EDIT,
'needs-update.png' => self::ICON_TRANSLATION_NEEDS_UPDATE,
'add_translation.png' => self::ICON_TRANSLATION_ADD,
'in_progress.png' => self::ICON_TRANSLATION_IN_PROGRESS,
'add_translation_disabled.png' => self::ICON_TRANSLATION_ADD_DISABLED,
'edit_translation_disabled.png' => self::ICON_TRANSLATION_EDIT_DISABLED,
);
$old_icon = array_search( $css_class, $map, true );
/**
* Filters the old icon image
*
* @deprecated since 4.2.0, use `wpml_css_class_to_translation` instead
*
* @param string $old_icon
* @param int $post_id
* @param string $lang
* @param int $trid
* @param string $css_class
*/
$old_icon = apply_filters( 'wpml_icon_to_translation', $old_icon, $post_id, $lang, $trid, $css_class );
if ( $old_icon && array_key_exists( $old_icon, $map ) ) {
$css_class = $map[ $old_icon ];
}
return $css_class;
}
public function get_status_data( $post_id, $lang ) {
global $wpml_post_translations;
$status_helper = wpml_get_post_status_helper();
$trid = $wpml_post_translations->get_element_trid( $post_id );
$status = $status_helper->get_status( false, $trid, $lang );
$source_language_code = $wpml_post_translations->get_element_lang_code( $post_id );
$correct_id = $wpml_post_translations->element_id_in( $post_id, $lang );
if ( $status && $correct_id ) {
list( $text, $link, $css_class ) = $this->generate_edit_allowed_data( $correct_id, $status_helper->needs_update( $correct_id ) );
} else {
list( $text, $link, $css_class ) = $this->generate_add_data( $trid, $lang, $source_language_code, $post_id );
}
if ($status === ICL_TM_ATE_NEEDS_RETRY) {
list( $text, $link, $css_class ) = $this->generate_retry_data();
}
return array( $text, $link, $trid, $css_class, $status );
}
/**
* @param int $post_id
* @param bool $update true if the translation in questions is in need of an update,
* false otherwise.
*
* @return array
*/
private function generate_edit_allowed_data( $post_id, $update = false ) {
global $wpml_post_translations;
$lang_code = $wpml_post_translations->get_element_lang_code( $post_id );
$post_type = $wpml_post_translations->get_type( $post_id );
$css_class = self::ICON_TRANSLATION_EDIT;
if ( $update && ! $wpml_post_translations->is_a_duplicate( $post_id ) ) {
$css_class = self::ICON_TRANSLATION_NEEDS_UPDATE;
}
if ( $update ) {
$text = __( 'Update %s translation', 'sitepress' );
} else {
$text = __( 'Edit the %s translation', 'sitepress' );
}
$text = sprintf( $text, $this->active_langs[ $lang_code ]['display_name'] );
$link = 'post.php?' . http_build_query (
array( 'lang' => $lang_code,
'action' => 'edit',
'post_type' => $post_type,
'post' => $post_id
)
);
return array( $text, $link, $css_class );
}
/**
* Generates the data for displaying a link element pointing towards a translation, that the current user can
* create.
*
* @param int $trid
* @param int $original_id
* @param string $lang_code
* @param string $source_language
*
* @return array
*/
private function generate_add_data( $trid, $lang_code, $source_language, $original_id ) {
$link = 'post-new.php?' . http_build_query (
array(
'lang' => $lang_code,
'post_type' => get_post_type ( $original_id ),
'trid' => $trid,
'source_lang' => $source_language
)
);
return array(
sprintf( __( 'Add translation to %s', 'sitepress' ), $this->active_langs[ $lang_code ]['display_name'] ),
$link,
self::ICON_TRANSLATION_ADD,
);
}
private function generate_retry_data( ) {
return array(
null,
null,
self::ICON_TRANSLATION_IN_PROGRESS,
);
}
}

View File

@@ -0,0 +1,990 @@
<?php
use WPML\API\Sanitize;
use WPML\Setup\Option;
use WPML\TM\API\Basket;
use WPML\TM\ATE\ClonedSites\Lock as AteApiLock;
use WPML\TM\Menu\TranslationBasket\Utility;
use WPML\TM\Menu\TranslationServices\Section;
use function WPML\Container\make;
class WPML_TM_Menus_Management extends WPML_TM_Menus {
const SKIP_TM_WIZARD_META_KEY = 'wpml_skip_tm_wizard';
/** @var IWPML_Template_Service $template_service */
private $template_service;
/** @var WPML_Translation_Manager_Records $manager_records */
private $manager_records;
/** @var WPML_Translator_Records $translator_records */
private $translator_records;
private $active_languages;
private $translatable_types;
private $current_language;
private $filter_post_status;
private $filter_translation_type;
private $post_statuses;
private $selected_languages;
private $source_language;
/** @var \WPML_TM_Translation_Priorities */
private $translation_priorities;
private $dashboard_title_sort_link;
private $dashboard_date_sort_link;
private $documents;
private $selected_posts = array();
private $translation_filter;
private $found_documents;
/**
* @var \Mockery\MockInterface
*/
private $admin_sections;
public function __construct(
IWPML_Template_Service $template_service,
WPML_Translation_Manager_Records $manager_records,
WPML_Translator_Records $translator_records
) {
$this->template_service = $template_service;
$this->manager_records = $manager_records;
$this->translator_records = $translator_records;
$wpml_wp_api = new WPML_WP_API();
$this->admin_sections = WPML\Container\make( 'WPML_TM_Admin_Sections' );
$this->admin_sections->init_hooks();
parent::__construct();
}
protected function render_main() {
if ( ! AteApiLock::isLocked() ) {
?>
<div class="wrap">
<h1><?php echo esc_html__( 'Translation Management', 'wpml-translation-management' ); ?></h1>
<?php
do_action( 'icl_tm_messages' );
$this->build_tab_items();
$this->render_items();
?>
</div>
<?php
}
}
/**
* It builds all the sections.
*/
protected function build_tab_items() {
$this->tab_items = array();
$this->build_dashboard_item();
$this->build_basket_item();
/** @var \WPML_TM_Admin_Sections $admin_sections */
foreach ( $this->admin_sections->get_tab_items() as $slug => $tab_item ) {
$this->tab_items[ $slug ] = $tab_item;
}
$this->build_translation_jobs_item();
$this->build_tp_com_log_item();
$this->reorder_items();
}
/**
* It reorders all items based on their `order` key as well as the order (index) they were added.
*/
private function reorder_items() {
$order_of_sections = array();
$tab_items = $this->tab_items;
foreach ( $tab_items as $key => $value ) {
$order_of_sections[ $key ] = (int) $value['order'];
}
if ( array_multisort( $order_of_sections, SORT_ASC, $tab_items ) ) {
$this->tab_items = $tab_items;
}
}
private function build_dashboard_item() {
$this->tab_items['dashboard'] = array(
'caption' => __( 'Dashboard', 'wpml-translation-management' ),
'current_user_can' => array( WPML_Manage_Translations_Role::CAPABILITY, 'manage_options' ),
'callback' => array( $this, 'build_content_dashboard' ),
'order' => 100,
);
}
public function build_content_dashboard() {
/** @var SitePress $sitepress */
global $sitepress;
$this->active_languages = $sitepress->get_active_languages();
$this->translatable_types = apply_filters( 'wpml_tm_dashboard_translatable_types', $sitepress->get_translatable_documents() );
$this->build_dashboard_data();
if ( $this->found_documents > $this->documents || $this->there_are_hidden_posts() ) {
$this->display_hidden_posts_message();
}
$this->build_content_dashboard_remote_translations_controls();
$this->build_content_dashboard_filter();
$this->build_content_dashboard_results();
}
/**
* Used only by unit tests at the moment
*/
private function build_dashboard_data() {
$this->build_dashboard_filter_arguments();
$this->build_dashboard_documents();
}
private function build_dashboard_filter_arguments() {
global $sitepress, $iclTranslationManagement;
$this->current_language = $sitepress->get_current_language();
$this->source_language = TranslationProxy_Basket::get_source_language();
if ( isset( $_COOKIE['wp-translation_dashboard_filter'] ) ) {
parse_str( Sanitize::stringProp('wp-translation_dashboard_filter', $_COOKIE), $this->translation_filter );
}
if ( $this->source_language || ! isset( $this->translation_filter['from_lang'] ) ) {
if ( $this->source_language ) {
$this->translation_filter['from_lang'] = $this->source_language;
} else {
$this->translation_filter['from_lang'] = $this->current_language;
if ( $lang = Sanitize::stringProp( 'lang', $_GET ) ) {
$this->translation_filter['from_lang'] = $lang;
}
}
}
if ( ! isset( $this->translation_filter['to_lang'] ) ) {
$this->translation_filter['to_lang'] = '';
if ( $lang = Sanitize::stringProp( 'to_lang', $_GET ) ) {
$this->translation_filter['to_lang'] = $lang;
}
}
if ( $this->translation_filter['to_lang'] == $this->translation_filter['from_lang'] ) {
$this->translation_filter['to_lang'] = false;
}
if ( ! isset( $this->translation_filter['tstatus'] ) ) {
$this->translation_filter['tstatus'] = isset( $_GET['tstatus'] ) ? $_GET['tstatus'] : -1; // -1 == All documents
}
if ( ! isset( $this->translation_filter['sort_by'] ) || ! $this->translation_filter['sort_by'] ) {
$this->translation_filter['sort_by'] = 'date';
}
if ( ! isset( $this->translation_filter['sort_order'] ) || ! $this->translation_filter['sort_order'] ) {
$this->translation_filter['sort_order'] = 'DESC';
}
if ( ! isset( $this->translation_filter['type'] ) ) {
$this->translation_filter['type'] = ''; // All Types.
}
$sort_order_next = $this->translation_filter['sort_order'] == 'ASC' ? 'DESC' : 'ASC';
$this->dashboard_title_sort_link = 'admin.php?page=' . WPML_TM_FOLDER . $this->get_page_slug() . '&sm=dashboard&icl_tm_action=sort&sort_by=title&sort_order=' . $sort_order_next;
$this->dashboard_date_sort_link = 'admin.php?page=' . WPML_TM_FOLDER . $this->get_page_slug() . '&sm=dashboard&icl_tm_action=sort&sort_by=date&sort_order=' . $sort_order_next;
$this->post_statuses = array(
'publish' => __( 'Published', 'wpml-translation-management' ),
'draft' => __( 'Draft', 'wpml-translation-management' ),
'pending' => __( 'Pending Review', 'wpml-translation-management' ),
'future' => __( 'Scheduled', 'wpml-translation-management' ),
'private' => __( 'Private', 'wpml-translation-management' ),
);
$this->post_statuses = apply_filters( 'wpml_tm_dashboard_post_statuses', $this->post_statuses );
$this->translation_priorities = new WPML_TM_Translation_Priorities();
// Get the document types that we can translate
/**
* attachments are excluded
*
* @since 2.6.0
*/
add_filter( 'wpml_tm_dashboard_translatable_types', array( $this, 'exclude_attachments' ) );
$this->post_types = $sitepress->get_translatable_documents();
$this->post_types = apply_filters( 'wpml_tm_dashboard_translatable_types', $this->post_types );
$this->build_external_types();
$this->selected_languages = array();
if ( ! empty( $iclTranslationManagement->dashboard_select ) ) {
$this->selected_posts = $iclTranslationManagement->dashboard_select['post'];
$this->selected_languages = $iclTranslationManagement->dashboard_select['translate_to'];
}
if ( isset( $this->translation_filter['icl_selected_posts'] ) ) {
parse_str( $this->translation_filter['icl_selected_posts'], $this->selected_posts );
}
$this->filter_post_status = isset( $this->translation_filter['status'] ) ? $this->translation_filter['status'] : false;
if ( isset( $_GET['type'] ) ) {
$this->translation_filter['type'] = $_GET['type'];
}
$paged = (int) filter_input( INPUT_GET, 'paged', FILTER_SANITIZE_NUMBER_INT );
$this->translation_filter['page'] = $paged ? $paged - 1 : 0;
$this->filter_translation_type = isset( $this->translation_filter['type'] ) ? $this->translation_filter['type'] : false;
}
private function build_dashboard_documents() {
global $wpdb, $sitepress;
$wpml_tm_dashboard_pagination = new WPML_TM_Dashboard_Pagination();
$wpml_tm_dashboard_pagination->add_hooks();
$tm_dashboard = new WPML_TM_Dashboard( $wpdb, $sitepress );
$this->translation_filter['limit_no'] = $this->dashboard_pagination ? $this->dashboard_pagination->get_items_per_page() : 20;
$dashboard_data = $tm_dashboard->get_documents( $this->translation_filter );
$this->documents = $dashboard_data['documents'];
$this->found_documents = $dashboard_data['found_documents'];
}
/**
* @return bool
*/
private function there_are_hidden_posts() {
return -1 === $this->found_documents;
}
private function display_hidden_posts_message() {
?>
<div class="notice notice-warning otgs-notice-icon inline">
<p>
<?php
echo sprintf(
esc_html__( 'To see more items, use the filter and narrow down the search. %s', 'wpml-translation-management' ),
'<a href="https://wpml.org/documentation/translating-your-contents/?utm_source=plugin&utm_medium=gui&utm_campaign=wpmltm" target="_blank">' . esc_html__( 'Help', 'wpml-translation-management' ) . '</a>'
)
?>
</p>
</div>
<?php
}
private function build_content_dashboard_remote_translations_controls() {
// shows only when translation polling is on and there are translations in progress
$this->build_content_dashboard_fetch_translations_box();
$active_service = icl_do_not_promote() ? false : TranslationProxy::get_current_service();
$service_dashboard_info = TranslationProxy::get_service_dashboard_info();
if ( $active_service && $service_dashboard_info ) {
?>
<div class="icl_cyan_box">
<h3>
<?php
echo $active_service->name . ' ' . __(
'account status',
'wpml-translation-management'
)
?>
</h3>
<?php echo $service_dashboard_info; ?>
</div>
<?php
}
}
private function build_content_dashboard_results() {
?>
<form method="post" id="icl_tm_dashboard_form">
<?php
// #############################################
// Display the items for translation in a table.
// #############################################
$this->build_content_dashboard_documents();
$this->heading( __( '2. Select translation options', 'wpml-translation-management' ) );
$this->build_content_dashboard_documents_options();
do_action( 'wpml_tm_dashboard_promo' );
?>
</form>
<?php
}
private function build_content_dashboard_documents() {
?>
<input type="hidden" name="icl_tm_action" value="add_jobs"/>
<input type="hidden" name="translate_from" value="<?php echo esc_attr( $this->translation_filter['from_lang'] ); ?>"/>
<table class="widefat fixed striped" id="icl-tm-translation-dashboard">
<thead>
<?php $this->build_content_dashboard_documents_head_footer_cells(); ?>
</thead>
<tfoot>
<?php $this->build_content_dashboard_documents_head_footer_cells(); ?>
</tfoot>
<tbody>
<?php
$this->build_content_dashboard_documents_body();
?>
</tbody>
</table>
<div class="tablenav clearfix">
<div class="alignleft">
<strong><?php echo esc_html__( 'Word count estimate:', 'wpml-translation-management' ); ?></strong>
<?php printf( esc_html__( '%s words', 'wpml-translation-management' ), '<span id="icl-tm-estimated-words-count">0</span>' ); ?>
<span id="icl-tm-doc-wrap" style="display: none">
<?php printf( esc_html__( 'in %s document(s)', 'wpml-translation-management' ), '<span id="icl-tm-sel-doc-count">0</span>' ); ?>
</span>
<?php do_action( 'wpml_tm_dashboard_word_count_estimation' ); ?>
</div>
<?php
if ( $this->dashboard_pagination ) {
do_action( 'wpml_tm_dashboard_pagination', $this->dashboard_pagination->get_items_per_page(), $this->found_documents );
}
?>
</div>
<?php
do_action( 'wpml_tm_after_translation_dashboard_documents' );
}
private function get_translate_tooltip_attributes() {
$translate_radio_message = $this->get_translate_tooltip_text();
if ( $translate_radio_message ) {
return ' class="js-otgs-popover-tooltip" data-tippy-zIndex="999999" title="' . esc_attr( $translate_radio_message ) . '"';
}
return null;
}
private function get_translate_tooltip_text() {
if (
! Option::shouldTranslateEverything()
&& ! wpml_tm_load_blog_translators()->has_translators()
) {
if ( ! wpml_translation_management()->has_active_service() ) {
/* translators: This text will be used to build a link to the translation roles page */
$translators_link = $this->get_translation_roles_link( __( 'at least one translator', 'wpml-translation-management' ) );
/* translators: This text will be used to build a link to the translation services page */
$translation_services_link = $this->get_translation_services_link( __( 'active and authenticated translation service', 'wpml-translation-management' ) );
/* translators: %1$s contains a link to the translation roles page with "at least one translator" as a text whilst %2$s is a link to the translation services page with "active and authenticated translation service" as a text */
$tooltip_text = __( 'To send content to translation first make sure you either have %1$s or an %2$s.', 'wpml-translation-management' );
return sprintf( $tooltip_text, $translators_link, $translation_services_link );
}
if ( wpml_translation_management()->service_activation_incomplete() ) {
/* translators: %s is replaced with the name of the active translation service */
$tooltip_text = __( 'To send content to translation first make sure "%s" is authenticated or you have at least one translator.', 'wpml-translation-management' );
$translation_services_link = $this->get_translation_services_link( TranslationProxy::get_current_service_name() );
return sprintf( $tooltip_text, $translation_services_link );
}
}
return null;
}
private function build_content_dashboard_documents_options() {
global $wpdb;
$translate_checked = 'checked="checked"';
$duplicate_checked = '';
$do_nothing_checked = '';
$flag_factory = new WPML_Flags_Factory( $wpdb );
$flags = $flag_factory->create();
$translate_radio_text = __( 'Translate', 'wpml-translation-management' );
$translate_tooltip_attributes = $this->get_translate_tooltip_attributes();
if ( $translate_tooltip_attributes ) {
$translate_checked = 'disabled="disabled"';
$do_nothing_checked = 'checked="checked"';
}
$hasMoreThan1SecondaryLanguage = count( $this->active_languages ) > 2;
?>
<div class="tm-dashboard-translation-options">
<table id="icl_tm_languages" class="widefat">
<?php if ( $hasMoreThan1SecondaryLanguage ) { ?>
<thead>
<tr>
<th><?php echo esc_html__( 'All Languages', 'wpml-translation-management' ); ?></th>
<td>
<label <?php echo $translate_tooltip_attributes; ?>>
<input type="radio" id="translate-all" value="1" name="radio-action-all" <?php echo $translate_checked; ?> /> <?php echo esc_html( $translate_radio_text ); ?>
</label>
</td>
<td>
<label>
<input type="radio" id="duplicate-all" value="2" name="radio-action-all" <?php echo $duplicate_checked; ?> />
<?php
echo esc_html__(
'Duplicate content',
'wpml-translation-management'
)
?>
</label>
</td>
<td>
<label>
<input type="radio" id="update-none" value="0" name="radio-action-all" <?php echo $do_nothing_checked; ?> /> <?php echo esc_html__( 'Do nothing', 'wpml-translation-management' ); ?>
</label>
</td>
</tr>
<tr class="blank_row">
<td colspan="3" style="height:6px!important;"></td>
</tr>
</thead>
<?php } ?>
<tbody>
<?php foreach ( $this->active_languages as $lang ) : ?>
<?php
if ( $lang['code'] == $this->translation_filter['from_lang'] ) {
continue;
}
$radio_prefix_html = '<input type="radio" name="tr_action[' . esc_attr( $lang['code'] ) . ']" ';
?>
<tr>
<th>
<?php echo $flags->get_flag_image( $lang['code'] ) ?>
<strong><?php echo esc_html( $lang['display_name'] ); ?></strong>
</th>
<td>
<label <?php echo $translate_tooltip_attributes; ?>>
<?php echo $radio_prefix_html; ?> value="1" <?php echo $translate_checked; ?>/>
<?php echo esc_html( $translate_radio_text ); ?>
</label>
</td>
<td>
<label>
<?php echo $radio_prefix_html; ?> value="2" <?php echo $duplicate_checked; ?>/>
<?php echo esc_html__( 'Duplicate content', 'wpml-translation-management' ); ?>
</label>
</td>
<td>
<label>
<?php echo $radio_prefix_html; ?> value="0" <?php echo $do_nothing_checked; ?>/>
<?php echo esc_html__( 'Do nothing', 'wpml-translation-management' ); ?>
</label>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<input name="iclnonce" type="hidden" value="<?php echo wp_create_nonce( 'pro-translation-icl' ); ?>"/>
<?php
$tm_jobs_submit_disabled = disabled( empty( $this->selected_languages ) && empty( $this->selected_posts ), true, false );
$shouldUseBasket = Basket::shouldUse();
$tm_jobs_submit_caption = $shouldUseBasket
? __( 'Add selected content to translation basket', 'wpml-translation-management' )
: __( 'Translate selected content', 'wpml-translation-management' );
?>
<span class="wpml-display-block text-center wpml-margin-top-lg">
<button
id="icl_tm_jobs_submit"
class="button-primary button-lg wpml-tm-button-basket <?php echo $shouldUseBasket ? 'otgs-ico-basket' : ''; ?>"
data-use-basket="<?php echo $shouldUseBasket ? 1 : 0; ?>"
type="submit" <?php echo $tm_jobs_submit_disabled; ?>><?php echo $tm_jobs_submit_caption; ?>
</button>
</span>
<div id="icl_dup_ovr_warn" class="wpml-margin-top-base" style="display:none;">
<?php
$dup_message = '<p>';
$dup_message .= __( 'Any existing content (translations) will be overwritten when creating duplicates.', 'wpml-translation-management' );
$dup_message .= '</p>';
$dup_message .= '<p>';
$dup_message .= __( "When duplicating content, please first duplicate parent pages to maintain the site's hierarchy.", 'wpml-translation-management' );
$dup_message .= '</p>';
ICL_AdminNotifier::display_instant_message( $dup_message, 'error' );
?>
</div>
<div style="width: 45%; margin: auto; position: relative; top: -30px;">
<?php
ICL_AdminNotifier::display_messages( 'translation-dashboard-under-translation-options' );
ICL_AdminNotifier::remove_message( 'items_added_to_basket' );
?>
</div>
</div>
<?php
wp_enqueue_script( 'wpml-tooltip' );
wp_enqueue_style( 'wpml-tooltip' );
}
private function build_content_dashboard_documents_head_footer_cells() {
global $sitepress;
?>
<tr>
<td scope="col" class="manage-column column-cb check-column">
<?php
$check_all_checked = checked( true, isset( $_GET['post_id'] ), false );
?>
<input type="checkbox" <?php echo $check_all_checked; ?>/>
</td>
<th scope="col" class="manage-column column-title">
<?php
$dashboard_title_sort_caption = __( 'Title', 'wpml-translation-management' );
$this->build_content_dashboard_documents_sorting_link( $this->dashboard_title_sort_link, $dashboard_title_sort_caption, 'p.post_title' );
?>
</th>
<th scope="col" class="manage-column wpml-column-type">
<?php echo esc_html__( 'Type', 'wpml-translation-management' ); ?>
</th>
<?php
$active_languages = $sitepress->get_active_languages();
$lang_count = count( $active_languages );
$lang_col_width = ( $lang_count - 1 ) * 26 . 'px';
if ( $lang_count > 10 ) {
$lang_col_width = '30%';
}
?>
<th scope="col" class="manage-column column-active-languages wpml-col-languages" style="width: <?php echo esc_attr( $lang_col_width ); ?>">
<?php
if ( $this->translation_filter['to_lang'] && array_key_exists( $this->translation_filter['to_lang'], $active_languages ) ) {
$lang = $active_languages[ $this->translation_filter['to_lang'] ];
?>
<span title="<?php echo esc_attr( $lang['display_name'] ); ?>">
<?php echo $sitepress->get_flag_image( $lang['code'], [ 16, 12 ], $this->translation_filter['to_lang'] ) ?>
</span>
<?php
} else {
foreach ( $active_languages as $lang ) {
if ( $lang['code'] === $this->translation_filter['from_lang'] ) {
continue;
}
?>
<span title="<?php echo esc_attr( $lang['display_name'] ); ?>">
<?php echo $sitepress->get_flag_image( $lang['code'], [ 16, 12 ], $lang['code'] ) ?>
</span>
<?php
}
}
?>
</th>
<th scope="col" class="manage-column column-date">
<?php
$dashboard_date_sort_label = __( 'Date', 'wpml-translation-management' );
$this->build_content_dashboard_documents_sorting_link( $this->dashboard_date_sort_link, $dashboard_date_sort_label, 'p.post_date' );
?>
</th>
<th scope="col" class="manage-column column-actions">
<?php echo esc_html__( 'Actions', 'wpml-translation-management' ); ?>
</th>
</tr>
<?php
}
private function build_content_dashboard_documents_body() {
global $sitepress;
if ( ! $this->documents ) {
?>
<tr>
<td scope="col" colspan="6" align="center">
<span class="no-documents-found"><?php echo esc_html__( 'No documents found', 'wpml-translation-management' ); ?></span>
</td>
</tr>
<?php
} else {
$records_factory = new WPML_TM_Word_Count_Records_Factory();
$single_process_factory = new WPML_TM_Word_Count_Single_Process_Factory();
$translatable_element_provider = new WPML_TM_Translatable_Element_Provider(
$records_factory->create(),
$single_process_factory->create(),
class_exists( 'WPML_ST_Package_Factory' ) ? new WPML_ST_Package_Factory() : null
);
wp_nonce_field( 'save_translator_note_nonce', '_icl_nonce_stn_' );
$active_languages = $this->translation_filter['to_lang']
? array( $this->translation_filter['to_lang'] => $this->active_languages[ $this->translation_filter['to_lang'] ] )
: $this->active_languages;
foreach ( $this->documents as $doc ) {
$selected = is_array( $this->selected_posts ) && in_array( $doc->ID, $this->selected_posts );
$doc_row = new WPML_TM_Dashboard_Document_Row(
$doc,
$this->post_types,
$this->post_statuses,
$active_languages,
$selected,
$sitepress,
$translatable_element_provider
);
$doc_row->display();
}
}
}
/**
* @return bool
*/
private function current_user_can_manage_translations() {
return current_user_can( WPML_Manage_Translations_Role::CAPABILITY );
}
private function build_content_dashboard_documents_sorting_link( $url, $label, $filter_argument ) {
$caption = $label;
if ( $this->translation_filter['sort_by'] === $filter_argument ) {
$caption .= '&nbsp;';
$caption .= $this->translation_filter['sort_order'] === 'ASC' ? '&uarr;' : '&darr;';
}
?>
<a href="<?php echo esc_url( $url ); ?>">
<?php echo $caption; ?>
</a>
<?php
}
private function build_basket_item() {
$basket_items_count = TranslationProxy_Basket::get_basket_items_count( true );
if ( $basket_items_count > 0 ) {
$this->tab_items['basket'] = array(
'caption' => $this->build_basket_item_caption( $basket_items_count ),
'current_user_can' => WPML_Manage_Translations_Role::CAPABILITY,
'callback' => array( $this, 'build_content_basket' ),
'order' => 101,
);
}
}
/**
* @param int $basket_items_count
*
* @return string
*/
private function build_basket_item_caption( $basket_items_count = 0 ) {
if ( isset( $_GET['clear_basket'] ) && $_GET['clear_basket'] ) {
$basket_items_count = 0;
} else {
if ( ! is_numeric( $basket_items_count ) ) {
$basket_items_count = TranslationProxy_Basket::get_basket_items_count( true );
}
if ( isset( $_GET['action'], $_GET['id'] ) && $_GET['action'] === 'delete' && $_GET['id'] ) {
-- $basket_items_count;
}
}
$basket_items_count_caption = esc_html__( 'Translation Basket', 'wpml-translation-management' );
if ( $basket_items_count > 0 ) {
$basket_item_count_badge = '<span id="wpml-basket-items"><span id="basket-item-count">' . $basket_items_count . '</span></span>';
$basket_items_count_caption .= $basket_item_count_badge;
}
return $basket_items_count_caption;
}
public function build_content_basket() {
$basket_table = new SitePress_Table_Basket();
do_action( 'wpml_tm_before_basket_items_display' );
$basket_table->prepare_items();
$action_url = esc_attr( 'admin.php?page=' . WPML_TM_FOLDER . $this->get_page_slug() . '&sm=' . $_GET['sm'] );
$this->heading( __( '1. Review documents for translation', 'wpml-translation-management' ) );
?>
<form method="post" id="translation-jobs-basket-form" class="js-translation-jobs-basket-form"
data-message="
<?php
echo esc_attr__(
'You are about to delete selected items from the basket. Are you sure you want to do that?',
'wpml-translation-management'
)
?>
"
name="translation-jobs-basket" action="<?php echo $action_url; ?>">
<?php
$basket_table->display();
?>
</form>
<?php
$this->build_translation_options();
}
private function build_translation_options() {
global $sitepress, $wpdb;
$basket_items_number = TranslationProxy_Basket::get_basket_items_count( true );
if ( $basket_items_number > 0 ) {
$deadline_estimate_factory = new WPML_TM_Jobs_Deadline_Estimate_Factory();
$deadline_estimate_date = $deadline_estimate_factory->create()->get(
TranslationProxy_Basket::get_basket(),
array(
'translator_id' => TranslationProxy_Service::get_wpml_translator_id(),
'service' => TranslationProxy::get_current_service_id(),
)
);
$basket_name_max_length = TranslationProxy::get_current_service_batch_name_max_length();
$source_language = TranslationProxy_Basket::get_source_language();
$basket = new WPML_Translation_Basket( $wpdb );
$basket_name_placeholder = sprintf(
__( '%1$s|WPML|%2$s', 'wpml-translation-management' ),
htmlspecialchars_decode( get_option( 'blogname' ), ENT_QUOTES ),
$source_language
);
$basket_name_placeholder = $basket->get_unique_basket_name( $basket_name_placeholder, $basket_name_max_length );
$utility = make( Utility::class );
$target_languages = $utility->getTargetLanguages();
$isTheOnlyAvailableTranslator = $utility->isTheOnlyAvailableTranslatorForTargetLanguages( $target_languages );
$translators_dropdowns = wpml_collect( $target_languages )->pluck( 'code', 'code' )
->map( [ $this, 'get_translators_dropdown' ] );
$tooltip_content = esc_html__( 'This deadline is what WPML suggests according to the amount of work that you already sent to this translator. You can modify this date to set the deadline manually.', 'wpml-translation-management' );
$translation_service_enabled = $this->is_translation_service_enabled();
$model = array(
'strings' => array(
'heading_basket_name' => __( '2. Set a batch name and deadline', 'wpml-translation-management' ),
'heading_translators' => __( '3. Choose translator or Translation Service', 'wpml-translation-management' ),
'batch_name_label' => __( 'Batch name:', 'wpml-translation-management' ),
'batch_name_desc' => __( 'Give a name to the batch. If omitted, the default name will be applied.', 'wpml-translation-management' ),
'column_language' => __( 'Language pair', 'wpml-translation-management' ),
'column_translator' => __( 'Translator', 'wpml-translation-management' ),
'pro_translation_tip' => __( 'Did you know that you can also set Translation Services and professional translators will handle your translation?', 'wpml-translation-management' ),
'batch_deadline_label' => __( 'Suggested deadline:', 'wpml-translation-management' ),
'batch_deadline_tooltip' => $tooltip_content,
'button_send_all' => __( 'Send all items for translation', 'wpml-translation-management' ),
),
'source_language' => $sitepress->get_language_details( $source_language ),
'source_language_flag' => $sitepress->get_flag_img( $source_language ),
'basket_name_max_length' => $basket_name_max_length,
'basket_name_placeholder' => $basket_name_placeholder,
'target_languages' => $target_languages,
'dropdowns_translators' => $translators_dropdowns,
'pro_translation_link' => '<br /><a href="' . admin_url( 'admin.php?page=' . WPML_TM_FOLDER . $this->get_page_slug() . '&sm=translators' ) . '">'
. __( 'Check available Translation Services', 'wpml-translation-management' ) . '</a>',
'deadline_estimation_date' => $deadline_estimate_date,
'extra_basket_fields' => TranslationProxy_Basket::get_basket_extra_fields_section(),
'nonces' => array(
'_icl_nonce_send_basket_items' => wp_create_nonce( 'send_basket_items_nonce' ),
'_icl_nonce_send_basket_item' => wp_create_nonce( 'send_basket_item_nonce' ),
'_icl_nonce_send_basket_commit' => wp_create_nonce( 'send_basket_commit_nonce' ),
'_icl_nonce_check_basket_name' => wp_create_nonce( 'check_basket_name_nonce' ),
'_icl_nonce_refresh_deadline' => wp_create_nonce( 'wpml-tm-jobs-deadline-estimate-ajax-action' ),
'_icl_nonce_rollback_basket' => wp_create_nonce( 'rollback_basket_nonce' ),
),
'translation_service_enabled' => $translation_service_enabled,
'current_user_only_translator' => $isTheOnlyAvailableTranslator,
);
echo $this->template_service->show( $model, 'basket/options.twig' );
}
do_action( 'wpml_translation_basket_page_after' );
}
public function get_translators_dropdown( $lang_code ) {
$selected_translator = TranslationProxy_Service::get_wpml_translator_id();
$args = array(
'from' => TranslationProxy_Basket::get_source_language(),
'to' => $lang_code,
'name' => 'translator[' . $lang_code . ']',
'selected' => $selected_translator,
'services' => array( 'local', TranslationProxy::get_current_service_id() ),
'echo' => false,
);
return wpml_tm_get_translators_dropdown()->render( $args );
}
private function build_translation_jobs_item() {
$jobs_repository = wpml_tm_get_jobs_repository();
$jobs_count = $jobs_repository->get_count( new WPML_TM_Jobs_Search_Params() );
if ( $jobs_count ) {
$this->tab_items['jobs'] = array(
'caption' => __( 'Jobs', 'wpml-translation-management' ),
'current_user_can' => WPML_Manage_Translations_Role::CAPABILITY,
'callback' => array( $this, 'build_content_translation_jobs' ),
'order' => 100000,
'visible' => ! Option::shouldTranslateEverything(),
);
}
}
public function build_content_translation_jobs() {
echo "<div id='wpml-remote-jobs-container'></div>";
}
private function build_tp_com_log_item() {
if ( isset( $_GET['sm'] ) && 'com-log' === $_GET['sm'] ) {
$this->tab_items['com-log'] = array(
'caption' => __( 'Communication Log', 'wpml-translation-management' ),
'current_user_can' => 'manage_options',
'callback' => array( $this, 'build_tp_com_log' ),
'order' => 1000000,
);
}
}
public function build_tp_com_log() {
if ( isset( $_POST['tp-com-clear-log'] ) ) {
WPML_TranslationProxy_Com_Log::clear_log();
}
if ( isset( $_POST['tp-com-disable-log'] ) ) {
WPML_TranslationProxy_Com_Log::set_logging_state( false );
}
if ( isset( $_POST['tp-com-enable-log'] ) ) {
WPML_TranslationProxy_Com_Log::set_logging_state( true );
}
$action_url = esc_attr( 'admin.php?page=' . WPML_TM_FOLDER . $this->get_page_slug() . '&sm=' . $_GET['sm'] );
$com_log = WPML_TranslationProxy_Com_Log::get_log();
?>
<form method="post" id="tp-com-log-form" name="tp-com-log-form" action="<?php echo $action_url; ?>">
<?php if ( WPML_TranslationProxy_Com_Log::is_logging_enabled() ) : ?>
<?php echo esc_html__( "This is a log of the communication between your site and the translation system. It doesn't include any private information and allows WPML support to help with problems related to sending content to translation.", 'wpml-translation-management' ); ?>
<br />
<br />
<?php if ( $com_log != '' ) : ?>
<textarea wrap="off" readonly="readonly" rows="16" style="font-size:10px; width:100%"><?php echo $com_log; ?></textarea>
<br />
<br />
<input class="button-secondary" type="submit" name="tp-com-clear-log" value="<?php echo esc_attr__( 'Clear log', 'wpml-translation-management' ); ?>">
<?php else : ?>
<strong><?php echo esc_html__( 'The communication log is empty.', 'wpml-translation-management' ); ?></strong>
<br />
<br />
<?php endif; ?>
<input class="button-secondary" type="submit" name="tp-com-disable-log" value="<?php echo esc_attr__( 'Disable logging', 'wpml-translation-management' ); ?>">
<?php else : ?>
<?php echo esc_html__( 'Communication logging is currently disabled. To allow WPML support to help you with issues related to sending content to translation, you need to enable the communication logging.', 'wpml-translation-management' ); ?>
<br />
<br />
<input class="button-secondary" type="submit" name="tp-com-enable-log" value="<?php echo esc_attr__( 'Enable logging', 'wpml-translation-management' ); ?>">
<?php endif; ?>
</form>
<?php
}
public function get_dashboard_documents() {
return $this->documents;
}
public function build_content_dashboard_filter() {
global $wpdb;
$dashboard_filter = new WPML_TM_Dashboard_Display_Filter(
$this->active_languages,
$this->source_language,
$this->translation_filter,
$this->post_types,
$this->post_statuses,
$this->translation_priorities->get_values(),
$wpdb
);
$dashboard_filter->display();
}
private function build_external_types() {
$this->post_types = apply_filters( 'wpml_get_translatable_types', $this->post_types );
foreach ( $this->post_types as $id => $type_info ) {
if ( isset( $type_info->prefix ) ) {
// this is an external type returned by wpml_get_translatable_types
$new_type = new stdClass();
$new_type->labels = new stdClass();
$new_type->labels->singular_name = isset( $type_info->labels->singular_name ) ? $type_info->labels->singular_name : $type_info->label;
$new_type->labels->name = isset( $type_info->labels->name ) ? $type_info->labels->name : $type_info->label;
$new_type->prefix = $type_info->prefix;
$new_type->external_type = 1;
$this->post_types[ $id ] = $new_type;
}
}
}
/**
* @param array $post_types
*
* @since 2.6.0
*
* @return array
*/
public function exclude_attachments( $post_types ) {
unset( $post_types['attachment'] );
return $post_types;
}
protected function get_page_slug() {
return WPML_Translation_Management::PAGE_SLUG_MANAGEMENT;
}
protected function get_default_tab() {
return 'dashboard';
}
/**
* @return bool|\TranslationProxy_Service|\WP_Error
*/
private function is_translation_service_enabled() {
$translation_service_enabled = TranslationProxy::get_current_service();
if ( is_wp_error( $translation_service_enabled ) ) {
$translation_service_enabled = false;
}
return $translation_service_enabled;
}
/**
* @return string
*/
private function get_translation_roles_link( $text ) {
return $this->get_tm_menu_link( WPML_TM_Translation_Roles_Section::SLUG, $text );
}
/**
* @return string
*/
private function get_translation_services_link( $text ) {
return $this->get_tm_menu_link( Section::SLUG, $text );
}
private function get_tm_menu_link( $section, $text ) {
$admin_url = admin_url( 'admin.php' );
$args = array(
'page' => urlencode( WPML_TM_FOLDER . WPML_Translation_Management::PAGE_SLUG_MANAGEMENT ),
'sm' => urlencode( $section ),
);
$menu_link_url = add_query_arg( $args, $admin_url );
return '<a href="' . esc_url( $menu_link_url ) . '">' . esc_html( $text ) . '</a>';
}
}

View File

@@ -0,0 +1,729 @@
<?php
use WPML\API\Settings;
use WPML\DocPage;
use WPML\TM\Menu\TranslationMethod\TranslationMethodSettings;
class WPML_TM_Menus_Settings extends WPML_TM_Menus {
/** @var WPML_Translate_Link_Targets_UI $translate_link_targets_ui */
private $translate_link_targets_ui;
/** @var bool $end_user_feature_enabled */
private $end_user_feature_enabled;
private $mcsetup_sections = array();
public function init() {
$this->init_navigation_links();
}
private function init_navigation_links() {
/**
* @var SitePress $sitepress
* @var TranslationManagement $iclTranslationManagement
*/
global $sitepress, $iclTranslationManagement;
$is_admin = current_user_can( 'manage_options' );
$this->mcsetup_sections['ml-content-setup-sec-1'] = esc_html__( 'Translation Editor', 'wpml-translation-management' );
if ( $is_admin ) {
$this->mcsetup_sections['ml-content-setup-sec-2'] = esc_html__( 'Posts and pages synchronization', 'wpml-translation-management' );
$this->mcsetup_sections['ml-content-setup-sec-3'] = esc_html__( 'Translated documents options', 'wpml-translation-management' );
$this->mcsetup_sections['ml-content-setup-sec-wp-login'] = esc_html__( 'Login and registration pages', 'wpml-translation-management' );
if ( defined( 'WPML_ST_VERSION' ) ) {
$this->mcsetup_sections['ml-content-setup-sec-4'] = esc_html__( 'Custom posts slug translation options', 'wpml-translation-management' );
}
if ( TranslationProxy::is_current_service_active_and_authenticated() ) {
$this->mcsetup_sections['ml-content-setup-sec-5'] = esc_html__( 'Translation pickup mode', 'wpml-translation-management' );
}
}
$this->mcsetup_sections['ml-content-setup-sec-5-1'] = esc_html__( 'XLIFF file options', 'wpml-translation-management' );
if ( $is_admin ) {
$this->mcsetup_sections['ml-content-setup-sec-cf'] = esc_html__( 'Custom Fields Translation', 'wpml-translation-management' );
$this->mcsetup_sections['ml-content-setup-sec-tcf'] = esc_html__( 'Custom Term Meta Translation', 'wpml-translation-management' );
$custom_posts = array();
$this->post_types = $sitepress->get_translatable_documents( true );
foreach ( $this->post_types as $k => $v ) {
$custom_posts[ $k ] = $v;
}
global $wp_taxonomies;
$custom_taxonomies = array_diff( array_keys( (array) $wp_taxonomies ), array(
'post_tag',
'category',
'nav_menu',
'link_category',
'post_format'
) );
if ( $custom_posts ) {
$this->mcsetup_sections['ml-content-setup-sec-7'] = esc_html__( 'Post Types Translation', 'wpml-translation-management' );
}
if ( $custom_taxonomies ) {
$this->mcsetup_sections['ml-content-setup-sec-8'] = esc_html__( 'Taxonomies Translation', 'wpml-translation-management' );
}
if ( ! empty( $iclTranslationManagement->admin_texts_to_translate ) && function_exists( 'icl_register_string' ) ) {
$this->mcsetup_sections['ml-content-setup-sec-9'] = esc_html__( 'Admin Strings to Translate', 'wpml-translation-management' );
}
}
$this->get_translate_link_targets_ui()->add_hooks();
$this->mcsetup_sections = apply_filters( 'wpml_mcsetup_navigation_links', $this->mcsetup_sections, $sitepress, $iclTranslationManagement );
}
protected function render_main() {
?>
<div class="wrap">
<h1><?php echo esc_html__( 'Settings', 'wpml-translation-management' ); ?></h1>
<?php
do_action( 'icl_tm_messages' );
$this->build_tab_items();
$this->render_items();
?>
</div>
<?php
}
protected function build_tab_items() {
$this->build_mcs_item();
$this->build_translation_notifications_item();
$this->tab_items = apply_filters( 'wpml_tm_tab_items', $this->tab_items );
}
private function build_mcs_item() {
global $sitepress;
$this->tab_items['mcsetup']['caption'] = esc_html__( 'Multilingual Content Setup', 'wpml-translation-management' );
$translate_link_targets = new WPML_Translate_Link_Target_Global_State( $sitepress );
if ( $translate_link_targets->is_rescan_required() ) {
$this->tab_items['mcsetup']['caption'] = '<i class="otgs-ico-warning"></i>' . esc_html( $this->tab_items['mcsetup']['caption'] );
}
$this->tab_items['mcsetup']['callback'] = array( $this, 'build_content_mcs' );
$this->tab_items['mcsetup']['current_user_can'] = array(
'manage_options',
WPML_Manage_Translations_Role::CAPABILITY
);
}
private function build_translation_notifications_item() {
$this->tab_items['notifications'] = array(
'caption' => esc_html__( 'Translation Notifications', 'wpml-translation-management' ),
'current_user_can' => WPML_Manage_Translations_Role::CAPABILITY,
'callback' => array( $this, 'build_content_translation_notifications' ),
);
}
public function build_content_mcs() {
/**
* included by menu translation-management.php
*
* @var TranslationManagement $iclTranslationManagement
*/
global $sitepress, $sitepress_settings, $iclTranslationManagement;
$translate_link_targets = new WPML_Translate_Link_Target_Global_State( $sitepress );
if ( $translate_link_targets->is_rescan_required() ) {
?>
<div class="update-nag">
<p>
<i class="otgs-ico-warning"></i>
<?php
echo esc_html__(
'There is new translated content on this site. You can scan posts and strings to adjust links to point to translated content.',
'wpml-translation-management'
);
?>
</p>
<p><?php echo $this->get_navigation_link( $this->get_translate_link_targets_ui()->get_id() ); ?></p>
</div>
<?php
}
$this->render_mcsetup_navigation_links();
if ( $this->should_show_mcsetup_section( 'ml-content-setup-sec-1' ) ) : ?>
<div class="wpml-section">
<div class="wpml-section-header">
<h3>
<?php echo esc_html__( 'Translation Mode', 'wpml-translation-management' ); ?>
</h3>
<a href="<?php echo DocPage::getTranslateAutomatically(); ?>" target="_blank" rel="noopener" class="wpml-external-link">
<?php esc_html_e( "How to translate your site's content", 'wpml-translation-management' ); ?>
</a>
</div>
<div class="wpml-section-content">
<?php TranslationMethodSettings::render(); ?>
</div>
</div>
<div class="wpml-section" id="ml-content-setup-sec-1">
<?php
$doc_translation_method = Settings::pathOr( ICL_TM_TMETHOD_MANUAL, [
'translation-management',
'doc_translation_method'
] );
$isClassicEditor = (string) ICL_TM_TMETHOD_EDITOR === (string) $doc_translation_method;
$isATEEditor = (string) ICL_TM_TMETHOD_ATE === (string) $doc_translation_method;
?>
<div class="wpml-section-header">
<h3>
<?php echo esc_html__( 'Translation Editor', 'wpml-translation-management' ); ?>
</h3>
<a href="<?php echo DocPage::editorOptions(); ?>" target="_blank" rel="noopener" class="wpml-external-link">
<?php esc_html_e( 'Learn more about translation editor options', 'wpml-translation-management' ) ?>
</a>
</div>
<div class="wpml-section-content">
<form id="icl_doc_translation_method" name="icl_doc_translation_method" action="">
<?php wp_nonce_field( 'icl_doc_translation_method_nonce', '_icl_nonce' ); ?>
<div class="wpml-section-content-inner">
<h4>
<?php
/* translators: Heading shown for selecting the editor to use with WPML's Translation Management when creating new content */
echo esc_html__( 'Editor for new translations', 'wpml-translation-management' );
?>
</h4>
<ul class="t_method">
<li>
<label>
<input type="radio" name="t_method" value="<?php echo ICL_TM_TMETHOD_ATE; ?>"
<?php
if ( $isATEEditor ) :
?>
checked="checked"<?php endif; ?> />
<?php
/* translators: Editor to use with WPML's Translation Management when creating new content */
echo esc_html__( 'Advanced Translation Editor (recommended)', 'wpml-translation-management' );
?>
</label>
<?php do_action( 'wpml_tm_mcs_' . ICL_TM_TMETHOD_ATE ); ?>
</li>
<li>
<label>
<input type="radio" name="t_method" value="<?php echo ICL_TM_TMETHOD_EDITOR; ?>"
<?php
if ( $isClassicEditor ) :
?>
checked="checked"<?php endif; ?> />
<?php
/* translators: Editor to use with WPML's Translation Management when creating new content */
echo esc_html__( "Classic Translation Editor", 'wpml-translation-management' );
?>
</label>
</li>
</ul>
</div>
<?php
$default_editor_for_old_jobs = get_option( WPML_TM_Old_Jobs_Editor::OPTION_NAME, null );
?>
<div class="wpml-section-content-inner">
<h4>
<?php
/* translators: heading shown for selecting the editor to use when updating content that was created with WPML's Classic Translation Editor */
esc_html_e( "Editor for translations previously created using Classic Translation Editor", 'wpml-translation-management' );
?>
</h4>
<ul class="<?php echo WPML_TM_Old_Jobs_Editor::OPTION_NAME; ?>">
<li>
<label>
<input
type="radio" name="<?php echo WPML_TM_Old_Jobs_Editor::OPTION_NAME; ?>"
value="<?php echo esc_attr( WPML_TM_Editors::WPML ); ?>"
<?php checked( $default_editor_for_old_jobs === WPML_TM_Editors::WPML ); ?> />
<?php
/* translators: Which editor to use when updating content that was created with WPML's Classic Translation Editor? */
esc_html_e( "Classic Translation Editor (recommended)", 'wpml-translation-management' );
?>
</label>
</li>
<li>
<label>
<input
type="radio" name="<?php echo WPML_TM_Old_Jobs_Editor::OPTION_NAME; ?>"
value="<?php echo esc_attr( WPML_TM_Editors::ATE ); ?>"
<?php checked( $default_editor_for_old_jobs === WPML_TM_Editors::ATE ); ?> />
<?php
/* translators: Which editor to use when updating content that was created with WPML's Classic Translation Editor? */
_e( "Advanced Translation Editor", 'wpml-translation-management' );
?>
</label>
</li>
</ul>
</div>
<?php do_action( 'wpml_doc_translation_method_below' ); ?>
<div class="wpml-section-content-inner">
<h4>
<?php echo esc_html__( 'Taxonomy visibility in the translation editor', 'wpml-translation-management' ) ?>
</h4>
<p id="tm_block_retranslating_terms">
<label>
<input
name="tm_block_retranslating_terms"
value="1"
<?php checked( icl_get_setting( 'tm_block_retranslating_terms' ), "1" ) ?>
type="checkbox"
/>
<?php echo esc_html__( "Only show taxonomy terms that haven't been translated yet", 'wpml-translation-management' ) ?>
</label>
</p>
</div>
<p class="buttons-wrap">
<span class="icl_ajx_response" id="icl_ajx_response_dtm"> </span>
<input type="submit" class="button-primary"
value="<?php echo esc_html__( 'Save', 'wpml-translation-management' ); ?>"/>
</p>
</form>
</div>
<!-- .wpml-section-content -->
</div><!-- #ml-content-setup-sec-1 -->
<?php endif; ?>
<?php if ( $this->should_show_mcsetup_section( 'ml-content-setup-sec-2' ) ) : ?>
<?php include ICL_PLUGIN_PATH . '/menu/_posts_sync_options.php'; ?>
<?php endif; ?><!-- #ml-content-setup-sec-2 -->
<?php if ( $this->should_show_mcsetup_section( 'ml-content-setup-sec-3' ) ) : ?>
<div class="wpml-section" id="ml-content-setup-sec-3">
<div class="wpml-section-header">
<h3><?php echo esc_html__( 'Translated documents options', 'wpml-translation-management' ); ?></h3>
</div>
<div class="wpml-section-content">
<form name="icl_tdo_options" id="icl_tdo_options" action="">
<?php
wp_nonce_field(
'wpml-translated-document-options-nonce',
WPML_TM_Options_Ajax::NONCE_TRANSLATED_DOCUMENT
);
?>
<div class="wpml-section-content-inner">
<h4>
<?php echo esc_html__( 'Document status', 'wpml-translation-management' ); ?>
</h4>
<ul>
<li>
<label>
<input type="radio" name="icl_translated_document_status" value="0"
<?php
checked(
(bool) icl_get_setting( 'translated_document_status' ),
false
);
?>
/>
<?php echo esc_html__( 'Draft', 'wpml-translation-management' ); ?>
</label>
</li>
<li>
<label>
<input type="radio" name="icl_translated_document_status" value="1"
<?php
checked(
(bool) icl_get_setting( 'translated_document_status' ),
true
);
?>
/>
<?php
echo esc_html__(
'Same as the original document',
'wpml-translation-management'
)
?>
</label>
</li>
</ul>
<p class="explanation-text">
<?php
echo esc_html__(
'Choose if translations should be published when received. Note: If Publish is selected, the translation will only be published if the original document is published when the translation is received.',
'wpml-translation-management'
)
?>
</p>
</div>
<div class="wpml-section-content-inner">
<h4>
<?php echo esc_html__( 'Page URL', 'wpml-translation-management' ); ?>
</h4>
<ul>
<li>
<label><input type="radio" name="icl_translated_document_page_url"
value="auto-generate"
<?php
if ( empty( $sitepress_settings['translated_document_page_url'] )
|| $sitepress_settings['translated_document_page_url']
=== 'auto-generate' ) :
?>
checked="checked"<?php endif; ?> />
<?php
echo esc_html__(
'Auto-generate from title (default)',
'wpml-translation-management'
)
?>
</label>
</li>
<li>
<label><input type="radio" name="icl_translated_document_page_url" value="translate"
<?php
if ( $sitepress_settings['translated_document_page_url']
=== 'translate' ) :
?>
checked="checked"<?php endif; ?> />
<?php
echo esc_html__(
'Translate (this will include the slug in the translation and not create it automatically from the title)',
'wpml-translation-management'
)
?>
</label>
</li>
<li>
<label><input type="radio" name="icl_translated_document_page_url"
value="copy-encoded"
<?php
if ( $sitepress_settings['translated_document_page_url']
=== 'copy-encoded' ) :
?>
checked="checked"<?php endif; ?> />
<?php
echo esc_html__(
'Copy from original language if translation language uses encoded URLs',
'wpml-translation-management'
)
?>
</label>
</li>
</ul>
</div>
<div class="wpml-section-content-inner">
<p class="buttons-wrap">
<span class="icl_ajx_response" id="icl_ajx_response_tdo"> </span>
<input id="js-translated_document-options-btn" type="button" class="button-primary"
value="
<?php
echo esc_attr__(
'Save',
'wpml-translation-management'
)
?>
"/>
</p>
</div>
</form>
</div>
<!-- .wpml-section-content -->
</div><!-- #ml-content-setup-sec-3 -->
<?php endif; ?>
<?php
if ( $this->should_show_mcsetup_section( 'ml-content-setup-sec-wp-login' ) ) {
include ICL_PLUGIN_PATH . '/menu/_login_translation_options.php';
}
?>
<!-- #ml-content-setup-sec-wp-login -->
<?php if ( $this->should_show_mcsetup_section( 'ml-content-setup-sec-4' ) ) : ?>
<?php include WPML_ST_PATH . '/menu/_slug-translation-options.php'; ?><!-- #ml-content-setup-sec-4 -->
<?php endif; ?>
<?php if ( $this->should_show_mcsetup_section( 'ml-content-setup-sec-5' ) ) : ?>
<div class="wpml-section" id="ml-content-setup-sec-5">
<div class="wpml-section-header">
<h3><?php echo esc_html__( 'Translation pickup mode', 'wpml-translation-management' ); ?></h3>
</div>
<div class="wpml-section-content">
<form id="icl_translation_pickup_mode" name="icl_translation_pickup_mode" action="">
<?php
wp_nonce_field(
'wpml_save_translation_pickup_mode',
WPML_TM_Pickup_Mode_Ajax::NONCE_PICKUP_MODE
)
?>
<p>
<?php
echo esc_html__(
'How should the site receive completed translations from Translation Service?',
'wpml-translation-management'
);
?>
</p>
<p>
<label>
<input type="radio" name="icl_translation_pickup_method"
value="<?php echo ICL_PRO_TRANSLATION_PICKUP_XMLRPC; ?>"
<?php
if ( $sitepress_settings['translation_pickup_method']
=== ICL_PRO_TRANSLATION_PICKUP_XMLRPC ) :
?>
checked="checked"<?php endif ?>/>
<?php
echo esc_html__(
'Translation Service will deliver translations automatically using XML-RPC',
'wpml-translation-management'
);
?>
</label>
</p>
<p>
<label>
<input type="radio" name="icl_translation_pickup_method"
value="<?php echo ICL_PRO_TRANSLATION_PICKUP_POLLING; ?>"
<?php
if ( $sitepress_settings['translation_pickup_method']
=== ICL_PRO_TRANSLATION_PICKUP_POLLING ) :
?>
checked="checked"<?php endif; ?> />
<?php
echo esc_html__(
'The site will fetch translations manually',
'wpml-translation-management'
);
?>
</label>
</p>
<p class="buttons-wrap">
<span class="icl_ajx_response" id="icl_ajx_response_tpm"> </span>
<input
id="translation-pickup-mode"
class="button-primary"
name="save"
value="<?php echo esc_attr__( 'Save', 'wpml-translation-management' ) ?>"
type="button"
/>
</p>
<?php
$this->build_content_dashboard_fetch_translations_box();
?>
</form>
<?php do_action( 'wpml_tm_mcs_translation_pickup_mode' ); ?>
</div>
<!-- .wpml-section-content -->
</div><!-- #ml-content-setup-sec-5 -->
<?php endif; ?>
<?php if ( $this->should_show_mcsetup_section( 'ml-content-setup-sec-5-1' ) ) : ?>
<?php include WPML_TM_PATH . '/menu/xliff-options.php'; ?><!-- #ml-content-setup-sec-5-1 -->
<?php endif; ?>
<?php $this->build_content_mcs_custom_fields(); ?>
<?php if ( $this->should_show_mcsetup_section( 'ml-content-setup-sec-7' ) ) : ?>
<?php include ICL_PLUGIN_PATH . '/menu/_custom_types_translation.php'; ?><!-- #ml-content-setup-sec-7 -->
<?php endif; ?>
<?php if ( $this->should_show_mcsetup_section( 'ml-content-setup-sec-9' ) ) : ?>
<div class="wpml-section" id="ml-content-setup-sec-9">
<div class="wpml-section-header">
<h3><?php echo esc_html__( 'Admin Strings to Translate', 'wpml-translation-management' ); ?></h3>
</div>
<div class="wpml-section-content">
<table class="widefat">
<thead>
<tr>
<th colspan="3">
<?php echo esc_html__( 'Admin Strings', 'wpml-translation-management' ); ?>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<?php
foreach (
$iclTranslationManagement->admin_texts_to_translate as $option_name =>
$option_value
) {
$iclTranslationManagement->render_option_writes( $option_name, $option_value );
}
?>
<br/>
href="
<?php
echo admin_url(
'admin.php?page='
. WPML_ST_FOLDER
. '/menu/string-translation.php'
)
?>
">
<?php
echo esc_html__(
'Edit translatable strings',
'wpml-translation-management'
)
?>
</a>
</p>
</td>
</tr>
</tbody>
</table>
</div>
<!-- .wpml-section-content -->
</div><!-- #ml-content-setup-sec-9 -->
<?php endif; ?>
<?php if ( $this->should_show_mcsetup_section( $this->get_translate_link_targets_ui()->get_id() ) ) : ?>
<?php echo $this->get_translate_link_targets_ui()->render(); ?><!-- #ml-content-setup-sec-links-target -->
<?php endif; ?>
<?php
wp_enqueue_script( 'wpml-tm-mcs' );
wp_enqueue_script( 'wpml-tm-mcs-translate-link-targets' );
}
private function build_content_mcs_custom_fields() {
global $wpdb;
$factory = new WPML_TM_MCS_Custom_Field_Settings_Menu_Factory();
if ( $this->should_show_mcsetup_section( 'ml-content-setup-sec-cf' ) ) {
$menu_item_posts = $factory->create_post();
$menu_item_posts->init_data();
echo $menu_item_posts->render();
}
if ( ! empty( $wpdb->termmeta ) && $this->should_show_mcsetup_section( 'ml-content-setup-sec-tcf' ) ) {
$menu_item_terms = $factory->create_term();
$menu_item_terms->init_data();
echo $menu_item_terms->render();
}
}
public function build_content_translation_notifications() {
?>
<form method="post" name="translation-notifications" id="translation-notifications"
action="admin.php?page=<?php echo WPML_TM_FOLDER . $this->get_page_slug(); ?>&amp;sm=notifications">
<input type="hidden" name="icl_tm_action" value="save_notification_settings"/>
<?php do_action( 'wpml_tm_translation_notification_setting_after' ); ?>
<div class="wpml-section" id="translation-notifications-sec-3">
<p class="submit">
<input type="submit" class="button-primary"
value="<?php echo esc_html__( 'Save', 'wpml-translation-management' ); ?>"/>
</p>
</div>
<?php wp_nonce_field( 'save_notification_settings_nonce', 'save_notification_settings_nonce' ); ?>
</form>
<?php
}
protected function get_page_slug() {
return WPML_Translation_Management::PAGE_SLUG_SETTINGS;
}
protected function get_default_tab() {
return 'mcsetup';
}
private function render_mcsetup_navigation_links() {
echo '<ul class="wpml-navigation-links js-wpml-navigation-links">';
foreach ( $this->mcsetup_sections as $anchor => $title ) {
echo '<li>' . $this->get_navigation_link( $anchor ) . '</li>';
}
echo '</ul>';
}
private function get_navigation_link( $anchor ) {
if ( array_key_exists( $anchor, $this->mcsetup_sections ) ) {
return '<a href="#' . $anchor . '">' . $this->mcsetup_sections[ $anchor ] . '</a>';
}
}
/** @return bool */
private function should_show_mcsetup_section( $anchor ) {
return array_key_exists( $anchor, $this->mcsetup_sections );
}
/** @return WPML_Translate_Link_Targets_UI */
private function get_translate_link_targets_ui() {
/**
* @var SitePress $sitepress
* @var wpdb $wpdb
* @var $ICL_Pro_Translation
*/
global $sitepress, $wpdb, $ICL_Pro_Translation;
if ( ! $this->translate_link_targets_ui ) {
$this->translate_link_targets_ui = new WPML_Translate_Link_Targets_UI(
__( 'Translate Link Targets', 'wpml-translation-management' ),
$wpdb,
$sitepress,
$ICL_Pro_Translation
);
}
return $this->translate_link_targets_ui;
}
}

View File

@@ -0,0 +1,168 @@
<?php
use WPML\API\Sanitize;
if ( Sanitize::stringProp( 'sm', $_GET ) === 'basket' ) {
add_action( 'admin_enqueue_scripts', array( 'SitePress_Table_Basket', 'enqueue_js' ) );
}
abstract class WPML_TM_Menus {
protected $post_types;
protected $tab_items;
private $base_target_url;
protected $current_shown_item;
/** @var WPML_UI_Screen_Options_Pagination|null $dashboard_pagination */
protected $dashboard_pagination;
function __construct() {
$this->current_shown_item = isset( $_GET['sm'] ) ? $_GET['sm'] : $this->get_default_tab();
$this->base_target_url = dirname( __FILE__ );
}
public function display_main( WPML_UI_Screen_Options_Pagination $dashboard_pagination = null ) {
$this->dashboard_pagination = $dashboard_pagination;
if ( true !== apply_filters( 'wpml_tm_lock_ui', false ) ) {
$this->render_main();
}
}
abstract protected function render_main();
private function build_tab_item_target_url( $target ) {
return $this->base_target_url . $target;
}
abstract protected function build_tab_items();
/**
* @return string
*/
private function get_current_shown_item() {
return $this->current_shown_item;
}
private function build_tabs() {
$tm_sub_menu = $this->get_current_shown_item();
foreach ( $this->tab_items as $id => $tab_item ) {
if ( ! isset( $tab_item['caption'] ) ) {
continue;
}
if ( isset( $tab_item['visible'] ) && ! $tab_item['visible'] ) {
continue;
}
if ( ! isset( $tab_item['target'] ) && ! isset( $tab_item['callback'] ) ) {
continue;
}
$caption = $tab_item['caption'];
if ( ! $this->current_user_can_access( $tab_item ) ) {
continue;
}
$classes = array(
'nav-tab',
'nav-tab-' . $id,
);
if ( $tm_sub_menu === $id ) {
$classes[] = 'nav-tab-active';
}
$class = implode( ' ', $classes );
$href = 'admin.php?page=' . WPML_TM_FOLDER . $this->get_page_slug() . '&sm=' . $id;
?>
<a class="<?php echo esc_attr( $class ); ?>" href="<?php echo esc_attr( $href ); ?>">
<?php echo $caption; ?>
</a>
<?php
}
}
private function build_content() {
$tm_sub_menu = $this->get_current_shown_item();
foreach ( $this->tab_items as $id => $tab_item ) {
if ( ! isset( $tab_item['caption'] ) ) {
continue;
}
if ( ! isset( $tab_item['target'] ) && ! isset( $tab_item['callback'] ) ) {
continue;
}
if ( $tm_sub_menu == $id ) {
if ( $this->current_user_can_access( $tab_item ) ) {
if ( isset( $tab_item['target'] ) ) {
$target = $tab_item['target'];
/** @noinspection PhpIncludeInspection */
include_once $this->build_tab_item_target_url( $target );
}
if ( isset( $tab_item['callback'] ) ) {
$callback = $tab_item['callback'];
call_user_func( $callback );
}
}
}
}
do_action( 'icl_tm_menu_' . $tm_sub_menu );
}
protected function render_items() {
if ( $this->tab_items ) {
?>
<div class="icl-translation-management-menu wpml-tabs">
<?php
$this->build_tabs();
?>
</div>
<div class="icl_tm_wrap wpml-wrap">
<?php
$this->build_content();
?>
</div>
<?php
}
}
public function build_content_dashboard_fetch_translations_box() {
if ( TranslationProxy::is_current_service_active_and_authenticated() ) {
$tm_polling_box = new WPML_TM_Polling_Box();
echo $tm_polling_box->render();
}
}
/**
* Used only by unit tests at the moment
*
* @return mixed
*/
public function get_post_types() {
return $this->post_types;
}
protected function heading( $text ) {
?>
<h3 class="wpml-tm-section-header wpml-tm-dashboard-h3"><?php echo esc_html( $text ); ?></h3>
<?php
}
private function current_user_can_access( $tab_item ) {
$current_user_can = isset( $tab_item['current_user_can'] ) ? $tab_item['current_user_can'] : false;
if ( is_array( $current_user_can ) ) {
foreach ( $current_user_can as $capability ) {
if ( current_user_can( $capability ) ) {
return true;
}
}
return false;
} else {
return current_user_can( $current_user_can );
}
}
abstract protected function get_page_slug();
abstract protected function get_default_tab();
}

View File

@@ -0,0 +1,123 @@
<?php
class WPML_Translation_Selector extends WPML_SP_User {
private $default_language_code;
private $source_language_code;
private $element_id;
public function __construct( &$sitepress, $default_language, $source_language, $element_id ) {
$this->default_language_code = $default_language;
$this->source_language_code = $source_language;
$this->element_id = $element_id;
parent::__construct( $sitepress );
}
function add_translation_of_selector_to_page( $trid, $current_language, $selected_language, $untranslated_ids ) {
$default_language = $this->default_language_code;
$source_language = $this->source_language_code;
?>
<input type="hidden" name="icl_trid" value="<?php echo $trid; ?>"/>
<?php
if ( $selected_language !== $default_language && 'all' !== $current_language ) {
?>
<br/><br/>
<?php echo __( 'This is a translation of', 'sitepress' ); ?><br/>
<select name="icl_translation_of"
id="icl_translation_of"
<?php
if ( ! $this->sitepress->get_wp_api()->is_term_edit_page() && $trid ) {
echo ' disabled';
}
?>
>
<?php
if ( $trid ) {
?>
<option value="none"><?php echo __( '--None--', 'sitepress' ); ?></option>
<?php
$src_term = $this->get_original_name_by_trid( $trid );
if ( $src_term !== null ) {
?>
<option value="<?php echo $src_term->ttid; ?>"
selected="selected"><?php echo $src_term->name; ?></option>
<?php
}
} else {
?>
<option value="none" selected="selected"><?php echo __( '--None--', 'sitepress' ); ?></option>
<?php
}
if ( ! $source_language || $source_language === $default_language ) {
foreach ( $untranslated_ids as $translation_of_id ) {
$title = $this->get_name_by_ttid( $translation_of_id );
if ( $title !== null ) {
?>
<option value="<?php echo $translation_of_id; ?>"><?php echo $title; ?></option>
<?php
}
}
}
?>
</select>
<?php
}
}
private function get_name_by_ttid( $ttid ) {
global $wpdb;
return $wpdb->get_var(
$wpdb->prepare(
" SELECT t.name
FROM {$wpdb->terms} t
JOIN {$wpdb->term_taxonomy} tt
ON t.term_id = tt.term_id
WHERE tt.term_taxonomy_id = %d
LIMIT 1",
$ttid
)
);
}
/**
* @param int $trid
* @return null|object
*/
private function get_original_name_by_trid( $trid ) {
global $wpdb;
$src_snippet = $this->source_language_code ? $wpdb->prepare(
' AND language_code = %s LIMIT 1',
$this->source_language_code
) : '';
$all_translations = $wpdb->get_results(
$wpdb->prepare(
" SELECT t.name, i.element_id as ttid, i.language_code
FROM {$wpdb->terms} t
JOIN {$wpdb->term_taxonomy} tt
ON t.term_id = tt.term_id
JOIN {$wpdb->prefix}icl_translations i
ON i.element_type = CONCAT('tax_', tt.taxonomy)
AND i.element_id = tt.term_taxonomy_id
WHERE i.trid = %d
AND i.element_id != %d
{$src_snippet}",
$trid,
$this->element_id
)
);
$res = null;
foreach ( $all_translations as $translation ) {
$res = $res === null ? $translation : $res;
if ( $translation->language_code === $this->default_language_code ) {
$res = $translation;
break;
}
}
return $res;
}
}

View File

@@ -0,0 +1,139 @@
<?php
use WPML\API\Sanitize;
class WPML_Troubleshooting_Terms_Menu {
/**
* Displays the admin notice informing about terms in the old format, using the language suffix.
* The notice is displayed until it is either dismissed or the update button is pressed.
*/
public static function display_terms_with_suffix_admin_notice() {
global $sitepress;
if ( ! $sitepress->get_setting( 'taxonomy_names_checked' ) ) {
$suffix_count = count( WPML_Terms_Translations::get_all_terms_with_language_suffix() );
if ( $suffix_count > 0 ) {
$message = '<p>';
$message .= sprintf( __( 'In this version of WPML, you can give your taxonomy terms the same name across multiple languages. You need to update %d taxonomy terms on your website so that they display the same name without any language suffixes.', 'sitepress' ), $suffix_count );
$message .= '</p>';
if ( defined( 'ICL_PLUGIN_URL' ) ) {
$message .= '<p><a href="' . admin_url( 'admin.php?page=' . WPML_PLUGIN_FOLDER . '/menu/troubleshooting.php#termsuffixupdate' ) . '"><button class="button-primary">Open terms update page</button></a>';
}
ICL_AdminNotifier::addMessage( 'termssuffixnotice', $message, 'error', true, false, false, 'terms-suffix', true );
}
$sitepress->set_setting( 'taxonomy_names_checked', true, true );
}
// TODO: [WPML 3.3] the ICL_AdminNotifier class got improved and we should not call \ICL_AdminNotifier::displayMessages to display an admin notice
ICL_AdminNotifier::displayMessages( 'terms-suffix' );
}
/**
* Returns the HTML for the display of all terms with a language suffix in the troubleshooting menu.
*
* @return string
*/
public static function display_terms_with_suffix() {
$terms_to_display = WPML_Terms_Translations::get_all_terms_with_language_suffix();
$output = '';
if ( ! empty( $terms_to_display ) ) {
$output = '<div class="icl_cyan_box">';
$output .= '<table class="widefat" id="icl-updated-term-names-table">';
$output .= '<a name="termsuffixupdate"></a>';
$output .= '<tr><h3>' . __( 'Remove language suffixes from taxonomy names.', 'sitepress' ) . '</h3></tr>';
$output .= '<tr id="icl-updated-term-names-headings"><th></th><th>' . __( 'Old Name', 'sitepress' ) . '</th><th>' . __( 'Updated Name', 'sitepress' ) . '</th><th>' . __( 'Affected Taxonomies', 'sitepress' ) . '</th></tr>';
foreach ( $terms_to_display as $term_id => $term ) {
$updated_term_name = self::strip_language_suffix( $term['name'] );
$output .= '<tr class="icl-term-with-suffix-row"><td>';
$output .= '<input type="checkbox" checked="checked" name="' . $updated_term_name . '" value="' . $term_id . '"/>';
$output .= '</td>';
$output .= '<td>' . $term['name'] . '</td>';
$output .= '<td id="term_' . $term_id . '">' . $updated_term_name . '</td>';
$output .= '<td>' . join( ', ', $term['taxonomies'] ) . '</td>';
$output .= '</tr>';
}
$output .= '</table>';
$output .= '</br></br>';
$output .= '<button id="icl-update-term-names" class="button-primary">' . __( 'Update term names', 'sitepress' ) . '</button>';
$output .= '<button id="icl-update-term-names-done" class="button-primary" disabled="disabled" style="display:none;">' . __( 'All term names updated', 'sitepress' ) . '</button>';
$output .= '</div>';
}
return $output;
}
/**
* @param string $term_name
* Strips a term off all language suffixes in the form @<lang_code> on it.
*
* @return string
*/
public static function strip_language_suffix( $term_name ) {
global $wpdb;
$lang_codes = $wpdb->get_col( "SELECT code FROM {$wpdb->prefix}icl_languages" );
$new_name_parts = explode( ' @', $term_name );
$new_name_parts = array_filter( $new_name_parts );
$last_part = array_pop( $new_name_parts );
while ( in_array( $last_part, $lang_codes ) ) {
$last_part = array_pop( $new_name_parts );
}
$new_name = '';
if ( ! empty( $new_name_parts ) ) {
$new_name = join( ' @', $new_name_parts ) . ' @';
}
$new_name .= $last_part;
return $new_name;
}
/**
* Ajax handler for the troubleshoot page. Updates the term name on those terms given via the Ajax action.
*/
public static function wpml_update_term_names_troubleshoot() {
global $wpdb;
ICL_AdminNotifier::removeMessage( 'termssuffixnotice' );
$term_names = array();
$nonce = Sanitize::stringProp( '_icl_nonce', $_POST );
if ( ! wp_verify_nonce( $nonce, 'update_term_names_nonce' ) ) {
die( 'Wrong Nonce' );
}
$request_post_terms = Sanitize::stringProp( 'terms', $_POST );
if ( $request_post_terms ) {
$term_names = json_decode( stripcslashes( $request_post_terms ) );
if ( ! is_object( $term_names ) ) {
$term_names = array();
}
}
$updated = array();
foreach ( $term_names as $term_id => $new_name ) {
$res = $wpdb->update( $wpdb->terms, array( 'name' => $new_name ), array( 'term_id' => $term_id ) );
if ( $res ) {
$updated[] = $term_id;
}
}
wp_send_json_success( $updated );
}
}

View File

@@ -0,0 +1,10 @@
<script type="text/javascript">
var wpml_xliff_ajxloaderimg_src = '<?php echo WPML_XLIFF_TM_URL; ?>/res/img/ajax-loader.gif';
var wpml_xliff_ajxloaderimg = '<img src="'+wpml_xliff_ajxloaderimg_src+'" alt="loading" width="16" height="16" />';
</script>
<div class="wrap">
<h2><?php echo __( 'XLIFF translation', 'wpml-translation-management' ); ?></h2>
</div>

View File

@@ -0,0 +1,85 @@
<?php
global $sitepress;
$xliff_newlines = (int) $sitepress->get_setting( 'xliff_newlines' );
if ( ! $xliff_newlines ) {
$xliff_newlines = WPML_XLIFF_TM_NEWLINES_ORIGINAL;
}
$new_line_labels = array(
WPML_XLIFF_TM_NEWLINES_ORIGINAL => __(
'Do nothing - all new line characters will stay untouched.',
'wpml-translation-management'
),
WPML_XLIFF_TM_NEWLINES_REPLACE => sprintf(
__( 'All new lines should be replaced by HTML element %s. Use this option if translation tool used by translator does not support new lines characters (for example Virtaal software)', 'wpml-translation-management' ),
'<br class="xliff-newline" />'
),
);
?>
<div class="wpml-section" id="ml-content-setup-sec-5-1">
<div class="wpml-section-header">
<h3><?php esc_html_e( 'XLIFF file options', 'wpml-translation-management' ); ?></h3>
</div>
<div class="wpml-section-content">
<form name="icl_xliff_options_form" id="icl_xliff_options_form" action="">
<?php wp_nonce_field( 'icl_xliff_options_form_nonce', '_icl_nonce' ); ?>
<div class="wpml-section-content-inner">
<h4><?php esc_html_e( 'XLIFF version', 'wpml-translation-management' ); ?></h4>
<p>
<?php esc_html_e( 'Choose default format for XLIFF file:', 'wpml-translation-management' ); ?>
<select name="icl_xliff_version">
<option value="false"><?php echo esc_html__( 'Please choose', 'wpml-translation-management' ); ?></option>
<?php
$xliff_instance = setup_xliff_frontend();
$available_xliff_versions = $xliff_instance->get_available_xliff_versions();
foreach ( $available_xliff_versions as $value => $version ) {
$selected = '';
if ( $sitepress->get_setting( 'tm_xliff_version' ) === $value ) {
$selected = 'selected="selected"';
}
$version_label = sprintf( __( 'XLIFF %s', 'wpml-translation-management' ), $version );
echo sprintf( '<option value="%1$s" %2$s >%3$s</option>', esc_attr( $value ), $selected, esc_html( $version_label ) );
}
?>
</select>
</p>
</div>
<div class="wpml-section-content-inner">
<h4><?php esc_html_e( 'New lines character', 'wpml-translation-management' ); ?></h4>
<p>
<?php esc_html_e( 'How new lines characters in XLIFF files should be handled?', 'wpml-translation-management' ); ?>
</p>
<?php foreach ( $new_line_labels as $mode => $label ) { ?>
<p>
<label>
<input type="radio" name="icl_xliff_newlines"
value="<?php echo esc_attr( $mode ); ?>"<?php checked( $xliff_newlines, $mode ); ?>/>
<?php echo esc_html( $label ); ?>
</label>
</p>
<?php } ?>
</div>
<p class="buttons-wrap">
<span class="icl_ajx_response" id="icl_ajx_response"></span>
<input type="submit" class="button-primary"
value="<?php esc_attr_e( 'Save', 'wpml-translation-management' ); ?>"/>
</p>
</form>
</div> <!-- .wpml-section-content -->
</div>