Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
076e9e4
feat: 타이머 오버뷰에서 토론자 순번 번역 추가
useon Mar 3, 2026
95e3234
feat: 헤더의 테이블정보와 타이틀 번역 추가
useon Mar 3, 2026
e1d6cf3
refactor: 토론 정보 수정시 언어에 따른 기본 value 번역되도록 수정
useon Mar 3, 2026
a59ed25
fix: 직접입력의 키가 불일치하여 번역이 적용되지 않는 문제 해결
useon Mar 3, 2026
dcdf38c
refactor: 찬성, 반대, 중립을 선택하는 드롭박스가 번역되도록 사용처에 번역 작업 추가
useon Mar 3, 2026
348e76e
refactor: 헤더 컴포넌트 내부에서 번역 작업하던 구조를 사용처에서 하도록 개선
useon Mar 3, 2026
efc49e9
refactor: 팀 이름 키가 있는 경우 번역되도록 번역 작업 추가
useon Mar 3, 2026
3fd8dbe
refactor: 기본 입력으로 생성된 각각의 타이머 경우에도 팀명이 번역되도록 번역 작업 추가
useon Mar 3, 2026
d4a6eea
refactor: Schedule -> Timetable로 수정
useon Mar 3, 2026
20a0764
refactor: 팀 이름 검증 규칙 번역키, 밸류 수정
useon Mar 3, 2026
6a1f84f
refactor: 팀 이름 15자 이내로 변경
useon Mar 3, 2026
0fb87b1
refactor: 번역 오류 수정 및 대소문자 수정
useon Mar 3, 2026
9e1b6c0
refactor: 분과 초를 함께 쓰는 경우 기호 버전으로 min -> m 사용하도록 수정
useon Mar 3, 2026
4558e29
refactor: 이전차례, 다음차례 번역 수정
useon Mar 3, 2026
537c87a
refactor: 기본 템플릿에 설정된 발언 유형 번역 추가
useon Mar 10, 2026
19c4bfe
refactor: 1회당 발언 시간, 팀당 발언 시간 번역 수정
useon Mar 10, 2026
d4bd5d3
refactor: 좌측 영역의 정보의 길이 때문에 레이아웃이 바뀌지 않도록 수정
useon Mar 10, 2026
6f3b798
refactor: 새로운 템플릿 신청 관련 번역 수정
useon Mar 10, 2026
306c803
refactor: 동사형으로 들어가야 하는 번역 수정
useon Mar 10, 2026
0abcd94
refactor: 사용하지 않는 prop 삭제
useon Mar 10, 2026
765a7ac
refactor: 번역 수정
useon Mar 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 40 additions & 36 deletions public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@
"공유받은 데이터 처리에 실패했어요.": "Failed to process the shared data.",
"팀 선정하기": "Select teams",
"토론하기": "Start debate",
"토론 시간표를 선택해주세요": "Please select a debate schedule",
"토론 시간표를 선택해주세요": "Please select a debate timetable",
"테이블 모드가 올바르지 않습니다.": "Invalid table mode.",
"시간표 1": "Schedule 1",
"시간표 1": "Timetable 1",
"찬성": "Affirmative",
"반대": "Negative",
"시간표 정보를 불러오지 못했어요.\n다시 시도할까요?": "Couldn't load the schedule.\nTry again?",
"시간표 정보를 불러오지 못했어요.\n다시 시도할까요?": "Couldn't load the timetable.\nTry again?",
"무승부": "Tie",
"유효하지 않은 투표 결과 링크입니다.": "Invalid vote result link.",
"세부 결과 확인하기": "View detailed results",
Expand All @@ -52,8 +52,8 @@
"링크가 클립보드에 복사됨": "Link copied to clipboard",
"링크 준비 중": "Preparing link",
"공유 링크 복사": "Copy share link",
"이전 차례": "Previous turn",
"다음 차례": "Next turn",
"이전 차례": "Previous",
"다음 차례": "Next",
"토론 종료": "End debate",
"알림 개수_one": "{{displayCount}} notification",
"알림 개수_other": "{{displayCount}} notifications",
Expand Down Expand Up @@ -81,7 +81,7 @@
"팀": "Team",
"토론자": "Debater",
"작전 시간 사용": "Use Prep Time",
"토론을 끝내셨군요!\n지금까지의 시간표를 로그인하고 저장할까요?": "You've finished the debate!\nLog in to save your schedule so far?",
"토론을 끝내셨군요!\n지금까지의 시간표를 로그인하고 저장할까요?": "You've finished the debate!\nLog in to save your timetable so far?",
"자유토론 타이머 조작": "Open Debate Timer Controls",
"재생 버튼을 눌러 타이머를 시작": "Press Play to start the timer",
"타이머가 동작 중일 때, 일시정지 버튼을 눌러 타이머를 일시정지": "When the timer is running, press Pause to pause it",
Expand All @@ -108,7 +108,7 @@
"+5분": "+5 min",
"비회원 상태로 토론하기": "Debate as guest",
"저장하기": "Save",
"공유받은 토론 시간표를 내 시간표 목록에 저장하시겠어요?": "Save the shared debate schedule to my schedules?",
"공유받은 토론 시간표를 내 시간표 목록에 저장하시겠어요?": "Save the shared debate timetable to my timetables?",
"수정하기": "Edit",
"삭제하기": "Delete",
"공유하기": "Share",
Expand All @@ -121,10 +121,10 @@
"토론자가 작전 시간을\n요청하면 <0/>\n버튼을 눌러 시간을 사용해요": "If a debater requests Prep Time\npress <0/>\nto use time",
"작전 시간이 나타나면\n원하는 시간을 입력하세요!": "When Prep Time appears,\nenter the time you want!",
"키보드 방향키로\n더 편리한 조작": "More convenient control\nwith arrow keys",
"시간표 설정화면": "Schedule setup screen",
"간편한 시간표 구성": "Simple schedule setup",
"시간표 추가": "Add schedule",
"시간표 추가 버튼": "Add schedule button",
"시간표 설정화면": "Timetable setup screen",
"간편한 시간표 구성": "Simple timetable setup",
"시간표 추가": "Add timetable",
"시간표 추가 버튼": "Add timetable button",
"두가지 타이머": "Two timers",
"일반형과 자유토론형 타이머로\n다양한 토론 방식을 지원해요.": "Support various debate formats\nwith Standard and Open Debate timers.",
"종소리 설정": "Bell settings",
Expand All @@ -133,15 +133,15 @@
"{{title}} 로고": "{{title}} logo",
"{{label}} 토론하기": "Debate {{label}}",
"템플릿 신청하기": "Request a template",
"새로운 템플릿도 신청해 볼까요?": "Want to request a new template too?",
"새로운 템플릿도 신청해 볼까요?": "Would you like to apply for a new template?",
"신청하기": "Apply",
"홈 | 설정": "Home | Settings",
"토론 정보\n관리 및 기록": "Debate info\nManagement and records",
"토론 기본 정보 설정": "Set debate basics",
"시간표 이름부터 주제까지!": "From schedule name to Topic!",
"시간표 목록": "Schedule list",
"내가 만든 시간표를 저장하고 싶나요?": "Want to save the schedules you made?",
"시간표를 저장하려면,\n디베이트 타이머에 로그인해 보세요!": "To save your schedule,\nplease log in to Debate Timer!",
"시간표 이름부터 주제까지!": "From timetable name to topic!",
"시간표 목록": "Timetable list",
"내가 만든 시간표를 저장하고 싶나요?": "Want to save the timetables you made?",
"시간표를 저장하려면,\n디베이트 타이머에 로그인해 보세요!": "To save your timetable,\nplease log in to Debate Timer!",
"3초 로그인 하기": "3-second login",
"아래로 스크롤": "Scroll down",
"이미 많은 사람들이 디베이트 타이머로\n더 나은 토론환경을 만들고 있어요.": "Many people already use Debate Timer\nto create a better debate environment.",
Expand All @@ -161,11 +161,11 @@
"투표 세부 결과": "Detailed vote results",
"명_one": " person",
"명_other": " people",
"시간표로 돌아가기": "Back to schedule",
"시간표로 돌아가기": "Back to timetable",
"비회원 모드": "Guest mode",
"홈으로 이동": "Go to Home",
"로그인": "Log in",
"비회원으로 사용하던 시간표가 있습니다.\n로그인 후에도 이 시간표를 계속 사용하시겠습니까?": "You have schedules created in guest mode.\nDo you want to keep using them after you log in?",
"비회원으로 사용하던 시간표가 있습니다.\n로그인 후에도 이 시간표를 계속 사용하시겠습니까?": "You have timetables created in guest mode.\nDo you want to keep using them after you log in?",
"언어 선택": "Select language",
"팀별로\n동전의 앞 / 뒷면 중\n하나를 선택해 주세요.": "For each team,\nchoose heads or tails\non the coin.",
"동전": "Coin",
Expand All @@ -181,27 +181,29 @@
"작전시간": "Prep Time",
"교차조사": "Cross Fire",
"직접입력": "Custom",
"1번": "No.1",
"2번": "No.2",
"3번": "No.3",
"발언 시간은 1초 이상이어야 해요.": "Speaking Time must be at least 1 second.",
"종료 전 타종은 발언 시간보다 길 수 없어요.": "The bell before the end cannot be longer than the Speaking Time.",
"팀당 발언 시간은 1초 이상이어야 해요.": "Speaking Time per team must be at least 1 second.",
"1회당 발언 시간은 팀당 발언 시간을 초과할 수 없어요.": "Speaking Time per turn cannot exceed the team's total Speaking Time.",
"팀당 발언 시간은 1초 이상이어야 해요.": "Team time must be at least 1 second.",
"1회당 발언 시간은 팀당 발언 시간을 초과할 수 없어요.": "Turn time cannot exceed team time.",
"발언 유형은 최대 10자까지 입력할 수 있습니다.": "Speech Type can be up to 10 characters.",
"발언자는 최대 5자까지 입력할 수 있습니다.": "Speaker can be up to 5 characters.",
"1회당 발언 시간은 팀당 총 발언 시간보다 클 수 없습니다.": "Per-turn Speaking Time cannot exceed the total team Speaking Time.",
"발언 유형을 입력해주세요.": "Please enter a Speech Type.",
"자유토론": "Open Debate",
"중립은 발언 유형이 '직접 입력'일 경우에만 선택할 수 있습니다.": "Neutral can only be selected when Speech Type is 'Custom'.",
"중립은 발언 유형이 '직접입력'일 경우에만 선택할 수 있습니다.": "Neutral can only be selected when Speech Type is 'Custom'.",
"중립": "Neutral",
"일반 타이머": "Standard timer",
"자유토론 타이머": "Open Debate timer",
"한 팀의 발언 시간이 세팅된 일반적인 타이머": "A standard timer with a single team's Speaking Time set",
"팀별 발언 시간과 1회당 발언 시간이 세팅된 타이머\n1회당 발언 시간이 지나면, 상대 팀으로 발언권이 넘어감": "A timer with team time and per-turn time set\nWhen a per-turn time ends, the turn passes to the other team",
"한 팀의 발언 시간이 세팅된 일반적인 타이머": "A standard timer with team time set",
"팀별 발언 시간과 1회당 발언 시간이 세팅된 타이머\n1회당 발언 시간이 지나면, 상대 팀으로 발언권이 넘어감": "A timer with team time and turn time.\nWhen the turn time ends, the turn passes to the other team.",
"종류": "Type",
"발언자": "Speaker",
"N번 토론자": "Speaker N",
"발언 시간": "Speaking Time",
"1회당\n발언 시간": "Per-turn\nSpeaking Time",
"팀당\n발언 시간": "Per-team\nSpeaking Time",
"1회당\n발언 시간": "Turn Time",
"팀당\n발언 시간": "Team Time",
"발언 유형": "Speech Type",
"주도권 토론 등": "e.g. Lead debate",
"입론, 반론, 작전 시간 등": "e.g. Constructive, Rebuttal, Prep Time",
Expand All @@ -219,19 +221,19 @@
"추가하기": "Add",
"복사하기": "Copy",
"이 타이머를 삭제하시겠습니까?": "Delete this timer?",
"{{minutes}}분 {{seconds}}초": "{{minutes}} min {{seconds}} sec",
"팀당 {{minutes}}분 {{seconds}}초": "{{minutes}} min {{seconds}} sec per team",
"발언당 {{minutes}}분 {{seconds}}초": "{{minutes}} min {{seconds}} sec per speech",
"{{minutes}}분 {{seconds}}초": "{{minutes}}m {{seconds}}s",
"팀당 {{minutes}}분 {{seconds}}초": "{{minutes}}m {{seconds}}s per team",
"발언당 {{minutes}}분 {{seconds}}초": "{{minutes}}m {{seconds}}s per speech",
"위/아래로 드래그": "Drag up/down",
" | {{speaker}} 토론자": " | {{speaker}} Debater",
"토론 정보를 {{val0}}해주세요": "Please {{val0}} the debate info",
"수정": "Edit",
"설정": "Settings",
"토론 시간표 이름": "Debate schedule name",
"토론 주제": "Debate Topic",
"토론 주제를 입력해주세요": "Please enter a debate Topic",
"수정": "edit",
"설정": "configure",
"토론 시간표 이름": "Debate timetable name",
"토론 주제": "Debate topic",
"토론 주제를 입력해주세요": "Please enter a debate topic",
"팀명": "Team name",
"팀명은 최대 8자까지 입력할 수 있습니다.": "Team name can be up to 8 characters.",
"팀명은 최대 15자까지 입력할 수 있습니다.": "Team name can be up to 15 characters.",
"다음": "Next",
"볼륨 조절": "Volume control",
"투표 종료에 실패했습니다.": "Failed to end the vote.",
Expand All @@ -248,5 +250,7 @@
"500 내부 서버 오류": "500 Internal Server Error",
"502 게이트웨이 불량": "502 Bad Gateway",
"503 서비스가 일시적으로 중단됨": "503 Service Unavailable",
"504 게이트웨이 시간 초과": "504 Gateway Timeout"
"504 게이트웨이 시간 초과": "504 Gateway Timeout",
"나의 토론 주제": "My Debate Topic",
"나의 시간표": "My Timetable"
}
14 changes: 9 additions & 5 deletions public/locales/ko/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"이전 차례": "이전 차례",
"다음 차례": "다음 차례",
"토론 종료": "토론 종료",
"알림 개수_one": "알림 {{displayCount}}개",
"알림 개수_one": "알림 {{displayCount}}개",
"알림 개수_other": "알림 {{displayCount}}개",
"{{team}} 팀": "{{team}} 팀",
"데이터를 불러오고 있습니다...": "데이터를 불러오고 있습니다...",
Expand Down Expand Up @@ -182,16 +182,18 @@
"작전시간": "작전시간",
"교차조사": "교차조사",
"직접입력": "직접입력",
"1번": "1번",
"2번": "2번",
"3번": "3번",
"발언 시간은 1초 이상이어야 해요.": "발언 시간은 1초 이상이어야 해요.",
"종료 전 타종은 발언 시간보다 길 수 없어요.": "종료 전 타종은 발언 시간보다 길 수 없어요.",
"팀당 발언 시간은 1초 이상이어야 해요.": "팀당 발언 시간은 1초 이상이어야 해요.",
"1회당 발언 시간은 팀당 발언 시간을 초과할 수 없어요.": "1회당 발언 시간은 팀당 발언 시간을 초과할 수 없어요.",
"발언 유형은 최대 10자까지 입력할 수 있습니다.": "발언 유형은 최대 10자까지 입력할 수 있습니다.",
"발언자는 최대 5자까지 입력할 수 있습니다.": "발언자는 최대 5자까지 입력할 수 있습니다.",
"1회당 발언 시간은 팀당 총 발언 시간보다 클 수 없습니다.": "1회당 발언 시간은 팀당 총 발언 시간보다 클 수 없습니다.",
"발언 유형을 입력해주세요.": "발언 유형을 입력해주세요.",
"자유토론": "자유토론",
"중립은 발언 유형이 '직접 입력'일 경우에만 선택할 수 있습니다.": "중립은 발언 유형이 '직접 입력'일 경우에만 선택할 수 있습니다.",
"중립은 발언 유형이 '직접입력'일 경우에만 선택할 수 있습니다.": "중립은 발언 유형이 '직접입력'일 경우에만 선택할 수 있습니다.",
"일반 타이머": "일반 타이머",
"자유토론 타이머": "자유토론 타이머",
"한 팀의 발언 시간이 세팅된 일반적인 타이머": "한 팀의 발언 시간이 세팅된 일반적인 타이머",
Expand Down Expand Up @@ -231,7 +233,7 @@
"토론 주제": "토론 주제",
"토론 주제를 입력해주세요": "토론 주제를 입력해주세요",
"팀명": "팀명",
"팀명은 최대 8자까지 입력할 수 있습니다.": "팀명은 최대 8자까지 입력할 수 있습니다.",
"팀명은 최대 15자까지 입력할 수 있습니다.": "팀명은 최대 15자까지 입력할 수 있습니다.",
"다음": "다음",
"볼륨 조절": "볼륨 조절",
"투표 종료에 실패했습니다.": "투표 종료에 실패했습니다.",
Expand All @@ -248,5 +250,7 @@
"500 내부 서버 오류": "500 내부 서버 오류",
"502 게이트웨이 불량": "502 게이트웨이 불량",
"503 서비스가 일시적으로 중단됨": "503 서비스가 일시적으로 중단됨",
"504 게이트웨이 시간 초과": "504 게이트웨이 시간 초과"
"504 게이트웨이 시간 초과": "504 게이트웨이 시간 초과",
"나의 토론 주제": "나의 토론 주제",
"나의 시간표": "나의 시간표"
}
5 changes: 1 addition & 4 deletions src/components/HeaderTableInfo/HeaderTableInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { useTranslation } from 'react-i18next';
import Skeleton from '../Skeleton/Skeleton';

interface HeaderTitleProps {
Expand All @@ -7,9 +6,7 @@ interface HeaderTitleProps {
}

export default function HeaderTableInfo(props: HeaderTitleProps) {
const { t } = useTranslation();
const { name, skeletonEnabled: isLoading = false } = props;
const displayName = !name?.trim() ? t('테이블 이름 없음') : name.trim();

return (
<>
Expand All @@ -21,7 +18,7 @@ export default function HeaderTableInfo(props: HeaderTitleProps) {
)}
{!isLoading && (
<div className="flex flex-col space-y-[4px]">
<h1 className="text-2xl">{displayName}</h1>
<h1 className="text-2xl">{name}</h1>
</div>
)}
</>
Expand Down
5 changes: 1 addition & 4 deletions src/components/HeaderTitle/HeaderTitle.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { useTranslation } from 'react-i18next';
import Skeleton from '../Skeleton/Skeleton';

interface HeaderTitleProps {
Expand All @@ -7,9 +6,7 @@ interface HeaderTitleProps {
}

export default function HeaderTitle(props: HeaderTitleProps) {
const { t } = useTranslation();
const { title, skeletonEnabled: isLoading = false } = props;
const displayTitle = !title?.trim() ? t('주제 없음') : title.trim();

return (
<>
Expand All @@ -20,7 +17,7 @@ export default function HeaderTitle(props: HeaderTitleProps) {
)}
{!isLoading && (
<h1 className="w-full max-w-[50vw] overflow-hidden text-ellipsis whitespace-nowrap text-3xl">
{displayTitle}
{title}
</h1>
)}
</>
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useFullscreen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export default function useFullscreen() {
}
}, [isFullscreen]);

// 값을 직접 입력하는 함수
// 값을 직접입력하는 함수
const setFullscreen = useCallback(async (value: boolean) => {
const element = document.documentElement as HTMLElementWithFullscreen;
const isCurrentlyFullscreen = !!getFullscreenElement();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export default function TableNameAndType(props: TableNameAndTypeProps) {
{t('토론 시간표 이름')}
</label>
<ClearableInput
value={info.name}
value={t(info.name)}
onChange={(e) => handleFieldChange('name', e.target.value)}
onClear={() => clearField('name')}
placeholder={t('시간표 1')}
Expand All @@ -77,7 +77,7 @@ export default function TableNameAndType(props: TableNameAndTypeProps) {
{t('토론 주제')}
</label>
<ClearableInput
value={info.agenda}
value={t(info.agenda)}
onChange={(e) => handleFieldChange('agenda', e.target.value)}
onClear={() => clearField('agenda')}
placeholder={t('토론 주제를 입력해주세요')}
Expand All @@ -90,29 +90,29 @@ export default function TableNameAndType(props: TableNameAndTypeProps) {
</label>
<div className="flex items-center gap-8">
<ClearableInput
value={info.prosTeamName || ''}
value={t(info.prosTeamName) || ''}
onChange={(e) =>
onInfoChange({
...info,
prosTeamName: e.target.value,
})
}
onClear={() => clearTeamNameField('prosTeamName')}
placeholder={StanceToString['PROS']}
placeholder={t(StanceToString['PROS'])}
disabled={isLoading}
/>

<span>vs.</span>
<ClearableInput
value={info.consTeamName || ''}
value={t(info.consTeamName) || ''}
onChange={(e) =>
onInfoChange({
...info,
consTeamName: e.target.value,
})
}
onClear={() => clearTeamNameField('consTeamName')}
placeholder={StanceToString['CONS']}
placeholder={t(StanceToString['CONS'])}
disabled={isLoading}
/>
</div>
Expand All @@ -128,10 +128,10 @@ export default function TableNameAndType(props: TableNameAndTypeProps) {
const pros = info.prosTeamName || '';
const cons = info.consTeamName || '';

const isTooLong = pros.length > 8 || cons.length > 8;
const isTooLong = pros.length > 15 || cons.length > 15;

if (isTooLong) {
alert(t('팀명은 최대 8자까지 입력할 수 있습니다.'));
alert(t('팀명은 최대 15자까지 입력할 수 있습니다.'));
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/page/TableComposition/components/TimeBox/TimeBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ export default function TimeBox(props: TimeBoxProps) {
{getSpeechTypeLabel(speechType)}
{speaker && (
<span className="font-medium">
{t(' | {{speaker}} 토론자', { speaker })}
{t(' | {{speaker}} 토론자', { speaker: t(speaker) })}
</span>
)}
</p>
Expand Down
Loading
Loading