В попередній статті я приділив увагу основам інтернаціоналізації WordPress (скорочено i18n); розповів, як встановити локалізовану версію WordPress і легко перевести працюючий сайт на локалізовану версію WordPress.

У цій статті я опишу процес інтернаціоналізації плагінів WordPress. Сам процес зовсім не складний, і, придбавши ці знання, ви самі зможете легко переводити свої плагіни WordPress на інші мови.

Різниця між інтернаціоналізацією і локалізацією

Протягом багатьох років розробники, як правило, невірно тлумачили зміст цих термінів — інтернаціоналізація та локалізація:

  • Інтернаціоналізація являє собою процес розробки плагіна таким чином, щоб його легко можна було перекласти на інші мови;
  • Локалізація охоплює подальший процес перекладу інтернаціоналізувати плагіна на новий мову.

Варто відзначити, що інтернаціоналізацію часто скорочено позначають i18n (тому що в цьому слові (Internationalization) між ‘i’ і ‘n’ 18 літер), а локалізацію скорочують l10n (тому що аналогічно між ‘l’ і ‘n’ розміщується 10 літер).

Для чого потрібна інтернаціоналізація?

Відповідь проста — WordPress використовується у всьому світі на різних мовах. Коли плагіни інтернаціоналізовані, вони привертають велику аудиторію з різних частин світу, яка, очевидно, отримує велику користь від плагіну на їх рідній мові.

Як розробник, ви можете бути не в змозі забезпечити локалізовані версії плагіна, тому що ви не говорите на інших мовах. Тим не менше, коли ви интернационализируете ваш плагін, ви залишаєте відчинені двері для інших людей, які зможуть створити локалізацію без необхідності вносити зміни у вихідний код.

Інтернаціоналізація плагінів

Тепер, коли ми розібралися з поняттями інтернаціоналізації та локалізації плагіна, давайте зануримося в процес підготовки плагіна до перекладу.

Установка перекладу заголовків

Перший крок до того, щоб зробити плагін перекладним, буде полягати в додаванні заголовків перекладу в заголовках плагіна.

Заголовки перекладу — це Text Domain і Domain Path.

Text Domain використовується для позначення тексту, що належить директорії.

Це унікальний ідентифікатор, який забезпечує WordPress можливість розрізняти всі завантажені переклади. Це дозволяє зберігати компактність файлів і забезпечує кращу взаємодію з вже існуючими інструментами WordPress.

Text Domain повинен збігатися з slug плагіна. Наприклад, якщо ваш плагін представляє собою один файл, який називається sample-plugin.php, або він міститься в папці sample-plugin, то Text Domain повинен бути sample-plugin.

Уточнення по Text Domain

У text domain повинно використовуватись тире, і неприпустимо використання підкреслення.

Пам’ятаєте, я сказав, що text domain повинен відповідати slug плагіна? Насправді це не зовсім так. Я провів невеликий експеримент з одним з моїх плагінів, замість slug плагіна, я використовував унікальний текст, і він працював без проблем.

Висновок: забезпечте унікальність Text Domain, так щоб він не конфліктував з іншими плагінами.

Domain Path — це папка, в якій WordPress буде шукати файли перекладу .mo.

За замовчуванням WordPress шукає файли в кореневій папці плагіна. Однак розміщення файлу перекладу в кореневій папці може дезорганізувати структуру плагіна.

Якщо ви хочете зберігати файли перекладу в іншій папці, наприклад: /languages, необхідно повідомити про це WordPress, використовуючи заголовок Domain Path.

Нижче наводиться стандартна шапка плагіна WordPress, в тому числі і заголовків перекладу:

Завантаження Text Domain

Щоб WordPress завантажував файл перекладу, якщо він існує для мови користувача, ми можемо використовувати функцію load_plugin_textdomain() function.

Нижче наведена структура даної функції:

Перший параметр $domain повинен представляти text domain; $abs_rel_path — застарілий параметр і його значення повинно бути встановлено на false; і останній параметр $plugin_rel_path — відносний шлях до файлів перекладу.

Якщо MO-файли перекладу знаходяться в папці плагіна, використовується наступний код:

load_plugin_textdomain( ‘espw-plugin’, false, dirname( plugin_basename( __FILE__ ) ) );

