__( 'Translation editor', 'swiftling' ), 'title' => __( 'Translation editor', 'swiftling' ), ) ); Ui::emptyState( __( 'Choose what to translate', 'swiftling' ), __( 'Open a page or post from Translations, or with Translate in the list of pages. Templates, categories and tags have their own tabs in Translations.', 'swiftling' ), array( __( 'Open translations', 'swiftling' ), admin_url( 'admin.php?page=swiftling-content' ) ) ); return; } if ( ! swiftling_can_translate_subject( $swiftling_subject ) ) { wp_die( esc_html__( 'You may not edit this content, so you cannot translate it either.', 'swiftling' ), '', array( 'response' => 403 ) ); } if ( ! swiftling_languages()['targets'] ) { Ui::emptyState( __( 'Choose the languages first', 'swiftling' ), __( 'Tell SwiftLing which languages this content should be translated into.', 'swiftling' ), array( __( 'Add languages', 'swiftling' ), admin_url( 'admin.php?page=swiftling-languages' ) ) ); return; } $swiftling_is_post = 'post' === $swiftling_subject['kind']; $swiftling_is_package = 'package' === $swiftling_subject['kind']; $swiftling_back = $swiftling_is_post ? array( __( 'Translations', 'swiftling' ), admin_url( 'admin.php?page=swiftling-content' ) ) : array( __( 'Templates', 'swiftling' ), admin_url( 'admin.php?page=swiftling-templates' ) ); if ( $swiftling_is_package ) { $swiftling_back = array( __( 'Themes & plugins', 'swiftling' ), swiftling_package_url() ); } elseif ( 'terms' === $swiftling_subject['kind'] ) { $swiftling_back = array( __( 'Categories & tags', 'swiftling' ), admin_url( 'admin.php?page=swiftling-terms' ) ); } elseif ( 'menu' === $swiftling_subject['kind'] ) { $swiftling_back = array( __( 'Menus', 'swiftling' ), admin_url( 'admin.php?page=swiftling-menus' ) ); } elseif ( 'comments' === $swiftling_subject['kind'] ) { $swiftling_back = array( __( 'Comments', 'swiftling' ), admin_url( 'admin.php?page=swiftling-comments' ) ); } $swiftling_languages = swiftling_languages(); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only screen parameter. $swiftling_lang = isset( $_GET['lang'] ) ? sanitize_key( wp_unslash( $_GET['lang'] ) ) : ''; if ( ! swiftling_target_language( $swiftling_lang ) ) { $swiftling_lang = (string) key( $swiftling_languages['targets'] ); } $swiftling_target = swiftling_target_language( $swiftling_lang ); // A post can have a separate copy for the language, see includes/copies.php. $swiftling_copy = $swiftling_is_post ? swiftling_copy_for( $swiftling_subject['post']->ID, $swiftling_target['locale'] ) : null; $swiftling_can_copy = $swiftling_is_post && ! $swiftling_copy && swiftling_can_make_copy( $swiftling_subject['post'] ); // How the language shows the post: translated here, as the copy, or the original kept as it is. $swiftling_mode = $swiftling_is_post ? swiftling_language_mode( $swiftling_subject['post']->ID, $swiftling_target['locale'] ) : 'translation'; $swiftling_can_choose = $swiftling_is_post && swiftling_can_choose_mode( $swiftling_subject['post'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Only which message to show after a redirect. $swiftling_notice = isset( $_GET['swiftling_notice'] ) ? sanitize_key( wp_unslash( $_GET['swiftling_notice'] ) ) : ''; // A list of terms, of a menu, of a builder's texts or of a theme's or plugin's texts needs no page // check: its rows are ready now. Saving them first lets the state of the languages below count them. $swiftling_rows = null; $swiftling_list = array(); $swiftling_search = ''; $swiftling_check = false; if ( $swiftling_is_package ) { // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Which texts of the list to show. $swiftling_search = isset( $_GET['find'] ) ? sanitize_text_field( wp_unslash( $_GET['find'] ) ) : ''; $swiftling_list = swiftling_save_package_list( $swiftling_subject, $swiftling_lang, array( 'show' => isset( $_GET['show'] ) ? sanitize_key( wp_unslash( $_GET['show'] ) ) : '', 'search' => $swiftling_search, 'page' => isset( $_GET['paged'] ) ? absint( $_GET['paged'] ) : 1, ) ); // phpcs:enable } elseif ( 'terms' === $swiftling_subject['kind'] ) { // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Which terms of the list to show. $swiftling_search = isset( $_GET['find'] ) ? sanitize_text_field( wp_unslash( $_GET['find'] ) ) : ''; $swiftling_list = swiftling_save_term_list( $swiftling_subject ); // A field of the terms that may show on the page of a term: the page is checked first, and the // rows come with what it found. $swiftling_check = swiftling_term_list_needs_check( $swiftling_subject, $swiftling_list['fields'] ); $swiftling_list = swiftling_term_list_page( $swiftling_list, array( 'page' => isset( $_GET['paged'] ) ? absint( $_GET['paged'] ) : 1, 'search' => $swiftling_search, ) ); // phpcs:enable } elseif ( 'comments' === $swiftling_subject['kind'] ) { // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Which comments of the list to show. $swiftling_search = isset( $_GET['find'] ) ? sanitize_text_field( wp_unslash( $_GET['find'] ) ) : ''; $swiftling_list = swiftling_save_comment_list( $swiftling_subject, $swiftling_lang, array( 'show' => isset( $_GET['show'] ) ? sanitize_key( wp_unslash( $_GET['show'] ) ) : '', 'search' => $swiftling_search, 'for' => isset( $_GET['for'] ) ? absint( $_GET['for'] ) : 0, 'page' => isset( $_GET['paged'] ) ? absint( $_GET['paged'] ) : 1, ) ); // phpcs:enable } elseif ( 'fields' === $swiftling_subject['kind'] ) { $swiftling_list = swiftling_save_field_list( $swiftling_subject ); } elseif ( 'menu' === $swiftling_subject['kind'] ) { $swiftling_list = swiftling_save_menu_list( $swiftling_subject ); } if ( $swiftling_list && ! $swiftling_check ) { $swiftling_rows = array( 'rows' => swiftling_live_rows_html( $swiftling_subject, $swiftling_lang, $swiftling_list ), 'extras' => swiftling_live_extras_count( $swiftling_list ), ); } if ( ! $swiftling_subject['probe'] && ! $swiftling_rows ) { Ui::screenHeader( array( 'crumb' => __( 'Templates', 'swiftling' ), 'title' => $swiftling_subject['title'], ) ); Ui::emptyState( __( 'No page shows this template', 'swiftling' ), __( 'Visitors never see this template on this site right now, so there is nothing to translate. Once a page uses it, it can be translated here.', 'swiftling' ), array( __( 'Back to templates', 'swiftling' ), admin_url( 'admin.php?page=swiftling-templates' ) ) ); return; } $swiftling_states = swiftling_subject_states( $swiftling_subject['key'] ); $swiftling_counts = swiftling_subject_counts( $swiftling_subject['key'] ); // A list of texts from code shows one page at a time; its languages count the whole list, and a // text its theme's or plugin's translators translated counts as translated. // So does a list of comments, see includes/comments.php. if ( $swiftling_is_package && $swiftling_list['list']['progress'] ) { $swiftling_counts = $swiftling_list['list']['progress']; } elseif ( 'comments' === $swiftling_subject['kind'] ) { $swiftling_counts = $swiftling_list['progress']; } if ( ( $swiftling_is_package && $swiftling_list['list']['progress'] ) || 'comments' === $swiftling_subject['kind'] ) { foreach ( $swiftling_counts as $swiftling_slug => $swiftling_count ) { // Machine translations not reviewed yet show as such, where the list counts them. $swiftling_done = empty( $swiftling_count['machine'] ) ? 'reviewed' : 'machine'; $swiftling_states[ $swiftling_slug ] = $swiftling_count['translated'] >= $swiftling_count['total'] ? $swiftling_done : ( $swiftling_count['translated'] ? 'partial' : 'missing' ); } } $swiftling_subtitle = $swiftling_subject['type']; if ( $swiftling_is_post ) { $swiftling_built = array_map( static function ( Builder $builder ): string { return $builder->name(); }, array_values( Registry::forPost( $swiftling_subject['post']->ID ) ) ); if ( $swiftling_built ) { /* translators: 1: kind of content, e.g. Page, 2: builders, e.g. Elementor. */ $swiftling_subtitle = sprintf( __( '%1$s, built with %2$s', 'swiftling' ), $swiftling_subject['type'], wp_sprintf( '%l', $swiftling_built ) ); } } $swiftling_view_url = $swiftling_subject['url']; // Where the page opens in the language: a published post at its translated address. if ( '' === $swiftling_view_url ) { $swiftling_view_in = ''; } elseif ( $swiftling_is_post && 'publish' === $swiftling_subject['post']->post_status ) { $swiftling_view_in = swiftling_post_language_url( $swiftling_subject['post'], $swiftling_lang ); } else { $swiftling_view_in = swiftling_language_url( $swiftling_view_url, $swiftling_lang ); } // Where the header, footer and menu around a post are translated. $swiftling_frame = $swiftling_is_post ? swiftling_post_view_subject( $swiftling_subject['post'] ) : null; // A list of terms checks its page only when it needs to, see swiftling_term_list_needs_check(). $swiftling_probes = $swiftling_subject['probe'] && ( 'terms' !== $swiftling_subject['kind'] || $swiftling_check ) ? array( 'marked' => swiftling_probe_url( $swiftling_subject, 'marked' ), 'control' => swiftling_probe_url( $swiftling_subject, 'control' ), ) : null; // Machine translation with the service that translates this subject into the language, when one is // connected and translates both languages. $swiftling_service = Services::forTarget( $swiftling_subject['key'], $swiftling_target ); // A translator the site's manager keeps from machine translation works as without a service. if ( ! swiftling_can_machine_translate() ) { $swiftling_service = null; } $swiftling_unsupported = ''; $swiftling_unsupported_note = ''; if ( $swiftling_service ) { foreach ( array( $swiftling_languages['source'], $swiftling_target ) as $swiftling_needed ) { if ( '' === $swiftling_unsupported && null === $swiftling_service->languageCode( $swiftling_needed ) ) { /* translators: 1: service name, e.g. Google, 2: language name, e.g. Montenegrin. */ $swiftling_unsupported = sprintf( __( '%1$s does not translate %2$s.', 'swiftling' ), $swiftling_service->name(), $swiftling_needed['name'] ); /* translators: 1: service name, e.g. Google, 2: language name, e.g. Montenegrin. */ $swiftling_unsupported_note = sprintf( __( '%1$s does not translate %2$s, so machine translation is off for this language. Write the translations here, or connect another service.', 'swiftling' ), $swiftling_service->name(), $swiftling_needed['name'] ); } } } $swiftling_config = array( 'subject' => $swiftling_subject['key'], 'lang' => $swiftling_lang, 'rest' => esc_url_raw( rest_url( 'swiftling/v1/' ) ), 'nonce' => wp_create_nonce( 'wp_rest' ), 'probes' => $swiftling_probes, 'rows' => $swiftling_rows, 'labels' => Ui::statusLabels(), 'machine' => $swiftling_service && '' === $swiftling_unsupported ? array( 'service' => $swiftling_service->name() ) : null, // A list of texts from code, or of terms, shows one page at a time: its languages count the // whole list. 'paged' => ( $swiftling_is_package && 'settings' !== $swiftling_subject['view'] ) || 'comments' === $swiftling_subject['kind'] || ( isset( $swiftling_list['list'] ) && 'terms' === $swiftling_subject['kind'] && ( $swiftling_list['list']['pages'] > 1 || '' !== $swiftling_search ) ), // Which terms of a list the rows show, for the rows that come after its page check. 'list' => 'terms' === $swiftling_subject['kind'] ? array( 'paged' => $swiftling_list['list']['page'], 'find' => $swiftling_search, ) : null, // Which comments translating every one without a translation goes through, see includes/comments.php. 'comments' => 'comments' === $swiftling_subject['kind'] ? array( 'missing' => $swiftling_list['list']['counts']['missing'], 'for' => $swiftling_list['list']['for'], 'find' => $swiftling_search, ) : null, 'strings' => array( /* translators: %s: seconds since the check started. */ 'stepOpen' => __( 'Preparing the translation fields: loading the page · %s s', 'swiftling' ), /* translators: %s: seconds since the check started. */ 'stepRead' => __( 'Preparing the translation fields: finding the texts · %s s', 'swiftling' ), /* translators: %s: seconds since the check started. */ 'stepSave' => __( 'Preparing the translation fields: saving · %s s', 'swiftling' ), 'ready' => __( 'The translation fields are ready.', 'swiftling' ), 'failed' => __( 'The page could not be checked. Reload the editor to try again.', 'swiftling' ), 'pickImage' => __( 'Choose the image for this language', 'swiftling' ), 'useImage' => __( 'Use this image', 'swiftling' ), 'saving' => __( 'Saving…', 'swiftling' ), 'saved' => __( 'Saved.', 'swiftling' ), 'nothing' => __( 'No changes to save.', 'swiftling' ), 'saveFailed' => __( 'The translations could not be saved.', 'swiftling' ), 'noEmpty' => __( 'Every field is filled in.', 'swiftling' ), 'leave' => __( 'Some translations are not saved yet.', 'swiftling' ), 'noMachine' => __( 'Every text field is filled in. Empty a field to translate it again.', 'swiftling' ), 'noAgain' => __( 'No translation of this page is in that state.', 'swiftling' ), 'machineOff' => __( 'The translation stopped.', 'swiftling' ), 'slugHint' => __( 'Empty: the original slug. A changed address keeps leading here from the old one.', 'swiftling' ), 'slugMade' => __( 'Made from the translated title. Change it if you like.', 'swiftling' ), 'slugSaved' => __( 'The address is saved.', 'swiftling' ), 'slugFailed' => __( 'The address could not be saved.', 'swiftling' ), ), ); ?>
$swiftling_subject['key'], 'lang' => $swiftling_lang, 'keep' => $swiftling_for ? array( 'for' => (string) $swiftling_for->ID ) : array(), 'shows' => array( 'missing' => array( __( 'Without a translation', 'swiftling' ), $swiftling_list['list']['counts']['missing'] ), 'all' => array( __( 'All', 'swiftling' ), $swiftling_list['list']['counts']['all'] ), ), 'show' => $swiftling_list['list']['show'], 'search' => $swiftling_search, 'placeholder' => __( 'Search comments', 'swiftling' ), 'page' => $swiftling_list['list']['page'], 'pages' => $swiftling_list['list']['pages'], 'per_page' => SWIFTLING_COMMENTS_PER_PAGE, 'shown' => $swiftling_list['list']['shown'], ) ); } elseif ( 'terms' === $swiftling_subject['kind'] && ( $swiftling_list['list']['pages'] > 1 || '' !== $swiftling_search ) ) { Ui::listFilters( array( 'subject' => $swiftling_subject['key'], 'lang' => $swiftling_lang, 'search' => $swiftling_search, 'placeholder' => __( 'Search terms', 'swiftling' ), 'page' => $swiftling_list['list']['page'], 'pages' => $swiftling_list['list']['pages'], 'per_page' => SWIFTLING_TERMS_PER_PAGE, 'shown' => $swiftling_list['list']['shown'], ) ); } $swiftling_messages = array( 'mode_copy_made' => array( 'is-success', __( 'The copy is made. Edit it, and publish it when it is ready.', 'swiftling' ) ), /* translators: %s: language name, e.g. Deutsch. */ 'mode_translation' => array( 'is-success', sprintf( __( '%s shows this page translated in this editor.', 'swiftling' ), $swiftling_target['name'] ) ), /* translators: 1: language name, e.g. Deutsch, 2: the original's language, e.g. English. */ 'mode_duplicate' => array( 'is-success', sprintf( __( '%1$s keeps the original: visitors there see this page in %2$s, as it is.', 'swiftling' ), $swiftling_target['name'], swiftling_languages()['source']['name'] ) ), 'mode_copy_kept' => array( 'is-info', __( 'This language already has a separate copy.', 'swiftling' ) ), 'swiftling_copy_refused' => array( 'is-info', __( 'This content cannot have a separate copy.', 'swiftling' ) ), 'swiftling_copy_kept' => array( 'is-info', __( 'You may not remove the separate copy.', 'swiftling' ) ), 'swiftling_mode_refused' => array( 'is-info', __( 'This cannot be changed here.', 'swiftling' ) ), ); /** * Prints a button that chooses how the language shows the post, see swiftling_set_language_mode(). * * @param string $mode translation, manual or duplicate. * @param string $label Text of the button. * @param string $variant Button variant. * @param string $note Optional text next to the button. * @param string $classes Optional classes of the form. */ $swiftling_mode_fields = static function ( $mode ) use ( $swiftling_subject, $swiftling_lang ) { ?> ID ); }; $swiftling_mode_form = static function ( $mode, $label, $variant, $note = '', $classes = '' ) use ( $swiftling_mode_fields ) { ?> $swiftling_messages[ $swiftling_notice ][1] ) ); ?> sprintf( /* translators: 1: number of comments, 2: translation service name, e.g. Google. */ _n( '%1$s comment translated with %2$s and saved as a machine translation. Read it in the list of all comments, then save to mark it reviewed.', '%1$s comments translated with %2$s and saved as machine translations. Read them in the list of all comments, then save to mark them reviewed.', $swiftling_run, 'swiftling' ), number_format_i18n( $swiftling_run ), $swiftling_service->name() ), ) ); } ?>
post_status; $swiftling_original = $swiftling_subject['post']; ?>
sprintf( __( 'The original changed on %s, after the copy was last edited. Check whether the copy needs the same change.', 'swiftling' ), get_post_modified_time( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), false, $swiftling_original, true ) ), 'compact' => true, ) ); ?>