Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,10 @@ flowchart LR
| Path | Page | Description |
| --- | --- | --- |
| `/` | Home | 최신글, 인기글, 블로그 통계 |
| `/posts` | Posts | 전체 글 목록, 리스트/그리드 뷰 |
| `/posts` | Posts | 전체 글 목록, 검색, 정렬, 태그/연도 필터 |
| `/posts/:slug` | Post | Markdown 글 상세, TOC, 댓글 |
| `/tags` | Tags | 태그별 탐색 |
| `/tags` | Tags | 태그별 주제 탐색, 관련 태그, 최근 글 |
| `/series` | Series | 시리즈별 글 탐색 |
| `/search` | Search | 키워드, 날짜, 태그 기반 고급 검색 |
| `/analytics` | Analytics | 방문자 및 조회수 대시보드 |
| `/about` | About | 소개, 경력, 프로젝트 요약 |
| `/about/projects/:slug` | Project Detail | 프로젝트 상세 |
Expand Down
4 changes: 1 addition & 3 deletions src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NavLink, useLocation, useNavigate } from "react-router-dom"
import { Home, FileText, Tags, User, Search, Library, BarChart3 } from "lucide-react"
import { Home, FileText, Tags, User, Library, BarChart3 } from "lucide-react"
import {
Sidebar as SidebarRoot,
SidebarContent,
Expand All @@ -25,7 +25,6 @@ const navIcons = {
home: Home,
posts: FileText,
series: Library,
search: Search,
tags: Tags,
analytics: BarChart3,
about: User,
Expand All @@ -50,7 +49,6 @@ export function AppSidebar() {
{ label: t.common.home, to: localizePath("/", language), basePath: "/", icon: navIcons.home },
{ label: t.common.posts, to: localizePath("/posts", language), basePath: "/posts", icon: navIcons.posts },
{ label: t.common.series, to: localizePath("/series", language), basePath: "/series", icon: navIcons.series },
{ label: t.common.search, to: localizePath("/search", language), basePath: "/search", icon: navIcons.search },
{ label: t.common.tags, to: localizePath("/tags", language), basePath: "/tags", icon: navIcons.tags },
{ label: t.common.analytics, to: localizePath("/analytics", language), basePath: "/analytics", icon: navIcons.analytics },
{ label: t.common.about, to: localizePath("/about", language), basePath: "/about", icon: navIcons.about },
Expand Down
10 changes: 6 additions & 4 deletions src/entry-server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,13 @@ function localizedStaticRoutes(language: Language, posts: PostMeta[]): Prerender
{
path: path("/search/"),
language,
title: isEnglish ? "Search" : "검색",
description: isEnglish ? "Search blog posts by keyword, tag, or date." : "블로그 글을 키워드, 태그, 날짜로 검색합니다.",
title: isEnglish ? "Posts" : "글 목록",
description: postsDescription,
noindex: true,
canonicalPath: path("/posts/"),
alternates: {
ko: "/search/",
en: "/en/search/",
ko: "/posts/",
en: "/en/posts/",
},
},
{
Expand Down
108 changes: 108 additions & 0 deletions src/i18n/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,22 @@ export interface Translations {
description: string
listView: string
gridView: string
searchPlaceholder: string
sortLabel: string
yearLabel: string
scopeLabel: string
sortLatest: string
sortPopular: string
sortOldest: string
allYears: string
allTags: string
scopeAll: string
scopeSummary: string
scopeTags: string
reset: string
totalCount: (count: number) => string
filteredCount: (count: number) => string
noResults: string
}
search: {
description: string
Expand All @@ -55,6 +71,9 @@ export interface Translations {
reset: string
noResults: string
searchGuide: string
redirectTitle: string
redirectDescription: string
goToPosts: string
}
series: {
description: string
Expand All @@ -65,6 +84,23 @@ export interface Translations {
}
tags: {
description: string
summary: (postCount: number, tagCount: number) => string
searchPlaceholder: string
sortPopular: string
sortRecent: string
sortName: string
reset: string
selectedLabel: (tag: string) => string
topTags: string
topTagsNote: string
topicGroups: string
ungrouped: string
postCount: (count: number) => string
relatedTags: string
recentPosts: string
selectedDescription: (tag: string) => string
viewInPosts: (tag: string) => string
noMatchingTags: string
noTags: string
allTags: string
noPostsWithTag: string
Expand Down Expand Up @@ -184,6 +220,22 @@ export const ko: Translations = {
description: "전체 블로그 글 목록",
listView: "리스트 보기",
gridView: "그리드 보기",
searchPlaceholder: "제목, 설명, 태그, 본문 검색",
sortLabel: "정렬",
yearLabel: "연도",
scopeLabel: "검색 범위",
sortLatest: "최신순",
sortPopular: "인기순",
sortOldest: "오래된순",
allYears: "전체 연도",
allTags: "전체",
scopeAll: "제목, 설명, 태그, 본문",
scopeSummary: "제목, 설명, 태그",
scopeTags: "태그만",
reset: "초기화",
totalCount: (count) => `${count}개의 글을 최신순으로 보고 있습니다.`,
filteredCount: (count) => `${count}개의 글을 찾았습니다.`,
noResults: "조건에 맞는 글이 없습니다.",
},
search: {
description: "블로그 글 검색",
Expand All @@ -195,6 +247,9 @@ export const ko: Translations = {
reset: "초기화",
noResults: "검색 결과가 없습니다.",
searchGuide: "키워드, 날짜, 태그를 선택하여 검색하세요.",
redirectTitle: "검색이 글 목록으로 통합되었습니다",
redirectDescription: "글 검색과 필터는 이제 글 목록에서 함께 사용할 수 있습니다.",
goToPosts: "글 목록으로 이동",
},
series: {
description: "시리즈별 블로그 글 목록",
Expand All @@ -205,6 +260,23 @@ export const ko: Translations = {
},
tags: {
description: "태그별 블로그 글 목록",
summary: (postCount, tagCount) => `${postCount}개의 글이 ${tagCount}개의 태그로 정리되어 있습니다.`,
searchPlaceholder: "태그 이름 검색",
sortPopular: "많은 글순",
sortRecent: "최근 글순",
sortName: "가나다순",
reset: "초기화",
selectedLabel: (tag) => `선택됨 · ${tag}`,
topTags: "주요 태그",
topTagsNote: "글 수와 최근 발행 기준",
topicGroups: "주제 그룹",
ungrouped: "기타",
postCount: (count) => `${count}개 글`,
relatedTags: "관련 태그",
recentPosts: "최근 글",
selectedDescription: (tag) => `${tag} 태그가 붙은 글의 흐름과 함께 자주 등장하는 주제를 모아봅니다.`,
viewInPosts: (tag) => `${tag} 글 목록으로 보기`,
noMatchingTags: "조건에 맞는 태그가 없습니다.",
noTags: "태그가 없습니다.",
allTags: "전체 태그",
noPostsWithTag: "해당 태그의 글이 없습니다.",
Expand Down Expand Up @@ -324,6 +396,22 @@ export const en: Translations = {
description: "All blog posts",
listView: "List view",
gridView: "Grid view",
searchPlaceholder: "Search title, description, tags, or content",
sortLabel: "Sort",
yearLabel: "Year",
scopeLabel: "Search scope",
sortLatest: "Latest",
sortPopular: "Popular",
sortOldest: "Oldest",
allYears: "All years",
allTags: "All",
scopeAll: "Title, description, tags, content",
scopeSummary: "Title, description, tags",
scopeTags: "Tags only",
reset: "Reset",
totalCount: (count) => `Showing ${count} post${count !== 1 ? "s" : ""} by latest date.`,
filteredCount: (count) => `Found ${count} post${count !== 1 ? "s" : ""}.`,
noResults: "No posts match these filters.",
},
search: {
description: "Search blog posts",
Expand All @@ -335,6 +423,9 @@ export const en: Translations = {
reset: "Reset",
noResults: "No results found.",
searchGuide: "Search by keyword, date, or tag.",
redirectTitle: "Search moved to Posts",
redirectDescription: "Post search and filters are now available directly in the posts list.",
goToPosts: "Go to posts",
},
series: {
description: "Blog posts by series",
Expand All @@ -345,6 +436,23 @@ export const en: Translations = {
},
tags: {
description: "Blog posts by tag",
summary: (postCount, tagCount) => `${postCount} post${postCount !== 1 ? "s" : ""} are organized with ${tagCount} tag${tagCount !== 1 ? "s" : ""}.`,
searchPlaceholder: "Search tags",
sortPopular: "Most used",
sortRecent: "Recent",
sortName: "A-Z",
reset: "Reset",
selectedLabel: (tag) => `Selected · ${tag}`,
topTags: "Top Tags",
topTagsNote: "By post count and latest publish date",
topicGroups: "Topic Groups",
ungrouped: "Other",
postCount: (count) => `${count} post${count !== 1 ? "s" : ""}`,
relatedTags: "Related Tags",
recentPosts: "Recent Posts",
selectedDescription: (tag) => `Explore posts tagged with ${tag} and the topics that often appear with it.`,
viewInPosts: (tag) => `View ${tag} posts`,
noMatchingTags: "No tags match these filters.",
noTags: "No tags yet.",
allTags: "All tags",
noPostsWithTag: "No posts with this tag.",
Expand Down
Loading
Loading