رفتن به محتوای اصلی

تست i۱۸n و L۱۰n؛ چک‌لیست فارسی و RTL

چک‌لیست عملی تست i18n و L10n برای فارسی و بازار ایران؛ از Unicode و RTL تا تاریخ شمسی، ریال/تومان، ماتریس Locale و Playwright.

محمد عسکری ۲۱ دقیقه مطالعه به‌روزرسانی
فهرست مطالب
  1. i18n و L10n دقیقاً چه هستند؟
  2. زبان، Locale، منطقه و جهت را یکی نگیرید
  3. پیش از تست، قرارداد Locale بنویسید
  4. ماتریس تست Locale را بر پایهٔ ریسک بسازید
  5. ابعاد ماتریس
  6. سه لایهٔ پوشش
  7. Unicode و UTF-8: شرط لازم، نه اثبات نهایی
  8. کدپوینت‌های دام‌دار فارسی
  9. Normalization را متناسب با دامنه تست کنید
  10. RTL فقط راست‌چین‌کردن CSS نیست
  11. چک‌لیست ساختار و چیدمان RTL
  12. متن دوجهته را با دادهٔ واقعی آزمایش کنید
  13. ارقام فارسی، ورودی عدد و شناسه‌ها
  14. جست‌وجو، مرتب‌سازی و مقایسهٔ فارسی
  15. تاریخ، تقویم و منطقهٔ زمانی را جدا کنید
  16. سناریوهای مرزی زمان برای ایران
  17. ریال و تومان را به Locale Library واگذار نکنید
  18. چک‌لیست پول
  19. رشته‌ها را ترجمه‌پذیر طراحی کنید
  20. شبه‌بومی‌سازی را پیش از ترجمه اجرا کنید
  21. سه پروفایل مفید
  22. تست L10n سه لایه دارد
  23. بازبینی زبانی
  24. بازبینی کارکردی
  25. بازبینی دیداری و فرهنگی
  26. دسترس‌پذیری در Locale فارسی
  27. فرم نام، نشانی و تلفن را محلی تست کنید
  28. همهٔ کانال‌ها را در قرارداد بگنجانید
  29. امنیت Unicode و محتوای بومی‌شده
  30. مرز انسان و اتوماسیون در تست بومی‌سازی
  31. نمونه تست Locale با Playwright
  32. معماری پیشنهادی Suite اتوماسیون
  33. ماتریس عملی فارسی و بازار ایران
  34. عیب‌یابی شکست‌های i18n و L10n
  35. حاکمیت و مالکیت کیفیت بومی‌سازی
  36. معیارهایی که واقعاً کمک می‌کنند
  37. برنامهٔ ۳۰روزهٔ اجرای تست فارسی و RTL
  38. هفتهٔ اول: قرارداد و Baseline
  39. هفتهٔ دوم: Gateهای ارزان
  40. هفتهٔ سوم: Oracleهای دامنه
  41. هفتهٔ چهارم: LQA و بازخورد تولید
  42. اشتباهات رایج در تست i18n و L10n
  43. چک‌لیست نهایی انتشار Locale
  44. پرسش‌های متداول
  45. تفاوت تست i18n و L10n چیست؟
  46. آیا fa-IR به‌تنهایی تقویم شمسی و منطقهٔ زمانی تهران را تعیین می‌کند؟
  47. برای فارسی، ی و ک عربی را همیشه باید به فارسی تبدیل کنیم؟
  48. چگونه ریال و تومان را تست کنیم؟
  49. آیا اتوماسیون و شبه‌بومی‌سازی جای بازبین فارسی‌زبان را می‌گیرند؟
  50. جمع‌بندی: Locale را به یک قرارداد قابل‌آزمون تبدیل کنید
تست i۱۸n و L۱۰n؛ چک‌لیست فارسی و RTL

دو رشتهٔ «یکسان» می‌توانند در پایگاه داده برابر نباشند: «ی» فارسی با U+06CC و «ی» عربی با U+064A فقط شبیه هم دیده می‌شوند. یک زمان ثابت UTC می‌تواند در تهران روز دیگری باشد؛ مبلغ «۱۰۰٬۰۰۰ تومان» نیز با «۱۰۰٬۰۰۰ ریال» ده برابر تفاوت دارد. اگر تست فقط تغییر زبان منو و چند Screenshot را ببیند، این خطاهای واقعی از آن عبور می‌کنند.

تست i18n و L10n باید یک قرارداد کامل را از ورودی تا ذخیره، پردازش، نمایش و خروجی‌های جانبی بررسی کند. در این راهنما، ابتدا تفاوت جهانی‌سازی و بومی‌سازی را روشن می‌کنیم، سپس قرارداد Locale و ماتریس ریسک می‌سازیم و آن را برای فارسی ایران، RTL، Unicode، تاریخ شمسی، منطقهٔ زمانی تهران، ریال/تومان و اتوماسیون Playwright به سناریوهای قابل‌اجرا تبدیل می‌کنیم.

i18n و L10n دقیقاً چه هستند؟

Internationalization یا i18n طراحی و پیاده‌سازی نرم‌افزار به‌گونه‌ای است که بدون بازنویسی منطق اصلی بتواند زبان، خط، منطقه، تقویم، منطقهٔ زمانی و قواعد قالب‌بندی متفاوت را پشتیبانی کند. عدد ۱۸ تعداد حروف میان I و n در واژهٔ Internationalization است.

Localization یا L10n تطبیق یک محصول i18n‌شده برای بازار یا Locale مشخص است: ترجمه، واژه‌نامه، قالب تاریخ و عدد، تصاویر، قوانین محصول، محتوای حقوقی و کیفیت تجربهٔ همان مخاطب. Globalization یا g11n گاهی نام چتر فرایند کسب‌وکاری و فنی عرضه در چند بازار است.

