mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-06-25 17:17:19 +00:00
Compare commits
3 Commits
version-bu
...
codex/fix-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ede5556644 | ||
|
|
da55529d23 | ||
|
|
52d430d1b6 |
5
.github/workflows/ci-tests-e2e-coverage.yaml
vendored
5
.github/workflows/ci-tests-e2e-coverage.yaml
vendored
@@ -88,9 +88,9 @@ jobs:
|
||||
- name: Strip non-source entries from coverage
|
||||
if: steps.coverage-shards.outputs.has-coverage == 'true'
|
||||
run: |
|
||||
# Drop served bundle scripts (localhost-8188/assets/*.js) that V8 records but have no source file on disk, which would abort genhtml.
|
||||
lcov --remove coverage/playwright/coverage.lcov \
|
||||
'*localhost-8188*' \
|
||||
'assets/images/*' \
|
||||
-o coverage/playwright/coverage.lcov \
|
||||
--ignore-errors unused
|
||||
wc -l coverage/playwright/coverage.lcov
|
||||
@@ -121,7 +121,8 @@ jobs:
|
||||
--title "ComfyUI E2E Coverage" \
|
||||
--no-function-coverage \
|
||||
--precision 1 \
|
||||
--ignore-errors source,unmapped
|
||||
--ignore-errors source,unmapped,range \
|
||||
--synthesize-missing
|
||||
|
||||
- name: Upload HTML report artifact
|
||||
if: steps.coverage-shards.outputs.has-coverage == 'true'
|
||||
|
||||
@@ -47,6 +47,11 @@ test.describe('Download page @smoke', () => {
|
||||
const downloadBtn = hero.getByRole('link', { name: /DOWNLOAD DESKTOP/i })
|
||||
await expect(downloadBtn).toBeVisible()
|
||||
await expect(downloadBtn).toHaveAttribute('target', '_blank')
|
||||
await expect(downloadBtn).toHaveAttribute(
|
||||
'href',
|
||||
'https://comfy.org/download/windows/nsis/x64'
|
||||
)
|
||||
await expect(downloadBtn).toHaveAttribute('data-astro-prefetch', 'false')
|
||||
|
||||
const githubBtn = hero.getByRole('link', { name: /INSTALL FROM GITHUB/i })
|
||||
await expect(githubBtn).toBeVisible()
|
||||
@@ -73,7 +78,7 @@ test.describe('Download page @smoke', () => {
|
||||
})
|
||||
|
||||
const windowsBtn = hero.locator(
|
||||
'a[href="https://download.comfy.org/windows/nsis/x64"]'
|
||||
'a[href="https://comfy.org/download/windows/nsis/x64"]'
|
||||
)
|
||||
await expect(windowsBtn).toBeVisible()
|
||||
await expect(windowsBtn).toHaveText(/DOWNLOAD DESKTOP/i)
|
||||
|
||||
@@ -72,6 +72,7 @@ const buttons = computed<ButtonSpec[]>(() => {
|
||||
size="lg"
|
||||
:class="customClass"
|
||||
:aria-label="btn.ariaLabel"
|
||||
:data-astro-prefetch="btn.key === 'windows' ? 'false' : undefined"
|
||||
@click="captureDownloadClick(btn.key)"
|
||||
>
|
||||
<span class="inline-flex items-center gap-2">
|
||||
|
||||
@@ -3,7 +3,7 @@ import { computed, onMounted, ref } from 'vue'
|
||||
import { externalLinks } from '@/config/routes'
|
||||
|
||||
export const downloadUrls = {
|
||||
windows: 'https://download.comfy.org/windows/nsis/x64',
|
||||
windows: 'https://comfy.org/download/windows/nsis/x64',
|
||||
macArm: 'https://download.comfy.org/mac/dmg/arm64'
|
||||
} as const
|
||||
|
||||
|
||||
165
browser_tests/tests/billingFacadeConsumers.spec.ts
Normal file
165
browser_tests/tests/billingFacadeConsumers.spec.ts
Normal file
@@ -0,0 +1,165 @@
|
||||
import { expect } from '@playwright/test'
|
||||
import type { Page } from '@playwright/test'
|
||||
|
||||
import type { CloudSubscriptionStatusResponse } from '@/platform/cloud/subscription/composables/useSubscription'
|
||||
import type { RemoteConfig } from '@/platform/remoteConfig/types'
|
||||
|
||||
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
|
||||
import { mockSystemStats } from '@e2e/fixtures/data/systemStats'
|
||||
import { CloudAuthHelper } from '@e2e/fixtures/helpers/CloudAuthHelper'
|
||||
|
||||
/**
|
||||
* Billing facade consumers — FE-933 (B3) regression.
|
||||
*
|
||||
* The repointed surfaces (avatar popover tier badge / balance, free-tier
|
||||
* dialog renewal date) must keep rendering from `useBillingContext`, which in
|
||||
* a personal workspace routes through the legacy `/customers/*` endpoints
|
||||
* (mocked here). Drives a raw `page` (not the `comfyPage` fixture) so the
|
||||
* cloud app boots against fully mocked endpoints — same pattern as
|
||||
* creditsTile.spec.ts. `team_workspaces_enabled: false` keeps the topbar on
|
||||
* the legacy popover variant that FE-933 repointed.
|
||||
*/
|
||||
const APP_URL = process.env.PLAYWRIGHT_TEST_URL || 'http://localhost:8188'
|
||||
|
||||
const jsonRoute = (body: unknown) => ({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
|
||||
async function mockCloudBoot(
|
||||
page: Page,
|
||||
subscriptionStatus: CloudSubscriptionStatusResponse,
|
||||
remoteConfig: RemoteConfig = { team_workspaces_enabled: false }
|
||||
) {
|
||||
await page.route('**/api/features', (r) => r.fulfill(jsonRoute(remoteConfig)))
|
||||
await page.route('**/api/system_stats', (r) =>
|
||||
r.fulfill(jsonRoute(mockSystemStats))
|
||||
)
|
||||
await page.route('**/api/users', (r) =>
|
||||
r.fulfill(
|
||||
jsonRoute({
|
||||
storage: 'server',
|
||||
migrated: true,
|
||||
users: { 'test-user-e2e': 'E2E Test User' }
|
||||
})
|
||||
)
|
||||
)
|
||||
// TutorialCompleted suppresses the new-user template browser, whose modal
|
||||
// overlay would otherwise intercept clicks on the topbar.
|
||||
await page.route('**/api/settings', (r) =>
|
||||
r.fulfill(jsonRoute({ 'Comfy.TutorialCompleted': true }))
|
||||
)
|
||||
await page.route('**/api/userdata**', (r) => r.fulfill(jsonRoute([])))
|
||||
await page.route('**/api/extensions', (r) => r.fulfill(jsonRoute([])))
|
||||
await page.route('**/api/object_info', (r) => r.fulfill(jsonRoute({})))
|
||||
await page.route('**/api/global_subgraphs', (r) => r.fulfill(jsonRoute({})))
|
||||
await page.route('**/api/i18n', (r) => r.fulfill(jsonRoute({})))
|
||||
await page.route('**/api/auth/session', (r) =>
|
||||
r.fulfill(jsonRoute({ token: 'mock-workspace-token' }))
|
||||
)
|
||||
await page.route('**/releases**', (r) => r.fulfill(jsonRoute([])))
|
||||
|
||||
// Single personal workspace: keeps the billing facade on the legacy
|
||||
// `/customers/*` path when team workspaces are enabled.
|
||||
await page.route('**/api/workspaces', (r) =>
|
||||
r.fulfill(
|
||||
jsonRoute({
|
||||
workspaces: [
|
||||
{
|
||||
id: 'ws-personal',
|
||||
name: 'Personal Workspace',
|
||||
type: 'personal',
|
||||
role: 'owner'
|
||||
}
|
||||
]
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
await page.route('**/customers/cloud-subscription-status', (r) =>
|
||||
r.fulfill(jsonRoute(subscriptionStatus))
|
||||
)
|
||||
await page.route('**/customers/balance', (r) =>
|
||||
r.fulfill(
|
||||
jsonRoute({
|
||||
amount_micros: 6000, // -> 12,660 credits
|
||||
currency: 'usd',
|
||||
effective_balance_micros: 6000
|
||||
})
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
async function bootApp(page: Page) {
|
||||
const auth = new CloudAuthHelper(page)
|
||||
await auth.mockAuth()
|
||||
|
||||
await page.addInitScript(() => {
|
||||
localStorage.setItem('Comfy.userId', 'test-user-e2e')
|
||||
})
|
||||
|
||||
await page.goto(APP_URL)
|
||||
await page.waitForFunction(() => !!window.app?.extensionManager, null, {
|
||||
timeout: 45_000
|
||||
})
|
||||
}
|
||||
|
||||
test.describe('Billing facade consumers (FE-933)', { tag: '@cloud' }, () => {
|
||||
test('avatar popover renders tier badge and balance from the facade', async ({
|
||||
page
|
||||
}) => {
|
||||
test.setTimeout(60_000)
|
||||
|
||||
await mockCloudBoot(page, {
|
||||
is_active: true,
|
||||
subscription_tier: 'PRO',
|
||||
subscription_duration: 'MONTHLY',
|
||||
renewal_date: '2099-02-20T10:00:00Z',
|
||||
end_date: null
|
||||
})
|
||||
await bootApp(page)
|
||||
|
||||
await page.getByRole('button', { name: 'Current user' }).click()
|
||||
const popover = page.locator('.current-user-popover')
|
||||
await expect(popover).toBeVisible()
|
||||
|
||||
await expect(popover.getByText('Pro', { exact: true })).toBeVisible()
|
||||
await expect(popover.getByText('12,660')).toBeVisible()
|
||||
await expect(popover.getByTestId('add-credits-button')).toBeVisible()
|
||||
})
|
||||
|
||||
test('free-tier dialog shows the renewal date from the facade', async ({
|
||||
page
|
||||
}) => {
|
||||
test.setTimeout(60_000)
|
||||
|
||||
// Boots with team workspaces enabled (production shape); the facade still
|
||||
// routes a personal workspace through `/customers/*`. With subscription
|
||||
// gating on, an inactive FREE user gets the "Subscribe to run" button,
|
||||
// which opens the free-tier dialog on click. (refreshRemoteConfig
|
||||
// overwrites window.__CONFIG__ from /api/features, so the flags must come
|
||||
// from the features mock, not an init script.)
|
||||
await mockCloudBoot(
|
||||
page,
|
||||
{
|
||||
is_active: false,
|
||||
subscription_tier: 'FREE',
|
||||
subscription_duration: 'MONTHLY',
|
||||
// 10:00Z keeps the en-US calendar date stable across CI timezones.
|
||||
renewal_date: '2099-02-20T10:00:00Z',
|
||||
end_date: null
|
||||
},
|
||||
{ team_workspaces_enabled: true, subscription_required: true }
|
||||
)
|
||||
await bootApp(page)
|
||||
|
||||
await page.getByTestId('subscribe-to-run-button').click()
|
||||
|
||||
// T5: the dialog must source the date from facade renewalDate — when this
|
||||
// line read the legacy store it silently vanished for team users.
|
||||
await expect(
|
||||
page.getByText('Your credits refresh on Feb 20, 2099.')
|
||||
).toBeVisible()
|
||||
})
|
||||
})
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@comfyorg/comfyui-frontend",
|
||||
"version": "1.47.4",
|
||||
"version": "1.47.3",
|
||||
"private": true,
|
||||
"description": "Official front-end implementation of ComfyUI",
|
||||
"homepage": "https://comfy.org",
|
||||
|
||||
@@ -1,37 +1,18 @@
|
||||
import { render, screen } from '@testing-library/vue'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { afterAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { h, ref } from 'vue'
|
||||
import { defineComponent, h, ref } from 'vue'
|
||||
import { createI18n } from 'vue-i18n'
|
||||
|
||||
import { formatCreditsFromCents } from '@/base/credits/comfyCredits'
|
||||
import type { BalanceInfo, SubscriptionInfo } from '@/composables/billing/types'
|
||||
import enMessages from '@/locales/en/main.json' with { type: 'json' }
|
||||
|
||||
import CurrentUserPopoverLegacy from './CurrentUserPopoverLegacy.vue'
|
||||
|
||||
// Mock all firebase modules
|
||||
vi.mock('firebase/app', () => ({
|
||||
initializeApp: vi.fn(),
|
||||
getApp: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('firebase/auth', () => ({
|
||||
getAuth: vi.fn(),
|
||||
setPersistence: vi.fn(),
|
||||
browserLocalPersistence: {},
|
||||
onAuthStateChanged: vi.fn(),
|
||||
signInWithEmailAndPassword: vi.fn(),
|
||||
signOut: vi.fn()
|
||||
}))
|
||||
|
||||
// Mock pinia
|
||||
vi.mock('pinia')
|
||||
|
||||
// Mock showSettingsDialog and showTopUpCreditsDialog
|
||||
const mockShowSettingsDialog = vi.fn()
|
||||
const mockShowTopUpCreditsDialog = vi.fn()
|
||||
|
||||
// Mock the settings dialog composable
|
||||
vi.mock('@/platform/settings/composables/useSettingsDialog', () => ({
|
||||
useSettingsDialog: vi.fn(() => ({
|
||||
show: mockShowSettingsDialog,
|
||||
@@ -40,7 +21,6 @@ vi.mock('@/platform/settings/composables/useSettingsDialog', () => ({
|
||||
}))
|
||||
}))
|
||||
|
||||
// Mock window.open
|
||||
const originalWindowOpen = window.open
|
||||
beforeEach(() => {
|
||||
window.open = vi.fn()
|
||||
@@ -50,7 +30,6 @@ afterAll(() => {
|
||||
window.open = originalWindowOpen
|
||||
})
|
||||
|
||||
// Mock the useCurrentUser composable
|
||||
const mockHandleSignOut = vi.fn()
|
||||
vi.mock('@/composables/auth/useCurrentUser', () => ({
|
||||
useCurrentUser: vi.fn(() => ({
|
||||
@@ -61,60 +40,50 @@ vi.mock('@/composables/auth/useCurrentUser', () => ({
|
||||
}))
|
||||
}))
|
||||
|
||||
// Mock the useAuthActions composable
|
||||
const mockLogout = vi.fn()
|
||||
vi.mock('@/composables/auth/useAuthActions', () => ({
|
||||
useAuthActions: vi.fn(() => ({
|
||||
fetchBalance: vi.fn().mockResolvedValue(undefined),
|
||||
logout: mockLogout
|
||||
}))
|
||||
}))
|
||||
|
||||
// Mock the dialog service
|
||||
vi.mock('@/services/dialogService', () => ({
|
||||
useDialogService: vi.fn(() => ({
|
||||
showTopUpCreditsDialog: mockShowTopUpCreditsDialog
|
||||
}))
|
||||
}))
|
||||
|
||||
// Mock the authStore with hoisted state for per-test manipulation
|
||||
const mockAuthStoreState = vi.hoisted(() => ({
|
||||
balance: {
|
||||
amount_micros: 100_000,
|
||||
effective_balance_micros: 100_000,
|
||||
currency: 'usd'
|
||||
} as {
|
||||
amount_micros?: number
|
||||
effective_balance_micros?: number
|
||||
currency: string
|
||||
},
|
||||
isFetchingBalance: false
|
||||
}))
|
||||
function makeSubscription(
|
||||
overrides: Partial<SubscriptionInfo> = {}
|
||||
): SubscriptionInfo {
|
||||
return {
|
||||
isActive: true,
|
||||
tier: 'CREATOR',
|
||||
duration: 'MONTHLY',
|
||||
planSlug: null,
|
||||
renewalDate: null,
|
||||
endDate: null,
|
||||
isCancelled: false,
|
||||
hasFunds: true,
|
||||
...overrides
|
||||
}
|
||||
}
|
||||
|
||||
vi.mock('@/stores/authStore', () => ({
|
||||
useAuthStore: vi.fn(() => ({
|
||||
getAuthHeader: vi
|
||||
.fn()
|
||||
.mockResolvedValue({ Authorization: 'Bearer mock-token' }),
|
||||
balance: mockAuthStoreState.balance,
|
||||
isFetchingBalance: mockAuthStoreState.isFetchingBalance
|
||||
}))
|
||||
}))
|
||||
|
||||
// Mock the useSubscription composable
|
||||
const mockFetchStatus = vi.fn().mockResolvedValue(undefined)
|
||||
const mockFetchBalance = vi.fn().mockResolvedValue(undefined)
|
||||
const mockIsActiveSubscription = ref(true)
|
||||
const mockIsFreeTier = ref(false)
|
||||
vi.mock('@/platform/cloud/subscription/composables/useSubscription', () => ({
|
||||
useSubscription: vi.fn(() => ({
|
||||
isActiveSubscription: ref(true),
|
||||
const mockTier = ref<SubscriptionInfo['tier']>('CREATOR')
|
||||
const mockSubscription = ref<SubscriptionInfo | null>(makeSubscription())
|
||||
const mockBalance = ref<BalanceInfo | null>(null)
|
||||
const mockIsLoading = ref(false)
|
||||
|
||||
vi.mock('@/composables/billing/useBillingContext', () => ({
|
||||
useBillingContext: vi.fn(() => ({
|
||||
isActiveSubscription: mockIsActiveSubscription,
|
||||
isFreeTier: mockIsFreeTier,
|
||||
subscriptionTierName: ref('Creator'),
|
||||
subscriptionTier: ref('CREATOR'),
|
||||
fetchStatus: mockFetchStatus
|
||||
tier: mockTier,
|
||||
subscription: mockSubscription,
|
||||
balance: mockBalance,
|
||||
isLoading: mockIsLoading,
|
||||
fetchStatus: mockFetchStatus,
|
||||
fetchBalance: mockFetchBalance
|
||||
}))
|
||||
}))
|
||||
|
||||
// Mock the useSubscriptionDialog composable
|
||||
const mockShowPricingTable = vi.fn()
|
||||
vi.mock(
|
||||
'@/platform/cloud/subscription/composables/useSubscriptionDialog',
|
||||
@@ -127,7 +96,6 @@ vi.mock(
|
||||
})
|
||||
)
|
||||
|
||||
// Mock UserAvatar component
|
||||
vi.mock('@/components/common/UserAvatar.vue', () => ({
|
||||
default: {
|
||||
name: 'UserAvatarMock',
|
||||
@@ -137,22 +105,10 @@ vi.mock('@/components/common/UserAvatar.vue', () => ({
|
||||
}
|
||||
}))
|
||||
|
||||
// Mock UserCredit component
|
||||
vi.mock('@/components/common/UserCredit.vue', () => ({
|
||||
default: {
|
||||
name: 'UserCreditMock',
|
||||
render() {
|
||||
return h('div', 'Credit: 100')
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
// Mock formatCreditsFromCents
|
||||
vi.mock('@/base/credits/comfyCredits', () => ({
|
||||
formatCreditsFromCents: vi.fn(({ cents }) => (cents / 100).toString())
|
||||
}))
|
||||
|
||||
// Mock useExternalLink
|
||||
vi.mock('@/composables/useExternalLink', () => ({
|
||||
useExternalLink: vi.fn(() => ({
|
||||
buildDocsUrl: vi.fn((path) => `https://docs.comfy.org${path}`),
|
||||
@@ -162,14 +118,12 @@ vi.mock('@/composables/useExternalLink', () => ({
|
||||
}))
|
||||
}))
|
||||
|
||||
// Mock useTelemetry
|
||||
vi.mock('@/platform/telemetry', () => ({
|
||||
useTelemetry: vi.fn(() => ({
|
||||
trackAddApiCreditButtonClicked: vi.fn()
|
||||
}))
|
||||
}))
|
||||
|
||||
// Mock isCloud with hoisted state for per-test toggling
|
||||
const mockIsCloud = vi.hoisted(() => ({ value: true }))
|
||||
vi.mock('@/platform/distribution/types', () => ({
|
||||
get isCloud() {
|
||||
@@ -178,25 +132,37 @@ vi.mock('@/platform/distribution/types', () => ({
|
||||
}))
|
||||
|
||||
vi.mock('@/platform/cloud/subscription/components/SubscribeButton.vue', () => ({
|
||||
default: {
|
||||
default: defineComponent({
|
||||
name: 'SubscribeButtonMock',
|
||||
render() {
|
||||
return h('div', 'Subscribe Button')
|
||||
emits: ['subscribed'],
|
||||
setup(_, { emit }) {
|
||||
return () =>
|
||||
h(
|
||||
'button',
|
||||
{
|
||||
'data-testid': 'subscribe-button-mock',
|
||||
onClick: () => emit('subscribed')
|
||||
},
|
||||
'Subscribe Button'
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}))
|
||||
|
||||
describe('CurrentUserPopoverLegacy', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
mockIsCloud.value = true
|
||||
mockIsActiveSubscription.value = true
|
||||
mockIsFreeTier.value = false
|
||||
mockAuthStoreState.balance = {
|
||||
amount_micros: 100_000,
|
||||
effective_balance_micros: 100_000,
|
||||
mockTier.value = 'CREATOR'
|
||||
mockSubscription.value = makeSubscription()
|
||||
mockBalance.value = {
|
||||
amountMicros: 100_000,
|
||||
effectiveBalanceMicros: 100_000,
|
||||
currency: 'usd'
|
||||
}
|
||||
mockAuthStoreState.isFetchingBalance = false
|
||||
mockIsLoading.value = false
|
||||
})
|
||||
|
||||
function renderComponent() {
|
||||
@@ -230,7 +196,47 @@ describe('CurrentUserPopoverLegacy', () => {
|
||||
expect(screen.getByText('test@example.com')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('calls formatCreditsFromCents with correct parameters and displays formatted credits', () => {
|
||||
it('fetches the balance through the billing facade on mount', () => {
|
||||
renderComponent()
|
||||
|
||||
expect(mockFetchBalance).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('refreshes subscription status through the billing facade after subscribing', async () => {
|
||||
mockIsActiveSubscription.value = false
|
||||
const { user } = renderComponent()
|
||||
|
||||
await user.click(screen.getByTestId('subscribe-button-mock'))
|
||||
|
||||
expect(mockFetchStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
describe('subscription tier badge', () => {
|
||||
it('renders the tier name derived from the facade tier', () => {
|
||||
renderComponent()
|
||||
|
||||
expect(screen.getByText('Creator')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('renders the yearly tier name when the facade subscription is annual', () => {
|
||||
mockSubscription.value = makeSubscription({ duration: 'ANNUAL' })
|
||||
|
||||
renderComponent()
|
||||
|
||||
expect(screen.getByText('Creator Yearly')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('hides the badge when the facade reports no tier', () => {
|
||||
mockTier.value = null
|
||||
mockSubscription.value = null
|
||||
|
||||
renderComponent()
|
||||
|
||||
expect(screen.queryByText('Creator')).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
it('formats and displays the facade balance', () => {
|
||||
renderComponent()
|
||||
|
||||
expect(formatCreditsFromCents).toHaveBeenCalledWith({
|
||||
@@ -245,6 +251,14 @@ describe('CurrentUserPopoverLegacy', () => {
|
||||
expect(screen.getByText('1000')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('shows a skeleton instead of the balance while billing is loading', () => {
|
||||
mockIsLoading.value = true
|
||||
|
||||
renderComponent()
|
||||
|
||||
expect(screen.queryByText('1000')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('renders logout menu item with correct text', () => {
|
||||
renderComponent()
|
||||
|
||||
@@ -324,11 +338,11 @@ describe('CurrentUserPopoverLegacy', () => {
|
||||
expect(onClose).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
describe('effective_balance_micros handling', () => {
|
||||
it('uses effective_balance_micros when present (positive balance)', () => {
|
||||
mockAuthStoreState.balance = {
|
||||
amount_micros: 200_000,
|
||||
effective_balance_micros: 150_000,
|
||||
describe('facade balance handling', () => {
|
||||
it('uses effectiveBalanceMicros when present (positive balance)', () => {
|
||||
mockBalance.value = {
|
||||
amountMicros: 200_000,
|
||||
effectiveBalanceMicros: 150_000,
|
||||
currency: 'usd'
|
||||
}
|
||||
|
||||
@@ -345,10 +359,10 @@ describe('CurrentUserPopoverLegacy', () => {
|
||||
expect(screen.getByText('1500')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('uses effective_balance_micros when zero', () => {
|
||||
mockAuthStoreState.balance = {
|
||||
amount_micros: 100_000,
|
||||
effective_balance_micros: 0,
|
||||
it('uses effectiveBalanceMicros when zero', () => {
|
||||
mockBalance.value = {
|
||||
amountMicros: 100_000,
|
||||
effectiveBalanceMicros: 0,
|
||||
currency: 'usd'
|
||||
}
|
||||
|
||||
@@ -365,10 +379,10 @@ describe('CurrentUserPopoverLegacy', () => {
|
||||
expect(screen.getByText('0')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('uses effective_balance_micros when negative', () => {
|
||||
mockAuthStoreState.balance = {
|
||||
amount_micros: 0,
|
||||
effective_balance_micros: -50_000,
|
||||
it('uses effectiveBalanceMicros when negative', () => {
|
||||
mockBalance.value = {
|
||||
amountMicros: 0,
|
||||
effectiveBalanceMicros: -50_000,
|
||||
currency: 'usd'
|
||||
}
|
||||
|
||||
@@ -385,9 +399,9 @@ describe('CurrentUserPopoverLegacy', () => {
|
||||
expect(screen.getByText('-500')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('falls back to amount_micros when effective_balance_micros is missing', () => {
|
||||
mockAuthStoreState.balance = {
|
||||
amount_micros: 100_000,
|
||||
it('falls back to amountMicros when effectiveBalanceMicros is missing', () => {
|
||||
mockBalance.value = {
|
||||
amountMicros: 100_000,
|
||||
currency: 'usd'
|
||||
}
|
||||
|
||||
@@ -404,10 +418,8 @@ describe('CurrentUserPopoverLegacy', () => {
|
||||
expect(screen.getByText('1000')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('falls back to 0 when both effective_balance_micros and amount_micros are missing', () => {
|
||||
mockAuthStoreState.balance = {
|
||||
currency: 'usd'
|
||||
}
|
||||
it('falls back to 0 when the facade reports no balance', () => {
|
||||
mockBalance.value = null
|
||||
|
||||
renderComponent()
|
||||
|
||||
@@ -466,8 +478,11 @@ describe('CurrentUserPopoverLegacy', () => {
|
||||
})
|
||||
|
||||
it('hides subscribe button', () => {
|
||||
mockIsActiveSubscription.value = false
|
||||
renderComponent()
|
||||
expect(screen.queryByText('Subscribe Button')).not.toBeInTheDocument()
|
||||
expect(
|
||||
screen.queryByTestId('subscribe-button-mock')
|
||||
).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('still shows partner nodes menu item', () => {
|
||||
|
||||
@@ -32,12 +32,7 @@
|
||||
<!-- Credits Section -->
|
||||
<div v-if="isActiveSubscription" class="flex items-center gap-2 px-4 py-2">
|
||||
<i class="icon-[lucide--component] text-sm text-amber-400" />
|
||||
<Skeleton
|
||||
v-if="authStore.isFetchingBalance"
|
||||
width="4rem"
|
||||
height="1.25rem"
|
||||
class="w-full"
|
||||
/>
|
||||
<Skeleton v-if="isLoading" width="4rem" height="1.25rem" class="w-full" />
|
||||
<span v-else class="text-base font-semibold text-base-foreground">{{
|
||||
formattedBalance
|
||||
}}</span>
|
||||
@@ -162,16 +157,15 @@ import { formatCreditsFromCents } from '@/base/credits/comfyCredits'
|
||||
import UserAvatar from '@/components/common/UserAvatar.vue'
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import { useCurrentUser } from '@/composables/auth/useCurrentUser'
|
||||
import { useAuthActions } from '@/composables/auth/useAuthActions'
|
||||
import { useBillingContext } from '@/composables/billing/useBillingContext'
|
||||
import { useExternalLink } from '@/composables/useExternalLink'
|
||||
import SubscribeButton from '@/platform/cloud/subscription/components/SubscribeButton.vue'
|
||||
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
|
||||
import { useSubscriptionDialog } from '@/platform/cloud/subscription/composables/useSubscriptionDialog'
|
||||
import { isCloud } from '@/platform/distribution/types'
|
||||
import { useTelemetry } from '@/platform/telemetry'
|
||||
import { useSettingsDialog } from '@/platform/settings/composables/useSettingsDialog'
|
||||
import { useWorkspaceTierLabel } from '@/platform/workspace/composables/useWorkspaceTierLabel'
|
||||
import { useDialogService } from '@/services/dialogService'
|
||||
import { useAuthStore } from '@/stores/authStore'
|
||||
|
||||
const emit = defineEmits<{
|
||||
close: []
|
||||
@@ -181,25 +175,29 @@ const { buildDocsUrl, docsPaths } = useExternalLink()
|
||||
|
||||
const { userDisplayName, userEmail, userPhotoUrl, handleSignOut } =
|
||||
useCurrentUser()
|
||||
const authActions = useAuthActions()
|
||||
const authStore = useAuthStore()
|
||||
const settingsDialog = useSettingsDialog()
|
||||
const dialogService = useDialogService()
|
||||
const {
|
||||
isActiveSubscription,
|
||||
isFreeTier,
|
||||
subscriptionTierName,
|
||||
subscriptionTier,
|
||||
fetchStatus
|
||||
} = useSubscription()
|
||||
tier,
|
||||
subscription,
|
||||
balance,
|
||||
isLoading,
|
||||
fetchStatus,
|
||||
fetchBalance
|
||||
} = useBillingContext()
|
||||
const { formatTierName } = useWorkspaceTierLabel()
|
||||
const subscriptionDialog = useSubscriptionDialog()
|
||||
const { locale } = useI18n()
|
||||
|
||||
const subscriptionTierName = computed(() =>
|
||||
formatTierName(tier.value, subscription.value?.duration === 'ANNUAL')
|
||||
)
|
||||
|
||||
const formattedBalance = computed(() => {
|
||||
const cents =
|
||||
authStore.balance?.effective_balance_micros ??
|
||||
authStore.balance?.amount_micros ??
|
||||
0
|
||||
balance.value?.effectiveBalanceMicros ?? balance.value?.amountMicros ?? 0
|
||||
return formatCreditsFromCents({
|
||||
cents,
|
||||
locale: locale.value,
|
||||
@@ -211,12 +209,12 @@ const formattedBalance = computed(() => {
|
||||
})
|
||||
|
||||
const canUpgrade = computed(() => {
|
||||
const tier = subscriptionTier.value
|
||||
const currentTier = tier.value
|
||||
return (
|
||||
tier === 'FREE' ||
|
||||
tier === 'FOUNDERS_EDITION' ||
|
||||
tier === 'STANDARD' ||
|
||||
tier === 'CREATOR'
|
||||
currentTier === 'FREE' ||
|
||||
currentTier === 'FOUNDERS_EDITION' ||
|
||||
currentTier === 'STANDARD' ||
|
||||
currentTier === 'CREATOR'
|
||||
)
|
||||
})
|
||||
|
||||
@@ -270,6 +268,6 @@ const handleSubscribed = async () => {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
void authActions.fetchBalance()
|
||||
void fetchBalance()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -92,7 +92,6 @@
|
||||
"errorUserTokenAccessDenied": "رمز API الخاص بك لا يملك صلاحية الوصول إلى هذا المورد. يرجى التحقق من أذونات الرمز.",
|
||||
"errorUserTokenInvalid": "رمز API المخزن غير صالح أو منتهي الصلاحية. يرجى تحديث الرمز في الإعدادات.",
|
||||
"failedToCreateNode": "فشل إنشاء العقدة. يرجى المحاولة مرة أخرى أو التحقق من وحدة التحكم للحصول على التفاصيل.",
|
||||
"failedToSetModelValue": "تمت إضافة العقدة، لكن لم يتم تعيين النموذج تلقائيًا. تحقق من وحدة التحكم لمزيد من التفاصيل.",
|
||||
"fileFormats": "تنسيقات الملفات",
|
||||
"fileName": "اسم الملف",
|
||||
"fileSize": "حجم الملف",
|
||||
@@ -242,8 +241,7 @@
|
||||
"auth/user-not-found": "لم يتم العثور على حساب بهذا البريد الإلكتروني. هل ترغب في إنشاء حساب جديد؟",
|
||||
"auth/weak-password": "كلمة المرور ضعيفة جداً. يرجى استخدام كلمة مرور أقوى تحتوي على 6 أحرف على الأقل.",
|
||||
"auth/wrong-password": "كلمة المرور التي أدخلتها غير صحيحة. يرجى المحاولة مرة أخرى.",
|
||||
"generic": "حدث خطأ أثناء تسجيل الدخول. يرجى المحاولة مرة أخرى.",
|
||||
"signupBlocked": "تعذر إنشاء حسابك الآن. يرجى المحاولة لاحقًا. إذا استمرت المشكلة، راسل support@comfy.org."
|
||||
"generic": "حدث خطأ أثناء تسجيل الدخول. يرجى المحاولة مرة أخرى."
|
||||
},
|
||||
"login": {
|
||||
"andText": "و",
|
||||
@@ -348,17 +346,6 @@
|
||||
"x": "س",
|
||||
"y": "ص"
|
||||
},
|
||||
"boundingBoxes": {
|
||||
"clearAll": "مسح الكل",
|
||||
"clickRegionToEdit": "انقر على منطقة لتعديلها.",
|
||||
"colors": "لوحة الألوان",
|
||||
"descLabel": "الوصف",
|
||||
"descPlaceholder": "وصف هذه المنطقة",
|
||||
"textLabel": "نص",
|
||||
"textPlaceholder": "النص المراد عرضه (كما هو)",
|
||||
"typeObj": "كائن",
|
||||
"typeText": "نص"
|
||||
},
|
||||
"breadcrumbsMenu": {
|
||||
"app": "التطبيق",
|
||||
"blueprint": "المخطط",
|
||||
@@ -768,13 +755,6 @@
|
||||
"creditsAvailable": "الرصيد المتاح",
|
||||
"details": "التفاصيل",
|
||||
"eventType": "نوع الحدث",
|
||||
"eventTypes": {
|
||||
"accountCreated": "تم إنشاء الحساب",
|
||||
"apiNodeUsage": "استخدام عقدة الشريك",
|
||||
"apiUsage": "استخدام API",
|
||||
"creditAdded": "تمت إضافة أرصدة",
|
||||
"gpuUsage": "استخدام GPU"
|
||||
},
|
||||
"faqs": "الأسئلة المتكررة",
|
||||
"invoiceHistory": "تاريخ الفواتير",
|
||||
"lastUpdated": "آخر تحديث",
|
||||
@@ -1850,35 +1830,6 @@
|
||||
"zoomOptions": "خيارات التكبير",
|
||||
"zoomOut": "تصغير"
|
||||
},
|
||||
"hdrViewer": {
|
||||
"channel": "القناة",
|
||||
"channels": {
|
||||
"a": "ألفا",
|
||||
"b": "B",
|
||||
"g": "G",
|
||||
"luminance": "السطوع",
|
||||
"r": "R",
|
||||
"rgb": "RGB"
|
||||
},
|
||||
"clipWarnings": "تحذيرات القص",
|
||||
"dither": "تنعيم",
|
||||
"exposure": "التعريض",
|
||||
"failedToLoad": "فشل في تحميل صورة HDR",
|
||||
"fitView": "ملاءمة",
|
||||
"hdrImage": "صورة HDR",
|
||||
"histogram": "مخطط بياني",
|
||||
"inf": "لانهاية",
|
||||
"max": "الحد الأقصى",
|
||||
"mean": "المتوسط",
|
||||
"min": "الحد الأدنى",
|
||||
"nan": "غير رقم",
|
||||
"normalizeExposure": "التعريض التلقائي",
|
||||
"openInHdrViewer": "افتح في عارض HDR",
|
||||
"resolution": "الدقة",
|
||||
"sourceGamut": "مجال الألوان الأصلي",
|
||||
"stdDev": "الانحراف المعياري",
|
||||
"title": "عارض HDR"
|
||||
},
|
||||
"help": {
|
||||
"helpCenterMenu": "قائمة مركز المساعدة",
|
||||
"recentReleases": "الإصدارات الأخيرة"
|
||||
@@ -3006,10 +2957,6 @@
|
||||
"uploadError": "فشل في رفع صورة الرسام: {status} - {statusText}",
|
||||
"width": "العرض"
|
||||
},
|
||||
"palette": {
|
||||
"addColor": "إضافة لون",
|
||||
"swatchTitle": "انقر للتعديل · اسحب لإعادة الترتيب · انقر بزر الفأرة الأيمن للإزالة"
|
||||
},
|
||||
"progressToast": {
|
||||
"allDownloadsCompleted": "اكتملت جميع التنزيلات",
|
||||
"downloadingModel": "جاري تنزيل النموذج...",
|
||||
@@ -3755,27 +3702,6 @@
|
||||
"customLoRAsLabel": "استيراد LoRAs الخاصة بك",
|
||||
"description": "اختر الخطة الأنسب لك",
|
||||
"descriptionWorkspace": "اختر أفضل خطة لمساحة العمل الخاصة بك",
|
||||
"downgrade": {
|
||||
"body": "سيتم إزالة جميع الأعضاء الآخرين من مساحة العمل هذه فورًا.",
|
||||
"confirm": "تغيير الخطة",
|
||||
"confirmationPhrase": "أنا أفهم",
|
||||
"confirmationPrompt": "اكتب \"{phrase}\" للتأكيد.",
|
||||
"failed": "فشل في تغيير الخطة",
|
||||
"failedAfterMemberRemoval": "تمت إزالة أعضاء الفريق، لكن لم يكتمل تغيير الخطة — يرجى المحاولة مرة أخرى أو التواصل مع الدعم",
|
||||
"memberRemovalFailed": "تعذر إزالة {email} من الفريق — قد يكون بعض الأعضاء قد أُزيلوا بالفعل ولم يتم تغيير خطتك",
|
||||
"notAllowed": "تغيير الخطة غير متاح",
|
||||
"paymentMethodRequired": "مطلوب وسيلة دفع لتغيير الخطط",
|
||||
"paymentPageBlocked": "تعذر فتح صفحة الدفع — يرجى المحاولة مرة أخرى",
|
||||
"title": "تغيير إلى خطة {plan}؟"
|
||||
},
|
||||
"enterprise": {
|
||||
"cta": "اعرف المزيد",
|
||||
"flexibility": "تبحث عن مزيد من المرونة أو ميزات مخصصة؟",
|
||||
"name": "المؤسسات",
|
||||
"needMoreMembers": "تحتاج إلى المزيد من الأعضاء؟",
|
||||
"reachOut": "تواصل معنا ولنحدد موعدًا للحديث."
|
||||
},
|
||||
"everythingInPlus": "كل ما في {plan}، بالإضافة إلى:",
|
||||
"expiresDate": "ينتهي في {date}",
|
||||
"freeTier": {
|
||||
"description": "تشمل خطتك المجانية {credits} رصيد شهري لتجربة Comfy Cloud.",
|
||||
@@ -3822,7 +3748,6 @@
|
||||
"messageSupport": "مراسلة الدعم",
|
||||
"monthly": "شهري",
|
||||
"monthlyBonusDescription": "مكافأة الرصيد الشهرية",
|
||||
"monthlyCredits": "رصيد شهري",
|
||||
"monthlyCreditsInfo": "يتم تحديث هذا الرصيد شهريًا ولا ينتقل للشهر التالي",
|
||||
"monthlyCreditsLabel": "الرصيد الشهري",
|
||||
"monthlyCreditsPerMemberLabel": "الرصيد الشهري / عضو",
|
||||
@@ -3835,13 +3760,7 @@
|
||||
"partnerNodesCredits": "رصيد العقد الشريكة",
|
||||
"partnerNodesDescription": "لتشغيل النماذج التجارية/المملوكة",
|
||||
"perMonth": "دولار أمريكي / شهر",
|
||||
"personalHeader": "الخطط الشخصية للاستخدام الفردي فقط. {action}",
|
||||
"personalHeaderAction": "لإضافة زملاء، اشترك في خطة الفريق.",
|
||||
"personalWorkspace": "مساحة العمل الشخصية",
|
||||
"planScope": {
|
||||
"personal": "للاستخدام الشخصي",
|
||||
"team": "للفرق"
|
||||
},
|
||||
"plansAndPricing": "الخطط والأسعار",
|
||||
"plansForWorkspace": "الخطط لمساحة العمل {workspace}",
|
||||
"prepaidCreditsInfo": "رصيد تم شراؤه بشكل منفصل ولا ينتهي صلاحيته",
|
||||
@@ -3852,10 +3771,8 @@
|
||||
"confirm": "تأكيد",
|
||||
"confirmPayment": "تأكيد الدفع",
|
||||
"confirmPlanChange": "تأكيد تغيير الخطة",
|
||||
"creditsRefillTo": "سيتم إعادة تعبئة الرصيد إلى",
|
||||
"eachMonthCreditsRefill": "يتم إعادة تعبئة الرصيد كل شهر إلى",
|
||||
"ends": "ينتهي في {date}",
|
||||
"everyMonthStarting": "كل شهر ابتداءً من {date}",
|
||||
"hideFeatures": "إخفاء الميزات",
|
||||
"nextPaymentDue": "الدفع القادم مستحق في {date}. يمكنك الإلغاء في أي وقت.",
|
||||
"perMember": "/ عضو",
|
||||
@@ -3865,18 +3782,10 @@
|
||||
"showMoreFeatures": "عرض المزيد من الميزات",
|
||||
"starting": "يبدأ في {date}",
|
||||
"startingToday": "يبدأ اليوم",
|
||||
"subscribeToPlan": "اشترك في {plan}",
|
||||
"switchToPlan": "انتقل إلى {plan}",
|
||||
"terms": "الشروط",
|
||||
"termsAgreement": "بالمتابعة، أنت توافق على {terms} و{privacy} الخاصة بـ Comfy Org.",
|
||||
"totalDueToday": "الإجمالي المستحق اليوم",
|
||||
"youllBeCharged": "سيتم خصم"
|
||||
"totalDueToday": "الإجمالي المستحق اليوم"
|
||||
},
|
||||
"pricingBlurb": "*استنادًا إلى هذا القالب، {seeDetails}. تواصل معنا لـ {questions} أو {enterpriseDiscussions}. لمزيد من تفاصيل الأسعار، {clickHere}.",
|
||||
"pricingBlurbClickHere": "اضغط هنا",
|
||||
"pricingBlurbEnterprise": "مناقشات المؤسسات",
|
||||
"pricingBlurbQuestions": "الاستفسارات",
|
||||
"pricingBlurbSeeDetails": "اعرض التفاصيل",
|
||||
"refreshCredits": "تحديث الرصيد",
|
||||
"renewsDate": "تجديد في {date}",
|
||||
"required": {
|
||||
@@ -3890,8 +3799,6 @@
|
||||
"resubscribe": "إعادة الاشتراك",
|
||||
"resubscribeSuccess": "تمت إعادة تفعيل الاشتراك بنجاح",
|
||||
"resubscribeTo": "إعادة الاشتراك في {plan}",
|
||||
"saveYearly": "وفر ٢٠٪",
|
||||
"saveYearlyUpTo": "وفر حتى ٢٠٪",
|
||||
"soloUseOnly": "للاستخدام الفردي فقط",
|
||||
"subscribeForMore": "ترقية",
|
||||
"subscribeNow": "اشترك الآن",
|
||||
@@ -3900,34 +3807,10 @@
|
||||
"subscribeToRun": "اشتراك",
|
||||
"subscribeToRunFull": "الاشتراك للتشغيل",
|
||||
"subscriptionRequiredMessage": "الاشتراك مطلوب للأعضاء لتشغيل سير العمل على السحابة",
|
||||
"success": {
|
||||
"allSet": "تم كل شيء بنجاح",
|
||||
"planUpdated": "تم تحديث خطتك بنجاح.",
|
||||
"receiptEmailed": "تم إرسال إيصال إلى بريدك الإلكتروني."
|
||||
},
|
||||
"teamHeader": "للفرق التي ترغب في التعاون. تحتاج إلى المزيد من الأعضاء؟ {learnMore} حول المؤسسات.",
|
||||
"teamHeaderLearnMore": "اعرف المزيد",
|
||||
"teamPlan": {
|
||||
"changePlan": "تغيير الخطة",
|
||||
"checkoutComingSoon": "الدفع لخطة الفريق قادم قريبًا.",
|
||||
"comingSoonLabel": "قريبًا:",
|
||||
"cta": "اشترك في خطة الفريق السنوية",
|
||||
"ctaMonthly": "اشترك في خطة الفريق الشهرية",
|
||||
"currentPlan": "الخطة الحالية",
|
||||
"detailsTitle": "التفاصيل",
|
||||
"name": "خطة الفريق",
|
||||
"perkConcurrentRuns": "يمكن للأعضاء تشغيل سير العمل في نفس الوقت",
|
||||
"perkInviteMembers": "دعوة أعضاء الفريق",
|
||||
"perkProjectAssets": "إدارة المشاريع والأصول",
|
||||
"perkRolePermissions": "أذونات حسب الدور",
|
||||
"perkSharedPool": "رصيد مشترك لجميع الأعضاء",
|
||||
"tagline": "اختر اشتراك الرصيد الشهري الخاص بك. احصل على خصم أكبر مع اشتراك رصيد أكبر."
|
||||
},
|
||||
"teamWorkspace": "مساحة عمل الفريق",
|
||||
"tierNameYearly": "{name} سنوي",
|
||||
"tiers": {
|
||||
"creator": {
|
||||
"feature1": "استيراد نماذجك الخاصة",
|
||||
"name": "المُبدع"
|
||||
},
|
||||
"founder": {
|
||||
@@ -3937,12 +3820,9 @@
|
||||
"name": "مجاني"
|
||||
},
|
||||
"pro": {
|
||||
"feature1": "مدة تشغيل سير عمل أطول (حتى ساعة واحدة)",
|
||||
"name": "احترافي"
|
||||
},
|
||||
"standard": {
|
||||
"feature1": "حد أقصى لمدة تشغيل سير العمل ٣٠ دقيقة",
|
||||
"feature2": "إضافة المزيد من الرصيد في أي وقت",
|
||||
"name": "قياسي"
|
||||
}
|
||||
},
|
||||
@@ -3955,7 +3835,6 @@
|
||||
"upgradeToAddCredits": "قم بالترقية لإضافة أرصدة",
|
||||
"usdPerMonth": "دولار أمريكي / شهريًا",
|
||||
"usdPerMonthPerMember": "دولار أمريكي / شهر / عضو",
|
||||
"videoEstimate": "ينتج تقريبًا ~{count} فيديوهات ٥ ثوانٍ*",
|
||||
"videoEstimateExplanation": "هذه التقديرات مبنية على قالب Wan 2.2 لتحويل الصورة إلى فيديو باستخدام الإعدادات الافتراضية (5 ثوانٍ، 640x640، 16 إطار/ثانية، 4 خطوات أخذ عينات).",
|
||||
"videoEstimateHelp": "مزيد من التفاصيل حول هذا القالب",
|
||||
"videoEstimateLabel": "العدد التقريبي لمقاطع الفيديو 5 ثوانٍ التي يتم إنشاؤها باستخدام قالب Wan 2.2 لتحويل الصورة إلى فيديو",
|
||||
@@ -3965,11 +3844,10 @@
|
||||
"viewMoreDetails": "عرض المزيد من التفاصيل",
|
||||
"viewMoreDetailsPlans": "عرض المزيد من التفاصيل حول الخطط والأسعار",
|
||||
"viewUsageHistory": "عرض سجل الاستخدام",
|
||||
"whatsIncluded": "ما يتضمنه:",
|
||||
"workspaceNotSubscribed": "هذه مساحة العمل ليست مشتركة",
|
||||
"yearly": "سنوي",
|
||||
"yearlyCreditsLabel": "إجمالي الرصيد السنوي",
|
||||
"yearlyDiscount": "خصم 20%",
|
||||
"saveYearly": "وفّر 20%",
|
||||
"yourPlanIncludes": "خطتك تشمل:"
|
||||
},
|
||||
"tabMenu": {
|
||||
|
||||
@@ -895,8 +895,8 @@
|
||||
"nodes": "Nodes",
|
||||
"models": "Models",
|
||||
"assets": "Assets",
|
||||
"workflows": "Workflows",
|
||||
"templates": "Templates",
|
||||
"workflows": "Work\u00adflows",
|
||||
"templates": "Tem\u00adplates",
|
||||
"console": "Console",
|
||||
"menu": "Menu",
|
||||
"imported": "Imported",
|
||||
@@ -2563,6 +2563,7 @@
|
||||
"billedYearly": "{total} Billed yearly",
|
||||
"monthly": "Monthly",
|
||||
"yearly": "Yearly",
|
||||
"saveYearly": "Save 20%",
|
||||
"tierNameYearly": "{name} Yearly",
|
||||
"messageSupport": "Message support",
|
||||
"invoiceHistory": "Invoice history",
|
||||
@@ -2573,7 +2574,6 @@
|
||||
"benefit2": "Up to 1 hour runtime per job on Pro",
|
||||
"benefit3": "Bring your own models (Creator & Pro)"
|
||||
},
|
||||
"yearlyDiscount": "20% DISCOUNT",
|
||||
"tiers": {
|
||||
"free": {
|
||||
"name": "Free"
|
||||
@@ -2636,6 +2636,7 @@
|
||||
"everythingInPlus": "Everything in {plan}, plus:",
|
||||
"monthlyCredits": "monthly credits",
|
||||
"videoEstimate": "Generates ~{count} 5s videos*",
|
||||
"saveYearly": "Save 20%",
|
||||
"saveYearlyUpTo": "Save up to 20%",
|
||||
"teamPlan": {
|
||||
"name": "Team Plan",
|
||||
@@ -2989,7 +2990,7 @@
|
||||
"share": "Share"
|
||||
},
|
||||
"shortcuts": {
|
||||
"shortcuts": "Shortcuts",
|
||||
"shortcuts": "Short\u00adcuts",
|
||||
"essentials": "Essential",
|
||||
"viewControls": "View Controls",
|
||||
"manageShortcuts": "Manage Shortcuts",
|
||||
|
||||
@@ -5419,7 +5419,7 @@
|
||||
},
|
||||
"resolution": {
|
||||
"name": "resolution",
|
||||
"tooltip": "The resolution of the output video. 1080p is only available for grok-imagine-video-1.5."
|
||||
"tooltip": "The resolution of the output video."
|
||||
},
|
||||
"aspect_ratio": {
|
||||
"name": "aspect_ratio",
|
||||
|
||||
@@ -92,7 +92,6 @@
|
||||
"errorUserTokenAccessDenied": "Tu token de API no tiene acceso a este recurso. Por favor, revisa los permisos de tu token.",
|
||||
"errorUserTokenInvalid": "Tu token de API almacenado no es válido o ha expirado. Por favor, actualiza tu token en la configuración.",
|
||||
"failedToCreateNode": "No se pudo crear el nodo. Inténtalo de nuevo o revisa la consola para más detalles.",
|
||||
"failedToSetModelValue": "Nodo añadido, pero su modelo no pudo establecerse automáticamente. Consulta la consola para más detalles.",
|
||||
"fileFormats": "Formatos de archivo",
|
||||
"fileName": "Nombre del archivo",
|
||||
"fileSize": "Tamaño del archivo",
|
||||
@@ -242,8 +241,7 @@
|
||||
"auth/user-not-found": "No se encontró ninguna cuenta con este correo electrónico. ¿Te gustaría crear una nueva cuenta?",
|
||||
"auth/weak-password": "La contraseña es demasiado débil. Por favor, usa una contraseña más segura con al menos 6 caracteres.",
|
||||
"auth/wrong-password": "La contraseña que ingresaste es incorrecta. Por favor, inténtalo de nuevo.",
|
||||
"generic": "Ocurrió un error al iniciar sesión. Por favor, inténtalo de nuevo.",
|
||||
"signupBlocked": "No pudimos crear tu cuenta en este momento. Por favor, inténtalo de nuevo más tarde. Si el problema persiste, escribe a support@comfy.org."
|
||||
"generic": "Ocurrió un error al iniciar sesión. Por favor, inténtalo de nuevo."
|
||||
},
|
||||
"login": {
|
||||
"andText": "y",
|
||||
@@ -348,17 +346,6 @@
|
||||
"x": "X",
|
||||
"y": "Y"
|
||||
},
|
||||
"boundingBoxes": {
|
||||
"clearAll": "Borrar todo",
|
||||
"clickRegionToEdit": "Haz clic en una región para editarla.",
|
||||
"colors": "paleta_de_colores",
|
||||
"descLabel": "descripción",
|
||||
"descPlaceholder": "descripción de esta región",
|
||||
"textLabel": "Texto",
|
||||
"textPlaceholder": "texto a renderizar (literal)",
|
||||
"typeObj": "obj",
|
||||
"typeText": "texto"
|
||||
},
|
||||
"breadcrumbsMenu": {
|
||||
"app": "Aplicación",
|
||||
"blueprint": "Plano",
|
||||
@@ -768,13 +755,6 @@
|
||||
"creditsAvailable": "Créditos disponibles",
|
||||
"details": "Detalles",
|
||||
"eventType": "Tipo de evento",
|
||||
"eventTypes": {
|
||||
"accountCreated": "Cuenta creada",
|
||||
"apiNodeUsage": "Uso de nodo asociado",
|
||||
"apiUsage": "Uso de API",
|
||||
"creditAdded": "Créditos añadidos",
|
||||
"gpuUsage": "Uso de GPU"
|
||||
},
|
||||
"faqs": "Preguntas frecuentes",
|
||||
"invoiceHistory": "Historial de facturas",
|
||||
"lastUpdated": "Última actualización",
|
||||
@@ -1850,35 +1830,6 @@
|
||||
"zoomOptions": "Opciones de Zoom",
|
||||
"zoomOut": "Alejar"
|
||||
},
|
||||
"hdrViewer": {
|
||||
"channel": "Canal",
|
||||
"channels": {
|
||||
"a": "Alfa",
|
||||
"b": "B",
|
||||
"g": "G",
|
||||
"luminance": "Luminancia",
|
||||
"r": "R",
|
||||
"rgb": "RGB"
|
||||
},
|
||||
"clipWarnings": "Avisos de recorte",
|
||||
"dither": "Difuminado",
|
||||
"exposure": "Exposición",
|
||||
"failedToLoad": "No se pudo cargar la imagen HDR",
|
||||
"fitView": "Ajustar",
|
||||
"hdrImage": "Imagen HDR",
|
||||
"histogram": "Histograma",
|
||||
"inf": "Inf",
|
||||
"max": "Máx",
|
||||
"mean": "Media",
|
||||
"min": "Mín",
|
||||
"nan": "NaN",
|
||||
"normalizeExposure": "Exposición automática",
|
||||
"openInHdrViewer": "Abrir en el visor HDR",
|
||||
"resolution": "Resolución",
|
||||
"sourceGamut": "Gama de origen",
|
||||
"stdDev": "Desv. estándar",
|
||||
"title": "Visor HDR"
|
||||
},
|
||||
"help": {
|
||||
"helpCenterMenu": "Menú del Centro de Ayuda",
|
||||
"recentReleases": "Lanzamientos recientes"
|
||||
@@ -3006,10 +2957,6 @@
|
||||
"uploadError": "Error al cargar la imagen del pintor: {status} - {statusText}",
|
||||
"width": "Ancho"
|
||||
},
|
||||
"palette": {
|
||||
"addColor": "Agregar un color",
|
||||
"swatchTitle": "Haz clic para editar · arrastra para reordenar · clic derecho para eliminar"
|
||||
},
|
||||
"progressToast": {
|
||||
"allDownloadsCompleted": "Todas las descargas completadas",
|
||||
"downloadingModel": "Descargando modelo...",
|
||||
@@ -3755,27 +3702,6 @@
|
||||
"customLoRAsLabel": "Importa tus propios LoRAs",
|
||||
"description": "Elige el mejor plan para ti",
|
||||
"descriptionWorkspace": "Elige el mejor plan para tu espacio de trabajo",
|
||||
"downgrade": {
|
||||
"body": "Todos los demás miembros de este espacio de trabajo serán eliminados inmediatamente.",
|
||||
"confirm": "Cambiar plan",
|
||||
"confirmationPhrase": "Entiendo",
|
||||
"confirmationPrompt": "Escribe \"{phrase}\" para confirmar.",
|
||||
"failed": "No se pudo cambiar el plan",
|
||||
"failedAfterMemberRemoval": "Los miembros del equipo fueron eliminados, pero el cambio de plan no se completó — por favor, inténtalo de nuevo o contacta con soporte",
|
||||
"memberRemovalFailed": "No se pudo eliminar a {email} del equipo — algunos miembros pueden haber sido eliminados y tu plan no fue cambiado",
|
||||
"notAllowed": "Este cambio de plan no está disponible",
|
||||
"paymentMethodRequired": "Se requiere un método de pago para cambiar de plan",
|
||||
"paymentPageBlocked": "No se pudo abrir la página de pago — por favor, inténtalo de nuevo",
|
||||
"title": "¿Cambiar al plan {plan}?"
|
||||
},
|
||||
"enterprise": {
|
||||
"cta": "Saber más",
|
||||
"flexibility": "¿Buscas más flexibilidad o funciones personalizadas?",
|
||||
"name": "Enterprise",
|
||||
"needMoreMembers": "¿Necesitas más miembros?",
|
||||
"reachOut": "Contáctanos y agendemos una charla."
|
||||
},
|
||||
"everythingInPlus": "Todo en {plan}, además:",
|
||||
"expiresDate": "Caduca el {date}",
|
||||
"freeTier": {
|
||||
"description": "Tu plan gratuito incluye {credits} créditos cada mes para probar Comfy Cloud.",
|
||||
@@ -3822,7 +3748,6 @@
|
||||
"messageSupport": "Contactar con soporte",
|
||||
"monthly": "Mensual",
|
||||
"monthlyBonusDescription": "Bono de créditos mensual",
|
||||
"monthlyCredits": "créditos mensuales",
|
||||
"monthlyCreditsInfo": "Estos créditos se renuevan mensualmente y no se acumulan",
|
||||
"monthlyCreditsLabel": "Créditos mensuales",
|
||||
"monthlyCreditsPerMemberLabel": "Créditos mensuales / miembro",
|
||||
@@ -3835,13 +3760,7 @@
|
||||
"partnerNodesCredits": "Créditos de Nodos de Socio",
|
||||
"partnerNodesDescription": "Para ejecutar modelos comerciales/propietarios",
|
||||
"perMonth": "USD / mes",
|
||||
"personalHeader": "Los planes personales son solo para uso individual. {action}",
|
||||
"personalHeaderAction": "Para agregar compañeros, suscríbete al plan de equipo.",
|
||||
"personalWorkspace": "Espacio de trabajo personal",
|
||||
"planScope": {
|
||||
"personal": "Para uso personal",
|
||||
"team": "Para equipos"
|
||||
},
|
||||
"plansAndPricing": "Planes y precios",
|
||||
"plansForWorkspace": "Planes para {workspace}",
|
||||
"prepaidCreditsInfo": "Créditos comprados por separado que no expiran",
|
||||
@@ -3852,10 +3771,8 @@
|
||||
"confirm": "Confirmar",
|
||||
"confirmPayment": "Confirma tu pago",
|
||||
"confirmPlanChange": "Confirma el cambio de plan",
|
||||
"creditsRefillTo": "Los créditos se recargan hasta",
|
||||
"eachMonthCreditsRefill": "Cada mes los créditos se recargan a",
|
||||
"ends": "Finaliza el {date}",
|
||||
"everyMonthStarting": "Cada mes a partir del {date}",
|
||||
"hideFeatures": "Ocultar funciones",
|
||||
"nextPaymentDue": "Próximo pago el {date}. Cancela en cualquier momento.",
|
||||
"perMember": "/ miembro",
|
||||
@@ -3865,18 +3782,10 @@
|
||||
"showMoreFeatures": "Mostrar más funciones",
|
||||
"starting": "Comienza el {date}",
|
||||
"startingToday": "Comienza hoy",
|
||||
"subscribeToPlan": "Suscribirse al plan {plan}",
|
||||
"switchToPlan": "Cambiar al plan {plan}",
|
||||
"terms": "Términos",
|
||||
"termsAgreement": "Al continuar, aceptas los {terms} y la {privacy} de Comfy Org.",
|
||||
"totalDueToday": "Total a pagar hoy",
|
||||
"youllBeCharged": "Se te cobrará"
|
||||
"totalDueToday": "Total a pagar hoy"
|
||||
},
|
||||
"pricingBlurb": "*Basado en esta plantilla, {seeDetails}. Contáctanos para {questions} o {enterpriseDiscussions}. Para más detalles sobre precios, {clickHere}.",
|
||||
"pricingBlurbClickHere": "haz clic aquí",
|
||||
"pricingBlurbEnterprise": "discusiones enterprise",
|
||||
"pricingBlurbQuestions": "preguntas",
|
||||
"pricingBlurbSeeDetails": "ver detalles",
|
||||
"refreshCredits": "Actualizar créditos",
|
||||
"renewsDate": "Se renueva el {date}",
|
||||
"required": {
|
||||
@@ -3890,8 +3799,6 @@
|
||||
"resubscribe": "Volver a suscribirse",
|
||||
"resubscribeSuccess": "¡Suscripción reactivada correctamente!",
|
||||
"resubscribeTo": "Volver a suscribirse a {plan}",
|
||||
"saveYearly": "Ahorra 20%",
|
||||
"saveYearlyUpTo": "Ahorra hasta un 20%",
|
||||
"soloUseOnly": "Solo para uso individual",
|
||||
"subscribeForMore": "Mejorar",
|
||||
"subscribeNow": "Suscribirse Ahora",
|
||||
@@ -3900,34 +3807,10 @@
|
||||
"subscribeToRun": "Suscribirse",
|
||||
"subscribeToRunFull": "Suscribirse a Ejecutar",
|
||||
"subscriptionRequiredMessage": "Se requiere una suscripción para que los miembros ejecuten flujos de trabajo en la nube",
|
||||
"success": {
|
||||
"allSet": "Todo listo",
|
||||
"planUpdated": "Tu plan se ha actualizado correctamente.",
|
||||
"receiptEmailed": "Se ha enviado un recibo a tu correo electrónico."
|
||||
},
|
||||
"teamHeader": "Para equipos que desean colaborar. ¿Necesitas más miembros? {learnMore} sobre enterprise.",
|
||||
"teamHeaderLearnMore": "Saber más",
|
||||
"teamPlan": {
|
||||
"changePlan": "Cambiar plan",
|
||||
"checkoutComingSoon": "El pago del plan de equipo estará disponible próximamente.",
|
||||
"comingSoonLabel": "Próximamente:",
|
||||
"cta": "Suscribirse al plan anual de equipo",
|
||||
"ctaMonthly": "Suscribirse al plan mensual de equipo",
|
||||
"currentPlan": "Plan actual",
|
||||
"detailsTitle": "Detalles",
|
||||
"name": "Plan de equipo",
|
||||
"perkConcurrentRuns": "Los miembros pueden ejecutar flujos de trabajo simultáneamente",
|
||||
"perkInviteMembers": "Invita a miembros del equipo",
|
||||
"perkProjectAssets": "Gestión de proyectos y recursos",
|
||||
"perkRolePermissions": "Permisos basados en roles",
|
||||
"perkSharedPool": "Bolsa de créditos compartida para todos los miembros",
|
||||
"tagline": "Elige tu propia suscripción mensual de créditos. Obtén un mayor descuento con una suscripción de más créditos."
|
||||
},
|
||||
"teamWorkspace": "Espacio de trabajo en equipo",
|
||||
"tierNameYearly": "{name} Anual",
|
||||
"tiers": {
|
||||
"creator": {
|
||||
"feature1": "Importa tus propios modelos",
|
||||
"name": "Creador"
|
||||
},
|
||||
"founder": {
|
||||
@@ -3937,12 +3820,9 @@
|
||||
"name": "Gratis"
|
||||
},
|
||||
"pro": {
|
||||
"feature1": "Mayor tiempo de ejecución del flujo de trabajo (hasta 1 hora)",
|
||||
"name": "Pro"
|
||||
},
|
||||
"standard": {
|
||||
"feature1": "Tiempo máximo de ejecución del flujo de trabajo de 30 minutos",
|
||||
"feature2": "Agrega más créditos en cualquier momento",
|
||||
"name": "Estándar"
|
||||
}
|
||||
},
|
||||
@@ -3955,7 +3835,6 @@
|
||||
"upgradeToAddCredits": "Mejorar para añadir créditos",
|
||||
"usdPerMonth": "USD / mes",
|
||||
"usdPerMonthPerMember": "USD / mes / miembro",
|
||||
"videoEstimate": "Genera ~{count} videos de 5s*",
|
||||
"videoEstimateExplanation": "Estas estimaciones se basan en la plantilla Wan 2.2 Imagen a Video usando la configuración predeterminada (5 segundos, 640x640, 16fps, muestreo de 4 pasos).",
|
||||
"videoEstimateHelp": "Más detalles sobre esta plantilla",
|
||||
"videoEstimateLabel": "Cantidad aprox. de videos de 5s generados con la plantilla Wan 2.2 Imagen a Video",
|
||||
@@ -3965,11 +3844,10 @@
|
||||
"viewMoreDetails": "Ver más detalles",
|
||||
"viewMoreDetailsPlans": "Ver más detalles sobre planes y precios",
|
||||
"viewUsageHistory": "Ver historial de uso",
|
||||
"whatsIncluded": "Qué está incluido:",
|
||||
"workspaceNotSubscribed": "Este espacio de trabajo no tiene una suscripción",
|
||||
"yearly": "Anual",
|
||||
"yearlyCreditsLabel": "Total de créditos anuales",
|
||||
"yearlyDiscount": "20% DESCUENTO",
|
||||
"saveYearly": "Ahorra 20%",
|
||||
"yourPlanIncludes": "Tu plan incluye:"
|
||||
},
|
||||
"tabMenu": {
|
||||
|
||||
@@ -92,7 +92,6 @@
|
||||
"errorUserTokenAccessDenied": "توکن API شما به این منبع دسترسی ندارد. لطفاً مجوزهای توکن خود را بررسی کنید.",
|
||||
"errorUserTokenInvalid": "توکن API ذخیرهشده شما نامعتبر یا منقضی شده است. لطفاً توکن خود را در تنظیمات بهروزرسانی کنید.",
|
||||
"failedToCreateNode": "ایجاد node ناموفق بود. لطفاً دوباره تلاش کنید یا کنسول را بررسی کنید.",
|
||||
"failedToSetModelValue": "Node اضافه شد، اما مدل آن بهصورت خودکار تنظیم نشد. برای جزئیات بیشتر کنسول را بررسی کنید.",
|
||||
"fileFormats": "فرمتهای فایل",
|
||||
"fileName": "نام فایل",
|
||||
"fileSize": "اندازه فایل",
|
||||
@@ -242,8 +241,7 @@
|
||||
"auth/user-not-found": "حسابی با این ایمیل یافت نشد. مایل به ایجاد حساب جدید هستید؟",
|
||||
"auth/weak-password": "رمز عبور خیلی ضعیف است. لطفاً از رمز عبور قویتر با حداقل ۶ کاراکتر استفاده کنید.",
|
||||
"auth/wrong-password": "رمز عبور وارد شده نادرست است. لطفاً دوباره تلاش کنید.",
|
||||
"generic": "در ورود شما مشکلی پیش آمد. لطفاً دوباره تلاش کنید.",
|
||||
"signupBlocked": "در حال حاضر امکان ایجاد حساب کاربری وجود ندارد. لطفاً بعداً دوباره تلاش کنید. اگر این مشکل ادامه داشت، با support@comfy.org تماس بگیرید."
|
||||
"generic": "در ورود شما مشکلی پیش آمد. لطفاً دوباره تلاش کنید."
|
||||
},
|
||||
"login": {
|
||||
"andText": "و",
|
||||
@@ -348,17 +346,6 @@
|
||||
"x": "ایکس",
|
||||
"y": "وای"
|
||||
},
|
||||
"boundingBoxes": {
|
||||
"clearAll": "پاکسازی همه",
|
||||
"clickRegionToEdit": "برای ویرایش، روی یک ناحیه کلیک کنید.",
|
||||
"colors": "پالت رنگ",
|
||||
"descLabel": "توضیحات",
|
||||
"descPlaceholder": "توضیحات این ناحیه",
|
||||
"textLabel": "متن",
|
||||
"textPlaceholder": "متن برای نمایش (عیناً)",
|
||||
"typeObj": "obj",
|
||||
"typeText": "متن"
|
||||
},
|
||||
"breadcrumbsMenu": {
|
||||
"app": "برنامه",
|
||||
"blueprint": "نقشه راه",
|
||||
@@ -768,13 +755,6 @@
|
||||
"creditsAvailable": "اعتبار موجود",
|
||||
"details": "جزئیات",
|
||||
"eventType": "نوع رویداد",
|
||||
"eventTypes": {
|
||||
"accountCreated": "حساب کاربری ایجاد شد",
|
||||
"apiNodeUsage": "استفاده از Node شریک",
|
||||
"apiUsage": "استفاده از API",
|
||||
"creditAdded": "اعتبار افزوده شد",
|
||||
"gpuUsage": "استفاده از GPU"
|
||||
},
|
||||
"faqs": "سؤالات متداول",
|
||||
"invoiceHistory": "تاریخچه فاکتورها",
|
||||
"lastUpdated": "آخرین بهروزرسانی",
|
||||
@@ -1850,35 +1830,6 @@
|
||||
"zoomOptions": "گزینههای بزرگنمایی",
|
||||
"zoomOut": "کوچکنمایی"
|
||||
},
|
||||
"hdrViewer": {
|
||||
"channel": "کانال",
|
||||
"channels": {
|
||||
"a": "آلفا",
|
||||
"b": "B",
|
||||
"g": "G",
|
||||
"luminance": "درخشندگی",
|
||||
"r": "R",
|
||||
"rgb": "RGB"
|
||||
},
|
||||
"clipWarnings": "هشدار برش",
|
||||
"dither": "دیتر",
|
||||
"exposure": "نوردهی",
|
||||
"failedToLoad": "بارگذاری تصویر HDR ناموفق بود",
|
||||
"fitView": "متناسبسازی",
|
||||
"hdrImage": "تصویر HDR",
|
||||
"histogram": "هیستوگرام",
|
||||
"inf": "بینهایت",
|
||||
"max": "بیشینه",
|
||||
"mean": "میانگین",
|
||||
"min": "کمینه",
|
||||
"nan": "NaN",
|
||||
"normalizeExposure": "نوردهی خودکار",
|
||||
"openInHdrViewer": "باز کردن در نمایشگر HDR",
|
||||
"resolution": "وضوح",
|
||||
"sourceGamut": "گاموت منبع",
|
||||
"stdDev": "انحراف معیار",
|
||||
"title": "نمایشگر HDR"
|
||||
},
|
||||
"help": {
|
||||
"helpCenterMenu": "منوی مرکز راهنما",
|
||||
"recentReleases": "انتشارهای اخیر"
|
||||
@@ -3006,10 +2957,6 @@
|
||||
"uploadError": "بارگذاری تصویر painter ناموفق بود: {status} - {statusText}",
|
||||
"width": "عرض"
|
||||
},
|
||||
"palette": {
|
||||
"addColor": "افزودن رنگ",
|
||||
"swatchTitle": "برای ویرایش کلیک کنید · برای جابجایی بکشید · برای حذف راستکلیک کنید"
|
||||
},
|
||||
"progressToast": {
|
||||
"allDownloadsCompleted": "همه دانلودها تکمیل شدند",
|
||||
"downloadingModel": "در حال دانلود مدل...",
|
||||
@@ -3767,27 +3714,6 @@
|
||||
"customLoRAsLabel": "LoRAهای خود را وارد کنید",
|
||||
"description": "بهترین طرح را برای خود انتخاب کنید",
|
||||
"descriptionWorkspace": "بهترین طرح را برای فضای کاری خود انتخاب کنید",
|
||||
"downgrade": {
|
||||
"body": "تمام اعضای دیگر این فضای کاری بلافاصله حذف خواهند شد.",
|
||||
"confirm": "تغییر پلن",
|
||||
"confirmationPhrase": "متوجه شدم",
|
||||
"confirmationPrompt": "برای تأیید، عبارت «{phrase}» را وارد کنید.",
|
||||
"failed": "تغییر پلن انجام نشد",
|
||||
"failedAfterMemberRemoval": "اعضای تیم حذف شدند، اما تغییر پلن کامل نشد — لطفاً دوباره تلاش کنید یا با پشتیبانی تماس بگیرید",
|
||||
"memberRemovalFailed": "امکان حذف {email} از تیم وجود ندارد — برخی اعضا ممکن است قبلاً حذف شده باشند و پلن شما تغییر نکرده است",
|
||||
"notAllowed": "این تغییر پلن در دسترس نیست",
|
||||
"paymentMethodRequired": "برای تغییر پلن، نیاز به روش پرداخت است",
|
||||
"paymentPageBlocked": "امکان باز کردن صفحه پرداخت وجود ندارد — لطفاً دوباره تلاش کنید",
|
||||
"title": "تغییر به پلن {plan}؟"
|
||||
},
|
||||
"enterprise": {
|
||||
"cta": "بیشتر بدانید",
|
||||
"flexibility": "به دنبال امکانات یا انعطافپذیری بیشتر هستید؟",
|
||||
"name": "سازمانی",
|
||||
"needMoreMembers": "به اعضای بیشتری نیاز دارید؟",
|
||||
"reachOut": "با ما تماس بگیرید تا زمانی برای گفتگو هماهنگ کنیم."
|
||||
},
|
||||
"everythingInPlus": "همه امکانات {plan}، بهعلاوه:",
|
||||
"expiresDate": "انقضا در {date}",
|
||||
"freeTier": {
|
||||
"description": "طرح رایگان شما شامل {credits} اعتبار در هر ماه برای استفاده از Comfy Cloud است.",
|
||||
@@ -3834,7 +3760,6 @@
|
||||
"messageSupport": "پیام به پشتیبانی",
|
||||
"monthly": "ماهانه",
|
||||
"monthlyBonusDescription": "پاداش ماهانه اعتبار",
|
||||
"monthlyCredits": "اعتبار ماهانه",
|
||||
"monthlyCreditsInfo": "این اعتبارها هر ماه شارژ میشوند و منتقل نمیشوند",
|
||||
"monthlyCreditsLabel": "اعتبار ماهانه",
|
||||
"monthlyCreditsPerMemberLabel": "اعتبار ماهانه / هر عضو",
|
||||
@@ -3847,13 +3772,7 @@
|
||||
"partnerNodesCredits": "قیمتگذاری Partner Nodes",
|
||||
"partnerNodesDescription": "برای اجرای مدلهای تجاری/اختصاصی",
|
||||
"perMonth": "/ ماه",
|
||||
"personalHeader": "پلنهای شخصی فقط برای استفاده فردی هستند. {action}",
|
||||
"personalHeaderAction": "برای افزودن همتیمی، به پلن تیمی ارتقا دهید.",
|
||||
"personalWorkspace": "فضای کاری شخصی",
|
||||
"planScope": {
|
||||
"personal": "برای استفاده شخصی",
|
||||
"team": "برای تیمها"
|
||||
},
|
||||
"plansAndPricing": "طرحها و قیمتها",
|
||||
"plansForWorkspace": "طرحها برای {workspace}",
|
||||
"prepaidCreditsInfo": "اعتبارهای پیشپرداخت تا یک سال پس از تاریخ خرید منقضی میشوند.",
|
||||
@@ -3864,10 +3783,8 @@
|
||||
"confirm": "تأیید",
|
||||
"confirmPayment": "تأیید پرداخت",
|
||||
"confirmPlanChange": "تأیید تغییر طرح",
|
||||
"creditsRefillTo": "اعتبارها به این مقدار شارژ میشوند",
|
||||
"eachMonthCreditsRefill": "هر ماه اعتبار به این مقدار بازنشانی میشود",
|
||||
"ends": "پایان در {date}",
|
||||
"everyMonthStarting": "هر ماه از {date} شروع میشود",
|
||||
"hideFeatures": "مخفی کردن امکانات",
|
||||
"nextPaymentDue": "پرداخت بعدی در {date}. هر زمان میتوانید لغو کنید.",
|
||||
"perMember": "/ هر عضو",
|
||||
@@ -3877,18 +3794,10 @@
|
||||
"showMoreFeatures": "نمایش امکانات بیشتر",
|
||||
"starting": "شروع از {date}",
|
||||
"startingToday": "شروع از امروز",
|
||||
"subscribeToPlan": "اشتراک پلن {plan}",
|
||||
"switchToPlan": "تغییر به پلن {plan}",
|
||||
"terms": "شرایط",
|
||||
"termsAgreement": "با ادامه، شما با {terms} و {privacy} Comfy Org موافقت میکنید.",
|
||||
"totalDueToday": "مبلغ قابل پرداخت امروز",
|
||||
"youllBeCharged": "شما مبلغ زیر را پرداخت خواهید کرد"
|
||||
"totalDueToday": "مبلغ قابل پرداخت امروز"
|
||||
},
|
||||
"pricingBlurb": "*بر اساس این قالب، {seeDetails}. برای {questions} یا {enterpriseDiscussions} با ما تماس بگیرید. برای جزئیات بیشتر قیمتگذاری، {clickHere}.",
|
||||
"pricingBlurbClickHere": "اینجا کلیک کنید",
|
||||
"pricingBlurbEnterprise": "بحثهای سازمانی",
|
||||
"pricingBlurbQuestions": "سؤالات",
|
||||
"pricingBlurbSeeDetails": "جزئیات را ببینید",
|
||||
"refreshCredits": "بهروزرسانی اعتبارها",
|
||||
"renewsDate": "تمدید در {date}",
|
||||
"required": {
|
||||
@@ -3902,8 +3811,6 @@
|
||||
"resubscribe": "تمدید اشتراک",
|
||||
"resubscribeSuccess": "اشتراک با موفقیت فعال شد",
|
||||
"resubscribeTo": "تمدید اشتراک {plan}",
|
||||
"saveYearly": "صرفهجویی ۲۰٪",
|
||||
"saveYearlyUpTo": "تا ۲۰٪ صرفهجویی کنید",
|
||||
"soloUseOnly": "فقط برای استفاده فردی",
|
||||
"subscribeForMore": "ارتقاء",
|
||||
"subscribeNow": "هماکنون اشتراک بگیرید",
|
||||
@@ -3912,34 +3819,10 @@
|
||||
"subscribeToRun": "اشتراک",
|
||||
"subscribeToRunFull": "اشتراک برای اجرا",
|
||||
"subscriptionRequiredMessage": "برای اجرای workflowها در Cloud، اشتراک لازم است.",
|
||||
"success": {
|
||||
"allSet": "همه چیز آماده است",
|
||||
"planUpdated": "پلن شما با موفقیت بهروزرسانی شد.",
|
||||
"receiptEmailed": "رسید به ایمیل شما ارسال شد."
|
||||
},
|
||||
"teamHeader": "برای تیمهایی که قصد همکاری دارند. به اعضای بیشتری نیاز دارید؟ {learnMore} درباره پلن سازمانی.",
|
||||
"teamHeaderLearnMore": "بیشتر بدانید",
|
||||
"teamPlan": {
|
||||
"changePlan": "تغییر پلن",
|
||||
"checkoutComingSoon": "پرداخت پلن تیمی بهزودی فعال میشود.",
|
||||
"comingSoonLabel": "بهزودی:",
|
||||
"cta": "اشتراک سالانه تیمی",
|
||||
"ctaMonthly": "اشتراک ماهانه تیمی",
|
||||
"currentPlan": "پلن فعلی",
|
||||
"detailsTitle": "جزئیات",
|
||||
"name": "پلن تیمی",
|
||||
"perkConcurrentRuns": "اعضا میتوانند workflowها را بهصورت همزمان اجرا کنند",
|
||||
"perkInviteMembers": "دعوت اعضای تیم",
|
||||
"perkProjectAssets": "مدیریت پروژه و داراییها",
|
||||
"perkRolePermissions": "دسترسی مبتنی بر نقش",
|
||||
"perkSharedPool": "استخر اعتبار مشترک برای همه اعضا",
|
||||
"tagline": "اشتراک اعتباری ماهانه دلخواه خود را انتخاب کنید. با اعتبار بیشتر، تخفیف بیشتری دریافت کنید."
|
||||
},
|
||||
"teamWorkspace": "فضای کاری تیمی",
|
||||
"tierNameYearly": "{name} سالانه",
|
||||
"tiers": {
|
||||
"creator": {
|
||||
"feature1": "امکان وارد کردن مدلهای شخصی",
|
||||
"name": "خالق"
|
||||
},
|
||||
"founder": {
|
||||
@@ -3949,12 +3832,9 @@
|
||||
"name": "رایگان"
|
||||
},
|
||||
"pro": {
|
||||
"feature1": "زمان اجرای workflow طولانیتر (تا ۱ ساعت)",
|
||||
"name": "حرفهای"
|
||||
},
|
||||
"standard": {
|
||||
"feature1": "حداکثر زمان اجرای workflow: ۳۰ دقیقه",
|
||||
"feature2": "امکان افزودن اعتبار بیشتر در هر زمان",
|
||||
"name": "استاندارد"
|
||||
}
|
||||
},
|
||||
@@ -3967,7 +3847,6 @@
|
||||
"upgradeToAddCredits": "برای افزودن اعتبار ارتقاء دهید",
|
||||
"usdPerMonth": "دلار آمریکا / ماه",
|
||||
"usdPerMonthPerMember": "دلار آمریکا / ماه / هر عضو",
|
||||
"videoEstimate": "تولید حدود ~{count} ویدیو ۵ ثانیهای*",
|
||||
"videoEstimateExplanation": "این تخمینها بر اساس قالب Wan 2.2 Image-to-Video با تنظیمات پیشفرض (۵ ثانیه، ۶۴۰×۶۴۰، ۱۶ فریم بر ثانیه، ۴ مرحله نمونهگیری) است.",
|
||||
"videoEstimateHelp": "جزئیات بیشتر درباره این قالب",
|
||||
"videoEstimateLabel": "تخمین تعداد ویدیوهای ۵ ثانیهای تولید شده با قالب Wan 2.2 Image-to-Video",
|
||||
@@ -3977,11 +3856,10 @@
|
||||
"viewMoreDetails": "مشاهده جزئیات بیشتر",
|
||||
"viewMoreDetailsPlans": "مشاهده جزئیات بیشتر درباره طرحها و قیمتها",
|
||||
"viewUsageHistory": "مشاهده تاریخچه استفاده",
|
||||
"whatsIncluded": "شامل موارد زیر:",
|
||||
"workspaceNotSubscribed": "این محیط کاری اشتراک فعال ندارد",
|
||||
"yearly": "سالانه",
|
||||
"yearlyCreditsLabel": "کل اعتبار سالانه",
|
||||
"yearlyDiscount": "٪۲۰ تخفیف",
|
||||
"saveYearly": "٪۲۰ صرفهجویی",
|
||||
"yourPlanIncludes": "طرح شما شامل:"
|
||||
},
|
||||
"tabMenu": {
|
||||
|
||||
@@ -92,7 +92,6 @@
|
||||
"errorUserTokenAccessDenied": "Votre jeton API n’a pas accès à cette ressource. Veuillez vérifier les autorisations de votre jeton.",
|
||||
"errorUserTokenInvalid": "Votre jeton API enregistré est invalide ou expiré. Veuillez le mettre à jour dans les paramètres.",
|
||||
"failedToCreateNode": "Échec de la création du nœud. Veuillez réessayer ou consulter la console pour plus de détails.",
|
||||
"failedToSetModelValue": "Nœud ajouté, mais son modèle n’a pas pu être défini automatiquement. Consultez la console pour plus de détails.",
|
||||
"fileFormats": "Formats de fichier",
|
||||
"fileName": "Nom du fichier",
|
||||
"fileSize": "Taille du fichier",
|
||||
@@ -242,8 +241,7 @@
|
||||
"auth/user-not-found": "Aucun compte trouvé avec cette adresse e-mail. Souhaitez-vous créer un nouveau compte ?",
|
||||
"auth/weak-password": "Le mot de passe est trop faible. Veuillez utiliser un mot de passe plus fort avec au moins 6 caractères.",
|
||||
"auth/wrong-password": "Le mot de passe que vous avez saisi est incorrect. Veuillez réessayer.",
|
||||
"generic": "Une erreur s'est produite lors de votre connexion. Veuillez réessayer.",
|
||||
"signupBlocked": "Nous ne pouvons pas créer votre compte pour le moment. Veuillez réessayer plus tard. Si le problème persiste, contactez support@comfy.org."
|
||||
"generic": "Une erreur s'est produite lors de votre connexion. Veuillez réessayer."
|
||||
},
|
||||
"login": {
|
||||
"andText": "et",
|
||||
@@ -348,17 +346,6 @@
|
||||
"x": "X",
|
||||
"y": "Y"
|
||||
},
|
||||
"boundingBoxes": {
|
||||
"clearAll": "Tout effacer",
|
||||
"clickRegionToEdit": "Cliquez sur une région pour la modifier.",
|
||||
"colors": "palette_de_couleurs",
|
||||
"descLabel": "description",
|
||||
"descPlaceholder": "description de cette région",
|
||||
"textLabel": "Texte",
|
||||
"textPlaceholder": "texte à afficher (tel quel)",
|
||||
"typeObj": "objet",
|
||||
"typeText": "texte"
|
||||
},
|
||||
"breadcrumbsMenu": {
|
||||
"app": "Application",
|
||||
"blueprint": "Plan",
|
||||
@@ -768,13 +755,6 @@
|
||||
"creditsAvailable": "Crédits disponibles",
|
||||
"details": "Détails",
|
||||
"eventType": "Type d'événement",
|
||||
"eventTypes": {
|
||||
"accountCreated": "Compte créé",
|
||||
"apiNodeUsage": "Utilisation du nœud partenaire",
|
||||
"apiUsage": "Utilisation de l'API",
|
||||
"creditAdded": "Crédits ajoutés",
|
||||
"gpuUsage": "Utilisation du GPU"
|
||||
},
|
||||
"faqs": "FAQ",
|
||||
"invoiceHistory": "Historique des factures",
|
||||
"lastUpdated": "Dernière mise à jour",
|
||||
@@ -1850,35 +1830,6 @@
|
||||
"zoomOptions": "Options de zoom",
|
||||
"zoomOut": "Zoom arrière"
|
||||
},
|
||||
"hdrViewer": {
|
||||
"channel": "Canal",
|
||||
"channels": {
|
||||
"a": "Alpha",
|
||||
"b": "B",
|
||||
"g": "V",
|
||||
"luminance": "Luminance",
|
||||
"r": "R",
|
||||
"rgb": "RVB"
|
||||
},
|
||||
"clipWarnings": "Avertissements de clipping",
|
||||
"dither": "Tramage",
|
||||
"exposure": "Exposition",
|
||||
"failedToLoad": "Échec du chargement de l'image HDR",
|
||||
"fitView": "Ajuster",
|
||||
"hdrImage": "Image HDR",
|
||||
"histogram": "Histogramme",
|
||||
"inf": "Inf",
|
||||
"max": "Max",
|
||||
"mean": "Moyenne",
|
||||
"min": "Min",
|
||||
"nan": "NaN",
|
||||
"normalizeExposure": "Exposition auto",
|
||||
"openInHdrViewer": "Ouvrir dans la visionneuse HDR",
|
||||
"resolution": "Résolution",
|
||||
"sourceGamut": "Gamme source",
|
||||
"stdDev": "Écart-type",
|
||||
"title": "Visionneuse HDR"
|
||||
},
|
||||
"help": {
|
||||
"helpCenterMenu": "Menu du centre d’aide",
|
||||
"recentReleases": "Dernières versions"
|
||||
@@ -3006,10 +2957,6 @@
|
||||
"uploadError": "Échec du téléversement de l'image du peintre : {status} - {statusText}",
|
||||
"width": "Largeur"
|
||||
},
|
||||
"palette": {
|
||||
"addColor": "Ajouter une couleur",
|
||||
"swatchTitle": "Cliquez pour éditer · glissez pour réordonner · clic droit pour supprimer"
|
||||
},
|
||||
"progressToast": {
|
||||
"allDownloadsCompleted": "Tous les téléchargements sont terminés",
|
||||
"downloadingModel": "Téléchargement du modèle...",
|
||||
@@ -3755,27 +3702,6 @@
|
||||
"customLoRAsLabel": "Importer vos propres LoRAs",
|
||||
"description": "Choisissez le forfait qui vous convient",
|
||||
"descriptionWorkspace": "Choisissez la meilleure offre pour votre espace de travail",
|
||||
"downgrade": {
|
||||
"body": "Tous les autres membres de cet espace de travail seront immédiatement supprimés.",
|
||||
"confirm": "Changer de plan",
|
||||
"confirmationPhrase": "Je comprends",
|
||||
"confirmationPrompt": "Tapez « {phrase} » pour confirmer.",
|
||||
"failed": "Échec du changement de plan",
|
||||
"failedAfterMemberRemoval": "Les membres de l’équipe ont été retirés, mais le changement de plan n’a pas abouti — veuillez réessayer ou contacter le support",
|
||||
"memberRemovalFailed": "Impossible de retirer {email} de l’équipe — certains membres ont peut-être déjà été retirés et votre plan n’a pas été modifié",
|
||||
"notAllowed": "Ce changement de plan n'est pas disponible",
|
||||
"paymentMethodRequired": "Un moyen de paiement est requis pour changer de plan",
|
||||
"paymentPageBlocked": "Impossible d’ouvrir la page de paiement — veuillez réessayer",
|
||||
"title": "Passer au plan {plan} ?"
|
||||
},
|
||||
"enterprise": {
|
||||
"cta": "En savoir plus",
|
||||
"flexibility": "Vous cherchez plus de flexibilité ou des fonctionnalités personnalisées ?",
|
||||
"name": "Entreprise",
|
||||
"needMoreMembers": "Besoin de plus de membres ?",
|
||||
"reachOut": "Contactez-nous pour planifier un échange."
|
||||
},
|
||||
"everythingInPlus": "Tout ce qui est dans {plan}, plus :",
|
||||
"expiresDate": "Expire le {date}",
|
||||
"freeTier": {
|
||||
"description": "Votre plan gratuit inclut {credits} crédits chaque mois pour essayer Comfy Cloud.",
|
||||
@@ -3822,7 +3748,6 @@
|
||||
"messageSupport": "Contacter le support",
|
||||
"monthly": "Mensuel",
|
||||
"monthlyBonusDescription": "Bonus de crédits mensuel",
|
||||
"monthlyCredits": "crédits mensuels",
|
||||
"monthlyCreditsInfo": "Ces crédits se renouvellent chaque mois et ne sont pas reportés",
|
||||
"monthlyCreditsLabel": "Crédits mensuels",
|
||||
"monthlyCreditsPerMemberLabel": "Crédits mensuels / membre",
|
||||
@@ -3835,13 +3760,7 @@
|
||||
"partnerNodesCredits": "Crédits Nœuds Partenaires",
|
||||
"partnerNodesDescription": "Pour exécuter des modèles commerciaux/propriétaires",
|
||||
"perMonth": "USD / mois",
|
||||
"personalHeader": "Les plans personnels sont réservés à un usage individuel. {action}",
|
||||
"personalHeaderAction": "Pour ajouter des coéquipiers, abonnez-vous au plan équipe.",
|
||||
"personalWorkspace": "Espace de travail personnel",
|
||||
"planScope": {
|
||||
"personal": "Pour usage personnel",
|
||||
"team": "Pour les équipes"
|
||||
},
|
||||
"plansAndPricing": "Forfaits & tarifs",
|
||||
"plansForWorkspace": "Formules pour {workspace}",
|
||||
"prepaidCreditsInfo": "Crédits achetés séparément qui n'expirent pas",
|
||||
@@ -3852,10 +3771,8 @@
|
||||
"confirm": "Confirmer",
|
||||
"confirmPayment": "Confirmer votre paiement",
|
||||
"confirmPlanChange": "Confirmer le changement d'offre",
|
||||
"creditsRefillTo": "Les crédits sont réinitialisés à",
|
||||
"eachMonthCreditsRefill": "Chaque mois, les crédits sont réinitialisés à",
|
||||
"ends": "Se termine le {date}",
|
||||
"everyMonthStarting": "Chaque mois à partir du {date}",
|
||||
"hideFeatures": "Masquer les fonctionnalités",
|
||||
"nextPaymentDue": "Prochain paiement dû le {date}. Annulez à tout moment.",
|
||||
"perMember": "/ membre",
|
||||
@@ -3865,18 +3782,10 @@
|
||||
"showMoreFeatures": "Afficher plus de fonctionnalités",
|
||||
"starting": "À partir du {date}",
|
||||
"startingToday": "À partir d'aujourd'hui",
|
||||
"subscribeToPlan": "S’abonner au plan {plan}",
|
||||
"switchToPlan": "Passer au plan {plan}",
|
||||
"terms": "Conditions",
|
||||
"termsAgreement": "En continuant, vous acceptez les {terms} et la {privacy} de Comfy Org.",
|
||||
"totalDueToday": "Total dû aujourd'hui",
|
||||
"youllBeCharged": "Vous serez facturé"
|
||||
"totalDueToday": "Total dû aujourd'hui"
|
||||
},
|
||||
"pricingBlurb": "*Basé sur ce modèle, {seeDetails}. Contactez-nous pour {questions} ou {enterpriseDiscussions}. Pour plus de détails sur les tarifs, {clickHere}.",
|
||||
"pricingBlurbClickHere": "cliquez ici",
|
||||
"pricingBlurbEnterprise": "discussions entreprise",
|
||||
"pricingBlurbQuestions": "questions",
|
||||
"pricingBlurbSeeDetails": "voir les détails",
|
||||
"refreshCredits": "Actualiser les crédits",
|
||||
"renewsDate": "Renouvellement le {date}",
|
||||
"required": {
|
||||
@@ -3890,8 +3799,6 @@
|
||||
"resubscribe": "Se réabonner",
|
||||
"resubscribeSuccess": "Abonnement réactivé avec succès",
|
||||
"resubscribeTo": "Se réabonner à {plan}",
|
||||
"saveYearly": "Économisez 20 %",
|
||||
"saveYearlyUpTo": "Économisez jusqu’à 20 %",
|
||||
"soloUseOnly": "Usage solo uniquement",
|
||||
"subscribeForMore": "Mettre à niveau",
|
||||
"subscribeNow": "S'abonner maintenant",
|
||||
@@ -3900,34 +3807,10 @@
|
||||
"subscribeToRun": "S'abonner",
|
||||
"subscribeToRunFull": "S'abonner pour exécuter",
|
||||
"subscriptionRequiredMessage": "Un abonnement est requis pour que les membres puissent exécuter des workflows sur le Cloud",
|
||||
"success": {
|
||||
"allSet": "Tout est prêt",
|
||||
"planUpdated": "Votre plan a été mis à jour avec succès.",
|
||||
"receiptEmailed": "Un reçu vous a été envoyé par e-mail."
|
||||
},
|
||||
"teamHeader": "Pour les équipes souhaitant collaborer. Besoin de plus de membres ? {learnMore} sur l’offre entreprise.",
|
||||
"teamHeaderLearnMore": "En savoir plus",
|
||||
"teamPlan": {
|
||||
"changePlan": "Changer de plan",
|
||||
"checkoutComingSoon": "Le paiement du plan équipe arrive bientôt.",
|
||||
"comingSoonLabel": "Bientôt disponible :",
|
||||
"cta": "S’abonner à l’offre Équipe annuelle",
|
||||
"ctaMonthly": "S’abonner à l’offre Équipe mensuelle",
|
||||
"currentPlan": "Plan actuel",
|
||||
"detailsTitle": "Détails",
|
||||
"name": "Plan Équipe",
|
||||
"perkConcurrentRuns": "Les membres peuvent exécuter des workflows simultanément",
|
||||
"perkInviteMembers": "Invitez des membres dans l’équipe",
|
||||
"perkProjectAssets": "Gestion des projets et des ressources",
|
||||
"perkRolePermissions": "Permissions basées sur les rôles",
|
||||
"perkSharedPool": "Crédits partagés pour tous les membres",
|
||||
"tagline": "Choisissez votre propre abonnement mensuel de crédits. Bénéficiez d’une plus grande remise avec un abonnement de crédits plus important."
|
||||
},
|
||||
"teamWorkspace": "Espace de travail d’équipe",
|
||||
"tierNameYearly": "{name} Annuel",
|
||||
"tiers": {
|
||||
"creator": {
|
||||
"feature1": "Importez vos propres modèles",
|
||||
"name": "Créateur"
|
||||
},
|
||||
"founder": {
|
||||
@@ -3937,12 +3820,9 @@
|
||||
"name": "Gratuit"
|
||||
},
|
||||
"pro": {
|
||||
"feature1": "Durée d’exécution du workflow prolongée (jusqu’à 1 h)",
|
||||
"name": "Pro"
|
||||
},
|
||||
"standard": {
|
||||
"feature1": "Durée maximale d’exécution du workflow : 30 minutes",
|
||||
"feature2": "Ajoutez des crédits à tout moment",
|
||||
"name": "Standard"
|
||||
}
|
||||
},
|
||||
@@ -3955,7 +3835,6 @@
|
||||
"upgradeToAddCredits": "Mettre à niveau pour ajouter des crédits",
|
||||
"usdPerMonth": "USD / mois",
|
||||
"usdPerMonthPerMember": "USD / mois / membre",
|
||||
"videoEstimate": "Génère environ {count} vidéos de 5 s*",
|
||||
"videoEstimateExplanation": "Ces estimations sont basées sur le modèle Wan 2.2 Image-to-Video avec les paramètres par défaut (5 secondes, 640x640, 16fps, échantillonnage en 4 étapes).",
|
||||
"videoEstimateHelp": "Plus de détails sur ce modèle",
|
||||
"videoEstimateLabel": "Nombre approx. de vidéos de 5s générées avec le modèle Wan 2.2 Image-to-Video",
|
||||
@@ -3965,11 +3844,10 @@
|
||||
"viewMoreDetails": "Voir plus de détails",
|
||||
"viewMoreDetailsPlans": "Voir plus de détails sur les forfaits et tarifs",
|
||||
"viewUsageHistory": "Voir l'historique d'utilisation",
|
||||
"whatsIncluded": "Inclus :",
|
||||
"workspaceNotSubscribed": "Cet espace de travail n’a pas d’abonnement",
|
||||
"yearly": "Annuel",
|
||||
"yearlyCreditsLabel": "Crédits annuels totaux",
|
||||
"yearlyDiscount": "20% DE RÉDUCTION",
|
||||
"saveYearly": "Économisez 20 %",
|
||||
"yourPlanIncludes": "Votre forfait comprend :"
|
||||
},
|
||||
"tabMenu": {
|
||||
|
||||
@@ -92,7 +92,6 @@
|
||||
"errorUserTokenAccessDenied": "お使いのAPIトークンにはこのリソースへのアクセス権がありません。トークンの権限を確認してください。",
|
||||
"errorUserTokenInvalid": "保存されているAPIトークンが無効または期限切れです。設定でトークンを更新してください。",
|
||||
"failedToCreateNode": "ノードの作成に失敗しました。再試行するか、詳細はコンソールをご確認ください。",
|
||||
"failedToSetModelValue": "ノードは追加されましたが、モデルを自動設定できませんでした。詳細はコンソールをご確認ください。",
|
||||
"fileFormats": "ファイル形式",
|
||||
"fileName": "ファイル名",
|
||||
"fileSize": "ファイルサイズ",
|
||||
@@ -242,8 +241,7 @@
|
||||
"auth/user-not-found": "このメールアドレスに紐づくアカウントが見つかりません。新しいアカウントを作成しますか?",
|
||||
"auth/weak-password": "パスワードが弱すぎます。6文字以上のより強力なパスワードを使用してください。",
|
||||
"auth/wrong-password": "入力されたパスワードが正しくありません。もう一度お試しください。",
|
||||
"generic": "サインイン中に問題が発生しました。もう一度お試しください。",
|
||||
"signupBlocked": "現在アカウントを作成できません。しばらくしてから再度お試しください。繰り返し発生する場合は support@comfy.org までご連絡ください。"
|
||||
"generic": "サインイン中に問題が発生しました。もう一度お試しください。"
|
||||
},
|
||||
"login": {
|
||||
"andText": "および",
|
||||
@@ -348,17 +346,6 @@
|
||||
"x": "X",
|
||||
"y": "Y"
|
||||
},
|
||||
"boundingBoxes": {
|
||||
"clearAll": "すべてクリア",
|
||||
"clickRegionToEdit": "編集する領域をクリックしてください。",
|
||||
"colors": "カラーパレット",
|
||||
"descLabel": "説明",
|
||||
"descPlaceholder": "この領域の説明",
|
||||
"textLabel": "テキスト",
|
||||
"textPlaceholder": "表示するテキスト(そのまま)",
|
||||
"typeObj": "obj",
|
||||
"typeText": "テキスト"
|
||||
},
|
||||
"breadcrumbsMenu": {
|
||||
"app": "アプリ",
|
||||
"blueprint": "ブループリント",
|
||||
@@ -768,13 +755,6 @@
|
||||
"creditsAvailable": "利用可能なクレジット",
|
||||
"details": "詳細",
|
||||
"eventType": "イベントタイプ",
|
||||
"eventTypes": {
|
||||
"accountCreated": "アカウント作成",
|
||||
"apiNodeUsage": "パートナーノード利用",
|
||||
"apiUsage": "API利用",
|
||||
"creditAdded": "クレジット追加",
|
||||
"gpuUsage": "GPU利用"
|
||||
},
|
||||
"faqs": "よくある質問",
|
||||
"invoiceHistory": "請求履歴",
|
||||
"lastUpdated": "最終更新",
|
||||
@@ -1850,35 +1830,6 @@
|
||||
"zoomOptions": "ズームオプション",
|
||||
"zoomOut": "縮小"
|
||||
},
|
||||
"hdrViewer": {
|
||||
"channel": "チャンネル",
|
||||
"channels": {
|
||||
"a": "アルファ",
|
||||
"b": "B",
|
||||
"g": "G",
|
||||
"luminance": "輝度",
|
||||
"r": "R",
|
||||
"rgb": "RGB"
|
||||
},
|
||||
"clipWarnings": "クリップ警告",
|
||||
"dither": "ディザ",
|
||||
"exposure": "露出",
|
||||
"failedToLoad": "HDR画像の読み込みに失敗しました",
|
||||
"fitView": "フィット",
|
||||
"hdrImage": "HDR画像",
|
||||
"histogram": "ヒストグラム",
|
||||
"inf": "Inf",
|
||||
"max": "最大",
|
||||
"mean": "平均",
|
||||
"min": "最小",
|
||||
"nan": "NaN",
|
||||
"normalizeExposure": "自動露出",
|
||||
"openInHdrViewer": "HDRビューアで開く",
|
||||
"resolution": "解像度",
|
||||
"sourceGamut": "ソースガマット",
|
||||
"stdDev": "標準偏差",
|
||||
"title": "HDRビューア"
|
||||
},
|
||||
"help": {
|
||||
"helpCenterMenu": "ヘルプセンターメニュー",
|
||||
"recentReleases": "最近のリリース"
|
||||
@@ -3006,10 +2957,6 @@
|
||||
"uploadError": "ペインター画像のアップロードに失敗しました: {status} - {statusText}",
|
||||
"width": "幅"
|
||||
},
|
||||
"palette": {
|
||||
"addColor": "色を追加",
|
||||
"swatchTitle": "クリックで編集 · ドラッグで並べ替え · 右クリックで削除"
|
||||
},
|
||||
"progressToast": {
|
||||
"allDownloadsCompleted": "すべてのダウンロードが完了しました",
|
||||
"downloadingModel": "モデルをダウンロード中...",
|
||||
@@ -3755,27 +3702,6 @@
|
||||
"customLoRAsLabel": "独自のLoRAをインポート",
|
||||
"description": "あなたに最適なプランを選択してください",
|
||||
"descriptionWorkspace": "ワークスペースに最適なプランを選択してください",
|
||||
"downgrade": {
|
||||
"body": "このワークスペースの他のメンバーはすぐに削除されます。",
|
||||
"confirm": "プランを変更",
|
||||
"confirmationPhrase": "理解しました",
|
||||
"confirmationPrompt": "確認のため「{phrase}」と入力してください。",
|
||||
"failed": "プランの変更に失敗しました",
|
||||
"failedAfterMemberRemoval": "チームメンバーは削除されましたが、プランの変更が完了しませんでした。再度お試しいただくか、サポートまでご連絡ください。",
|
||||
"memberRemovalFailed": "{email} をチームから削除できませんでした。一部のメンバーはすでに削除されている可能性があり、プランは変更されませんでした。",
|
||||
"notAllowed": "このプラン変更は利用できません",
|
||||
"paymentMethodRequired": "プランを変更するにはお支払い方法が必要です",
|
||||
"paymentPageBlocked": "お支払いページを開けませんでした。再度お試しください。",
|
||||
"title": "{plan}プランに変更しますか?"
|
||||
},
|
||||
"enterprise": {
|
||||
"cta": "詳細を見る",
|
||||
"flexibility": "より柔軟な対応やカスタム機能をご希望ですか?",
|
||||
"name": "エンタープライズ",
|
||||
"needMoreMembers": "さらに多くのメンバーが必要ですか?",
|
||||
"reachOut": "ぜひご連絡ください。お打ち合わせを調整いたします。"
|
||||
},
|
||||
"everythingInPlus": "{plan}のすべて、さらに:",
|
||||
"expiresDate": "{date} に期限切れ",
|
||||
"freeTier": {
|
||||
"description": "無料プランには、Comfy Cloudをお試しいただける毎月{credits}クレジットが含まれています。",
|
||||
@@ -3822,7 +3748,6 @@
|
||||
"messageSupport": "サポートに連絡",
|
||||
"monthly": "月額",
|
||||
"monthlyBonusDescription": "月間クレジットボーナス",
|
||||
"monthlyCredits": "月間クレジット",
|
||||
"monthlyCreditsInfo": "これらのクレジットは毎月リフレッシュされ、繰り越しはできません",
|
||||
"monthlyCreditsLabel": "月間クレジット",
|
||||
"monthlyCreditsPerMemberLabel": "月間クレジット / メンバー",
|
||||
@@ -3835,13 +3760,7 @@
|
||||
"partnerNodesCredits": "パートナーノードクレジット",
|
||||
"partnerNodesDescription": "商用/独自モデルの実行用",
|
||||
"perMonth": "USD / 月",
|
||||
"personalHeader": "個人プランは個人利用専用です。{action}",
|
||||
"personalHeaderAction": "チームメンバーを追加するには、チームプランにご加入ください。",
|
||||
"personalWorkspace": "個人ワークスペース",
|
||||
"planScope": {
|
||||
"personal": "個人向け",
|
||||
"team": "チーム向け"
|
||||
},
|
||||
"plansAndPricing": "プランと価格",
|
||||
"plansForWorkspace": "{workspace} のプラン",
|
||||
"prepaidCreditsInfo": "別途購入した有効期限のないクレジット",
|
||||
@@ -3852,10 +3771,8 @@
|
||||
"confirm": "確認",
|
||||
"confirmPayment": "お支払いを確認",
|
||||
"confirmPlanChange": "プラン変更を確認",
|
||||
"creditsRefillTo": "クレジットが補充されます:",
|
||||
"eachMonthCreditsRefill": "毎月クレジットが補充されます",
|
||||
"ends": "{date}に終了",
|
||||
"everyMonthStarting": "毎月{date}から開始",
|
||||
"hideFeatures": "機能を隠す",
|
||||
"nextPaymentDue": "次回のお支払いは{date}です。いつでもキャンセルできます。",
|
||||
"perMember": "/ メンバー",
|
||||
@@ -3865,18 +3782,10 @@
|
||||
"showMoreFeatures": "さらに機能を表示",
|
||||
"starting": "{date}から開始",
|
||||
"startingToday": "本日から開始",
|
||||
"subscribeToPlan": "{plan}に加入",
|
||||
"switchToPlan": "{plan}に切り替え",
|
||||
"terms": "利用規約",
|
||||
"termsAgreement": "続行することで、Comfy Orgの{terms}および{privacy}に同意したものとみなされます。",
|
||||
"totalDueToday": "本日のお支払い合計",
|
||||
"youllBeCharged": "ご請求額:"
|
||||
"totalDueToday": "本日のお支払い合計"
|
||||
},
|
||||
"pricingBlurb": "*このテンプレートに基づきます。{seeDetails}。{questions}や{enterpriseDiscussions}についてはお問い合わせください。詳細な料金については{clickHere}。",
|
||||
"pricingBlurbClickHere": "こちらをクリック",
|
||||
"pricingBlurbEnterprise": "エンタープライズのご相談",
|
||||
"pricingBlurbQuestions": "ご質問",
|
||||
"pricingBlurbSeeDetails": "詳細を見る",
|
||||
"refreshCredits": "クレジットを更新",
|
||||
"renewsDate": "{date} に更新",
|
||||
"required": {
|
||||
@@ -3890,8 +3799,6 @@
|
||||
"resubscribe": "再購読する",
|
||||
"resubscribeSuccess": "サブスクリプションが再開されました",
|
||||
"resubscribeTo": "{plan}を再購読する",
|
||||
"saveYearly": "年間契約で20%お得",
|
||||
"saveYearlyUpTo": "最大20%お得",
|
||||
"soloUseOnly": "個人利用のみ",
|
||||
"subscribeForMore": "アップグレード",
|
||||
"subscribeNow": "今すぐ購読",
|
||||
@@ -3900,34 +3807,10 @@
|
||||
"subscribeToRun": "購読する",
|
||||
"subscribeToRunFull": "実行を購読",
|
||||
"subscriptionRequiredMessage": "クラウドでワークフローを実行するにはメンバーにサブスクリプションが必要です",
|
||||
"success": {
|
||||
"allSet": "準備が整いました",
|
||||
"planUpdated": "プランが正常に更新されました。",
|
||||
"receiptEmailed": "領収書をメールで送信しました。"
|
||||
},
|
||||
"teamHeader": "コラボレーションを希望するチーム向け。さらに多くのメンバーが必要ですか?{learnMore}(エンタープライズについて)。",
|
||||
"teamHeaderLearnMore": "詳細はこちら",
|
||||
"teamPlan": {
|
||||
"changePlan": "プランを変更",
|
||||
"checkoutComingSoon": "チームプランのチェックアウトは近日公開予定です。",
|
||||
"comingSoonLabel": "近日公開:",
|
||||
"cta": "チーム年間プランに加入",
|
||||
"ctaMonthly": "チーム月間プランに加入",
|
||||
"currentPlan": "現在のプラン",
|
||||
"detailsTitle": "詳細",
|
||||
"name": "チームプラン",
|
||||
"perkConcurrentRuns": "メンバーはワークフローを同時に実行可能",
|
||||
"perkInviteMembers": "チームメンバーを招待",
|
||||
"perkProjectAssets": "プロジェクト・アセット管理",
|
||||
"perkRolePermissions": "ロールベースの権限管理",
|
||||
"perkSharedPool": "全メンバーで共有するクレジットプール",
|
||||
"tagline": "月間クレジット数を自由に選択。多くのクレジットでさらに割引。"
|
||||
},
|
||||
"teamWorkspace": "チームワークスペース",
|
||||
"tierNameYearly": "{name} 年間",
|
||||
"tiers": {
|
||||
"creator": {
|
||||
"feature1": "独自モデルのインポート",
|
||||
"name": "クリエイター"
|
||||
},
|
||||
"founder": {
|
||||
@@ -3937,12 +3820,9 @@
|
||||
"name": "無料"
|
||||
},
|
||||
"pro": {
|
||||
"feature1": "より長いワークフロー実行時間(最大1時間)",
|
||||
"name": "プロ"
|
||||
},
|
||||
"standard": {
|
||||
"feature1": "最大30分のワークフロー実行時間",
|
||||
"feature2": "いつでもクレジットを追加可能",
|
||||
"name": "スタンダード"
|
||||
}
|
||||
},
|
||||
@@ -3955,7 +3835,6 @@
|
||||
"upgradeToAddCredits": "クレジット追加のためアップグレード",
|
||||
"usdPerMonth": "USD / 月",
|
||||
"usdPerMonthPerMember": "USD / 月 / メンバー",
|
||||
"videoEstimate": "約{count}本の5秒動画を生成*",
|
||||
"videoEstimateExplanation": "これらの見積もりは、Wan 2.2 画像から動画テンプレートのデフォルト設定(5秒、640x640、16fps、4ステップサンプリング)に基づいています。",
|
||||
"videoEstimateHelp": "このテンプレートの詳細",
|
||||
"videoEstimateLabel": "Wan 2.2 画像から動画テンプレートで生成される約5秒動画数",
|
||||
@@ -3965,11 +3844,10 @@
|
||||
"viewMoreDetails": "詳細を表示",
|
||||
"viewMoreDetailsPlans": "プランと価格の詳細を見る",
|
||||
"viewUsageHistory": "利用履歴を表示",
|
||||
"whatsIncluded": "含まれる内容:",
|
||||
"workspaceNotSubscribed": "このワークスペースはサブスクリプションに加入していません",
|
||||
"yearly": "年額",
|
||||
"yearlyCreditsLabel": "年間合計クレジット",
|
||||
"yearlyDiscount": "20%割引",
|
||||
"saveYearly": "20%お得",
|
||||
"yourPlanIncludes": "ご利用プランに含まれるもの:"
|
||||
},
|
||||
"tabMenu": {
|
||||
|
||||
@@ -92,7 +92,6 @@
|
||||
"errorUserTokenAccessDenied": "API 토큰에 이 리소스에 대한 접근 권한이 없습니다. 토큰 권한을 확인해 주세요.",
|
||||
"errorUserTokenInvalid": "저장된 API 토큰이 유효하지 않거나 만료되었습니다. 설정에서 토큰을 업데이트해 주세요.",
|
||||
"failedToCreateNode": "노드 생성에 실패했습니다. 다시 시도하거나 콘솔에서 세부 정보를 확인하세요.",
|
||||
"failedToSetModelValue": "노드는 추가되었으나 모델이 자동으로 설정되지 않았습니다. 자세한 내용은 콘솔을 확인하세요.",
|
||||
"fileFormats": "파일 형식",
|
||||
"fileName": "파일 이름",
|
||||
"fileSize": "파일 크기",
|
||||
@@ -242,8 +241,7 @@
|
||||
"auth/user-not-found": "이 이메일로 등록된 계정이 없습니다. 새 계정을 생성하시겠습니까?",
|
||||
"auth/weak-password": "비밀번호가 너무 약합니다. 최소 6자 이상의 강력한 비밀번호를 사용해 주세요.",
|
||||
"auth/wrong-password": "입력하신 비밀번호가 올바르지 않습니다. 다시 시도해 주세요.",
|
||||
"generic": "로그인 중 문제가 발생했습니다. 다시 시도해 주세요.",
|
||||
"signupBlocked": "현재 계정을 생성할 수 없습니다. 잠시 후 다시 시도해 주세요. 계속 문제가 발생하면 support@comfy.org로 문의해 주세요."
|
||||
"generic": "로그인 중 문제가 발생했습니다. 다시 시도해 주세요."
|
||||
},
|
||||
"login": {
|
||||
"andText": "및",
|
||||
@@ -348,17 +346,6 @@
|
||||
"x": "X",
|
||||
"y": "Y"
|
||||
},
|
||||
"boundingBoxes": {
|
||||
"clearAll": "모두 지우기",
|
||||
"clickRegionToEdit": "편집할 영역을 클릭하세요.",
|
||||
"colors": "색상 팔레트",
|
||||
"descLabel": "설명",
|
||||
"descPlaceholder": "이 영역에 대한 설명",
|
||||
"textLabel": "텍스트",
|
||||
"textPlaceholder": "표시할 텍스트 (원문 그대로)",
|
||||
"typeObj": "obj",
|
||||
"typeText": "텍스트"
|
||||
},
|
||||
"breadcrumbsMenu": {
|
||||
"app": "앱",
|
||||
"blueprint": "블루프린트",
|
||||
@@ -768,13 +755,6 @@
|
||||
"creditsAvailable": "사용 가능한 크레딧",
|
||||
"details": "세부 정보",
|
||||
"eventType": "이벤트 유형",
|
||||
"eventTypes": {
|
||||
"accountCreated": "계정 생성됨",
|
||||
"apiNodeUsage": "파트너 노드 사용",
|
||||
"apiUsage": "API 사용",
|
||||
"creditAdded": "크레딧 추가됨",
|
||||
"gpuUsage": "GPU 사용"
|
||||
},
|
||||
"faqs": "자주 묻는 질문",
|
||||
"invoiceHistory": "청구서 내역",
|
||||
"lastUpdated": "마지막 업데이트",
|
||||
@@ -1850,35 +1830,6 @@
|
||||
"zoomOptions": "줌 옵션",
|
||||
"zoomOut": "축소"
|
||||
},
|
||||
"hdrViewer": {
|
||||
"channel": "채널",
|
||||
"channels": {
|
||||
"a": "알파",
|
||||
"b": "B",
|
||||
"g": "G",
|
||||
"luminance": "휘도",
|
||||
"r": "R",
|
||||
"rgb": "RGB"
|
||||
},
|
||||
"clipWarnings": "클리핑 경고",
|
||||
"dither": "디더",
|
||||
"exposure": "노출",
|
||||
"failedToLoad": "HDR 이미지를 불러오지 못했습니다",
|
||||
"fitView": "맞춤",
|
||||
"hdrImage": "HDR 이미지",
|
||||
"histogram": "히스토그램",
|
||||
"inf": "Inf",
|
||||
"max": "최대",
|
||||
"mean": "평균",
|
||||
"min": "최소",
|
||||
"nan": "NaN",
|
||||
"normalizeExposure": "자동 노출",
|
||||
"openInHdrViewer": "HDR 뷰어에서 열기",
|
||||
"resolution": "해상도",
|
||||
"sourceGamut": "소스 감마",
|
||||
"stdDev": "표준편차",
|
||||
"title": "HDR 뷰어"
|
||||
},
|
||||
"help": {
|
||||
"helpCenterMenu": "도움말 센터 메뉴",
|
||||
"recentReleases": "최근 릴리스"
|
||||
@@ -3006,10 +2957,6 @@
|
||||
"uploadError": "페인터 이미지를 업로드하지 못했습니다: {status} - {statusText}",
|
||||
"width": "너비"
|
||||
},
|
||||
"palette": {
|
||||
"addColor": "색상 추가",
|
||||
"swatchTitle": "클릭: 편집 · 드래그: 순서 변경 · 우클릭: 삭제"
|
||||
},
|
||||
"progressToast": {
|
||||
"allDownloadsCompleted": "모든 다운로드가 완료되었습니다",
|
||||
"downloadingModel": "모델 다운로드 중...",
|
||||
@@ -3755,27 +3702,6 @@
|
||||
"customLoRAsLabel": "나만의 LoRA 가져오기",
|
||||
"description": "가장 적합한 플랜을 선택하세요",
|
||||
"descriptionWorkspace": "워크스페이스에 가장 적합한 플랜을 선택하세요",
|
||||
"downgrade": {
|
||||
"body": "이 워크스페이스의 다른 모든 멤버가 즉시 제거됩니다.",
|
||||
"confirm": "플랜 변경",
|
||||
"confirmationPhrase": "이해했습니다",
|
||||
"confirmationPrompt": "확인을 위해 \"{phrase}\"를 입력하세요.",
|
||||
"failed": "플랜 변경에 실패했습니다",
|
||||
"failedAfterMemberRemoval": "팀 멤버는 제거되었지만 플랜 변경이 완료되지 않았습니다 — 다시 시도하거나 지원팀에 문의해 주세요",
|
||||
"memberRemovalFailed": "{email}을(를) 팀에서 제거할 수 없습니다 — 일부 멤버가 이미 제거되었을 수 있으며 플랜이 변경되지 않았습니다",
|
||||
"notAllowed": "이 플랜 변경은 사용할 수 없습니다",
|
||||
"paymentMethodRequired": "플랜을 변경하려면 결제 수단이 필요합니다",
|
||||
"paymentPageBlocked": "결제 페이지를 열 수 없습니다 — 다시 시도해 주세요",
|
||||
"title": "{plan} 플랜으로 변경하시겠습니까?"
|
||||
},
|
||||
"enterprise": {
|
||||
"cta": "자세히 알아보기",
|
||||
"flexibility": "더 많은 유연성이나 맞춤 기능이 필요하신가요?",
|
||||
"name": "엔터프라이즈",
|
||||
"needMoreMembers": "더 많은 멤버가 필요하신가요?",
|
||||
"reachOut": "문의해 주시면 상담 일정을 잡아드리겠습니다."
|
||||
},
|
||||
"everythingInPlus": "{plan}의 모든 기능, 그리고 추가로:",
|
||||
"expiresDate": "만료일 {date}",
|
||||
"freeTier": {
|
||||
"description": "무료 플랜에는 Comfy Cloud를 체험할 수 있도록 매월 {credits} 크레딧이 포함되어 있습니다.",
|
||||
@@ -3822,7 +3748,6 @@
|
||||
"messageSupport": "고객 지원 문의",
|
||||
"monthly": "월간",
|
||||
"monthlyBonusDescription": "월간 크레딧 보너스",
|
||||
"monthlyCredits": "월간 크레딧",
|
||||
"monthlyCreditsInfo": "이 크레딧은 매월 갱신되며 이월되지 않습니다",
|
||||
"monthlyCreditsLabel": "월간 크레딧",
|
||||
"monthlyCreditsPerMemberLabel": "월별 크레딧 / 멤버",
|
||||
@@ -3835,13 +3760,7 @@
|
||||
"partnerNodesCredits": "파트너 노드 크레딧",
|
||||
"partnerNodesDescription": "상용/독점 모델 실행용",
|
||||
"perMonth": "USD / 월",
|
||||
"personalHeader": "개인 플랜은 개인 사용만을 위한 것입니다. {action}",
|
||||
"personalHeaderAction": "팀원을 추가하려면 팀 플랜을 구독하세요.",
|
||||
"personalWorkspace": "개인 워크스페이스",
|
||||
"planScope": {
|
||||
"personal": "개인용",
|
||||
"team": "팀용"
|
||||
},
|
||||
"plansAndPricing": "플랜 및 가격",
|
||||
"plansForWorkspace": "{workspace}의 플랜",
|
||||
"prepaidCreditsInfo": "별도 구매하여 만료되지 않는 크레딧",
|
||||
@@ -3852,10 +3771,8 @@
|
||||
"confirm": "확인",
|
||||
"confirmPayment": "결제 확인",
|
||||
"confirmPlanChange": "플랜 변경 확인",
|
||||
"creditsRefillTo": "크레딧이 다음으로 충전됨",
|
||||
"eachMonthCreditsRefill": "매월 크레딧이 다시 충전됩니다",
|
||||
"ends": "{date}에 종료",
|
||||
"everyMonthStarting": "매월 {date}부터",
|
||||
"hideFeatures": "기능 숨기기",
|
||||
"nextPaymentDue": "다음 결제일: {date}. 언제든지 취소할 수 있습니다.",
|
||||
"perMember": "/ 멤버",
|
||||
@@ -3865,18 +3782,10 @@
|
||||
"showMoreFeatures": "더 많은 기능 보기",
|
||||
"starting": "{date}부터 시작",
|
||||
"startingToday": "오늘부터 시작",
|
||||
"subscribeToPlan": "{plan} 구독하기",
|
||||
"switchToPlan": "{plan}으로 전환",
|
||||
"terms": "이용약관",
|
||||
"termsAgreement": "계속 진행하면 Comfy Org의 {terms} 및 {privacy}에 동의하게 됩니다.",
|
||||
"totalDueToday": "오늘 결제 금액 합계",
|
||||
"youllBeCharged": "결제가 진행됩니다"
|
||||
"totalDueToday": "오늘 결제 금액 합계"
|
||||
},
|
||||
"pricingBlurb": "*이 템플릿 기준, {seeDetails}. {questions} 또는 {enterpriseDiscussions}에 대해 문의해 주세요. 더 자세한 가격 정보는 {clickHere}.",
|
||||
"pricingBlurbClickHere": "여기를 클릭하세요",
|
||||
"pricingBlurbEnterprise": "엔터프라이즈 상담",
|
||||
"pricingBlurbQuestions": "문의",
|
||||
"pricingBlurbSeeDetails": "자세히 보기",
|
||||
"refreshCredits": "크레딧 새로고침",
|
||||
"renewsDate": "{date}에 갱신됨",
|
||||
"required": {
|
||||
@@ -3890,8 +3799,6 @@
|
||||
"resubscribe": "다시 구독하기",
|
||||
"resubscribeSuccess": "구독이 성공적으로 재활성화되었습니다",
|
||||
"resubscribeTo": "{plan} 다시 구독하기",
|
||||
"saveYearly": "연간 결제 시 20% 절약",
|
||||
"saveYearlyUpTo": "최대 20% 절약",
|
||||
"soloUseOnly": "개인용 전용",
|
||||
"subscribeForMore": "업그레이드",
|
||||
"subscribeNow": "지금 구독하기",
|
||||
@@ -3900,34 +3807,10 @@
|
||||
"subscribeToRun": "구독",
|
||||
"subscribeToRunFull": "실행 구독",
|
||||
"subscriptionRequiredMessage": "클라우드에서 워크플로우를 실행하려면 멤버가 구독해야 합니다",
|
||||
"success": {
|
||||
"allSet": "모든 준비가 완료되었습니다",
|
||||
"planUpdated": "플랜이 성공적으로 업데이트되었습니다.",
|
||||
"receiptEmailed": "영수증이 이메일로 발송되었습니다."
|
||||
},
|
||||
"teamHeader": "협업을 원하는 팀을 위한 플랜입니다. 더 많은 멤버가 필요하신가요? {learnMore} 엔터프라이즈에 대해 알아보세요.",
|
||||
"teamHeaderLearnMore": "자세히 알아보기",
|
||||
"teamPlan": {
|
||||
"changePlan": "플랜 변경",
|
||||
"checkoutComingSoon": "팀 플랜 결제는 곧 제공될 예정입니다.",
|
||||
"comingSoonLabel": "곧 제공:",
|
||||
"cta": "팀 연간 구독하기",
|
||||
"ctaMonthly": "팀 월간 구독하기",
|
||||
"currentPlan": "현재 플랜",
|
||||
"detailsTitle": "상세 정보",
|
||||
"name": "팀 플랜",
|
||||
"perkConcurrentRuns": "멤버별 동시 워크플로우 실행 가능",
|
||||
"perkInviteMembers": "팀 멤버 초대",
|
||||
"perkProjectAssets": "프로젝트 및 에셋 관리",
|
||||
"perkRolePermissions": "역할 기반 권한 관리",
|
||||
"perkSharedPool": "모든 멤버를 위한 공유 크레딧 풀",
|
||||
"tagline": "원하는 월간 크레딧 구독을 선택하세요. 더 많은 크레딧 구독 시 더 큰 할인 혜택을 받으세요."
|
||||
},
|
||||
"teamWorkspace": "팀 워크스페이스",
|
||||
"tierNameYearly": "{name} 연간",
|
||||
"tiers": {
|
||||
"creator": {
|
||||
"feature1": "나만의 모델 가져오기",
|
||||
"name": "Creator"
|
||||
},
|
||||
"founder": {
|
||||
@@ -3937,12 +3820,9 @@
|
||||
"name": "무료"
|
||||
},
|
||||
"pro": {
|
||||
"feature1": "더 긴 워크플로우 실행 시간(최대 1시간)",
|
||||
"name": "Pro"
|
||||
},
|
||||
"standard": {
|
||||
"feature1": "최대 30분 워크플로우 실행 시간",
|
||||
"feature2": "언제든지 크레딧 추가 가능",
|
||||
"name": "Standard"
|
||||
}
|
||||
},
|
||||
@@ -3955,7 +3835,6 @@
|
||||
"upgradeToAddCredits": "크레딧 추가를 위해 업그레이드하세요",
|
||||
"usdPerMonth": "USD / 월",
|
||||
"usdPerMonthPerMember": "USD / 월 / 멤버",
|
||||
"videoEstimate": "약 {count}개의 5초 영상 생성*",
|
||||
"videoEstimateExplanation": "이 추정치는 기본 설정(5초, 640x640, 16fps, 4단계 샘플링)을 사용한 Wan 2.2 이미지-투-비디오 템플릿을 기준으로 합니다.",
|
||||
"videoEstimateHelp": "이 템플릿에 대한 자세한 정보",
|
||||
"videoEstimateLabel": "Wan 2.2 이미지-투-비디오 템플릿으로 생성 가능한 5초 비디오 수",
|
||||
@@ -3965,11 +3844,10 @@
|
||||
"viewMoreDetails": "자세히 보기",
|
||||
"viewMoreDetailsPlans": "플랜 및 가격에 대한 자세한 정보 보기",
|
||||
"viewUsageHistory": "사용 기록 보기",
|
||||
"whatsIncluded": "포함 내용:",
|
||||
"workspaceNotSubscribed": "이 워크스페이스는 구독 중이 아닙니다",
|
||||
"yearly": "연간",
|
||||
"yearlyCreditsLabel": "연간 총 크레딧",
|
||||
"yearlyDiscount": "20% 할인",
|
||||
"saveYearly": "20% 절감",
|
||||
"yourPlanIncludes": "귀하의 플랜 포함 사항:"
|
||||
},
|
||||
"tabMenu": {
|
||||
|
||||
@@ -92,7 +92,6 @@
|
||||
"errorUserTokenAccessDenied": "Seu token de API não tem acesso a este recurso. Verifique as permissões do seu token.",
|
||||
"errorUserTokenInvalid": "Seu token de API armazenado é inválido ou expirou. Atualize seu token nas configurações.",
|
||||
"failedToCreateNode": "Falha ao criar o nó. Por favor, tente novamente ou verifique o console para mais detalhes.",
|
||||
"failedToSetModelValue": "Nó adicionado, mas seu modelo não pôde ser definido automaticamente. Verifique o console para mais detalhes.",
|
||||
"fileFormats": "Formatos de arquivo",
|
||||
"fileName": "Nome do arquivo",
|
||||
"fileSize": "Tamanho do arquivo",
|
||||
@@ -242,8 +241,7 @@
|
||||
"auth/user-not-found": "Nenhuma conta encontrada com este e-mail. Gostaria de criar uma nova conta?",
|
||||
"auth/weak-password": "A senha é muito fraca. Use uma senha mais forte com pelo menos 6 caracteres.",
|
||||
"auth/wrong-password": "A senha que você digitou está incorreta. Por favor, tente novamente.",
|
||||
"generic": "Algo deu errado ao fazer login. Por favor, tente novamente.",
|
||||
"signupBlocked": "Não foi possível criar sua conta agora. Por favor, tente novamente mais tarde. Se o problema persistir, envie um e-mail para support@comfy.org."
|
||||
"generic": "Algo deu errado ao fazer login. Por favor, tente novamente."
|
||||
},
|
||||
"login": {
|
||||
"andText": "e",
|
||||
@@ -348,17 +346,6 @@
|
||||
"x": "X",
|
||||
"y": "Y"
|
||||
},
|
||||
"boundingBoxes": {
|
||||
"clearAll": "Limpar tudo",
|
||||
"clickRegionToEdit": "Clique em uma região para editar.",
|
||||
"colors": "paleta_de_cores",
|
||||
"descLabel": "descrição",
|
||||
"descPlaceholder": "descrição desta região",
|
||||
"textLabel": "Texto",
|
||||
"textPlaceholder": "texto a ser exibido (literal)",
|
||||
"typeObj": "obj",
|
||||
"typeText": "texto"
|
||||
},
|
||||
"breadcrumbsMenu": {
|
||||
"app": "App",
|
||||
"blueprint": "Blueprint",
|
||||
@@ -768,13 +755,6 @@
|
||||
"creditsAvailable": "Créditos disponíveis",
|
||||
"details": "Detalhes",
|
||||
"eventType": "Tipo de evento",
|
||||
"eventTypes": {
|
||||
"accountCreated": "Conta criada",
|
||||
"apiNodeUsage": "Uso de Node Parceiro",
|
||||
"apiUsage": "Uso da API",
|
||||
"creditAdded": "Créditos adicionados",
|
||||
"gpuUsage": "Uso de GPU"
|
||||
},
|
||||
"faqs": "Perguntas frequentes",
|
||||
"invoiceHistory": "Histórico de faturas",
|
||||
"lastUpdated": "Última atualização",
|
||||
@@ -1850,35 +1830,6 @@
|
||||
"zoomOptions": "Opções de Zoom",
|
||||
"zoomOut": "Afastar"
|
||||
},
|
||||
"hdrViewer": {
|
||||
"channel": "Canal",
|
||||
"channels": {
|
||||
"a": "Alfa",
|
||||
"b": "B",
|
||||
"g": "G",
|
||||
"luminance": "Luminância",
|
||||
"r": "R",
|
||||
"rgb": "RGB"
|
||||
},
|
||||
"clipWarnings": "Avisos de recorte",
|
||||
"dither": "Dithering",
|
||||
"exposure": "Exposição",
|
||||
"failedToLoad": "Falha ao carregar a imagem HDR",
|
||||
"fitView": "Ajustar",
|
||||
"hdrImage": "Imagem HDR",
|
||||
"histogram": "Histograma",
|
||||
"inf": "Inf",
|
||||
"max": "Máx",
|
||||
"mean": "Média",
|
||||
"min": "Mín",
|
||||
"nan": "NaN",
|
||||
"normalizeExposure": "Exposição automática",
|
||||
"openInHdrViewer": "Abrir no Visualizador HDR",
|
||||
"resolution": "Resolução",
|
||||
"sourceGamut": "Gama de origem",
|
||||
"stdDev": "Desvio padrão",
|
||||
"title": "Visualizador HDR"
|
||||
},
|
||||
"help": {
|
||||
"helpCenterMenu": "Menu do Centro de Ajuda",
|
||||
"recentReleases": "Lançamentos recentes"
|
||||
@@ -3006,10 +2957,6 @@
|
||||
"uploadError": "Falha ao enviar imagem do painter: {status} - {statusText}",
|
||||
"width": "Largura"
|
||||
},
|
||||
"palette": {
|
||||
"addColor": "Adicionar cor",
|
||||
"swatchTitle": "Clique para editar · arraste para reordenar · clique direito para remover"
|
||||
},
|
||||
"progressToast": {
|
||||
"allDownloadsCompleted": "Todos os downloads concluídos",
|
||||
"downloadingModel": "Baixando modelo...",
|
||||
@@ -3767,27 +3714,6 @@
|
||||
"customLoRAsLabel": "Importe seus próprios LoRAs",
|
||||
"description": "Escolha o melhor plano para você",
|
||||
"descriptionWorkspace": "Escolha o melhor plano para seu workspace",
|
||||
"downgrade": {
|
||||
"body": "Todos os outros membros deste workspace serão removidos imediatamente.",
|
||||
"confirm": "Mudar plano",
|
||||
"confirmationPhrase": "Eu entendo",
|
||||
"confirmationPrompt": "Digite \"{phrase}\" para confirmar.",
|
||||
"failed": "Falha ao mudar o plano",
|
||||
"failedAfterMemberRemoval": "Os membros da equipe foram removidos, mas a alteração do plano não foi concluída — tente novamente ou entre em contato com o suporte",
|
||||
"memberRemovalFailed": "Não foi possível remover {email} da equipe — alguns membros podem já ter sido removidos e seu plano não foi alterado",
|
||||
"notAllowed": "Esta alteração de plano não está disponível",
|
||||
"paymentMethodRequired": "É necessário um método de pagamento para mudar de plano",
|
||||
"paymentPageBlocked": "Não foi possível abrir a página de pagamento — tente novamente",
|
||||
"title": "Mudar para o plano {plan}?"
|
||||
},
|
||||
"enterprise": {
|
||||
"cta": "Saiba mais",
|
||||
"flexibility": "Procurando mais flexibilidade ou recursos personalizados?",
|
||||
"name": "Enterprise",
|
||||
"needMoreMembers": "Precisa de mais membros?",
|
||||
"reachOut": "Entre em contato conosco e vamos agendar uma conversa."
|
||||
},
|
||||
"everythingInPlus": "Tudo do {plan}, além de:",
|
||||
"expiresDate": "Expira em {date}",
|
||||
"freeTier": {
|
||||
"description": "Seu plano gratuito inclui {credits} créditos por mês para testar o Comfy Cloud.",
|
||||
@@ -3834,7 +3760,6 @@
|
||||
"messageSupport": "Falar com o suporte",
|
||||
"monthly": "Mensal",
|
||||
"monthlyBonusDescription": "Bônus mensal de créditos",
|
||||
"monthlyCredits": "créditos mensais",
|
||||
"monthlyCreditsInfo": "Esses créditos são renovados mensalmente e não acumulam",
|
||||
"monthlyCreditsLabel": "Créditos mensais",
|
||||
"monthlyCreditsPerMemberLabel": "Créditos mensais / membro",
|
||||
@@ -3847,13 +3772,7 @@
|
||||
"partnerNodesCredits": "Preços dos Partner Nodes",
|
||||
"partnerNodesDescription": "Para executar modelos comerciais/proprietários",
|
||||
"perMonth": "/ mês",
|
||||
"personalHeader": "Planos pessoais são apenas para uso individual. {action}",
|
||||
"personalHeaderAction": "Para adicionar colegas, assine o plano de equipe.",
|
||||
"personalWorkspace": "Espaço de Trabalho Pessoal",
|
||||
"planScope": {
|
||||
"personal": "Para uso pessoal",
|
||||
"team": "Para equipes"
|
||||
},
|
||||
"plansAndPricing": "Planos e preços",
|
||||
"plansForWorkspace": "Planos para {workspace}",
|
||||
"prepaidCreditsInfo": "Créditos pré-pagos expiram após 1 ano da data de compra.",
|
||||
@@ -3864,10 +3783,8 @@
|
||||
"confirm": "Confirmar",
|
||||
"confirmPayment": "Confirme seu pagamento",
|
||||
"confirmPlanChange": "Confirme a alteração do plano",
|
||||
"creditsRefillTo": "Créditos recarregados para",
|
||||
"eachMonthCreditsRefill": "A cada mês os créditos são recarregados para",
|
||||
"ends": "Termina em {date}",
|
||||
"everyMonthStarting": "Todo mês a partir de {date}",
|
||||
"hideFeatures": "Ocultar recursos",
|
||||
"nextPaymentDue": "Próximo pagamento em {date}. Cancele a qualquer momento.",
|
||||
"perMember": "/ membro",
|
||||
@@ -3877,18 +3794,10 @@
|
||||
"showMoreFeatures": "Mostrar mais recursos",
|
||||
"starting": "Começando em {date}",
|
||||
"startingToday": "Começando hoje",
|
||||
"subscribeToPlan": "Assinar {plan}",
|
||||
"switchToPlan": "Mudar para {plan}",
|
||||
"terms": "Termos",
|
||||
"termsAgreement": "Ao continuar, você concorda com os {terms} e {privacy} da Comfy Org.",
|
||||
"totalDueToday": "Total devido hoje",
|
||||
"youllBeCharged": "Você será cobrado"
|
||||
"totalDueToday": "Total devido hoje"
|
||||
},
|
||||
"pricingBlurb": "*Baseado neste template, {seeDetails}. Entre em contato para {questions} ou {enterpriseDiscussions}. Para mais detalhes sobre preços, {clickHere}.",
|
||||
"pricingBlurbClickHere": "clique aqui",
|
||||
"pricingBlurbEnterprise": "discussões enterprise",
|
||||
"pricingBlurbQuestions": "dúvidas",
|
||||
"pricingBlurbSeeDetails": "ver detalhes",
|
||||
"refreshCredits": "Atualizar créditos",
|
||||
"renewsDate": "Renova em {date}",
|
||||
"required": {
|
||||
@@ -3902,8 +3811,6 @@
|
||||
"resubscribe": "Reassinar",
|
||||
"resubscribeSuccess": "Assinatura reativada com sucesso",
|
||||
"resubscribeTo": "Reassinar {plan}",
|
||||
"saveYearly": "Economize 20%",
|
||||
"saveYearlyUpTo": "Economize até 20%",
|
||||
"soloUseOnly": "Apenas para uso individual",
|
||||
"subscribeForMore": "Fazer upgrade",
|
||||
"subscribeNow": "Assine Agora",
|
||||
@@ -3912,34 +3819,10 @@
|
||||
"subscribeToRun": "Assinar",
|
||||
"subscribeToRunFull": "Assine para Executar",
|
||||
"subscriptionRequiredMessage": "Uma assinatura é necessária para que os membros executem fluxos de trabalho na Nuvem",
|
||||
"success": {
|
||||
"allSet": "Tudo pronto",
|
||||
"planUpdated": "Seu plano foi atualizado com sucesso.",
|
||||
"receiptEmailed": "Um recibo foi enviado para seu e-mail."
|
||||
},
|
||||
"teamHeader": "Para equipes que desejam colaborar. Precisa de mais membros? {learnMore} sobre enterprise.",
|
||||
"teamHeaderLearnMore": "Saiba mais",
|
||||
"teamPlan": {
|
||||
"changePlan": "Mudar plano",
|
||||
"checkoutComingSoon": "Checkout do plano de equipe em breve.",
|
||||
"comingSoonLabel": "Em breve:",
|
||||
"cta": "Assinar Equipe Anual",
|
||||
"ctaMonthly": "Assinar Equipe Mensal",
|
||||
"currentPlan": "Plano atual",
|
||||
"detailsTitle": "Detalhes",
|
||||
"name": "Plano Equipe",
|
||||
"perkConcurrentRuns": "Membros podem executar workflows simultaneamente",
|
||||
"perkInviteMembers": "Convide membros da equipe",
|
||||
"perkProjectAssets": "Gestão de projetos e ativos",
|
||||
"perkRolePermissions": "Permissões baseadas em função",
|
||||
"perkSharedPool": "Pool de créditos compartilhado para todos os membros",
|
||||
"tagline": "Escolha sua própria assinatura mensal de créditos. Obtenha um desconto maior com uma assinatura de mais créditos."
|
||||
},
|
||||
"teamWorkspace": "Espaço de Trabalho em Equipe",
|
||||
"tierNameYearly": "{name} Anual",
|
||||
"tiers": {
|
||||
"creator": {
|
||||
"feature1": "Importe seus próprios modelos",
|
||||
"name": "Criador"
|
||||
},
|
||||
"founder": {
|
||||
@@ -3949,12 +3832,9 @@
|
||||
"name": "Gratuito"
|
||||
},
|
||||
"pro": {
|
||||
"feature1": "Tempo de execução do workflow mais longo (até 1 hora)",
|
||||
"name": "Pro"
|
||||
},
|
||||
"standard": {
|
||||
"feature1": "Tempo máximo de execução do workflow: 30 minutos",
|
||||
"feature2": "Adicione mais créditos a qualquer momento",
|
||||
"name": "Padrão"
|
||||
}
|
||||
},
|
||||
@@ -3967,7 +3847,6 @@
|
||||
"upgradeToAddCredits": "Faça upgrade para adicionar créditos",
|
||||
"usdPerMonth": "USD / mês",
|
||||
"usdPerMonthPerMember": "USD / mês / membro",
|
||||
"videoEstimate": "Gera aproximadamente {count} vídeos de 5s*",
|
||||
"videoEstimateExplanation": "Essas estimativas são baseadas no template Wan 2.2 Image-to-Video usando as configurações padrão (5 segundos, 640x640, 16fps, amostragem de 4 etapas).",
|
||||
"videoEstimateHelp": "Mais detalhes sobre este template",
|
||||
"videoEstimateLabel": "Quantidade aprox. de vídeos de 5s gerados com o template Wan 2.2 Image-to-Video",
|
||||
@@ -3977,11 +3856,10 @@
|
||||
"viewMoreDetails": "Ver mais detalhes",
|
||||
"viewMoreDetailsPlans": "Veja mais detalhes sobre planos e preços",
|
||||
"viewUsageHistory": "Ver histórico de uso",
|
||||
"whatsIncluded": "O que está incluído:",
|
||||
"workspaceNotSubscribed": "Este espaço de trabalho não possui uma assinatura",
|
||||
"yearly": "Anual",
|
||||
"yearlyCreditsLabel": "Total de créditos anuais",
|
||||
"yearlyDiscount": "20% DE DESCONTO",
|
||||
"saveYearly": "Economize 20%",
|
||||
"yourPlanIncludes": "Seu plano inclui:"
|
||||
},
|
||||
"tabMenu": {
|
||||
|
||||
@@ -92,7 +92,6 @@
|
||||
"errorUserTokenAccessDenied": "Ваш API-токен не имеет доступа к этому ресурсу. Проверьте права доступа токена.",
|
||||
"errorUserTokenInvalid": "Ваш сохранённый API-токен недействителен или истёк. Обновите токен в настройках.",
|
||||
"failedToCreateNode": "Не удалось создать узел. Попробуйте ещё раз или проверьте консоль для подробностей.",
|
||||
"failedToSetModelValue": "Узел добавлен, но его модель не удалось установить автоматически. Проверьте консоль для подробностей.",
|
||||
"fileFormats": "Форматы файлов",
|
||||
"fileName": "Имя файла",
|
||||
"fileSize": "Размер файла",
|
||||
@@ -242,8 +241,7 @@
|
||||
"auth/user-not-found": "Учетная запись с этим email не найдена. Хотите создать новую учетную запись?",
|
||||
"auth/weak-password": "Пароль слишком слабый. Пожалуйста, используйте более надежный пароль длиной не менее 6 символов.",
|
||||
"auth/wrong-password": "Введенный пароль неверен. Пожалуйста, попробуйте еще раз.",
|
||||
"generic": "Произошла ошибка при входе в систему. Пожалуйста, попробуйте еще раз.",
|
||||
"signupBlocked": "Сейчас не удалось создать ваш аккаунт. Пожалуйста, попробуйте позже. Если проблема повторяется, напишите на support@comfy.org."
|
||||
"generic": "Произошла ошибка при входе в систему. Пожалуйста, попробуйте еще раз."
|
||||
},
|
||||
"login": {
|
||||
"andText": "и",
|
||||
@@ -348,17 +346,6 @@
|
||||
"x": "X",
|
||||
"y": "Y"
|
||||
},
|
||||
"boundingBoxes": {
|
||||
"clearAll": "Очистить всё",
|
||||
"clickRegionToEdit": "Кликните по области для редактирования.",
|
||||
"colors": "палитра_цветов",
|
||||
"descLabel": "описание",
|
||||
"descPlaceholder": "описание этой области",
|
||||
"textLabel": "Текст",
|
||||
"textPlaceholder": "текст для отображения (дословно)",
|
||||
"typeObj": "объект",
|
||||
"typeText": "текст"
|
||||
},
|
||||
"breadcrumbsMenu": {
|
||||
"app": "Приложение",
|
||||
"blueprint": "Чертёж",
|
||||
@@ -768,13 +755,6 @@
|
||||
"creditsAvailable": "Доступно кредитов",
|
||||
"details": "Детали",
|
||||
"eventType": "Тип события",
|
||||
"eventTypes": {
|
||||
"accountCreated": "Аккаунт создан",
|
||||
"apiNodeUsage": "Использование партнерского узла",
|
||||
"apiUsage": "Использование API",
|
||||
"creditAdded": "Кредиты добавлены",
|
||||
"gpuUsage": "Использование GPU"
|
||||
},
|
||||
"faqs": "Часто задаваемые вопросы",
|
||||
"invoiceHistory": "История счетов",
|
||||
"lastUpdated": "Последнее обновление",
|
||||
@@ -1850,35 +1830,6 @@
|
||||
"zoomOptions": "Параметры масштабирования",
|
||||
"zoomOut": "Уменьшить"
|
||||
},
|
||||
"hdrViewer": {
|
||||
"channel": "Канал",
|
||||
"channels": {
|
||||
"a": "Альфа",
|
||||
"b": "B",
|
||||
"g": "G",
|
||||
"luminance": "Яркость",
|
||||
"r": "R",
|
||||
"rgb": "RGB"
|
||||
},
|
||||
"clipWarnings": "Предупреждения о клиппинге",
|
||||
"dither": "Дизеринг",
|
||||
"exposure": "Экспозиция",
|
||||
"failedToLoad": "Не удалось загрузить HDR изображение",
|
||||
"fitView": "Вписать",
|
||||
"hdrImage": "HDR изображение",
|
||||
"histogram": "Гистограмма",
|
||||
"inf": "Беск.",
|
||||
"max": "Макс.",
|
||||
"mean": "Среднее",
|
||||
"min": "Мин.",
|
||||
"nan": "NaN",
|
||||
"normalizeExposure": "Автоэкспозиция",
|
||||
"openInHdrViewer": "Открыть в HDR просмотрщике",
|
||||
"resolution": "Разрешение",
|
||||
"sourceGamut": "Исходный цветовой охват",
|
||||
"stdDev": "Ст. отклонение",
|
||||
"title": "HDR Просмотрщик"
|
||||
},
|
||||
"help": {
|
||||
"helpCenterMenu": "Меню справочного центра",
|
||||
"recentReleases": "Недавние релизы"
|
||||
@@ -3006,10 +2957,6 @@
|
||||
"uploadError": "Не удалось загрузить изображение: {status} - {statusText}",
|
||||
"width": "Ширина"
|
||||
},
|
||||
"palette": {
|
||||
"addColor": "Добавить цвет",
|
||||
"swatchTitle": "Клик — редактировать · перетащить — изменить порядок · ПКМ — удалить"
|
||||
},
|
||||
"progressToast": {
|
||||
"allDownloadsCompleted": "Все загрузки завершены",
|
||||
"downloadingModel": "Загрузка модели...",
|
||||
@@ -3755,27 +3702,6 @@
|
||||
"customLoRAsLabel": "Импортируйте свои LoRA",
|
||||
"description": "Выберите лучший план для себя",
|
||||
"descriptionWorkspace": "Выберите лучший тариф для вашего рабочего пространства",
|
||||
"downgrade": {
|
||||
"body": "Все остальные участники этой рабочей области будут немедленно удалены.",
|
||||
"confirm": "Сменить тариф",
|
||||
"confirmationPhrase": "Я понимаю",
|
||||
"confirmationPrompt": "Введите «{phrase}» для подтверждения.",
|
||||
"failed": "Не удалось сменить тариф",
|
||||
"failedAfterMemberRemoval": "Участники команды были удалены, но смена тарифа не завершена — попробуйте еще раз или обратитесь в поддержку",
|
||||
"memberRemovalFailed": "Не удалось удалить {email} из команды — некоторые участники могли быть уже удалены, и ваш тариф не был изменён",
|
||||
"notAllowed": "Смена этого тарифа недоступна",
|
||||
"paymentMethodRequired": "Для смены тарифа требуется способ оплаты",
|
||||
"paymentPageBlocked": "Не удалось открыть страницу оплаты — попробуйте еще раз",
|
||||
"title": "Перейти на тариф {plan}?"
|
||||
},
|
||||
"enterprise": {
|
||||
"cta": "Узнать больше",
|
||||
"flexibility": "Нужна большая гибкость или индивидуальные функции?",
|
||||
"name": "Корпоративный тариф",
|
||||
"needMoreMembers": "Нужно больше участников?",
|
||||
"reachOut": "Свяжитесь с нами, чтобы назначить встречу."
|
||||
},
|
||||
"everythingInPlus": "Всё в {plan}, плюс:",
|
||||
"expiresDate": "Истекает {date}",
|
||||
"freeTier": {
|
||||
"description": "Ваш бесплатный тариф включает {credits} кредитов каждый месяц для использования Comfy Cloud.",
|
||||
@@ -3822,7 +3748,6 @@
|
||||
"messageSupport": "Написать в поддержку",
|
||||
"monthly": "Ежемесячно",
|
||||
"monthlyBonusDescription": "Ежемесячный бонус кредитов",
|
||||
"monthlyCredits": "кредитов в месяц",
|
||||
"monthlyCreditsInfo": "Эти кредиты обновляются ежемесячно и не переносятся",
|
||||
"monthlyCreditsLabel": "Ежемесячные кредиты",
|
||||
"monthlyCreditsPerMemberLabel": "Ежемесячные кредиты / участник",
|
||||
@@ -3835,13 +3760,7 @@
|
||||
"partnerNodesCredits": "Кредиты партнёрских узлов",
|
||||
"partnerNodesDescription": "Для запуска коммерческих/проприетарных моделей",
|
||||
"perMonth": "USD / месяц",
|
||||
"personalHeader": "Личные тарифы предназначены только для индивидуального использования. {action}",
|
||||
"personalHeaderAction": "Чтобы добавить участников, оформите командный тариф.",
|
||||
"personalWorkspace": "Личное рабочее пространство",
|
||||
"planScope": {
|
||||
"personal": "Для личного использования",
|
||||
"team": "Для команд"
|
||||
},
|
||||
"plansAndPricing": "Планы и цены",
|
||||
"plansForWorkspace": "Тарифы для {workspace}",
|
||||
"prepaidCreditsInfo": "Кредиты, приобретённые отдельно и не имеющие срока действия",
|
||||
@@ -3852,10 +3771,8 @@
|
||||
"confirm": "Подтвердить",
|
||||
"confirmPayment": "Подтвердите оплату",
|
||||
"confirmPlanChange": "Подтвердите смену тарифа",
|
||||
"creditsRefillTo": "Кредиты пополняются до",
|
||||
"eachMonthCreditsRefill": "Ежемесячное пополнение кредитов до",
|
||||
"ends": "Заканчивается {date}",
|
||||
"everyMonthStarting": "Каждый месяц начиная с {date}",
|
||||
"hideFeatures": "Скрыть функции",
|
||||
"nextPaymentDue": "Следующий платеж {date}. Отменить можно в любое время.",
|
||||
"perMember": "/ участник",
|
||||
@@ -3865,18 +3782,10 @@
|
||||
"showMoreFeatures": "Показать больше функций",
|
||||
"starting": "Начинается {date}",
|
||||
"startingToday": "Начинается сегодня",
|
||||
"subscribeToPlan": "Подписаться на {plan}",
|
||||
"switchToPlan": "Перейти на {plan}",
|
||||
"terms": "Условия",
|
||||
"termsAgreement": "Продолжая, вы соглашаетесь с {terms} и {privacy} Comfy Org.",
|
||||
"totalDueToday": "Итого к оплате сегодня",
|
||||
"youllBeCharged": "С вас будет списано"
|
||||
"totalDueToday": "Итого к оплате сегодня"
|
||||
},
|
||||
"pricingBlurb": "*Основано на этом шаблоне, {seeDetails}. Свяжитесь с нами по {questions} или для {enterpriseDiscussions}. Для подробной информации о ценах {clickHere}.",
|
||||
"pricingBlurbClickHere": "нажмите здесь",
|
||||
"pricingBlurbEnterprise": "корпоративным обсуждениям",
|
||||
"pricingBlurbQuestions": "вопросам",
|
||||
"pricingBlurbSeeDetails": "подробнее",
|
||||
"refreshCredits": "Обновить кредиты",
|
||||
"renewsDate": "Обновляется {date}",
|
||||
"required": {
|
||||
@@ -3890,8 +3799,6 @@
|
||||
"resubscribe": "Возобновить подписку",
|
||||
"resubscribeSuccess": "Подписка успешно возобновлена",
|
||||
"resubscribeTo": "Возобновить подписку на {plan}",
|
||||
"saveYearly": "Экономьте 20%",
|
||||
"saveYearlyUpTo": "Экономьте до 20%",
|
||||
"soloUseOnly": "Только для индивидуального использования",
|
||||
"subscribeForMore": "Обновить",
|
||||
"subscribeNow": "Подписаться сейчас",
|
||||
@@ -3900,34 +3807,10 @@
|
||||
"subscribeToRun": "Подписаться",
|
||||
"subscribeToRunFull": "Подписаться для запуска",
|
||||
"subscriptionRequiredMessage": "Для запуска рабочих процессов в облаке участникам требуется подписка",
|
||||
"success": {
|
||||
"allSet": "Всё готово",
|
||||
"planUpdated": "Ваш тариф успешно обновлён.",
|
||||
"receiptEmailed": "Квитанция отправлена на вашу электронную почту."
|
||||
},
|
||||
"teamHeader": "Для команд, желающих сотрудничать. Нужно больше участников? {learnMore} о корпоративных возможностях.",
|
||||
"teamHeaderLearnMore": "Узнать больше",
|
||||
"teamPlan": {
|
||||
"changePlan": "Сменить тариф",
|
||||
"checkoutComingSoon": "Оформление командного тарифа скоро появится.",
|
||||
"comingSoonLabel": "Скоро появится:",
|
||||
"cta": "Оформить командную годовую подписку",
|
||||
"ctaMonthly": "Оформить командную месячную подписку",
|
||||
"currentPlan": "Текущий тариф",
|
||||
"detailsTitle": "Детали",
|
||||
"name": "Командный тариф",
|
||||
"perkConcurrentRuns": "Участники могут запускать рабочие процессы одновременно",
|
||||
"perkInviteMembers": "Приглашайте участников команды",
|
||||
"perkProjectAssets": "Управление проектами и ресурсами",
|
||||
"perkRolePermissions": "Ролевые разрешения",
|
||||
"perkSharedPool": "Общий пул кредитов для всех участников",
|
||||
"tagline": "Выберите собственную ежемесячную подписку на кредиты. Чем больше кредитов — тем больше скидка."
|
||||
},
|
||||
"teamWorkspace": "Командное рабочее пространство",
|
||||
"tierNameYearly": "{name} Ежегодно",
|
||||
"tiers": {
|
||||
"creator": {
|
||||
"feature1": "Импортируйте собственные модели",
|
||||
"name": "Creator"
|
||||
},
|
||||
"founder": {
|
||||
@@ -3937,12 +3820,9 @@
|
||||
"name": "Бесплатно"
|
||||
},
|
||||
"pro": {
|
||||
"feature1": "Более длительное выполнение рабочего процесса (до 1 часа)",
|
||||
"name": "Pro"
|
||||
},
|
||||
"standard": {
|
||||
"feature1": "Максимальное время выполнения рабочего процесса — 30 минут",
|
||||
"feature2": "Добавляйте кредиты в любое время",
|
||||
"name": "Standard"
|
||||
}
|
||||
},
|
||||
@@ -3955,7 +3835,6 @@
|
||||
"upgradeToAddCredits": "Обновите, чтобы добавить кредиты",
|
||||
"usdPerMonth": "USD / мес",
|
||||
"usdPerMonthPerMember": "USD / мес / участник",
|
||||
"videoEstimate": "Генерирует ~{count} 5-секундных видео*",
|
||||
"videoEstimateExplanation": "Эти оценки основаны на шаблоне Wan 2.2 Image-to-Video с настройками по умолчанию (5 секунд, 640x640, 16 кадров/с, 4 шага семплирования).",
|
||||
"videoEstimateHelp": "Подробнее об этом шаблоне",
|
||||
"videoEstimateLabel": "Примерное количество 5-секундных видео, созданных с помощью шаблона Wan 2.2 Image-to-Video",
|
||||
@@ -3965,11 +3844,10 @@
|
||||
"viewMoreDetails": "Подробнее",
|
||||
"viewMoreDetailsPlans": "Подробнее о планах и ценах",
|
||||
"viewUsageHistory": "История использования",
|
||||
"whatsIncluded": "Что входит:",
|
||||
"workspaceNotSubscribed": "Это рабочее пространство не имеет подписки",
|
||||
"yearly": "Ежегодно",
|
||||
"yearlyCreditsLabel": "Годовые кредиты",
|
||||
"yearlyDiscount": "СКИДКА 20%",
|
||||
"saveYearly": "Экономия 20%",
|
||||
"yourPlanIncludes": "Ваш план включает:"
|
||||
},
|
||||
"tabMenu": {
|
||||
|
||||
@@ -92,7 +92,6 @@
|
||||
"errorUserTokenAccessDenied": "API anahtarınızın bu kaynağa erişimi yok. Lütfen anahtar izinlerinizi kontrol edin.",
|
||||
"errorUserTokenInvalid": "Kayıtlı API anahtarınız geçersiz veya süresi dolmuş. Lütfen ayarlardan anahtarınızı güncelleyin.",
|
||||
"failedToCreateNode": "Düğüm oluşturulamadı. Lütfen tekrar deneyin veya ayrıntılar için konsolu kontrol edin.",
|
||||
"failedToSetModelValue": "Düğüm eklendi, ancak modeli otomatik olarak ayarlanamadı. Detaylar için konsolu kontrol edin.",
|
||||
"fileFormats": "Dosya formatları",
|
||||
"fileName": "Dosya Adı",
|
||||
"fileSize": "Dosya Boyutu",
|
||||
@@ -242,8 +241,7 @@
|
||||
"auth/user-not-found": "Bu e-posta ile ilişkili bir hesap bulunamadı. Yeni bir hesap oluşturmak ister misiniz?",
|
||||
"auth/weak-password": "Parola çok zayıf. Lütfen en az 6 karakterden oluşan daha güçlü bir parola kullanın.",
|
||||
"auth/wrong-password": "Girdiğiniz parola yanlış. Lütfen tekrar deneyin.",
|
||||
"generic": "Oturum açarken bir hata oluştu. Lütfen tekrar deneyin.",
|
||||
"signupBlocked": "Şu anda hesabınızı oluşturamıyoruz. Lütfen daha sonra tekrar deneyin. Sorun devam ederse support@comfy.org adresine e-posta gönderin."
|
||||
"generic": "Oturum açarken bir hata oluştu. Lütfen tekrar deneyin."
|
||||
},
|
||||
"login": {
|
||||
"andText": "ve",
|
||||
@@ -348,17 +346,6 @@
|
||||
"x": "X",
|
||||
"y": "Y"
|
||||
},
|
||||
"boundingBoxes": {
|
||||
"clearAll": "Tümünü temizle",
|
||||
"clickRegionToEdit": "Düzenlemek için bir bölgeye tıklayın.",
|
||||
"colors": "renk_paleti",
|
||||
"descLabel": "açıklama",
|
||||
"descPlaceholder": "bu bölgenin açıklaması",
|
||||
"textLabel": "Metin",
|
||||
"textPlaceholder": "görüntülenecek metin (aynen)",
|
||||
"typeObj": "nesne",
|
||||
"typeText": "metin"
|
||||
},
|
||||
"breadcrumbsMenu": {
|
||||
"app": "Uygulama",
|
||||
"blueprint": "Plan",
|
||||
@@ -768,13 +755,6 @@
|
||||
"creditsAvailable": "Mevcut kredi",
|
||||
"details": "Detaylar",
|
||||
"eventType": "Etkinlik Türü",
|
||||
"eventTypes": {
|
||||
"accountCreated": "Hesap Oluşturuldu",
|
||||
"apiNodeUsage": "Partner Node Kullanımı",
|
||||
"apiUsage": "API Kullanımı",
|
||||
"creditAdded": "Kredi Eklendi",
|
||||
"gpuUsage": "GPU Kullanımı"
|
||||
},
|
||||
"faqs": "SSS",
|
||||
"invoiceHistory": "Fatura Geçmişi",
|
||||
"lastUpdated": "Son güncellenme",
|
||||
@@ -1850,35 +1830,6 @@
|
||||
"zoomOptions": "Yakınlaştırma Seçenekleri",
|
||||
"zoomOut": "Uzaklaştır"
|
||||
},
|
||||
"hdrViewer": {
|
||||
"channel": "Kanal",
|
||||
"channels": {
|
||||
"a": "Alfa",
|
||||
"b": "B",
|
||||
"g": "G",
|
||||
"luminance": "Parlaklık",
|
||||
"r": "R",
|
||||
"rgb": "RGB"
|
||||
},
|
||||
"clipWarnings": "Kırpma uyarıları",
|
||||
"dither": "Dithering",
|
||||
"exposure": "Pozlama",
|
||||
"failedToLoad": "HDR görüntü yüklenemedi",
|
||||
"fitView": "Sığdır",
|
||||
"hdrImage": "HDR görüntü",
|
||||
"histogram": "Histogram",
|
||||
"inf": "Sonsuz",
|
||||
"max": "Maks",
|
||||
"mean": "Ortalama",
|
||||
"min": "Min",
|
||||
"nan": "NaN",
|
||||
"normalizeExposure": "Otomatik pozlama",
|
||||
"openInHdrViewer": "HDR Görüntüleyicide Aç",
|
||||
"resolution": "Çözünürlük",
|
||||
"sourceGamut": "Kaynak renk aralığı",
|
||||
"stdDev": "Std sapma",
|
||||
"title": "HDR Görüntüleyici"
|
||||
},
|
||||
"help": {
|
||||
"helpCenterMenu": "Yardım Merkezi Menüsü",
|
||||
"recentReleases": "Son sürümler"
|
||||
@@ -3006,10 +2957,6 @@
|
||||
"uploadError": "Ressam görseli yüklenemedi: {status} - {statusText}",
|
||||
"width": "Genişlik"
|
||||
},
|
||||
"palette": {
|
||||
"addColor": "Renk ekle",
|
||||
"swatchTitle": "Düzenlemek için tıkla · Sürükleyerek sırala · Kaldırmak için sağ tıkla"
|
||||
},
|
||||
"progressToast": {
|
||||
"allDownloadsCompleted": "Tüm indirmeler tamamlandı",
|
||||
"downloadingModel": "Model indiriliyor...",
|
||||
@@ -3755,27 +3702,6 @@
|
||||
"customLoRAsLabel": "Kendi LoRA'larınızı içe aktarın",
|
||||
"description": "Sizin için en iyi planı seçin",
|
||||
"descriptionWorkspace": "Çalışma alanınız için en iyi planı seçin",
|
||||
"downgrade": {
|
||||
"body": "Bu çalışma alanındaki diğer tüm üyeler hemen kaldırılacaktır.",
|
||||
"confirm": "Planı değiştir",
|
||||
"confirmationPhrase": "Anladım",
|
||||
"confirmationPrompt": "Onaylamak için \"{phrase}\" yazın.",
|
||||
"failed": "Plan değiştirilemedi",
|
||||
"failedAfterMemberRemoval": "Ekip üyeleri kaldırıldı, ancak plan değişikliği tamamlanamadı — lütfen tekrar deneyin veya destek ile iletişime geçin",
|
||||
"memberRemovalFailed": "{email} ekipten kaldırılamadı — bazı üyeler zaten kaldırılmış olabilir ve planınız değiştirilmedi",
|
||||
"notAllowed": "Bu plan değişikliği mevcut değil",
|
||||
"paymentMethodRequired": "Plan değiştirmek için bir ödeme yöntemi gereklidir",
|
||||
"paymentPageBlocked": "Ödeme sayfası açılamadı — lütfen tekrar deneyin",
|
||||
"title": "{plan} planına geçilsin mi?"
|
||||
},
|
||||
"enterprise": {
|
||||
"cta": "Daha fazla bilgi",
|
||||
"flexibility": "Daha fazla esneklik veya özel özellikler mi arıyorsunuz?",
|
||||
"name": "Kurumsal",
|
||||
"needMoreMembers": "Daha fazla üyeye mi ihtiyacınız var?",
|
||||
"reachOut": "Bizimle iletişime geçin ve bir görüşme planlayalım."
|
||||
},
|
||||
"everythingInPlus": "{plan} planındaki her şey ve ayrıca:",
|
||||
"expiresDate": "{date} tarihinde sona erer",
|
||||
"freeTier": {
|
||||
"description": "Ücretsiz planınız, Comfy Cloud'u denemek için her ay {credits} kredi içerir.",
|
||||
@@ -3822,7 +3748,6 @@
|
||||
"messageSupport": "Destek ekibine mesaj gönder",
|
||||
"monthly": "Aylık",
|
||||
"monthlyBonusDescription": "Aylık kredi bonusu",
|
||||
"monthlyCredits": "aylık kredi",
|
||||
"monthlyCreditsInfo": "Bu krediler her ay yenilenir ve devretmez",
|
||||
"monthlyCreditsLabel": "Aylık krediler",
|
||||
"monthlyCreditsPerMemberLabel": "Aylık kredi / üye",
|
||||
@@ -3835,13 +3760,7 @@
|
||||
"partnerNodesCredits": "Partner Düğümleri kredileri",
|
||||
"partnerNodesDescription": "Ticari/özel modelleri çalıştırmak için",
|
||||
"perMonth": "USD / ay",
|
||||
"personalHeader": "Bireysel planlar yalnızca kişisel kullanım içindir. {action}",
|
||||
"personalHeaderAction": "Ekip arkadaşları eklemek için ekip planına abone olun.",
|
||||
"personalWorkspace": "Kişisel Çalışma Alanı",
|
||||
"planScope": {
|
||||
"personal": "Bireysel Kullanım İçin",
|
||||
"team": "Ekipler İçin"
|
||||
},
|
||||
"plansAndPricing": "Planlar ve fiyatlandırma",
|
||||
"plansForWorkspace": "{workspace} için planlar",
|
||||
"prepaidCreditsInfo": "Ayrıca satın alınan ve son kullanma tarihi olmayan krediler",
|
||||
@@ -3852,10 +3771,8 @@
|
||||
"confirm": "Onayla",
|
||||
"confirmPayment": "Ödemenizi onaylayın",
|
||||
"confirmPlanChange": "Plan değişikliğini onaylayın",
|
||||
"creditsRefillTo": "Krediler yenilenir",
|
||||
"eachMonthCreditsRefill": "Her ay krediler yenilenir",
|
||||
"ends": "{date} tarihinde bitiyor",
|
||||
"everyMonthStarting": "Her ay {date} tarihinde başlar",
|
||||
"hideFeatures": "Özellikleri gizle",
|
||||
"nextPaymentDue": "Sonraki ödeme {date} tarihinde. İstediğiniz zaman iptal edebilirsiniz.",
|
||||
"perMember": "/ üye",
|
||||
@@ -3865,18 +3782,10 @@
|
||||
"showMoreFeatures": "Daha fazla özelliği göster",
|
||||
"starting": "{date} tarihinde başlıyor",
|
||||
"startingToday": "Bugünden itibaren başlıyor",
|
||||
"subscribeToPlan": "{plan} planına abone ol",
|
||||
"switchToPlan": "{plan} planına geç",
|
||||
"terms": "Şartlar",
|
||||
"termsAgreement": "Devam ederek Comfy Org'un {terms} ve {privacy} politikasını kabul etmiş olursunuz.",
|
||||
"totalDueToday": "Bugün ödenecek toplam tutar",
|
||||
"youllBeCharged": "Şu kadar ücretlendirileceksiniz"
|
||||
"totalDueToday": "Bugün ödenecek toplam tutar"
|
||||
},
|
||||
"pricingBlurb": "*Bu şablona göre, {seeDetails}. {questions} veya {enterpriseDiscussions} için bizimle iletişime geçin. Daha fazla fiyatlandırma detayı için {clickHere}.",
|
||||
"pricingBlurbClickHere": "buraya tıklayın",
|
||||
"pricingBlurbEnterprise": "kurumsal görüşmeler",
|
||||
"pricingBlurbQuestions": "sorular",
|
||||
"pricingBlurbSeeDetails": "detayları gör",
|
||||
"refreshCredits": "Kredileri yenile",
|
||||
"renewsDate": "{date} tarihinde yenilenir",
|
||||
"required": {
|
||||
@@ -3890,8 +3799,6 @@
|
||||
"resubscribe": "Yeniden abone ol",
|
||||
"resubscribeSuccess": "Abonelik başarıyla yeniden etkinleştirildi",
|
||||
"resubscribeTo": "{plan} planına yeniden abone ol",
|
||||
"saveYearly": "%20 tasarruf edin",
|
||||
"saveYearlyUpTo": "%20'ye kadar tasarruf edin",
|
||||
"soloUseOnly": "Sadece bireysel kullanım",
|
||||
"subscribeForMore": "Yükselt",
|
||||
"subscribeNow": "Hemen Abone Ol",
|
||||
@@ -3900,34 +3807,10 @@
|
||||
"subscribeToRun": "Abone Ol",
|
||||
"subscribeToRunFull": "Çalıştırmaya Abone Ol",
|
||||
"subscriptionRequiredMessage": "Üyelerin Bulut'ta iş akışlarını çalıştırabilmesi için abonelik gereklidir",
|
||||
"success": {
|
||||
"allSet": "Her şey hazır",
|
||||
"planUpdated": "Planınız başarıyla güncellendi.",
|
||||
"receiptEmailed": "Makbuz e-posta ile gönderildi."
|
||||
},
|
||||
"teamHeader": "Birlikte çalışmak isteyen ekipler için. Daha fazla üyeye mi ihtiyacınız var? {learnMore} kurumsal hakkında.",
|
||||
"teamHeaderLearnMore": "Daha fazla bilgi",
|
||||
"teamPlan": {
|
||||
"changePlan": "Planı değiştir",
|
||||
"checkoutComingSoon": "Ekip planı ödeme sayfası yakında geliyor.",
|
||||
"comingSoonLabel": "Yakında:",
|
||||
"cta": "Ekip Yıllık Aboneliğe Geç",
|
||||
"ctaMonthly": "Ekip Aylık Aboneliğe Geç",
|
||||
"currentPlan": "Mevcut plan",
|
||||
"detailsTitle": "Detaylar",
|
||||
"name": "Ekip Planı",
|
||||
"perkConcurrentRuns": "Üyeler iş akışlarını aynı anda çalıştırabilir",
|
||||
"perkInviteMembers": "Ekip üyelerini davet edin",
|
||||
"perkProjectAssets": "Proje ve varlık yönetimi",
|
||||
"perkRolePermissions": "Rol tabanlı izinler",
|
||||
"perkSharedPool": "Tüm üyeler için ortak kredi havuzu",
|
||||
"tagline": "Kendi aylık kredi aboneliğinizi seçin. Daha fazla krediyle daha büyük indirim elde edin."
|
||||
},
|
||||
"teamWorkspace": "Takım Çalışma Alanı",
|
||||
"tierNameYearly": "{name} Yıllık",
|
||||
"tiers": {
|
||||
"creator": {
|
||||
"feature1": "Kendi modellerinizi içe aktarın",
|
||||
"name": "Yaratıcı"
|
||||
},
|
||||
"founder": {
|
||||
@@ -3937,12 +3820,9 @@
|
||||
"name": "Ücretsiz"
|
||||
},
|
||||
"pro": {
|
||||
"feature1": "Daha uzun iş akışı çalışma süresi (1 saate kadar)",
|
||||
"name": "Pro"
|
||||
},
|
||||
"standard": {
|
||||
"feature1": "30 dakika maksimum iş akışı çalışma süresi",
|
||||
"feature2": "İstediğiniz zaman daha fazla kredi ekleyin",
|
||||
"name": "Standart"
|
||||
}
|
||||
},
|
||||
@@ -3955,7 +3835,6 @@
|
||||
"upgradeToAddCredits": "Kredi eklemek için yükselt",
|
||||
"usdPerMonth": "USD / ay",
|
||||
"usdPerMonthPerMember": "USD / ay / üye",
|
||||
"videoEstimate": "Yaklaşık {count} adet 5 sn'lik video üretir*",
|
||||
"videoEstimateExplanation": "Bu tahminler, varsayılan ayarlarla (5 saniye, 640x640, 16fps, 4 adım örnekleme) Wan 2.2 Görselden Videoya şablonuna dayanmaktadır.",
|
||||
"videoEstimateHelp": "Bu şablon hakkında daha fazla bilgi",
|
||||
"videoEstimateLabel": "Wan 2.2 Görselden Videoya şablonu ile yaklaşık 5 sn'lik video sayısı",
|
||||
@@ -3965,11 +3844,10 @@
|
||||
"viewMoreDetails": "Daha fazla detay görüntüle",
|
||||
"viewMoreDetailsPlans": "Planlar ve fiyatlandırma hakkında daha fazla detay",
|
||||
"viewUsageHistory": "Kullanım geçmişini görüntüle",
|
||||
"whatsIncluded": "Dahil olanlar:",
|
||||
"workspaceNotSubscribed": "Bu çalışma alanı bir aboneliğe sahip değil",
|
||||
"yearly": "Yıllık",
|
||||
"yearlyCreditsLabel": "Toplam yıllık krediler",
|
||||
"yearlyDiscount": "%20 İNDİRİM",
|
||||
"saveYearly": "%20 tasarruf",
|
||||
"yourPlanIncludes": "Planınız şunları içerir:"
|
||||
},
|
||||
"tabMenu": {
|
||||
|
||||
@@ -92,7 +92,6 @@
|
||||
"errorUserTokenAccessDenied": "您的 API 金鑰無法存取此資源,請檢查權限。",
|
||||
"errorUserTokenInvalid": "儲存的 API 金鑰無效或已過期,請在設定中更新。",
|
||||
"failedToCreateNode": "無法建立節點。請重試或查看主控台以取得詳細資訊。",
|
||||
"failedToSetModelValue": "已新增節點,但無法自動設定其模型。請查看主控台以獲取詳細資訊。",
|
||||
"fileFormats": "檔案格式",
|
||||
"fileName": "檔案名稱",
|
||||
"fileSize": "檔案大小",
|
||||
@@ -242,8 +241,7 @@
|
||||
"auth/user-not-found": "找不到使用此電子郵件的帳戶。您要建立新帳戶嗎?",
|
||||
"auth/weak-password": "密碼強度不足。請使用至少 6 個字元的更強密碼。",
|
||||
"auth/wrong-password": "您輸入的密碼不正確。請再試一次。",
|
||||
"generic": "登入時發生錯誤,請再試一次。",
|
||||
"signupBlocked": "目前無法建立您的帳號。請稍後再試。如果問題持續發生,請聯絡 support@comfy.org。"
|
||||
"generic": "登入時發生錯誤,請再試一次。"
|
||||
},
|
||||
"login": {
|
||||
"andText": "以及",
|
||||
@@ -348,17 +346,6 @@
|
||||
"x": "X",
|
||||
"y": "Y"
|
||||
},
|
||||
"boundingBoxes": {
|
||||
"clearAll": "全部清除",
|
||||
"clickRegionToEdit": "點擊區域以編輯。",
|
||||
"colors": "色彩調色盤",
|
||||
"descLabel": "描述",
|
||||
"descPlaceholder": "此區域的描述",
|
||||
"textLabel": "文字",
|
||||
"textPlaceholder": "要呈現的文字(原文)",
|
||||
"typeObj": "物件",
|
||||
"typeText": "文字"
|
||||
},
|
||||
"breadcrumbsMenu": {
|
||||
"app": "應用程式",
|
||||
"blueprint": "藍圖",
|
||||
@@ -768,13 +755,6 @@
|
||||
"creditsAvailable": "可用點數",
|
||||
"details": "詳細資料",
|
||||
"eventType": "事件類型",
|
||||
"eventTypes": {
|
||||
"accountCreated": "帳號已建立",
|
||||
"apiNodeUsage": "合作夥伴節點使用量",
|
||||
"apiUsage": "API 使用量",
|
||||
"creditAdded": "已新增點數",
|
||||
"gpuUsage": "GPU 使用量"
|
||||
},
|
||||
"faqs": "常見問題",
|
||||
"invoiceHistory": "發票紀錄",
|
||||
"lastUpdated": "最後更新",
|
||||
@@ -1850,35 +1830,6 @@
|
||||
"zoomOptions": "縮放選項",
|
||||
"zoomOut": "縮小"
|
||||
},
|
||||
"hdrViewer": {
|
||||
"channel": "通道",
|
||||
"channels": {
|
||||
"a": "Alpha",
|
||||
"b": "B",
|
||||
"g": "G",
|
||||
"luminance": "亮度",
|
||||
"r": "R",
|
||||
"rgb": "RGB"
|
||||
},
|
||||
"clipWarnings": "裁切警告",
|
||||
"dither": "抖動",
|
||||
"exposure": "曝光",
|
||||
"failedToLoad": "無法載入 HDR 圖像",
|
||||
"fitView": "適合畫面",
|
||||
"hdrImage": "HDR 圖像",
|
||||
"histogram": "直方圖",
|
||||
"inf": "無限大",
|
||||
"max": "最大值",
|
||||
"mean": "平均值",
|
||||
"min": "最小值",
|
||||
"nan": "NaN",
|
||||
"normalizeExposure": "自動曝光",
|
||||
"openInHdrViewer": "在 HDR 檢視器中開啟",
|
||||
"resolution": "解析度",
|
||||
"sourceGamut": "來源色域",
|
||||
"stdDev": "標準差",
|
||||
"title": "HDR 檢視器"
|
||||
},
|
||||
"help": {
|
||||
"helpCenterMenu": "說明中心選單",
|
||||
"recentReleases": "近期版本"
|
||||
@@ -3006,10 +2957,6 @@
|
||||
"uploadError": "上傳繪圖圖像失敗:{status} - {statusText}",
|
||||
"width": "寬度"
|
||||
},
|
||||
"palette": {
|
||||
"addColor": "新增顏色",
|
||||
"swatchTitle": "點擊編輯 · 拖曳排序 · 右鍵移除"
|
||||
},
|
||||
"progressToast": {
|
||||
"allDownloadsCompleted": "所有下載已完成",
|
||||
"downloadingModel": "正在下載模型...",
|
||||
@@ -3755,27 +3702,6 @@
|
||||
"customLoRAsLabel": "匯入您自己的 LoRAs",
|
||||
"description": "選擇最適合您的方案",
|
||||
"descriptionWorkspace": "為您的工作區選擇最佳方案",
|
||||
"downgrade": {
|
||||
"body": "此工作區的所有其他成員將會立即被移除。",
|
||||
"confirm": "更改方案",
|
||||
"confirmationPhrase": "我已了解",
|
||||
"confirmationPrompt": "請輸入「{phrase}」以確認。",
|
||||
"failed": "更改方案失敗",
|
||||
"failedAfterMemberRemoval": "團隊成員已移除,但方案更改未完成 — 請再試一次或聯絡客服",
|
||||
"memberRemovalFailed": "無法將 {email} 從團隊移除 — 有些成員可能已被移除,您的方案未被更改",
|
||||
"notAllowed": "無法進行此方案更改",
|
||||
"paymentMethodRequired": "更改方案需要新增付款方式",
|
||||
"paymentPageBlocked": "無法開啟付款頁面 — 請再試一次",
|
||||
"title": "更改為 {plan} 方案?"
|
||||
},
|
||||
"enterprise": {
|
||||
"cta": "了解更多",
|
||||
"flexibility": "需要更多彈性或自訂功能?",
|
||||
"name": "企業方案",
|
||||
"needMoreMembers": "需要更多成員嗎?",
|
||||
"reachOut": "歡迎聯絡我們,安排諮詢。"
|
||||
},
|
||||
"everythingInPlus": "包含 {plan} 的所有內容,並加上:",
|
||||
"expiresDate": "將於 {date} 到期",
|
||||
"freeTier": {
|
||||
"description": "您的免費方案每月包含 {credits} 點數,可體驗 Comfy Cloud。",
|
||||
@@ -3822,7 +3748,6 @@
|
||||
"messageSupport": "聯繫客服",
|
||||
"monthly": "每月",
|
||||
"monthlyBonusDescription": "每月點數獎勵",
|
||||
"monthlyCredits": "每月額度",
|
||||
"monthlyCreditsInfo": "這些點數每月重置,不可累積",
|
||||
"monthlyCreditsLabel": "每月點數",
|
||||
"monthlyCreditsPerMemberLabel": "每月點數/成員",
|
||||
@@ -3835,13 +3760,7 @@
|
||||
"partnerNodesCredits": "合作節點點數",
|
||||
"partnerNodesDescription": "用於執行商業/專有模型",
|
||||
"perMonth": "美元 / 月",
|
||||
"personalHeader": "個人方案僅供個人使用。{action}",
|
||||
"personalHeaderAction": "如需新增團隊成員,請訂閱團隊方案。",
|
||||
"personalWorkspace": "個人工作區",
|
||||
"planScope": {
|
||||
"personal": "個人使用",
|
||||
"team": "團隊使用"
|
||||
},
|
||||
"plansAndPricing": "方案與價格",
|
||||
"plansForWorkspace": "{workspace} 的方案",
|
||||
"prepaidCreditsInfo": "單獨購買且不會過期的點數",
|
||||
@@ -3852,10 +3771,8 @@
|
||||
"confirm": "確認",
|
||||
"confirmPayment": "確認您的付款",
|
||||
"confirmPlanChange": "確認您的方案變更",
|
||||
"creditsRefillTo": "額度補充至",
|
||||
"eachMonthCreditsRefill": "每月點數補充至",
|
||||
"ends": "結束於 {date}",
|
||||
"everyMonthStarting": "每月自 {date} 起",
|
||||
"hideFeatures": "隱藏功能",
|
||||
"nextPaymentDue": "下次付款日為 {date}。可隨時取消。",
|
||||
"perMember": "/成員",
|
||||
@@ -3865,18 +3782,10 @@
|
||||
"showMoreFeatures": "顯示更多功能",
|
||||
"starting": "自 {date} 開始",
|
||||
"startingToday": "今日開始",
|
||||
"subscribeToPlan": "訂閱 {plan}",
|
||||
"switchToPlan": "切換至 {plan}",
|
||||
"terms": "服務條款",
|
||||
"termsAgreement": "繼續即表示您同意 Comfy Org 的{terms}與{privacy}。",
|
||||
"totalDueToday": "今日應付總額",
|
||||
"youllBeCharged": "您將被收取"
|
||||
"totalDueToday": "今日應付總額"
|
||||
},
|
||||
"pricingBlurb": "*根據此範本,{seeDetails}。如有{questions}或{enterpriseDiscussions},歡迎聯絡我們。更多價格資訊,請{clickHere}。",
|
||||
"pricingBlurbClickHere": "點此查看",
|
||||
"pricingBlurbEnterprise": "企業洽談",
|
||||
"pricingBlurbQuestions": "問題諮詢",
|
||||
"pricingBlurbSeeDetails": "查看詳情",
|
||||
"refreshCredits": "刷新點數",
|
||||
"renewsDate": "將於 {date} 續訂",
|
||||
"required": {
|
||||
@@ -3890,8 +3799,6 @@
|
||||
"resubscribe": "重新訂閱",
|
||||
"resubscribeSuccess": "訂閱已重新啟用",
|
||||
"resubscribeTo": "重新訂閱 {plan}",
|
||||
"saveYearly": "年繳省 20%",
|
||||
"saveYearlyUpTo": "最高可省 20%",
|
||||
"soloUseOnly": "僅限個人使用",
|
||||
"subscribeForMore": "升級",
|
||||
"subscribeNow": "立即訂閱",
|
||||
@@ -3900,34 +3807,10 @@
|
||||
"subscribeToRun": "訂閱",
|
||||
"subscribeToRunFull": "訂閱運行方案",
|
||||
"subscriptionRequiredMessage": "會員需訂閱才能在雲端執行工作流程",
|
||||
"success": {
|
||||
"allSet": "設定完成",
|
||||
"planUpdated": "您的方案已成功更新。",
|
||||
"receiptEmailed": "收據已寄送至您的電子郵件。"
|
||||
},
|
||||
"teamHeader": "適合需要協作的團隊。需要更多成員嗎?{learnMore} 企業方案。",
|
||||
"teamHeaderLearnMore": "了解更多",
|
||||
"teamPlan": {
|
||||
"changePlan": "更改方案",
|
||||
"checkoutComingSoon": "團隊方案結帳功能即將推出。",
|
||||
"comingSoonLabel": "即將推出:",
|
||||
"cta": "訂閱團隊年繳方案",
|
||||
"ctaMonthly": "訂閱團隊月繳方案",
|
||||
"currentPlan": "目前方案",
|
||||
"detailsTitle": "詳細資訊",
|
||||
"name": "團隊方案",
|
||||
"perkConcurrentRuns": "成員可同時運行多個工作流程",
|
||||
"perkInviteMembers": "邀請團隊成員",
|
||||
"perkProjectAssets": "專案與資產管理",
|
||||
"perkRolePermissions": "依角色分配權限",
|
||||
"perkSharedPool": "全體成員共享額度池",
|
||||
"tagline": "自選每月額度訂閱。額度越高,折扣越多。"
|
||||
},
|
||||
"teamWorkspace": "團隊工作區",
|
||||
"tierNameYearly": "{name} 年度方案",
|
||||
"tiers": {
|
||||
"creator": {
|
||||
"feature1": "可匯入自有模型",
|
||||
"name": "創作者版"
|
||||
},
|
||||
"founder": {
|
||||
@@ -3937,12 +3820,9 @@
|
||||
"name": "免費"
|
||||
},
|
||||
"pro": {
|
||||
"feature1": "更長的工作流程運行時間(最長 1 小時)",
|
||||
"name": "專業版"
|
||||
},
|
||||
"standard": {
|
||||
"feature1": "工作流程最長 30 分鐘",
|
||||
"feature2": "隨時可加購額度",
|
||||
"name": "標準版"
|
||||
}
|
||||
},
|
||||
@@ -3955,7 +3835,6 @@
|
||||
"upgradeToAddCredits": "升級以增加點數",
|
||||
"usdPerMonth": "美元/月",
|
||||
"usdPerMonthPerMember": "美元/月/成員",
|
||||
"videoEstimate": "可產生約 {count} 個 5 秒影片*",
|
||||
"videoEstimateExplanation": "此估算以 Wan 2.2 圖轉影範本的預設設定(5 秒、640x640、16fps、4 步採樣)為基礎。",
|
||||
"videoEstimateHelp": "查看更多此範本細節",
|
||||
"videoEstimateLabel": "以 Wan 2.2 圖轉影範本約可產生的 5 秒影片數量",
|
||||
@@ -3965,11 +3844,10 @@
|
||||
"viewMoreDetails": "查看更多詳情",
|
||||
"viewMoreDetailsPlans": "查看更多方案與價格細節",
|
||||
"viewUsageHistory": "檢視使用記錄",
|
||||
"whatsIncluded": "包含內容:",
|
||||
"workspaceNotSubscribed": "此工作區尚未訂閱",
|
||||
"yearly": "每年",
|
||||
"yearlyCreditsLabel": "年度總點數",
|
||||
"yearlyDiscount": "八折優惠",
|
||||
"saveYearly": "節省 20%",
|
||||
"yourPlanIncludes": "您的方案包含:"
|
||||
},
|
||||
"tabMenu": {
|
||||
|
||||
@@ -92,7 +92,6 @@
|
||||
"errorUserTokenAccessDenied": "您的 API 密钥无权访问此资源。请检查密钥权限。",
|
||||
"errorUserTokenInvalid": "您保存的 API 密钥无效或已过期。请在设置中更新密钥。",
|
||||
"failedToCreateNode": "创建节点失败。请重试或查看控制台获取详细信息。",
|
||||
"failedToSetModelValue": "节点已添加,但其模型未能自动设置。详情请查看控制台。",
|
||||
"fileFormats": "文件格式",
|
||||
"fileName": "文件名",
|
||||
"fileSize": "文件大小",
|
||||
@@ -242,8 +241,7 @@
|
||||
"auth/user-not-found": "未找到使用此电子邮件的账户。您想要创建一个新账户吗?",
|
||||
"auth/weak-password": "密码强度太弱。请使用至少6个字符的更强密码。",
|
||||
"auth/wrong-password": "您输入的密码不正确,请重试。",
|
||||
"generic": "登录时出现问题,请重试。",
|
||||
"signupBlocked": "我们目前无法创建您的账户。请稍后再试。如果问题持续,请发送邮件至 support@comfy.org。"
|
||||
"generic": "登录时出现问题,请重试。"
|
||||
},
|
||||
"login": {
|
||||
"andText": "和",
|
||||
@@ -348,17 +346,6 @@
|
||||
"x": "X",
|
||||
"y": "Y"
|
||||
},
|
||||
"boundingBoxes": {
|
||||
"clearAll": "全部清除",
|
||||
"clickRegionToEdit": "点击区域进行编辑。",
|
||||
"colors": "调色板",
|
||||
"descLabel": "描述",
|
||||
"descPlaceholder": "该区域的描述",
|
||||
"textLabel": "文本",
|
||||
"textPlaceholder": "要渲染的文本(原文)",
|
||||
"typeObj": "obj",
|
||||
"typeText": "text"
|
||||
},
|
||||
"breadcrumbsMenu": {
|
||||
"app": "应用",
|
||||
"blueprint": "蓝图",
|
||||
@@ -768,13 +755,6 @@
|
||||
"creditsAvailable": "积分可用",
|
||||
"details": "详情",
|
||||
"eventType": "事件类型",
|
||||
"eventTypes": {
|
||||
"accountCreated": "账户已创建",
|
||||
"apiNodeUsage": "合作节点使用",
|
||||
"apiUsage": "API 使用",
|
||||
"creditAdded": "已添加积分",
|
||||
"gpuUsage": "GPU 使用"
|
||||
},
|
||||
"faqs": "常见问题",
|
||||
"invoiceHistory": "发票历史",
|
||||
"lastUpdated": "最近更新",
|
||||
@@ -1850,35 +1830,6 @@
|
||||
"zoomOptions": "缩放选项",
|
||||
"zoomOut": "缩小"
|
||||
},
|
||||
"hdrViewer": {
|
||||
"channel": "通道",
|
||||
"channels": {
|
||||
"a": "Alpha",
|
||||
"b": "B",
|
||||
"g": "G",
|
||||
"luminance": "亮度",
|
||||
"r": "R",
|
||||
"rgb": "RGB"
|
||||
},
|
||||
"clipWarnings": "裁剪警告",
|
||||
"dither": "抖动",
|
||||
"exposure": "曝光",
|
||||
"failedToLoad": "HDR 图像加载失败",
|
||||
"fitView": "适应",
|
||||
"hdrImage": "HDR 图像",
|
||||
"histogram": "直方图",
|
||||
"inf": "无穷大",
|
||||
"max": "最大值",
|
||||
"mean": "均值",
|
||||
"min": "最小值",
|
||||
"nan": "NaN",
|
||||
"normalizeExposure": "自动曝光",
|
||||
"openInHdrViewer": "在 HDR 查看器中打开",
|
||||
"resolution": "分辨率",
|
||||
"sourceGamut": "源色域",
|
||||
"stdDev": "标准差",
|
||||
"title": "HDR 查看器"
|
||||
},
|
||||
"help": {
|
||||
"helpCenterMenu": "帮助中心菜单",
|
||||
"recentReleases": "最近发布"
|
||||
@@ -3006,10 +2957,6 @@
|
||||
"uploadError": "上传绘图图像失败:{status} - {statusText}",
|
||||
"width": "宽度"
|
||||
},
|
||||
"palette": {
|
||||
"addColor": "添加颜色",
|
||||
"swatchTitle": "点击编辑 · 拖动排序 · 右键移除"
|
||||
},
|
||||
"progressToast": {
|
||||
"allDownloadsCompleted": "所有下载已完成",
|
||||
"downloadingModel": "正在下载模型...",
|
||||
@@ -3767,27 +3714,6 @@
|
||||
"customLoRAsLabel": "导入您的 Lora",
|
||||
"description": "选择最适合您的订阅计划",
|
||||
"descriptionWorkspace": "为您的工作区选择最佳方案",
|
||||
"downgrade": {
|
||||
"body": "该工作区的所有其他成员将被立即移除。",
|
||||
"confirm": "更改方案",
|
||||
"confirmationPhrase": "我已了解",
|
||||
"confirmationPrompt": "请输入“{phrase}”以确认。",
|
||||
"failed": "更改方案失败",
|
||||
"failedAfterMemberRemoval": "团队成员已被移除,但方案更改未完成 — 请重试或联系客服",
|
||||
"memberRemovalFailed": "无法将 {email} 从团队移除 — 部分成员可能已被移除,您的方案未更改",
|
||||
"notAllowed": "无法进行此方案更改",
|
||||
"paymentMethodRequired": "更改方案需要添加支付方式",
|
||||
"paymentPageBlocked": "无法打开支付页面 — 请重试",
|
||||
"title": "切换到 {plan} 方案?"
|
||||
},
|
||||
"enterprise": {
|
||||
"cta": "了解更多",
|
||||
"flexibility": "需要更多灵活性或定制功能?",
|
||||
"name": "企业版",
|
||||
"needMoreMembers": "需要更多成员?",
|
||||
"reachOut": "请联系我们,安排沟通。"
|
||||
},
|
||||
"everythingInPlus": "包含 {plan} 的所有内容,并额外提供:",
|
||||
"expiresDate": "于 {date} 过期",
|
||||
"freeTier": {
|
||||
"description": "您的免费套餐每月包含 {credits} 积分,可体验 Comfy Cloud。",
|
||||
@@ -3834,7 +3760,6 @@
|
||||
"messageSupport": "消息支持",
|
||||
"monthly": "月度",
|
||||
"monthlyBonusDescription": "每月积分奖励",
|
||||
"monthlyCredits": "每月积分",
|
||||
"monthlyCreditsInfo": "积分每月刷新,不会保留",
|
||||
"monthlyCreditsLabel": "每月积分",
|
||||
"monthlyCreditsPerMemberLabel": "每成员每月积分",
|
||||
@@ -3847,13 +3772,7 @@
|
||||
"partnerNodesCredits": "合作伙伴节点积分",
|
||||
"partnerNodesDescription": "用于运行商业/专有模型",
|
||||
"perMonth": "美元 / 月",
|
||||
"personalHeader": "个人方案仅限个人使用。{action}",
|
||||
"personalHeaderAction": "如需添加团队成员,请订阅团队方案。",
|
||||
"personalWorkspace": "个人工作区",
|
||||
"planScope": {
|
||||
"personal": "个人使用",
|
||||
"team": "团队使用"
|
||||
},
|
||||
"plansAndPricing": "订阅和定价",
|
||||
"plansForWorkspace": "{workspace} 的套餐",
|
||||
"prepaidCreditsInfo": "单独购买且不会过期的积分",
|
||||
@@ -3864,10 +3783,8 @@
|
||||
"confirm": "确认",
|
||||
"confirmPayment": "确认付款",
|
||||
"confirmPlanChange": "确认更改方案",
|
||||
"creditsRefillTo": "积分补充至",
|
||||
"eachMonthCreditsRefill": "每月积分补充至",
|
||||
"ends": "{date} 结束",
|
||||
"everyMonthStarting": "每月从 {date} 开始",
|
||||
"hideFeatures": "隐藏功能",
|
||||
"nextPaymentDue": "下次付款截止日期 {date}。可随时取消。",
|
||||
"perMember": "/ 每成员",
|
||||
@@ -3877,18 +3794,10 @@
|
||||
"showMoreFeatures": "显示更多功能",
|
||||
"starting": "{date} 开始",
|
||||
"startingToday": "今日开始",
|
||||
"subscribeToPlan": "订阅 {plan}",
|
||||
"switchToPlan": "切换到 {plan}",
|
||||
"terms": "条款",
|
||||
"termsAgreement": "继续操作即表示您同意 Comfy Org 的{terms}和{privacy}。",
|
||||
"totalDueToday": "今日应付总额",
|
||||
"youllBeCharged": "您将被收取"
|
||||
"totalDueToday": "今日应付总额"
|
||||
},
|
||||
"pricingBlurb": "*基于此模板,{seeDetails}。如有{questions}或{enterpriseDiscussions},请联系我们。更多价格详情,{clickHere}。",
|
||||
"pricingBlurbClickHere": "点击这里",
|
||||
"pricingBlurbEnterprise": "企业合作",
|
||||
"pricingBlurbQuestions": "问题咨询",
|
||||
"pricingBlurbSeeDetails": "查看详情",
|
||||
"refreshCredits": "刷新额度",
|
||||
"renewsDate": "将于 {date} 续订",
|
||||
"required": {
|
||||
@@ -3902,8 +3811,6 @@
|
||||
"resubscribe": "重新订阅",
|
||||
"resubscribeSuccess": "订阅已成功重新激活",
|
||||
"resubscribeTo": "重新订阅 {plan}",
|
||||
"saveYearly": "年付节省 20%",
|
||||
"saveYearlyUpTo": "最高可节省 20%",
|
||||
"soloUseOnly": "仅限个人使用",
|
||||
"subscribeForMore": "升级",
|
||||
"subscribeNow": "立即订阅",
|
||||
@@ -3912,34 +3819,10 @@
|
||||
"subscribeToRun": "订阅",
|
||||
"subscribeToRunFull": "订阅 Run",
|
||||
"subscriptionRequiredMessage": "成员在云端运行工作流需要订阅",
|
||||
"success": {
|
||||
"allSet": "设置完成",
|
||||
"planUpdated": "您的方案已成功更新。",
|
||||
"receiptEmailed": "收据已发送至您的邮箱。"
|
||||
},
|
||||
"teamHeader": "适合希望协作的团队。需要更多成员?{learnMore} 了解企业版。",
|
||||
"teamHeaderLearnMore": "了解更多",
|
||||
"teamPlan": {
|
||||
"changePlan": "更改方案",
|
||||
"checkoutComingSoon": "团队方案结算即将上线。",
|
||||
"comingSoonLabel": "即将上线:",
|
||||
"cta": "订阅团队年付方案",
|
||||
"ctaMonthly": "订阅团队月付方案",
|
||||
"currentPlan": "当前方案",
|
||||
"detailsTitle": "详情",
|
||||
"name": "团队方案",
|
||||
"perkConcurrentRuns": "成员可同时运行多个工作流",
|
||||
"perkInviteMembers": "邀请团队成员",
|
||||
"perkProjectAssets": "项目与资产管理",
|
||||
"perkRolePermissions": "基于角色的权限管理",
|
||||
"perkSharedPool": "所有成员共享积分池",
|
||||
"tagline": "自定义每月积分订阅。订阅更多积分可享更大折扣。"
|
||||
},
|
||||
"teamWorkspace": "团队工作区",
|
||||
"tierNameYearly": "{name} 年度",
|
||||
"tiers": {
|
||||
"creator": {
|
||||
"feature1": "导入您自己的模型",
|
||||
"name": "Creator"
|
||||
},
|
||||
"founder": {
|
||||
@@ -3949,12 +3832,9 @@
|
||||
"name": "免费"
|
||||
},
|
||||
"pro": {
|
||||
"feature1": "更长的工作流运行时间(最长 1 小时)",
|
||||
"name": "Pro"
|
||||
},
|
||||
"standard": {
|
||||
"feature1": "最长 30 分钟工作流运行时间",
|
||||
"feature2": "可随时增加积分",
|
||||
"name": "Standard"
|
||||
}
|
||||
},
|
||||
@@ -3967,7 +3847,6 @@
|
||||
"upgradeToAddCredits": "升级以添加积分",
|
||||
"usdPerMonth": "USD / mo",
|
||||
"usdPerMonthPerMember": "美元 / 月 / 每成员",
|
||||
"videoEstimate": "可生成约 {count} 个 5 秒视频*",
|
||||
"videoEstimateExplanation": "这些预估基于 Wan Fun Control 生成 5 秒视频。",
|
||||
"videoEstimateHelp": "这是什么?",
|
||||
"videoEstimateLabel": "可使用 Wan Fun Control 模板生成 5 秒视频的数量",
|
||||
@@ -3977,11 +3856,10 @@
|
||||
"viewMoreDetails": "查看更多详情",
|
||||
"viewMoreDetailsPlans": "查看有关订阅和定价的更多信息",
|
||||
"viewUsageHistory": "查看使用历史",
|
||||
"whatsIncluded": "包含内容:",
|
||||
"workspaceNotSubscribed": "此工作区未订阅",
|
||||
"yearly": "年度",
|
||||
"yearlyCreditsLabel": "总共年度积分",
|
||||
"yearlyDiscount": "20% 减免",
|
||||
"saveYearly": "立省 20%",
|
||||
"yourPlanIncludes": "您的计划包括:"
|
||||
},
|
||||
"tabMenu": {
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { createI18n } from 'vue-i18n'
|
||||
|
||||
import { render, screen } from '@testing-library/vue'
|
||||
|
||||
import enMessages from '@/locales/en/main.json' with { type: 'json' }
|
||||
|
||||
import FreeTierDialogContent from './FreeTierDialogContent.vue'
|
||||
|
||||
const mockRenewalDate = vi.hoisted(() => ({ value: null as string | null }))
|
||||
|
||||
vi.mock('@/composables/billing/useBillingContext', () => ({
|
||||
useBillingContext: vi.fn(() => ({
|
||||
renewalDate: mockRenewalDate
|
||||
}))
|
||||
}))
|
||||
|
||||
function renderComponent() {
|
||||
const i18n = createI18n({
|
||||
legacy: false,
|
||||
locale: 'en',
|
||||
messages: { en: enMessages }
|
||||
})
|
||||
|
||||
return render(FreeTierDialogContent, {
|
||||
global: {
|
||||
plugins: [i18n]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
describe('FreeTierDialogContent', () => {
|
||||
it('renders the next refresh line formatted from the facade renewalDate', () => {
|
||||
mockRenewalDate.value = '2026-07-15T10:00:00Z'
|
||||
renderComponent()
|
||||
expect(
|
||||
screen.getByText('Your credits refresh on Jul 15, 2026.')
|
||||
).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('hides the next refresh line when renewalDate is null', () => {
|
||||
mockRenewalDate.value = null
|
||||
renderComponent()
|
||||
expect(screen.queryByText(/credits refresh on/)).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
@@ -102,9 +102,9 @@
|
||||
import { computed } from 'vue'
|
||||
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import { useBillingContext } from '@/composables/billing/useBillingContext'
|
||||
import type { SubscriptionDialogReason } from '@/platform/cloud/subscription/composables/useSubscriptionDialog'
|
||||
import SubscriptionBenefits from '@/platform/cloud/subscription/components/SubscriptionBenefits.vue'
|
||||
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
|
||||
import { getTierCredits } from '@/platform/cloud/subscription/constants/tierPricing'
|
||||
|
||||
defineProps<{
|
||||
@@ -116,7 +116,17 @@ defineEmits<{
|
||||
upgrade: []
|
||||
}>()
|
||||
|
||||
const { formattedRenewalDate } = useSubscription()
|
||||
const { renewalDate } = useBillingContext()
|
||||
|
||||
const formattedRenewalDate = computed(() => {
|
||||
if (!renewalDate.value) return ''
|
||||
|
||||
return new Date(renewalDate.value).toLocaleDateString('en-US', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric'
|
||||
})
|
||||
})
|
||||
|
||||
const freeTierCredits = computed(() => getTierCredits('free'))
|
||||
</script>
|
||||
|
||||
@@ -7,6 +7,7 @@ import { createI18n } from 'vue-i18n'
|
||||
|
||||
import PricingTable from '@/platform/cloud/subscription/components/PricingTable.vue'
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import type { SubscriptionTier } from '@/platform/cloud/subscription/constants/tierPricing'
|
||||
import { PENDING_SUBSCRIPTION_CHECKOUT_STORAGE_KEY } from '@/platform/cloud/subscription/utils/subscriptionCheckoutTracker'
|
||||
|
||||
async function flushPromises() {
|
||||
@@ -23,10 +24,8 @@ function createDeferredPromise<T>() {
|
||||
}
|
||||
|
||||
const mockIsActiveSubscription = ref(false)
|
||||
const mockSubscriptionTier = ref<
|
||||
'STANDARD' | 'CREATOR' | 'PRO' | 'FOUNDERS_EDITION' | null
|
||||
>(null)
|
||||
const mockIsYearlySubscription = ref(false)
|
||||
const mockSubscriptionTier = ref<SubscriptionTier | null>(null)
|
||||
const mockSubscriptionDuration = ref<'MONTHLY' | 'ANNUAL'>('MONTHLY')
|
||||
const mockAccessBillingPortal = vi.fn()
|
||||
const mockReportError = vi.fn()
|
||||
const mockTrackBeginCheckout = vi.fn()
|
||||
@@ -65,13 +64,25 @@ Object.defineProperty(globalThis, 'localStorage', {
|
||||
writable: true
|
||||
})
|
||||
|
||||
vi.mock('@/platform/cloud/subscription/composables/useSubscription', () => ({
|
||||
useSubscription: () => ({
|
||||
vi.mock('@/composables/billing/useBillingContext', () => ({
|
||||
useBillingContext: () => ({
|
||||
isActiveSubscription: computed(() => mockIsActiveSubscription.value),
|
||||
isFreeTier: computed(() => false),
|
||||
subscriptionTier: computed(() => mockSubscriptionTier.value),
|
||||
isYearlySubscription: computed(() => mockIsYearlySubscription.value),
|
||||
subscriptionStatus: ref(null)
|
||||
isFreeTier: computed(() => mockSubscriptionTier.value === 'FREE'),
|
||||
tier: computed(() => mockSubscriptionTier.value),
|
||||
subscription: computed(() =>
|
||||
mockSubscriptionTier.value
|
||||
? {
|
||||
isActive: mockIsActiveSubscription.value,
|
||||
tier: mockSubscriptionTier.value,
|
||||
duration: mockSubscriptionDuration.value,
|
||||
planSlug: null,
|
||||
renewalDate: null,
|
||||
endDate: null,
|
||||
isCancelled: false,
|
||||
hasFunds: true
|
||||
}
|
||||
: null
|
||||
)
|
||||
})
|
||||
}))
|
||||
|
||||
@@ -217,7 +228,7 @@ describe('PricingTable', () => {
|
||||
vi.clearAllMocks()
|
||||
mockIsActiveSubscription.value = false
|
||||
mockSubscriptionTier.value = null
|
||||
mockIsYearlySubscription.value = false
|
||||
mockSubscriptionDuration.value = 'MONTHLY'
|
||||
mockUserId.value = 'user-123'
|
||||
mockAccessBillingPortal.mockReset()
|
||||
mockAccessBillingPortal.mockResolvedValue(true)
|
||||
@@ -362,6 +373,7 @@ describe('PricingTable', () => {
|
||||
it('should not call accessBillingPortal when clicking current plan', async () => {
|
||||
mockIsActiveSubscription.value = true
|
||||
mockSubscriptionTier.value = 'CREATOR'
|
||||
mockSubscriptionDuration.value = 'ANNUAL'
|
||||
|
||||
renderComponent()
|
||||
await flushPromises()
|
||||
@@ -370,12 +382,29 @@ describe('PricingTable', () => {
|
||||
.getAllByRole('button')
|
||||
.find((b) => b.textContent?.includes('Current Plan'))
|
||||
|
||||
expect(currentPlanButton).toBeDefined()
|
||||
expect(currentPlanButton).toBeDisabled()
|
||||
await userEvent.click(currentPlanButton!)
|
||||
await flushPromises()
|
||||
|
||||
expect(mockAccessBillingPortal).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('does not highlight a current plan when the facade duration differs from the selected cycle', async () => {
|
||||
mockIsActiveSubscription.value = true
|
||||
mockSubscriptionTier.value = 'CREATOR'
|
||||
mockSubscriptionDuration.value = 'MONTHLY'
|
||||
|
||||
renderComponent()
|
||||
await flushPromises()
|
||||
|
||||
const currentPlanButton = screen
|
||||
.getAllByRole('button')
|
||||
.find((b) => b.textContent?.includes('Current Plan'))
|
||||
|
||||
expect(currentPlanButton).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should initiate checkout instead of billing portal for new subscribers', async () => {
|
||||
mockIsActiveSubscription.value = false
|
||||
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
<span>{{ option.label }}</span>
|
||||
<div
|
||||
v-if="option.value === 'yearly'"
|
||||
class="flex items-center rounded-full bg-primary-background px-1 py-0.5 text-2xs font-bold text-white"
|
||||
class="flex items-center rounded-full bg-primary-background px-2 py-0.5 text-2xs font-bold whitespace-nowrap text-white"
|
||||
>
|
||||
-20%
|
||||
{{ t('subscription.saveYearly') }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -67,15 +67,15 @@
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex flex-row items-baseline gap-2">
|
||||
<span
|
||||
class="font-inter text-[28px] leading-normal font-semibold text-base-foreground"
|
||||
class="font-inter text-[28px] leading-normal font-semibold text-base-foreground tabular-nums"
|
||||
>
|
||||
${{ getPrice(tier) }}
|
||||
<span
|
||||
v-show="currentBillingCycle === 'yearly'"
|
||||
class="text-2xl text-muted-foreground line-through"
|
||||
>
|
||||
${{ tier.pricing.monthly }}
|
||||
</span>
|
||||
${{ getPrice(tier) }}
|
||||
</span>
|
||||
<span class="font-inter text-xl/normal text-base-foreground">
|
||||
{{ t('subscription.usdPerMonth') }}
|
||||
@@ -122,9 +122,12 @@
|
||||
}}
|
||||
</span>
|
||||
<div class="flex flex-row items-center gap-1">
|
||||
<i class="icon-[lucide--component] text-sm text-amber-400" />
|
||||
<i
|
||||
class="icon-[comfy--credits] size-4 shrink-0 bg-amber-400"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span
|
||||
class="font-inter text-sm/normal font-bold text-base-foreground"
|
||||
class="font-inter text-sm/normal font-bold text-base-foreground tabular-nums"
|
||||
>
|
||||
{{ n(getCreditsDisplay(tier)) }}
|
||||
</span>
|
||||
@@ -136,7 +139,7 @@
|
||||
{{ t('subscription.maxDurationLabel') }}
|
||||
</span>
|
||||
<span
|
||||
class="font-inter text-sm/normal font-bold text-base-foreground"
|
||||
class="font-inter text-sm/normal font-bold text-base-foreground tabular-nums"
|
||||
>
|
||||
{{ tier.maxDuration }}
|
||||
</span>
|
||||
@@ -186,7 +189,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
class="font-inter text-sm/normal font-bold text-base-foreground"
|
||||
class="font-inter text-sm/normal font-bold text-base-foreground tabular-nums"
|
||||
>
|
||||
~{{ n(tier.pricing.videoEstimate) }}
|
||||
</span>
|
||||
@@ -263,8 +266,8 @@ import { useI18n } from 'vue-i18n'
|
||||
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import { useAuthActions } from '@/composables/auth/useAuthActions'
|
||||
import { useBillingContext } from '@/composables/billing/useBillingContext'
|
||||
import { useErrorHandling } from '@/composables/useErrorHandling'
|
||||
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
|
||||
import {
|
||||
TIER_PRICING,
|
||||
TIER_TO_KEY
|
||||
@@ -361,9 +364,13 @@ const tiers: PricingTierConfig[] = [
|
||||
const {
|
||||
isActiveSubscription,
|
||||
isFreeTier,
|
||||
subscriptionTier,
|
||||
isYearlySubscription
|
||||
} = useSubscription()
|
||||
tier: subscriptionTier,
|
||||
subscription
|
||||
} = useBillingContext()
|
||||
|
||||
const isYearlySubscription = computed(
|
||||
() => subscription.value?.duration === 'ANNUAL'
|
||||
)
|
||||
const telemetry = useTelemetry()
|
||||
const { userId } = storeToRefs(useAuthStore())
|
||||
const { accessBillingPortal, reportError } = useAuthActions()
|
||||
|
||||
@@ -16,7 +16,6 @@ import { onBeforeUnmount, ref, watch } from 'vue'
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import { useBillingContext } from '@/composables/billing/useBillingContext'
|
||||
import { isCloud } from '@/platform/distribution/types'
|
||||
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
|
||||
import { useTelemetry } from '@/platform/telemetry'
|
||||
import { cn } from '@comfyorg/tailwind-utils'
|
||||
|
||||
@@ -38,8 +37,8 @@ const emit = defineEmits<{
|
||||
subscribed: []
|
||||
}>()
|
||||
|
||||
const { isActiveSubscription, showSubscriptionDialog } = useBillingContext()
|
||||
const { subscriptionTier } = useSubscription()
|
||||
const { isActiveSubscription, showSubscriptionDialog, tier } =
|
||||
useBillingContext()
|
||||
const isAwaitingStripeSubscription = ref(false)
|
||||
|
||||
watch(
|
||||
@@ -54,7 +53,7 @@ watch(
|
||||
|
||||
const handleSubscribe = () => {
|
||||
useTelemetry()?.trackSubscription('subscribe_clicked', {
|
||||
current_tier: subscriptionTier.value?.toLowerCase()
|
||||
current_tier: tier.value?.toLowerCase()
|
||||
})
|
||||
isAwaitingStripeSubscription.value = true
|
||||
showSubscriptionDialog()
|
||||
|
||||
@@ -2,26 +2,26 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import { useSubscriptionActions } from '@/platform/cloud/subscription/composables/useSubscriptionActions'
|
||||
|
||||
// Mock dependencies
|
||||
const mockFetchBalance = vi.fn()
|
||||
const mockBillingFetchBalance = vi.fn()
|
||||
const mockAuthFetchBalance = vi.fn()
|
||||
const mockFetchStatus = vi.fn()
|
||||
const mockShowTopUpCreditsDialog = vi.fn()
|
||||
const mockExecute = vi.fn()
|
||||
const mockToastAdd = vi.fn()
|
||||
|
||||
vi.mock('@/platform/updates/common/toastStore', () => ({
|
||||
useToastStore: () => ({ add: mockToastAdd })
|
||||
}))
|
||||
|
||||
vi.mock('@/composables/auth/useAuthActions', () => ({
|
||||
useAuthActions: () => ({
|
||||
fetchBalance: mockFetchBalance
|
||||
})
|
||||
}))
|
||||
|
||||
vi.mock('@/platform/cloud/subscription/composables/useSubscription', () => ({
|
||||
useSubscription: () => ({
|
||||
fetchStatus: mockFetchStatus
|
||||
fetchBalance: mockAuthFetchBalance
|
||||
})
|
||||
}))
|
||||
|
||||
vi.mock('@/composables/billing/useBillingContext', () => ({
|
||||
useBillingContext: () => ({
|
||||
fetchBalance: mockBillingFetchBalance,
|
||||
fetchStatus: mockFetchStatus
|
||||
})
|
||||
}))
|
||||
@@ -119,20 +119,21 @@ describe('useSubscriptionActions', () => {
|
||||
})
|
||||
|
||||
describe('handleRefresh', () => {
|
||||
it('should call both fetchBalance and fetchStatus', async () => {
|
||||
it('should refresh balance and status through the billing facade', async () => {
|
||||
const { handleRefresh } = useSubscriptionActions()
|
||||
await handleRefresh()
|
||||
|
||||
expect(mockFetchBalance).toHaveBeenCalledOnce()
|
||||
expect(mockBillingFetchBalance).toHaveBeenCalledOnce()
|
||||
expect(mockFetchStatus).toHaveBeenCalledOnce()
|
||||
expect(mockAuthFetchBalance).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should handle errors gracefully', async () => {
|
||||
mockFetchBalance.mockRejectedValueOnce(new Error('Fetch failed'))
|
||||
it('swallows refresh failures without surfacing a toast', async () => {
|
||||
mockBillingFetchBalance.mockRejectedValueOnce(new Error('Fetch failed'))
|
||||
const { handleRefresh } = useSubscriptionActions()
|
||||
|
||||
// Should not throw
|
||||
await expect(handleRefresh()).resolves.toBeUndefined()
|
||||
expect(mockToastAdd).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
||||
import { useBillingContext } from '@/composables/billing/useBillingContext'
|
||||
import { useAuthActions } from '@/composables/auth/useAuthActions'
|
||||
import { useTelemetry } from '@/platform/telemetry'
|
||||
import { useDialogService } from '@/services/dialogService'
|
||||
import { useCommandStore } from '@/stores/commandStore'
|
||||
@@ -11,10 +10,9 @@ import { useCommandStore } from '@/stores/commandStore'
|
||||
*/
|
||||
export function useSubscriptionActions() {
|
||||
const dialogService = useDialogService()
|
||||
const authActions = useAuthActions()
|
||||
const commandStore = useCommandStore()
|
||||
const telemetry = useTelemetry()
|
||||
const { fetchStatus } = useBillingContext()
|
||||
const { fetchBalance, fetchStatus } = useBillingContext()
|
||||
|
||||
const isLoadingSupport = ref(false)
|
||||
|
||||
@@ -44,7 +42,7 @@ export function useSubscriptionActions() {
|
||||
|
||||
const handleRefresh = async () => {
|
||||
try {
|
||||
await Promise.all([authActions.fetchBalance(), fetchStatus()])
|
||||
await Promise.all([fetchBalance(), fetchStatus()])
|
||||
} catch (error) {
|
||||
console.error('[useSubscriptionActions] Error refreshing data:', error)
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ import CurrentUserMessage from '@/components/dialog/content/setting/CurrentUserM
|
||||
import BaseModalLayout from '@/components/widget/layout/BaseModalLayout.vue'
|
||||
import NavItem from '@/components/widget/nav/NavItem.vue'
|
||||
import NavTitle from '@/components/widget/nav/NavTitle.vue'
|
||||
import { useAuthActions } from '@/composables/auth/useAuthActions'
|
||||
import { useBillingContext } from '@/composables/billing/useBillingContext'
|
||||
import ColorPaletteMessage from '@/platform/settings/components/ColorPaletteMessage.vue'
|
||||
import SettingsPanel from '@/platform/settings/components/SettingsPanel.vue'
|
||||
import { useSettingSearch } from '@/platform/settings/composables/useSettingSearch'
|
||||
@@ -130,7 +130,7 @@ const {
|
||||
getSearchResults
|
||||
} = useSettingSearch()
|
||||
|
||||
const authActions = useAuthActions()
|
||||
const { fetchBalance } = useBillingContext()
|
||||
|
||||
const navRef = ref<HTMLElement | null>(null)
|
||||
const activeCategoryKey = ref<string | null>(defaultCategory.value?.key ?? null)
|
||||
@@ -238,7 +238,7 @@ watch(activeCategoryKey, (newKey, oldKey) => {
|
||||
activeCategoryKey.value = oldKey
|
||||
}
|
||||
if (newKey === 'credits') {
|
||||
void authActions.fetchBalance()
|
||||
void fetchBalance()
|
||||
}
|
||||
if (newKey) {
|
||||
void nextTick(() => {
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import type * as VueModule from 'vue'
|
||||
import type { Ref } from 'vue'
|
||||
import { nextTick, ref } from 'vue'
|
||||
|
||||
import { TelemetryEvents } from '../../types'
|
||||
|
||||
@@ -12,6 +15,10 @@ const hoisted = vi.hoisted(() => {
|
||||
const mockReset = vi.fn()
|
||||
const mockOnUserResolved = vi.fn()
|
||||
const mockOnUserLogout = vi.fn()
|
||||
const refs = {
|
||||
tier: null as unknown as Ref<string | null>,
|
||||
remoteConfig: null as unknown as Ref<Record<string, unknown> | null>
|
||||
}
|
||||
|
||||
return {
|
||||
mockCapture,
|
||||
@@ -23,6 +30,7 @@ const hoisted = vi.hoisted(() => {
|
||||
mockReset,
|
||||
mockOnUserResolved,
|
||||
mockOnUserLogout,
|
||||
refs,
|
||||
mockPosthog: {
|
||||
default: {
|
||||
init: mockInit,
|
||||
@@ -36,14 +44,6 @@ const hoisted = vi.hoisted(() => {
|
||||
}
|
||||
})
|
||||
|
||||
vi.mock('vue', async () => {
|
||||
const actual = await vi.importActual('vue')
|
||||
return {
|
||||
...actual,
|
||||
watch: vi.fn()
|
||||
}
|
||||
})
|
||||
|
||||
vi.mock('@/composables/auth/useCurrentUser', () => ({
|
||||
useCurrentUser: () => ({
|
||||
onUserResolved: hoisted.mockOnUserResolved,
|
||||
@@ -51,21 +51,19 @@ vi.mock('@/composables/auth/useCurrentUser', () => ({
|
||||
})
|
||||
}))
|
||||
|
||||
const mockRemoteConfig = vi.hoisted(
|
||||
() => ({ value: null }) as { value: Record<string, unknown> | null }
|
||||
)
|
||||
|
||||
vi.mock('@/platform/remoteConfig/remoteConfig', () => ({
|
||||
remoteConfig: mockRemoteConfig
|
||||
}))
|
||||
vi.mock('@/platform/remoteConfig/remoteConfig', async () => {
|
||||
const { ref } = await vi.importActual<typeof VueModule>('vue')
|
||||
hoisted.refs.remoteConfig = ref<Record<string, unknown> | null>(null)
|
||||
return { remoteConfig: hoisted.refs.remoteConfig }
|
||||
})
|
||||
|
||||
vi.mock('posthog-js', () => hoisted.mockPosthog)
|
||||
|
||||
vi.mock('@/platform/cloud/subscription/composables/useSubscription', () => ({
|
||||
useSubscription: () => ({
|
||||
subscriptionTier: { value: null }
|
||||
})
|
||||
}))
|
||||
vi.mock('@/composables/billing/useBillingContext', async () => {
|
||||
const { ref } = await vi.importActual<typeof VueModule>('vue')
|
||||
hoisted.refs.tier = ref<string | null>(null)
|
||||
return { useBillingContext: () => ({ tier: hoisted.refs.tier }) }
|
||||
})
|
||||
|
||||
import { PostHogTelemetryProvider } from './PostHogTelemetryProvider'
|
||||
|
||||
@@ -82,7 +80,10 @@ function createProvider(
|
||||
describe('PostHogTelemetryProvider', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
mockRemoteConfig.value = null
|
||||
hoisted.refs.remoteConfig.value = null
|
||||
// Fresh tier ref per test: each provider registers an undisposed tier
|
||||
// watch, so a shared ref would leak watchers across tests.
|
||||
hoisted.refs.tier = ref<string | null>(null)
|
||||
window.__CONFIG__ = {
|
||||
posthog_project_token: 'phc_test_token'
|
||||
} as typeof window.__CONFIG__
|
||||
@@ -116,7 +117,7 @@ describe('PostHogTelemetryProvider', () => {
|
||||
})
|
||||
|
||||
it('applies posthog_config overrides from remote config', async () => {
|
||||
mockRemoteConfig.value = {
|
||||
hoisted.refs.remoteConfig.value = {
|
||||
posthog_config: {
|
||||
debug: true,
|
||||
api_host: 'https://custom.host.com'
|
||||
@@ -150,6 +151,48 @@ describe('PostHogTelemetryProvider', () => {
|
||||
|
||||
expect(hoisted.mockIdentify).toHaveBeenCalledWith('user-123')
|
||||
})
|
||||
|
||||
function tierPropertySets(): unknown[] {
|
||||
return hoisted.mockPeopleSet.mock.calls
|
||||
.map(([props]) => props)
|
||||
.filter((props) => props && 'subscription_tier' in props)
|
||||
}
|
||||
|
||||
it('sets subscription_tier reactively when the facade tier resolves', async () => {
|
||||
createProvider()
|
||||
await vi.dynamicImportSettled()
|
||||
|
||||
const onResolved = hoisted.mockOnUserResolved.mock.calls[0][0]
|
||||
onResolved({ id: 'user-123' })
|
||||
|
||||
// Unresolved tier (null) does not set the property
|
||||
expect(tierPropertySets()).toHaveLength(0)
|
||||
|
||||
hoisted.refs.tier.value = 'PRO'
|
||||
await nextTick()
|
||||
expect(hoisted.mockPeopleSet).toHaveBeenCalledWith({
|
||||
subscription_tier: 'PRO'
|
||||
})
|
||||
|
||||
hoisted.refs.tier.value = null
|
||||
await nextTick()
|
||||
expect(tierPropertySets()).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('keeps a single tier watcher across repeated user resolutions', async () => {
|
||||
createProvider()
|
||||
await vi.dynamicImportSettled()
|
||||
|
||||
const onResolved = hoisted.mockOnUserResolved.mock.calls[0][0]
|
||||
onResolved({ id: 'user-1' })
|
||||
onResolved({ id: 'user-1' })
|
||||
onResolved({ id: 'user-2' })
|
||||
|
||||
hoisted.refs.tier.value = 'PRO'
|
||||
await nextTick()
|
||||
|
||||
expect(tierPropertySets()).toHaveLength(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('desktop entry capture', () => {
|
||||
@@ -670,7 +713,7 @@ describe('PostHogTelemetryProvider', () => {
|
||||
|
||||
it('remoteConfig.posthog_config cannot override before_send or person_profiles', async () => {
|
||||
const remoteBefore_send = vi.fn()
|
||||
mockRemoteConfig.value = {
|
||||
hoisted.refs.remoteConfig.value = {
|
||||
posthog_config: {
|
||||
before_send: remoteBefore_send,
|
||||
person_profiles: 'always'
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import type { PostHog } from 'posthog-js'
|
||||
import { watch } from 'vue'
|
||||
import type { WatchStopHandle } from 'vue'
|
||||
|
||||
import { createPostHogBeforeSend } from '@comfyorg/shared-frontend-utils/piiUtil'
|
||||
|
||||
import { useCurrentUser } from '@/composables/auth/useCurrentUser'
|
||||
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
|
||||
import { useBillingContext } from '@/composables/billing/useBillingContext'
|
||||
import { remoteConfig } from '@/platform/remoteConfig/remoteConfig'
|
||||
import type { RemoteConfig } from '@/platform/remoteConfig/types'
|
||||
|
||||
@@ -98,6 +99,7 @@ export class PostHogTelemetryProvider implements TelemetryProvider {
|
||||
private isInitialized = false
|
||||
private disabledEvents = new Set<TelemetryEventName>(DEFAULT_DISABLED_EVENTS)
|
||||
private desktopEntryProps: DesktopEntryProps | null = null
|
||||
private stopSubscriptionTierWatch: WatchStopHandle | null = null
|
||||
|
||||
constructor() {
|
||||
this.configureDisabledEvents(
|
||||
@@ -307,12 +309,13 @@ export class PostHogTelemetryProvider implements TelemetryProvider {
|
||||
}
|
||||
|
||||
private setSubscriptionProperties(): void {
|
||||
const { subscriptionTier } = useSubscription()
|
||||
watch(
|
||||
subscriptionTier,
|
||||
(tier) => {
|
||||
if (tier && this.posthog) {
|
||||
this.posthog.people.set({ subscription_tier: tier })
|
||||
if (this.stopSubscriptionTierWatch) return
|
||||
const { tier } = useBillingContext()
|
||||
this.stopSubscriptionTierWatch = watch(
|
||||
tier,
|
||||
(value) => {
|
||||
if (value && this.posthog) {
|
||||
this.posthog.people.set({ subscription_tier: value })
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
|
||||
Reference in New Issue
Block a user