fix: resolve i18n no-restricted-imports lint warnings (#8704)

## Summary

Fix all i18n `no-restricted-imports` lint warnings and upgrade rules
from `warn` to `error`.

## Changes

- **What**: Migrate Vue components from `import { t/d } from '@/i18n'`
to `const { t } = useI18n()`. Migrate non-component `.ts` files from
`useI18n()` to `import { t/d } from '@/i18n'`. Allow `st` import from
`@/i18n` in Vue components (it wraps `te`/`t` for safe fallback
translation). Remove `@deprecated` tag from `i18n.ts` global exports
(still used by `st` and non-component code). Upgrade both lint rules
from `warn` to `error`.

## Review Focus

- The `st` helper is intentionally excluded from the Vue component
restriction since it provides safe fallback translation needed for
custom node definitions.

Fixes #8701

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8704-fix-resolve-i18n-no-restricted-imports-lint-warnings-2ff6d73d365081ae84d8eb0dfef24323)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Alexander Brown
2026-02-06 20:54:53 -08:00
committed by GitHub
parent c5431de123
commit 69c8c84aef
35 changed files with 117 additions and 66 deletions

View File

@@ -287,12 +287,12 @@ export default defineConfig([
files: ['**/*.vue'],
rules: {
'no-restricted-imports': [
'warn',
'error',
{
paths: [
{
name: '@/i18n',
importNames: ['t', 'd', 'st', 'te'],
importNames: ['t', 'd', 'te'],
message:
"In Vue components, use `const { t } = useI18n()` instead of importing from '@/i18n'."
}
@@ -301,13 +301,13 @@ export default defineConfig([
]
}
},
// Non-composable .ts files must use the global t/d/st/te, not useI18n()
// Non-composable .ts files must use the global t/d/te, not useI18n()
{
files: ['**/*.ts'],
ignores: ['**/use[A-Z]*.ts', '**/*.test.ts', 'src/i18n.ts'],
rules: {
'no-restricted-imports': [
'warn',
'error',
{
paths: [
{

View File

@@ -111,6 +111,7 @@ import {
watch,
watchEffect
} from 'vue'
import { useI18n } from 'vue-i18n'
import LiteGraphCanvasSplitterOverlay from '@/components/LiteGraphCanvasSplitterOverlay.vue'
import TopMenuSection from '@/components/TopMenuSection.vue'
@@ -137,7 +138,6 @@ import { useCopy } from '@/composables/useCopy'
import { useGlobalLitegraph } from '@/composables/useGlobalLitegraph'
import { usePaste } from '@/composables/usePaste'
import { useVueFeatureFlags } from '@/composables/useVueFeatureFlags'
import { t } from '@/i18n'
import { LiteGraph } from '@/lib/litegraph/src/litegraph'
import { useLitegraphSettings } from '@/platform/settings/composables/useLitegraphSettings'
import { CORE_SETTINGS } from '@/platform/settings/constants/coreSettings'
@@ -175,6 +175,7 @@ import { isCloud } from '@/platform/distribution/types'
import { useFeatureFlags } from '@/composables/useFeatureFlags'
import { useInviteUrlLoader } from '@/platform/workspace/composables/useInviteUrlLoader'
const { t } = useI18n()
const emit = defineEmits<{
ready: []
}>()

View File

@@ -94,6 +94,7 @@
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref, toRaw } from 'vue'
import { useI18n } from 'vue-i18n'
import AnimationControls from '@/components/load3d/controls/AnimationControls.vue'
import CameraControls from '@/components/load3d/controls/viewer/ViewerCameraControls.vue'
@@ -104,11 +105,11 @@ import SceneControls from '@/components/load3d/controls/viewer/ViewerSceneContro
import Button from '@/components/ui/button/Button.vue'
import { useLoad3dDrag } from '@/composables/useLoad3dDrag'
import { useLoad3dViewer } from '@/composables/useLoad3dViewer'
import { t } from '@/i18n'
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import { useLoad3dService } from '@/services/load3dService'
import { useDialogStore } from '@/stores/dialogStore'
const { t } = useI18n()
const props = defineProps<{
node?: LGraphNode
modelUrl?: string

View File

@@ -94,15 +94,16 @@
<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import type {
MaterialMode,
UpDirection
} from '@/extensions/core/load3d/interfaces'
import { t } from '@/i18n'
import { cn } from '@/utils/tailwindUtil'
const { t } = useI18n()
const {
hideMaterialMode = false,
isPlyModel = false,

View File

@@ -19,13 +19,15 @@
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import Load3DViewerContent from '@/components/load3d/Load3dViewerContent.vue'
import Button from '@/components/ui/button/Button.vue'
import { t } from '@/i18n'
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import { useLoad3dService } from '@/services/load3dService'
import { useDialogStore } from '@/stores/dialogStore'
const { t } = useI18n()
const { node } = defineProps<{
node: LGraphNode
}>()

View File

@@ -30,10 +30,11 @@
import Select from 'primevue/select'
import Slider from 'primevue/slider'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import type { CameraType } from '@/extensions/core/load3d/interfaces'
import { t } from '@/i18n'
const { t } = useI18n()
const cameras = [
{ title: t('load3d.cameraType.perspective'), value: 'perspective' },
{ title: t('load3d.cameraType.orthographic'), value: 'orthographic' }

View File

@@ -25,13 +25,14 @@
<script setup lang="ts">
import Select from 'primevue/select'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import type {
MaterialMode,
UpDirection
} from '@/extensions/core/load3d/interfaces'
import { t } from '@/i18n'
const { t } = useI18n()
const { hideMaterialMode = false, isPlyModel = false } = defineProps<{
hideMaterialMode?: boolean
isPlyModel?: boolean

View File

@@ -160,14 +160,15 @@
<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { BrushShape } from '@/extensions/core/maskeditor/types'
import { t } from '@/i18n'
import { useMaskEditorStore } from '@/stores/maskEditorStore'
import { cn } from '@/utils/tailwindUtil'
import SliderControl from './controls/SliderControl.vue'
const { t } = useI18n()
const store = useMaskEditorStore()
const colorInputRef = ref<HTMLInputElement>()

View File

@@ -61,14 +61,16 @@
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import { ColorComparisonMethod } from '@/extensions/core/maskeditor/types'
import { t } from '@/i18n'
import { useMaskEditorStore } from '@/stores/maskEditorStore'
import DropdownControl from './controls/DropdownControl.vue'
import SliderControl from './controls/SliderControl.vue'
import ToggleControl from './controls/ToggleControl.vue'
const { t } = useI18n()
const store = useMaskEditorStore()
const methodOptions = Object.values(ColorComparisonMethod)

View File

@@ -131,12 +131,12 @@
<script setup lang="ts">
import { computed, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { useCanvasManager } from '@/composables/maskeditor/useCanvasManager'
import type { useToolManager } from '@/composables/maskeditor/useToolManager'
import type { ImageLayer } from '@/extensions/core/maskeditor/types'
import { MaskBlendMode, Tools } from '@/extensions/core/maskeditor/types'
import { t } from '@/i18n'
import { useMaskEditorStore } from '@/stores/maskEditorStore'
import SliderControl from './controls/SliderControl.vue'
@@ -145,6 +145,7 @@ const { toolManager } = defineProps<{
toolManager?: ReturnType<typeof useToolManager>
}>()
const { t } = useI18n()
const store = useMaskEditorStore()
const canvasManager = useCanvasManager()

View File

@@ -27,11 +27,13 @@
</template>
<script setup lang="ts">
import { t } from '@/i18n'
import { useI18n } from 'vue-i18n'
import { useMaskEditorStore } from '@/stores/maskEditorStore'
import SliderControl from './controls/SliderControl.vue'
const { t } = useI18n()
const store = useMaskEditorStore()
const onToleranceChange = (value: number) => {

View File

@@ -31,18 +31,19 @@
<script setup lang="ts">
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import type { useToolManager } from '@/composables/maskeditor/useToolManager'
import { iconsHtml } from '@/extensions/core/maskeditor/constants'
import type { Tools } from '@/extensions/core/maskeditor/types'
import { allTools } from '@/extensions/core/maskeditor/types'
import { t } from '@/i18n'
import { useMaskEditorStore } from '@/stores/maskEditorStore'
const { toolManager } = defineProps<{
toolManager: ReturnType<typeof useToolManager>
}>()
const { t } = useI18n()
const store = useMaskEditorStore()
const onToolSelect = (tool: Tools) => {

View File

@@ -128,15 +128,16 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import { useCanvasTools } from '@/composables/maskeditor/useCanvasTools'
import { useCanvasTransform } from '@/composables/maskeditor/useCanvasTransform'
import { useMaskEditorSaver } from '@/composables/maskeditor/useMaskEditorSaver'
import { t } from '@/i18n'
import { useDialogStore } from '@/stores/dialogStore'
import { useMaskEditorStore } from '@/stores/maskEditorStore'
const { t } = useI18n()
const store = useMaskEditorStore()
const dialogStore = useDialogStore()
const canvasTools = useCanvasTools()

View File

@@ -44,6 +44,7 @@ const props = defineProps<{
}>()
const { t } = useI18n()
const executionStore = useExecutionStore()
const {
totalPercent,

View File

@@ -36,6 +36,7 @@ const canvasStore = useCanvasStore()
const rightSidePanelStore = useRightSidePanelStore()
const settingStore = useSettingStore()
const { t } = useI18n()
const { findParentGroup } = useGraphHierarchy()
const { selectedItems: directlySelectedItems } = storeToRefs(canvasStore)

View File

@@ -46,6 +46,7 @@ const emit = defineEmits<{
}>()
const { t } = useI18n()
const canvasStore = useCanvasStore()
const favoritedWidgetsStore = useFavoritedWidgetsStore()
const isEditing = ref(false)

View File

@@ -1,12 +1,13 @@
<script setup lang="ts">
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import { t } from '@/i18n'
import { useKeybindingStore } from '@/platform/keybindings/keybindingStore'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
import { useCommandStore } from '@/stores/commandStore'
const { t } = useI18n()
const canvasStore = useCanvasStore()
const keybindingStore = useKeybindingStore()

View File

@@ -58,6 +58,7 @@
import { useResizeObserver } from '@vueuse/core'
import { debounce } from 'es-toolkit/compat'
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import HelpCenterPopups from '@/components/helpcenter/HelpCenterPopups.vue'
import ComfyMenuButton from '@/components/sidebar/ComfyMenuButton.vue'
@@ -66,7 +67,6 @@ import SidebarBottomPanelToggleButton from '@/components/sidebar/SidebarBottomPa
import SidebarSettingsButton from '@/components/sidebar/SidebarSettingsButton.vue'
import SidebarShortcutsToggleButton from '@/components/sidebar/SidebarShortcutsToggleButton.vue'
import { useFeatureFlags } from '@/composables/useFeatureFlags'
import { t } from '@/i18n'
import { isCloud } from '@/platform/distribution/types'
import { useSettingStore } from '@/platform/settings/settingStore'
import { useTelemetry } from '@/platform/telemetry'
@@ -84,6 +84,7 @@ import SidebarIcon from './SidebarIcon.vue'
import SidebarLogoutIcon from './SidebarLogoutIcon.vue'
import SidebarTemplatesButton from './SidebarTemplatesButton.vue'
const { t } = useI18n()
const workspaceStore = useWorkspaceStore()
const settingStore = useSettingStore()
const userStore = useUserStore()

View File

@@ -10,8 +10,8 @@
<script setup lang="ts">
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { t } from '@/i18n'
import type { TopbarBadge as TopbarBadgeType } from '@/types/comfy'
import TopbarBadge from './TopbarBadge.vue'
@@ -31,6 +31,8 @@ withDefaults(
}
)
const { t } = useI18n()
const cloudBadge = computed<TopbarBadgeType>(() => ({
label: t('g.beta'),
text: 'Comfy Cloud'

View File

@@ -37,17 +37,18 @@
import Popover from 'primevue/popover'
import type { HTMLAttributes } from 'vue'
import { ref } from 'vue'
import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import { useCurrentUser } from '@/composables/auth/useCurrentUser'
import { useExternalLink } from '@/composables/useExternalLink'
import { t } from '@/i18n'
import { cn } from '@/utils/tailwindUtil'
const { class: className } = defineProps<{
class?: HTMLAttributes['class']
}>()
const { t } = useI18n()
const { isLoggedIn, handleSignIn } = useCurrentUser()
const { buildDocsUrl } = useExternalLink()
const apiNodesOverviewUrl = buildDocsUrl(

View File

@@ -201,7 +201,6 @@ export const i18n = createI18n({
})
/** Convenience shorthand: i18n.global */
/** @deprecated use useI18n */
export const { t, te, d } = i18n.global
/**

View File

@@ -62,14 +62,17 @@
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import { t } from '@/i18n'
import videoPoster from '@/platform/cloud/onboarding/assets/videos/thumbnail.png'
import videoSrc from '@/platform/cloud/onboarding/assets/videos/video.mp4'
import CloudLogo from '@/platform/cloud/onboarding/components/CloudLogo.vue'
import CloudTemplateFooter from '@/platform/cloud/onboarding/components/CloudTemplateFooter.vue'
import BaseViewTemplate from '@/views/templates/BaseViewTemplate.vue'
const { t } = useI18n()
const handleDownloadClick = () => {
window.open('https://www.comfy.org/download', '_blank')
}

View File

@@ -79,6 +79,17 @@ const i18n = createI18n({
currentPlan: 'Current Plan',
subscribeTo: 'Subscribe to {plan}',
changeTo: 'Change to {plan}',
tierNameYearly: '{name} Yearly',
yearlyCreditsLabel: 'Yearly credits',
monthlyCreditsLabel: 'Monthly credits',
maxDurationLabel: 'Max duration',
gpuLabel: 'GPU',
addCreditsLabel: 'Add more credits',
customLoRAsLabel: 'Custom LoRAs',
videoEstimateLabel: 'Video estimate',
videoEstimateHelp: 'How is this calculated?',
videoEstimateExplanation: 'Based on average usage.',
videoEstimateTryTemplate: 'Try template',
maxDuration: {
standard: '30 min',
creator: '30 min',

View File

@@ -252,7 +252,6 @@ import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions'
import { useErrorHandling } from '@/composables/useErrorHandling'
import { t } from '@/i18n'
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
import {
TIER_PRICING,
@@ -292,6 +291,8 @@ interface PricingTierConfig {
isPopular?: boolean
}
const { t, n } = useI18n()
const billingCycleOptions: BillingCycleOption[] = [
{ label: t('subscription.yearly'), value: 'yearly' },
{ label: t('subscription.monthly'), value: 'monthly' }
@@ -326,8 +327,6 @@ const tiers: PricingTierConfig[] = [
isPopular: false
}
]
const { n } = useI18n()
const { isActiveSubscription, subscriptionTier, isYearlySubscription } =
useSubscription()
const { accessBillingPortal, reportError } = useFirebaseAuthActions()

View File

@@ -40,6 +40,7 @@ const props = defineProps<{
}>()
const { t } = useI18n()
function translateOptions(options: (SettingOption | string)[]) {
if (typeof options === 'function') {
// @ts-expect-error: Audit and deprecate usage of legacy options type:

View File

@@ -3,11 +3,11 @@ import { useEventListener, useTimeout } from '@vueuse/core'
import { partition } from 'es-toolkit'
import { storeToRefs } from 'pinia'
import { computed, ref, shallowRef } from 'vue'
import { useI18n } from 'vue-i18n'
import Popover from '@/components/ui/Popover.vue'
import Button from '@/components/ui/button/Button.vue'
import { extractVueNodeData } from '@/composables/graph/useGraphNodeManager'
import { t } from '@/i18n'
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import { useBillingContext } from '@/composables/billing/useBillingContext'
import SubscribeToRunButton from '@/platform/cloud/subscription/components/SubscribeToRun.vue'
@@ -26,6 +26,7 @@ import { useQueueSettingsStore } from '@/stores/queueStore'
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
import { cn } from '@/utils/tailwindUtil'
const { t } = useI18n()
const commandStore = useCommandStore()
const executionStore = useExecutionStore()
const { batchCount } = storeToRefs(useQueueSettingsStore())

View File

@@ -1,10 +1,10 @@
<script setup lang="ts">
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { downloadFile } from '@/base/common/downloadUtil'
import Popover from '@/components/ui/Popover.vue'
import Button from '@/components/ui/button/Button.vue'
import { d, t } from '@/i18n'
import { useMediaAssetActions } from '@/platform/assets/composables/useMediaAssetActions'
import { getOutputAssetMetadata } from '@/platform/assets/schemas/assetMetadataSchema'
import type { AssetItem } from '@/platform/assets/schemas/assetSchema'
@@ -26,6 +26,7 @@ import { formatDuration } from '@/utils/dateTimeUtil'
import { collectAllNodes } from '@/utils/graphTraversalUtil'
import { executeWidgetsCallback } from '@/utils/litegraphUtil'
const { t, d } = useI18n()
const mediaActions = useMediaAssetActions()
const { runButtonClick, selectedItem, selectedOutput } = defineProps<{

View File

@@ -1,5 +1,7 @@
<script setup lang="ts">
import { t } from '@/i18n'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
</script>
<template>

View File

@@ -4,13 +4,15 @@ import {
CollapsibleTrigger,
CollapsibleContent
} from 'reka-ui'
import { useI18n } from 'vue-i18n'
import WorkflowsSidebarTab from '@/components/sidebar/tabs/WorkflowsSidebarTab.vue'
import Button from '@/components/ui/button/Button.vue'
import Popover from '@/components/ui/Popover.vue'
import { useWorkflowTemplateSelectorDialog } from '@/composables/useWorkflowTemplateSelectorDialog'
import { t } from '@/i18n'
import { useCommandStore } from '@/stores/commandStore'
const { t } = useI18n()
</script>
<template>
<CollapsibleRoot class="flex flex-col">

View File

@@ -85,8 +85,8 @@
import { useIntervalFn } from '@vueuse/core'
import { Button } from 'primevue'
import { computed, onMounted, onUnmounted, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { t } from '@/i18n'
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'
import { useToastStore } from '@/platform/updates/common/toastStore'
@@ -98,6 +98,8 @@ import { useAudioRecorder } from '../composables/audio/useAudioRecorder'
import { useAudioWaveform } from '../composables/audio/useAudioWaveform'
import { formatTime } from '../utils/audioUtils'
const { t } = useI18n()
const props = defineProps<{
readonly?: boolean
nodeId: string

View File

@@ -1,8 +1,8 @@
<script setup lang="ts">
import Popover from 'primevue/popover'
import { computed, ref, useTemplateRef } from 'vue'
import { useI18n } from 'vue-i18n'
import { t } from '@/i18n'
import { useToastStore } from '@/platform/updates/common/toastStore'
import type {
@@ -46,16 +46,28 @@ interface Props {
) => Promise<FormDropdownItem[]>
}
const props = withDefaults(defineProps<Props>(), {
placeholder: t('widgets.uploadSelect.placeholder'),
multiple: false,
uploadable: false,
disabled: false,
filterOptions: () => [],
sortOptions: () => getDefaultSortOptions(),
isSelected: (selected, item, _index) => selected.has(item.id),
searcher: defaultSearcher
})
const { t } = useI18n()
const {
placeholder,
multiple = false,
uploadable = false,
disabled = false,
accept,
filterOptions = [],
sortOptions = getDefaultSortOptions(),
showOwnershipFilter,
ownershipOptions,
showBaseModelFilter,
baseModelOptions,
isSelected = (selected, item, _index) => selected.has(item.id),
searcher = defaultSearcher,
items
} = defineProps<Props>()
const placeholderText = computed(
() => placeholder ?? t('widgets.uploadSelect.placeholder')
)
const selected = defineModel<Set<string>>('selected', {
default: () => new Set()
@@ -82,24 +94,22 @@ const triggerRef = useTemplateRef('triggerRef')
const isOpen = ref(false)
const maxSelectable = computed(() => {
if (props.multiple === true) return Infinity
if (typeof props.multiple === 'number') return props.multiple
if (multiple === true) return Infinity
if (typeof multiple === 'number') return multiple
return 1
})
const itemsKey = computed(() => props.items.map((item) => item.id).join('|'))
const itemsKey = computed(() => items.map((item) => item.id).join('|'))
const filteredItems = ref<FormDropdownItem[]>([])
const defaultSorter = computed<SortOption['sorter']>(() => {
const sorter = props.sortOptions.find(
(option) => option.id === 'default'
)?.sorter
return sorter || (({ items }) => items.slice())
const sorter = sortOptions.find((option) => option.id === 'default')?.sorter
return sorter || (({ items: i }) => i.slice())
})
const selectedSorter = computed<SortOption['sorter']>(() => {
if (sortSelected.value === 'default') return defaultSorter.value
const sorter = props.sortOptions.find(
const sorter = sortOptions.find(
(option) => option.id === sortSelected.value
)?.sorter
return sorter || defaultSorter.value
@@ -109,11 +119,11 @@ const sortedItems = computed(() => {
})
function internalIsSelected(item: FormDropdownItem, index: number): boolean {
return props.isSelected?.(selected.value, item, index) ?? false
return isSelected(selected.value, item, index)
}
const toggleDropdown = (event: Event) => {
if (props.disabled) return
if (disabled) return
if (popoverRef.value && triggerRef.value) {
popoverRef.value.toggle(event, triggerRef.value)
isOpen.value = !isOpen.value
@@ -128,7 +138,7 @@ const closeDropdown = () => {
}
function handleFileChange(event: Event) {
if (props.disabled) return
if (disabled) return
const target = event.target
if (!(target instanceof HTMLInputElement)) return
if (target.files) {
@@ -138,7 +148,7 @@ function handleFileChange(event: Event) {
}
function handleSelection(item: FormDropdownItem, index: number) {
if (props.disabled) return
if (disabled) return
const sel = selected.value
if (internalIsSelected(item, index)) {
sel.delete(item.id)
@@ -170,11 +180,9 @@ async function customSearcher(
isCleanup = true
cleanupFn?.()
})
await props
.searcher(query, props.items, (cb) => (cleanupFn = cb))
.then((results) => {
if (!isCleanup) filteredItems.value = results
})
await searcher(query, items, (cb) => (cleanupFn = cb)).then((results) => {
if (!isCleanup) filteredItems.value = results
})
}
</script>
@@ -183,7 +191,7 @@ async function customSearcher(
<FormDropdownInput
:files
:is-open
:placeholder
:placeholder="placeholderText"
:items
:max-selectable
:selected

View File

@@ -31,8 +31,8 @@ vi.mock('@/stores/firebaseAuthStore', () => ({
useFirebaseAuthStore: vi.fn(() => mockFirebaseAuthStore)
}))
vi.mock('vue-i18n', () => ({
useI18n: vi.fn(() => mockI18n)
vi.mock('@/i18n', () => ({
d: mockI18n.d
}))
vi.mock('@/utils/typeGuardUtil', () => ({

View File

@@ -1,9 +1,9 @@
import type { AxiosError, AxiosResponse } from 'axios'
import axios from 'axios'
import { ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { getComfyApiBaseUrl } from '@/config/comfyApi'
import { d } from '@/i18n'
import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'
import type { components, operations } from '@/types/comfyRegistryTypes'
import { isAbortError } from '@/utils/typeGuardUtil'
@@ -33,7 +33,6 @@ const customerApiClient = axios.create({
export const useCustomerEventsService = () => {
const isLoading = ref(false)
const error = ref<string | null>(null)
const { d } = useI18n()
watch(
() => getComfyApiBaseUrl(),

View File

@@ -8,12 +8,12 @@ import {
import Splitter from 'primevue/splitter'
import SplitterPanel from 'primevue/splitterpanel'
import { ref, useTemplateRef } from 'vue'
import { useI18n } from 'vue-i18n'
import ModeToggle from '@/components/sidebar/ModeToggle.vue'
import TopbarBadges from '@/components/topbar/TopbarBadges.vue'
import WorkflowTabs from '@/components/topbar/WorkflowTabs.vue'
import TypeformPopoverButton from '@/components/ui/TypeformPopoverButton.vue'
import { t } from '@/i18n'
import type { AssetItem } from '@/platform/assets/schemas/assetSchema'
import { useSettingStore } from '@/platform/settings/settingStore'
import LinearControls from '@/renderer/extensions/linearMode/LinearControls.vue'
@@ -23,6 +23,7 @@ import OutputHistory from '@/renderer/extensions/linearMode/OutputHistory.vue'
import { useNodeOutputStore } from '@/stores/imagePreviewStore'
import type { ResultItemImpl } from '@/stores/queueStore'
const { t } = useI18n()
const nodeOutputStore = useNodeOutputStore()
const settingStore = useSettingStore()

View File

@@ -2,8 +2,8 @@ import { useEventListener, whenever } from '@vueuse/core'
import { defineStore } from 'pinia'
import { v4 as uuidv4 } from 'uuid'
import { ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { t } from '@/i18n'
import { useCachedRequest } from '@/composables/useCachedRequest'
import { useServerLogs } from '@/composables/useServerLogs'
import { api } from '@/scripts/api'
@@ -30,7 +30,6 @@ type UpdateAllPacksParams = components['schemas']['UpdateAllPacksParams']
* Store for state of installed node packs
*/
export const useComfyManagerStore = defineStore('comfyManager', () => {
const { t } = useI18n()
const managerService = useComfyManagerService()
const installedPacks = ref<InstalledPacksResponse>({})