Якщо MO-файли перекладу знаходяться в папці мов плагіна, використовується наступне:

load_plugin_textdomain( ‘espw-plugin’, false, dirname( plugin_basename( __FILE__ ) ) . ‘/languages/’ );

Ви не просто викликаєте функцію load_plugin_textdomain, вона повинна викликати у вашому плагіні, тоді ж, коли викликається дія plugins_loaded, наступним чином:

function load_plugin_textdomain() {
load_plugin_textdomain( ‘espw-plugin’, FALSE, basename( dirname( __FILE__ ) ) . ‘/languages/’ );
}
add_action( ‘plugins_loaded’, ‘load_plugin_textdomain’ );

Докладно про інтернаціоналізацію плагіна

Тепер, коли заголовки Text Domain і Domain Path встановлено, пора навчитися інтернаціоналізувати плагін.

Цю частину статті ми розділимо на наступні розділи:

  • Переклад рядків;
  • Використання заповнювачів;
  • Переклад HTML;
  • Робота з множинними формами;
  • Дизамбигуация контексту;
  • Безпека рядків перекладу.

Будь ласка, зверніть увагу: рядок espw-plugin буде використовуватися в якості text domain для цієї статті.

1. Переклад рядків

Щоб зробити рядок плагіна переказаної, оберніть вихідну рядок виклик функції __() наступним чином:

$text = __( ‘Hello, SitePoint Readers!’, ‘espw-plugin’ );

Якщо ви хочете вивести в браузері рядок, а не мовну конструкцію, використовуйте функцію _e:

_e( ‘Hello, SitePoint Readers!’, ‘espw-plugin’ );

2. Використання заповнювачів

Я думаю, ви знаєте, що являють собою заповнювачі. Для отримання додаткової інформації ви можете швидко переглянути сторінки документації PHP sprintf і printf().

Якщо ви використовуєте в рядках змінні, як показано в прикладі нижче, ви повинні використовувати заповнювачі:

echo ‘Your city is $city.’

Коректно наступне використання функції printf():

printf(
__( ‘Your city is %s.’, ‘espw-plugin’ ),
$city
);

Розібравши код деяких плагінів, розміщених у сховищі плагінів WordPress, я побачив там наступне:

echo __(‘Your city is $city’, ‘espw-plugin’);
_e(‘Your city is $city’, ‘espw-plugin’);

Тут перекладаються не лише рядки, але і змінна $city.

Це невдала практика, тому що перекладач може помилково змінити змінну або впровадити шкідливу програму в базовий код плагіна, і це в кінцевому підсумку призведе до збою плагіна.

Функція sprintf схожа на printf тим, що вони обидві форматують рядка, використовуючи заповнювачі, тільки printf виводить відформатовану рядок, а sprintf повертає її.

Приклад: наступний код присвоює відформатовану рядок змінної $text:

$text = sprintf( __(‘Your city is %s.’, ‘espw-plugin’), $city );

3. Переклад HTML

Включення HTML в переказуються рядка залежить від контексту.

В якості прикладу можна навести посилання (відокремлена від навколишнього її тексту):

Іншим прикладом є посилання в параграфі (не відокремлена від тексту навколо неї):

4. Робота з множинними формами

Рядок, яка змінюється, коли змінюється кількість елементів, може бути інтернаціоналізована з допомогою функції _n().

Ця функція приймає 4 аргументу:

  • Singular — єдина форма рядка;
  • Plural — множинна форма рядка;
  • Count — кількість об’єктів, які будуть визначати, повинна повертатися єдина або множинна форма;
  • Text Domaintext domain плагіна.

Давайте розглянемо кілька прикладів, щоб зрозуміти, як працює функція _n().

В англійській версії у вас є «One comment» і «Two comments«. В інших мовах ви можете мати декілька форм для множинних чисел.

Наведений нижче код демонструє, як впоратися з таким сценарієм, використовуючи функцію _n():

printf(
_n(
‘One comment’,
‘%s comments’,
get_comments_number(),
‘espw-plugin’
),
number_format_i18n( get_comments_number() )
);

Пояснення наведеного вище коду складається з цих трьох функцій printf, _n і number_format_i18n.

Для зручності, код функції буде розчленований на пояснення кожного компонента функції:

_n(
‘One comment’,
‘%s comments’,
get_comments_number(),
‘espw-plugin’
)

Першим аргументом, передаваних у функцію _n, є текст, який буде відображатися, коли кількість коментарів одинично.

Другий — текст, який відображається, коли кількість коментарів більше одиниці.

Заповнювач %s буде містити значення number_format_i18n(get_comments_number()), яке я розгляну трохи пізніше.

Третім аргументом get_comments_number() вважається функція, яка повертає кількість коментарів.

Якщо вона повертає 1, тоді функцією printf виводиться перший аргумент, в іншому випадку, якщо значення більше одиниці, повертається другий аргумент %s comments.

Будь ласка, зверніть увагу: заповнювач %s замінюється цілим числом, її обчислене number_format_i18n( get_comments_number() ), що в свою чергу є другим аргументом, переданих у функцію printf.

Нарешті, четвертий аргумент — це text domain перекладу.

Функція number_format_i18n() перетворює кількість коментарів у формат, виходячи з локації перекладу. Для отримання додаткової інформації ознайомтеся з документацією.

Подібно number_format_i18n() date_i18n зажадає дату в локалізованому форматі, на основі тимчасової мітки.

У той же час функція _n(), наведена нижче, демонструє ще один варіант того, як це працює:

printf( _n( ‘We deleted one spam message.’, ‘We deleted %d spam messages.’, $count, ‘my-text-domain’ ), $count );

Якщо змінна $count повертає 1, буде відображатися текст We deleted one spam message; але якщо обчислене значення більше 1, тоді текст We deleted %d spam messages буде відображатися з заповнювачем %d, який замінюється на ціле значення $count.

5. Дизамбигуация контексту

Іноді термін використовується в декількох значеннях. Хоча в англійській мові це одне і те ж слово, на інших мовах воно повинно перекладатися по-різному.

Наприклад, слово Post може використовуватися як в якості дієслова у фразі «Click here to post your comment«, і як іменник: «Edit this post«.

У таких випадках слід використовувати функцію _x або _ex.

Вони схожі на функції __() і _e(), але мають додатковий аргумент — $context:

_x( ‘Post’, ‘noun’, ‘espw-plugin’ );
_x( ‘Post’, ‘verb’, ‘espw-plugin’ );

За допомогою цього методу в обох випадках ми отримаємо рядок Comment для оригінальної версії, але перекладачі побачать два рядки Comment для перекладу, кожна в різному контексті.

Коли рядка, зроблені перекладними з допомогою функції _x(), розбираються інструментами перекладу, такими як Poedit, аргумент контексту надає перекладачеві вказівку на контекст, в якому використана рядок / текст.

На німецький Post як іменник перекладається Beitrag, а як дієслово — verbuchen.

Нижче наведено скріншот з Poedit, на якому показано переведення рядка Post на німецьку з контекстом, взятим у квадратні дужки.

У той час як _x() повертає рядок перекладу, _ex() виводить їх на екран.

6. Безпека рядків перекладу

WordPress має ряд функцій для перевірки і забезпечення безпеки даних.

Список функцій для безпеки текстів переказів включає в себе: esc_html(), esc_html_e(), esc_html_x(), esc_attr(), esc_attr_e() and esc_attr_x(). Більш детальну інформацію ви можете отримати, ознайомившись з розділом Кодексу WordPress по кожній з цих функцій.

Я не буду детально розглядати кожну з них, але в цілому можу сказати, що вони забезпечують безпеку перекладних текстів.

Висновок

Одне із завдань WordPress — забезпечити користувачам по всьому світу можливість легко публікувати свій контент. Як розробник плагіна, ви можете спростити для користувачів процес публікації з допомогою інтернаціоналізації плагінів.

У першій частині цієї статті я, по суті, розповів вам усе, що ви повинні знати про інтернаціоналізацію плагінів.

У заключній частині наведено покрокове керівництво того, як зробити плагін готовим до перекладу. Також ви дізналися, як локалізувати плагін.

Я сподіваюся, ви почерпнули з цієї статті багато цікавого.

Удачі всім!

Переклад статті «WordPress i18n Make Your Plugin Translation Ready» був підготовлений дружною командою проекту Сайтостроение від А до Я.