diff --git a/src/app/admin/layout.tsx b/src/app/admin/layout.tsx index cf1ece4c..9508fc45 100644 --- a/src/app/admin/layout.tsx +++ b/src/app/admin/layout.tsx @@ -116,6 +116,7 @@ async function Sidebar({ key={`${group.labelKey}-${item.href}`} href={item.href} matchPrefixes={item.matchPrefixes} + matchExcludePrefixes={item.matchExcludePrefixes} icon={} > {t(item.labelKey)} diff --git a/src/components/admin/admin-hub-chrome.tsx b/src/components/admin/admin-hub-chrome.tsx index 893e369f..99fffc68 100644 --- a/src/components/admin/admin-hub-chrome.tsx +++ b/src/components/admin/admin-hub-chrome.tsx @@ -30,7 +30,7 @@ export function AdminHubChrome({ children }: { children: ReactNode }) { icon={hub.icon} title={t(hub.titleKey)} subtitle={t(hub.subtitleKey)} - tabs={} + tabs={tabs.length > 1 ? : undefined} className="admin-hub-panel" > {children} diff --git a/src/components/admin/admin-nav-link.tsx b/src/components/admin/admin-nav-link.tsx index 5dceb87e..3f63ba0a 100644 --- a/src/components/admin/admin-nav-link.tsx +++ b/src/components/admin/admin-nav-link.tsx @@ -13,18 +13,26 @@ export function AdminNavLink({ href, icon, matchPrefixes, + matchExcludePrefixes, children, }: { href: string; icon?: ReactNode; matchPrefixes?: string[]; + matchExcludePrefixes?: string[]; children: ReactNode; }) { const pathname = usePathname() ?? ""; const { close } = useAdminMobile(); + const excluded = matchExcludePrefixes?.some( + (p) => pathname === p || pathname.startsWith(`${p}/`), + ); + let active: boolean; - if (href === "/admin") { + if (excluded) { + active = false; + } else if (href === "/admin") { active = pathname === "/admin"; } else if (matchPrefixes?.length) { active = matchPrefixes.some( diff --git a/src/lib/admin-nav.ts b/src/lib/admin-nav.ts index 5c0b21a5..796d96c0 100644 --- a/src/lib/admin-nav.ts +++ b/src/lib/admin-nav.ts @@ -1,19 +1,42 @@ import type { LucideIcon } from "lucide-react"; import { + Activity, + AlertTriangle, + BadgeCheck, Ban, Calendar, + CalendarDays, + ClipboardList, Cog, Compass, + FileText, + Filter, Gavel, + HelpCircle, + Image, + Import, + KeyRound, + Languages, LayoutDashboard, + Megaphone, Monitor, Newspaper, + Package, Radio, + Server, Settings, Shield, ShoppingCart, + Sparkles, Store, + Tags, + Terminal, + Ticket, + Trophy, Users, + Volume2, + Vote, + Wifi, Wrench, } from "lucide-react"; @@ -43,6 +66,8 @@ export interface AdminNavItem { icon: LucideIcon; /** When set, sidebar item is active if pathname matches any prefix. */ matchPrefixes?: string[]; + /** Prefixes that must NOT count as active (e.g. /admin/users vs multi-accounts). */ + matchExcludePrefixes?: string[]; } export interface AdminNavGroup { @@ -51,65 +76,29 @@ export interface AdminNavGroup { items: AdminNavItem[]; } +/** + * Hubs with real sibling tabs only. Standalone features have no hub chrome + * (sidebar links go straight to the page). + */ export const ADMIN_HUBS: AdminHubDefinition[] = [ { - id: "news-media", - titleKey: "newsMedia", - subtitleKey: "newsMediaSubtitle", - icon: Newspaper, - prefixes: [ - "/admin/articles", - "/admin/photos", - "/admin/banners", - "/admin/ads", - "/admin/media", - ], - tabs: [ - { - href: "/admin/articles", - labelKey: "articles", - match: ["/admin/articles"], - }, - { href: "/admin/photos", labelKey: "photos" }, - { href: "/admin/banners", labelKey: "banners" }, - { href: "/admin/ads", labelKey: "ads", match: ["/admin/ads"] }, - { href: "/admin/media", labelKey: "media" }, - ], - }, - { - id: "site-content", - titleKey: "siteContent", - subtitleKey: "siteContentSubtitle", - icon: Compass, - prefixes: [ - "/admin/navigation", - "/admin/help-questions", - "/admin/writeable-boxes", - "/admin/tags", - "/admin/prefixes", - ], - tabs: [ - { href: "/admin/navigation", labelKey: "navigator" }, - { - href: "/admin/help-questions", - labelKey: "help", - match: ["/admin/help-questions"], - }, - { href: "/admin/writeable-boxes", labelKey: "boxes" }, - { href: "/admin/tags", labelKey: "tags" }, - { href: "/admin/prefixes", labelKey: "prefixes" }, - ], - }, - { - id: "engagement", - titleKey: "engagement", - subtitleKey: "engagementSubtitle", + id: "events", + titleKey: "events", + subtitleKey: "eventsSubtitle", icon: Calendar, - prefixes: ["/admin/events", "/admin/polls", "/admin/tickets"], + prefixes: ["/admin/events"], tabs: [ { href: "/admin/events", labelKey: "events", match: ["/admin/events"] }, { href: "/admin/events/types", labelKey: "eventTypes" }, - { href: "/admin/polls", labelKey: "polls", match: ["/admin/polls"] }, + ], + }, + { + id: "tickets", + titleKey: "tickets", + subtitleKey: "ticketsSubtitle", + icon: Ticket, + prefixes: ["/admin/tickets"], + tabs: [ { href: "/admin/tickets", labelKey: "tickets", @@ -119,50 +108,19 @@ export const ADMIN_HUBS: AdminHubDefinition[] = [ ], }, { - id: "users", - titleKey: "users", - subtitleKey: "usersSubtitle", - icon: Users, - prefixes: [ - "/admin/users", - "/admin/online", - "/admin/applications", - "/admin/teams", - ], + id: "staff-access", + titleKey: "staffAccess", + subtitleKey: "staffAccessSubtitle", + icon: KeyRound, + prefixes: ["/admin/teams", "/admin/permissions", "/admin/housekeeping"], tabs: [ - { - href: "/admin/users", - labelKey: "directory", - match: ["/admin/users"], - }, - { href: "/admin/users/multi-accounts", labelKey: "multiAccounts" }, - { href: "/admin/online", labelKey: "online" }, - { href: "/admin/applications", labelKey: "applications" }, { href: "/admin/teams", labelKey: "teams" }, - ], - }, - { - id: "access", - titleKey: "access", - subtitleKey: "accessSubtitle", - icon: Shield, - prefixes: [ - "/admin/bans", - "/admin/ip", - "/admin/vpn", - "/admin/permissions", - "/admin/wordfilter", - ], - tabs: [ - { href: "/admin/bans", labelKey: "bans" }, - { href: "/admin/ip", labelKey: "ip" }, - { href: "/admin/vpn", labelKey: "vpn" }, { href: "/admin/permissions", labelKey: "permissions", match: ["/admin/permissions"], }, - { href: "/admin/wordfilter", labelKey: "wordFilter" }, + { href: "/admin/housekeeping", labelKey: "housekeeping" }, ], }, { @@ -182,50 +140,6 @@ export const ADMIN_HUBS: AdminHubDefinition[] = [ { href: "/admin/moderation/team", labelKey: "team" }, ], }, - { - id: "catalog", - titleKey: "catalog", - subtitleKey: "catalogSubtitle", - icon: Store, - prefixes: [ - "/admin/catalog", - "/admin/rare-values", - "/admin/badges", - "/admin/achievements", - "/admin/sounds", - ], - tabs: [ - { href: "/admin/catalog", labelKey: "catalogTab", match: ["/admin/catalog"] }, - { href: "/admin/rare-values", labelKey: "rares" }, - { href: "/admin/badges", labelKey: "badges" }, - { href: "/admin/achievements", labelKey: "achievements" }, - { href: "/admin/sounds", labelKey: "sounds" }, - ], - }, - { - id: "shop", - titleKey: "shop", - subtitleKey: "shopSubtitle", - icon: ShoppingCart, - prefixes: [ - "/admin/shop", - "/admin/transactions", - "/admin/vouchers", - "/admin/subscriptions", - "/admin/calendar", - ], - tabs: [ - { href: "/admin/shop", labelKey: "shopTab" }, - { href: "/admin/transactions", labelKey: "transactions" }, - { href: "/admin/vouchers", labelKey: "vouchers" }, - { href: "/admin/subscriptions", labelKey: "subscriptions" }, - { - href: "/admin/calendar", - labelKey: "calendar", - match: ["/admin/calendar"], - }, - ], - }, { id: "radio", titleKey: "radio", @@ -245,7 +159,11 @@ export const ADMIN_HUBS: AdminHubDefinition[] = [ labelKey: "monitoring", group: "primary", }, - { href: "/admin/radio/settings", labelKey: "settingsTab", group: "primary" }, + { + href: "/admin/radio/settings", + labelKey: "settingsTab", + group: "primary", + }, { href: "/admin/radio/banners", labelKey: "banners", group: "tools" }, { href: "/admin/radio/embed", labelKey: "embed", group: "tools" }, { href: "/admin/radio/api-keys", labelKey: "apiKeys", group: "tools" }, @@ -255,68 +173,12 @@ export const ADMIN_HUBS: AdminHubDefinition[] = [ ], }, { - id: "settings", - titleKey: "settings", - subtitleKey: "settingsSubtitle", - icon: Cog, - prefixes: [ - "/admin/settings", - "/admin/theme", - "/admin/maintenance", - "/admin/favicon", - "/admin/emulator", - "/admin/email-templates", - "/admin/housekeeping", - ], + id: "analytics", + titleKey: "analytics", + subtitleKey: "analyticsSubtitle", + icon: Activity, + prefixes: ["/admin/analytics"], tabs: [ - { href: "/admin/settings", labelKey: "cms" }, - { href: "/admin/theme", labelKey: "theme" }, - { href: "/admin/maintenance", labelKey: "maintenance" }, - { href: "/admin/favicon", labelKey: "favicon" }, - { href: "/admin/emulator", labelKey: "emulator" }, - { href: "/admin/email-templates", labelKey: "email" }, - { href: "/admin/housekeeping", labelKey: "housekeeping" }, - ], - }, - { - id: "tools", - titleKey: "tools", - subtitleKey: "toolsSubtitle", - icon: Wrench, - prefixes: [ - "/admin/commandocentrum", - "/admin/rooms", - "/admin/import", - "/admin/translations", - ], - tabs: [ - { href: "/admin/commandocentrum", labelKey: "commando" }, - { href: "/admin/rooms", labelKey: "rooms", match: ["/admin/rooms"] }, - { href: "/admin/import", labelKey: "import", match: ["/admin/import"] }, - { - href: "/admin/translations", - labelKey: "translations", - match: ["/admin/translations"], - }, - ], - }, - { - id: "observability", - titleKey: "observability", - subtitleKey: "observabilitySubtitle", - icon: Monitor, - prefixes: [ - "/admin/logs", - "/admin/analytics", - "/admin/devops", - "/admin/alerts", - ], - tabs: [ - { href: "/admin/logs", labelKey: "logs" }, - { href: "/admin/logs/audit", labelKey: "audit" }, - { href: "/admin/logs/chat", labelKey: "chat" }, - { href: "/admin/logs/commands", labelKey: "commands" }, - { href: "/admin/logs/trades", labelKey: "trades" }, { href: "/admin/analytics", labelKey: "analytics", @@ -324,26 +186,38 @@ export const ADMIN_HUBS: AdminHubDefinition[] = [ }, { href: "/admin/analytics/activity", labelKey: "activity" }, { href: "/admin/analytics/economy", labelKey: "economy" }, + ], + }, + { + id: "devops", + titleKey: "devops", + subtitleKey: "devopsSubtitle", + icon: Server, + prefixes: ["/admin/devops"], + tabs: [ { href: "/admin/devops", labelKey: "devops", match: ["/admin/devops"] }, { href: "/admin/devops/errors", labelKey: "errors" }, - { href: "/admin/alerts", labelKey: "alerts" }, ], }, ]; +/** Longest-prefix match so nested routes (e.g. /admin/logs/audit) win. */ export function findAdminHub(pathname: string): AdminHubDefinition | null { - return ( - ADMIN_HUBS.find((hub) => - hub.prefixes.some((p) => pathname === p || pathname.startsWith(`${p}/`)), - ) ?? null - ); + let best: AdminHubDefinition | null = null; + let bestLen = -1; + for (const hub of ADMIN_HUBS) { + for (const prefix of hub.prefixes) { + const hit = pathname === prefix || pathname.startsWith(`${prefix}/`); + if (hit && prefix.length > bestLen) { + best = hub; + bestLen = prefix.length; + } + } + } + return best; } -function hubPrefixes(id: string): string[] { - return ADMIN_HUBS.find((h) => h.id === id)?.prefixes ?? []; -} - -/** Condensed sidebar — one entry per hub (plus dashboard). */ +/** Feature-first sidebar: one entry per feature; hubs only for sibling tabs. */ export const ADMIN_NAV_GROUPS: AdminNavGroup[] = [ { labelKey: "overview", @@ -362,45 +236,100 @@ export const ADMIN_NAV_GROUPS: AdminNavGroup[] = [ items: [ { href: "/admin/articles", - labelKey: "hubNewsMedia", + labelKey: "articles", icon: Newspaper, - matchPrefixes: hubPrefixes("news-media"), + matchPrefixes: ["/admin/articles"], + }, + { href: "/admin/photos", labelKey: "photos", icon: Image }, + { href: "/admin/banners", labelKey: "banners", icon: Megaphone }, + { + href: "/admin/ads", + labelKey: "advertisements", + icon: FileText, + matchPrefixes: ["/admin/ads"], + }, + { href: "/admin/media", labelKey: "media", icon: Image }, + { href: "/admin/navigation", labelKey: "navigator", icon: Compass }, + { + href: "/admin/help-questions", + labelKey: "helpCenter", + icon: HelpCircle, + matchPrefixes: ["/admin/help-questions"], }, { - href: "/admin/navigation", - labelKey: "hubSiteContent", - icon: Compass, - matchPrefixes: hubPrefixes("site-content"), + href: "/admin/writeable-boxes", + labelKey: "writeableBoxes", + icon: Package, }, + { href: "/admin/tags", labelKey: "tags", icon: Tags }, + { href: "/admin/prefixes", labelKey: "prefixes", icon: Sparkles }, + ], + }, + { + labelKey: "community", + icon: Calendar, + items: [ { href: "/admin/events", - labelKey: "hubEngagement", + labelKey: "events", icon: Calendar, - matchPrefixes: hubPrefixes("engagement"), + matchPrefixes: ["/admin/events"], + }, + { + href: "/admin/polls", + labelKey: "polls", + icon: Vote, + matchPrefixes: ["/admin/polls"], + }, + { + href: "/admin/tickets", + labelKey: "tickets", + icon: Ticket, + matchPrefixes: ["/admin/tickets"], }, ], }, { labelKey: "usersAndAccess", - icon: Shield, + icon: Users, items: [ { href: "/admin/users", - labelKey: "hubUsers", + labelKey: "users", icon: Users, - matchPrefixes: hubPrefixes("users"), + matchPrefixes: ["/admin/users"], + matchExcludePrefixes: ["/admin/users/multi-accounts"], }, { - href: "/admin/bans", - labelKey: "hubAccess", - icon: Ban, - matchPrefixes: hubPrefixes("access"), + href: "/admin/users/multi-accounts", + labelKey: "multiAccounts", + icon: Users, }, + { href: "/admin/online", labelKey: "onlineUsers", icon: Wifi }, + { + href: "/admin/applications", + labelKey: "applications", + icon: ClipboardList, + }, + { + href: "/admin/teams", + labelKey: "staffAccess", + icon: KeyRound, + matchPrefixes: [ + "/admin/teams", + "/admin/permissions", + "/admin/housekeeping", + ], + }, + { href: "/admin/bans", labelKey: "bans", icon: Ban }, + { href: "/admin/ip", labelKey: "ipManagement", icon: Shield }, + { href: "/admin/vpn", labelKey: "vpn", icon: Shield }, + { href: "/admin/wordfilter", labelKey: "wordFilter", icon: Filter }, { href: "/admin/moderation", labelKey: "moderation", icon: Gavel, - matchPrefixes: hubPrefixes("moderation"), + matchPrefixes: ["/admin/moderation"], }, ], }, @@ -410,15 +339,27 @@ export const ADMIN_NAV_GROUPS: AdminNavGroup[] = [ items: [ { href: "/admin/catalog", - labelKey: "hubCatalog", + labelKey: "catalog", icon: Store, - matchPrefixes: hubPrefixes("catalog"), + matchPrefixes: ["/admin/catalog"], + }, + { href: "/admin/rare-values", labelKey: "rareValues", icon: Sparkles }, + { href: "/admin/badges", labelKey: "badges", icon: BadgeCheck }, + { href: "/admin/achievements", labelKey: "achievements", icon: Trophy }, + { href: "/admin/sounds", labelKey: "sounds", icon: Volume2 }, + { href: "/admin/shop", labelKey: "shop", icon: ShoppingCart }, + { href: "/admin/transactions", labelKey: "transactions", icon: Activity }, + { href: "/admin/vouchers", labelKey: "vouchers", icon: Ticket }, + { + href: "/admin/subscriptions", + labelKey: "subscriptions", + icon: ClipboardList, }, { - href: "/admin/shop", - labelKey: "hubShop", - icon: ShoppingCart, - matchPrefixes: hubPrefixes("shop"), + href: "/admin/calendar", + labelKey: "calendar", + icon: CalendarDays, + matchPrefixes: ["/admin/calendar"], }, ], }, @@ -438,24 +379,80 @@ export const ADMIN_NAV_GROUPS: AdminNavGroup[] = [ labelKey: "system", icon: Settings, items: [ + { href: "/admin/settings", labelKey: "settings", icon: Cog }, + { href: "/admin/theme", labelKey: "theme", icon: Sparkles }, + { href: "/admin/maintenance", labelKey: "maintenance", icon: Wrench }, + { href: "/admin/favicon", labelKey: "favicon", icon: Image }, + { href: "/admin/emulator", labelKey: "emulator", icon: Server }, { - href: "/admin/settings", - labelKey: "settings", - icon: Cog, - matchPrefixes: hubPrefixes("settings"), - }, - { - href: "/admin/commandocentrum", - labelKey: "hubTools", - icon: Wrench, - matchPrefixes: hubPrefixes("tools"), - }, - { - href: "/admin/logs", - labelKey: "hubObservability", - icon: Monitor, - matchPrefixes: hubPrefixes("observability"), + href: "/admin/email-templates", + labelKey: "emailTemplates", + icon: FileText, }, ], }, + { + labelKey: "tools", + icon: Wrench, + items: [ + { + href: "/admin/commandocentrum", + labelKey: "commandocentrum", + icon: Terminal, + }, + { + href: "/admin/rooms", + labelKey: "rooms", + icon: Store, + matchPrefixes: ["/admin/rooms"], + }, + { + href: "/admin/import", + labelKey: "import", + icon: Import, + matchPrefixes: ["/admin/import"], + }, + { + href: "/admin/translations", + labelKey: "translations", + icon: Languages, + matchPrefixes: ["/admin/translations"], + }, + ], + }, + { + labelKey: "monitoring", + icon: Monitor, + items: [ + { + href: "/admin/logs", + labelKey: "logs", + icon: FileText, + matchPrefixes: ["/admin/logs"], + matchExcludePrefixes: [ + "/admin/logs/audit", + "/admin/logs/chat", + "/admin/logs/commands", + "/admin/logs/trades", + ], + }, + { href: "/admin/logs/audit", labelKey: "auditLog", icon: ClipboardList }, + { href: "/admin/logs/chat", labelKey: "chatLog", icon: FileText }, + { href: "/admin/logs/commands", labelKey: "commandLog", icon: Terminal }, + { href: "/admin/logs/trades", labelKey: "tradeLog", icon: Activity }, + { + href: "/admin/analytics", + labelKey: "analytics", + icon: Activity, + matchPrefixes: ["/admin/analytics"], + }, + { + href: "/admin/devops", + labelKey: "devops", + icon: Server, + matchPrefixes: ["/admin/devops"], + }, + { href: "/admin/alerts", labelKey: "alerts", icon: AlertTriangle }, + ], + }, ]; diff --git a/src/lib/theme-contrast.test.ts b/src/lib/theme-contrast.test.ts index ed8e3ee6..8541de0e 100644 --- a/src/lib/theme-contrast.test.ts +++ b/src/lib/theme-contrast.test.ts @@ -131,7 +131,7 @@ describe("deriveAdminPalette", () => { expect(admin.surface).not.toBe("#00ff00"); }); - it("in light mode mirrors readable public surfaces", () => { + it("in light mode softens harsh white public surfaces", () => { const admin = deriveAdminPalette( { color_background: "#f8fafc", @@ -150,8 +150,8 @@ describe("deriveAdminPalette", () => { }, "light", ); - expect(admin.canvas).toBe("#f8fafc"); - expect(admin.surface).toBe("#ffffff"); + expect(admin.canvas).toBe("#eef1f4"); + expect(admin.surface).toBe("#f5f7fa"); expect(contrastRatio(admin.text, admin.canvas)).toBeGreaterThanOrEqual(4.5); expect(contrastRatio(admin.sidebarText, admin.sidebar)).toBeGreaterThanOrEqual( 4.5, @@ -169,7 +169,7 @@ describe("deriveAdminPalette", () => { { canvas: "#0b0f19", text: "#f8fafc" }, "light", ); - expect(admin.canvas).toBe("#ffffff"); + expect(admin.canvas).toBe("#eef1f4"); expect(admin.text.toLowerCase()).not.toBe("#f8fafc"); }); diff --git a/src/lib/theme-contrast.ts b/src/lib/theme-contrast.ts index 930afc3d..49b9412d 100644 --- a/src/lib/theme-contrast.ts +++ b/src/lib/theme-contrast.ts @@ -27,6 +27,19 @@ export interface AdminPalette { focusRing: string; } +/** Pure / near-white public surfaces → soft admin paper (less eye strain). */ +function softLightSurface( + value: string | undefined, + softDefault: string, +): string { + if (!value) return softDefault; + const v = value.trim().toLowerCase(); + if (v === "#fff" || v === "#ffffff" || v === "white") return softDefault; + // Common slate/zinc paper whites (#f8fafc, #fafafa, #f9fafb, …) + if (/^#f[89a-f][0-9a-f]{4}$/i.test(v)) return softDefault; + return value; +} + export function deriveAdminPalette( colors: PublicThemeColors, overrides?: Partial, @@ -34,13 +47,14 @@ export function deriveAdminPalette( ): AdminPalette { const accent = overrides?.accent ?? colors.color_primary ?? "#f59e0b"; + // Soft cool gray-blue paper (not pure white) — easier on the eyes in light HK. const lightDefaults: AdminPalette = { - canvas: colors.color_background ?? "#f8fafc", - surface: colors.color_surface ?? "#ffffff", - surfaceElevated: colors.color_dropdown ?? "#f1f5f9", + canvas: softLightSurface(colors.color_background, "#eef1f4"), + surface: softLightSurface(colors.color_surface, "#f5f7fa"), + surfaceElevated: softLightSurface(colors.color_dropdown, "#fafbfc"), text: colors.color_text ?? "#0f172a", muted: colors.color_text_muted ?? "#64748b", - border: "#e2e8f0", + border: "#d8dee6", accent, accentText: accent, accentForeground: "#ffffff", @@ -48,7 +62,10 @@ export function deriveAdminPalette( warning: colors.color_warning ?? "#eab308", error: colors.color_error ?? "#ef4444", info: colors.color_info ?? "#0ea5e9", - sidebar: colors.color_navbar ?? colors.color_surface ?? "#ffffff", + sidebar: softLightSurface( + colors.color_navbar ?? colors.color_surface, + "#e8ecf1", + ), sidebarText: colors.color_navbar_text ?? colors.color_text ?? "#0f172a", overlay: "rgba(15, 23, 42, 0.45)", focusRing: accent, diff --git a/src/messages/en.json b/src/messages/en.json index a0ef1b7b..f1b1e353 100644 --- a/src/messages/en.json +++ b/src/messages/en.json @@ -781,7 +781,15 @@ "backToSite": "Back to site", "housekeeping": "Housekeeping", "hotelManagementPanel": "Hotel management panel", - "rankLabel": "Rank {rank}" + "rankLabel": "Rank {rank}", + "community": "Community", + "monitoring": "Monitoring", + "staffAccess": "Ranks & permissions", + "multiAccounts": "Multi-accounts", + "chatLog": "Chat log", + "commandLog": "Command log", + "tradeLog": "Trade log", + "tools": "Tools" }, "dashboard": { "title": "Dashboard", @@ -2153,7 +2161,17 @@ "errors": "Errors", "alerts": "Alerts", "toolsGroup": "Tools" - } + }, + "events": "Events", + "eventsSubtitle": "Hotel events and event types", + "tickets": "Tickets", + "ticketsSubtitle": "Support tickets and reply templates", + "staffAccess": "Ranks & permissions", + "staffAccessSubtitle": "Staff ranks, ACL permissions and housekeeping access", + "analytics": "Analytics", + "analyticsSubtitle": "Hotel activity, retention and economy", + "devops": "DevOps", + "devopsSubtitle": "Service health and emulator errors" }, "wordfilter": { "title": "Word Filter", diff --git a/src/messages/it.json b/src/messages/it.json index b47c234a..f86f0bbd 100644 --- a/src/messages/it.json +++ b/src/messages/it.json @@ -673,7 +673,7 @@ "content": "Contenuti", "articles": "Articoli", "tags": "Tag", - "navigator": "Navigatore", + "navigator": "Navigazione", "helpCenter": "Centro assistenza", "advertisements": "Pubblicità", "writeableBoxes": "Box modificabili", @@ -737,15 +737,23 @@ "backToSite": "Torna al sito", "hotelManagementPanel": "Pannello di gestione hotel", "rankLabel": "Grado {rank}", - "hubNewsMedia": "News & media", - "hubSiteContent": "Site content", - "hubEngagement": "Engagement", + "hubNewsMedia": "Notizie e media", + "hubSiteContent": "Contenuti sito", + "hubEngagement": "Community", "hubUsers": "Users", "hubAccess": "Access & security", "hubCatalog": "Catalog & rares", "hubShop": "Shop & payments", "hubTools": "Tools", - "hubObservability": "Observability" + "hubObservability": "Observability", + "community": "Community", + "monitoring": "Monitoraggio", + "staffAccess": "Gradi e permessi", + "multiAccounts": "Multi-account", + "chatLog": "Log chat", + "commandLog": "Log comandi", + "tradeLog": "Log trade", + "tools": "Strumenti" }, "dashboard": { "title": "Dashboard", @@ -2396,7 +2404,17 @@ "errors": "Errori", "alerts": "Alert", "toolsGroup": "Strumenti" - } + }, + "events": "Eventi", + "eventsSubtitle": "Eventi hotel e tipi evento", + "tickets": "Ticket", + "ticketsSubtitle": "Ticket di supporto e template risposte", + "staffAccess": "Gradi e permessi", + "staffAccessSubtitle": "Gradi staff, permessi ACL e accesso housekeeping", + "analytics": "Analitiche", + "analyticsSubtitle": "Attività hotel, retention ed economia", + "devops": "DevOps", + "devopsSubtitle": "Salute servizi ed errori emulator" }, "settings": { "title": "Impostazioni CMS", diff --git a/src/messages/nl.json b/src/messages/nl.json index 1a728e75..72618fc3 100644 --- a/src/messages/nl.json +++ b/src/messages/nl.json @@ -712,7 +712,7 @@ "navigator": "Navigator", "helpCenter": "Helpcentrum", "advertisements": "Advertenties", - "writeableBoxes": "Beschrijfbare boxes", + "writeableBoxes": "Bewerkbare boxes", "photos": "Foto's", "tickets": "Tickets", "events": "Events", @@ -781,7 +781,15 @@ "hubCatalog": "Catalog & rares", "hubShop": "Shop & payments", "hubTools": "Tools", - "hubObservability": "Observability" + "hubObservability": "Observability", + "community": "Community", + "monitoring": "Monitoring", + "staffAccess": "Rangen & rechten", + "multiAccounts": "Multi-accounts", + "chatLog": "Chatlog", + "commandLog": "Commandolog", + "tradeLog": "Tradelog", + "tools": "Tools" }, "dashboard": { "title": "Dashboard", @@ -2443,7 +2451,17 @@ "errors": "Fouten", "alerts": "Meldingen", "toolsGroup": "Tools" - } + }, + "events": "Evenementen", + "eventsSubtitle": "Hotel-evenementen en evenementtypes", + "tickets": "Tickets", + "ticketsSubtitle": "Supporttickets en antwoordtemplates", + "staffAccess": "Rangen & rechten", + "staffAccessSubtitle": "Staffrangen, ACL-rechten en housekeeping-toegang", + "analytics": "Analytics", + "analyticsSubtitle": "Hotelactiviteit, retentie en economie", + "devops": "DevOps", + "devopsSubtitle": "Servicegezondheid en emulatorfouten" }, "tickets": { "title": "Tickets",