fix: improve mobile layout for bandwidth and add pluralization support

This commit is contained in:
c0mrade
2026-02-02 11:14:29 +03:00
parent ed86dfa8bd
commit e9af285dad
5 changed files with 31 additions and 4 deletions

View File

@@ -881,6 +881,8 @@
"restartAll": "Restart All", "restartAll": "Restart All",
"confirmRestartAll": "Are you sure you want to restart all nodes?", "confirmRestartAll": "Are you sure you want to restart all nodes?",
"usersOnline": "online", "usersOnline": "online",
"usersOnlineCount_one": "{{count}} online",
"usersOnlineCount_other": "{{count}} online",
"trafficUsed": "used", "trafficUsed": "used",
"uptimeLabel": "Uptime", "uptimeLabel": "Uptime",
"stats": { "stats": {
@@ -897,7 +899,11 @@
"noSquads": "No squads found", "noSquads": "No squads found",
"syncServers": "Sync Servers", "syncServers": "Sync Servers",
"members": "members", "members": "members",
"membersCount_one": "{{count}} member",
"membersCount_other": "{{count}} members",
"inbounds": "inbounds", "inbounds": "inbounds",
"inboundsCount_one": "{{count}} inbound",
"inboundsCount_other": "{{count}} inbounds",
"available": "Available", "available": "Available",
"unavailable": "Unavailable", "unavailable": "Unavailable",
"stats": { "stats": {

View File

@@ -1704,6 +1704,7 @@
"restart": "راه‌اندازی مجدد", "restart": "راه‌اندازی مجدد",
"restartAll": "راه‌اندازی مجدد همه", "restartAll": "راه‌اندازی مجدد همه",
"usersOnline": "آنلاین", "usersOnline": "آنلاین",
"usersOnlineCount_other": "{{count}} آنلاین",
"trafficUsed": "استفاده شده", "trafficUsed": "استفاده شده",
"uptimeLabel": "زمان فعالیت", "uptimeLabel": "زمان فعالیت",
"stats": { "stats": {
@@ -1742,7 +1743,9 @@
"syncServers": "همگام‌سازی سرورها", "syncServers": "همگام‌سازی سرورها",
"synced": "همگام شده", "synced": "همگام شده",
"members": "اعضا", "members": "اعضا",
"membersCount_other": "{{count}} عضو",
"inbounds": "ورودی‌ها", "inbounds": "ورودی‌ها",
"inboundsCount_other": "{{count}} ورودی",
"available": "در دسترس", "available": "در دسترس",
"unavailable": "در دسترس نیست", "unavailable": "در دسترس نیست",
"stats": { "stats": {

View File

@@ -897,6 +897,9 @@
"restartAll": "Перезапустить все", "restartAll": "Перезапустить все",
"confirmRestartAll": "Вы уверены, что хотите перезапустить все ноды?", "confirmRestartAll": "Вы уверены, что хотите перезапустить все ноды?",
"usersOnline": "онлайн", "usersOnline": "онлайн",
"usersOnlineCount_one": "{{count}} онлайн",
"usersOnlineCount_few": "{{count}} онлайн",
"usersOnlineCount_many": "{{count}} онлайн",
"trafficUsed": "использовано", "trafficUsed": "использовано",
"uptimeLabel": "Аптайм", "uptimeLabel": "Аптайм",
"stats": { "stats": {
@@ -913,7 +916,13 @@
"noSquads": "Сквады не найдены", "noSquads": "Сквады не найдены",
"syncServers": "Синхронизировать серверы", "syncServers": "Синхронизировать серверы",
"members": "участников", "members": "участников",
"membersCount_one": "{{count}} участник",
"membersCount_few": "{{count}} участника",
"membersCount_many": "{{count}} участников",
"inbounds": "inbounds", "inbounds": "inbounds",
"inboundsCount_one": "{{count}} inbound",
"inboundsCount_few": "{{count}} inbounds",
"inboundsCount_many": "{{count}} inbounds",
"available": "Доступен", "available": "Доступен",
"unavailable": "Недоступен", "unavailable": "Недоступен",
"stats": { "stats": {

View File

@@ -1712,6 +1712,7 @@
"restart": "重启", "restart": "重启",
"restartAll": "全部重启", "restartAll": "全部重启",
"usersOnline": "在线", "usersOnline": "在线",
"usersOnlineCount_other": "{{count}} 在线",
"trafficUsed": "已使用", "trafficUsed": "已使用",
"uptimeLabel": "运行时间", "uptimeLabel": "运行时间",
"stats": { "stats": {
@@ -1750,7 +1751,9 @@
"syncServers": "同步服务器", "syncServers": "同步服务器",
"synced": "已同步", "synced": "已同步",
"members": "成员", "members": "成员",
"membersCount_other": "{{count}} 成员",
"inbounds": "入站", "inbounds": "入站",
"inboundsCount_other": "{{count}} 入站",
"available": "可用", "available": "可用",
"unavailable": "不可用", "unavailable": "不可用",
"stats": { "stats": {

View File

@@ -157,7 +157,9 @@ function NodeCard({ node, onAction, isLoading }: NodeCardProps) {
<div className="mt-3 flex flex-wrap gap-x-4 gap-y-1 text-xs text-dark-400"> <div className="mt-3 flex flex-wrap gap-x-4 gap-y-1 text-xs text-dark-400">
<span className="flex items-center gap-1"> <span className="flex items-center gap-1">
<UsersIcon className="h-3.5 w-3.5" /> <UsersIcon className="h-3.5 w-3.5" />
{node.users_online ?? 0} {t('admin.remnawave.nodes.usersOnline', 'online')} {t('admin.remnawave.nodes.usersOnlineCount', '{{count}} online', {
count: node.users_online ?? 0,
})}
</span> </span>
{node.traffic_used_bytes !== undefined && ( {node.traffic_used_bytes !== undefined && (
<span> <span>
@@ -239,7 +241,9 @@ function SquadCard({ squad, onClick }: SquadCardProps) {
<div className="mt-3 flex flex-wrap gap-x-4 gap-y-1 text-xs text-dark-400"> <div className="mt-3 flex flex-wrap gap-x-4 gap-y-1 text-xs text-dark-400">
<span className="flex items-center gap-1"> <span className="flex items-center gap-1">
<UsersIcon className="h-3.5 w-3.5" /> <UsersIcon className="h-3.5 w-3.5" />
{squad.members_count} {t('admin.remnawave.squads.members', 'members')} {t('admin.remnawave.squads.membersCount', '{{count}} members', {
count: squad.members_count,
})}
</span> </span>
{squad.current_users !== undefined && ( {squad.current_users !== undefined && (
<span> <span>
@@ -247,7 +251,9 @@ function SquadCard({ squad, onClick }: SquadCardProps) {
</span> </span>
)} )}
<span> <span>
{squad.inbounds_count} {t('admin.remnawave.squads.inbounds', 'inbounds')} {t('admin.remnawave.squads.inboundsCount', '{{count}} inbounds', {
count: squad.inbounds_count,
})}
</span> </span>
{squad.is_available !== undefined && ( {squad.is_available !== undefined && (
<span className={squad.is_available ? 'text-success-400' : 'text-error-400'}> <span className={squad.is_available ? 'text-success-400' : 'text-error-400'}>
@@ -389,7 +395,7 @@ function OverviewTab({ stats, isLoading, onRefresh }: OverviewTabProps) {
<h3 className="mb-3 text-sm font-medium text-dark-300"> <h3 className="mb-3 text-sm font-medium text-dark-300">
{t('admin.remnawave.overview.bandwidth', 'Realtime Bandwidth')} {t('admin.remnawave.overview.bandwidth', 'Realtime Bandwidth')}
</h3> </h3>
<div className="grid grid-cols-3 gap-3"> <div className="grid grid-cols-2 gap-3 sm:grid-cols-3">
<StatCard <StatCard
label={t('admin.remnawave.overview.download', 'Download')} label={t('admin.remnawave.overview.download', 'Download')}
value={formatBytes(stats.bandwidth.realtime_download) + '/s'} value={formatBytes(stats.bandwidth.realtime_download) + '/s'}