From 79f74b83a867772d8a6058f44887b5141d3a5301 Mon Sep 17 00:00:00 2001 From: "Andrey K. Choi" Date: Sun, 9 Nov 2025 15:25:03 +0900 Subject: [PATCH] localization --- .../src/app/components/CustomizationPanel.tsx | 24 +- .../src/app/components/LanguageSelector.tsx | 43 +++ .../src/app/components/LayoutWrapper.tsx | 17 +- .../src/app/components/Providers.tsx | 19 ++ .../src/app/components/ThemeToggle.tsx | 31 +++ .../src/app/contexts/LocaleContext.tsx | 97 +++++++ .../src/app/contexts/ThemeContext.tsx | 67 +++++ frontend/linktree-frontend/src/app/layout.css | 4 + frontend/linktree-frontend/src/app/layout.tsx | 6 +- .../linktree-frontend/src/app/locales/en.json | 195 +++++++++++++ .../linktree-frontend/src/app/locales/ja.json | 195 +++++++++++++ .../linktree-frontend/src/app/locales/ko.json | 195 +++++++++++++ .../linktree-frontend/src/app/locales/ru.json | 195 +++++++++++++ .../linktree-frontend/src/app/locales/zh.json | 195 +++++++++++++ .../src/app/styles/themes.css | 257 ++++++++++++++++++ 15 files changed, 1524 insertions(+), 16 deletions(-) create mode 100644 frontend/linktree-frontend/src/app/components/LanguageSelector.tsx create mode 100644 frontend/linktree-frontend/src/app/components/Providers.tsx create mode 100644 frontend/linktree-frontend/src/app/components/ThemeToggle.tsx create mode 100644 frontend/linktree-frontend/src/app/contexts/LocaleContext.tsx create mode 100644 frontend/linktree-frontend/src/app/contexts/ThemeContext.tsx create mode 100644 frontend/linktree-frontend/src/app/layout.css create mode 100644 frontend/linktree-frontend/src/app/locales/en.json create mode 100644 frontend/linktree-frontend/src/app/locales/ja.json create mode 100644 frontend/linktree-frontend/src/app/locales/ko.json create mode 100644 frontend/linktree-frontend/src/app/locales/ru.json create mode 100644 frontend/linktree-frontend/src/app/locales/zh.json create mode 100644 frontend/linktree-frontend/src/app/styles/themes.css diff --git a/frontend/linktree-frontend/src/app/components/CustomizationPanel.tsx b/frontend/linktree-frontend/src/app/components/CustomizationPanel.tsx index 4c882aa..84db0de 100644 --- a/frontend/linktree-frontend/src/app/components/CustomizationPanel.tsx +++ b/frontend/linktree-frontend/src/app/components/CustomizationPanel.tsx @@ -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({ theme_color: '#ffffff', dashboard_layout: 'list', @@ -278,7 +280,7 @@ export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate, user, gr
- Настройки дашборда + {t('customization.title')}
  • @@ -305,7 +307,7 @@ export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate, user, gr onClick={() => setActiveTab('colors')} > - Цвета + {t('customization.colors')}
  • @@ -314,7 +316,7 @@ export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate, user, gr onClick={() => setActiveTab('groups')} > - Группы + {t('customization.groups')}
  • @@ -323,7 +325,7 @@ export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate, user, gr onClick={() => setActiveTab('templates')} > - Шаблоны + {t('customization.templates')}
  • @@ -332,7 +334,7 @@ export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate, user, gr onClick={() => setActiveTab('advanced')} > - Дополнительно + {t('customization.advanced')}
  • @@ -341,7 +343,7 @@ export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate, user, gr onClick={() => setActiveTab('data')} > - Данные + {t('customization.data')}
  • @@ -1215,10 +1217,10 @@ export function CustomizationPanel({ isOpen, onClose, onSettingsUpdate, user, gr } }} disabled={loading} - title="Сбросить все настройки к значениям по умолчанию" + title={t('customization.resetSettings')} > - Сбросить настройки + {t('customization.resetSettings')} diff --git a/frontend/linktree-frontend/src/app/components/LanguageSelector.tsx b/frontend/linktree-frontend/src/app/components/LanguageSelector.tsx new file mode 100644 index 0000000..597f215 --- /dev/null +++ b/frontend/linktree-frontend/src/app/components/LanguageSelector.tsx @@ -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 ( +
    + +
      + {languages.map((language) => ( +
    • + +
    • + ))} +
    +
    + ); +}; + +export default LanguageSelector; \ No newline at end of file diff --git a/frontend/linktree-frontend/src/app/components/LayoutWrapper.tsx b/frontend/linktree-frontend/src/app/components/LayoutWrapper.tsx index 7cee167..4e0f5f6 100644 --- a/frontend/linktree-frontend/src/app/components/LayoutWrapper.tsx +++ b/frontend/linktree-frontend/src/app/components/LayoutWrapper.tsx @@ -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(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')} />