Skip to main content

Translation

Сервис переводов

Для понимания это управление умной экселькой, в которой первая колонка это ключ перевода, а вторая и последующие колонки - перевод на разных языках (каждая колонка - это новый язык)

Make New Enc Keys

ulapiutls enc_keys --algorithm RS256 --follower-services translation-web --service-name translation-auth --jwt-permissions-module src.conf.permissions --jwt-environment local --jwt-user-id 6ff8eaba-b5b4-49b2-9a83-f48fcdf6d361

Services

  • translation__balancer = nginx
  • translation__public_api = flask+sqlalchemy
  • translation__internal_api = flask+sqlalchemy
  • translation__auth_api = COMMON SERVICE
  • translation__management_view = flask+jingja2
  • translation__db = pg14
  • translation__db_ui = pgweb

Структура хранимых данных

lang:
    id: uuid, pk
    user_created: uuid, fk(api_user)
    user_modified: uuid, fk(api_user)
    date_created: date-time, utc
    date_modified: date-time, utc
    is_alive: bool

    name: str(255), uniq  # human readable text in ANY LANGUAGE
    abbr: str(10), uniq, ASCII symbols only, RESTRICT WHITE SPACES  # exaples - en, ru, en_EN, en_US, ...

key:
    id: uuid, pk
    user_created: uuid, fk(api_user)
    user_modified: uuid, fk(api_user)
    date_created: date-time, utc
    date_modified: date-time, utc
    is_alive: bool

    name: str(255), uniq, ASCII symbols only, RESTRICT WHITE SPACES !!!!   # examples - "account.something.0.else",   "user_profile.full_name", "name"  

translation:  # не может стать удаленным или помечен быть как удален
    id: uuid, pk
    user_created: uuid, fk(api_user)
    user_modified: uuid, fk(api_user)
    date_created: date-time, utc
    date_modified: date-time, utc

    lang_id: fk(lang)
    key_id: fk(key)
    content: text  #  ЛЮБАЯ СТРОКА. БЕЗ ВАЛИДАЦИИ. ПУСТАЯ СТРОКА ВАЛИДНА

translation_cache:  # material-view, trigger(translation, key, lang). ТОЛЬКО активные записи
    translation_id: uuid, fk(translation)
    lang_abbr: str(10)
    key_name: str(255)
    translation_content: text

    # constaint: uniq_together(lang_id, key_id, content)

PUBLIC API service

GET /lang/en_EN/translation-cache

где en_EN - это существующая абривиатура языка

нет авторизации. ЛЮБОЙ может получить ответ

Кэш запроса на уровне nginx = 1 час

Строится ответ по таблице translation-cache

ключи сортируются согласно alpha-numeric

{
    "key.name": "translation_content",
    "field.0.some": "translation_content 2",
    /*другие ключи этого языка и переводы к ним*/
}

если такого языка не найдено в translation_cache то возвращается пустой обьект со статусом 404

GET /lang/en_EN/translation-cache-compiled

тоже самое что и GET /lang/en_EN/translation-cache НО ключи разворачиваются согласно точкам в структуры обьектов

если точка вначале или в конце - игнорируются

Напрмер key.name - это вложенные обьекты. в первом есть атрибут key и его значение равен обьекту у которого есть ключ name. пустая строка = валидное проперти обьекта

{
    "key": {
        "name": "translation_content",
    },

    "field": {
        "0": {
            "some": "translation_content 2"
        }
    },
    /*другие ключи этого языка и переводы к ним*/
}

Решением построения дерева предлагается как утилитарная функция

def set_obj_attr_by_path(mut_obj: Dict[str, Any], path_key: str, value: Any) -> NDict[str, Any]:
    obj = mut_obj 
    segments = path_key.strip(".").split(".")
    for i, segment in enumerate(segments):
        if i == (len(segments) - 1):
            obj[segment] = value
        else:
            if segment not in obj:
                obj[segment] = dict()
            obj = obj[segment]
    return mut_obj

INTERNAL API service

Languages API

GET /langs

Получение списка всех (даже неактивных) языков (при создании нового, создаются записи для всех переводов translation по всем существующим ключам с пустым контентом)

/* Response example */
[
    {
        "id": "...",
        "user_created": "...",
        "user_modified": "...",
        "date_created": "...",
        "date_modified": "...",
        "is_alive": "...",

        "name": "English",
        "abbr": "en_EN",
    },
    ...
]

GET /langs/:id

Получение списка конкретного языка

/* Response example */
{
    "id": "...",
    "user_created": "...",
    "user_modified": "...",
    "date_created": "...",
    "date_modified": "...",
    "is_alive": "...",

    "name": "English",
    "abbr": "en_EN",
}

POST /langs/

Созданиен языка

/* Request example */
{
    "name": "Russian",
    "abbr": "ru_RU",
}

PUT /langs/:id

Изменение конкретного языка

/* Request example */
{
    "id": "...",
    "user_created": "...",
    "user_modified": "...",
    "date_created": "...",
    "date_modified": "...",
    "is_alive": "...",

    "name": "Russian",
    "abbr": "ru_RU",
}

DELETE /langs/:id

Удаление конкретного языка

