mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-09-18 10:04:55 +08:00
fix(tm):建立 Trusted 唯一性与 Supersede 治理
This commit is contained in:
@@ -479,9 +479,10 @@ const (
|
||||
type TranslationMemoryMatchKind string
|
||||
|
||||
const (
|
||||
TranslationMemoryMatchStrongExact TranslationMemoryMatchKind = "strong_exact"
|
||||
TranslationMemoryMatchCandidateExact TranslationMemoryMatchKind = "candidate_exact"
|
||||
TranslationMemoryMatchSourceOnly TranslationMemoryMatchKind = "source_only"
|
||||
TranslationMemoryMatchStrongExact TranslationMemoryMatchKind = "strong_exact"
|
||||
TranslationMemoryMatchTrustedConflict TranslationMemoryMatchKind = "trusted_conflict"
|
||||
TranslationMemoryMatchCandidateExact TranslationMemoryMatchKind = "candidate_exact"
|
||||
TranslationMemoryMatchSourceOnly TranslationMemoryMatchKind = "source_only"
|
||||
)
|
||||
|
||||
// TranslationMemorySummaryParams selects an optional Rust-owned TM database.
|
||||
@@ -504,16 +505,19 @@ type TranslationMemoryConfirmParams struct {
|
||||
RecordID string `json:"record_id"`
|
||||
Reviewer string `json:"reviewer"`
|
||||
Reason string `json:"reason,omitempty"`
|
||||
SupersedeRecordID string `json:"supersede_record_id,omitempty"`
|
||||
}
|
||||
|
||||
// TranslationMemorySummary mirrors translation.memory.summary data.
|
||||
type TranslationMemorySummary struct {
|
||||
SchemaVersion uint64 `json:"schema_version"`
|
||||
RecordCount uint64 `json:"record_count"`
|
||||
TrustedCount uint64 `json:"trusted_count"`
|
||||
CandidateCount uint64 `json:"candidate_count"`
|
||||
SupersededCount uint64 `json:"superseded_count"`
|
||||
RejectedCount uint64 `json:"rejected_count"`
|
||||
SchemaVersion uint64 `json:"schema_version"`
|
||||
RecordCount uint64 `json:"record_count"`
|
||||
TrustedCount uint64 `json:"trusted_count"`
|
||||
CandidateCount uint64 `json:"candidate_count"`
|
||||
SupersededCount uint64 `json:"superseded_count"`
|
||||
RejectedCount uint64 `json:"rejected_count"`
|
||||
TrustedConflictGroupCount uint64 `json:"trusted_conflict_group_count"`
|
||||
CurrentTrustedCount uint64 `json:"current_trusted_count,omitempty"`
|
||||
}
|
||||
|
||||
// TranslationMemorySummaryReport distinguishes a missing database from an
|
||||
@@ -591,6 +595,47 @@ type TranslationMemoryConfirmReport struct {
|
||||
Entry TranslationMemoryEntry `json:"entry"`
|
||||
}
|
||||
|
||||
// TranslationMemoryConflict groups all records sharing one exact source
|
||||
// identity when more than one current Trusted record exists.
|
||||
type TranslationMemoryConflict struct {
|
||||
SourceText string `json:"source_text"`
|
||||
SourceHash string `json:"source_hash"`
|
||||
SourceContext TranslationMemoryContext `json:"source_context,omitempty"`
|
||||
SourceContextHash string `json:"source_context_hash"`
|
||||
TrustedRecordIDs []string `json:"trusted_record_ids"`
|
||||
Records []TranslationMemoryEntry `json:"records"`
|
||||
}
|
||||
|
||||
// TranslationMemoryConflictsParams lists current Trusted conflicts.
|
||||
type TranslationMemoryConflictsParams struct {
|
||||
TranslationMemoryPath string `json:"translation_memory_path,omitempty"`
|
||||
Limit *uint64 `json:"limit,omitempty"`
|
||||
}
|
||||
|
||||
// TranslationMemoryConflictsReport mirrors translation.memory.conflicts data.
|
||||
type TranslationMemoryConflictsReport struct {
|
||||
Available bool `json:"available"`
|
||||
Path string `json:"path"`
|
||||
Conflicts []TranslationMemoryConflict `json:"conflicts"`
|
||||
Reason string `json:"reason,omitempty"`
|
||||
}
|
||||
|
||||
// TranslationMemoryResolveConflictParams resolves one exact-identity conflict.
|
||||
type TranslationMemoryResolveConflictParams struct {
|
||||
TranslationMemoryPath string `json:"translation_memory_path,omitempty"`
|
||||
WinnerRecordID string `json:"winner_record_id"`
|
||||
ExpectedTrustedRecordIDs []string `json:"expected_trusted_record_ids"`
|
||||
Reviewer string `json:"reviewer"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
|
||||
// TranslationMemoryResolveConflictReport mirrors the conflict resolution result.
|
||||
type TranslationMemoryResolveConflictReport struct {
|
||||
Available bool `json:"available"`
|
||||
Path string `json:"path"`
|
||||
Entry TranslationMemoryEntry `json:"entry"`
|
||||
}
|
||||
|
||||
// GlossaryReviewStatus is the Rust-owned term review state.
|
||||
type GlossaryReviewStatus string
|
||||
|
||||
@@ -1067,6 +1112,18 @@ func (c *Client) TranslationMemoryConfirm(ctx context.Context, params Translatio
|
||||
return &out, err
|
||||
}
|
||||
|
||||
func (c *Client) TranslationMemoryConflicts(ctx context.Context, params TranslationMemoryConflictsParams) (*TranslationMemoryConflictsReport, error) {
|
||||
var out TranslationMemoryConflictsReport
|
||||
_, err := c.Call(ctx, "translation.memory.conflicts", params, &out)
|
||||
return &out, err
|
||||
}
|
||||
|
||||
func (c *Client) TranslationMemoryResolveConflict(ctx context.Context, params TranslationMemoryResolveConflictParams) (*TranslationMemoryResolveConflictReport, error) {
|
||||
var out TranslationMemoryResolveConflictReport
|
||||
_, err := c.Call(ctx, "translation.memory.resolve_conflict", params, &out)
|
||||
return &out, err
|
||||
}
|
||||
|
||||
func (c *Client) GlossarySummary(ctx context.Context, params GlossarySummaryParams) (*GlossarySummaryReport, error) {
|
||||
var out GlossarySummaryReport
|
||||
_, err := c.Call(ctx, "translation.glossary.summary", params, &out)
|
||||
|
||||
@@ -756,14 +756,15 @@ func TestTranslationMemoryTypedContract(t *testing.T) {
|
||||
Data: map[string]any{
|
||||
"available": true,
|
||||
"path": "/var/lib/bat/translation-memory.sqlite",
|
||||
"schema_version": 1,
|
||||
"schema_version": 2,
|
||||
"summary": map[string]any{
|
||||
"schema_version": 1,
|
||||
"record_count": 3,
|
||||
"trusted_count": 1,
|
||||
"candidate_count": 1,
|
||||
"superseded_count": 1,
|
||||
"rejected_count": 0,
|
||||
"schema_version": 2,
|
||||
"record_count": 3,
|
||||
"trusted_count": 1,
|
||||
"candidate_count": 1,
|
||||
"superseded_count": 1,
|
||||
"rejected_count": 0,
|
||||
"current_trusted_count": 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -859,6 +860,50 @@ func TestTranslationMemoryTypedContract(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
case "translation.memory.conflicts":
|
||||
var params TranslationMemoryConflictsParams
|
||||
if err := json.Unmarshal(req.Params, ¶ms); err != nil {
|
||||
t.Fatalf("decode conflicts params: %v", err)
|
||||
}
|
||||
if params.TranslationMemoryPath != "/var/lib/bat/translation-memory.sqlite" ||
|
||||
params.Limit == nil || *params.Limit != limit {
|
||||
t.Fatalf("conflicts params=%#v", params)
|
||||
}
|
||||
return testResponse{
|
||||
Result: testEnvelope{
|
||||
OK: true, Status: "ok", RequestID: "req-tm-conflicts",
|
||||
Data: map[string]any{
|
||||
"available": true,
|
||||
"path": "/var/lib/bat/translation-memory.sqlite",
|
||||
"conflicts": []any{},
|
||||
},
|
||||
},
|
||||
}
|
||||
case "translation.memory.resolve_conflict":
|
||||
var params TranslationMemoryResolveConflictParams
|
||||
if err := json.Unmarshal(req.Params, ¶ms); err != nil {
|
||||
t.Fatalf("decode resolve params: %v", err)
|
||||
}
|
||||
if params.WinnerRecordID != "tm-record-1" ||
|
||||
len(params.ExpectedTrustedRecordIDs) != 2 ||
|
||||
params.ExpectedTrustedRecordIDs[1] != "tm-record-2" ||
|
||||
params.Reviewer != "reviewer" ||
|
||||
params.Reason != "selected" {
|
||||
t.Fatalf("resolve params=%#v", params)
|
||||
}
|
||||
return testResponse{
|
||||
Result: testEnvelope{
|
||||
OK: true, Status: "ok", RequestID: "req-tm-resolve",
|
||||
Data: map[string]any{
|
||||
"available": true,
|
||||
"path": "/var/lib/bat/translation-memory.sqlite",
|
||||
"entry": map[string]any{
|
||||
"record_id": "tm-record-1",
|
||||
"trust_status": "trusted",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
default:
|
||||
t.Fatalf("unexpected method %q", req.Method)
|
||||
return testResponse{}
|
||||
@@ -915,6 +960,32 @@ func TestTranslationMemoryTypedContract(t *testing.T) {
|
||||
confirmed.Entry.RecordID != "tm-record-1" {
|
||||
t.Fatalf("confirmed=%#v", confirmed)
|
||||
}
|
||||
|
||||
conflicts, err := client.TranslationMemoryConflicts(context.Background(), TranslationMemoryConflictsParams{
|
||||
TranslationMemoryPath: "/var/lib/bat/translation-memory.sqlite",
|
||||
Limit: &limit,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("TranslationMemoryConflicts error: %v", err)
|
||||
}
|
||||
if !conflicts.Available || len(conflicts.Conflicts) != 0 {
|
||||
t.Fatalf("conflicts=%#v", conflicts)
|
||||
}
|
||||
|
||||
resolved, err := client.TranslationMemoryResolveConflict(context.Background(), TranslationMemoryResolveConflictParams{
|
||||
TranslationMemoryPath: "/var/lib/bat/translation-memory.sqlite",
|
||||
WinnerRecordID: "tm-record-1",
|
||||
ExpectedTrustedRecordIDs: []string{"tm-record-1", "tm-record-2"},
|
||||
Reviewer: "reviewer",
|
||||
Reason: "selected",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("TranslationMemoryResolveConflict error: %v", err)
|
||||
}
|
||||
if !resolved.Available || resolved.Entry.RecordID != "tm-record-1" ||
|
||||
resolved.Entry.TrustStatus != TranslationMemoryStatusTrusted {
|
||||
t.Fatalf("resolved=%#v", resolved)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTranslationProofreadUsesRustMethod(t *testing.T) {
|
||||
@@ -1064,9 +1135,9 @@ func TestGlossaryTypedContract(t *testing.T) {
|
||||
Data: map[string]any{
|
||||
"available": true,
|
||||
"path": "/var/lib/bat/glossary.sqlite",
|
||||
"schema_version": 1,
|
||||
"schema_version": 2,
|
||||
"summary": map[string]any{
|
||||
"schema_version": 1,
|
||||
"schema_version": 2,
|
||||
"term_count": 2,
|
||||
"approved_count": 1,
|
||||
"draft_count": 1,
|
||||
|
||||
Reference in New Issue
Block a user