+
@@ -56,34 +47,6 @@ export default function SponsorsPage() {
const { data, fetched } = useSponsorsQuery();
const sponsors = sponsorsForSlot(data.sponsors, 'page');
- const { datepicker } = useDatepicker();
- const placements: { slot: SponsorSlot; icon: ReactNode; title: string; desc: string }[] = [
- {
- slot: 'dashboard',
- icon:
,
- title: t('pages.sponsors.placementDashboard'),
- desc: t('pages.sponsors.placementDashboardDesc'),
- },
- {
- slot: 'sidebar',
- icon:
,
- title: t('pages.sponsors.placementSidebar'),
- desc: t('pages.sponsors.placementSidebarDesc'),
- },
- {
- slot: 'login',
- icon:
,
- title: t('pages.sponsors.placementLogin'),
- desc: t('pages.sponsors.placementLoginDesc'),
- },
- {
- slot: 'page',
- icon:
,
- title: t('pages.sponsors.placementPage'),
- desc: t('pages.sponsors.placementPageDesc'),
- },
- ];
-
const pageClass = useMemo(() => {
const classes = ['sponsors-page'];
if (isDark) classes.push('is-dark');
@@ -110,63 +73,17 @@ export default function SponsorsPage() {
{sponsors.length === 0 ? (
- fetched &&
+ fetched &&
) : (
{sponsors.map((sponsor) => (
-
+
))}
- {data.contact && (
-
-
-
- )}
)}
-
-
- {t('pages.sponsors.placements')}
-
-
- {placements.map((p) => {
- const status = placementStatus(data.sponsors, p.slot);
- return (
-
-
-
{p.icon}
-
-
{p.title}
-
{p.desc}
-
- {status.takenUntil ? (
-
- {t('pages.sponsors.takenUntil', {
- date: IntlUtil.formatDate(status.takenUntil, datepicker),
- })}
-
- ) : (
- {t('pages.sponsors.available')}
- )}
- {status.count > 0 && !status.takenUntil && (
-
- {t('pages.sponsors.activeCount', {
- count:
- status.capacity && status.capacity > 1
- ? `${status.count}/${status.capacity}`
- : status.count,
- })}
-
- )}
-
-
-
-
- );
- })}
-
diff --git a/frontend/src/test/sponsors.test.tsx b/frontend/src/test/sponsors.test.tsx
index 218491101..9d5d469db 100644
--- a/frontend/src/test/sponsors.test.tsx
+++ b/frontend/src/test/sponsors.test.tsx
@@ -1,12 +1,6 @@
import { afterEach, describe, expect, test } from 'vitest';
-import {
- SPONSOR_DISMISS_MS,
- dismissSponsor,
- isSponsorDismissed,
- pickLocale,
- placementStatus,
-} from '@/lib/sponsors';
+import { SPONSOR_DISMISS_MS, dismissSponsor, isSponsorDismissed, pickLocale } from '@/lib/sponsors';
afterEach(() => {
localStorage.clear();
@@ -33,10 +27,10 @@ describe('sponsor dismissal', () => {
const t0 = 1_800_000_000_000;
test('hides only the dismissed slot until the window elapses', () => {
- dismissSponsor('acme', 'sidebar', t0);
- expect(isSponsorDismissed('acme', 'sidebar', t0 + SPONSOR_DISMISS_MS - 1)).toBe(true);
+ dismissSponsor('acme', 'login', t0);
+ expect(isSponsorDismissed('acme', 'login', t0 + SPONSOR_DISMISS_MS - 1)).toBe(true);
expect(isSponsorDismissed('acme', 'dashboard', t0)).toBe(false);
- expect(isSponsorDismissed('acme', 'sidebar', t0 + SPONSOR_DISMISS_MS)).toBe(false);
+ expect(isSponsorDismissed('acme', 'login', t0 + SPONSOR_DISMISS_MS)).toBe(false);
});
test('prunes expired entries on the next dismiss', () => {
@@ -48,51 +42,6 @@ describe('sponsor dismissal', () => {
test('corrupt storage is treated as nothing dismissed', () => {
localStorage.setItem('xui.sponsor.dismissed', 'not json');
- expect(isSponsorDismissed('acme', 'sidebar', t0)).toBe(false);
- });
-});
-
-describe('placementStatus', () => {
- const sp = (id: string, slots: string[], until: string) => ({
- id,
- name: id,
- slots,
- until,
- title: {},
- text: {},
- link: 'https://x.example/',
- });
-
- test('exclusive slot is taken until the latest booking ends', () => {
- const sponsors = [
- sp('a', ['dashboard'], '2026-11-01T00:00:00Z'),
- sp('b', ['dashboard'], '2026-12-15T00:00:00Z'),
- ];
- expect(placementStatus(sponsors, 'dashboard')).toEqual({
- count: 2,
- capacity: 1,
- takenUntil: '2026-12-15T00:00:00Z',
- });
- });
-
- test('sidebar is full at three and frees up when the earliest ends', () => {
- const sponsors = [
- sp('a', ['sidebar'], '2026-12-01T00:00:00Z'),
- sp('b', ['sidebar'], '2026-10-20T00:00:00Z'),
- sp('c', ['sidebar'], '2026-11-10T00:00:00Z'),
- ];
- expect(placementStatus(sponsors, 'sidebar')).toEqual({
- count: 3,
- capacity: 3,
- takenUntil: '2026-10-20T00:00:00Z',
- });
- expect(placementStatus(sponsors.slice(0, 2), 'sidebar')).toEqual({ count: 2, capacity: 3 });
- });
-
- test('uncapped page slot reports only a count', () => {
- expect(placementStatus([sp('a', ['page'], '2026-12-01T00:00:00Z')], 'page')).toEqual({
- count: 1,
- capacity: undefined,
- });
+ expect(isSponsorDismissed('acme', 'login', t0)).toBe(false);
});
});
diff --git a/internal/web/service/panel/sponsor.go b/internal/web/service/panel/sponsor.go
index 6f9b27a92..d8e6c4ad1 100644
--- a/internal/web/service/panel/sponsor.go
+++ b/internal/web/service/panel/sponsor.go
@@ -45,7 +45,6 @@ const (
sponsorsErrTTL = 10 * time.Minute
maxSponsorsBytes = 256 << 10
maxLogoBytes = 256 << 10
- maxSidebarSlots = 3
localSponsorsDir = "../sponsors/3X"
sponsorLogoPath = "/sponsors/logo/"
)
@@ -67,7 +66,7 @@ var (
// The panel proxies logos from sponsorLogoBase: CSP stays 'self' and no third party sees admin IPs.
sponsorLogoRe = regexp.MustCompile(`^[A-Za-z0-9_-][A-Za-z0-9._-]*\.(png|webp|jpg)$`)
- sponsorSlots = map[string]bool{"dashboard": true, "sidebar": true, "page": true, "login": true}
+ sponsorSlots = map[string]bool{"dashboard": true, "page": true, "login": true}
sponsorsMu sync.Mutex
sponsorsRaw *SponsorList
@@ -217,7 +216,6 @@ func activeSponsors(raw *SponsorList, now time.Time) *SponsorList {
if strings.HasPrefix(raw.Contact, "https://") {
out.Contact = raw.Contact
}
- sidebarTaken := 0
for _, sp := range raw.Sponsors {
// A missing enable counts as on, so a forgotten field never hides a paid slot.
disabled := sp.Enable != nil && !*sp.Enable
@@ -233,18 +231,13 @@ func activeSponsors(raw *SponsorList, now time.Time) *SponsorList {
}
slots := make([]string, 0, len(sp.Slots))
for _, slot := range sp.Slots {
- // The sidebar rotates, so capping it keeps each paid card on screen long enough.
- if !sponsorSlots[slot] || (slot == "sidebar" && sidebarTaken >= maxSidebarSlots) {
- continue
+ if sponsorSlots[slot] {
+ slots = append(slots, slot)
}
- slots = append(slots, slot)
}
if len(slots) == 0 {
continue
}
- if slices.Contains(slots, "sidebar") {
- sidebarTaken++
- }
sp.Slots = slots
out.Sponsors = append(out.Sponsors, sp)
}
diff --git a/internal/web/service/panel/sponsor_test.go b/internal/web/service/panel/sponsor_test.go
index b2d244c12..c6bfe0c6b 100644
--- a/internal/web/service/panel/sponsor_test.go
+++ b/internal/web/service/panel/sponsor_test.go
@@ -6,7 +6,6 @@ import (
"net/http/httptest"
"os"
"path/filepath"
- "slices"
"strings"
"sync/atomic"
"testing"
@@ -22,7 +21,7 @@ func validSponsor() Sponsor {
return Sponsor{
ID: "acme",
Name: "Acme",
- Slots: []string{"dashboard", "sidebar"},
+ Slots: []string{"dashboard"},
Until: sponsorTestNow.Add(24 * time.Hour),
Logo: "acme.png",
Link: "https://acme.example/",
@@ -59,34 +58,6 @@ func TestActiveSponsorsFilters(t *testing.T) {
}
}
-func TestActiveSponsorsCapsSidebarAtThree(t *testing.T) {
- raw := &SponsorList{}
- for _, id := range []string{"expired", "a", "b", "c", "d", "e"} {
- sp := validSponsor()
- sp.ID = id
- sp.Slots = []string{"sidebar", "page"}
- if id == "expired" {
- sp.Until = sponsorTestNow
- }
- if id == "e" {
- sp.Slots = []string{"sidebar"}
- }
- raw.Sponsors = append(raw.Sponsors, sp)
- }
- got := activeSponsors(raw, sponsorTestNow)
- want := map[string][]string{
- "a": {"sidebar", "page"}, "b": {"sidebar", "page"}, "c": {"sidebar", "page"}, "d": {"page"},
- }
- if len(got.Sponsors) != len(want) {
- t.Fatalf("got %d sponsors, want %d (e has only sidebar and must drop)", len(got.Sponsors), len(want))
- }
- for _, sp := range got.Sponsors {
- if !slices.Equal(sp.Slots, want[sp.ID]) {
- t.Errorf("%s slots = %v, want %v", sp.ID, sp.Slots, want[sp.ID])
- }
- }
-}
-
func TestActiveSponsorsLogoName(t *testing.T) {
cases := []struct{ logo, want string }{
{"acme.png", "/sponsors/logo/acme.png"},
@@ -114,7 +85,7 @@ func TestActiveSponsorsLogoName(t *testing.T) {
func TestActiveSponsorsResolvesLogoAndSlots(t *testing.T) {
sp := validSponsor()
- sp.Slots = []string{"subpage", "login"}
+ sp.Slots = []string{"subpage", "sidebar", "login"}
got := activeSponsors(&SponsorList{Contact: "javascript:x", Sponsors: []Sponsor{sp}}, sponsorTestNow)
if len(got.Sponsors) != 1 {
t.Fatalf("got %d sponsors, want 1", len(got.Sponsors))
diff --git a/internal/web/translation/ar-EG.json b/internal/web/translation/ar-EG.json
index ccf5c6c28..16e143831 100644
--- a/internal/web/translation/ar-EG.json
+++ b/internal/web/translation/ar-EG.json
@@ -2423,19 +2423,7 @@
"tag": "راعٍ",
"visit": "زيارة",
"yourBrand": "علامتك التجارية هنا",
- "yourBrandText": "ضع شركتك أمام آلاف مسؤولي الخوادم الذين يفتحون 3X-UI كل يوم.",
- "placements": "المواضع المتاحة",
- "placementDashboard": "لافتة لوحة المعلومات",
- "placementDashboardDesc": "موضع مميز أعلى لوحة المعلومات، راعٍ واحد في كل مرة.",
- "placementSidebar": "بطاقة الشريط الجانبي",
- "placementSidebarDesc": "تظهر في كل صفحات اللوحة وتتناوب بين الرعاة.",
- "placementLogin": "صفحة تسجيل الدخول",
- "placementLoginDesc": "يراها المسؤول عند كل تسجيل دخول.",
- "placementPage": "صفحة الرعاة",
- "placementPageDesc": "مدرجة هنا مع الشعار والوصف والرابط.",
- "available": "متاح",
- "takenUntil": "محجوز حتى {date}",
- "activeCount": "{count} نشط"
+ "yourBrandText": "ضع شركتك أمام آلاف مسؤولي الخوادم الذين يفتحون 3X-UI كل يوم."
}
},
"tgbot": {
diff --git a/internal/web/translation/en-US.json b/internal/web/translation/en-US.json
index 1e36a4f10..97290aa34 100644
--- a/internal/web/translation/en-US.json
+++ b/internal/web/translation/en-US.json
@@ -2423,19 +2423,7 @@
"tag": "Sponsor",
"visit": "Visit",
"yourBrand": "Your brand here",
- "yourBrandText": "Put your company in front of thousands of server admins who open 3X-UI every day.",
- "placements": "Available placements",
- "placementDashboard": "Overview banner",
- "placementDashboardDesc": "Premium spot at the top of the dashboard, one sponsor at a time.",
- "placementSidebar": "Sidebar card",
- "placementSidebarDesc": "Shown on every panel page, rotating between sponsors.",
- "placementLogin": "Login page",
- "placementLoginDesc": "Seen by the admin at every sign-in.",
- "placementPage": "Sponsors page",
- "placementPageDesc": "Listed here with logo, description and link.",
- "available": "Available",
- "takenUntil": "Taken until {date}",
- "activeCount": "{count} active"
+ "yourBrandText": "Put your company in front of thousands of server admins who open 3X-UI every day."
}
},
"tgbot": {
diff --git a/internal/web/translation/es-ES.json b/internal/web/translation/es-ES.json
index a7ecf7081..d6953176c 100644
--- a/internal/web/translation/es-ES.json
+++ b/internal/web/translation/es-ES.json
@@ -2423,19 +2423,7 @@
"tag": "Patrocinador",
"visit": "Visitar",
"yourBrand": "Tu marca aquí",
- "yourBrandText": "Muestra tu empresa a miles de administradores de servidores que abren 3X-UI cada día.",
- "placements": "Espacios disponibles",
- "placementDashboard": "Banner del panel",
- "placementDashboardDesc": "Espacio premium en la parte superior del panel, un patrocinador a la vez.",
- "placementSidebar": "Tarjeta lateral",
- "placementSidebarDesc": "Se muestra en todas las páginas del panel, rotando entre patrocinadores.",
- "placementLogin": "Página de inicio de sesión",
- "placementLoginDesc": "La ve el administrador en cada inicio de sesión.",
- "placementPage": "Página de patrocinadores",
- "placementPageDesc": "Aparece aquí con logo, descripción y enlace.",
- "available": "Disponible",
- "takenUntil": "Ocupado hasta {date}",
- "activeCount": "{count} activos"
+ "yourBrandText": "Muestra tu empresa a miles de administradores de servidores que abren 3X-UI cada día."
}
},
"tgbot": {
diff --git a/internal/web/translation/fa-IR.json b/internal/web/translation/fa-IR.json
index da42d9691..3a4e934c3 100644
--- a/internal/web/translation/fa-IR.json
+++ b/internal/web/translation/fa-IR.json
@@ -2423,19 +2423,7 @@
"tag": "اسپانسر",
"visit": "مشاهده",
"yourBrand": "جای برند شما",
- "yourBrandText": "شرکت خود را جلوی چشم هزاران ادمین سروری بگذارید که هر روز 3X-UI را باز میکنند.",
- "placements": "جایگاههای موجود",
- "placementDashboard": "بنر داشبورد",
- "placementDashboardDesc": "جایگاه ویژه بالای صفحهی داشبورد، هر بار فقط یک اسپانسر.",
- "placementSidebar": "کارت سایدبار",
- "placementSidebarDesc": "در همهی صفحات پنل نمایش داده میشود و بین اسپانسرها چرخش دارد.",
- "placementLogin": "صفحهی ورود",
- "placementLoginDesc": "ادمین در هر بار ورود آن را میبیند.",
- "placementPage": "صفحهی اسپانسرها",
- "placementPageDesc": "همراه با لوگو، توضیحات و لینک در همین صفحه.",
- "available": "خالی",
- "takenUntil": "پر شده تا {date}",
- "activeCount": "{count} فعال"
+ "yourBrandText": "شرکت خود را جلوی چشم هزاران ادمین سروری بگذارید که هر روز 3X-UI را باز میکنند."
}
},
"tgbot": {
diff --git a/internal/web/translation/id-ID.json b/internal/web/translation/id-ID.json
index 024054197..1af42df6f 100644
--- a/internal/web/translation/id-ID.json
+++ b/internal/web/translation/id-ID.json
@@ -2423,19 +2423,7 @@
"tag": "Sponsor",
"visit": "Kunjungi",
"yourBrand": "Merek Anda di sini",
- "yourBrandText": "Tampilkan perusahaan Anda kepada ribuan admin server yang membuka 3X-UI setiap hari.",
- "placements": "Slot yang tersedia",
- "placementDashboard": "Banner dasbor",
- "placementDashboardDesc": "Tempat premium di atas dasbor, satu sponsor dalam satu waktu.",
- "placementSidebar": "Kartu sidebar",
- "placementSidebarDesc": "Tampil di setiap halaman panel, bergantian antar sponsor.",
- "placementLogin": "Halaman login",
- "placementLoginDesc": "Dilihat admin setiap kali masuk.",
- "placementPage": "Halaman sponsor",
- "placementPageDesc": "Tercantum di sini dengan logo, deskripsi, dan tautan.",
- "available": "Tersedia",
- "takenUntil": "Terisi hingga {date}",
- "activeCount": "{count} aktif"
+ "yourBrandText": "Tampilkan perusahaan Anda kepada ribuan admin server yang membuka 3X-UI setiap hari."
}
},
"tgbot": {
diff --git a/internal/web/translation/ja-JP.json b/internal/web/translation/ja-JP.json
index 2ad0a2f8c..d8927f102 100644
--- a/internal/web/translation/ja-JP.json
+++ b/internal/web/translation/ja-JP.json
@@ -2423,19 +2423,7 @@
"tag": "スポンサー",
"visit": "訪問",
"yourBrand": "ここにあなたのブランドを",
- "yourBrandText": "毎日 3X-UI を開く何千人ものサーバー管理者に御社をアピールできます。",
- "placements": "掲載枠",
- "placementDashboard": "ダッシュボードバナー",
- "placementDashboardDesc": "ダッシュボード上部のプレミアム枠。一度に 1 社のみ。",
- "placementSidebar": "サイドバーカード",
- "placementSidebarDesc": "パネルの全ページに表示され、スポンサー間でローテーションします。",
- "placementLogin": "ログインページ",
- "placementLoginDesc": "管理者がログインするたびに表示されます。",
- "placementPage": "スポンサーページ",
- "placementPageDesc": "ロゴ、説明、リンク付きでここに掲載されます。",
- "available": "空きあり",
- "takenUntil": "{date} まで予約済み",
- "activeCount": "{count} 件掲載中"
+ "yourBrandText": "毎日 3X-UI を開く何千人ものサーバー管理者に御社をアピールできます。"
}
},
"tgbot": {
diff --git a/internal/web/translation/pt-BR.json b/internal/web/translation/pt-BR.json
index e62c85309..b78050110 100644
--- a/internal/web/translation/pt-BR.json
+++ b/internal/web/translation/pt-BR.json
@@ -2423,19 +2423,7 @@
"tag": "Patrocinador",
"visit": "Visitar",
"yourBrand": "Sua marca aqui",
- "yourBrandText": "Coloque sua empresa diante de milhares de administradores de servidores que abrem o 3X-UI todos os dias.",
- "placements": "Espaços disponíveis",
- "placementDashboard": "Banner do painel",
- "placementDashboardDesc": "Espaço premium no topo do painel, um patrocinador por vez.",
- "placementSidebar": "Cartão lateral",
- "placementSidebarDesc": "Exibido em todas as páginas do painel, alternando entre patrocinadores.",
- "placementLogin": "Página de login",
- "placementLoginDesc": "Visto pelo administrador a cada login.",
- "placementPage": "Página de patrocinadores",
- "placementPageDesc": "Listado aqui com logo, descrição e link.",
- "available": "Disponível",
- "takenUntil": "Ocupado até {date}",
- "activeCount": "{count} ativos"
+ "yourBrandText": "Coloque sua empresa diante de milhares de administradores de servidores que abrem o 3X-UI todos os dias."
}
},
"tgbot": {
diff --git a/internal/web/translation/ru-RU.json b/internal/web/translation/ru-RU.json
index b8b4029bc..59c308fb4 100644
--- a/internal/web/translation/ru-RU.json
+++ b/internal/web/translation/ru-RU.json
@@ -2423,19 +2423,7 @@
"tag": "Спонсор",
"visit": "Перейти",
"yourBrand": "Здесь может быть ваш бренд",
- "yourBrandText": "Покажите свою компанию тысячам администраторов серверов, которые каждый день открывают 3X-UI.",
- "placements": "Доступные места",
- "placementDashboard": "Баннер на главной",
- "placementDashboardDesc": "Премиум-место вверху панели, один спонсор за раз.",
- "placementSidebar": "Карточка в боковой панели",
- "placementSidebarDesc": "Показывается на всех страницах панели, спонсоры чередуются.",
- "placementLogin": "Страница входа",
- "placementLoginDesc": "Администратор видит её при каждом входе.",
- "placementPage": "Страница спонсоров",
- "placementPageDesc": "Размещение здесь с логотипом, описанием и ссылкой.",
- "available": "Свободно",
- "takenUntil": "Занято до {date}",
- "activeCount": "Активных: {count}"
+ "yourBrandText": "Покажите свою компанию тысячам администраторов серверов, которые каждый день открывают 3X-UI."
}
},
"tgbot": {
diff --git a/internal/web/translation/tr-TR.json b/internal/web/translation/tr-TR.json
index 1d487bcb7..656485cf4 100644
--- a/internal/web/translation/tr-TR.json
+++ b/internal/web/translation/tr-TR.json
@@ -2423,19 +2423,7 @@
"tag": "Sponsor",
"visit": "Ziyaret et",
"yourBrand": "Markanız burada",
- "yourBrandText": "Şirketinizi her gün 3X-UI açan binlerce sunucu yöneticisinin önüne çıkarın.",
- "placements": "Mevcut yerleşimler",
- "placementDashboard": "Genel bakış afişi",
- "placementDashboardDesc": "Panonun üstünde premium alan, aynı anda tek sponsor.",
- "placementSidebar": "Kenar çubuğu kartı",
- "placementSidebarDesc": "Tüm panel sayfalarında gösterilir, sponsorlar arasında döner.",
- "placementLogin": "Giriş sayfası",
- "placementLoginDesc": "Yönetici her girişte görür.",
- "placementPage": "Sponsorlar sayfası",
- "placementPageDesc": "Logo, açıklama ve bağlantıyla burada listelenir.",
- "available": "Müsait",
- "takenUntil": "{date} tarihine kadar dolu",
- "activeCount": "{count} aktif"
+ "yourBrandText": "Şirketinizi her gün 3X-UI açan binlerce sunucu yöneticisinin önüne çıkarın."
}
},
"tgbot": {
diff --git a/internal/web/translation/uk-UA.json b/internal/web/translation/uk-UA.json
index 991e112b5..f365d3f08 100644
--- a/internal/web/translation/uk-UA.json
+++ b/internal/web/translation/uk-UA.json
@@ -2423,19 +2423,7 @@
"tag": "Спонсор",
"visit": "Перейти",
"yourBrand": "Тут може бути ваш бренд",
- "yourBrandText": "Покажіть свою компанію тисячам адміністраторів серверів, які щодня відкривають 3X-UI.",
- "placements": "Доступні місця",
- "placementDashboard": "Банер на головній",
- "placementDashboardDesc": "Преміум-місце вгорі панелі, один спонсор за раз.",
- "placementSidebar": "Картка в бічній панелі",
- "placementSidebarDesc": "Показується на всіх сторінках панелі, спонсори чергуються.",
- "placementLogin": "Сторінка входу",
- "placementLoginDesc": "Адміністратор бачить її під час кожного входу.",
- "placementPage": "Сторінка спонсорів",
- "placementPageDesc": "Розміщення тут із логотипом, описом і посиланням.",
- "available": "Вільно",
- "takenUntil": "Зайнято до {date}",
- "activeCount": "Активних: {count}"
+ "yourBrandText": "Покажіть свою компанію тисячам адміністраторів серверів, які щодня відкривають 3X-UI."
}
},
"tgbot": {
diff --git a/internal/web/translation/vi-VN.json b/internal/web/translation/vi-VN.json
index 6df8d3ac7..98a6ddcab 100644
--- a/internal/web/translation/vi-VN.json
+++ b/internal/web/translation/vi-VN.json
@@ -2423,19 +2423,7 @@
"tag": "Tài trợ",
"visit": "Truy cập",
"yourBrand": "Thương hiệu của bạn ở đây",
- "yourBrandText": "Đưa công ty bạn đến hàng nghìn quản trị viên máy chủ mở 3X-UI mỗi ngày.",
- "placements": "Vị trí hiện có",
- "placementDashboard": "Banner tổng quan",
- "placementDashboardDesc": "Vị trí cao cấp ở đầu bảng điều khiển, mỗi lần một nhà tài trợ.",
- "placementSidebar": "Thẻ thanh bên",
- "placementSidebarDesc": "Hiển thị trên mọi trang của panel, luân phiên giữa các nhà tài trợ.",
- "placementLogin": "Trang đăng nhập",
- "placementLoginDesc": "Quản trị viên thấy mỗi lần đăng nhập.",
- "placementPage": "Trang nhà tài trợ",
- "placementPageDesc": "Được liệt kê tại đây với logo, mô tả và liên kết.",
- "available": "Còn trống",
- "takenUntil": "Đã đặt đến {date}",
- "activeCount": "{count} đang hoạt động"
+ "yourBrandText": "Đưa công ty bạn đến hàng nghìn quản trị viên máy chủ mở 3X-UI mỗi ngày."
}
},
"tgbot": {
diff --git a/internal/web/translation/zh-CN.json b/internal/web/translation/zh-CN.json
index a083b48bb..816bf5ee1 100644
--- a/internal/web/translation/zh-CN.json
+++ b/internal/web/translation/zh-CN.json
@@ -2423,19 +2423,7 @@
"tag": "赞助",
"visit": "访问",
"yourBrand": "您的品牌展示位",
- "yourBrandText": "让每天打开 3X-UI 的数千名服务器管理员看到您的公司。",
- "placements": "可用展示位",
- "placementDashboard": "概览横幅",
- "placementDashboardDesc": "仪表盘顶部的高级位置,每次仅一家赞助商。",
- "placementSidebar": "侧边栏卡片",
- "placementSidebarDesc": "在面板所有页面显示,并在赞助商之间轮换。",
- "placementLogin": "登录页",
- "placementLoginDesc": "管理员每次登录时都能看到。",
- "placementPage": "赞助商页面",
- "placementPageDesc": "在此页面展示徽标、简介和链接。",
- "available": "可预订",
- "takenUntil": "已预订至 {date}",
- "activeCount": "{count} 个进行中"
+ "yourBrandText": "让每天打开 3X-UI 的数千名服务器管理员看到您的公司。"
}
},
"tgbot": {
diff --git a/internal/web/translation/zh-TW.json b/internal/web/translation/zh-TW.json
index 7a22cbca5..fc1949802 100644
--- a/internal/web/translation/zh-TW.json
+++ b/internal/web/translation/zh-TW.json
@@ -2423,19 +2423,7 @@
"tag": "贊助",
"visit": "造訪",
"yourBrand": "您的品牌展示位",
- "yourBrandText": "讓每天打開 3X-UI 的數千名伺服器管理員看到您的公司。",
- "placements": "可用展示位",
- "placementDashboard": "總覽橫幅",
- "placementDashboardDesc": "儀表板頂部的高級位置,每次僅一家贊助商。",
- "placementSidebar": "側邊欄卡片",
- "placementSidebarDesc": "在面板所有頁面顯示,並在贊助商之間輪換。",
- "placementLogin": "登入頁",
- "placementLoginDesc": "管理員每次登入時都能看到。",
- "placementPage": "贊助商頁面",
- "placementPageDesc": "在此頁面展示標誌、簡介與連結。",
- "available": "可預訂",
- "takenUntil": "已預訂至 {date}",
- "activeCount": "{count} 個進行中"
+ "yourBrandText": "讓每天打開 3X-UI 的數千名伺服器管理員看到您的公司。"
}
},
"tgbot": {