Desarrollo de complementos¶
Complementos son una forma de personalizar el flujo de trabajo de localización en Weblate.
- class weblate.addons.base.BaseAddon(storage)¶
Base class for Weblate add-ons.
- classmethod can_install(*, component=None, category=None, project=None) bool¶
Check whether add-on is compatible with given component.
- change_event(change, activity_log_id: int | None = None)¶
Event handler for change event.
- check_change_action(change) bool¶
Early filtering of Change actions before triggering change_event callback.
- component_update(component, activity_log_id: int | None = None)¶
Event handler for component update.
- configure(configuration) None¶
Save configuration.
- daily(component=None, category=None, project=None, activity_log_id: int | None = None)¶
Scope-aware daily entry point.
Override this for project-level logic, or override daily_component() for per-component logic.
- daily_component(component, activity_log_id: int | None = None)¶
Per-component daily processing. Override this for component-level logic.
- classmethod get_add_form(user, *, component=None, category=None, project=None, **kwargs)¶
Return configuration form for adding new add-on.
- classmethod get_api_urls()¶
Return named Django URL patterns for this provider’s API.
- get_change_details(compared_configuration)¶
Return a public configuration snapshot and changed field names.
- get_public_configuration()¶
Return configuration with non-public values redacted.
- classmethod get_public_configuration_fields() frozenset[str]¶
Return configuration fields which are safe for public use.
- get_settings_form(user, **kwargs)¶
Return configuration form for this add-on.
- manual(component=None, category=None, project=None, activity_log_id: int | None = None)¶
Scope-aware manual entry point.
By default this mirrors the daily handler and lets add-ons opt in explicitly by subscribing to the manual event.
- manual_component(component, activity_log_id: int | None = None)¶
Per-component manual processing.
- post_add(translation, activity_log_id: int | None = None)¶
Event handler after new translation is added.
- post_commit(component, store_hash: bool, activity_log_id: int | None = None)¶
Event handler after changes are committed to the repository.
- post_install(component, store_hash: bool, activity_log_id: int | None = None)¶
Event handler after add-on is installed.
- post_push(component, activity_log_id: int | None = None)¶
Event handler after repository is pushed upstream.
- post_remove(translation, activity_log_id: int | None = None)¶
Event handler after a translation is removed.
- post_update(component, previous_head: str, skip_push: bool, changed_files: list[str], parse_after_update: bool = False, activity_log_id: int | None = None)¶
Event handler after repository is updated from upstream.
- Parámetros:
previous_head (str) – HEAD of the repository prior to update, can be blank on initial clone.
skip_push (bool) – Whether the add-on operation should skip pushing changes upstream. Usually you can pass this to underlying methods as
commit_and_pushorcommit_pending.changed_files (list[str]) – Files changed by the repository update.
- pre_commit(translation, author: str, store_hash: bool, activity_log_id: int | None = None)¶
Event handler before changes are committed to the repository.
- pre_push(component, activity_log_id: int | None = None)¶
Event handler before repository is pushed upstream.
- pre_update(component, activity_log_id: int | None = None)¶
Event handler before repository is updated from upstream.
- resolve_components(*, component=None, category=None, project=None)¶
Resolve scope to components iterator.
- save_state() None¶
Save add-on state information.
- unit_pre_create(unit, activity_log_id: int | None = None)¶
Event handler before new unit is created.
- update_component_state(component, updater: Callable[[dict[str, object]], None]) None¶
Atomically merge component-scoped add-on state into the shared JSON field.
- user()¶
Weblate user used to track changes by this add-on.
Los ganchos de complementos reciben objetos ORM de los módulos weblate.*.models, incluidos Addon, Component, Translation, Category, Project, Unit, Change y User. Los formularios de configuración de complementos deben heredar de weblate.addons.forms.BaseAddonForm.
He aquí un complemento de ejemplo:
# Copyright © Michal Čihař <michal@weblate.org>
#
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import annotations
from typing import TYPE_CHECKING, ClassVar
from django.utils.translation import gettext_lazy
from weblate.addons.base import BaseAddon
from weblate.addons.events import AddonEvent
if TYPE_CHECKING:
from weblate.addons.base import CompatDict
from weblate.trans.models import Translation
class ExampleAddon(BaseAddon):
# Filter for compatible components, every key is
# matched against property of component
compat: ClassVar[CompatDict] = {
"file_format": {"po", "po-mono"},
}
# List of events add-on should receive
events: ClassVar[set[AddonEvent]] = {
AddonEvent.EVENT_PRE_COMMIT,
}
# Add-on unique identifier
name = "weblate.example.example"
# Verbose name shown in the user interface
verbose = gettext_lazy("Example add-on")
# Detailed add-on description
description = gettext_lazy("This add-on does nothing it is just an example.")
# Callback to implement custom behavior
def pre_commit(
self,
translation: Translation | None,
author: str,
store_hash: bool,
activity_log_id: int | None = None,
) -> None:
return
Tecleando configuración del complemento¶
La configuración del complemento se almacena en el campo JSON Addon.configuration, por lo que el modelo conserva los datos persistentes como JSON sin procesar. Las implementaciones del complemento pueden definir su propia configuración por parametrización BaseAddon y BaseAddonForm.
Utilice dos clases TypedDict cuando el JSON almacenado pueda diferir de la estructura en tiempo de ejecución: una configuración almacenada permisiva, generalmente total=False, para valores heredados o ausentes, y una configuración total en tiempo de ejecución devuelta por normalize_configuration(). El código del complemento en tiempo de ejecución debe leer self.configuration o self.get_configuration() tales que vea valores predeterminados normalizados en lugar del JSON persistente sin procesar.
Para complementos sencillos donde las formas almacenadas y en tiempo de ejecución son idénticas, defina un único TypedDict y úselo para ambos parámetros de tipo BaseAddon. Mantenga el tipo de retorno serialize_form() del formulario alineado con el tipo de configuración almacenado.
Publishing add-on configuration¶
Add-on change history can be visible without add-on management permission.
List configuration fields that are safe to publish in the form’s
public_configuration_fields attribute. Fields not explicitly listed are
kept in the snapshot with a null value and identified as redacted. The default
is an empty set so that newly added settings are not published accidentally.
Use BaseAddon.get_public_configuration() whenever configuration is exposed
outside trusted add-on management code. Internal operations which intentionally
clone a working add-on can continue to use the stored configuration.
Component-mounted add-on APIs¶
Declare an api_name and return named Django URL patterns from
get_api_urls(). Use ordinary Django converters and DRF views. Patterns are
registered for every provider enabled in WEBLATE_ADDONS, regardless
of whether the add-on is installed on a component.
Routes are mounted under
/api/components/<project>/<component>/addons/<api_name>/.
For categorized components, encode the full category and component path in the
component segment, as for the component REST API. Use the installation’s
api_url instead of constructing this URL manually.
API names must contain 1 to 64 ASCII letters, digits, underscores, or hyphens,
and must be globally unique among enabled provider classes. Weblate validates
these declarations at startup, without querying the database, and rejects
invalid or conflicting names. Providers must declare needs_component = True,
repo_scope = False, and multiple = False. The same provider can be
installed on many components, but only once on each component.
Subclass weblate.addons.api.InstalledAddonAPIView and set its addon_name
to the provider’s internal add-on name. The base view authenticates the request,
checks component access, and resolves the installation as self.addon.
An absent or incompatible installation returns HTTP 404. Its permission
defaults to component.edit and is checked before request data is parsed.
The default JSON parser bounds requests to 5 MiB, including requests without
a Content-Length header.
Use normal DRF serializer validation in the view methods. Document the full
contract using drf_spectacular.utils.extend_schema and serializer field
help text: OpenAPI discovers the same views used for runtime routing.
Reverse endpoints using api:<api_name>:<pattern_name>, providing
project__slug, slug, and any endpoint parameters.
API names are public contracts and should remain stable across implementation
changes. Restart Weblate after changing provider registration; tests overriding
registrations must rebuild their URL configuration and clear Django’s URL caches.
The existing /api/addons/<id>/ management API remains available.
Its read-only api_name and api_url fields reflect the enabled provider’s
current declaration. Both are null when the provider is disabled or incompatible.