perf: ensure unnecessary config translations are not sent to the client (#10524)

This will reduce the size of the initial HTML
This commit is contained in:
Alessio Gravili
2025-01-15 13:22:32 -07:00
committed by GitHub
parent 813e70be1f
commit 3fb6ac3ca4
5 changed files with 31 additions and 24 deletions

View File

@@ -1,5 +1,5 @@
import type { AcceptedLanguages } from '@payloadcms/translations' import type { AcceptedLanguages } from '@payloadcms/translations'
import type { ImportMap, SanitizedConfig, ServerFunctionClient } from 'payload' import type { ImportMap, LanguageOptions, SanitizedConfig, ServerFunctionClient } from 'payload'
import { rtlLanguages } from '@payloadcms/translations' import { rtlLanguages } from '@payloadcms/translations'
import { RootProvider } from '@payloadcms/ui' import { RootProvider } from '@payloadcms/ui'
@@ -60,19 +60,18 @@ export const RootLayout = async ({
? 'RTL' ? 'RTL'
: 'LTR' : 'LTR'
const languageOptions = Object.entries(config.i18n.supportedLanguages || {}).reduce( const languageOptions: LanguageOptions = Object.entries(
(acc, [language, languageConfig]) => { config.i18n.supportedLanguages || {},
if (Object.keys(config.i18n.supportedLanguages).includes(language)) { ).reduce((acc, [language, languageConfig]) => {
acc.push({ if (Object.keys(config.i18n.supportedLanguages).includes(language)) {
label: languageConfig.translations.general.thisLanguage, acc.push({
value: language, label: languageConfig.translations.general.thisLanguage,
}) value: language,
} })
}
return acc return acc
}, }, [])
[],
)
async function switchLanguageServerAction(lang: string): Promise<void> { async function switchLanguageServerAction(lang: string): Promise<void> {
'use server' 'use server'

View File

@@ -26,6 +26,7 @@ export type ServerOnlyRootProperties = keyof Pick<
| 'endpoints' | 'endpoints'
| 'graphQL' | 'graphQL'
| 'hooks' | 'hooks'
| 'i18n'
| 'jobs' | 'jobs'
| 'logger' | 'logger'
| 'onInit' | 'onInit'
@@ -44,7 +45,6 @@ export type ClientConfig = {
collections: ClientCollectionConfig[] collections: ClientCollectionConfig[]
custom?: Record<string, any> custom?: Record<string, any>
globals: ClientGlobalConfig[] globals: ClientGlobalConfig[]
i18n?: Omit<SanitizedConfig['i18n'], 'supportedLanguages'>
} & Omit<SanitizedConfig, 'admin' | 'collections' | 'globals' | 'i18n' | ServerOnlyRootProperties> } & Omit<SanitizedConfig, 'admin' | 'collections' | 'globals' | 'i18n' | ServerOnlyRootProperties>
export const serverOnlyAdminConfigProperties: readonly Partial<ServerOnlyRootAdminProperties>[] = [] export const serverOnlyAdminConfigProperties: readonly Partial<ServerOnlyRootAdminProperties>[] = []
@@ -59,6 +59,7 @@ export const serverOnlyConfigProperties: readonly Partial<ServerOnlyRootProperti
'secret', 'secret',
'hooks', 'hooks',
'bin', 'bin',
'i18n',
'typescript', 'typescript',
'cors', 'cors',
'csrf', 'csrf',
@@ -122,12 +123,6 @@ export const createClientConfig = ({
importMap, importMap,
}) })
break break
case 'i18n':
clientConfig.i18n = {
fallbackLanguage: config.i18n.fallbackLanguage,
translations: config.i18n.translations,
}
break
case 'localization': case 'localization':
if (typeof config.localization === 'object' && config.localization) { if (typeof config.localization === 'object' && config.localization) {
clientConfig.localization = {} clientConfig.localization = {}

View File

@@ -1,5 +1,5 @@
'use client' 'use client'
import type { I18nClient, Language } from '@payloadcms/translations' import type { I18nClient, I18nOptions, Language } from '@payloadcms/translations'
import type { import type {
ClientConfig, ClientConfig,
LanguageOptions, LanguageOptions,
@@ -38,7 +38,7 @@ type Props = {
readonly children: React.ReactNode readonly children: React.ReactNode
readonly config: ClientConfig readonly config: ClientConfig
readonly dateFNSKey: Language['dateFNSKey'] readonly dateFNSKey: Language['dateFNSKey']
readonly fallbackLang: ClientConfig['i18n']['fallbackLanguage'] readonly fallbackLang: I18nOptions['fallbackLanguage']
readonly isNavOpen?: boolean readonly isNavOpen?: boolean
readonly languageCode: string readonly languageCode: string
readonly languageOptions: LanguageOptions readonly languageOptions: LanguageOptions

View File

@@ -4,11 +4,12 @@ import type {
ClientTranslationKeys, ClientTranslationKeys,
ClientTranslationsObject, ClientTranslationsObject,
I18nClient, I18nClient,
I18nOptions,
Language, Language,
TFunction, TFunction,
} from '@payloadcms/translations' } from '@payloadcms/translations'
import type { Locale } from 'date-fns' import type { Locale } from 'date-fns'
import type { ClientConfig, LanguageOptions } from 'payload' import type { LanguageOptions } from 'payload'
import { importDateFNSLocale, t } from '@payloadcms/translations' import { importDateFNSLocale, t } from '@payloadcms/translations'
import { enUS } from 'date-fns/locale/en-US' import { enUS } from 'date-fns/locale/en-US'
@@ -47,7 +48,7 @@ const Context = createContext<ContextType<any, any>>({
type Props = { type Props = {
children: React.ReactNode children: React.ReactNode
dateFNSKey: Language['dateFNSKey'] dateFNSKey: Language['dateFNSKey']
fallbackLang: ClientConfig['i18n']['fallbackLanguage'] fallbackLang: I18nOptions['fallbackLanguage']
language: string language: string
languageOptions: LanguageOptions languageOptions: LanguageOptions
switchLanguageServerAction: (lang: string) => Promise<void> switchLanguageServerAction: (lang: string) => Promise<void>

View File

@@ -1278,6 +1278,18 @@ describe('lexicalMain', () => {
}) })
describe('localization', () => { describe('localization', () => {
test('ensure lexical translations from other languages do not get sent to the client', async () => {
await navigateToLexicalFields()
// Now check if the html contains "Comience a escribir"
const htmlContent = await page.content()
// Check if the HTML contains "Comience a escribir"
expect(htmlContent).not.toContain('Comience a escribir')
expect(htmlContent).not.toContain('Beginne zu tippen oder')
expect(htmlContent).not.toContain('Cargando...')
expect(htmlContent).toContain('Start typing, or press')
})
test.skip('ensure simple localized lexical field works', async () => { test.skip('ensure simple localized lexical field works', async () => {
await navigateToLexicalFields(true, true) await navigateToLexicalFields(true, true)
}) })