حوزهپرسش اصلی تستنمونهٔ نقص
i18nآیا معماری از تفاوت‌ها بدون Fork کد پشتیبانی می‌کند؟متن هاردکد، چیدمان فقط LTR، Parser وابسته به فرمت انگلیسی
L10nآیا خروجی برای یک Locale خاص درست و طبیعی است؟ترجمهٔ نادرست، «تومان» با مقدار ریالی، تاریخ شمسی اشتباه
بازار/محصولآیا سیاست تجاری و حقوقی مقصد درست اعمال شده است؟روش پرداخت ناموجود، متن رضایت یا نشانی نامتناسب

تست i18n موفق ثابت نمی‌کند ترجمهٔ فارسی خوب است؛ LQA خوب هم ثابت نمی‌کند Parser در Locale دیگری امن است. هر کدام مرز اثبات خودش را دارد.

زبان، Locale، منطقه و جهت را یکی نگیرید

fa زبان فارسی را معرفی می‌کند و fa-IR فارسی در زمینهٔ منطقهٔ ایران را. با این حال، Language Tag به‌تنهایی واحد پول، منطقهٔ زمانی یا تقویم انتخابی کاربر را قطعی نمی‌کند. ممکن است کاربری زبان فارسی، تقویم میلادی، ارقام لاتین و منطقهٔ زمانی اروپا را انتخاب کرده باشد.

تگ‌های زبان بر اساس BCP ۴۷ ساخته می‌شوند. RFC ۵۶۴۶ از IETF ساختار زیرتگ‌های زبان، Script، Region، Variant و Extension را تعریف می‌کند. پس مقدارهایی مانند fa_IR و Persian-Iran را به‌عنوان Language Tag اختراع نکنید؛ قالب استاندارد وب fa-IR است.

  • Language: فارسی، انگلیسی یا عربی؛
  • Script: خط عربی یا لاتین و جهت غالب آن؛
  • Region: بازار و قراردادهای منطقه‌ای؛
  • Calendar: هجری شمسی، میلادی یا انتخاب دیگر؛
  • Time zone: مانند Asia/Tehran؛
  • Numbering system: ارقام فارسی/Extended Arabic-Indic یا لاتین؛
  • Currency/domain unit: IRR، ریال یا نمایش محصولی تومان؛
  • Direction: RTL/LTR؛ ویژگی ارائه است و از نام زبان به‌تنهایی استنتاج کامل نمی‌شود.

پیش از تست، قرارداد Locale بنویسید

چک‌لیست بدون Oracle فقط فهرست چیزهایی است که باید «نگاه شوند». قرارداد Locale منبع قضاوت را برای هر تبدیل مشخص می‌کند:

بخش قراردادنمونه برای محصول ایرانیشاهد تست
Locale پشتیبانی‌شدهfa-IR و en-USRegistry نسخه‌دار و تنظیم حساب
ترتیب انتخابانتخاب کاربر ← حساب/سازمان ← مرورگر ← پیش‌فرض امنتست هر منبع و تعارض آن‌ها
Fallback ترجمهfa-IR → fa → en یا خط‌مشی صریح دیگرکلید گم‌شده و Telemetry fallback
مدل داخلی پولعدد صحیح ریال + کد/واحد صریحAPI و Ledger، مستقل از متن UI
ورودی عددپذیرش یا رد ارقام فارسی، عربی و لاتین طبق فیلدجدول نمونه و خطای مشخص
زمان و تقویمInstant در UTC؛ نمایش با Asia/Tehran و تقویم انتخابیInstant ثابت، zone و calendar ثبت‌شده
NormalizationNFC برای متن عادی؛ نگاشت ی/ک فقط در حوزهٔ مصوبورودی کدپوینتی و خروجی/ذخیره
جهتسند فارسی RTL؛ شناسه‌ها و قطعات لاتین ایزولهDOM معنایی + بازبینی دیداری/کیبورد

قرارداد باید Owner و نسخه داشته باشد. ارتقای CLDR، ICU، tzdata، فونت یا فایل ترجمه می‌تواند خروجی را بدون تغییر مستقیم کد کسب‌وکار عوض کند؛ این هویت‌ها را در گزارش اجرا ثبت کنید.

ماتریس تست Locale را بر پایهٔ ریسک بسازید

ضرب همهٔ زبان‌ها در همهٔ مرورگرها، دستگاه‌ها، مناطق زمانی و کانال‌ها به انفجار ترکیبی می‌رسد. ابتدا جریان‌های پرپیامد را با ماتریس تست مبتنی بر ریسک اولویت‌بندی کنید، سپس از ترکیب نماینده و Pairwise برای بقیه استفاده کنید.

ابعاد ماتریس

  • Language Tag، Script و جهت پایه؛
  • Region، ارز، واحد دامنه و قواعد محصول؛
  • تقویم، منطقهٔ زمانی و Instant مرزی؛
  • سیستم ارقام، صفحه‌کلید و روش ورودی؛
  • مرورگر، سیستم‌عامل، اندازهٔ صفحه و Font fallback؛
  • کانال: Web، Mobile، API، Email، SMS، Push، PDF و CSV؛
  • منبع Locale: پروفایل، سازمان، URL، Header یا پیش‌فرض؛
  • نسخهٔ Resource bundle، CLDR/ICU، tzdata و Feature Flag.

سه لایهٔ پوشش

  1. Smoke هر Locale: بارگذاری Resource، نبود کلید خام، جهت و مسیر حیاتی؛
  2. Regression نماینده: ترکیب‌های ریسک‌محور در واحد، Component، API و E2E؛
  3. LQA انسانی: زبان، لحن، فرهنگ، دسترس‌پذیری و تجربه روی محصول واقعی.

برای پوشش دستگاه و مرورگر، منطق انتخاب را با راهنمای Browser و Device Matrix ترکیب کنید؛ Locale نباید ماتریس سازگاری جدا و بدون اولویت بسازد.

Unicode و UTF-۸: شرط لازم، نه اثبات نهایی

UTF-۸ از مسیر مرورگر، API، Queue، Log، پایگاه داده، جست‌وجو و Export باید بدون تبدیل ناخواسته عبور کند. راهنمای کوتاه i18n وب از W3C استفاده و اعلام UTF-۸، پرهیز از اتصال رشته، پشتیبانی فرم‌های محلی و تعیین جهت را توصیه می‌کند. اما ذخیرهٔ صحیح بایت‌ها هنوز Equality، Search و Sort درست را ثابت نمی‌کند.

