آموزش وردپرس

تاریخ شمسی در وردپرس بدون افزونه: کد امن برای سایت

مهسا مظفری
تاریخ شمسی در وردپرس بدون افزونه: کد امن برای سایت

برای تاریخ شمسی در وردپرس بدون افزونه کافی است یک فیلتر روی تابع نمایش تاریخ وردپرس بگذارید و تبدیل را به کلاس تقویم خود PHP (IntlDateFormatter) بسپارید. تاریخی که در دیتابیس ذخیره شده دست نمی‌خورد، پس با برداشتن کد همه‌چیز همان‌طور که بود برمی‌گردد.

این راه برای تاریخ نوشته‌ها، دیدگاه‌ها و هر جای دیگری از سایت که قالب تاریخ نشان می‌دهد کافی است. اگر فروشگاه ووکامرس دارید و پیشخوان و گزارش‌های فروش را هم شمسی می‌خواهید، بخش «این کد کجا نمی‌رسد؟» را ببینید. آنجا گفته‌ایم از کجا به بعد ابزار آماده می‌صرفد.

پیش از کد: تاریخ را در دیتابیس عوض نکنید

در بعضی انجمن‌ها پیشنهاد شده ستون‌های تاریخ جدول نوشته‌ها و دیدگاه‌ها را با یک اسکریپت به شمسی تبدیل کنید. این کار را نکنید.

وردپرس با همان تاریخ میلادی ذخیره‌شده نوشته‌ها را مرتب می‌کند، نوشته‌ی زمان‌بندی‌شده را سر وقت منتشر می‌کند، فید و نقشه‌ی سایت می‌سازد و بایگانی ماهانه را می‌چیند. افزونه‌های دیگر، از افزونه‌ی سئو تا ووکامرس، هم همین مقدار را می‌خوانند و انتظار دارند میلادی باشد. تاریخی مثل 1405-08-06 در ستونی که وردپرس میلادی فرضش می‌کند یعنی نوشته‌ای که از نظر سیستم حدود ۶۲۰ سال پیش منتشر شده.

راه امن این است که تاریخ فقط موقع نمایش شمسی شود. دیتابیس میلادی می‌ماند، همه‌ی سیستم‌ها درست کار می‌کنند، و اگر روزی کد را برداشتید چیزی برای برگرداندن نمانده است. قالب همین سایت هم تاریخ نوشته‌ها را به همین شکل، در نمایش و بدون افزونه، شمسی می‌کند.

کد را کجا بگذارید که پاک نشود؟

بیشتر آموزش‌ها می‌گویند کد را در functions.php قالب بگذارید. این ساده‌ترین جاست و بدترین جا هم هست:

کجابا به‌روزرسانی قالببا عوض کردن قالبمناسب برای
functions.php قالب اصلیپاک می‌شوداز کار می‌افتدهیچ‌وقت
functions.php قالب فرزندمی‌مانداز کار می‌افتدکسی که قالب فرزند دارد و قالب را عوض نمی‌کند
افزونه‌ی اجباری (mu-plugin)می‌ماندمی‌ماندپیشنهاد ما
افزونه‌های «قطعه‌کد»می‌ماندمی‌ماندکسی که به فایل‌های هاست دسترسی ندارد (ولی این هم یک افزونه است)

افزونه‌ی اجباری یک فایل PHP معمولی است که در پوشه‌ی wp-content/mu-plugins/ قرار می‌گیرد. وردپرس هر فایل این پوشه را خودکار اجرا می‌کند و از پیشخوان نمی‌شود خاموشش کرد. با به‌روزرسانی هیچ قالب و افزونه‌ای هم پاک نمی‌شود. ساختنش سه قدم دارد:

  1. با مدیر فایل هاست یا FTP به پوشه‌ی wp-content بروید. اگر پوشه‌ی mu-plugins نیست، آن را بسازید.
  2. یک فایل به اسم jalali-date.php در آن بسازید.
  3. کد بخش بعد را در آن بگذارید و ذخیره کنید. لازم نیست چیزی را فعال کنید.

بعد از ذخیره، در پیشخوان در افزونه‌ها، زبانه‌ی لازم پیدا می‌شود و فایل شما آنجا فهرست شده است.

زبانه‌ی افزونه‌های لازم در پیشخوان وردپرس با افزونه‌ی Jalali Date

