Skip to content

Commit 1a0be6d

Browse files
committed
refactor: locale 유지 링크와 프로필 배지 문구 국제화 정리
1 parent a58aa40 commit 1a0be6d

5 files changed

Lines changed: 53 additions & 24 deletions

File tree

src/features/home/components/hero-section.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ import { useReducedMotion } from "@/shared/hooks/use-reduced-motion"
1616
import { LiveTicker } from "@/shared/components/ui/live-ticker"
1717
import { toast } from "sonner"
1818
import { useI18n } from "@/shared/providers/locale-provider"
19+
import { localizePathname } from "@/shared/i18n/config"
1920

2021
export function HeroSection() {
21-
const { t } = useI18n()
22+
const { t, locale } = useI18n()
2223
const router = useRouter()
2324
const { recentSearches, addSearch, removeSearch } = useSearchStore()
2425
const [open, setOpen] = useState(false)
@@ -86,8 +87,8 @@ export function HeroSection() {
8687
setQuery("")
8788
setSelectedIndex(-1)
8889
inputRef.current?.blur()
89-
router.push(`/users/${trimmedUsername}`)
90-
}, [addSearch, router])
90+
router.push(localizePathname(`/users/${trimmedUsername}`, locale))
91+
}, [addSearch, locale, router, t])
9192