کدپوینت‌های دام‌دار فارسی

نمایشکدپوینتنام/ریسک
یU+06CCPersian Yeh
یU+064AArabic Yeh؛ شبیه ولی متفاوت
کU+06A9Keheh فارسی
کU+0643Arabic Kaf؛ شبیه ولی متفاوت
‌U+200CZWNJ یا نیم‌فاصله؛ نامرئی اما معنادار در واژه
۰…۹U+06F0…U+06F9Extended Arabic-Indic / ارقام رایج فارسی
۰…۹U+0660…U+0669Arabic-Indic؛ با ارقام فارسی یکسان نیست
0…9U+0030…U+0039ASCII؛ در شناسه‌ها و قراردادهای فنی رایج

تست Round-trip بسازید: ورود از کیبورد، API و Import؛ ذخیره؛ بازیابی؛ جست‌وجو؛ و Export. علاوه بر ظاهر، کدپوینت‌ها و طول Grapheme را در شواهد تشخیصیِ امن نمایش دهید.

Normalization را متناسب با دامنه تست کنید

رشته‌های canonically equivalent ممکن است بایت‌های متفاوت داشته باشند. ضمیمهٔ استاندارد Unicode شمارهٔ ۱۵ فرم‌های NFC، NFD، NFKC و NFKD را تعریف می‌کند و هشدار می‌دهد NFKC/NFKD تمایزهای سازگاری را حذف می‌کنند؛ بنابراین نباید کورکورانه روی هر متن اعمال شوند.

  • برای محتوای عادی، سیاست NFC را از ورودی تا Index و خروجی تست کنید.
  • نگاشت ی→ی و ک→ک بخشی از Unicode Normalization استاندارد نیست؛ یک قاعدهٔ دامنه‌ای جداست.
  • در Search نام، می‌توانید متن اصلی را حفظ و یک کلید جست‌وجوی مصوب بسازید.
  • برای Password، Token، Hash، امضای دیجیتال، IBAN یا شناسهٔ قراردادی، تبدیل خودسرانه نکنید؛ Equality باید صریحاً تعریف شود.
  • Transformation را قابل‌مشاهده کنید تا کاربر بداند چه چیزی تغییر کرده و تیم بتواند Incident را بازتولید کند.

سناریوهای مهم شامل فاصله در برابر ZWNJ، کاراکتر ترکیبی، Emoji چندکدپوینتی، متن تهی پس از Sanitization، Copy/Paste از پیام‌رسان و ورودی حاوی کنترل نامرئی است.

RTL فقط راست‌چین‌کردن CSS نیست

برای سند فارسی، زبان و جهت را در HTML صریح کنید: <html lang="fa-IR" dir="rtl">. راهنمای اعلام زبان در HTML از W3C استفاده از lang روی عنصر html و علامت‌گذاری بخش‌های با زبان دیگر را توضیح می‌دهد. زبان به فناوری کمکی، جست‌وجو و پردازش کمک می‌کند؛ ولی lang جای dir نیست.

چک‌لیست ساختار و چیدمان RTL

  • از CSS Logical Properties مانند margin-inline-start به‌جای نسخه‌های پراکندهٔ left/right استفاده شده است؟
  • آیکون جهت‌دار مانند بازگشت و Progress با معنا Mirror شده، اما آیکون غیرجهت‌دار بی‌دلیل برنگشته است؟
  • ترتیب DOM، Focus و Screen Reader منطقی مانده و فقط با CSS معکوس نشده است؟
  • جدول، Breadcrumb، نمودار، Slider و صفحه‌بندی در RTL قابل‌فهم‌اند؟
  • Tooltip، Modal، Toast و Validation message از قاب بیرون نمی‌زنند؟

راهنمای ساختار RTL در HTML از W3C تعیین جهت پایه با dir، استفاده از Propertyهای منطقی و dir="auto" برای ورودی کاربر را تشریح می‌کند.

متن دوجهته را با دادهٔ واقعی آزمایش کنید

فارسی در کنار شماره سفارش، URL، Email، کد تخفیف و شناسهٔ شبا یک خط دوجهته می‌سازد. الگوریتم Bidi بیشتر ترتیب را حل می‌کند، اما مرز قطعهٔ LTR ممکن است نیاز به ایزوله‌سازی معنایی با <bdi> یا dir="auto" داشته باشد.

این رشته‌ها را در عنوان، دکمه، جدول، اعلان، Log و Copy/Paste تست کنید:

  • سفارش AB-123-IR پرداخت شد؛
  • شماره پیگیری 2026/08/11-A9؛
  • ایمیل user+qa@example.test ثبت شد؛
  • IR820540102680020817909002 کنار برچسب فارسی؛
  • رشته‌ای که با عدد، پرانتز یا Emoji شروع و تمام می‌شود.

فقط Screenshot کافی نیست. Selection، حرکت Cursor، Backspace، Copy/Paste، خواندن Screen Reader و ترتیب متن در Clipboard را نیز مشاهده کنید.

ارقام فارسی، ورودی عدد و شناسه‌ها

سیاست «همهٔ رقم‌ها را فارسی کن» می‌تواند شناسهٔ فنی، کد OTP یا دادهٔ API را خراب کند. برای هر فیلد سه پرسش جدا دارید: چه چیزی پذیرفته می‌شود، مدل canonical چیست و چه چیزی نمایش داده می‌شود؟

فیلدورودی محتملمدل و نمایش پیشنهادیِ قراردادی
مبلغفارسی/لاتین، جداکننده، PasteDecimal/Integer canonical؛ نمایش Locale-aware با واحد صریح
OTPکیبورد عددی و Paste پیامکقرارداد پذیرش رقم روشن؛ Compare امن با canonical digits
شماره سفارشحروف لاتین، خط تیره، عددExact identifier؛ نمایش در Bidi isolate
کد ملیممکن است صفر آغازین داشته باشدString، نه Number؛ طول و checksum طبق قرارداد دامنه
شماره موبایل09… یا +98…Parsing و canonical form صریح، بدون Regex جهانی ساده‌انگارانه

