تولید خودکار فلش کارت انگلیسی به فارسی برای Anki با کمی شل اسکریپت

·

7 min read

ولی خوب‌، ایمان هم کالیبرش بالاست‌. شاید هم کمال همنشین… این است که بعد از یک مدتی که خیلی ذوق داشت و همه مدل فلش کارت آماده می‌کرد‌، چون سختش بود‌، کم کم فرمت‌های آماده شده را آنقدر کم کرد که این اواخر دیگر تنها kvtml آماده می‌کرد‌. فرمتی که آماده کردنش خیلی آسان‌تر از باقی قضایا بود‌، ولی مال نرم‌افزار بسیار به درد نخور kwordquiz میزکار KDE بود! این بود که دو سه هفته پیش‌، این ایده به سرم افتاد که اول کمی از کار ایمان کم کنم‌! بندهٔ خدا زحمت زیادی می‌کشد و به هر حال حیف است که فقط مصرف کننده باشم‌. این شد که با پایتون اسکریپتی برایش نوشتم که kvtml‌ها را خیلی راحت به anki تبدیل کند‌. ذکر خیر این اسکریپت را خودش [کرده‌](emanlog.com/?p=292 "kvtml 2 anki in emanlog").

معنی این اسکریپت قبلی این بود که حالا حالاها خوراک اضافه خواهم داشت‌. ولی حقیقتش کلمه‌های ایمان‌، حداقل تا این‌جایی که من دیده‌ام‌، اکثریتشان‌ در سطح من نیست‌. اگر هم باشد من خودم خیلی خیلی بیشتر از آن‌ها را در کتاب‌ها و مطالبی که روزانه می‌خوانم می‌بینم! مساله این‌جاست که از روی تنبلی‌، فقط به زور دیکشنری (mdic روی میزکار، google translate روی اینترنت و mobidic روی موبایل) ترجمه‌شان می‌کنم و بعد از چند جمله معنی‌شان از یادم می‌پرد‌. خسته کننده است‌. این طور نیست؟

خوب کمی با خودم دو دو تا چهارتا می‌کنم و یادم می‌آید که روی آن اسکریپت تبدیل kvtml دوست خوبم anki یک فرمت متنی خیلی تمیزی را به عنوان ورودی می‌گرفت و فلش کارتش می‌کرد‌. (اصلا آن اسکریپت بر همین مبنا کار می‌کند) یک همچین نحوی:

English;انگلیسی

که البته می‌توان بهش فایل‌های چند رسانه‌ای هم چسباند و یا با HTML خوشگلش کرد‌. خوب این یعنی می‌شود هر وقت که کلمه‌ای ترجمه می‌کنم‌، ترمینالم را باز کنم و مثلا از یک همچین دستوری استفاده کنم:

echo "English;انگلیسی" >> deck.txt

یا شایدم همیشه یک ادیتور زیر دستم باز بگذارم‌! ولی نه فکر کنم همان اولی بهتر است‌ (چون ترمینال در دسترس‌تر است). ولی خوب این این‌قدر‌ها هم خوشگل نیست‌. ضمن این که مثل فلش کارت‌های ایمان صدا و عکس ندارد‌. حالا عکس به کنار‌، تلفظ برای من از نان شب واجب‌تر است‌. بعضی کلمات آن‌قدر به چشمم سخت می‌آیند که اصلا نمی‌خوانمشان D:

خوب تلفظ را هم می‌شود مشکلش را با espeak حل کرد‌ (هر چند صدای روباتیکش خیلی نچسب است!). جهنم‌، شروع می‌کنم به نوشتن یک اسکریپت‌. این ایده‌، در میانهٔ راه آن‌قدر این در و آن در می‌خورد‌. آن‌قدر از ابزار‌ها و وسایلی که بقیه نوشته‌اند توش استفاده می‌شود که می‌شود اسکریپتی که اگر اینترنت دم دستش باشد‌، خودش عبارت وارد شده را با استفاده از google translate ترجمه می‌کند و تلفظ google translate را می‌چسباند تنگش و کار را تمام می‌کند‌.

چون می‌دانم همه حوصلهٔ خواندن نکات فنی اسکریپت را ندارند‌، این پست را در دو بخش می‌نویسم‌. بخش اول‌، برای کاربرانی که فقط می‌خواهند از آن استفاده کنند‌، و بخش دوم برای اشاره به نکات فنی کار ;-)

معرفی:

این اسکریپت برای اجرا به fribidi, ffmpeg, curl و html2text نیاز دارد‌. سه تای اول که عموما وضع و حال‌شان مشخص است‌. اما این آخری یک اسکریپت پایتون است که می‌توانید از مخازن‌تان نصب کنید‌. ولی من پیشنهاد می‌کنم به جای آن distribute یا pysetuptools پایتون را نصب کنید و پس از آن با دستور زیر سر و ته این اسکریپت را هم بیاورید:

sudo pip install html2text

دلیلش هم ساده است‌. مخازن پایتون خیلی سریع‌تر از مخازن توزیع‌تان به روز می‌شوند و صد البته در آخر کار مدیریت این بسته‌ها با آن‌ها آسان‌تر است‌! حالا اسکریپت را از [این‌جا](github.com/shahinism/Scripts/blob/master/Sh.. "fcgenerator on github") دانلود کنید و به صورت زیر چشم‌تان را به جمالش روشن کنید:

chmod +x fcgenerator.sh

./fcgenerator.sh -w "Some english word" -d firstDeck

مقدار Some english word که به اپراتور ‎-w نسبت داده شده‌، همان عبارت انگلیسی‌ای است که می‌خواهیم ترجمه‌اش کنیم‌. مقدار firstDeck هم اسم Deckای (مجموعه فلش کارت) که می‌خواهیم این لغت به آن اضافه شود است‌. اگر اینترنت‌تان وصل است که برنامه مثل پلنگ کارش را انجام می‌دهد و فایل‌ها را تولید می‌کند‌. اکر هم نه که می‌توانید به روش‌های دیگری کلمه را اضافه کنید‌.

مثلا فرض کنید که شما از ترجمهٔ google translate حال نمی‌کنید‌. خوب راحت است‌. کافی است که با استفاده از اپراتور ‎-t ترجمهٔ خودتان را به لغت بچسبانید‌. همین‌طور می‌توانید به جای تلفظ گوگل‌، از espeak استفاده کنید‌. برای این کار هم از اپراتور ‎-e استفاده می‌کنید. طرز کارش ساده است‌، این‌طور نیست؟

بعد از اجرای فرمان بالا اسکریپت برای ما یک فایل firstDeck.txt و یک دایرکتوری firstDeck.media ساخته‌. اگر کلمات دیگری هم داشتید و خواستید به این فلش کارت اضافه کنید‌، کافیست به دایرکتوری که این فایل‌ها در آن قرار دارند بروید و فقط مقدار ‎-w دستور را با کلمهٔ جدید‌تان عوض کنید‌.

حالا نوبت نصب Deck جدید‌تان روی Ankiاست‌. اگر Deck‌های شما هم در مسیر ‎~/.anki/decks قرار دارد (اگر توزیع‌تان خوشمزگی نکرده و جای دیگر نریخته باشد‌، بعید می‌دانم این مسیر فرق کند) می‌توانید با دستور زیر دایرکتوری مدیا را در این مسیر کپی کنید:

./fcgenerator.sh -i firstDeck

اگر هم نه که دستی کپی کنید! حالا Anki را باز کنید‌ و از منوی File گزینهٔ Import را انتخاب کنید‌. در قسمت نام Deck همان چیزی را بنویسید که برای اپراتور ‎-d قرار دادید (در این‌جا firstDeck) و سپس فایل firstDeck.txt را به آن بخورانید‌. تمام شد‌. فلش‌کارت‌های جدید‌تان آماده‌اند‌.

طرز کار اسکریپت خیلی ساده است‌. دیگر باقی‌اش به خودتان بستگی دارد که چطور از آن استفاده می‌کنید‌. می‌توانید برای راحتی کار آن را به PATHتان انتقال دهید و یا یک alias برای خیلی راحت‌تر شدنش تعریف کنید‌. یا حتی می‌توانید یک اسکریپت کوچک دیگر بنویسید که برای لیستی از لغات این فرمان را ایجاد کند و به صورت خودکار یک لیست بلند بالا از لغات + ترجمه + تلفظ‌شان داشته باشید‌! البته جنبه هم در کنارش خوب است‌. با Google طرفید‌. همچین هم زیاده روی نکنید که IPتان را به خاطر فرستادن درخواست‌های زیادی بلاک کند‌، یا کلا در گوگل ترنسلیت را گل بگیرد! ها در ضمن‌، می‌توانید با استفاده از ‎-T (به چه زبانی) و ‎-F (از چه زبانی) به جای حالت پیش‌فرض انگلیسی به فارسی از زبان‌های دیگر هم استفاده کنید.

چطور کار می‌کند؟