9293
const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
9394
if (!open) {
@@ -279,7 +280,7 @@ export function HeroSection() {
279280
<a href="https://github.com/alexization/git-ranker" target="_blank" rel="noreferrer" className="flex items-center gap-2 text-sm font-semibold text-muted-foreground hover:text-foreground transition-colors">
280281
<BookOpen className="h-4 w-4" /> {t("home.links.guide")}
281282
</a>
282-
<a href="/ranking" className="flex items-center gap-2 text-sm font-semibold text-muted-foreground hover:text-primary transition-colors">
283+
<a href={localizePathname("/ranking", locale)} className="flex items-center gap-2 text-sm font-semibold text-muted-foreground hover:text-primary transition-colors">
283284
<TrendingUp className="h-4 w-4" /> {t("home.links.ranking")}
284285
</a>
285286
</motion.div>

src/features/user/components/badge-generator.tsx

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { Button } from "@/shared/components/button"
66
import { Check, Copy, Link2, Code2, ExternalLink } from "lucide-react"
77
import { toast } from "sonner"
88
import { cn } from "@/shared/lib/utils"
9+
import { useI18n } from "@/shared/providers/locale-provider"
10+
import { localizePathname } from "@/shared/i18n/config"
911

1012
interface BadgeGeneratorProps {
1113
nodeId: string
@@ -15,10 +17,12 @@ interface BadgeGeneratorProps {
1517
type CopyType = "markdown" | "html" | "link" | null
1618

1719
export function BadgeGenerator({ nodeId, username }: BadgeGeneratorProps) {
20+
const { t, locale } = useI18n()
1821
const [copied, setCopied] = useState<CopyType>(null)
1922

23+
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || "https://www.git-ranker.com"
2024
const badgeUrl = `${process.env.NEXT_PUBLIC_API_URL || 'https://www.git-ranker.com'}/api/v1/badges/${nodeId}`
21-
const profileUrl = `https://www.git-ranker.com/users/${username}`
25+
const profileUrl = `${baseUrl}${localizePathname(`/users/${username}`, locale)}`
2226

2327
const markdownCode = `[![Git Ranker](${badgeUrl})](${profileUrl})`
2428
const htmlCode = `<a href="${profileUrl}"><img src="${badgeUrl}" alt="Git Ranker Badge" /></a>`
@@ -27,9 +31,9 @@ export function BadgeGenerator({ nodeId, username }: BadgeGeneratorProps) {
2731
await navigator.clipboard.writeText(text)
2832
setCopied(type)
2933
toast.success(
30-
type === "markdown" ? "마크다운이 복사되었습니다!" :
31-
type === "html" ? "HTML이 복사되었습니다!" :
32-
"링크가 복사되었습니다!"
34+
type === "markdown" ? t("profile.badge.copied.markdown") :
35+
type === "html" ? t("profile.badge.copied.html") :
36+
t("profile.badge.copied.link")
3337
)
3438
setTimeout(() => setCopied(null), 2000)
3539
}
@@ -70,10 +74,10 @@ export function BadgeGenerator({ nodeId, username }: BadgeGeneratorProps) {
7074
<div className="p-2 rounded-xl bg-gradient-to-br from-primary/20 to-primary/5">
7175
<Code2 className="h-4 w-4 sm:h-5 sm:w-5 text-primary" />
7276
</div>
73-
README 배지
77+
{t("profile.badge.section.title")}
7478
</CardTitle>
7579
<CardDescription className="text-xs sm:text-sm mt-1.5 ml-11">
76-
GitHub 프로필에 나만의 배지를 추가해보세요
80+
{t("profile.badge.section.description")}
7781
</CardDescription>
7882
</CardHeader>
7983

@@ -91,7 +95,7 @@ export function BadgeGenerator({ nodeId, username }: BadgeGeneratorProps) {
9195
{/* eslint-disable-next-line @next/next/no-img-element */}
9296
<img
9397
src={badgeUrl}
94-
alt="Git Ranker Badge"
98+
alt={t("profile.badge.alt")}
9599
className="max-w-full h-auto object-contain"
96100
/>
97101
</a>
@@ -116,7 +120,7 @@ export function BadgeGenerator({ nodeId, username }: BadgeGeneratorProps) {
116120
type="link"
117121
text={badgeUrl}
118122
icon={Link2}
119-
label="이미지 링크"
123+
label={t("profile.badge.image-link")}
120124
/>
121125
<Button
122126
asChild
@@ -125,19 +129,19 @@ export function BadgeGenerator({ nodeId, username }: BadgeGeneratorProps) {
125129
>
126130
<a href={badgeUrl} target="_blank" rel="noreferrer">
127131
<ExternalLink className="w-4 h-4 mr-2" />
128-
미리보기
132+
{t("profile.badge.preview")}
129133
</a>
130134
</Button>
131135
</div>
132136

133137
{/* Usage Hint */}
134138
<div className="p-3 sm:p-4 rounded-xl bg-amber-500/5 border border-amber-500/10">
135139
<p className="text-xs sm:text-sm text-amber-700 dark:text-amber-400/90 leading-relaxed">
136-
<span className="font-semibold">💡 Tip:</span>{" "}
137-
GitHub 프로필 README.md 파일에 마크다운 코드를 붙여넣으세요!
140+
<span className="font-semibold">{t("profile.badge.tip.label")}</span>{" "}
141+
{t("profile.badge.tip.description")}
138142
</p>
139143
</div>
140144
</CardContent>
141145
</Card>
142146
)
143-
}
147+
}

src/shared/components/layout/header.tsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,22 @@ import { Avatar, AvatarFallback, AvatarImage } from "@/shared/components/avatar"
3030
import { useState } from "react"
3131
import { cn } from "@/shared/lib/utils"
3232
import { useI18n } from "@/shared/providers/locale-provider"
33+
import { localizePathname } from "@/shared/i18n/config"
3334

3435
export function Header() {
35-
const { t } = useI18n()
36+
const { t, locale } = useI18n()
3637
const { user, isAuthenticated } = useAuthStore()
3738
const hydrated = useAuthHydrated()
3839
const logoutMutation = useLogout()
3940
const router = useRouter()
4041
const [showLogoutDialog, setShowLogoutDialog] = useState(false)
4142
const pathname = usePathname()
43+
const homePath = localizePathname("/", locale)
44+
const rankingPath = localizePathname("/ranking", locale)
45+
const loginPath = localizePathname("/login", locale)
4246

4347
const handleLogin = () => {
44-
window.location.href = '/login'
48+
window.location.href = loginPath
4549
}
4650

4751
const handleLogoutClick = () => {
@@ -51,7 +55,7 @@ export function Header() {
5155
const handleLogoutConfirm = async () => {
5256
await logoutMutation.mutateAsync()
5357
setShowLogoutDialog(false)
54-
router.push('/')
58+
router.push(homePath)
5559
}
5660

5761
return (
@@ -60,7 +64,7 @@ export function Header() {
6064

6165
{/* Left Side: Logo & Navigation */}
6266
<div className="flex items-center gap-8">
63-
<Link href="/" className="flex items-center gap-2 transition-opacity hover:opacity-80">
67+
<Link href={homePath} className="flex items-center gap-2 transition-opacity hover:opacity-80">
6468
<GithubIcon className="h-6 w-6 text-foreground" />
6569
<span className="text-base font-bold tracking-tight text-foreground">
6670
Git Ranker
@@ -69,7 +73,7 @@ export function Header() {
6973

7074
<nav className="hidden md:flex items-center gap-6">
7175
<Link
72-
href="/ranking"
76+
href={rankingPath}
7377
className={cn(
7478
"text-sm font-medium transition-colors hover:text-primary flex items-center gap-1.5",
7579
pathname.endsWith("/ranking") ? "text-foreground" : "text-muted-foreground"
@@ -84,7 +88,7 @@ export function Header() {
8488
{/* Right Actions */}
8589
<div className="flex items-center gap-1.5 sm:gap-3">
8690
<Link
87-
href="/ranking"
91+
href={rankingPath}
8892
className="md:hidden p-2 text-muted-foreground hover:text-primary"
8993
aria-label={t("header.ranking.aria")}
9094
>
@@ -134,15 +138,15 @@ export function Header() {
134138
{/* Menu Items */}
135139
<div className="p-2 space-y-1">
136140
<DropdownMenuItem asChild className="rounded-xl h-11 px-3 cursor-pointer transition-colors duration-150">
137-
<Link href={`/users/${user.username}`} className="flex items-center gap-3">
141+
<Link href={localizePathname(`/users/${user.username}`, locale)} className="flex items-center gap-3">
138142
<div className="flex items-center justify-center w-8 h-8 rounded-full bg-primary/10">
139143
<User className="h-4 w-4 text-primary" />
140144
</div>
141145
<span className="text-[14px] font-medium">{t("common.profile")}</span>
142146
</Link>
143147
</DropdownMenuItem>
144148
<DropdownMenuItem asChild className="rounded-xl h-11 px-3 cursor-pointer transition-colors duration-150">
145-
<Link href="/settings" className="flex items-center gap-3">
149+
<Link href={localizePathname("/settings", locale)} className="flex items-center gap-3">
146150
<div className="flex items-center justify-center w-8 h-8 rounded-full bg-muted">
147151
<Settings className="h-4 w-4 text-muted-foreground" />
148152
</div>

src/shared/i18n/messages/en.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ export const enMessages = {
8686
"profile.refresh.success": "Data refreshed successfully!",
8787
"profile.refresh.error": "Failed to refresh data.",
8888
"profile.badge.copied": "Badge markdown copied!",
89+
"profile.badge.copied.markdown": "Markdown copied!",
90+
"profile.badge.copied.html": "HTML copied!",
91+
"profile.badge.copied.link": "Link copied!",
8992
"profile.share.copied": "Profile link copied!",
9093
"profile.not-found.title": "User not found",
9194
"profile.not-found.description.line1": "Please check the GitHub username again.",
@@ -100,6 +103,13 @@ export const enMessages = {
100103
"profile.percentile.aria": "Top {percent} percent",
101104
"profile.share.button": "Share profile",
102105
"profile.badge.copy-button": "Copy badge",
106+
"profile.badge.section.title": "README Badge",
107+
"profile.badge.section.description": "Add your custom badge to your GitHub profile.",
108+
"profile.badge.alt": "Git Ranker Badge",
109+
"profile.badge.image-link": "Image link",
110+
"profile.badge.preview": "Preview",
111+
"profile.badge.tip.label": "Tip:",
112+
"profile.badge.tip.description": "Paste the markdown code into your GitHub profile README.md.",
103113
"profile.refresh.pending": "Syncing...",
104114
"profile.refresh.button": "Load latest data",
105115
"profile.chart.subtitle": "Contribution distribution by activity type",

src/shared/i18n/messages/ko.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ export const koMessages: Record<MessageKey, string> = {
8787
"profile.refresh.success": "데이터가 갱신되었습니다!",
8888
"profile.refresh.error": "데이터 갱신에 실패했습니다.",
8989
"profile.badge.copied": "배지 마크다운이 복사되었습니다!",
90+
"profile.badge.copied.markdown": "마크다운이 복사되었습니다!",
91+
"profile.badge.copied.html": "HTML이 복사되었습니다!",
92+
"profile.badge.copied.link": "링크가 복사되었습니다!",
9093
"profile.share.copied": "프로필 링크가 복사되었습니다!",
9194
"profile.not-found.title": "사용자를 찾을 수 없어요",
9295
"profile.not-found.description.line1": "GitHub 아이디를 다시 확인해 주세요.",
@@ -101,6 +104,13 @@ export const koMessages: Record<MessageKey, string> = {
101104
"profile.percentile.aria": "상위 {percent} 퍼센트",
102105
"profile.share.button": "프로필 공유",
103106
"profile.badge.copy-button": "배지 복사",
107+
"profile.badge.section.title": "README 배지",
108+
"profile.badge.section.description": "GitHub 프로필에 나만의 배지를 추가해보세요",
109+
"profile.badge.alt": "Git Ranker 배지",
110+
"profile.badge.image-link": "이미지 링크",
111+
"profile.badge.preview": "미리보기",
112+
"profile.badge.tip.label": "Tip:",
113+
"profile.badge.tip.description": "GitHub 프로필 README.md 파일에 마크다운 코드를 붙여넣으세요!",
104114
"profile.refresh.pending": "동기화 중...",
105115
"profile.refresh.button": "최신 데이터 불러오기",
106116
"profile.chart.subtitle": "활동 유형별 기여도 분포",

0 commit comments

Comments
 (0)