آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

پرسش و پاسخ شماره ۹۸

پرسش و پاسخ شماره ۹۸

چگونه پشتیبانی محلی را به اسکریپت‌های bash خود اضافه کنید

جستجو برای مثالهای چگونگی افزودن محلی‌سازی ساده به اسکریپت‌های bash خودتان، و چگونگی انجام آزمایش؟ احتمالاً آنچه شما می‌خواهید این است....

نخست، چند متغیر که باید آنها را درک کنید

قبل از اینکه حتی بتوانیم شروع کنیم، باید تمام متغیرهای محیط منطقه را شیرفهم بشویم. این مورد پایه‌ای است و در محل‌هایی که مردم به مستندات(صفحات man، و غیره) توجه می‌نمایند، برای مستندسازی بینهایت مهم است. بعضی از این متغیرها ممکن است در سیستم شما فراهم نباشند، زیرا به نظر می‌رسد استانداردهای گوناگونی برای توسعه و رقابت وجود دارد....

در سیستم‌های اخیر گنو، متغیرها به این ترتیب استفاده می‌شوند:

  1. اگر LANGUAGE تنظیم است، آن را استفاده کنید، مگر اینکه LANG برابر با C تنظیم شود، در چنین حالتی LANGUAGE صرف نظر می‌شود. همچنین، بعضی برنامه‌ها در حقیقت ابداً از LANGUAGE استفاده نمی‌کنند.

  2. در غیر این صورت، اگر LC_ALL تنظیم باشد، آنرا به کار ببرید.
  3. و گرنه، در صورتی که متغیر ‎LC_*‎ که چنین حالتی را پوشش می‌دهد برقرار باشد، آن را استفاده نمایید. (برای مثال، LC_MESSAGES پیغام‌های خطا را پوشش می‌دهد.)
  4. در غیر این صورت، LANG را به کار ببرید.

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

$ env | egrep 'LC|LANG'
LANG=en_US.UTF-8
LANGUAGE=en_US:en_GB:en

این مثالی از یک سیستم دبیان است. در این حالت، متغیر LANGUAGE برقرار است، یعنی ما هر آزمایشی انجام بدهیم که با تغییر LANG درگیر بشود احتمالاً ناموفق است، مگر اینکه ما LANGUAGE را هم تغییر بدهیم. حال در اینجا مثال دیگری از یک سیستم دبیان دیگر:

$ env | egrep 'LC|LANG'
LANG=en_US.utf8

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

بنابراین، پیش بروید و با سیستم خودتان بررسی کنید و ببینید کدام کار می‌کند و کدام کار نمی‌کند. ممکن است شما اصلاً متغیر LANGUAGE نداشته باشید(محصوصاً اگر در گنو-لینوکس نباشید)، از اینرو ممکن است تنظیم آن برای شما نتیجه‌ای نداشته باشد. شاید لازم باشد دستور ‎locale -a‎ را به کار ببرید تا ببینید کدام تنظیمات منطقه معتبر هستند. ممکن است لازم باشد یک مجموعه کاراکتری را در متغیر LANG تعیین نمایید(به عنوان مثال ‎es_ES.utf8‎ به جای ‎es_ES‎). شاید برای اینکه موجب کار کردن آنها بشوید، بایستی مناطق را در سیستم عامل خود ایجاد کنید(پردازشی که فراتر از حوزه این صفحه است، اما در سیستم دبیان متشکل از اجرای ‎dpkg-reconfigure locales‎ و پاسخ دادن به پرسش‌ها است).

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

$ wc -q
wc: invalid option -- 'q'
Try `wc --help' for more information.
$ LANGUAGE=es_ES wc -q
wc: opción inválida -- q
Pruebe `wc --help' para más información.

وقتی که بتوانید آن کار را به طور قابل قبولی انجام بدهید، می‌توانید کار واقعیِ تولید اسکریپت bash با محلی‌سازی را شروع کنید.

نشانه‌گذاری رشته‌های قابل ترجمه

این قسمت حداقل از جهت فهمیدن، ساده‌ترین بخش است. هر رشته در ‎$"..."‎ با استفاده از امکانات پشتیبانی زبان محلی (NLS) سیستم ترجمه می‌شود. تمام رشته‌های ثابت در برنامه خود را که می‌خواهید ترجمه شوند، یافته و علامت‌گذاری کنید. رشته‌های شامل متغیرها یا سایر جایگزینی‌ها را علامت نزنید. برای مثال

#!/bin/bash
echo $"Hello, world"

(به طوری که می‌توانید ببینید، ما در اینجا با مورد بسیار ساده شروع می‌کنیم.)

