fix(admin): زبان ویرایش از زبان صفحه پیروی کند — ویرایش روی /en دیگر متن فارسی را بازنویسی نمیکند
قبلاً زبان ویرایش (editLang) کلید جداگانهای در نوار ادمین بود که با زبان صفحهٔ در حال نمایش هیچ ارتباطی نداشت و پیشفرضش فارسی میماند؛ نتیجهاش این بود که ویرایش درجا روی صفحههای /en به ستونهای فارسی میرفت و تغییرها «سمت دیگر» یعنی سایت فارسی ظاهر میشدند. - AdminBar: در حالت ویرایش، editLang با زبان URL همگام میشود (syncEditLang)؛ کلید دستی فقط برای ویرایش ستون زبان دیگر روی همین صفحه میماند. - entities: تعریف status-labels اضافه شد — نبودش یعنی ویرایش برچسب وضعیت روی صفحهٔ انگلیسی همیشه ستون فارسی را بازنویسی میکرد.
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import { useState } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import Swal from 'sweetalert2'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { KeyRoundIcon, XIcon } from 'lucide-react'
|
||||
import { useAdmin } from './AdminContext'
|
||||
import { adminApi } from './adminClient'
|
||||
import { useLang } from '../i18n/lang'
|
||||
|
||||
const STATUS_TEXT: Record<string, string> = {
|
||||
idle: 'همگامسازی شد',
|
||||
@@ -127,9 +128,18 @@ function ChangePasswordModal({ onClose }: { onClose: () => void }) {
|
||||
|
||||
/** نوار شناور ادمین — فقط برای کاربر واردشده رندر میشود */
|
||||
export function AdminBar() {
|
||||
const { isEditMode, toggleEditMode, saveStatus, logout, editLang, toggleEditLang, role, canManageSite } = useAdmin()
|
||||
const { isEditMode, toggleEditMode, saveStatus, logout, editLang, toggleEditLang, syncEditLang, role, canManageSite } = useAdmin()
|
||||
const { lang } = useLang()
|
||||
const [pwOpen, setPwOpen] = useState(false)
|
||||
|
||||
// زبان ویرایش از زبان صفحهٔ در حال نمایش پیروی میکند — ویرایش روی /en به ستونهای
|
||||
// انگلیسی میرود و روی صفحات فارسی به فارسی؛ وگرنه ویرایشِ دیدهشده در /en ناخواسته
|
||||
// متن فارسی را بازنویسی میکرد. کلید دستی پایین فقط برای ویرایش ستون زبان دیگر
|
||||
// روی همین صفحه است و با ناوبری بعدی دوباره همگام میشود.
|
||||
useEffect(() => {
|
||||
if (isEditMode) syncEditLang(lang)
|
||||
}, [isEditMode, lang, syncEditLang])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
@@ -167,7 +177,7 @@ export function AdminBar() {
|
||||
<button
|
||||
type="button"
|
||||
onClick={toggleEditLang}
|
||||
title="تعیین میکند ویرایشها روی کدام ستون زبان ذخیره شوند"
|
||||
title="معمولاً خودکار با زبان صفحه همگام میشود — این کلید فقط برای ویرایش ستون زبان دیگر روی همین صفحه است"
|
||||
className={`flex items-center gap-1.5 border px-3 py-1.5 text-xs font-light transition-colors duration-200 ${
|
||||
editLang === 'en'
|
||||
? 'border-copper bg-copper/10 text-copper'
|
||||
|
||||
@@ -28,6 +28,9 @@ interface AdminContextValue {
|
||||
/** زبان محتوایی که در حالت ویرایش ذخیره میشود (فارسی یا انگلیسی) */
|
||||
editLang: EditLang
|
||||
toggleEditLang: () => void
|
||||
/** همگامسازی زبان ویرایش با زبان صفحهٔ در حال نمایش — کلید دستی فقط برای
|
||||
* ویرایش ستون زبان دیگر روی همان صفحه است؛ در ناوبری دوباره از صفحه پیروی میکند */
|
||||
syncEditLang: (lang: EditLang) => void
|
||||
}
|
||||
|
||||
const AdminContext = createContext<AdminContextValue | null>(null)
|
||||
@@ -80,7 +83,7 @@ export function AdminProvider({ children }: { children: ReactNode }) {
|
||||
const [isEditMode, setIsEditMode] = useState<boolean>(
|
||||
() => sessionStorage.getItem('aramesh_edit_mode') === '1',
|
||||
)
|
||||
const [editLang, setEditLang] = useState<EditLang>(
|
||||
const [editLang, setEditLangState] = useState<EditLang>(
|
||||
() => (sessionStorage.getItem('aramesh_edit_lang') === 'en' ? 'en' : 'fa'),
|
||||
)
|
||||
const [saveStatus, setSaveStatus] = useState<SaveStatus>('idle')
|
||||
@@ -94,13 +97,22 @@ export function AdminProvider({ children }: { children: ReactNode }) {
|
||||
}, [])
|
||||
|
||||
const toggleEditLang = useCallback(() => {
|
||||
setEditLang((v) => {
|
||||
setEditLangState((v) => {
|
||||
const next: EditLang = v === 'fa' ? 'en' : 'fa'
|
||||
sessionStorage.setItem('aramesh_edit_lang', next)
|
||||
return next
|
||||
})
|
||||
}, [])
|
||||
|
||||
// بدون بازنویسی انتخاب دستی وقتی مقدار همان است — تا اثر همگامسازی بیدلیل رندر نکند
|
||||
const syncEditLang = useCallback((next: EditLang) => {
|
||||
setEditLangState((v) => {
|
||||
if (v === next) return v
|
||||
sessionStorage.setItem('aramesh_edit_lang', next)
|
||||
return next
|
||||
})
|
||||
}, [])
|
||||
|
||||
const login = useCallback(async (username: string, password: string): Promise<AdminRole> => {
|
||||
await adminApi.login(username, password)
|
||||
const nextRole = roleFromToken(getToken()) ?? 'admin'
|
||||
@@ -194,8 +206,9 @@ export function AdminProvider({ children }: { children: ReactNode }) {
|
||||
runSave,
|
||||
editLang,
|
||||
toggleEditLang,
|
||||
syncEditLang,
|
||||
}),
|
||||
[isAuthenticated, role, canManageSite, isEditMode, toggleEditMode, login, logout, saveStatus, runSave, editLang, toggleEditLang],
|
||||
[isAuthenticated, role, canManageSite, isEditMode, toggleEditMode, login, logout, saveStatus, runSave, editLang, toggleEditLang, syncEditLang],
|
||||
)
|
||||
|
||||
return <AdminContext.Provider value={value}>{children}</AdminContext.Provider>
|
||||
|
||||
@@ -176,6 +176,14 @@ export const ENTITIES: Record<string, EntityConfig> = {
|
||||
fields: [F('label', 'عنوان'), F('href', 'مسیر (مثل /about)', 'text', undefined, true)],
|
||||
defaults: { label: 'آیتم جدید', href: '/' },
|
||||
},
|
||||
'status-labels': {
|
||||
resource: 'status-labels', dataKey: 'status_labels', title: 'برچسبهای وضعیت پروژه', kind: 'collection',
|
||||
titleKey: 'label',
|
||||
// نبودِ این تعریف یعنی isTranslatable همیشه false برمیگشت و ویرایشِ برچسب روی
|
||||
// صفحهٔ انگلیسی بهجای ستون label_en ستون فارسی را بازنویسی میکرد
|
||||
fields: [F('label', 'برچسب'), F('key', 'کلید وضعیت', 'text', 'done یا progress', true)],
|
||||
defaults: { key: 'done', label: 'برچسب جدید' },
|
||||
},
|
||||
seo_meta: {
|
||||
resource: 'seo-meta', dataKey: 'seo_meta', title: 'سئوی صفحه', kind: 'collection',
|
||||
titleKey: 'page_key',
|
||||
|
||||
Reference in New Issue
Block a user