کد تاریخ شمسی وردپرس

این کد را عینا در wp-content/mu-plugins/jalali-date.php بگذارید:

<?php
/**
 * Plugin Name: Jalali Date
 * Description: Shows dates in the Persian (Jalali) calendar. Stored dates are not changed.
 */

if ( ! class_exists( 'IntlDateFormatter' ) ) {
	return; // PHP intl extension is missing: do nothing.
}

add_filter( 'wp_date', 'rk_jalali_wp_date', 10, 4 );

function rk_jalali_wp_date( $date, $format, $timestamp, $timezone ) {
	// The admin area stays Gregorian.
	if ( is_admin() ) {
		return $date;
	}

	// Machine-readable formats stay Gregorian (datetime attributes, schema).
	$machine = array( 'c', 'r', 'U', 'G', DATE_W3C, DATE_RFC2822, 'Y-m-d', 'Y-m-d H:i:s' );
	if ( in_array( $format, $machine, true ) ) {
		return $date;
	}

	$map = array(
		'Y' => 'yyyy', 'y' => 'yy',
		'm' => 'MM', 'n' => 'M', 'F' => 'MMMM', 'M' => 'MMM',
		'd' => 'dd', 'j' => 'd',
		'l' => 'EEEE', 'D' => 'EEE',
		'H' => 'HH', 'G' => 'H', 'h' => 'hh', 'g' => 'h',
		'i' => 'mm', 's' => 'ss', 'a' => 'a', 'A' => 'a',
	);

	// PHP date format to ICU pattern; any other character stays as text.
	$pattern = '';
	$text    = '';
	$len     = strlen( $format );
	for ( $i = 0; $i < $len; $i++ ) {
		$char = $format[ $i ];
		if ( '\\' === $char && $i + 1 < $len ) {
			$text .= $format[ ++$i ];
		} elseif ( isset( $map[ $char ] ) ) {
			if ( '' !== $text ) {
				$pattern .= "'" . str_replace( "'", "''", $text ) . "'";
				$text     = '';
			}
			$pattern .= $map[ $char ];
		} else {
			$text .= $char;
		}
	}
	if ( '' !== $text ) {
		$pattern .= "'" . str_replace( "'", "''", $text ) . "'";
	}

	$formatter = new IntlDateFormatter(
		'fa_IR@calendar=persian',
		IntlDateFormatter::NONE,
		IntlDateFormatter::NONE,
		$timezone ? $timezone : wp_timezone(),
		IntlDateFormatter::TRADITIONAL,
		$pattern
	);

	$jalali = $formatter->format( (int) $timestamp );

	return false === $jalali ? $date : $jalali;
}
تاریخ شمسی در وردپرس بدون افزونه در فهرست نوشته‌ها پس از گذاشتن کد

کد چهار کار می‌کند:

اول چک می‌کند افزونه‌ی intl روی سرور هست. تبدیل تقویم کار همین افزونه‌ی PHP است. اگر نباشد، کد بی‌صدا کنار می‌رود و سایت با همان تاریخ میلادی بالا می‌ماند. هیچ صفحه‌ی سفیدی در کار نیست.

روی فیلتر wp_date می‌نشیند. از وردپرس ۵٫۳ به بعد تقریبا همه‌ی تاریخ‌هایی که قالب نشان می‌دهد از تابع wp_date می‌گذرند: تاریخ نوشته، تاریخ دیدگاه، بلوک «تاریخ نوشته» در قالب‌های بلوکی، و تابع قدیمی‌تر date_i18n که خودش wp_date را صدا می‌زند. یک فیلتر همه‌ی این‌ها را می‌گیرد.

قالب‌های ماشینی را میلادی پس می‌دهد. این همان قسمتی است که در کدهای آماده‌ی دیگر نیست. قالب‌ها برای ویژگی datetime در تگ <time> معمولا تاریخ را با قالب c می‌گیرند (مثلا بلوک «آخرین نوشته‌ها» در خود وردپرس). این تاریخ برای موتور جست‌وجوست و باید میلادی و استاندارد بماند. خروجی کد برای قالب c همان 2026-10-28T14:30:00+03:30 است.

سورس صفحه با ویژگی datetime میلادی در کنار تاریخ شمسی نمایشی