Bash (حداقل بعد از ‎4.0‎) بسط منطقه را قبل از سایر جایگزینی‌ها انجام می‌دهد. بدین معنی، در حالتی مانند این مورد:

echo $"The answer is $answer"

رشته لفظی ‎$answer‎ بخشی از رشته علامت زده خواهد شد. ترجمه نیز باید شامل ‎$answer‎ باشد، و bash جایگزینی متغیر را در رشته ترجمه شده انجام خواهد داد. ترتیبی که bash این جایگزینی‌ها را انجام می‌دهد یک حفره امنیتی بالقوه را مطرح می‌کند که ما در اینجا آن را پوشش نخواهیم داد. (وصله‌ای ارائه شده است، اما هنوز خیلی ابتدایی است....)

تولید و(یا) ادغام فایلهای PO

سپس، آنچه ‎"PO files"‎ نامیده شده را بواسطه برنامه خودتان تولید کنید. این فایلها محتوی رشته‌هایی که علامت‌گذاری کرده‌ایم، و ترجمه آنها(که بعداً قرار خواهیم داد) هستند.

با ایجاد یک فایل ‎*.pot‎ که یک الگو می‌باشد، شروع می‌کنیم.

bash --dump-po-strings hello > hello.pot

خروجی که این کد تولید می‌کند به این شکل خواهد بود:

#: hello:5
msgid "Hello, world"
msgstr ""

نام فایل شما(بدون پسوند ‎.pot‎) ‏domain‏ متن قابل ترجمه شما نامیده می‌شود. domain در این زمینه مشابه نام یک بسته( package) است. به عنوان مثال، بسته coreutils گنو شامل تعداد بسیاری برنامه‌های کوچک است، اما تمام آنها متفقاً توزیع می‌گردند، و بنابراین، معقول است تمام ترجمه‌های آنها نیز با یکدیگر باشند. ما در این مثال از domain با نام hello استفاده می‌کنیم. در یک مثال بزرگترِ محتوی تعداد زیادی برنامه در یک مجموعه، احتمالاً باید نام کل مجموعه را استفاده کنیم.

این الگو برای هر زبانی که می‌خواهیم پشتیبانی نماییم، یکبار کپی خواهد شد. بیایید فرض کنیم می‌خواهیم ترجمه‌های اسپانیایی و فرانسوی را برای برنامه‌های خود پشتیبانی نماییم. ما دو فایل PO (یکی برای هر ترجمه) ایجاد خواهیم نمود، پس اجازه بدهید دو شاخه فرعی بسازیم و الگو را در هر یک از آنها کپی کنیم:

mkdir es fr
cp hello.pot es/hello.po
cp hello.pot fr/hello.po

این است آنچه ما در نوبت اول انجام می‌دهیم. اگر از قبل بعضی فایلهای جزئی یا حتی ترجمه تکمیل شده PO درآنجا وجود داشت، ما نمی‌خواستیم آنها را رونویسی کنیم. پس به جای آن، موارد ترجمه جدید را در فایل قدیمی PO ادغام می‌نمودیم. برای این کار از ابزار ویژه‌ای به نام msgmerge استفاده می‌نماییم. اجازه بدهید فرض کنیم که مقدار بیشتری کُد(و رشته‌های قابل ترجمه) به برنامه خودمان اضافه می‌کنیم:

vi hello
bash --dump-po-strings hello > hello.pot
msgmerge --update es/hello.po hello.pot
msgmerge --update fr/hello.po hello.pot

مؤلف اصلی این صفحه مقداری یادداشت تهیه نموده است که من در اینجا دست‌نخورده رها می‌کنم. شاید سودمند واقع بشوند...؟

# step 5: try to merge existing po with new updates
# remove duplicated strings by hand or with sed or something else
# awk '/^msgid/&&!seen[$0]++;!/^msgid/' lang/nl.pot > lang/nl.pot.new
msgmerge lang/nl.po lang/nl.pot

# step 5.1: try to merge existing po with new updates
cp --verbose lang/pct-scanner-script-nl.po lang/pct-scanner-script-nl.po.old
awk '/^msgid/&&!seen[$0]++;!/^msgid/' lang/pct-scanner-script-nl.pot > lang/pct-scanner-script-nl.pot.new
msgmerge lang/pct-scanner-script-nl.po.old lang/pct-scanner-script-nl.pot.new > lang/pct-scanner-script-nl.po

