refactor(editor): Extract @n8n/i18n package for internationalization (no-changelog) (#15466)

This commit is contained in:
Alex Grozav
2025-05-30 11:44:33 +02:00
committed by GitHub
parent bbe2b12bf2
commit e704077864
408 changed files with 1002 additions and 767 deletions

View File

@@ -5,6 +5,7 @@ import { Service } from '@n8n/di';
import { createHash } from 'crypto';
import type { NextFunction, Response } from 'express';
import { JsonWebTokenError, TokenExpiredError } from 'jsonwebtoken';
import type { StringValue as TimeUnitValue } from 'ms';
import { Logger } from 'n8n-core';
import config from '@/config';
@@ -180,7 +181,7 @@ export class AuthService {
return user;
}
generatePasswordResetToken(user: User, expiresIn = '20m') {
generatePasswordResetToken(user: User, expiresIn: TimeUnitValue = '20m') {
const payload: PasswordResetToken = { sub: user.id, hash: this.createJWTHash(user) };
return this.jwtService.sign(payload, { expiresIn });
}

View File

@@ -1,5 +1,6 @@
import { Container, Service } from '@n8n/di';
import jwt from 'jsonwebtoken';
import type { StringValue as TimeUnitValue } from 'ms';
import { BINARY_ENCODING, UnexpectedError } from 'n8n-workflow';
import type { INodeExecutionData, IBinaryData } from 'n8n-workflow';
import { readFile, stat } from 'node:fs/promises';
@@ -45,7 +46,7 @@ export class BinaryDataService {
}
}
createSignedToken(binaryData: IBinaryData, expiresIn = '1 day') {
createSignedToken(binaryData: IBinaryData, expiresIn: TimeUnitValue = '1 day') {
if (!binaryData.id) {
throw new UnexpectedError('URL signing is not available in memory mode');
}

View File

@@ -4,6 +4,7 @@ import FileType from 'file-type';
import { IncomingMessage } from 'http';
import iconv from 'iconv-lite';
import { extension, lookup } from 'mime-types';
import type { StringValue as TimeUnitValue } from 'ms';
import type {
BinaryHelperFunctions,
IBinaryData,
@@ -279,7 +280,7 @@ export const getBinaryHelperFunctions = (
getBinaryMetadata,
binaryToBuffer,
binaryToString,
createBinarySignedUrl(binaryData: IBinaryData, expiresIn?: string) {
createBinarySignedUrl(binaryData: IBinaryData, expiresIn?: TimeUnitValue) {
const token = Container.get(BinaryDataService).createSignedToken(binaryData, expiresIn);
return `${restApiUrl}/binary-data/signed?token=${token}`;
},

View File

@@ -1,7 +1,7 @@
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['src/**/*.ts', '!src/**/*.test.ts', '!src/**/*.d.ts', '!src/__tests__**/*'],
entry: ['src/**/*.ts', '!src/**/*.test.ts', '!src/**/*.d.ts', '!src/__tests__/**/*'],
format: ['cjs', 'esm'],
clean: true,
dts: true,

View File

@@ -0,0 +1,10 @@
const sharedOptions = require('@n8n/eslint-config/shared');
/**
* @type {import('@types/eslint').ESLint.ConfigData}
*/
module.exports = {
extends: ['@n8n/eslint-config/frontend'],
...sharedOptions(__dirname, 'frontend'),
};

24
packages/frontend/@n8n/i18n/.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@@ -0,0 +1,27 @@
# @n8n/i18n
A package for managing internationalization (i18n) in n8n's Frontend codebase. It provides a structured way to handle translations and localization, ensuring that the application can be easily adapted to different languages and regions.
## Table of Contents
- [Features](#features)
- [Contributing](#contributing)
- [License](#license)
## Features
- **Translation Management**: Simplifies the process of managing translations for different languages.
- **Localization Support**: Provides tools to adapt the application for different regions and cultures.
- **Easy Integration**: Seamlessly integrates with n8n's Frontend codebase, making it easy to implement and use.
- **Reusable Base Text**: Allows for the definition of reusable base text strings, reducing redundancy in translations.
- **Pluralization and Interpolation**: Supports pluralization and interpolation in base text strings, making it flexible for various use cases.
- **Versioned Nodes Support**: Facilitates the management of translations for nodes in versioned directories, ensuring consistency across different versions.
- **Documentation**: Comprehensive documentation to help developers understand and utilize the package effectively.
## Contributing
For more details, please read our [CONTRIBUTING.md](CONTRIBUTING.md).
## License
For more details, please read our [LICENSE.md](LICENSE.md).

View File

@@ -0,0 +1,4 @@
{
"$schema": "../../../../node_modules/@biomejs/biome/configuration_schema.json",
"extends": ["../../../../biome.jsonc"]
}

View File

Before

Width:  |  Height:  |  Size: 857 KiB

After

Width:  |  Height:  |  Size: 857 KiB

View File

Before

Width:  |  Height:  |  Size: 253 KiB

After

Width:  |  Height:  |  Size: 253 KiB

View File

Before

Width:  |  Height:  |  Size: 161 KiB

After

Width:  |  Height:  |  Size: 161 KiB

View File

Before

Width:  |  Height:  |  Size: 239 KiB

After

Width:  |  Height:  |  Size: 239 KiB

View File

Before

Width:  |  Height:  |  Size: 344 KiB

After

Width:  |  Height:  |  Size: 344 KiB

View File

Before

Width:  |  Height:  |  Size: 296 KiB

After

Width:  |  Height:  |  Size: 296 KiB

View File

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

View File

@@ -0,0 +1,60 @@
{
"name": "@n8n/i18n",
"type": "module",
"version": "1.0.0",
"files": [
"dist"
],
"main": "dist/index.cjs",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
},
"./*": {
"types": "./dist/*.d.ts",
"import": "./dist/*.js",
"require": "./dist/*.cjs"
}
},
"scripts": {
"dev": "vite",
"build": "pnpm run typecheck && tsup",
"preview": "vite preview",
"typecheck": "vue-tsc --noEmit",
"test": "vitest run",
"test:dev": "vitest --silent=false",
"lint": "eslint src --ext .js,.ts,.vue --quiet",
"lintfix": "eslint src --ext .js,.ts,.vue --fix",
"format": "biome format --write . && prettier --write . --ignore-path ../../../../.prettierignore",
"format:check": "biome ci . && prettier --check . --ignore-path ../../../../.prettierignore"
},
"dependencies": {
"n8n-workflow": "workspace:*",
"vue-i18n": "catalog:frontend"
},
"devDependencies": {
"@n8n/eslint-config": "workspace:*",
"@n8n/typescript-config": "workspace:*",
"@n8n/vitest-config": "workspace:*",
"@testing-library/jest-dom": "catalog:frontend",
"@testing-library/user-event": "catalog:frontend",
"@testing-library/vue": "catalog:frontend",
"@vitejs/plugin-vue": "catalog:frontend",
"@vue/tsconfig": "catalog:frontend",
"@vueuse/core": "catalog:frontend",
"vue": "catalog:frontend",
"tsup": "catalog:",
"typescript": "catalog:frontend",
"vite": "catalog:frontend",
"vitest": "catalog:frontend",
"vue-tsc": "catalog:frontend"
},
"peerDependencies": {
"vue": "catalog:frontend"
},
"license": "See LICENSE.md file in the root of the repository"
}

View File

@@ -1,13 +1,9 @@
import axios from 'axios';
import { createI18n } from 'vue-i18n';
import { locale } from '@n8n/design-system';
/* eslint-disable @typescript-eslint/no-this-alias */
import type { INodeProperties, INodePropertyCollection, INodePropertyOptions } from 'n8n-workflow';
import { createI18n } from 'vue-i18n';
import type { INodeTranslationHeaders } from '@/Interface';
import { useUIStore } from '@/stores/ui.store';
import { useNDVStore } from '@/stores/ndv.store';
import { useRootStore } from '@n8n/stores/useRootStore';
import englishBaseText from './locales/en.json';
import type { BaseTextKey, INodeTranslationHeaders } from './types';
import {
deriveMiddleKey,
isNestedInCollectionLike,
@@ -15,6 +11,8 @@ import {
insertOptionsAndValues,
} from './utils';
export * from './types';
export const i18nInstance = createI18n({
locale: 'en',
fallbackLocale: 'en',
@@ -118,9 +116,7 @@ export class I18nClass {
/**
* Namespace for methods to render text in the credentials details modal.
*/
credText() {
const uiStore = useUIStore();
const credentialType = uiStore.activeCredentialType;
credText(credentialType: string | null) {
const credentialPrefix = `n8n-nodes-base.credentials.${credentialType}`;
const context = this;
@@ -204,10 +200,8 @@ export class I18nClass {
* Namespace for methods to render text in the node details view,
* except for `eventTriggerDescription`.
*/
nodeText() {
const ndvStore = useNDVStore();
const activeNode = ndvStore.activeNode;
const nodeType = activeNode ? this.shortNodeType(activeNode.type) : ''; // unused in eventTriggerDescription
nodeText(activeNodeType?: string | null) {
const nodeType = activeNodeType ? this.shortNodeType(activeNodeType) : ''; // unused in eventTriggerDescription
const initialKey = `n8n-nodes-base.nodes.${nodeType}.nodeView`;
const context = this;
@@ -355,10 +349,8 @@ export class I18nClass {
};
}
localizeNodeName(nodeName: string, type: string) {
const isEnglishLocale = useRootStore().defaultLocale === 'en';
if (isEnglishLocale) return nodeName;
localizeNodeName(language: string, nodeName: string, type: string) {
if (language === 'en') return nodeName;
const nodeTypeName = this.shortNodeType(type);
@@ -377,12 +369,8 @@ const loadedLanguages = ['en'];
async function setLanguage(language: string) {
i18nInstance.global.locale = language as 'en';
axios.defaults.headers.common['Accept-Language'] = language;
document!.querySelector('html')!.setAttribute('lang', language);
// update n8n design system and element ui
await locale.use(language);
return language;
}
@@ -449,14 +437,6 @@ export function addHeaders(headers: INodeTranslationHeaders, language: string) {
export const i18n: I18nClass = new I18nClass();
// ----------------------------------
// typings
// ----------------------------------
type GetBaseTextKey<T> = T extends `_${string}` ? never : T;
export type BaseTextKey = GetBaseTextKey<keyof typeof englishBaseText>;
type GetCategoryName<T> = T extends `nodeCreator.categoryNames.${infer C}` ? C : never;
export type CategoryName = GetCategoryName<keyof typeof englishBaseText>;
export function useI18n() {
return i18n;
}

View File

@@ -0,0 +1,5 @@
/// <reference types="vite/client" />
export {};
declare module '*.json';

View File

@@ -0,0 +1,18 @@
import type englishBaseText from './locales/en.json';
export type GetBaseTextKey<T> = T extends `_${string}` ? never : T;
export type BaseTextKey = GetBaseTextKey<keyof typeof englishBaseText>;
export type GetCategoryName<T> = T extends `nodeCreator.categoryNames.${infer C}` ? C : never;
export type CategoryName = GetCategoryName<keyof typeof englishBaseText>;
export interface INodeTranslationHeaders {
data: {
[key: string]: {
displayName: string;
description: string;
};
};
}

View File

@@ -0,0 +1,12 @@
{
"extends": "@n8n/typescript-config/tsconfig.frontend.json",
"compilerOptions": {
"baseUrl": ".",
"rootDir": ".",
"outDir": "dist",
"types": ["vite/client", "vitest/globals"],
"isolatedModules": true,
"resolveJsonModule": true
},
"include": ["src/**/*.ts", "src/**/*.vue", "vite.config.ts", "tsup.config.ts"]
}

View File

@@ -0,0 +1,11 @@
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['src/**/*.ts', '!src/**/*.test.ts', '!src/**/*.d.ts', '!src/__tests__/**/*'],
format: ['cjs', 'esm'],
clean: true,
dts: true,
cjsInterop: true,
splitting: true,
sourcemap: true,
});

View File

@@ -0,0 +1,4 @@
import { defineConfig, mergeConfig } from 'vite';
import { vitestConfig } from '@n8n/vitest-config/frontend';
export default mergeConfig(defineConfig({}), vitestConfig);

View File

@@ -1,7 +1,7 @@
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['src/**/*.ts', '!src/**/*.test.ts', '!src/**/*.d.ts', '!src/__tests__**/*'],
entry: ['src/**/*.ts', '!src/**/*.test.ts', '!src/**/*.d.ts', '!src/__tests__/**/*'],
format: ['cjs', 'esm'],
clean: true,
dts: true,

View File

@@ -37,6 +37,7 @@
"@n8n/codemirror-lang-sql": "^1.0.2",
"@n8n/composables": "workspace:*",
"@n8n/design-system": "workspace:*",
"@n8n/i18n": "workspace:*",
"@n8n/permissions": "workspace:*",
"@n8n/stores": "workspace:*",
"@n8n/utils": "workspace:*",
@@ -84,7 +85,7 @@
"vue-agile": "^2.0.0",
"vue-chartjs": "^5.2.0",
"vue-github-button": "^3.1.3",
"vue-i18n": "^11.1.2",
"vue-i18n": "catalog:frontend",
"vue-json-pretty": "2.2.4",
"vue-markdown-render": "catalog:frontend",
"vue-router": "catalog:frontend",

View File

@@ -9,7 +9,7 @@ import Modals from '@/components/Modals.vue';
import Telemetry from '@/components/Telemetry.vue';
import AskAssistantFloatingButton from '@/components/AskAssistant/Chat/AskAssistantFloatingButton.vue';
import AssistantsHub from '@/components/AskAssistant/AssistantsHub.vue';
import { loadLanguage } from '@/plugins/i18n';
import { loadLanguage } from '@n8n/i18n';
import { APP_MODALS_ELEMENT_ID, HIRING_BANNER, VIEWS } from '@/constants';
import { useRootStore } from '@n8n/stores/useRootStore';
import { useAssistantStore } from '@/stores/assistant.store';
@@ -19,6 +19,8 @@ import { useUsersStore } from '@/stores/users.store';
import { useSettingsStore } from '@/stores/settings.store';
import { useHistoryHelper } from '@/composables/useHistoryHelper';
import { useStyles } from './composables/useStyles';
import { locale } from '@n8n/design-system';
import axios from 'axios';
const route = useRoute();
const rootStore = useRootStore();
@@ -79,9 +81,15 @@ watch(route, (r) => {
);
});
watch(defaultLocale, (newLocale) => {
void loadLanguage(newLocale);
});
watch(
defaultLocale,
(newLocale) => {
void loadLanguage(newLocale);
void locale.use(newLocale);
axios.defaults.headers.common['Accept-Language'] = newLocale;
},
{ immediate: true },
);
</script>
<template>

View File

@@ -178,15 +178,6 @@ export interface INodeTypesMaxCount {
};
}
export interface INodeTranslationHeaders {
data: {
[key: string]: {
displayName: string;
description: string;
};
};
}
export interface IAiDataContent {
data: INodeExecutionData[] | null;
inOut: 'input' | 'output';

View File

@@ -1,6 +1,6 @@
import type { Plugin } from 'vue';
import { render } from '@testing-library/vue';
import { i18nInstance } from '@/plugins/i18n';
import { i18nInstance } from '@n8n/i18n';
import { GlobalComponentsPlugin } from '@/plugins/components';
import { GlobalDirectivesPlugin } from '@/plugins/directives';
import { FontAwesomePlugin } from '@/plugins/icons';

View File

@@ -1,5 +1,3 @@
import type { INodeTranslationHeaders, IRestApiContext } from '@/Interface';
import { makeRestApiRequest } from '@/utils/apiUtils';
import type {
ActionResultRequestDto,
CommunityNodeType,
@@ -7,6 +5,9 @@ import type {
ResourceLocatorRequestDto,
ResourceMapperFieldsRequestDto,
} from '@n8n/api-types';
import { makeRestApiRequest } from '@/utils/apiUtils';
import type { IRestApiContext } from '@/Interface';
import type { INodeTranslationHeaders } from '@n8n/i18n';
import axios from 'axios';
import {
type INodeListSearchResult,

View File

@@ -6,7 +6,7 @@ import { useRootStore } from '@n8n/stores/useRootStore';
import { useToast } from '@/composables/useToast';
import { useClipboard } from '@/composables/useClipboard';
import { useDebugInfo } from '@/composables/useDebugInfo';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
const modalBus = createEventBus();
const toast = useToast();

View File

@@ -15,7 +15,7 @@ import { useNodeTypesStore } from '@/stores/nodeTypes.store';
import { useStorage } from '@/composables/useStorage';
import { useExecutionsStore } from '@/stores/executions.store';
import { useRouter } from 'vue-router';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
const checked = ref(false);

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
const i18n = useI18n();
defineProps<{

View File

@@ -1,6 +1,6 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import type { ApiKey } from '@n8n/api-types';
import { DateTime } from 'luxon';

View File

@@ -4,12 +4,12 @@ import { API_KEY_CREATE_OR_EDIT_MODAL_KEY, EnterpriseEditionFeature } from '@/co
import { computed, onMounted, ref } from 'vue';
import { useUIStore } from '@/stores/ui.store';
import { createEventBus } from '@n8n/utils/event-bus';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { useRootStore } from '@n8n/stores/useRootStore';
import { useDocumentTitle } from '@/composables/useDocumentTitle';
import { useApiKeysStore } from '@/stores/apiKeys.store';
import { useToast } from '@/composables/useToast';
import type { BaseTextKey } from '@/plugins/i18n';
import type { BaseTextKey } from '@n8n/i18n';
import { N8nText } from '@n8n/design-system';
import { DateTime } from 'luxon';
import type { ApiKey, ApiKeyWithRawValue, CreateApiKeyRequestDto } from '@n8n/api-types';

View File

@@ -3,7 +3,7 @@ import { ref, computed, watch } from 'vue';
// eslint-disable-next-line import/no-extraneous-dependencies
import { ElSelect, ElOption, ElOptionGroup } from 'element-plus';
import { capitalCase } from 'change-case';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { usePageRedirectionHelper } from '@/composables/usePageRedirectionHelper';
// Define props

View File

@@ -27,7 +27,8 @@ vi.mock('@/composables/useTelemetry', () => ({
}));
// Mock i18n
vi.mock('@/composables/useI18n', () => ({
vi.mock('@n8n/i18n', async (importOriginal) => ({
...(await importOriginal()),
useI18n: () => ({
baseText: (key: string) => key,
}),

View File

@@ -7,7 +7,7 @@ import { useTelemetry } from '@/composables/useTelemetry';
import type { IWorkflowDataUpdate } from '@/Interface';
import { nodeViewEventBus } from '@/event-bus';
import { v4 as uuid } from 'uuid';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { STICKY_NODE_TYPE } from '@/constants';
const emit = defineEmits<{

View File

@@ -5,7 +5,7 @@ import { computed } from 'vue';
import AskAssistantChat from '@n8n/design-system/components/AskAssistantChat/AskAssistantChat.vue';
import { useTelemetry } from '@/composables/useTelemetry';
import { useBuilderStore } from '@/stores/builder.store';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
const emit = defineEmits<{
close: [];

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { useStyles } from '@/composables/useStyles';
import { useAssistantStore } from '@/stores/assistant.store';
import { useLogsStore } from '@/stores/logs.store';

View File

@@ -3,7 +3,7 @@ import { NEW_ASSISTANT_SESSION_MODAL } from '@/constants';
import Modal from '@/components/Modal.vue';
import AssistantIcon from '@n8n/design-system/components/AskAssistantIcon/AssistantIcon.vue';
import AssistantText from '@n8n/design-system/components/AskAssistantText/AssistantText.vue';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { useUIStore } from '@/stores/ui.store';
import type { ChatRequest } from '@/types/assistant.types';
import { useAssistantStore } from '@/stores/assistant.store';

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { computed } from 'vue';
defineProps<{

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import { useDebounce } from '@/composables/useDebounce';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { useNDVStore } from '@/stores/ndv.store';
import type {
AssignmentCollectionValue,

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import { useI18n } from '@/composables/useI18n';
import type { BaseTextKey } from '@/plugins/i18n';
import { useI18n } from '@n8n/i18n';
import type { BaseTextKey } from '@n8n/i18n';
import { ASSIGNMENT_TYPES } from './constants';
import { computed } from 'vue';

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { useTelemetry } from '@/composables/useTelemetry';
import { useBecomeTemplateCreatorStore } from './becomeTemplateCreatorStore';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
const i18n = useI18n();
const store = useBecomeTemplateCreatorStore();

View File

@@ -4,7 +4,7 @@ import type { IBinaryData, IRunData } from 'n8n-workflow';
import BinaryDataDisplayEmbed from '@/components/BinaryDataDisplayEmbed.vue';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { useNodeHelpers } from '@/composables/useNodeHelpers';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
const props = defineProps<{
displayData: IBinaryData;

View File

@@ -5,7 +5,7 @@ import type { IBinaryData } from 'n8n-workflow';
import { jsonParse } from 'n8n-workflow';
import VueJsonPretty from 'vue-json-pretty';
import RunDataHtml from '@/components/RunDataHtml.vue';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
const props = defineProps<{
binaryData: IBinaryData;

View File

@@ -7,7 +7,6 @@ import { useNDVStore } from '@/stores/ndv.store';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { usePostHog } from '@/stores/posthog.store';
import { useRootStore } from '@n8n/stores/useRootStore';
import { useI18n } from '@/composables/useI18n';
import { useToast } from '@/composables/useToast';
import type { INodeProperties } from 'n8n-workflow';
@@ -16,7 +15,16 @@ vi.mock('@/stores/workflows.store');
vi.mock('@/stores/posthog.store');
vi.mock('@n8n/stores/useRootStore');
vi.mock('@/api/ai');
vi.mock('@/composables/useI18n');
vi.mock('@n8n/i18n', async (importOriginal) => ({
...(await importOriginal()),
useI18n: () => ({
baseText: vi.fn().mockReturnValue('Mocked Text'),
nodeText: () => ({
inputLabelDisplayName: vi.fn().mockReturnValue('Mocked Display Name'),
inputLabelDescription: vi.fn().mockReturnValue('Mocked Description'),
}),
}),
}));
vi.mock('@/composables/useToast');
describe('ButtonParameter', () => {
@@ -66,14 +74,6 @@ describe('ButtonParameter', () => {
pushRef: 'testPushRef',
} as any);
vi.mocked(useI18n).mockReturnValue({
baseText: vi.fn().mockReturnValue('Mocked Text'),
nodeText: () => ({
inputLabelDisplayName: vi.fn().mockReturnValue('Mocked Display Name'),
inputLabelDescription: vi.fn().mockReturnValue('Mocked Description'),
}),
} as any);
vi.mocked(useToast).mockReturnValue({
showMessage: vi.fn(),
} as any);

View File

@@ -3,7 +3,7 @@ import { type INodeProperties, type NodePropertyAction } from 'n8n-workflow';
import type { INodeUi, IUpdateInformation } from '@/Interface';
import { ref, computed, onMounted } from 'vue';
import { N8nButton, N8nInput, N8nTooltip } from '@n8n/design-system/components';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { useToast } from '@/composables/useToast';
import { useNDVStore } from '@/stores/ndv.store';
import {
@@ -31,7 +31,8 @@ export type Props = {
};
const props = defineProps<Props>();
const { activeNode } = useNDVStore();
const ndvStore = useNDVStore();
const activeNode = computed(() => ndvStore.activeNode);
const i18n = useI18n();
@@ -57,7 +58,7 @@ const isSubmitEnabled = computed(() => {
return true;
});
const promptUpdated = computed(() => {
const lastPrompt = activeNode?.parameters[AI_TRANSFORM_CODE_GENERATED_FOR_PROMPT] as string;
const lastPrompt = activeNode.value?.parameters[AI_TRANSFORM_CODE_GENERATED_FOR_PROMPT] as string;
if (!lastPrompt) return false;
return lastPrompt.trim() !== prompt.value.trim();
});
@@ -81,7 +82,7 @@ async function onSubmit() {
const action: string | NodePropertyAction | undefined =
props.parameter.typeOptions?.buttonConfig?.action;
if (!action || !activeNode) return;
if (!action || !activeNode.value) return;
if (typeof action === 'string') {
switch (action) {
@@ -196,8 +197,8 @@ async function updateCursorPositionOnMouseMove(event: MouseEvent, activeDrop: bo
<div>
<n8n-input-label
v-if="hasInputField"
:label="i18n.nodeText().inputLabelDisplayName(parameter, path)"
:tooltip-text="i18n.nodeText().inputLabelDescription(parameter, path)"
:label="i18n.nodeText(activeNode?.type).inputLabelDisplayName(parameter, path)"
:tooltip-text="i18n.nodeText(activeNode?.type).inputLabelDescription(parameter, path)"
:bold="false"
size="small"
color="text-dark"

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import type { INode, Workflow } from 'n8n-workflow';
import RunDataAi from '@/components/RunDataAi/RunDataAi.vue';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
defineProps<{
node: INode | null;

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import type { ChatMessage, ChatMessageText } from '@n8n/chat/types';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import MessagesList from '@n8n/chat/components/MessagesList.vue';
import MessageOptionTooltip from './MessageOptionTooltip.vue';
import MessageOptionAction from './MessageOptionAction.vue';

View File

@@ -15,7 +15,7 @@ import { useToast } from '@/composables/useToast';
import { useMessage } from '@/composables/useMessage';
import { usePinnedData } from '@/composables/usePinnedData';
import { MODAL_CONFIRM } from '@/constants';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import type { IExecutionPushResponse, INodeUi } from '@/Interface';
import { extractBotResponse, getInputKey } from '@/components/CanvasChat/utils';

View File

@@ -1,7 +1,7 @@
import type { RunWorkflowChatPayload } from '@/components/CanvasChat/composables/useChatMessaging';
import { useChatMessaging } from '@/components/CanvasChat/composables/useChatMessaging';
import { useChatTrigger } from '@/components/CanvasChat/composables/useChatTrigger';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { useNodeHelpers } from '@/composables/useNodeHelpers';
import { useRunWorkflow } from '@/composables/useRunWorkflow';
import { VIEWS } from '@/constants';

View File

@@ -8,7 +8,7 @@ import {
type LogDetailsPanelState,
} from '@/components/CanvasChat/types/logs';
import NodeIcon from '@/components/NodeIcon.vue';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
import LogsViewNodeName from '@/components/CanvasChat/future/components/LogsViewNodeName.vue';
import {

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import LogsPanelHeader from '@/components/CanvasChat/future/components/LogsPanelHeader.vue';
import { useClearExecutionButtonVisible } from '@/composables/useClearExecutionButtonVisible';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { N8nButton, N8nRadioButtons, N8nText, N8nTooltip } from '@n8n/design-system';
import { computed, nextTick, toRef, watch } from 'vue';
import LogsOverviewRow from '@/components/CanvasChat/future/components/LogsOverviewRow.vue';

View File

@@ -3,7 +3,7 @@ import { computed, nextTick, useTemplateRef, watch } from 'vue';
import { N8nButton, N8nIcon, N8nIconButton, N8nText } from '@n8n/design-system';
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
import { upperFirst } from 'lodash-es';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import LogsViewConsumedTokenCountText from '@/components/CanvasChat/future/components/LogsViewConsumedTokenCountText.vue';
import { I18nT } from 'vue-i18n';
import { toDayMonth, toTime } from '@/utils/formatters/dateFormatter';

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import KeyboardShortcutTooltip from '@/components/KeyboardShortcutTooltip.vue';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { useStyles } from '@/composables/useStyles';
import { N8nActionDropdown, N8nIconButton } from '@n8n/design-system';
import { computed } from 'vue';

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import { formatTokenUsageCount } from '@/components/RunDataAi/utils';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { type LlmTokenUsageData } from '@/Interface';
import { N8nTooltip } from '@n8n/design-system';

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import LogsViewConsumedTokenCountText from '@/components/CanvasChat/future/components/LogsViewConsumedTokenCountText.vue';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { type LlmTokenUsageData } from '@/Interface';
import { N8nText } from '@n8n/design-system';
import { useTimestamp } from '@vueuse/core';

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import RunData from '@/components/RunData.vue';
import { type LogEntry } from '@/components/RunDataAi/utils';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { type IRunDataDisplayMode, type NodePanelType } from '@/Interface';
import { useNDVStore } from '@/stores/ndv.store';
import { waitingNodeTooltip } from '@/utils/executionUtils';

View File

@@ -7,7 +7,7 @@ import { useUsersStore } from '@/stores/users.store';
import { createFormEventBus } from '@n8n/design-system/utils';
import { createEventBus } from '@n8n/utils/event-bus';
import type { IFormInputs, IFormInput } from '@/Interface';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
const config = ref<IFormInputs | null>(null);
const formBus = createFormEventBus();

View File

@@ -8,7 +8,7 @@ import { useRootStore } from '@n8n/stores/useRootStore';
import { useWorkflowsStore } from '@/stores/workflows.store';
import HtmlEditor from '@/components/HtmlEditor/HtmlEditor.vue';
import JsEditor from '@/components/JsEditor/JsEditor.vue';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
const props = withDefaults(
defineProps<{

View File

@@ -7,12 +7,12 @@ import { N8nButton, N8nInput, N8nTooltip } from '@n8n/design-system/components';
import { randomInt } from 'n8n-workflow';
import type { CodeExecutionMode, INodeExecutionData } from 'n8n-workflow';
import type { BaseTextKey } from '@/plugins/i18n';
import type { BaseTextKey } from '@n8n/i18n';
import type { INodeUi, Schema } from '@/Interface';
import { generateCodeForPrompt } from '@/api/ai';
import { useTelemetry } from '@/composables/useTelemetry';
import { useDataSchema } from '@/composables/useDataSchema';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { useMessage } from '@/composables/useMessage';
import { useToast } from '@/composables/useToast';
import { useNDVStore } from '@/stores/ndv.store';

View File

@@ -11,7 +11,7 @@ import { codeNodeEditorEventBus } from '@/event-bus';
import { useRootStore } from '@n8n/stores/useRootStore';
import { useCodeEditor } from '@/composables/useCodeEditor';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { useMessage } from '@/composables/useMessage';
import { useTelemetry } from '@/composables/useTelemetry';
import AskAI from './AskAI/AskAI.vue';

View File

@@ -4,7 +4,7 @@ import type { Completion, CompletionContext, CompletionResult } from '@codemirro
import type { INodeUi } from '@/Interface';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { escapeMappingString } from '@/utils/mappingUtils';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
function getAutoCompletableNodeNames(nodes: INodeUi[]) {
return nodes

View File

@@ -1,6 +1,6 @@
import { addInfoRenderer, addVarType, escape } from '../utils';
import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
export function useExecutionCompletions() {
const i18n = useI18n();

View File

@@ -1,6 +1,6 @@
import { addInfoRenderer, addVarType, escape } from '../utils';
import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
export function useItemFieldCompletions(language: 'python' | 'javaScript') {
const i18n = useI18n();

View File

@@ -1,4 +1,4 @@
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
import type { CodeExecutionMode } from 'n8n-workflow';
import { toValue, type MaybeRefOrGetter } from 'vue';

View File

@@ -3,7 +3,7 @@ import type { Completion, CompletionContext, CompletionResult } from '@codemirro
import { useWorkflowsStore } from '@/stores/workflows.store';
import { useNDVStore } from '@/stores/ndv.store';
import { isAllowedInDotNotation } from '@/plugins/codemirror/completions/utils';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import type { IPinData, IRunData, IDataObject } from 'n8n-workflow';
function useJsonFieldCompletions() {

View File

@@ -1,6 +1,6 @@
import { addVarType } from '../utils';
import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
const DEFAULT_MATCHER = '$prevNode';

View File

@@ -1,6 +1,6 @@
import { addVarType } from '../utils';
import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
const escape = (str: string) => str.replace('$', '\\$');

View File

@@ -6,7 +6,7 @@ import type { Node, MemberExpression } from 'estree';
import type { CodeExecutionMode, CodeNodeEditorLanguage } from 'n8n-workflow';
import { computed, toValue, type MaybeRefOrGetter } from 'vue';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import {
DEFAULT_LINTER_DELAY_IN_MS,
DEFAULT_LINTER_SEVERITY,

View File

@@ -14,7 +14,8 @@ import { get } from 'lodash-es';
import { useNDVStore } from '@/stores/ndv.store';
import { useNodeHelpers } from '@/composables/useNodeHelpers';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { storeToRefs } from 'pinia';
const selectedOption = ref<string | undefined>(undefined);
export interface Props {
@@ -34,9 +35,11 @@ const ndvStore = useNDVStore();
const i18n = useI18n();
const nodeHelpers = useNodeHelpers();
const { activeNode } = storeToRefs(ndvStore);
const getPlaceholderText = computed(() => {
return (
i18n.nodeText().placeholder(props.parameter, props.path) ??
i18n.nodeText(activeNode.value?.type).placeholder(props.parameter, props.path) ??
i18n.baseText('collectionParameter.choose')
);
});
@@ -51,7 +54,9 @@ function getParameterOptionLabel(
item: INodePropertyOptions | INodeProperties | INodePropertyCollection,
): string {
if (isNodePropertyCollection(item)) {
return i18n.nodeText().collectionOptionDisplayName(props.parameter, item, props.path);
return i18n
.nodeText(activeNode.value?.type)
.collectionOptionDisplayName(props.parameter, item, props.path);
}
return 'displayName' in item ? item.displayName : item.name;

View File

@@ -2,7 +2,7 @@
import { useUIStore } from '@/stores/ui.store';
import type { PublicInstalledPackage } from 'n8n-workflow';
import { NPM_PACKAGE_DOCS_BASE_URL, COMMUNITY_PACKAGE_MANAGE_ACTIONS } from '@/constants';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { useTelemetry } from '@/composables/useTelemetry';
import { useSettingsStore } from '@/stores/settings.store';

View File

@@ -11,7 +11,7 @@ import { useToast } from '@/composables/useToast';
import { useCommunityNodesStore } from '@/stores/communityNodes.store';
import { ref } from 'vue';
import { useTelemetry } from '@/composables/useTelemetry';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
const communityNodesStore = useCommunityNodesStore();

View File

@@ -4,7 +4,7 @@ import { COMMUNITY_PACKAGE_CONFIRM_MODAL_KEY, COMMUNITY_PACKAGE_MANAGE_ACTIONS }
import { useToast } from '@/composables/useToast';
import { useCommunityNodesStore } from '@/stores/communityNodes.store';
import { createEventBus } from '@n8n/utils/event-bus';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { useTelemetry } from '@/composables/useTelemetry';
import { computed, ref } from 'vue';
import { useNodeTypesStore } from '@/stores/nodeTypes.store';

View File

@@ -5,7 +5,7 @@ import type { Validatable, IValidator } from '@n8n/design-system';
import { N8nFormInput } from '@n8n/design-system';
import { VALID_EMAIL_REGEX, COMMUNITY_PLUS_DOCS_URL } from '@/constants';
import Modal from '@/components/Modal.vue';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { useToast } from '@/composables/useToast';
import { useUsageStore } from '@/stores/usage.store';
import { useTelemetry } from '@/composables/useTelemetry';

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import { formatTokenUsageCount } from '@/components/RunDataAi/utils';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { type LlmTokenUsageData } from '@/Interface';
import { N8nText } from '@n8n/design-system';

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import { useClipboard } from '@/composables/useClipboard';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { useToast } from '@/composables/useToast';
type Props = {

View File

@@ -10,7 +10,7 @@ import { useCredentialsStore } from '@/stores/credentials.store';
import TimeAgo from '@/components/TimeAgo.vue';
import { useProjectsStore } from '@/stores/projects.store';
import ProjectCardBadge from '@/components/Projects/ProjectCardBadge.vue';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { ResourceType } from '@/utils/projects.utils';
import type { CredentialsResource } from './layouts/ResourcesListLayout.vue';

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import ParameterInputFull from '@/components/ParameterInputFull.vue';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import type { IUpdateInformation, NodeAuthenticationOption } from '@/Interface';
import { useNDVStore } from '@/stores/ndv.store';
import { useNodeTypesStore } from '@/stores/nodeTypes.store';

View File

@@ -11,7 +11,7 @@ import type {
import type { IUpdateInformation } from '@/Interface';
import AuthTypeSelector from '@/components/CredentialEdit/AuthTypeSelector.vue';
import EnterpriseEdition from '@/components/EnterpriseEdition.ee.vue';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { useTelemetry } from '@/composables/useTelemetry';
import {
BUILTIN_CREDENTIALS_DOCS_URL,
@@ -20,7 +20,7 @@ import {
NEW_ASSISTANT_SESSION_MODAL,
} from '@/constants';
import type { PermissionsRecord } from '@/permissions';
import { addCredentialTranslation } from '@/plugins/i18n';
import { addCredentialTranslation } from '@n8n/i18n';
import { useCredentialsStore } from '@/stores/credentials.store';
import { useNDVStore } from '@/stores/ndv.store';
import { useRootStore } from '@n8n/stores/useRootStore';

View File

@@ -42,7 +42,7 @@ import { assert } from '@n8n/utils/assert';
import { createEventBus } from '@n8n/utils/event-bus';
import { useExternalHooks } from '@/composables/useExternalHooks';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { useTelemetry } from '@/composables/useTelemetry';
import { useProjectsStore } from '@/stores/projects.store';
import { isExpression, isTestableExpression } from '@/utils/expressions';

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import TimeAgo from '../TimeAgo.vue';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import type { ICredentialsDecryptedResponse, ICredentialsResponse } from '@/Interface';
import { N8nText } from '@n8n/design-system';

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import type { AllRolesMap } from '@n8n/permissions';
import ProjectSharing from '@/components/Projects/ProjectSharing.vue';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { usePageRedirectionHelper } from '@/composables/usePageRedirectionHelper';
import { EnterpriseEditionFeature } from '@/constants';
import type { ICredentialsDecryptedResponse, ICredentialsResponse } from '@/Interface';

View File

@@ -1,7 +1,7 @@
<script lang="ts" setup>
import { useUIStore } from '@/stores/ui.store';
import { useRootStore } from '@n8n/stores/useRootStore';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
const { baseUrl } = useRootStore();
const type = useUIStore().appliedTheme === 'dark' ? '.dark.png' : '.png';

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import GoogleAuthButton from './GoogleAuthButton.vue';
defineProps<{

View File

@@ -4,7 +4,7 @@ import { listenForModalChanges, useUIStore } from '@/stores/ui.store';
import { listenForCredentialChanges, useCredentialsStore } from '@/stores/credentials.store';
import { assert } from '@n8n/utils/assert';
import CredentialsDropdown from './CredentialsDropdown.vue';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { CREDENTIAL_EDIT_MODAL_KEY } from '@/constants';
const props = defineProps<{

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
export type CredentialOption = {
id: string;

View File

@@ -6,7 +6,7 @@ import NodeCredentials from '@/components/NodeCredentials.vue';
import { useCredentialsStore } from '@/stores/credentials.store';
import { N8nOption, N8nSelect } from '@n8n/design-system';
import type { INodeUi, INodeUpdatePropertiesInformation } from '@/Interface';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
type Props = {
activeCredentialType: string;

View File

@@ -9,7 +9,7 @@ import { createEventBus } from '@n8n/utils/event-bus';
import { onMounted, ref } from 'vue';
import { CREDENTIAL_SELECT_MODAL_KEY } from '../constants';
import Modal from './Modal.vue';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
const externalHooks = useExternalHooks();
const telemetry = useTelemetry();

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import Modal from '@/components/Modal.vue';
const props = defineProps<{

View File

@@ -7,7 +7,7 @@ import { useUsersStore } from '@/stores/users.store';
import { useProjectsStore } from '@/stores/projects.store';
import { createEventBus } from '@n8n/utils/event-bus';
import type { ProjectSharingData } from '@/types/projects.types';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
const props = defineProps<{
modalName: string;

View File

@@ -11,7 +11,7 @@ import { createEventBus, type EventBus } from '@n8n/utils/event-bus';
import { useCredentialsStore } from '@/stores/credentials.store';
import { useWorkflowHelpers } from '@/composables/useWorkflowHelpers';
import { useRouter } from 'vue-router';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { useTelemetry } from '@/composables/useTelemetry';
const props = defineProps<{

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { computed } from 'vue';
import { useClipboard } from '@/composables/useClipboard';
import { useToast } from '@/composables/useToast';
@@ -17,7 +17,7 @@ import type {
} from 'n8n-workflow';
import { sanitizeHtml } from '@/utils/htmlUtils';
import { MAX_DISPLAY_DATA_SIZE, NEW_ASSISTANT_SESSION_MODAL } from '@/constants';
import type { BaseTextKey } from '@/plugins/i18n';
import type { BaseTextKey } from '@n8n/i18n';
import { useAssistantStore } from '@/stores/assistant.store';
import type { ChatRequest } from '@/types/assistant.types';
import InlineAskAssistantButton from '@n8n/design-system/components/InlineAskAssistantButton/InlineAskAssistantButton.vue';

View File

@@ -2,7 +2,7 @@
import type { TestRunRecord } from '@/api/evaluation.ee';
import MetricsChart from '@/components/Evaluations.ee/ListRuns/MetricsChart.vue';
import TestRunsTable from '@/components/Evaluations.ee/ListRuns/TestRunsTable.vue';
import { useI18n } from '@/composables/useI18n';
import { useI18n } from '@n8n/i18n';
import { VIEWS } from '@/constants';
import { convertToDisplayDate } from '@/utils/formatters/dateFormatter';
import { computed } from 'vue';

Some files were not shown because too many files have changed in this diff Show More