Загрузка...

Loco Translate блокирует запись: «File modification disallowed by the plugin settings»

Короткая заметка о том, как я полчаса разбирался с ошибкой, которая не имела
никакого отношения к правам на файлы, и куда вообще копать, если в Loco
Translate вдруг не сохраняются переводы.

Симптом

Loco Translate в админке WP перестал сохранять .po/.mo файлы плагина.
Сообщение:

File modification disallowed by the plugin settings

При этом chmod показывает 0664, владелец совпадает с пользователем
PHP-FPM, остальные плагины правятся нормально. То есть на уровне FS всё
выглядит рабочим.

Куда смотреть в первую очередь

Ошибка не про DISALLOW_FILE_MODS и не про WP wp_is_file_mod_allowed(). Это
сообщение внутренней проверки Loco, которая срабатывает в
FileWriter::authorize() (loco-translate/src/fs/FileWriter.php):

$opts = Loco_data_Settings::get();

// Запрет на запись в «опасные» системные папки
if (1 < $opts->fs_protect && $this->file->getUpdateType()) {
    throw new Loco_error_WriteException( ... );
}

// Главное: путь должен попадать в список «разрешённых» директорий
$roots = Loco_fs_Locations::getBaseDirs();
if ($roots->count() && ! $roots->check($this->file->getPath())) {
    throw new Loco_error_WriteException(
        __('File modification disallowed by the plugin settings', 'loco-translate')
    );
}

Список разрешённых директорий — это опция fs_basedir в wp_options.loco_settings.
В UI она называется Restricted writeable directories (раздел
File system access в настройках Loco). По дефолту там wp-content
значение относительно ABSPATH, каждая директория с новой строки.

Что не так с дефолтом

После нормализации значение wp-content превращается в абсолютный путь
через Loco_fs_File::normalize(ABSPATH). В текущей версии (Loco 2.8.x) путь
для относительного сегмента wp-content резолвится так, что префикс не
совпадает с реальным расположением плагина — check() возвращает false,
хотя по логике должен бы быть true.

Грубо: это баг/особенность нормализации относительных путей в Loco 2.8.4.
Другие плагины (themes, wp-content/languages/plugins) у меня работали,
а wp-content/plugins/woo2iiko/languages/ — нет.

Решение

Самое простое: оставить поле «Restricted writeable directories» пустым.

Код выше использует короткое замыкание &&:

if ($roots->count() && ! $roots->check(...)) { ... }

Если fs_basedir пустой, getBaseDirs() вернёт пустую коллекцию,
count() === 0, условие целиком ложно, и проверка отключается. Loco в
таком случае полагается на fs_protect (защита «installed files») — этого
достаточно для большинства случаев.

Шаги:

  1. WP-админка → Loco Translate → Settings.
  2. Секция File system access → поле Restricted writeable directories.
  3. Очистить поле, сохранить.

После этого правки .po/.mo снова сохраняются. Остальные настройки
(fs_protect, pot_protect, fs_persist) остаются по дефолту.

Если нужен более строгий режим

По официальной документации Loco рекомендует хранить пользовательские
переводы вне wp-content/plugins/..., потому что WP-обновления могут
затереть файлы. Канонический путь — wp-content/languages/loco/<domain>/.
Тогда в Restricted writeable directories указывается:

wp-content/languages/loco

И при сохранении перевода в Loco нужно выбирать именно эту папку. Это
безопаснее, но требует переноса существующих .po файлов.

Итог

  • Сообщение «File modification disallowed by the plugin settings» — это не
    про FS-права, а про настройку Restricted writeable directories в Loco.
  • Если wp-content (дефолт) не пускает в wp-content/plugins/<plugin>/languages/,
    обнулите поле — проверка отключится по short-circuit.
  • Для продакшна лучше перенести переводы в wp-content/languages/loco/.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *