Skip to main content

Архитектура поддержки переводов интерфейсов на другие языки для wordpress в целом и в связке с React

Ниже — полная архитектура переводов в WordPress:

1️⃣ как это работает в целом
2️⃣ как это работает в PHP
3️⃣ как это работает в React / Gutenberg
4️⃣ как соединяются PHP + JS переводы
5️⃣ как это обычно делают профессиональные плагины.


1. Общая архитектура переводов в WordPress

Система переводов в WordPress состоит из 4 уровней:

код → POT → PO → MO / JSON

1️⃣ Код

В коде используются функции:

PHP:

__()
_e()
_n()
_x()

JS:

wp.i18n.__()
wp.i18n._n()
wp.i18n._x()

2️⃣ POT (template)

.pot — шаблон переводов.

Пример:

nv-seo.pot

Он содержит все строки из кода.


3️⃣ PO

Файл конкретного языка:

ru_RU.po
de_DE.po
fr_FR.po

Пример:

msgid "Save settings"
msgstr "Сохранить настройки"

4️⃣ MO / JSON

WordPress использует:

тип для
MO PHP
JSON JavaScript

2. Архитектура переводов для PHP

структура плагина

plugin
 ├─ languages
 │   ├─ nv-seo.pot
 │   ├─ nv-seo-ru_RU.po
 │   ├─ nv-seo-ru_RU.mo
 │
 ├─ nv-seo.php

подключение textdomain

add_action('plugins_loaded', function () {

    load_plugin_textdomain(
        'nv-seo',
        false,
        dirname(plugin_basename(__FILE__)) . '/languages'
    );

});

использование

__('Settings saved', 'nv-seo')

или

echo __('Save', 'nv-seo');

3. Архитектура переводов для React / JS

В React используется пакет:

@wordpress/i18n

(глобально это wp.i18n)


использование

import { __ } from '@wordpress/i18n';

__('Save settings', 'nv-seo')

пример React

import { __ } from '@wordpress/i18n';
import { Button } from '@wordpress/components';

export default function SaveButton() {

    return (
        <Button variant="primary">
            {__('Save settings', 'nv-seo')}
        </Button>
    );

}

4. Как WordPress переводит JS

WordPress не использует MO для JS.

Он использует:

JSON

пример:

languages/nv-seo-ru_RU-3a4f2.json

5. Связка PHP и JS

Очень важная функция:

wp_set_script_translations()

Она говорит WordPress:

"подключи JSON переводы для этого JS файла"


пример

wp_enqueue_script(
    'nv-seo-admin',
    plugins_url('build/index.js', __FILE__),
    ['wp-i18n', 'wp-element', 'wp-components'],
    '1.0',
    true
);

wp_set_script_translations(
    'nv-seo-admin',
    'nv-seo',
    plugin_dir_path(__FILE__) . 'languages'
);

6. Как формируется JSON

WordPress CLI генерирует его из PO.

wp i18n make-json languages

Результат:

nv-seo-ru_RU-xxxx.json

7. Полная структура современного плагина

nv-seo
│
├─ src
│   └─ index.js
│
├─ build
│   └─ index.js
│
├─ languages
│   ├─ nv-seo.pot
│   ├─ nv-seo-ru_RU.po
│   ├─ nv-seo-ru_RU.mo
│   ├─ nv-seo-ru_RU-xxxx.json
│
├─ nv-seo.php
└─ package.json

8. Поток разработки

1️⃣ пишем код

PHP:

__('Save settings', 'nv-seo')

JS:

__('Save settings', 'nv-seo')

2️⃣ генерируем POT

wp i18n make-pot . languages/nv-seo.pot

3️⃣ создаём переводы

ru_RU.po

через:

  • Poedit

  • Loco Translate


4️⃣ компилируем

PO → MO


5️⃣ генерируем JSON

wp i18n make-json languages

9. Как делают крупные плагины

Например:

  • Yoast SEO

  • Rank Math

  • WooCommerce

используют:

languages/
build/
src/

и WordPress i18n CLI.


10. Лучшие практики

всегда указывайте textdomain

__('Save', 'nv-seo')

не используйте динамические строки

❌ плохо

__(text, 'nv-seo')

используйте sprintf

sprintf(
    __('Found %d errors', 'nv-seo'),
    count
)

используйте контекст

