352 lines
13 KiB
TypeScript
352 lines
13 KiB
TypeScript
|
||
import { Language } from '../types';
|
||
|
||
export const getSystemLanguage = (): Language => {
|
||
if (typeof navigator === 'undefined') return 'en';
|
||
const lang = navigator.language.split('-')[0];
|
||
return lang === 'ru' ? 'ru' : 'en';
|
||
};
|
||
|
||
const translations = {
|
||
en: {
|
||
// Tabs
|
||
tab_tracker: 'Tracker',
|
||
tab_plans: 'Plans',
|
||
tab_history: 'History',
|
||
tab_stats: 'Stats',
|
||
tab_ai: 'AI Coach',
|
||
tab_profile: 'Profile',
|
||
|
||
// Auth
|
||
login_title: 'GymFlow AI',
|
||
login_email: 'Email',
|
||
login_password: 'Password',
|
||
login_btn: 'Login',
|
||
login_contact_admin: 'Contact administrator to get an account.',
|
||
login_error: 'Invalid email or password',
|
||
login_password_short: 'Password too short',
|
||
change_pass_title: 'Change Password',
|
||
change_pass_desc: 'This is your first login. Please set a new password.',
|
||
change_pass_new: 'New Password',
|
||
change_pass_save: 'Save & Login',
|
||
change_pass_error: 'Error changing password',
|
||
passwords_mismatch: 'Passwords do not match',
|
||
register_title: 'Create Account',
|
||
confirm_password: 'Confirm Password',
|
||
register_btn: 'Register',
|
||
have_account: 'Already have an account? Login',
|
||
need_account: 'Need an account? Register',
|
||
|
||
// Tracker
|
||
ready_title: 'Ready?',
|
||
ready_subtitle: 'Start your workout and break records.',
|
||
my_weight: 'My Weight (kg)',
|
||
change_in_profile: 'Change in profile',
|
||
free_workout: 'Free Workout',
|
||
or_choose_plan: 'Or choose a plan',
|
||
exercises_count: 'exercises',
|
||
prep_title: 'Preparation',
|
||
prep_no_instructions: 'No specific instructions.',
|
||
cancel: 'Cancel',
|
||
quit: 'Quit',
|
||
start: 'Start',
|
||
finish: 'Finish',
|
||
finish_confirm_title: 'Finish Workout?',
|
||
finish_confirm_msg: 'Are you sure you want to finish this workout? Your progress will be saved.',
|
||
quit_no_save: 'Quit without saving',
|
||
quit_confirm_title: 'Quit without saving?',
|
||
quit_confirm_msg: 'All progress from this session will be lost. This action cannot be undone.',
|
||
confirm: 'Confirm',
|
||
plan_completed: 'Plan Completed!',
|
||
step: 'Step',
|
||
of: 'of',
|
||
select_exercise: 'Select Exercise',
|
||
weight_kg: 'Weight (kg)',
|
||
reps: 'Reps',
|
||
time_sec: 'Time (sec)',
|
||
dist_m: 'Dist (m)',
|
||
height_cm: 'Height (cm)',
|
||
body_weight_percent: 'Body Weight',
|
||
log_set: 'Log Set',
|
||
prev: 'Prev',
|
||
history_section: 'History',
|
||
create_exercise: 'New Exercise',
|
||
ex_name: 'Name',
|
||
ex_type: 'Type',
|
||
create_btn: 'Create',
|
||
completed_session_sets: 'Completed in this session',
|
||
add_weight: 'Add. Weight',
|
||
no_exercises_found: 'No exercises found',
|
||
|
||
// Types
|
||
type_strength: 'Free Weights & Machines',
|
||
type_bodyweight: 'Bodyweight',
|
||
type_cardio: 'Cardio',
|
||
type_static: 'Static',
|
||
type_height: 'Height',
|
||
type_dist: 'Length',
|
||
type_jump: 'Plyo',
|
||
|
||
// History
|
||
history_empty: 'History is empty. Finish your first workout!',
|
||
sets_count: 'Sets',
|
||
finished: 'Finished',
|
||
delete_workout: 'Delete workout?',
|
||
delete_set: 'Delete set?',
|
||
delete_confirm: 'This action cannot be undone.',
|
||
delete_set_confirm: 'Are you sure you want to delete this set?',
|
||
delete: 'Delete',
|
||
edit: 'Edit',
|
||
save: 'Save',
|
||
start_time: 'Start',
|
||
end_time: 'End',
|
||
max: 'Max',
|
||
upto: 'Up to',
|
||
no_plan: 'No plan',
|
||
|
||
// Plans
|
||
plans_empty: 'No plans created',
|
||
plan_editor: 'Plan Editor',
|
||
plan_name_ph: 'E.g. Full-body Routine',
|
||
plan_desc_ph: 'Describe preparation...',
|
||
exercises_list: 'Exercises',
|
||
weighted: 'Weighted',
|
||
add_exercise: 'Add Exercise',
|
||
my_plans: 'My Plans',
|
||
|
||
// Stats
|
||
progress: 'Progress',
|
||
volume_title: 'Work Volume',
|
||
volume_subtitle: 'Tonnage (kg * reps)',
|
||
sets_title: 'Number of Sets',
|
||
weight_title: 'Body Weight History',
|
||
not_enough_data: 'Not enough data for statistics. Complete a few workouts!',
|
||
|
||
// AI
|
||
ai_expert: 'AI Coach',
|
||
ai_intro: 'Hi! I am your AI coach. I analyzed your workouts. Ask me about progress, technique, or routine.',
|
||
ai_typing: 'Typing...',
|
||
ai_placeholder: 'Ask about workouts...',
|
||
ai_error: 'API Key not configured',
|
||
|
||
// Profile
|
||
profile_title: 'Profile',
|
||
logout: 'Logout',
|
||
personal_data: 'Personal Data',
|
||
height: 'Height (cm)',
|
||
birth_date: 'Birth Date',
|
||
gender: 'Gender',
|
||
male: 'Male',
|
||
female: 'Female',
|
||
other: 'Other',
|
||
save_profile: 'Save Profile',
|
||
change_pass_btn: 'Change Password',
|
||
admin_area: 'Manage Users',
|
||
create_user: 'Create User',
|
||
user_created: 'User created',
|
||
language: 'Language',
|
||
admin_users_list: 'Users List',
|
||
block: 'Block',
|
||
unblock: 'Unblock',
|
||
reset_pass: 'Reset Pass',
|
||
delete_account: 'Delete Account',
|
||
delete_account_confirm: 'Are you sure? All your data (sessions, plans) will be permanently deleted.',
|
||
user_deleted: 'User deleted',
|
||
pass_reset: 'Password reset',
|
||
manage_exercises: 'Manage Exercises',
|
||
archive: 'Archive',
|
||
unarchive: 'Unarchive',
|
||
show_archived: 'Show Archived',
|
||
filter_by_name: 'Filter by name',
|
||
type_to_filter: 'Type to filter...',
|
||
exercise_name_exists: 'An exercise with this name already exists',
|
||
profile_saved: 'Profile saved successfully',
|
||
|
||
// Sporadic Sets
|
||
quick_log: 'Quick Log',
|
||
sporadic_sets_title: 'Quick Logged Sets',
|
||
log_sporadic_success: 'Set logged successfully',
|
||
sporadic_set_note: 'Note (optional)',
|
||
done: 'Done',
|
||
saved: 'Saved',
|
||
|
||
// Unilateral exercises
|
||
unilateral_exercise: 'Unilateral exercise (separate left/right tracking)',
|
||
unilateral: 'Unilateral',
|
||
same_values_both_sides: 'Same values for both sides',
|
||
left: 'Left',
|
||
right: 'Right',
|
||
},
|
||
ru: {
|
||
// Tabs
|
||
tab_tracker: 'Трекер',
|
||
tab_plans: 'Планы',
|
||
tab_history: 'История',
|
||
tab_stats: 'Статы',
|
||
tab_ai: 'AI Тренер',
|
||
tab_profile: 'Профиль',
|
||
|
||
// Auth
|
||
login_title: 'GymFlow AI',
|
||
login_email: 'Email',
|
||
login_password: 'Пароль',
|
||
login_btn: 'Войти',
|
||
login_contact_admin: 'Свяжитесь с администратором для получения учетной записи.',
|
||
login_error: 'Неверный email или пароль',
|
||
login_password_short: 'Пароль слишком короткий',
|
||
change_pass_title: 'Смена пароля',
|
||
change_pass_desc: 'Это ваш первый вход. Пожалуйста, установите новый пароль.',
|
||
change_pass_new: 'Новый пароль',
|
||
change_pass_save: 'Сохранить и войти',
|
||
change_pass_error: 'Ошибка смены пароля',
|
||
passwords_mismatch: 'Пароли не совпадают',
|
||
register_title: 'Регистрация',
|
||
confirm_password: 'Подтвердите пароль',
|
||
register_btn: 'Зарегистрироваться',
|
||
have_account: 'Уже есть аккаунт? Войти',
|
||
need_account: 'Нет аккаунта? Регистрация',
|
||
|
||
// Tracker
|
||
ready_title: 'Готовы?',
|
||
ready_subtitle: 'Начните тренировку и побейте рекорды.',
|
||
my_weight: 'Мой вес (кг)',
|
||
change_in_profile: 'Можно изменить в профиле',
|
||
free_workout: 'Свободная тренировка',
|
||
or_choose_plan: 'Или выберите план',
|
||
exercises_count: 'упражнений',
|
||
prep_title: 'Подготовка',
|
||
prep_no_instructions: 'Нет особых указаний.',
|
||
cancel: 'Отмена',
|
||
start: 'Начать',
|
||
finish: 'Завершить',
|
||
finish_confirm_title: 'Завершить тренировку?',
|
||
finish_confirm_msg: 'Вы уверены, что хотите завершить эту тренировку? Ваш прогресс будет сохранен.',
|
||
quit_no_save: 'Выйти без сохранения',
|
||
quit_confirm_title: 'Выйти без сохранения?',
|
||
quit_confirm_msg: 'Весь прогресс этой сессии будет потерян. Это действие нельзя отменить.',
|
||
confirm: 'Подтвердить',
|
||
plan_completed: 'План выполнен!',
|
||
step: 'Шаг',
|
||
of: 'из',
|
||
select_exercise: 'Выберите упражнение',
|
||
weight_kg: 'Вес (кг)',
|
||
reps: 'Повторения',
|
||
time_sec: 'Время (сек)',
|
||
dist_m: 'Дистанция (м)',
|
||
height_cm: 'Высота (см)',
|
||
body_weight_percent: 'Вес тела',
|
||
log_set: 'Записать подход',
|
||
prev: 'Предыдущий',
|
||
history_section: 'История',
|
||
create_exercise: 'Новое упражнение',
|
||
ex_name: 'Название',
|
||
ex_type: 'Тип упражнения',
|
||
create_btn: 'Создать',
|
||
completed_session_sets: 'Выполнено в этой тренировке',
|
||
add_weight: 'Доп. вес',
|
||
no_exercises_found: 'Упражнения не найдены',
|
||
|
||
// Types
|
||
type_strength: 'Свободные веса и тренажеры',
|
||
type_bodyweight: 'Свой вес',
|
||
type_cardio: 'Кардио',
|
||
type_static: 'Статика',
|
||
type_height: 'Высота',
|
||
type_dist: 'Длина',
|
||
type_jump: 'Прыжки',
|
||
|
||
// History
|
||
history_empty: 'История пуста. Завершите свою первую тренировку!',
|
||
sets_count: 'Сетов',
|
||
finished: 'Завершено',
|
||
delete_workout: 'Удалить тренировку?',
|
||
delete_set: 'Удалить подход?',
|
||
delete_confirm: 'Это действие нельзя отменить.',
|
||
delete_set_confirm: 'Вы уверены, что хотите удалить этот подход?',
|
||
delete: 'Удалить',
|
||
edit: 'Редактировать',
|
||
save: 'Сохранить',
|
||
start_time: 'Начало',
|
||
end_time: 'Конец',
|
||
max: 'Макс',
|
||
upto: 'До',
|
||
no_plan: 'Без плана',
|
||
|
||
// Plans
|
||
plans_empty: 'Нет созданных планов',
|
||
plan_editor: 'Редактор плана',
|
||
plan_name_ph: 'Например: Комплекс на всё тело',
|
||
plan_desc_ph: 'Опишите подготовку...',
|
||
exercises_list: 'Упражнения',
|
||
weighted: 'С отягощением',
|
||
add_exercise: 'Добавить упражнение',
|
||
my_plans: 'Мои планы',
|
||
|
||
// Stats
|
||
progress: 'Прогресс',
|
||
volume_title: 'Объем работы',
|
||
volume_subtitle: 'Тоннаж (кг * повторения)',
|
||
sets_title: 'Количество сетов',
|
||
weight_title: 'История веса тела',
|
||
not_enough_data: 'Недостаточно данных для статистики. Проведите хотя бы пару тренировок!',
|
||
|
||
// AI
|
||
ai_expert: 'AI Эксперт',
|
||
ai_intro: 'Привет! Я твой AI-тренер. Я проанализировал твои тренировки. Спрашивай меня о прогрессе, технике или плане занятий.',
|
||
ai_typing: 'Печатает...',
|
||
ai_placeholder: 'Спроси о тренировках...',
|
||
ai_error: 'API ключ не настроен',
|
||
|
||
// Profile
|
||
profile_title: 'Профиль',
|
||
logout: 'Выйти',
|
||
personal_data: 'Личные данные',
|
||
height: 'Рост (см)',
|
||
birth_date: 'Дата рожд.',
|
||
gender: 'Пол',
|
||
male: 'Мужской',
|
||
female: 'Женский',
|
||
other: 'Другой',
|
||
save_profile: 'Сохранить профиль',
|
||
change_pass_btn: 'Сменить пароль',
|
||
admin_area: 'Управление пользователями',
|
||
create_user: 'Создать пользователя',
|
||
user_created: 'Пользователь создан',
|
||
language: 'Язык / Language',
|
||
admin_users_list: 'Список пользователей',
|
||
block: 'Блок',
|
||
unblock: 'Разблок',
|
||
reset_pass: 'Сброс пароля',
|
||
delete_account: 'Удалить аккаунт',
|
||
delete_account_confirm: 'Вы уверены? Все ваши данные (сессии, планы) будут безвозвратно удалены.',
|
||
user_deleted: 'Пользователь удален',
|
||
pass_reset: 'Пароль сброшен',
|
||
manage_exercises: 'Управление упражнениями',
|
||
archive: 'Архив',
|
||
unarchive: 'Вернуть',
|
||
show_archived: 'Показать архивные',
|
||
filter_by_name: 'Фильтр по названию',
|
||
type_to_filter: 'Введите для фильтрации...',
|
||
exercise_name_exists: 'Упражнение с таким названием уже существует',
|
||
profile_saved: 'Профиль успешно сохранен',
|
||
|
||
// Sporadic Sets
|
||
quick_log: 'Быстрая запись',
|
||
sporadic_sets_title: 'Быстрые записи',
|
||
log_sporadic_success: 'Сет записан',
|
||
sporadic_set_note: 'Заметка (опц.)',
|
||
done: 'Готово',
|
||
saved: 'Сохранено',
|
||
|
||
// Unilateral exercises
|
||
unilateral_exercise: 'Односторонее упражнение (отдельно левая/правая)',
|
||
unilateral: 'Одностороннее',
|
||
same_values_both_sides: 'Одинаковые значения для обеих сторон',
|
||
left: 'Левая',
|
||
right: 'Правая',
|
||
},
|
||
};
|
||
|
||
export const t = (key: keyof typeof translations['en'], lang: Language) => {
|
||
return translations[lang][key] || translations['en'][key] || key;
|
||
}; |