Files
public/translation_helper/README.rst

291 lines
16 KiB
ReStructuredText
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
=====================
Помощник по переводам
=====================
.. |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