feat: display the current translating stuff in settings

This commit is contained in:
hanyixuanten
2026-07-26 00:23:37 +08:00
parent 146b017ed7
commit 696b37c100
3 changed files with 107 additions and 0 deletions
+2
View File
@@ -73,6 +73,8 @@ Before production use, add WordPress PHPUnit integration tests with mocked `wp_r
The Posts and Pages lists show a status column for every target language, including the latest successful translation time and a translation action. The Settings page also provides **重新翻译所有内容**. It shows a confirmation warning before scheduling a forced refresh of published posts, pages, categories, and tags; this bypasses persisted translations and consumes Baidu API quota.
The Settings page also shows a live progress panel. It refreshes every five seconds and counts completed post/page and category/tag items for every configured target language. Progress reads only local WordPress and translation-table data; it does not send additional requests to Baidu.
## Known Limitations
- The settings UI accepts language codes but does not yet validate them against a maintained Baidu language-code list.
+73
View File
@@ -8,6 +8,7 @@ class WPT_Admin {
add_action( 'admin_init', array( $this, 'register_settings' ) );
add_action( 'admin_post_wpt_queue_existing_translations', array( $this, 'queue_existing_translations' ) );
add_action( 'admin_post_wpt_translate_post', array( $this, 'queue_post_translation' ) );
add_action( 'wp_ajax_wpt_translation_progress', array( $this, 'translation_progress' ) );
add_filter( 'manage_post_posts_columns', array( $this, 'add_translation_column' ) );
add_filter( 'manage_page_posts_columns', array( $this, 'add_translation_column' ) );
add_action( 'manage_post_posts_custom_column', array( $this, 'render_translation_column' ), 10, 2 );
@@ -76,6 +77,38 @@ class WPT_Admin {
<?php wp_nonce_field( 'wpt_queue_existing_translations' ); ?>
<?php submit_button( '重新翻译所有内容', 'secondary', 'submit', false ); ?>
</form>
<hr />
<h2>翻译进度</h2>
<div id="wpt-translation-progress" aria-live="polite">
<p>正在读取翻译进度...</p>
</div>
<script>
(function () {
var container = document.getElementById('wpt-translation-progress');
var endpoint = <?php echo wp_json_encode( admin_url( 'admin-ajax.php' ) ); ?>;
var nonce = <?php echo wp_json_encode( wp_create_nonce( 'wpt_translation_progress' ) ); ?>;
function updateProgress() {
fetch(endpoint + '?action=wpt_translation_progress&_ajax_nonce=' + encodeURIComponent(nonce), { credentials: 'same-origin' })
.then(function (response) { return response.json(); })
.then(function (response) {
if (!response.success) {
throw new Error('progress_request_failed');
}
var progress = response.data;
container.innerHTML = '<p><strong>' + progress.percent + '%</strong>' + progress.completed + ' / ' + progress.total + ' 个内容项)</p>' +
'<div style="max-width:480px;height:12px;background:#dcdcde"><div style="height:12px;width:' + progress.percent + '%;background:#2271b1"></div></div>' +
'<p class="description">文章和页面:' + progress.posts_completed + ' / ' + progress.posts_total + ';分类和标签:' + progress.terms_completed + ' / ' + progress.terms_total + '。每 5 秒自动更新。</p>';
})
.catch(function () {
container.innerHTML = '<p>暂时无法读取翻译进度。</p>';
});
}
updateProgress();
window.setInterval(updateProgress, 5000);
}());
</script>
</div>
<?php
}
@@ -134,6 +167,46 @@ class WPT_Admin {
return $links;
}
public function translation_progress() {
check_ajax_referer( 'wpt_translation_progress' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( array( 'message' => 'forbidden' ), 403 );
}
$post_count = (int) wp_count_posts( 'post' )->publish + (int) wp_count_posts( 'page' )->publish;
$terms = get_terms(
array(
'taxonomy' => array( 'category', 'post_tag' ),
'hide_empty' => false,
'fields' => 'ids',
)
);
$term_count = is_wp_error( $terms ) ? 0 : count( $terms );
$languages = WPT_Settings::target_languages();
$counts = ( new WPT_Translation_Store() )->get_completed_item_counts( $languages );
$posts_total = $post_count * count( $languages );
$terms_total = $term_count * count( $languages );
$total = $posts_total + $terms_total;
$posts_completed = min( $counts['posts'], $posts_total );
$terms_completed = min( $counts['terms'], $terms_total );
$completed = $posts_completed + $terms_completed;
$percent = $total ? (int) floor( ( $completed / $total ) * 100 ) : 100;
wp_send_json_success(
array(
'posts_completed' => $posts_completed,
'posts_total' => $posts_total,
'terms_completed' => $terms_completed,
'terms_total' => $terms_total,
'completed' => $completed,
'total' => $total,
'percent' => $percent,
)
);
}
public function add_translation_column( $columns ) {
$columns['wpt_translation'] = '翻译状态';
+32
View File
@@ -86,4 +86,36 @@ class WPT_Translation_Store {
return $wpdb->get_row( $sql, ARRAY_A );
}
public function get_completed_item_counts( $target_languages ) {
global $wpdb;
$target_languages = array_values( array_filter( array_map( 'sanitize_key', (array) $target_languages ) ) );
if ( empty( $target_languages ) ) {
return array(
'posts' => 0,
'terms' => 0,
);
}
$table_name = self::table_name();
$placeholders = implode( ',', array_fill( 0, count( $target_languages ), '%s' ) );
$post_sql = $wpdb->prepare(
"SELECT COUNT(DISTINCT CONCAT(target_language, '|', SUBSTRING_INDEX(field_context, ':', 2)))
FROM {$table_name}
WHERE status = 'complete' AND target_language IN ({$placeholders}) AND field_context LIKE 'post:%'",
$target_languages
);
$term_sql = $wpdb->prepare(
"SELECT COUNT(DISTINCT CONCAT(target_language, '|', SUBSTRING_INDEX(field_context, ':', 2)))
FROM {$table_name}
WHERE status = 'complete' AND target_language IN ({$placeholders}) AND field_context LIKE 'term:%'",
$target_languages
);
return array(
'posts' => (int) $wpdb->get_var( $post_sql ),
'terms' => (int) $wpdb->get_var( $term_sql ),
);
}
}