Define the local evaluation task
A synthetic bilingual handoff has independently ordered EN and zh-HK segments. Staff supply a concept key for each segment after checking its meaning. Match one EN segment to one Chinese segment by that key; repeated or missing counterparts are errors rather than nearest-position matches. The checker evaluates associations, not translation quality.
- Read staff-confirmed concept keys
- Count counterparts in each locale
- Emit unique pairs and unresolved keys
Unverified meaning labels need bilingual review before using this association checker.
Use the filled cases
| Case | Supplied input | Expected structured output | Decision and reason |
|---|---|---|---|
| Different locale orders | {"en":[{"id":"E1","key":"pickup"},{"id":"E2","key":"delivery"}],"zh":[{"id":"Z7","key":"delivery"},{"id":"Z8","key":"pickup"}]} | {"pairs":[{"key":"delivery","en":"E2","zh":"Z7"},{"key":"pickup","en":"E1","zh":"Z8"}],"errors":[]} | Concept keys give crossed positions without crossing meanings. |
| Chinese counterpart missing | {"en":[{"id":"E1","key":"pickup"}],"zh":[]} | {"pairs":[],"errors":["pickup"]} | No paired receipt can be claimed for a missing counterpart. |
| Two Chinese counterparts | {"en":[{"id":"E1","key":"pickup"}],"zh":[{"id":"Z1","key":"pickup"},{"id":"Z2","key":"pickup"}]} | {"pairs":[],"errors":["pickup"]} | The one-to-one contract has no authority to choose Z1 or Z2. |
Work the two-chinese-candidates case. Which output is required, and why?
Show the worked answer
{"pairs":[],"errors":["pickup"]} — The one-to-one contract has no authority to choose Z1 or Z2.
Run the self-contained evaluator
import assert from 'node:assert/strict';
function evaluate(x){
const keys=[...new Set([...x.en,...x.zh].map(s=>s.key))].sort(),pairs=[],errors=[];
for(const key of keys){const a=x.en.filter(s=>s.key===key),b=x.zh.filter(s=>s.key===key);if(a.length===1&&b.length===1)pairs.push({key,en:a[0].id,zh:b[0].id});else errors.push(key);}
return {pairs,errors};
}
const cases = [
{
"id": "independent-order",
"input": {
"en": [
{
"id": "E1",
"key": "pickup"
},
{
"id": "E2",
"key": "delivery"
}
],
"zh": [
{
"id": "Z7",
"key": "delivery"
},
{
"id": "Z8",
"key": "pickup"
}
]
},
"expected": {
"pairs": [
{
"key": "delivery",
"en": "E2",
"zh": "Z7"
},
{
"key": "pickup",
"en": "E1",
"zh": "Z8"
}
],
"errors": []
}
},
{
"id": "missing-chinese",
"input": {
"en": [
{
"id": "E1",
"key": "pickup"
}
],
"zh": []
},
"expected": {
"pairs": [],
"errors": [
"pickup"
]
}
},
{
"id": "two-chinese-candidates",
"input": {
"en": [
{
"id": "E1",
"key": "pickup"
}
],
"zh": [
{
"id": "Z1",
"key": "pickup"
},
{
"id": "Z2",
"key": "pickup"
}
]
},
"expected": {
"pairs": [],
"errors": [
"pickup"
]
}
}
];
for (const c of cases) assert.deepEqual(evaluate(c.input), c.expected, c.id);
console.log(JSON.stringify({checked:cases.length,caseIds:cases.map(c=>c.id)}));
Store segment text beside its key and ID in a real evaluation. Matching labels only tests the supplied alignment; correct keys cannot prove that either sentence is accurate.