Compare commits
8 Commits
feat/lexic
...
fix/locale
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe028f39ee | ||
|
|
4a1bb3c405 | ||
|
|
17425e999e | ||
|
|
2a0d9f1f78 | ||
|
|
c02c0d6fa8 | ||
|
|
3a61b82f9e | ||
|
|
c4d9c90506 | ||
|
|
8e0b9b4aa2 |
@@ -4,7 +4,14 @@ import type { groupNavItems } from '@payloadcms/ui/shared'
|
||||
import type { NavPreferences } from 'payload'
|
||||
|
||||
import { getTranslation } from '@payloadcms/translations'
|
||||
import { BrowseByFolderButton, Link, NavGroup, useConfig, useTranslation } from '@payloadcms/ui'
|
||||
import {
|
||||
BrowseByFolderButton,
|
||||
Link,
|
||||
NavGroup,
|
||||
useConfig,
|
||||
useLocale,
|
||||
useTranslation,
|
||||
} from '@payloadcms/ui'
|
||||
import { EntityType } from '@payloadcms/ui/shared'
|
||||
import { usePathname } from 'next/navigation.js'
|
||||
import { formatAdminURL } from 'payload/shared'
|
||||
@@ -24,12 +31,15 @@ export const DefaultNavClient: React.FC<{
|
||||
routes: { browseByFolder: foldersRoute },
|
||||
},
|
||||
folders,
|
||||
localization,
|
||||
routes: { admin: adminRoute },
|
||||
},
|
||||
} = useConfig()
|
||||
|
||||
const { i18n } = useTranslation()
|
||||
|
||||
const locale = useLocale()
|
||||
|
||||
const folderURL = formatAdminURL({
|
||||
adminRoute,
|
||||
path: foldersRoute,
|
||||
@@ -37,6 +47,8 @@ export const DefaultNavClient: React.FC<{
|
||||
|
||||
const viewingRootFolderView = pathname.startsWith(folderURL)
|
||||
|
||||
const addLocaleToURL = localization && locale.code ? `?locale=${locale.code}` : ''
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{folders && folders.browseByFolder && <BrowseByFolderButton active={viewingRootFolderView} />}
|
||||
@@ -48,12 +60,12 @@ export const DefaultNavClient: React.FC<{
|
||||
let id: string
|
||||
|
||||
if (type === EntityType.collection) {
|
||||
href = formatAdminURL({ adminRoute, path: `/collections/${slug}` })
|
||||
href = `${formatAdminURL({ adminRoute, path: `/collections/${slug}` })}${addLocaleToURL}`
|
||||
id = `nav-${slug}`
|
||||
}
|
||||
|
||||
if (type === EntityType.global) {
|
||||
href = formatAdminURL({ adminRoute, path: `/globals/${slug}` })
|
||||
href = `${formatAdminURL({ adminRoute, path: `/globals/${slug}` })}${addLocaleToURL}`
|
||||
id = `nav-global-${slug}`
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,10 @@ export const initPage = async ({
|
||||
useLayoutReq,
|
||||
}: Args): Promise<InitPageResult> => {
|
||||
const queryString = `${qs.stringify(searchParams ?? {}, { addQueryPrefix: true })}`
|
||||
const query = qs.parse(queryString, {
|
||||
depth: 10,
|
||||
ignoreQueryPrefix: true,
|
||||
})
|
||||
|
||||
const {
|
||||
cookies,
|
||||
@@ -35,10 +39,7 @@ export const initPage = async ({
|
||||
overrides: {
|
||||
fallbackLocale: false,
|
||||
req: {
|
||||
query: qs.parse(queryString, {
|
||||
depth: 10,
|
||||
ignoreQueryPrefix: true,
|
||||
}),
|
||||
query,
|
||||
routeParams,
|
||||
},
|
||||
urlSuffix: `${route}${searchParams ? queryString : ''}`,
|
||||
@@ -46,6 +47,7 @@ export const initPage = async ({
|
||||
})
|
||||
|
||||
const {
|
||||
admin: { routes },
|
||||
collections,
|
||||
globals,
|
||||
routes: { admin: adminRoute },
|
||||
@@ -80,6 +82,12 @@ export const initPage = async ({
|
||||
|
||||
let redirectTo = null
|
||||
|
||||
const logoutPath = `${adminRoute || '/admin'}${routes.logout || '/logout'}`
|
||||
|
||||
if (req?.user && payload.config?.localization && !query.locale && req.pathname !== logoutPath) {
|
||||
redirectTo = `${req.pathname}${queryString ? '&' : '?'}locale=${locale.code}`
|
||||
}
|
||||
|
||||
if (
|
||||
!permissions.canAccessAdmin &&
|
||||
!isPublicAdminRoute({ adminRoute, config: payload.config, route }) &&
|
||||
|
||||
@@ -46,6 +46,7 @@ export function DefaultDashboard(props: DashboardViewServerProps) {
|
||||
admin: {
|
||||
components: { afterDashboard, beforeDashboard },
|
||||
},
|
||||
localization,
|
||||
routes: { admin: adminRoute },
|
||||
},
|
||||
},
|
||||
@@ -55,6 +56,8 @@ export function DefaultDashboard(props: DashboardViewServerProps) {
|
||||
user,
|
||||
} = props
|
||||
|
||||
const addLocaleToURL = localization && locale.code ? `?locale=${locale.code}` : ''
|
||||
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<Gutter className={`${baseClass}__wrap`}>
|
||||
@@ -96,11 +99,14 @@ export function DefaultDashboard(props: DashboardViewServerProps) {
|
||||
|
||||
buttonAriaLabel = t('general:showAllLabel', { label: title })
|
||||
|
||||
href = formatAdminURL({ adminRoute, path: `/collections/${slug}` })
|
||||
href = formatAdminURL({
|
||||
adminRoute,
|
||||
path: `/collections/${slug}${addLocaleToURL}`,
|
||||
})
|
||||
|
||||
createHREF = formatAdminURL({
|
||||
adminRoute,
|
||||
path: `/collections/${slug}/create`,
|
||||
path: `/collections/${slug}/create${addLocaleToURL}`,
|
||||
})
|
||||
|
||||
hasCreatePermission = permissions?.collections?.[slug]?.create
|
||||
@@ -115,7 +121,7 @@ export function DefaultDashboard(props: DashboardViewServerProps) {
|
||||
|
||||
href = formatAdminURL({
|
||||
adminRoute,
|
||||
path: `/globals/${slug}`,
|
||||
path: `/globals/${slug}${addLocaleToURL}`,
|
||||
})
|
||||
|
||||
// Find the lock status for the global
|
||||
|
||||
@@ -5,6 +5,7 @@ import React, { useEffect, useRef, useState } from 'react'
|
||||
import { Account } from '../../graphics/Account/index.js'
|
||||
import { useActions } from '../../providers/Actions/index.js'
|
||||
import { useConfig } from '../../providers/Config/index.js'
|
||||
import { useLocale } from '../../providers/Locale/index.js'
|
||||
import { useTranslation } from '../../providers/Translation/index.js'
|
||||
import { Hamburger } from '../Hamburger/index.js'
|
||||
import { Link } from '../Link/index.js'
|
||||
@@ -37,6 +38,8 @@ export function AppHeader({ CustomAvatar, CustomIcon }: Props) {
|
||||
},
|
||||
} = useConfig()
|
||||
|
||||
const locale = useLocale()
|
||||
|
||||
const { navOpen } = useNav()
|
||||
|
||||
const customControlsRef = useRef<HTMLDivElement>(null)
|
||||
@@ -61,6 +64,8 @@ export function AppHeader({ CustomAvatar, CustomIcon }: Props) {
|
||||
|
||||
const ActionComponents = Actions ? Object.values(Actions) : []
|
||||
|
||||
const addLocaleToURL = localization && locale.code ? `?locale=${locale.code}` : ''
|
||||
|
||||
return (
|
||||
<header className={[baseClass, navOpen && `${baseClass}--nav-open`].filter(Boolean).join(' ')}>
|
||||
<div className={`${baseClass}__bg`} />
|
||||
@@ -96,7 +101,7 @@ export function AppHeader({ CustomAvatar, CustomIcon }: Props) {
|
||||
<Link
|
||||
aria-label={t('authentication:account')}
|
||||
className={`${baseClass}__account`}
|
||||
href={formatAdminURL({ adminRoute, path: accountRoute })}
|
||||
href={formatAdminURL({ adminRoute, path: accountRoute }) + addLocaleToURL}
|
||||
prefetch={false}
|
||||
tabIndex={0}
|
||||
>
|
||||
|
||||
@@ -5,6 +5,7 @@ import './index.scss'
|
||||
import { Link } from '../../elements/Link/index.js'
|
||||
import { useConfig } from '../../providers/Config/index.js'
|
||||
import { useDocumentInfo } from '../../providers/DocumentInfo/index.js'
|
||||
import { useLocale } from '../../providers/Locale/index.js'
|
||||
import { formatAdminURL } from '../../utilities/formatAdminURL.js'
|
||||
import { sanitizeID } from '../../utilities/sanitizeID.js'
|
||||
import { useDrawerDepth } from '../Drawer/index.js'
|
||||
@@ -18,17 +19,21 @@ export const IDLabel: React.FC<{ className?: string; id: string; prefix?: string
|
||||
}) => {
|
||||
const {
|
||||
config: {
|
||||
localization,
|
||||
routes: { admin: adminRoute },
|
||||
},
|
||||
} = useConfig()
|
||||
|
||||
const { collectionSlug, globalSlug } = useDocumentInfo()
|
||||
const drawerDepth = useDrawerDepth()
|
||||
const locale = useLocale()
|
||||
|
||||
const docPath = formatAdminURL({
|
||||
adminRoute,
|
||||
path: `/${collectionSlug ? `collections/${collectionSlug}` : `globals/${globalSlug}`}/${id}`,
|
||||
})
|
||||
const addLocaleToURL = localization && locale.code ? `?locale=${locale.code}` : ''
|
||||
const docPath =
|
||||
formatAdminURL({
|
||||
adminRoute,
|
||||
path: `/${collectionSlug ? `collections/${collectionSlug}` : `globals/${globalSlug}`}/${id}`,
|
||||
}) + addLocaleToURL
|
||||
|
||||
return (
|
||||
<div className={[baseClass, className].filter(Boolean).join(' ')} title={id}>
|
||||
|
||||
@@ -6,6 +6,7 @@ import { fieldAffectsData, fieldIsID } from 'payload/shared'
|
||||
import React from 'react' // TODO: abstract this out to support all routers
|
||||
|
||||
import { useConfig } from '../../../providers/Config/index.js'
|
||||
import { useLocale } from '../../../providers/Locale/index.js'
|
||||
import { useTranslation } from '../../../providers/Translation/index.js'
|
||||
import { formatAdminURL } from '../../../utilities/formatAdminURL.js'
|
||||
import { getDisplayedFieldValue } from '../../../utilities/getDisplayedFieldValue.js'
|
||||
@@ -31,6 +32,7 @@ export const DefaultCell: React.FC<DefaultCellComponentProps> = (props) => {
|
||||
|
||||
const {
|
||||
config: {
|
||||
localization,
|
||||
routes: { admin: adminRoute },
|
||||
},
|
||||
getEntityConfig,
|
||||
@@ -38,6 +40,8 @@ export const DefaultCell: React.FC<DefaultCellComponentProps> = (props) => {
|
||||
|
||||
const collectionConfig = getEntityConfig({ collectionSlug })
|
||||
|
||||
const locale = useLocale()
|
||||
|
||||
const classNameFromConfigContext = admin && 'className' in admin ? admin.className : undefined
|
||||
|
||||
const className =
|
||||
@@ -59,14 +63,16 @@ export const DefaultCell: React.FC<DefaultCellComponentProps> = (props) => {
|
||||
className,
|
||||
}
|
||||
|
||||
const addLocaleToURL = localization && locale.code ? `?locale=${locale.code}` : ''
|
||||
|
||||
if (link) {
|
||||
wrapElementProps.prefetch = false
|
||||
WrapElement = Link
|
||||
wrapElementProps.href = collectionConfig?.slug
|
||||
? formatAdminURL({
|
||||
adminRoute,
|
||||
path: `/collections/${collectionConfig?.slug}${viewType === 'trash' ? '/trash' : ''}/${encodeURIComponent(rowData.id)}`,
|
||||
})
|
||||
adminRoute,
|
||||
path: `/collections/${collectionConfig?.slug}${viewType === 'trash' ? '/trash' : ''}/${encodeURIComponent(rowData.id)}${addLocaleToURL}`,
|
||||
})
|
||||
: ''
|
||||
}
|
||||
|
||||
|
||||
@@ -657,6 +657,27 @@ describe('Localization', () => {
|
||||
await expect(searchInput).toHaveAttribute('placeholder', 'Search by Full title')
|
||||
})
|
||||
|
||||
test('should not persist locale after back navigation', async () => {
|
||||
await changeLocale(page, defaultLocale)
|
||||
await page.goto(url.create)
|
||||
await page.locator('#field-title').fill(title)
|
||||
await saveDocAndAssert(page)
|
||||
|
||||
await changeLocale(page, spanishLocale)
|
||||
await page.goBack()
|
||||
await page.reload()
|
||||
const localeLabel = page.locator('.localizer-button__current-label').first()
|
||||
|
||||
await expect
|
||||
.poll(
|
||||
async () => {
|
||||
return await localeLabel.textContent()
|
||||
},
|
||||
{ timeout: 3000 },
|
||||
)
|
||||
.toContain('English')
|
||||
})
|
||||
|
||||
describe('publish specific locale', () => {
|
||||
test('should create post in correct locale with publishSpecificLocale', async () => {
|
||||
await page.goto(urlPostsWithDrafts.create)
|
||||
|
||||
Reference in New Issue
Block a user