===================== Помощник по переводам ===================== .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status :alt: Beta .. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html :alt: License: LGPL-3 |badge1| |badge2| .. warning:: Модуль находится на стадии бета-тестирования. Использование в промышленной эксплуатации требует осторожности. Модуль для Odoo 19 Community Edition. Помогает переводчику работать прямо в интерфейсе Odoo: переводить поля, представления и меню «на лету», накапливать переводы в локальных PO-файлах и переносить переводы между базами данных. **Содержание** .. contents:: :local: Назначение ========== Модуль решает две задачи: #. **Ручной перевод** полей, представлений и меню прямо из интерфейса Odoo — без ручного редактирования PO-файлов и без перезапуска сервера для большинства случаев. #. **Перенос переводов** из внешних источников: из Weblate (старая интеграция) и — что нового — напрямую с удалённой базы Odoo по XML-RPC. Ключевая архитектурная предпосылка: в Odoo 16+/19 модели ``ir.translation`` больше нет. Переводы хранятся в JSONB-колонках самих моделей. Поэтому перенос переводов между базами выполняется только через штатный PO-pipeline (export → PO → import), а не через чтение/запись ``ir.translation``. Подробности — в разделе «Техническая архитектура». Возможности =========== * Ручной перевод полей через контекстное меню в UI («Режим переводчика»). * Перевод нескольких полей одновременно. * Поддержка переводимых полей типа ``char``, ``text`` и ``html``. * Перевод меню и элементов представлений (метки полей, подсказки, текст-заполнитель, метки кнопок, заголовки групп). * Сохранение переводов в локальные PO-файлы модулей (``translations//.po``). * Локальные PO-оверрайды: модуль подменяет штатные PO-файлы Odoo своими файлами из каталога ``translations/`` через монкипатчи ``odoo.tools.translate``. * Интеграция с Weblate (старая интеграция; на момент ревью известно нерабочая, см. соответствующий раздел). * **Новое:** «Загрузка перевода из удалённой базы» — тянет переводы выбранных модулей с удалённого Odoo-сервера по XML-RPC и применяет их локально. Активация и ручной перевод из UI ================================= #. Установите модуль. #. Перейдите в настройки и активируйте **«Режим переводчика»** — он работает аналогично режиму разработчика. #. В правом верхнем углу появится дополнительная иконка. Нажмите на неё, чтобы открыть меню доступных действий перевода. #. У каждого пункта меню появится иконка перевода. При изменении перевода он применяется, и страница автоматически перезагружается. #. У каждого поля появится кнопка перевода. Можно перевести: * название поля; * подсказку (tooltip), которая показывается при наведении на знак вопроса. Перевод применяется немедленно. #. Все переводы сохраняются: * в базу данных (в JSONB-колонки моделей); * в ``.po``-файлы выбранного языка, с именем модуля, в котором объявлен термин. Например, перевод термина из модуля ``crm`` попадёт в файл:: translation_helper/translations/<код_языка>/crm.po Локальные PO-оверрайды ====================== Модуль переопределяет внутренние точки ``odoo.tools.translate`` в ``__init__.py`` (монкипатчи ``get_po_paths`` и ``TranslationReader._push_translation``), а также ``_load_module_terms`` в ``ir.module.module``. Благодаря этому при загрузке переводов Odoo обращается не к штатному файлу модуля, а к локальному оверрайду модуля ``translation_helper``. Например, при выборе русского языка система «на лету» подменяет обращение к файлу ``odoo/addons/crm/i18n/ru.po`` на ваш собственный файл ``translation_helper/translations/ru/crm.po``. Это позволяет накапливать собственные переводы, независимые от апстрима, и переносить их между инстансами простым копированием модуля. .. important:: **Хрупкая точка:** монкипатчи повторяют приватную логику Odoo. При обновлении Odoo сигнатуры этих внутренних функций могут измениться, что молча сломает подмену переводов. Проверяйте совместимость после обновлений. Интеграция с Weblate ==================== Модуль содержит старую интеграцию с Weblate (``models/translation_service.py``, ``wizards/translation_helper_wizard.py``, настройки Weblate в ``res.config.settings``). Она формирует ссылки на проект Weblate для выбранных модулей и языка. .. note:: **Статус:** на момент ревью Weblate-путь известно нерабочий (вероятные причины — ошибка области видимости переменной при сборке ссылки, жёсткая привязка к внешнему серверу, пустая запись ``res.lang``). Используйте с осторожностью; основные рабочие сценарии — ручной перевод и загрузка из удалённой базы. Загрузка перевода из удалённой базы =================================== Позволяет вытянуть переводы выбранных модулей с удалённого сервера Odoo и применить их в текущей базе — без ручного экспорта/импорта PO-файлов. Где находится ------------- Меню: **Настройки → Переводы → «Загрузка перевода из удаленной базы»** (пункт меню доступен только пользователям группы «Администратор настроек», ``base.group_system``). Поля визарда ------------ .. list-table:: :header-rows: 1 :widths: 25 75 * - Поле - Назначение * - ``remote_url`` - URL удалённого сервера Odoo (например, ``http://192.168.1.10:8069``). * - ``remote_db`` - Имя базы данных на удалённом сервере. * - ``remote_user`` - Логин на удалённом сервере (по умолчанию ``admin``). * - ``remote_password`` - Пароль (или API-ключ) удалённого пользователя. * - ``modules`` - Список модулей, переводы которых нужно загрузить (только установленные на удалённой стороне). * - ``language`` - Язык (``res.lang``), по умолчанию ``ru_RU``. * - ``overwrite`` - Перезаписывать существующие переводы значениями из удалённой базы. * - ``save_credentials`` - Запомнить URL, базу, логин и пароль для повторного использования. Как пользоваться (по шагам) --------------------------- #. Откройте **Настройки → Переводы → «Загрузка перевода из удаленной базы»**. #. Заполните параметры подключения: ``remote_url``, ``remote_db``, ``remote_user``, ``remote_password``. #. Выберите модули (``modules``) и язык (``language``). #. При необходимости включите ``overwrite`` и/или ``save_credentials``. #. Нажмите **«Просмотр»** (режим ``preview``). Модуль подключится к удалённому серверу, выполнит экспорт PO и покажет сводку: сколько всего записей, сколько переведено, и первые строки «оригинал → перевод». Скачанный PO кэшируется в визарде. #. Нажмите **«Загрузить»** (режим ``sync``). Переводы импортируются в текущую базу через штатный ``TranslationImporter``. По завершении визард показывает итоговое сообщение (модули, язык, число записей, режим перезаписи). Режимы ------ * **preview** — только читает переводы с удалённой базы и показывает сводку, ничего не меняя локально. Скачанный PO кэшируется для последующего применения. * **sync** — применяет переводы к текущей базе. Если PO уже скачан на шаге preview, используется кэш; иначе экспорт выполняется заново. Что делает ``overwrite`` ------------------------ * ``overwrite = True`` (по умолчанию) — существующие локальные переводы заменяются значениями из удалённой базы. * ``overwrite = False`` — заполняются только отсутствующие переводы, уже имеющиеся локальные значения сохраняются. Сохранение учётных данных ------------------------- При включённом ``save_credentials`` параметры подключения (``remote_url``, ``remote_db``, ``remote_user``, ``remote_password``) сохраняются в ``ir.config_parameter`` и подставляются при следующем открытии визарда. .. warning:: **Безопасность:** пароль сохраняется в ``ir.config_parameter`` в открытом виде — он читается администраторами и попадает в дампы/бэкапы БД. Рекомендуется использовать для удалённого доступа отдельный API-ключ (который можно отозвать) и отключать ``save_credentials`` на боевых серверах. Соединение идёт по указанному URL; для защиты учётных данных используйте ``https://``. Требования ========== * Odoo 19 Community Edition. * Внешние Python-зависимости: ``siphashc``, ``polib``. * Для новой фичи: сетевой доступ к XML-RPC-эндпоинтам удалённого сервера Odoo (``/xmlrpc/2/common``, ``/xmlrpc/2/object``) и учётные данные с правами на экспорт переводов на удалённой стороне. Техническая архитектура ======================== Хранение переводов в Odoo 19 ---------------------------- В Odoo 16+/19 модели ``ir.translation`` **не существует**. Переводы хранятся прямо в JSONB-колонках самих моделей: значение колонки — это ``JSON``-словарь вида ``{"en_US": "Foo", "ru_RU": "Фу"}``, где ключ — код языка. Ключ ``en_US`` используется по умолчанию. Поэтому единственный надёжный, кросс-версионный путь переноса переводов между базами — штатный PO-pipeline, а не прямое чтение/запись ``ir.translation``. Поток новой фичи ---------------- Передача переводов между базами идёт только через PO: #. **Экспорт на удалённой базе** — через штатный визард ``base.language.export`` (режим ``module``, формат ``po``). #. **Передача** PO по XML-RPC в виде base64. #. **Локальный импорт** — через ``TranslationImporter``, который пишет значения в JSONB-колонки. XML-RPC-поток ------------- * Аутентификация: ``POST /xmlrpc/2/common`` → ``authenticate(db, user, password)`` возвращает ``uid``. * Вызовы моделей: ``/xmlrpc/2/object`` → ``execute_kw(db, uid, password, model, method, args)``. Последовательность вызовов при экспорте с удалённой стороны: #. ``ir.module.module.search`` — найти установленные модули по именам. #. ``base.language.export.create`` — создать визард экспорта (``lang``, ``format=po``, ``export_type=module``, список модулей). #. ``base.language.export.act_getfile`` — сгенерировать PO и записать его в поле ``data``. #. ``base.language.export.read(['data', 'name'])`` — прочитать base64-содержимое PO. Полученный PO декодируется из base64 и импортируется локально через ``TranslationImporter.load()`` + ``save(overwrite=...)`` с последующим ``cr.precommit.run()``. Разделение по слоям ------------------- * ``models/remote_translation_service.py`` — ``AbstractModel`` ``translation.remote.service``: XML-RPC-транспорт и PO-pipeline (``fetch_po_from_remote``, ``apply_po``, ``preview_po``). * ``wizards/remote_translation_sync_wizard.py`` — ``TransientModel`` ``translation.remote.sync.wizard``: форма, предпросмотр, применение, сохранение учётных данных. * ``views/remote_translation_sync_wizard_views.xml`` — форма визарда (состояния ``form → preview → done``), action и пункт меню в ``base.menu_translation_export``. * ``security/ir.model.access.csv`` — ACL визарда для ``base.group_system``. Авторы ====== * MK.Lab, RuOdoo .. image:: https://ruodoo.ru/logo.png :alt: MK.Lab, RuOdoo :target: https://ruodoo.ru