+
+
+
{/* Header */}
-
+
RepoHub
-
- Cross-Platform Package Manager
+
+ {t('common.subtitle')}
-
- Simplify software installation across Linux, Windows, and macOS with official repositories
+
+ {t('common.description')}
@@ -109,3 +115,11 @@ export function RepoHubApp() {
)
}
+
+export function RepoHubApp() {
+ return (
+
+
+
+ )
+}
diff --git a/src/components/SelectionManager.tsx b/src/components/SelectionManager.tsx
index 46e7289..66d379e 100644
--- a/src/components/SelectionManager.tsx
+++ b/src/components/SelectionManager.tsx
@@ -2,6 +2,7 @@
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
+import { useLocale } from '@/contexts/LocaleContext'
import { Package, SelectedPackage } from '@/types'
import { X, PackageOpen, Download } from 'lucide-react'
@@ -18,13 +19,15 @@ export function SelectionManager({
onClearAll,
onGenerateScript
}: SelectionManagerProps) {
+ const { t } = useLocale()
+
if (selectedPackages.length === 0) {
return (
-
No packages selected
+
{t('selection.none')}
@@ -36,18 +39,18 @@ export function SelectionManager({
- Selected Packages ({selectedPackages.length})
+ {t('selection.title')} ({selectedPackages.length})
- These packages will be included in your installation script
+ {t('selection.description')}
@@ -90,8 +93,7 @@ export function SelectionManager({
- Note: The generated script will use official repositories only
- and will be idempotent (safe to run multiple times).
+ Note: {t('selection.note')}
diff --git a/src/contexts/LocaleContext.tsx b/src/contexts/LocaleContext.tsx
new file mode 100644
index 0000000..341c221
--- /dev/null
+++ b/src/contexts/LocaleContext.tsx
@@ -0,0 +1,189 @@
+"use client"
+
+import { createContext, useContext, useState, useEffect, ReactNode } from 'react'
+
+type Locale = 'en' | 'tr'
+
+const translations = {
+ en: {
+ common: {
+ title: "RepoHub - Cross-Platform Package Manager",
+ subtitle: "Cross-Platform Package Manager",
+ description: "Simplify software installation across Linux, Windows, and macOS with official repositories"
+ },
+ platform: {
+ select: "Select Your Platform",
+ description: "Choose your operating system and package manager to browse available packages",
+ selected: "Selected"
+ },
+ packages: {
+ browse: "Available Packages",
+ description: "Select packages to include in your installation script",
+ search: "Search packages...",
+ no_packages: "No packages found matching your criteria",
+ filters: {
+ category: "Category",
+ type: "Type",
+ repository: "Repository",
+ gui: "GUI Applications",
+ cli: "CLI Tools",
+ official: "Official Only",
+ third_party: "Third Party"
+ }
+ },
+ selection: {
+ title: "Selected Packages",
+ description: "These packages will be included in your installation script",
+ none: "No packages selected",
+ clear_all: "Clear All",
+ generate_script: "Generate Script",
+ note: "The generated script will use official repositories only and will be idempotent (safe to run multiple times)."
+ },
+ script: {
+ title: "Installation Script",
+ description: "Idempotent script for",
+ official_repos: "Official Repositories",
+ official_repos_desc: "All packages from trusted sources",
+ idempotent: "Idempotent",
+ idempotent_desc: "Safe to run multiple times",
+ packages_count: "Packages",
+ packages_count_desc: "Ready for installation",
+ included_packages: "Included Packages:",
+ script_content: "Script Content:",
+ copy: "Copy",
+ copied: "Copied!",
+ download: "Download",
+ usage: "How to use:",
+ usage_steps: [
+ "Download the script file to your target machine",
+ "Make it executable (for Linux/macOS):",
+ "Run the script with appropriate permissions",
+ "The script will automatically handle repository setup and package installation"
+ ]
+ }
+ },
+ tr: {
+ common: {
+ title: "RepoHub - Çok Platformlu Paket Yöneticisi",
+ subtitle: "Çok Platformlu Paket Yöneticisi",
+ description: "Linux, Windows ve macOS'te resmi depoları kullanarak yazılım kurulumunu basitleştirin"
+ },
+ platform: {
+ select: "Platformunuzu Seçin",
+ description: "Mevcut paketlere göz atmak için işletim sisteminizi ve paket yöneticinizi seçin",
+ selected: "Seçildi"
+ },
+ packages: {
+ browse: "Mevcut Paketler",
+ description: "Kurulum scriptinize dahil edilecek paketleri seçin",
+ search: "Paket ara...",
+ no_packages: "Kriterlerinize uyan paket bulunamadı",
+ filters: {
+ category: "Kategori",
+ type: "Tür",
+ repository: "Depo",
+ gui: "GUI Uygulamaları",
+ cli: "CLI Araçları",
+ official: "Sadece Resmi",
+ third_party: "Üçüncü Parti"
+ }
+ },
+ selection: {
+ title: "Seçilen Paketler",
+ description: "Bu paketler kurulum scriptinize dahil edilecek",
+ none: "Seçilen paket yok",
+ clear_all: "Tümünü Temizle",
+ generate_script: "Script Oluştur",
+ note: "Oluşturulan script yalnızca resmi depoları kullanacak ve idempotent olacak (birden çok kez çalıştırılması güvenli)."
+ },
+ script: {
+ title: "Kurulum Scripti",
+ description: "için idempotent script",
+ official_repos: "Resmi Depolar",
+ official_repos_desc: "Tüm paketler güvenilir kaynaklardan",
+ idempotent: "Idempotent",
+ idempotent_desc: "Birden çok kez çalıştırılması güvenli",
+ packages_count: "Paket",
+ packages_count_desc: "Kurulum için hazır",
+ included_packages: "Dahil Edilen Paketler:",
+ script_content: "Script İçeriği:",
+ copy: "Kopyala",
+ copied: "Kopyalandı!",
+ download: "İndir",
+ usage: "Nasıl kullanılır:",
+ usage_steps: [
+ "Script dosyasını hedef makinenize indirin",
+ "Çalıştırılabilir yapın (Linux/macOS için):",
+ "Scripti uygun izinlerle çalıştırın",
+ "Script otomatik olarak depo kurulumunu ve paket kurulumunu yönetecektir"
+ ]
+ }
+ }
+}
+
+interface LocaleContextType {
+ locale: Locale
+ changeLocale: (locale: Locale) => void
+ toggleLocale: () => void
+ t: (key: string) => string
+}
+
+const LocaleContext = createContext
(undefined)
+
+export function LocaleProvider({ children }: { children: ReactNode }) {
+ const [locale, setLocale] = useState('en')
+
+ useEffect(() => {
+ // Detect user's preferred locale
+ const detectLocale = (): Locale => {
+ const stored = localStorage.getItem('locale') as Locale
+ if (stored && (stored === 'en' || stored === 'tr')) {
+ return stored
+ }
+
+ // Get browser language
+ const browserLang = navigator.language.toLowerCase()
+ if (browserLang.startsWith('tr')) {
+ return 'tr'
+ }
+
+ return 'en'
+ }
+
+ setLocale(detectLocale())
+ }, [])
+
+ const changeLocale = (newLocale: Locale) => {
+ setLocale(newLocale)
+ localStorage.setItem('locale', newLocale)
+ }
+
+ const toggleLocale = () => {
+ changeLocale(locale === 'en' ? 'tr' : 'en')
+ }
+
+ const t = (key: string) => {
+ const keys = key.split('.')
+ let value: any = translations[locale]
+
+ for (const k of keys) {
+ value = value?.[k]
+ }
+
+ return value || key
+ }
+
+ return (
+
+ {children}
+
+ )
+}
+
+export function useLocale() {
+ const context = useContext(LocaleContext)
+ if (context === undefined) {
+ throw new Error('useLocale must be used within a LocaleProvider')
+ }
+ return context
+}
diff --git a/src/hooks/useLocale.ts b/src/hooks/useLocale.ts
new file mode 100644
index 0000000..94f3efa
--- /dev/null
+++ b/src/hooks/useLocale.ts
@@ -0,0 +1,173 @@
+"use client"
+
+import { useState, useEffect } from 'react'
+
+type Locale = 'en' | 'tr'
+
+const translations = {
+ en: {
+ common: {
+ title: "RepoHub - Cross-Platform Package Manager",
+ subtitle: "Cross-Platform Package Manager",
+ description: "Simplify software installation across Linux, Windows, and macOS with official repositories"
+ },
+ platform: {
+ select: "Select Your Platform",
+ description: "Choose your operating system and package manager to browse available packages",
+ selected: "Selected"
+ },
+ packages: {
+ browse: "Available Packages",
+ description: "Select packages to include in your installation script",
+ search: "Search packages...",
+ no_packages: "No packages found matching your criteria",
+ filters: {
+ category: "Category",
+ type: "Type",
+ repository: "Repository",
+ gui: "GUI Applications",
+ cli: "CLI Tools",
+ official: "Official Only",
+ third_party: "Third Party"
+ }
+ },
+ selection: {
+ title: "Selected Packages",
+ description: "These packages will be included in your installation script",
+ none: "No packages selected",
+ clear_all: "Clear All",
+ generate_script: "Generate Script",
+ note: "The generated script will use official repositories only and will be idempotent (safe to run multiple times)."
+ },
+ script: {
+ title: "Installation Script",
+ description: "Idempotent script for",
+ official_repos: "Official Repositories",
+ official_repos_desc: "All packages from trusted sources",
+ idempotent: "Idempotent",
+ idempotent_desc: "Safe to run multiple times",
+ packages_count: "Packages",
+ packages_count_desc: "Ready for installation",
+ included_packages: "Included Packages:",
+ script_content: "Script Content:",
+ copy: "Copy",
+ copied: "Copied!",
+ download: "Download",
+ usage: "How to use:",
+ usage_steps: [
+ "Download the script file to your target machine",
+ "Make it executable (for Linux/macOS):",
+ "Run the script with appropriate permissions",
+ "The script will automatically handle repository setup and package installation"
+ ]
+ }
+ },
+ tr: {
+ common: {
+ title: "RepoHub - Çok Platformlu Paket Yöneticisi",
+ subtitle: "Çok Platformlu Paket Yöneticisi",
+ description: "Linux, Windows ve macOS'te resmi depoları kullanarak yazılım kurulumunu basitleştirin"
+ },
+ platform: {
+ select: "Platformunuzu Seçin",
+ description: "Mevcut paketlere göz atmak için işletim sisteminizi ve paket yöneticinizi seçin",
+ selected: "Seçildi"
+ },
+ packages: {
+ browse: "Mevcut Paketler",
+ description: "Kurulum scriptinize dahil edilecek paketleri seçin",
+ search: "Paket ara...",
+ no_packages: "Kriterlerinize uyan paket bulunamadı",
+ filters: {
+ category: "Kategori",
+ type: "Tür",
+ repository: "Depo",
+ gui: "GUI Uygulamaları",
+ cli: "CLI Araçları",
+ official: "Sadece Resmi",
+ third_party: "Üçüncü Parti"
+ }
+ },
+ selection: {
+ title: "Seçilen Paketler",
+ description: "Bu paketler kurulum scriptinize dahil edilecek",
+ none: "Seçilen paket yok",
+ clear_all: "Tümünü Temizle",
+ generate_script: "Script Oluştur",
+ note: "Oluşturulan script yalnızca resmi depoları kullanacak ve idempotent olacak (birden çok kez çalıştırılması güvenli)."
+ },
+ script: {
+ title: "Kurulum Scripti",
+ description: "için idempotent script",
+ official_repos: "Resmi Depolar",
+ official_repos_desc: "Tüm paketler güvenilir kaynaklardan",
+ idempotent: "Idempotent",
+ idempotent_desc: "Birden çok kez çalıştırılması güvenli",
+ packages_count: "Paket",
+ packages_count_desc: "Kurulum için hazır",
+ included_packages: "Dahil Edilen Paketler:",
+ script_content: "Script İçeriği:",
+ copy: "Kopyala",
+ copied: "Kopyalandı!",
+ download: "İndir",
+ usage: "Nasıl kullanılır:",
+ usage_steps: [
+ "Script dosyasını hedef makinenize indirin",
+ "Çalıştırılabilir yapın (Linux/macOS için):",
+ "Scripti uygun izinlerle çalıştırın",
+ "Script otomatik olarak depo kurulumunu ve paket kurulumunu yönetecektir"
+ ]
+ }
+ }
+}
+
+export function useLocale() {
+ const [locale, setLocale] = useState('en')
+
+ useEffect(() => {
+ // Detect user's preferred locale
+ const detectLocale = (): Locale => {
+ const stored = localStorage.getItem('locale') as Locale
+ if (stored && (stored === 'en' || stored === 'tr')) {
+ return stored
+ }
+
+ // Get browser language
+ const browserLang = navigator.language.toLowerCase()
+ if (browserLang.startsWith('tr')) {
+ return 'tr'
+ }
+
+ return 'en'
+ }
+
+ setLocale(detectLocale())
+ }, [])
+
+ const changeLocale = (newLocale: Locale) => {
+ setLocale(newLocale)
+ localStorage.setItem('locale', newLocale)
+ }
+
+ const toggleLocale = () => {
+ changeLocale(locale === 'en' ? 'tr' : 'en')
+ }
+
+ const t = (key: string) => {
+ const keys = key.split('.')
+ let value: any = translations[locale]
+
+ for (const k of keys) {
+ value = value?.[k]
+ }
+
+ return value || key
+ }
+
+ return {
+ locale,
+ changeLocale,
+ toggleLocale,
+ t
+ }
+}
diff --git a/src/hooks/useTheme.ts b/src/hooks/useTheme.ts
new file mode 100644
index 0000000..ad69e0d
--- /dev/null
+++ b/src/hooks/useTheme.ts
@@ -0,0 +1,65 @@
+"use client"
+
+import { useState, useEffect } from 'react'
+
+type Theme = 'light' | 'dark' | 'system'
+
+export function useTheme() {
+ const [theme, setTheme] = useState('system')
+ const [isDark, setIsDark] = useState(false)
+
+ useEffect(() => {
+ // Get stored theme or default to system
+ const stored = localStorage.getItem('theme') as Theme
+ setTheme(stored || 'system')
+ }, [])
+
+ useEffect(() => {
+ const updateTheme = () => {
+ if (theme === 'system') {
+ setIsDark(window.matchMedia('(prefers-color-scheme: dark)').matches)
+ } else {
+ setIsDark(theme === 'dark')
+ }
+ }
+
+ updateTheme()
+
+ if (theme === 'system') {
+ const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
+ mediaQuery.addEventListener('change', updateTheme)
+ return () => mediaQuery.removeEventListener('change', updateTheme)
+ }
+ }, [theme])
+
+ useEffect(() => {
+ // Apply theme to document
+ if (isDark) {
+ document.documentElement.classList.add('dark')
+ } else {
+ document.documentElement.classList.remove('dark')
+ }
+ }, [isDark])
+
+ const setThemeMode = (newTheme: Theme) => {
+ setTheme(newTheme)
+ localStorage.setItem('theme', newTheme)
+ }
+
+ const toggleTheme = () => {
+ if (theme === 'light') {
+ setThemeMode('dark')
+ } else if (theme === 'dark') {
+ setThemeMode('light')
+ } else {
+ setThemeMode(isDark ? 'light' : 'dark')
+ }
+ }
+
+ return {
+ theme,
+ isDark,
+ setThemeMode,
+ toggleTheme
+ }
+}