Commit 8ad83bf6 by CaIon

feat(dashboard): interactive sankey highlighting and persistent filters

- Highlight full paths through a clicked node or link in the flow Sankey,
  dimming unrelated nodes/links instead of removing them
- Disable VChart built-in emphasis to avoid crash, use custom highlight sets
- Initialize models filter dialog from currently applied filters so manual
  time ranges are not overridden by preferences; auto-pick granularity by range
- Lift user charts time range/granularity/limit to dashboard as controlled state
parent 06194801
/*
Copyright (C) 2023-2026 QuantumNous
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
For commercial licensing, please contact support@quantumnous.com
*/
import { useMemo } from 'react'
import { Filter, X } from 'lucide-react'
import { useTranslation } from 'react-i18next'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandSeparator,
} from '@/components/ui/command'
import {
Popover,
PopoverContent,
PopoverDescription,
PopoverHeader,
PopoverTitle,
PopoverTrigger,
} from '@/components/ui/popover'
import type {
FlowNodeFilter,
FlowNodeFilterOption,
FlowNodeKind,
} from '@/features/dashboard/types'
interface FlowNodeFilterControlProps {
stages: FlowNodeKind[]
stageLabels: Record<FlowNodeKind, string>
metricLabel: string
formatMetricValue: (value: number) => string
options: FlowNodeFilterOption[]
selectedNodes: FlowNodeFilter[]
onToggleNode: (filter: FlowNodeFilter) => void
onRemoveNode: (filter: FlowNodeFilter) => void
onClearNodes: () => void
}
function flowNodeFilterKey(filter: FlowNodeFilter): string {
return `${filter.kind}\u0000${filter.id}`
}
export function FlowNodeFilterControl(props: FlowNodeFilterControlProps) {
const { t } = useTranslation()
const selectedKeys = useMemo(
() => new Set(props.selectedNodes.map(flowNodeFilterKey)),
[props.selectedNodes]
)
const optionLabels = useMemo(() => {
const labels = new Map<string, FlowNodeFilterOption>()
for (const option of props.options) {
labels.set(
flowNodeFilterKey({ kind: option.kind, id: option.value }),
option
)
}
return labels
}, [props.options])
const optionsByStage = useMemo(
() =>
props.stages
.map((stage) => ({
stage,
options: props.options.filter((option) => option.kind === stage),
}))
.filter((group) => group.options.length > 0),
[props.options, props.stages]
)
const selectedOptions = props.selectedNodes.map((filter) => {
const option = optionLabels.get(flowNodeFilterKey(filter))
return {
...filter,
label: option?.label ?? filter.id,
}
})
const selectedCount = selectedOptions.length
return (
<div className='flex min-w-0 flex-col gap-1.5'>
<span className='text-muted-foreground text-xs font-medium'>
{t('Node filters')}
</span>
<div className='flex min-w-0 flex-wrap items-center gap-1.5'>
<Popover>
<PopoverTrigger
render={
<Button
type='button'
variant='outline'
size='sm'
aria-label={t('Filter by node')}
/>
}
>
<Filter data-icon='inline-start' aria-hidden='true' />
{selectedCount > 0 ? t('Selected nodes') : t('All nodes')}
{selectedCount > 0 && (
<Badge variant='secondary' className='rounded-sm px-1'>
{selectedCount}
</Badge>
)}
</PopoverTrigger>
<PopoverContent
className='w-[min(28rem,calc(100vw-2rem))] p-0'
align='start'
>
<PopoverHeader className='px-3 pt-3'>
<PopoverTitle>{t('Node filters')}</PopoverTitle>
<PopoverDescription>
{t('Value metric')}: {props.metricLabel}
</PopoverDescription>
</PopoverHeader>
<Command>
<CommandInput placeholder={t('Filter by node')} />
<CommandList>
<CommandEmpty>{t('No nodes')}</CommandEmpty>
{optionsByStage.map((group) => {
const stageLabel = t(props.stageLabels[group.stage])
return (
<CommandGroup key={group.stage} heading={stageLabel}>
{group.options.map((option) => {
const key = flowNodeFilterKey({
kind: option.kind,
id: option.value,
})
const metricValueLabel = props.formatMetricValue(
option.valueRaw
)
return (
<CommandItem
key={key}
value={`${stageLabel} ${option.label} ${props.metricLabel} ${metricValueLabel}`}
data-checked={selectedKeys.has(key)}
onSelect={() =>
props.onToggleNode({
kind: option.kind,
id: option.value,
})
}
>
<span
className='size-2.5 shrink-0 rounded-full'
style={{ backgroundColor: option.color }}
aria-hidden='true'
/>
<span className='min-w-0 flex-1 truncate'>
{option.label}
</span>
<span className='text-muted-foreground flex shrink-0 items-center gap-1 text-xs'>
<span>{props.metricLabel}</span>
<span className='font-mono'>
{metricValueLabel}
</span>
</span>
</CommandItem>
)
})}
</CommandGroup>
)
})}
{selectedCount > 0 && (
<>
<CommandSeparator />
<CommandGroup>
<CommandItem
onSelect={props.onClearNodes}
className='justify-center text-center'
>
{t('Clear node filters')}
</CommandItem>
</CommandGroup>
</>
)}
</CommandList>
</Command>
</PopoverContent>
</Popover>
{selectedOptions.map((option) => (
<Badge
key={flowNodeFilterKey(option)}
variant='secondary'
className='max-w-[14rem] rounded-sm pr-1'
>
<span className='truncate'>
{t(props.stageLabels[option.kind])}: {option.label}
</span>
<button
type='button'
className='hover:bg-muted-foreground/15 flex size-4 shrink-0 items-center justify-center rounded-sm'
aria-label={t('Remove node filter')}
onClick={() =>
props.onRemoveNode({ kind: option.kind, id: option.id })
}
>
<X aria-hidden='true' />
</button>
</Badge>
))}
{selectedCount > 1 && (
<Button
type='button'
variant='ghost'
size='xs'
onClick={props.onClearNodes}
>
{t('Clear')}
</Button>
)}
</div>
</div>
)
}
...@@ -51,12 +51,36 @@ import type { ...@@ -51,12 +51,36 @@ import type {
interface ModelsFilterProps { interface ModelsFilterProps {
preferences: DashboardChartPreferences preferences: DashboardChartPreferences
// The filters currently applied to the dashboard. The dialog edits a copy of
// these so reopening it never discards a manually picked range.
currentFilters: DashboardFilters
onFilterChange: (filters: DashboardFilters) => void onFilterChange: (filters: DashboardFilters) => void
onReset: () => void onReset: () => void
titleKey?: string titleKey?: string
descriptionKey?: string descriptionKey?: string
} }
// Quick-range presets imply a sensible granularity (matching the app's
// range<->granularity pairing), so picking "7 Days" requests daily buckets
// instead of leaving the granularity on its previous value (e.g. hourly).
function granularityForRangeDays(days: number): TimeGranularity {
if (days <= 1) return 'hour'
if (days >= 29) return 'week'
return 'day'
}
// Highlights the matching quick-range button when the applied range spans an
// exact preset; custom ranges leave every quick button unselected.
function detectQuickRangeDays(
filters: DashboardFilters | undefined
): number | null {
const start = filters?.start_timestamp
const end = filters?.end_timestamp
if (!start || !end) return null
const days = Math.round((end.getTime() - start.getTime()) / 86_400_000)
return TIME_RANGE_PRESETS.some((preset) => preset.days === days) ? days : null
}
/** /**
* Section divider component for better visual organization * Section divider component for better visual organization
*/ */
...@@ -78,20 +102,22 @@ export function ModelsFilter(props: ModelsFilterProps) { ...@@ -78,20 +102,22 @@ export function ModelsFilter(props: ModelsFilterProps) {
const isAdmin = user?.role && user.role >= 10 const isAdmin = user?.role && user.role >= 10
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const [filters, setFilters] = useState<DashboardFilters>(() => const [filters, setFilters] = useState<DashboardFilters>(
buildDefaultDashboardFilters(props.preferences) () => props.currentFilters ?? buildDefaultDashboardFilters(props.preferences)
) )
const [selectedRange, setSelectedRange] = useState<number | null>( const [selectedRange, setSelectedRange] = useState<number | null>(() =>
() => props.preferences.defaultTimeRangeDays detectQuickRangeDays(props.currentFilters)
) )
const resetFiltersFromPreferences = () => {
setFilters(buildDefaultDashboardFilters(props.preferences))
setSelectedRange(props.preferences.defaultTimeRangeDays)
}
const handleOpenChange = (nextOpen: boolean) => { const handleOpenChange = (nextOpen: boolean) => {
if (nextOpen) resetFiltersFromPreferences() // Sync the editing state from the applied filters every time the dialog
// opens so a previously applied manual range is preserved.
if (nextOpen) {
const applied =
props.currentFilters ?? buildDefaultDashboardFilters(props.preferences)
setFilters(applied)
setSelectedRange(detectQuickRangeDays(applied))
}
setOpen(nextOpen) setOpen(nextOpen)
} }
...@@ -133,6 +159,7 @@ export function ModelsFilter(props: ModelsFilterProps) { ...@@ -133,6 +159,7 @@ export function ModelsFilter(props: ModelsFilterProps) {
...prev, ...prev,
start_timestamp: start, start_timestamp: start,
end_timestamp: end, end_timestamp: end,
time_granularity: granularityForRangeDays(days),
})) }))
setSelectedRange(days) setSelectedRange(days)
} }
......
...@@ -33,11 +33,13 @@ import { ...@@ -33,11 +33,13 @@ import {
} from '@/features/dashboard/constants' } from '@/features/dashboard/constants'
import { import {
getDefaultDays, getDefaultDays,
getSavedGranularity,
saveGranularity, saveGranularity,
processUserChartData, processUserChartData,
} from '@/features/dashboard/lib' } from '@/features/dashboard/lib'
import type { ProcessedUserChartData } from '@/features/dashboard/types' import type {
ProcessedUserChartData,
UserChartsFilters,
} from '@/features/dashboard/types'
let themeManagerPromise: Promise< let themeManagerPromise: Promise<
(typeof import('@visactor/vchart'))['ThemeManager'] (typeof import('@visactor/vchart'))['ThemeManager']
...@@ -62,7 +64,12 @@ const USER_CHARTS: { ...@@ -62,7 +64,12 @@ const USER_CHARTS: {
const TOP_USER_LIMIT_OPTIONS = [5, 10, 20, 50] const TOP_USER_LIMIT_OPTIONS = [5, 10, 20, 50]
export function UserCharts() { interface UserChartsProps {
filters: UserChartsFilters
onFiltersChange: (filters: UserChartsFilters) => void
}
export function UserCharts(props: UserChartsProps) {
const { t } = useTranslation() const { t } = useTranslation()
const { resolvedTheme } = useTheme() const { resolvedTheme } = useTheme()
const [themeReady, setThemeReady] = useState(false) const [themeReady, setThemeReady] = useState(false)
...@@ -70,41 +77,45 @@ export function UserCharts() { ...@@ -70,41 +77,45 @@ export function UserCharts() {
(typeof import('@visactor/vchart'))['ThemeManager'] | null (typeof import('@visactor/vchart'))['ThemeManager'] | null
>(null) >(null)
const [timeGranularity, setTimeGranularity] = useState<TimeGranularity>(() => // The selection is owned by the dashboard parent so it persists across
getSavedGranularity() // sub-section switches; the rolling window is derived from the chosen range.
) const timeGranularity = props.filters.timeGranularity
const [selectedRange, setSelectedRange] = useState<number>(() => const selectedRange = props.filters.selectedRange
getDefaultDays(timeGranularity) const topUserLimit = props.filters.topUserLimit
) const onFiltersChange = props.onFiltersChange
const [topUserLimit, setTopUserLimit] = useState(10)
const [timeRange, setTimeRange] = useState(() => { const timeRange = useMemo(() => {
const days = getDefaultDays(timeGranularity) const { start, end } = getRollingDateRange(selectedRange)
const { start, end } = getRollingDateRange(days)
return { return {
start_timestamp: Math.floor(start.getTime() / 1000), start_timestamp: Math.floor(start.getTime() / 1000),
end_timestamp: Math.floor(end.getTime() / 1000), end_timestamp: Math.floor(end.getTime() / 1000),
} }
}) }, [selectedRange])
const handleRangeChange = useCallback((days: number) => { const handleRangeChange = useCallback(
setSelectedRange(days) (days: number) => {
const { start, end } = getRollingDateRange(days) onFiltersChange({ ...props.filters, selectedRange: days })
setTimeRange({ },
start_timestamp: Math.floor(start.getTime() / 1000), [onFiltersChange, props.filters]
end_timestamp: Math.floor(end.getTime() / 1000), )
})
}, [])
const handleGranularityChange = useCallback( const handleGranularityChange = useCallback(
(g: TimeGranularity) => { (g: TimeGranularity) => {
setTimeGranularity(g)
saveGranularity(g) saveGranularity(g)
const days = getDefaultDays(g) onFiltersChange({
if (days !== selectedRange) { ...props.filters,
handleRangeChange(days) timeGranularity: g,
} selectedRange: getDefaultDays(g),
})
},
[onFiltersChange, props.filters]
)
const handleTopUserLimitChange = useCallback(
(limit: number) => {
onFiltersChange({ ...props.filters, topUserLimit: limit })
}, },
[selectedRange, handleRangeChange] [onFiltersChange, props.filters]
) )
useEffect(() => { useEffect(() => {
...@@ -184,7 +195,7 @@ export function UserCharts() { ...@@ -184,7 +195,7 @@ export function UserCharts() {
<Tabs <Tabs
value={String(topUserLimit)} value={String(topUserLimit)}
onValueChange={(value) => setTopUserLimit(Number(value))} onValueChange={(value) => handleTopUserLimitChange(Number(value))}
className='shrink-0' className='shrink-0'
> >
<TabsList> <TabsList>
......
...@@ -31,7 +31,9 @@ import { OverviewDashboard } from './components/overview/overview-dashboard' ...@@ -31,7 +31,9 @@ import { OverviewDashboard } from './components/overview/overview-dashboard'
import { DEFAULT_TIME_GRANULARITY } from './constants' import { DEFAULT_TIME_GRANULARITY } from './constants'
import { import {
buildDefaultDashboardFilters, buildDefaultDashboardFilters,
getDefaultDays,
getSavedChartPreferences, getSavedChartPreferences,
getSavedGranularity,
saveChartPreferences, saveChartPreferences,
} from './lib' } from './lib'
import { import {
...@@ -43,6 +45,7 @@ import { ...@@ -43,6 +45,7 @@ import {
type DashboardChartPreferences, type DashboardChartPreferences,
type DashboardFilters, type DashboardFilters,
type QuotaDataItem, type QuotaDataItem,
type UserChartsFilters,
} from './types' } from './types'
const route = getRouteApi('/_authenticated/dashboard/$section') const route = getRouteApi('/_authenticated/dashboard/$section')
...@@ -166,6 +169,16 @@ export function Dashboard() { ...@@ -166,6 +169,16 @@ export function Dashboard() {
const [modelFilters, setModelFilters] = useState<DashboardFilters>(() => const [modelFilters, setModelFilters] = useState<DashboardFilters>(() =>
buildDefaultDashboardFilters(getSavedChartPreferences()) buildDefaultDashboardFilters(getSavedChartPreferences())
) )
const [userChartsFilters, setUserChartsFilters] = useState<UserChartsFilters>(
() => {
const granularity = getSavedGranularity()
return {
timeGranularity: granularity,
selectedRange: getDefaultDays(granularity),
topUserLimit: 10,
}
}
)
const handleFilterChange = useCallback((filters: DashboardFilters) => { const handleFilterChange = useCallback((filters: DashboardFilters) => {
setModelFilters(filters) setModelFilters(filters)
...@@ -221,6 +234,7 @@ export function Dashboard() { ...@@ -221,6 +234,7 @@ export function Dashboard() {
/> />
<ModelsFilter <ModelsFilter
preferences={chartPreferences} preferences={chartPreferences}
currentFilters={modelFilters}
onFilterChange={handleFilterChange} onFilterChange={handleFilterChange}
onReset={handleResetFilters} onReset={handleResetFilters}
/> />
...@@ -230,6 +244,7 @@ export function Dashboard() { ...@@ -230,6 +244,7 @@ export function Dashboard() {
activeSection === 'flow' ? ( activeSection === 'flow' ? (
<ModelsFilter <ModelsFilter
preferences={chartPreferences} preferences={chartPreferences}
currentFilters={modelFilters}
onFilterChange={handleFilterChange} onFilterChange={handleFilterChange}
onReset={handleResetFilters} onReset={handleResetFilters}
titleKey='Flow Filters' titleKey='Flow Filters'
...@@ -314,7 +329,10 @@ export function Dashboard() { ...@@ -314,7 +329,10 @@ export function Dashboard() {
{activeSection === 'users' && ( {activeSection === 'users' && (
<FadeIn> <FadeIn>
<Suspense fallback={<ModelChartsFallback />}> <Suspense fallback={<ModelChartsFallback />}>
<LazyUserCharts /> <LazyUserCharts
filters={userChartsFilters}
onFiltersChange={setUserChartsFilters}
/>
</Suspense> </Suspense>
</FadeIn> </FadeIn>
)} )}
......
...@@ -36,6 +36,8 @@ export { processChartData, processUserChartData } from './charts' ...@@ -36,6 +36,8 @@ export { processChartData, processUserChartData } from './charts'
export { export {
buildDashboardFlowData, buildDashboardFlowData,
buildFlowSankeySpec, buildFlowSankeySpec,
flowNodeFilterFromSankeyDatum,
flowSankeyDatumValue,
getFlowStages, getFlowStages,
} from './flow' } from './flow'
export { safeDivide, calculateDashboardStats } from './stats' export { safeDivide, calculateDashboardStats } from './stats'
......
...@@ -62,9 +62,22 @@ export type FlowNodeKind = ...@@ -62,9 +62,22 @@ export type FlowNodeKind =
| 'model' | 'model'
| 'channel' | 'channel'
export interface FlowNodeFilter {
kind: FlowNodeKind
id: string
}
export interface FlowLinkSelection {
source: string
target: string
}
export interface FlowBuildOptions { export interface FlowBuildOptions {
role?: FlowRole role?: FlowRole
selectedUsers?: string[] selectedUsers?: string[]
selectedNodes?: FlowNodeFilter[]
activeNode?: FlowNodeFilter
activeLink?: FlowLinkSelection
colorPalette?: readonly string[] colorPalette?: readonly string[]
visibleStages?: FlowNodeKind[] visibleStages?: FlowNodeKind[]
topNodeLimit?: number topNodeLimit?: number
...@@ -85,6 +98,8 @@ export interface DashboardFlowNode { ...@@ -85,6 +98,8 @@ export interface DashboardFlowNode {
tokens: number tokens: number
color: string color: string
colorKey: string colorKey: string
highlighted?: boolean
dimmed?: boolean
} }
export interface DashboardFlowLink { export interface DashboardFlowLink {
...@@ -102,6 +117,8 @@ export interface DashboardFlowLink { ...@@ -102,6 +117,8 @@ export interface DashboardFlowLink {
hoverColor: string hoverColor: string
colorKey: string colorKey: string
share: number share: number
highlighted?: boolean
dimmed?: boolean
} }
export interface DashboardFlowGraph { export interface DashboardFlowGraph {
...@@ -117,8 +134,18 @@ export interface FlowUserFilterOption { ...@@ -117,8 +134,18 @@ export interface FlowUserFilterOption {
color: string color: string
} }
export interface FlowNodeFilterOption {
kind: FlowNodeKind
value: string
label: string
valueLabel: string
valueRaw: number
color: string
}
export interface FlowFilterOptions { export interface FlowFilterOptions {
users: FlowUserFilterOption[] users: FlowUserFilterOption[]
nodes: FlowNodeFilterOption[]
} }
export interface FlowSummary { export interface FlowSummary {
...@@ -171,6 +198,14 @@ export interface DashboardChartPreferences { ...@@ -171,6 +198,14 @@ export interface DashboardChartPreferences {
defaultTimeGranularity: TimeGranularity defaultTimeGranularity: TimeGranularity
} }
// User analytics selections are held by the dashboard parent so they survive
// switching between dashboard sub-sections, matching the model/flow filters.
export interface UserChartsFilters {
timeGranularity: TimeGranularity
selectedRange: number
topUserLimit: number
}
// ============================================================================ // ============================================================================
// API Info Types // API Info Types
// ============================================================================ // ============================================================================
......
...@@ -271,6 +271,7 @@ ...@@ -271,6 +271,7 @@
"All Models": "All Models", "All Models": "All Models",
"All models in use are properly configured.": "All models in use are properly configured.", "All models in use are properly configured.": "All models in use are properly configured.",
"All Must Match (AND)": "All Must Match (AND)", "All Must Match (AND)": "All Must Match (AND)",
"All nodes": "All nodes",
"All requests must include": "All requests must include", "All requests must include": "All requests must include",
"All Status": "All Status", "All Status": "All Status",
"All Sync Status": "All Sync Status", "All Sync Status": "All Sync Status",
...@@ -780,6 +781,7 @@ ...@@ -780,6 +781,7 @@
"Clear filters": "Clear filters", "Clear filters": "Clear filters",
"Clear Mapping": "Clear Mapping", "Clear Mapping": "Clear Mapping",
"Clear mode flags in prompts": "Clear mode flags in prompts", "Clear mode flags in prompts": "Clear mode flags in prompts",
"Clear node filters": "Clear node filters",
"Clear search": "Clear search", "Clear search": "Clear search",
"Clear selection": "Clear selection", "Clear selection": "Clear selection",
"Clear selection (Escape)": "Clear selection (Escape)", "Clear selection (Escape)": "Clear selection (Escape)",
...@@ -1842,6 +1844,7 @@ ...@@ -1842,6 +1844,7 @@
"Filter by name or ID...": "Filter by name or ID...", "Filter by name or ID...": "Filter by name or ID...",
"Filter by name, ID, or key...": "Filter by name, ID, or key...", "Filter by name, ID, or key...": "Filter by name, ID, or key...",
"Filter by name...": "Filter by name...", "Filter by name...": "Filter by name...",
"Filter by node": "Filter by node",
"Filter by price field": "Filter by price field", "Filter by price field": "Filter by price field",
"Filter by ratio type": "Filter by ratio type", "Filter by ratio type": "Filter by ratio type",
"Filter by request ID": "Filter by request ID", "Filter by request ID": "Filter by request ID",
...@@ -2431,6 +2434,7 @@ ...@@ -2431,6 +2434,7 @@
"Memory Threshold (%)": "Memory Threshold (%)", "Memory Threshold (%)": "Memory Threshold (%)",
"Merchant ID": "Merchant ID", "Merchant ID": "Merchant ID",
"Merchant ID is required": "Merchant ID is required", "Merchant ID is required": "Merchant ID is required",
"Merge into Other": "Merge into Other",
"Message Priority": "Message Priority", "Message Priority": "Message Priority",
"Metadata": "Metadata", "Metadata": "Metadata",
"min downtime": "min downtime", "min downtime": "min downtime",
...@@ -2557,7 +2561,6 @@ ...@@ -2557,7 +2561,6 @@
"More than 999 days left": "More than 999 days left", "More than 999 days left": "More than 999 days left",
"More...": "More...", "More...": "More...",
"Most-used models in the selected period and category": "Most-used models in the selected period and category", "Most-used models in the selected period and category": "Most-used models in the selected period and category",
"Merge into Other": "Merge into Other",
"Move": "Move", "Move": "Move",
"Move a request header": "Move a request header", "Move a request header": "Move a request header",
"Move affiliate rewards to your main balance": "Move affiliate rewards to your main balance", "Move affiliate rewards to your main balance": "Move affiliate rewards to your main balance",
...@@ -2733,6 +2736,7 @@ ...@@ -2733,6 +2736,7 @@
"No models to remove": "No models to remove", "No models to remove": "No models to remove",
"No new models to add": "No new models to add", "No new models to add": "No new models to add",
"No new models yet": "No new models yet", "No new models yet": "No new models yet",
"No nodes": "No nodes",
"No notable climbers right now": "No notable climbers right now", "No notable climbers right now": "No notable climbers right now",
"No notable drops right now": "No notable drops right now", "No notable drops right now": "No notable drops right now",
"No parameter overrides configured.": "No parameter overrides configured.", "No parameter overrides configured.": "No parameter overrides configured.",
...@@ -2791,6 +2795,7 @@ ...@@ -2791,6 +2795,7 @@
"No vendor data available": "No vendor data available", "No vendor data available": "No vendor data available",
"No X Found": "No X Found", "No X Found": "No X Found",
"Node": "Node", "Node": "Node",
"Node filters": "Node filters",
"Node Name": "Node Name", "Node Name": "Node Name",
"Non-stream": "Non-stream", "Non-stream": "Non-stream",
"Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.": "Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.", "Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.": "Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.",
...@@ -2958,8 +2963,8 @@ ...@@ -2958,8 +2963,8 @@
"Output tokens": "Output tokens", "Output tokens": "Output tokens",
"Output Tokens": "Output Tokens", "Output Tokens": "Output Tokens",
"Overage limited": "Overage limited", "Overage limited": "Overage limited",
"Overflow items": "Overflow items",
"overall": "overall", "overall": "overall",
"Overflow items": "Overflow items",
"Overnight range": "Overnight range", "Overnight range": "Overnight range",
"override": "override", "override": "override",
"Override": "Override", "Override": "Override",
...@@ -3460,6 +3465,7 @@ ...@@ -3460,6 +3465,7 @@
"Remove functionResponse.id field": "Remove functionResponse.id field", "Remove functionResponse.id field": "Remove functionResponse.id field",
"Remove mapped targets": "Remove mapped targets", "Remove mapped targets": "Remove mapped targets",
"Remove Models": "Remove Models", "Remove Models": "Remove Models",
"Remove node filter": "Remove node filter",
"Remove Passkey": "Remove Passkey", "Remove Passkey": "Remove Passkey",
"Remove Passkey?": "Remove Passkey?", "Remove Passkey?": "Remove Passkey?",
"Remove rule group": "Remove rule group", "Remove rule group": "Remove rule group",
...@@ -3804,6 +3810,7 @@ ...@@ -3804,6 +3810,7 @@
"Selected {{count}}": "Selected {{count}}", "Selected {{count}}": "Selected {{count}}",
"selected channel(s). Leave empty to remove tag.": "selected channel(s). Leave empty to remove tag.", "selected channel(s). Leave empty to remove tag.": "selected channel(s). Leave empty to remove tag.",
"Selected conflicts were overwritten successfully.": "Selected conflicts were overwritten successfully.", "Selected conflicts were overwritten successfully.": "Selected conflicts were overwritten successfully.",
"Selected nodes": "Selected nodes",
"Selected when creating a token and used as the default billing group for API calls.": "Selected when creating a token and used as the default billing group for API calls.", "Selected when creating a token and used as the default billing group for API calls.": "Selected when creating a token and used as the default billing group for API calls.",
"Self-Use Mode": "Self-Use Mode", "Self-Use Mode": "Self-Use Mode",
"Send": "Send", "Send": "Send",
...@@ -4582,6 +4589,7 @@ ...@@ -4582,6 +4589,7 @@
"Value": "Value", "Value": "Value",
"Value (supports JSON or plain text)": "Value (supports JSON or plain text)", "Value (supports JSON or plain text)": "Value (supports JSON or plain text)",
"Value is required": "Value is required", "Value is required": "Value is required",
"Value metric": "Value metric",
"Value must be at least 0": "Value must be at least 0", "Value must be at least 0": "Value must be at least 0",
"Value Regex": "Value Regex", "Value Regex": "Value Regex",
"variable": "variable", "variable": "variable",
......
...@@ -271,6 +271,7 @@ ...@@ -271,6 +271,7 @@
"All Models": "Tous les modèles", "All Models": "Tous les modèles",
"All models in use are properly configured.": "Tous les modèles utilisés sont correctement configurés.", "All models in use are properly configured.": "Tous les modèles utilisés sont correctement configurés.",
"All Must Match (AND)": "Toutes doivent correspondre (AND)", "All Must Match (AND)": "Toutes doivent correspondre (AND)",
"All nodes": "Tous les nœuds",
"All requests must include": "Toutes les requêtes doivent inclure", "All requests must include": "Toutes les requêtes doivent inclure",
"All Status": "Tous les statuts", "All Status": "Tous les statuts",
"All Sync Status": "Tous les statuts de synchronisation", "All Sync Status": "Tous les statuts de synchronisation",
...@@ -780,6 +781,7 @@ ...@@ -780,6 +781,7 @@
"Clear filters": "Effacer les filtres", "Clear filters": "Effacer les filtres",
"Clear Mapping": "Effacer le mappage", "Clear Mapping": "Effacer le mappage",
"Clear mode flags in prompts": "Effacer les indicateurs de mode dans les prompts", "Clear mode flags in prompts": "Effacer les indicateurs de mode dans les prompts",
"Clear node filters": "Effacer les filtres de nœuds",
"Clear search": "Effacer la recherche", "Clear search": "Effacer la recherche",
"Clear selection": "Effacer la sélection", "Clear selection": "Effacer la sélection",
"Clear selection (Escape)": "Effacer la sélection (Échap)", "Clear selection (Escape)": "Effacer la sélection (Échap)",
...@@ -1842,6 +1844,7 @@ ...@@ -1842,6 +1844,7 @@
"Filter by name or ID...": "Filtrer par nom ou ID...", "Filter by name or ID...": "Filtrer par nom ou ID...",
"Filter by name, ID, or key...": "Filtrer par nom, ID ou clé...", "Filter by name, ID, or key...": "Filtrer par nom, ID ou clé...",
"Filter by name...": "Filtrer par nom...", "Filter by name...": "Filtrer par nom...",
"Filter by node": "Filtrer par nœud",
"Filter by price field": "Filtrer par champ de prix", "Filter by price field": "Filtrer par champ de prix",
"Filter by ratio type": "Filtrer par type de ratio", "Filter by ratio type": "Filtrer par type de ratio",
"Filter by request ID": "Filtrer par ID de requête", "Filter by request ID": "Filtrer par ID de requête",
...@@ -2431,6 +2434,7 @@ ...@@ -2431,6 +2434,7 @@
"Memory Threshold (%)": "Seuil mémoire (%)", "Memory Threshold (%)": "Seuil mémoire (%)",
"Merchant ID": "ID du commerçant", "Merchant ID": "ID du commerçant",
"Merchant ID is required": "L'ID marchand est requis", "Merchant ID is required": "L'ID marchand est requis",
"Merge into Other": "Fusionner dans Autres",
"Message Priority": "Priorité du message", "Message Priority": "Priorité du message",
"Metadata": "Métadonnées", "Metadata": "Métadonnées",
"min downtime": "min d'interruption", "min downtime": "min d'interruption",
...@@ -2557,7 +2561,6 @@ ...@@ -2557,7 +2561,6 @@
"More than 999 days left": "Plus de 999 jours restants", "More than 999 days left": "Plus de 999 jours restants",
"More...": "Plus...", "More...": "Plus...",
"Most-used models in the selected period and category": "Modèles les plus utilisés dans la période et catégorie choisies", "Most-used models in the selected period and category": "Modèles les plus utilisés dans la période et catégorie choisies",
"Merge into Other": "Fusionner dans Autres",
"Move": "Déplacer", "Move": "Déplacer",
"Move a request header": "Déplacer un en-tête de requête", "Move a request header": "Déplacer un en-tête de requête",
"Move affiliate rewards to your main balance": "Transférer les récompenses d'affiliation vers votre solde principal", "Move affiliate rewards to your main balance": "Transférer les récompenses d'affiliation vers votre solde principal",
...@@ -2733,6 +2736,7 @@ ...@@ -2733,6 +2736,7 @@
"No models to remove": "Aucun modèle à supprimer", "No models to remove": "Aucun modèle à supprimer",
"No new models to add": "Aucun nouveau modèle à ajouter", "No new models to add": "Aucun nouveau modèle à ajouter",
"No new models yet": "Pas encore de nouveaux modèles", "No new models yet": "Pas encore de nouveaux modèles",
"No nodes": "Aucun nœud",
"No notable climbers right now": "Aucune progression notable pour le moment", "No notable climbers right now": "Aucune progression notable pour le moment",
"No notable drops right now": "Aucune chute notable pour le moment", "No notable drops right now": "Aucune chute notable pour le moment",
"No parameter overrides configured.": "Aucune surcharge de paramètres configurée.", "No parameter overrides configured.": "Aucune surcharge de paramètres configurée.",
...@@ -2791,6 +2795,7 @@ ...@@ -2791,6 +2795,7 @@
"No vendor data available": "Aucune donnée de fournisseur disponible", "No vendor data available": "Aucune donnée de fournisseur disponible",
"No X Found": "Aucun X trouvé", "No X Found": "Aucun X trouvé",
"Node": "Nœud", "Node": "Nœud",
"Node filters": "Filtres de nœuds",
"Node Name": "Nom du nœud", "Node Name": "Nom du nœud",
"Non-stream": "Non-streaming", "Non-stream": "Non-streaming",
"Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.": "Les récompenses d’invitation non nulles nécessitent une confirmation de conformité dans les paramètres de la passerelle de paiement.", "Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.": "Les récompenses d’invitation non nulles nécessitent une confirmation de conformité dans les paramètres de la passerelle de paiement.",
...@@ -2958,8 +2963,8 @@ ...@@ -2958,8 +2963,8 @@
"Output tokens": "Jetons de sortie", "Output tokens": "Jetons de sortie",
"Output Tokens": "Tokens de sortie", "Output Tokens": "Tokens de sortie",
"Overage limited": "Dépassement limité", "Overage limited": "Dépassement limité",
"Overflow items": "Éléments excédentaires",
"overall": "global", "overall": "global",
"Overflow items": "Éléments excédentaires",
"Overnight range": "Plage nocturne", "Overnight range": "Plage nocturne",
"override": "remplacer", "override": "remplacer",
"Override": "Remplacer", "Override": "Remplacer",
...@@ -3460,6 +3465,7 @@ ...@@ -3460,6 +3465,7 @@
"Remove functionResponse.id field": "Supprimer le champ functionResponse.id", "Remove functionResponse.id field": "Supprimer le champ functionResponse.id",
"Remove mapped targets": "Retirer les cibles mappées", "Remove mapped targets": "Retirer les cibles mappées",
"Remove Models": "Supprimer des modèles", "Remove Models": "Supprimer des modèles",
"Remove node filter": "Supprimer le filtre de nœud",
"Remove Passkey": "Supprimer le Passkey", "Remove Passkey": "Supprimer le Passkey",
"Remove Passkey?": "Supprimer la clé d'accès ?", "Remove Passkey?": "Supprimer la clé d'accès ?",
"Remove rule group": "Supprimer le groupe de règles", "Remove rule group": "Supprimer le groupe de règles",
...@@ -3804,6 +3810,7 @@ ...@@ -3804,6 +3810,7 @@
"Selected {{count}}": "{{count}} sélectionné(s)", "Selected {{count}}": "{{count}} sélectionné(s)",
"selected channel(s). Leave empty to remove tag.": "canal(aux) sélectionné(s). Laisser vide pour supprimer l'étiquette.", "selected channel(s). Leave empty to remove tag.": "canal(aux) sélectionné(s). Laisser vide pour supprimer l'étiquette.",
"Selected conflicts were overwritten successfully.": "Les conflits sélectionnés ont été écrasés avec succès.", "Selected conflicts were overwritten successfully.": "Les conflits sélectionnés ont été écrasés avec succès.",
"Selected nodes": "Nœuds sélectionnés",
"Selected when creating a token and used as the default billing group for API calls.": "Sélectionné lors de la création d’un jeton et utilisé comme groupe de facturation par défaut pour les appels API.", "Selected when creating a token and used as the default billing group for API calls.": "Sélectionné lors de la création d’un jeton et utilisé comme groupe de facturation par défaut pour les appels API.",
"Self-Use Mode": "Mode d'utilisation personnelle", "Self-Use Mode": "Mode d'utilisation personnelle",
"Send": "Envoyer", "Send": "Envoyer",
...@@ -4582,6 +4589,7 @@ ...@@ -4582,6 +4589,7 @@
"Value": "Valeur", "Value": "Valeur",
"Value (supports JSON or plain text)": "Valeur (JSON ou texte brut)", "Value (supports JSON or plain text)": "Valeur (JSON ou texte brut)",
"Value is required": "La valeur est obligatoire", "Value is required": "La valeur est obligatoire",
"Value metric": "Métrique de valeur",
"Value must be at least 0": "La valeur doit être au moins 0", "Value must be at least 0": "La valeur doit être au moins 0",
"Value Regex": "Regex de valeur", "Value Regex": "Regex de valeur",
"variable": "variable", "variable": "variable",
......
...@@ -271,6 +271,7 @@ ...@@ -271,6 +271,7 @@
"All Models": "すべてのモデル", "All Models": "すべてのモデル",
"All models in use are properly configured.": "使用中のすべてのモデルが適切に構成されています。", "All models in use are properly configured.": "使用中のすべてのモデルが適切に構成されています。",
"All Must Match (AND)": "すべて一致(AND)", "All Must Match (AND)": "すべて一致(AND)",
"All nodes": "すべてのノード",
"All requests must include": "すべてのリクエストには", "All requests must include": "すべてのリクエストには",
"All Status": "すべてのステータス", "All Status": "すべてのステータス",
"All Sync Status": "すべての同期状態", "All Sync Status": "すべての同期状態",
...@@ -780,6 +781,7 @@ ...@@ -780,6 +781,7 @@
"Clear filters": "フィルターをクリア", "Clear filters": "フィルターをクリア",
"Clear Mapping": "マッピングをクリア", "Clear Mapping": "マッピングをクリア",
"Clear mode flags in prompts": "プロンプト内のモードフラグをクリア", "Clear mode flags in prompts": "プロンプト内のモードフラグをクリア",
"Clear node filters": "ノードフィルターをクリア",
"Clear search": "検索をクリア", "Clear search": "検索をクリア",
"Clear selection": "選択をクリア", "Clear selection": "選択をクリア",
"Clear selection (Escape)": "選択をクリア (Escape)", "Clear selection (Escape)": "選択をクリア (Escape)",
...@@ -1842,6 +1844,7 @@ ...@@ -1842,6 +1844,7 @@
"Filter by name or ID...": "名前またはIDでフィルター...", "Filter by name or ID...": "名前またはIDでフィルター...",
"Filter by name, ID, or key...": "名前、ID、またはキーでフィルター...", "Filter by name, ID, or key...": "名前、ID、またはキーでフィルター...",
"Filter by name...": "名前でフィルター...", "Filter by name...": "名前でフィルター...",
"Filter by node": "ノードでフィルター",
"Filter by price field": "価格フィールドでフィルター", "Filter by price field": "価格フィールドでフィルター",
"Filter by ratio type": "倍率タイプで絞り込み", "Filter by ratio type": "倍率タイプで絞り込み",
"Filter by request ID": "リクエストIDで絞り込み", "Filter by request ID": "リクエストIDで絞り込み",
...@@ -2431,6 +2434,7 @@ ...@@ -2431,6 +2434,7 @@
"Memory Threshold (%)": "メモリ閾値 (%)", "Memory Threshold (%)": "メモリ閾値 (%)",
"Merchant ID": "マーチャントID", "Merchant ID": "マーチャントID",
"Merchant ID is required": "マーチャント ID は必須です", "Merchant ID is required": "マーチャント ID は必須です",
"Merge into Other": "その他にまとめる",
"Message Priority": "メッセージの優先度", "Message Priority": "メッセージの優先度",
"Metadata": "メタデータ", "Metadata": "メタデータ",
"min downtime": "分のダウンタイム", "min downtime": "分のダウンタイム",
...@@ -2557,7 +2561,6 @@ ...@@ -2557,7 +2561,6 @@
"More than 999 days left": "999日以上", "More than 999 days left": "999日以上",
"More...": "その他...", "More...": "その他...",
"Most-used models in the selected period and category": "選択した期間とカテゴリで最も使われているモデル", "Most-used models in the selected period and category": "選択した期間とカテゴリで最も使われているモデル",
"Merge into Other": "その他にまとめる",
"Move": "移動", "Move": "移動",
"Move a request header": "リクエストヘッダーを移動", "Move a request header": "リクエストヘッダーを移動",
"Move affiliate rewards to your main balance": "アフィリエイト報酬をメイン残高に移動する", "Move affiliate rewards to your main balance": "アフィリエイト報酬をメイン残高に移動する",
...@@ -2733,6 +2736,7 @@ ...@@ -2733,6 +2736,7 @@
"No models to remove": "削除するモデルがありません", "No models to remove": "削除するモデルがありません",
"No new models to add": "追加する新しいモデルはありません", "No new models to add": "追加する新しいモデルはありません",
"No new models yet": "新しいモデルはまだありません", "No new models yet": "新しいモデルはまだありません",
"No nodes": "ノードなし",
"No notable climbers right now": "現在、目立った上昇はありません", "No notable climbers right now": "現在、目立った上昇はありません",
"No notable drops right now": "現在、目立った下降はありません", "No notable drops right now": "現在、目立った下降はありません",
"No parameter overrides configured.": "パラメータのオーバーライドが設定されていません。", "No parameter overrides configured.": "パラメータのオーバーライドが設定されていません。",
...@@ -2791,6 +2795,7 @@ ...@@ -2791,6 +2795,7 @@
"No vendor data available": "ベンダーデータがありません", "No vendor data available": "ベンダーデータがありません",
"No X Found": "X が見つかりません", "No X Found": "X が見つかりません",
"Node": "ノード", "Node": "ノード",
"Node filters": "ノードフィルター",
"Node Name": "ノード名", "Node Name": "ノード名",
"Non-stream": "非ストリーミング", "Non-stream": "非ストリーミング",
"Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.": "0 以外の招待報酬には、支払いゲートウェイ設定でのコンプライアンス確認が必要です。", "Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.": "0 以外の招待報酬には、支払いゲートウェイ設定でのコンプライアンス確認が必要です。",
...@@ -2958,8 +2963,8 @@ ...@@ -2958,8 +2963,8 @@
"Output tokens": "出力トークン", "Output tokens": "出力トークン",
"Output Tokens": "出力トークン", "Output Tokens": "出力トークン",
"Overage limited": "超過利用制限中", "Overage limited": "超過利用制限中",
"Overflow items": "超過項目",
"overall": "全体", "overall": "全体",
"Overflow items": "超過項目",
"Overnight range": "日跨ぎ範囲", "Overnight range": "日跨ぎ範囲",
"override": "上書き", "override": "上書き",
"Override": "上書き", "Override": "上書き",
...@@ -3460,6 +3465,7 @@ ...@@ -3460,6 +3465,7 @@
"Remove functionResponse.id field": "functionResponse.id フィールドを削除", "Remove functionResponse.id field": "functionResponse.id フィールドを削除",
"Remove mapped targets": "マッピング先を削除", "Remove mapped targets": "マッピング先を削除",
"Remove Models": "モデルを削除", "Remove Models": "モデルを削除",
"Remove node filter": "ノードフィルターを削除",
"Remove Passkey": "Passkey連携解除", "Remove Passkey": "Passkey連携解除",
"Remove Passkey?": "Passkeyを削除しますか?", "Remove Passkey?": "Passkeyを削除しますか?",
"Remove rule group": "ルールグループを削除", "Remove rule group": "ルールグループを削除",
...@@ -3804,6 +3810,7 @@ ...@@ -3804,6 +3810,7 @@
"Selected {{count}}": "{{count}} 件選択済み", "Selected {{count}}": "{{count}} 件選択済み",
"selected channel(s). Leave empty to remove tag.": "選択されたチャネル。タグを削除するには空のままにしてください。", "selected channel(s). Leave empty to remove tag.": "選択されたチャネル。タグを削除するには空のままにしてください。",
"Selected conflicts were overwritten successfully.": "選択した競合が正常に上書きされました。", "Selected conflicts were overwritten successfully.": "選択した競合が正常に上書きされました。",
"Selected nodes": "選択したノード",
"Selected when creating a token and used as the default billing group for API calls.": "トークン作成時に選択され、API 呼び出しのデフォルト課金グループとして使われます。", "Selected when creating a token and used as the default billing group for API calls.": "トークン作成時に選択され、API 呼び出しのデフォルト課金グループとして使われます。",
"Self-Use Mode": "セルフユースモード", "Self-Use Mode": "セルフユースモード",
"Send": "送信", "Send": "送信",
...@@ -4582,6 +4589,7 @@ ...@@ -4582,6 +4589,7 @@
"Value": "値", "Value": "値",
"Value (supports JSON or plain text)": "値(JSONまたはプレーンテキスト対応)", "Value (supports JSON or plain text)": "値(JSONまたはプレーンテキスト対応)",
"Value is required": "値は必須です", "Value is required": "値は必須です",
"Value metric": "値の指標",
"Value must be at least 0": "値は 0 以上である必要があります", "Value must be at least 0": "値は 0 以上である必要があります",
"Value Regex": "Value 正規表現", "Value Regex": "Value 正規表現",
"variable": "変数", "variable": "変数",
......
...@@ -271,6 +271,7 @@ ...@@ -271,6 +271,7 @@
"All Models": "Все модели", "All Models": "Все модели",
"All models in use are properly configured.": "Все используемые модели настроены правильно.", "All models in use are properly configured.": "Все используемые модели настроены правильно.",
"All Must Match (AND)": "Все должны совпасть (AND)", "All Must Match (AND)": "Все должны совпасть (AND)",
"All nodes": "Все узлы",
"All requests must include": "Все запросы должны содержать", "All requests must include": "Все запросы должны содержать",
"All Status": "Все статусы", "All Status": "Все статусы",
"All Sync Status": "Все статусы синхронизации", "All Sync Status": "Все статусы синхронизации",
...@@ -780,6 +781,7 @@ ...@@ -780,6 +781,7 @@
"Clear filters": "Очистить фильтры", "Clear filters": "Очистить фильтры",
"Clear Mapping": "Очистить сопоставление", "Clear Mapping": "Очистить сопоставление",
"Clear mode flags in prompts": "Очистить флаги режимов в промптах", "Clear mode flags in prompts": "Очистить флаги режимов в промптах",
"Clear node filters": "Очистить фильтры узлов",
"Clear search": "Очистить поиск", "Clear search": "Очистить поиск",
"Clear selection": "Снять выделение", "Clear selection": "Снять выделение",
"Clear selection (Escape)": "Снять выделение (Escape)", "Clear selection (Escape)": "Снять выделение (Escape)",
...@@ -1842,6 +1844,7 @@ ...@@ -1842,6 +1844,7 @@
"Filter by name or ID...": "Фильтр по имени или ID...", "Filter by name or ID...": "Фильтр по имени или ID...",
"Filter by name, ID, or key...": "Фильтровать по имени, ID или ключу...", "Filter by name, ID, or key...": "Фильтровать по имени, ID или ключу...",
"Filter by name...": "Фильтр по имени...", "Filter by name...": "Фильтр по имени...",
"Filter by node": "Фильтр по узлу",
"Filter by price field": "Фильтр по полю цены", "Filter by price field": "Фильтр по полю цены",
"Filter by ratio type": "Фильтровать по типу коэффициента", "Filter by ratio type": "Фильтровать по типу коэффициента",
"Filter by request ID": "Фильтр по ID запроса", "Filter by request ID": "Фильтр по ID запроса",
...@@ -2431,6 +2434,7 @@ ...@@ -2431,6 +2434,7 @@
"Memory Threshold (%)": "Порог памяти (%)", "Memory Threshold (%)": "Порог памяти (%)",
"Merchant ID": "ID мерчанта", "Merchant ID": "ID мерчанта",
"Merchant ID is required": "Требуется ID мерчанта", "Merchant ID is required": "Требуется ID мерчанта",
"Merge into Other": "Объединить в «Другое»",
"Message Priority": "Приоритет сообщения", "Message Priority": "Приоритет сообщения",
"Metadata": "Метаданные", "Metadata": "Метаданные",
"min downtime": "мин простоя", "min downtime": "мин простоя",
...@@ -2557,7 +2561,6 @@ ...@@ -2557,7 +2561,6 @@
"More than 999 days left": "Более 999 дней", "More than 999 days left": "Более 999 дней",
"More...": "Подробнее...", "More...": "Подробнее...",
"Most-used models in the selected period and category": "Самые используемые модели в выбранном периоде и категории", "Most-used models in the selected period and category": "Самые используемые модели в выбранном периоде и категории",
"Merge into Other": "Объединить в «Другое»",
"Move": "Переместить", "Move": "Переместить",
"Move a request header": "Переместить заголовок запроса", "Move a request header": "Переместить заголовок запроса",
"Move affiliate rewards to your main balance": "Перевести партнерские вознаграждения на основной баланс", "Move affiliate rewards to your main balance": "Перевести партнерские вознаграждения на основной баланс",
...@@ -2733,6 +2736,7 @@ ...@@ -2733,6 +2736,7 @@
"No models to remove": "Нет моделей для удаления", "No models to remove": "Нет моделей для удаления",
"No new models to add": "Нет новых моделей для добавления", "No new models to add": "Нет новых моделей для добавления",
"No new models yet": "Новых моделей пока нет", "No new models yet": "Новых моделей пока нет",
"No nodes": "Нет узлов",
"No notable climbers right now": "Сейчас нет значимых поднявшихся моделей", "No notable climbers right now": "Сейчас нет значимых поднявшихся моделей",
"No notable drops right now": "Сейчас нет значимых упавших моделей", "No notable drops right now": "Сейчас нет значимых упавших моделей",
"No parameter overrides configured.": "Нет настроенных переопределений параметров.", "No parameter overrides configured.": "Нет настроенных переопределений параметров.",
...@@ -2791,6 +2795,7 @@ ...@@ -2791,6 +2795,7 @@
"No vendor data available": "Данных по поставщикам нет", "No vendor data available": "Данных по поставщикам нет",
"No X Found": "X не найдено", "No X Found": "X не найдено",
"Node": "Узел", "Node": "Узел",
"Node filters": "Фильтры узлов",
"Node Name": "Имя узла", "Node Name": "Имя узла",
"Non-stream": "Не потоковый", "Non-stream": "Не потоковый",
"Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.": "Ненулевые награды за приглашения требуют подтверждения соответствия в настройках платежного шлюза.", "Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.": "Ненулевые награды за приглашения требуют подтверждения соответствия в настройках платежного шлюза.",
...@@ -2958,8 +2963,8 @@ ...@@ -2958,8 +2963,8 @@
"Output tokens": "Выходные токены", "Output tokens": "Выходные токены",
"Output Tokens": "Выходные токены", "Output Tokens": "Выходные токены",
"Overage limited": "Ограничение перерасхода", "Overage limited": "Ограничение перерасхода",
"Overflow items": "Элементы сверх лимита",
"overall": "всего", "overall": "всего",
"Overflow items": "Элементы сверх лимита",
"Overnight range": "Диапазон через полночь", "Overnight range": "Диапазон через полночь",
"override": "переопределить", "override": "переопределить",
"Override": "Перезаписать", "Override": "Перезаписать",
...@@ -3460,6 +3465,7 @@ ...@@ -3460,6 +3465,7 @@
"Remove functionResponse.id field": "Удалить поле functionResponse.id", "Remove functionResponse.id field": "Удалить поле functionResponse.id",
"Remove mapped targets": "Удалить сопоставленные цели", "Remove mapped targets": "Удалить сопоставленные цели",
"Remove Models": "Удалить модели", "Remove Models": "Удалить модели",
"Remove node filter": "Удалить фильтр узла",
"Remove Passkey": "Отвязать Passkey", "Remove Passkey": "Отвязать Passkey",
"Remove Passkey?": "Удалить ключ доступа?", "Remove Passkey?": "Удалить ключ доступа?",
"Remove rule group": "Удалить группу правил", "Remove rule group": "Удалить группу правил",
...@@ -3804,6 +3810,7 @@ ...@@ -3804,6 +3810,7 @@
"Selected {{count}}": "Выбрано: {{count}}", "Selected {{count}}": "Выбрано: {{count}}",
"selected channel(s). Leave empty to remove tag.": "выбранный канал(ы). Оставьте пустым, чтобы удалить тег.", "selected channel(s). Leave empty to remove tag.": "выбранный канал(ы). Оставьте пустым, чтобы удалить тег.",
"Selected conflicts were overwritten successfully.": "Выбранные конфликты успешно перезаписаны.", "Selected conflicts were overwritten successfully.": "Выбранные конфликты успешно перезаписаны.",
"Selected nodes": "Выбранные узлы",
"Selected when creating a token and used as the default billing group for API calls.": "Выбирается при создании токена и используется как группа тарификации по умолчанию для вызовов API.", "Selected when creating a token and used as the default billing group for API calls.": "Выбирается при создании токена и используется как группа тарификации по умолчанию для вызовов API.",
"Self-Use Mode": "Режим самоиспользования", "Self-Use Mode": "Режим самоиспользования",
"Send": "Отправить", "Send": "Отправить",
...@@ -4582,6 +4589,7 @@ ...@@ -4582,6 +4589,7 @@
"Value": "Значение", "Value": "Значение",
"Value (supports JSON or plain text)": "Значение (JSON или текст)", "Value (supports JSON or plain text)": "Значение (JSON или текст)",
"Value is required": "Значение обязательно", "Value is required": "Значение обязательно",
"Value metric": "Метрика значения",
"Value must be at least 0": "Значение должно быть не менее 0", "Value must be at least 0": "Значение должно быть не менее 0",
"Value Regex": "Регулярное выражение значения", "Value Regex": "Регулярное выражение значения",
"variable": "переменная", "variable": "переменная",
......
...@@ -271,6 +271,7 @@ ...@@ -271,6 +271,7 @@
"All Models": "Tất cả các mẫu", "All Models": "Tất cả các mẫu",
"All models in use are properly configured.": "Tất cả các mô hình đang được sử dụng đều được cấu hình đúng cách.", "All models in use are properly configured.": "Tất cả các mô hình đang được sử dụng đều được cấu hình đúng cách.",
"All Must Match (AND)": "Tất cả phải khớp (AND)", "All Must Match (AND)": "Tất cả phải khớp (AND)",
"All nodes": "Tất cả nút",
"All requests must include": "Mọi yêu cầu phải có header", "All requests must include": "Mọi yêu cầu phải có header",
"All Status": "Tất cả trạng thái", "All Status": "Tất cả trạng thái",
"All Sync Status": "Tất cả Trạng thái Đồng bộ", "All Sync Status": "Tất cả Trạng thái Đồng bộ",
...@@ -780,6 +781,7 @@ ...@@ -780,6 +781,7 @@
"Clear filters": "Clear filter", "Clear filters": "Clear filter",
"Clear Mapping": "Xóa Ánh xạ", "Clear Mapping": "Xóa Ánh xạ",
"Clear mode flags in prompts": "Xóa các cờ chế độ trong lời nhắc", "Clear mode flags in prompts": "Xóa các cờ chế độ trong lời nhắc",
"Clear node filters": "Xóa bộ lọc nút",
"Clear search": "Xóa tìm kiếm", "Clear search": "Xóa tìm kiếm",
"Clear selection": "Bỏ chọn", "Clear selection": "Bỏ chọn",
"Clear selection (Escape)": "Bỏ chọn (Escape)", "Clear selection (Escape)": "Bỏ chọn (Escape)",
...@@ -1842,6 +1844,7 @@ ...@@ -1842,6 +1844,7 @@
"Filter by name or ID...": "Lọc theo tên hoặc ID...", "Filter by name or ID...": "Lọc theo tên hoặc ID...",
"Filter by name, ID, or key...": "Lọc theo tên, ID hoặc khóa...", "Filter by name, ID, or key...": "Lọc theo tên, ID hoặc khóa...",
"Filter by name...": "Lọc theo tên...", "Filter by name...": "Lọc theo tên...",
"Filter by node": "Lọc theo nút",
"Filter by price field": "Lọc theo trường giá", "Filter by price field": "Lọc theo trường giá",
"Filter by ratio type": "Lọc theo loại tỷ lệ", "Filter by ratio type": "Lọc theo loại tỷ lệ",
"Filter by request ID": "Lọc theo ID yêu cầu", "Filter by request ID": "Lọc theo ID yêu cầu",
...@@ -2431,6 +2434,7 @@ ...@@ -2431,6 +2434,7 @@
"Memory Threshold (%)": "Ngưỡng bộ nhớ (%)", "Memory Threshold (%)": "Ngưỡng bộ nhớ (%)",
"Merchant ID": "Mã thương gia", "Merchant ID": "Mã thương gia",
"Merchant ID is required": "Bắt buộc nhập Merchant ID", "Merchant ID is required": "Bắt buộc nhập Merchant ID",
"Merge into Other": "Gộp vào Khác",
"Message Priority": "Ưu tiên tin nhắn", "Message Priority": "Ưu tiên tin nhắn",
"Metadata": "Siêu dữ liệu", "Metadata": "Siêu dữ liệu",
"min downtime": "phút gián đoạn", "min downtime": "phút gián đoạn",
...@@ -2557,7 +2561,6 @@ ...@@ -2557,7 +2561,6 @@
"More than 999 days left": "Hơn 999 ngày", "More than 999 days left": "Hơn 999 ngày",
"More...": "Thêm...", "More...": "Thêm...",
"Most-used models in the selected period and category": "Mô hình được dùng nhiều nhất trong khoảng thời gian và danh mục đã chọn", "Most-used models in the selected period and category": "Mô hình được dùng nhiều nhất trong khoảng thời gian và danh mục đã chọn",
"Merge into Other": "Gộp vào Khác",
"Move": "Di chuyển", "Move": "Di chuyển",
"Move a request header": "Di chuyển header yêu cầu", "Move a request header": "Di chuyển header yêu cầu",
"Move affiliate rewards to your main balance": "Chuyển phần thưởng liên kết vào số dư chính của bạn", "Move affiliate rewards to your main balance": "Chuyển phần thưởng liên kết vào số dư chính của bạn",
...@@ -2733,6 +2736,7 @@ ...@@ -2733,6 +2736,7 @@
"No models to remove": "Không có mô hình để xóa", "No models to remove": "Không có mô hình để xóa",
"No new models to add": "Không có mô hình mới để thêm", "No new models to add": "Không có mô hình mới để thêm",
"No new models yet": "Chưa có mô hình mới", "No new models yet": "Chưa có mô hình mới",
"No nodes": "Không có nút",
"No notable climbers right now": "Hiện chưa có mô hình nào tăng đáng kể", "No notable climbers right now": "Hiện chưa có mô hình nào tăng đáng kể",
"No notable drops right now": "Hiện chưa có mô hình nào giảm đáng kể", "No notable drops right now": "Hiện chưa có mô hình nào giảm đáng kể",
"No parameter overrides configured.": "Không có ghi đè tham số nào được cấu hình.", "No parameter overrides configured.": "Không có ghi đè tham số nào được cấu hình.",
...@@ -2791,6 +2795,7 @@ ...@@ -2791,6 +2795,7 @@
"No vendor data available": "Không có dữ liệu nhà cung cấp", "No vendor data available": "Không có dữ liệu nhà cung cấp",
"No X Found": "Không tìm thấy X", "No X Found": "Không tìm thấy X",
"Node": "Nút", "Node": "Nút",
"Node filters": "Bộ lọc nút",
"Node Name": "Tên nút", "Node Name": "Tên nút",
"Non-stream": "Không phát trực tuyến", "Non-stream": "Không phát trực tuyến",
"Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.": "Phần thưởng mời khác 0 yêu cầu xác nhận tuân thủ trong cài đặt Cổng thanh toán.", "Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.": "Phần thưởng mời khác 0 yêu cầu xác nhận tuân thủ trong cài đặt Cổng thanh toán.",
...@@ -2958,8 +2963,8 @@ ...@@ -2958,8 +2963,8 @@
"Output tokens": "Token đầu ra", "Output tokens": "Token đầu ra",
"Output Tokens": "Token đầu ra", "Output Tokens": "Token đầu ra",
"Overage limited": "Đã giới hạn vượt mức", "Overage limited": "Đã giới hạn vượt mức",
"Overflow items": "Mục vượt giới hạn",
"overall": "tổng", "overall": "tổng",
"Overflow items": "Mục vượt giới hạn",
"Overnight range": "Khoảng qua nửa đêm", "Overnight range": "Khoảng qua nửa đêm",
"override": "ghi đè", "override": "ghi đè",
"Override": "Ghi đè", "Override": "Ghi đè",
...@@ -3460,6 +3465,7 @@ ...@@ -3460,6 +3465,7 @@
"Remove functionResponse.id field": "Loại bỏ trường functionResponse.id", "Remove functionResponse.id field": "Loại bỏ trường functionResponse.id",
"Remove mapped targets": "Xóa đích đã ánh xạ", "Remove mapped targets": "Xóa đích đã ánh xạ",
"Remove Models": "Xóa mô hình", "Remove Models": "Xóa mô hình",
"Remove node filter": "Xóa bộ lọc nút này",
"Remove Passkey": "Xóa Khóa truy cập", "Remove Passkey": "Xóa Khóa truy cập",
"Remove Passkey?": "Xóa khóa truy cập?", "Remove Passkey?": "Xóa khóa truy cập?",
"Remove rule group": "Gỡ nhóm quy tắc", "Remove rule group": "Gỡ nhóm quy tắc",
...@@ -3804,6 +3810,7 @@ ...@@ -3804,6 +3810,7 @@
"Selected {{count}}": "Đã chọn {{count}}", "Selected {{count}}": "Đã chọn {{count}}",
"selected channel(s). Leave empty to remove tag.": "Kênh đã chọn. Để trống để xóa thẻ.", "selected channel(s). Leave empty to remove tag.": "Kênh đã chọn. Để trống để xóa thẻ.",
"Selected conflicts were overwritten successfully.": "Các xung đột được chọn đã được ghi đè thành công.", "Selected conflicts were overwritten successfully.": "Các xung đột được chọn đã được ghi đè thành công.",
"Selected nodes": "Nút đã chọn",
"Selected when creating a token and used as the default billing group for API calls.": "Được chọn khi tạo token và dùng làm nhóm tính phí mặc định cho các lệnh gọi API.", "Selected when creating a token and used as the default billing group for API calls.": "Được chọn khi tạo token và dùng làm nhóm tính phí mặc định cho các lệnh gọi API.",
"Self-Use Mode": "Chế độ tự sử dụng", "Self-Use Mode": "Chế độ tự sử dụng",
"Send": "Gửi", "Send": "Gửi",
...@@ -4582,6 +4589,7 @@ ...@@ -4582,6 +4589,7 @@
"Value": "Giá trị", "Value": "Giá trị",
"Value (supports JSON or plain text)": "Giá trị (hỗ trợ JSON hoặc văn bản thuần)", "Value (supports JSON or plain text)": "Giá trị (hỗ trợ JSON hoặc văn bản thuần)",
"Value is required": "Giá trị là bắt buộc", "Value is required": "Giá trị là bắt buộc",
"Value metric": "Chỉ số giá trị",
"Value must be at least 0": "Giá trị phải ít nhất là 0", "Value must be at least 0": "Giá trị phải ít nhất là 0",
"Value Regex": "Regex giá trị", "Value Regex": "Regex giá trị",
"variable": "biến", "variable": "biến",
......
...@@ -271,6 +271,7 @@ ...@@ -271,6 +271,7 @@
"All Models": "所有模型", "All Models": "所有模型",
"All models in use are properly configured.": "所有正在使用的模型都已正确配置。", "All models in use are properly configured.": "所有正在使用的模型都已正确配置。",
"All Must Match (AND)": "全部满足(AND)", "All Must Match (AND)": "全部满足(AND)",
"All nodes": "全部节点",
"All requests must include": "所有请求必须携带", "All requests must include": "所有请求必须携带",
"All Status": "所有状态", "All Status": "所有状态",
"All Sync Status": "所有同步状态", "All Sync Status": "所有同步状态",
...@@ -780,6 +781,7 @@ ...@@ -780,6 +781,7 @@
"Clear filters": "清除筛选器", "Clear filters": "清除筛选器",
"Clear Mapping": "清除映射", "Clear Mapping": "清除映射",
"Clear mode flags in prompts": "在提示中清除模式标志", "Clear mode flags in prompts": "在提示中清除模式标志",
"Clear node filters": "清空节点筛选",
"Clear search": "清除搜索", "Clear search": "清除搜索",
"Clear selection": "清除选择", "Clear selection": "清除选择",
"Clear selection (Escape)": "清除选择 (Escape)", "Clear selection (Escape)": "清除选择 (Escape)",
...@@ -1842,6 +1844,7 @@ ...@@ -1842,6 +1844,7 @@
"Filter by name or ID...": "按名称或 ID 筛选...", "Filter by name or ID...": "按名称或 ID 筛选...",
"Filter by name, ID, or key...": "按名称、ID 或密钥筛选...", "Filter by name, ID, or key...": "按名称、ID 或密钥筛选...",
"Filter by name...": "按名称筛选...", "Filter by name...": "按名称筛选...",
"Filter by node": "按节点筛选",
"Filter by price field": "按价格字段筛选", "Filter by price field": "按价格字段筛选",
"Filter by ratio type": "按倍率类型筛选", "Filter by ratio type": "按倍率类型筛选",
"Filter by request ID": "按请求 ID 筛选", "Filter by request ID": "按请求 ID 筛选",
...@@ -2431,6 +2434,7 @@ ...@@ -2431,6 +2434,7 @@
"Memory Threshold (%)": "内存阈值 (%)", "Memory Threshold (%)": "内存阈值 (%)",
"Merchant ID": "商户 ID", "Merchant ID": "商户 ID",
"Merchant ID is required": "商户 ID 为必填项", "Merchant ID is required": "商户 ID 为必填项",
"Merge into Other": "合并为其他",
"Message Priority": "消息优先级", "Message Priority": "消息优先级",
"Metadata": "元信息", "Metadata": "元信息",
"min downtime": "分钟停机", "min downtime": "分钟停机",
...@@ -2557,7 +2561,6 @@ ...@@ -2557,7 +2561,6 @@
"More than 999 days left": "剩余超过 999 天", "More than 999 days left": "剩余超过 999 天",
"More...": "更多...", "More...": "更多...",
"Most-used models in the selected period and category": "所选时间范围与分类下使用率最高的模型", "Most-used models in the selected period and category": "所选时间范围与分类下使用率最高的模型",
"Merge into Other": "合并为其他",
"Move": "移动", "Move": "移动",
"Move a request header": "移动请求头", "Move a request header": "移动请求头",
"Move affiliate rewards to your main balance": "将推广奖励转移到您的主余额", "Move affiliate rewards to your main balance": "将推广奖励转移到您的主余额",
...@@ -2733,6 +2736,7 @@ ...@@ -2733,6 +2736,7 @@
"No models to remove": "无待删除模型", "No models to remove": "无待删除模型",
"No new models to add": "没有新模型可添加", "No new models to add": "没有新模型可添加",
"No new models yet": "暂无新模型", "No new models yet": "暂无新模型",
"No nodes": "无节点",
"No notable climbers right now": "当前没有显著上升的模型", "No notable climbers right now": "当前没有显著上升的模型",
"No notable drops right now": "当前没有显著下降的模型", "No notable drops right now": "当前没有显著下降的模型",
"No parameter overrides configured.": "未配置参数覆盖。", "No parameter overrides configured.": "未配置参数覆盖。",
...@@ -2791,6 +2795,7 @@ ...@@ -2791,6 +2795,7 @@
"No vendor data available": "暂无厂商数据", "No vendor data available": "暂无厂商数据",
"No X Found": "未找到 X", "No X Found": "未找到 X",
"Node": "节点", "Node": "节点",
"Node filters": "节点筛选",
"Node Name": "节点名称", "Node Name": "节点名称",
"Non-stream": "非流式", "Non-stream": "非流式",
"Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.": "非零邀请奖励需要先在支付网关设置中确认合规条款。", "Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.": "非零邀请奖励需要先在支付网关设置中确认合规条款。",
...@@ -2958,8 +2963,8 @@ ...@@ -2958,8 +2963,8 @@
"Output tokens": "输出 token", "Output tokens": "输出 token",
"Output Tokens": "输出 Token", "Output Tokens": "输出 Token",
"Overage limited": "超额受限", "Overage limited": "超额受限",
"Overflow items": "超出项",
"overall": "总体", "overall": "总体",
"Overflow items": "超出项",
"Overnight range": "跨日范围", "Overnight range": "跨日范围",
"override": "覆盖", "override": "覆盖",
"Override": "覆盖", "Override": "覆盖",
...@@ -3460,6 +3465,7 @@ ...@@ -3460,6 +3465,7 @@
"Remove functionResponse.id field": "移除 functionResponse.id 字段", "Remove functionResponse.id field": "移除 functionResponse.id 字段",
"Remove mapped targets": "移除映射目标", "Remove mapped targets": "移除映射目标",
"Remove Models": "删除模型", "Remove Models": "删除模型",
"Remove node filter": "移除节点筛选",
"Remove Passkey": "解绑 Passkey", "Remove Passkey": "解绑 Passkey",
"Remove Passkey?": "移除通行密钥?", "Remove Passkey?": "移除通行密钥?",
"Remove rule group": "移除规则组", "Remove rule group": "移除规则组",
...@@ -3804,6 +3810,7 @@ ...@@ -3804,6 +3810,7 @@
"Selected {{count}}": "已选 {{count}} 个", "Selected {{count}}": "已选 {{count}} 个",
"selected channel(s). Leave empty to remove tag.": "选定的渠道。留空以移除标签。", "selected channel(s). Leave empty to remove tag.": "选定的渠道。留空以移除标签。",
"Selected conflicts were overwritten successfully.": "选中的冲突已成功覆盖。", "Selected conflicts were overwritten successfully.": "选中的冲突已成功覆盖。",
"Selected nodes": "已选节点",
"Selected when creating a token and used as the default billing group for API calls.": "创建令牌时选择,用作 API 调用的默认计费分组。", "Selected when creating a token and used as the default billing group for API calls.": "创建令牌时选择,用作 API 调用的默认计费分组。",
"Self-Use Mode": "自用模式", "Self-Use Mode": "自用模式",
"Send": "发送", "Send": "发送",
...@@ -4582,6 +4589,7 @@ ...@@ -4582,6 +4589,7 @@
"Value": "值", "Value": "值",
"Value (supports JSON or plain text)": "值(支持 JSON 或普通文本)", "Value (supports JSON or plain text)": "值(支持 JSON 或普通文本)",
"Value is required": "值为必填项", "Value is required": "值为必填项",
"Value metric": "数值口径",
"Value must be at least 0": "值必须至少为 0", "Value must be at least 0": "值必须至少为 0",
"Value Regex": "Value 正则", "Value Regex": "Value 正则",
"variable": "变量", "variable": "变量",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment