Public release from ruodoo-project: 19.0 - 2026-11-01 22:52:25 UTC
This commit is contained in:
290
translation_helper/README.rst
Normal file
290
translation_helper/README.rst
Normal 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
|
||||
Reference in New Issue
Block a user