2626
2727 .layout {
2828 flex : 1 ;
29- padding : var (--space-xl );
29+ max-width : 1280px ;
30+ width : 100% ;
31+ margin : 0 auto;
32+ padding : var (--space-lg );
3033 display : flex;
3134 flex-direction : column;
3235 gap : var (--space-lg );
3336 min-width : 0 ;
3437 }
35- .page-header { display : flex; align-items : flex-start; gap : var (--space-md ); }
36- .page-title { font-size : 28px ; line-height : 1.2 ; font-weight : 700 ; }
37- .page-subtitle { font-size : 14px ; color : var (--color-ink-muted ); margin-top : 6px ; }
38+ .page-header { display : flex; align-items : flex-start; gap : var (--space-md ); margin-bottom : 24px ; }
39+ .page-title {
40+ font-family : var (--font-serif-display );
41+ font-size : 28px ;
42+ line-height : 1.3 ;
43+ font-weight : 700 ;
44+ color : var (--color-ink );
45+ margin : 0 0 4px ;
46+ }
47+ .page-subtitle { font-size : 14px ; line-height : 1.8 ; color : var (--color-text-soft ); margin : 0 ; }
3848 .list {
3949 display : grid;
4050 gap : var (--space-sm );
450460
451461 @media (max-width : 768px ) {
452462 .layout { padding : var (--space-md ) var (--space-md ) var (--space-xl ); }
453- .page-title { font-size : 22px ; }
454463 .task-item-header {
455464 flex-direction : column;
456465 align-items : flex-start;
500509 }
501510 @media (max-width : 420px ) {
502511 .mobile-user-name { max-width : 56px ; font-size : 11px ; }
503- .navbar-brand { width : auto; flex : 1 ; min-width : 0 ; }
504- .navbar-wordmark { font-size : 13px ; }
505- .mobile-lang-toggle { padding : 6px 8px ; }
506512 }
507513 .toast-container { position : fixed; bottom : var (--space-lg ); right : var (--space-lg ); z-index : var (--z-toast ); pointer-events : none; }
508514 .toast {
@@ -643,7 +649,7 @@ <h1 class="page-title" id="pageTitle">標記清單</h1>
643649 < tbody id ="sampleRows "> </ tbody >
644650 </ table >
645651 </ div >
646- < div class ="empty hidden " id ="emptyState "> 找不到符合條件的資料。 </ div >
652+ < div class ="empty hidden " id ="emptyState "> </ div >
647653 < div class ="pagination hidden " id ="paginationBar ">
648654 < div class ="pagination-left ">
649655 < span class ="pagination-info " id ="paginationInfo "> </ span >
@@ -708,10 +714,15 @@ <h1 class="page-title" id="pageTitle">標記清單</h1>
708714 quickContinueBtnReviewer : '快速審核' ,
709715 editBtnLabel : '編輯' ,
710716 expandBtnLabel : '展開' ,
717+ approveBtnLabel : '通過' ,
718+ rejectBtnLabel : '退回' ,
719+ approveAllBtnLabel : '全部通過' ,
720+ rejectAllBtnLabel : '全部退回' ,
711721 searchPlaceholder : '搜尋' ,
712722 searchAriaLabel : '搜尋' ,
713723 statusFilterAll : '全部完成狀態' ,
714724 clearFiltersLabel : '清除篩選' ,
725+ emptyNoResults : '找不到符合條件的資料。' ,
715726 paginationTpl : '共 {total} 筆 · 第 {page} / {totalPages} 頁' ,
716727 pageSizeTpl : '{size} / 頁' ,
717728 roleLabelAnnotator : '標記員' ,
@@ -750,10 +761,15 @@ <h1 class="page-title" id="pageTitle">標記清單</h1>
750761 quickContinueBtnReviewer : 'Quick Review' ,
751762 editBtnLabel : 'Edit' ,
752763 expandBtnLabel : 'Expand' ,
764+ approveBtnLabel : 'Approve' ,
765+ rejectBtnLabel : 'Reject' ,
766+ approveAllBtnLabel : 'Approve all' ,
767+ rejectAllBtnLabel : 'Reject all' ,
753768 searchPlaceholder : 'Search' ,
754769 searchAriaLabel : 'Search' ,
755770 statusFilterAll : 'All statuses' ,
756771 clearFiltersLabel : 'Clear filters' ,
772+ emptyNoResults : 'No matching data.' ,
757773 paginationTpl : 'Total {total} · Page {page} / {totalPages}' ,
758774 pageSizeTpl : '{size} / page' ,
759775 roleLabelAnnotator : 'Annotator' ,
@@ -771,6 +787,97 @@ <h1 class="page-title" id="pageTitle">標記清單</h1>
771787 return CURRENT_LANG === 'en' && sample . textEn ? sample . textEn : sample . text ;
772788 }
773789
790+ var REVIEWER_RESULT_TRANSLATIONS = {
791+ '電池續航力' : 'battery life' ,
792+ '服務員的態度' : 'staff attitude' ,
793+ '操作流程順暢' : 'smooth workflow' ,
794+ '客服回應速度' : 'support response speed' ,
795+ '半導體產業論壇' : 'Semiconductor Industry Forum' ,
796+ '創辦人張忠謀' : 'founder Morris Chang' ,
797+ '鴻海精密工業' : 'Foxconn' ,
798+ '越南胡志明市' : 'Ho Chi Minh City, Vietnam' ,
799+ '超音波檢查' : 'ultrasound exam' ,
800+ '賀爾蒙變化' : 'hormonal changes' ,
801+ '胃部不適' : 'gastrointestinal discomfort' ,
802+ '整體設計' : 'overall design' ,
803+ '菜色選擇' : 'menu options' ,
804+ '服務態度' : 'service attitude' ,
805+ '用餐體驗' : 'dining experience' ,
806+ '停車空間' : 'parking space' ,
807+ '房間隔音' : 'room soundproofing' ,
808+ '介面設計' : 'interface design' ,
809+ '操作流程' : 'workflow' ,
810+ '客戶支援' : 'customer support' ,
811+ '佩戴舒適度' : 'wearing comfort' ,
812+ '主動降噪功能' : 'active noise cancellation' ,
813+ '主動降噪' : 'active noise cancellation' ,
814+ '降噪功能' : 'noise cancellation' ,
815+ '音質表現' : 'audio quality' ,
816+ '服務員' : 'staff' ,
817+ '早餐品質' : 'breakfast quality' ,
818+ '停車場' : 'parking' ,
819+ '隔音效果' : 'soundproofing' ,
820+ '電池壽命' : 'battery life' ,
821+ '高效能' : 'high performance' ,
822+ '未完全出現在句子中' : 'not an exact sentence match' ,
823+ '已刪除' : 'deleted' ,
824+ '螢幕' : 'screen' ,
825+ '價格' : 'price' ,
826+ '環境' : 'ambiance' ,
827+ '介面' : 'interface' ,
828+ '音質' : 'audio quality' ,
829+ '舒適度' : 'comfort' ,
830+ '隔音' : 'soundproofing' ,
831+ '體育' : 'Sports' ,
832+ '娛樂' : 'Entertainment' ,
833+ '社會' : 'Society' ,
834+ '政治' : 'Politics' ,
835+ '科技' : 'Technology' ,
836+ '財經' : 'Finance' ,
837+ '等價' : 'Equivalent' ,
838+ '相關' : 'Related' ,
839+ '無關' : 'Unrelated' ,
840+ '阿司匹靈' : 'Aspirin' ,
841+ '頭痛' : 'headache' ,
842+ '乳房' : 'breast' ,
843+ '疼痛' : 'pain' ,
844+ '月經週期' : 'menstrual cycle' ,
845+ '超音波' : 'ultrasound' ,
846+ '膽囊結石' : 'gallstones' ,
847+ '腹部疼痛' : 'abdominal pain' ,
848+ '台積電' : 'TSMC' ,
849+ '張忠謀' : 'Morris Chang' ,
850+ '台北' : 'Taipei' ,
851+ '鴻海' : 'Foxconn' ,
852+ '越南' : 'Vietnam' ,
853+ '胡志明市' : 'Ho Chi Minh City' ,
854+ '衛生福利部' : 'Ministry of Health and Welfare' ,
855+ '薛瑞元' : 'Hsueh Jui-yuan' ,
856+ '2025年' : '2025' ,
857+ '草稿' : 'draft'
858+ } ;
859+
860+ var SORTED_REVIEWER_TRANSLATION_KEYS = Object . keys ( REVIEWER_RESULT_TRANSLATIONS ) . sort ( function ( a , b ) {
861+ return b . length - a . length ;
862+ } ) ;
863+
864+ function localizeReviewerText ( text ) {
865+ var output = String ( text || '' ) ;
866+ if ( CURRENT_LANG !== 'en' || output === '-' ) return output ;
867+ SORTED_REVIEWER_TRANSLATION_KEYS . forEach ( function ( source ) {
868+ output = output . split ( source ) . join ( REVIEWER_RESULT_TRANSLATIONS [ source ] ) ;
869+ } ) ;
870+ return output
871+ . replace ( / 、 / g, ', ' )
872+ . replace ( / ( / g, ' (' )
873+ . replace ( / ) / g, ')' )
874+ . replace ( / 原 : / g, 'original: ' )
875+ . replace ( / \s + , / g, ',' )
876+ . replace ( / , \s * / g, ', ' )
877+ . replace ( / \s { 2 , } / g, ' ' )
878+ . trim ( ) ;
879+ }
880+
774881 var toastTimer = null ;
775882 function showToast ( msg , type ) {
776883 var toast = document . getElementById ( 'toast' ) ;
@@ -1425,17 +1532,17 @@ <h1 class="page-title" id="pageTitle">標記清單</h1>
14251532 var resultSpan = document . createElement ( 'span' ) ;
14261533 var colorClass = getVaColorClass ( ann . result , vaRange ) ;
14271534 resultSpan . className = 'annotator-result-tag' + ( colorClass ? ' ' + colorClass : '' ) ;
1428- resultSpan . textContent = ann . result ;
1535+ resultSpan . textContent = localizeReviewerText ( ann . result ) ;
14291536
14301537 var approveBtn = document . createElement ( 'button' ) ;
14311538 approveBtn . type = 'button' ;
14321539 approveBtn . className = 'mini-btn mini-btn-approve' ;
1433- approveBtn . textContent = '✓ 通過' ;
1540+ approveBtn . textContent = '✓ ' + t ( 'approveBtnLabel' ) ;
14341541
14351542 var rejectBtn = document . createElement ( 'button' ) ;
14361543 rejectBtn . type = 'button' ;
14371544 rejectBtn . className = 'mini-btn mini-btn-reject' ;
1438- rejectBtn . textContent = '✕ 退回' ;
1545+ rejectBtn . textContent = '✕ ' + t ( 'rejectBtnLabel' ) ;
14391546
14401547 updateAnnotatorBtns ( approveBtn , rejectBtn , REVIEW_STATES [ key ] ) ;
14411548
@@ -1819,7 +1926,7 @@ <h1 class="page-title" id="pageTitle">標記清單</h1>
18191926 }
18201927
18211928 function formatReviewerLabelStats ( sample , taskType ) {
1822- var statsText = sample && sample . labelStats ? String ( sample . labelStats ) : '-' ;
1929+ var statsText = sample && sample . labelStats ? localizeReviewerText ( sample . labelStats ) : '-' ;
18231930 if ( taskType !== 'relation_extraction' ) return statsText ;
18241931 return statsText . replace ( / \s · \s / g, '\n' ) ;
18251932 }
@@ -1902,12 +2009,12 @@ <h1 class="page-title" id="pageTitle">標記清單</h1>
19022009 var approveAllBtn = document . createElement ( 'button' ) ;
19032010 approveAllBtn . type = 'button' ;
19042011 approveAllBtn . className = 'mini-btn mini-btn-approve' ;
1905- approveAllBtn . textContent = '✓ 全部通過' ;
2012+ approveAllBtn . textContent = '✓ ' + t ( 'approveAllBtnLabel' ) ;
19062013 approveAllBtn . dataset . bulkApproveFor = sample . sampleId ;
19072014 var rejectAllBtn = document . createElement ( 'button' ) ;
19082015 rejectAllBtn . type = 'button' ;
19092016 rejectAllBtn . className = 'mini-btn mini-btn-reject' ;
1910- rejectAllBtn . textContent = '✕ 全部退回' ;
2017+ rejectAllBtn . textContent = '✕ ' + t ( 'rejectAllBtnLabel' ) ;
19112018 rejectAllBtn . dataset . bulkRejectFor = sample . sampleId ;
19122019
19132020 updateBulkReviewBtns ( approveAllBtn , rejectAllBtn , getBulkReviewState ( sample . sampleId , annotators ) ) ;
@@ -2123,6 +2230,8 @@ <h1 class="page-title" id="pageTitle">標記清單</h1>
21232230 }
21242231 var clearFiltersBtn = document . getElementById ( 'clearFiltersBtn' ) ;
21252232 if ( clearFiltersBtn ) clearFiltersBtn . setAttribute ( 'aria-label' , t ( 'clearFiltersLabel' ) ) ;
2233+ var emptyState = document . getElementById ( 'emptyState' ) ;
2234+ if ( emptyState ) emptyState . textContent = t ( 'emptyNoResults' ) ;
21262235
21272236 renderTableHeader ( context . role ) ;
21282237 renderTaskInfo ( context ) ;
0 commit comments