文章目录
-
- 在当今全球化的互联网环境中,多语言支持和实时互动功能已成为网站提升用户体验的关键要素。WordPress作为全球最流行的内容管理系统,其强大的插件架构为开发者提供了无限的可能性。本教程将深入探讨如何通过WordPress插件开发,集成网站实时翻译与多语言聊天工具,实现常用互联网小工具功能。 WordPress插件开发不仅仅是简单的功能添加,更是对现有系统进行二次开发,创造独特价值的过程。通过本教程,您将学习到如何从零开始构建一个功能全面的插件,将实时翻译和聊天工具无缝集成到您的WordPress网站中,从而提升网站的国际化水平和用户互动体验。
-
- WordPress插件系统基于PHP语言构建,采用事件驱动的钩子(Hooks)机制。插件通过动作(Actions)和过滤器(Filters)与WordPress核心进行交互,这种设计模式使得开发者可以在不修改核心代码的情况下扩展功能。 每个WordPress插件至少需要一个主文件,其中包含插件头部信息,用于向WordPress系统标识插件: <?php /** * Plugin Name: 多语言实时工具套件 * Plugin URI: https://yourwebsite.com/multilingual-tools * Description: 集成实时翻译与多语言聊天功能的WordPress插件 * Version: 1.0.0 * Author: 您的名字 * License: GPL v2 or later * Text Domain: multilingual-tools */
- 在开始插件开发前,需要搭建合适的开发环境: 本地开发环境:推荐使用XAMPP、MAMP或Local by Flywheel 代码编辑器:VS Code、PHPStorm或Sublime Text 调试工具:安装Query Monitor、Debug Bar等调试插件 版本控制:使用Git进行代码版本管理
- 合理的文件结构是插件可维护性的基础: multilingual-tools/ ├── multilingual-tools.php # 主插件文件 ├── includes/ # 核心功能文件 │ ├── class-translation-engine.php │ ├── class-chat-system.php │ └── class-admin-settings.php ├── assets/ # 静态资源 │ ├── css/ │ ├── js/ │ └── images/ ├── languages/ # 国际化文件 ├── templates/ # 前端模板 └── vendor/ # 第三方库
-
- 集成实时翻译功能首先需要选择合适的翻译API。目前市场上有多种选择: Google Cloud Translation API:准确度高,支持100多种语言 Microsoft Azure Translator:企业级解决方案,稳定性好 DeepL API:欧洲语言翻译质量优秀 百度翻译API:中文相关翻译效果较好 本教程将以Google Cloud Translation API为例,但代码设计将保持灵活性,便于切换不同服务商。
- 创建一个翻译引擎类,封装所有翻译相关功能: class MLT_Translation_Engine { private $api_key; private $api_endpoint = 'https://translation.googleapis.com/language/translate/v2'; public function __construct($api_key) { $this->api_key = $api_key; } /** * 检测文本语言 */ public function detect_language($text) { $response = wp_remote_post($this->api_endpoint . '/detect', [ 'body' => [ 'q' => $text, 'key' => $this->api_key ] ]); if (is_wp_error($response)) { return false; } $body = json_decode(wp_remote_retrieve_body($response), true); return isset($body['data']['detections'][0][0]['language']) ? $body['data']['detections'][0][0]['language'] : false; } /** * 执行翻译 */ public function translate($text, $target_language, $source_language = null) { $args = [ 'q' => $text, 'target' => $target_language, 'key' => $this->api_key ]; if ($source_language) { $args['source'] = $source_language; } $response = wp_remote_post($this->api_endpoint, [ 'body' => $args ]); if (is_wp_error($response)) { return $text; // 翻译失败时返回原文 } $body = json_decode(wp_remote_retrieve_body($response), true); return isset($body['data']['translations'][0]['translatedText']) ? $body['data']['translations'][0]['translatedText'] : $text; } /** * 批量翻译 */ public function translate_batch($texts, $target_language, $source_language = null) { $results = []; // 免费API通常有频率限制,这里添加延迟避免超限 foreach ($texts as $index => $text) { $results[$index] = $this->translate($text, $target_language, $source_language); // 每翻译5个文本暂停1秒 if ($index % 5 === 0 && $index > 0) { sleep(1); } } return $results; } }
- 在前端添加翻译控件,让用户可以选择翻译页面内容: class MLT_Frontend_Translator { public function __construct() { add_action('wp_footer', [$this, 'add_translation_widget']); add_action('wp_enqueue_scripts', [$this, 'enqueue_scripts']); add_action('wp_ajax_mlt_translate_content', [$this, 'ajax_translate_content']); add_action('wp_ajax_nopriv_mlt_translate_content', [$this, 'ajax_translate_content']); } public function enqueue_scripts() { wp_enqueue_style( 'mlt-frontend-style', plugin_dir_url(__FILE__) . '../assets/css/frontend.css', [], '1.0.0' ); wp_enqueue_script( 'mlt-frontend-script', plugin_dir_url(__FILE__) . '../assets/js/frontend.js', ['jquery'], '1.0.0', true ); wp_localize_script('mlt-frontend-script', 'mlt_ajax', [ 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('mlt_translate_nonce') ]); } public function add_translation_widget() { if (!is_singular()) return; $languages = [ 'en' => 'English', 'es' => 'Español', 'fr' => 'Français', 'de' => 'Deutsch', 'zh-CN' => '中文(简体)', 'ja' => '日本語' ]; include plugin_dir_path(__FILE__) . '../templates/translation-widget.php'; } public function ajax_translate_content() { // 验证nonce if (!wp_verify_nonce($_POST['nonce'], 'mlt_translate_nonce')) { wp_die('安全验证失败'); } $post_id = intval($_POST['post_id']); $target_lang = sanitize_text_field($_POST['target_lang']); $post = get_post($post_id); if (!$post) { wp_send_json_error('文章不存在'); } // 获取翻译引擎实例 $api_key = get_option('mlt_google_api_key'); $translator = new MLT_Translation_Engine($api_key); // 翻译标题和内容 $translated_title = $translator->translate($post->post_title, $target_lang); $translated_content = $translator->translate($post->post_content, $target_lang); wp_send_json_success([ 'title' => $translated_title, 'content' => apply_filters('the_content', $translated_content) ]); } }
-
- 多语言聊天系统需要处理实时通信、消息存储和语言转换。我们将采用以下架构: 前端界面:使用WebSocket或AJAX轮询实现实时通信 消息处理:PHP处理消息接收、存储和转发 数据库设计:创建自定义表存储聊天记录 翻译集成:在消息发送/接收时自动翻译
- 创建聊天消息数据库表: class MLT_Chat_Database { public static function create_tables() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $table_name = $wpdb->prefix . 'mlt_chat_messages'; $sql = "CREATE TABLE IF NOT EXISTS $table_name ( id bigint(20) NOT NULL AUTO_INCREMENT, session_id varchar(100) NOT NULL, sender_id bigint(20) DEFAULT 0, sender_type enum('user','admin') DEFAULT 'user', message_text text NOT NULL, original_language varchar(10) DEFAULT '', target_language varchar(10) DEFAULT '', translated_text text, is_translated tinyint(1) DEFAULT 0, timestamp datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY session_id (session_id), KEY timestamp (timestamp) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); } public static function save_message($data) { global $wpdb; $table_name = $wpdb->prefix . 'mlt_chat_messages'; return $wpdb->insert($table_name, $data); } public static function get_chat_history($session_id, $limit = 50) { global $wpdb; $table_name = $wpdb->prefix . 'mlt_chat_messages'; return $wpdb->get_results($wpdb->prepare( "SELECT * FROM $table_name WHERE session_id = %s ORDER BY timestamp ASC LIMIT %d", $session_id, $limit )); } }
- 使用AJAX轮询实现实时聊天功能(为简化示例,生产环境建议使用WebSocket): class MLT_Chat_System { private $translation_engine; public function __construct() { $api_key = get_option('mlt_google_api_key'); $this->translation_engine = new MLT_Translation_Engine($api_key); add_action('wp_ajax_mlt_send_message', [$this, 'handle_send_message']); add_action('wp_ajax_nopriv_mlt_send_message', [$this, 'handle_send_message']); add_action('wp_ajax_mlt_get_messages', [$this, 'handle_get_messages']); add_action('wp_ajax_nopriv_mlt_get_messages', [$this, 'handle_get_messages']); } public function handle_send_message() { // 验证nonce和安全检查 if (!wp_verify_nonce($_POST['nonce'], 'mlt_chat_nonce')) { wp_send_json_error('安全验证失败'); } $session_id = sanitize_text_field($_POST['session_id']); $message = sanitize_textarea_field($_POST['message']); $user_lang = sanitize_text_field($_POST['user_lang']); $target_lang = sanitize_text_field($_POST['target_lang']); // 检测消息语言 $detected_lang = $this->translation_engine->detect_language($message); // 如果需要翻译,则翻译消息 $translated_message = $message; if ($detected_lang && $detected_lang !== $target_lang) { $translated_message = $this->translation_engine->translate( $message, $target_lang, $detected_lang ); } // 保存消息到数据库 $message_id = MLT_Chat_Database::save_message([ 'session_id' => $session_id, 'sender_type' => 'user', 'message_text' => $message, 'original_language' => $detected_lang, 'target_language' => $target_lang, 'translated_text' => $translated_message, 'is_translated' => ($detected_lang !== $target_lang) ? 1 : 0 ]); if ($message_id) { // 这里可以添加通知管理员新消息的逻辑 wp_send_json_success([ 'message_id' => $message_id, 'translated_message' => $translated_message, 'timestamp' => current_time('mysql') ]); } else { wp_send_json_error('消息发送失败'); } } public function handle_get_messages() { $session_id = sanitize_text_field($_POST['session_id']); $last_message_id = intval($_POST['last_message_id']); global $wpdb; $table_name = $wpdb->prefix . 'mlt_chat_messages'; // 获取新消息 $new_messages = $wpdb->get_results($wpdb->prepare( "SELECT * FROM $table_name WHERE session_id = %s AND id > %d ORDER BY timestamp ASC", $session_id, $last_message_id )); wp_send_json_success([ 'messages' => $new_messages, 'count' => count($new_messages) ]); } }
- 创建美观的聊天界面: <!-- templates/chat-widget.php --> <div id="mlt-chat-widget" class="mlt-chat-container"> <div class="mlt-chat-header"> <h3>多语言在线客服</h3> <div class="mlt-language-selector"> <select id="mlt-chat-language"> <option value="auto">自动检测</option> <option value="zh-CN">中文</option> <option value="en">English</option> <option value="es">Español</option> <option value="fr">Français</option> <option value="de">Deutsch</option> <option value="ja">日本語</option> </select> </div> <button class="mlt-chat-close">×</button> </div> <div class="mlt-chat-messages"> <!-- 消息将在这里动态加载 --> <div class="mlt-welcome-message"> <p>您好!我是多语言客服助手。请选择您的语言开始聊天。</p> </div> </div> <div class="mlt-chat-input-area"> <textarea id="mlt-chat-input" placeholder="输入消息... (按Enter发送,Shift+Enter换行)" rows="2" ></textarea> <button id="mlt-send-button">发送</button> </div> </div> <button id="mlt-chat-toggle" class="mlt-chat-toggle-button"> <span class="mlt-chat-icon">💬</span> <span class="mlt-chat-label">在线聊天</span> </button>
-
- 创建完整的插件设置页面,让管理员可以配置API密钥和其他选项: class MLT_Admin_Settings { public function __construct() { add_action('admin_menu', [$this, 'add_admin_menu']); add_action('admin_init', [$this, 'register_settings']); add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_scripts']); } public function add_admin_menu() { add_menu_page( '多语言工具设置', '多语言工具', 'manage_options', 'mlt-settings', [$this, 'render_settings_page'], 'dashicons-translation', 80 ); add_submenu_page( 'mlt-settings', '聊天记录', '聊天记录', 'manage_options', 'mlt-chat-logs', [$this, 'render_chat_logs_page'] ); add_submenu_page( 'mlt-settings', '翻译统计', '翻译统计', 'manage_options', 'mlt-translation-stats', [$this, 'render_stats_page'] ); } public function register_settings() { register_setting('mlt_settings_group', 'mlt_google_api_key'); register_setting('mlt_settings_group', 'mlt_default_language'); register_setting('mlt_settings_group', 'mlt_chat_enabled'); register_setting('mlt_settings_group', 'mlt_translation_enabled'); register_setting('mlt_settings_group', 'mlt_supported_languages'); add_settings_section( 'mlt_api_section', 'API设置', [$this, 'render_api_section'], 'mlt-settings' ); add_settings_field( 'mlt_google_api_key', 'Google翻译API密钥', [$this, 'render_api_key_field'], 'mlt-settings', 'mlt_api_section' );
- public function render_api_section() { echo '<p>配置翻译和聊天功能所需的API密钥和基本设置。</p>'; } public function render_api_key_field() { $api_key = get_option('mlt_google_api_key', ''); echo '<input type="password" id="mlt_google_api_key" name="mlt_google_api_key" value="' . esc_attr($api_key) . '" class="regular-text" /> <p class="description">获取Google Cloud Translation API密钥:<a href="https://cloud.google.com/translate/docs/setup" target="_blank">点击这里</a></p>'; } public function render_settings_page() { if (!current_user_can('manage_options')) { return; } // 检查API密钥是否有效 $api_key = get_option('mlt_google_api_key'); $api_status = $this->check_api_status($api_key); ?> <div class="wrap"> <h1><?php echo esc_html(get_admin_page_title()); ?></h1> <?php if ($api_status['valid'] === false): ?> <div class="notice notice-error"> <p><?php echo esc_html($api_status['message']); ?></p> </div> <?php endif; ?> <form action="options.php" method="post"> <?php settings_fields('mlt_settings_group'); do_settings_sections('mlt-settings'); submit_button('保存设置'); ?> </form> <div class="mlt-settings-extra"> <h2>功能测试</h2> <div class="mlt-test-area"> <h3>翻译功能测试</h3> <textarea id="mlt-test-text" rows="3" class="large-text" placeholder="输入要测试翻译的文本..."></textarea> <select id="mlt-test-target-lang"> <option value="en">英语</option> <option value="es">西班牙语</option> <option value="fr">法语</option> <option value="zh-CN">中文</option> </select> <button id="mlt-test-translate" class="button button-secondary">测试翻译</button> <div id="mlt-test-result" class="mlt-test-result"></div> </div> </div> </div> <?php } private function check_api_status($api_key) { if (empty($api_key)) { return ['valid' => false, 'message' => 'API密钥未设置']; } // 简单的API测试 $test_url = 'https://translation.googleapis.com/language/translate/v2/languages?key=' . $api_key; $response = wp_remote_get($test_url); if (is_wp_error($response)) { return ['valid' => false, 'message' => '网络连接错误: ' . $response->get_error_message()]; } $status_code = wp_remote_retrieve_response_code($response); if ($status_code === 200) { return ['valid' => true, 'message' => 'API连接正常']; } elseif ($status_code === 403) { return ['valid' => false, 'message' => 'API密钥无效或未启用翻译API服务']; } else { return ['valid' => false, 'message' => 'API连接失败,状态码: ' . $status_code]; } } public function render_chat_logs_page() { if (!current_user_can('manage_options')) { return; } global $wpdb; $table_name = $wpdb->prefix . 'mlt_chat_messages'; // 分页参数 $per_page = 20; $current_page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1; $offset = ($current_page - 1) * $per_page; // 获取聊天会话列表 $sessions = $wpdb->get_results( "SELECT session_id, COUNT(*) as message_count, MIN(timestamp) as start_time, MAX(timestamp) as end_time FROM $table_name GROUP BY session_id ORDER BY end_time DESC LIMIT $offset, $per_page" ); $total_sessions = $wpdb->get_var("SELECT COUNT(DISTINCT session_id) FROM $table_name"); $total_pages = ceil($total_sessions / $per_page); ?> <div class="wrap"> <h1>聊天记录管理</h1> <table class="wp-list-table widefat fixed striped"> <thead> <tr> <th>会话ID</th> <th>消息数量</th> <th>开始时间</th> <th>最后活动</th> <th>操作</th> </tr> </thead> <tbody> <?php if (empty($sessions)): ?> <tr> <td colspan="5">暂无聊天记录</td> </tr> <?php else: ?> <?php foreach ($sessions as $session): ?> <tr> <td><?php echo esc_html($session->session_id); ?></td> <td><?php echo intval($session->message_count); ?></td> <td><?php echo esc_html($session->start_time); ?></td> <td><?php echo esc_html($session->end_time); ?></td> <td> <a href="#" class="button button-small view-chat-details" data-session="<?php echo esc_attr($session->session_id); ?>"> 查看详情 </a> <a href="<?php echo wp_nonce_url( admin_url('admin.php?page=mlt-chat-logs&action=delete_session&session_id=' . $session->session_id), 'delete_chat_session' ); ?>" class="button button-small button-link-delete" onclick="return confirm('确定删除此会话的所有记录吗?')"> 删除 </a> </td> </tr> <?php endforeach; ?> <?php endif; ?> </tbody> </table> <?php if ($total_pages > 1): ?> <div class="tablenav bottom"> <div class="tablenav-pages"> <?php echo paginate_links([ 'base' => add_query_arg('paged', '%#%'), 'format' => '', 'prev_text' => '«', 'next_text' => '»', 'total' => $total_pages, 'current' => $current_page ]); ?> </div> </div> <?php endif; ?> <!-- 聊天详情模态框 --> <div id="mlt-chat-details-modal" class="mlt-modal" style="display:none;"> <div class="mlt-modal-content"> <div class="mlt-modal-header"> <h3>聊天详情 - <span id="modal-session-id"></span></h3> <span class="mlt-modal-close">×</span> </div> <div class="mlt-modal-body"> <div id="mlt-chat-details-content"></div> </div> </div> </div> </div> <?php } }
-
- 为了减少API调用次数和提高性能,实现翻译缓存: class MLT_Translation_Cache { private $cache_group = 'mlt_translations'; private $cache_expiry = WEEK_IN_SECONDS; // 缓存一周 public function get_cached_translation($text, $target_lang, $source_lang = null) { $cache_key = $this->generate_cache_key($text, $target_lang, $source_lang); $cached = wp_cache_get($cache_key, $this->cache_group); if ($cached !== false) { return $cached; } // 检查数据库缓存 global $wpdb; $table_name = $wpdb->prefix . 'mlt_translation_cache'; $result = $wpdb->get_row($wpdb->prepare( "SELECT translated_text FROM $table_name WHERE original_text_hash = %s AND target_language = %s AND (source_language = %s OR source_language IS NULL) AND expiry_time > NOW()", md5($text), $target_lang, $source_lang )); if ($result) { wp_cache_set($cache_key, $result->translated_text, $this->cache_group, $this->cache_expiry); return $result->translated_text; } return false; } public function cache_translation($text, $translated_text, $target_lang, $source_lang = null) { $cache_key = $this->generate_cache_key($text, $target_lang, $source_lang); // 设置内存缓存 wp_cache_set($cache_key, $translated_text, $this->cache_group, $this->cache_expiry); // 存储到数据库 global $wpdb; $table_name = $wpdb->prefix . 'mlt_translation_cache'; $wpdb->replace($table_name, [ 'original_text_hash' => md5($text), 'original_text' => $text, 'translated_text' => $translated_text, 'source_language' => $source_lang, 'target_language' => $target_lang, 'expiry_time' => date('Y-m-d H:i:s', time() + $this->cache_expiry), 'created_at' => current_time('mysql') ]); } private function generate_cache_key($text, $target_lang, $source_lang) { return 'trans_' . md5($text . $target_lang . $source_lang); } public static function create_cache_table() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $table_name = $wpdb->prefix . 'mlt_translation_cache'; $sql = "CREATE TABLE IF NOT EXISTS $table_name ( id bigint(20) NOT NULL AUTO_INCREMENT, original_text_hash varchar(32) NOT NULL, original_text text NOT NULL, translated_text text NOT NULL, source_language varchar(10), target_language varchar(10) NOT NULL, expiry_time datetime NOT NULL, created_at datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY text_hash_lang (original_text_hash, target_language, source_language), KEY expiry_time (expiry_time) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); } }
- 对于大量翻译请求,使用异步处理避免阻塞: class MLT_Async_Processor { private $queue_table; public function __construct() { global $wpdb; $this->queue_table = $wpdb->prefix . 'mlt_async_queue'; add_action('mlt_process_queue', [$this, 'process_queue']); add_action('wp_ajax_nopriv_mlt_async_translate', [$this, 'handle_async_translate']); } public function add_translation_job($data) { global $wpdb; return $wpdb->insert($this->queue_table, [ 'job_type' => 'translation', 'job_data' => json_encode($data), 'status' => 'pending', 'created_at' => current_time('mysql') ]); } public function process_queue() { global $wpdb; // 获取待处理的任务 $jobs = $wpdb->get_results( "SELECT * FROM {$this->queue_table} WHERE status = 'pending' ORDER BY created_at ASC LIMIT 10" ); foreach ($jobs as $job) { $this->process_job($job); } } private function process_job($job) { global $wpdb; $job_data = json_decode($job->job_data, true); try { // 更新状态为处理中 $wpdb->update( $this->queue_table, ['status' => 'processing'], ['id' => $job->id] ); // 执行翻译 $api_key = get_option('mlt_google_api_key'); $translator = new MLT_Translation_Engine($api_key); $result = $translator->translate( $job_data['text'], $job_data['target_lang'], $job_data['source_lang'] ?? null ); // 更新状态为完成 $wpdb->update( $this->queue_table, [ 'status' => 'completed', 'result_data' => json_encode(['translated_text' => $result]), 'completed_at' => current_time('mysql') ], ['id' => $job->id] ); } catch (Exception $e) { $wpdb->update( $this->queue_table, [ 'status' => 'failed', 'error_message' => $e->getMessage(), 'completed_at' => current_time('mysql') ], ['id' => $job->id] ); } } public static function create_queue_table() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $table_name = $wpdb->prefix . 'mlt_async_queue'; $sql = "CREATE TABLE IF NOT EXISTS $table_name ( id bigint(20) NOT NULL AUTO_INCREMENT, job_type varchar(50) NOT NULL, job_data text NOT NULL, status varchar(20) DEFAULT 'pending', result_data text, error_message text, created_at datetime DEFAULT CURRENT_TIMESTAMP, completed_at datetime, PRIMARY KEY (id), KEY status (status), KEY job_type (job_type) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); } }
- class MLT_Security_Manager { public static function sanitize_chat_input($input) { // 移除危险标签但保留基本格式 $allowed_tags = [ 'b' => [], 'i' => [], 'u' => [], 'em' => [], 'strong' => [], 'br' => [], 'p' => [], 'span' => ['class' => []] ]; $sanitized = wp_kses($input, $allowed_tags); // 限制长度 if (strlen($sanitized) > 1000) { $sanitized = substr($sanitized, 0, 1000); } return $sanitized; } public static function validate_language_code($lang_code) { $supported_languages = [ 'en', 'es', 'fr', 'de', 'zh-CN', 'zh-TW', 'ja', 'ko', 'ru', 'ar', 'pt', 'it', 'nl', 'pl', 'tr', 'th', 'vi' ]; return in_array($lang_code, $supported_languages) ? $lang_code : 'en'; } public static function prevent_flood_attack($session_id, $limit = 10, $time_window = 60) { $transient_key = 'mlt_chat_flood_' . md5($session_id); $request_count = get_transient($transient_key); if ($request_count === false) { set_transient($transient_key, 1, $time_window); return true; } if ($request_count >= $limit) { return false; } set_transient($transient_key, $request_count + 1, $time_window); return true; } public static function encrypt_sensitive_data($data) { if (!extension_loaded('openssl')) { return $data; // 回退到基本编码 } $method = 'AES-256-CBC'; $key = defined('MLT_ENCRYPTION_KEY') ? MLT_ENCRYPTION_KEY : wp_salt(); $iv_length = openssl_cipher_iv_length($method); $iv = openssl_random_pseudo_bytes($iv_length); $encrypted = openssl_encrypt($data, $method, $key, 0, $iv); return base64_encode($iv . $encrypted); } }
在当今全球化的互联网环境中,多语言支持和实时互动功能已成为网站提升用户体验的关键要素。WordPress作为全球最流行的内容管理系统,其强大的插件架构为开发者提供了无限的可能性。本教程将深入探讨如何通过WordPress插件开发,集成网站实时翻译与多语言聊天工具,实现常用互联网小工具功能。
WordPress插件开发不仅仅是简单的功能添加,更是对现有系统进行二次开发,创造独特价值的过程。通过本教程,您将学习到如何从零开始构建一个功能全面的插件,将实时翻译和聊天工具无缝集成到您的WordPress网站中,从而提升网站的国际化水平和用户互动体验。
WordPress插件系统基于PHP语言构建,采用事件驱动的钩子(Hooks)机制。插件通过动作(Actions)和过滤器(Filters)与WordPress核心进行交互,这种设计模式使得开发者可以在不修改核心代码的情况下扩展功能。
每个WordPress插件至少需要一个主文件,其中包含插件头部信息,用于向WordPress系统标识插件:
<?php
/**
* Plugin Name: 多语言实时工具套件
* Plugin URI: https://yourwebsite.com/multilingual-tools
* Description: 集成实时翻译与多语言聊天功能的WordPress插件
* Version: 1.0.0
* Author: 您的名字
* License: GPL v2 or later
* Text Domain: multilingual-tools
*/
在开始插件开发前,需要搭建合适的开发环境:
- 本地开发环境:推荐使用XAMPP、MAMP或Local by Flywheel
- 代码编辑器:VS Code、PHPStorm或Sublime Text
- 调试工具:安装Query Monitor、Debug Bar等调试插件
- 版本控制:使用Git进行代码版本管理
合理的文件结构是插件可维护性的基础:
multilingual-tools/
├── multilingual-tools.php # 主插件文件
├── includes/ # 核心功能文件
│ ├── class-translation-engine.php
│ ├── class-chat-system.php
│ └── class-admin-settings.php
├── assets/ # 静态资源
│ ├── css/
│ ├── js/
│ └── images/
├── languages/ # 国际化文件
├── templates/ # 前端模板
└── vendor/ # 第三方库
集成实时翻译功能首先需要选择合适的翻译API。目前市场上有多种选择:
- Google Cloud Translation API:准确度高,支持100多种语言
- Microsoft Azure Translator:企业级解决方案,稳定性好
- DeepL API:欧洲语言翻译质量优秀
- 百度翻译API:中文相关翻译效果较好
本教程将以Google Cloud Translation API为例,但代码设计将保持灵活性,便于切换不同服务商。
创建一个翻译引擎类,封装所有翻译相关功能:
class MLT_Translation_Engine {
private $api_key;
private $api_endpoint = 'https://translation.googleapis.com/language/translate/v2';
public function __construct($api_key) {
$this->api_key = $api_key;
}
/**
* 检测文本语言
*/
public function detect_language($text) {
$response = wp_remote_post($this->api_endpoint . '/detect', [
'body' => [
'q' => $text,
'key' => $this->api_key
]
]);
if (is_wp_error($response)) {
return false;
}
$body = json_decode(wp_remote_retrieve_body($response), true);
return isset($body['data']['detections'][0][0]['language'])
? $body['data']['detections'][0][0]['language']
: false;
}
/**
* 执行翻译
*/
public function translate($text, $target_language, $source_language = null) {
$args = [
'q' => $text,
'target' => $target_language,
'key' => $this->api_key
];
if ($source_language) {
$args['source'] = $source_language;
}
$response = wp_remote_post($this->api_endpoint, [
'body' => $args
]);
if (is_wp_error($response)) {
return $text; // 翻译失败时返回原文
}
$body = json_decode(wp_remote_retrieve_body($response), true);
return isset($body['data']['translations'][0]['translatedText'])
? $body['data']['translations'][0]['translatedText']
: $text;
}
/**
* 批量翻译
*/
public function translate_batch($texts, $target_language, $source_language = null) {
$results = [];
// 免费API通常有频率限制,这里添加延迟避免超限
foreach ($texts as $index => $text) {
$results[$index] = $this->translate($text, $target_language, $source_language);
// 每翻译5个文本暂停1秒
if ($index % 5 === 0 && $index > 0) {
sleep(1);
}
}
return $results;
}
}
在前端添加翻译控件,让用户可以选择翻译页面内容:
class MLT_Frontend_Translator {
public function __construct() {
add_action('wp_footer', [$this, 'add_translation_widget']);
add_action('wp_enqueue_scripts', [$this, 'enqueue_scripts']);
add_action('wp_ajax_mlt_translate_content', [$this, 'ajax_translate_content']);
add_action('wp_ajax_nopriv_mlt_translate_content', [$this, 'ajax_translate_content']);
}
public function enqueue_scripts() {
wp_enqueue_style(
'mlt-frontend-style',
plugin_dir_url(__FILE__) . '../assets/css/frontend.css',
[],
'1.0.0'
);
wp_enqueue_script(
'mlt-frontend-script',
plugin_dir_url(__FILE__) . '../assets/js/frontend.js',
['jquery'],
'1.0.0',
true
);
wp_localize_script('mlt-frontend-script', 'mlt_ajax', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('mlt_translate_nonce')
]);
}
public function add_translation_widget() {
if (!is_singular()) return;
$languages = [
'en' => 'English',
'es' => 'Español',
'fr' => 'Français',
'de' => 'Deutsch',
'zh-CN' => '中文(简体)',
'ja' => '日本語'
];
include plugin_dir_path(__FILE__) . '../templates/translation-widget.php';
}
public function ajax_translate_content() {
// 验证nonce
if (!wp_verify_nonce($_POST['nonce'], 'mlt_translate_nonce')) {
wp_die('安全验证失败');
}
$post_id = intval($_POST['post_id']);
$target_lang = sanitize_text_field($_POST['target_lang']);
$post = get_post($post_id);
if (!$post) {
wp_send_json_error('文章不存在');
}
// 获取翻译引擎实例
$api_key = get_option('mlt_google_api_key');
$translator = new MLT_Translation_Engine($api_key);
// 翻译标题和内容
$translated_title = $translator->translate($post->post_title, $target_lang);
$translated_content = $translator->translate($post->post_content, $target_lang);
wp_send_json_success([
'title' => $translated_title,
'content' => apply_filters('the_content', $translated_content)
]);
}
}
多语言聊天系统需要处理实时通信、消息存储和语言转换。我们将采用以下架构:
- 前端界面:使用WebSocket或AJAX轮询实现实时通信
- 消息处理:PHP处理消息接收、存储和转发
- 数据库设计:创建自定义表存储聊天记录
- 翻译集成:在消息发送/接收时自动翻译
创建聊天消息数据库表:
class MLT_Chat_Database {
public static function create_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name = $wpdb->prefix . 'mlt_chat_messages';
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id bigint(20) NOT NULL AUTO_INCREMENT,
session_id varchar(100) NOT NULL,
sender_id bigint(20) DEFAULT 0,
sender_type enum('user','admin') DEFAULT 'user',
message_text text NOT NULL,
original_language varchar(10) DEFAULT '',
target_language varchar(10) DEFAULT '',
translated_text text,
is_translated tinyint(1) DEFAULT 0,
timestamp datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY session_id (session_id),
KEY timestamp (timestamp)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
public static function save_message($data) {
global $wpdb;
$table_name = $wpdb->prefix . 'mlt_chat_messages';
return $wpdb->insert($table_name, $data);
}
public static function get_chat_history($session_id, $limit = 50) {
global $wpdb;
$table_name = $wpdb->prefix . 'mlt_chat_messages';
return $wpdb->get_results($wpdb->prepare(
"SELECT * FROM $table_name
WHERE session_id = %s
ORDER BY timestamp ASC
LIMIT %d",
$session_id, $limit
));
}
}
使用AJAX轮询实现实时聊天功能(为简化示例,生产环境建议使用WebSocket):
class MLT_Chat_System {
private $translation_engine;
public function __construct() {
$api_key = get_option('mlt_google_api_key');
$this->translation_engine = new MLT_Translation_Engine($api_key);
add_action('wp_ajax_mlt_send_message', [$this, 'handle_send_message']);
add_action('wp_ajax_nopriv_mlt_send_message', [$this, 'handle_send_message']);
add_action('wp_ajax_mlt_get_messages', [$this, 'handle_get_messages']);
add_action('wp_ajax_nopriv_mlt_get_messages', [$this, 'handle_get_messages']);
}
public function handle_send_message() {
// 验证nonce和安全检查
if (!wp_verify_nonce($_POST['nonce'], 'mlt_chat_nonce')) {
wp_send_json_error('安全验证失败');
}
$session_id = sanitize_text_field($_POST['session_id']);
$message = sanitize_textarea_field($_POST['message']);
$user_lang = sanitize_text_field($_POST['user_lang']);
$target_lang = sanitize_text_field($_POST['target_lang']);
// 检测消息语言
$detected_lang = $this->translation_engine->detect_language($message);
// 如果需要翻译,则翻译消息
$translated_message = $message;
if ($detected_lang && $detected_lang !== $target_lang) {
$translated_message = $this->translation_engine->translate(
$message,
$target_lang,
$detected_lang
);
}
// 保存消息到数据库
$message_id = MLT_Chat_Database::save_message([
'session_id' => $session_id,
'sender_type' => 'user',
'message_text' => $message,
'original_language' => $detected_lang,
'target_language' => $target_lang,
'translated_text' => $translated_message,
'is_translated' => ($detected_lang !== $target_lang) ? 1 : 0
]);
if ($message_id) {
// 这里可以添加通知管理员新消息的逻辑
wp_send_json_success([
'message_id' => $message_id,
'translated_message' => $translated_message,
'timestamp' => current_time('mysql')
]);
} else {
wp_send_json_error('消息发送失败');
}
}
public function handle_get_messages() {
$session_id = sanitize_text_field($_POST['session_id']);
$last_message_id = intval($_POST['last_message_id']);
global $wpdb;
$table_name = $wpdb->prefix . 'mlt_chat_messages';
// 获取新消息
$new_messages = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM $table_name
WHERE session_id = %s AND id > %d
ORDER BY timestamp ASC",
$session_id, $last_message_id
));
wp_send_json_success([
'messages' => $new_messages,
'count' => count($new_messages)
]);
}
}
创建美观的聊天界面:
<!-- templates/chat-widget.php -->
<div id="mlt-chat-widget" class="mlt-chat-container">
<div class="mlt-chat-header">
<h3>多语言在线客服</h3>
<div class="mlt-language-selector">
<select id="mlt-chat-language">
<option value="auto">自动检测</option>
<option value="zh-CN">中文</option>
<option value="en">English</option>
<option value="es">Español</option>
<option value="fr">Français</option>
<option value="de">Deutsch</option>
<option value="ja">日本語</option>
</select>
</div>
<button class="mlt-chat-close">×</button>
</div>
<div class="mlt-chat-messages">
<!-- 消息将在这里动态加载 -->
<div class="mlt-welcome-message">
<p>您好!我是多语言客服助手。请选择您的语言开始聊天。</p>
</div>
</div>
<div class="mlt-chat-input-area">
<textarea
id="mlt-chat-input"
placeholder="输入消息... (按Enter发送,Shift+Enter换行)"
rows="2"
></textarea>
<button id="mlt-send-button">发送</button>
</div>
</div>
<button id="mlt-chat-toggle" class="mlt-chat-toggle-button">
<span class="mlt-chat-icon">💬</span>
<span class="mlt-chat-label">在线聊天</span>
</button>
创建完整的插件设置页面,让管理员可以配置API密钥和其他选项:
class MLT_Admin_Settings {
public function __construct() {
add_action('admin_menu', [$this, 'add_admin_menu']);
add_action('admin_init', [$this, 'register_settings']);
add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_scripts']);
}
public function add_admin_menu() {
add_menu_page(
'多语言工具设置',
'多语言工具',
'manage_options',
'mlt-settings',
[$this, 'render_settings_page'],
'dashicons-translation',
80
);
add_submenu_page(
'mlt-settings',
'聊天记录',
'聊天记录',
'manage_options',
'mlt-chat-logs',
[$this, 'render_chat_logs_page']
);
add_submenu_page(
'mlt-settings',
'翻译统计',
'翻译统计',
'manage_options',
'mlt-translation-stats',
[$this, 'render_stats_page']
);
}
public function register_settings() {
register_setting('mlt_settings_group', 'mlt_google_api_key');
register_setting('mlt_settings_group', 'mlt_default_language');
register_setting('mlt_settings_group', 'mlt_chat_enabled');
register_setting('mlt_settings_group', 'mlt_translation_enabled');
register_setting('mlt_settings_group', 'mlt_supported_languages');
add_settings_section(
'mlt_api_section',
'API设置',
[$this, 'render_api_section'],
'mlt-settings'
);
add_settings_field(
'mlt_google_api_key',
'Google翻译API密钥',
[$this, 'render_api_key_field'],
'mlt-settings',
'mlt_api_section'
);
public function render_api_section() {
echo '<p>配置翻译和聊天功能所需的API密钥和基本设置。</p>';
}
public function render_api_key_field() {
$api_key = get_option('mlt_google_api_key', '');
echo '<input type="password" id="mlt_google_api_key"
name="mlt_google_api_key" value="' . esc_attr($api_key) . '"
class="regular-text" />
<p class="description">获取Google Cloud Translation API密钥:<a href="https://cloud.google.com/translate/docs/setup" target="_blank">点击这里</a></p>';
}
public function render_settings_page() {
if (!current_user_can('manage_options')) {
return;
}
// 检查API密钥是否有效
$api_key = get_option('mlt_google_api_key');
$api_status = $this->check_api_status($api_key);
?>
<div class="wrap">
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
<?php if ($api_status['valid'] === false): ?>
<div class="notice notice-error">
<p><?php echo esc_html($api_status['message']); ?></p>
</div>
<?php endif; ?>
<form action="options.php" method="post">
<?php
settings_fields('mlt_settings_group');
do_settings_sections('mlt-settings');
submit_button('保存设置');
?>
</form>
<div class="mlt-settings-extra">
<h2>功能测试</h2>
<div class="mlt-test-area">
<h3>翻译功能测试</h3>
<textarea id="mlt-test-text" rows="3" class="large-text" placeholder="输入要测试翻译的文本..."></textarea>
<select id="mlt-test-target-lang">
<option value="en">英语</option>
<option value="es">西班牙语</option>
<option value="fr">法语</option>
<option value="zh-CN">中文</option>
</select>
<button id="mlt-test-translate" class="button button-secondary">测试翻译</button>
<div id="mlt-test-result" class="mlt-test-result"></div>
</div>
</div>
</div>
<?php
}
private function check_api_status($api_key) {
if (empty($api_key)) {
return ['valid' => false, 'message' => 'API密钥未设置'];
}
// 简单的API测试
$test_url = 'https://translation.googleapis.com/language/translate/v2/languages?key=' . $api_key;
$response = wp_remote_get($test_url);
if (is_wp_error($response)) {
return ['valid' => false, 'message' => '网络连接错误: ' . $response->get_error_message()];
}
$status_code = wp_remote_retrieve_response_code($response);
if ($status_code === 200) {
return ['valid' => true, 'message' => 'API连接正常'];
} elseif ($status_code === 403) {
return ['valid' => false, 'message' => 'API密钥无效或未启用翻译API服务'];
} else {
return ['valid' => false, 'message' => 'API连接失败,状态码: ' . $status_code];
}
}
public function render_chat_logs_page() {
if (!current_user_can('manage_options')) {
return;
}
global $wpdb;
$table_name = $wpdb->prefix . 'mlt_chat_messages';
// 分页参数
$per_page = 20;
$current_page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1;
$offset = ($current_page - 1) * $per_page;
// 获取聊天会话列表
$sessions = $wpdb->get_results(
"SELECT session_id, COUNT(*) as message_count,
MIN(timestamp) as start_time, MAX(timestamp) as end_time
FROM $table_name
GROUP BY session_id
ORDER BY end_time DESC
LIMIT $offset, $per_page"
);
$total_sessions = $wpdb->get_var("SELECT COUNT(DISTINCT session_id) FROM $table_name");
$total_pages = ceil($total_sessions / $per_page);
?>
<div class="wrap">
<h1>聊天记录管理</h1>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th>会话ID</th>
<th>消息数量</th>
<th>开始时间</th>
<th>最后活动</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php if (empty($sessions)): ?>
<tr>
<td colspan="5">暂无聊天记录</td>
</tr>
<?php else: ?>
<?php foreach ($sessions as $session): ?>
<tr>
<td><?php echo esc_html($session->session_id); ?></td>
<td><?php echo intval($session->message_count); ?></td>
<td><?php echo esc_html($session->start_time); ?></td>
<td><?php echo esc_html($session->end_time); ?></td>
<td>
<a href="#" class="button button-small view-chat-details"
data-session="<?php echo esc_attr($session->session_id); ?>">
查看详情
</a>
<a href="<?php echo wp_nonce_url(
admin_url('admin.php?page=mlt-chat-logs&action=delete_session&session_id=' . $session->session_id),
'delete_chat_session'
); ?>" class="button button-small button-link-delete"
onclick="return confirm('确定删除此会话的所有记录吗?')">
删除
</a>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
<?php if ($total_pages > 1): ?>
<div class="tablenav bottom">
<div class="tablenav-pages">
<?php
echo paginate_links([
'base' => add_query_arg('paged', '%#%'),
'format' => '',
'prev_text' => '«',
'next_text' => '»',
'total' => $total_pages,
'current' => $current_page
]);
?>
</div>
</div>
<?php endif; ?>
<!-- 聊天详情模态框 -->
<div id="mlt-chat-details-modal" class="mlt-modal" style="display:none;">
<div class="mlt-modal-content">
<div class="mlt-modal-header">
<h3>聊天详情 - <span id="modal-session-id"></span></h3>
<span class="mlt-modal-close">×</span>
</div>
<div class="mlt-modal-body">
<div id="mlt-chat-details-content"></div>
</div>
</div>
</div>
</div>
<?php
}
}
public function render_api_section() {
echo '<p>配置翻译和聊天功能所需的API密钥和基本设置。</p>';
}
public function render_api_key_field() {
$api_key = get_option('mlt_google_api_key', '');
echo '<input type="password" id="mlt_google_api_key"
name="mlt_google_api_key" value="' . esc_attr($api_key) . '"
class="regular-text" />
<p class="description">获取Google Cloud Translation API密钥:<a href="https://cloud.google.com/translate/docs/setup" target="_blank">点击这里</a></p>';
}
public function render_settings_page() {
if (!current_user_can('manage_options')) {
return;
}
// 检查API密钥是否有效
$api_key = get_option('mlt_google_api_key');
$api_status = $this->check_api_status($api_key);
?>
<div class="wrap">
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
<?php if ($api_status['valid'] === false): ?>
<div class="notice notice-error">
<p><?php echo esc_html($api_status['message']); ?></p>
</div>
<?php endif; ?>
<form action="options.php" method="post">
<?php
settings_fields('mlt_settings_group');
do_settings_sections('mlt-settings');
submit_button('保存设置');
?>
</form>
<div class="mlt-settings-extra">
<h2>功能测试</h2>
<div class="mlt-test-area">
<h3>翻译功能测试</h3>
<textarea id="mlt-test-text" rows="3" class="large-text" placeholder="输入要测试翻译的文本..."></textarea>
<select id="mlt-test-target-lang">
<option value="en">英语</option>
<option value="es">西班牙语</option>
<option value="fr">法语</option>
<option value="zh-CN">中文</option>
</select>
<button id="mlt-test-translate" class="button button-secondary">测试翻译</button>
<div id="mlt-test-result" class="mlt-test-result"></div>
</div>
</div>
</div>
<?php
}
private function check_api_status($api_key) {
if (empty($api_key)) {
return ['valid' => false, 'message' => 'API密钥未设置'];
}
// 简单的API测试
$test_url = 'https://translation.googleapis.com/language/translate/v2/languages?key=' . $api_key;
$response = wp_remote_get($test_url);
if (is_wp_error($response)) {
return ['valid' => false, 'message' => '网络连接错误: ' . $response->get_error_message()];
}
$status_code = wp_remote_retrieve_response_code($response);
if ($status_code === 200) {
return ['valid' => true, 'message' => 'API连接正常'];
} elseif ($status_code === 403) {
return ['valid' => false, 'message' => 'API密钥无效或未启用翻译API服务'];
} else {
return ['valid' => false, 'message' => 'API连接失败,状态码: ' . $status_code];
}
}
public function render_chat_logs_page() {
if (!current_user_can('manage_options')) {
return;
}
global $wpdb;
$table_name = $wpdb->prefix . 'mlt_chat_messages';
// 分页参数
$per_page = 20;
$current_page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1;
$offset = ($current_page - 1) * $per_page;
// 获取聊天会话列表
$sessions = $wpdb->get_results(
"SELECT session_id, COUNT(*) as message_count,
MIN(timestamp) as start_time, MAX(timestamp) as end_time
FROM $table_name
GROUP BY session_id
ORDER BY end_time DESC
LIMIT $offset, $per_page"
);
$total_sessions = $wpdb->get_var("SELECT COUNT(DISTINCT session_id) FROM $table_name");
$total_pages = ceil($total_sessions / $per_page);
?>
<div class="wrap">
<h1>聊天记录管理</h1>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th>会话ID</th>
<th>消息数量</th>
<th>开始时间</th>
<th>最后活动</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php if (empty($sessions)): ?>
<tr>
<td colspan="5">暂无聊天记录</td>
</tr>
<?php else: ?>
<?php foreach ($sessions as $session): ?>
<tr>
<td><?php echo esc_html($session->session_id); ?></td>
<td><?php echo intval($session->message_count); ?></td>
<td><?php echo esc_html($session->start_time); ?></td>
<td><?php echo esc_html($session->end_time); ?></td>
<td>
<a href="#" class="button button-small view-chat-details"
data-session="<?php echo esc_attr($session->session_id); ?>">
查看详情
</a>
<a href="<?php echo wp_nonce_url(
admin_url('admin.php?page=mlt-chat-logs&action=delete_session&session_id=' . $session->session_id),
'delete_chat_session'
); ?>" class="button button-small button-link-delete"
onclick="return confirm('确定删除此会话的所有记录吗?')">
删除
</a>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
<?php if ($total_pages > 1): ?>
<div class="tablenav bottom">
<div class="tablenav-pages">
<?php
echo paginate_links([
'base' => add_query_arg('paged', '%#%'),
'format' => '',
'prev_text' => '«',
'next_text' => '»',
'total' => $total_pages,
'current' => $current_page
]);
?>
</div>
</div>
<?php endif; ?>
<!-- 聊天详情模态框 -->
<div id="mlt-chat-details-modal" class="mlt-modal" style="display:none;">
<div class="mlt-modal-content">
<div class="mlt-modal-header">
<h3>聊天详情 - <span id="modal-session-id"></span></h3>
<span class="mlt-modal-close">×</span>
</div>
<div class="mlt-modal-body">
<div id="mlt-chat-details-content"></div>
</div>
</div>
</div>
</div>
<?php
}
}
为了减少API调用次数和提高性能,实现翻译缓存:
class MLT_Translation_Cache {
private $cache_group = 'mlt_translations';
private $cache_expiry = WEEK_IN_SECONDS; // 缓存一周
public function get_cached_translation($text, $target_lang, $source_lang = null) {
$cache_key = $this->generate_cache_key($text, $target_lang, $source_lang);
$cached = wp_cache_get($cache_key, $this->cache_group);
if ($cached !== false) {
return $cached;
}
// 检查数据库缓存
global $wpdb;
$table_name = $wpdb->prefix . 'mlt_translation_cache';
$result = $wpdb->get_row($wpdb->prepare(
"SELECT translated_text FROM $table_name
WHERE original_text_hash = %s
AND target_language = %s
AND (source_language = %s OR source_language IS NULL)
AND expiry_time > NOW()",
md5($text),
$target_lang,
$source_lang
));
if ($result) {
wp_cache_set($cache_key, $result->translated_text, $this->cache_group, $this->cache_expiry);
return $result->translated_text;
}
return false;
}
public function cache_translation($text, $translated_text, $target_lang, $source_lang = null) {
$cache_key = $this->generate_cache_key($text, $target_lang, $source_lang);
// 设置内存缓存
wp_cache_set($cache_key, $translated_text, $this->cache_group, $this->cache_expiry);
// 存储到数据库
global $wpdb;
$table_name = $wpdb->prefix . 'mlt_translation_cache';
$wpdb->replace($table_name, [
'original_text_hash' => md5($text),
'original_text' => $text,
'translated_text' => $translated_text,
'source_language' => $source_lang,
'target_language' => $target_lang,
'expiry_time' => date('Y-m-d H:i:s', time() + $this->cache_expiry),
'created_at' => current_time('mysql')
]);
}
private function generate_cache_key($text, $target_lang, $source_lang) {
return 'trans_' . md5($text . $target_lang . $source_lang);
}
public static function create_cache_table() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name = $wpdb->prefix . 'mlt_translation_cache';
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id bigint(20) NOT NULL AUTO_INCREMENT,
original_text_hash varchar(32) NOT NULL,
original_text text NOT NULL,
translated_text text NOT NULL,
source_language varchar(10),
target_language varchar(10) NOT NULL,
expiry_time datetime NOT NULL,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY text_hash_lang (original_text_hash, target_language, source_language),
KEY expiry_time (expiry_time)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
}
对于大量翻译请求,使用异步处理避免阻塞:
class MLT_Async_Processor {
private $queue_table;
public function __construct() {
global $wpdb;
$this->queue_table = $wpdb->prefix . 'mlt_async_queue';
add_action('mlt_process_queue', [$this, 'process_queue']);
add_action('wp_ajax_nopriv_mlt_async_translate', [$this, 'handle_async_translate']);
}
public function add_translation_job($data) {
global $wpdb;
return $wpdb->insert($this->queue_table, [
'job_type' => 'translation',
'job_data' => json_encode($data),
'status' => 'pending',
'created_at' => current_time('mysql')
]);
}
public function process_queue() {
global $wpdb;
// 获取待处理的任务
$jobs = $wpdb->get_results(
"SELECT * FROM {$this->queue_table}
WHERE status = 'pending'
ORDER BY created_at ASC
LIMIT 10"
);
foreach ($jobs as $job) {
$this->process_job($job);
}
}
private function process_job($job) {
global $wpdb;
$job_data = json_decode($job->job_data, true);
try {
// 更新状态为处理中
$wpdb->update(
$this->queue_table,
['status' => 'processing'],
['id' => $job->id]
);
// 执行翻译
$api_key = get_option('mlt_google_api_key');
$translator = new MLT_Translation_Engine($api_key);
$result = $translator->translate(
$job_data['text'],
$job_data['target_lang'],
$job_data['source_lang'] ?? null
);
// 更新状态为完成
$wpdb->update(
$this->queue_table,
[
'status' => 'completed',
'result_data' => json_encode(['translated_text' => $result]),
'completed_at' => current_time('mysql')
],
['id' => $job->id]
);
} catch (Exception $e) {
$wpdb->update(
$this->queue_table,
[
'status' => 'failed',
'error_message' => $e->getMessage(),
'completed_at' => current_time('mysql')
],
['id' => $job->id]
);
}
}
public static function create_queue_table() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name = $wpdb->prefix . 'mlt_async_queue';
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id bigint(20) NOT NULL AUTO_INCREMENT,
job_type varchar(50) NOT NULL,
job_data text NOT NULL,
status varchar(20) DEFAULT 'pending',
result_data text,
error_message text,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
completed_at datetime,
PRIMARY KEY (id),
KEY status (status),
KEY job_type (job_type)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
}
class MLT_Security_Manager {
public static function sanitize_chat_input($input) {
// 移除危险标签但保留基本格式
$allowed_tags = [
'b' => [],
'i' => [],
'u' => [],
'em' => [],
'strong' => [],
'br' => [],
'p' => [],
'span' => ['class' => []]
];
$sanitized = wp_kses($input, $allowed_tags);
// 限制长度
if (strlen($sanitized) > 1000) {
$sanitized = substr($sanitized, 0, 1000);
}
return $sanitized;
}
public static function validate_language_code($lang_code) {
$supported_languages = [
'en', 'es', 'fr', 'de', 'zh-CN', 'zh-TW', 'ja', 'ko',
'ru', 'ar', 'pt', 'it', 'nl', 'pl', 'tr', 'th', 'vi'
];
return in_array($lang_code, $supported_languages) ? $lang_code : 'en';
}
public static function prevent_flood_attack($session_id, $limit = 10, $time_window = 60) {
$transient_key = 'mlt_chat_flood_' . md5($session_id);
$request_count = get_transient($transient_key);
if ($request_count === false) {
set_transient($transient_key, 1, $time_window);
return true;
}
if ($request_count >= $limit) {
return false;
}
set_transient($transient_key, $request_count + 1, $time_window);
return true;
}
public static function encrypt_sensitive_data($data) {
if (!extension_loaded('openssl')) {
return $data; // 回退到基本编码
}
$method = 'AES-256-CBC';
$key = defined('MLT_ENCRYPTION_KEY') ? MLT_ENCRYPTION_KEY : wp_salt();
$iv_length = openssl_cipher_iv_length($method);
$iv = openssl_random_pseudo_bytes($iv_length);
$encrypted = openssl_encrypt($data, $method, $key, 0, $iv);
return base64_encode($iv . $encrypted);
}
}
class MLT_Security_Manager {
public static function sanitize_chat_input($input) {
// 移除危险标签但保留基本格式
$allowed_tags = [
'b' => [],
'i' => [],
'u' => [],
'em' => [],
'strong' => [],
'br' => [],
'p' => [],
'span' => ['class' => []]
];
$sanitized = wp_kses($input, $allowed_tags);
// 限制长度
if (strlen($sanitized) > 1000) {
$sanitized = substr($sanitized, 0, 1000);
}
return $sanitized;
}
public static function validate_language_code($lang_code) {
$supported_languages = [
'en', 'es', 'fr', 'de', 'zh-CN', 'zh-TW', 'ja', 'ko',
'ru', 'ar', 'pt', 'it', 'nl', 'pl', 'tr', 'th', 'vi'
];
return in_array($lang_code, $supported_languages) ? $lang_code : 'en';
}
public static function prevent_flood_attack($session_id, $limit = 10, $time_window = 60) {
$transient_key = 'mlt_chat_flood_' . md5($session_id);
$request_count = get_transient($transient_key);
if ($request_count === false) {
set_transient($transient_key, 1, $time_window);
return true;
}
if ($request_count >= $limit) {
return false;
}
set_transient($transient_key, $request_count + 1, $time_window);
return true;
}
public static function encrypt_sensitive_data($data) {
if (!extension_loaded('openssl')) {
return $data; // 回退到基本编码
}
$method = 'AES-256-CBC';
$key = defined('MLT_ENCRYPTION_KEY') ? MLT_ENCRYPTION_KEY : wp_salt();
$iv_length = openssl_cipher_iv_length($method);
$iv = openssl_random_pseudo_bytes($iv_length);
$encrypted = openssl_encrypt($data, $method, $key, 0, $iv);
return base64_encode($iv . $encrypted);
}
}
class MLT_Plugin_Manager {
public static function activate() {
// 创建数据库表
MLT_Chat_Database::create_tables();
MLT_Translation_Cache::create_cache_table();
MLT_Async_Processor::create_queue_table();
// 设置默认选项
add_option('mlt_chat_enabled', '1');
add_option('mlt_translation_enabled', '1');
add_option('mlt_default_language', 'zh-CN');
add_option('mlt_supported_languages', ['en', 'zh-CN', 'es', 'fr', 'de']);
// 创建定时任务
if (!wp_next_scheduled('mlt_process_queue')) {
wp_schedule_event(time(), 'hourly', 'mlt_process_queue');
}
// 创建必要的目录
class MLT_Plugin_Manager {
public static function activate() {
// 创建数据库表
MLT_Chat_Database::create_tables();
MLT_Translation_Cache::create_cache_table();
MLT_Async_Processor::create_queue_table();
// 设置默认选项
add_option('mlt_chat_enabled', '1');
add_option('mlt_translation_enabled', '1');
add_option('mlt_default_language', 'zh-CN');
add_option('mlt_supported_languages', ['en', 'zh-CN', 'es', 'fr', 'de']);
// 创建定时任务
if (!wp_next_scheduled('mlt_process_queue')) {
wp_schedule_event(time(), 'hourly', 'mlt_process_queue');
}
// 创建必要的目录


