دسته بندی:

رفع مشکل ادیتور دایرکت ادمین برای فایل های UTF8

رفع مشکل ادیتور دایرکت ادمین برای فایل های UTF8

اگر فایل فارسی را در فایل‌منیجر دایرکت‌ادمین باز کنید و متن به شکل Ø§ÛØ±Ø§Ù یا مجموعه‌ای از علامت سؤال دیده شود، تقریباً همیشه محتوای فایل سالم است و فقط ادیتور بایت‌های UTF-8 را با انکودینگ دیگری تفسیر کرده است. تا وقتی تنظیم انکودینگ را درست نکرده‌اید همان صفحه را ذخیره نکنید، چون ذخیرهٔ متن به‌هم‌ریخته آن را روی فایل اصلی می‌نویسد؛ امن‌ترین کار این است که فایل را با SFTP و یک ادیتور درست ویرایش کنید.

چرا متن فارسی در ادیتور دایرکت‌ادمین به‌هم می‌ریزد؟

هر فایل متنی روی دیسک فقط یک رشته بایت است و «انکودینگ» تصمیمی است دربارهٔ اینکه هر بایت چه حرفی را نشان می‌دهد. حروف فارسی در UTF-8 دو بایتی هستند؛ اگر صفحه‌ای که ادیتور را نمایش می‌دهد خودش را تک‌بایتی (مثلاً iso-8859-1) معرفی کند، مرورگر همان دو بایت را دو حرف لاتین جداگانه می‌خواند و نتیجه همان متن ناخوانای معروف می‌شود. اسکین‌های قدیمی دایرکت‌ادمین این انکودینگ را در فایل‌های زبان خود اعلام می‌کردند و ریشهٔ مشکل هم دقیقاً همان‌جاست.

نکتهٔ مهم این است که تا وقتی فقط نگاه می‌کنید، آسیبی به فایل نرسیده؛ خرابی واقعی وقتی رخ می‌دهد که روی همان صفحه دکمهٔ ذخیره را بزنید و برداشت غلط ادیتور روی فایل نوشته شود. این رفتار مخصوص یک سرویس خاص نیست و روی هاست اشتراکی و سرور اختصاصی به یک شکل دیده می‌شود. پس اولین قدم، گرفتن یک نسخهٔ پشتیبان است: cp -a index.php index.php.bak

مرحلهٔ اول: مطمئن شوید فایل واقعاً UTF-8 است

پیش از تغییر هر تنظیمی، وضعیت خود فایل را روی هر سروری که دسترسی SSH دارید بررسی کنید:

  • تشخیص انکودینگ فعلی: file --mime-encoding /home/user/public_html/index.php
  • دیدن محتوا بدون دخالت مرورگر: less /home/user/public_html/index.php
  • بررسی وجود BOM در ابتدای فایل: head -c 3 index.php | xxd

اگر خروجی دستور اول charset=utf-8 باشد، فایل سالم است و مشکل صرفاً نمایشی است. اگر خروجی چیزی مثل charset=iso-8859-1 بود، فایل واقعاً با انکودینگ دیگری ذخیره شده و باید تبدیل شود؛ برای مثال از ویندوز-۱۲۵۶ به یونیکد: iconv -f WINDOWS-1256 -t UTF-8 old.php > new.php. خروجی را هرگز به خود همان فایل هدایت نکنید، چون فایل مبدأ خالی می‌شود. اگر هم سه بایت efbbbf در ابتدای فایل دیدید، فایل BOM دارد؛ در فایل‌های PHP همین سه بایت باعث خطای headers already sent یا یک خط خالی ناخواسته در خروجی می‌شود و بهتر است فایل را بدون BOM ذخیره کنید.

مطمئن‌ترین راه: ویرایش با SFTP به‌جای فایل‌منیجر

