Public release from ruodoo-project: 19.0 - 2026-11-01 22:52:25 UTC

This commit is contained in:
CI Publish Bot
2026-11-01 22:54:30 +00:00
commit 26250aa580
2492 changed files with 664277 additions and 0 deletions

View File

@@ -0,0 +1,290 @@
=====================
Помощник по переводам
=====================
.. |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/<lang>/<module>.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