feat: 다국어 지원 (프랑스, 독일) 및 항해 화면 크루 포함

This commit is contained in:
2026-02-16 23:21:31 +09:00
parent 2ec2ba4b3a
commit f008af0d9b
11 changed files with 773 additions and 48 deletions

View File

@@ -3,6 +3,24 @@
import { FormEvent, useState } from 'react';
import { useI18n } from '@/features/i18n/model/useI18n';
const OPTIONAL_PREFIX_PATTERN = /^(?:선택|optional|任意|facultatif)\s*[:]\s*/i;
const EXAMPLE_PREFIX_PATTERN =
/^(?:예|例|e\.?\s?g\.?|eg\.?|example|exemple|beispiel|p\.?\s?ex\.?|z\.?\s?b\.?)\s*[:)\.]\s*/i;
const buildMissionPlaceholder = (raw: string, optionalLabel: string) => {
const sanitized = raw
.trim()
.replace(OPTIONAL_PREFIX_PATTERN, '')
.replace(EXAMPLE_PREFIX_PATTERN, '')
.trim();
if (!sanitized) return '';
const normalizedOptionalLabel = optionalLabel.trim();
if (!normalizedOptionalLabel) return sanitized;
return `${sanitized} (${normalizedOptionalLabel})`;
};
export function BoardingMissionForm({
onDock,
onCancel,
@@ -17,11 +35,13 @@ export function BoardingMissionForm({
const { t } = useI18n();
const [mission, setMission] = useState('');
const trimmedMission = mission.trim();
const canSubmit = Boolean(trimmedMission);
const missionPlaceholder = buildMissionPlaceholder(
t('boarding.missionPlaceholder'),
t('boarding.optionalLabel'),
);
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
if (!canSubmit) return;
onDock(trimmedMission);
};
@@ -38,7 +58,7 @@ export function BoardingMissionForm({
type="text"
value={mission}
onChange={(event) => setMission(event.target.value)}
placeholder={t('boarding.missionPlaceholder')}
placeholder={missionPlaceholder}
className="w-full border-b-2 border-slate-700 bg-slate-900/50 px-0 py-3 text-lg outline-none transition-colors placeholder:text-slate-600 focus:border-indigo-500"
autoFocus={autoFocus}
/>
@@ -56,8 +76,7 @@ export function BoardingMissionForm({
)}
<button
type="submit"
disabled={!canSubmit}
className={`rounded-xl bg-indigo-600 font-bold text-white transition-all shadow-lg shadow-indigo-900/30 hover:bg-indigo-500 disabled:bg-slate-800 disabled:text-slate-500 ${compact ? 'px-6 py-2' : 'w-full py-4 text-lg'}`}
className={`rounded-xl bg-indigo-600 font-bold text-white transition-all shadow-lg shadow-indigo-900/30 hover:bg-indigo-500 ${compact ? 'px-6 py-2' : 'w-full py-4 text-lg'}`}
>
{t('boarding.submit')}
</button>