وب مدرن، رابط کاربری و تجربهی وب · فصل ۷ — Locale، Translation Memory و QA · 56
ICU MessageFormat و Locale-aware Formatting
syntax یا framework را میشناسد اما contract، runtime behavior، accessibility و failure boundary را یکپارچه نمیکند. موضوع جاری: «ICU MessageFormat و Locale-aware Formatting». میتواند «ICU MessageFormat و Locale-aware Formatting» را در یک feature محدود طراحی/پیادهسازی کند و correctness، accessibility یا failure behavior مرتبط را اثبات کند.
خلاصهٔ درس
syntax یا framework را میشناسد اما contract، runtime behavior، accessibility و failure boundary را یکپارچه نمیکند. موضوع جاری: «ICU MessageFormat و Locale-aware Formatting».
میتواند «ICU MessageFormat و Locale-aware Formatting» را در یک feature محدود طراحی/پیادهسازی کند و correctness، accessibility یا failure behavior مرتبط را اثبات کند.
خروجی این درس
میتواند «ICU MessageFormat و Locale-aware Formatting» را در یک feature محدود طراحی/پیادهسازی کند و correctness، accessibility یا failure behavior مرتبط را اثبات کند.
پیشنیازها
۱. صفحه اول: درست بودن جمله انگلیسی یعنی درست بودن قرارداد پیام نیست
فرض کنید خلاصه پرداخت در انگلیسی مینویسد «۳ قلم انتخاب شد، مبلغ ۱٬۲۴۹٫۵۰ دلار و سررسید ۱۸ سپتامبر ۲۰۲۶». خروجی در سیستم توسعهدهنده طبیعی به نظر میرسد، اما جمله از چند تکه ساخته شده، جمع با شرط count === 1 تعیین شده، جداکنندههای عدد و نماد ارز دستیاند و تاریخ با الگوی انگلیسی تولید میشود. مسئله صرفاً ترجمه نیست؛ داده دامنه، تصمیم دستوری، قالببندی محلی و ترتیب جمله در یک میانبُر وابسته به زبان مبدأ قاطی شدهاند.
خروجی محدود این درس ساخت یک قرارداد پیام locale-aware قابل بازرسی است. متن کاربرپسند همراه متغیرها باید یک واحد پیام منسجم بماند تا مترجم بتواند جای متغیرها را مطابق دستور زبان مقصد جابهجا کند. انتخاب plural/select باید به قواعد locale سپرده شود و عدد، ارز، تاریخ و زمان در لبه نمایش با formatter مناسب locale ساخته شوند. راهنمای ICU دقیقاً روی همین حفظ context برای مترجم تأکید میکند. [S-ICU-MSG] راهنمای formatting در ICU نیز داده داخلی را از نمایش محلی جدا میکند. [S-ICU-FMT]
Artifact درس Locale-Aware Message Contract Record v1 است. در آن message key، متغیرها، locale، دسته plural مورد انتظار، مقادیر formatشده، خروجی مشاهدهشده، mutation، repair و محدودیت باقیمانده ثبت میشوند. قبولی fixture آموزشی فقط همین قرارداد محدود را در محیط ثبتشده اثبات میکند؛ نه اینکه همه runtimeها و libraryها دقیقاً یک syntax یا behavior داشته باشند.
۲. مسیر یادگیری: میتوان توضیح مقدماتی را کم کرد، evidence را نه
در مسیر پایه، از matrix پیام شروع کنید. count، amount و dueDate را دادههای locale-neutral فرض کنید. برای هر locale ابتدا plural category را پیشبینی کنید، بعد currency و date format را ببینید و در آخر جمله نهایی را بررسی کنید. این ترتیب اجازه نمیدهد یک خروجی «ظاهراً ترجمهشده» جای چند قرارداد مستقل را بگیرد.
در مسیر repair، یک regression عمدی را انتخاب کنید: message unit را به fragmentهای concatenateشده تبدیل کنید، separator را hard-code کنید یا plural را به منطق انگلیسی one/other تقلیل دهید. قبل از اجرا مشخص کنید کدام evidence باید fail شود، سپس فقط همان boundary را repair کنید.
در مسیر experienced، fixture را مانند یک localization contract review کنید: آیا placeholderها قابل جابهجاییاند؟ انتخاب plural واقعاً locale-aware است؟ display valueها از formatter محلی میآیند؟ runtime/version مشخص است؟ و evidence بیش از یک locale را پوشش میدهد؟ تجربه میتواند توضیح را کوتاه کند، اما mutation و transfer و residual limitation حذف نمیشوند.
۳. مدل ذهنی: یک pipeline با چند قرارداد مستقل
pipeline را اینطور نگه دارید:
domain value → locale + message key → locale-aware selection → locale formatter → rendered message → contrasting-locale evidence
Message unit مالک context دستوری است. جمله یا عبارت کامل باید در اختیار مترجم باشد تا placeholderها را جابهجا کند. اگر متن از fragmentهای کوچک ساخته شود، مترجم الزاماً context کافی برای ترتیب و صرف درست ندارد. [S-ICU-MSG]
Selection contract مالک انتخاب variant است. plural category داده locale است، نه یک شرط انگلیسی. زبان مقصد ممکن است دستههایی داشته باشد که در انگلیسی وجود ندارند. برنامه باید operand و locale را به مکانیزم locale-aware بدهد و resource باید variantهای لازم را داشته باشد.
Formatter contract مالک نمایش مقدار است. عدد، timestamp و amount باید بهصورت domain value باقی بمانند و در مرز نمایش format شوند. ICU برای عدد، ارز، تاریخ، زمان و message سرویسهای locale-sensitive ارائه میکند تا code و presentation از هم جدا بمانند. [S-ICU-FMT]
Version boundary مالک ادعای compatibility است. Unicode MessageFormat که در دوره توسعه با نام MessageFormat 2 شناخته میشد، امروز بخشی پایدار از UTS #35 است؛ اما سطح پشتیبانی implementationها همچنان به runtime و version وابسته است. مستندات ICU برای MessageFormatter هنوز این سطح را implementation/version-bounded معرفی میکند. پس stable بودن spec مساوی universal runtime support نیست. [S-MF2]
۴. لایه پایه: ابتدا message را منسجم نگه دارید
کدی مانند prefix + count + noun + suffix حتی با ترجمه شدن هر fragment، sentence structure را در اختیار مترجم نمیگذارد. ممکن است آلمانی تاریخ را زودتر بخواهد، عربی variantهای بیشتری برای count داشته باشد یا زبان دیگری رابطه دستوری متغیر و noun را تغییر دهد. default امن، fragment بیشتر نیست؛ یک message کامل با placeholder است.
یکپارچگی message نباید domain data را به text تبدیل کند. count = 3، amount = 1249.5 و dueDate = 2026-09-18 باید مقدارهای قابل محاسبه و قابل انتقال باقی بمانند. message layer فقط در زمان نمایش، locale و message key را همراه این مقدارها میگیرد و display string را تولید میکند.
بهصورت پیشفرض localized string را دوباره به domain value parse نکنید. رشتهای مثل 1.249,50 € presentation است، نه serialization قابل اتکا. همین منطق درباره تاریخ نمایشی نیز صدق میکند.
۵. توضیح عمیق: plural یک جدول دستوری وابسته به locale است
مثالهای انگلیسی ذهن را به مدل دوشاخهای عادت میدهند؛ one و other کافی به نظر میرسد. این مدل عمومی نیست. plural system دسته را با قواعد locale انتخاب میکند. وظیفه برنامه این است که عدد و locale را بدهد؛ وظیفه message resource این است که variantهای مورد نیاز locale را فراهم کند.
fixture این درس از Intl.PluralRules، Intl.NumberFormat و Intl.DateTimeFormat بهعنوان teaching primitiveهای deterministic استفاده میکند. این انتخاب به معنی پیادهسازی کامل ICU MessageFormat نیست. Lab عمداً contract evidence را از syntax compatibility evidence جدا میکند. ما ثابت میکنیم message unit، plural selection و locale formatter برای سه fixture ثبتشده درست عمل میکنند. اگر محصول شما ICU4J، ICU4C، JavaScript MessageFormat یا Unicode MessageFormat دارد، باید همان runtime/library/version واقعی جداگانه تست شود.
selectهای keyword-based نیز همین قاعده را دارند. اگر plan type یا status variant جمله را انتخاب میکند، selection باید در message contract باشد، نه اینکه fragmentهای sentence در business code چسبانده شوند.
۶. مثال کامل: checkout در انگلیسی، آلمانی و عربی
ورودی domain برای همه localeها یکسان است: item count، مبلغ USD و due date UTC. اما نمایش میتواند متفاوت باشد. en-US ممکن است گروهبندی با comma داشته باشد، de-DE separator و جای symbol دیگری داشته باشد و ar-EG ارقام، directionality و plural category متفاوت نشان دهد. exact output باید از runtime مشاهده و ثبت شود، نه از مقاله کپی شود.
هر evidence row شش چیز را جدا نگه میدارد: raw value، plural category، formatted amount، formatted date، rendered message و residual limitation. این تفکیک diagnosis را ممکن میکند. اگر category درست است ولی currency string دستی است، formatter contract fail شده. اگر formatted valueها درستاند ولی جمله عربی ترتیب fragment انگلیسی را دارد، message-unit contract fail شده.
ادعای دقیق این است: «در runtime ثبتشده، Intl.PluralRules برای locale و count مورد نظر category مشخصی داد؛ resource همان branch را داشت؛ formatterها valueهای مشاهدهشده را ساختند؛ و output از template یکپارچه locale ساخته شد.» نتیجه محدود است: «fixture محدود در همین محیط contract را حفظ کرد.»
۷. Failure modeهای پنهان
String concatenation: خروجی انگلیسی سالم میماند و bug تا زمان نیاز زبان مقصد به ترتیب دیگر دیده نمیشود.
Plural انگلیسی: شرط count === 1 همه زبانها را به مدل one/other فرو میکاهد و categoryهای لازم locale دیگر را از بین میبرد.
Formatting دستی: comma، decimal point، currency symbol یا نام ماه در code نوشته میشوند و presentation مبدأ جای data contract مینشیند.
Locale ضمنی: formatter با default ماشین اجرا میشود. نتیجه روی سیستم دیگر تغییر میکند ولی تست توسعهدهنده خبر نمیدهد.
Version overclaim: نمونه syntax جدید دیده میشود و بدون ثبت runtime/library/version فرض میشود deployment همان syntax را پشتیبانی میکند. maturity spec و implementation support دو fact جدا هستند.
Evidence تکlocale: قبولی انگلیسی correctness localization را اثبات نمیکند. matrix آموزشی عمداً en-US، de-DE و ar-EG را مقایسه میکند.
۸. پل برای برنامهنویس باتجربه: از API به قرارداد قابل audit
مهندس باتجربه احتمالاً Intl.NumberFormat، CLDR، ICU یا i18n framework را میشناسد. مهارت عمیقتر این است که code review بتواند دقیق جواب دهد: message کامل کجاست؟ چه variableهایی وارد آن میشوند؟ branch را چه چیزی انتخاب میکند؟ formatter هر value کدام است؟ چه runtimeی syntax را تفسیر میکند؟ کدام localeها واقعاً مشاهده شدهاند؟ کدام mutation عمداً fail شده است؟
برچسب معماری evidence نیست. «ما ICU داریم» کافی نیست. «ما MessageFormat 2 داریم» بدون نام implementation و version کافی نیست. «formatter محلی داریم» بدون locale مؤثر و output مشاهدهشده کافی نیست.
workflow مترجم، extraction، translation memory و terminology governance مهماند، اما مالک درس بعدیاند. این درس فقط boundary اجرای message و locale formatting را میبندد.
۹. Alternatives و trade-off
ICU MessageFormat قدیمی هنوز guidance و API بالغی دارد. Unicode MessageFormat استاندارد جدیدتری برای data model و syntax است. frameworkها ممکن است یکی از اینها را wrap کنند یا layer خودشان را داشته باشند. انتخاب صحیح به runtime واقعی، tooling مترجم، extraction pipeline، migration cost و ecosystem بستگی دارد.
این درس library واحدی را تجویز نمیکند. معیار تصمیم این است: message context حفظ شود، selection locale-aware باشد، valueها با formatter مقصد نمایش داده شوند، implementation/version صریح باشد و evidence روی localeهای متضاد ثبت شود. limitation باید نوشته شود، نه اینکه زیر نام API پنهان شود.
۱۰. تمرین هدایتشده و مستقل
تمرین هدایتشده: baseline را اجرا کنید. قبل از اجرا category و تفاوت formatting در en-US، de-DE و ar-EG را پیشبینی کنید. سپس mutationی اجرا کنید که message-unit requirement را خاموش کند یا branch عربی لازم را حذف کند. audit باید issue code مشخص بدهد. repair را انجام دهید و rerun کنید.
تمرین مستقل: subscription renewal notice با plan name، renewal date، price و seat count برای locale جدید. wording checkout را کپی نکنید. فقط method را منتقل کنید: message unit، variableها، locale، selection rule، formatter، evidence case، version boundary و residual limitation.
۱۱. Verification و evidence: مشاهده را از inference جدا کنید
در Locale-Aware Message Contract Record v1 برای هر case، locale، input، selected category، formatted values، rendered message و source evidence ثبت میشود. mutation section شامل predicted failure، issue code، diagnosis، repair و rerun است. transfer section باید مشخص کند learner بدون decisive scaffold مسئله جدید را حل کرده است.
Observation: «بعد از حذف branch few عربی، audit کد PLURAL_CATEGORY_COVERAGE داد.» Inference: «resource دیگر category لازم برای fixture ثبتشده را ندارد.» Decision: «branch locale-owned را برگردان و rerun کن.» Residual limitation: «این fixture کیفیت ترجمه انسانی، همه localeها یا compatibility یک ICU/MessageFormat runtime تستنشده را اثبات نمیکند.»
۱۲. Assessment و transfer
باید بتوانید core contract و یک non-goal را بیان کنید، feature محدود را پیاده کنید، mutation را diagnose کنید، mechanism را در برابر alternative دفاع کنید و method را به context جدید منتقل کنید. failهای blocking عبارتاند از: mutation بحرانی شناسایی نشود، نام API جای evidence بنشیند، prerequisite نادیده گرفته شود یا compatibility تستنشده ادعا شود.
تصمیم نهایی مسئولانه انسانی است. AI میتواند بعد از تعریف contract پیشنهاد check بدهد، اما حق ندارد localized output مشاهدهنشده، feedback مترجم، runtime support یا acceptance evidence بسازد.
۱۳. منابع و freshness
S-ICU-MSG — مستندات ICU درباره Formatting Messages، message unit منسجم، جابهجایی variable توسط مترجم و plural/select. [S-ICU-MSG]
S-ICU-FMT — مستندات ICU درباره locale-sensitive formatting برای number/currency/date/time/message و جداسازی program data از presentation. [S-ICU-FMT]
S-MF2 — مستندات Unicode MessageFormat درباره successor syntax/data model و integration surface. freshness review فعلی ثبت میکند که specification در UTS #35 Part 9 پایدار است، اما support runtime/library باید جداگانه و version-bounded بررسی شود. [S-MF2]
مرز freshness تغییر نکرده است. review_due برابر 2026-10-17 است یا زودتر اگر guidance رسمی، status implementation یا behavior fixture تغییر کند. این درس universal production support برای یک syntax واحد در همه implementationها ادعا نمیکند.
ارزیابی
پاسخنامهی این درس در بستهی آموزش وجود ندارد؛ خودت جواب بده و صادقانه علامت بزن. «نیاز به مرور» درس را به صف تکرار میفرستد.
WEB-020-S1 retrieval
قرارداد پیام locale-aware را بیان کنید: message unit منسجم، plural/select وابسته به locale و قالببندی مقادیر با locale صریح؛ یک non-goal را نیز نام ببرید.
WEB-020-S2 application
fixture محدود locale-aware را برای en-US، de-DE و ar-EG با plural، number/currency و date formatting وابسته به locale صریح پیادهسازی کنید و evidence record را کامل کنید.
WEB-020-S3 diagnosis
یک mutation عمدی در placeholderهای message unit، plural category، locale binding، formatter behavior، مرز نسخه MessageFormat یا integrity شواهد را پیشبینی، اجرا، diagnose و repair کنید.
WEB-020-S4 decision
مکانیزم انتخابی message/formatter را در برابر یک shortcut محتمل دفاع کنید و مرز runtime/version و residual limitation را صریح بیان کنید.
WEB-020-S5 transfer
مسئله changed-context تمدید اشتراک را برای pl-PL با نام پلن، تاریخ تمدید، قیمت و تعداد seat مستقل حل کنید، بدون کپی کردن wording سناریوی checkout.
ملاکهای ارزیابی (rubric)
Critical dimensions:
- MESSAGE_UNIT — Variable-bearing learner-visible text remains one coherent translatable message unit; unsafe concatenation fails.
- PLURAL_SELECT — Plural/select behavior is delegated to locale-aware rules; an English one/many shortcut is not universal evidence.
- LOCALE_FORMATTERS — Number/currency/date formatting is explicitly locale-sensitive while domain values remain locale-neutral.
- MF_VERSION_BOUNDARY — Stable Unicode MessageFormat specification status is kept distinct from runtime/library implementation support; actual runtime/version claims must be bounded.
- EVIDENCE_MATRIX / TRANSFER — Contrasting locale fixtures, mutation/repair and an independent changed-context transfer are required; deterministic Node Intl evidence does not prove universal ICU or MF2 runtime support.
Blocking assessments: S2, S3 and S5. S1 and S4 are non-blocking but must preserve the observation/inference and runtime/version boundaries.
The internal synthetic oracle is admin/audit material and is not published as learner evidence.
منابع و تازگی
مطالعهٔ موارد (case studies)
فایلهای آزمایشگاه
رسانه و اسلایدهای درس
فایلهای آموزشی (دانلود)