fix sitemap 2

This commit is contained in:
hanyixuanten
2026-07-27 18:19:50 +08:00
parent 206bd8d5f7
commit 20090bdf2c
3 changed files with 45 additions and 26 deletions
+1 -1
View File
@@ -49,7 +49,7 @@ Post, page, term, and home links are generated for the active language. For exam
For a bound subdomain, enter a value such as `en.example.com=en`. The server and DNS must route that hostname to the same WordPress installation before WordPress can resolve the language.
Sitemap requests made through a configured target-language subdirectory or bound domain are proxied to the same sitemap path on the source site. The plugin rewrites standard `<loc>` entries in both sitemap indexes and URL sets to the active language URL, so sitemap index links continue through the same language route. Source sitemap failures remain non-fatal and fall back to normal WordPress request handling. The source sitemap must be available from the WordPress `home` origin; upstream redirects are not followed.
The plugin handles only the target language's `sitemap.xml` request: `/{language}/sitemap.xml` in subdirectory mode and `/sitemap.xml` on a bound domain. It always fetches `/sitemap.xml` from the source site's origin and rewrites complete source-site URLs in XML text nodes and attributes to the current language URL. Other sitemap filenames and external URLs remain unchanged. Source sitemap failures remain non-fatal and fall back to normal WordPress request handling. The source sitemap must be available from the WordPress `home` origin; upstream redirects are not followed.
After changing routing settings, rewrite rules are refreshed. The initial implementation does not yet generate translated permalinks, canonical URLs, `hreflang` alternates, or redirects.
+1 -1
View File
@@ -48,7 +48,7 @@ Btranslate 是一个 WordPress 插件骨架,使用百度翻译 API 持久化
对于已绑定的子域名,请填写类似 `en.example.com=en` 的值。服务器和 DNS 必须先将该主机名指向同一 WordPress 安装,WordPress 才能解析该语言。
通过已配置目标语言子目录或绑定域名发起的 sitemap 请求,会代理到源站相同路径的 sitemap。插件会改写 sitemap 索引和 URL 集中的标准 `<loc>` 条目,使索引内的子 sitemap 链接继续使用同一语言路由。源站 sitemap 获取失败时不会造成致命错误,而是交回 WordPress 按普通请求处理。源 sitemap 必须可从 WordPress `home` 配置的源站访问,且插件不会跟随上游重定向。
插件只处理目标语言的 `sitemap.xml` 请求:子目录模式为 `/{语言}/sitemap.xml`,域名绑定模式为绑定域名上的 `/sitemap.xml`。它始终获取源站根路径的 `/sitemap.xml`,并将 XML 文本节点和属性中指向源站的完整 URL 改写为当前语言 URL;其他 sitemap 文件及外部 URL 不会被改写。源站 sitemap 获取失败时不会造成致命错误,而是交回 WordPress 按普通请求处理。源 sitemap 必须可从 WordPress `home` 配置的源站访问,且插件不会跟随上游重定向。
路由设置变更后会刷新重写规则。初始实现尚不生成翻译固定链接、规范 URL、`hreflang` 替代链接或重定向。
@@ -21,12 +21,11 @@ class BTRANSLATE_Sitemap_Controller {
return;
}
$request_path = $this->request_path();
if ( ! $this->is_sitemap_path( $request_path ) ) {
if ( ! $this->is_sitemap_request( $this->request_path(), $language, $settings['routing_mode'] ) ) {
return;
}
$source_url = $this->source_sitemap_url( $request_path, $language, $settings['routing_mode'] );
$source_url = $this->source_sitemap_url();
if ( '' === $source_url ) {
return;
}
@@ -46,7 +45,7 @@ class BTRANSLATE_Sitemap_Controller {
return;
}
$xml = $this->rewrite_sitemap( wp_remote_retrieve_body( $response ) );
$xml = $this->rewrite_sitemap( wp_remote_retrieve_body( $response ), $source_url );
if ( '' === $xml ) {
return;
}
@@ -65,13 +64,13 @@ class BTRANSLATE_Sitemap_Controller {
return is_string( $path ) ? '/' . ltrim( $path, '/' ) : '';
}
private function is_sitemap_path( $path ) {
$filename = basename( $path );
private function is_sitemap_request( $path, $language, $routing_mode ) {
$expected_path = 'subdirectory' === $routing_mode ? '/' . $language . '/sitemap.xml' : '/sitemap.xml';
return 1 === preg_match( '/^[a-z0-9_-]*sitemap[a-z0-9_.-]*\.xml$/i', $filename );
return $expected_path === untrailingslashit( $path );
}
private function source_sitemap_url( $request_path, $language, $routing_mode ) {
private function source_sitemap_url() {
$home_url = (string) get_option( 'home', '' );
$parts = wp_parse_url( $home_url );
@@ -79,17 +78,12 @@ class BTRANSLATE_Sitemap_Controller {
return '';
}
if ( 'subdirectory' === $routing_mode ) {
$request_path = preg_replace( '#^/' . preg_quote( $language, '#' ) . '(?=/|$)#i', '', $request_path, 1 );
$request_path = '/' . ltrim( (string) $request_path, '/' );
}
$port = isset( $parts['port'] ) ? ':' . $parts['port'] : '';
return $parts['scheme'] . '://' . $parts['host'] . $port . $request_path;
return $parts['scheme'] . '://' . $parts['host'] . $port . '/sitemap.xml';
}
private function rewrite_sitemap( $xml ) {
private function rewrite_sitemap( $xml, $source_url ) {
if ( '' === trim( $xml ) || ! class_exists( 'DOMDocument' ) ) {
return '';
}
@@ -105,25 +99,50 @@ class BTRANSLATE_Sitemap_Controller {
return '';
}
foreach ( $document->childNodes as $child_node ) {
if ( XML_PI_NODE === $child_node->nodeType && 'xml-stylesheet' === $child_node->nodeName ) {
$document->removeChild( $child_node );
}
}
$xpath = new DOMXPath( $document );
$nodes = $xpath->query( '/*[local-name()="urlset" or local-name()="sitemapindex"]/*[local-name()="url" or local-name()="sitemap"]/*[local-name()="loc"]' );
$nodes = $xpath->query( '//text() | //@*' );
if ( false === $nodes ) {
return '';
}
foreach ( $nodes as $node ) {
$node->nodeValue = $this->router->localized_url( trim( $node->textContent ) );
$value = trim( $node->nodeValue );
$rewritten = $this->rewrite_source_url( $value, $source_url );
if ( $rewritten !== $value ) {
$node->nodeValue = str_replace( $value, $rewritten, $node->nodeValue );
}
}
$result = $document->saveXML();
return false === $result ? '' : $result;
}
private function rewrite_source_url( $url, $source_url ) {
$url_parts = wp_parse_url( $url );
$source_parts = wp_parse_url( $source_url );
if (
! is_array( $url_parts ) ||
! is_array( $source_parts ) ||
empty( $url_parts['scheme'] ) ||
empty( $url_parts['host'] ) ||
0 !== strcasecmp( $url_parts['host'], $source_parts['host'] ) ||
$this->url_port( $url_parts ) !== $this->url_port( $source_parts )
) {
return $url;
}
return $this->router->localized_url( $url );
}
private function url_port( $parts ) {
if ( isset( $parts['port'] ) ) {
return (int) $parts['port'];
}
return isset( $parts['scheme'] ) && 'http' === strtolower( $parts['scheme'] ) ? 80 : 443;
}
}