Initial commit: base slice (auth, roles, users, admin) scaffold
Backend: .NET 10 Clean Architecture + LiteCqrs.Net + EF Core/PostgreSQL + Identity/JWT. Frontend: React 19 + Vite + TanStack Query/Router + Tailwind v4 with a retro CRT theme. Docker/compose deployment mirroring PnvPanel's conventions, scoped down to the current base feature set.
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
import i18n from 'i18next'
|
||||
import { initReactI18next } from 'react-i18next'
|
||||
|
||||
const resources = {
|
||||
ru: {
|
||||
translation: {
|
||||
appName: 'TeleWave',
|
||||
nav: {
|
||||
home: 'Главная',
|
||||
dashboard: 'Эфир',
|
||||
admin: 'Админка',
|
||||
settings: 'Настройки',
|
||||
login: 'Войти',
|
||||
register: 'Регистрация',
|
||||
logout: 'Выйти',
|
||||
},
|
||||
theme: { light: 'Светлая', dark: 'Тёмная', system: 'Системная' },
|
||||
lang: { ru: 'RU', en: 'EN' },
|
||||
common: {
|
||||
save: 'Сохранить',
|
||||
cancel: 'Отмена',
|
||||
delete: 'Удалить',
|
||||
create: 'Создать',
|
||||
loading: 'Загрузка…',
|
||||
error: 'Что-то пошло не так',
|
||||
confirm: 'Подтвердить',
|
||||
search: 'Поиск',
|
||||
actions: 'Действия',
|
||||
yes: 'Да',
|
||||
no: 'Нет',
|
||||
},
|
||||
home: {
|
||||
title: 'TELEWAVE',
|
||||
subtitle: 'ЭФИРНАЯ СЕТКА КАНАЛОВ',
|
||||
tagline: 'Твои каналы. Твой эфир. В любое время.',
|
||||
cta: 'Войти в эфир',
|
||||
ctaRegister: 'Создать аккаунт',
|
||||
},
|
||||
auth: {
|
||||
userName: 'Имя пользователя',
|
||||
password: 'Пароль',
|
||||
loginTitle: 'Вход в эфир',
|
||||
loginSubtitle: 'Введите учётные данные для доступа к сетке каналов',
|
||||
registerTitle: 'Новый зритель',
|
||||
registerSubtitle: 'Создайте аккаунт, чтобы настроить свою сетку каналов',
|
||||
submitLogin: 'Войти',
|
||||
submitRegister: 'Зарегистрироваться',
|
||||
noAccount: 'Нет аккаунта?',
|
||||
haveAccount: 'Уже есть аккаунт?',
|
||||
invalidCredentials: 'Неверное имя пользователя или пароль',
|
||||
userNameTaken: 'Это имя пользователя уже занято',
|
||||
blocked: 'Аккаунт заблокирован администратором',
|
||||
genericError: 'Не удалось выполнить вход. Попробуйте ещё раз',
|
||||
},
|
||||
dashboard: {
|
||||
welcome: 'На связи, {{userName}}',
|
||||
placeholder: 'Список каналов появится здесь позже — пока в эфире только тестовая заставка.',
|
||||
role: 'Роль',
|
||||
},
|
||||
settings: {
|
||||
title: 'Настройки аккаунта',
|
||||
changeUserName: 'Смена имени пользователя',
|
||||
newUserName: 'Новое имя пользователя',
|
||||
changePassword: 'Смена пароля',
|
||||
currentPassword: 'Текущий пароль',
|
||||
newPassword: 'Новый пароль',
|
||||
dangerZone: 'Опасная зона',
|
||||
deleteAccount: 'Удалить аккаунт',
|
||||
deleteAccountConfirm: 'Аккаунт и все данные будут удалены безвозвратно. Продолжить?',
|
||||
saved: 'Сохранено',
|
||||
},
|
||||
admin: {
|
||||
roles: {
|
||||
title: 'Роли',
|
||||
name: 'Название',
|
||||
system: 'Системная',
|
||||
create: 'Новая роль',
|
||||
rename: 'Переименовать',
|
||||
cannotModifySystem: 'Системную роль нельзя изменить или удалить',
|
||||
roleInUse: 'Роль назначена пользователям',
|
||||
},
|
||||
users: {
|
||||
title: 'Пользователи',
|
||||
userName: 'Имя пользователя',
|
||||
role: 'Роль',
|
||||
status: 'Статус',
|
||||
createdAt: 'Регистрация',
|
||||
blocked: 'Заблокирован',
|
||||
active: 'Активен',
|
||||
block: 'Заблокировать',
|
||||
unblock: 'Разблокировать',
|
||||
filterAll: 'Все роли',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
en: {
|
||||
translation: {
|
||||
appName: 'TeleWave',
|
||||
nav: {
|
||||
home: 'Home',
|
||||
dashboard: 'On Air',
|
||||
admin: 'Admin',
|
||||
settings: 'Settings',
|
||||
login: 'Log in',
|
||||
register: 'Sign up',
|
||||
logout: 'Log out',
|
||||
},
|
||||
theme: { light: 'Light', dark: 'Dark', system: 'System' },
|
||||
lang: { ru: 'RU', en: 'EN' },
|
||||
common: {
|
||||
save: 'Save',
|
||||
cancel: 'Cancel',
|
||||
delete: 'Delete',
|
||||
create: 'Create',
|
||||
loading: 'Loading…',
|
||||
error: 'Something went wrong',
|
||||
confirm: 'Confirm',
|
||||
search: 'Search',
|
||||
actions: 'Actions',
|
||||
yes: 'Yes',
|
||||
no: 'No',
|
||||
},
|
||||
home: {
|
||||
title: 'TELEWAVE',
|
||||
subtitle: 'BROADCAST CHANNEL GRID',
|
||||
tagline: 'Your channels. Your broadcast. Anytime.',
|
||||
cta: 'Go on air',
|
||||
ctaRegister: 'Create account',
|
||||
},
|
||||
auth: {
|
||||
userName: 'Username',
|
||||
password: 'Password',
|
||||
loginTitle: 'Sign in',
|
||||
loginSubtitle: 'Enter your credentials to access the channel grid',
|
||||
registerTitle: 'New viewer',
|
||||
registerSubtitle: 'Create an account to set up your channel grid',
|
||||
submitLogin: 'Log in',
|
||||
submitRegister: 'Sign up',
|
||||
noAccount: "Don't have an account?",
|
||||
haveAccount: 'Already have an account?',
|
||||
invalidCredentials: 'Invalid username or password',
|
||||
userNameTaken: 'This username is already taken',
|
||||
blocked: 'Account blocked by an administrator',
|
||||
genericError: 'Could not sign in. Please try again',
|
||||
},
|
||||
dashboard: {
|
||||
welcome: 'On air, {{userName}}',
|
||||
placeholder: 'The channel list will show up here later — for now, enjoy the test card.',
|
||||
role: 'Role',
|
||||
},
|
||||
settings: {
|
||||
title: 'Account settings',
|
||||
changeUserName: 'Change username',
|
||||
newUserName: 'New username',
|
||||
changePassword: 'Change password',
|
||||
currentPassword: 'Current password',
|
||||
newPassword: 'New password',
|
||||
dangerZone: 'Danger zone',
|
||||
deleteAccount: 'Delete account',
|
||||
deleteAccountConfirm: 'The account and all its data will be permanently deleted. Continue?',
|
||||
saved: 'Saved',
|
||||
},
|
||||
admin: {
|
||||
roles: {
|
||||
title: 'Roles',
|
||||
name: 'Name',
|
||||
system: 'System',
|
||||
create: 'New role',
|
||||
rename: 'Rename',
|
||||
cannotModifySystem: 'A system role cannot be modified or deleted',
|
||||
roleInUse: 'Role is assigned to users',
|
||||
},
|
||||
users: {
|
||||
title: 'Users',
|
||||
userName: 'Username',
|
||||
role: 'Role',
|
||||
status: 'Status',
|
||||
createdAt: 'Joined',
|
||||
blocked: 'Blocked',
|
||||
active: 'Active',
|
||||
block: 'Block',
|
||||
unblock: 'Unblock',
|
||||
filterAll: 'All roles',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const STORAGE_KEY = 'tw-lang'
|
||||
const stored = typeof localStorage !== 'undefined' ? localStorage.getItem(STORAGE_KEY) : null
|
||||
|
||||
void i18n.use(initReactI18next).init({
|
||||
resources,
|
||||
lng: stored ?? 'ru',
|
||||
fallbackLng: 'ru',
|
||||
interpolation: { escapeValue: false },
|
||||
})
|
||||
|
||||
export function setLanguage(lng: string) {
|
||||
localStorage.setItem(STORAGE_KEY, lng)
|
||||
void i18n.changeLanguage(lng)
|
||||
}
|
||||
|
||||
export default i18n
|
||||
Reference in New Issue
Block a user