simplifize the dir

This commit is contained in:
hanyixuanten
2026-07-26 23:52:09 +08:00
parent 2ef024e756
commit 076aea0c9f
13 changed files with 5 additions and 2014 deletions
-3
View File
@@ -1,10 +1,7 @@
/vendor/
/node_modules/
/.phpunit.result.cache
/coverage/
/build/
/dist/
/phpunit.xml
/.intelephense/
.env
.env.*
+1 -1
View File
@@ -45,5 +45,5 @@ Unless a user explicitly requests a refresh, each translatable value must be tra
- Mock Baidu API calls in every test. Tests must not require live credentials or outbound network access.
- Keep changes narrow and avoid unrelated refactors or formatting churn.
- Plugin slug and PHP prefix: `wp-translate` and `wpt_`/`WPT_`. The current minimum supported PHP version is 8.1 and the current minimum WordPress version is 6.4.
- Composer manages the development dependencies. Run `composer test` for isolated unit tests and `composer lint` for PHP syntax checks. WordPress API calls must be mocked in tests; tests must not require live credentials, external network access, or a WordPress database.
- The repository has no Composer-managed development dependencies or bundled automated test suite. Validate PHP syntax with `find . -path './.git' -prune -o -type f -name '*.php' -print0 | xargs -0 -n1 php -l`. Any future automated tests must mock WordPress API calls and must not require live credentials, external network access, or a WordPress database.
- Document supported languages, routing modes, data retention, translation lifecycle, and known limitations in the README whenever the implementation changes.
+2 -10
View File
@@ -63,21 +63,13 @@ Uninstalling Btranslate permanently deletes its settings and credentials, retran
## Development
Install development dependencies with `composer install`. The project includes WordPress API stubs for Intelephense and PHPUnit tests that use fake providers and storage, so they do not need WordPress, a database, credentials, or network access.
Run tests with:
```sh
composer test
```
Validate PHP syntax with:
The repository has no Composer or PHPUnit dependency. Validate PHP syntax with the PHP executable available on your system:
```sh
find . -path './.git' -prune -o -type f -name '*.php' -print0 | xargs -0 -n1 php -l
```
Before production use, add WordPress PHPUnit integration tests with mocked `wp_remote_post` responses. Required coverage includes language resolution, rewrite behavior, persistence reuse and invalidation, Baidu request signing and errors, content filtering, and fallback rendering.
Before production use, test the plugin in a WordPress staging environment. Cover language resolution, rewrite behavior, persistence reuse and invalidation, Baidu request signing and errors, content filtering, and fallback rendering. Mock `wp_remote_post` responses for any automated tests so they do not need live credentials, a database, or outbound network access.
## Retranslation
+2 -10
View File
@@ -62,21 +62,13 @@ Btranslate 是一个 WordPress 插件骨架,使用百度翻译 API 持久化
## 开发
使用 `composer install` 安装开发依赖。项目包含用于 Intelephense 的 WordPress API 存根,以及使用伪造提供程序和存储的 PHPUnit 测试;因此测试不需要 WordPress、数据库、凭据或网络访问。
运行测试:
```sh
composer test
```
验证 PHP 语法:
仓库不依赖 Composer 或 PHPUnit。使用系统中可用的 PHP 可执行文件验证 PHP 语法:
```sh
find . -path './.git' -prune -o -type f -name '*.php' -print0 | xargs -0 -n1 php -l
```
投入生产前,应添加 WordPress PHPUnit 集成测试,并模拟 `wp_remote_post` 响应。所需覆盖范围包括语言解析、重写行为、持久化复用与失效、百度请求签名和错误处理、内容过滤和回退渲染
投入生产前,应 WordPress 预发布环境中测试插件,覆盖语言解析、重写行为、持久化复用与失效、百度请求签名和错误处理、内容过滤和回退渲染。任何自动化测试都应模拟 `wp_remote_post` 响应,避免依赖真实凭据、数据库或外部网络访问
## 重新翻译
-17
View File
@@ -1,17 +0,0 @@
{
"name": "wp-btranslate/wp-btranslate",
"description": "Persistent multilingual WordPress translations powered by Baidu Translate.",
"type": "wordpress-plugin",
"license": "proprietary",
"require": {
"php": "^8.1"
},
"require-dev": {
"php-stubs/wordpress-stubs": "^6.8",
"phpunit/phpunit": "^12"
},
"scripts": {
"lint": "find . -path './.git' -prune -o -path './vendor' -prune -o -type f -name '*.php' -print0 | xargs -0 -n1 php -l",
"test": "phpunit"
}
}
Generated
-1754
View File
File diff suppressed because it is too large Load Diff
-8
View File
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php" colors="true">
<testsuites>
<testsuite name="WP Translate">
<directory suffix="Test.php">tests</directory>
</testsuite>
</testsuites>
</phpunit>
-30
View File
@@ -1,30 +0,0 @@
<?php
use PHPUnit\Framework\TestCase;
class ContentTranslatorTest extends TestCase {
public function test_translates_link_text_separately_and_preserves_link_attributes() {
$store = new WPT_Test_Translation_Store();
$provider = new WPT_Test_Translation_Provider();
$service = new WPT_Translation_Service( $store, $provider );
$translator = new WPT_Content_Translator( $service );
$result = $translator->translate( 'Read <a href="https://example.com/docs" target="_blank">our guide</a>.', 'en', 'zh', 'post:1:post_content' );
$this->assertTrue( $result->success );
$this->assertSame( 'Read <a href="https://example.com/docs" target="_blank">our guide</a>.', $result->value );
$this->assertSame( 3, $provider->calls );
$this->assertSame( 'post:1:post_content:text:0', $store->save_calls[0]['field_context'] );
$this->assertSame( 'post:1:post_content:text:1', $store->save_calls[1]['field_context'] );
$this->assertSame( 'post:1:post_content:text:2', $store->save_calls[2]['field_context'] );
}
public function test_splits_text_while_preserving_links_images_and_other_tags() {
$segments = WPT_Content_Translator::segments( 'See <a href="/docs">docs</a><img src="/hero.jpg" alt="Hero"><strong>now</strong>.' );
$this->assertSame(
array( 'See ', '<a href="/docs">', 'docs', '</a>', '<img src="/hero.jpg" alt="Hero">', '<strong>', 'now', '</strong>', '.' ),
$segments
);
}
}
-35
View File
@@ -1,35 +0,0 @@
<?php
use PHPUnit\Framework\TestCase;
class WPT_Test_Language_Router extends WPT_Language_Router {
public function current_language() {
return 'en';
}
}
class DocumentTitleTest extends TestCase {
public function test_document_title_callback_leaves_non_singular_title_parts_unchanged() {
$controller = new WPT_Content_Controller( new WPT_Test_Translation_Store(), new WPT_Test_Language_Router() );
$parts = array( 'title' => '中文主页', 'site' => '示例站点' );
$this->assertSame( $parts, $controller->translate_document_title_parts( $parts ) );
}
public function test_wordpress_ai_meta_description_metadata_uses_persisted_translation() {
$store = new WPT_Test_Translation_Store();
$description = 'Original description';
$identity_key = WPT_Translation_Identity::key( $description, 'zh', 'en', 'post:42:meta:wpai_meta_description', 'baidu-vip-v1' );
$store->values[ $identity_key ] = array( 'translated_value' => 'Translated description' );
$controller = new WPT_Content_Controller( $store, new WPT_Test_Language_Router() );
global $wpt_test_post_meta;
$wpt_test_post_meta[42]['wpai_meta_description'] = $description;
$this->assertSame(
'Translated description',
$controller->translate_wordpress_ai_meta_description_metadata( null, 42, 'wpai_meta_description', true )
);
$this->assertNull( $controller->translate_wordpress_ai_meta_description_metadata( null, 42, 'wpai_meta_description', false ) );
$this->assertSame( $description, $controller->translate_wordpress_ai_meta_description_metadata( $description, 42, '_unrelated_meta', true ) );
}
}
-13
View File
@@ -1,13 +0,0 @@
<?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' ) );
}
}
-19
View File
@@ -1,19 +0,0 @@
<?php
use PHPUnit\Framework\TestCase;
class TranslationIdentityTest extends TestCase {
public function test_key_is_stable_for_identical_translation_input() {
$first = WPT_Translation_Identity::key( 'Hello', 'en', 'zh', 'post:15:post_title', 'provider-v1' );
$second = WPT_Translation_Identity::key( 'Hello', 'en', 'zh', 'post:15:post_title', 'provider-v1' );
$this->assertSame( $first, $second );
}
public function test_key_changes_when_source_value_changes() {
$first = WPT_Translation_Identity::key( 'Hello', 'en', 'zh', 'post:15:post_title', 'provider-v1' );
$second = WPT_Translation_Identity::key( 'Hello again', 'en', 'zh', 'post:15:post_title', 'provider-v1' );
$this->assertNotSame( $first, $second );
}
}
-80
View File
@@ -1,80 +0,0 @@
<?php
use PHPUnit\Framework\TestCase;
class WPT_Test_Translation_Store extends WPT_Translation_Store {
public $values = array();
public $save_calls = array();
public function find_valid( $identity_key ) {
return $this->values[ $identity_key ] ?? null;
}
public function save( $identity_key, $source_language, $target_language, $field_context, $source_fingerprint, $translated_value, $status ) {
$this->save_calls[] = compact( 'identity_key', 'source_language', 'target_language', 'field_context', 'source_fingerprint', 'translated_value', 'status' );
if ( 'complete' === $status ) {
$this->values[ $identity_key ] = array( 'translated_value' => $translated_value );
}
}
}
class WPT_Test_Translation_Provider implements WPT_Translation_Provider {
public $calls = 0;
public function get_version() {
return 'test-provider-v1';
}
public function translate( $source_value, $source_language, $target_language, $context ) {
++$this->calls;
return WPT_Translation_Result::success( '[' . $target_language . '] ' . $source_value );
}
}
class TranslationServiceTest extends TestCase {
public function test_second_request_reuses_persisted_translation_without_provider_call() {
$store = new WPT_Test_Translation_Store();
$provider = new WPT_Test_Translation_Provider();
$service = new WPT_Translation_Service( $store, $provider );
$first = $service->get_or_translate( 'Welcome', 'en', 'zh', 'post:8:post_title' );
$second = $service->get_or_translate( 'Welcome', 'en', 'zh', 'post:8:post_title' );
$this->assertTrue( $first->success );
$this->assertSame( '[zh] Welcome', $second->value );
$this->assertSame( 1, $provider->calls );
$this->assertCount( 1, $store->save_calls );
}
public function test_failed_request_is_persisted_with_failed_status() {
$store = new WPT_Test_Translation_Store();
$provider = new class implements WPT_Translation_Provider {
public function get_version() {
return 'test-provider-v1';
}
public function translate( $source_value, $source_language, $target_language, $context ) {
return WPT_Translation_Result::failure( 'request_failed', 'Network error' );
}
};
$service = new WPT_Translation_Service( $store, $provider );
$result = $service->get_or_translate( 'Welcome', 'en', 'zh', 'post:8:post_title' );
$this->assertFalse( $result->success );
$this->assertSame( 'failed', $store->save_calls[0]['status'] );
}
public function test_forced_refresh_calls_the_provider_when_a_translation_is_already_persisted() {
$store = new WPT_Test_Translation_Store();
$provider = new WPT_Test_Translation_Provider();
$service = new WPT_Translation_Service( $store, $provider );
$service->get_or_translate( 'Welcome', 'en', 'zh', 'post:8:post_title' );
$service->get_or_translate( 'Welcome', 'en', 'zh', 'post:8:post_title', true );
$this->assertSame( 2, $provider->calls );
$this->assertCount( 2, $store->save_calls );
}
}
-34
View File
@@ -1,34 +0,0 @@
<?php
define( 'ABSPATH', __DIR__ . '/' );
function is_singular() {
return false;
}
function get_option( $option, $default = false ) {
return $default;
}
function wp_parse_args( $args, $defaults = array() ) {
return array_merge( $defaults, $args );
}
function get_metadata_raw( $meta_type, $object_id, $meta_key = '', $single = false ) {
global $wpt_test_post_meta;
$value = $wpt_test_post_meta[ $object_id ][ $meta_key ] ?? null;
return $single ? $value : array( $value );
}
require_once dirname( __DIR__ ) . '/includes/interface-wpt-translation-provider.php';
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-baidu-provider.php';
require_once dirname( __DIR__ ) . '/includes/class-wpt-content-translator.php';
require_once dirname( __DIR__ ) . '/includes/class-wpt-settings.php';
require_once dirname( __DIR__ ) . '/includes/class-wpt-language-router.php';
require_once dirname( __DIR__ ) . '/includes/class-wpt-content-controller.php';