سناریوهای Paste شامل فاصلهٔ عادی/نامرئی، جداکنندهٔ عربی، علامت منفی، اعشار، صفر آغازین و مخلوط سه مجموعه رقم را اضافه کنید. پیام خطا باید بگوید چه فرمتی پذیرفته است.

جست‌وجو، مرتب‌سازی و مقایسهٔ فارسی

Binary order برای فهرست نام‌های فارسی الزاماً ترتیب مورد انتظار کاربر نیست. Collation باید با Locale و نیاز دامنه تعیین شود. برای Search نیز دربارهٔ ی/ی، ک/ک، اعراب، ZWNJ، فاصله، بزرگی/کوچکی حروف لاتین و typo tolerance قرارداد بنویسید.

  • نتایج Search با نسخهٔ Index و Normalization یکسان‌اند؟
  • مرتب‌سازی Server و Client نتیجهٔ متناقض نمی‌دهند؟
  • Pagination پس از تغییر Collation پایدار است؟
  • Exact match شناسه با fuzzy match نام قاطی نشده است؟
  • Highlight نتیجه مرز Grapheme و RTL را خراب نمی‌کند؟

دادهٔ تست را از نام‌های کوتاه و لاتین فراتر ببرید. راهنمای مدیریت داده تست برای ساخت دادهٔ مصنوعی، مالکیت و TTL مفید است.

تاریخ، تقویم و منطقهٔ زمانی را جدا کنید

«تاریخ شمسی» سه تصمیم متفاوت را پنهان می‌کند: لحظهٔ واقعی، منطقهٔ زمانی و تقویم نمایش. برای رویداد، یک Instant بدون ابهام ذخیره کنید؛ سپس آن را با منطقهٔ زمانی IANA و تقویم انتخابی نمایش دهید. برای تاریخ کسب‌وکاری بدون زمان—مثلاً تاریخ تولد یا سررسید قراردادی—مدل مناسب می‌تواند Local Date به همراه Calendar/Rule باشد.

پایگاه دادهٔ منطقهٔ زمانی IANA تاریخچه و قواعد قابل‌خواندن ماشین را نگه می‌دارد و با تغییر تصمیم‌های سیاسی به‌روزرسانی می‌شود. پس Asia/Tehran را به offset ثابت +03:30 تبدیل نکنید؛ نسخهٔ tzdata محیط را در شاهد ثبت کنید.

سناریوهای مرزی زمان برای ایران

  • لحظهٔ نزدیک نیمه‌شب تهران که تاریخ UTC و محلی متفاوت است؛
  • پایان اسفند و قواعد سال کبیسهٔ تقویم مورد استفاده؛
  • تبدیل رفت‌وبرگشت Gregorian ↔ Persian بدون جابه‌جایی روز؛
  • تاریخ تاریخی در نسخه‌های متفاوت tzdata؛
  • Session یا Token که بر Instant منقضی می‌شود، نه متن تاریخ نمایش؛
  • گزارش «روزانه» که مرز روز را بر اساس منطقهٔ سازمان می‌بندد؛
  • کاربر فارسی در منطقهٔ زمانی دیگری و کاربر انگلیسی در تهران.

استاندارد Unicode LDML یا UTS #۳۵ مدل دادهٔ Locale و قالب‌های تاریخ، عدد، واحد و ترجیحات را مشخص می‌کند. خروجی کتابخانه را به‌عنوان حقیقت کسب‌وکار فرض نکنید؛ نسخه و قرارداد محصول را هم بررسی کنید.

ریال و تومان را به Locale Library واگذار نکنید

IRR کد ارز ریال ایران است؛ «تومان» یک واحد رایج دامنه‌ای است و تبدیل آن باید در قرارداد محصول صریح باشد. Formatter ممکن است نماد، نام یا تعداد رقم متفاوتی تولید کند، اما نمی‌داند کسب‌وکار شما چه زمانی تومان را می‌پذیرد.

چک‌لیست پول

  • مقدار canonical و واحد در API، Database، Queue و Ledger صریح است؟
  • تبدیل ریال/تومان دقیقاً یک‌بار و در مرز تعیین‌شده انجام می‌شود؟
  • از Float برای مبلغ استفاده نشده و قاعدهٔ گردکردن مشخص است؟
  • عدد و واحد در UI، رسید، Email، PDF و Export با هم سازگارند؟
  • Copy/Paste جداکننده‌ها را بدون تغییر مرتبهٔ بزرگی Parse می‌کند؟
  • حداقل/حداکثر، صفر، مبلغ منفی، Refund و جمع سبد آزموده شده‌اند؟
  • در Log و Error، واحد کنار مقدار وجود دارد؟

مثال پرریسک: UI «۱۲۵٬۰۰۰ تومان» نشان می‌دهد، API باید طبق قرارداد { "amount": 1250000, "unit": "IRR" } بفرستد و Ledger همان ۱٬۲۵۰٬۰۰۰ ریال را یک‌بار ثبت کند. Assertion روی متن UI به‌تنهایی کافی نیست.

رشته‌ها را ترجمه‌پذیر طراحی کنید

اتصال "سلام " + name + "!" فقط یک مشکل کدنویسی نیست؛ ترتیب، جنس، جمع و نشانه‌گذاری در زبان‌ها فرق می‌کند. هر پیام باید یک واحد معنایی با Placeholder نام‌دار باشد و مترجم Context، Screenshot، محدودیت و توضیح متغیرها را ببیند.

  • کلید پایدار است و متن منبع به‌عنوان شناسه استفاده نشده؟
  • Placeholderها نام‌دار، typed و در ترجمه حفظ شده‌اند؟
  • Plural/Select به قواعد Locale سپرده شده، نه شرط‌های انگلیسی؟
  • HTML/Markdown داخل ترجمه محدود، Escape و از نظر XSS بررسی شده است؟
  • ترجمهٔ گم‌شده، خالی، قدیمی و Extra key در Build قابل‌مشاهده‌اند؟
  • Fallback کنترل‌شده است و متن چندزبانهٔ ناخواسته را پنهان نمی‌کند؟