_x('Post', 'noun', 'nv-seo')

11. Очень важная оптимизация "Code splitting"

Если ваш интерфейс React большой, лучше:

code splitting

тогда JSON будет загружаться по частям.

Code splitting — это разбиение большого JavaScript-бандла на несколько файлов, которые загружаются только тогда, когда они реально нужны.
В WordPress это особенно полезно для React-интерфейсов в админке, чтобы не грузить весь JS сразу.

В сборке через @wordpress/scripts code splitting уже поддерживается, потому что внутри используется Webpack.


1. Основная идея

Без code splitting:

index.js
   ↓
build/index.js (400 KB)

С code splitting:

index.js
   ↓
build/index.js
build/settings.js
build/schema.js
build/faq.js

Подгружается только нужный модуль.


2. Как это делается в React

Используется dynamic import().

обычный импорт
import SettingsPage from './settings';

всё попадает в один файл.


dynamic import
const SettingsPage = import('./settings');

Webpack создаст отдельный chunk.

Но в React правильнее использовать React.lazy.


3. Пример code splitting

структура

src
 ├─ index.js
 ├─ pages
 │   ├─ dashboard.js
 │   ├─ schema.js
 │   └─ settings.js

index.js
import { lazy, Suspense } from '@wordpress/element';
import { Spinner } from '@wordpress/components';

const Dashboard = lazy(() => import('./pages/dashboard'));
const Settings = lazy(() => import('./pages/settings'));

export default function App() {

    return (
        <Suspense fallback={<Spinner />}>
            <Dashboard />
        </Suspense>
    );

}

4. Что создаст сборка

После

npm run build

в папке build будет:

build
 ├─ index.js
 ├─ dashboard.js
 ├─ settings.js

5. Как WordPress загружает chunks

Важный момент.

WordPress должен знать путь:

wp_enqueue_script(
    'nv-seo-admin',
    plugins_url('build/index.js', __FILE__),
    ['wp-element','wp-components','wp-i18n'],
    '1.0',
    true
);

Webpack автоматически будет подгружать:

build/dashboard.js
build/settings.js

через

import()

6. Как это выглядит в браузере

Без splitting:

index.js 400KB

Со splitting:

index.js 80KB
settings.js 100KB
schema.js 120KB
faq.js 100KB

7. Где это особенно полезно

В вашем SEO-плагине можно разделить:

src
 ├─ index.js
 ├─ pages
 │   ├─ dashboard.js
 │   ├─ schema.js
 │   ├─ sitemap.js
 │   └─ redirects.js

Пользователь открывает Schema → грузится только:

schema.js

8. Пример с роутингом

Если используется **React Router:

const Settings = lazy(() => import('./pages/settings'));
const Schema = lazy(() => import('./pages/schema'));

9. Очень полезная оптимизация

Можно разбить даже библиотеки.

Например:

schema-builder.js

грузить только при редактировании Schema.


10. Важный момент для WordPress

Чтобы chunks работали, build папка должна содержать все файлы:

build
 ├─ index.js
 ├─ index.asset.php
 ├─ 234.js
 ├─ 567.js

WordPress автоматически подхватывает зависимости из:

index.asset.php

11. Подключение через asset

Правильный способ:

$asset = include plugin_dir_path(__FILE__) . 'build/index.asset.php';

wp_enqueue_script(
    'nv-seo-admin',
    plugins_url('build/index.js', __FILE__),
    $asset['dependencies'],
    $asset['version'],
    true
);

12. Итог по "Code splitting"

Code splitting позволяет:

✔ ускорить загрузку
✔ уменьшить первый бандл
✔ грузить код по требованию

Это стандартная практика для:

  • Yoast SEO

  • WooCommerce

  • Rank Math


12. Типичная проблема новичков

Они думают:

JSON перевод нужно писать вручную.

Нет.

Он генерируется автоматически.


13. Самая правильная архитектура для вашего SEO-плагина

nv-seo
 ├─ src
 │   └─ admin
 │       └─ index.js
 │
 ├─ build
 │   └─ admin.js
 │
 ├─ languages
 │   ├─ nv-seo.pot
 │   ├─ nv-seo-ru_RU.po
 │   ├─ nv-seo-ru_RU.mo
 │   ├─ nv-seo-ru_RU.json
 │
 └─ nv-seo.php