Files
dify/web/test/i18n-mock.ts
Stephen Zhou 36e840cd87
Some checks failed
autofix.ci / autofix (push) Has been cancelled
Build and Push API & Web / build (api, {{defaultContext}}:api, Dockerfile, DIFY_API_IMAGE_NAME, linux/amd64, ubuntu-latest, build-api-amd64) (push) Has been cancelled
Build and Push API & Web / build (api, {{defaultContext}}:api, Dockerfile, DIFY_API_IMAGE_NAME, linux/arm64, ubuntu-24.04-arm, build-api-arm64) (push) Has been cancelled
Build and Push API & Web / build (web, {{defaultContext}}, web/Dockerfile, DIFY_WEB_IMAGE_NAME, linux/amd64, ubuntu-latest, build-web-amd64) (push) Has been cancelled
Build and Push API & Web / build (web, {{defaultContext}}, web/Dockerfile, DIFY_WEB_IMAGE_NAME, linux/arm64, ubuntu-24.04-arm, build-web-arm64) (push) Has been cancelled
Build and Push API & Web / create-manifest (api, DIFY_API_IMAGE_NAME, merge-api-images) (push) Has been cancelled
Build and Push API & Web / create-manifest (web, DIFY_WEB_IMAGE_NAME, merge-web-images) (push) Has been cancelled
Main CI Pipeline / Skip Duplicate Checks (push) Has been cancelled
Main CI Pipeline / Check Changed Files (push) Has been cancelled
Main CI Pipeline / Run API Tests (push) Has been cancelled
Main CI Pipeline / Skip API Tests (push) Has been cancelled
Main CI Pipeline / API Tests (push) Has been cancelled
Main CI Pipeline / Run Web Tests (push) Has been cancelled
Main CI Pipeline / Skip Web Tests (push) Has been cancelled
Main CI Pipeline / Web Tests (push) Has been cancelled
Main CI Pipeline / Run Web Full-Stack E2E (push) Has been cancelled
Main CI Pipeline / Skip Web Full-Stack E2E (push) Has been cancelled
Main CI Pipeline / Web Full-Stack E2E (push) Has been cancelled
Main CI Pipeline / Style Check (push) Has been cancelled
Main CI Pipeline / Run VDB Tests (push) Has been cancelled
Main CI Pipeline / Skip VDB Tests (push) Has been cancelled
Main CI Pipeline / VDB Tests (push) Has been cancelled
Main CI Pipeline / Run DB Migration Test (push) Has been cancelled
Main CI Pipeline / Skip DB Migration Test (push) Has been cancelled
Main CI Pipeline / DB Migration Test (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
chore: knip fix (#34481)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-04-02 15:03:42 +00:00

91 lines
2.6 KiB
TypeScript

import * as React from 'react'
import { vi } from 'vitest'
type TranslationMap = Record<string, string | string[]>
/**
* Create a t function with optional custom translations
* Checks translations[key] first, then translations[ns.key], then returns ns.key as fallback
*/
function createTFunction(translations: TranslationMap, defaultNs?: string) {
return (key: string, options?: Record<string, unknown>) => {
// Check custom translations first (without namespace)
if (translations[key] !== undefined)
return translations[key]
const ns = (options?.ns as string | undefined) ?? defaultNs
const fullKey = ns ? `${ns}.${key}` : key
// Check custom translations with namespace
if (translations[fullKey] !== undefined)
return translations[fullKey]
// Serialize params (excluding ns) for test assertions
const params = { ...options }
delete params.ns
const suffix = Object.keys(params).length > 0 ? `:${JSON.stringify(params)}` : ''
return `${fullKey}${suffix}`
}
}
/**
* Create useTranslation mock with optional custom translations
*
* Caches t functions by defaultNs so the same reference is returned
* across renders, preventing infinite re-render loops when components
* include t in useEffect/useMemo dependency arrays.
*
* @example
* vi.mock('react-i18next', () => createUseTranslationMock({
* 'operation.confirm': 'Confirm',
* }))
*/
function createUseTranslationMock(translations: TranslationMap = {}) {
const tCache = new Map<string, ReturnType<typeof createTFunction>>()
const i18n = {
language: 'en',
changeLanguage: vi.fn(),
}
return {
useTranslation: (defaultNs?: string) => {
const cacheKey = defaultNs ?? ''
if (!tCache.has(cacheKey))
tCache.set(cacheKey, createTFunction(translations, defaultNs))
return {
t: tCache.get(cacheKey)!,
i18n,
}
},
}
}
/**
* Create Trans component mock with optional custom translations
*/
function createTransMock(translations: TranslationMap = {}) {
return {
Trans: ({ i18nKey, children }: {
i18nKey: string
children?: React.ReactNode
}) => {
const text = translations[i18nKey] ?? i18nKey
return React.createElement('span', { 'data-i18n-key': i18nKey }, children ?? text)
},
}
}
/**
* Create complete react-i18next mock (useTranslation + Trans)
*
* @example
* vi.mock('react-i18next', () => createReactI18nextMock({
* 'modal.title': 'My Modal',
* }))
*/
export function createReactI18nextMock(translations: TranslationMap = {}) {
return {
...createUseTranslationMock(translations),
...createTransMock(translations),
}
}