راهنمای MessageFormat در ICU الگوهای Argument، Select و Plural را توضیح می‌دهد. تست باید شاخه‌های واقعی پیام، حفظ Placeholder و خروجی خطرناک را پوشش دهد؛ صرف Compileشدن فایل ترجمه کافی نیست.

شبه‌بومی‌سازی را پیش از ترجمه اجرا کنید

Pseudo-localization رشته‌ها را به شکل کنترل‌شده تغییر می‌دهد تا نقص معماری زودتر دیده شود. این تکنیک جای ترجمهٔ واقعی یا بازبین بومی را نمی‌گیرد.

سه پروفایل مفید

  • Expansion: متن را با نسبت آزمایشی مبتنی بر دادهٔ محصول بلند و در کروشه محصور کنید تا clipping و متن هاردکد دیده شود.
  • Accented/Unicode: کاراکترهای غیرASCII و ترکیبی تزریق کنید، در حالی که Placeholder و Markup سالم می‌مانند.
  • Pseudo-RTL: جهت و متن مختلط را فعال کنید تا وابستگی به left/right و ترتیب نامناسب آشکار شود.

در CI بررسی کنید همهٔ رشته‌های قابل‌مشاهده از Resource می‌آیند، Placeholderها گم نشده‌اند و Screenshotهای صفحات کلیدی Overflow ندارند. درصد Expansion قانون جهانی نیست؛ آن را از توزیع طول ترجمه‌های واقعی محصول تنظیم کنید.

تست L10n سه لایه دارد

بازبینی زبانی

دقت معنا، اصطلاحات، دستور، املا، لحن، جمع، ضمیر و سازگاری با واژه‌نامه بررسی می‌شود. مترجم باید Context داشته باشد؛ رشتهٔ «Save» بدون اینکه دکمه است یا اسم، قابل‌قضاوت نیست.

بازبینی کارکردی

لینک، Shortcut، Validation، پرداخت، Search، فایل، Notification و انتخاب Locale اجرا می‌شوند. ترجمهٔ درست اگر Placeholder را شکسته یا Route را تغییر داده باشد، محصول هنوز معیوب است.

بازبینی دیداری و فرهنگی

Clipping، Font fallback، Line height، جهت، تصویر، رنگ، مثال، واحد و محتوای حساس بازار بررسی می‌شوند. نظر یک فرد بومی دادهٔ کیفی مهمی است، نه تضمین جهانی؛ بازبین، تصمیم و نسخهٔ محتوا را ثبت کنید.

دسترس‌پذیری در Locale فارسی

ترجمهٔ قابل‌دیدن لزوماً قابل‌خواندن برای فناوری کمکی نیست. lang درست به تلفظ Screen Reader کمک می‌کند و dir ترتیب نمایش را هدایت می‌کند. راهنمای کامل تست دسترس‌پذیری و WCAG ۲.۲ را در کنار سناریوهای زیر اجرا کنید:

  • زبان صفحه و قطعهٔ انگلیسی داخل آن درست علامت‌گذاری شده است؛
  • ترتیب Focus با منطق کار و نه صرفاً جهت بصری هماهنگ است؛
  • Error با فیلد مرتبط و به فارسی قابل‌فهم اعلام می‌شود؛
  • Live region، Dialog و Toast ترجمه‌شده به‌موقع خوانده می‌شوند؛
  • Zoom، اندازه متن و فونت جایگزین باعث clipping نمی‌شود؛
  • آیکون بدون متن، نام دسترس‌پذیر بومی و دقیق دارد؛
  • کیبورد فیزیکی و On-screen فارسی، Shortcutها را از کار نمی‌اندازند.

فرم نام، نشانی و تلفن را محلی تست کنید

فرض‌هایی مانند «نام دو بخش دارد»، «همهٔ نشانی‌ها یک خط‌اند» یا «شماره تلفن همیشه ده رقم است» دادهٔ کاربر را رد می‌کنند. فیلدها را فقط تا حد نیاز کسب‌وکار ساخت‌یافته کنید.

  • نام تک‌بخشی، چندبخشی، فارسی/لاتین، ZWNJ و فاصلهٔ اضافی؛
  • استان، شهر، کدپستی با صفر آغازین و نشانی چندخطی؛
  • موبایل ملی و قالب بین‌المللی +98؛
  • کد ملی/شناسه با مدل String، Validation مرحله‌ای و پیام امن؛
  • Auto-complete و Browser autofill در RTL؛
  • Paste، IME، Voice input و اصلاح خودکار کیبورد موبایل؛
  • حفظ متن اصلی در کنار نسخهٔ canonical برای موارد مجاز.

برای PII از دادهٔ مصنوعی معتبر استفاده کنید؛ Screenshot، Video و Trace تست نباید نام، تلفن یا شناسهٔ واقعی را منتشر کنند.

همهٔ کانال‌ها را در قرارداد بگنجانید

کانالریسک i18n/L10nشاهد
Web/MobileRTL، Font، keyboard، deep link و cache LocaleDOM/semantics، screenshot هدفمند، device run
API/Webhookتبدیل متن نمایش به مدل canonical، header و error codeSchema، payload و contract test
Email/SMS/PushBidi، Placeholder، محدودیت طول، لینک و fallbackrender واقعی و capture امن
PDF/PrintFont embedding، glyph shaping، pagination و جدول RTLمتن استخراج‌شده + بازبینی تصویری
CSV/ExcelEncoding، delimiter، formula injection و ارقامبازکردن در مصرف‌کنندهٔ هدف و round-trip
Search/IndexNormalization/Collation متفاوت با Databasequery corpus نسخه‌دار

ماتریس تست Cross Browser با Playwright به شما کمک می‌کند اختلاف موتورهای رندر و سیستم‌عامل را از نقص ترجمه یا Locale جدا کنید.

امنیت Unicode و محتوای بومی‌شده

