diff --git a/components/Navigator/MainNavigator.tsx b/components/Navigator/MainNavigator.tsx index 943f739..c4ada80 100644 --- a/components/Navigator/MainNavigator.tsx +++ b/components/Navigator/MainNavigator.tsx @@ -39,6 +39,7 @@ const topNavBarMenu = ({ t }: typeof i18n): MenuItem[] => [ title: t('open_source_projects'), subs: [ { href: '/project', title: t('self_developed_projects') }, + { href: '/library', title: t('open_library') }, { href: '/search/project', title: t('bazaar_projects') }, { href: '/issue', title: 'GitHub issues' }, { href: '/license-filter', title: t('license_filter') }, diff --git a/pages/library.tsx b/pages/library.tsx new file mode 100644 index 0000000..1704803 --- /dev/null +++ b/pages/library.tsx @@ -0,0 +1,249 @@ +import { observer } from 'mobx-react'; +import Link from 'next/link'; +import { FC, useContext } from 'react'; +import { Badge, Button, Card, Col, Container, ListGroup, Row, Stack } from 'react-bootstrap'; + +import { PageHead } from '../components/Layout/PageHead'; +import { I18nContext, I18nKey } from '../models/Translation'; + +type LibraryStatus = 'available' | 'borrowed'; + +interface LibraryBook { + id: string; + titleKey: I18nKey; + authorKey: I18nKey; + descriptionKey: I18nKey; + categoryKey: I18nKey; + status: LibraryStatus; + shelfCode: string; + borrowInfoKey: I18nKey; +} + +const libraryBooks: LibraryBook[] = [ + { + id: 'cathedral-bazaar', + titleKey: 'library_book_cathedral_title', + authorKey: 'library_book_cathedral_author', + descriptionKey: 'library_book_cathedral_description', + categoryKey: 'library_category_open_source', + status: 'available', + shelfCode: 'OS-001', + borrowInfoKey: 'library_book_available_note', + }, + { + id: 'producing-oss', + titleKey: 'library_book_producing_oss_title', + authorKey: 'library_book_producing_oss_author', + descriptionKey: 'library_book_producing_oss_description', + categoryKey: 'library_category_community', + status: 'borrowed', + shelfCode: 'OS-002', + borrowInfoKey: 'library_book_borrowed_note', + }, + { + id: 'pro-git', + titleKey: 'library_book_pro_git_title', + authorKey: 'library_book_pro_git_author', + descriptionKey: 'library_book_pro_git_description', + categoryKey: 'library_category_engineering', + status: 'available', + shelfCode: 'ENG-003', + borrowInfoKey: 'library_book_available_note', + }, + { + id: 'community-playbook', + titleKey: 'library_book_community_playbook_title', + authorKey: 'library_book_community_playbook_author', + descriptionKey: 'library_book_community_playbook_description', + categoryKey: 'library_category_community', + status: 'available', + shelfCode: 'COM-004', + borrowInfoKey: 'library_book_available_note', + }, + { + id: 'governance-guide', + titleKey: 'library_book_governance_title', + authorKey: 'library_book_governance_author', + descriptionKey: 'library_book_governance_description', + categoryKey: 'library_category_governance', + status: 'borrowed', + shelfCode: 'GOV-005', + borrowInfoKey: 'library_book_borrowed_note', + }, + { + id: 'license-handbook', + titleKey: 'library_book_license_title', + authorKey: 'library_book_license_author', + descriptionKey: 'library_book_license_description', + categoryKey: 'library_category_license', + status: 'available', + shelfCode: 'LIC-006', + borrowInfoKey: 'library_book_available_note', + }, +]; + +const guideStepKeys: I18nKey[] = [ + 'library_guide_step_1', + 'library_guide_step_2', + 'library_guide_step_3', +]; + +const statusVariant: Record = { + available: 'success', + borrowed: 'secondary', +}; + +const statusLabelKey: Record = { + available: 'library_status_available', + borrowed: 'library_status_borrowed', +}; + +const LibraryPage: FC = observer(() => { + const { t } = useContext(I18nContext); + const availableCount = libraryBooks.filter(({ status }) => status === 'available').length; + const borrowedCount = libraryBooks.length - availableCount; + + return ( + + + +
+ + {t('library_badge')} + +

{t('library_page_title')}

+

{t('library_page_description')}

+ + + + +
+ + + + + + {t('library_stat_total_label')} + + + {libraryBooks.length} + + {t('library_stat_total_desc')} + + + + + + {t('library_stat_available_label')} + + + {availableCount} + + {t('library_stat_available_desc')} + + + + + + {t('library_stat_borrowed_label')} + + + {borrowedCount} + + {t('library_stat_borrowed_desc')} + + + + + + +
+
+
+

{t('library_catalog_title')}

+

{t('library_catalog_description')}

+
+ + {t('library_status_legend')} + +
+ + + {libraryBooks.map(book => ( + + + + + + {t(statusLabelKey[book.status])} + + + {t(book.categoryKey)} + + + + + {t(book.titleKey)} + + {t(book.authorKey)} + {t(book.descriptionKey)} + + + + {t('library_shelf_code')} + {book.shelfCode} + + + {t('library_borrow_status')} + {t(book.borrowInfoKey)} + + + + + ))} + +
+ + + +
+ + + + {t('library_borrow_guide')} + + + {t('library_borrow_guide_description')} + + + {guideStepKeys.map(key => ( + + {t(key)} + + ))} + + + + + + + + +
+ +
+
+ ); +}); + +export default LibraryPage; diff --git a/translation/en-US.ts b/translation/en-US.ts index 4419cb6..d063fa0 100644 --- a/translation/en-US.ts +++ b/translation/en-US.ts @@ -210,6 +210,71 @@ export default { 'Find corresponding ETFs or index funds, paying attention to fees and fund size.', finance_edu_next_3: 'Set up a recurring investment plan and track valuation and drawdown.', + // Open Library + open_library: 'Open Library', + library_page_title: 'Open Library', + library_page_description: + 'Browse books about open collaboration, open-source governance, and engineering practice with clear borrowing status and instructions.', + library_badge: 'Open Library', + library_browse_catalog: 'Browse catalog', + library_borrow_guide: 'Borrowing guide', + library_stat_total_label: 'Books in catalog', + library_stat_total_desc: + 'Covering open-source culture, community operations, engineering collaboration, and licensing practice.', + library_stat_available_label: 'Available now', + library_stat_available_desc: 'Contact an administrator to register a borrowing request.', + library_stat_borrowed_label: 'Borrowed', + library_stat_borrowed_desc: 'Check borrowing details and reserve the next slot after return.', + library_catalog_title: 'Book catalog', + library_catalog_description: + 'Review topics, shelf codes, availability, and borrowing notes for each book.', + library_status_legend: 'Status: available / borrowed', + library_status_available: 'Available', + library_status_borrowed: 'Borrowed', + library_category_open_source: 'Open-source culture', + library_category_community: 'Community operations', + library_category_engineering: 'Engineering collaboration', + library_category_governance: 'Governance practice', + library_category_license: 'Licensing', + library_book_cathedral_title: 'The Cathedral and the Bazaar', + library_book_cathedral_author: 'Eric S. Raymond', + library_book_cathedral_description: + 'A classic open-source culture essay about open collaboration, fast iteration, and community-driven software development.', + library_book_producing_oss_title: 'Producing Open Source Software', + library_book_producing_oss_author: 'Karl Fogel', + library_book_producing_oss_description: + 'A practical guide to launching open-source projects, communication, contribution workflows, and maintainer responsibilities.', + library_book_pro_git_title: 'Pro Git', + library_book_pro_git_author: 'Scott Chacon and Ben Straub', + library_book_pro_git_description: + 'A systematic guide to daily Git collaboration, branching models, and distributed version control workflows.', + library_book_community_playbook_title: 'Open Source Community Playbook', + library_book_community_playbook_author: 'Open Source Bazaar', + library_book_community_playbook_description: + 'Templates and practices for community organizers covering events, volunteer collaboration, contributor growth, and retrospectives.', + library_book_governance_title: 'Open Source Governance Guide', + library_book_governance_author: 'Open Source Initiative', + library_book_governance_description: + 'Guidance on governance models, decision-making, codes of conduct, and long-term project sustainability.', + library_book_license_title: 'Open Source License Handbook', + library_book_license_author: 'Open Source Bazaar', + library_book_license_description: + 'Helps contributors understand common licenses, reuse boundaries, and project compliance checklists.', + library_book_available_note: + 'Available to borrow after registration and administrator confirmation.', + library_book_borrowed_note: + 'Currently borrowed. Contact an administrator to reserve the next slot after return.', + library_shelf_code: 'Shelf code', + library_borrow_status: 'Borrowing info', + library_borrow_guide_description: + 'Register in three steps; after confirmation, pick up the book offline or agree on a handoff method.', + library_guide_step_1: 'Find the book in the catalog and record its title and shelf code.', + library_guide_step_2: + 'Contact an administrator through the bounty or activity page with your name, contact information, and expected return date.', + library_guide_step_3: + 'After confirmation, complete the registration and receive return reminders or reservation queue updates.', + library_submit_books: 'Submit a book or request borrowing', + // Hackathon hackathon_detail: 'Hackathon Details', hackathon_highlights: 'Tracks', diff --git a/translation/zh-CN.ts b/translation/zh-CN.ts index ae27758..8e948b7 100644 --- a/translation/zh-CN.ts +++ b/translation/zh-CN.ts @@ -206,6 +206,61 @@ export default { finance_edu_next_2: '了解对应的 ETF 或联接基金,关注费率与规模。', finance_edu_next_3: '设定定投计划并持续跟踪估值、回撤。', + // Open Library + open_library: '开源图书馆', + library_page_title: '开源图书馆', + library_page_description: + '浏览开放协作、开源治理与工程实践相关书籍,并快速了解可借状态与借阅方式。', + library_badge: 'Open Library', + library_browse_catalog: '浏览图书目录', + library_borrow_guide: '借阅指南', + library_stat_total_label: '馆藏图书', + library_stat_total_desc: '覆盖开源文化、社区运营、工程协作与许可证实践。', + library_stat_available_label: '当前可借', + library_stat_available_desc: '可直接联系管理员登记借阅。', + library_stat_borrowed_label: '已借出', + library_stat_borrowed_desc: '可查看归还信息并预约下一次借阅。', + library_catalog_title: '图书目录', + library_catalog_description: '按主题查看馆藏、书架编号、可借状态和借阅说明。', + library_status_legend: '状态:可借 / 已借出', + library_status_available: '可借', + library_status_borrowed: '已借出', + library_category_open_source: '开源文化', + library_category_community: '社区运营', + library_category_engineering: '工程协作', + library_category_governance: '治理实践', + library_category_license: '许可证', + library_book_cathedral_title: '《大教堂与集市》', + library_book_cathedral_author: 'Eric S. Raymond', + library_book_cathedral_description: + '经典开源文化读本,介绍开放协作、快速迭代与社区共创的软件开发模式。', + library_book_producing_oss_title: '《Producing Open Source Software》', + library_book_producing_oss_author: 'Karl Fogel', + library_book_producing_oss_description: + '围绕开源项目启动、沟通、贡献流程与维护者职责的实用指南。', + library_book_pro_git_title: '《Pro Git》', + library_book_pro_git_author: 'Scott Chacon 与 Ben Straub', + library_book_pro_git_description: '系统讲解 Git 的日常协作、分支模型和分布式版本控制工作流。', + library_book_community_playbook_title: '开源社区行动手册', + library_book_community_playbook_author: 'Open Source Bazaar', + library_book_community_playbook_description: + '面向社区组织者的活动策划、志愿者协作、贡献者成长与复盘模板。', + library_book_governance_title: '开源治理指南', + library_book_governance_author: 'Open Source Initiative', + library_book_governance_description: '梳理治理结构、决策机制、行为规范和项目可持续性建设要点。', + library_book_license_title: '开源许可证手册', + library_book_license_author: 'Open Source Bazaar', + library_book_license_description: '帮助贡献者理解常见许可证、复用边界和项目合规检查清单。', + library_book_available_note: '可借阅,提交登记后等待管理员确认。', + library_book_borrowed_note: '已借出,可联系管理员预约归还后的下一位。', + library_shelf_code: '书架编号', + library_borrow_status: '借阅信息', + library_borrow_guide_description: '三步完成借阅登记,管理员确认后即可线下领取或约定传递方式。', + library_guide_step_1: '在目录中找到想借阅的书籍,记录书名与书架编号。', + library_guide_step_2: '通过开源市集悬赏或活动页面联系管理员,提交姓名、联系方式和预计归还时间。', + library_guide_step_3: '管理员确认可借状态后完成登记,并同步归还提醒或预约排队信息。', + library_submit_books: '提交新书或借阅请求', + // Hackathon hackathon_detail: '黑客松详情', hackathon_highlights: '赛道方向', diff --git a/translation/zh-TW.ts b/translation/zh-TW.ts index a657e06..425ee9f 100644 --- a/translation/zh-TW.ts +++ b/translation/zh-TW.ts @@ -206,6 +206,61 @@ export default { finance_edu_next_2: '了解對應的 ETF 或聯接基金,關注費率與規模。', finance_edu_next_3: '設定定投計畫並持續跟蹤估值、回撤。', + // Open Library + open_library: '開源圖書館', + library_page_title: '開源圖書館', + library_page_description: + '瀏覽開放協作、開源治理與工程實踐相關書籍,並快速了解可借狀態與借閱方式。', + library_badge: 'Open Library', + library_browse_catalog: '瀏覽圖書目錄', + library_borrow_guide: '借閱指南', + library_stat_total_label: '館藏圖書', + library_stat_total_desc: '涵蓋開源文化、社群營運、工程協作與授權實務。', + library_stat_available_label: '目前可借', + library_stat_available_desc: '可直接聯繫管理員登記借閱。', + library_stat_borrowed_label: '已借出', + library_stat_borrowed_desc: '可查看歸還資訊並預約下一次借閱。', + library_catalog_title: '圖書目錄', + library_catalog_description: '依主題查看館藏、書架編號、可借狀態和借閱說明。', + library_status_legend: '狀態:可借 / 已借出', + library_status_available: '可借', + library_status_borrowed: '已借出', + library_category_open_source: '開源文化', + library_category_community: '社群營運', + library_category_engineering: '工程協作', + library_category_governance: '治理實踐', + library_category_license: '授權條款', + library_book_cathedral_title: '《大教堂與市集》', + library_book_cathedral_author: 'Eric S. Raymond', + library_book_cathedral_description: + '經典開源文化讀本,介紹開放協作、快速迭代與社群共創的軟體開發模式。', + library_book_producing_oss_title: '《Producing Open Source Software》', + library_book_producing_oss_author: 'Karl Fogel', + library_book_producing_oss_description: + '圍繞開源專案啟動、溝通、貢獻流程與維護者職責的實用指南。', + library_book_pro_git_title: '《Pro Git》', + library_book_pro_git_author: 'Scott Chacon 與 Ben Straub', + library_book_pro_git_description: '系統講解 Git 的日常協作、分支模型和分散式版本控制工作流。', + library_book_community_playbook_title: '開源社群行動手冊', + library_book_community_playbook_author: 'Open Source Bazaar', + library_book_community_playbook_description: + '面向社群組織者的活動策劃、志工協作、貢獻者成長與復盤模板。', + library_book_governance_title: '開源治理指南', + library_book_governance_author: 'Open Source Initiative', + library_book_governance_description: '梳理治理結構、決策機制、行為準則和專案永續性建設要點。', + library_book_license_title: '開源授權手冊', + library_book_license_author: 'Open Source Bazaar', + library_book_license_description: '協助貢獻者理解常見授權條款、複用邊界和專案合規檢查清單。', + library_book_available_note: '可借閱,提交登記後等待管理員確認。', + library_book_borrowed_note: '已借出,可聯繫管理員預約歸還後的下一位。', + library_shelf_code: '書架編號', + library_borrow_status: '借閱資訊', + library_borrow_guide_description: '三步完成借閱登記,管理員確認後即可線下領取或約定交付方式。', + library_guide_step_1: '在目錄中找到想借閱的書籍,記錄書名與書架編號。', + library_guide_step_2: '透過開源市集懸賞或活動頁面聯繫管理員,提交姓名、聯絡方式和預計歸還時間。', + library_guide_step_3: '管理員確認可借狀態後完成登記,並同步歸還提醒或預約排隊資訊。', + library_submit_books: '提交新書或借閱請求', + // Hackathon hackathon_detail: '黑客松詳情', hackathon_highlights: '賽道方向',