fix: 모선 검토 패널 i18n 번역 키 추가 (ko/en)

parentInference.* 키가 누락되어 UI에 번역 키가 그대로 노출되던 문제.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
htlee 2026-04-04 01:06:14 +09:00
부모 8362bc5b6c
커밋 973b419287
2개의 변경된 파일392개의 추가작업 그리고 0개의 파일을 삭제

파일 보기

@ -195,6 +195,202 @@
"operator": "Operator", "operator": "Operator",
"yearSuffix": "" "yearSuffix": ""
}, },
"fleetGear": {
"fleetSection": "Fleet Status ({{count}})",
"fleetFallback": "Fleet #{{id}}",
"inZoneSection": "Gear In Zone ({{count}})",
"outZoneSection": "Unauthorized Gear ({{count}})",
"toggleFleetSection": "Collapse or expand fleet status",
"emptyFleet": "No fleet data",
"vesselCountCompact": "({{count}} vessels)",
"zoom": "Zoom",
"moveToFleet": "Move map to this fleet",
"moveToGroup": "Move map to this gear group",
"moveToShip": "Move to ship",
"moveToShipItem": "Move to ship {{name}}",
"moveToGear": "Move to gear position",
"moveToGearItem": "Move to {{name}} position",
"shipList": "Ships",
"gearList": "Gear List",
"roleMain": "Main",
"roleSub": "Sub"
},
"parentInference": {
"title": "Parent Review",
"actorLabel": "Review Actor",
"actorPlaceholder": "lab-ui",
"reviewQueue": "Review Queue ({{count}})",
"reviewQueueFiltered": "Review Queue ({{filtered}} / {{total}})",
"queueMeta": "sc#{{subClusterId}} · {{count}} candidates",
"emptyQueue": "No items waiting for review.",
"loading": "Loading...",
"emptyState": "No parent inference data yet.",
"filters": {
"minScore": "Minimum score",
"minScoreValue": "{{value}}%+",
"minScoreAll": "All",
"minMemberCount": "Minimum gear",
"search": "Search",
"searchPlaceholder": "Search name, zone, suggested parent",
"clearSearch": "Clear",
"resetFilters": "Reset filters",
"sort": "Sort",
"startSpatial": "Draw map range",
"finishSpatial": "Apply range",
"clearSpatial": "Clear range",
"spatialIdle": "No map range filter is applied.",
"spatialDrawing": "{{count}} points added on the map. Move the mouse for a live preview, and click near the start point after 3 or more points to close the polygon.",
"spatialApplied": "Only gear groups inside the drawn map range are shown.",
"queueFilterFallback": "Saved filters currently hide every item, so the full review queue is shown temporarily.",
"queueTopScore": "Top Score {{score}}",
"queueMemberCount": "{{count}} gear",
"sortOptions": {
"backend": "Default order",
"topScore": "Highest score",
"memberCount": "Most gear",
"candidateCount": "Most candidates",
"zoneDistance": "Closest to fishing zone",
"name": "Name"
}
},
"summary": {
"label": "Inference",
"recommendedParent": "Suggested Parent",
"confidence": "Confidence",
"topMargin": "Top Score/Margin",
"stableCycles": "Stable Cycles",
"statusReason": "Reason",
"marginOnly": "Margin",
"activeLabel": "Active Label",
"activeUntil": "until {{value}}",
"groupExclusions": "Group Exclusions"
},
"metrics": {
"corr": "Corr",
"name": "Name",
"track": "Track",
"visit": "Visit",
"prox": "Prox",
"activity": "Activity"
},
"actions": {
"refresh": "Refresh",
"duration": "Duration",
"durationOption": "{{days}}d",
"label": "Label",
"jumpSubCluster": "Locate",
"cancelLabel": "Clear Label",
"groupExclude": "Group Excl.",
"releaseGroupExclude": "Group Clear",
"globalExclude": "Global Excl.",
"releaseGlobalExclude": "Global Clear",
"otherLabelActive": "Another candidate is already active as the labeled parent."
},
"badges": {
"AUTO_PROMOTED": "AUTO",
"MANUAL_CONFIRMED": "MANUAL",
"DIRECT_PARENT_MATCH": "DIRECT",
"REVIEW_REQUIRED": "REVIEW",
"SKIPPED_SHORT_NAME": "SHORT",
"NO_CANDIDATE": "NO CAND",
"UNRESOLVED": "OPEN",
"NONE": "NONE"
},
"status": {
"AUTO_PROMOTED": "Auto Promoted",
"MANUAL_CONFIRMED": "Manual Confirmed",
"DIRECT_PARENT_MATCH": "Direct Parent Match",
"REVIEW_REQUIRED": "Review Required",
"SKIPPED_SHORT_NAME": "Skipped: Short Name",
"NO_CANDIDATE": "No Candidate",
"UNRESOLVED": "Unresolved"
},
"reasons": {
"shortName": "Normalized name is shorter than 4 characters",
"directParentMatch": "A direct parent vessel is already included in the group",
"noCandidate": "No candidate could be generated"
},
"reference": {
"shipOnly": "Only ship candidates are used for confirm and 24-hour exclusion. Gear remains reference-only for replay comparison.",
"reviewDriven": "When parent review is active, this panel becomes reference-only. Actual overlay visibility follows the state of the right-side parent review panel.",
"referenceGear": "Reference Gear"
},
"candidate": {
"hoverHint": "Hover a candidate card to compare that vessel's full track and current replay movement more clearly.",
"trackReady": "Track Ready",
"trackMissing": "No Track",
"totalScore": "Total",
"nationalityBonusApplied": "Nationality +{{value}}%",
"nationalityBonusNone": "No nationality bonus",
"evidenceConfidence": "Evidence {{value}}%",
"emptyThreshold": "No candidates at or above {{score}}%.",
"labelActive": "Label",
"groupExcludedUntil": "Group Excluded · {{value}}",
"globalExcluded": "Global Excl.",
"trackWindow": "Observed",
"overlapWindow": "Overlap",
"inZoneWindow": "In zone",
"scoreWindow": "Score win.",
"trackCoverage": "Track adj.",
"visitCoverage": "Visit adj.",
"activityCoverage": "Activity adj.",
"proxCoverage": "Prox adj."
},
"help": {
"title": "Parent Review Guide",
"intro": "All scores are shown as 0-100%. The final candidate score is built from the components below, and reviewers should use both the candidate cards and replay comparison together.",
"close": "Close",
"scoreTitle": "Scoring",
"scoreScaleLabel": "Display scale",
"scoreScaleDesc": "Each candidate metric is stored as 0.0-1.0 internally and displayed as 0-100%.",
"formulaLabel": "Final score formula",
"formulaDesc": "Corr 40% + Name 15% + Track 15% + Visit 10% + Proximity 5% + Activity 5% + Stability 10% + Registry bonus 5%. After that, if the pre-bonus score is at least 30% and MMSI starts with 412/413, a +15% nationality bonus is added at the very end.",
"nameScoreLabel": "Name score",
"nameScoreDesc": "100% for raw uppercase exact match, 80% for normalized exact match after removing spaces/`_`/`-`/`%`, 50% for prefix or contains match, 30% when only the pure alphabetic portion matches after removing digits, and 0% otherwise. Normalized comparison uses the gear-group name against candidate AIS/registry names.",
"corrLabel": "Corr",
"corrDesc": "Uses the current_score from the default correlation model directly. This is the base linkage score between the group and the vessel candidate.",
"trackLabel": "Track",
"trackDesc": "Compares the last 6 hours of gear-polygon center movement and vessel track with DTW. Near 0m average distance approaches 100%; 10km or more approaches 0%. Short observations are reduced afterward by a coverage adjustment based on observed points and span.",
"coverageLabel": "Coverage adjustment",
"coverageDesc": "Track, visit, proximity, and activity are discounted when the observed track, overlap window, or in-zone stay is too short. The candidate card shows this as Observed/Overlap/In zone plus the adjustment rows.",
"visitLabel": "Visit",
"visitDesc": "Average visit_score from raw metrics over the last 6 hours. It rises when the vessel repeatedly visits the group area, but short in-zone coverage lowers the effective value.",
"proxLabel": "Proximity",
"proxDesc": "Average proximity_ratio from raw metrics over the last 6 hours. It rises when the vessel stays physically close over aligned observations, but very short tracks are reduced by the track coverage adjustment.",
"activityLabel": "Activity",
"activityDesc": "Average activity_sync from raw metrics over the last 6 hours. It reflects how similarly movement and working patterns evolve together, and is reduced when in-zone coverage is too short.",
"stabilityLabel": "Stability",
"stabilityDesc": "Computed as default correlation streak_count divided by 6, then clamped to 100%. It rises when the same top candidate persists across cycles.",
"bonusLabel": "Bonuses",
"bonusDesc": "A registry-matched vessel gets a fixed +5%. A 412/413 MMSI gets +15% only when the pre-bonus score is already at least 30%.",
"summaryLabel": "Top / Margin / Stable cycles",
"summaryDesc": "Top score is the final score of the #1 candidate for the group, margin is the gap between #1 and #2, and stable cycles counts how many consecutive cycles the same top MMSI remained on top.",
"filterTitle": "Filters",
"filterSortLabel": "Sort",
"filterSortDesc": "Reorders the queue by default order, score, gear count, candidate count, fishing-zone distance, or name.",
"filterMemberLabel": "Min gear count",
"filterMemberDesc": "Only groups with at least this many gear members remain in the review queue. Default is 2.",
"filterScoreLabel": "Min score",
"filterScoreDesc": "Only groups whose top score is at or above this threshold remain in the list and on the map. Candidate cards are also limited to 30%+ scores in the current UI.",
"filterSearchLabel": "Search",
"filterSearchDesc": "Matches input text while ignoring spaces and case. Groups remain visible when the query is contained in the group name, zone name, or suggested parent name.",
"filterSpatialLabel": "Map area",
"filterSpatialDesc": "Start drawing, click the map to create a polygon, and finish to keep only groups inside that area. It combines with score/gear-count filters using AND logic.",
"actionTitle": "Buttons and interactions",
"actionRefreshLabel": "Refresh",
"actionRefreshDesc": "Reloads the selected group's inference, active labels/exclusions, and the review queue.",
"actionLocateLabel": "Locate",
"actionLocateDesc": "Moves the map to the actual member bounds of that `sc#` subcluster, which helps when the same name is split into far-apart clusters.",
"actionLabelLabel": "Label",
"actionLabelDesc": "Stores the selected candidate as the answer label for this group. During the chosen duration (1/3/5 days), shadow tracking rows are accumulated for model evaluation.",
"actionGroupExcludeLabel": "Group Excl.",
"actionGroupExcludeDesc": "Excludes the selected candidate only from this gear group for the chosen duration. Other groups are unaffected.",
"actionGlobalExcludeLabel": "Global Excl.",
"actionGlobalExcludeDesc": "Excludes the selected MMSI from every gear group's candidate pool for the chosen duration. Use this for AIS targets that were misclassified as vessel candidates.",
"actionHoverLabel": "Hover compare",
"actionHoverDesc": "Hovering a candidate card strongly highlights that vessel's full track and current movement in replay so you can visually compare it against the gear polygon movement."
}
},
"auth": { "auth": {
"title": "KCG Monitoring Dashboard", "title": "KCG Monitoring Dashboard",
"subtitle": "Maritime Situational Awareness", "subtitle": "Maritime Situational Awareness",

파일 보기

@ -195,6 +195,202 @@
"operator": "운영", "operator": "운영",
"yearSuffix": "년" "yearSuffix": "년"
}, },
"fleetGear": {
"fleetSection": "선단 현황 ({{count}}개)",
"fleetFallback": "선단 #{{id}}",
"inZoneSection": "조업구역내 어구 ({{count}}개)",
"outZoneSection": "비허가 어구 ({{count}}개)",
"toggleFleetSection": "선단 현황 접기/펴기",
"emptyFleet": "선단 데이터 없음",
"vesselCountCompact": "({{count}}척)",
"zoom": "이동",
"moveToFleet": "이 선단으로 지도 이동",
"moveToGroup": "이 어구 그룹으로 지도 이동",
"moveToShip": "선박으로 이동",
"moveToShipItem": "{{name}} 선박으로 이동",
"moveToGear": "어구 위치로 이동",
"moveToGearItem": "{{name}} 위치로 이동",
"shipList": "선박",
"gearList": "어구 목록",
"roleMain": "주선",
"roleSub": "구성"
},
"parentInference": {
"title": "모선 검토",
"actorLabel": "검토자",
"actorPlaceholder": "lab-ui",
"reviewQueue": "검토 대기 ({{count}}건)",
"reviewQueueFiltered": "검토 대기 ({{filtered}} / {{total}}건)",
"queueMeta": "sc#{{subClusterId}} · 후보 {{count}}건",
"emptyQueue": "대기 중인 검토가 없습니다.",
"loading": "불러오는 중...",
"emptyState": "모선 추론 데이터가 아직 없습니다.",
"filters": {
"minScore": "최소 일치율",
"minScoreValue": "{{value}}%+",
"minScoreAll": "전체",
"minMemberCount": "최소 어구 수",
"search": "검색",
"searchPlaceholder": "이름, 수역, 추천 모선 검색",
"clearSearch": "초기화",
"resetFilters": "필터 초기화",
"sort": "정렬",
"startSpatial": "지도 범위 그리기",
"finishSpatial": "범위 확정",
"clearSpatial": "범위 해제",
"spatialIdle": "지도 범위 필터가 적용되지 않았습니다.",
"spatialDrawing": "지도에서 점 {{count}}개를 찍었습니다. 마우스를 움직이면 미리보기가 보이고, 3개 이상이면 시작점 근처 클릭으로 바로 닫을 수 있습니다.",
"spatialApplied": "사용자가 그린 지도 범위 안의 어구 그룹만 표시합니다.",
"queueFilterFallback": "저장된 필터로 0건이 되어 전체 검토 대기 목록을 임시 표시 중입니다.",
"queueTopScore": "Top 점수 {{score}}",
"queueMemberCount": "{{count}}개",
"sortOptions": {
"backend": "기본 순서",
"topScore": "일치율 높은순",
"memberCount": "어구 수 많은순",
"candidateCount": "후보 수 많은순",
"zoneDistance": "조업구역 가까운순",
"name": "이름순"
}
},
"summary": {
"label": "추론",
"recommendedParent": "추천 모선",
"confidence": "신뢰도",
"topMargin": "Top/격차",
"stableCycles": "연속 안정 주기",
"statusReason": "사유",
"marginOnly": "격차",
"activeLabel": "활성 정답 라벨",
"activeUntil": "{{value}}까지",
"groupExclusions": "그룹 제외 후보"
},
"metrics": {
"corr": "상관",
"name": "이름",
"track": "궤적",
"visit": "방문",
"prox": "근접",
"activity": "활동"
},
"actions": {
"refresh": "새로고침",
"duration": "적용 기간",
"durationOption": "{{days}}일",
"label": "라벨",
"jumpSubCluster": "이동",
"cancelLabel": "라벨 해제",
"groupExclude": "그룹 제외",
"releaseGroupExclude": "그룹 해제",
"globalExclude": "전체 제외",
"releaseGlobalExclude": "전체 해제",
"otherLabelActive": "다른 후보가 이미 정답 라벨로 활성화되어 있습니다."
},
"badges": {
"AUTO_PROMOTED": "자동",
"MANUAL_CONFIRMED": "수동",
"DIRECT_PARENT_MATCH": "직접일치",
"REVIEW_REQUIRED": "검토",
"SKIPPED_SHORT_NAME": "짧음",
"NO_CANDIDATE": "후보없음",
"UNRESOLVED": "미해결",
"NONE": "없음"
},
"status": {
"AUTO_PROMOTED": "자동 승격",
"MANUAL_CONFIRMED": "수동 확정",
"DIRECT_PARENT_MATCH": "직접 모선 일치",
"REVIEW_REQUIRED": "검토 필요",
"SKIPPED_SHORT_NAME": "짧은 이름 제외",
"NO_CANDIDATE": "후보 없음",
"UNRESOLVED": "미해결"
},
"reasons": {
"shortName": "정규화 이름 길이 4 미만",
"directParentMatch": "그룹 멤버에 직접 모선이 포함됨",
"noCandidate": "후보를 생성하지 못함"
},
"reference": {
"shipOnly": "모선 확정과 24시간 제외 판단은 선박 후보만 사용합니다. 어구는 재생 비교용 참고 정보입니다.",
"reviewDriven": "모선 검토가 선택되면 이 패널은 참고 정보만 보여주고, 실제 오버레이 표시는 우측 모선 검토 패널 상태를 그대로 따릅니다.",
"referenceGear": "참고 어구"
},
"candidate": {
"hoverHint": "후보 카드에 마우스를 올리면 리플레이에서 해당 선박 항적과 현재 움직임을 강하게 비교할 수 있습니다.",
"trackReady": "항적 비교 가능",
"trackMissing": "항적 없음",
"totalScore": "전체",
"nationalityBonusApplied": "국적 가산 +{{value}}%",
"nationalityBonusNone": "국적 가산 없음",
"evidenceConfidence": "증거 {{value}}%",
"emptyThreshold": "{{score}}% 이상 후보가 없습니다.",
"labelActive": "라벨 활성",
"groupExcludedUntil": "그룹 제외 · {{value}}",
"globalExcluded": "전체 제외",
"trackWindow": "관측",
"overlapWindow": "겹침",
"inZoneWindow": "영역내",
"scoreWindow": "점수창",
"trackCoverage": "궤적 보정",
"visitCoverage": "방문 보정",
"activityCoverage": "활동 보정",
"proxCoverage": "근접 보정"
},
"help": {
"title": "모선 검토 가이드",
"intro": "각 점수는 0~100%로 표시됩니다. 최종 후보 점수는 아래 항목을 합산해 계산하고, 검토자는 우측 후보 카드와 리플레이 비교를 함께 사용합니다.",
"close": "닫기",
"scoreTitle": "점수 기준",
"scoreScaleLabel": "표시 단위",
"scoreScaleDesc": "후보 카드의 각 수치는 0.0~1.0 내부 점수를 0~100%로 변환해 보여줍니다.",
"formulaLabel": "전체 점수 산식",
"formulaDesc": "상관 40% + 이름 15% + 궤적 15% + 방문 10% + 근접 5% + 활동 5% + 안정성 10% + 등록보너스 5%를 합산합니다. 그 뒤 pre-bonus 점수가 30% 이상이고 MMSI가 412/413으로 시작하면 국적 가산 +15%를 마지막에 후가산합니다.",
"nameScoreLabel": "이름 점수",
"nameScoreDesc": "원문을 대문자로 본 완전일치면 100%, 공백/`_`/`-`/`%` 제거 후 정규화 일치면 80%, prefix 또는 contains 일치면 50%, 숫자를 제거한 순수 문자 기준으로만 같으면 30%, 그 외는 0%입니다. 정규화 비교는 어구 그룹 이름과 후보 AIS/registry 이름을 기준으로 합니다.",
"corrLabel": "상관",
"corrDesc": "기본 correlation model의 current_score를 그대로 사용합니다. 해당 어구 그룹과 후보 선박이 기존 상관 모델에서 얼마나 강하게 연결됐는지의 기본 점수입니다.",
"trackLabel": "궤적",
"trackDesc": "최근 6시간의 어구 폴리곤 중심 이동과 선박 항적을 DTW 기반으로 비교합니다. 평균 거리 0m에 가까울수록 100%, 평균 거리 10km 이상이면 0%에 수렴합니다. 다만 관측 포인트 수와 관측 시간폭이 짧으면 coverage 보정으로 실제 반영치는 더 낮아집니다.",
"coverageLabel": "Coverage 보정",
"coverageDesc": "짧은 항적, 짧은 겹침, 짧은 영역내 체류가 과대평가되지 않도록 궤적/방문/근접/활동에 별도 보정 계수를 곱합니다. 후보 카드의 `관측/겹침/영역내`와 `XX 보정` 항목이 이 근거입니다.",
"visitLabel": "방문",
"visitDesc": "최근 6시간 raw metrics의 visit_score 평균입니다. 선박이 해당 어구 그룹 주변을 반복 방문할수록 높아집니다. 단, 영역내 포인트 수와 체류 시간이 짧으면 coverage 보정으로 낮아집니다.",
"proxLabel": "근접",
"proxDesc": "최근 6시간 raw metrics의 proximity_ratio 평균입니다. 같은 시계열 기준으로 가까이 붙어 있던 비율이 높을수록 올라갑니다. 단, 짧은 관측은 궤적 coverage 보정으로 그대로 100%를 유지하지 못합니다.",
"activityLabel": "활동",
"activityDesc": "최근 6시간 raw metrics의 activity_sync 평균입니다. 이동/조업 패턴이 함께 움직인 정도를 반영합니다. 영역내 관측이 짧으면 activity coverage 보정으로 반영치를 낮춥니다.",
"stabilityLabel": "안정성",
"stabilityDesc": "기본 correlation model의 streak_count를 6으로 나눈 뒤 100%로 clamp 합니다. 같은 후보가 여러 cycle 연속 유지될수록 올라갑니다.",
"bonusLabel": "보너스",
"bonusDesc": "registry 선박으로 식별되면 +5% 고정 가산, MMSI 412/413 후보는 pre-bonus 점수 30% 이상일 때만 +15%를 마지막에 추가합니다.",
"summaryLabel": "Top/격차/안정 주기",
"summaryDesc": "Top 점수는 현재 그룹의 1위 후보 최종 점수, 격차는 1위와 2위의 차이, 연속 안정 주기는 같은 1위 MMSI가 연속 유지된 cycle 수입니다.",
"filterTitle": "필터 사용법",
"filterSortLabel": "정렬",
"filterSortDesc": "기본 순서, 일치율, 어구 수, 후보 수, 조업구역 거리, 이름 기준으로 검토 대기 목록을 재배열합니다.",
"filterMemberLabel": "최소 어구 수",
"filterMemberDesc": "해당 수 이상 멤버를 가진 어구 그룹만 검토 대기에 남깁니다. 기본값은 2입니다.",
"filterScoreLabel": "최소 일치율",
"filterScoreDesc": "Top 점수가 지정한 값 이상인 그룹만 목록과 지도에 남깁니다. 현재 UI 후보 카드도 30% 이상 후보만 보여줍니다.",
"filterSearchLabel": "검색",
"filterSearchDesc": "입력한 텍스트를 공백 무관, 대소문자 무관으로 비교합니다. 그룹 이름, 수역명, 추천 모선 이름에 포함되면 목록과 지도에 남깁니다.",
"filterSpatialLabel": "지도 범위",
"filterSpatialDesc": "범위 시작 후 지도를 클릭해 다각형을 그리고, 완료를 누르면 그 범위 안의 어구 그룹만 검토 대기에 남깁니다. 최소 일치율/어구 수와 AND 조건으로 함께 적용됩니다.",
"actionTitle": "버튼과 동작",
"actionRefreshLabel": "새로고침",
"actionRefreshDesc": "현재 선택 그룹의 추론 결과, 활성 라벨/제외 상태, 검토 대기 목록을 다시 불러옵니다.",
"actionLocateLabel": "이동",
"actionLocateDesc": "해당 `sc#` 서브클러스터의 실제 멤버 bounds로 지도를 이동시켜, 멀리 떨어진 클러스터를 바로 찾을 수 있게 합니다.",
"actionLabelLabel": "라벨",
"actionLabelDesc": "선택한 후보를 이 어구 그룹의 정답 라벨로 기록합니다. 기간(1/3/5일) 동안 별도 tracking row가 쌓여 모델 평가용 백데이터로 사용됩니다.",
"actionGroupExcludeLabel": "그룹 제외",
"actionGroupExcludeDesc": "선택한 후보를 현재 어구 그룹에서만 기간 동안 제외합니다. 다른 어구 그룹의 후보군에는 영향을 주지 않습니다.",
"actionGlobalExcludeLabel": "전체 제외",
"actionGlobalExcludeDesc": "선택한 MMSI를 모든 어구 그룹의 후보군에서 기간 동안 제외합니다. 패턴 기반 이름이 아니어서 선박으로 오분류된 AIS를 제거할 때 사용합니다.",
"actionHoverLabel": "호버 비교",
"actionHoverDesc": "후보 카드에 마우스를 올리면 리플레이에서 해당 후보 선박의 전체 항적과 현재 움직임이 강하게 강조되어, 어구 폴리곤 중심 이동과 시각적으로 비교할 수 있습니다."
}
},
"auth": { "auth": {
"title": "KCG 모니터링 대시보드", "title": "KCG 모니터링 대시보드",
"subtitle": "해양 상황 인식 시스템", "subtitle": "해양 상황 인식 시스템",