کاراکترهای هم‌شکل، کنترل‌های Bidi و متن نامرئی می‌توانند Log، شناسه، نام کاربری یا حتی مرور کد را گمراه کنند. استاندارد UTS #۳۹ درباره سازوکارهای امنیت Unicode روش‌هایی برای شناسایی Confusableها و محدودسازی شناسه‌ها ارائه می‌کند. خط‌مشی شما باید متناسب با نوع فیلد باشد، نه ممنوعیت عمومی زبان‌های غیرلاتین.

  • نام نمایشی می‌تواند گسترده باشد؛ نام کاربری/دامنه/شناسه سیاست محدودتر و هشدار شباهت می‌خواهد.
  • کنترل‌های Bidi غیرمنتظره در Source، Log و فیلد امنیتی شناسایی و قابل‌مشاهده شوند.
  • Placeholder ترجمه با Context مناسب Escape شود و HTML مترجم قابل‌اعتماد فرض نشود.
  • Resource bundle و TMS دسترسی، Audit trail و امضای Release داشته باشند.
  • Error بومی‌شده Secret، Stack، Token یا وجود حساب کاربری را افشا نکند.
  • Normalization پیش از Validation و پس از آن طبق ترتیب مستند و تست‌شده انجام شود.

مرز انسان و اتوماسیون در تست بومی‌سازی

کنترل مناسب ماشینداوری مناسب انسان
کلید مفقود/اضافی، Placeholder، Encoding، Schemaمعنای ترجمه، لحن و تناسب فرهنگی
Hardcoded text، API ممنوع، Property منطقی CSSخوانایی، سلسله‌مراتب بصری و طبیعی‌بودن UI
Formatter/Parser با Golden و boundary corpusقابل‌فهم‌بودن تاریخ، پول و پیام برای کاربر هدف
Pseudo-localization، screenshot diff، overflow heuristicتشخیص تغییر معنادار از اختلاف رندر بی‌اهمیت
E2E مسیر حیاتی با Locale/zone مشخصExploration، فناوری کمکی و رفتار فرهنگی پیچیده

Ruleهای قطعی مانند متن هاردکد و استفاده از left/right را با الگوی تحلیل استاتیک و Quality Gate خودکار کنید. بازبین انسانی نباید وقت خود را صرف تکرار خروجی Linter کند.

نمونه تست Locale با Playwright

مستند Emulation در Playwright تنظیم Locale و Timezone را در BrowserContext نشان می‌دهد. این قابلیت محیط را شبیه‌سازی می‌کند، اما برای نتیجهٔ مالی یا زمان کسب‌وکاری هنوز به Oracle مستقل نیاز دارید.

import { test, expect } from '@playwright/test';

test.use({
  locale: 'fa-IR',
  timezoneId: 'Asia/Tehran',
});

test('Persian checkout keeps rial semantics and RTL contract', async ({ page, request }) => {
  const order = await createOrder({ amountRial: 1_250_000 });
  await page.goto(`/checkout/${order.id}`);

  await expect(page.locator('html')).toHaveAttribute('lang', 'fa-IR');
  await expect(page.locator('html')).toHaveAttribute('dir', 'rtl');
  await expect(page.getByTestId('payable-amount'))
    .toHaveText('۱٬۲۵۰٬۰۰۰ ریال');

  await page.getByRole('button', { name: 'پرداخت' }).click();
  await completeSandboxPayment(order.id);

  const response = await request.get(`/test-support/orders/${order.id}`);
  expect(await response.json()).toMatchObject({
    status: 'PAID', amountRial: 1_250_000, ledgerEntries: 1
  });
});

در پروژهٔ واقعی، helperها باید دادهٔ یکتا، پاک‌سازی امن و هویت Run داشته باشند. برای جلوگیری از Abstractionهای مبهم، اصول کد تست قابل نگهداری را اعمال کنید.

معماری پیشنهادی Suite اتوماسیون

  1. Static: کلید، Placeholder، Hardcode، Encoding، Bidi control و CSS physical property؛
  2. Unit: Parser/Formatter، fallback، Normalization، plural/select و تبدیل دامنه؛
  3. Property/Fuzz: Unicode corpus، round-trip، طول و رشته‌های مختلط؛
  4. Component: pseudo locales، overflow، جهت، state و accessibility tree؛
  5. API/Contract: مدل canonical، Error code و نشت‌نکردن متن نمایش در قرارداد؛
  6. Visual: صفحات نماینده با OS/font/browser pin‌شده و Review انسانی؛
  7. E2E: تعداد کمی مسیر حیاتی در ترکیب‌های پرریسک؛
  8. LQA/Exploratory: بازبین بومی و سناریوهای تازه در نسخهٔ Candidate.

Screenshot را Oracle همه‌چیز نکنید. اختلاف Anti-aliasing می‌تواند نویز بسازد و در عین حال خطای Ledger را نبیند. «قرارداد کنترل و مشاهده» در راهنمای تست‌پذیری نرم‌افزار به طراحی seamهای Locale، clock و evidence کمک می‌کند.

ماتریس عملی فارسی و بازار ایران

ریسکداده/محرکOracle اصلیسطح
ی/ک عربی و فارسیچهار ترکیب در نام و Searchسیاست Normalization + حفظ متن اصلیUnit/API
ZWNJ و فاصله«می‌شود»، «می شود»، «میشود»Search contract و نمایش بدون خرابیUnit/Search
سه مجموعه رقم۱۲۳، ۱۲۳، ۱۲۳ و مخلوطپذیرش/رد و canonical value صریحUnit/Component
Bidi شناسهمتن فارسی + AB-123DOM isolate، visual و ClipboardComponent/E2E
ریال/تومان۱۲۵٬۰۰۰ تومان۱٬۲۵۰٬۰۰۰ IRR در API/LedgerAPI/E2E
نیمه‌شب تهرانInstant دو سوی مرز روزLocal date طبق Asia/TehranUnit/API
تقویم شمسیپایان اسفند/سال کبیسهکتابخانه/قرارداد نسخه‌دار و round-tripUnit
callback تکراری پرداختدو callback با authority یکسانیک Payment، Ledger و fulfillmentIntegration/E2E
PDF فارسیجدول، عدد و شناسه LTRFont embedded، متن قابل‌استخراج، visualIntegration/Manual
Locale leakageدو کاربر fa/en پشت cacheپاسخ هر کاربر مطابق preference خودشIntegration/Security

