diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 8b5aeb4..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -assets/.DS_Store diff --git a/README.md b/README.md index 4e9bfb8..2a79b78 100755 --- a/README.md +++ b/README.md @@ -101,14 +101,15 @@ - **不转换**: 指定不需要转换的内容区域 ### 短代码支持 -- 语言切换器(老短代码,平铺/下拉由“展示形式”设置控制) -``` -[wp-chinese-converter] -``` -- 不转换内容(编辑器无法保留注释时作为稳健占位): -``` -[wpcc_nc]不转换的内容[/wpcc_nc] -[wpcs_nc]不转换的内容[/wpcs_nc] +```php +// 显示语言切换器 +[wpcc_language_switcher] + +// 显示转换状态 +[wpcc_conversion_status] + +// 不转换指定内容 +[wpcc_no_conversion]不转换的内容[/wpcc_no_conversion] ``` ### PHP 函数调用 @@ -146,25 +147,6 @@ add_action('wpcc_before_conversion', 'before_convert'); add_action('wpcc_after_conversion', 'after_convert'); ``` -## 链接与重写规则行为说明(重要) - -- 链接格式与固定链接的关系 - - 当 WordPress 启用了固定链接,且“URL 链接格式”选择了“前缀/后缀”时:生成 /zh-xx/ 样式链接(或 …/zh-xx/) - - 当 WordPress 未启用固定链接(或环境未正确应用 rewrite 规则)时:自动回退为 ?variant=zh-xx,避免 404 -- 首页根级变体访问行为 - - 访问 /zh/ 或 /zh-reset/:作为“哨兵”回到不转换首页(https://example.com/),并设置 zh 偏好以覆盖浏览器/Cookie 策略 - - 访问 /zh-xx/(如 /zh-tw/、/zh-hk/):统一 302 跳转到首页,避免首页重复内容与 404 -- zh 哨兵与 rel="nofollow" - - 仅当“不转换”链接为覆盖策略而携带 zh 哨兵(URL 含 /zh/ 或 ?variant=zh)时自动添加 rel="nofollow" - - 当不需要哨兵(直接是原始 URL)时,不加 nofollow,避免影响站内权重传递 - -## 兼容层与新版内核 - -- 新内核(WPCC_Main / WPCC_Config 等)统一管理重写、变体解析、链接构造、注入脚本等; -- 为了兼容历史主题/插件/短代码调用,保留了 includes/wpcc-core.php 中的“老函数”(如 wpcc_link_conversion、set_wpcc_langs_urls、wpcc_output_navi、短代码 [wp-chinese-converter] 等); -- 老函数的行为已与新内核对齐(例如固定链接未启用时自动降级为 ?variant=xx),确保前后端一致; -- 建议新项目优先使用区块与新内核能力;对生态依赖的老接口,后续会以 @deprecated 标注与迁移指引逐步过渡。 - ## 故障排除 ### 常见问题 @@ -179,7 +161,7 @@ A: 请检查选择的转换引擎和目标语言是否正确。OpenCC 引擎适 A: 请检查 WordPress 缓存配置,或尝试清除转换缓存:`设置 > WP Chinese Converter > 高级设置 > 清除缓存` **Q: URL 重写不工作?** -A: 请确保 WordPress 固定链接已启用并“保存更改”一次;服务器需正确支持 rewrite(如 Nginx/Apache 规则)。插件在未启用固定链接时会自动回退为 ?variant=xx。 +A: 请确保服务器的 mod_rewrite 模块已启用,并重新保存固定链接设置。 ## 性能优化建议 @@ -213,13 +195,6 @@ A: 请确保 WordPress 固定链接已启用并“保存更改”一次;服务 ## 版本历史 -### v1.4.x (2025年稳定版补丁) -- 统一“展示形式”数值语义:1=平铺,0=下拉;修复短代码展示反向问题 -- 单站模式:当 WordPress 未启用固定链接时,链接自动降级为 ?variant=xx,避免 /zh-xx/ 404 -- 首页根级变体:/zh/ 与 /zh-xx/ 统一 302 到首页;/zh/ 同时设置 zh 偏好覆盖浏览器/Cookie 策略 -- 前端切换器:仅在携带 zh 哨兵时为“不转换”链接添加 rel="nofollow",并与新窗口 noopener noreferrer 兼容 -- 统一文件命名风格:核心类重命名为 class-wpcc-*.php;保留兼容层但与新内核对齐 - ### v1.3.0 (2025年重构版本) - 完全重写插件架构,采用现代化 OOP 设计 - 新增 Gutenberg 区块支持 diff --git a/assets/.DS_Store b/assets/.DS_Store index 65796ab..0b230cb 100644 Binary files a/assets/.DS_Store and b/assets/.DS_Store differ diff --git a/assets/admin/admin.css b/assets/admin/admin.css index 843491d..f50d039 100644 --- a/assets/admin/admin.css +++ b/assets/admin/admin.css @@ -317,30 +317,6 @@ max-width: 120px; } -/* Disabled state styling for network-controlled or engine-restricted options */ -.wpcc-disabled, -.wpcc-disabled * { - opacity: 0.6 !important; - cursor: not-allowed !important; - pointer-events: none !important; -} - -.wpcc-disabled .wpcc-slider { - background-color: #e0e0e0 !important; -} - -.wpcc-disabled .wpcc-slider:before { - background-color: #f5f5f5 !important; -} - -input[disabled] + .wpcc-slider { - background-color: #e0e0e0 !important; -} - -input[disabled] + .wpcc-slider:before { - background-color: #f5f5f5 !important; -} - @media (max-width: 768px) { .wpcc-sync-tabs { flex-direction: column; @@ -580,193 +556,3 @@ input[disabled] + .wpcc-slider:before { text-decoration: none; } -/* 网络管理提示样式 */ -.wpcc-network-notice { - margin: 10px 0 20px 0; - padding: 12px 15px; - background: #fff3cd; - border-left: 4px solid #ffc107; - border-radius: 4px; - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04); - font-size: 13px; - line-height: 1.4; -} - -.wpcc-network-notice p { - margin: 0; - color: #856404; -} - -.wpcc-network-notice p:not(:last-child) { - margin-bottom: 8px; -} - -.wpcc-network-notice .dashicons { - font-size: 14px; - width: 14px; - height: 14px; - vertical-align: text-top; - margin-right: 4px; - color: #856404; -} - -.wpcc-network-notice a { - color: #856404; - text-decoration: underline; -} - -.wpcc-network-notice a:hover { - color: #533f03; - text-decoration: none; -} - -.wpcc-network-notice strong { - font-weight: 600; - color: #533f03; -} - -.wpcc-network-notice em { - font-style: normal; - opacity: 0.9; -} - -/* 响应式设计 */ -@media (max-width: 768px) { - .wpcc-network-notice { - margin: 15px 0; - padding: 10px 12px; - font-size: 12px; - } - - .wpcc-network-notice .dashicons { - font-size: 12px; - width: 12px; - height: 12px; - } -} - -/* 深色模式支持 */ -@media (prefers-color-scheme: dark) { - .wpcc-network-notice { - background: #2c2611; - border-left-color: #d4a017; - } - - .wpcc-network-notice p, - .wpcc-network-notice .dashicons { - color: #f4d03f; - } - - .wpcc-network-notice strong { - color: #f7dc6f; - } - - .wpcc-network-notice a { - color: #f4d03f; - } - - .wpcc-network-notice a:hover { - color: #f7dc6f; - } -}/* Disab -led 字段样式 */ -.wpcc-switch.wpcc-disabled { - opacity: 0.6; - pointer-events: none; - cursor: not-allowed; -} - -.wpcc-switch.wpcc-disabled .wpcc-slider { - background-color: #ddd; - cursor: not-allowed; -} - -.wpcc-switch.wpcc-disabled .wpcc-switch-label { - color: #999; - cursor: not-allowed; -} - -.wpcc-radio input[disabled] + .wpcc-radio-label { - color: #999; - cursor: not-allowed; -} - -input[disabled].wpcc-input, -select[disabled].wpcc-select, -textarea[disabled].wpcc-textarea { - background-color: #f5f5f5; - color: #999; - cursor: not-allowed; - opacity: 0.6; -} - - - -/* 网络控 -制禁用状态样式 */ -.wpcc-switch.wpcc-disabled { - opacity: 0.6; - pointer-events: none !important; - cursor: not-allowed !important; -} - -.wpcc-switch.wpcc-disabled input[type="checkbox"] { - pointer-events: none !important; - cursor: not-allowed !important; -} - -.wpcc-switch.wpcc-disabled .wpcc-slider { - background-color: #ddd !important; - cursor: not-allowed !important; - pointer-events: none !important; -} - -.wpcc-switch.wpcc-disabled .wpcc-switch-label { - color: #999 !important; - cursor: not-allowed !important; - pointer-events: none !important; -} - -.wpcc-switch.wpcc-disabled input[type="checkbox"]:checked + .wpcc-slider { - background-color: #ccc !important; -} - -.wpcc-switch.wpcc-disabled input[type="checkbox"]:checked + .wpcc-slider:before { - background-color: #f0f0f0 !important; -} - -/* 网络控制区域样式 */ -.wpcc-network-controlled { - opacity: 0.6; - pointer-events: none !important; -} - -.wpcc-network-controlled select, -.wpcc-network-controlled input, -.wpcc-network-controlled textarea { - background-color: #f5f5f5 !important; - color: #999 !important; - cursor: not-allowed !important; - pointer-events: none !important; -} - -/* 网络控制提示样式 */ -.wpcc-network-notice { - margin: 10px 0; - padding: 10px 12px; - background: #fff3cd; - border-left: 4px solid #ffc107; - border-radius: 4px; -} - -.wpcc-network-notice p { - margin: 0; - color: #856404; -} - -.wpcc-network-notice .dashicons { - font-size: 16px; - width: 16px; - height: 16px; - vertical-align: text-top; -} \ No newline at end of file diff --git a/assets/css/blocks-editor.css b/assets/css/blocks-editor.css index 3466373..e27e159 100644 --- a/assets/css/blocks-editor.css +++ b/assets/css/blocks-editor.css @@ -24,12 +24,11 @@ .wpcc-lang-item .wpcc-link { display: inline-block; - padding: 4px 10px; + padding: 4px 8px; background: #f0f0f0; color: #333; text-decoration: none; border: 1px solid #ddd; - border-radius: 5px; font-size: 12px; } @@ -161,4 +160,4 @@ .wpcc-language-switcher .wpcc-custom-label { font-weight: 500; -} +} \ No newline at end of file diff --git a/assets/css/blocks-frontend.css b/assets/css/blocks-frontend.css index 316597a..9d82ebc 100644 --- a/assets/css/blocks-frontend.css +++ b/assets/css/blocks-frontend.css @@ -26,62 +26,46 @@ .wpcc-lang-item .wpcc-link { display: inline-block; - padding: 4px 10px; - background: #f0f0f0; - color: #333; + padding: 4px 8px; + background: #0073aa; + color: #fff; text-decoration: none; - border: 1px solid #ddd; - border-radius: 5px; - font-size: 12px; - transition: background-color 0.2s ease, border-color 0.2s ease; + border: 1px solid #0073aa; + font-size: 13px; } .wpcc-lang-item .wpcc-link:hover { - background: #e0e0e0; - border-color: #ccc; -} - -.wpcc-lang-item.wpcc-current .wpcc-link { - background: #0073aa; - color: #fff; - border-color: #0073aa; -} - -.wpcc-lang-item.wpcc-current .wpcc-link:hover { background: #005a87; border-color: #005a87; } +.wpcc-lang-item.wpcc-current .wpcc-link { + background: #00a32a; + border-color: #00a32a; +} + .wpcc-lang-item.wpcc-no-conversion .wpcc-link { - background: #f9f9f9; - color: #666; - border-color: #ddd; + background: #666; + border-color: #666; } .wpcc-lang-item.wpcc-no-conversion .wpcc-link:hover { - background: #f0f0f0; - border-color: #ccc; + background: #555; + border-color: #555; } .wpcc-dropdown-switcher { padding: 6px 8px; border: 1px solid #ddd; background: #fff; - font-size: 12px; + font-size: 13px; cursor: pointer; min-width: 150px; - border-radius: 5px; - transition: border-color 0.2s ease; -} - -.wpcc-dropdown-switcher:hover { - border-color: #bbb; } .wpcc-dropdown-switcher:focus { - outline: 2px solid #0073aa; - outline-offset: 0; - border-color: #0073aa; + outline: 1px solid #0073aa; + outline-offset: 1px; } .wpcc-conversion-status { @@ -92,12 +76,11 @@ .wpcc-status-container { display: flex; align-items: center; - gap: 6px; + gap: 4px; } .wpcc-status-text { - font-size: 12px; - color: #333; + font-size: 13px; } .wpcc-conversion-status.wpcc-format-badge .wpcc-status-text { @@ -110,7 +93,7 @@ .wpcc-conversion-status.wpcc-format-text .wpcc-status-text { color: #333; - font-size: 12px; + font-size: 13px; } .wpcc-conversion-status.wpcc-format-minimal .wpcc-status-text { @@ -118,37 +101,25 @@ color: #666; } -/* 不转换区块在前台不显示任何视觉样式 */ .wpcc-no-conversion-wrapper { - /* 仅保留功能性标记,无视觉样式 */ -} - -.wpcc-no-conversion-header { - display: none; /* 前台隐藏标题 */ -} - -.wpcc-label { - display: none; /* 前台隐藏标签 */ + position: relative; } .wpcc-no-conversion-content { - /* 内容正常显示,无额外样式 */ + position: relative; } @media (max-width: 768px) { .wpcc-horizontal-switcher { - display: flex; - align-items: stretch; flex-direction: column; - flex-direction: row; - flex-wrap: nowrap; + align-items: stretch; gap: 6px; } - + .wpcc-lang-item { width: 100%; } - + .wpcc-lang-item .wpcc-link { padding: 8px 12px; font-size: 14px; @@ -156,7 +127,7 @@ width: 100%; box-sizing: border-box; } - + .wpcc-dropdown-switcher { width: 100%; padding: 8px 12px; @@ -186,14 +157,13 @@ min-width: 180px; } -/* 前台所有不转换区块的边框变体都不显示 */ -.wpcc-no-conversion-wrapper.wpcc-border-solid, -.wpcc-no-conversion-wrapper.wpcc-border-dashed, +.wpcc-no-conversion-wrapper.wpcc-border-solid { + border-style: solid; +} + .wpcc-no-conversion-wrapper.wpcc-border-none { border: none; background: transparent; - padding: 0; - margin: 0; } .wpcc-conversion-status.wpcc-clickable { @@ -237,4 +207,4 @@ .wpcc-language-switcher.wpcc-current-first .wpcc-lang-item.wpcc-current { order: -1; -} +} \ No newline at end of file diff --git a/assets/js/blocks-frontend.js b/assets/js/blocks-frontend.js index 5bf39c0..ee90571 100644 --- a/assets/js/blocks-frontend.js +++ b/assets/js/blocks-frontend.js @@ -86,10 +86,8 @@ function renderLanguageSwitcher( if (showNoConversion) { const isActive = !currentLang || currentLang === ""; - const noConvUrl = getNoConversionUrl(); - const relForNoConv = buildRelAttribute(noConvUrl, openInNewWindow); html += ` - ${noConversionText} + ${noConversionText} `; } @@ -263,7 +261,7 @@ function getCurrentLanguage() { return variant; } - const pathMatch = window.location.pathname.match(/\/(zh(?:-[a-z]+)?)\//i); + const pathMatch = window.location.pathname.match(/\/(zh-[a-z]+)\//); if (pathMatch) { return pathMatch[1]; } @@ -286,120 +284,27 @@ function getLanguageUrl(langCode) { // 优先使用服务端注入的 URL 映射(如可用) try { if (typeof wpcc_langs_urls === "object" && wpcc_langs_urls) { - if (langCode && wpcc_langs_urls[langCode]) { - return wpcc_langs_urls[langCode]; - } if (!langCode || langCode === "") { if (typeof wpcc_noconversion_url === "string" && wpcc_noconversion_url) { return wpcc_noconversion_url; } + } else if (wpcc_langs_urls[langCode]) { + return wpcc_langs_urls[langCode]; } } } catch (e) { // 忽略映射读取错误,回退到查询参数模式 } - // 回退:使用查询参数模式(并避免重复:/zh-xx/ 与 ?variant=zh-xx 共存) + // 回退:使用查询参数模式 const currentUrl = new URL(window.location.href); - const pathMatch = currentUrl.pathname.match(/^\/(zh(?:-[a-z]+)?)(\b|\/)/i); - if (langCode) { - // 若当前已处于同一变体路径,则仅移除冗余的 variant 参数,返回干净的漂亮链接 - if (pathMatch && pathMatch[1].toLowerCase() === langCode.toLowerCase()) { - currentUrl.searchParams.delete("variant"); - return currentUrl.toString(); - } currentUrl.searchParams.set("variant", langCode); - return currentUrl.toString(); } else { - // 不转换:尽量去除语言段与冗余参数 currentUrl.searchParams.delete("variant"); - if (pathMatch) { - // 去掉开头的 /zh-xx 段,回到原始路径 - currentUrl.pathname = currentUrl.pathname.replace(/^\/(zh-[a-z]+)(\/?)/i, "/"); - } - return currentUrl.toString(); - } -} - -// 构建“不转换”链接:在变体页面时注入 zh 哨兵以覆盖浏览器/Cookie 策略 -function getNoConversionUrl() { - // 基于服务端注入的原始 URL 获取基础地址 - let baseUrl = (typeof wpcc_noconversion_url === "string" && wpcc_noconversion_url) - ? wpcc_noconversion_url - : (function() { - const u = new URL(window.location.href); - // 去除 variant 查询与路径前缀 - u.searchParams.delete("variant"); - u.pathname = u.pathname.replace(/^\/(zh(?:-[a-z]+)?)(\/?)/i, "/"); - return u.toString(); - })(); - - const currentLang = getCurrentLanguage(); - if (!currentLang) { - return baseUrl; // 已经是不转换 } - // 检测站点使用的链接风格:查询参数 / 后缀 / 前缀 - const detectStyle = () => { - try { - if (typeof wpcc_langs_urls === 'object' && wpcc_langs_urls) { - for (const k in wpcc_langs_urls) { - if (!Object.prototype.hasOwnProperty.call(wpcc_langs_urls, k)) continue; - const href = String(wpcc_langs_urls[k] || ''); - if (/([?&])variant=zh-[a-z]+/i.test(href)) return 'query'; - const u = new URL(href, window.location.origin); - const path = u.pathname; - // 前缀: /zh-xx/... 后缀: .../zh-xx/ - if (/^\/(zh(?:-[a-z]+)?)(\/|$)/i.test(path)) return 'prefix'; - if (/(\/)(zh(?:-[a-z]+)?)\/?$/i.test(path)) return 'suffix'; - } - } - } catch (e) {} - return 'query'; - }; - - const style = detectStyle(); - try { - const u = new URL(baseUrl); - if (style === 'query') { - u.searchParams.set('variant', 'zh'); - return u.toString(); - } - if (style === 'suffix') { - // 确保末尾带 /zh/ - u.pathname = u.pathname.replace(/\/$/, '') + '/zh/'; - return u.toString(); - } - // prefix - // 将路径改为 /zh/ + 原路径 - u.pathname = u.pathname.replace(/^\/+/, '/'); - // 避免在已是 /zh/ 的情况下重复添加 /zh - if (!/^\/(zh)(\/|$)/i.test(u.pathname)) { - u.pathname = '/zh' + (u.pathname.startsWith('/') ? '' : '/') + u.pathname; - } - // 合并多余斜杠 - u.pathname = u.pathname.replace(/\/{2,}/g, '/'); - return u.toString(); - } catch (e) { - // 回退:总是可用的查询参数 - try { - const u2 = new URL(baseUrl); - u2.searchParams.set('variant', 'zh'); - return u2.toString(); - } catch (_e) { - return baseUrl; - } - } -} - -// 根据链接是否包含 zh 哨兵决定 rel,且兼容新窗口的 noopener noreferrer -function buildRelAttribute(url, openInNewWindow) { - const hasZhSentinel = /\/(?:zh)(?:\b|\/)/i.test(url) || /(?:[?&])variant=zh(?:&|$)/i.test(url); - let relParts = []; - if (hasZhSentinel) relParts.push('nofollow'); - if (openInNewWindow) relParts.push('noopener', 'noreferrer'); - return relParts.length ? ` rel="${Array.from(new Set(relParts)).join(' ')}"` : ''; + return currentUrl.toString(); } function handleLanguageChange(langCode, selectElement) { diff --git a/assets/js/tinymce-wpcc-nc.js b/assets/js/tinymce-wpcc-nc.js deleted file mode 100644 index 12e12df..0000000 --- a/assets/js/tinymce-wpcc-nc.js +++ /dev/null @@ -1,44 +0,0 @@ -(function() { - if (typeof window.tinymce === 'undefined') { - return; - } - - tinymce.PluginManager.add('wpcc_nc', function(editor, url) { - function insertShortcode() { - var sel = editor.selection ? editor.selection.getContent({ format: 'text' }) : ''; - var before = '[wpcc_nc]'; - var after = '[/wpcc_nc]'; - var content = before + (sel || '') + after; - editor.insertContent(content); - } - - // TinyMCE 5+ API - if (editor.ui && editor.ui.registry && editor.ui.registry.addButton) { - editor.ui.registry.addButton('wpcc_nc', { - text: 'wpcc_NC', - tooltip: '插入不转换包裹 [wpcc_nc]...[/wpcc_nc]', - onAction: insertShortcode - }); - editor.ui.registry.addMenuItem('wpcc_nc', { - text: '插入不转换包裹', - onAction: insertShortcode - }); - } else if (editor.addButton) { - // TinyMCE 4 API (WordPress Classic Editor) - editor.addButton('wpcc_nc', { - text: 'wpcc_NC', - tooltip: '插入不转换包裹 [wpcc_nc]...[/wpcc_nc]', - onclick: insertShortcode - }); - } - - return { - getMetadata: function () { - return { - name: 'WPCC No-Conversion Shortcode Helper', - url: 'https://wpcc.net' - }; - } - }; - }); -})(); diff --git a/changelog.txt b/changelog.txt deleted file mode 100644 index c0382fe..0000000 --- a/changelog.txt +++ /dev/null @@ -1,27 +0,0 @@ -WP Chinese Converter (WPCC) — 更新日志 / Changelog - -Version 1.5.0 (2025-10-11) -- 修复 单站模式下“展示形式”反向的问题:统一语义为 1=平铺、0=下拉,短代码 [wp-chinese-converter] 与区块表现一致 -- 修复 单站设置保存问题:确保语言模块、全页面转换、展示形式等选项在单站模式可正确保存 -- 优化 zh 哨兵与 rel="nofollow" 规则:仅当“不转换”链接为覆盖策略而携带 zh 哨兵(/zh/ 或 ?variant=zh)时添加 nofollow;新窗口时追加 noopener noreferrer -- 优化 前端语言切换器:在变体页为“不转换”注入 zh 哨兵;缓存破除(基于文件 mtime 的版本号) -- 链接与重写 统一策略: - * WordPress 未启用固定链接时,所有语言链接自动回退为 ?variant=xx,避免 /zh-xx/ 404 - * 首页根级变体(/zh/、/zh-xx/)统一 302 到首页;/zh/ 同时设置 zh 偏好 -- 内核一致性:老函数(includes/wpcc-core.php)与新内核(WPCC_Main)策略对齐(固定链接检测、链接降级) -- 架构与清理:统一核心类文件命名为 class-wpcc-*.php;移除旧 url fix 入口;保留兼容层并与新内核对齐 -- 文档:更新 README,补充链接/重写行为说明与兼容策略 - -Version 1.4.x (2025) -- 统一 SEO 行为:在不需要 zh 哨兵时不添加 nofollow,避免权重传递受影响 -- 改善 区块与脚本的加载与配置注入,优化多语言切换体验 -- 多站点:网络设置与子站策略协调,增强稳定性 - -Version 1.3.0 (2025 重构) -- 完整重写插件架构为 OOP:WPCC_Main / WPCC_Config / 模块管理器等 -- 新增 Gutenberg 区块(语言切换器、转换状态、不转换区块) -- 优化 性能与内存占用;OpenCC 与 MediaWiki 双引擎;转换缓存 -- 增强 SEO(canonical、hreflang、schema/meta 转换)与 REST API 支持 - -历史说明 -- 本项目分叉自 WP Chinese Conversion,2025 年起由文派团队(WPCC.NET)进行长期维护与重构。 diff --git a/includes/admin/class-wpcc-admin.php b/includes/admin/wp-chinese-converter-admin.php similarity index 73% rename from includes/admin/class-wpcc-admin.php rename to includes/admin/wp-chinese-converter-admin.php index cf41f58..7dbb8d6 100755 --- a/includes/admin/class-wpcc-admin.php +++ b/includes/admin/wp-chinese-converter-admin.php @@ -11,10 +11,6 @@ class wpcc_Admin private $langs = false; private string $url = ""; private $admin_lang = false; - - private array $network_controlled_options = []; - private bool $is_network_enforced = false; - private array $network_options = []; // 移除旧式构造函数,只使用 __construct @@ -47,10 +43,6 @@ class wpcc_Admin } $this->langs = &$wpcc_langs; $this->options = $wpcc_options; - - // 初始化网络控制 - $this->init_network_control(); - if (empty($this->options)) { $this->options = [ // 语言与标签 @@ -74,7 +66,7 @@ class wpcc_Admin "wpcc_use_cookie_variant" => 1, // 不转换 -"wpcc_no_conversion_tag" => "", +"wpcc_no_conversion_tag" => "pre,code,pre.wp-block-code,pre.wp-block-preformatted,script,noscript,style,kbd,samp", "wpcc_no_conversion_ja" => 0, "wpcc_no_conversion_qtag" => 0, @@ -93,7 +85,6 @@ class wpcc_Admin "wpcc_enable_schema_conversion" => 1, "wpcc_enable_meta_conversion" => 1, - // 其他 "wpcc_flag_option" => 1, "wpcc_trackback_plugin_author" => 0, @@ -106,7 +97,6 @@ class wpcc_Admin } $this->clean_invalid_langs(); - update_wpcc_option("wpcc_options", $this->options); $this->base = plugin_basename(dirname(__FILE__)) . "/"; @@ -118,28 +108,23 @@ class wpcc_Admin $this->url = admin_url("options-general.php?page=" . $page_slug); } - if (is_multisite() && is_network_admin() && wpcc_mobile_exist("network")) { - // 网络管理界面菜单(实际网络设置页面由 WPCC_Network_Settings 提供,此处保持入口一致) + if (is_multisite() && wpcc_mobile_exist("network")) { add_submenu_page( "settings.php", - "文派译词", - "文派译词", + "WP Chinese Converter", + "WP Chinese Converter", "manage_network_options", $page_slug, [&$this, "display_options"], ); - } elseif (!is_network_admin()) { - // 子站点菜单:当未启用强制网络管理时显示 - $network_enforced = is_multisite() ? (int) get_site_option('wpcc_network_enforce', 0) : 0; - if (!$network_enforced) { - add_options_page( - "文派译词", - "译词", - "manage_options", - $page_slug, - [&$this, "display_options"], - ); - } + } else { + add_options_page( + "WP Chinese Converter", + "WP Chinese Converter", + "manage_options", + $page_slug, + [&$this, "display_options"], + ); } wp_enqueue_script("jquery"); @@ -252,7 +237,7 @@ class wpcc_Admin dirname(dirname(__DIR__)) . "/wp-chinese-converter.php", ) . "assets/admin/admin.css", [], - wpcc_VERSION, + "2.0.0", ); wp_enqueue_script( @@ -261,7 +246,7 @@ class wpcc_Admin dirname(dirname(__DIR__)) . "/wp-chinese-converter.php", ) . "assets/admin/admin.js", ["jquery"], - wpcc_VERSION, + "2.0.0", true, ); @@ -416,44 +401,36 @@ class wpcc_Admin // 只更新表单中实际提交的字段 - // 确保关键字段存在默认值,防止未定义键产生警告 - if (!is_array($options)) { $options = []; } - if (!isset($options['wpcc_use_permalink'])) { $options['wpcc_use_permalink'] = 0; } - if (!isset($this->options['wpcc_use_permalink'])) { $this->options['wpcc_use_permalink'] = 0; } - if (!isset($options['wpcc_used_langs']) || !is_array($options['wpcc_used_langs'])) { $options['wpcc_used_langs'] = []; } - if (!isset($this->options['wpcc_used_langs']) || !is_array($this->options['wpcc_used_langs'])) { $this->options['wpcc_used_langs'] = []; } - - // 语言设置:总是基于提交的 wpcco_variant_* 重建已启用语言,避免部分站点无法保存 - $langs = []; - if (is_array($this->langs)) { - foreach ($this->langs as $key => $value) { - if (isset($_POST["wpcco_variant_" . $key])) { - $langs[] = $key; + // 语言设置 + if ( + isset($_POST["wpcco_variant_zh-cn"]) || + isset($_POST["wpcco_variant_zh-tw"]) || + isset($_POST["wpcco_variant_zh-hk"]) + ) { + $langs = []; + if (is_array($this->langs)) { + foreach ($this->langs as $key => $value) { + if (isset($_POST["wpcco_variant_" . $key])) { + $langs[] = $key; + } } } + $options["wpcc_used_langs"] = $langs; } - $options["wpcc_used_langs"] = $langs; // 复选框字段(未选中时不会在POST中出现) $checkbox_fields = [ - // 同时兼容两种命名(历史与现用) "wpcco_use_fullpage_conversion" => "wpcc_use_fullpage_conversion", - "wpcc_use_fullpage_conversion" => "wpcc_use_fullpage_conversion", "wpcco_use_sitemap" => "wpcco_use_sitemap", - // 支持两种命名(历史兼容):wpcco_* 与 wpcc_* "wpcco_auto_language_recong" => "wpcc_auto_language_recong", - "wpcc_auto_language_recong" => "wpcc_auto_language_recong", "wpcc_enable_cache_addon" => "wpcc_enable_cache_addon", "wpcc_enable_network_module" => "wpcc_enable_network_module", "wpcc_enable_hreflang_tags" => "wpcc_enable_hreflang_tags", - "wpcc_enable_hreflang_x_default" => "wpcc_enable_hreflang_x_default", "wpcc_enable_schema_conversion" => "wpcc_enable_schema_conversion", "wpcc_enable_meta_conversion" => "wpcc_enable_meta_conversion", "wpcc_show_more_langs" => "wpcc_show_more_langs", "wpcc_no_conversion_qtag" => "wpcc_no_conversion_qtag", - "wpcc_no_conversion_ja" => "wpcc_no_conversion_ja", "wpcc_enable_post_conversion" => "wpcc_enable_post_conversion", - "wpcc_first_visit_default" => "wpcc_first_visit_default", ]; foreach ($checkbox_fields as $post_field => $option_field) { @@ -463,19 +440,13 @@ class wpcc_Admin // 文本字段和下拉选择框 $text_fields = [ "wpcc_translate_type" => "wpcc_translate_type", - // 同时兼容两种命名(历史与现用):wpcco_no_conversion_tag 与 wpcc_no_conversion_tag "wpcco_no_conversion_tag" => "wpcc_no_conversion_tag", - "wpcc_no_conversion_tag" => "wpcc_no_conversion_tag", "wpcco_no_conversion_tip" => "nctip", "wpcc_engine" => "wpcc_engine", "wpcco_search_conversion" => "wpcc_search_conversion", - // 支持两种命名(历史兼容):wpcco_* 与 wpcc_* "wpcco_browser_redirect" => "wpcc_browser_redirect", - "wpcc_browser_redirect" => "wpcc_browser_redirect", "wpcco_use_cookie_variant" => "wpcc_use_cookie_variant", - "wpcc_use_cookie_variant" => "wpcc_use_cookie_variant", "wpcco_use_permalink" => "wpcc_use_permalink", - "wpcc_use_permalink" => "wpcc_use_permalink", "wpcco_sitemap_post_type" => "wpcco_sitemap_post_type", "wpcc_hreflang_x_default" => "wpcc_hreflang_x_default", "wpcc_post_conversion_target" => "wpcc_post_conversion_target", @@ -483,7 +454,7 @@ class wpcc_Admin foreach ($text_fields as $post_field => $option_field) { if (isset($_POST[$post_field])) { - if ($post_field === "wpcco_no_conversion_tag" || $post_field === "wpcc_no_conversion_tag") { + if ($post_field === "wpcco_no_conversion_tag") { $options[$option_field] = trim( $_POST[$post_field], " \t\n\r\0\x0B,|", @@ -510,11 +481,6 @@ class wpcc_Admin } } - // 兼容旧字段:当表单提交了 wpcc_flag_option 时,将其映射为 wpcc_translate_type - if (isset($_POST['wpcc_flag_option'])) { - $options['wpcc_translate_type'] = intval($_POST['wpcc_flag_option']); - } - if (is_array($this->langs)) { foreach ($this->langs as $lang => $value) { if ( @@ -528,22 +494,6 @@ class wpcc_Admin } } - // 根据本地“显示更多语言”与引擎裁剪启用语言,防止未启用的扩展语言(如 zh-sg)误入站点配置 - $enable_more = isset($options['wpcc_show_more_langs']) ? (int)$options['wpcc_show_more_langs'] : 1; - if (! $enable_more) { - $base_langs = array('zh-cn','zh-tw','zh-hk'); - $options['wpcc_used_langs'] = array_values(array_intersect($options['wpcc_used_langs'], $base_langs)); - } - // 非 OpenCC 引擎移除 zh-jp - $engine = isset($options['wpcc_engine']) ? $options['wpcc_engine'] : 'opencc'; - if ($engine !== 'opencc') { - $options['wpcc_used_langs'] = array_values(array_diff($options['wpcc_used_langs'], array('zh-jp'))); - } - // 至少保留一种语言 - if (empty($options['wpcc_used_langs'])) { - $options['wpcc_used_langs'] = array('zh-cn'); - } - if ( $this->get_cache_status() == 2 && empty($options["wpcc_browser_redirect"]) && @@ -555,14 +505,12 @@ class wpcc_Admin $wpcc_options = $options; $need_flush_rules = false; - $current_permalink = isset($this->options["wpcc_use_permalink"]) ? (int) $this->options["wpcc_use_permalink"] : 0; - $new_permalink = isset($options["wpcc_use_permalink"]) ? (int) $options["wpcc_use_permalink"] : 0; - $current_langs = isset($this->options["wpcc_used_langs"]) && is_array($this->options["wpcc_used_langs"]) ? $this->options["wpcc_used_langs"] : []; - $new_langs = isset($options["wpcc_used_langs"]) && is_array($options["wpcc_used_langs"]) ? $options["wpcc_used_langs"] : []; - if ( - $current_permalink !== $new_permalink || - ($current_permalink !== 0 && $current_langs != $new_langs) + $this->options["wpcc_use_permalink"] != + $options["wpcc_use_permalink"] || + ($this->options["wpcc_use_permalink"] != 0 && + $this->options["wpcc_used_langs"] != + $options["wpcc_used_langs"]) ) { if (!has_filter("rewrite_rules_array", "wpcc_rewrite_rules")) { add_filter("rewrite_rules_array", "wpcc_rewrite_rules"); @@ -585,8 +533,6 @@ class wpcc_Admin $wp_rewrite->flush_rules(); } - // 网络设置交由 WPCC_Network_Settings 统一管理,此处不再重复保存以避免冲突 - update_wpcc_option("wpcc_options", $options); $this->options = $options; @@ -668,71 +614,4 @@ class wpcc_Admin wp_send_json_success(["message" => "已优化 {$optimized} 个数据表"]); } - - /** - * 初始化网络控制 - */ - private function init_network_control() { - if (!is_multisite()) { - return; - } - - // 获取网络控制的选项 - $this->network_controlled_options = get_site_option('wpcc_network_controlled_options', []); - $this->is_network_enforced = get_site_option('wpcc_network_enforce', false); - - // 如果启用了网络强制模式,获取网络选项值 - if ($this->is_network_enforced) { - $this->network_options = get_site_option('wpcc_network_options', []); - $this->apply_network_options(); - } - } - - /** - * 应用网络选项值 - */ - private function apply_network_options() { - foreach ($this->network_controlled_options as $option_name) { - if (isset($this->network_options[$option_name])) { - $this->options[$option_name] = $this->network_options[$option_name]; - } - } - } - - /** - * 检查选项是否被网络控制 - */ - public function is_option_controlled($option_name) { - if (!is_multisite()) { - return false; - } - return in_array($option_name, $this->network_controlled_options); - } - - /** - * 获取字段属性(用于禁用网络控制的字段) - */ - public function get_field_attributes($option_name) { - if ($this->is_option_controlled($option_name)) { - return 'disabled="disabled" title="此选项由网络管理员控制"'; - } - return ''; - } - - /** - * 获取网络控制提示 - */ - public function get_network_controlled_notice($option_name) { - if ($this->is_option_controlled($option_name)) { - return '
此选项由网络管理员统一控制,无法在子站点修改。
'; - } - return ''; - } - - /** - * 检查是否为网络强制模式 - */ - public function is_network_enforced() { - return $this->is_network_enforced; - } } diff --git a/includes/blocks/blocks-init.php b/includes/blocks/blocks-init.php index 29db599..9924ce9 100644 --- a/includes/blocks/blocks-init.php +++ b/includes/blocks/blocks-init.php @@ -8,28 +8,10 @@ class WPCC_Blocks { public function __construct() { add_action( 'init', array( $this, 'register_blocks' ) ); - add_action( 'init', array( $this, 'register_block_styles' ) ); add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_block_editor_assets' ) ); add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend_assets' ) ); } - public function register_block_styles() { - // 在 init 阶段注册样式句柄,供 block.json 中的 editorStyle 和 style 字段使用 - wp_register_style( - 'wpcc-blocks-editor', - plugins_url( 'assets/css/blocks-editor.css', dirname( dirname( __FILE__ ) ) ), - array(), - wpcc_VERSION - ); - - wp_register_style( - 'wpcc-blocks-frontend', - plugins_url( 'assets/css/blocks-frontend.css', dirname( dirname( __FILE__ ) ) ), - array(), - wpcc_VERSION - ); - } - public function register_blocks() { $blocks = array( 'language-switcher', @@ -54,18 +36,22 @@ class WPCC_Blocks { public function enqueue_block_editor_assets() { // 确保wpcc-variant脚本已加载 if ( ! wp_script_is( 'wpcc-variant', 'registered' ) ) { - wp_register_script( 'wpcc-variant', plugins_url( 'assets/dist/wpcc-variant.umd.js', dirname( dirname( __FILE__ ) ) ), array(), wpcc_VERSION ); + wp_register_script( 'wpcc-variant', plugins_url( 'assets/dist/wpcc-variant.umd.js', dirname( dirname( __FILE__ ) ) ), array(), '1.1.0' ); } - // 样式已在 init 阶段注册,这里只需要加载即可 - wp_enqueue_style( 'wpcc-blocks-editor' ); + wp_enqueue_style( + 'wpcc-blocks-editor', + plugins_url( 'assets/css/blocks-editor.css', dirname( dirname( __FILE__ ) ) ), + array(), + '1.0.0' + ); // 兼容层:为编辑器注册旧占位文本的 deprecated 版本,避免校验失败 wp_enqueue_script( 'wpcc-block-compat', plugins_url( 'assets/js/wpcc-block-compat.js', dirname( dirname( __FILE__ ) ) ), array( 'wp-blocks', 'wp-element', 'wp-block-editor', 'wp-hooks' ), -wpcc_VERSION, + '1.0.0', true ); @@ -73,7 +59,7 @@ wpcc_VERSION, $enabled_languages = $wpcc_options['wpcc_used_langs'] ?? array(); wp_localize_script( - 'wpcc-block-compat', + 'wp-blocks', 'wpccBlockSettings', array( 'enabledLanguages' => $enabled_languages, @@ -99,23 +85,24 @@ wpcc_VERSION, public function enqueue_frontend_assets() { // 确保wpcc-variant脚本已加载 if ( ! wp_script_is( 'wpcc-variant', 'registered' ) ) { - wp_register_script( 'wpcc-variant', plugins_url( 'assets/dist/wpcc-variant.umd.js', dirname( dirname( __FILE__ ) ) ), array(), wpcc_VERSION ); + wp_register_script( 'wpcc-variant', plugins_url( 'assets/dist/wpcc-variant.umd.js', dirname( dirname( __FILE__ ) ) ), array(), '1.1.0' ); } // 为前端状态指示器的 dashicons 图标提供样式支持 wp_enqueue_style( 'dashicons' ); - // 样式已在 init 阶段注册,这里只需要加载即可 - wp_enqueue_style( 'wpcc-blocks-frontend' ); + wp_enqueue_style( + 'wpcc-blocks-frontend', + plugins_url( 'assets/css/blocks-frontend.css', dirname( dirname( __FILE__ ) ) ), + array(), + '1.0.0' + ); - // 使用文件修改时间作为版本号,避免浏览器缓存导致逻辑不更新 - $blocks_front_js = plugin_dir_path( dirname( __FILE__ ) ) . 'assets/js/blocks-frontend.js'; - $blocks_front_ver = file_exists( $blocks_front_js ) ? filemtime( $blocks_front_js ) : wpcc_VERSION; wp_enqueue_script( 'wpcc-blocks-frontend', plugins_url( 'assets/js/blocks-frontend.js', dirname( dirname( __FILE__ ) ) ), array( 'wpcc-variant' ), - $blocks_front_ver, + '1.0.0', true ); diff --git a/includes/core/class-wpcc-conversion-cache.php b/includes/core/class-conversion-cache.php similarity index 100% rename from includes/core/class-wpcc-conversion-cache.php rename to includes/core/class-conversion-cache.php diff --git a/includes/core/class-wpcc-converter-factory.php b/includes/core/class-converter-factory.php similarity index 79% rename from includes/core/class-wpcc-converter-factory.php rename to includes/core/class-converter-factory.php index 7e15e60..9f73b43 100644 --- a/includes/core/class-wpcc-converter-factory.php +++ b/includes/core/class-converter-factory.php @@ -25,16 +25,16 @@ class WPCC_Converter_Factory { } private static function create_converter( $engine ) { - switch ( $engine ) { - case 'opencc': - require_once dirname( __FILE__ ) . '/class-wpcc-opencc-converter.php'; - return new WPCC_OpenCC_Converter(); - - case 'mediawiki': - default: - require_once dirname( __FILE__ ) . '/class-wpcc-mediawiki-converter.php'; - return new WPCC_MediaWiki_Converter(); - } + switch ( $engine ) { + case 'opencc': + require_once dirname( __FILE__ ) . '/class-opencc-converter.php'; + return new WPCC_OpenCC_Converter(); + + case 'mediawiki': + default: + require_once dirname( __FILE__ ) . '/class-mediawiki-converter.php'; + return new WPCC_MediaWiki_Converter(); + } } public static function get_available_engines() { diff --git a/includes/core/class-mediawiki-converter.php b/includes/core/class-mediawiki-converter.php new file mode 100644 index 0000000..65dee37 --- /dev/null +++ b/includes/core/class-mediawiki-converter.php @@ -0,0 +1,284 @@ +ensure_conversion_tables_loaded( $target_variant ); + + $result = $text; + switch ( $target_variant ) { + case 'zh-hans': + $result = $this->convert_to_hans( $text ); + break; + case 'zh-hant': + $result = $this->convert_to_hant( $text ); + break; + case 'zh-cn': + $result = $this->convert_to_cn( $text ); + break; + case 'zh-tw': + $result = $this->convert_to_tw( $text ); + break; + case 'zh-hk': + $result = $this->convert_to_hk( $text ); + break; + case 'zh-sg': + $result = $this->convert_to_sg( $text ); + break; + } + + // 缓存转换结果 + if ( $result !== $text ) { + WPCC_Conversion_Cache::set_cached_conversion( $text, $target_variant, $result ); + } + + return $result; + } + + public function get_supported_variants() { + return array( 'zh-hans', 'zh-hant', 'zh-cn', 'zh-tw', 'zh-hk', 'zh-sg' ); + } + + public function get_engine_name() { + return 'mediawiki'; + } + + public function get_engine_info() { + $memory_usage = $this->get_memory_usage_info(); + + return array( + 'name' => 'MediaWiki', + 'version' => '1.23.5', + 'description' => '基于MediaWiki的字符映射转换引擎', + 'features' => array( + '字符级精确映射', + '快速转换速度', + '良好的兼容性', + '支持多地区变体', + '按需加载优化' + ), + 'memory_usage' => $memory_usage, + 'conversion_type' => 'character_mapping', + 'lazy_load_enabled' => $this->lazy_load_enabled, + 'loaded_tables' => array_keys( array_filter( self::$loaded_tables ) ) + ); + } + + public function get_memory_usage_info() { + $loaded_count = count( array_filter( self::$loaded_tables ) ); + $total_count = count( $this->get_supported_variants() ); + + if ( $this->lazy_load_enabled ) { + $estimated_usage = $loaded_count * 0.25; // MB per table approximately + return sprintf( '约 %.1fMB (%d/%d 表已加载, 按需加载开启)', $estimated_usage, $loaded_count, $total_count ); + } else { + return '约 1.5MB (所有转换表已加载)'; + } + } + + public function enable_lazy_loading( $enable = true ) { + $this->lazy_load_enabled = $enable; + } + + public function is_lazy_loading_enabled() { + return $this->lazy_load_enabled; + } + + public static function get_loaded_tables_status() { + return self::$loaded_tables; + } + + public static function unload_table( $variant ) { + if ( isset( self::$loaded_tables[ $variant ] ) ) { + unset( self::$loaded_tables[ $variant ] ); + + // 清理对应的全局变量(这里只能标记,PHP不能真正释放全局变量内存) + return true; + } + return false; + } + + public function is_available() { + $conversion_file = dirname( dirname( __FILE__ ) ) . '/core/ZhConversion.php'; + return file_exists( $conversion_file ); + } + + private function ensure_conversion_tables_loaded( $target_variant = null ) { + if ( $this->lazy_load_enabled && $target_variant ) { + // 按需加载特定语言变体的转换表 + $this->ensure_specific_table_loaded( $target_variant ); + } else { + // 传统方式:加载所有转换表 + $this->load_all_conversion_tables(); + } + } + + private function ensure_specific_table_loaded( $target_variant ) { + if ( isset( self::$loaded_tables[ $target_variant ] ) ) { + return; // 已经加载 + } + + $conversion_file = dirname( dirname( __FILE__ ) ) . '/core/ZhConversion.php'; + if ( ! file_exists( $conversion_file ) ) { + return; + } + + // 只加载需要的转换表 + global $zh2Hans, $zh2Hant, $zh2CN, $zh2TW, $zh2HK, $zh2SG; + + switch ( $target_variant ) { + case 'zh-hans': + if ( ! isset( $zh2Hans ) ) { + $this->load_conversion_table_partial( 'zh2Hans' ); + } + self::$loaded_tables['zh-hans'] = true; + break; + + case 'zh-hant': + if ( ! isset( $zh2Hant ) ) { + $this->load_conversion_table_partial( 'zh2Hant' ); + } + self::$loaded_tables['zh-hant'] = true; + break; + + case 'zh-cn': + if ( ! isset( $zh2CN ) || ! isset( $zh2Hans ) ) { + $this->load_conversion_table_partial( array( 'zh2CN', 'zh2Hans' ) ); + } + self::$loaded_tables['zh-cn'] = true; + break; + + case 'zh-tw': + if ( ! isset( $zh2TW ) || ! isset( $zh2Hant ) ) { + $this->load_conversion_table_partial( array( 'zh2TW', 'zh2Hant' ) ); + } + self::$loaded_tables['zh-tw'] = true; + break; + + case 'zh-hk': + if ( ! isset( $zh2HK ) || ! isset( $zh2Hant ) ) { + $this->load_conversion_table_partial( array( 'zh2HK', 'zh2Hant' ) ); + } + self::$loaded_tables['zh-hk'] = true; + break; + + case 'zh-sg': + if ( ! isset( $zh2SG ) || ! isset( $zh2Hans ) ) { + $this->load_conversion_table_partial( array( 'zh2SG', 'zh2Hans' ) ); + } + self::$loaded_tables['zh-sg'] = true; + break; + + default: + $this->load_all_conversion_tables(); + break; + } + } + + private function load_conversion_table_partial( $table_names ) { + $conversion_file = dirname( dirname( __FILE__ ) ) . '/core/ZhConversion.php'; + + if ( ! is_array( $table_names ) ) { + $table_names = array( $table_names ); + } + + // 读取文件内容并解析指定的转换表 + $file_content = file_get_contents( $conversion_file ); + + foreach ( $table_names as $table_name ) { + $pattern = '/\$' . preg_quote( $table_name, '/' ) . '\s*=\s*array\s*\((.*?)\);/s'; + if ( preg_match( $pattern, $file_content, $matches ) ) { + $table_code = '$' . $table_name . ' = array(' . $matches[1] . ');'; + eval( $table_code ); + + // 将变量设置为全局 + $GLOBALS[ $table_name ] = ${$table_name}; + } + } + + // 加载额外转换文件 + $extra_conversion_file = WP_CONTENT_DIR . '/extra_zhconversion.php'; + if ( file_exists( $extra_conversion_file ) ) { + require_once $extra_conversion_file; + } + } + + private function load_all_conversion_tables() { + if ( $this->conversion_tables_loaded ) { + return; + } + + global $zh2Hans, $zh2Hant, $zh2CN, $zh2TW, $zh2HK, $zh2SG; + + if ( ! isset( $zh2Hans ) ) { + require_once dirname( dirname( __FILE__ ) ) . '/core/ZhConversion.php'; + + $extra_conversion_file = WP_CONTENT_DIR . '/extra_zhconversion.php'; + if ( file_exists( $extra_conversion_file ) ) { + require_once $extra_conversion_file; + } + } + + // 标记所有表为已加载 + self::$loaded_tables = array( + 'zh-hans' => true, + 'zh-hant' => true, + 'zh-cn' => true, + 'zh-tw' => true, + 'zh-hk' => true, + 'zh-sg' => true + ); + + $this->conversion_tables_loaded = true; + } + + private function convert_to_hans( $text ) { + global $zh2Hans; + return strtr( $text, $zh2Hans ); + } + + private function convert_to_hant( $text ) { + global $zh2Hant; + return strtr( $text, $zh2Hant ); + } + + private function convert_to_cn( $text ) { + global $zh2Hans, $zh2CN; + return strtr( strtr( $text, $zh2CN ), $zh2Hans ); + } + + private function convert_to_tw( $text ) { + global $zh2Hant, $zh2TW; + return strtr( strtr( $text, $zh2TW ), $zh2Hant ); + } + + private function convert_to_hk( $text ) { + global $zh2Hant, $zh2HK; + return strtr( strtr( $text, $zh2HK ), $zh2Hant ); + } + + private function convert_to_sg( $text ) { + global $zh2Hans, $zh2SG; + return strtr( strtr( $text, $zh2SG ), $zh2Hans ); + } +} \ No newline at end of file diff --git a/includes/core/class-wpcc-module-manager.php b/includes/core/class-module-manager.php similarity index 100% rename from includes/core/class-wpcc-module-manager.php rename to includes/core/class-module-manager.php diff --git a/includes/core/class-opencc-converter.php b/includes/core/class-opencc-converter.php new file mode 100644 index 0000000..8842971 --- /dev/null +++ b/includes/core/class-opencc-converter.php @@ -0,0 +1,159 @@ + Strategy::TRADITIONAL_TO_SIMPLIFIED, + 'zh-hant' => Strategy::SIMPLIFIED_TO_TRADITIONAL, + 'zh-cn' => Strategy::TRADITIONAL_TO_SIMPLIFIED, + 'zh-tw' => Strategy::SIMPLIFIED_TO_TAIWAN_WITH_PHRASE, + 'zh-hk' => Strategy::SIMPLIFIED_TO_HONGKONG, + 'zh-sg' => Strategy::TRADITIONAL_TO_SIMPLIFIED, + 'zh-jp' => Strategy::SIMPLIFIED_TO_JAPANESE, + ); + + public function convert( $text, $target_variant ) { + if ( empty( $text ) ) { + return $text; + } + + if ( ! $this->is_available() ) { + throw new Exception( 'OpenCC library is not available' ); + } + + if ( ! isset( $this->strategy_map[ $target_variant ] ) ) { + return $text; + } + + try { + return OpenCC::convert( $text, $this->strategy_map[ $target_variant ] ); + } catch ( Exception $e ) { + error_log( 'WPCC OpenCC Conversion Error: ' . $e->getMessage() ); + return $text; + } + } + + public function get_supported_variants() { + return array_keys( $this->strategy_map ); + } + + public function get_engine_name() { + return 'opencc'; + } + + public function get_engine_info() { + return array( + 'name' => 'OpenCC', + 'version' => '1.2.1', + 'description' => '基于 OpenCC 的智能词汇级转换引擎', + 'features' => array( + '词汇级别转换', + '异体字转换', + '地区习惯用词转换', + '智能语境分析', + '支持批量转换' + ), + 'memory_usage' => '按需加载,内存占用较低', + 'conversion_type' => 'vocabulary_based' + ); + } + + public function is_available() { + return class_exists( 'Overtrue\PHPOpenCC\OpenCC' ); + } + + public function batch_convert( $texts, $target_variant ) { + if ( ! $this->is_available() ) { + return $texts; + } + + if ( ! isset( $this->strategy_map[ $target_variant ] ) ) { + return $texts; + } + + if ( ! is_array( $texts ) ) { + return $texts; + } + + // 检查缓存 + $cached_results = array(); + $uncached_texts = array(); + $uncached_indices = array(); + + foreach ( $texts as $index => $text ) { + $cached_result = WPCC_Conversion_Cache::get_cached_conversion( $text, $target_variant ); + if ( $cached_result !== null ) { + $cached_results[ $index ] = $cached_result; + } else { + $uncached_texts[] = $text; + $uncached_indices[] = $index; + } + } + + // 如果所有内容都在缓存中,直接返回 + if ( empty( $uncached_texts ) ) { + $results = array(); + foreach ( $texts as $index => $text ) { + $results[] = $cached_results[ $index ]; + } + return $results; + } + + try { + // 转换未缓存的内容 + $converted_texts = OpenCC::convert( $uncached_texts, $this->strategy_map[ $target_variant ] ); + + // 合并结果并缓存新转换的内容 + $results = array(); + $uncached_index = 0; + + foreach ( $texts as $index => $original_text ) { + if ( isset( $cached_results[ $index ] ) ) { + $results[] = $cached_results[ $index ]; + } else { + $converted_text = is_array( $converted_texts ) ? $converted_texts[ $uncached_index ] : $converted_texts; + $results[] = $converted_text; + + // 缓存转换结果 + if ( $converted_text !== $original_text ) { + WPCC_Conversion_Cache::set_cached_conversion( $original_text, $target_variant, $converted_text ); + } + + $uncached_index++; + } + } + + return $results; + + } catch ( Exception $e ) { + error_log( 'WPCC OpenCC Batch Conversion Error: ' . $e->getMessage() ); + return $texts; + } + } + + public function get_available_strategies() { + return $this->strategy_map; + } + + public function convert_with_strategy( $text, $strategy ) { + if ( empty( $text ) || ! $this->is_available() ) { + return $text; + } + + try { + return OpenCC::convert( $text, $strategy ); + } catch ( Exception $e ) { + error_log( 'WPCC OpenCC Strategy Conversion Error: ' . $e->getMessage() ); + return $text; + } + } +} \ No newline at end of file diff --git a/includes/core/class-wpcc-config.php b/includes/core/class-wpcc-config.php index e4a106e..8620371 100644 --- a/includes/core/class-wpcc-config.php +++ b/includes/core/class-wpcc-config.php @@ -1,6 +1,6 @@ load_options(); $this->init_languages(); } - - public static function get_instance(): self - { - if (null === self::$instance) { + + public static function get_instance(): self { + if ( null === self::$instance ) { self::$instance = new self(); } return self::$instance; } - + /** * 加载插件选项 */ - private function load_options(): void - { - $options = $this->get_wpcc_options(); - - // 确保返回值是数组类型 - if (! is_array($options) || empty($options)) { + private function load_options(): void { + $this->options = get_wpcc_option( 'wpcc_options' ); + if ( empty( $this->options ) ) { $this->options = $this->get_default_options(); - } else { - $this->options = $options; } } - - /** - * 获取WPCC选项,考虑网络控制 - */ - private function get_wpcc_options(): array - { - // 获取本地选项 - $local_options = get_option('wpcc_options', []); - - // 如果不是多站点环境,直接返回本地选项 - if (! is_multisite() || is_network_admin()) { - return $local_options; - } - - // 检查网络控制 - if (! class_exists('WPCC_Network_Settings')) { - return $local_options; - } - - // 获取网络控制的选项列表 - $controlled_options = get_site_option('wpcc_network_controlled_options', []); - if (! is_array($controlled_options)) { - $controlled_options = explode(',', $controlled_options); - } - - // 如果没有网络控制选项,返回本地选项 - if (empty($controlled_options)) { - return $local_options; - } - - // 合并网络控制的选项 - $network_options = []; - - // 映射网络默认选项到本地选项名 - $option_mapping = [ - 'wpcc_default_used_langs' => 'wpcc_used_langs', - 'wpcc_default_cntip' => 'cntip', - 'wpcc_default_twtip' => 'twtip', - 'wpcc_default_hktip' => 'hktip', - 'wpcc_default_hanstip' => 'hanstip', - 'wpcc_default_hanttip' => 'hanttip', - 'wpcc_default_sgtip' => 'sgtip', - 'wpcc_default_jptip' => 'jptip', - 'wpcc_default_nctip' => 'nctip', - 'wpcc_default_flag_option' => 'wpcc_flag_option', - // Harmonize with single-site option key used in UI - 'wpcc_default_enable_extended_langs' => 'wpcc_show_more_langs', - 'wpcc_default_engine' => 'wpcc_engine', - 'wpcc_default_search_conversion' => 'wpcc_search_conversion', - 'wpcc_default_use_fullpage_conversion' => 'wpcc_use_fullpage_conversion', - // Quicktags uses wpcc_no_conversion_qtag in single-site - 'wpcc_default_no_conversion_qtag' => 'wpcc_no_conversion_qtag', - 'wpcc_default_enable_post_conversion' => 'wpcc_enable_post_conversion', - 'wpcc_default_post_conversion_target' => 'wpcc_post_conversion_target', - 'wpcc_default_use_permalink' => 'wpcc_use_permalink', - 'wpcc_default_sitemap_post_type' => 'wpcco_sitemap_post_type', - 'wpcc_default_use_sitemap' => 'wpcco_use_sitemap', - 'wpcc_default_browser_redirect' => 'wpcc_browser_redirect', - 'wpcc_default_auto_language_recong' => 'wpcc_auto_language_recong', - 'wpcc_default_use_cookie_variant' => 'wpcc_use_cookie_variant', - 'wpcc_default_no_conversion_tag' => 'wpcc_no_conversion_tag', - 'wpcc_default_no_conversion_ja' => 'wpcc_no_conversion_ja', - 'wpcc_default_hreflang_x_default' => 'wpcc_hreflang_x_default', - 'wpcc_default_enable_hreflang_tags' => 'wpcc_enable_hreflang_tags', - 'wpcc_default_enable_hreflang_x_default' => 'wpcc_enable_hreflang_x_default', - 'wpcc_default_enable_schema_conversion' => 'wpcc_enable_schema_conversion', - 'wpcc_default_enable_meta_conversion' => 'wpcc_enable_meta_conversion', - 'wpcc_default_enable_cache_addon' => 'wpcc_enable_cache_addon' - ]; - - // 对于每个被控制的选项,使用网络设置 - foreach ($controlled_options as $option_name) { - // 使用映射表查找对应的网络选项名 - $network_option_name = null; - - // 查找映射表中的对应关系 - foreach ($option_mapping as $network_key => $local_key) { - if ($local_key === $option_name) { - $network_option_name = $network_key; - break; - } - } - - // 如果映射表中没有找到,使用默认规则 - if (!$network_option_name) { - $network_option_name = 'wpcc_default_' . str_replace('wpcc_', '', $option_name); - } - - // 获取网络设置值 - $network_value = get_site_option($network_option_name); - if ($network_value !== false) { - $network_options[$option_name] = $network_value; - } - } - - // 合并选项:网络控制的选项覆盖本地选项 - return array_merge($local_options, $network_options); - } - + /** * 获取默认配置 */ - private function get_default_options(): array - { + private function get_default_options(): array { return [ // 语言与标签 - 'wpcc_used_langs' => ['zh-cn', 'zh-tw'], + 'wpcc_used_langs' => ['zh-cn','zh-tw'], 'cntip' => '简体', 'twtip' => '繁体', 'hktip' => '港澳', @@ -176,7 +69,7 @@ class WPCC_Config 'wpcc_use_cookie_variant' => 1, // 不转换 - 'wpcc_no_conversion_tag' => '', +'wpcc_no_conversion_tag' => 'pre,code,pre.wp-block-code,pre.wp-block-preformatted,script,noscript,style,kbd,samp', 'wpcc_no_conversion_ja' => 0, 'wpcc_no_conversion_qtag' => 0, @@ -191,12 +84,10 @@ class WPCC_Config // SEO 'wpcc_enable_hreflang_tags' => 1, - 'wpcc_enable_hreflang_x_default' => 1, 'wpcc_hreflang_x_default' => 'zh-cn', 'wpcc_enable_schema_conversion' => 1, 'wpcc_enable_meta_conversion' => 1, - // 其他 'wpcc_flag_option' => 1, 'wpcc_trackback_plugin_author' => 0, @@ -207,210 +98,193 @@ class WPCC_Config 'wpcc_enable_network_module' => 0, ]; } - + /** * 初始化语言配置 */ - private function init_languages(): void - { - // 使用中心化的语言配置 - $this->languages = WPCC_Language_Config::get_all_languages(); + private function init_languages(): void { + $this->languages = [ + 'zh-cn' => [ 'zhconversion_cn', 'cntip', __( '简体中文', 'wp-chinese-converter' ), 'zh-CN' ], + 'zh-tw' => [ 'zhconversion_tw', 'twtip', __( '台灣正體', 'wp-chinese-converter' ), 'zh-TW' ], + 'zh-hk' => [ 'zhconversion_hk', 'hktip', __( '港澳繁體', 'wp-chinese-converter' ), 'zh-HK' ], + 'zh-hans' => [ 'zhconversion_hans', 'hanstip', __( '简体中文', 'wp-chinese-converter' ), 'zh-Hans' ], + 'zh-hant' => [ 'zhconversion_hant', 'hanttip', __( '繁体中文', 'wp-chinese-converter' ), 'zh-Hant' ], + 'zh-sg' => [ 'zhconversion_sg', 'sgtip', __( '马新简体', 'wp-chinese-converter' ), 'zh-SG' ], + 'zh-jp' => [ 'zhconversion_jp', 'jptip', __( '日式汉字', 'wp-chinese-converter' ), 'zh-JP' ], + ]; } - + /** * 获取配置选项 */ - public function get_option(string $key, $default = null) - { + public function get_option( string $key, $default = null ) { return $this->options[$key] ?? $default; } - + /** * 设置配置选项 */ - public function set_option(string $key, $value): void - { + public function set_option( string $key, $value ): void { $this->options[$key] = $value; } - + /** * 更新配置选项到数据库 */ - public function save_options(): bool - { - return update_option('wpcc_options', $this->options); + public function save_options(): bool { + return update_wpcc_option( 'wpcc_options', $this->options ); } - + /** * 获取所有配置选项 */ - public function get_all_options(): array - { + public function get_all_options(): array { return $this->options; } - + /** * 获取语言配置 */ - public function get_languages(): array - { + public function get_languages(): array { return $this->languages; } - + /** * 获取特定语言配置 */ - public function get_language(string $lang_code): ?array - { + public function get_language( string $lang_code ): ?array { return $this->languages[$lang_code] ?? null; } - + /** * 设置目标语言 */ - public function set_target_lang(string $lang): void - { + public function set_target_lang( string $lang ): void { $this->target_lang = $lang; } - + /** * 获取目标语言 */ - public function get_target_lang(): string - { + public function get_target_lang(): string { return $this->target_lang; } - + /** * 设置无转换URL */ - public function set_noconversion_url(string $url): void - { + public function set_noconversion_url( string $url ): void { $this->noconversion_url = $url; } - + /** * 获取无转换URL */ - public function get_noconversion_url(): string - { + public function get_noconversion_url(): string { return $this->noconversion_url; } - + /** * 设置语言URL映射 */ - public function set_langs_urls(array $urls): void - { + public function set_langs_urls( array $urls ): void { $this->langs_urls = $urls; } - + /** * 获取语言URL映射 */ - public function get_langs_urls(): array - { + public function get_langs_urls(): array { return $this->langs_urls; } - + /** * 设置重定向标志 */ - public function set_redirect_to(bool $redirect): void - { + public function set_redirect_to( bool $redirect ): void { $this->redirect_to = $redirect; } - + /** * 获取重定向标志 */ - public function get_redirect_to(): bool - { + public function get_redirect_to(): bool { return $this->redirect_to; } - + /** * 设置直接转换标志 */ - public function set_direct_conversion_flag(bool $flag): void - { + public function set_direct_conversion_flag( bool $flag ): void { $this->direct_conversion_flag = $flag; } - + /** * 获取直接转换标志 */ - public function get_direct_conversion_flag(): bool - { + public function get_direct_conversion_flag(): bool { return $this->direct_conversion_flag; } - + /** * 添加调试数据 */ - public function add_debug_data(string $key, $data): void - { - if (defined('wpcc_DEBUG') && wpcc_DEBUG) { + public function add_debug_data( string $key, $data ): void { + if ( defined( 'wpcc_DEBUG' ) && wpcc_DEBUG ) { $this->debug_data[$key] = $data; } } - + /** * 获取调试数据 */ - public function get_debug_data(): array - { + public function get_debug_data(): array { return $this->debug_data; } - + /** * 检查是否启用了指定功能 */ - public function is_feature_enabled(string $feature): bool - { - return (bool) $this->get_option($feature, false); + public function is_feature_enabled( string $feature ): bool { + return (bool) $this->get_option( $feature, false ); } - + /** * 获取启用的语言列表 */ - public function get_enabled_languages(): array - { - return $this->get_option('wpcc_used_langs', []); + public function get_enabled_languages(): array { + return $this->get_option( 'wpcc_used_langs', [] ); } - + /** * 检查语言是否启用 */ - public function is_language_enabled(string $lang_code): bool - { - return in_array($lang_code, $this->get_enabled_languages(), true); + public function is_language_enabled( string $lang_code ): bool { + return in_array( $lang_code, $this->get_enabled_languages(), true ); } - + /** * 获取转换引擎 */ - public function get_conversion_engine(): string - { - return $this->get_option('wpcc_engine', 'opencc'); + public function get_conversion_engine(): string { + return $this->get_option( 'wpcc_engine', 'opencc' ); } - + /** * 验证配置完整性 */ - public function validate_config(): array - { + public function validate_config(): array { $errors = []; - - if (empty($this->get_enabled_languages())) { + + if ( empty( $this->get_enabled_languages() ) ) { $errors[] = 'No languages enabled'; } - + $engine = $this->get_conversion_engine(); - if (! in_array($engine, ['opencc', 'mediawiki'])) { + if ( ! in_array( $engine, ['opencc', 'mediawiki'] ) ) { $errors[] = 'Invalid conversion engine: ' . $engine; } - + return $errors; } -} +} \ No newline at end of file diff --git a/includes/core/class-wpcc-exception-handler.php b/includes/core/class-wpcc-exception-handler.php index 07b7b10..cfb681a 100644 --- a/includes/core/class-wpcc-exception-handler.php +++ b/includes/core/class-wpcc-exception-handler.php @@ -194,14 +194,8 @@ final class WPCC_Exception_Handler { return; } - // 统一异常计数键,保证与 should_suppress_error 使用的键一致 - if ( $exception instanceof WPCC_Exception ) { - $ekey = 'wpcc_error_' . $exception->get_error_code(); - self::$error_counts[ $ekey ] = ( self::$error_counts[ $ekey ] ?? 0 ) + 1; - } else { - $ekey = get_class( $exception ); - self::$error_counts[ $ekey ] = ( self::$error_counts[ $ekey ] ?? 0 ) + 1; - } + $error_key = get_class( $exception ); + self::$error_counts[ $error_key ] = ( self::$error_counts[ $error_key ] ?? 0 ) + 1; $log_message = sprintf( 'WPCC Error in %s: %s [%s:%d] Context: %s', diff --git a/includes/core/class-wpcc-extension.php b/includes/core/class-wpcc-extension.php index b471551..52497ec 100644 --- a/includes/core/class-wpcc-extension.php +++ b/includes/core/class-wpcc-extension.php @@ -18,7 +18,7 @@ abstract class WPCC_Extension extends WPCC_Abstract_Module { protected $update_server_url; protected $extension_slug; protected $is_premium = true; -protected $required_core_version = '1.5'; + protected $required_core_version = '1.3.0'; protected $pricing_tier = 'pro'; // free, pro, enterprise, ultimate public function __construct() { diff --git a/includes/core/class-wpcc-language-config.php b/includes/core/class-wpcc-language-config.php deleted file mode 100644 index 979b3a6..0000000 --- a/includes/core/class-wpcc-language-config.php +++ /dev/null @@ -1,165 +0,0 @@ - [转换函数名, 选项键名, 默认显示名, BCP47代码]] - */ - private static array $languages = []; - - /** - * 默认语言显示名称 - */ - private static array $default_names = [ - 'zh-cn' => '简体中文', - 'zh-tw' => '台灣正體', - 'zh-hk' => '港澳繁體', - 'zh-hans' => '简体中文', - 'zh-hant' => '繁体中文', - 'zh-sg' => '马新简体', - 'zh-jp' => '日式汉字', - ]; - - /** - * 初始化语言配置 - */ - public static function init(): void { - if ( ! empty( self::$languages ) ) { - return; - } - - self::$languages = [ - 'zh-cn' => [ 'zhconversion_cn', 'cntip', self::get_translated_name( 'zh-cn' ), 'zh-CN' ], - 'zh-tw' => [ 'zhconversion_tw', 'twtip', self::get_translated_name( 'zh-tw' ), 'zh-TW' ], - 'zh-hk' => [ 'zhconversion_hk', 'hktip', self::get_translated_name( 'zh-hk' ), 'zh-HK' ], - 'zh-hans' => [ 'zhconversion_hans', 'hanstip', self::get_translated_name( 'zh-hans' ), 'zh-Hans' ], - 'zh-hant' => [ 'zhconversion_hant', 'hanttip', self::get_translated_name( 'zh-hant' ), 'zh-Hant' ], - 'zh-sg' => [ 'zhconversion_sg', 'sgtip', self::get_translated_name( 'zh-sg' ), 'zh-SG' ], - 'zh-jp' => [ 'zhconversion_jp', 'jptip', self::get_translated_name( 'zh-jp' ), 'zh-JP' ], - ]; - } - - /** - * 获取翻译后的语言名称 - */ - private static function get_translated_name( string $lang_code ): string { - // 只在WordPress完全初始化后才使用翻译函数 - if ( function_exists( 'did_action' ) && did_action( 'init' ) && function_exists( '__' ) ) { - return __( self::$default_names[ $lang_code ] ?? $lang_code, 'wp-chinese-converter' ); - } - return self::$default_names[ $lang_code ] ?? $lang_code; - } - - /** - * 获取所有语言配置 - */ - public static function get_all_languages(): array { - self::init(); - return self::$languages; - } - - /** - * 获取特定语言配置 - */ - public static function get_language( string $lang_code ): ?array { - self::init(); - return self::$languages[ $lang_code ] ?? null; - } - - /** - * 获取语言显示名称 - */ - public static function get_language_name( string $lang_code, ?array $custom_names = null ): string { - self::init(); - - // 优先使用自定义名称 - if ( $custom_names && isset( $custom_names[ $lang_code ] ) ) { - return $custom_names[ $lang_code ]; - } - - // 使用配置中的名称 - if ( isset( self::$languages[ $lang_code ][2] ) ) { - return self::$languages[ $lang_code ][2]; - } - - // 降级到默认名称 - return self::$default_names[ $lang_code ] ?? $lang_code; - } - - /** - * 获取语言的BCP47代码 - */ - public static function get_bcp47_code( string $lang_code ): string { - self::init(); - return self::$languages[ $lang_code ][3] ?? $lang_code; - } - - /** - * 获取语言的转换函数名 - */ - public static function get_conversion_function( string $lang_code ): ?string { - self::init(); - return self::$languages[ $lang_code ][0] ?? null; - } - - /** - * 获取语言的选项键名 - */ - public static function get_option_key( string $lang_code ): ?string { - self::init(); - return self::$languages[ $lang_code ][1] ?? null; - } - - /** - * 检查语言代码是否有效 - */ - public static function is_valid_language( string $lang_code ): bool { - self::init(); - return isset( self::$languages[ $lang_code ] ); - } - - /** - * 获取所有有效的语言代码 - */ - public static function get_valid_language_codes(): array { - self::init(); - return array_keys( self::$languages ); - } - - /** - * 获取自定义语言名称配置 - * - * @param array $options 插件选项数组 - * @return array 自定义名称数组 - */ - public static function get_custom_names( array $options ): array { - self::init(); - - $custom_names = []; - foreach ( self::$languages as $code => $config ) { - $option_key = $config[1]; - $default_name = self::$default_names[ $code ]; - $custom_names[ $code ] = $options[ $option_key ] ?? $default_name; - } - - return $custom_names; - } - - /** - * 获取默认语言名称 - */ - public static function get_default_names(): array { - return self::$default_names; - } -} diff --git a/includes/core/class-wpcc-main.php b/includes/core/class-wpcc-main.php index 2dfa84d..89ec156 100644 --- a/includes/core/class-wpcc-main.php +++ b/includes/core/class-wpcc-main.php @@ -40,14 +40,9 @@ class WPCC_Main { add_action( 'init', [ $this, 'init' ], 1 ); add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] ); add_filter( 'query_vars', [ $this, 'add_query_vars' ] ); - // 在 WordPress 基于重写规则生成 query_vars 之后,优先级0先行修正 pagename=zh-xx 的场景 - add_filter( 'request', [ $this, 'filter_request_vars' ], 0 ); add_action( 'parse_request', [ $this, 'parse_request' ] ); add_action( 'template_redirect', [ $this, 'template_redirect' ], -100 ); - // 进一步兜底:在主查询生成前修正“纯语言前缀”为首页查询 - add_action( 'pre_get_posts', [ $this, 'pre_get_posts_fix' ], 0 ); - // 调试模式钩子 if ( WP_DEBUG || ( defined( 'wpcc_DEBUG' ) && wpcc_DEBUG ) ) { add_action( 'init', [ $this, 'flush_rewrite_rules' ] ); @@ -65,12 +60,6 @@ class WPCC_Main { $this->handle_config_errors( $config_errors ); return; } - - // 标记 AJAX/REST/wc-ajax 请求为"直接输出",跳过页面级转换 - $is_ajax = function_exists('wp_doing_ajax') ? wp_doing_ajax() : ( defined('DOING_AJAX') && DOING_AJAX ); - $is_rest = defined('REST_REQUEST') && REST_REQUEST; - $is_wc_ajax = isset($_REQUEST['wc-ajax']) && is_string($_REQUEST['wc-ajax']) && $_REQUEST['wc-ajax'] !== ''; - $this->config->set_direct_conversion_flag( (bool) ( $is_ajax || $is_rest || $is_wc_ajax ) ); // 初始化模块 $this->init_modules(); @@ -78,8 +67,6 @@ class WPCC_Main { // 设置重写规则 if ( $this->config->is_feature_enabled( 'wpcc_use_permalink' ) ) { $this->setup_rewrite_rules(); - // 自愈:在启用固定链接模式但尚未生成 WPCC 语言规则时,尝试一次性刷新重写规则,避免 /zh-xx/ 访问 404 - $this->maybe_autoflush_rewrite_rules(); } // 处理评论提交 @@ -121,7 +108,7 @@ class WPCC_Main { // 注册核心模块 $this->module_manager->register_module( 'WPCC_Cache_Addon', $modules_dir . 'wpcc-cache-addon.php' ); - // $this->module_manager->register_module( 'WPCC_Network', $modules_dir . 'wpcc-network.php' ); // 已被新的网络设置模块替代 + $this->module_manager->register_module( 'WPCC_Network', $modules_dir . 'wpcc-network.php' ); $this->module_manager->register_module( 'WPCC_Rest_Api', $modules_dir . 'wpcc-rest-api.php' ); $this->module_manager->register_module( 'WPCC_Modern_Cache', $modules_dir . 'wpcc-modern-cache.php' ); $this->module_manager->register_module( 'WPCC_SEO_Enhancement', $modules_dir . 'wpcc-seo-enhancement.php' ); @@ -174,19 +161,6 @@ class WPCC_Main { if ( is_robots() ) { return; } - - // 兜底:若 rewrite 未捕获到 variant,但路径以语言前缀开头,则从路径中注入 variant - $path = isset( $wp->request ) ? trim( (string) $wp->request, "\r\n\t " ) : ''; - if ( empty( $wp->query_vars['variant'] ) && is_string( $path ) && $path !== '' ) { - $enabled = $this->config->get_enabled_languages(); - if ( ! empty( $enabled ) && is_array( $enabled ) ) { - $reg = implode( '|', array_map( 'preg_quote', $enabled ) ); - if ( preg_match( '/^(' . $reg . '|zh|zh-reset)(?:\/)?$/i', $path, $m ) ) { - // 仅当是“纯前缀”(如 zh-tw/ 或 zh/)时兜底注入; - $wp->query_vars['variant'] = strtolower( $m[1] ); - } - } - } if ( is_404() ) { $this->config->set_noconversion_url( home_url( '/' ) ); @@ -197,30 +171,11 @@ class WPCC_Main { // 设置无转换URL $noconversion_url = $this->get_noconversion_url(); $this->config->set_noconversion_url( $noconversion_url ); - // 向后兼容:同步全局变量 - $GLOBALS['wpcc_noconversion_url'] = $noconversion_url; // 获取目标语言 $target_lang = $this->determine_target_language( $wp ); $this->config->set_target_lang( $target_lang ); - // 向后兼容:同步全局变量 - $GLOBALS['wpcc_target_lang'] = $target_lang; - // 若首页为静态页面且请求为根级变体路径,则直接映射到首页,避免 404 - if ( get_option( 'show_on_front' ) === 'page' && get_option( 'page_on_front' ) ) { - $req_path = isset( $wp->request ) ? trim( (string) $wp->request, '/' ) : ''; - if ( $req_path !== '' ) { - $enabled = $this->config->get_enabled_languages(); - if ( ! empty( $enabled ) ) { - $pattern = '/^(?:' . implode( '|', array_map( 'preg_quote', $enabled ) ) . '|zh|zh-reset)$/i'; - if ( preg_match( $pattern, $req_path ) ) { - $wp->query_vars['page_id'] = (int) get_option( 'page_on_front' ); - unset( $wp->query_vars['pagename'], $wp->query_vars['name'] ); - } - } - } - } - // 处理搜索转换 $this->handle_search_conversion(); @@ -232,25 +187,20 @@ class WPCC_Main { * 确定目标语言 */ private function determine_target_language( $wp ): string { - $request_lang = isset( $wp->query_vars['variant'] ) ? sanitize_text_field( $wp->query_vars['variant'] ) : ''; - $cookie_lang = isset( $_COOKIE[ 'wpcc_variant_' . COOKIEHASH ] ) ? sanitize_text_field( wp_unslash( $_COOKIE[ 'wpcc_variant_' . COOKIEHASH ] ) ) : ''; + $request_lang = $wp->query_vars['variant'] ?? ''; + $cookie_lang = $_COOKIE[ 'wpcc_variant_' . COOKIEHASH ] ?? ''; // 检查URL参数中的语言 if ( $request_lang && $this->config->is_language_enabled( $request_lang ) ) { return $request_lang; } - // 处理特殊的'zh'重定向(用户明确选择“原始/不转换”) + // 处理特殊的'zh'重定向 if ( $request_lang === 'zh' && ! is_admin() ) { $this->handle_zh_redirect(); return ''; } - // 如果Cookie中记录了'zh'哨兵,则优先恢复为“不转换” - if ( $cookie_lang === 'zh' ) { - return ''; - } - // 浏览器语言检测 if ( $this->config->is_feature_enabled( 'wpcc_browser_redirect' ) ) { $browser_lang = $this->detect_browser_language(); @@ -276,23 +226,9 @@ class WPCC_Main { $cookie_key = 'wpcc_variant_' . COOKIEHASH; if ( $this->config->is_feature_enabled( 'wpcc_use_cookie_variant' ) ) { - setcookie( $cookie_key, 'zh', [ - 'expires' => time() + 30000000, - 'path' => COOKIEPATH, - 'domain' => COOKIE_DOMAIN, - 'secure' => is_ssl(), - 'httponly' => true, - 'samesite' => 'Lax', - ] ); + setcookie( $cookie_key, 'zh', time() + 30000000, COOKIEPATH, COOKIE_DOMAIN ); } else { - setcookie( 'wpcc_is_redirect_' . COOKIEHASH, '1', [ - 'expires' => 0, - 'path' => COOKIEPATH, - 'domain' => COOKIE_DOMAIN, - 'secure' => is_ssl(), - 'httponly' => true, - 'samesite' => 'Lax', - ] ); + setcookie( 'wpcc_is_redirect_' . COOKIEHASH, '1', 0, COOKIEPATH, COOKIE_DOMAIN ); } wp_redirect( $this->config->get_noconversion_url() ); @@ -303,7 +239,7 @@ class WPCC_Main { * 检测浏览器语言 */ private function detect_browser_language(): string { - $accept_language = isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ) : ''; + $accept_language = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? ''; if ( empty( $accept_language ) ) { return ''; } @@ -327,14 +263,7 @@ class WPCC_Main { $current_cookie = $_COOKIE[$cookie_key] ?? ''; if ( $current_cookie !== $target_lang ) { - setcookie( $cookie_key, $target_lang, [ - 'expires' => time() + 30000000, - 'path' => COOKIEPATH, - 'domain' => COOKIE_DOMAIN, - 'secure' => is_ssl(), - 'httponly' => true, - 'samesite' => 'Lax', - ] ); + setcookie( $cookie_key, $target_lang, time() + 30000000, COOKIEPATH, COOKIE_DOMAIN ); } } @@ -355,65 +284,18 @@ class WPCC_Main { * 模板重定向处理 */ public function template_redirect(): void { - // 排除 WooCommerce 关键页面(结算、购物车、我的账户等),避免转换影响功能 - if ( function_exists( 'is_checkout' ) && is_checkout() ) { - return; - } - if ( function_exists( 'is_cart' ) && is_cart() ) { - return; - } - if ( function_exists( 'is_account_page' ) && is_account_page() ) { - return; - } - $this->set_language_urls(); - // 处理“根级语言前缀”访问:/zh-xx/ 或 /zh/ - if ( ! is_admin() ) { - global $wp; - $req = isset( $wp->request ) ? trim( (string) $wp->request, "/" ) : ''; - if ( $req !== '' ) { - $enabled = $this->config->get_enabled_languages(); - $pattern = '/^(?:' . implode( '|', array_map( 'preg_quote', $enabled ) ) . '|zh|zh-reset)$/i'; - if ( preg_match( $pattern, $req ) ) { - // 禁用本次自动重定向(避免将根级变体再次重定向到其它 URL) - if ( method_exists( $this->config, 'set_redirect_to' ) ) { - $this->config->set_redirect_to( false ); - } - $v = strtolower( $req ); - - // 仅 zh/zh-reset 使用哨兵重定向到不转换首页;其它根级变体在当前 URL 下渲染(避免缓存都命中 /) - if ( $v === 'zh' || $v === 'zh-reset' ) { - $this->handle_zh_redirect(); - return; - } - - // 在根级变体 URL 下渲染首页:由下游 pre_get_posts/filter_request_vars 修正查询为首页 - // 注入头部脚本供前端使用 - add_action( 'wp_head', [ $this, 'output_header' ] ); - } - } - } - // 处理重定向 if ( ! is_404() && $this->config->get_redirect_to() && ! is_admin() ) { $redirect_url = $this->config->get_langs_urls()[ $this->config->get_redirect_to() ]; - setcookie( 'wpcc_is_redirect_' . COOKIEHASH, '1', [ - 'expires' => 0, - 'path' => COOKIEPATH, - 'domain' => COOKIE_DOMAIN, - 'secure' => is_ssl(), - 'httponly' => true, - 'samesite' => 'Lax', - ] ); + setcookie( 'wpcc_is_redirect_' . COOKIEHASH, '1', 0, COOKIEPATH, COOKIE_DOMAIN ); wp_redirect( $redirect_url, 302 ); exit; } $target_lang = $this->config->get_target_lang(); if ( ! $target_lang ) { - // 即使是“未选择语言(不转换)”也输出头部数据,供前端开关生成漂亮链接 - add_action( 'wp_head', [ $this, 'output_header' ] ); return; } @@ -430,36 +312,23 @@ class WPCC_Main { private function set_language_urls(): void { $langs_urls = []; $noconversion_url = $this->config->get_noconversion_url(); - $style = (int) $this->config->get_option( 'wpcc_use_permalink', 0 ); - $style_effective = $this->is_permalinks_enabled() ? $style : 0; + $use_permalink = $this->config->is_feature_enabled( 'wpcc_use_permalink' ); - // 语言映射 foreach ( $this->config->get_enabled_languages() as $lang ) { - if ( $style_effective !== 0 && $noconversion_url === home_url( '/' ) ) { + if ( $noconversion_url === home_url( '/' ) && $use_permalink ) { $langs_urls[$lang] = $noconversion_url . $lang . '/'; } else { $langs_urls[$lang] = $this->convert_link( $noconversion_url, $lang ); } } - // 增加 zh 哨兵映射,便于前端/菜单快速回到“不转换”状态 - // 在前缀/后缀模式下输出漂亮链接;在查询参数模式下回退为 ?variant=zh - $langs_urls['zh'] = $this->convert_link( $noconversion_url, 'zh' ); - $this->config->set_langs_urls( $langs_urls ); - // 向后兼容:同步全局变量 - $GLOBALS['wpcc_langs_urls'] = $langs_urls; } /** * 执行转换 */ private function do_conversion(): void { - // 若是 AJAX/REST/wc-ajax 等非 HTML 响应,直接跳过所有转换,避免破坏 JSON/片段 - if ( $this->config->get_direct_conversion_flag() ) { - return; - } - // 加载转换表 $this->load_conversion_table(); @@ -473,14 +342,6 @@ class WPCC_Main { // 添加链接转换过滤器 $this->add_link_conversion_filters(); - - // 导航与 Logo 链接也加入变体(兼容经典菜单与站点 Logo) - // 注意:不在 home_url 上挂钩,避免 convert_link 内部调用 home_url 时产生递归 - add_filter( 'get_custom_logo', [ $this, 'filter_custom_logo' ], 10, 1 ); - add_filter( 'wp_nav_menu', [ $this, 'filter_wp_nav_menu' ], 20, 2 ); - - // 取消错误的 canonical 跳转,避免语言前缀被 WP 错误重定向 - add_filter( 'redirect_canonical', [ $this, 'cancel_incorrect_redirect' ], 10, 2 ); } // 内容转换过滤器 @@ -549,24 +410,16 @@ class WPCC_Main { // 这里添加其他必要的私有方法... - /** - * 检查 WordPress 是否启用了固定链接 - */ - private function is_permalinks_enabled(): bool { - $structure = get_option( 'permalink_structure' ); - return is_string( $structure ) && $structure !== ''; - } - /** * 获取无转换URL */ private function get_noconversion_url(): string { $enabled_langs = $this->config->get_enabled_languages(); - $reg = implode( '|', array_map( 'preg_quote', $enabled_langs ) ); + $reg = implode( '|', $enabled_langs ); $protocol = is_ssl() ? 'https://' : 'http://'; - $host = isset( $_SERVER['HTTP_HOST'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : ''; - $uri = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; + $host = $_SERVER['HTTP_HOST'] ?? ''; + $uri = $_SERVER['REQUEST_URI'] ?? ''; $tmp = trim( strtolower( remove_query_arg( 'variant', $protocol . $host . $uri ) ) ); @@ -584,80 +437,7 @@ class WPCC_Main { * 设置重写规则 */ private function setup_rewrite_rules(): void { - // 仅在 WP 启用了固定链接 且 插件启用了固定链接格式时设置重写规则 - if ( ! $this->is_permalinks_enabled() || ! $this->config->is_feature_enabled( 'wpcc_use_permalink' ) ) { - return; - } add_filter( 'rewrite_rules_array', [ $this, 'modify_rewrite_rules' ] ); - - // 显式在规则顶端加入"根级变体"规则,确保 /zh-xx/ 能优先匹配到首页 - $enabled = $this->config->get_enabled_languages(); - if ( ! empty( $enabled ) && function_exists( 'add_rewrite_rule' ) ) { - $reg = implode( '|', array_map( 'preg_quote', $enabled ) ); - add_rewrite_rule( '^(' . $reg . '|zh|zh-reset)/?$', 'index.php?variant=$matches[1]', 'top' ); - - // 强制在init钩子中添加根级规则,确保优先级 - add_action( 'init', function() use ( $reg ) { - add_rewrite_rule( '^(' . $reg . '|zh|zh-reset)/?$', 'index.php?variant=$matches[1]', 'top' ); - }, 5 ); // 优先级5,早于大部分其他规则 - } - } - - /** - * 如有必要,自动刷新一次重写规则,避免未刷新导致的 404 - */ - private function maybe_autoflush_rewrite_rules(): void { - // 仅在启用了固定链接模式且 WP 启用了固定链接时尝试 - if ( ! $this->config->is_feature_enabled( 'wpcc_use_permalink' ) || ! $this->is_permalinks_enabled() ) { - return; - } - - // 延迟执行,确保所有规则都已加载 - add_action( 'wp_loaded', [ $this, 'check_and_flush_rules' ], 10 ); - } - - /** - * 检查并刷新规则 - */ - public function check_and_flush_rules(): void { - // 6 小时内最多尝试一次 - $last = (int) get_option( 'wpcc_rewrite_autoflush_ts', 0 ); - if ( $last && ( time() - $last ) < 6 * 3600 ) { - return; - } - - // 检查当前规则中是否已经包含根级的语言捕获规则 - $rules = get_option( 'rewrite_rules' ); - if ( ! is_array( $rules ) ) { - $rules = []; - } - - $enabled_langs = $this->config->get_enabled_languages(); - if ( empty( $enabled_langs ) ) { - return; - } - - $reg = implode( '|', $enabled_langs ); - $expected = '^(' . $reg . '|zh|zh-reset)/?$'; - $has_expected = false; - - foreach ( $rules as $regex => $query ) { - if ( $regex === $expected && strpos( $query, 'variant=' ) !== false ) { - $has_expected = true; - break; - } - } - - if ( ! $has_expected && function_exists( 'flush_rewrite_rules' ) ) { - // 刷新一次规则 - flush_rewrite_rules( false ); - update_option( 'wpcc_rewrite_autoflush_ts', time() ); - - // 记录日志 - if ( defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ) { - error_log( 'WPCC: Auto-flushed rewrite rules for language variants' ); - } - } } /** @@ -670,10 +450,6 @@ class WPCC_Main { $use_permalink = $this->config->get_option( 'wpcc_use_permalink', 0 ); - // 首先添加根级语言规则,确保最高优先级 - $root_rule_key = '^(' . $reg . '|zh|zh-reset)/?$'; - $rules2[ $root_rule_key ] = 'index.php?variant=$matches[1]'; - if ( $use_permalink == 1 ) { foreach ( $rules as $key => $value ) { if ( strpos( $key, 'trackback' ) !== false || strpos( $key, 'print' ) !== false || strpos( $value, 'lang=' ) !== false ) { @@ -698,6 +474,7 @@ class WPCC_Main { } } + $rules2[ '^(' . $reg . '|zh|zh-reset)/?$' ] = 'index.php?variant=$matches[1]'; return array_merge( $rules2, $rules ); } @@ -712,21 +489,15 @@ class WPCC_Main { * 处理评论提交 */ private function handle_comment_submission(): void { - $php_self = isset( $_SERVER['PHP_SELF'] ) ? sanitize_text_field( wp_unslash( $_SERVER['PHP_SELF'] ) ) : ''; - $request_method = isset( $_SERVER['REQUEST_METHOD'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) : ''; - - if ( ( $php_self && ( strpos( $php_self, 'wp-comments-post.php' ) !== false - || strpos( $php_self, 'ajax-comments.php' ) !== false - || strpos( $php_self, 'comments-ajax.php' ) !== false ) + if ( ( isset( $_SERVER['PHP_SELF'] ) && ( strpos( $_SERVER['PHP_SELF'], 'wp-comments-post.php' ) !== false + || strpos( $_SERVER['PHP_SELF'], 'ajax-comments.php' ) !== false + || strpos( $_SERVER['PHP_SELF'], 'comments-ajax.php' ) !== false ) ) && - $request_method === 'POST' && - isset( $_POST['variant'] ) && ! empty( $_POST['variant'] ) + isset( $_SERVER["REQUEST_METHOD"] ) && $_SERVER["REQUEST_METHOD"] == "POST" && + isset( $_POST['variant'] ) && ! empty( $_POST['variant'] ) && $this->config->is_language_enabled( $_POST['variant'] ) ) { - $variant = sanitize_text_field( wp_unslash( $_POST['variant'] ) ); - if ( $this->config->is_language_enabled( $variant ) ) { - $this->config->set_target_lang( $variant ); - $this->do_conversion(); - } + $this->config->set_target_lang( sanitize_text_field( $_POST['variant'] ) ); + $this->do_conversion(); } } @@ -763,8 +534,17 @@ class WPCC_Main { public function render_no_conversion_block( string $block_content, array $block ): string { if ( isset( $block['blockName'] ) && $block['blockName'] === 'wpcc/no-conversion' ) { $unique_id = uniqid(); - return '' . $block_content . ''; + + $pattern = '/' . - "WP Chinese Converter 插件正由网络管理员强制管理。所有设置将使用网络级别配置,任何更改将被忽略。如有疑问请联系网络管理员。" . - "
' . - sprintf( - "WP Chinese Converter 插件的 %d 项设置由网络管理员控制。这些设置的更改将不会生效。", - $controlled_count, - ) . - "
网络设置已更新。
设置导入成功。
网络设置已重置为默认值。
已成功重置 ' . - $reset_count . - " 个站点的设置。
- -
| - - ">↗ - | -
- 0,
- "opencc" => 0,
- "other" => 0,
- ];
- $language_stats = [];
-
- foreach ($sites as $site) {
- switch_to_blog($site->blog_id);
- $options = get_option("wpcc_options", []);
-
- if (!empty($options)) {
- $active_sites++;
-
- // 统计引擎使用情况
- $engine =
- $options["wpcc_engine"] ??
- "mediawiki";
- if (isset($engine_stats[$engine])) {
- $engine_stats[$engine]++;
- } else {
- $engine_stats["other"]++;
- }
-
- // 统计语言使用情况
- $used_langs =
- $options["wpcc_used_langs"] ?? [];
- foreach ($used_langs as $lang) {
- if (
- !isset($language_stats[$lang])
- ) {
- $language_stats[$lang] = 0;
- }
- $language_stats[$lang]++;
- }
- }
-
- restore_current_blog();
- }
- ?>
-
-
-
-
- 0): ?>
-
-
-
- 总站点数
-
-
-
- 已激活站点
-
-
-
- 未激活站点
-
-
-
- 转换引擎分布-
- $count
- ): ?>
- 0): ?>
-
- :
-
-
-
-
-
-
- 语言模块使用情况-
- "简体中文",
- "zh-tw" => "台湾正体",
- "zh-hk" => "港澳繁体",
- "zh-hans" => "简体中文(国际)",
- "zh-hant" => "繁体中文(国际)",
- "zh-sg" => "马新简体",
- "zh-jp" => "日式汉字",
- ];
- foreach (
- $language_stats
- as $lang => $count
- ):
- $lang_name = isset(
- $lang_names[$lang],
- )
- ? $lang_names[$lang]
- : $lang; ?>
-
- :
-
-
-
-
- |
-
|---|
| - - ">↗ - | -
-
-
-
- - - |
-
|---|
| - - ">↗ - | -
- [
- "name" => "WP Super Cache",
- "check" =>
- function_exists(
- "wp_cache_is_enabled",
- ) ||
- function_exists(
- "wp_super_cache_init",
- ),
- ],
- "wp_rocket" => [
- "name" => "WP Rocket",
- "check" => function_exists(
- "rocket_clean_domain",
- ),
- ],
- "litespeed_cache" => [
- "name" => "LiteSpeed Cache",
- "check" => class_exists(
- "LiteSpeed\Core",
- ),
- ],
- "w3_total_cache" => [
- "name" => "W3 Total Cache",
- "check" => function_exists(
- "w3tc_flush_all",
- ),
- ],
- "wp_fastest_cache" => [
- "name" => "WP Fastest Cache",
- "check" => class_exists(
- "WpFastestCache",
- ),
- ],
- "autoptimize" => [
- "name" => "Autoptimize",
- "check" =>
- class_exists("autoptimizeMain") ||
- function_exists(
- "autoptimize_autoload",
- ),
- ],
- "jetpack_boost" => [
- "name" => "Jetpack Boost",
- "check" =>
- defined("JETPACK_BOOST_VERSION") ||
- class_exists(
- "Automattic\Jetpack_Boost\Jetpack_Boost",
- ),
- ],
- ];
-
- $active_cache_plugins = [];
- foreach ($cache_plugins as $key => $plugin) {
- if ($plugin["check"]) {
- $active_cache_plugins[$key] =
- $plugin["name"];
- }
- }
-
- if (!empty($active_cache_plugins)) {
- echo ' ';
- echo ' ";
-
- // 检查缓存兼容设置
- $cache_controlled = in_array(
- "wpcc_enable_cache_addon",
- get_site_option(
- "wpcc_network_controlled_options",
- [],
- ),
- );
- if ($cache_controlled) {
- $cache_enabled = get_site_option(
- "wpcc_default_enable_cache_addon",
- 1,
- );
- if ($cache_enabled) {
- echo '检测到的缓存插件: ';
- echo '';
- foreach (
- $active_cache_plugins
- as $plugin_name
- ) {
- echo '' .
- esc_html($plugin_name) .
- "";
- }
- echo " ";
- echo "';
- echo '网络级缓存兼容已启用 ";
- } else {
- echo ''; - echo '所有子站点将自动使用缓存兼容功能'; - echo " ';
- echo '网络级缓存兼容已禁用 ";
- }
- } else {
- echo ''; - echo '子站点的缓存兼容功能将不可用'; - echo " ';
- echo '缓存兼容选项未被网络控制 ";
- }
- } else {
- echo ''; - echo '各子站点可自行配置缓存兼容功能'; - echo " ';
- echo "未检测到活跃的缓存插件";
- echo " ";
- }
- ?>
- |
-
|---|
| - - ">↗ - | -
-
-
-
-
- 危险操作警告
-
- 此操作将重置网络中所有站点的 WP Chinese Converter 设置为默认值。
- - 此操作不可逆,请谨慎使用! - |
-
|---|
没有找到站点。
"; - return; - } - - echo '| 站点 | 转换引擎 | 启用语言 | 状态 |
|---|---|---|---|
| ' . - esc_html(get_bloginfo("name")) . - " | "; - echo "" . esc_html($engine) . " | "; - echo "" . esc_html(implode(", ", $languages)) . " | "; - echo "" . ($active ? "✅ 激活" : "❌ 未激活") . " | "; - echo "
WP Chinese Converter: 检测到语言重写规则可能未正确配置,这可能导致语言主页404错误。 '; - echo '刷新重写规则
'; - echo '' . - esc_html($label) . - " 由网络管理员控制
"; - } else { - $notice .= - '以下 ' . - count($controlled_options) . - " 项设置由网络管理员控制:
"; - foreach ($controlled_options as $option) { - $label = $option_labels[$option] ?? $option; - $notice .= - '' . - esc_html($label) . - "
"; - } - } - - $notice .= - '以上选项由网络管理员控制,您的更改将不会生效。
'; - $notice .= "