Implement multi-language support in user management and system management pages

- Integrated multi-language functionality across various user management components, including user list, roles list, and user authorization pages, enhancing accessibility for diverse users.
- Updated UI elements to utilize translation keys, ensuring that all text is dynamically translated based on user preferences.
- Improved error handling messages to be localized, providing a better user experience in case of issues.

These changes significantly enhance the usability and internationalization of the user management features, making the application more inclusive.
This commit is contained in:
kjs
2026-04-01 15:57:12 +09:00
parent 2ff01456dc
commit 1d49fc7ac7
15 changed files with 812 additions and 200 deletions

View File

@@ -22,6 +22,7 @@ interface CompanyFormModalProps {
onSave: () => Promise<boolean>;
onFormChange: (field: keyof CompanyFormData, value: string) => void;
onClearError: () => void;
t?: (key: string, params?: Record<string, string | number>) => string;
}
/**
@@ -35,7 +36,32 @@ export function CompanyFormModal({
onSave,
onFormChange,
onClearError,
t,
}: CompanyFormModalProps) {
const _t = t || ((key: string) => {
const defaults: Record<string, string> = {
"company.form.titleCreate": "새 회사 등록",
"company.form.titleEdit": "회사 정보 수정",
"company.form.companyName": "회사명",
"company.form.companyNamePlaceholder": "회사명을 입력하세요",
"company.form.businessNumber": "사업자등록번호",
"company.form.businessNumberHint": "10자리 숫자 (자동 하이픈 추가)",
"company.form.representativeName": "대표자명",
"company.form.representativeNamePlaceholder": "대표자명을 입력하세요",
"company.form.representativePhone": "대표 연락처",
"company.form.email": "이메일",
"company.form.website": "웹사이트",
"company.form.address": "회사 주소",
"company.form.addressPlaceholder": "서울특별시 강남구...",
"company.form.companyCodeLabel": "회사 코드:",
"company.form.writerLabel": "등록자:",
"company.form.regdateLabel": "등록일:",
"company.form.cancel": "취소",
"company.form.save": "등록",
"company.form.update": "수정",
};
return defaults[key] || key;
});
const [isSaving, setIsSaving] = useState(false);
const [businessNumberError, setBusinessNumberError] = useState<string>("");
@@ -125,20 +151,20 @@ export function CompanyFormModal({
userId={modalState.companyCode}
>
<DialogHeader>
<DialogTitle>{isEditMode ? "회사 정보 수정" : "새 회사 등록"}</DialogTitle>
<DialogTitle>{isEditMode ? _t("company.form.titleEdit") : _t("company.form.titleCreate")}</DialogTitle>
</DialogHeader>
<div className="space-y-4 py-4">
{/* 회사명 입력 (필수) */}
<div className="space-y-2">
<Label htmlFor="company_name">
<span className="text-destructive">*</span>
{_t("company.form.companyName")} <span className="text-destructive">*</span>
</Label>
<Input
id="company_name"
value={formData.company_name}
onChange={(e) => onFormChange("company_name", e.target.value)}
placeholder="회사명을 입력하세요"
placeholder={_t("company.form.companyNamePlaceholder")}
disabled={isLoading || isSaving}
className={error ? "border-destructive" : ""}
autoFocus
@@ -148,7 +174,7 @@ export function CompanyFormModal({
{/* 사업자등록번호 입력 (필수) */}
<div className="space-y-2">
<Label htmlFor="business_registration_number">
<span className="text-destructive">*</span>
{_t("company.form.businessNumber")} <span className="text-destructive">*</span>
</Label>
<Input
id="business_registration_number"
@@ -162,25 +188,25 @@ export function CompanyFormModal({
{businessNumberError ? (
<p className="text-xs text-destructive">{businessNumberError}</p>
) : (
<p className="text-xs text-muted-foreground">10 ( )</p>
<p className="text-xs text-muted-foreground">{_t("company.form.businessNumberHint")}</p>
)}
</div>
{/* 대표자명 입력 */}
<div className="space-y-2">
<Label htmlFor="representative_name"></Label>
<Label htmlFor="representative_name">{_t("company.form.representativeName")}</Label>
<Input
id="representative_name"
value={formData.representative_name || ""}
onChange={(e) => onFormChange("representative_name", e.target.value)}
placeholder="대표자명을 입력하세요"
placeholder={_t("company.form.representativeNamePlaceholder")}
disabled={isLoading || isSaving}
/>
</div>
{/* 대표 연락처 입력 */}
<div className="space-y-2">
<Label htmlFor="representative_phone"> </Label>
<Label htmlFor="representative_phone">{_t("company.form.representativePhone")}</Label>
<Input
id="representative_phone"
value={formData.representative_phone || ""}
@@ -193,7 +219,7 @@ export function CompanyFormModal({
{/* 이메일 입력 */}
<div className="space-y-2">
<Label htmlFor="email"></Label>
<Label htmlFor="email">{_t("company.form.email")}</Label>
<Input
id="email"
value={formData.email || ""}
@@ -206,7 +232,7 @@ export function CompanyFormModal({
{/* 웹사이트 입력 */}
<div className="space-y-2">
<Label htmlFor="website"></Label>
<Label htmlFor="website">{_t("company.form.website")}</Label>
<Input
id="website"
value={formData.website || ""}
@@ -219,12 +245,12 @@ export function CompanyFormModal({
{/* 회사 주소 입력 */}
<div className="space-y-2">
<Label htmlFor="address"> </Label>
<Label htmlFor="address">{_t("company.form.address")}</Label>
<Input
id="address"
value={formData.address || ""}
onChange={(e) => onFormChange("address", e.target.value)}
placeholder="서울특별시 강남구..."
placeholder={_t("company.form.addressPlaceholder")}
disabled={isLoading || isSaving}
/>
</div>
@@ -241,13 +267,13 @@ export function CompanyFormModal({
<div className="bg-muted/50 rounded-md p-3">
<div className="space-y-1 text-sm">
<p>
<span className="font-medium"> :</span> {modalState.selectedCompany.company_code}
<span className="font-medium">{_t("company.form.companyCodeLabel")}</span> {modalState.selectedCompany.company_code}
</p>
<p>
<span className="font-medium">:</span> {modalState.selectedCompany.writer}
<span className="font-medium">{_t("company.form.writerLabel")}</span> {modalState.selectedCompany.writer}
</p>
<p>
<span className="font-medium">:</span>{" "}
<span className="font-medium">{_t("company.form.regdateLabel")}</span>{" "}
{new Date(modalState.selectedCompany.regdate).toLocaleDateString("ko-KR")}
</p>
</div>
@@ -257,7 +283,7 @@ export function CompanyFormModal({
<DialogFooter>
<Button variant="outline" onClick={handleCancel} disabled={isLoading || isSaving}>
{_t("company.form.cancel")}
</Button>
<Button
onClick={handleSave}
@@ -271,7 +297,7 @@ export function CompanyFormModal({
className="min-w-[80px]"
>
{(isLoading || isSaving) && <LoadingSpinner className="mr-2 h-4 w-4" />}
{isEditMode ? "수정" : "등록"}
{isEditMode ? _t("company.form.update") : _t("company.form.save")}
</Button>
</DialogFooter>
</DialogContent>