86 lines
9.4 KiB
Markdown
86 lines
9.4 KiB
Markdown
Переведенные поля больше не используют модель `ir.translation`. Теперь они хранят все свои значения как `JSON` и сохраняют их в столбцах `JSONB` в
|
||
таблице соответствующей модели. Значение столбца поля либо `NULL`, либо `JSON dict`, где ключом является код языка, а его значение и есть термин. Ключ
|
||
`en_US` всегда ставится по умолчанию, в тех случаях когда нет других ключей Пустой текст допускается в значениях перевода, но не `NULL`.
|
||
|
||
Вот пример поля с параметром `translate=True`:
|
||
|
||
```json
|
||
NULL
|
||
{"en_US": "Foo"}
|
||
{"en_US": "Foo", "fr_FR": "Bar", "nl_NL": "Baz"}
|
||
{"en_US": "Foo", "fr_FR": "", "nl_NL": "Baz"}
|
||
```
|
||
|
||
Как и ранее, если полю установить значение `False` , то на уровне БД оно будет `NULL`, т. е. `False` для всех языков. Однако если установить значение
|
||
`""` (пустая строка) система делает его значение пустым на текущем языке, но не отменяет значения на других языках.
|
||
|
||
Вот пример поля с параметром `translate=xml_translate`:
|
||
|
||
```json
|
||
NULL
|
||
{"en_US": "<div>Foo<p>Bar</p></div>", "fr_FR": "<div>Fou<p>Barre</p></div>"}
|
||
```
|
||
|
||
Изменение для полей `callable(translate)`: теперь в таком поле можно записать любое значение на любом языке. Новое значение будет адаптировано для
|
||
всех языков на основе сопоставления терминов между языками в старых значениях. В основном структура значения должна оставаться одинаковой для всех
|
||
языков, как и раньше.
|
||
|
||
Чтение переведенного поля теперь проще и быстрее, чем в предыдущей реализации. Мы извлекаем значение поля на текущем языке, объединяя его значение со
|
||
значением поля `en_US`:
|
||
|
||
```sql
|
||
SELECT id, COALESCE(name->>'fr_FR', name->>'en_US') AS name ...
|
||
```
|
||
|
||
Необработанный кэш поля содержит в базе данных (за исключением отсутствующих языков) либо `None`, либо `dict`, который концептуально является
|
||
подмножеством значения `JSON` . Для простоты большинство операций кэширования работают с `dict` и возвращают текстовое значение на текущем языке.
|
||
|
||
Индексы триграмм адаптированы к новой стратегии хранения и должны позволять поиск на любом языке. До этого изменения индексировалось только исходное
|
||
значение поля `en_US`.
|
||
|
||
Хранимые вычисляемые переведенные поля не поддерживаются фреймворком из-за сложности самого вычисления: поле должно быть вычислено на всех активных
|
||
языках. Мы решили не предоставлять никаких хуков для вычисления поля на всех языках одновременно, и фреймворк всегда вызывает метод вычисления один
|
||
раз, чтобы пересчитать его.
|
||
|
||
Переводы кода больше не хранятся в базе данных. Они становятся статическими и извлекаются из файлов PO по мере необходимости. Worker просто использует
|
||
кэш с извлеченными переводами кода для производительности. Это разумно, так как переводы кода `fr_FR` для всех модулей занимают около 2 МБ памяти, и
|
||
кэш может быть общим для всех реестров в Worker. Изменение переводов кода требует обновления соответствующего файла PO и перезагрузки Worker.
|
||
|
||
Сводка по производительности: (+) чтение переведенных полей `model` происходит быстрее (+) чтение переведенных полей `model_terms` происходит намного
|
||
быстрее (нет необходимости вводить переводы в исходное значение) (+) поиск переведенных полей с оператором `ilike` происходит намного быстрее, если
|
||
поле индексировано с помощью `trigram` (+) обновление переведенных полей требует меньше очистки `ORM` (-) импорт переводов из файлов `PO` происходит в
|
||
2 раза медленнее
|
||
|
||
Несколько экстра исправлений: сделать поле `name` модели `ir.actions.actions` переведенным; из-за наследования `PG` это необходимо для того, чтобы
|
||
сделать определение столбца согласованным во всех моделях, которые наследуются от `ir.actions.actions`. добавить внутренний API для
|
||
веб-клиента/клиента веб-сайта для редактирования переводов переместить методы `get_field_string()` в модель `ir.model.fields` переместить
|
||
`_load_module_terms` в модель `ir.module.module` адаптировать тесты в `test_impex`, `test_new_api` поскольку `env.lang` внедряется в запросы `SQL`,
|
||
его возвращаемое значение теперь гарантированно соответствует допустимому активному языку или `None` удалить мастер для вставки отсутствующих
|
||
переводов (больше не имеет смысла)
|
||
|
||
task-id: 2081307
|
||
|
||
Резюме по исследованию формирования переводов для представлений: Переводы для имен полей формируются следующим образом:
|
||
|
||
1. Необходимо иметь перевод в PO файле, тогда при обновлении перевода как такового, применится новый перевод
|
||
2. Для перевода имени поля создается в модели `ir.model.fields` создано поле `field_description` которое и хранит его перевод
|
||
3. Тем не менее данный перевод будет применен только после перезагрузке системы
|
||
4. Это связано с тем, что при обновлении страницы вызывается метод `get_views` из модели `ir.ui.view` в ответе которого есть ключ `models`, и в нем
|
||
содержатся переводы для имен полей. Но происходит это не через переводы, а через сбор атрибутов поля Есть предположение что для конкретного языка в
|
||
памяти создается единожды класс для каждого поля с переведенными атрибутами и именно по этому помогает только перезагрузка.
|
||
|
||
Дополнительные сведения полученные экспериментальным путем
|
||
|
||
1. Если в каталоге i18n есть pot файл, то если в нем не указаны какие либо термины для перевода, то эти термины будут игнорироваться во всех po файлах
|
||
этих переводов. Т.е для того, чтобы переводы из po файла применились нужно указать термины в pot файле, либо удалить pot файл из каталог
|
||
2. Часть терминов берется напрямую из po файлов при обновлении страницы и на фронт загружаются все термины, которые помечены комментарием
|
||
`#. odoo-javascript`
|
||
3.
|
||
|
||
В системе есть как минимум 3 больших блока для которых необходимо сформировать инструменты для перевода:
|
||
|
||
1. Атрибуты полей
|
||
2. Термины для перводов во вьюхах в том числе и Search View
|
||
3. Термины для переводов в js коде
|
||
4. Меню?
|