عیب‌یابی شکست‌های i18n و L10n

نشانهعلت محتملشاهد بعدی
کلید خام دیده می‌شودBundle ناقص، namespace یا fallbackresource version، key lookup trace
فقط CI متن متفاوت داردنسخه CLDR/ICU، OS، font یا timezoneimage/runtime/tzdata/font identity
تاریخ یک روز جابه‌جا استUTC/local، parse بدون zone یا calendarraw instant، zone، calendar و formatter
جست‌وجوی «ی» نتیجه نداردNormalization/Index ناسازگارcode points، analyzer و index version
پرانتز/شناسه برعکس استنبود base direction یا isolationDOM lang/dir/bdi و clipboard text
مبلغ ده برابر استتبدیل دوباره یا واحد ضمنیvalue+unit در هر hop و ledger
ترجمه کاربر دیگری دیده می‌شودcache key فاقد Locale/tenantrequest headers، cache key، user preference
Screenshot شکست خورده ولی UI سالم استfont/anti-aliasing محیطpixel diff، font hash و semantic assertions

گزارش شکست باید Locale resolved، منبع انتخاب، timezone، calendar، numbering system، resource version، tzdata/ICU/CLDR، browser/OS، run ID و دادهٔ حساس‌زدایی‌شده را ثبت کند.

حاکمیت و مالکیت کیفیت بومی‌سازی

  • Product/Market owner: بازار، واحد، محتوای حقوقی و ریسک پذیرفته‌شده؛
  • Engineering: قرارداد canonical، fallback، formatter/parser و observability؛
  • Design: Layout انعطاف‌پذیر، typography و componentهای bidirectional؛
  • Localization/Linguist: واژه‌نامه، لحن، Context و LQA؛
  • QA: ماتریس ریسک، Oracle، coverage و evidence؛
  • Security/Accessibility: کنترل‌های تخصصی برای جریان‌های مربوط؛

هر Locale یک DRI، وضعیت Launch و Exit criteria می‌خواهد. «ترجمه ۱۰۰٪» به معنی آمادگی انتشار نیست؛ ممکن است همهٔ کلیدها ترجمه شده باشند اما پرداخت، Screen Reader یا PDF کار نکند.

معیارهایی که واقعاً کمک می‌کنند

  • نرخ کلید مفقود و Fallback در Runtime، به تفکیک Locale و صفحه؛
  • نقص‌های تولید بر اساس دسته: معنا، جهت، قالب، Parser، داده، cache یا accessibility؛
  • زمان رفع نقص Locale و سهم Reopen؛
  • پوشش جریان‌های پرریسک در برابر ماتریس، نه تعداد کل Screenshot؛
  • نرخ شکست Pseudo-localization و Placeholder gate؛
  • اختلاف نسخه Resource/CLDR/ICU/tzdata بین محیط‌ها؛
  • درصد Visual diffهای معنادار در برابر نویز؛
  • سن و مالک Gapهای پذیرفته‌شدهٔ هر بازار.

تعداد کلمات ترجمه‌شده و درصد Automation شاخص ظرفیت‌اند، نه کیفیت. آن‌ها را بدون Defect، Risk coverage و تجربهٔ کاربر به KPI موفقیت تبدیل نکنید.

برنامهٔ ۳۰روزهٔ اجرای تست فارسی و RTL

هفتهٔ اول: قرارداد و Baseline

جریان‌های ورود، جست‌وجو، پرداخت، گزارش و اعلان را فهرست کنید. Locale contract، ترتیب انتخاب/fallback و مالک ریال/تومان، زمان و Normalization را تصویب کنید. پنج نقص اخیر را دسته‌بندی کنید.

هفتهٔ دوم: Gateهای ارزان

بررسی کلید/Placeholder، UTF-۸، متن هاردکد، CSS physical property و pseudo locales را به CI اضافه کنید. Corpus فارسی شامل ی/ک، ZWNJ، سه مجموعه رقم و متن Bidi بسازید.

هفتهٔ سوم: Oracleهای دامنه

Unit testهای زمان/پول/Normalization و Contract testهای API را تکمیل کنید. دو E2E حیاتی با Locale و timezone مشخص بسازید و نتیجهٔ مالی/داده‌ای را جدا از متن UI Assert کنید.

هفتهٔ چهارم: LQA و بازخورد تولید

یک LQA با متخصص فارسی و تست فناوری کمکی انجام دهید. Telemetry امن برای fallback و Locale resolution را بررسی، داشبورد متوازن را راه‌اندازی و Gapها را با Owner و تاریخ انقضا ثبت کنید.

اشتباهات رایج در تست i18n و L10n

  • یکی‌گرفتن Language، Locale، Region، Direction، Calendar و Timezone؛
  • اعلام «پشتیبانی فارسی» فقط به دلیل UTF-۸ یا یک صفحهٔ RTL؛
  • راست‌چین‌کردن با CSS بدون lang/dir معنایی؛
  • تبدیل همهٔ رقم‌ها و شناسه‌ها به فارسی بدون قرارداد فیلد؛
  • نگاشت کور ی/ی و ک/ک روی Password، Token یا شناسه؛
  • استفاده از offset ثابت به جای Asia/Tehran و tzdata؛
  • واگذاری ریال/تومان به Formatter و نبود واحد در API/Log؛
  • اتصال تکه‌رشته‌ها و شرط جمع مخصوص انگلیسی؛
  • Fallback ساکت که ترجمهٔ گم‌شده را تا تولید پنهان می‌کند؛
  • ماتریس Cartesian عظیم بدون اولویت ریسک؛
  • Screenshot به‌عنوان تنها Oracle و ذخیره Baseline روی محیط ناپایدار؛
  • فرض اینکه مترجم بومی همهٔ نقص‌های فنی را می‌یابد؛
  • تست فقط Web و فراموشی SMS، PDF، CSV، Search و Log؛
  • استفاده از PII واقعی در Screenshot/Trace؛
  • اعلام آمادگی بازار بر اساس «۱۰۰٪ ترجمه».