Keys API

GET /keys

Получение списка всех (даже неактивных) ключей

/* Response example */
[
    {
        "id": "...",
        "user_created": "...",
        "user_modified": "...",
        "date_created": "...",
        "date_modified": "...",
        "is_alive": "...",

        "name": "field.3.some",
    },
    ...
]

GET /keys/:id

Получение списка конкретного ключа

/* Response example */
{
    "id": "...",
    "user_created": "...",
    "user_modified": "...",
    "date_created": "...",
    "date_modified": "...",
    "is_alive": "...",

    "name": "field.3.some",
}

POST /keys/

Созданиен ключа

/* Request example */
{
    "name": "field.3.some",
}

PUT /keys/:id

Изменение конкретного ключа

/* Request example */
{
    "id": "...",
    "user_created": "...",
    "user_modified": "...",
    "date_created": "...",
    "date_modified": "...",
    "is_alive": "...",

    "name": "field.3.some",
}

DELETE /keys/:id

Удаление конкретного языка

Translation API

GET /translations

Получение списка всех переводов

/* Response example */
[
    {
        "translation_id": "fk(translation).id",
        "lang_abbr": "en_EN",
        "key_name": "field.3.some",
        "translation_content": "",
    },
    ...
]

GET /translations/:id

Получение списка конкретного переводов

/* Response example */
{
    "translation_id": "fk(translation).id",
    "lang_abbr": "en_EN",
    "key_name": "fields.3.some",
    "translation_content": "some text",
}

POST /translations

Созданиен ключа

/* Request example */
{
    "translation_id": "fk(translation).id",
    "content": "some text",
}

PUT /translations

Изменение конкретного ключа

/* Request example */
[
    {
        "translation_id": "fk(translation).id",
        "content": "some text",
    }
]

View service

Работает через логин в котором вставляется токен авторизации в поле при старте приложения

Токен генерируется в Auth Api

pages:

  • Login
  • Lang
  • Keys
  • Translation
  • Import *
  • Export *

Login Page

Одно поле - токен, который потом записывается в куку, если токен валиден

Lang Page

это таблица со всеми языками (даже с неактивными)

можно редактировать языки, добавлять, удалять - через модалку

модалка - поля, кнопка сохранить, кнопка отменить

Keys Page

это таблица со всеми ключами (даже с неактивными)

можно редактировать ключи, добавлять, удалять - через модалку

модалка - поля, кнопка сохранить, кнопка отменить

Translation Page

таблица строится по translation_cache и key

Выводятся Абсолютно все активные записи

колонки:

  • ПЕРВАЯ КОЛОНКА = key_name всех активных ключей
  • остальные колонки это все доступные АКТИВНЫЕ языки и переводы к ним

Ячейки в которых нет текста должны подстветиться оранжевым (или другим ярким) цветом

строки отсортированы по имени ключа

Нажимая на строку (или только на ключ строки) открывается модалка с изменениями сразу всех возможных переводов для данного ключа. ключ менять нельзя. после применения страница перезагружается

модалка - поля, кнопка сохранить, кнопка отменить

Export Page *

Кнопка с генерацией файла на скачку

Формат файла - JSON

Экспортируются ТОЛЬКО активные записи !

{
    "langs": [{/*... все поля языков*/}, /*...*/],
    "key": [{/*... все поля ключей*/}, /*...*/],
    "translation": [{/*... все поля переводов*/, /*...*/}],
}

Import Page *

На странице есть кнопка с загрузкой файла

Формат файла точно соответсвует формату файла экспорта.

Любое несоотвествие, лишние поля итп - ошибка !

Если такой айди существует - контент заменяется

Применяется одной транзакцией

Metadata

Release files for ul-translation-sdk 3.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ul-translation-sdk 3.0.0
File Size Uploaded
ul_translation_sdk-3.0.0.tar.gz 14.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ul-translation-sdk 3.0.0
File Interpreter ABI Platform
ul_translation_sdk-3.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 28.7 kB

Release files / ul_translation_sdk-3.0.0.tar.gz

Download URL ul_translation_sdk-3.0.0.tar.gz
Size 14.3 kB
Tags Source
SHA-256 checksum
How to use checksums
ee24fa2e505ddf1099a17f636e757f99c66d21164faad0b39f76d19accab3bcd
BLAKE2b-256 checksum
How to use checksums
9593522a28c25851fa990dd5992ee1a24d7a418d8901a28d9441f96c9f219f2a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Release files / ul_translation_sdk-3.0.0-py3-none-any.whl

Download URL ul_translation_sdk-3.0.0-py3-none-any.whl
Size 14.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d4155b59bb561f1df29bc5132b9c7dbae08b35058a1de9e5cbbe770ac92c2305
BLAKE2b-256 checksum
How to use checksums
f0eb23d9b3009bfb1eb60a669aa6ae537a5732b368e7f42c48a5ad0ee0aa80b7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Release history Release notifications | RSS feed

This release

3.0.0 This release

2 release files

2.0.8

2 release files

2.0.7

2 release files

2.0.4

2 release files

2.0.3

2 release files

2.0.2

2 release files

2.0.1

2 release files

1.2.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page