ترجمه یک فایل دوم است
جفت hreflang یعنی همین نام فایل در پوشهی زبان دیگر. بایگانی برچسب فقط وقتی ایندکس میشود که نامش در tagPairs باشد.
ترجمهی یک نوشته در این سایت یک پرچم روی همان صفحه نیست. یک فایل مارکداون دوم است، با همان نام، در پوشهی زبان دیگر. اگر آن فایل نباشد، سرصفحه ادعای hreflang نمیکند و دکمهی زبان به فهرست وبلاگ زبان دیگر میرود. آدرس فارسی و آدرس انگلیسی از اول جدا هستند: /fa/ و /en/.
یادداشت کوتاه راستبهچپ را از روز اول بگذار خوشهی همین موضوع است. دو مسیر، نه یک صفحهی وارونه همان مسیر را با فونت و تقویم طی میکند. این یکی روی قرارداد آدرس میماند: چه چیزی جفت حساب میشود، و چه چیزی عمداً جفت نمیشود.
ساخت، نه تعویض در مرورگر
src/pages/[lang]/ هر صفحهی عمومی را برای fa و en جدا میسازد. خانه، وبلاگ، پروژهها، درباره، و همکاری هر کدام lang را از مسیر میگیرند. متن رابط از src/i18n/ui.ts میآید، موقع ساخت صفحهی استاتیک. دیکشنریای نیست که بعد از بار شدن صفحه در مرورگر عوض شود.
نوشتهها در src/content/blog/fa و src/content/blog/en هستند. نام فایل، بدون پسوند، همان نامک است. getStaticPaths در مسیر نوشته نامکهای زبان دیگر را جمع میکند. hasTwin یعنی آن نام در آن جمع باشد.
فایدهی دو فایل فقط پرچم زبان نیست. یک جمله در انگلیسی کوتاه است و در فارسی بلند. اگر هر دو یک HTML بودند، طول سطرها با هم دعوا میکردند. اینجا شریک نمیشوند. جهت صفحه هم جای این دو فایل را نمیگیرد. جهت صفحه همهی کار را نمیکند میگوید dir چه را عوض نمیکند. رقم هم از مسیر جدا میآید، نه از یک سند مشترک. آن جزئیات در رقم فارسی یک ویژگی فونت نیست است.
سرصفحه فقط وقتی جفت واقعی باشد
Base.astro برای صفحهای که alternate روشن باشد سه لینک میگذارد: hreflang خود صفحه (fa-IR یا en-US)، زبان مقابل، و x-default روی آدرس فارسی. alternate برای نوشته برابر hasTwin است.
اگر جفت باشد، altPath آدرس همان نامک در زبان دیگر است و دکمهی زبان به ترجمه میرود. اگر جفت نباشد، altPath فهرست وبلاگ زبان دیگر است و alternate خاموش است. سرصفحه آنوقت ادعای ترجمه ندارد. og:locale:alternate هم همان شرط را دارد.
نام جفت یعنی فایل انگلیسی که ترجمه است. کپی مارکداون فارسی در پوشهی انگلیسی، با همان جملهها، ترجمه نیست. این سه نوشته هر کدام یک فایل فارسی و یک فایل انگلیسی با همین نام دارند، پس این قرارداد برایشان روشن است. خوراک هم جداست: هر زبان /${lang}/rss.xml خودش را در سرصفحه اعلام میکند. آن خوراک ترجمهی خوراک دیگر نیست. فهرست نوشتههای همان زبان است.
نقشهٔ سایت سختگیرتر از دکمه است
نقشهٔ سایت ریشهی / را برمیدارد، مسیر /og/ را برمیدارد، و rss.xml را هم برمیدارد. هر زبان خوراک خودش را دارد و آن خوراک در نقشه نیست.
برای بقیهی صفحهها، اگر هر دو زبان در لینکهای نقشه باشند، x-default به آدرس فارسی اضافه میشود. اگر یکی از fa-IR یا en-US نباشد، لینکهای جایگزین پاک میشوند. یک زبان تنها، در نقشه، ترجمهی غایب را تبلیغ نمیکند.
صفحهی ۴۰۴ جداست. زبانش فارسی است، noindex است، و alternate ندارد. خانهی هیچکدام از دو زبان نیست. پروژهای که مطالعهی موردی ندارد هم از نقشه کنار میرود، مگر صفحهی کارکیا. این قاعده به ترجمه مربوط نیست. میگوید نقشه فقط آدرسهایی را نگه میدارد که صفحهی واقعی و قابل معرفی باشند.
برچسب نوشته با جفتِ نوشته یکی نیست
بایگانی برچسب فقط وقتی ایندکس میشود که نامش در tagPairs باشد، هر دو طرف معرفی چندجملهای داشته باشند، و فهرست برچسب زیرمجموعهی واقعی وبلاگ باشد نه کپی تمام فهرست. جفتهای فهرستشده امروز اینها هستند: راستبهچپ با rtl، تایپوگرافی با typography، اعداد با numerals، فارسی با persian، دوزبانه با bilingual، خواندن با reading، سرعت با performance، حرکت با motion، و ایستا با static.
نامهایی که در آن جدول نیستند noindex میمانند و به نقشهٔ سایت نمیرسند، حتی اگر واژهی انگلیسی ترجمهی نام فارسی باشد. تمرکز و focus، سهبعدی و webgl، و برچسبهای تکی وب، web، طراحی، و design در همین گروه میمانند. صفحهی خود نوشته همچنان با نامک جفت میشود. بایگانی برچسب این کار را خودکار انجام نمیدهد.
اگر دو برچسب فقط با عوض کردن پیشوند زبان به هم وصل میشدند، بایگانی فارسی به یک آدرس انگلیسی بیمعنی اشاره میکرد. کد این کار را نمیکند. pairedTag فقط همان جدول را میشناسد. لینک برچسب روی خود نوشته هنوز کار میکند و به /fa/blog/tags/…/ یا /en/blog/tags/…/ میرود. ایندکس نشدن بایگانی، با وجود خود صفحه فرق دارد.
پالت هر دو درخت را دارد و صفحه را یکی نمیکند
Base.astro هنگام ساخت، فهرست پالت فرمان را از هر دو زبان پر میکند: صفحههای ثابت، و عنوان هر نوشته. هر ردیف زبان و آدرس خودش را دارد. گفتوگو dir="ltr" است. لینک نتیجه dir="auto" میگیرد تا عنوان فارسی، داخل فهرستی که جهت سندش لاتین است، جهت خودش را حفظ کند.
این فهرست ترجمهی لحظهای یک صفحه نیست. دو درخت از پیش ساختهشده کنار هماند. انتخاب یک ردیف به آدرس همان زبان میرود، نه اینکه dir صفحهی فعلی را عوض کند. اگر نوشتهای جفت نداشته باشد، باز هم عنوانش در زبان خودش در فهرست هست. پالت ادعای hreflang نمیکند. فقط لینک میدهد.
trailingSlash همیشه روشن است، پس آدرس نوشته با اسلش تمام میشود. مبدأ سایت https://mh-honarvar.github.io است و لینک hreflang با همین مبدأ مطلق میشود. یک نامک مشترک بدون اسلش، با آدرسی که قالب میسازد یکی نیست.
ریشه خانهی سوم نیست
/ یک صفحهی محتوا نیست. noindex, follow است. نشانی متعارفش https://mh-honarvar.github.io/fa/ است. بدون اسکریپت، noscript به /fa/ برمیگردد. با اسکریپت، اگر navigator.language با fa شروع شود مقصد /fa/ است و وگرنه /en/. زبان سند روی خود ریشه fa است، بدون dir. جهت راستبهچپ از صفحهی /fa/ میآید، نه از این ایستگاه.
دو لینک ساده روی همان صفحه هست، یکی به فارسی و یکی به انگلیسی، برای وقتی اسکریپت اجرا نشود و تازهسازی noscript هم دیده نشود. هیچکدام از اینها نسخهی سوم خانه نیستند. خانه همان /fa/ یا /en/ است، با متن خودش.
همکاری هم یک مسیر است
/fa/services/ و /en/services/ دو صفحه با متن خودشاناند، نه یک نوشتهی وبلاگ که نامک مشترک داشته باشد. در فهرست ناوبری سرصفحه نیستند. از پاپیچ و از متن به آنها میرسد. صفحهی همکاری میگوید چه کاری خوشامد است و چه چیزی خصوصی میماند. تنها تماس عمومی تلگرام است، @MH759.
اگر یک چیز بماند این است: ترجمهی قابل اعلام، فایلی است که واقعاً آنجاست. نامک مشترک برای نوشته کافی است. برای برچسب، نه، تا وقتی نامش در جدول جفتها نباشد.