tranth3truong's picture
Deploy public Scribe-only CarePath Space
cc678b9
Raw
History Blame Contribute Delete
18.5 kB
export type Language = "vi" | "en";
const languageStorageKey = "carepath-demo-language";
export const copy = {
vi: {
title: "CarePath | Phiên dịch khám bệnh trực tiếp",
breadcrumb: "Đường dẫn sản phẩm",
status: "Bản mô phỏng tương tác",
allProducts: "Tất cả chức năng",
language: "Ngôn ngữ thanh sản phẩm",
productName: "Phiên dịch khám bệnh trực tiếp",
consent: {
eyebrow: "Phiên dịch khám bệnh trực tiếp",
heading: "Phiên dịch khám bệnh trực tiếp",
description: "Dịch hai chiều giữa bác sĩ tiếng Việt và bệnh nhân tiếng Anh trong lúc khám.",
steps: "Cách phiên dịch diễn ra",
doctorSpeaks: "Bác sĩ nói tiếng Việt",
aiToPatient: "AI dịch sang tiếng Anh cho bệnh nhân",
patientSpeaks: "Bệnh nhân trả lời bằng tiếng Anh",
aiToDoctor: "AI dịch lại sang tiếng Việt cho bác sĩ",
limitation: "CarePath chỉ hỗ trợ phiên dịch, không đưa ra chẩn đoán hoặc tư vấn điều trị.",
acknowledgements: "Xác nhận trước khi bắt đầu",
aiDisclosure:
"Tôi đã được giải thích rằng bản dịch do AI tạo ra có thể có lỗi và cần được bác sĩ kiểm tra trước khi sử dụng.",
interpreterRight:
"Tôi đã được giải thích rằng có thể yêu cầu phiên dịch viên trực tiếp bất cứ lúc nào.",
start: "Bắt đầu phiên dịch",
starting: "Đang bắt đầu…",
retry: "Thử lại để bắt đầu phiên dịch",
startError: "Không thể bắt đầu phiên dịch. Vui lòng kiểm tra kết nối máy chủ và thử lại.",
startHint: "Đánh dấu cả hai xác nhận để bắt đầu.",
startReadyHint: "Đã đủ xác nhận. Bạn có thể bắt đầu phiên dịch.",
},
deviceCheck: {
title: "Kiểm tra micrô trước khi bắt đầu",
body: "Kiểm tra micrô để dùng chế độ nói, hoặc tiếp tục bằng văn bản.",
microphone: "Micrô",
test: "Kiểm tra micrô",
retry: "Thử lại",
idle: "Chưa kiểm tra micrô.",
ready: "Micrô đã sẵn sàng.",
level: "Mức âm thanh",
scaleLow: "Nhỏ",
scaleHigh: "To",
continueVoice: "Tiếp tục bằng micrô",
continueTyped: "Tiếp tục bằng văn bản",
unavailable: "Không tìm thấy micrô. Bạn có thể thử lại hoặc tiếp tục bằng văn bản.",
denied: "Không thể dùng micrô. Hãy cấp quyền rồi thử lại, hoặc tiếp tục bằng văn bản.",
},
workspace: {
title: "Phiên dịch khám bệnh trực tiếp",
mockDisclaimer: "Bản mô phỏng này không dùng cho chăm sóc lâm sàng thực tế.",
requestInterpreter: "Yêu cầu phiên dịch viên trực tiếp",
escalationTitle: "Đã yêu cầu phiên dịch viên trực tiếp",
escalationBody: "Tạm dừng phát bản dịch AI và kết nối phiên dịch viên đủ điều kiện trước khi tiếp tục.",
controls: "Điều khiển nói",
holdToTalk: "Nhấn giữ để nói",
doctor: "Bác sĩ",
patient: "Bệnh nhân",
vietnamese: "Tiếng Việt",
english: "Tiếng Anh",
speaker: "Người nói",
regionInactiveHint: "Chọn khu vực này để nói hoặc nhập cho người này.",
typedFallback: "Nhập văn bản thay thế",
typedPlaceholder: "Nhập nội dung cần dịch",
send: "Gửi",
connecting: "Đang kết nối",
connected: "Đã kết nối",
disconnected: "Đã ngắt kết nối",
inputReady: "Sẵn sàng",
inputProcessing: "Đang xử lý",
inputDelivered: "Đã chuyển bản dịch",
inputReviewRequired: "Cần bác sĩ xác nhận",
recording: "Đang ghi lời nói của {speaker}",
connectionNotReady: "Kết nối chưa sẵn sàng.",
connectionNotReadyType: "Kết nối chưa sẵn sàng. Hãy nhập văn bản thay thế.",
microphoneUnavailable: "Không thể dùng micrô. Hãy nhập văn bản thay thế.",
microphoneDenied: "Micrô chưa được cấp quyền. Hãy nhập văn bản thay thế.",
lowConfidence: "Độ tin cậy thấp. Hãy nói lại hoặc nhập văn bản.",
repeatTurn: "Nói lại",
typeTurn: "Nhập văn bản",
confirmationRequired: "Cần bác sĩ xác nhận trước khi phát cho bệnh nhân.",
confirmFailed: "Không thể xác nhận lượt dịch.",
escalationFailed: "Không thể đánh dấu đã yêu cầu phiên dịch viên.",
playbackSuppressed: "Đã tạm dừng phát tự động. Chỉ tiếp tục sau khi bác sĩ xác nhận phát cục bộ.",
resumePlayback: "Tiếp tục phát tự động trên thiết bị này",
turnError: "Lượt dịch gặp lỗi. Hãy thử lại hoặc nhập văn bản.",
pipelineFailureTitle: "Lượt dịch đã được chặn vì xử lý thất bại",
sourceUnavailable: "Chưa thể tạo văn bản nguồn từ âm thanh.",
translationUnavailable: "Chưa có bản dịch để phát cho người bệnh.",
pipelineFailureAction: "Kiểm tra nội dung nguồn nếu có, thử lại hoặc yêu cầu phiên dịch viên trực tiếp.",
lifecycle: "Kết thúc phiên",
endSession: "Kết thúc phiên",
withdrawConsent: "Rút lại xác nhận",
deleteSession: "Xóa dữ liệu phiên",
deleteConfirm: "Xóa toàn bộ dữ liệu của phiên này?",
lifecycleFailed: "Không thể hoàn tất thao tác. Phiên vẫn được giữ ở trạng thái an toàn.",
retry: "Thử lại",
confirmations: "Xác nhận của bác sĩ",
confirmationRequiredLabel: "Cần bác sĩ xác nhận",
interpreterRecommended: "Khuyến nghị phiên dịch viên trực tiếp",
readback: "Đọc lại để xác nhận",
entity: "Thông tin",
source: "Bản gốc",
translation: "Bản dịch",
flags: "Lưu ý",
editTranslation: "Sửa bản dịch",
confirm: "Xác nhận",
saveEdit: "Lưu chỉnh sửa",
escalate: "Yêu cầu phiên dịch viên",
transcript: "Nội dung trao đổi",
turns: "lượt",
noTurns: "Chưa có lượt trao đổi.",
sourceLanguage: "Ngôn ngữ gốc",
targetLanguage: "Ngôn ngữ dịch",
blocked: "Đã chặn, chờ bác sĩ xác nhận.",
patientSafeMask: "Nội dung đang chờ bác sĩ xem xét.",
openReview: "Mở bản xem xét",
reviewOpened: "Đã mở bản xem xét dành cho bác sĩ.",
draftTranslation: "Bản dịch nháp",
riskReason: "Lý do cần xem xét",
criticalEntities: "Thông tin cần kiểm tra",
confirmAndPlay: "Xác nhận và phát",
saveEditAndPlay: "Lưu chỉnh sửa và phát",
editRequired: "Bản dịch chỉnh sửa không được để trống.",
riskSpans: "Thông tin cần kiểm tra",
feedback: "Báo lỗi bản dịch",
feedbackSaved: "Đã lưu phản hồi.",
reason: "Lý do",
comment: "Ghi chú",
submitFeedback: "Gửi phản hồi",
risk: { low: "Thấp", medium: "Trung bình", high: "Cao", critical: "Nghiêm trọng", other: "Cần kiểm tra" },
status: { delivered: "Đã chuyển", awaiting_confirm: "Chờ xác nhận", confirmed: "Đã xác nhận", blocked: "Đã chặn", other: "Đang xử lý" },
feedbackReason: { wrong_term: "Sai thuật ngữ", wrong_meaning: "Sai nghĩa", missing: "Thiếu nội dung", other: "Khác" },
riskKind: { dose_number: "Liều lượng", dose: "Liều lượng", other: "Thông tin cần kiểm tra" },
},
demo: {
eyebrow: "Mô phỏng trước khi xác nhận",
heading: "Xem cách phiên dịch được xử lý",
start: "Xem mô phỏng",
next: "Xem tình huống tiếp theo",
restart: "Xem lại mô phỏng",
step: "Tình huống {current}/3",
normal: "Bản dịch được chuyển",
lowConfidence: "Độ tin cậy thấp",
blocked: "Đã chặn, chờ bác sĩ xác nhận",
normalSource: "Tôi bị đau đầu từ sáng nay.",
normalTranslation: "I have had a headache since this morning.",
lowSource: "Tôi uống một viên... hay nửa viên?",
lowTranslation: "I took one tablet... or half a tablet?",
blockedSource: "Uống 500 mg mỗi ngày.",
blockedTranslation: "Take 500 mg every day.",
},
intent: {
moment: "Trong buổi khám",
roleQuestion: "Hôm nay bạn là ai?",
doctor: "Bác sĩ",
clinicStaff: "Nhân viên phòng khám",
directionQuestion: "Bạn cần dịch theo chiều nào?",
viToEn: "Tiếng Việt → Tiếng Anh",
enToVi: "Tiếng Anh → Tiếng Việt",
continue: "Tiếp tục",
skip: "Bỏ qua và dùng lựa chọn đề xuất",
recommended: "Đề xuất",
},
stepper: {
label: "Tiến trình bắt đầu phiên dịch",
language: "Ngôn ngữ",
about: "Về bạn",
consent: "Xác nhận",
device: "Kiểm tra thiết bị",
start: "Bắt đầu",
complete: "Đã hoàn thành",
current: "Đang thực hiện",
upcoming: "Tiếp theo",
},
checklist: { title: "Danh sách an toàn phiên đầu", delivered: "Đã chuyển lượt đầu tiên", confirmed: "Đã hoàn tất xác nhận", escalation: "Đã xác định nút yêu cầu phiên dịch viên", dismiss: "Ẩn danh sách" },
},
en: {
title: "CarePath | Medical Interpreter",
breadcrumb: "Product breadcrumb",
status: "Interactive mock simulation",
allProducts: "All products",
language: "Product bar language",
productName: "Medical Interpreter",
consent: {
eyebrow: "Medical Interpreter",
heading: "Live medical interpretation",
description: "Two-way interpretation between a Vietnamese-speaking clinician and an English-speaking patient during a visit.",
steps: "How interpretation works",
doctorSpeaks: "The clinician speaks Vietnamese",
aiToPatient: "AI translates to English for the patient",
patientSpeaks: "The patient replies in English",
aiToDoctor: "AI translates back to Vietnamese for the clinician",
limitation: "CarePath provides translation support only; it does not provide diagnoses or treatment advice.",
acknowledgements: "Confirm before starting",
aiDisclosure:
"I have been told that AI-generated translations can contain errors and must be reviewed by the clinician before use.",
interpreterRight:
"I have been told that a human interpreter can be requested at any time.",
start: "Start interpreting",
starting: "Starting…",
retry: "Try starting interpretation again",
startError: "Unable to start interpretation. Check the server connection and try again.",
startHint: "Check both confirmations to start.",
startReadyHint: "Both confirmations complete. You can start interpreting.",
},
deviceCheck: {
title: "Check the microphone before starting",
body: "Test a microphone for voice mode, or continue with typed turns.",
microphone: "Microphone",
test: "Test microphone",
retry: "Try again",
idle: "Microphone not tested yet.",
ready: "Microphone is ready.",
level: "Sound level",
scaleLow: "Quiet",
scaleHigh: "Loud",
continueVoice: "Continue with microphone",
continueTyped: "Continue with typed turns",
unavailable: "No microphone was found. Try again or continue with typed turns.",
denied: "The microphone is unavailable. Grant permission and try again, or continue with typed turns.",
},
workspace: {
title: "Live medical interpretation",
mockDisclaimer: "This simulation is not for real clinical care.",
requestInterpreter: "Request a human interpreter",
escalationTitle: "Human interpreter requested",
escalationBody: "Pause AI playback and connect a qualified interpreter before continuing.",
controls: "Speaking controls",
holdToTalk: "Hold to talk",
doctor: "Clinician",
patient: "Patient",
vietnamese: "Vietnamese",
english: "English",
speaker: "Speaker",
regionInactiveHint: "Select this area to speak or type for this person.",
typedFallback: "Typed fallback",
typedPlaceholder: "Type a turn to interpret",
send: "Send",
connecting: "Connecting",
connected: "Connected",
disconnected: "Disconnected",
inputReady: "Ready",
inputProcessing: "Processing",
inputDelivered: "Translation delivered",
inputReviewRequired: "Clinician review required",
recording: "Recording {speaker}",
connectionNotReady: "Connection is not ready.",
connectionNotReadyType: "Connection is not ready. Type the turn instead.",
microphoneUnavailable: "Microphone is unavailable. Type the turn instead.",
microphoneDenied: "Microphone permission denied. Type the turn instead.",
lowConfidence: "Low confidence. Please repeat or type the turn.",
repeatTurn: "Repeat",
typeTurn: "Type text",
confirmationRequired: "Clinician confirmation is required before patient playback.",
confirmFailed: "Could not confirm the turn.",
escalationFailed: "Could not mark the session escalated.",
playbackSuppressed: "Automatic playback is paused. Resume only after the clinician confirms local playback.",
resumePlayback: "Resume automatic playback on this device",
turnError: "The turn could not be processed. Please try again or type it.",
pipelineFailureTitle: "Turn blocked because processing failed",
sourceUnavailable: "No source text could be produced from the audio.",
translationUnavailable: "No translation is available for patient playback.",
pipelineFailureAction: "Check the source when available, retry, or request a human interpreter.",
lifecycle: "Session actions",
endSession: "End session",
withdrawConsent: "Withdraw consent",
deleteSession: "Delete session data",
deleteConfirm: "Delete all data for this session?",
lifecycleFailed: "The action could not be completed. The session remains safely stopped.",
retry: "Retry",
confirmations: "Clinician confirmation",
confirmationRequiredLabel: "Clinician confirmation required",
interpreterRecommended: "Human interpreter recommended",
readback: "Read-back",
entity: "Item",
source: "Source",
translation: "Translation",
flags: "Notes",
editTranslation: "Edit translation",
confirm: "Confirm",
saveEdit: "Save edit",
escalate: "Request interpreter",
transcript: "Conversation",
turns: "turns",
noTurns: "No turns yet.",
sourceLanguage: "Source language",
targetLanguage: "Translation language",
blocked: "Blocked pending clinician confirmation.",
patientSafeMask: "This content is awaiting clinician review.",
openReview: "Open review",
reviewOpened: "Clinician review opened.",
draftTranslation: "Draft translation",
riskReason: "Reason for review",
criticalEntities: "Critical information to check",
confirmAndPlay: "Confirm and play",
saveEditAndPlay: "Save edit and play",
editRequired: "An edited translation cannot be empty.",
riskSpans: "Items to check",
feedback: "Flag translation",
feedbackSaved: "Feedback saved.",
reason: "Reason",
comment: "Comment",
submitFeedback: "Submit feedback",
risk: { low: "Low", medium: "Medium", high: "High", critical: "Critical", other: "Needs review" },
status: { delivered: "Delivered", awaiting_confirm: "Awaiting confirmation", confirmed: "Confirmed", blocked: "Blocked", other: "Processing" },
feedbackReason: { wrong_term: "Wrong term", wrong_meaning: "Wrong meaning", missing: "Missing content", other: "Other" },
riskKind: { dose_number: "Dose", dose: "Dose", other: "Item to check" },
},
demo: {
eyebrow: "Pre-consent simulation",
heading: "See how interpretation is handled",
start: "View simulation",
next: "View next situation",
restart: "Replay simulation",
step: "Situation {current}/3",
normal: "Translation delivered",
lowConfidence: "Low confidence",
blocked: "Blocked pending clinician confirmation",
normalSource: "I have had a headache since this morning.",
normalTranslation: "Tôi bị đau đầu từ sáng nay.",
lowSource: "I took one tablet... or half a tablet?",
lowTranslation: "Tôi uống một viên... hay nửa viên?",
blockedSource: "Take 500 mg every day.",
blockedTranslation: "Uống 500 mg mỗi ngày.",
},
intent: {
moment: "During the visit",
roleQuestion: "Who are you today?",
doctor: "Clinician",
clinicStaff: "Clinic staff",
directionQuestion: "Which direction do you need?",
viToEn: "Vietnamese → English",
enToVi: "English → Vietnamese",
continue: "Continue",
skip: "Skip and use recommended choices",
recommended: "Recommended",
},
stepper: {
label: "Interpreter setup progress",
language: "Language",
about: "About you",
consent: "Confirmation",
device: "Device check",
start: "Start",
complete: "Complete",
current: "Current step",
upcoming: "Upcoming",
},
checklist: { title: "First-session safety checklist", delivered: "First turn delivered", confirmed: "Confirmation completed", escalation: "Human-interpreter control located", dismiss: "Dismiss checklist" },
},
} as const;
export function initialLanguage(): Language {
const value = new URLSearchParams(window.location.search).get("lang");
if (value !== null) {
return value === "en" || value === "vi" ? value : "vi";
}
return localStorage.getItem(languageStorageKey) === "en" ? "en" : "vi";
}
export function persistLanguage(language: Language) {
localStorage.setItem(languageStorageKey, language);
}