2026-08-14 平台渠道专项更新:前端和静态SEO只展示平台官网、官方入驻及非中文入驻页辅助翻译;移除类目入口翻译、消费者官网翻译和内部成熟度/新兴参考分文案。 同步59/59权威源、65场跨境活动、28个平台和208条趋势内容;修正IBTE、CCBEC、法国教育部、Shopee和Shopify语种判断,更新README与CHANGELOG并通过Python、Node及静态构建验证。
146 lines
6.6 KiB
Python
146 lines
6.6 KiB
Python
#!/usr/bin/env python3
|
|
"""识别官网语种,并生成简体中文网页翻译链接。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
from typing import Any
|
|
from urllib.parse import quote, urlparse
|
|
|
|
|
|
TRADITIONAL_MARKERS = "體臺灣與為這個開會網頁讀覽資訊國際廣東學術裝趨關寧設計藝應將來產品時們業務發後點選專報導現場還裡讓從對實現線數據萬價銷購貿環驗證標準"
|
|
SIMPLIFIED_MARKERS = "体台湾与为这个开会网页读览资讯国际广东学术装趋关宁设计艺应将来产品时们业务发后点选专报道现场还里让从对实现线数据万价销购贸环验证标准"
|
|
GOOGLE_TRANSLATE_BLOCKED_HOSTS = {
|
|
"abai.kgd.gov.kz",
|
|
"cpsc.gov",
|
|
"www.cpsc.gov",
|
|
"www.zatca.gov.sa",
|
|
"zatca.gov.sa",
|
|
}
|
|
YANDEX_TRANSLATE_BLOCKED_HOSTS = {"abai.kgd.gov.kz"}
|
|
|
|
|
|
def google_translation_url(url: str) -> str:
|
|
"""Google 网页翻译可显式指定简体中文,作为主要阅读入口。"""
|
|
return f"https://translate.google.com/translate?sl=auto&tl=zh-CN&u={quote(url, safe='')}"
|
|
|
|
|
|
def yandex_translation_url(url: str, source_language: str = "en") -> str:
|
|
"""使用稳定入口,让 Yandex 自行生成带时效令牌的 TurboPages 译文地址。"""
|
|
source = (source_language or "en").lower().split("-")[0]
|
|
return f"https://translate.yandex.com/translate?url={quote(url, safe='')}&lang={source}-zh"
|
|
|
|
|
|
def detect_text_language(text: str = "", declared_language: str = "") -> str:
|
|
"""用页面声明优先、字符特征兜底,返回前端可直接判断的语种代码。"""
|
|
declared = (declared_language or "").strip().lower().replace("_", "-")
|
|
if declared:
|
|
if declared.startswith(("zh-cn", "zh-sg", "zh-hans")):
|
|
return "zh-CN"
|
|
if declared.startswith(("zh-tw", "zh-hk", "zh-mo", "zh-hant")):
|
|
return "zh-Hant"
|
|
return declared.split("-")[0]
|
|
|
|
value = text or ""
|
|
han_count = len(re.findall(r"[\u3400-\u9fff]", value))
|
|
latin_count = len(re.findall(r"[A-Za-z]", value))
|
|
if han_count >= 8 and han_count >= latin_count * 0.2:
|
|
traditional_count = sum(value.count(char) for char in TRADITIONAL_MARKERS)
|
|
simplified_count = sum(value.count(char) for char in SIMPLIFIED_MARKERS)
|
|
return "zh-Hant" if traditional_count >= 2 and traditional_count > simplified_count else "zh-CN"
|
|
return "en"
|
|
|
|
|
|
def url_language_hint(url: str) -> str:
|
|
value = (url or "").lower()
|
|
if re.search(r"(?:[?&](?:lang|language|localetype)=|/)(?:zh-cn|zh-hans|zh|cn)(?:\.html?)?(?:[&#/?]|$)", value):
|
|
return "zh-CN"
|
|
if re.search(r"(?:[?&](?:lang|language|localetype)=|/)(?:zh-tw|zh-hant|tw|hk)(?:\.html?)?(?:[&#/?]|$)", value):
|
|
return "zh-Hant"
|
|
host = (urlparse(url).hostname or "").lower().rstrip(".")
|
|
host_languages = {
|
|
"bizevent.ccpit.org": "zh-CN",
|
|
"ccbec-shenzhen.com": "zh-CN",
|
|
"ibte.co.id": "en",
|
|
"www.ccbec-shenzhen.com": "zh-CN",
|
|
"www.coupang.com": "ko",
|
|
"www.mercadolibre.com": "es",
|
|
}
|
|
if host in host_languages:
|
|
return host_languages[host]
|
|
for suffix, language in (
|
|
((".co.jp", ".jp"), "ja"),
|
|
((".ru",), "ru"),
|
|
((".de",), "de"),
|
|
((".fr",), "fr"),
|
|
((".pl",), "pl"),
|
|
((".kr",), "ko"),
|
|
((".it",), "it"),
|
|
((".es",), "es"),
|
|
((".com.mx",), "es"),
|
|
((".nl",), "nl"),
|
|
((".com.tr", ".tr"), "tr"),
|
|
):
|
|
if host.endswith(suffix):
|
|
return language
|
|
return ""
|
|
|
|
|
|
def is_simplified_chinese_site(url: str, source_language: str = "", source_text: str = "") -> bool:
|
|
"""简体中文内容和 .cn 域名不生成翻译入口。"""
|
|
host = (urlparse(url).hostname or "").lower().rstrip(".")
|
|
if host.endswith(".cn"):
|
|
return True
|
|
url_language = url_language_hint(url)
|
|
if url_language:
|
|
return url_language == "zh-CN"
|
|
declared = detect_text_language("", source_language) if source_language else ""
|
|
content_language = detect_text_language(source_text) if source_text.strip() else ""
|
|
return declared == "zh-CN" or content_language == "zh-CN"
|
|
|
|
|
|
def needs_simplified_chinese_translation(language: str) -> bool:
|
|
return (language or "").lower() not in ("zh-cn", "zh-hans", "zh-sg")
|
|
|
|
|
|
def google_translation_supported(url: str) -> bool:
|
|
"""记录已验证会拒绝 Google 网页代理的站点,避免发布无效按钮。"""
|
|
host = (urlparse(url).hostname or "").lower().rstrip(".")
|
|
return host not in GOOGLE_TRANSLATE_BLOCKED_HOSTS
|
|
|
|
|
|
def yandex_translation_supported(url: str) -> bool:
|
|
"""记录已验证会返回 Yandex 翻译错误页的站点。"""
|
|
host = (urlparse(url).hostname or "").lower().rstrip(".")
|
|
return host not in YANDEX_TRANSLATE_BLOCKED_HOSTS
|
|
|
|
|
|
def translation_fields(url: str, source_language: str = "", source_text: str = "") -> dict[str, Any]:
|
|
"""只为非简体中文页面输出翻译入口,避免中文官网出现无意义按钮。"""
|
|
if not url.startswith("https://"):
|
|
return {}
|
|
language = url_language_hint(url) or detect_text_language(source_text, source_language)
|
|
if is_simplified_chinese_site(url, source_language, source_text):
|
|
language = "zh-CN"
|
|
needs_translation = needs_simplified_chinese_translation(language)
|
|
google_supported = google_translation_supported(url)
|
|
yandex_supported = yandex_translation_supported(url)
|
|
return {
|
|
"source_language": language,
|
|
"needs_translation": needs_translation,
|
|
"google_translation_supported": google_supported,
|
|
"yandex_translation_supported": yandex_supported,
|
|
"translation_url": google_translation_url(url) if needs_translation and google_supported else "",
|
|
"translation_provider": "Google 简体中文网页翻译" if needs_translation and google_supported else "",
|
|
"translation_fallback_url": yandex_translation_url(url, language) if needs_translation and yandex_supported else "",
|
|
"translation_fallback_provider": "Yandex 网页翻译" if needs_translation and yandex_supported else "",
|
|
"translation_notice": (
|
|
("该官网已验证不支持 Google 与 Yandex 网页代理;请使用本站中文摘要并打开官方原文。"
|
|
if needs_translation and not google_supported and not yandex_supported else
|
|
"该官网已验证不支持 Google 网页代理;可尝试 Yandex 译文入口,或使用本站中文摘要并打开官方原文。"
|
|
if needs_translation and not google_supported else
|
|
"机器翻译仅用于中文辅助阅读;报名、付款或提交资料请返回官方原文页面。")
|
|
if needs_translation else "官网已识别为简体中文,无需机器翻译。"
|
|
),
|
|
}
|