fix bug
This commit is contained in:
@@ -35,7 +35,9 @@ Only the listed SEO meta fields are sent for translation. Arbitrary metadata, se
|
||||
|
||||
## Routing
|
||||
|
||||
The **Subdirectory** mode resolves configured language paths such as `/en/example-post/`. The **Domain binding** mode maps a request host to a language using one `domain=language` entry per line in Settings. Use one canonical strategy for each language to avoid duplicate URLs.
|
||||
The **Subdirectory** mode resolves configured language paths such as `/en/example-post/`. The **Domain binding** mode maps a request host to a language using one `domain=language` entry per line in Settings. Use one canonical strategy for each language to avoid duplicate URLs. In domain mode, the plugin does not register front-end rewrite rules, so the primary site URL is not affected.
|
||||
|
||||
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.
|
||||
|
||||
After changing routing settings, rewrite rules are refreshed. The initial implementation does not yet generate translated permalinks, canonical URLs, `hreflang` alternates, redirects, or sitemap entries.
|
||||
|
||||
|
||||
@@ -22,8 +22,10 @@ class WPT_Admin {
|
||||
|
||||
foreach ( preg_split( '/\r\n|\r|\n/', (string) ( $settings['domain_bindings'] ?? '' ) ) as $line ) {
|
||||
$parts = array_map( 'trim', explode( '=', $line, 2 ) );
|
||||
if ( 2 === count( $parts ) && '' !== $parts[0] && '' !== $parts[1] ) {
|
||||
$bindings[ sanitize_text_field( $parts[0] ) ] = sanitize_key( $parts[1] );
|
||||
$domain = 2 === count( $parts ) ? WPT_Settings::normalize_domain( $parts[0] ) : '';
|
||||
$language = 2 === count( $parts ) ? sanitize_key( $parts[1] ) : '';
|
||||
if ( '' !== $domain && '' !== $language ) {
|
||||
$bindings[ $domain ] = $language;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,16 +48,16 @@ class WPT_Admin {
|
||||
}
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?php esc_html_e( 'WP Translate', 'wp-translate' ); ?></h1>
|
||||
<h1>WP Translate</h1>
|
||||
<form action="options.php" method="post">
|
||||
<?php settings_fields( 'wpt_settings' ); ?>
|
||||
<table class="form-table" role="presentation">
|
||||
<tr><th scope="row"><label for="wpt-source-language"><?php esc_html_e( 'Source language', 'wp-translate' ); ?></label></th><td><input id="wpt-source-language" name="wpt_settings[source_language]" type="text" value="<?php echo esc_attr( $settings['source_language'] ); ?>" /></td></tr>
|
||||
<tr><th scope="row"><label for="wpt-target-languages"><?php esc_html_e( 'Target languages', 'wp-translate' ); ?></label></th><td><input id="wpt-target-languages" name="wpt_settings[target_languages]" type="text" value="<?php echo esc_attr( implode( ',', $settings['target_languages'] ) ); ?>" class="regular-text" /></td></tr>
|
||||
<tr><th scope="row"><label for="wpt-routing-mode"><?php esc_html_e( 'URL mode', 'wp-translate' ); ?></label></th><td><select id="wpt-routing-mode" name="wpt_settings[routing_mode]"><option value="subdirectory" <?php selected( $settings['routing_mode'], 'subdirectory' ); ?>><?php esc_html_e( 'Subdirectory', 'wp-translate' ); ?></option><option value="domain" <?php selected( $settings['routing_mode'], 'domain' ); ?>><?php esc_html_e( 'Domain binding', 'wp-translate' ); ?></option></select></td></tr>
|
||||
<tr><th scope="row"><label for="wpt-domain-bindings"><?php esc_html_e( 'Domain bindings', 'wp-translate' ); ?></label></th><td><textarea id="wpt-domain-bindings" name="wpt_settings[domain_bindings]" rows="4" class="large-text"><?php echo esc_textarea( implode( "\n", $bindings ) ); ?></textarea></td></tr>
|
||||
<tr><th scope="row"><label for="wpt-baidu-app-id"><?php esc_html_e( 'Baidu app ID', 'wp-translate' ); ?></label></th><td><input id="wpt-baidu-app-id" name="wpt_settings[baidu_app_id]" type="text" value="<?php echo esc_attr( $settings['baidu_app_id'] ); ?>" class="regular-text" /></td></tr>
|
||||
<tr><th scope="row"><label for="wpt-baidu-secret-key"><?php esc_html_e( 'Baidu secret key', 'wp-translate' ); ?></label></th><td><input id="wpt-baidu-secret-key" name="wpt_settings[baidu_secret_key]" type="password" value="<?php echo esc_attr( $settings['baidu_secret_key'] ); ?>" class="regular-text" autocomplete="new-password" /></td></tr>
|
||||
<tr><th scope="row"><label for="wpt-source-language">源语言</label></th><td><input id="wpt-source-language" name="wpt_settings[source_language]" type="text" value="<?php echo esc_attr( $settings['source_language'] ); ?>" /><p class="description">使用百度翻译语言代码,例如 <code>zh</code>。</p></td></tr>
|
||||
<tr><th scope="row"><label for="wpt-target-languages">目标语言</label></th><td><input id="wpt-target-languages" name="wpt_settings[target_languages]" type="text" value="<?php echo esc_attr( implode( ',', $settings['target_languages'] ) ); ?>" class="regular-text" /><p class="description">多个语言代码用英文逗号分隔,例如 <code>en,ja</code>。</p></td></tr>
|
||||
<tr><th scope="row"><label for="wpt-routing-mode">网址模式</label></th><td><select id="wpt-routing-mode" name="wpt_settings[routing_mode]"><option value="subdirectory" <?php selected( $settings['routing_mode'], 'subdirectory' ); ?>>子目录</option><option value="domain" <?php selected( $settings['routing_mode'], 'domain' ); ?>>绑定域名</option></select></td></tr>
|
||||
<tr><th scope="row"><label for="wpt-domain-bindings">域名绑定</label></th><td><textarea id="wpt-domain-bindings" name="wpt_settings[domain_bindings]" rows="4" class="large-text" placeholder="en.example.com=en"><?php echo esc_textarea( implode( "\n", $bindings ) ); ?></textarea><p class="description">每行一个 <code>域名=语言代码</code>,例如 <code>en.example.com=en</code>。请勿填写 <code>https://</code>、路径或端口。</p></td></tr>
|
||||
<tr><th scope="row"><label for="wpt-baidu-app-id">百度应用 ID</label></th><td><input id="wpt-baidu-app-id" name="wpt_settings[baidu_app_id]" type="text" value="<?php echo esc_attr( $settings['baidu_app_id'] ); ?>" class="regular-text" /></td></tr>
|
||||
<tr><th scope="row"><label for="wpt-baidu-secret-key">百度密钥</label></th><td><input id="wpt-baidu-secret-key" name="wpt_settings[baidu_secret_key]" type="password" value="<?php echo esc_attr( $settings['baidu_secret_key'] ); ?>" class="regular-text" autocomplete="new-password" /></td></tr>
|
||||
</table>
|
||||
<?php submit_button(); ?>
|
||||
</form>
|
||||
|
||||
@@ -4,10 +4,25 @@ defined( 'ABSPATH' ) || exit;
|
||||
|
||||
class WPT_Language_Router {
|
||||
public function register() {
|
||||
add_rewrite_tag( '%wpt_language%', '([a-zA-Z-]+)' );
|
||||
add_rewrite_rule( '^([a-zA-Z-]+)/(.*)?$', 'index.php?wpt_language=$matches[1]&pagename=$matches[2]', 'top' );
|
||||
add_filter( 'query_vars', array( $this, 'query_vars' ) );
|
||||
add_action( 'parse_request', array( $this, 'resolve_domain_language' ) );
|
||||
$this->register_rewrite_rules();
|
||||
}
|
||||
|
||||
public function register_rewrite_rules() {
|
||||
if ( 'subdirectory' !== WPT_Settings::get()['routing_mode'] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$language_pattern = implode( '|', array_map( 'preg_quote', array_map( 'strtolower', WPT_Settings::target_languages() ) ) );
|
||||
|
||||
if ( '' === $language_pattern ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_rewrite_tag( '%wpt_language%', '(' . $language_pattern . ')' );
|
||||
add_rewrite_rule( '^(' . $language_pattern . ')/(.*)$', 'index.php?wpt_language=$matches[1]&pagename=$matches[2]', 'top' );
|
||||
add_rewrite_rule( '^(' . $language_pattern . ')/?$', 'index.php?wpt_language=$matches[1]', 'top' );
|
||||
}
|
||||
|
||||
public function query_vars( $query_vars ) {
|
||||
@@ -18,10 +33,10 @@ class WPT_Language_Router {
|
||||
|
||||
public function resolve_domain_language( $wp ) {
|
||||
$settings = WPT_Settings::get();
|
||||
$host = isset( $_SERVER['HTTP_HOST'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : '';
|
||||
$host = isset( $_SERVER['HTTP_HOST'] ) ? WPT_Settings::normalize_domain( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : '';
|
||||
$bindings = (array) $settings['domain_bindings'];
|
||||
|
||||
if ( 'domain' === $settings['routing_mode'] && isset( $bindings[ $host ] ) && WPT_Settings::is_supported_language( $bindings[ $host ] ) ) {
|
||||
if ( 'domain' === $settings['routing_mode'] && '' !== $host && isset( $bindings[ $host ] ) && WPT_Settings::is_supported_language( $bindings[ $host ] ) ) {
|
||||
$wp->query_vars['wpt_language'] = sanitize_key( $bindings[ $host ] );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ class WPT_Plugin {
|
||||
'',
|
||||
false
|
||||
);
|
||||
$router = new WPT_Language_Router();
|
||||
$router->register_rewrite_rules();
|
||||
flush_rewrite_rules();
|
||||
}
|
||||
|
||||
@@ -55,6 +57,7 @@ class WPT_Plugin {
|
||||
|
||||
public function refresh_rewrite_rules( $old_value, $new_value ) {
|
||||
if ( (array) $old_value !== (array) $new_value ) {
|
||||
$this->router->register_rewrite_rules();
|
||||
flush_rewrite_rules();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,4 +27,13 @@ class WPT_Settings {
|
||||
|
||||
return in_array( sanitize_key( $language ), $languages, true );
|
||||
}
|
||||
|
||||
public static function normalize_domain( $domain ) {
|
||||
$domain = strtolower( trim( (string) $domain ) );
|
||||
$domain = preg_replace( '#^https?://#', '', $domain );
|
||||
$domain = explode( '/', $domain, 2 )[0];
|
||||
$domain = preg_replace( '/:\d+$/', '', $domain );
|
||||
|
||||
return preg_match( '/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/', $domain ) ? $domain : '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class SettingsTest extends TestCase {
|
||||
public function test_normalize_domain_accepts_a_subdomain_and_removes_protocol_port_and_path() {
|
||||
$this->assertSame( 'en.example.com', WPT_Settings::normalize_domain( 'https://EN.Example.com:8443/news' ) );
|
||||
}
|
||||
|
||||
public function test_normalize_domain_rejects_a_domain_without_a_public_suffix() {
|
||||
$this->assertSame( '', WPT_Settings::normalize_domain( 'invalid-domain' ) );
|
||||
}
|
||||
}
|
||||
@@ -7,3 +7,4 @@ require_once dirname( __DIR__ ) . '/includes/class-wpt-translation-result.php';
|
||||
require_once dirname( __DIR__ ) . '/includes/class-wpt-translation-identity.php';
|
||||
require_once dirname( __DIR__ ) . '/includes/class-wpt-translation-store.php';
|
||||
require_once dirname( __DIR__ ) . '/includes/class-wpt-translation-service.php';
|
||||
require_once dirname( __DIR__ ) . '/includes/class-wpt-settings.php';
|
||||
Reference in New Issue
Block a user