ساده‌ترین راه‌حل قطعی این است که فایل‌های فارسی را اصلاً داخل مرورگر ویرایش نکنید. با یک کلاینت SFTP مثل FileZilla یا WinSCP به سرور وصل شوید و فایل را با ادیتوری مثل VS Code، Notepad++ یا Sublime باز کنید؛ در تنظیمات این ادیتورها انکودینگ پیش‌فرض را روی UTF-8 without BOM بگذارید. در تنظیمات خود کلاینت هم اگر گزینهٔ انکودینگ نام فایل‌ها وجود دارد، آن را روی UTF-8 تنظیم کنید تا نام فایل‌های فارسی هم درست منتقل شوند.

اگر ترجیح می‌دهید مستقیم روی سرور مجازی لینوکسی و در ترمینال کار کنید، پیش از ویرایش وضعیت لوکیل را ببینید: locale. اگر مقدار LANG روی چیزی مثل POSIX یا C بود، برای همان نشست تنظیمش کنید: export LANG=en_US.UTF-8. در vim هم می‌توانید با :set fileencoding=utf-8 انکودینگ ذخیره‌سازی را صریح تعیین کنید. فراموش نکنید که خود برنامهٔ ترمینال (مثلاً PuTTY) هم باید روی UTF-8 تنظیم باشد، وگرنه متن سالم را هم ناخوانا نشان می‌دهد.

اصلاح انکودینگ در اسکین قدیمی دایرکت‌ادمین

روی سرورهایی که هنوز اسکین enhanced را دارند، انکودینگ صفحهٔ فایل‌منیجر در فایل زبان تعریف شده است؛ فایل‌منیجر سی‌پنل ساختار جداگانه‌ای دارد که در راهنمای فایل منیجر سی پنل شرح داده شده است. ابتدا ببینید این مسیر روی سرور شما وجود دارد یا نه: ls /usr/local/directadmin/data/skins/. اگر پوشهٔ enhanced نبود، نسخهٔ دایرکت‌ادمین شما از اسکین دیگری استفاده می‌کند و این راه‌حل موضوعیت ندارد؛ در آن صورت مستقیم سراغ بخش‌های بعدی بروید.

در غیر این صورت اول پشتیبان بگیرید: cp -a /usr/local/directadmin/data/skins/enhanced/lang/en/lf_standard.html /root/lf_standard.html.bak و بعد فایل را باز کنید: nano -w /usr/local/directadmin/data/skins/enhanced/lang/en/lf_standard.html. حالا خط LANG_ENCODING=iso-8859-1 را پیدا کنید و آن را به LANG_ENCODING=utf-8 تغییر دهید. پس از ذخیره، یک‌بار از پنل خارج و دوباره وارد شوید تا صفحه از کش مرورگر خوانده نشود. توجه داشته باشید که به‌روزرسانی‌های دایرکت‌ادمین می‌توانند فایل‌های اسکین پیش‌فرض را بازنویسی کنند، پس این تغییر را جایی یادداشت کنید تا بعد از هر آپدیت دوباره بررسی‌اش کنید. اگر سرور را خودتان مدیریت می‌کنید و لایسنس دایرکت‌ادمین اختصاصی دارید، دسترسی روت برای این کار در اختیارتان است؛ روی هاست اشتراکی چنین تغییری فقط از سمت مدیر سرور ممکن است.

اگر فایل سالم است ولی خروجی سایت خراب نشان داده می‌شود

گاهی متن داخل فایل درست است و در less هم درست دیده می‌شود، اما مرورگر آن را ناخوانا نمایش می‌دهد. اینجا مشکل «اعلام» انکودینگ است، نه محتوا. سه نقطه را بررسی کنید:

  • در ابتدای بخش head صفحه، تگ <meta charset="UTF-8"> وجود داشته باشد.
  • هدر HTTP پاسخ را ببینید: curl -I https://example.com و مقدار Content-Type را چک کنید. اگر هدر انکودینگ دیگری اعلام کند، همان بر تگ متا اولویت دارد.
  • در آپاچی می‌توانید با افزودن AddDefaultCharset UTF-8 به فایل .htaccess انکودینگ پیش‌فرض پاسخ‌ها را مشخص کنید. در PHP هم دستور header('Content-Type: text/html; charset=UTF-8'); باید پیش از هر خروجی اجرا شود و مقدار default_charset در php.ini نقش مشابهی دارد.

