BookTranslator
BookTranslator

چگونه یک فایل HTML را بدون شکستن تگ‌ها، ویژگی‌ها یا پیوندها ترجمه کنیم

چه چیزی را در یک فایل HTML ترجمه کنید، چه چیزی را دست نزنید، و چگونه آن را بررسی کنید. همراه با یک صفحه نمونه، یک بررسی‌کننده رایگان، و یک آزمون ۹ باره با مدل زبانی محلی.

BookTranslator

BookTranslator Team

15 دقیقه مطالعه

برای ترجمه یک فایل HTML، متنی را که مردم می‌خوانند و ویژگی‌هایی را که حاوی کلمات خواندنی برای خواننده هستند، مانند alt، title، placeholder، aria-label و توضیحات متای صفحه، ترجمه کنید. نشانه‌گذاری را دست نزنید: نام تگ‌ها، href، src، id، class، اسکریپت‌ها، استایل‌ها و هر چیزی که با translate="no" علامت‌گذاری شده است. سپس یک مقدار را که فراموش کردنش آسان است تغییر دهید، ویژگی lang روی عنصر <html>، تا مرورگرها، صفحه‌خوان‌ها و موتورهای جستجو بدانند صفحه اکنون به چه زبانی است.

حفظ سالم تگ‌ها در نهایت بخش آسان ماجرا بود. ما یک صفحه راهنمای HTML ۵۹ خطی را نه بار با یک مدل محلی به چینی ساده‌شده ترجمه کردیم، با استفاده از سه روش، و هر خروجی را با یک اسکریپت بررسی کردیم. هر اجرا همه تگ‌ها، پیوندها و شناسه‌ها را حفظ کرد. آنچه اشتباه پیش رفت آرام‌تر بود: مدل یک خط داخل یک بلوک کد <pre> را در هر شش اجرایی که کل فایل را فرستادند ترجمه کرد، aria-label ناوبری را در هر شش اجرا به انگلیسی باقی گذاشت، و روشی که به‌طور طراحی‌شده نشانه‌گذاری را ایمن‌ترین نگه می‌دارد، یعنی ترجمه تکه‌های متن یکی‌یکی، جمله‌ای تولید کرد که به خواننده می‌گفت کار اشتباهی انجام دهد، در هر سه اجرای خود.

پاسخ سریع: چه چیزی را ترجمه کنید و چه چیزی را دست نزنید

بخشی از فایلنمونه‌ای از صفحه نمونه ماترجمه شود؟
متن قابل مشاهدهسرتیترها، پاراگراف‌ها، سلول‌های جدول، متن پیوند، <label>بله
<title> و توضیحات متا<title>Export Your Library | Shelfmark Help</title>بله. هر دو در نتایج جستجو و زبانه‌های مرورگر نمایش داده می‌شوند.
og:title و سایر متاتگ‌های شبکه‌های اجتماعی<meta property="og:title" content="Export Your Library">بله، فقط مقدار content
alt, title, placeholder, aria-labelalt="The Export dialog with EPUB selected", aria-label="Breadcrumb"بله
lang روی <html><html lang="en">آن را به زبان مقصد تغییر دهید، برای مثال zh-Hans
نام تگ‌ها و ویژگی‌ها<a>، <img>، width، خود aria-labelخیر
href, src, id, class, for, name, type, data-*href="#choose-format", id="q"خیر
<code>, <pre>, <script>, <style>shelfmark export --format epubخیر. درباره توضیحات کد و خروجی نمونه جداگانه تصمیم بگیرید.
متنی که با CSS تنظیم شده است.note::before { content: "Note: "; }بله، اما در شیت استایل قرار دارد، پس برایش برنامه‌ریزی کنید
داده‌های ساختاریافته JSON-LD"name": "Export your Shelfmark library"مقادیر name و description را ترجمه کنید؛ کلیدها و JSON را معتبر نگه دارید
عناصر دارای translate="no"<span translate="no">Shelfmark</span>خیر
کامنت‌های HTML<!-- Generated by the help-center build... -->اختیاری. خوانندگان هرگز آن‌ها را نمی‌بینند.
ارجاع‌های نویسه‌ای&lt;library&gt;, &nbsp;, &copy;موارد escape شده را escape شده نگه دارید. &lt; نباید به < واقعی تبدیل شود.

این فهرست ساختهٔ ما نیست. بخش ویژگی translate در استاندارد HTML «ویژگی‌های قابل ترجمه» را تعریف می‌کند: title در همه عناصر، alt در تصاویر، placeholder در ورودی‌ها، content در عناصر meta که نامشان قابل ترجمه شناخته شده است، و lang که می‌گوید باید برای هماهنگی با زبان جدید تغییر کند. همچنین aria-label در ARIA را به عنوان نمونه‌ای از ویژگی‌هایی نام می‌برد که مشخصات دیگر می‌توانند اضافه کنند، و می‌گوید در یک عنصر translate="no"، متن و مقادیر ویژگی «هنگام بومی‌سازی صفحه باید دست‌نخورده باقی بمانند.»

آنچه آزمایش کردیم

ما sample-source.html را نوشتیم، یک صفحه مرکز راهنما برای همان اپلیکیشن خواندن داستانی، Shelfmark، که در آزمون ترجمه Markdown استفاده کردیم. این صفحه یک نمونه از هر ردیف جدول بالا را دارد، به‌علاوه چند تله:

  • جمله‌ای که با تگ‌های درون‌خطی تقسیم شده است: «قبل از خروجی گرفتن، از یادداشت‌هایتان نسخه پشتیبان بگیرید. خروجی گرفتن کتاب‌های شما را کپی می‌کند، اما چیزی را از Shelfmark حذف نمی‌کند،» با نام محصول درون translate="no"؛
  • جمله‌ای با دو عنصر درون‌خطی <code> که ترتیبشان مهم است: «مسیر پوشه <library> را بعد از --out تایپ کنید»؛
  • یک بلوک <pre><code> با یک دستور و یک خط خروجی نمونه، # Export finished: 128 books؛
  • یک قاعده CSS که کلمه «Note:» را قبل از یک پاراگراف درج می‌کند؛
  • یک پیوند درون‌صفحه‌ای به #choose-format، یک پیوند mailto:، یک فرم جستجو، و یک بلوک JSON-LD.

سپس از یک مدل محلی خواستیم آن را به سه روش به چینی ساده‌شده ترجمه کند:

  1. کل فایل. کل فایل را جای‌گذاری کنید و فایل ترجمه‌شده را بخواهید.
  2. با دستور. همان، به‌علاوه هشت قاعده: هر نام تگ و ویژگی را نگه دار، مقادیر href، src، id، class و مشابه را تغییر نده، ویژگی‌های متنی فهرست‌شده و متا تگ‌ها را ترجمه کن، <code>، <pre>، <script>، و <style> را به جز name و description در JSON-LD دست نزن، به translate="no" احترام بگذار، ارجاع‌های نویسه‌ای و کامنت‌ها را نگه دار، و lang را روی zh-Hans تنظیم کن.
  3. قطعه‌ها. رویکرد ابزارهایی که متن را از HTML استخراج می‌کنند: یک اسکریپت فایل را به تگ‌ها و متن تقسیم می‌کند، از <code>، <pre>، <script>، <style>، و عناصر translate="no" صرف‌نظر می‌کند، قطعه‌های متنی باقی‌مانده و ویژگی‌های متنی را به صورت یک فهرست JSON شماره‌گذاری‌شده به مدل می‌فرستد، و ترجمه‌ها را دوباره در نشانه‌گذاری دست‌نخورده می‌نویسد. همچنین خودش lang="zh-Hans" را تنظیم می‌کند.

مدل Qwen 3.6 27B (Q4_K_M) در LM Studio بود، با تفکر خاموش و دمای 0.3، روی یک Apple M4 Max با 64 گیگابایت حافظه. هر روش را سه بار اجرا کردیم، در مجموع نه اجرا، در 27 اکتبر 2026. اسکریپت run_llm_html_test.py است، و هر نه خروجی ویرایش‌نشده منتشر شده‌اند؛ README همه فایل‌ها را فهرست می‌کند. اگر قبلاً مدل محلی راه‌اندازی نکرده‌اید، راهنمای ترجمه با LLM محلی ما تنظیمات را پوشش می‌دهد.

این آزمایش کوچکی از یک مدل، یک جفت زبان، و یک صفحه بود. نشان می‌دهد چه مشکلاتی رخ می‌دهد و چگونه می‌توان آن‌ها را گرفت. مدل‌ها یا ابزارها را رتبه‌بندی نمی‌کند.

نتیجه: نشانه‌گذاری جان سالم به در برد؛ سه تصمیم نه

ما هر خروجی را با check_html_translation.py بررسی کردیم، یک بررسی‌کننده که فقط از کتابخانه استاندارد پایتون استفاده می‌کند. خروجی کامل در check-results.txt است و results.csv یک ردیف برای هر اجرا دارد.

بررسیکل فایل (۳ اجرا)دستور داده‌شده (۳ اجرا)قطعه‌ها (۳ اجرا)
همان ۵۸ تگ به ترتیب؛ هر href، src، id، class بدون تغییر۳ از ۳۳ از ۳۳ از ۳
متن translate="no" حفظ شد، پیوند درون‌صفحه‌ای هنوز کار می‌کند، &lt;library&gt; هنوز escape شده است۳ از ۳۳ از ۳۳ از ۳
خط خروجی نمونه داخل <pre> ترجمه شد۳ از ۳۳ از ۳۰ از ۳ (طبق طراحی رد شد)
content: "Note: " در CSS ترجمه شد۳ از ۳۰ از ۳۰ از ۳ (طبق طراحی رد شد)
name و description در JSON-LD ترجمه شدند۳ از ۳۳ از ۳۰ از ۳ (طبق طراحی نادیده گرفته شد)
aria-label="Breadcrumb" ترجمه شد۰ از ۳۰ از ۳۳ از ۳
جمله‌ای با دو عنصر درون‌خطی <code> حرف درست را می‌زند۳ از ۳۳ از ۳۰ از ۳
فاصله‌های بین متن چینی در سراسر یک تگ درون‌خطیهیچ۰، ۵ و ۴۶ در هر اجرا
lang روی <html>zh-CN (درخواست نشده)zh-Hanszh-Hans (توسط اسکریپت تنظیم شده)

هر یک از نُه اجرا همان ۵۸ تگ را به همان ترتیب، هر href، src، id و class، هدف پیوند درون‌صفحه، توضیح، &lt;library&gt; فرار داده شده و نام محصول داخل translate="no" را حفظ کرد. اگر نگران بودید که مدلی نشانه‌گذاری یک صفحه ساده را خراب کند، این کار را نکرد. مشکلات همه در این بود که چه چیزی ترجمه شود.

۱. خروجی نمونه داخل <pre> ترجمه شد

بلوک کد در نمونه ما با یک خط خروجی برنامه پایان می‌یابد:

<pre><code>shelfmark export --format epub --covers --out ~/Books/export
# Export finished: 128 books</code></pre>

در هر شش اجرای کل‌فایل و دستور‌داده‌شده، مدل # 导出完成:128 本书 را در آن خط برگرداند، از جمله سه اجرایی که در آن دستور گفته بود چیزی داخل <pre> را تغییر ندهد. خود دستور هرگز دست نخورد. مدل آن خط را به عنوان توضیح در نظر گرفت و ترجمه توضیحات در یک آموزش انتخاب معقولی است. اما این خط همان چیزی است که برنامه چاپ می‌کند و خواننده‌ای که آن را با ترمینال خود مقایسه کند، انگلیسی می‌بیند. پیش از ترجمه تصمیم بگیرید که آیا خروجی نمونه و توضیحات کد ترجمه می‌شوند یا نه، و به ابزار بگویید، یا بلوک‌های <pre> را کاملاً محافظت کنید.

اجراهای کل‌فایل همچنین content: "Note: " در CSS را در بلوک <style> ترجمه کردند، در حالی که اجراهای دستور‌داده‌شده که گفته شده بود <style> را رها کنند، آن را به انگلیسی نگه داشتند. هیچ‌کدام به‌تنهایی غلط نیست. ترجمه شیت استایل برای صفحه‌ای که CSS آن درون‌خطی است درست و برای سایتی که یک شیت استایل مشترک به همه زبان‌ها سرویس می‌دهد غلط است. در هر صورت، این تصمیمی است که کسی باید بگیرد، نه جزئیاتی که مدل باید حدس بزند.

۲. برچسب‌های دسترس‌پذیری نادیده گرفته شدند

ناوبری مسیر راهنما <nav aria-label="Breadcrumb"> است. صفحه‌خوان آن برچسب را اعلام می‌کند؛ خوانندگان بینا هرگز آن را نمی‌بینند. در هر شش اجرای کل‌فایل و دستور‌داده‌شده، به انگلیسی ماند، حتی اگر دستور دستور‌داده‌شده aria-label را در میان ویژگی‌های قابل ترجمه فهرست کرده بود. در یک اجرای دستور‌داده‌شده، aria-label="Search" دکمه جستجو نیز به انگلیسی ماند.

روش قطعه‌ای هر بار آن را ترجمه کرد، زیرا اسکریپت آن هر مقدار aria-label، alt، title و placeholder را جمع‌آوری می‌کرد و صریحاً برای هر یک درخواست ترجمه می‌داد. این قوی‌ترین دلیل برای استخراج هدفمند ویژگی‌های متنی است، به جای امیدواری به اینکه مدل متوجه آن‌ها شود.

۳. ترجمهٔ تکه‌تکه تگ‌ها را حفظ کرد اما جمله را شکست

روش تکه‌تکه از نظر ساختاری برای نشانه‌گذاری امن است: مدل هرگز تگی نمی‌بیند، پس نمی‌تواند به آن آسیب بزند. این روش در هر سه اجرا از تمام بررسی‌های ساختاری گذشت. همچنین تنها ترجمه‌ای را در آزمون تولید کرد که به خواننده دستورالعمل نادرست می‌داد.

جملهٔ انگلیسی این است: «Type the path to the <library> folder after --out.» کد درون‌خطی <code> آن را به سه تکه تقسیم می‌کند: «Type the path to the»، «folder after» و یک نقطه. چینی این واژه‌ها را به ترتیب متفاوتی می‌آورد، بنابراین مترجم باید دو عنصر کد را جابه‌جا کند. روش تکه‌تکه نمی‌تواند آن‌ها را جابه‌جا کند. هر سه اجرا دستورالعمل را برعکس کردند. اجرای ۲ این را تولید کرد (اجراهای ۱ و ۳ به جای 之后 از 后 با همان معنا استفاده می‌کنند):

在 <code>&lt;library&gt;</code> 之后输入 <code>--out</code>文件夹的路径。

این می‌خواند «پس از <library>، مسیر پوشهٔ --out را تایپ کنید»، یعنی برعکس دستورالعمل. هر شش اجرای کل‌فایل و دستورالعمل‌دار عناصر کد را جابه‌جا کردند و درست انجام دادند:

在 <code>--out</code> 后面输入 <code>&lt;library&gt;</code> 文件夹的路径。

همین تقسیم‌بندی فاصله‌های ناخواسته‌ای در محل برخورد تگ با متن چینی باقی گذاشت، مانند 前往 <b>设置</b> و <b>书库</b> ,، در هر سه اجرای تکه‌تکه، شش جا در هر اجرا. مرورگر آن‌ها را به صورت شکاف‌های قابل مشاهده نشان می‌دهد، از جمله پیش از نقطه‌گذاری چینی. اجراهای کل‌فایل هیچ‌کدام را نداشتند؛ دو تا از سه اجرای دستورالعمل‌دار چهار یا پنج مورد داشتند.

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

تفاوت‌های کوچک‌تر

  • lang: اجراهای کل‌فایل خودشان آن را به zh-CN تغییر دادند. اجراهای دستورالعمل‌دار طبق درخواست از zh-Hans استفاده کردند. هر دو تگ زبان معتبرند؛ zh-Hans خط (چینی ساده‌شده) را نام می‌برد، zh-CN یک منطقه را. راهنمای W3C دربارهٔ اعلان‌های زبان توصیه می‌کند زبان را روی عنصر <html> اعلان کنید و نه با تگ متای Content-Language.
  • JSON-LD: اجراهای کل‌فایل و دستورالعمل‌دار مقادیر name و description را ترجمه کردند و JSON را معتبر نگه داشتند. اسکریپت تکه‌تکهٔ ما محتوای <script> را نادیده گرفت، بنابراین دادهٔ ساختاریافتهٔ آن به انگلیسی ماند، که رفتار ابزاری که اسکریپت‌ها را نادیده می‌گیرد نیز همین خواهد بود.
  • ارجاع‌های نویسه‌ای: اجراهای کل‌فایل و دستورالعمل‌دار &rsaquo;، &nbsp;، &copy; و ارجاع ایموجی را همان‌طور که نوشته شده بود نگه داشتند. پنج تا از آن شش اجرا بازهٔ 2&ndash;5 را با واژه‌های چینی بازنویسی کردند (2 到 5 یا 2 至 5)؛ یک اجرای دستورالعمل‌دار به جای ارجاع یک خط تیرهٔ ساده نوشت، هرچند در دستور آن گفته شده بود ارجاع‌ها را نگه دارد. اسکریپت تکه‌تکهٔ ما همه را رمزگشایی کرد و نویسه‌ها را دوباره نوشت، که همان را نمایش می‌دهد. موردی که اهمیت دارد، &lt;library&gt; درون <code>، در هر نه اجرا به صورت escape‌شده ماند.

پیش از ترجمه: فایل را آماده کنید

  1. چیزهایی که نباید تغییر کنند را علامت بزنید. translate="no" را روی نام محصولات، شماره مدل‌ها، رشته‌های شبه‌کد در متن، و هر چیز دیگری که باید همان‌طور بماند بگذارید. این بخشی از HTML است، هزینه‌ای ندارد، و مدل در هر شش اجرایی که کل فایل را فرستادیم به آن احترام گذاشت. ابزارهای تکه‌تکه که آن را می‌خوانند، مثل اسکریپت ما، آن عناصر را کاملاً نادیده می‌گیرند. راهنمای ترجمه‌نکردن ما توضیح می‌دهد چگونه تصمیم بگیرید چه چیزی در آن فهرست قرار گیرد.
  2. سیاست کد را تعیین کنید. آیا توضیحات کد ترجمه می‌شوند؟ آیا خروجی نمونه ترجمه می‌شود؟ آیا شیوه‌نامه بین زبان‌ها مشترک است؟ پاسخ را همراه با نام‌هایی که نباید تغییر کنند در یک واژه‌نامهٔ ترجمه بنویسید و به هر کس یا هر چیزی که ترجمه می‌کند بدهید.
  3. شناسه‌ها را به زبان مبدأ نگه دارید. پیوندهای درون‌صفحه به مقادیر id اشاره می‌کنند. اگر کسی یک id را ترجمه کند، هر پیوندی به آن می‌شکند. هیچ‌یک از اجراهای ما این کار را نکرد، اما مترجمی که «از روی لطف» لنگرها را بومی‌سازی کند این کار را خواهد کرد.
  4. متن پنهان را جمع‌آوری کنید. ویژگی‌هایی را که واژه دارند فهرست کنید: alt، title، placeholder، aria-label، value روی دکمه‌ها، تگ‌های متا و JSON-LD، تا بررسی شوند و فراموش نشوند.
  5. رشته‌های جاوااسکریپت را درجا ترجمه نکنید. پیام‌هایی که با اسکریپت تنظیم می‌شوند، مانند یک هشدار یا برچسب دکمه‌ای که در کد ساخته می‌شود، به یک مرحلهٔ بومی‌سازی جداگانه در کد نیاز دارند. هیچ‌یک از شش اجرای کل‌فایل یا دستورالعمل‌دار بلوک اسکریپت ما را تغییر نداد، که درست است، اما یعنی آن رشته‌ها به انگلیسی می‌مانند.

