new api endpoint and api rate limit

This commit is contained in:
Georgiy Syralev
2026-01-01 16:55:17 +03:00
parent 4690bdf23e
commit bdb333958a
32 changed files with 884 additions and 377 deletions

View File

@@ -61,9 +61,92 @@ export const en: TranslationKeys = {
about: {
title: 'About Us',
subtitle: 'Ospab.host — modern cloud storage platform',
hero: {
title: 'The Story of ospab.host',
subtitle: 'The first data center in Veliky Novgorod.',
},
founder: {
name: 'Georgy',
title: 'Founder & CEO',
age: '13 years old',
location: 'Veliky Novgorod',
github: 'Project source code',
bio: "At 13, I decided to create something that didn't exist in my city — a modern data center. Starting with learning technologies and working on my first hosting, I'm gradually turning a dream into reality. With the help of an investor friend, we're building the infrastructure of the future for Veliky Novgorod.",
alt: 'Georgy, founder of ospab.host',
},
story: {
title: 'Our Story',
text: 'We created ospab.host to provide reliable and affordable cloud storage for businesses and developers.',
sections: {
start: {
title: 'September 2025 — The Beginning',
text: "It all started with a simple idea: create a place where anyone can host their project, website, or server with maximum reliability and speed. Veliky Novgorod deserves its own data center, and I decided to take on this task.",
},
support: {
title: 'Support and Development',
text: "My investor friend believed in the project and helps with infrastructure development. We're building not just a business, but a community where every client is like a friend, and support is always nearby.",
},
future: {
title: 'Present and Future',
text: "Currently, we're actively working on hosting and preparing infrastructure for the future data center. ospab.host is the first step towards the digital future of Veliky Novgorod, and we're just getting started.",
},
},
},
mission: {
title: 'Our Mission',
subtitle: "Make quality hosting accessible to everyone, and the data center — the city's pride",
features: {
technologies: {
title: 'Modern Technologies',
description: 'We use the latest equipment and software for maximum performance',
},
security: {
title: 'Data Security',
description: 'Customer data protection is our priority. Regular backups and 24/7 monitoring',
},
support: {
title: 'Personal Support',
description: 'Every customer receives personal attention and help from the founder',
},
},
},
whyChoose: {
title: 'Why choose ospab.host?',
features: {
first: {
title: 'First data center in the city',
description: "We're making Veliky Novgorod history",
},
pricing: {
title: 'Affordable pricing',
description: 'Quality hosting for everyone without overpaying',
},
fastSupport: {
title: 'Fast support',
description: "We'll answer questions anytime",
},
transparency: {
title: 'Transparency',
description: 'Honest about capabilities and limitations',
},
infrastructure: {
title: 'Modern infrastructure',
description: 'Up-to-date software and equipment',
},
dream: {
title: 'A dream becoming reality',
description: 'A story to be proud of',
},
openSource: {
title: 'Source code on GitHub',
},
},
},
cta: {
title: 'Become part of history',
subtitle: 'Join ospab.host and help create the digital future of Veliky Novgorod',
startFree: 'Start for free',
viewPlans: 'View plans',
},
team: {
title: 'Our Team',
@@ -324,8 +407,13 @@ export const en: TranslationKeys = {
title: 'S3 Storage Pricing',
subtitle: 'Choose the right plan for your needs',
popular: 'Popular',
features: 'Features',
storage: 'Storage',
features: 'Features', baseFeatures: [
'S3-compatible API and AWS SDK support',
'Deployment in ru-central-1 region',
'Versioning and presigned URLs',
'Access management via Access Key/Secret Key',
'Notifications and monitoring in client panel'
], storage: 'Storage',
traffic: 'Outbound Traffic',
requests: 'Requests',
support: 'Support',
@@ -338,5 +426,45 @@ export const en: TranslationKeys = {
contactUs: 'Contact Us',
customPlan: 'Need a custom plan?',
customPlanDescription: 'Contact us to discuss special requirements.',
error: {
loadFailed: 'Failed to load plans',
loadError: 'Error loading plans',
},
page: {
title: 'Transparent pricing for any volume',
subtitle: 'Pay only for the resources you need. 12 ready-made plans for teams of any size, with included traffic, requests and priority support.',
network: 'network',
api: 'S3-compatible API',
loadReady: 'Load Ready',
loadReadyDesc: 'Infrastructure ready for peak loads up to 10 Gbit/s per server.',
security: 'Security',
securityDesc: 'AES-256 encryption, regular audits and compliance with standards.',
compatibility: 'Compatibility',
compatibilityDesc: 'Full compatibility with AWS S3 API and SDK.',
payAsYouGo: 'Pay as you go',
payAsYouGoDesc: 'Pay only for used resources without hidden fees.',
customPlanTitle: 'Custom Plan',
customPlanDesc: 'Calculate cost for your project',
gb: 'GB',
calculate: 'Calculate',
paymentError: 'Failed to start payment',
creatingCart: 'Creating cart...',
selectPlan: 'Select plan',
customTitle: 'Custom Plan',
customDesc: 'Specify the required amount of GB and get automatic cost calculation',
gbQuestion: 'How many GB do you need?',
useCases: {
backups: 'Backups & DR',
backupsDesc: 'Replication, Object Lock and object lifecycle allow storing backups and quick recovery.',
media: 'Media Platforms',
mediaDesc: 'CDN integration, presigned URLs and high bandwidth for video, images and audio.',
saas: 'SaaS & Data Lake',
saasDesc: 'IAM, API versions and audit logs ensure security and compliance with GDPR, 152-FZ and SOC 2.',
},
cta: {
title: 'Ready to deploy S3 storage?',
subtitle: 'Create an account and get access to management console, API keys and detailed usage analytics.',
},
},
},
};

View File

@@ -59,9 +59,92 @@ export const ru = {
about: {
title: 'О компании',
subtitle: 'Ospab.host — современная платформа облачного хранилища',
hero: {
title: 'История ospab.host',
subtitle: 'Первый дата-центр в Великом Новгороде.',
},
founder: {
name: 'Георгий',
title: 'Основатель и CEO',
age: '13 лет',
location: 'Великий Новгород',
github: 'Исходный код проекта',
bio: 'В 13 лет я решил создать то, чего не было в моём городе — современный дата-центр. Начав с изучения технологий и работы над первым хостингом, я постепенно превращаю мечту в реальность. С помощью друга-инвестора мы строим инфраструктуру будущего для Великого Новгорода.',
alt: 'Георгий, основатель ospab.host',
},
story: {
title: 'Наша история',
text: 'Мы создали ospab.host чтобы предоставить надёжное и доступное облачное хранилище для бизнеса и разработчиков.',
sections: {
start: {
title: 'Сентябрь 2025 — Начало пути',
text: 'Всё началось с простой идеи: создать место, где любой сможет разместить свой проект, сайт или сервер с максимальной надёжностью и скоростью. Великий Новгород заслуживает свой дата-центр, и я решил взяться за эту задачу.',
},
support: {
title: 'Поддержка и развитие',
text: 'Мой друг-инвестор поверил в проект и помогает с развитием инфраструктуры. Мы строим не просто бизнес, а сообщество, где каждый клиент — как друг, а поддержка всегда рядом.',
},
future: {
title: 'Настоящее и будущее',
text: 'Сейчас мы активно работаем над хостингом и подготовкой инфраструктуры для будущего ЦОД. ospab.host — это первый шаг к цифровому будущему Великого Новгорода, и мы только начинаем.',
},
},
},
mission: {
title: 'Наша миссия',
subtitle: 'Сделать качественный хостинг доступным для всех, а ЦОД — гордостью города',
features: {
technologies: {
title: 'Современные технологии',
description: 'Используем новейшее оборудование и программное обеспечение для максимальной производительности',
},
security: {
title: 'Безопасность данных',
description: 'Защита информации клиентов — наш приоритет. Регулярные бэкапы и мониторинг 24/7',
},
support: {
title: 'Личная поддержка',
description: 'Каждый клиент получает персональное внимание и помощь от основателя',
},
},
},
whyChoose: {
title: 'Почему выбирают ospab.host?',
features: {
first: {
title: 'Первый ЦОД в городе',
description: 'Мы создаём историю Великого Новгорода',
},
pricing: {
title: 'Доступные тарифы',
description: 'Качественный хостинг для всех без переплат',
},
fastSupport: {
title: 'Быстрая поддержка',
description: 'Ответим на вопросы в любое время',
},
transparency: {
title: 'Прозрачность',
description: 'Честно о возможностях и ограничениях',
},
infrastructure: {
title: 'Современная инфраструктура',
description: 'Актуальное ПО и оборудование',
},
dream: {
title: 'Мечта становится реальностью',
description: 'История, которой можно гордиться',
},
openSource: {
title: 'Исходный код на GitHub',
},
},
},
cta: {
title: 'Станьте частью истории',
subtitle: 'Присоединяйтесь к ospab.host и помогите создать цифровое будущее Великого Новгорода',
startFree: 'Начать бесплатно',
viewPlans: 'Посмотреть тарифы',
},
team: {
title: 'Наша команда',
@@ -323,6 +406,13 @@ export const ru = {
subtitle: 'Выберите подходящий план для ваших задач',
popular: 'Популярный',
features: 'Возможности',
baseFeatures: [
'S3-совместимый API и совместимость с AWS SDK',
'Развёртывание в регионе ru-central-1',
'Версионирование и presigned URL',
'Управление доступом через Access Key/Secret Key',
'Уведомления и мониторинг в панели клиента'
],
storage: 'Хранилище',
traffic: 'Исходящий трафик',
requests: 'Запросов',
@@ -336,6 +426,46 @@ export const ru = {
contactUs: 'Связаться с нами',
customPlan: 'Нужен индивидуальный план?',
customPlanDescription: 'Свяжитесь с нами для обсуждения особых условий.',
error: {
loadFailed: 'Не удалось загрузить тарифы',
loadError: 'Ошибка загрузки тарифов',
},
page: {
title: 'Прозрачные тарифы для любого объёма',
subtitle: 'Оплачивайте только за необходимые ресурсы. 12 готовых тарифов для команд любого размера, с включённым трафиком, запросами и приоритетной поддержкой.',
network: 'сеть',
api: 'S3-совместимый API',
loadReady: 'Готовность к нагрузке',
loadReadyDesc: 'Инфраструктура готова к пиковым нагрузкам до 10 Гбит/с на сервер.',
security: 'Безопасность',
securityDesc: 'Шифрование AES-256, регулярные аудиты и соответствие стандартам.',
compatibility: 'Совместимость',
compatibilityDesc: 'Полная совместимость с AWS S3 API и SDK.',
payAsYouGo: 'Оплата по факту',
payAsYouGoDesc: 'Оплачивайте только за использованные ресурсы без скрытых платежей.',
customPlanTitle: 'Индивидуальный тариф',
customPlanDesc: 'Рассчитайте стоимость для вашего проекта',
gb: 'ГБ',
calculate: 'Рассчитать',
paymentError: 'Не удалось начать оплату',
creatingCart: 'Создание корзины...',
selectPlan: 'Выбрать план',
customTitle: 'Кастомный тариф',
customDesc: 'Укажите нужное количество GB и получите автоматический расчёт стоимости',
gbQuestion: 'Сколько GB вам нужно?',
useCases: {
backups: 'Бэкапы и DR',
backupsDesc: 'Репликация, Object Lock и цикл жизни объектов позволяют хранить резервные копии и быстро восстанавливаться.',
media: 'Медиа-платформы',
mediaDesc: 'CDN-интеграция, presigned URL и высокая пропускная способность для видео, изображений и аудио.',
saas: 'SaaS & Data Lake',
saasDesc: 'IAM, версии API и аудит логов обеспечивают безопасность и соответствие требованиям GDPR, 152-ФЗ и SOC 2.',
},
cta: {
title: 'Готовы развернуть S3 хранилище?',
subtitle: 'Создайте аккаунт и получите доступ к консоли управления, API ключам и детальной аналитике использования.',
},
},
},
};

View File

@@ -24,7 +24,7 @@ type TranslationKey = NestedKeyOf<TranslationKeys>;
/**
* Получить значение по вложенному ключу
*/
function getNestedValue(obj: Record<string, unknown>, path: string): string {
function getNestedValue(obj: Record<string, unknown>, path: string): any {
const keys = path.split('.');
let current: unknown = obj;
@@ -36,7 +36,7 @@ function getNestedValue(obj: Record<string, unknown>, path: string): string {
}
}
return typeof current === 'string' ? current : path;
return current;
}
/**
@@ -46,18 +46,20 @@ export function useTranslation() {
const { locale, setLocale } = useLocale();
const t = useCallback(
(key: TranslationKey, params?: Record<string, string | number>): string => {
(key: TranslationKey, params?: Record<string, string | number>): any => {
const translation = getNestedValue(
translations[locale] as unknown as Record<string, unknown>,
key
);
if (!params) return translation;
if (typeof translation === 'string' && params) {
// Замена параметров {{param}}
return translation.replace(/\{\{(\w+)\}\}/g, (_, paramKey) => {
return params[paramKey]?.toString() ?? `{{${paramKey}}}`;
});
}
// Замена параметров {{param}}
return translation.replace(/\{\{(\w+)\}\}/g, (_, paramKey) => {
return params[paramKey]?.toString() ?? `{{${paramKey}}}`;
});
return translation ?? key;
},
[locale]
);