در پیشخوان کاری نمی‌کند. فهرست نوشته‌ها و تنظیمات وردپرس میلادی می‌مانند. اگر پیشخوان را هم شمسی می‌خواهید، شرط is_admin() را بردارید. ولی جدول بخش «کجا نمی‌رسد» را هم ببینید.

اسکیما، نقشه‌ی سایت و تگ‌های Open Graph افزونه‌ی Rank Math و فید RSS خود وردپرس اصلا از این فیلتر رد نمی‌شوند. تاریخ را مستقیم و بدون ترجمه می‌سازند، پس با این کد میلادی می‌مانند.

قالب تاریخ را چطور بنویسید؟

کد قالب تاریخ را از تنظیمات خود وردپرس می‌خواند. پس شکل تاریخ را از تنظیمات ← عمومی ← قالب تاریخ عوض کنید، با همان حرف‌های قالب PHP که وردپرس می‌شناسد. این خروجی‌ها را خود کد روی تاریخ ۲۸ اکتبر ۲۰۲۶ ساعت ۱۴:۳۰ تهران داده است:

قالب در تنظیماتخروجی
Y/m/d۱۴۰۵/۰۸/۰۶
j F Y۶ آبان ۱۴۰۵
l j F Yچهارشنبه ۶ آبان ۱۴۰۵
F Yآبان ۱۴۰۵
j F Y ساعت H:i۶ آبان ۱۴۰۵ ساعت ۱۴:۳۰
g:i a۲:۳۰ بعدازظهر

دو نکته دارد. کلمه‌ی فارسی را می‌شود مستقیم در قالب نوشت، مثل «ساعت» در ردیف پنجم. حرف لاتین را مثل همیشه در PHP باید با بک‌اسلش نوشت. قالب پیش‌فرض انگلیسی وردپرس (F j, Y) هم «آبان ۶, ۱۴۰۵» می‌دهد که در فارسی غلط خوانده می‌شود. پس اگر سایت را با زبان انگلیسی نصب کرده‌اید، قالب تاریخ را روی j F Y بگذارید.

ارقام خروجی فارسی‌اند. اگر رقم لاتین می‌خواهید (۱۴۰۵ به‌صورت 1405)، در کد fa_IR@calendar=persian را به fa_IR@calendar=persian;numbers=latn تغییر دهید.

اگر سرور intl نداشت

در پیشخوان به ابزارها ← سلامت سایت ← اطلاعات بروید و بخش سرور را باز کنید. اگر سرور به شما دسترسی خط فرمان می‌دهد، دستور php -m هم فهرست افزونه‌های PHP را نشان می‌دهد. اگر intl در فهرست نیست، کد بالا هیچ کاری نمی‌کند.

دو راه دارید. راه اول این است که از پشتیبانی هاست بخواهید intl را روشن کند. روی هاست‌هایی که کنترل پنل cPanel دارند، معمولا یک تیک در بخش انتخاب نسخه‌ی PHP است. راه دوم یک تابع تبدیل جلالی دستی است که در وب زیاد پیدا می‌شود. ما این دومی را پیشنهاد نمی‌کنیم. تابع‌های دستی کبیسه را هرکدام به روش خودشان حساب می‌کنند، ولی intl تقویم را از کتابخانه‌ی ICU می‌گیرد که سیستم‌عامل‌ها و مرورگرها هم از آن استفاده می‌کنند. در تست ما، کد بالا ۳۰ اسفند ۱۴۰۳ (سال کبیسه) و ۲۹ اسفند ۱۴۰۴ را درست داد.

این کد کجا نمی‌رسد؟

هر جایی که تاریخ از wp_date نگذرد، این کد هم به آن نمی‌رسد:

کجابا این کد شمسی می‌شود؟چرا
تاریخ نوشته و دیدگاه در قالببلهاز wp_date می‌گذرد
بلوک «تاریخ نوشته» در قالب‌های بلوکیبلهاز wp_date می‌گذرد. ویژگی datetime میلادی می‌ماند
تاریخی که قالب با date() خام PHP ساختهنهاز تابع‌های وردپرس رد نمی‌شود. باید در خود قالب عوض شود
پیشخوان و فهرست نوشته‌هانهعمدا. شرط is_admin()
تقویم انتخاب تاریخ در ویرایشگرنهجاوااسکریپتی است و از PHP رد نمی‌شود
بایگانی ماهانهنهبایگانی بر اساس ماه میلادی است. ابزارک بایگانی نام ماه میلادی را نشان می‌دهد. عنوان صفحه‌ی بایگانی، ماه شمسی اولین نوشته را می‌گیرد. «آبان ۱۴۰۵» ممکن است روی صفحه‌ای بیاید که نصف نوشته‌هایش مال مهر است
پیوند یکتای تاریخ‌دار (/2026/10/…)نهاز تاریخ ذخیره‌شده ساخته می‌شود. میلادی ماندنش درست است
«سفارش‌های من» در حساب مشتری ووکامرسبلهووکامرس تاریخ را با date_i18n نشان می‌دهد
گزارش‌ها و تحلیل ووکامرسنهدر پیشخوان است و بیشترش جاوااسکریپتی است
ایمیل سفارش ووکامرسگاهیایمیلی که موقع ثبت سفارش می‌رود شمسی است. ایمیلی که با تغییر وضعیت سفارش در پیشخوان می‌رود، میلادی

اگر فقط وبلاگ دارید، چهار ردیف اول همه‌ی چیزی است که لازم دارید و این کد کافی است. اگر فروشگاه دارید، ردیف‌های ووکامرس مهم‌ترند. یک سفارش با دو تاریخ در دو ایمیل، برای مشتری گیج‌کننده است. این‌جا ابزار آماده می‌صرفد. در راهنمای تاریخ شمسی ووکامرس همه‌ی جاهای تاریخ‌دار فروشگاه و معیار انتخاب ابزار را آورده‌ایم. ماژول تقویم شمسی افزونه‌ی رایگان راهکار وردپرس هم مثل همین کد فقط در نمایش تبدیل می‌کند، و پیشخوان و سایت را جدا روشن می‌کند. تاریخ هم فقط یکی از کارهای فارسی سازی ووکامرس است که با ترجمه درست نمی‌شود.

بعد از گذاشتن کد چه چیزهایی را چک کنید؟

  1. یک نوشته را در سایت باز کنید. تاریخ باید شمسی باشد.
  2. فهرست نوشته‌ها در پیشخوان را باز کنید. تاریخ‌ها باید میلادی بمانند (مگر شرط پیشخوان را برداشته باشید).
  3. سورس صفحه‌ی نوشته را باز کنید و دنبال datePublished بگردید. مقدارش باید میلادی و به شکل 2026-10-28T14:30:00+03:30 باشد.
  4. نقشه‌ی سایت را باز کنید (در Rank Math، ‎/sitemap_index.xml). ستون آخرین تغییر باید میلادی باشد.
  5. ‎/feed/ را باز کنید. تاریخ‌ها باید میلادی باشند.
  6. یک نوشته را برای ده دقیقه بعد زمان‌بندی کنید و ببینید سر وقت منتشر می‌شود.

اگر قدم ۳ یا ۴ تاریخ شمسی نشان داد، افزونه یا قالبی که دارید تاریخ را با قالبی می‌سازد که در فهرست $machine کد نیست. همان قالب را به فهرست اضافه کنید.

سؤال‌های پرتکرار

با عوض کردن قالب، کد از کار می‌افتد؟ اگر در mu-plugins باشد، نه. اگر در functions.php قالب باشد، با قالب می‌رود.

روی سرعت سایت اثر دارد؟ برای هر تاریخی که روی صفحه نشان داده می‌شود یک تبدیل انجام می‌شود. در صفحه‌ای با ده نوشته یعنی ده تبدیل. عددی برای اندازه‌اش نداریم، ولی کاری که انجام می‌شود فقط قالب‌بندی یک عدد است، نه کوئری به دیتابیس.

با افزونه‌ی تاریخ شمسی هم‌زمان کار می‌کند؟ نه. اگر افزونه هم تاریخ را تبدیل کند، یا دو بار تبدیل می‌شود یا یکی کار دیگری را خنثی می‌کند. یکی را نگه دارید.

این آموزش به کارت آمد؟ برای کسی بفرست.

نظرات

ایمیل شما نمایش داده نمی‌شود. نظرها پس از تأیید تیم منتشر می‌شوند.

هنوز نظری ثبت نشده. اولین نفر باش.

نظر خودت را بنویس

۰ / ۱۵۰۰