با عرض سلام و وقت به خیر خدمت کاربران سایت پی وی لرن به ویژه کاربرانی که به سیستم مدیریت محتوای قدرتمند وردپرس علاقمند هستند.
به ” دوره متخصص وردپرس ” خوش آمدید!
در این دوره قرار است توسعه و ارتقاء پلاگین های وردپرس را به صورت جامع و کامل بیاموزیم.
فرقی نمی کند که در شرف نوشتن اولین پلاگین خود هستید و یا این که پنجاهمین پلاگین خود را می نویسید! امیدوارم این دوره برایتان مفید باشد.
در جلسه قبلی با مفهوم بومی سازی یا Localization و کاربرد آن آشنا شدیم و آموختیم که بومی سازی فرایند بعدی ترجمه یک افزونه بین المللی است.
در این جلسه به سراغ بین المللی سازی رفته و به آموزش بین المللی سازی پلاگین می پردازیم.
به منظور ایجاد یک رشته قابل ترجمه در برنامه، باید رشته های اصلی را در فراخوانی با یکی از مجموعه های توابع خاص بپیچید.
آموزش بین المللی سازی پلاگین را با معرفی Gettext آغاز می نماییم.
وردپرس از کتابخانه ها و ابزارهای gettext برای i18n استفاده می کند.
اگر به صورت آنلاین جستجو کنید ، تابع ()_ را که مربوط به عملکرد ترجمه سازگار با متن PHP است، مشاهده خواهید کرد.
اگر از وردپرس استفاده می نمایید باید از تابع PHP تعریف شده با وردپرس استفاده کنید.
استفاده از یک دامنه متنی برای نشان دادن تمام متن های متعلق به آن افزونه مهم است.
دامنه متن یک شناسه منحصر به فرد است ، که باعث می شود وردپرس بتواند بین همه ترجمه های لود شده تمایز قایل شود.
این قابلیت توانایی جا به جای را افزایش می دهد و با ابزارهای موجود در وردپرس، تعامل بهتری برقرار می کند.
دامنه متن باید با اسلاگ افزونه مطابقت داشته باشد.
اگر افزونه شما یک پرونده واحد به نام my-plugin.php است یا در پوشه ای به نام plugin my وجود دارد، نام دامنه باید my-plugin باشد.
اگر افزونه شما در wordpress.org میزبانی شده است ، باید آن را با گزیده ای از آدرس اینترنتی افزونه شما (wordpress.org/plugins/ <slug>) مشخص نمود.
نام دامنه متن باید از dashes استفاده کند و underscores را به کار نبرد.
مثال رشته:
1 | __( 'String (text to be internationalized)', 'text-domain' ); |
“دامنه متن” را به اسلاگ پلاگین خود تغییر دهید.
برای قسمت دامنه متن یک تابع gettext از اسامی متغیر یا ثابت استفاده نکنید.
و این کار را به عنوان میانبر انجام ندهید: ;( ‘Translate me.’ , $text_domain )_
دامنه متن نیز باید به هدر افزونه اضافه شود.
وردپرس به این دلیل از آن استفاده می کند تا حتی در صورت غیرفعال بودن افزونه، متا داده های افزونه شما را نیز برای بین المللی سازی، سازگار کند.
دامنه متن باید مشابه با همان مورد استفاده در هنگام بارگیری دامنه متن باشد.
مثال هدر:
1 2 3 4 5 | /* * Plugin Name: My Plugin * Author: Plugin Author * Text Domain: my-plugin */ |
اگر افزونه در دایرکتوری رسمی افزونه وردپرس موجود باشد ، مسیر دامنه هدر Domain Path header را نمی توان حذف کرد.
مسیر دامنه به این خاطر استفاده می شود که وردپرس هنگام غیر فعال بودن پلاگین، بتواند آن را ترجمه نماید.
این قابلیت تنها در صورتی کاربرد دارد که بخش ترجمه در یک پوشه زبان جداگانه قرار گرفته باشد؛ زیرا پوشه پلاگین به صورت پیش فرض در آن قرار گرفته است.
به عنوان مثال :
اگر فایلهای mo. در پوشه languages در افزونه شما و در داخل پلاگین تان قرار دارد.
در این حال مسیر دامنه باید به صورت “languages/” است و باید با یک اسلش نوشته شود.
مثال هدر:
1 2 3 4 5 6 | /* * Plugin Name: My Plugin * Author: Plugin Author * Text Domain: my-plugin * Domain Path: /languages */ |
متداول ترین آن ()__ است.
این رشته فقط ترجمه آرگومان را بازگردانی می کند.
1 | __( 'Blog Options', 'my-plugin' ); |
یکی دیگر از رشتهای ساده دیگر ()e_ است.
این رشته ترجمه آرگومان را به عنوان خروجی تعیین می کند.
1 | echo __( 'WordPress is the best!', 'my-plugin' ); |
البته می توانید مورد کوتاه تر آن را نیز به کار ببرید:
1 | _e( 'WordPress is the best!', 'my-plugin' ); |
اگر به طور کلی قصد استفاده از رشته ها دارید؛ بهتر است از متغیرهای زیر استفاده نمایید.
1 | echo 'Your city is $city.' |
پیشنهاد ما استفاده از گروه توابع printf است.
printf و sprintf بسیار مفید هستند.
در ادامه می توانید راه حل ارائه شده را به صورت درست ببینید:
1 2 3 4 5 | printf( /* translators: %s: Name of a city */ __( 'Your city is %s.', 'my-plugin' ), $city ); |
توجه کنید که رشته در نظر گرفته شده برای ترجمه، فقط قالب “.Your city is %s” است که هر دو هم در منبع و هم در زمان اجرا یکسان هستند.
اگر فقط یک مکان نگهداری placeholder در یک رشته دارید؛ از argument swapping یا مبادله آرگومان استفاده نمایید.
در این مورد نقل قول های یکتا (‘) الزامی است:
نقل قول های دوگانه (“) به php می گویند s$ را به عنوان متغیر s تفسیر کند؛ و این چیزی نیست که ما می خواهیم.
1 2 3 4 5 6 | printf( /* translators: 1: Name of a city 2: ZIP code */ __( 'Your city is %1$s, and your zip code is %2$s.', 'my-plugin' ), $city, $zipcode ); |
در اینجا کد پستی بعد از نام شهر نمایش داده می شود.
در بعضی از زبانها نمایش کد پستی و شهر به ترتیب مخالف مناسب تر است.
با استفاده از پیشوند s٪ در مثال بالا ، چنین موردی امکان پذیر است.
از این طریق ترجمه ما به صورت زیر قابل نوشتن است:
1 2 3 4 5 6 | printf( /* translators: 1: Name of a city 2: ZIP code */ __( 'Your zip code is %2$s, and your city is %1$s.', 'my-plugin' ), $city, $zipcode ); |
این کد اشتباه است!
1 2 | // This is incorrect do not use. _e( "Your city is $city.", 'my-plugin' ); |
رشته های ترجمه از منابع استخراج شده است.
بنابراین مترجمان این عبارت را برای ترجمه دریافت می کنند: “.Your city is $city”
به هر حال برنامه e_ به فراخوانی یک آرگومان مانند “Your city is London” می پردازد.
یک ترجمه مناسب برای این یکی پیدا نکرده و این آرگومان را بازمی گرداند:
“.Your city is London”متاسفانه به درستی ترجمه نشده است.
آموزش بین المللی سازی پلاگین را با چندگانگی یا Plurals ادامه می دهیم
اگر رشته ای دارید وقتی تعداد موارد تغییر می کند آن ها نیز تغییر می کنند.
در انگلیسی شما “One comment” و “Two comments” دارید.
به زبانهای دیگر می توانید چندین فرم جمع داشته باشید.
برای رسیدگی به این مورد در وردپرس می توانید از تابع ()n_ استفاده کنید.
1 2 3 4 5 6 7 8 9 | printf( _n( '%s comment', '%s comments', get_comments_number(), 'my-plugin' ), number_format_i18n( get_comments_number() ) ); |
فرم مفرد رشته، (توجه داشته باشید که می توان برای عددهایی غیر از یک در برخی از زبانها استفاده کرد ، بنابراین باید از “s item%” به جای “One item” استفاده شود).
شکل جمع رشته
تعداد رشته ها، که تعیین می کند آیا فرم مفرد یا جمع باید برگردانده شود (زبانهایی وجود دارند ، که به مراتب بیش از ۲ شکل دارند).
دامنه متن افزونه ها
مقدار برگشتی توابع فرم ترجمه شده صحیح است که مربوط به تعداد ارائه شده است.
شما ابتدا رشته های جمع را با ()_n_noop یا ()_nx_noop تنظیم می کنید.
1 2 3 4 | $comments_plural = _n_noop( '%s comment.', '%s comments.' ); |
سپس در یک مرحله بعد از کد می توانید از ()translate_nooped_plural برای بارگذاری رشته ها استفاده کنید.
1 2 3 4 5 6 7 8 | printf( translate_nooped_plural( $comments_plural, get_comments_number(), 'my-plugin' ), number_format_i18n( get_comments_number() ) ); |
گاهی اوقات یک اصطلاح در چندین متن به کار می رود و در انگلیسی یک کلمه متفاوت است و باید در زبان های دیگر به صورت متفاوتی ترجمه شود.
به عنوان مثال کلمه Post
می تواند به عنوان یک فعل “Click here to post your comment” و به عنوان یک اسم “Edit this post” در نظر گرفته شود.
در چنین مواردی باید از توابع ()x_ یا ()ex_ استفاده نمایید.
این توابع بسیار شبیه توابع ()__ و ()e_ هستند اما توابعی که اول به آن ها اشاره شد یک آرگومان اضافه — دارند.
1 2 | _x( 'Post', 'noun', 'my-plugin' ); _x( 'Post', 'verb', 'my-plugin' ); |
با استفاده از این روش در هر دو مورد ، در مورد رشته اصلی string Comment را دریافت خواهیم کرد.
اما مترجمان دو Comment strings برای ترجمه مشاهده می کنند.
Comment strings و string Comment هر دور در زمینه متفاوتی خواهند بود.
توجه داشته باشید که مشابه()__ ، ()x_ دارای نسخه echo است: ()ex_.
مثال قبلی را می توان به صورت زیر نوشت:
1 2 | _ex( 'Post', 'noun', 'my-plugin' ); _ex( 'Post', 'verb', 'my-plugin' ); |
از هر چیزی که احساس می کنید خوانایی و سهولت کد نویسی را افزایش می دهد استفاده کنید.
در ادامه آموزش بین المللی سازی پلاگین به مبحث Descriptions می پردازیم.
همان طوری که مترجمان می دانند چگونه رشته ای مانند (‘g: i: s a’) __ را ترجمه کنند ، می توانید یک توضیح واضح در کد منبع اضافه کنید.
این کار باید با :translators شروع شود.
آخرین نظر PHP قبل از فراخوانیgettext است.
در ادامه می توانید مثال آن را مشاهده نمایید:
1 2 | /* translators: draft saved date format, see http://php.net/date */ $saved_date_format = __( 'g:i:s a' ); |
همچنین برای توضیح متغیرهایی در رشته مانند _n_noop( '<strong>Version %1$s</strong> addressed %2$s bug.','<strong>Version %1$s</strong> addressed %2$s bugs.' )
می توانید از این قابلیت استفاده نمایید.
1 2 3 | /* translators: 1: WordPress version number, 2: plural number of bugs. */ _n_noop( '<strong>Version %1$s</strong> addressed %2$s bug.', '<strong>Version %1$s</strong> addressed %2$s bugs.' ); |
Gettext در واقع r\ (کد ASCII: 13) را در رشته های قابل ترجمه دوست ندارد.
بنابراین لطفاً از این کار خودداری کنید و به جای آن از \ n استفاده کنید.
رشته خالی برای استفاده داخلی Gettext ساخته شده است و نباید سعی کنید رشته های خالی را بین المللی سازی کنید.
اگر این کار را کنید مترجمان هیچ زمینه ای را نمی بینند.
اگر یک مورد استفاده معتبر برای بین المللی کردن یک رشته خالی دارید ، متن را به کمک مترجمان اضافه کنید و رابطه تان را با سیستم Gettext خراب نکنید.
از ()wp_localize_script برای افزودن رشته های ترجمه شده یا سایر داده های سمت سرور به یک اسکریپت قبلاً درج شده استفاده کنید.
بهتر است که از همه رشته های خود فرار کنید!
به این ترتیب مترجمان نمی توانند کد مخربی را اجرا کنند.
چند تابع فرار وجود دارد که با توابع بین المللی سازی یکپارچه شده اند.
در پایان آموزش بین المللی سازی پلاگین به معرفی چند تابع محلی ساز می پردازیم.
در این جلسه با ارائه آموزش بین المللی سازی پلاگین مراحل و شرایط لازم برای بین المللی کردن یک افزونه وردپرس را آموختیم.
در جلسه بعدی به مسئله امنیت در بین المللی سازی پلاگین خواهیم پرداخت.
با پی وی لرن همراه باشید.