چک‌لیست نهایی انتشار Locale

  1. Language Tag استاندارد، جهت و ترتیب انتخاب/fallback نسخه‌دار است.
  2. مدل canonical از نمایش تاریخ، عدد و پول جداست.
  3. UTF-۸ در Web/API/DB/Queue/Export round-trip شده است.
  4. سیاست NFC و نگاشت‌های دامنه‌ای فارسی با مرز روشن تست شده‌اند.
  5. ی/ی، ک/ک، ZWNJ، سه مجموعه رقم و متن Bidi در Corpus هستند.
  6. CSS منطقی، DOM/Focus و Componentهای RTL بررسی شده‌اند.
  7. زمان با Instant، Calendar، Asia/Tehran و tzdata نسخه‌دار سنجیده شده است.
  8. ریال/تومان در هر hop واحد صریح و Oracle مالی مستقل دارد.
  9. Placeholder، plural/select، missing key و pseudo locale Gate دارند.
  10. فرم، Search، Sort، PDF، CSV، Email/SMS و Notification پوشش متناسب دارند.
  11. LQA فارسی، دسترس‌پذیری و امنیت Unicode انجام شده‌اند.
  12. گزارش اجرا Locale/resource/runtime identity و دادهٔ امن دارد.
  13. Gap باقی‌مانده Owner، اثر و تاریخ بازنگری دارد.

پرسش‌های متداول

تفاوت تست i18n و L10n چیست؟

تست i18n انعطاف معماری برای زبان، خط، Locale، قالب و جهت‌های مختلف را می‌سنجد؛ تست L10n درستی ترجمه، قالب، محتوا و تجربهٔ یک بازار مشخص مانند فارسی ایران را بررسی می‌کند. اولی زیرساخت عمومی را هدف می‌گیرد و دومی کیفیت تطبیق واقعی را؛ هیچ‌کدام جای دیگری نیست.

آیا fa-IR به‌تنهایی تقویم شمسی و منطقهٔ زمانی تهران را تعیین می‌کند؟

خیر. fa-IR Language Tag است، اما Calendar، Timezone، Numbering system و ترجیح کاربر باید جداگانه در قرارداد و Runtime حل شوند. کاربر فارسی ممکن است خارج ایران باشد یا تقویم میلادی بخواهد. مقدار resolved هر بُعد را در شواهد تست ثبت کنید.

برای فارسی، ی و ک عربی را همیشه باید به فارسی تبدیل کنیم؟

نه به‌صورت جهانی. برای Search نام یا متن نمایشی می‌توان یک نگاشت دامنه‌ای مصوب داشت، ولی Password، Token، امضا و شناسهٔ قراردادی ممکن است Exact match بخواهند. متن اصلی را در موارد لازم حفظ و نسخهٔ canonical را جدا تعریف کنید.

چگونه ریال و تومان را تست کنیم؟

مقدار و واحد را در هر مرز—UI، API، Database، Queue و Ledger—صریح کنید. سناریو باید تبدیل دقیق یک‌باره، جداکننده، ارقام، حدها، Refund و اثر مالی را بسنجد. Assertion متن «تومان» بدون Oracle روی مقدار canonical و Ledger کافی نیست.

آیا اتوماسیون و شبه‌بومی‌سازی جای بازبین فارسی‌زبان را می‌گیرند؟

خیر. ماشین کلید مفقود، Placeholder، Overflow، Parser، جهت و Regression را سریع پیدا می‌کند؛ انسان معنا، لحن، حساسیت فرهنگی، خوانایی و تجربه را داوری می‌کند. بهترین استراتژی، Gateهای خودکار ارزان در هر تغییر و LQA انسانی هدفمند پیش از انتشار است.

جمع‌بندی: Locale را به یک قرارداد قابل‌آزمون تبدیل کنید

تست بومی‌سازی با ترجمهٔ چند صفحه تمام نمی‌شود. Language Tag، جهت، Unicode، Normalization، ورودی، Search، تقویم، زمان، پول، کانال و Resource version باید از مدل canonical تا تجربهٔ کاربر قابل‌ردیابی باشند. برای ایران، ی/ک، نیم‌فاصله، سه مجموعه رقم، Bidi، تقویم شمسی، Asia/Tehran و مرز ریال/تومان سناریوهای درجه‌یک‌اند، نه جزئیات ظاهری.

از یک جریان پرریسک مانند پرداخت شروع کنید: قرارداد Locale را بنویسید، Corpus فارسی بسازید، Oracle UI را به API/Ledger وصل کنید و Pseudo-RTL را در CI اجرا کنید. وقتی هر شکست Locale identity، نسخه و شاهد قابل‌بازتولید داشته باشد، تیم به‌جای شکار Screenshotهای پراکنده می‌تواند درباره ریسک انتشار تصمیم بگیرد.

این مقاله را با دیگران به اشتراک بگذارید

نویسنده

محمد عسکری

محمد هستم، توسعه‌دهنده وب با بیش از ده سال تجربه در برنامه‌نویسی سمت سرور و کاربر. به یادگیری و اشتراک‌گذاری دانش علاقه‌مندم و اخیراً تمرکزم را روی حوزه تست نرم‌افزار گذاشته‌ام تا تجربیاتم را در این زمینه نیز به اشتراک بگذارم و به درک بهتر کیفیت نرم‌افزار کمک کنم.

همه مقاله‌ها

ادامه مطالعه

دیدگاهتان را بنویسید

ایستگاه بعدی شما

TestRail را همین حالا در محیط دمو ببینید.

محیط تست آماده

دسترسی به دمو TestRail

قبل از ورود، مشخصات زیر را در صفحه ورود محیط دمو وارد کنید.

آدرس دمو

https://demo.testrail.ir

ایمیل ورود

demo@testrail.ir

رمز عبور

demo_user