mirror of
https://github.com/langgenius/dify.git
synced 2026-08-28 20:03:22 +08:00
feat: improve ai-credits display (#38589)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
5af8f6af4d
commit
85cc183501
@ -88,6 +88,7 @@ class TenantInfoResponse(ResponseModel):
|
|||||||
custom_config: WorkspaceCustomConfigResponse | None = None
|
custom_config: WorkspaceCustomConfigResponse | None = None
|
||||||
trial_credits: int | None = None
|
trial_credits: int | None = None
|
||||||
trial_credits_used: int | None = None
|
trial_credits_used: int | None = None
|
||||||
|
trial_credits_exhausted_at: int | None = None
|
||||||
next_credit_reset_date: int | None = None
|
next_credit_reset_date: int | None = None
|
||||||
|
|
||||||
@field_validator("plan", "status", "trial_end_reason", mode="before")
|
@field_validator("plan", "status", "trial_end_reason", mode="before")
|
||||||
|
|||||||
@ -22008,6 +22008,7 @@ Tag type
|
|||||||
| role | string | | No |
|
| role | string | | No |
|
||||||
| status | string | | No |
|
| status | string | | No |
|
||||||
| trial_credits | integer | | No |
|
| trial_credits | integer | | No |
|
||||||
|
| trial_credits_exhausted_at | integer | | No |
|
||||||
| trial_credits_used | integer | | No |
|
| trial_credits_used | integer | | No |
|
||||||
| trial_end_reason | string | | No |
|
| trial_end_reason | string | | No |
|
||||||
|
|
||||||
|
|||||||
@ -55,6 +55,7 @@ class QuotaBalanceResult(TypedDict):
|
|||||||
reserved: int
|
reserved: int
|
||||||
quota: int
|
quota: int
|
||||||
usage: int
|
usage: int
|
||||||
|
exhausted_at: NotRequired[int]
|
||||||
|
|
||||||
|
|
||||||
class QuotaConsumeCappedResult(TypedDict):
|
class QuotaConsumeCappedResult(TypedDict):
|
||||||
|
|||||||
@ -32,6 +32,7 @@ class CreditPoolBalance:
|
|||||||
pool_type: str
|
pool_type: str
|
||||||
quota_limit: int
|
quota_limit: int
|
||||||
quota_used: int
|
quota_used: int
|
||||||
|
exhausted_at: int | None = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def remaining_credits(self) -> int:
|
def remaining_credits(self) -> int:
|
||||||
@ -133,6 +134,7 @@ class CreditPoolService:
|
|||||||
pool_type=normalized_pool_type,
|
pool_type=normalized_pool_type,
|
||||||
quota_limit=balance["quota"],
|
quota_limit=balance["quota"],
|
||||||
quota_used=balance["usage"],
|
quota_used=balance["usage"],
|
||||||
|
exhausted_at=balance.get("exhausted_at"),
|
||||||
)
|
)
|
||||||
|
|
||||||
session = cls._require_session(session)
|
session = cls._require_session(session)
|
||||||
|
|||||||
@ -9,6 +9,15 @@ from services.account_service import TenantService
|
|||||||
from services.feature_service import FeatureService
|
from services.feature_service import FeatureService
|
||||||
|
|
||||||
|
|
||||||
|
def _set_credit_pool_info(
|
||||||
|
tenant_info: dict[str, object], *, quota_limit: int, quota_used: int, exhausted_at: int | None = None
|
||||||
|
) -> None:
|
||||||
|
tenant_info["trial_credits"] = quota_limit
|
||||||
|
tenant_info["trial_credits_used"] = quota_used
|
||||||
|
if isinstance(exhausted_at, int) and exhausted_at > 0 and quota_limit > 0 and quota_used >= quota_limit:
|
||||||
|
tenant_info["trial_credits_exhausted_at"] = exhausted_at
|
||||||
|
|
||||||
|
|
||||||
class WorkspaceService:
|
class WorkspaceService:
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_tenant_info(cls, tenant: Tenant, session: Session):
|
def get_tenant_info(cls, tenant: Tenant, session: Session):
|
||||||
@ -54,7 +63,7 @@ class WorkspaceService:
|
|||||||
if dify_config.EDITION == "CLOUD":
|
if dify_config.EDITION == "CLOUD":
|
||||||
tenant_info["next_credit_reset_date"] = feature.next_credit_reset_date
|
tenant_info["next_credit_reset_date"] = feature.next_credit_reset_date
|
||||||
|
|
||||||
from services.credit_pool_service import CreditPoolService
|
from services.credit_pool_service import CreditPoolBalance, CreditPoolService
|
||||||
|
|
||||||
paid_pool = CreditPoolService.get_pool(tenant_id=tenant.id, pool_type="paid", session=session)
|
paid_pool = CreditPoolService.get_pool(tenant_id=tenant.id, pool_type="paid", session=session)
|
||||||
# if the tenant is not on the sandbox plan and the paid pool is not full, use the paid pool
|
# if the tenant is not on the sandbox plan and the paid pool is not full, use the paid pool
|
||||||
@ -63,12 +72,22 @@ class WorkspaceService:
|
|||||||
and paid_pool is not None
|
and paid_pool is not None
|
||||||
and (paid_pool.quota_limit == -1 or paid_pool.quota_limit > paid_pool.quota_used)
|
and (paid_pool.quota_limit == -1 or paid_pool.quota_limit > paid_pool.quota_used)
|
||||||
):
|
):
|
||||||
tenant_info["trial_credits"] = paid_pool.quota_limit
|
exhausted_at = paid_pool.exhausted_at if isinstance(paid_pool, CreditPoolBalance) else None
|
||||||
tenant_info["trial_credits_used"] = paid_pool.quota_used
|
_set_credit_pool_info(
|
||||||
|
tenant_info,
|
||||||
|
quota_limit=paid_pool.quota_limit,
|
||||||
|
quota_used=paid_pool.quota_used,
|
||||||
|
exhausted_at=exhausted_at,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
trial_pool = CreditPoolService.get_pool(tenant_id=tenant.id, pool_type="trial", session=session)
|
trial_pool = CreditPoolService.get_pool(tenant_id=tenant.id, pool_type="trial", session=session)
|
||||||
if trial_pool:
|
if trial_pool:
|
||||||
tenant_info["trial_credits"] = trial_pool.quota_limit
|
exhausted_at = trial_pool.exhausted_at if isinstance(trial_pool, CreditPoolBalance) else None
|
||||||
tenant_info["trial_credits_used"] = trial_pool.quota_used
|
_set_credit_pool_info(
|
||||||
|
tenant_info,
|
||||||
|
quota_limit=trial_pool.quota_limit,
|
||||||
|
quota_used=trial_pool.quota_used,
|
||||||
|
exhausted_at=exhausted_at,
|
||||||
|
)
|
||||||
|
|
||||||
return tenant_info
|
return tenant_info
|
||||||
|
|||||||
@ -7,6 +7,7 @@ from faker import Faker
|
|||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from models import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
from models import Account, Tenant, TenantAccountJoin, TenantAccountRole
|
||||||
|
from services.credit_pool_service import CreditPoolBalance
|
||||||
from services.workspace_service import WorkspaceService
|
from services.workspace_service import WorkspaceService
|
||||||
|
|
||||||
|
|
||||||
@ -720,7 +721,13 @@ class TestWorkspaceService:
|
|||||||
mock_external_service_dependencies["tenant_service"].has_roles.return_value = False
|
mock_external_service_dependencies["tenant_service"].has_roles.return_value = False
|
||||||
|
|
||||||
paid_pool = MagicMock(quota_limit=500, quota_used=500)
|
paid_pool = MagicMock(quota_limit=500, quota_used=500)
|
||||||
trial_pool = MagicMock(quota_limit=100, quota_used=10)
|
trial_pool = CreditPoolBalance(
|
||||||
|
tenant_id=tenant.id,
|
||||||
|
pool_type="trial",
|
||||||
|
quota_limit=100,
|
||||||
|
quota_used=100,
|
||||||
|
exhausted_at=1748908800,
|
||||||
|
)
|
||||||
|
|
||||||
with (
|
with (
|
||||||
patch("services.workspace_service.current_user", account),
|
patch("services.workspace_service.current_user", account),
|
||||||
@ -730,7 +737,8 @@ class TestWorkspaceService:
|
|||||||
|
|
||||||
assert result is not None
|
assert result is not None
|
||||||
assert result["trial_credits"] == 100
|
assert result["trial_credits"] == 100
|
||||||
assert result["trial_credits_used"] == 10
|
assert result["trial_credits_used"] == 100
|
||||||
|
assert result["trial_credits_exhausted_at"] == 1748908800
|
||||||
|
|
||||||
def test_get_tenant_info_cloud_fall_back_to_trial_when_paid_none(
|
def test_get_tenant_info_cloud_fall_back_to_trial_when_paid_none(
|
||||||
self, db_session_with_containers: Session, mock_external_service_dependencies
|
self, db_session_with_containers: Session, mock_external_service_dependencies
|
||||||
|
|||||||
@ -465,11 +465,17 @@ class TestBillingServiceSubscriptionInfo:
|
|||||||
def test_quota_get_balance_uses_quota_request(self):
|
def test_quota_get_balance_uses_quota_request(self):
|
||||||
tenant_id = "tenant-123"
|
tenant_id = "tenant-123"
|
||||||
with patch.object(BillingService, "_send_quota_request") as mock_send_quota_request:
|
with patch.object(BillingService, "_send_quota_request") as mock_send_quota_request:
|
||||||
mock_send_quota_request.return_value = {"quota": "200", "usage": "6", "available": "194", "reserved": "0"}
|
mock_send_quota_request.return_value = {
|
||||||
|
"quota": "200",
|
||||||
|
"usage": "6",
|
||||||
|
"available": "194",
|
||||||
|
"reserved": "0",
|
||||||
|
"exhausted_at": "1748908800",
|
||||||
|
}
|
||||||
|
|
||||||
result = BillingService.quota_get_balance(tenant_id, "credit_pool", bucket="trial")
|
result = BillingService.quota_get_balance(tenant_id, "credit_pool", bucket="trial")
|
||||||
|
|
||||||
assert result == {"quota": 200, "usage": 6, "available": 194, "reserved": 0}
|
assert result == {"quota": 200, "usage": 6, "available": 194, "reserved": 0, "exhausted_at": 1748908800}
|
||||||
mock_send_quota_request.assert_called_once_with(
|
mock_send_quota_request.assert_called_once_with(
|
||||||
"GET",
|
"GET",
|
||||||
"/quota/balance",
|
"/quota/balance",
|
||||||
|
|||||||
@ -265,13 +265,20 @@ def test_get_pool_uses_billing_quota_balance_when_enabled() -> None:
|
|||||||
patch("services.credit_pool_service.dify_config.BILLING_ENABLED", True),
|
patch("services.credit_pool_service.dify_config.BILLING_ENABLED", True),
|
||||||
patch("services.billing_service.BillingService.quota_get_balance") as quota_get_balance,
|
patch("services.billing_service.BillingService.quota_get_balance") as quota_get_balance,
|
||||||
):
|
):
|
||||||
quota_get_balance.return_value = {"quota": 1000, "usage": 250, "available": 750, "reserved": 0}
|
quota_get_balance.return_value = {
|
||||||
|
"quota": 1000,
|
||||||
|
"usage": 250,
|
||||||
|
"available": 750,
|
||||||
|
"reserved": 0,
|
||||||
|
"exhausted_at": 1748908800,
|
||||||
|
}
|
||||||
|
|
||||||
pool = CreditPoolService.get_pool(tenant_id=tenant_id, pool_type=ProviderQuotaType.PAID)
|
pool = CreditPoolService.get_pool(tenant_id=tenant_id, pool_type=ProviderQuotaType.PAID)
|
||||||
|
|
||||||
assert isinstance(pool, CreditPoolBalance)
|
assert isinstance(pool, CreditPoolBalance)
|
||||||
assert pool.quota_limit == 1000
|
assert pool.quota_limit == 1000
|
||||||
assert pool.quota_used == 250
|
assert pool.quota_used == 250
|
||||||
|
assert pool.exhausted_at == 1748908800
|
||||||
assert pool.remaining_credits == 750
|
assert pool.remaining_credits == 750
|
||||||
quota_get_balance.assert_called_once_with(
|
quota_get_balance.assert_called_once_with(
|
||||||
tenant_id=tenant_id,
|
tenant_id=tenant_id,
|
||||||
|
|||||||
@ -3388,14 +3388,6 @@
|
|||||||
"count": 3
|
"count": 3
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"web/app/components/header/account-setting/model-provider-page/provider-added-card/quota-panel.tsx": {
|
|
||||||
"jsx_a11y/click-events-have-key-events": {
|
|
||||||
"count": 1
|
|
||||||
},
|
|
||||||
"jsx_a11y/no-static-element-interactions": {
|
|
||||||
"count": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"web/app/components/header/account-setting/model-provider-page/utils.ts": {
|
"web/app/components/header/account-setting/model-provider-page/utils.ts": {
|
||||||
"no-barrel-files/no-barrel-files": {
|
"no-barrel-files/no-barrel-files": {
|
||||||
"count": 2
|
"count": 2
|
||||||
|
|||||||
@ -15,6 +15,7 @@ export type TenantInfoResponse = {
|
|||||||
role?: string | null
|
role?: string | null
|
||||||
status?: string | null
|
status?: string | null
|
||||||
trial_credits?: number | null
|
trial_credits?: number | null
|
||||||
|
trial_credits_exhausted_at?: number | null
|
||||||
trial_credits_used?: number | null
|
trial_credits_used?: number | null
|
||||||
trial_end_reason?: string | null
|
trial_end_reason?: string | null
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,6 +24,7 @@ export const zTenantInfoResponse = z.object({
|
|||||||
role: z.string().nullish(),
|
role: z.string().nullish(),
|
||||||
status: z.string().nullish(),
|
status: z.string().nullish(),
|
||||||
trial_credits: z.int().nullish(),
|
trial_credits: z.int().nullish(),
|
||||||
|
trial_credits_exhausted_at: z.int().nullish(),
|
||||||
trial_credits_used: z.int().nullish(),
|
trial_credits_used: z.int().nullish(),
|
||||||
trial_end_reason: z.string().nullish(),
|
trial_end_reason: z.string().nullish(),
|
||||||
})
|
})
|
||||||
|
|||||||
@ -19,6 +19,7 @@ export type TenantInfoResponse = {
|
|||||||
role?: string | null
|
role?: string | null
|
||||||
status?: string | null
|
status?: string | null
|
||||||
trial_credits?: number | null
|
trial_credits?: number | null
|
||||||
|
trial_credits_exhausted_at?: number | null
|
||||||
trial_credits_used?: number | null
|
trial_credits_used?: number | null
|
||||||
trial_end_reason?: string | null
|
trial_end_reason?: string | null
|
||||||
}
|
}
|
||||||
|
|||||||
@ -633,6 +633,7 @@ export const zTenantInfoResponse = z.object({
|
|||||||
role: z.string().nullish(),
|
role: z.string().nullish(),
|
||||||
status: z.string().nullish(),
|
status: z.string().nullish(),
|
||||||
trial_credits: z.int().nullish(),
|
trial_credits: z.int().nullish(),
|
||||||
|
trial_credits_exhausted_at: z.int().nullish(),
|
||||||
trial_credits_used: z.int().nullish(),
|
trial_credits_used: z.int().nullish(),
|
||||||
trial_end_reason: z.string().nullish(),
|
trial_end_reason: z.string().nullish(),
|
||||||
})
|
})
|
||||||
|
|||||||
@ -79,6 +79,7 @@ const defaultCurrentWorkspace = {
|
|||||||
providers: [],
|
providers: [],
|
||||||
trial_credits: 0,
|
trial_credits: 0,
|
||||||
trial_credits_used: 0,
|
trial_credits_used: 0,
|
||||||
|
trial_credits_exhausted_at: 0,
|
||||||
next_credit_reset_date: 0,
|
next_credit_reset_date: 0,
|
||||||
} satisfies ICurrentWorkspace
|
} satisfies ICurrentWorkspace
|
||||||
|
|
||||||
|
|||||||
@ -116,6 +116,7 @@ const buildAppContext = (
|
|||||||
providers: [],
|
providers: [],
|
||||||
trial_credits: 200,
|
trial_credits: 200,
|
||||||
trial_credits_used: 0,
|
trial_credits_used: 0,
|
||||||
|
trial_credits_exhausted_at: 0,
|
||||||
next_credit_reset_date: 0,
|
next_credit_reset_date: 0,
|
||||||
}
|
}
|
||||||
const langGeniusVersionInfo: LangGeniusVersionInfo = {
|
const langGeniusVersionInfo: LangGeniusVersionInfo = {
|
||||||
|
|||||||
@ -8,6 +8,7 @@ let mockWorkspaceData:
|
|||||||
| {
|
| {
|
||||||
trial_credits: number
|
trial_credits: number
|
||||||
trial_credits_used: number
|
trial_credits_used: number
|
||||||
|
trial_credits_exhausted_at?: number
|
||||||
next_credit_reset_date: number
|
next_credit_reset_date: number
|
||||||
}
|
}
|
||||||
| undefined = {
|
| undefined = {
|
||||||
@ -38,13 +39,18 @@ vi.mock('@/app/components/base/icons/src/public/llm', () => {
|
|||||||
|
|
||||||
vi.mock('../use-trial-credits', () => ({
|
vi.mock('../use-trial-credits', () => ({
|
||||||
useTrialCredits: () => {
|
useTrialCredits: () => {
|
||||||
const totalCredits = mockWorkspaceData?.trial_credits ?? 0
|
const totalCredits = Math.max(mockWorkspaceData?.trial_credits ?? 0, 0)
|
||||||
const credits = Math.max(totalCredits - (mockWorkspaceData?.trial_credits_used ?? 0), 0)
|
const rawUsedCredits = mockWorkspaceData?.trial_credits_used ?? 0
|
||||||
|
const normalizedUsedCredits = Math.max(rawUsedCredits, 0)
|
||||||
|
const usedCredits = Math.min(normalizedUsedCredits, totalCredits)
|
||||||
|
const credits = Math.max(totalCredits - usedCredits, 0)
|
||||||
return {
|
return {
|
||||||
credits,
|
credits,
|
||||||
|
usedCredits,
|
||||||
totalCredits,
|
totalCredits,
|
||||||
isExhausted: credits <= 0,
|
isExhausted: credits <= 0,
|
||||||
isLoading: mockWorkspaceIsPending && !mockWorkspaceData,
|
isLoading: mockWorkspaceIsPending && !mockWorkspaceData,
|
||||||
|
exhaustedAt: mockWorkspaceData?.trial_credits_exhausted_at,
|
||||||
nextCreditResetDate: mockWorkspaceData?.next_credit_reset_date,
|
nextCreditResetDate: mockWorkspaceData?.next_credit_reset_date,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -74,7 +80,8 @@ vi.mock(
|
|||||||
|
|
||||||
vi.mock('@/hooks/use-timestamp', () => ({
|
vi.mock('@/hooks/use-timestamp', () => ({
|
||||||
default: () => ({
|
default: () => ({
|
||||||
formatTime: () => '2024-12-31',
|
formatTime: () => 'Dec 31',
|
||||||
|
formatMonthDay: () => 'Dec 31',
|
||||||
}),
|
}),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@ -118,11 +125,16 @@ describe('QuotaPanel', () => {
|
|||||||
expect(screen.getByRole('status')).toBeInTheDocument()
|
expect(screen.getByRole('status')).toBeInTheDocument()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should show remaining credits and reset date', () => {
|
it('should show used credits, total credits, and reset date', () => {
|
||||||
renderQuotaPanel(<QuotaPanel providers={mockProviders} />)
|
renderQuotaPanel(<QuotaPanel providers={mockProviders} />)
|
||||||
|
|
||||||
expect(screen.getByText(/modelProvider\.quota/)).toBeInTheDocument()
|
expect(screen.getByText(/modelProvider\.quota/)).toBeInTheDocument()
|
||||||
expect(screen.getByText('70')).toBeInTheDocument()
|
expect(screen.getByText('30')).toBeInTheDocument()
|
||||||
|
expect(screen.getByText('/')).toHaveClass('font-normal', 'text-text-tertiary')
|
||||||
|
expect(screen.getByText('/')).not.toHaveClass('system-xl-semibold')
|
||||||
|
expect(screen.getByText('100')).toBeInTheDocument()
|
||||||
|
expect(screen.getByText(/modelProvider\.used/)).toBeInTheDocument()
|
||||||
|
expect(screen.queryByText(/modelProvider\.ranOutDate/)).not.toBeInTheDocument()
|
||||||
expect(screen.getByText(/modelProvider\.resetDate/)).toBeInTheDocument()
|
expect(screen.getByText(/modelProvider\.resetDate/)).toBeInTheDocument()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -132,19 +144,26 @@ describe('QuotaPanel', () => {
|
|||||||
renderQuotaPanel(<QuotaPanel providers={mockProviders} />)
|
renderQuotaPanel(<QuotaPanel providers={mockProviders} />)
|
||||||
|
|
||||||
expect(screen.queryByRole('status')).not.toBeInTheDocument()
|
expect(screen.queryByRole('status')).not.toBeInTheDocument()
|
||||||
expect(screen.getByText('70')).toBeInTheDocument()
|
expect(screen.getByText('30')).toBeInTheDocument()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should floor credits at zero when usage is higher than quota', () => {
|
it('should keep usage display within quota when usage is higher than quota', () => {
|
||||||
mockWorkspaceData = {
|
mockWorkspaceData = {
|
||||||
trial_credits: 10,
|
trial_credits: 10,
|
||||||
trial_credits_used: 999,
|
trial_credits_used: 999,
|
||||||
|
trial_credits_exhausted_at: 1733011200,
|
||||||
next_credit_reset_date: 0,
|
next_credit_reset_date: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
renderQuotaPanel(<QuotaPanel providers={mockProviders} />)
|
renderQuotaPanel(<QuotaPanel providers={mockProviders} />)
|
||||||
|
|
||||||
expect(screen.getByText(/modelProvider\.card\.quotaExhausted/)).toBeInTheDocument()
|
const usageNumbers = screen.getAllByText('10')
|
||||||
|
expect(usageNumbers).toHaveLength(2)
|
||||||
|
usageNumbers.forEach((number) => expect(number).toHaveClass('text-text-destructive'))
|
||||||
|
expect(screen.getByText(/modelProvider\.used/)).toHaveClass('text-text-destructive')
|
||||||
|
expect(screen.getByText(/modelProvider\.ranOutDate/)).toBeInTheDocument()
|
||||||
|
expect(screen.getByText('/')).toHaveClass('font-normal', 'text-text-tertiary')
|
||||||
|
expect(screen.getByText('/')).not.toHaveClass('system-xl-semibold', 'text-text-destructive')
|
||||||
expect(screen.queryByText(/modelProvider\.resetDate/)).not.toBeInTheDocument()
|
expect(screen.queryByText(/modelProvider\.resetDate/)).not.toBeInTheDocument()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -30,6 +30,7 @@ describe('useTrialCredits', () => {
|
|||||||
| {
|
| {
|
||||||
trial_credits?: number
|
trial_credits?: number
|
||||||
trial_credits_used?: number
|
trial_credits_used?: number
|
||||||
|
trial_credits_exhausted_at?: number
|
||||||
next_credit_reset_date?: number
|
next_credit_reset_date?: number
|
||||||
}
|
}
|
||||||
| undefined,
|
| undefined,
|
||||||
@ -46,6 +47,7 @@ describe('useTrialCredits', () => {
|
|||||||
mockTrialCreditsQuery({
|
mockTrialCreditsQuery({
|
||||||
trial_credits: 100,
|
trial_credits: 100,
|
||||||
trial_credits_used: 40,
|
trial_credits_used: 40,
|
||||||
|
trial_credits_exhausted_at: undefined,
|
||||||
next_credit_reset_date: 1775001600,
|
next_credit_reset_date: 1775001600,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -56,9 +58,11 @@ describe('useTrialCredits', () => {
|
|||||||
|
|
||||||
expect(result.current).toEqual({
|
expect(result.current).toEqual({
|
||||||
credits: 60,
|
credits: 60,
|
||||||
|
usedCredits: 40,
|
||||||
totalCredits: 100,
|
totalCredits: 100,
|
||||||
isExhausted: false,
|
isExhausted: false,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
|
exhaustedAt: undefined,
|
||||||
nextCreditResetDate: 1775001600,
|
nextCreditResetDate: 1775001600,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -77,6 +81,7 @@ describe('useTrialCredits', () => {
|
|||||||
|
|
||||||
expect(result.current.isLoading).toBe(false)
|
expect(result.current.isLoading).toBe(false)
|
||||||
expect(result.current.credits).toBe(60)
|
expect(result.current.credits).toBe(60)
|
||||||
|
expect(result.current.usedCredits).toBe(20)
|
||||||
expect(result.current.isExhausted).toBe(false)
|
expect(result.current.isExhausted).toBe(false)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -89,9 +94,11 @@ describe('useTrialCredits', () => {
|
|||||||
|
|
||||||
expect(result.current).toEqual({
|
expect(result.current).toEqual({
|
||||||
credits: 0,
|
credits: 0,
|
||||||
|
usedCredits: 0,
|
||||||
totalCredits: 0,
|
totalCredits: 0,
|
||||||
isExhausted: true,
|
isExhausted: true,
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
|
exhaustedAt: undefined,
|
||||||
nextCreditResetDate: undefined,
|
nextCreditResetDate: undefined,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -100,13 +107,16 @@ describe('useTrialCredits', () => {
|
|||||||
mockTrialCreditsQuery({
|
mockTrialCreditsQuery({
|
||||||
trial_credits: 10,
|
trial_credits: 10,
|
||||||
trial_credits_used: 99,
|
trial_credits_used: 99,
|
||||||
|
trial_credits_exhausted_at: 1772323200,
|
||||||
next_credit_reset_date: undefined,
|
next_credit_reset_date: undefined,
|
||||||
})
|
})
|
||||||
|
|
||||||
const { result } = renderHook(() => useTrialCredits())
|
const { result } = renderHook(() => useTrialCredits())
|
||||||
|
|
||||||
expect(result.current.credits).toBe(0)
|
expect(result.current.credits).toBe(0)
|
||||||
|
expect(result.current.usedCredits).toBe(10)
|
||||||
expect(result.current.isExhausted).toBe(true)
|
expect(result.current.isExhausted).toBe(true)
|
||||||
|
expect(result.current.exhaustedAt).toBe(1772323200)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -14,6 +14,7 @@ const baseWorkspace: ICurrentWorkspace = {
|
|||||||
providers: [],
|
providers: [],
|
||||||
trial_credits: 200,
|
trial_credits: 200,
|
||||||
trial_credits_used: 200,
|
trial_credits_used: 200,
|
||||||
|
trial_credits_exhausted_at: 0,
|
||||||
next_credit_reset_date: Date.now() + 86400000,
|
next_credit_reset_date: Date.now() + 86400000,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -73,7 +73,8 @@ type QuotaPanelProps = {
|
|||||||
}
|
}
|
||||||
const QuotaPanel: FC<QuotaPanelProps> = ({ providers }) => {
|
const QuotaPanel: FC<QuotaPanelProps> = ({ providers }) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { credits, isExhausted, isLoading, nextCreditResetDate } = useTrialCredits()
|
const { usedCredits, totalCredits, isExhausted, isLoading, exhaustedAt, nextCreditResetDate } =
|
||||||
|
useTrialCredits()
|
||||||
const { data: trialModels = [] } = useQuery(
|
const { data: trialModels = [] } = useQuery(
|
||||||
consoleQuery.trialModels.get.queryOptions({
|
consoleQuery.trialModels.get.queryOptions({
|
||||||
enabled: IS_CLOUD_EDITION,
|
enabled: IS_CLOUD_EDITION,
|
||||||
@ -88,7 +89,7 @@ const QuotaPanel: FC<QuotaPanelProps> = ({ providers }) => {
|
|||||||
() => new Map(providers.map((p) => [p.provider, p.custom_configuration.available_credentials])),
|
() => new Map(providers.map((p) => [p.provider, p.custom_configuration.available_credentials])),
|
||||||
[providers],
|
[providers],
|
||||||
)
|
)
|
||||||
const { formatTime } = useTimestamp()
|
const { formatMonthDay } = useTimestamp()
|
||||||
const { plugins: allPlugins } = useMarketplaceAllPlugins(providers, '')
|
const { plugins: allPlugins } = useMarketplaceAllPlugins(providers, '')
|
||||||
const [selectedPlugin, setSelectedPlugin] = useState<Plugin | null>(null)
|
const [selectedPlugin, setSelectedPlugin] = useState<Plugin | null>(null)
|
||||||
const [
|
const [
|
||||||
@ -141,6 +142,8 @@ const QuotaPanel: FC<QuotaPanelProps> = ({ providers }) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const creditUsageTextClassName = isExhausted ? 'text-text-destructive' : 'text-text-secondary'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
@ -156,32 +159,48 @@ const QuotaPanel: FC<QuotaPanelProps> = ({ providers }) => {
|
|||||||
{t(($) => $['modelProvider.quotaLabel'], { ns: 'common' })}
|
{t(($) => $['modelProvider.quotaLabel'], { ns: 'common' })}
|
||||||
<QuotaInfotip tipText={tipText} />
|
<QuotaInfotip tipText={tipText} />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex h-6 items-center justify-between">
|
<div className="flex h-6 items-center justify-between gap-3">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex min-w-0 items-center gap-1.5">
|
||||||
{credits > 0 ? (
|
<div className="flex shrink-0 items-baseline gap-1">
|
||||||
<span className="mr-0.5 system-xl-semibold text-text-secondary">
|
<span className={cn('system-xl-semibold', creditUsageTextClassName)}>
|
||||||
{formatNumber(credits)}
|
{formatNumber(usedCredits)}
|
||||||
</span>
|
</span>
|
||||||
) : (
|
<span className="text-base leading-6 font-normal text-text-tertiary">/</span>
|
||||||
<span className="mr-0.5 system-xl-semibold text-text-destructive">
|
<span className={cn('system-xl-semibold', creditUsageTextClassName)}>
|
||||||
{t(($) => $['modelProvider.card.quotaExhausted'], { ns: 'common' })}
|
{formatNumber(totalCredits)}
|
||||||
|
</span>
|
||||||
|
<span className={cn('system-md-medium', creditUsageTextClassName)}>
|
||||||
|
{t(($) => $['modelProvider.used'], { ns: 'common' })}
|
||||||
</span>
|
</span>
|
||||||
)}
|
|
||||||
<div className="flex h-[18px] items-start gap-1 pt-0.5 system-xs-regular text-text-tertiary">
|
|
||||||
<span>{t(($) => $['modelProvider.credits'], { ns: 'common' })}</span>
|
|
||||||
{nextCreditResetDate ? (
|
|
||||||
<>
|
|
||||||
<span className="text-text-quaternary">·</span>
|
|
||||||
<span>
|
|
||||||
{t(($) => $['modelProvider.resetDate'], {
|
|
||||||
ns: 'common',
|
|
||||||
date: formatTime(nextCreditResetDate, 'YYYY-MM-DD'),
|
|
||||||
interpolation: { escapeValue: false },
|
|
||||||
})}
|
|
||||||
</span>
|
|
||||||
</>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
|
{isExhausted && exhaustedAt ? (
|
||||||
|
<>
|
||||||
|
<span aria-hidden className="shrink-0 system-sm-regular text-text-tertiary">
|
||||||
|
·
|
||||||
|
</span>
|
||||||
|
<span className="min-w-0 truncate system-sm-regular text-text-tertiary">
|
||||||
|
{t(($) => $['modelProvider.ranOutDate'], {
|
||||||
|
ns: 'common',
|
||||||
|
date: formatMonthDay(exhaustedAt),
|
||||||
|
interpolation: { escapeValue: false },
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
{nextCreditResetDate ? (
|
||||||
|
<>
|
||||||
|
<span aria-hidden className="shrink-0 system-sm-regular text-text-tertiary">
|
||||||
|
·
|
||||||
|
</span>
|
||||||
|
<span className="min-w-0 truncate system-sm-regular text-text-tertiary">
|
||||||
|
{t(($) => $['modelProvider.resetDate'], {
|
||||||
|
ns: 'common',
|
||||||
|
date: formatMonthDay(nextCreditResetDate),
|
||||||
|
interpolation: { escapeValue: false },
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex shrink-0 items-center gap-1">
|
<div className="flex shrink-0 items-center gap-1">
|
||||||
{allProviders
|
{allProviders
|
||||||
@ -204,9 +223,10 @@ const QuotaPanel: FC<QuotaPanelProps> = ({ providers }) => {
|
|||||||
<TooltipTrigger
|
<TooltipTrigger
|
||||||
aria-label={tooltipText}
|
aria-label={tooltipText}
|
||||||
render={
|
render={
|
||||||
<div
|
<button
|
||||||
|
type="button"
|
||||||
className={cn(
|
className={cn(
|
||||||
'relative size-6',
|
'relative size-6 border-0 bg-transparent p-0',
|
||||||
!providerType && canInstallPlugin && 'cursor-pointer hover:opacity-80',
|
!providerType && canInstallPlugin && 'cursor-pointer hover:opacity-80',
|
||||||
)}
|
)}
|
||||||
onClick={() => handleIconClick(key)}
|
onClick={() => handleIconClick(key)}
|
||||||
@ -215,7 +235,7 @@ const QuotaPanel: FC<QuotaPanelProps> = ({ providers }) => {
|
|||||||
{!providerType && (
|
{!providerType && (
|
||||||
<div className="absolute inset-0 rounded-lg border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge opacity-30" />
|
<div className="absolute inset-0 rounded-lg border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge opacity-30" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</button>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<TooltipContent>{tooltipText}</TooltipContent>
|
<TooltipContent>{tooltipText}</TooltipContent>
|
||||||
|
|||||||
@ -4,15 +4,21 @@ import { consoleQuery } from '@/service/client'
|
|||||||
const selectTrialCredits = (workspace: {
|
const selectTrialCredits = (workspace: {
|
||||||
trial_credits?: number | null
|
trial_credits?: number | null
|
||||||
trial_credits_used?: number | null
|
trial_credits_used?: number | null
|
||||||
|
trial_credits_exhausted_at?: number | null
|
||||||
next_credit_reset_date?: number | null
|
next_credit_reset_date?: number | null
|
||||||
}) => {
|
}) => {
|
||||||
const totalCredits = workspace.trial_credits ?? 0
|
const totalCredits = Math.max(workspace.trial_credits ?? 0, 0)
|
||||||
const credits = Math.max(totalCredits - (workspace.trial_credits_used ?? 0), 0)
|
const rawUsedCredits = workspace.trial_credits_used ?? 0
|
||||||
|
const normalizedUsedCredits = Math.max(rawUsedCredits, 0)
|
||||||
|
const usedCredits = Math.min(normalizedUsedCredits, totalCredits)
|
||||||
|
const credits = Math.max(totalCredits - usedCredits, 0)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
credits,
|
credits,
|
||||||
|
usedCredits,
|
||||||
totalCredits,
|
totalCredits,
|
||||||
isExhausted: credits <= 0,
|
isExhausted: credits <= 0,
|
||||||
|
exhaustedAt: workspace.trial_credits_exhausted_at ?? undefined,
|
||||||
nextCreditResetDate: workspace.next_credit_reset_date ?? undefined,
|
nextCreditResetDate: workspace.next_credit_reset_date ?? undefined,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -27,9 +33,11 @@ export const useTrialCredits = () => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
credits: trialCredits?.credits ?? 0,
|
credits: trialCredits?.credits ?? 0,
|
||||||
|
usedCredits: trialCredits?.usedCredits ?? 0,
|
||||||
totalCredits: trialCredits?.totalCredits ?? 0,
|
totalCredits: trialCredits?.totalCredits ?? 0,
|
||||||
isExhausted: trialCredits?.isExhausted ?? true,
|
isExhausted: trialCredits?.isExhausted ?? true,
|
||||||
isLoading: trialCreditsQuery.isPending && !trialCredits,
|
isLoading: trialCreditsQuery.isPending && !trialCredits,
|
||||||
|
exhaustedAt: trialCredits?.exhaustedAt,
|
||||||
nextCreditResetDate: trialCredits?.nextCreditResetDate,
|
nextCreditResetDate: trialCredits?.nextCreditResetDate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -130,6 +130,7 @@ const currentWorkspaceValue: ICurrentWorkspace = {
|
|||||||
providers: [],
|
providers: [],
|
||||||
trial_credits: 10000,
|
trial_credits: 10000,
|
||||||
trial_credits_used: 2500,
|
trial_credits_used: 2500,
|
||||||
|
trial_credits_exhausted_at: 0,
|
||||||
next_credit_reset_date: 0,
|
next_credit_reset_date: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,5 +25,6 @@ export const initialWorkspaceInfo: ICurrentWorkspace = {
|
|||||||
providers: [],
|
providers: [],
|
||||||
trial_credits: 200,
|
trial_credits: 200,
|
||||||
trial_credits_used: 0,
|
trial_credits_used: 0,
|
||||||
|
trial_credits_exhausted_at: 0,
|
||||||
next_credit_reset_date: 0,
|
next_credit_reset_date: 0,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,6 +50,8 @@ export function normalizeCurrentWorkspace(
|
|||||||
providers: initialWorkspaceInfo.providers,
|
providers: initialWorkspaceInfo.providers,
|
||||||
trial_credits: workspace.trial_credits ?? initialWorkspaceInfo.trial_credits,
|
trial_credits: workspace.trial_credits ?? initialWorkspaceInfo.trial_credits,
|
||||||
trial_credits_used: workspace.trial_credits_used ?? initialWorkspaceInfo.trial_credits_used,
|
trial_credits_used: workspace.trial_credits_used ?? initialWorkspaceInfo.trial_credits_used,
|
||||||
|
trial_credits_exhausted_at:
|
||||||
|
workspace.trial_credits_exhausted_at ?? initialWorkspaceInfo.trial_credits_exhausted_at,
|
||||||
next_credit_reset_date:
|
next_credit_reset_date:
|
||||||
workspace.next_credit_reset_date ?? initialWorkspaceInfo.next_credit_reset_date,
|
workspace.next_credit_reset_date ?? initialWorkspaceInfo.next_credit_reset_date,
|
||||||
trial_end_reason: workspace.trial_end_reason ?? undefined,
|
trial_end_reason: workspace.trial_end_reason ?? undefined,
|
||||||
|
|||||||
@ -6,6 +6,12 @@ import { userProfileQueryOptions } from '@/features/account-profile/client'
|
|||||||
import { createAccountProfileQueryWrapper } from '@/test/account-profile-query'
|
import { createAccountProfileQueryWrapper } from '@/test/account-profile-query'
|
||||||
import useTimestamp from './use-timestamp'
|
import useTimestamp from './use-timestamp'
|
||||||
|
|
||||||
|
const mockUseLocale = vi.hoisted(() => vi.fn(() => 'en-US'))
|
||||||
|
|
||||||
|
vi.mock('@/context/i18n', () => ({
|
||||||
|
useLocale: mockUseLocale,
|
||||||
|
}))
|
||||||
|
|
||||||
const createEmptyQueryWrapper = () => {
|
const createEmptyQueryWrapper = () => {
|
||||||
const queryClient = new QueryClient({
|
const queryClient = new QueryClient({
|
||||||
defaultOptions: {
|
defaultOptions: {
|
||||||
@ -23,6 +29,10 @@ const createEmptyQueryWrapper = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('useTimestamp', () => {
|
describe('useTimestamp', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mockUseLocale.mockReturnValue('en-US')
|
||||||
|
})
|
||||||
|
|
||||||
describe('formatTime', () => {
|
describe('formatTime', () => {
|
||||||
it('should format unix timestamp correctly', () => {
|
it('should format unix timestamp correctly', () => {
|
||||||
const { result } = renderHook(() => useTimestamp(), {
|
const { result } = renderHook(() => useTimestamp(), {
|
||||||
@ -45,6 +55,16 @@ describe('useTimestamp', () => {
|
|||||||
|
|
||||||
expect(result.current.formatTime(timestamp, 'HH:mm')).toBe('02:00')
|
expect(result.current.formatTime(timestamp, 'HH:mm')).toBe('02:00')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should format month names with the current interface locale', () => {
|
||||||
|
mockUseLocale.mockReturnValue('zh-Hans')
|
||||||
|
const { result } = renderHook(() => useTimestamp(), {
|
||||||
|
wrapper: createAccountProfileQueryWrapper(),
|
||||||
|
})
|
||||||
|
const timestamp = 1704132000
|
||||||
|
|
||||||
|
expect(result.current.formatTime(timestamp, 'MMM D')).toBe('1月 2')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('formatDate', () => {
|
describe('formatDate', () => {
|
||||||
@ -69,6 +89,37 @@ describe('useTimestamp', () => {
|
|||||||
|
|
||||||
expect(result.current.formatDate(dateString, 'HH:mm')).toBe('20:00')
|
expect(result.current.formatDate(dateString, 'HH:mm')).toBe('20:00')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should format date string month names with the current interface locale', () => {
|
||||||
|
mockUseLocale.mockReturnValue('zh-Hans')
|
||||||
|
const { result } = renderHook(() => useTimestamp(), {
|
||||||
|
wrapper: createAccountProfileQueryWrapper(),
|
||||||
|
})
|
||||||
|
const dateString = '2024-01-01T12:00:00Z'
|
||||||
|
|
||||||
|
expect(result.current.formatDate(dateString, 'MMM D')).toBe('1月 1')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('formatMonthDay', () => {
|
||||||
|
it('should format month and day naturally for English', () => {
|
||||||
|
const { result } = renderHook(() => useTimestamp(), {
|
||||||
|
wrapper: createAccountProfileQueryWrapper(),
|
||||||
|
})
|
||||||
|
const timestamp = 1704132000
|
||||||
|
|
||||||
|
expect(result.current.formatMonthDay(timestamp)).toBe('Jan 2')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should format month and day naturally for Chinese', () => {
|
||||||
|
mockUseLocale.mockReturnValue('zh-Hans')
|
||||||
|
const { result } = renderHook(() => useTimestamp(), {
|
||||||
|
wrapper: createAccountProfileQueryWrapper(),
|
||||||
|
})
|
||||||
|
const timestamp = 1704132000
|
||||||
|
|
||||||
|
expect(result.current.formatMonthDay(timestamp)).toBe('1月2日')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not request account profile when timezone is provided', () => {
|
it('should not request account profile when timezone is provided', () => {
|
||||||
|
|||||||
@ -4,7 +4,9 @@ import dayjs from 'dayjs'
|
|||||||
import timezone from 'dayjs/plugin/timezone'
|
import timezone from 'dayjs/plugin/timezone'
|
||||||
import utc from 'dayjs/plugin/utc'
|
import utc from 'dayjs/plugin/utc'
|
||||||
import { useCallback } from 'react'
|
import { useCallback } from 'react'
|
||||||
|
import { useLocale } from '@/context/i18n'
|
||||||
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||||
|
import { formatToLocalTime } from '@/utils/format'
|
||||||
|
|
||||||
dayjs.extend(utc)
|
dayjs.extend(utc)
|
||||||
dayjs.extend(timezone)
|
dayjs.extend(timezone)
|
||||||
@ -17,7 +19,10 @@ const getBrowserTimezone = () => {
|
|||||||
return new Intl.DateTimeFormat().resolvedOptions().timeZone
|
return new Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getIntlLocale = (locale: string) => locale.replace('_', '-')
|
||||||
|
|
||||||
const useTimestamp = ({ timezone: timezoneOverride }: UseTimestampOptions = {}) => {
|
const useTimestamp = ({ timezone: timezoneOverride }: UseTimestampOptions = {}) => {
|
||||||
|
const locale = useLocale()
|
||||||
const { data: accountTimezone } = useQuery({
|
const { data: accountTimezone } = useQuery({
|
||||||
...userProfileQueryOptions(),
|
...userProfileQueryOptions(),
|
||||||
select: (data) => data.profile.timezone ?? undefined,
|
select: (data) => data.profile.timezone ?? undefined,
|
||||||
@ -27,19 +32,30 @@ const useTimestamp = ({ timezone: timezoneOverride }: UseTimestampOptions = {})
|
|||||||
|
|
||||||
const formatTime = useCallback(
|
const formatTime = useCallback(
|
||||||
(value: number, format: string) => {
|
(value: number, format: string) => {
|
||||||
return dayjs.unix(value).tz(resolvedTimezone).format(format)
|
return formatToLocalTime(dayjs.unix(value).tz(resolvedTimezone), locale, format)
|
||||||
},
|
},
|
||||||
[resolvedTimezone],
|
[locale, resolvedTimezone],
|
||||||
)
|
)
|
||||||
|
|
||||||
const formatDate = useCallback(
|
const formatDate = useCallback(
|
||||||
(value: string, format: string) => {
|
(value: string, format: string) => {
|
||||||
return dayjs(value).tz(resolvedTimezone).format(format)
|
return formatToLocalTime(dayjs(value).tz(resolvedTimezone), locale, format)
|
||||||
},
|
},
|
||||||
[resolvedTimezone],
|
[locale, resolvedTimezone],
|
||||||
)
|
)
|
||||||
|
|
||||||
return { formatTime, formatDate }
|
const formatMonthDay = useCallback(
|
||||||
|
(value: number) => {
|
||||||
|
return new Intl.DateTimeFormat(getIntlLocale(locale), {
|
||||||
|
month: 'short',
|
||||||
|
day: 'numeric',
|
||||||
|
timeZone: resolvedTimezone,
|
||||||
|
}).format(value * 1000)
|
||||||
|
},
|
||||||
|
[locale, resolvedTimezone],
|
||||||
|
)
|
||||||
|
|
||||||
|
return { formatTime, formatDate, formatMonthDay }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useTimestamp
|
export default useTimestamp
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "بعض المعلمات غير صالحة وتمت إزالتها",
|
"modelProvider.parametersInvalidRemoved": "بعض المعلمات غير صالحة وتمت إزالتها",
|
||||||
"modelProvider.providerManaged": "مدار من قبل المزود",
|
"modelProvider.providerManaged": "مدار من قبل المزود",
|
||||||
"modelProvider.quotaLabel": "QUOTA",
|
"modelProvider.quotaLabel": "QUOTA",
|
||||||
|
"modelProvider.ranOutDate": "نفد في {{date}}",
|
||||||
"modelProvider.rerankModel.key": "نموذج إعادة الترتيب",
|
"modelProvider.rerankModel.key": "نموذج إعادة الترتيب",
|
||||||
"modelProvider.rerankModel.tip": "سيعيد نموذج إعادة الترتيب ترتيب قائمة المستندات المرشحة بناءً على المطابقة الدلالية مع استعلام المستخدم، مما يحسن نتائج الترتيب الدلالي",
|
"modelProvider.rerankModel.tip": "سيعيد نموذج إعادة الترتيب ترتيب قائمة المستندات المرشحة بناءً على المطابقة الدلالية مع استعلام المستخدم، مما يحسن نتائج الترتيب الدلالي",
|
||||||
"modelProvider.resetDate": "إعادة التعيين في {{date}}",
|
"modelProvider.resetDate": "إعادة التعيين في {{date}}",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "نموذج تحويل النص إلى كلام",
|
"modelProvider.ttsModel.key": "نموذج تحويل النص إلى كلام",
|
||||||
"modelProvider.ttsModel.tip": "تعيين النموذج الافتراضي لإدخال تحويل النص إلى كلام في المحادثة.",
|
"modelProvider.ttsModel.tip": "تعيين النموذج الافتراضي لإدخال تحويل النص إلى كلام في المحادثة.",
|
||||||
"modelProvider.upgradeForLoadBalancing": "قم بترقية خطتك لتمكين موازنة التحميل.",
|
"modelProvider.upgradeForLoadBalancing": "قم بترقية خطتك لتمكين موازنة التحميل.",
|
||||||
|
"modelProvider.used": "مستخدم",
|
||||||
"navigation.skipToMain": "الانتقال إلى المحتوى الرئيسي",
|
"navigation.skipToMain": "الانتقال إلى المحتوى الرئيسي",
|
||||||
"noData": "لا توجد بيانات",
|
"noData": "لا توجد بيانات",
|
||||||
"operation.add": "إضافة",
|
"operation.add": "إضافة",
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "Einige Parameter sind ungültig und wurden entfernt.",
|
"modelProvider.parametersInvalidRemoved": "Einige Parameter sind ungültig und wurden entfernt.",
|
||||||
"modelProvider.providerManaged": "Vom Anbieter verwaltet",
|
"modelProvider.providerManaged": "Vom Anbieter verwaltet",
|
||||||
"modelProvider.quotaLabel": "QUOTA",
|
"modelProvider.quotaLabel": "QUOTA",
|
||||||
|
"modelProvider.ranOutDate": "Aufgebraucht am {{date}}",
|
||||||
"modelProvider.rerankModel.key": "Rerank-Modell",
|
"modelProvider.rerankModel.key": "Rerank-Modell",
|
||||||
"modelProvider.rerankModel.tip": "Rerank-Modell wird die Kandidatendokumentenliste basierend auf der semantischen Übereinstimmung mit der Benutzeranfrage neu ordnen und die Ergebnisse der semantischen Rangordnung verbessern",
|
"modelProvider.rerankModel.tip": "Rerank-Modell wird die Kandidatendokumentenliste basierend auf der semantischen Übereinstimmung mit der Benutzeranfrage neu ordnen und die Ergebnisse der semantischen Rangordnung verbessern",
|
||||||
"modelProvider.resetDate": "Zurücksetzen am {{date}}",
|
"modelProvider.resetDate": "Zurücksetzen am {{date}}",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "Text-zu-Sprache-Modell",
|
"modelProvider.ttsModel.key": "Text-zu-Sprache-Modell",
|
||||||
"modelProvider.ttsModel.tip": "Legen Sie das Standardmodell für die Text-zu-Sprache-Eingabe in Konversationen fest.",
|
"modelProvider.ttsModel.tip": "Legen Sie das Standardmodell für die Text-zu-Sprache-Eingabe in Konversationen fest.",
|
||||||
"modelProvider.upgradeForLoadBalancing": "Aktualisieren Sie Ihren Plan, um den Lastenausgleich zu aktivieren.",
|
"modelProvider.upgradeForLoadBalancing": "Aktualisieren Sie Ihren Plan, um den Lastenausgleich zu aktivieren.",
|
||||||
|
"modelProvider.used": "verwendet",
|
||||||
"navigation.skipToMain": "Zum Hauptinhalt springen",
|
"navigation.skipToMain": "Zum Hauptinhalt springen",
|
||||||
"noData": "Keine Daten",
|
"noData": "Keine Daten",
|
||||||
"operation.add": "Hinzufügen",
|
"operation.add": "Hinzufügen",
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "Some parameters are invalid and have been removed",
|
"modelProvider.parametersInvalidRemoved": "Some parameters are invalid and have been removed",
|
||||||
"modelProvider.providerManaged": "Provider managed",
|
"modelProvider.providerManaged": "Provider managed",
|
||||||
"modelProvider.quotaLabel": "AI CREDITS",
|
"modelProvider.quotaLabel": "AI CREDITS",
|
||||||
|
"modelProvider.ranOutDate": "Ran out on {{date}}",
|
||||||
"modelProvider.rerankModel.key": "Rerank Model",
|
"modelProvider.rerankModel.key": "Rerank Model",
|
||||||
"modelProvider.rerankModel.tip": "Rerank model will reorder the candidate document list based on the semantic match with user query, improving the results of semantic ranking",
|
"modelProvider.rerankModel.tip": "Rerank model will reorder the candidate document list based on the semantic match with user query, improving the results of semantic ranking",
|
||||||
"modelProvider.resetDate": "Reset on {{date}}",
|
"modelProvider.resetDate": "Reset on {{date}}",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "Text-to-Speech Model",
|
"modelProvider.ttsModel.key": "Text-to-Speech Model",
|
||||||
"modelProvider.ttsModel.tip": "Set the default model for text-to-speech input in conversation.",
|
"modelProvider.ttsModel.tip": "Set the default model for text-to-speech input in conversation.",
|
||||||
"modelProvider.upgradeForLoadBalancing": "Upgrade your plan to enable Load Balancing.",
|
"modelProvider.upgradeForLoadBalancing": "Upgrade your plan to enable Load Balancing.",
|
||||||
|
"modelProvider.used": "used",
|
||||||
"navigation.skipToMain": "Skip to main content",
|
"navigation.skipToMain": "Skip to main content",
|
||||||
"noData": "No data",
|
"noData": "No data",
|
||||||
"operation.add": "Add",
|
"operation.add": "Add",
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "Algunos parámetros son inválidos y han sido eliminados",
|
"modelProvider.parametersInvalidRemoved": "Algunos parámetros son inválidos y han sido eliminados",
|
||||||
"modelProvider.providerManaged": "Gestionado por el proveedor",
|
"modelProvider.providerManaged": "Gestionado por el proveedor",
|
||||||
"modelProvider.quotaLabel": "QUOTA",
|
"modelProvider.quotaLabel": "QUOTA",
|
||||||
|
"modelProvider.ranOutDate": "Agotado el {{date}}",
|
||||||
"modelProvider.rerankModel.key": "Modelo de Reordenar",
|
"modelProvider.rerankModel.key": "Modelo de Reordenar",
|
||||||
"modelProvider.rerankModel.tip": "El modelo de reordenar reordenará la lista de documentos candidatos basada en la coincidencia semántica con la consulta del usuario, mejorando los resultados de clasificación semántica",
|
"modelProvider.rerankModel.tip": "El modelo de reordenar reordenará la lista de documentos candidatos basada en la coincidencia semántica con la consulta del usuario, mejorando los resultados de clasificación semántica",
|
||||||
"modelProvider.resetDate": "Restablecer el {{date}}",
|
"modelProvider.resetDate": "Restablecer el {{date}}",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "Modelo de Texto a Voz",
|
"modelProvider.ttsModel.key": "Modelo de Texto a Voz",
|
||||||
"modelProvider.ttsModel.tip": "Establece el modelo predeterminado para la entrada de texto a voz en la conversación.",
|
"modelProvider.ttsModel.tip": "Establece el modelo predeterminado para la entrada de texto a voz en la conversación.",
|
||||||
"modelProvider.upgradeForLoadBalancing": "Actualiza tu plan para habilitar el Balanceo de Carga.",
|
"modelProvider.upgradeForLoadBalancing": "Actualiza tu plan para habilitar el Balanceo de Carga.",
|
||||||
|
"modelProvider.used": "usados",
|
||||||
"navigation.skipToMain": "Saltar al contenido principal",
|
"navigation.skipToMain": "Saltar al contenido principal",
|
||||||
"noData": "Sin datos",
|
"noData": "Sin datos",
|
||||||
"operation.add": "Agregar",
|
"operation.add": "Agregar",
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "برخی پارامترها نامعتبر هستند و حذف شدهاند",
|
"modelProvider.parametersInvalidRemoved": "برخی پارامترها نامعتبر هستند و حذف شدهاند",
|
||||||
"modelProvider.providerManaged": "مدیریت شده توسط ارائهدهنده",
|
"modelProvider.providerManaged": "مدیریت شده توسط ارائهدهنده",
|
||||||
"modelProvider.quotaLabel": "QUOTA",
|
"modelProvider.quotaLabel": "QUOTA",
|
||||||
|
"modelProvider.ranOutDate": "در {{date}} تمام شد",
|
||||||
"modelProvider.rerankModel.key": "مدل رتبهبندی مجدد",
|
"modelProvider.rerankModel.key": "مدل رتبهبندی مجدد",
|
||||||
"modelProvider.rerankModel.tip": "مدل رتبهبندی مجدد، لیست اسناد کاندید را بر اساس تطابق معنایی با پرسش کاربر مرتب میکند و نتایج رتبهبندی معنایی را بهبود میبخشد",
|
"modelProvider.rerankModel.tip": "مدل رتبهبندی مجدد، لیست اسناد کاندید را بر اساس تطابق معنایی با پرسش کاربر مرتب میکند و نتایج رتبهبندی معنایی را بهبود میبخشد",
|
||||||
"modelProvider.resetDate": "بازنشانی در {{date}}",
|
"modelProvider.resetDate": "بازنشانی در {{date}}",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "مدل تبدیل متن به گفتار",
|
"modelProvider.ttsModel.key": "مدل تبدیل متن به گفتار",
|
||||||
"modelProvider.ttsModel.tip": "مدل پیشفرض را برای ورودی متن به گفتار در مکالمه تنظیم کنید.",
|
"modelProvider.ttsModel.tip": "مدل پیشفرض را برای ورودی متن به گفتار در مکالمه تنظیم کنید.",
|
||||||
"modelProvider.upgradeForLoadBalancing": "برای فعال کردن تعادل بار، طرح خود را ارتقا دهید.",
|
"modelProvider.upgradeForLoadBalancing": "برای فعال کردن تعادل بار، طرح خود را ارتقا دهید.",
|
||||||
|
"modelProvider.used": "استفادهشده",
|
||||||
"navigation.skipToMain": "پرش به محتوای اصلی",
|
"navigation.skipToMain": "پرش به محتوای اصلی",
|
||||||
"noData": "بدون داده",
|
"noData": "بدون داده",
|
||||||
"operation.add": "افزودن",
|
"operation.add": "افزودن",
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "Certains paramètres sont invalides et ont été supprimés.",
|
"modelProvider.parametersInvalidRemoved": "Certains paramètres sont invalides et ont été supprimés.",
|
||||||
"modelProvider.providerManaged": "Géré par le fournisseur",
|
"modelProvider.providerManaged": "Géré par le fournisseur",
|
||||||
"modelProvider.quotaLabel": "QUOTA",
|
"modelProvider.quotaLabel": "QUOTA",
|
||||||
|
"modelProvider.ranOutDate": "Épuisé le {{date}}",
|
||||||
"modelProvider.rerankModel.key": "Modèle de Réorganisation",
|
"modelProvider.rerankModel.key": "Modèle de Réorganisation",
|
||||||
"modelProvider.rerankModel.tip": "Le modèle de réorganisation réorganisera la liste des documents candidats en fonction de la correspondance sémantique avec la requête de l'utilisateur, améliorant ainsi les résultats du classement sémantique.",
|
"modelProvider.rerankModel.tip": "Le modèle de réorganisation réorganisera la liste des documents candidats en fonction de la correspondance sémantique avec la requête de l'utilisateur, améliorant ainsi les résultats du classement sémantique.",
|
||||||
"modelProvider.resetDate": "Réinitialiser le {{date}}",
|
"modelProvider.resetDate": "Réinitialiser le {{date}}",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "Modèle de Texte-à-Parole",
|
"modelProvider.ttsModel.key": "Modèle de Texte-à-Parole",
|
||||||
"modelProvider.ttsModel.tip": "Définissez le modèle par défaut pour l'entrée de texte à la parole dans une conversation.",
|
"modelProvider.ttsModel.tip": "Définissez le modèle par défaut pour l'entrée de texte à la parole dans une conversation.",
|
||||||
"modelProvider.upgradeForLoadBalancing": "Mettez à niveau votre plan pour activer l’équilibrage de charge.",
|
"modelProvider.upgradeForLoadBalancing": "Mettez à niveau votre plan pour activer l’équilibrage de charge.",
|
||||||
|
"modelProvider.used": "utilisés",
|
||||||
"navigation.skipToMain": "Aller au contenu principal",
|
"navigation.skipToMain": "Aller au contenu principal",
|
||||||
"noData": "Aucune donnée",
|
"noData": "Aucune donnée",
|
||||||
"operation.add": "Ajouter",
|
"operation.add": "Ajouter",
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "कुछ पैरामीटर अमान्य हैं और हटा दिए गए हैं",
|
"modelProvider.parametersInvalidRemoved": "कुछ पैरामीटर अमान्य हैं और हटा दिए गए हैं",
|
||||||
"modelProvider.providerManaged": "प्रदाता प्रबंधित",
|
"modelProvider.providerManaged": "प्रदाता प्रबंधित",
|
||||||
"modelProvider.quotaLabel": "QUOTA",
|
"modelProvider.quotaLabel": "QUOTA",
|
||||||
|
"modelProvider.ranOutDate": "{{date}} को समाप्त",
|
||||||
"modelProvider.rerankModel.key": "रीरैंक मॉडल",
|
"modelProvider.rerankModel.key": "रीरैंक मॉडल",
|
||||||
"modelProvider.rerankModel.tip": "रीरैंक मॉडल उपयोगकर्ता प्रश्न के साथ सांविधिक मेल के आधार पर उम्मीदवार दस्तावेज़ सूची को पुनः क्रमित करेगा, सांविधिक रैंकिंग के परिणामों में सुधार करेगा।",
|
"modelProvider.rerankModel.tip": "रीरैंक मॉडल उपयोगकर्ता प्रश्न के साथ सांविधिक मेल के आधार पर उम्मीदवार दस्तावेज़ सूची को पुनः क्रमित करेगा, सांविधिक रैंकिंग के परिणामों में सुधार करेगा।",
|
||||||
"modelProvider.resetDate": "{{date}} को रीसेट करें",
|
"modelProvider.resetDate": "{{date}} को रीसेट करें",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "पाठ-से-भाषण मॉडल",
|
"modelProvider.ttsModel.key": "पाठ-से-भाषण मॉडल",
|
||||||
"modelProvider.ttsModel.tip": "संवाद में पाठ-से-भाषण इनपुट के लिए डिफ़ॉल्ट मॉडल सेट करें।",
|
"modelProvider.ttsModel.tip": "संवाद में पाठ-से-भाषण इनपुट के लिए डिफ़ॉल्ट मॉडल सेट करें।",
|
||||||
"modelProvider.upgradeForLoadBalancing": "लोड बैलेंसिंग सक्षम करने के लिए अपनी योजना अपग्रेड करें।",
|
"modelProvider.upgradeForLoadBalancing": "लोड बैलेंसिंग सक्षम करने के लिए अपनी योजना अपग्रेड करें।",
|
||||||
|
"modelProvider.used": "उपयोग किया गया",
|
||||||
"navigation.skipToMain": "मुख्य सामग्री पर जाएं",
|
"navigation.skipToMain": "मुख्य सामग्री पर जाएं",
|
||||||
"noData": "कोई डेटा नहीं",
|
"noData": "कोई डेटा नहीं",
|
||||||
"operation.add": "जोड़ें",
|
"operation.add": "जोड़ें",
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "Beberapa parameter tidak valid dan telah dihapus",
|
"modelProvider.parametersInvalidRemoved": "Beberapa parameter tidak valid dan telah dihapus",
|
||||||
"modelProvider.providerManaged": "Penyedia dikelola",
|
"modelProvider.providerManaged": "Penyedia dikelola",
|
||||||
"modelProvider.quotaLabel": "QUOTA",
|
"modelProvider.quotaLabel": "QUOTA",
|
||||||
|
"modelProvider.ranOutDate": "Habis pada {{date}}",
|
||||||
"modelProvider.rerankModel.key": "Peringkat ulang Model",
|
"modelProvider.rerankModel.key": "Peringkat ulang Model",
|
||||||
"modelProvider.rerankModel.tip": "Model rerank akan menyusun ulang daftar dokumen kandidat berdasarkan kecocokan semantik dengan kueri pengguna, meningkatkan hasil peringkat semantik",
|
"modelProvider.rerankModel.tip": "Model rerank akan menyusun ulang daftar dokumen kandidat berdasarkan kecocokan semantik dengan kueri pengguna, meningkatkan hasil peringkat semantik",
|
||||||
"modelProvider.resetDate": "Setel ulang pada {{date}}",
|
"modelProvider.resetDate": "Setel ulang pada {{date}}",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "Model Teks-ke-Ucapan",
|
"modelProvider.ttsModel.key": "Model Teks-ke-Ucapan",
|
||||||
"modelProvider.ttsModel.tip": "Atur model default untuk input teks-ke-ucapan dalam percakapan.",
|
"modelProvider.ttsModel.tip": "Atur model default untuk input teks-ke-ucapan dalam percakapan.",
|
||||||
"modelProvider.upgradeForLoadBalancing": "Tingkatkan paket Anda untuk mengaktifkan Penyeimbangan Beban.",
|
"modelProvider.upgradeForLoadBalancing": "Tingkatkan paket Anda untuk mengaktifkan Penyeimbangan Beban.",
|
||||||
|
"modelProvider.used": "digunakan",
|
||||||
"navigation.skipToMain": "Lewati ke konten utama",
|
"navigation.skipToMain": "Lewati ke konten utama",
|
||||||
"noData": "Tidak ada data",
|
"noData": "Tidak ada data",
|
||||||
"operation.add": "Tambah",
|
"operation.add": "Tambah",
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "Alcuni parametri non sono validi e sono stati rimossi.",
|
"modelProvider.parametersInvalidRemoved": "Alcuni parametri non sono validi e sono stati rimossi.",
|
||||||
"modelProvider.providerManaged": "Gestito dal fornitore",
|
"modelProvider.providerManaged": "Gestito dal fornitore",
|
||||||
"modelProvider.quotaLabel": "QUOTA",
|
"modelProvider.quotaLabel": "QUOTA",
|
||||||
|
"modelProvider.ranOutDate": "Esauriti il {{date}}",
|
||||||
"modelProvider.rerankModel.key": "Modello di Rerank",
|
"modelProvider.rerankModel.key": "Modello di Rerank",
|
||||||
"modelProvider.rerankModel.tip": "Il modello di rerank riordinerà la lista dei documenti candidati basandosi sulla corrispondenza semantica con la query dell'utente, migliorando i risultati del ranking semantico",
|
"modelProvider.rerankModel.tip": "Il modello di rerank riordinerà la lista dei documenti candidati basandosi sulla corrispondenza semantica con la query dell'utente, migliorando i risultati del ranking semantico",
|
||||||
"modelProvider.resetDate": "Ripristina il {{date}}",
|
"modelProvider.resetDate": "Ripristina il {{date}}",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "Modello da Testo a Voce",
|
"modelProvider.ttsModel.key": "Modello da Testo a Voce",
|
||||||
"modelProvider.ttsModel.tip": "Imposta il modello predefinito per l'input da testo a voce nella conversazione.",
|
"modelProvider.ttsModel.tip": "Imposta il modello predefinito per l'input da testo a voce nella conversazione.",
|
||||||
"modelProvider.upgradeForLoadBalancing": "Aggiorna il tuo piano per abilitare il Bilanciamento del Carico.",
|
"modelProvider.upgradeForLoadBalancing": "Aggiorna il tuo piano per abilitare il Bilanciamento del Carico.",
|
||||||
|
"modelProvider.used": "utilizzati",
|
||||||
"navigation.skipToMain": "Vai al contenuto principale",
|
"navigation.skipToMain": "Vai al contenuto principale",
|
||||||
"noData": "Nessun dato",
|
"noData": "Nessun dato",
|
||||||
"operation.add": "Aggiungi",
|
"operation.add": "Aggiungi",
|
||||||
|
|||||||
@ -394,9 +394,10 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "いくつかのパラメータが無効であり、削除されました。",
|
"modelProvider.parametersInvalidRemoved": "いくつかのパラメータが無効であり、削除されました。",
|
||||||
"modelProvider.providerManaged": "プロバイダ管理",
|
"modelProvider.providerManaged": "プロバイダ管理",
|
||||||
"modelProvider.quotaLabel": "AI クレジット",
|
"modelProvider.quotaLabel": "AI クレジット",
|
||||||
|
"modelProvider.ranOutDate": "{{date}}に使い切りました",
|
||||||
"modelProvider.rerankModel.key": "Rerank モデル",
|
"modelProvider.rerankModel.key": "Rerank モデル",
|
||||||
"modelProvider.rerankModel.tip": "Rerank モデルは、ユーザークエリとの意味的一致に基づいて候補文書リストを再配置し、意味的ランキングの結果を向上させます。",
|
"modelProvider.rerankModel.tip": "Rerank モデルは、ユーザークエリとの意味的一致に基づいて候補文書リストを再配置し、意味的ランキングの結果を向上させます。",
|
||||||
"modelProvider.resetDate": "{{date}} にリセット",
|
"modelProvider.resetDate": "{{date}}にリセット",
|
||||||
"modelProvider.searchModels": "モデルを検索...",
|
"modelProvider.searchModels": "モデルを検索...",
|
||||||
"modelProvider.selectModel": "モデルを選択",
|
"modelProvider.selectModel": "モデルを選択",
|
||||||
"modelProvider.selector.aiCredits": "AI クレジット",
|
"modelProvider.selector.aiCredits": "AI クレジット",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "テキスト-to-音声モデル",
|
"modelProvider.ttsModel.key": "テキスト-to-音声モデル",
|
||||||
"modelProvider.ttsModel.tip": "会話でのテキスト-to-音声入力に使用するデフォルトモデルを設定します。",
|
"modelProvider.ttsModel.tip": "会話でのテキスト-to-音声入力に使用するデフォルトモデルを設定します。",
|
||||||
"modelProvider.upgradeForLoadBalancing": "負荷分散を利用するには、プランのアップグレードが必要です。",
|
"modelProvider.upgradeForLoadBalancing": "負荷分散を利用するには、プランのアップグレードが必要です。",
|
||||||
|
"modelProvider.used": "使用済み",
|
||||||
"navigation.skipToMain": "メインコンテンツへスキップ",
|
"navigation.skipToMain": "メインコンテンツへスキップ",
|
||||||
"noData": "データなし",
|
"noData": "データなし",
|
||||||
"operation.add": "追加",
|
"operation.add": "追加",
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "일부 매개변수가 유효하지 않아 제거되었습니다.",
|
"modelProvider.parametersInvalidRemoved": "일부 매개변수가 유효하지 않아 제거되었습니다.",
|
||||||
"modelProvider.providerManaged": "제공자 관리",
|
"modelProvider.providerManaged": "제공자 관리",
|
||||||
"modelProvider.quotaLabel": "QUOTA",
|
"modelProvider.quotaLabel": "QUOTA",
|
||||||
|
"modelProvider.ranOutDate": "{{date}}에 소진됨",
|
||||||
"modelProvider.rerankModel.key": "재랭크 모델",
|
"modelProvider.rerankModel.key": "재랭크 모델",
|
||||||
"modelProvider.rerankModel.tip": "재랭크 모델은 사용자 쿼리와의 의미적 일치를 기반으로 후보 문서 목록을 재배열하여 의미적 순위를 향상시킵니다.",
|
"modelProvider.rerankModel.tip": "재랭크 모델은 사용자 쿼리와의 의미적 일치를 기반으로 후보 문서 목록을 재배열하여 의미적 순위를 향상시킵니다.",
|
||||||
"modelProvider.resetDate": "{{date}}에 재설정",
|
"modelProvider.resetDate": "{{date}}에 재설정",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "텍스트-to-음성 모델",
|
"modelProvider.ttsModel.key": "텍스트-to-음성 모델",
|
||||||
"modelProvider.ttsModel.tip": "대화에서의 텍스트-to-음성 입력에 사용되는 기본 모델을 설정합니다.",
|
"modelProvider.ttsModel.tip": "대화에서의 텍스트-to-음성 입력에 사용되는 기본 모델을 설정합니다.",
|
||||||
"modelProvider.upgradeForLoadBalancing": "로드 밸런싱을 사용하도록 계획을 업그레이드합니다.",
|
"modelProvider.upgradeForLoadBalancing": "로드 밸런싱을 사용하도록 계획을 업그레이드합니다.",
|
||||||
|
"modelProvider.used": "사용됨",
|
||||||
"navigation.skipToMain": "본문으로 건너뛰기",
|
"navigation.skipToMain": "본문으로 건너뛰기",
|
||||||
"noData": "데이터 없음",
|
"noData": "데이터 없음",
|
||||||
"operation.add": "추가",
|
"operation.add": "추가",
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "Some parameters are invalid and have been removed",
|
"modelProvider.parametersInvalidRemoved": "Some parameters are invalid and have been removed",
|
||||||
"modelProvider.providerManaged": "Provider managed",
|
"modelProvider.providerManaged": "Provider managed",
|
||||||
"modelProvider.quotaLabel": "QUOTA",
|
"modelProvider.quotaLabel": "QUOTA",
|
||||||
|
"modelProvider.ranOutDate": "Opgebruikt op {{date}}",
|
||||||
"modelProvider.rerankModel.key": "Rerank Model",
|
"modelProvider.rerankModel.key": "Rerank Model",
|
||||||
"modelProvider.rerankModel.tip": "Rerank model will reorder the candidate document list based on the semantic match with user query, improving the results of semantic ranking",
|
"modelProvider.rerankModel.tip": "Rerank model will reorder the candidate document list based on the semantic match with user query, improving the results of semantic ranking",
|
||||||
"modelProvider.resetDate": "Reset on {{date}}",
|
"modelProvider.resetDate": "Reset on {{date}}",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "Text-to-Speech Model",
|
"modelProvider.ttsModel.key": "Text-to-Speech Model",
|
||||||
"modelProvider.ttsModel.tip": "Set the default model for text-to-speech input in conversation.",
|
"modelProvider.ttsModel.tip": "Set the default model for text-to-speech input in conversation.",
|
||||||
"modelProvider.upgradeForLoadBalancing": "Upgrade your plan to enable Load Balancing.",
|
"modelProvider.upgradeForLoadBalancing": "Upgrade your plan to enable Load Balancing.",
|
||||||
|
"modelProvider.used": "gebruikt",
|
||||||
"navigation.skipToMain": "Naar hoofdinhoud springen",
|
"navigation.skipToMain": "Naar hoofdinhoud springen",
|
||||||
"noData": "No data",
|
"noData": "No data",
|
||||||
"operation.add": "Add",
|
"operation.add": "Add",
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "Niektóre parametry są nieprawidłowe i zostały usunięte.",
|
"modelProvider.parametersInvalidRemoved": "Niektóre parametry są nieprawidłowe i zostały usunięte.",
|
||||||
"modelProvider.providerManaged": "Zarządzany przez dostawcę",
|
"modelProvider.providerManaged": "Zarządzany przez dostawcę",
|
||||||
"modelProvider.quotaLabel": "QUOTA",
|
"modelProvider.quotaLabel": "QUOTA",
|
||||||
|
"modelProvider.ranOutDate": "Wyczerpano {{date}}",
|
||||||
"modelProvider.rerankModel.key": "Model ponownego rankingu",
|
"modelProvider.rerankModel.key": "Model ponownego rankingu",
|
||||||
"modelProvider.rerankModel.tip": "Model ponownego rankingu zmieni kolejność listy dokumentów kandydatów na podstawie semantycznego dopasowania z zapytaniem użytkownika, poprawiając wyniki rankingu semantycznego",
|
"modelProvider.rerankModel.tip": "Model ponownego rankingu zmieni kolejność listy dokumentów kandydatów na podstawie semantycznego dopasowania z zapytaniem użytkownika, poprawiając wyniki rankingu semantycznego",
|
||||||
"modelProvider.resetDate": "Reset {{date}}",
|
"modelProvider.resetDate": "Reset {{date}}",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "Model tekstu na mowę",
|
"modelProvider.ttsModel.key": "Model tekstu na mowę",
|
||||||
"modelProvider.ttsModel.tip": "Ustaw domyślny model dla konwersji tekstu na mowę w rozmowach.",
|
"modelProvider.ttsModel.tip": "Ustaw domyślny model dla konwersji tekstu na mowę w rozmowach.",
|
||||||
"modelProvider.upgradeForLoadBalancing": "Uaktualnij swój plan, aby włączyć równoważenie obciążenia.",
|
"modelProvider.upgradeForLoadBalancing": "Uaktualnij swój plan, aby włączyć równoważenie obciążenia.",
|
||||||
|
"modelProvider.used": "wykorzystano",
|
||||||
"navigation.skipToMain": "Przejdź do głównej treści",
|
"navigation.skipToMain": "Przejdź do głównej treści",
|
||||||
"noData": "Brak danych",
|
"noData": "Brak danych",
|
||||||
"operation.add": "Dodaj",
|
"operation.add": "Dodaj",
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "Alguns parâmetros são inválidos e foram removidos",
|
"modelProvider.parametersInvalidRemoved": "Alguns parâmetros são inválidos e foram removidos",
|
||||||
"modelProvider.providerManaged": "Gerenciado pelo provedor",
|
"modelProvider.providerManaged": "Gerenciado pelo provedor",
|
||||||
"modelProvider.quotaLabel": "QUOTA",
|
"modelProvider.quotaLabel": "QUOTA",
|
||||||
|
"modelProvider.ranOutDate": "Esgotado em {{date}}",
|
||||||
"modelProvider.rerankModel.key": "Modelo de Reordenação",
|
"modelProvider.rerankModel.key": "Modelo de Reordenação",
|
||||||
"modelProvider.rerankModel.tip": "O modelo de reordenaenação reorganizará a lista de documentos candidatos com base na correspondência semântica com a consulta do usuário, melhorando os resultados da classificação semântica",
|
"modelProvider.rerankModel.tip": "O modelo de reordenaenação reorganizará a lista de documentos candidatos com base na correspondência semântica com a consulta do usuário, melhorando os resultados da classificação semântica",
|
||||||
"modelProvider.resetDate": "Redefinir em {{date}}",
|
"modelProvider.resetDate": "Redefinir em {{date}}",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "Modelo de Texto para Fala",
|
"modelProvider.ttsModel.key": "Modelo de Texto para Fala",
|
||||||
"modelProvider.ttsModel.tip": "Defina o modelo padrão para entrada de texto para fala na conversa.",
|
"modelProvider.ttsModel.tip": "Defina o modelo padrão para entrada de texto para fala na conversa.",
|
||||||
"modelProvider.upgradeForLoadBalancing": "Atualize seu plano para habilitar o balanceamento de carga.",
|
"modelProvider.upgradeForLoadBalancing": "Atualize seu plano para habilitar o balanceamento de carga.",
|
||||||
|
"modelProvider.used": "usados",
|
||||||
"navigation.skipToMain": "Pular para o conteúdo principal",
|
"navigation.skipToMain": "Pular para o conteúdo principal",
|
||||||
"noData": "Sem dados",
|
"noData": "Sem dados",
|
||||||
"operation.add": "Adicionar",
|
"operation.add": "Adicionar",
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "Unele parametrii sunt invalizi și au fost eliminați.",
|
"modelProvider.parametersInvalidRemoved": "Unele parametrii sunt invalizi și au fost eliminați.",
|
||||||
"modelProvider.providerManaged": "Gestionat de furnizor",
|
"modelProvider.providerManaged": "Gestionat de furnizor",
|
||||||
"modelProvider.quotaLabel": "QUOTA",
|
"modelProvider.quotaLabel": "QUOTA",
|
||||||
|
"modelProvider.ranOutDate": "Epuizat la {{date}}",
|
||||||
"modelProvider.rerankModel.key": "Model de reordonare",
|
"modelProvider.rerankModel.key": "Model de reordonare",
|
||||||
"modelProvider.rerankModel.tip": "Modelul de reordonare va reordona lista de documente candidate pe baza potrivirii semantice cu interogarea utilizatorului, îmbunătățind rezultatele clasificării semantice",
|
"modelProvider.rerankModel.tip": "Modelul de reordonare va reordona lista de documente candidate pe baza potrivirii semantice cu interogarea utilizatorului, îmbunătățind rezultatele clasificării semantice",
|
||||||
"modelProvider.resetDate": "Resetare la {{date}}",
|
"modelProvider.resetDate": "Resetare la {{date}}",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "Model de conversie vorbire-la-text",
|
"modelProvider.ttsModel.key": "Model de conversie vorbire-la-text",
|
||||||
"modelProvider.ttsModel.tip": "Setați modelul implicit pentru intrarea de conversie vorbire-la-text în conversație.",
|
"modelProvider.ttsModel.tip": "Setați modelul implicit pentru intrarea de conversie vorbire-la-text în conversație.",
|
||||||
"modelProvider.upgradeForLoadBalancing": "Actualizați-vă planul pentru a activa Load Balancing.",
|
"modelProvider.upgradeForLoadBalancing": "Actualizați-vă planul pentru a activa Load Balancing.",
|
||||||
|
"modelProvider.used": "utilizate",
|
||||||
"navigation.skipToMain": "Sări la conținutul principal",
|
"navigation.skipToMain": "Sări la conținutul principal",
|
||||||
"noData": "Fără date",
|
"noData": "Fără date",
|
||||||
"operation.add": "Adaugă",
|
"operation.add": "Adaugă",
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "Некоторые параметры недействительны и были удалены",
|
"modelProvider.parametersInvalidRemoved": "Некоторые параметры недействительны и были удалены",
|
||||||
"modelProvider.providerManaged": "Управляется поставщиком",
|
"modelProvider.providerManaged": "Управляется поставщиком",
|
||||||
"modelProvider.quotaLabel": "QUOTA",
|
"modelProvider.quotaLabel": "QUOTA",
|
||||||
|
"modelProvider.ranOutDate": "Исчерпано {{date}}",
|
||||||
"modelProvider.rerankModel.key": "Модель повторного ранжирования",
|
"modelProvider.rerankModel.key": "Модель повторного ранжирования",
|
||||||
"modelProvider.rerankModel.tip": "Модель повторного ранжирования изменит порядок списка документов-кандидатов на основе семантического соответствия запросу пользователя, улучшая результаты семантического ранжирования",
|
"modelProvider.rerankModel.tip": "Модель повторного ранжирования изменит порядок списка документов-кандидатов на основе семантического соответствия запросу пользователя, улучшая результаты семантического ранжирования",
|
||||||
"modelProvider.resetDate": "Сброс {{date}}",
|
"modelProvider.resetDate": "Сброс {{date}}",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "Модель преобразования текста в речь",
|
"modelProvider.ttsModel.key": "Модель преобразования текста в речь",
|
||||||
"modelProvider.ttsModel.tip": "Установите модель по умолчанию для ввода текста в речь в разговоре.",
|
"modelProvider.ttsModel.tip": "Установите модель по умолчанию для ввода текста в речь в разговоре.",
|
||||||
"modelProvider.upgradeForLoadBalancing": "Обновите свой тарифный план, чтобы включить балансировку нагрузки.",
|
"modelProvider.upgradeForLoadBalancing": "Обновите свой тарифный план, чтобы включить балансировку нагрузки.",
|
||||||
|
"modelProvider.used": "использовано",
|
||||||
"navigation.skipToMain": "Перейти к основному содержанию",
|
"navigation.skipToMain": "Перейти к основному содержанию",
|
||||||
"noData": "Нет данных",
|
"noData": "Нет данных",
|
||||||
"operation.add": "Добавить",
|
"operation.add": "Добавить",
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "Nekateri parametri so neveljavni in so bili odstranjeni.",
|
"modelProvider.parametersInvalidRemoved": "Nekateri parametri so neveljavni in so bili odstranjeni.",
|
||||||
"modelProvider.providerManaged": "Upravljano s strani ponudnika",
|
"modelProvider.providerManaged": "Upravljano s strani ponudnika",
|
||||||
"modelProvider.quotaLabel": "QUOTA",
|
"modelProvider.quotaLabel": "QUOTA",
|
||||||
|
"modelProvider.ranOutDate": "Porabljeno {{date}}",
|
||||||
"modelProvider.rerankModel.key": "Model za prerazvrstitev",
|
"modelProvider.rerankModel.key": "Model za prerazvrstitev",
|
||||||
"modelProvider.rerankModel.tip": "Model za prerazvrstitev bo prerazporedil seznam kandidatskih dokumentov na podlagi semantične ujemanja z uporabniško poizvedbo, s čimer se izboljšajo rezultati semantičnega razvrščanja.",
|
"modelProvider.rerankModel.tip": "Model za prerazvrstitev bo prerazporedil seznam kandidatskih dokumentov na podlagi semantične ujemanja z uporabniško poizvedbo, s čimer se izboljšajo rezultati semantičnega razvrščanja.",
|
||||||
"modelProvider.resetDate": "Ponastavi {{date}}",
|
"modelProvider.resetDate": "Ponastavi {{date}}",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "Model za pretvorbo besedila v govor",
|
"modelProvider.ttsModel.key": "Model za pretvorbo besedila v govor",
|
||||||
"modelProvider.ttsModel.tip": "Nastavite privzeti model za pretvorbo besedila v govor v pogovoru.",
|
"modelProvider.ttsModel.tip": "Nastavite privzeti model za pretvorbo besedila v govor v pogovoru.",
|
||||||
"modelProvider.upgradeForLoadBalancing": "Nadgradite svoj načrt, da omogočite uravnoteženje obremenitev.",
|
"modelProvider.upgradeForLoadBalancing": "Nadgradite svoj načrt, da omogočite uravnoteženje obremenitev.",
|
||||||
|
"modelProvider.used": "porabljeno",
|
||||||
"navigation.skipToMain": "Preskoči na glavno vsebino",
|
"navigation.skipToMain": "Preskoči na glavno vsebino",
|
||||||
"noData": "Ni podatkov",
|
"noData": "Ni podatkov",
|
||||||
"operation.add": "Dodaj",
|
"operation.add": "Dodaj",
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "บางพารามิเตอร์ไม่ถูกต้องและถูกนำออก",
|
"modelProvider.parametersInvalidRemoved": "บางพารามิเตอร์ไม่ถูกต้องและถูกนำออก",
|
||||||
"modelProvider.providerManaged": "จัดการผู้ให้บริการ",
|
"modelProvider.providerManaged": "จัดการผู้ให้บริการ",
|
||||||
"modelProvider.quotaLabel": "QUOTA",
|
"modelProvider.quotaLabel": "QUOTA",
|
||||||
|
"modelProvider.ranOutDate": "หมดเมื่อ {{date}}",
|
||||||
"modelProvider.rerankModel.key": "จัดอันดับโมเดลใหม่",
|
"modelProvider.rerankModel.key": "จัดอันดับโมเดลใหม่",
|
||||||
"modelProvider.rerankModel.tip": "โมเดล Rerank จะจัดลําดับรายการเอกสารผู้สมัครใหม่ตามการจับคู่ความหมายกับการสืบค้นของผู้ใช้ ซึ่งช่วยปรับปรุงผลลัพธ์ของการจัดอันดับความหมาย",
|
"modelProvider.rerankModel.tip": "โมเดล Rerank จะจัดลําดับรายการเอกสารผู้สมัครใหม่ตามการจับคู่ความหมายกับการสืบค้นของผู้ใช้ ซึ่งช่วยปรับปรุงผลลัพธ์ของการจัดอันดับความหมาย",
|
||||||
"modelProvider.resetDate": "รีเซ็ตเมื่อ {{date}}",
|
"modelProvider.resetDate": "รีเซ็ตเมื่อ {{date}}",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "โมเดลการแปลงข้อความเป็นคําพูด",
|
"modelProvider.ttsModel.key": "โมเดลการแปลงข้อความเป็นคําพูด",
|
||||||
"modelProvider.ttsModel.tip": "ตั้งค่าโมเดลเริ่มต้นสําหรับการป้อนข้อมูลเป็นข้อความเป็นคําพูดในการสนทนา",
|
"modelProvider.ttsModel.tip": "ตั้งค่าโมเดลเริ่มต้นสําหรับการป้อนข้อมูลเป็นข้อความเป็นคําพูดในการสนทนา",
|
||||||
"modelProvider.upgradeForLoadBalancing": "อัปเกรดแผนของคุณเพื่อเปิดใช้งานการปรับสมดุลโหลด",
|
"modelProvider.upgradeForLoadBalancing": "อัปเกรดแผนของคุณเพื่อเปิดใช้งานการปรับสมดุลโหลด",
|
||||||
|
"modelProvider.used": "ใช้แล้ว",
|
||||||
"navigation.skipToMain": "ข้ามไปยังเนื้อหาหลัก",
|
"navigation.skipToMain": "ข้ามไปยังเนื้อหาหลัก",
|
||||||
"noData": "ไม่มีข้อมูล",
|
"noData": "ไม่มีข้อมูล",
|
||||||
"operation.add": "เพิ่ม",
|
"operation.add": "เพิ่ม",
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "Bazı parametreler geçersizdir ve kaldırılmıştır.",
|
"modelProvider.parametersInvalidRemoved": "Bazı parametreler geçersizdir ve kaldırılmıştır.",
|
||||||
"modelProvider.providerManaged": "Sağlayıcı tarafından yönetilen",
|
"modelProvider.providerManaged": "Sağlayıcı tarafından yönetilen",
|
||||||
"modelProvider.quotaLabel": "QUOTA",
|
"modelProvider.quotaLabel": "QUOTA",
|
||||||
|
"modelProvider.ranOutDate": "{{date}} tarihinde tükendi",
|
||||||
"modelProvider.rerankModel.key": "Yeniden Sıralama Modeli",
|
"modelProvider.rerankModel.key": "Yeniden Sıralama Modeli",
|
||||||
"modelProvider.rerankModel.tip": "Yeniden sıralama modeli, kullanıcı sorgusuyla anlam eşleştirmesine dayalı olarak aday belge listesini yeniden sıralayacak ve anlam sıralama sonuçlarını iyileştirecektir.",
|
"modelProvider.rerankModel.tip": "Yeniden sıralama modeli, kullanıcı sorgusuyla anlam eşleştirmesine dayalı olarak aday belge listesini yeniden sıralayacak ve anlam sıralama sonuçlarını iyileştirecektir.",
|
||||||
"modelProvider.resetDate": "{{date}} tarihinde sıfırla",
|
"modelProvider.resetDate": "{{date}} tarihinde sıfırla",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "Metinden Konuşmaya Modeli",
|
"modelProvider.ttsModel.key": "Metinden Konuşmaya Modeli",
|
||||||
"modelProvider.ttsModel.tip": "Konuşmada metinden konuşmaya giriş için varsayılan modeli ayarlayın.",
|
"modelProvider.ttsModel.tip": "Konuşmada metinden konuşmaya giriş için varsayılan modeli ayarlayın.",
|
||||||
"modelProvider.upgradeForLoadBalancing": "Yük Dengelemeyi etkinleştirmek için planınızı yükseltin.",
|
"modelProvider.upgradeForLoadBalancing": "Yük Dengelemeyi etkinleştirmek için planınızı yükseltin.",
|
||||||
|
"modelProvider.used": "kullanıldı",
|
||||||
"navigation.skipToMain": "Ana içeriğe geç",
|
"navigation.skipToMain": "Ana içeriğe geç",
|
||||||
"noData": "Veri yok",
|
"noData": "Veri yok",
|
||||||
"operation.add": "Ekle",
|
"operation.add": "Ekle",
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "Деякі параметри є недійсними і були видалені",
|
"modelProvider.parametersInvalidRemoved": "Деякі параметри є недійсними і були видалені",
|
||||||
"modelProvider.providerManaged": "Під управлінням провайдера",
|
"modelProvider.providerManaged": "Під управлінням провайдера",
|
||||||
"modelProvider.quotaLabel": "QUOTA",
|
"modelProvider.quotaLabel": "QUOTA",
|
||||||
|
"modelProvider.ranOutDate": "Вичерпано {{date}}",
|
||||||
"modelProvider.rerankModel.key": "Модель повторного ранжування",
|
"modelProvider.rerankModel.key": "Модель повторного ранжування",
|
||||||
"modelProvider.rerankModel.tip": "Модель повторного ранжування змінить порядок списку документів-кандидатів на основі семантичної відповідності запиту користувача, покращуючи результати семантичного ранжування.",
|
"modelProvider.rerankModel.tip": "Модель повторного ранжування змінить порядок списку документів-кандидатів на основі семантичної відповідності запиту користувача, покращуючи результати семантичного ранжування.",
|
||||||
"modelProvider.resetDate": "Скидання {{date}}",
|
"modelProvider.resetDate": "Скидання {{date}}",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "Модель перетворення тексту в мовлення",
|
"modelProvider.ttsModel.key": "Модель перетворення тексту в мовлення",
|
||||||
"modelProvider.ttsModel.tip": "Встановіть модель за замовчуванням для введення тексту в мовлення в розмові.",
|
"modelProvider.ttsModel.tip": "Встановіть модель за замовчуванням для введення тексту в мовлення в розмові.",
|
||||||
"modelProvider.upgradeForLoadBalancing": "Оновіть свій план, щоб увімкнути балансування навантаження.",
|
"modelProvider.upgradeForLoadBalancing": "Оновіть свій план, щоб увімкнути балансування навантаження.",
|
||||||
|
"modelProvider.used": "використано",
|
||||||
"navigation.skipToMain": "Перейти до основного вмісту",
|
"navigation.skipToMain": "Перейти до основного вмісту",
|
||||||
"noData": "Немає даних",
|
"noData": "Немає даних",
|
||||||
"operation.add": "Додати",
|
"operation.add": "Додати",
|
||||||
|
|||||||
@ -394,6 +394,7 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "Một số tham số không hợp lệ và đã được loại bỏ",
|
"modelProvider.parametersInvalidRemoved": "Một số tham số không hợp lệ và đã được loại bỏ",
|
||||||
"modelProvider.providerManaged": "Nhà cung cấp được quản lý",
|
"modelProvider.providerManaged": "Nhà cung cấp được quản lý",
|
||||||
"modelProvider.quotaLabel": "QUOTA",
|
"modelProvider.quotaLabel": "QUOTA",
|
||||||
|
"modelProvider.ranOutDate": "Hết vào {{date}}",
|
||||||
"modelProvider.rerankModel.key": "Mô hình Sắp xếp lại",
|
"modelProvider.rerankModel.key": "Mô hình Sắp xếp lại",
|
||||||
"modelProvider.rerankModel.tip": "Mô hình sắp xếp lại sẽ sắp xếp lại danh sách tài liệu ứng cử viên dựa trên sự phù hợp ngữ nghĩa với truy vấn của người dùng, cải thiện kết quả của việc xếp hạng ngữ nghĩa",
|
"modelProvider.rerankModel.tip": "Mô hình sắp xếp lại sẽ sắp xếp lại danh sách tài liệu ứng cử viên dựa trên sự phù hợp ngữ nghĩa với truy vấn của người dùng, cải thiện kết quả của việc xếp hạng ngữ nghĩa",
|
||||||
"modelProvider.resetDate": "Đặt lại vào {{date}}",
|
"modelProvider.resetDate": "Đặt lại vào {{date}}",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "Mô hình Văn bản thành Tiếng nói",
|
"modelProvider.ttsModel.key": "Mô hình Văn bản thành Tiếng nói",
|
||||||
"modelProvider.ttsModel.tip": "Thiết lập mô hình mặc định cho đầu vào văn bản thành tiếng nói trong cuộc trò chuyện.",
|
"modelProvider.ttsModel.tip": "Thiết lập mô hình mặc định cho đầu vào văn bản thành tiếng nói trong cuộc trò chuyện.",
|
||||||
"modelProvider.upgradeForLoadBalancing": "Nâng cấp gói của bạn để bật Cân bằng tải.",
|
"modelProvider.upgradeForLoadBalancing": "Nâng cấp gói của bạn để bật Cân bằng tải.",
|
||||||
|
"modelProvider.used": "đã dùng",
|
||||||
"navigation.skipToMain": "Chuyển đến nội dung chính",
|
"navigation.skipToMain": "Chuyển đến nội dung chính",
|
||||||
"noData": "Không có dữ liệu",
|
"noData": "Không có dữ liệu",
|
||||||
"operation.add": "Thêm",
|
"operation.add": "Thêm",
|
||||||
|
|||||||
@ -394,9 +394,10 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "部分参数无效,已移除",
|
"modelProvider.parametersInvalidRemoved": "部分参数无效,已移除",
|
||||||
"modelProvider.providerManaged": "由模型供应商管理",
|
"modelProvider.providerManaged": "由模型供应商管理",
|
||||||
"modelProvider.quotaLabel": "AI 消息额度",
|
"modelProvider.quotaLabel": "AI 消息额度",
|
||||||
|
"modelProvider.ranOutDate": "{{date}}用尽",
|
||||||
"modelProvider.rerankModel.key": "Rerank 模型",
|
"modelProvider.rerankModel.key": "Rerank 模型",
|
||||||
"modelProvider.rerankModel.tip": "重排序模型将根据候选文档列表与用户问题语义匹配度进行重新排序,从而改进语义排序的结果",
|
"modelProvider.rerankModel.tip": "重排序模型将根据候选文档列表与用户问题语义匹配度进行重新排序,从而改进语义排序的结果",
|
||||||
"modelProvider.resetDate": "于 {{date}} 重置",
|
"modelProvider.resetDate": "{{date}}重置",
|
||||||
"modelProvider.searchModels": "搜索模型...",
|
"modelProvider.searchModels": "搜索模型...",
|
||||||
"modelProvider.selectModel": "选择您的模型",
|
"modelProvider.selectModel": "选择您的模型",
|
||||||
"modelProvider.selector.aiCredits": "AI 消息额度",
|
"modelProvider.selector.aiCredits": "AI 消息额度",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "文本转语音模型",
|
"modelProvider.ttsModel.key": "文本转语音模型",
|
||||||
"modelProvider.ttsModel.tip": "设置对话中文字转语音输出的默认使用模型。",
|
"modelProvider.ttsModel.tip": "设置对话中文字转语音输出的默认使用模型。",
|
||||||
"modelProvider.upgradeForLoadBalancing": "升级以解锁负载均衡功能",
|
"modelProvider.upgradeForLoadBalancing": "升级以解锁负载均衡功能",
|
||||||
|
"modelProvider.used": "已用",
|
||||||
"navigation.skipToMain": "跳转到主要内容",
|
"navigation.skipToMain": "跳转到主要内容",
|
||||||
"noData": "暂无数据",
|
"noData": "暂无数据",
|
||||||
"operation.add": "添加",
|
"operation.add": "添加",
|
||||||
|
|||||||
@ -394,9 +394,10 @@
|
|||||||
"modelProvider.parametersInvalidRemoved": "一些參數無效,已被移除",
|
"modelProvider.parametersInvalidRemoved": "一些參數無效,已被移除",
|
||||||
"modelProvider.providerManaged": "提供者管理",
|
"modelProvider.providerManaged": "提供者管理",
|
||||||
"modelProvider.quotaLabel": "AI CREDITS",
|
"modelProvider.quotaLabel": "AI CREDITS",
|
||||||
|
"modelProvider.ranOutDate": "{{date}}用盡",
|
||||||
"modelProvider.rerankModel.key": "Rerank 模型",
|
"modelProvider.rerankModel.key": "Rerank 模型",
|
||||||
"modelProvider.rerankModel.tip": "重排序模型將根據候選文件列表與使用者問題語義匹配度進行重新排序,從而改進語義排序的結果",
|
"modelProvider.rerankModel.tip": "重排序模型將根據候選文件列表與使用者問題語義匹配度進行重新排序,從而改進語義排序的結果",
|
||||||
"modelProvider.resetDate": "於 {{date}} 重置",
|
"modelProvider.resetDate": "{{date}}重置",
|
||||||
"modelProvider.searchModels": "搜尋模型...",
|
"modelProvider.searchModels": "搜尋模型...",
|
||||||
"modelProvider.selectModel": "選擇您的模型",
|
"modelProvider.selectModel": "選擇您的模型",
|
||||||
"modelProvider.selector.aiCredits": "AI 額度",
|
"modelProvider.selector.aiCredits": "AI 額度",
|
||||||
@ -433,6 +434,7 @@
|
|||||||
"modelProvider.ttsModel.key": "文字轉語音模型",
|
"modelProvider.ttsModel.key": "文字轉語音模型",
|
||||||
"modelProvider.ttsModel.tip": "設定對話中文字轉語音輸出的預設使用模型。",
|
"modelProvider.ttsModel.tip": "設定對話中文字轉語音輸出的預設使用模型。",
|
||||||
"modelProvider.upgradeForLoadBalancing": "升級您的計劃以啟用 Load Balancing。",
|
"modelProvider.upgradeForLoadBalancing": "升級您的計劃以啟用 Load Balancing。",
|
||||||
|
"modelProvider.used": "已用",
|
||||||
"navigation.skipToMain": "跳至主要內容",
|
"navigation.skipToMain": "跳至主要內容",
|
||||||
"noData": "無資料",
|
"noData": "無資料",
|
||||||
"operation.add": "新增",
|
"operation.add": "新增",
|
||||||
|
|||||||
@ -72,6 +72,7 @@ export type ICurrentWorkspace = Omit<IWorkspace, 'current'> & {
|
|||||||
providers: Provider[]
|
providers: Provider[]
|
||||||
trial_credits: number
|
trial_credits: number
|
||||||
trial_credits_used: number
|
trial_credits_used: number
|
||||||
|
trial_credits_exhausted_at: number
|
||||||
next_credit_reset_date: number
|
next_credit_reset_date: number
|
||||||
trial_end_reason?: string
|
trial_end_reason?: string
|
||||||
custom_config?: {
|
custom_config?: {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user