پس از ترجمه: آن را بررسی کنید

  1. بررسی ساختاری را اجرا کنید.

    python3 check_html_translation.py source.html translated.html --lang zh-Hans --keep Shelfmark
    

    این ابزار تگ‌ها و ترتیبشان، هر ویژگی‌ای که متن خواندنی نیست، محتوای <pre>، <script> و <style>، کد درون‌خطی، کلیدهای JSON-LD، متن translate="no"، توضیحات و پیوندهای درون‌صفحه را مقایسه می‌کند. دربارهٔ ویژگی‌های متنی که هنوز انگلیسی‌اند، مقدار lang که با انتظار شما فرق دارد، متن قابل مشاهده‌ای که ترجمه‌نشده به نظر می‌رسد، کد درون‌خطی‌ای که ترتیبش تغییر کرده، و فاصله‌های بین متن چینی، ژاپنی یا کره‌ای در محل یک تگ درون‌خطی هشدار می‌دهد. کیفیت ترجمه را داوری نمی‌کند.

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

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

  4. برای زبان‌های راست‌به‌چپ، همچنین dir="rtl" را روی عنصر <html> تنظیم کنید. راهنمای ترجمهٔ کتاب راست‌به‌چپ ما توضیح می‌دهد چه چیز دیگری تغییر می‌کند.

  5. برای XHTML، مانند فایل‌های فصل درون یک EPUB، همچنین تأیید کنید که فایل هنوز XML خوش‌ساخت است، مثلاً با xmllint --noout chapter.xhtml. مرورگر یک تگ بسته‌نشده را می‌بخشد؛ کتاب‌خوان ممکن است نبخشد. چک‌لیست تضمین کیفیت ترجمهٔ EPUB ما بقیهٔ کارهای یک کتاب الکترونیکی را پوشش می‌دهد.

جایگاه BookTranslator

صفحهٔ بارگذاری BookTranslator فایل‌های .html، .htm و .xhtml را در کنار کتاب‌ها و اسناد می‌پذیرد، بنابراین می‌توانید یک صفحهٔ ذخیره‌شده یا یک مقالهٔ راهنمای ایستا را به‌صورت یک فایل کامل بارگذاری کنید. ما این نمونه را برای این مقاله از BookTranslator عبور ندادیم و نحوهٔ برخورد آن با ترتیب کد درون‌خطی، محتوای CSS یا JSON-LD را آزمایش نکرده‌ایم، پس خروجی آن را همان‌طور بررسی کنید که هر ابزار دیگری را بررسی می‌کنید. قیمت را پیش از پرداخت می‌بینید.

هر چه استفاده می‌کنید، مراحل آماده‌سازی را پیش از ترجمه و بررسی‌ها را پس از آن انجام دهید. صفحه‌ای که همهٔ تگ‌هایش سالم است باز هم می‌تواند چیز اشتباهی به خواننده بگوید. اگر HTML شما در واقع مستنداتی است که با Markdown نوشته شده، راهنمای ترجمهٔ Markdown ما به‌جای آن به قالب مبدأ می‌پردازد.

دریافت فایل‌های آزمایشی

استفادهٔ مجدد از همهٔ موارد این آزمایش آزاد است:

مطالب مرتبط