# step 5.2: try to merge existing po with new updates
touch lang/pct-scanner-script-process-nl.po lang/pct-scanner-script-process-nl.po.old
awk '/^msgid/&&!seen[$0]++;!/^msgid/' lang/pct-scanner-script-process-nl.pot > lang/pct-scanner-script-process-nl.pot.new
msgmerge lang/pct-scanner-script-process-nl.po.old lang/pct-scanner-script-process-nl.pot.new > lang/pct-scanner-script-process-nl.po

ترجمه رشته‌ها

این مرحله‌ای است که ‎100%‎ آن کار انسانی است. فایل PO هر زبان را ویرایش کنید و محل‌های خالی را پُر کنید.

#: hello:5
msgid "Hello, world"
msgstr "Hola el mundo"

#: hello:6
msgid "How are you?"
msgstr ""

نصب فایلهای MO

سیستم عامل شما، اگر شما را تا اینجا پیش‌آورده، احتمالاً از قبل چند برنامه محلی شده با کاتالوگ‌های ترجمه نصب شده درجایی مانند ‎/usr/share/locale‎ (یا جای دیگری) دارد. اگر می‌خواهید ترجمه‌های شما نیز در همان محل نصب بشوند، باید از اختیارات کاربر ارشد برخوردار باشید، و شما باید domain یا (namespace) ترجمه خود را به طوری مدیریت نمایید که از برخورد با تمام بسته‌های سیستم‌عامل اجتناب گردد.

اگر می‌خواهید از محل استاندارد سیستم برای ترجمه‌هایتان استفاده کنید، آنوقت فقط لازم است در اندیشه انجام یک تغییر در برنامه خود باشید: تنظیم متغیر TEXTDOMAIN.

#!/bin/bash
TEXTDOMAIN=hello

echo $"Hello, world"
echo $"How are you?"

این متغیر به bash و کتابخانه‌های سیستم می‌گوید از کدام فایل MO در محل استاندارد استفاده نمایند. اگر می‌خواهید از مکان غیر استاندارد استفاده نمایید، آنوقت باید آن محل را نیز در متغیری به نام TEXTDOMAINDIR قرار بدهیم:

#!/bin/bash
TEXTDOMAINDIR=/usr/local/share/locale
TEXTDOMAIN=hello

echo $"Hello, world"
echo $"How are you?"

بنابر نیاز خود یکی از این موارد را به کار ببرید.

یک فایل MO در اصل یک فایل کامپایل شده PO می‌باشد. برنامه‌ای به نام msgfmt عهده‌دار این کامپایل نمودن است. اکنون ما فقط باید بگوییم فایل PO کجاست و فایل MO کجا نوشته شود.

msgfmt -o /usr/share/locale/es/LC_MESSAGES/hello.mo es/hello.po
msgfmt -o /usr/share/locale/fr/LC_MESSAGES/hello.mo fr/hello.po

یا

mkdir -p /usr/local/share/locale/{es,fr}/LC_MESSAGES
msgfmt -o /usr/local/share/locale/es/LC_MESSAGES/hello.mo es/hello.po
msgfmt -o /usr/local/share/locale/fr/LC_MESSAGES/hello.mo fr/hello.po

(اگر ما بیش از دو ترجمه برای پشتیبانی داشتیم، می‌توانستیم تقلید از ساختار ‎/usr/share/locale‎ برای تسهیل کپی گروهی فایلهای MO از دایرکتوری محلی به مخزن سیسم‌عامل را انتخاب نماییم. این به عنوان تمرین واگذار شد.)

آزمون!

آنچه قبلاً در باره متغیرهای محیط منطقه گفتیم را به خاطر بیاورید...مثالهای اینجا ممکن است در سیستم شما کار بکنند یا نکنند.

برنامه gettext می‌تواند برای بازیابی ترجمه‌های شخصی از کاتالوگ به کار برود:

$ LANGUAGE=es_ES gettext -d hello -s "Hello, world"
Hola el mundo

همه رشته‌های ترجمه نشده به حال خود رها می‌شوند:

$ LANGUAGE=es_ES gettext -d hello -s "How are you?"
How are you?

و سرانجام، هیچ جایگزینی برای اجرای واقعی خود برنامه وجود ندارد:

wooledg@wooledg:~$ LANGUAGE=es_ES ./hello
Hola el mundo
How are you?

به طوری که می‌توانید ببینید، هنوز برای مثال ما مقدار دیگری ترجمه وجود دارد که باید انجام بشود. برگردید به کار....

منابع


CategoryShell

پرسش و پاسخ 98 (آخرین ویرایش ‎2012-03-11 00:08:39‎ توسط host-216-57-70-194)