خوب اکثر دستورات اگر سواد شل اسکریپتینگ داشته باشید‌، سر راست‌اند‌. من در این‌جا فقط به چیز‌های جالبی که از کد‌های دیگران بهره گرفتم اشاره می‌کنم‌. یکی از خوشگل‌ترین‌شان برایم این تابع بود:

function deps(){

DEPENDENCIES=$@

deps_ok=YES

for dep in $DEPENDENCIES

do

if ! which $dep &>/dev/null; then

echo "$dep is not installed. please install it and try again."

deps_ok=NO

fi

done

if [[ "$deps_ok" == "NO" ]]; then

echo -e "Unmet dependencies ^"

echo -e "Aborting!"

exit 1

else

return 0

fi

}

خوب می‌دانم چیز ساده‌ای است. ولی حقیقتش من عقلم نمی‌رسید که می‌توان به این خوشگلی پیش‌نیاز‌های اسکریپت را بررسی کرد‌. این اسکریپت را از [این لینک](snabelb.net/content/bash_support_function_c.. "bash support function check dependencies") برداشتم و کمی دستکاری‌اش کردم تا به اسکریپت من بیاید‌.

بخش بعدی ماجرا‌، هیولا‌ترین قسمت اسکریپت است‌. Google مثل همیشه احمق‌بازی در آورده و ما را از داشتن یک API ساده محروم کرده‌. ولی خوب این مرحمت گوگل باعث نشده که [این دوست](crunchbang.org/forums/viewtopic.php?id=17034 "access google translate from a terminal") ندیده و نشنیدهٔ عزیزمان دست از انگولک گوگل و نجات ما بردارد‌.

result=$(curl -s -i --user-agent "" -d "sl=$FROMT" -d "tl=$TARGETT" --data-urlencode "text=$WORD" http://translate.google.com)

encoding=$(awk '/Content-Type: .\* charset=/ {sub(/^.\*charset=["'\'']?/,""); sub(/[ "'\''].\*$/,""); print}' <<<"$result")

TRANSLATION=$(iconv -f $encoding <<<"$result" | awk 'BEGIN {RS="



"};/<span[^>]\* id=["'\'']?result_box["'\'']?/' | html2text)

مساله ساده است‌. ما صفحه وبی داریم که می‌توانیم در جای خاصی از آن بگوییم که ترجمهٔ چه کلمه‌ای را می‌خواهیم و این صفحه در مقابل در جای خاص دیگری از خودش ترجمهٔ کلمه را به ما نشان می‌دهد‌. اسم این صفحه translate.google.com است که چون از متد GET (اگر درست یادم باشد) استفاده می‌کند‌، می‌توان با تغییر متغیر‌هایش نتیجهٔ کلمات مختلف را در آن دید‌. ضمن این که اضافه کنم که این دوستمان از روش جالبی برای پیدا کردن این متد‌ها (غیر از نگاه کردن به URL استفاده کرده) که هر چند به نظرم استفاده‌اش در این‌جا بی‌خود است‌، ولی کاربرد‌های باحال‌تری می‌توان برایش پیدا کرد. فعلا برای فهمیدن ماجرا از زبان خودش به صفحه‌ای که در بالا گفتم رجوع کنید‌!

در ادامه کافیست که از صفحه‌ای که گرفته‌ایم‌، آن المنت خاصی که می‌خواهیم را جدا کنیم (جایی که ترجمه نشان داده می‌شود) و به html2text بخورانیم که نهایتا فقط متن به ما نشان داده شود‌. ولی از آن‌جا که html2text فقط یک فرمت یونیکد را می‌فهمد و فرمت کدینگ صفحهٔ نتیجهٔ گوگل با توجه به زبان پاسخ متفاوت است (چرا؟) با استفاده از iconv سعی می‌کند که کدینگ درست را به خوردش بدهد‌. و حالا چون نمی‌خواهد هر بار دستی وارد کند که از کدام کدینگ تبدیل کن‌، با awk سر صفحه را می‌خواند و کدینگ صفحه را پیدا می‌کند ;-)

و آخرین بخش ماجرا مربوط می‌شود به دانلود صدا. برای این کار از [این اسکریپت](gist.github.com/873364 "google translate download sound") کمک گرفتم‌. ولی چون نمی‌خواستم نتیجهٔ کار خیلی شلخته شود (دو فرمت متفاوت در صورت استفاده از espeak و google translate در کنار هم) با ffmpeg کلیه فرمت‌ها را به ‎.ogg تغییر دادم که آقایمان نیز از ما راضی باشد.