chore: requires languages to be passed to config

This commit is contained in:
James
2024-04-08 16:38:12 -04:00
parent 53d9c4ca95
commit be2134eb69
14 changed files with 94 additions and 194 deletions

View File

@@ -40,7 +40,7 @@ export const RootLayout = async ({
headers,
}) ?? config.i18n.fallbackLanguage
const i18n = await initI18n({ config: config.i18n, context: 'client', language: lang })
const i18n = initI18n({ config: config.i18n, context: 'client', language: lang })
const clientConfig = await createClientConfig({ config, t: i18n.t })
const dir = rtlLanguages.includes(lang) ? 'RTL' : 'LTR'

View File

@@ -71,7 +71,7 @@ export const createPayloadRequest = async ({
headers: request.headers,
})
const i18n = await initI18n({
const i18n = initI18n({
config: config.i18n,
context: 'api',
language,

View File

@@ -6,13 +6,13 @@ import { cookies, headers } from 'next/headers.js'
import { getRequestLanguage } from './getRequestLanguage.js'
export const getNextI18n = async ({
export const getNextI18n = ({
config,
language,
}: {
config: SanitizedConfig
language?: string
}): Promise<I18n> =>
}): I18n =>
initI18n({
config: config.i18n,
context: 'client',

View File

@@ -44,7 +44,7 @@ export const initPage = async ({
const cookies = parseCookies(headers)
const language = getRequestLanguage({ config: payload.config, cookies, headers })
const i18n = await initI18n({
const i18n = initI18n({
config: payload.config.i18n,
context: 'client',
language,

View File

@@ -89,7 +89,7 @@ export const getMetaBySegment: GenerateEditViewMetadata = async ({
}
}
const i18n = await getNextI18n({
const i18n = getNextI18n({
config,
})

View File

@@ -19,7 +19,7 @@ export const generatePageMetadata = async ({
}): Promise<Metadata> => {
const config = await configPromise
const i18n = await getNextI18n({
const i18n = getNextI18n({
config,
})

View File

@@ -49,7 +49,7 @@ export const generatePageMetadata = async ({ config: configPromise, params }: Ar
const isGlobal = segmentOne === 'globals'
const isCollection = segmentOne === 'collections'
const i18n = await getNextI18n({
const i18n = getNextI18n({
config,
})

View File

@@ -1,3 +1,4 @@
import en from '@payloadcms/translations/languages/en'
import merge from 'deepmerge'
import type {
@@ -86,7 +87,9 @@ export const sanitizeConfig = (incomingConfig: Config): SanitizedConfig => {
config.i18n = {
fallbackLanguage: 'en',
supportedLanguages: ['en'],
supportedLanguages: {
en,
},
translations: {},
...(incomingConfig?.i18n ?? {}),
}

View File

@@ -67,7 +67,7 @@ export const LinkFeature: FeatureProviderProviderServer<LinkFeatureServerProps,
enabledCollections: props.enabledCollections,
} as ExclusiveLinkCollectionsProps,
generateSchemaMap: async ({ config, props }) => {
const i18n = await initI18n({ config: config.i18n, context: 'client' })
const i18n = initI18n({ config: config.i18n, context: 'client' })
return {
fields: await transformExtraFields(

View File

@@ -12,8 +12,8 @@ import { uploadFieldsSchemaPath } from './field/elements/upload/shared.js'
export const getGenerateSchemaMap =
(args: AdapterArguments): RichTextAdapter['generateSchemaMap'] =>
async ({ config, schemaMap, schemaPath }) => {
const i18n = await initI18n({ config: config.i18n, context: 'client' })
({ config, schemaMap, schemaPath }) => {
const i18n = initI18n({ config: config.i18n, context: 'client' })
const validRelationships = config.collections.map((c) => c.slug) || []
;(args?.admin?.elements || Object.values(elementTypes)).forEach((el) => {

View File

@@ -22,7 +22,7 @@ export type I18n = {
export type I18nOptions = {
fallbackLanguage?: string
supportedLanguages?: string[]
supportedLanguages?: Translations
translations?: {
[language: string]:
| {
@@ -45,4 +45,4 @@ export type InitI18n = (args: {
config: I18nOptions
context: 'api' | 'client'
language?: string
}) => Promise<I18n>
}) => I18n

View File

@@ -1,174 +0,0 @@
import type { Translations } from '../types.js'
import { clientTranslationKeys } from '../clientKeys.js'
function filterKeys(obj, parentGroupKey = '', keys) {
const result = {}
for (const [namespaceKey, value] of Object.entries(obj)) {
// Skip $schema key
if (namespaceKey === '$schema') {
result[namespaceKey] = value
continue
}
if (typeof value === 'object') {
const filteredObject = filterKeys(value, namespaceKey, keys)
if (Object.keys(filteredObject).length > 0) {
result[namespaceKey] = filteredObject
}
} else {
for (const key of keys) {
const [groupKey, selector] = key.split(':')
if (parentGroupKey === groupKey) {
if (namespaceKey === selector) {
result[selector] = value
} else {
const pluralKeys = ['zero', 'one', 'two', 'few', 'many', 'other']
pluralKeys.forEach((pluralKey) => {
if (namespaceKey === `${selector}_${pluralKey}`) {
result[`${selector}_${pluralKey}`] = value
}
})
}
}
}
}
}
return result
}
function sortObject(obj) {
const sortedObject = {}
Object.keys(obj)
.sort()
.forEach((key) => {
if (typeof obj[key] === 'object') {
sortedObject[key] = sortObject(obj[key])
} else {
sortedObject[key] = obj[key]
}
})
return sortedObject
}
export const dynamicallyImportLanguages = async (
supportedLanguages: string[],
context: 'api' | 'client',
) => {
const languages: Translations = {}
await Promise.all(
supportedLanguages.map(async (supportedLanguage) => {
let imported
switch (supportedLanguage) {
case 'ar':
imported = await import(`@payloadcms/translations/languages/ar`)
break
case 'az':
imported = await import(`@payloadcms/translations/languages/az`)
break
case 'bg':
imported = await import(`@payloadcms/translations/languages/bg`)
break
case 'cs':
imported = await import(`@payloadcms/translations/languages/cs`)
break
case 'de':
imported = await import(`@payloadcms/translations/languages/de`)
break
case 'en':
imported = await import(`@payloadcms/translations/languages/en`)
break
case 'es':
imported = await import(`@payloadcms/translations/languages/es`)
break
case 'fa':
imported = await import(`@payloadcms/translations/languages/fa`)
break
case 'fr':
imported = await import(`@payloadcms/translations/languages/fr`)
break
case 'hr':
imported = await import(`@payloadcms/translations/languages/hr`)
break
case 'hu':
imported = await import(`@payloadcms/translations/languages/hu`)
break
case 'it':
imported = await import(`@payloadcms/translations/languages/it`)
break
case 'ja':
imported = await import(`@payloadcms/translations/languages/ja`)
break
case 'ko':
imported = await import(`@payloadcms/translations/languages/ko`)
break
case 'my':
imported = await import(`@payloadcms/translations/languages/my`)
break
case 'nb':
imported = await import(`@payloadcms/translations/languages/nb`)
break
case 'nl':
imported = await import(`@payloadcms/translations/languages/nl`)
break
case 'pl':
imported = await import(`@payloadcms/translations/languages/pl`)
break
case 'pt':
imported = await import(`@payloadcms/translations/languages/pt`)
break
case 'ro':
imported = await import(`@payloadcms/translations/languages/ro`)
break
case 'rs':
imported = await import(`@payloadcms/translations/languages/rs`)
break
case 'rsLatin':
imported = await import(`@payloadcms/translations/languages/rsLatin`)
break
case 'ru':
imported = await import(`@payloadcms/translations/languages/ru`)
break
case 'sv':
imported = await import(`@payloadcms/translations/languages/sv`)
break
case 'th':
imported = await import(`@payloadcms/translations/languages/th`)
break
case 'tr':
imported = await import(`@payloadcms/translations/languages/tr`)
break
case 'ua':
imported = await import(`@payloadcms/translations/languages/ua`)
break
case 'vi':
imported = await import(`@payloadcms/translations/languages/vi`)
break
case 'zh':
imported = await import(`@payloadcms/translations/languages/zh`)
break
case 'zhTw':
imported = await import(`@payloadcms/translations/languages/zhTw`)
break
}
if (imported) {
if (context === 'client') {
const clientTranslations = sortObject(
filterKeys(imported.default, '', clientTranslationKeys),
)
languages[supportedLanguage] = clientTranslations
} else {
languages[supportedLanguage] = imported.default
}
}
}),
)
return languages
}

View File

@@ -1,7 +1,7 @@
import type { I18n, InitI18n, InitTFunction, Translations } from '../types.js'
import { deepMerge } from './deepMerge.js'
import { dynamicallyImportLanguages } from './dynamicImport.js'
import { reduceLanguages } from './reduceLanguages.js'
/**
* @function getTranslationString
@@ -211,14 +211,14 @@ const initTFunction: InitTFunction = (args) => {
}
}
function memoize(fn: (args: unknown) => Promise<I18n>, keys: string[]) {
function memoize(fn: (args: unknown) => I18n, keys: string[]) {
const cacheMap = new Map()
const memoized = async (args) => {
const memoized = (args) => {
const cacheKey = keys.reduce((acc, key) => acc + args[key], '')
if (!cacheMap.has(cacheKey)) {
const result = await fn(args)
const result = fn(args)
cacheMap.set(cacheKey, result)
}
@@ -229,8 +229,8 @@ function memoize(fn: (args: unknown) => Promise<I18n>, keys: string[]) {
}
export const initI18n: InitI18n = memoize(
async ({ config, context, language = 'en' }: Parameters<InitI18n>[0]) => {
const languages = await dynamicallyImportLanguages(config.supportedLanguages, context)
({ config, context, language = 'en' }: Parameters<InitI18n>[0]) => {
const languages = reduceLanguages(config.supportedLanguages, context)
const { t, translations } = initTFunction({
config,

View File

@@ -0,0 +1,71 @@
import type { Translations } from '../types.js'
import { clientTranslationKeys } from '../clientKeys.js'
function filterKeys(obj, parentGroupKey = '', keys) {
const result = {}
for (const [namespaceKey, value] of Object.entries(obj)) {
// Skip $schema key
if (namespaceKey === '$schema') {
result[namespaceKey] = value
continue
}
if (typeof value === 'object') {
const filteredObject = filterKeys(value, namespaceKey, keys)
if (Object.keys(filteredObject).length > 0) {
result[namespaceKey] = filteredObject
}
} else {
for (const key of keys) {
const [groupKey, selector] = key.split(':')
if (parentGroupKey === groupKey) {
if (namespaceKey === selector) {
result[selector] = value
} else {
const pluralKeys = ['zero', 'one', 'two', 'few', 'many', 'other']
pluralKeys.forEach((pluralKey) => {
if (namespaceKey === `${selector}_${pluralKey}`) {
result[`${selector}_${pluralKey}`] = value
}
})
}
}
}
}
}
return result
}
function sortObject(obj) {
const sortedObject = {}
Object.keys(obj)
.sort()
.forEach((key) => {
if (typeof obj[key] === 'object') {
sortedObject[key] = sortObject(obj[key])
} else {
sortedObject[key] = obj[key]
}
})
return sortedObject
}
export const reduceLanguages = (supportedLanguages: Translations, context: 'api' | 'client') => {
const languages = {}
Object.entries(supportedLanguages).forEach(([lang, translations]) => {
if (context === 'client') {
const clientTranslations = sortObject(filterKeys(translations, '', clientTranslationKeys))
languages[lang] = clientTranslations
} else {
languages[lang] = translations
}
})
return languages
}