Google به عنوان بخشی از Google Cloud خود ، API ترجمه Google را با ساختار هزینه مبتنی بر استفاده ارائه می دهد. همچنین یک API فاقد سند وجود دارد که می تواند بدون کلید استفاده شود ، اما فقط پس از چند درخواست از کار خودداری می کند. هنگام استفاده از عملکرد ترجمه وب سایت Google Chrome ، قابل توجه است که صفحات را می توان بدون هیچ محدودیت قابل توجهی با کیفیت بسیار خوب ترجمه کرد.
ظاهراً مدل پیشرفته nmt در حال حاضر در اینجا استفاده می شود. اما گوگل کروم از کدام API به صورت داخلی برای ترجمه محتوا استفاده می کند و آیا می توانید مستقیماً به این API دسترسی داشته باشید - حتی در سمت سرور؟ برای تجزیه و تحلیل ترافیک شبکه، ابزارهایی مانند Wireshark یا Telerik Fiddler را توصیه می کنیم که می توانند ترافیک رمزگذاری شده را نیز تحلیل کنند. اما Chrome حتی درخواستهایی را که هنگام ترجمه صفحات ارسال میکند را به صورت رایگان ارائه میکند: آنها به راحتی از طریق ابزارهای توسعهدهنده Chrome قابل مشاهده هستند.:

اگر ترجمه ای انجام دادید ، درخواست POST مهم را از طریق "Copy> Copy as cURL (bash)" به https://translate.googleapis.com برسانید و آن را در ابزاری مانند Postman اجرا کنید ، به عنوان مثال ، می توانید دوباره درخواست را بدون مشکل ارسال کنید:

معنی پارامترهای URL نیز تقریباً واضح است.:
| کلید | مقدار مثال | معنی |
| دلخوری | 3 | حالت حاشیه نویسی (بر شکل بازگشت تأثیر می گذارد) |
| مشتری | te_lib | اطلاعات کلاینت (متفاوت است؛ از طریق رابط وب گوگل ترنسلیت، مقدار "webapp" است؛ بر قالب بازگشت و محدودیت سرعت تأثیر میگذارد) |
| قالب | html | قالب رشته (برای ترجمه برچسب های HTML مهم است) |
| v | 1.0 | شماره نسخه Google Translate |
| کلید | AIzaSyBOti4mM-6x9WDnZIjIeyEU21OpBXqWBgw | کلید API (زیر را ببینید) |
| logld | vTE_20200210_00 | نسخه پروتکل |
| اسل | د | زبان مبدا |
| tl | en | زبان مقصد |
| sp | nmt | مدل ML |
| تی سی | 1 | ناشناخته |
| sr | 1 | ناشناخته |
| tk | 709408.812158 | نشانه (نگاه کنید به زیر) |
| روش | 1 | ناشناخته |
برخی از عناوین درخواست نیز تنظیم شده اند - اما این موارد عمدتا قابل چشم پوشی هستند. پس از لغو انتخاب دستی همه عناوین ، از جمله عناوین مربوط به عامل کاربر ، هنگام وارد کردن نویسه های خاص ، مشکلی در رمزگذاری کشف می شود (اینجا هنگام ترجمه " سلام به جهان "):

اگر عامل کاربری را دوباره فعال کنید (که به طور کلی هیچ آسیبی نمی رساند) ، API نویسه های رمزگذاری شده UTF-8 را ارائه می دهد:

آیا اکنون به هدف خود رسیدهایم و تمام اطلاعات لازم برای استفاده از این API خارج از گوگل کروم را داریم؟ با این حال، اگر رشتهای که قرار است ترجمه شود (فیلد داده q در درخواست POST) را از مثلاً "Hello World" به "Hello World ! " تغییر دهید، یک پیام خطا دریافت خواهید کرد.:

اکنون با استفاده از تابع ترجمه وبسایت، ترجمه دیگری از این رشته اصلاحشده را در گوگل کروم انجام میدهیم و متوجه میشویم که علاوه بر پارامتر q ، پارامتر tk نیز تغییر کرده است (سایر پارامترها ثابت ماندهاند).:

بدیهی است که این توکن به رشته ای بستگی دارد که ساختار آن به راحتی قابل مشاهده نیست. هنگام شروع ترجمه وب سایت ، فایل های زیر بارگیری می شوند:
- 1 پرونده CSS: translateelement.css
- 4 گرافیک: translate_24dp.png (2x) ، gen204 (2x)
- 2 پرونده JS: main_de.js ، element_main.js
دو فایل جاوا اسکریپت مبهم و کوچک شده اند. ابزارهایی مانند JS Nice و de4js اکنون به ما کمک می کنند تا این پرونده ها را بیشتر بخوانیم . برای اشکال زدایی مستقیم آنها ، Chrome Extension Requestly را پیشنهاد می کنیم که فایلهای از راه دور را بصورت محلی تونل می کند:

اکنون می توانیم کد را اشکال زدایی کنیم (ابتدا CORS باید در سرور محلی فعال شود). بخش کد مربوط به تولید نشان داده میشود، رمز به در این بخش در فایل element_main.js پنهان شود:
b7739bf50b2edcf636c43a8f8910def9
در اینجا متن با کمک برخی شیفت بیت هاش شده است . اما متأسفانه ما هنوز یک قطعه از این معما را از دست داده ایم: علاوه بر استدلال a (که متنی است که باید ترجمه شود) ، استدلال دیگری b به تابع Bp () منتقل می شود - نوعی دانه که به نظر می رسد هر از گاهی تغییر می کند و همچنین شامل به هش ریختن اما او از کجا آمده است؟ اگر به فراخوانی عملکرد Bp () برویم ، بخش کد زیر را پیدا می کنیم:
b7739bf50b2edcf636c43a8f8910def9
تابع Hq از قبل به شرح زیر اعلام می شود:
b7739bf50b2edcf636c43a8f8910def9
ابهام زدا مقداری زباله در اینجا به جا گذاشته است. پس از اینکه String.fromCharCode('...') را با رشته های مربوطه جایگزین کردیم، a() منسوخ را حذف کردیم و فراخوانی های تابع [c(,c()] را کنار هم قرار دادیم، دریافت می کنیم.:
b7739bf50b2edcf636c43a8f8910def9
یا حتی راحت تر:
b7739bf50b2edcf636c43a8f8910def9
تابع yq قبلاً به این صورت تعریف شده است:
b7739bf50b2edcf636c43a8f8910def9
بنابراین به نظر می رسد seed در شیء جهانی google.translate._const._ctkk است که در زمان اجرا در دسترس است. اما در کجا قرار می گیرد؟ حداقل در ابتدا در فایل JS دیگر main_de.js که قبلاً بارگذاری شده است نیز موجود است. در ابتدا موارد زیر را اضافه می کنیم:
b7739bf50b2edcf636c43a8f8910def9
در کنسول ما واقعاً دانه فعلی را بدست می آوریم:

این خود گوگل کروم ، که ظاهراً دانه را ارائه می دهد ، به عنوان آخرین گزینه باقی می ماند. خوشبختانه کد منبع آن (Chromium ، از جمله ملفه Translate) منبع باز است و بنابراین در دسترس عموم است. ما مخزن را به صورت محلی می کشیم و فراخوانی عملکرد TranslateScript :: GetTranslateScriptURL را در فایل translate_script.cc در پوشه کامپوننت ها / ترجمه / هسته / مرورگر پیدا می کنیم:
b7739bf50b2edcf636c43a8f8910def9
متغیر دارای URL در همان پرونده به سختی تعریف شده است:
b7739bf50b2edcf636c43a8f8910def9
اگر اکنون فایل element.js را دقیقتر بررسی کنیم (پس از رفع ابهام)، ورودی سخت مجموعه c._ctkk را مییابیم - شی google.translate نیز بر این اساس تنظیم میشود و بارگیری همه داراییهای مربوطه (که قبلاً کشف کردهایم) راهاندازی میشود.:
b7739bf50b2edcf636c43a8f8910def9
اکنون کلید پارامتر برای بررسی باقی مانده است (با مقدار AIzaSyBOti4mM-6x9WDnZIjIeyEU21OpBXqWBgw). به نظر می رسد این یک کلید عمومی API مرورگر است (که در برخی از نتایج Google نیز یافت می شود). این در Chromium در فایل translate_url_util.cc در پوشه کامپوننت ها / ترجمه / هسته / مرورگر تنظیم شده است:
b7739bf50b2edcf636c43a8f8910def9
کلید در google_apis / google_api_keys.cc از یک مقدار ساختگی تولید می شود:
b7739bf50b2edcf636c43a8f8910def9
با این حال، آزمایشها نشان میدهد که فراخوانیهای API بدون این پارامتر کلیدی نیز به خوبی کار میکنند. آزمایش با API اکنون در صورت فراخوانیهای موفق، کد وضعیت ۲۰۰ را برمیگرداند. اگر به حد نصاب برسد، کد وضعیت ۴۱۱ با پیام « درخواستهای POST به یک هدر با طول محتوا نیاز دارند » بازگردانده میشود. بنابراین، توصیه میشود این هدر را نیز اضافه کنید (که به طور خودکار به عنوان یک هدر موقت در Postman تنظیم میشود).
قالب بازگشت رشته های ترجمه شده غیرمعمول است وقتی چندین جمله در یک درخواست وجود داشته باشد. جملات منفرد توسط برچسب های i- / b-HTML محصور شده اند:

همچنین ، Google Chrome کل HTML را به API نمی فرستد ، اما مقادیر صفتی مانند href را در درخواست ذخیره می کند (و به جای آن شاخص هایی را تنظیم می کند تا بعداً برچسب ها در سمت مشتری اختصاص یابد):

اگر مقدار مشتری کلیدی POST را از te_lib (Google Chrome) تغییر دهید در webapp ( وب سایت ترجمه Google ) ، رشته نهایی ترجمه شده را دریافت می کنید:

مشکل این است که احتمال اینکه شما با محدودیت نرخ روبرو شوید بسیار بیشتر از te_lib است (برای مقایسه: با webapp این بعد از 40،000 کاراکتر به دست می آید ، با te_lib هیچ محدودیتی برای نرخ وجود ندارد). بنابراین ما باید نگاه دقیق تری به نحوه تجزیه نتیجه Chrome بیندازیم. ما آن را در اینجا در element_main.js پیدا خواهیم کرد:
b7739bf50b2edcf636c43a8f8910def9
اگر کل کد HTML را به API ارسال کنید، ویژگی ها را در پاسخ ترجمه شده باقی می گذارد. بنابراین ما مجبور نیستیم کل رفتار تجزیه را تقلید کنیم، بلکه فقط رشته ترجمه شده نهایی را از پاسخ استخراج کنیم. برای انجام این کار، ما یک تجزیهکننده تگ HTML کوچک میسازیم که خارجیترین تگهای <i> را از جمله محتوای آنها حذف میکند و خارجیترین تگهای <b> را حذف میکند. با این دانش، اکنون میتوانیم (پس از نصب وابستگیها با composer به fzaninotto / faker vielhuber / stringhelper نیاز داریم ) یک نسخه سمت سرور از API ترجمه بسازیم.:
b7739bf50b2edcf636c43a8f8910def9
در زیر نتایج یک آزمایش اولیه که بر روی پنج سیستم مختلف با پهنای باند و آدرس های IP مختلف انجام شده است آورده شده است.:
| شخصیت | کاراکتر در هر درخواست | مدت زمان | نرخ خطا | هزینه از طریق API رسمی |
| 13.064.662 | ~250 | 03: 36: 17 ساعت | 0% | 237,78 € |
| 24.530.510 | ~250 | 11: 09: 13 ساعت | 0% | 446,46 € |
| 49.060.211 | ~250 | 20: 39: 10 ساعت | 0% | 892,90 € |
| 99.074.487 | ~1000 | 61: 24: 37 ساعت | 0% | 1803,16 € |
| 99.072.896 | ~1000 | 62: 22: 20 ساعت | 0% | 1803,13 € |
| Σ284.802.766 | ~550 | Σ159: 11: 37 ساعت | 0% | 5183.41 یورو |
توجه: این پست وبلاگ شامل همه اسکریپت ها فقط برای اهداف آزمون نوشته شده است. هنوز اسکریپت برای استفاده از مولد استفاده کنید، به جای با رسمی کار API ترجمه گوگل .