This commit is contained in:
@@ -5,6 +5,7 @@ import { TemplatesSelector } from './TemplatesSelector'
|
||||
import { ExportDataModal } from './ExportDataModal'
|
||||
import { ImportDataModal } from './ImportDataModal'
|
||||
import { designTemplates, DesignTemplate } from '../constants/designTemplates'
|
||||
import { useLocale } from '../contexts/LocaleContext'
|
||||
|
||||
interface DesignSettings {
|
||||
id?: number
|
||||
@@ -77,6 +78,7 @@ interface CustomizationPanelProps {
|
||||
}
|
||||
|
||||
export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate, user, groups = [], onDataUpdate }: CustomizationPanelProps) {
|
||||
const { t } = useLocale()
|
||||
const [settings, setSettings] = useState<DesignSettings>({
|
||||
theme_color: '#ffffff',
|
||||
dashboard_layout: 'list',
|
||||
@@ -278,7 +280,7 @@ export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate, user, gr
|
||||
<div className="modal-header">
|
||||
<h5 className="modal-title">
|
||||
<i className="bi bi-palette me-2"></i>
|
||||
Настройки дашборда
|
||||
{t('customization.title')}
|
||||
</h5>
|
||||
<button
|
||||
type="button"
|
||||
@@ -296,7 +298,7 @@ export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate, user, gr
|
||||
onClick={() => setActiveTab('layout')}
|
||||
>
|
||||
<i className="bi bi-layout-sidebar me-1"></i>
|
||||
Макет
|
||||
{t('customization.layout')}
|
||||
</button>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
@@ -305,7 +307,7 @@ export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate, user, gr
|
||||
onClick={() => setActiveTab('colors')}
|
||||
>
|
||||
<i className="bi bi-palette-fill me-1"></i>
|
||||
Цвета
|
||||
{t('customization.colors')}
|
||||
</button>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
@@ -314,7 +316,7 @@ export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate, user, gr
|
||||
onClick={() => setActiveTab('groups')}
|
||||
>
|
||||
<i className="bi bi-collection me-1"></i>
|
||||
Группы
|
||||
{t('customization.groups')}
|
||||
</button>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
@@ -323,7 +325,7 @@ export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate, user, gr
|
||||
onClick={() => setActiveTab('templates')}
|
||||
>
|
||||
<i className="bi bi-palette me-1"></i>
|
||||
Шаблоны
|
||||
{t('customization.templates')}
|
||||
</button>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
@@ -332,7 +334,7 @@ export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate, user, gr
|
||||
onClick={() => setActiveTab('advanced')}
|
||||
>
|
||||
<i className="bi bi-gear me-1"></i>
|
||||
Дополнительно
|
||||
{t('customization.advanced')}
|
||||
</button>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
@@ -341,7 +343,7 @@ export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate, user, gr
|
||||
onClick={() => setActiveTab('data')}
|
||||
>
|
||||
<i className="bi bi-database me-1"></i>
|
||||
Данные
|
||||
{t('customization.data')}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -1215,10 +1217,10 @@ export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate, user, gr
|
||||
}
|
||||
}}
|
||||
disabled={loading}
|
||||
title="Сбросить все настройки к значениям по умолчанию"
|
||||
title={t('customization.resetSettings')}
|
||||
>
|
||||
<i className="bi bi-arrow-counterclockwise me-2"></i>
|
||||
Сбросить настройки
|
||||
{t('customization.resetSettings')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
@@ -1229,12 +1231,12 @@ export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate, user, gr
|
||||
{loading ? (
|
||||
<>
|
||||
<span className="spinner-border spinner-border-sm me-2"></span>
|
||||
Сохранение...
|
||||
{t('common.saving')}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<i className="bi bi-check-lg me-2"></i>
|
||||
Сохранить
|
||||
{t('common.save')}
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import React from 'react';
|
||||
import { useLocale, Locale } from '../contexts/LocaleContext';
|
||||
|
||||
const LanguageSelector: React.FC = () => {
|
||||
const { locale, setLocale, t } = useLocale();
|
||||
|
||||
const languages: Array<{ code: Locale; name: string }> = [
|
||||
{ code: 'en', name: 'English' },
|
||||
{ code: 'ru', name: 'Русский' },
|
||||
{ code: 'ko', name: '한국어' },
|
||||
{ code: 'zh', name: '中文' },
|
||||
{ code: 'ja', name: '日本語' },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="dropdown">
|
||||
<button
|
||||
className="btn btn-outline-secondary btn-sm dropdown-toggle"
|
||||
type="button"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
title={t('language.select')}
|
||||
>
|
||||
<i className="fas fa-globe me-1"></i>
|
||||
{languages.find(lang => lang.code === locale)?.name || 'Language'}
|
||||
</button>
|
||||
<ul className="dropdown-menu">
|
||||
{languages.map((language) => (
|
||||
<li key={language.code}>
|
||||
<button
|
||||
className={`dropdown-item ${locale === language.code ? 'active' : ''}`}
|
||||
onClick={() => setLocale(language.code)}
|
||||
>
|
||||
{language.name}
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LanguageSelector;
|
||||
@@ -6,6 +6,11 @@ import { usePathname, useRouter } from 'next/navigation'
|
||||
import Link from 'next/link'
|
||||
import Image from 'next/image'
|
||||
import Script from 'next/script'
|
||||
import { useLocale } from '../contexts/LocaleContext'
|
||||
import { useTheme } from '../contexts/ThemeContext'
|
||||
import ThemeToggle from './ThemeToggle'
|
||||
import LanguageSelector from './LanguageSelector'
|
||||
import '../layout.css'
|
||||
|
||||
interface User {
|
||||
username: string
|
||||
@@ -18,6 +23,7 @@ export function LayoutWrapper({ children }: { children: ReactNode }) {
|
||||
const isDashboard = pathname === '/dashboard'
|
||||
const [user, setUser] = useState<User | null>(null)
|
||||
const router = useRouter()
|
||||
const { t } = useLocale()
|
||||
|
||||
// При монтировании пробуем загрузить профиль
|
||||
useEffect(() => {
|
||||
@@ -71,16 +77,19 @@ export function LayoutWrapper({ children }: { children: ReactNode }) {
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#navcol-1"
|
||||
title={t('common.menu')}
|
||||
/>
|
||||
<div className="collapse navbar-collapse" id="navcol-1">
|
||||
{!user && (
|
||||
<Link href="/auth/login" className="btn btn-primary ms-auto">
|
||||
<i className="fa fa-user"></i>
|
||||
<span className="d-none d-sm-inline"> Вход</span>
|
||||
<span className="d-none d-sm-inline"> {t('common.login')}</span>
|
||||
</Link>
|
||||
)}
|
||||
{user && (
|
||||
<div className="ms-auto d-flex align-items-center gap-3">
|
||||
<ThemeToggle />
|
||||
<LanguageSelector />
|
||||
<Image
|
||||
src={
|
||||
user.avatar && user.avatar.startsWith('http')
|
||||
@@ -97,14 +106,14 @@ export function LayoutWrapper({ children }: { children: ReactNode }) {
|
||||
<span>{user.username}</span>
|
||||
{!isDashboard && (
|
||||
<Link href="/dashboard" className="btn btn-outline-secondary btn-sm">
|
||||
Дашборд
|
||||
{t('dashboard.title')}
|
||||
</Link>
|
||||
)}
|
||||
<button
|
||||
onClick={handleLogout}
|
||||
className="btn btn-outline-danger btn-sm"
|
||||
>
|
||||
Выход
|
||||
{t('common.logout')}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
@@ -114,7 +123,7 @@ export function LayoutWrapper({ children }: { children: ReactNode }) {
|
||||
)}
|
||||
|
||||
{/* отступ, чтобы контент не прятался под фиксированным хедером */}
|
||||
{!isPublicUserPage && <div style={{ height: 70 }} />}
|
||||
{!isPublicUserPage && <div className="navbar-spacing" />}
|
||||
|
||||
{children}
|
||||
|
||||
|
||||
19
frontend/linktree-frontend/src/app/components/Providers.tsx
Normal file
19
frontend/linktree-frontend/src/app/components/Providers.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import React from 'react';
|
||||
import { ThemeProvider } from '../contexts/ThemeContext';
|
||||
import { LocaleProvider } from '../contexts/LocaleContext';
|
||||
|
||||
interface ProvidersProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const Providers: React.FC<ProvidersProps> = ({ children }) => {
|
||||
return (
|
||||
<LocaleProvider>
|
||||
<ThemeProvider>
|
||||
{children}
|
||||
</ThemeProvider>
|
||||
</LocaleProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default Providers;
|
||||
@@ -0,0 +1,31 @@
|
||||
'use client'
|
||||
|
||||
import React from 'react'
|
||||
import { useTheme } from '../contexts/ThemeContext'
|
||||
|
||||
interface ThemeToggleProps {
|
||||
className?: string
|
||||
showLabel?: boolean
|
||||
}
|
||||
|
||||
export const ThemeToggle: React.FC<ThemeToggleProps> = ({
|
||||
className = '',
|
||||
showLabel = true
|
||||
}) => {
|
||||
const { theme, toggleTheme } = useTheme()
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={toggleTheme}
|
||||
className={`btn btn-outline-secondary d-flex align-items-center ${className}`}
|
||||
title={theme === 'light' ? 'Переключить на темную тему' : 'Переключить на светлую тему'}
|
||||
>
|
||||
<i className={`bi ${theme === 'light' ? 'bi-moon' : 'bi-sun'} ${showLabel ? 'me-2' : ''}`}></i>
|
||||
{showLabel && (
|
||||
<span>{theme === 'light' ? 'Темная тема' : 'Светлая тема'}</span>
|
||||
)}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
export default ThemeToggle
|
||||
@@ -0,0 +1,97 @@
|
||||
'use client'
|
||||
|
||||
import React, { createContext, useContext, useEffect, useState } from 'react'
|
||||
|
||||
export type Locale = 'en' | 'ru' | 'ko' | 'zh' | 'ja'
|
||||
|
||||
interface LocaleContextType {
|
||||
locale: Locale
|
||||
setLocale: (locale: Locale) => void
|
||||
t: (key: string, params?: Record<string, string | number>) => string
|
||||
}
|
||||
|
||||
const LocaleContext = createContext<LocaleContextType | undefined>(undefined)
|
||||
|
||||
export const useLocale = () => {
|
||||
const context = useContext(LocaleContext)
|
||||
if (!context) {
|
||||
throw new Error('useLocale must be used within a LocaleProvider')
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
interface LocaleProviderProps {
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
// Функция для загрузки переводов
|
||||
const loadTranslations = async (locale: Locale): Promise<Record<string, string>> => {
|
||||
try {
|
||||
const translations = await import(`../locales/${locale}.json`)
|
||||
return translations.default
|
||||
} catch (error) {
|
||||
console.warn(`Failed to load translations for ${locale}, falling back to English`)
|
||||
const fallback = await import('../locales/en.json')
|
||||
return fallback.default
|
||||
}
|
||||
}
|
||||
|
||||
export const LocaleProvider: React.FC<LocaleProviderProps> = ({ children }) => {
|
||||
const [locale, setLocaleState] = useState<Locale>('ru')
|
||||
const [translations, setTranslations] = useState<Record<string, string>>({})
|
||||
|
||||
// Загружаем локаль из localStorage и браузера
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const savedLocale = localStorage.getItem('locale') as Locale
|
||||
const browserLocale = navigator.language.toLowerCase()
|
||||
|
||||
let initialLocale: Locale = 'en'
|
||||
|
||||
if (savedLocale) {
|
||||
initialLocale = savedLocale
|
||||
} else if (browserLocale.startsWith('ru')) {
|
||||
initialLocale = 'ru'
|
||||
} else if (browserLocale.startsWith('ko')) {
|
||||
initialLocale = 'ko'
|
||||
} else if (browserLocale.startsWith('zh')) {
|
||||
initialLocale = 'zh'
|
||||
} else if (browserLocale.startsWith('ja')) {
|
||||
initialLocale = 'ja'
|
||||
}
|
||||
|
||||
setLocaleState(initialLocale)
|
||||
}
|
||||
}, [])
|
||||
|
||||
// Загружаем переводы при изменении локали
|
||||
useEffect(() => {
|
||||
loadTranslations(locale).then(setTranslations)
|
||||
}, [locale])
|
||||
|
||||
const setLocale = (newLocale: Locale) => {
|
||||
setLocaleState(newLocale)
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem('locale', newLocale)
|
||||
}
|
||||
}
|
||||
|
||||
// Функция перевода с поддержкой интерполяции
|
||||
const t = (key: string, params?: Record<string, string | number>): string => {
|
||||
let translation = translations[key] || key
|
||||
|
||||
if (params) {
|
||||
Object.entries(params).forEach(([paramKey, paramValue]) => {
|
||||
translation = translation.replace(new RegExp(`{{${paramKey}}}`, 'g'), String(paramValue))
|
||||
})
|
||||
}
|
||||
|
||||
return translation
|
||||
}
|
||||
|
||||
return (
|
||||
<LocaleContext.Provider value={{ locale, setLocale, t }}>
|
||||
{children}
|
||||
</LocaleContext.Provider>
|
||||
)
|
||||
}
|
||||
67
frontend/linktree-frontend/src/app/contexts/ThemeContext.tsx
Normal file
67
frontend/linktree-frontend/src/app/contexts/ThemeContext.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
'use client'
|
||||
|
||||
import React, { createContext, useContext, useEffect, useState } from 'react'
|
||||
|
||||
export type Theme = 'light' | 'dark'
|
||||
|
||||
interface ThemeContextType {
|
||||
theme: Theme
|
||||
setTheme: (theme: Theme) => void
|
||||
toggleTheme: () => void
|
||||
}
|
||||
|
||||
const ThemeContext = createContext<ThemeContextType | undefined>(undefined)
|
||||
|
||||
export const useTheme = () => {
|
||||
const context = useContext(ThemeContext)
|
||||
if (!context) {
|
||||
throw new Error('useTheme must be used within a ThemeProvider')
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
interface ThemeProviderProps {
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export const ThemeProvider: React.FC<ThemeProviderProps> = ({ children }) => {
|
||||
const [theme, setThemeState] = useState<Theme>('light')
|
||||
|
||||
// Загружаем тему из localStorage при инициализации
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const savedTheme = localStorage.getItem('theme') as Theme
|
||||
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
||||
const initialTheme = savedTheme || systemTheme
|
||||
setThemeState(initialTheme)
|
||||
applyTheme(initialTheme)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const applyTheme = (newTheme: Theme) => {
|
||||
if (typeof document !== 'undefined') {
|
||||
document.documentElement.classList.remove('light', 'dark')
|
||||
document.documentElement.classList.add(newTheme)
|
||||
document.documentElement.setAttribute('data-theme', newTheme)
|
||||
}
|
||||
}
|
||||
|
||||
const setTheme = (newTheme: Theme) => {
|
||||
setThemeState(newTheme)
|
||||
applyTheme(newTheme)
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem('theme', newTheme)
|
||||
}
|
||||
}
|
||||
|
||||
const toggleTheme = () => {
|
||||
const newTheme = theme === 'light' ? 'dark' : 'light'
|
||||
setTheme(newTheme)
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={{ theme, setTheme, toggleTheme }}>
|
||||
{children}
|
||||
</ThemeContext.Provider>
|
||||
)
|
||||
}
|
||||
4
frontend/linktree-frontend/src/app/layout.css
Normal file
4
frontend/linktree-frontend/src/app/layout.css
Normal file
@@ -0,0 +1,4 @@
|
||||
/* Layout spacing */
|
||||
.navbar-spacing {
|
||||
height: 70px;
|
||||
}
|
||||
@@ -2,8 +2,10 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Geist, Geist_Mono } from "next/font/google";
|
||||
import "./globals.css";
|
||||
import "./themes.css";
|
||||
import { ReactNode } from "react";
|
||||
import { LayoutWrapper } from "./components/LayoutWrapper";
|
||||
import Providers from "./components/Providers";
|
||||
|
||||
const geistSans = Geist({
|
||||
variable: "--font-geist-sans",
|
||||
@@ -73,7 +75,9 @@ export default function RootLayout({
|
||||
<body
|
||||
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
||||
>
|
||||
<LayoutWrapper>{children}</LayoutWrapper>
|
||||
<Providers>
|
||||
<LayoutWrapper>{children}</LayoutWrapper>
|
||||
</Providers>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
195
frontend/linktree-frontend/src/app/locales/en.json
Normal file
195
frontend/linktree-frontend/src/app/locales/en.json
Normal file
@@ -0,0 +1,195 @@
|
||||
{
|
||||
"common.cancel": "Cancel",
|
||||
"common.save": "Save",
|
||||
"common.saving": "Saving...",
|
||||
"common.loading": "Loading...",
|
||||
"common.error": "Error",
|
||||
"common.success": "Success",
|
||||
"common.close": "Close",
|
||||
"common.edit": "Edit",
|
||||
"common.delete": "Delete",
|
||||
"common.add": "Add",
|
||||
"common.create": "Create",
|
||||
"common.update": "Update",
|
||||
"common.search": "Search",
|
||||
"common.settings": "Settings",
|
||||
"common.profile": "Profile",
|
||||
"common.logout": "Logout",
|
||||
"common.login": "Login",
|
||||
"common.register": "Register",
|
||||
"common.back": "Back",
|
||||
"common.next": "Next",
|
||||
"common.previous": "Previous",
|
||||
"common.submit": "Submit",
|
||||
"common.reset": "Reset",
|
||||
"common.clear": "Clear",
|
||||
"common.confirm": "Confirm",
|
||||
"common.yes": "Yes",
|
||||
"common.no": "No",
|
||||
"common.menu": "Menu",
|
||||
|
||||
"auth.login.title": "Login",
|
||||
"auth.login.email": "Email",
|
||||
"auth.login.password": "Password",
|
||||
"auth.login.remember": "Remember me",
|
||||
"auth.login.forgot": "Forgot password?",
|
||||
"auth.login.noAccount": "Don't have an account?",
|
||||
"auth.login.signUp": "Sign up",
|
||||
|
||||
"auth.register.title": "Register",
|
||||
"auth.register.username": "Username",
|
||||
"auth.register.email": "Email",
|
||||
"auth.register.password": "Password",
|
||||
"auth.register.confirmPassword": "Confirm password",
|
||||
"auth.register.firstName": "First name",
|
||||
"auth.register.lastName": "Last name",
|
||||
"auth.register.haveAccount": "Already have an account?",
|
||||
"auth.register.signIn": "Sign in",
|
||||
|
||||
"dashboard.title": "Dashboard",
|
||||
"dashboard.welcome": "Welcome, {{name}}!",
|
||||
"dashboard.groups": "Groups",
|
||||
"dashboard.links": "Links",
|
||||
"dashboard.settings": "Settings",
|
||||
"dashboard.customize": "Customize",
|
||||
"dashboard.addGroup": "Add Group",
|
||||
"dashboard.addLink": "Add Link",
|
||||
"dashboard.noGroups": "No groups yet",
|
||||
"dashboard.noLinks": "No links yet",
|
||||
"dashboard.createFirst": "Create your first",
|
||||
|
||||
"group.create": "Create Group",
|
||||
"group.edit": "Edit Group",
|
||||
"group.name": "Group name",
|
||||
"group.description": "Description",
|
||||
"group.icon": "Icon",
|
||||
"group.background": "Background image",
|
||||
"group.color": "Header color",
|
||||
"group.public": "Public",
|
||||
"group.favorite": "Favorite",
|
||||
"group.expanded": "Expanded by default",
|
||||
"group.removeIcon": "Remove icon",
|
||||
"group.removeBackground": "Remove background",
|
||||
|
||||
"link.create": "Create Link",
|
||||
"link.edit": "Edit Link",
|
||||
"link.title": "Link title",
|
||||
"link.url": "URL",
|
||||
"link.description": "Description",
|
||||
"link.icon": "Icon",
|
||||
"link.removeIcon": "Remove icon",
|
||||
"link.public": "Public",
|
||||
"link.featured": "Featured",
|
||||
|
||||
"profile.edit": "Edit Profile",
|
||||
"profile.username": "Username",
|
||||
"profile.email": "Email",
|
||||
"profile.firstName": "First name",
|
||||
"profile.lastName": "Last name",
|
||||
"profile.fullName": "Full name",
|
||||
"profile.bio": "Bio",
|
||||
"profile.avatar": "Avatar",
|
||||
"profile.cover": "Cover image",
|
||||
"profile.removeAvatar": "Remove avatar",
|
||||
"profile.removeCover": "Remove cover",
|
||||
|
||||
"customization.title": "Customization",
|
||||
"customization.templates": "Templates",
|
||||
"customization.layout": "Layout",
|
||||
"customization.colors": "Colors",
|
||||
"customization.groups": "Groups",
|
||||
"customization.advanced": "Advanced",
|
||||
"customization.data": "Data",
|
||||
|
||||
"customization.layout.style": "Display style for groups and links",
|
||||
"customization.layout.list": "List",
|
||||
"customization.layout.grid": "Grid",
|
||||
"customization.layout.cards": "Cards",
|
||||
"customization.layout.compact": "Compact",
|
||||
"customization.layout.masonry": "Masonry",
|
||||
"customization.layout.timeline": "Timeline",
|
||||
"customization.layout.magazine": "Magazine",
|
||||
|
||||
"customization.colors.theme": "Theme color",
|
||||
"customization.colors.background": "Background color",
|
||||
"customization.colors.backgroundImage": "Background image",
|
||||
"customization.colors.removeBackground": "Remove background",
|
||||
"customization.colors.header": "Header text color",
|
||||
"customization.colors.group": "Group text color",
|
||||
"customization.colors.link": "Link text color",
|
||||
|
||||
"customization.groups.showIcons": "Show group icons",
|
||||
"customization.groups.showLinks": "Show link icons",
|
||||
"customization.groups.defaultExpanded": "Groups expanded by default",
|
||||
"customization.groups.showTitle": "Show groups title",
|
||||
|
||||
"customization.advanced.fonts": "Font settings",
|
||||
"customization.advanced.mainFont": "Main font",
|
||||
"customization.advanced.headingFont": "Heading font",
|
||||
"customization.advanced.bodyFont": "Body font",
|
||||
"customization.advanced.customCSS": "Custom CSS",
|
||||
|
||||
"customization.data.title": "Profile data export and import",
|
||||
"customization.data.description": "Create backups of your profile data or restore them from archive",
|
||||
"customization.data.export.title": "Export data",
|
||||
"customization.data.export.description": "Create archive with profile data for backup or transfer",
|
||||
"customization.data.export.button": "Create export",
|
||||
"customization.data.import.title": "Import data",
|
||||
"customization.data.import.description": "Upload and restore data from export archive",
|
||||
"customization.data.import.file": "Select archive file (.zip)",
|
||||
"customization.data.import.button": "Open import wizard",
|
||||
"customization.data.history.title": "Operation history",
|
||||
"customization.data.history.description": "Export and import history will be displayed here",
|
||||
|
||||
"customization.resetSettings": "Reset settings",
|
||||
"customization.resetConfirm": "Are you sure you want to reset all interface settings to default values? This action cannot be undone.",
|
||||
|
||||
"export.title": "Export profile data",
|
||||
"export.description": "Select data to include in export archive",
|
||||
"export.general": "General data",
|
||||
"export.profile": "Profile data (name, bio, avatar)",
|
||||
"export.styles": "Design settings and styles",
|
||||
"export.media": "Media files (images, icons)",
|
||||
"export.groupsLinks": "Groups and links",
|
||||
"export.selectedCount": "{{groups}} groups, {{links}} links",
|
||||
"export.createButton": "Create and download",
|
||||
"export.creating": "Creating export...",
|
||||
|
||||
"import.title": "Import profile data",
|
||||
"import.selectFile": "Select archive for import",
|
||||
"import.analyzing": "Analyzing archive...",
|
||||
"import.content": "Archive content",
|
||||
"import.exportInfo": "Export information",
|
||||
"import.source": "Source",
|
||||
"import.exportDate": "Export date",
|
||||
"import.dataStats": "Data statistics",
|
||||
"import.groups": "Groups",
|
||||
"import.links": "Links",
|
||||
"import.designSettings": "Design settings",
|
||||
"import.mediaFiles": "Media files",
|
||||
"import.yes": "Yes",
|
||||
"import.no": "No",
|
||||
"import.groupsPreview": "Groups (first 5)",
|
||||
"import.linksPreview": "Links (first 10)",
|
||||
"import.settings": "Import settings",
|
||||
"import.importGroups": "Import groups ({{count}})",
|
||||
"import.importLinks": "Import links ({{count}})",
|
||||
"import.importStyles": "Import design settings",
|
||||
"import.importMedia": "Import media files ({{count}})",
|
||||
"import.overwriteExisting": "Overwrite existing data",
|
||||
"import.overwriteHelp": "If disabled, existing groups and links with the same names will be skipped",
|
||||
"import.unavailable": "(unavailable)",
|
||||
"import.button": "Import",
|
||||
"import.importing": "Importing...",
|
||||
|
||||
"theme.toggle": "Toggle theme",
|
||||
"theme.light": "Light theme",
|
||||
"theme.dark": "Dark theme",
|
||||
|
||||
"language.select": "Select language",
|
||||
"language.en": "English",
|
||||
"language.ru": "Русский",
|
||||
"language.ko": "한국어",
|
||||
"language.zh": "中文",
|
||||
"language.ja": "日本語"
|
||||
}
|
||||
195
frontend/linktree-frontend/src/app/locales/ja.json
Normal file
195
frontend/linktree-frontend/src/app/locales/ja.json
Normal file
@@ -0,0 +1,195 @@
|
||||
{
|
||||
"common.cancel": "キャンセル",
|
||||
"common.save": "保存",
|
||||
"common.saving": "保存中...",
|
||||
"common.loading": "読み込み中...",
|
||||
"common.error": "エラー",
|
||||
"common.success": "成功",
|
||||
"common.close": "閉じる",
|
||||
"common.edit": "編集",
|
||||
"common.delete": "削除",
|
||||
"common.add": "追加",
|
||||
"common.create": "作成",
|
||||
"common.update": "更新",
|
||||
"common.search": "検索",
|
||||
"common.settings": "設定",
|
||||
"common.profile": "プロフィール",
|
||||
"common.logout": "ログアウト",
|
||||
"common.login": "ログイン",
|
||||
"common.register": "登録",
|
||||
"common.back": "戻る",
|
||||
"common.next": "次へ",
|
||||
"common.previous": "前へ",
|
||||
"common.submit": "送信",
|
||||
"common.reset": "リセット",
|
||||
"common.clear": "クリア",
|
||||
"common.confirm": "確認",
|
||||
"common.yes": "はい",
|
||||
"common.no": "いいえ",
|
||||
"common.menu": "メニュー",
|
||||
|
||||
"auth.login.title": "ログイン",
|
||||
"auth.login.email": "メール",
|
||||
"auth.login.password": "パスワード",
|
||||
"auth.login.remember": "ログイン状態を保持",
|
||||
"auth.login.forgot": "パスワードを忘れましたか?",
|
||||
"auth.login.noAccount": "アカウントをお持ちでない方",
|
||||
"auth.login.signUp": "新規登録",
|
||||
|
||||
"auth.register.title": "新規登録",
|
||||
"auth.register.username": "ユーザー名",
|
||||
"auth.register.email": "メール",
|
||||
"auth.register.password": "パスワード",
|
||||
"auth.register.confirmPassword": "パスワード確認",
|
||||
"auth.register.firstName": "名",
|
||||
"auth.register.lastName": "姓",
|
||||
"auth.register.haveAccount": "既にアカウントをお持ちの方",
|
||||
"auth.register.signIn": "ログイン",
|
||||
|
||||
"dashboard.title": "ダッシュボード",
|
||||
"dashboard.welcome": "{{name}}さん、ようこそ!",
|
||||
"dashboard.groups": "グループ",
|
||||
"dashboard.links": "リンク",
|
||||
"dashboard.settings": "設定",
|
||||
"dashboard.customize": "カスタマイズ",
|
||||
"dashboard.addGroup": "グループ追加",
|
||||
"dashboard.addLink": "リンク追加",
|
||||
"dashboard.noGroups": "グループがありません",
|
||||
"dashboard.noLinks": "リンクがありません",
|
||||
"dashboard.createFirst": "最初の作成",
|
||||
|
||||
"group.create": "グループ作成",
|
||||
"group.edit": "グループ編集",
|
||||
"group.name": "グループ名",
|
||||
"group.description": "説明",
|
||||
"group.icon": "アイコン",
|
||||
"group.background": "背景画像",
|
||||
"group.color": "ヘッダー色",
|
||||
"group.public": "公開",
|
||||
"group.favorite": "お気に入り",
|
||||
"group.expanded": "デフォルトで展開",
|
||||
"group.removeIcon": "アイコンを削除",
|
||||
"group.removeBackground": "背景を削除",
|
||||
|
||||
"link.create": "リンク作成",
|
||||
"link.edit": "リンク編集",
|
||||
"link.title": "リンクタイトル",
|
||||
"link.url": "URL",
|
||||
"link.description": "説明",
|
||||
"link.icon": "アイコン",
|
||||
"link.removeIcon": "アイコンを削除",
|
||||
"link.public": "公開",
|
||||
"link.featured": "おすすめ",
|
||||
|
||||
"profile.edit": "プロフィール編集",
|
||||
"profile.username": "ユーザー名",
|
||||
"profile.email": "メール",
|
||||
"profile.firstName": "名",
|
||||
"profile.lastName": "姓",
|
||||
"profile.fullName": "氏名",
|
||||
"profile.bio": "自己紹介",
|
||||
"profile.avatar": "アバター",
|
||||
"profile.cover": "カバー画像",
|
||||
"profile.removeAvatar": "アバターを削除",
|
||||
"profile.removeCover": "カバーを削除",
|
||||
|
||||
"customization.title": "カスタマイゼーション",
|
||||
"customization.templates": "テンプレート",
|
||||
"customization.layout": "レイアウト",
|
||||
"customization.colors": "色",
|
||||
"customization.groups": "グループ",
|
||||
"customization.advanced": "詳細設定",
|
||||
"customization.data": "データ",
|
||||
|
||||
"customization.layout.style": "グループとリンクの表示スタイル",
|
||||
"customization.layout.list": "リスト",
|
||||
"customization.layout.grid": "グリッド",
|
||||
"customization.layout.cards": "カード",
|
||||
"customization.layout.compact": "コンパクト",
|
||||
"customization.layout.masonry": "メイソンリー",
|
||||
"customization.layout.timeline": "タイムライン",
|
||||
"customization.layout.magazine": "マガジン",
|
||||
|
||||
"customization.colors.theme": "テーマカラー",
|
||||
"customization.colors.background": "背景色",
|
||||
"customization.colors.backgroundImage": "背景画像",
|
||||
"customization.colors.removeBackground": "背景を削除",
|
||||
"customization.colors.header": "ヘッダーテキスト色",
|
||||
"customization.colors.group": "グループテキスト色",
|
||||
"customization.colors.link": "リンクテキスト色",
|
||||
|
||||
"customization.groups.showIcons": "グループアイコンを表示",
|
||||
"customization.groups.showLinks": "リンクアイコンを表示",
|
||||
"customization.groups.defaultExpanded": "グループをデフォルトで展開",
|
||||
"customization.groups.showTitle": "グループタイトルを表示",
|
||||
|
||||
"customization.advanced.fonts": "フォント設定",
|
||||
"customization.advanced.mainFont": "メインフォント",
|
||||
"customization.advanced.headingFont": "見出しフォント",
|
||||
"customization.advanced.bodyFont": "本文フォント",
|
||||
"customization.advanced.customCSS": "カスタムCSS",
|
||||
|
||||
"customization.data.title": "プロフィールデータのエクスポートとインポート",
|
||||
"customization.data.description": "プロフィールデータのバックアップを作成するか、アーカイブから復元します",
|
||||
"customization.data.export.title": "データエクスポート",
|
||||
"customization.data.export.description": "バックアップや転送のためのプロフィールデータアーカイブを作成",
|
||||
"customization.data.export.button": "エクスポート作成",
|
||||
"customization.data.import.title": "データインポート",
|
||||
"customization.data.import.description": "エクスポートアーカイブからデータをアップロードして復元",
|
||||
"customization.data.import.file": "アーカイブファイルを選択 (.zip)",
|
||||
"customization.data.import.button": "インポートウィザードを開く",
|
||||
"customization.data.history.title": "操作履歴",
|
||||
"customization.data.history.description": "エクスポートとインポートの履歴がここに表示されます",
|
||||
|
||||
"customization.resetSettings": "設定をリセット",
|
||||
"customization.resetConfirm": "すべてのインターフェース設定をデフォルト値にリセットしますか?この操作は元に戻せません。",
|
||||
|
||||
"export.title": "プロフィールデータのエクスポート",
|
||||
"export.description": "エクスポートアーカイブに含めるデータを選択",
|
||||
"export.general": "一般データ",
|
||||
"export.profile": "プロフィールデータ(名前、自己紹介、アバター)",
|
||||
"export.styles": "デザイン設定とスタイル",
|
||||
"export.media": "メディアファイル(画像、アイコン)",
|
||||
"export.groupsLinks": "グループとリンク",
|
||||
"export.selectedCount": "{{groups}}個のグループ、{{links}}個のリンク",
|
||||
"export.createButton": "作成してダウンロード",
|
||||
"export.creating": "エクスポート作成中...",
|
||||
|
||||
"import.title": "プロフィールデータのインポート",
|
||||
"import.selectFile": "インポートするアーカイブを選択",
|
||||
"import.analyzing": "アーカイブ分析中...",
|
||||
"import.content": "アーカイブ内容",
|
||||
"import.exportInfo": "エクスポート情報",
|
||||
"import.source": "ソース",
|
||||
"import.exportDate": "エクスポート日",
|
||||
"import.dataStats": "データ統計",
|
||||
"import.groups": "グループ",
|
||||
"import.links": "リンク",
|
||||
"import.designSettings": "デザイン設定",
|
||||
"import.mediaFiles": "メディアファイル",
|
||||
"import.yes": "あり",
|
||||
"import.no": "なし",
|
||||
"import.groupsPreview": "グループ(最初の5個)",
|
||||
"import.linksPreview": "リンク(最初の10個)",
|
||||
"import.settings": "インポート設定",
|
||||
"import.importGroups": "グループをインポート({{count}}個)",
|
||||
"import.importLinks": "リンクをインポート({{count}}個)",
|
||||
"import.importStyles": "デザイン設定をインポート",
|
||||
"import.importMedia": "メディアファイルをインポート({{count}}個)",
|
||||
"import.overwriteExisting": "既存データを上書き",
|
||||
"import.overwriteHelp": "無効にすると、同じ名前の既存グループとリンクはスキップされます",
|
||||
"import.unavailable": "(利用不可)",
|
||||
"import.button": "インポート",
|
||||
"import.importing": "インポート中...",
|
||||
|
||||
"theme.toggle": "テーマ切り替え",
|
||||
"theme.light": "ライトテーマ",
|
||||
"theme.dark": "ダークテーマ",
|
||||
|
||||
"language.select": "言語を選択",
|
||||
"language.en": "English",
|
||||
"language.ru": "Русский",
|
||||
"language.ko": "한국어",
|
||||
"language.zh": "中文",
|
||||
"language.ja": "日本語"
|
||||
}
|
||||
195
frontend/linktree-frontend/src/app/locales/ko.json
Normal file
195
frontend/linktree-frontend/src/app/locales/ko.json
Normal file
@@ -0,0 +1,195 @@
|
||||
{
|
||||
"common.cancel": "취소",
|
||||
"common.save": "저장",
|
||||
"common.saving": "저장 중...",
|
||||
"common.loading": "로딩 중...",
|
||||
"common.error": "오류",
|
||||
"common.success": "성공",
|
||||
"common.close": "닫기",
|
||||
"common.edit": "편집",
|
||||
"common.delete": "삭제",
|
||||
"common.add": "추가",
|
||||
"common.create": "생성",
|
||||
"common.update": "업데이트",
|
||||
"common.search": "검색",
|
||||
"common.settings": "설정",
|
||||
"common.profile": "프로필",
|
||||
"common.logout": "로그아웃",
|
||||
"common.login": "로그인",
|
||||
"common.register": "회원가입",
|
||||
"common.back": "뒤로",
|
||||
"common.next": "다음",
|
||||
"common.previous": "이전",
|
||||
"common.submit": "제출",
|
||||
"common.reset": "재설정",
|
||||
"common.clear": "지우기",
|
||||
"common.confirm": "확인",
|
||||
"common.yes": "예",
|
||||
"common.no": "아니오",
|
||||
"common.menu": "메뉴",
|
||||
|
||||
"auth.login.title": "로그인",
|
||||
"auth.login.email": "이메일",
|
||||
"auth.login.password": "비밀번호",
|
||||
"auth.login.remember": "기억하기",
|
||||
"auth.login.forgot": "비밀번호를 잊으셨나요?",
|
||||
"auth.login.noAccount": "계정이 없으신가요?",
|
||||
"auth.login.signUp": "회원가입",
|
||||
|
||||
"auth.register.title": "회원가입",
|
||||
"auth.register.username": "사용자명",
|
||||
"auth.register.email": "이메일",
|
||||
"auth.register.password": "비밀번호",
|
||||
"auth.register.confirmPassword": "비밀번호 확인",
|
||||
"auth.register.firstName": "이름",
|
||||
"auth.register.lastName": "성",
|
||||
"auth.register.haveAccount": "이미 계정이 있으신가요?",
|
||||
"auth.register.signIn": "로그인",
|
||||
|
||||
"dashboard.title": "대시보드",
|
||||
"dashboard.welcome": "환영합니다, {{name}}님!",
|
||||
"dashboard.groups": "그룹",
|
||||
"dashboard.links": "링크",
|
||||
"dashboard.settings": "설정",
|
||||
"dashboard.customize": "커스터마이즈",
|
||||
"dashboard.addGroup": "그룹 추가",
|
||||
"dashboard.addLink": "링크 추가",
|
||||
"dashboard.noGroups": "그룹이 없습니다",
|
||||
"dashboard.noLinks": "링크가 없습니다",
|
||||
"dashboard.createFirst": "첫 번째 생성하기",
|
||||
|
||||
"group.create": "그룹 생성",
|
||||
"group.edit": "그룹 편집",
|
||||
"group.name": "그룹 이름",
|
||||
"group.description": "설명",
|
||||
"group.icon": "아이콘",
|
||||
"group.background": "배경 이미지",
|
||||
"group.color": "헤더 색상",
|
||||
"group.public": "공개",
|
||||
"group.favorite": "즐겨찾기",
|
||||
"group.expanded": "기본으로 펼침",
|
||||
"group.removeIcon": "아이콘 제거",
|
||||
"group.removeBackground": "배경 제거",
|
||||
|
||||
"link.create": "링크 생성",
|
||||
"link.edit": "링크 편집",
|
||||
"link.title": "링크 제목",
|
||||
"link.url": "URL",
|
||||
"link.description": "설명",
|
||||
"link.icon": "아이콘",
|
||||
"link.removeIcon": "아이콘 제거",
|
||||
"link.public": "공개",
|
||||
"link.featured": "추천",
|
||||
|
||||
"profile.edit": "프로필 편집",
|
||||
"profile.username": "사용자명",
|
||||
"profile.email": "이메일",
|
||||
"profile.firstName": "이름",
|
||||
"profile.lastName": "성",
|
||||
"profile.fullName": "전체 이름",
|
||||
"profile.bio": "자기소개",
|
||||
"profile.avatar": "아바타",
|
||||
"profile.cover": "커버 이미지",
|
||||
"profile.removeAvatar": "아바타 제거",
|
||||
"profile.removeCover": "커버 제거",
|
||||
|
||||
"customization.title": "커스터마이제이션",
|
||||
"customization.templates": "템플릿",
|
||||
"customization.layout": "레이아웃",
|
||||
"customization.colors": "색상",
|
||||
"customization.groups": "그룹",
|
||||
"customization.advanced": "고급",
|
||||
"customization.data": "데이터",
|
||||
|
||||
"customization.layout.style": "그룹 및 링크 표시 스타일",
|
||||
"customization.layout.list": "목록",
|
||||
"customization.layout.grid": "그리드",
|
||||
"customization.layout.cards": "카드",
|
||||
"customization.layout.compact": "컴팩트",
|
||||
"customization.layout.masonry": "메이슨리",
|
||||
"customization.layout.timeline": "타임라인",
|
||||
"customization.layout.magazine": "매거진",
|
||||
|
||||
"customization.colors.theme": "테마 색상",
|
||||
"customization.colors.background": "배경 색상",
|
||||
"customization.colors.backgroundImage": "배경 이미지",
|
||||
"customization.colors.removeBackground": "배경 제거",
|
||||
"customization.colors.header": "헤더 텍스트 색상",
|
||||
"customization.colors.group": "그룹 텍스트 색상",
|
||||
"customization.colors.link": "링크 텍스트 색상",
|
||||
|
||||
"customization.groups.showIcons": "그룹 아이콘 표시",
|
||||
"customization.groups.showLinks": "링크 아이콘 표시",
|
||||
"customization.groups.defaultExpanded": "그룹 기본 펼침",
|
||||
"customization.groups.showTitle": "그룹 제목 표시",
|
||||
|
||||
"customization.advanced.fonts": "폰트 설정",
|
||||
"customization.advanced.mainFont": "기본 폰트",
|
||||
"customization.advanced.headingFont": "제목 폰트",
|
||||
"customization.advanced.bodyFont": "본문 폰트",
|
||||
"customization.advanced.customCSS": "사용자 정의 CSS",
|
||||
|
||||
"customization.data.title": "프로필 데이터 내보내기 및 가져오기",
|
||||
"customization.data.description": "프로필 데이터의 백업을 생성하거나 아카이브에서 복원하세요",
|
||||
"customization.data.export.title": "데이터 내보내기",
|
||||
"customization.data.export.description": "백업이나 이전을 위한 프로필 데이터 아카이브 생성",
|
||||
"customization.data.export.button": "내보내기 생성",
|
||||
"customization.data.import.title": "데이터 가져오기",
|
||||
"customization.data.import.description": "내보내기 아카이브에서 데이터 업로드 및 복원",
|
||||
"customization.data.import.file": "아카이브 파일 선택 (.zip)",
|
||||
"customization.data.import.button": "가져오기 마법사 열기",
|
||||
"customization.data.history.title": "작업 기록",
|
||||
"customization.data.history.description": "내보내기 및 가져오기 기록이 여기에 표시됩니다",
|
||||
|
||||
"customization.resetSettings": "설정 재설정",
|
||||
"customization.resetConfirm": "모든 인터페이스 설정을 기본값으로 재설정하시겠습니까? 이 작업은 되돌릴 수 없습니다.",
|
||||
|
||||
"export.title": "프로필 데이터 내보내기",
|
||||
"export.description": "내보내기 아카이브에 포함할 데이터 선택",
|
||||
"export.general": "일반 데이터",
|
||||
"export.profile": "프로필 데이터 (이름, 소개, 아바타)",
|
||||
"export.styles": "디자인 설정 및 스타일",
|
||||
"export.media": "미디어 파일 (이미지, 아이콘)",
|
||||
"export.groupsLinks": "그룹 및 링크",
|
||||
"export.selectedCount": "{{groups}}개 그룹, {{links}}개 링크",
|
||||
"export.createButton": "생성 및 다운로드",
|
||||
"export.creating": "내보내기 생성 중...",
|
||||
|
||||
"import.title": "프로필 데이터 가져오기",
|
||||
"import.selectFile": "가져올 아카이브 선택",
|
||||
"import.analyzing": "아카이브 분석 중...",
|
||||
"import.content": "아카이브 내용",
|
||||
"import.exportInfo": "내보내기 정보",
|
||||
"import.source": "소스",
|
||||
"import.exportDate": "내보내기 날짜",
|
||||
"import.dataStats": "데이터 통계",
|
||||
"import.groups": "그룹",
|
||||
"import.links": "링크",
|
||||
"import.designSettings": "디자인 설정",
|
||||
"import.mediaFiles": "미디어 파일",
|
||||
"import.yes": "있음",
|
||||
"import.no": "없음",
|
||||
"import.groupsPreview": "그룹 (첫 5개)",
|
||||
"import.linksPreview": "링크 (첫 10개)",
|
||||
"import.settings": "가져오기 설정",
|
||||
"import.importGroups": "그룹 가져오기 ({{count}}개)",
|
||||
"import.importLinks": "링크 가져오기 ({{count}}개)",
|
||||
"import.importStyles": "디자인 설정 가져오기",
|
||||
"import.importMedia": "미디어 파일 가져오기 ({{count}}개)",
|
||||
"import.overwriteExisting": "기존 데이터 덮어쓰기",
|
||||
"import.overwriteHelp": "비활성화하면 같은 이름의 기존 그룹 및 링크를 건너뜁니다",
|
||||
"import.unavailable": "(사용 불가)",
|
||||
"import.button": "가져오기",
|
||||
"import.importing": "가져오기 중...",
|
||||
|
||||
"theme.toggle": "테마 전환",
|
||||
"theme.light": "밝은 테마",
|
||||
"theme.dark": "어두운 테마",
|
||||
|
||||
"language.select": "언어 선택",
|
||||
"language.en": "English",
|
||||
"language.ru": "Русский",
|
||||
"language.ko": "한국어",
|
||||
"language.zh": "中文",
|
||||
"language.ja": "日本語"
|
||||
}
|
||||
195
frontend/linktree-frontend/src/app/locales/ru.json
Normal file
195
frontend/linktree-frontend/src/app/locales/ru.json
Normal file
@@ -0,0 +1,195 @@
|
||||
{
|
||||
"common.cancel": "Отмена",
|
||||
"common.save": "Сохранить",
|
||||
"common.saving": "Сохранение...",
|
||||
"common.loading": "Загрузка...",
|
||||
"common.error": "Ошибка",
|
||||
"common.success": "Успешно",
|
||||
"common.close": "Закрыть",
|
||||
"common.edit": "Редактировать",
|
||||
"common.delete": "Удалить",
|
||||
"common.add": "Добавить",
|
||||
"common.create": "Создать",
|
||||
"common.update": "Обновить",
|
||||
"common.search": "Поиск",
|
||||
"common.settings": "Настройки",
|
||||
"common.profile": "Профиль",
|
||||
"common.logout": "Выйти",
|
||||
"common.login": "Войти",
|
||||
"common.register": "Регистрация",
|
||||
"common.back": "Назад",
|
||||
"common.next": "Далее",
|
||||
"common.previous": "Предыдущий",
|
||||
"common.submit": "Отправить",
|
||||
"common.reset": "Сбросить",
|
||||
"common.clear": "Очистить",
|
||||
"common.confirm": "Подтвердить",
|
||||
"common.yes": "Да",
|
||||
"common.no": "Нет",
|
||||
"common.menu": "Меню",
|
||||
|
||||
"auth.login.title": "Вход",
|
||||
"auth.login.email": "Email",
|
||||
"auth.login.password": "Пароль",
|
||||
"auth.login.remember": "Запомнить меня",
|
||||
"auth.login.forgot": "Забыли пароль?",
|
||||
"auth.login.noAccount": "Нет аккаунта?",
|
||||
"auth.login.signUp": "Зарегистрироваться",
|
||||
|
||||
"auth.register.title": "Регистрация",
|
||||
"auth.register.username": "Имя пользователя",
|
||||
"auth.register.email": "Email",
|
||||
"auth.register.password": "Пароль",
|
||||
"auth.register.confirmPassword": "Подтвердите пароль",
|
||||
"auth.register.firstName": "Имя",
|
||||
"auth.register.lastName": "Фамилия",
|
||||
"auth.register.haveAccount": "Уже есть аккаунт?",
|
||||
"auth.register.signIn": "Войти",
|
||||
|
||||
"dashboard.title": "Панель управления",
|
||||
"dashboard.welcome": "Добро пожаловать, {{name}}!",
|
||||
"dashboard.groups": "Группы",
|
||||
"dashboard.links": "Ссылки",
|
||||
"dashboard.settings": "Настройки",
|
||||
"dashboard.customize": "Настроить",
|
||||
"dashboard.addGroup": "Добавить группу",
|
||||
"dashboard.addLink": "Добавить ссылку",
|
||||
"dashboard.noGroups": "Пока нет групп",
|
||||
"dashboard.noLinks": "Пока нет ссылок",
|
||||
"dashboard.createFirst": "Создайте вашу первую",
|
||||
|
||||
"group.create": "Создать группу",
|
||||
"group.edit": "Редактировать группу",
|
||||
"group.name": "Название группы",
|
||||
"group.description": "Описание",
|
||||
"group.icon": "Иконка",
|
||||
"group.background": "Фоновое изображение",
|
||||
"group.color": "Цвет заголовка",
|
||||
"group.public": "Публичная",
|
||||
"group.favorite": "Избранная",
|
||||
"group.expanded": "Развернута по умолчанию",
|
||||
"group.removeIcon": "Убрать иконку",
|
||||
"group.removeBackground": "Убрать фон",
|
||||
|
||||
"link.create": "Создать ссылку",
|
||||
"link.edit": "Редактировать ссылку",
|
||||
"link.title": "Название ссылки",
|
||||
"link.url": "URL",
|
||||
"link.description": "Описание",
|
||||
"link.icon": "Иконка",
|
||||
"link.removeIcon": "Убрать иконку",
|
||||
"link.public": "Публичная",
|
||||
"link.featured": "Рекомендуемая",
|
||||
|
||||
"profile.edit": "Редактировать профиль",
|
||||
"profile.username": "Имя пользователя",
|
||||
"profile.email": "Email",
|
||||
"profile.firstName": "Имя",
|
||||
"profile.lastName": "Фамилия",
|
||||
"profile.fullName": "Полное имя",
|
||||
"profile.bio": "О себе",
|
||||
"profile.avatar": "Аватар",
|
||||
"profile.cover": "Обложка",
|
||||
"profile.removeAvatar": "Убрать аватар",
|
||||
"profile.removeCover": "Убрать обложку",
|
||||
|
||||
"customization.title": "Настройки",
|
||||
"customization.templates": "Шаблоны",
|
||||
"customization.layout": "Макет",
|
||||
"customization.colors": "Цвета",
|
||||
"customization.groups": "Группы",
|
||||
"customization.advanced": "Дополнительно",
|
||||
"customization.data": "Данные",
|
||||
|
||||
"customization.layout.style": "Стиль отображения групп и ссылок",
|
||||
"customization.layout.list": "Список",
|
||||
"customization.layout.grid": "Сетка",
|
||||
"customization.layout.cards": "Карточки",
|
||||
"customization.layout.compact": "Компактный",
|
||||
"customization.layout.masonry": "Кирпичная кладка",
|
||||
"customization.layout.timeline": "Временная шкала",
|
||||
"customization.layout.magazine": "Журнал",
|
||||
|
||||
"customization.colors.theme": "Цвет темы",
|
||||
"customization.colors.background": "Цвет фона",
|
||||
"customization.colors.backgroundImage": "Фоновое изображение",
|
||||
"customization.colors.removeBackground": "Убрать фон",
|
||||
"customization.colors.header": "Цвет текста заголовков",
|
||||
"customization.colors.group": "Цвет текста групп",
|
||||
"customization.colors.link": "Цвет текста ссылок",
|
||||
|
||||
"customization.groups.showIcons": "Показывать иконки групп",
|
||||
"customization.groups.showLinks": "Показывать иконки ссылок",
|
||||
"customization.groups.defaultExpanded": "Группы развернуты по умолчанию",
|
||||
"customization.groups.showTitle": "Показывать заголовки групп",
|
||||
|
||||
"customization.advanced.fonts": "Настройки шрифтов",
|
||||
"customization.advanced.mainFont": "Основной шрифт",
|
||||
"customization.advanced.headingFont": "Шрифт заголовков",
|
||||
"customization.advanced.bodyFont": "Шрифт текста",
|
||||
"customization.advanced.customCSS": "Пользовательский CSS",
|
||||
|
||||
"customization.data.title": "Экспорт и импорт данных профиля",
|
||||
"customization.data.description": "Создавайте резервные копии данных профиля или восстанавливайте их из архива",
|
||||
"customization.data.export.title": "Экспорт данных",
|
||||
"customization.data.export.description": "Создать архив с данными профиля для резервного копирования или переноса",
|
||||
"customization.data.export.button": "Создать экспорт",
|
||||
"customization.data.import.title": "Импорт данных",
|
||||
"customization.data.import.description": "Загрузить и восстановить данные из архива экспорта",
|
||||
"customization.data.import.file": "Выберите файл архива (.zip)",
|
||||
"customization.data.import.button": "Открыть мастер импорта",
|
||||
"customization.data.history.title": "История операций",
|
||||
"customization.data.history.description": "Здесь будет отображаться история экспортов и импортов",
|
||||
|
||||
"customization.resetSettings": "Сбросить настройки",
|
||||
"customization.resetConfirm": "Вы уверены, что хотите сбросить все настройки интерфейса к значениям по умолчанию? Это действие нельзя отменить.",
|
||||
|
||||
"export.title": "Экспорт данных профиля",
|
||||
"export.description": "Выберите данные для включения в архив экспорта",
|
||||
"export.general": "Общие данные",
|
||||
"export.profile": "Данные профиля (имя, био, аватар)",
|
||||
"export.styles": "Настройки дизайна и стили",
|
||||
"export.media": "Медиафайлы (изображения, иконки)",
|
||||
"export.groupsLinks": "Группы и ссылки",
|
||||
"export.selectedCount": "{{groups}} групп, {{links}} ссылок",
|
||||
"export.createButton": "Создать и скачать",
|
||||
"export.creating": "Создание экспорта...",
|
||||
|
||||
"import.title": "Импорт данных профиля",
|
||||
"import.selectFile": "Выберите архив для импорта",
|
||||
"import.analyzing": "Анализ архива...",
|
||||
"import.content": "Содержимое архива",
|
||||
"import.exportInfo": "Информация об экспорте",
|
||||
"import.source": "Источник",
|
||||
"import.exportDate": "Дата экспорта",
|
||||
"import.dataStats": "Статистика данных",
|
||||
"import.groups": "Групп",
|
||||
"import.links": "Ссылок",
|
||||
"import.designSettings": "Настройки дизайна",
|
||||
"import.mediaFiles": "Медиафайлов",
|
||||
"import.yes": "Есть",
|
||||
"import.no": "Нет",
|
||||
"import.groupsPreview": "Группы (первые 5)",
|
||||
"import.linksPreview": "Ссылки (первые 10)",
|
||||
"import.settings": "Настройки импорта",
|
||||
"import.importGroups": "Импортировать группы ({{count}})",
|
||||
"import.importLinks": "Импортировать ссылки ({{count}})",
|
||||
"import.importStyles": "Импортировать настройки дизайна",
|
||||
"import.importMedia": "Импортировать медиафайлы ({{count}})",
|
||||
"import.overwriteExisting": "Перезаписать существующие данные",
|
||||
"import.overwriteHelp": "Если отключено, существующие группы и ссылки с такими же названиями будут пропущены",
|
||||
"import.unavailable": "(недоступно)",
|
||||
"import.button": "Импортировать",
|
||||
"import.importing": "Импорт...",
|
||||
|
||||
"theme.toggle": "Переключить тему",
|
||||
"theme.light": "Светлая тема",
|
||||
"theme.dark": "Темная тема",
|
||||
|
||||
"language.select": "Выберите язык",
|
||||
"language.en": "English",
|
||||
"language.ru": "Русский",
|
||||
"language.ko": "한국어",
|
||||
"language.zh": "中文",
|
||||
"language.ja": "日本語"
|
||||
}
|
||||
195
frontend/linktree-frontend/src/app/locales/zh.json
Normal file
195
frontend/linktree-frontend/src/app/locales/zh.json
Normal file
@@ -0,0 +1,195 @@
|
||||
{
|
||||
"common.cancel": "取消",
|
||||
"common.save": "保存",
|
||||
"common.saving": "保存中...",
|
||||
"common.loading": "加载中...",
|
||||
"common.error": "错误",
|
||||
"common.success": "成功",
|
||||
"common.close": "关闭",
|
||||
"common.edit": "编辑",
|
||||
"common.delete": "删除",
|
||||
"common.add": "添加",
|
||||
"common.create": "创建",
|
||||
"common.update": "更新",
|
||||
"common.search": "搜索",
|
||||
"common.settings": "设置",
|
||||
"common.profile": "个人资料",
|
||||
"common.logout": "登出",
|
||||
"common.login": "登录",
|
||||
"common.register": "注册",
|
||||
"common.back": "返回",
|
||||
"common.next": "下一步",
|
||||
"common.previous": "上一步",
|
||||
"common.submit": "提交",
|
||||
"common.reset": "重置",
|
||||
"common.clear": "清除",
|
||||
"common.confirm": "确认",
|
||||
"common.yes": "是",
|
||||
"common.no": "否",
|
||||
"common.menu": "菜单",
|
||||
|
||||
"auth.login.title": "登录",
|
||||
"auth.login.email": "邮箱",
|
||||
"auth.login.password": "密码",
|
||||
"auth.login.remember": "记住我",
|
||||
"auth.login.forgot": "忘记密码?",
|
||||
"auth.login.noAccount": "还没有账户?",
|
||||
"auth.login.signUp": "注册",
|
||||
|
||||
"auth.register.title": "注册",
|
||||
"auth.register.username": "用户名",
|
||||
"auth.register.email": "邮箱",
|
||||
"auth.register.password": "密码",
|
||||
"auth.register.confirmPassword": "确认密码",
|
||||
"auth.register.firstName": "名",
|
||||
"auth.register.lastName": "姓",
|
||||
"auth.register.haveAccount": "已有账户?",
|
||||
"auth.register.signIn": "登录",
|
||||
|
||||
"dashboard.title": "仪表板",
|
||||
"dashboard.welcome": "欢迎,{{name}}!",
|
||||
"dashboard.groups": "分组",
|
||||
"dashboard.links": "链接",
|
||||
"dashboard.settings": "设置",
|
||||
"dashboard.customize": "自定义",
|
||||
"dashboard.addGroup": "添加分组",
|
||||
"dashboard.addLink": "添加链接",
|
||||
"dashboard.noGroups": "暂无分组",
|
||||
"dashboard.noLinks": "暂无链接",
|
||||
"dashboard.createFirst": "创建您的第一个",
|
||||
|
||||
"group.create": "创建分组",
|
||||
"group.edit": "编辑分组",
|
||||
"group.name": "分组名称",
|
||||
"group.description": "描述",
|
||||
"group.icon": "图标",
|
||||
"group.background": "背景图片",
|
||||
"group.color": "标题颜色",
|
||||
"group.public": "公开",
|
||||
"group.favorite": "收藏",
|
||||
"group.expanded": "默认展开",
|
||||
"group.removeIcon": "移除图标",
|
||||
"group.removeBackground": "移除背景",
|
||||
|
||||
"link.create": "创建链接",
|
||||
"link.edit": "编辑链接",
|
||||
"link.title": "链接标题",
|
||||
"link.url": "网址",
|
||||
"link.description": "描述",
|
||||
"link.icon": "图标",
|
||||
"link.removeIcon": "移除图标",
|
||||
"link.public": "公开",
|
||||
"link.featured": "精选",
|
||||
|
||||
"profile.edit": "编辑个人资料",
|
||||
"profile.username": "用户名",
|
||||
"profile.email": "邮箱",
|
||||
"profile.firstName": "名",
|
||||
"profile.lastName": "姓",
|
||||
"profile.fullName": "全名",
|
||||
"profile.bio": "个人简介",
|
||||
"profile.avatar": "头像",
|
||||
"profile.cover": "封面图片",
|
||||
"profile.removeAvatar": "移除头像",
|
||||
"profile.removeCover": "移除封面",
|
||||
|
||||
"customization.title": "自定义",
|
||||
"customization.templates": "模板",
|
||||
"customization.layout": "布局",
|
||||
"customization.colors": "颜色",
|
||||
"customization.groups": "分组",
|
||||
"customization.advanced": "高级",
|
||||
"customization.data": "数据",
|
||||
|
||||
"customization.layout.style": "分组和链接的显示样式",
|
||||
"customization.layout.list": "列表",
|
||||
"customization.layout.grid": "网格",
|
||||
"customization.layout.cards": "卡片",
|
||||
"customization.layout.compact": "紧凑",
|
||||
"customization.layout.masonry": "瀑布流",
|
||||
"customization.layout.timeline": "时间线",
|
||||
"customization.layout.magazine": "杂志",
|
||||
|
||||
"customization.colors.theme": "主题颜色",
|
||||
"customization.colors.background": "背景颜色",
|
||||
"customization.colors.backgroundImage": "背景图片",
|
||||
"customization.colors.removeBackground": "移除背景",
|
||||
"customization.colors.header": "标题文字颜色",
|
||||
"customization.colors.group": "分组文字颜色",
|
||||
"customization.colors.link": "链接文字颜色",
|
||||
|
||||
"customization.groups.showIcons": "显示分组图标",
|
||||
"customization.groups.showLinks": "显示链接图标",
|
||||
"customization.groups.defaultExpanded": "分组默认展开",
|
||||
"customization.groups.showTitle": "显示分组标题",
|
||||
|
||||
"customization.advanced.fonts": "字体设置",
|
||||
"customization.advanced.mainFont": "主字体",
|
||||
"customization.advanced.headingFont": "标题字体",
|
||||
"customization.advanced.bodyFont": "正文字体",
|
||||
"customization.advanced.customCSS": "自定义CSS",
|
||||
|
||||
"customization.data.title": "个人资料数据导出和导入",
|
||||
"customization.data.description": "创建个人资料数据的备份或从归档文件中恢复",
|
||||
"customization.data.export.title": "导出数据",
|
||||
"customization.data.export.description": "为备份或转移创建包含个人资料数据的归档文件",
|
||||
"customization.data.export.button": "创建导出",
|
||||
"customization.data.import.title": "导入数据",
|
||||
"customization.data.import.description": "从导出归档文件上传和恢复数据",
|
||||
"customization.data.import.file": "选择归档文件 (.zip)",
|
||||
"customization.data.import.button": "打开导入向导",
|
||||
"customization.data.history.title": "操作历史",
|
||||
"customization.data.history.description": "导出和导入历史将显示在这里",
|
||||
|
||||
"customization.resetSettings": "重置设置",
|
||||
"customization.resetConfirm": "您确定要将所有界面设置重置为默认值吗?此操作无法撤消。",
|
||||
|
||||
"export.title": "导出个人资料数据",
|
||||
"export.description": "选择要包含在导出归档中的数据",
|
||||
"export.general": "通用数据",
|
||||
"export.profile": "个人资料数据(姓名、简介、头像)",
|
||||
"export.styles": "设计设置和样式",
|
||||
"export.media": "媒体文件(图片、图标)",
|
||||
"export.groupsLinks": "分组和链接",
|
||||
"export.selectedCount": "{{groups}} 个分组,{{links}} 个链接",
|
||||
"export.createButton": "创建并下载",
|
||||
"export.creating": "创建导出中...",
|
||||
|
||||
"import.title": "导入个人资料数据",
|
||||
"import.selectFile": "选择要导入的归档文件",
|
||||
"import.analyzing": "分析归档中...",
|
||||
"import.content": "归档内容",
|
||||
"import.exportInfo": "导出信息",
|
||||
"import.source": "来源",
|
||||
"import.exportDate": "导出日期",
|
||||
"import.dataStats": "数据统计",
|
||||
"import.groups": "分组",
|
||||
"import.links": "链接",
|
||||
"import.designSettings": "设计设置",
|
||||
"import.mediaFiles": "媒体文件",
|
||||
"import.yes": "有",
|
||||
"import.no": "无",
|
||||
"import.groupsPreview": "分组(前5个)",
|
||||
"import.linksPreview": "链接(前10个)",
|
||||
"import.settings": "导入设置",
|
||||
"import.importGroups": "导入分组({{count}}个)",
|
||||
"import.importLinks": "导入链接({{count}}个)",
|
||||
"import.importStyles": "导入设计设置",
|
||||
"import.importMedia": "导入媒体文件({{count}}个)",
|
||||
"import.overwriteExisting": "覆盖现有数据",
|
||||
"import.overwriteHelp": "如果禁用,将跳过具有相同名称的现有分组和链接",
|
||||
"import.unavailable": "(不可用)",
|
||||
"import.button": "导入",
|
||||
"import.importing": "导入中...",
|
||||
|
||||
"theme.toggle": "切换主题",
|
||||
"theme.light": "浅色主题",
|
||||
"theme.dark": "深色主题",
|
||||
|
||||
"language.select": "选择语言",
|
||||
"language.en": "English",
|
||||
"language.ru": "Русский",
|
||||
"language.ko": "한국어",
|
||||
"language.zh": "中文",
|
||||
"language.ja": "日本語"
|
||||
}
|
||||
257
frontend/linktree-frontend/src/app/styles/themes.css
Normal file
257
frontend/linktree-frontend/src/app/styles/themes.css
Normal file
@@ -0,0 +1,257 @@
|
||||
/* CSS Custom Properties для темизации */
|
||||
|
||||
:root {
|
||||
/* Светлая тема (по умолчанию) */
|
||||
--background: #ffffff;
|
||||
--background-secondary: #f8f9fa;
|
||||
--background-tertiary: #e9ecef;
|
||||
--text: #212529;
|
||||
--text-secondary: #6c757d;
|
||||
--text-muted: #868e96;
|
||||
--border: #dee2e6;
|
||||
--border-light: #e9ecef;
|
||||
--primary: #0d6efd;
|
||||
--primary-hover: #0b5ed7;
|
||||
--secondary: #6c757d;
|
||||
--success: #198754;
|
||||
--danger: #dc3545;
|
||||
--warning: #ffc107;
|
||||
--info: #0dcaf0;
|
||||
--card-bg: #ffffff;
|
||||
--card-border: #dee2e6;
|
||||
--input-bg: #ffffff;
|
||||
--input-border: #ced4da;
|
||||
--input-focus-border: #86b7fe;
|
||||
--dropdown-bg: #ffffff;
|
||||
--dropdown-border: #dee2e6;
|
||||
--modal-bg: #ffffff;
|
||||
--modal-backdrop: rgba(0, 0, 0, 0.5);
|
||||
--navbar-bg: #ffffff;
|
||||
--sidebar-bg: #f8f9fa;
|
||||
--shadow: rgba(0, 0, 0, 0.175);
|
||||
--shadow-lg: rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
/* Темная тема */
|
||||
--background: #0d1117;
|
||||
--background-secondary: #161b22;
|
||||
--background-tertiary: #21262d;
|
||||
--text: #f0f6fc;
|
||||
--text-secondary: #8b949e;
|
||||
--text-muted: #656d76;
|
||||
--border: #30363d;
|
||||
--border-light: #21262d;
|
||||
--primary: #4fb3ff;
|
||||
--primary-hover: #58a6ff;
|
||||
--secondary: #8b949e;
|
||||
--success: #3fb950;
|
||||
--danger: #f85149;
|
||||
--warning: #d29922;
|
||||
--info: #56d4dd;
|
||||
--card-bg: #161b22;
|
||||
--card-border: #30363d;
|
||||
--input-bg: #0d1117;
|
||||
--input-border: #30363d;
|
||||
--input-focus-border: #58a6ff;
|
||||
--dropdown-bg: #161b22;
|
||||
--dropdown-border: #30363d;
|
||||
--modal-bg: #161b22;
|
||||
--modal-backdrop: rgba(0, 0, 0, 0.7);
|
||||
--navbar-bg: #161b22;
|
||||
--sidebar-bg: #0d1117;
|
||||
--shadow: rgba(0, 0, 0, 0.4);
|
||||
--shadow-lg: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
/* Применение темы к основным элементам */
|
||||
body {
|
||||
background-color: var(--background);
|
||||
color: var(--text);
|
||||
transition: background-color 0.3s ease, color 0.3s ease;
|
||||
}
|
||||
|
||||
/* Bootstrap переопределения для темной темы */
|
||||
.card {
|
||||
background-color: var(--card-bg);
|
||||
border-color: var(--card-border);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: var(--modal-bg);
|
||||
border-color: var(--card-border);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
border-bottom-color: var(--border);
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
border-top-color: var(--border);
|
||||
}
|
||||
|
||||
.form-control {
|
||||
background-color: var(--input-bg);
|
||||
border-color: var(--input-border);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
background-color: var(--input-bg);
|
||||
border-color: var(--input-focus-border);
|
||||
color: var(--text);
|
||||
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .form-control:focus {
|
||||
box-shadow: 0 0 0 0.25rem rgba(88, 166, 255, 0.25);
|
||||
}
|
||||
|
||||
.form-select {
|
||||
background-color: var(--input-bg);
|
||||
border-color: var(--input-border);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.form-select:focus {
|
||||
background-color: var(--input-bg);
|
||||
border-color: var(--input-focus-border);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.btn-outline-secondary {
|
||||
color: var(--text);
|
||||
border-color: var(--border);
|
||||
}
|
||||
|
||||
.btn-outline-secondary:hover {
|
||||
background-color: var(--background-secondary);
|
||||
border-color: var(--border);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
background-color: var(--dropdown-bg);
|
||||
border-color: var(--dropdown-border);
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.dropdown-item:hover,
|
||||
.dropdown-item:focus {
|
||||
background-color: var(--background-secondary);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.nav-tabs {
|
||||
border-bottom-color: var(--border);
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link {
|
||||
color: var(--text-secondary);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link:hover {
|
||||
border-color: var(--border-light) var(--border-light) var(--border);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link.active {
|
||||
color: var(--text);
|
||||
background-color: var(--background);
|
||||
border-color: var(--border) var(--border) var(--background);
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
background-color: var(--card-bg);
|
||||
border-color: var(--border);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
color: var(--text-muted) !important;
|
||||
}
|
||||
|
||||
.text-secondary {
|
||||
color: var(--text-secondary) !important;
|
||||
}
|
||||
|
||||
.border {
|
||||
border-color: var(--border) !important;
|
||||
}
|
||||
|
||||
.border-top {
|
||||
border-top-color: var(--border) !important;
|
||||
}
|
||||
|
||||
.border-bottom {
|
||||
border-bottom-color: var(--border) !important;
|
||||
}
|
||||
|
||||
.border-start {
|
||||
border-left-color: var(--border) !important;
|
||||
}
|
||||
|
||||
.border-end {
|
||||
border-right-color: var(--border) !important;
|
||||
}
|
||||
|
||||
/* Специальные стили для темной темы */
|
||||
[data-theme="dark"] .bg-light {
|
||||
background-color: var(--background-secondary) !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .bg-white {
|
||||
background-color: var(--card-bg) !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .text-dark {
|
||||
color: var(--text) !important;
|
||||
}
|
||||
|
||||
/* Анимация переключения темы */
|
||||
* {
|
||||
transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
|
||||
}
|
||||
|
||||
/* Кастомные утилитарные классы для темизации */
|
||||
.theme-bg {
|
||||
background-color: var(--background);
|
||||
}
|
||||
|
||||
.theme-bg-secondary {
|
||||
background-color: var(--background-secondary);
|
||||
}
|
||||
|
||||
.theme-bg-tertiary {
|
||||
background-color: var(--background-tertiary);
|
||||
}
|
||||
|
||||
.theme-text {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.theme-text-secondary {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.theme-text-muted {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.theme-border {
|
||||
border-color: var(--border);
|
||||
}
|
||||
|
||||
.theme-shadow {
|
||||
box-shadow: 0 0.125rem 0.25rem var(--shadow);
|
||||
}
|
||||
|
||||
.theme-shadow-lg {
|
||||
box-shadow: 0 1rem 3rem var(--shadow-lg);
|
||||
}
|
||||
Reference in New Issue
Block a user