یک هشدار عملی: تشخیص خودکار مرورگر شما ممکن است مشکل را پنهان کند، در حالی که بازدیدکننده همچنان متن خراب می‌بیند؛ پس به خروجی curl اعتماد کنید، نه به مرورگر خودتان.

وقتی متن از دیتابیس می‌آید

اگر متن فارسی از پایگاه داده خوانده می‌شود، حتی با فایل و هدر درست هم ممکن است خروجی خراب باشد. رایج‌ترین حالت این است که جدول utf8mb4 باشد اما اتصال برنامه با انکودینگ دیگری برقرار شود؛ نتیجه، ذخیرهٔ داده‌های دوبار-انکودشده است. این حالت بیش از همه بعد از جابه‌جایی سایت بین دو کنترل‌پنل دیده می‌شود؛ اگر تازه مهاجرت کرده‌اید، ترتیب درست خروجی‌گرفتن و وارد کردن دیتابیس را در راهنمای انتقال بکاپ از دایرکت ادمین به سی پنل مرور کنید. برای بررسی از SHOW CREATE TABLE wp_posts; و SHOW VARIABLES LIKE 'character_set%'; استفاده کنید — همین دو کوئری را در phpMyAdmin هم می‌توانید اجرا کنید و اگر phpMyAdmin به‌جای صفحهٔ ورود یک صفحهٔ سفید نشان داد، اول مشکل سفید شدن صفحهٔ ورود به phpMyAdmin را حل کنید و مطمئن شوید اتصال برنامه هم صریح تنظیم شده است: SET NAMES utf8mb4، یا در سطح کد mysqli_set_charset($conn, 'utf8mb4') و در PDO افزودن charset=utf8mb4 به رشتهٔ اتصال. در وردپرس همین مقدار با ثابت DB_CHARSET در wp-config.php کنترل می‌شود.

پیش از هر تغییری روی خود جدول، حتماً بکاپ بگیرید: mysqldump -u user -p dbname > dbname.sql. اگر همین دستور با پیام Access denied رد شد، رمز اتصال دیتابیس درست نیست و رفع خطای Access denied for user در دایرکت ادمین مسیر بازیابی آن را توضیح می‌دهد. دستور ALTER TABLE tbl CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; تنها زمانی درست عمل می‌کند که داده‌ها سالم باشند؛ اگر متن‌ها از قبل خراب شده‌اند، این دستور خرابی را تثبیت می‌کند و برگشتی در کار نیست. اگر دیتابیس بزرگ است یا مطمئن نیستید داده‌ها در چه وضعیتی هستند، پیش از اجرای ALTER از پشتیبانی فنی کمک بگیرید.

چطور دیگر تکرار نشود

  • انکودینگ پیش‌فرض ادیتور خود را یک‌بار روی UTF-8 without BOM تنظیم کنید و دیگر سراغ ذخیرهٔ فایل با انکودینگ محلی نروید.
  • فایل‌های حاوی متن فارسی را با SFTP ویرایش کنید و فایل‌منیجر مرورگر را برای جابه‌جایی و مدیریت فایل نگه دارید، نه ویرایش محتوا.
  • هر صفحه‌ای که متن ناخوانا نشان می‌دهد را ذخیره نکنید؛ اول علت را پیدا کنید، بعد ویرایش.
  • زنجیره را کامل یکدست کنید: انکودینگ فایل، هدر پاسخ، تگ متا، انکودینگ جدول و انکودینگ اتصال دیتابیس همه باید UTF-8 باشند.
  • بعد از هر به‌روزرسانی کنترل‌پنل، یک فایل فارسی نمونه را باز کنید تا مطمئن شوید تنظیم قبلی هنوز پابرجاست.