.. _continuous-translation: Continuous localization ======================= There is infrastructure in place so that your translation closely follows development. This way translators can work on translations the entire time, instead of working through huge amount of new text just prior to release. .. seealso:: :doc:`/devel/integration` describes basic ways to integrate your development with Weblate. :doc:`/admin/code-hosting` lists provider-specific setup steps for common code-hosting sites. This is the process: 1. Developers make changes and push them to the VCS repository. 2. Optionally the translation files are updated, see :ref:`translations-update`. 3. Weblate pulls changes from the VCS repository, parses translation files and updates its database, see :ref:`update-vcs`. 4. Translators submit translations using the Weblate web interface, or upload offline changes. 5. Once the translators are finished, Weblate commits the changes to the local repository (see :ref:`lazy-commit`). 6. Changes are pushed back to the upstream repository (see :ref:`code-hosting-push-options`). .. graphviz:: digraph translations { graph [fontname = "sans-serif", fontsize=10, ranksep=0.6, newrank=true]; node [fontname = "sans-serif", fontsize=10, margin=0.15]; edge [fontname = "sans-serif", fontsize=10]; subgraph cluster_codehosting { rank=same; graph [color=lightgrey, label="Upstream code-hosting site", style=filled ]; "VCS repository" [shape=cylinder]; } subgraph cluster_weblate { rank=same; graph [color=lightgrey, label="Weblate", style=filled ]; repo [label="Weblate repository", shape=cylinder]; database [label=Database, shape=cylinder]; } "Developers" [shape=box, fillcolor="#144d3f", fontcolor=white, style=filled]; "Translators" [shape=box, fillcolor="#144d3f", fontcolor=white, style=filled]; "Developers" -> "VCS repository" [label=" 1. Push "]; "VCS repository" -> "VCS repository" [label=" 2. Updating translations ", style=dotted]; "VCS repository" -> repo [label=" 3. Pull "]; repo -> database [label=" 3. Parse translations "]; "database" -> repo [label=" 5. Commit changes "]; "Translators" -> "database" [label=" 4. Translate "]; "repo" -> "VCS repository" [label=" 6. Push repository "]; } .. hint:: Upstream code-hosting site is not necessary, you can use Weblate with :ref:`vcs-local` where there is only the repository inside Weblate. .. _update-vcs: Updating repositories --------------------- You should set up some way of updating backend repositories from their source. * Use :ref:`hooks` to integrate with the majority of common code-hosting services, see :doc:`/admin/code-hosting`. You must also :ref:`project-enable_hooks` for this to work. Hook deliveries update components whose repository URL matches the payload; see :ref:`hooks-target-matching`. * Manually trigger update either in the repository management or using :ref:`api` or :ref:`wlc` * Enable :setting:`AUTO_UPDATE` to automatically update all components on your Weblate instance * Execute :wladmin:`updategit` (with selection of project or ``--all`` to update all) Whenever Weblate updates the repository, the post-update addons will be triggered, see :ref:`addons`. .. _hooks-target-matching: Matching webhook targets ++++++++++++++++++++++++ Forge webhooks update components whose :ref:`component-repo` exactly matches a repository URL from the payload (HTTPS or SSH as reported by the forge, plus common variants such as a trailing slash). Generic forge webhook endpoints are compatibility interfaces, and ordinary repository deliveries are not cryptographically authenticated. Legacy GitHub App deliveries containing installation data are an exception: the generic GitHub endpoint verifies their signature using :setting:`GITHUB_LEGACY_APP_WEBHOOK_SECRET`. Repository matching does not apply project or component access control because webhooks also need to update private projects and :ref:`restricted components `. Their JSON responses include diagnostic counts for repository, branch, and enabled-hook matches. Successful responses also include the full project/component slugs and absolute API URLs of updated components. Supplying a matching repository URL can therefore confirm that a repository is registered and reveal these identifiers. Each matching delivery records a hook event and schedules a repository update. Generic hook deliveries are neither application-rate-limited nor coalesced. Repository operations are serialized to protect repository consistency, but this does not bound the number of accepted deliveries or queued update attempts. An update of an unchanged repository still fetches the configured remote, but stops before merging changes or parsing translation files. Components managed through an authenticated integration are excluded from generic webhook matching and its diagnostic counts. Currently this applies to the :guilabel:`GitHub (via Weblate GitHub app)` VCS backend. These components receive notifications only through their dedicated tokenized and signed :ref:`GitHub App webhook URL `. Future authenticated integrations are expected to use the same separation. The returned API URLs do not grant access to the components. The web interface and API continue to enforce normal access control, and webhook responses do not include repository content, translations, or credentials. Where available, prefer an authenticated integration such as :ref:`code-hosting-github-app-webhook`. .. versionchanged:: 2026.9 Host and path suffix fallback matching was removed. If updates stop, align :ref:`component-repo` with a URL from the forge webhook payload. .. _avoid-merge-conflicts: Avoiding merge conflicts ++++++++++++++++++++++++ The merge conflicts from Weblate arise when same file was changed both in Weblate and outside it. Depending on the situation, there are several approaches that might help here: * :ref:`merge-weblate-only` * :ref:`merge-weblate-locking` * :ref:`merge-weblate-git` .. _merge-weblate-only: Avoiding merge conflicts by changing translation files in Weblate only `````````````````````````````````````````````````````````````````````` Avoiding edits outside Weblate is easy with monolingual files — you can add new strings within Weblate and leave whole editing of the files there. For bilingual files, there is usually some kind of message extraction process to generate translatable files from the source code. In some cases, this can be split into two parts: 1. The extraction generates template (for example gettext POT is generated using :program:`xgettext`). 2. Further process merges it into actual translations (the gettext PO files are updated using :program:`msgmerge`). You can perform the second step within Weblate and it will ensure that all pending changes are included before this operation. .. _merge-weblate-locking: Avoiding merge conflicts by locking Weblate while doing outside changes ``````````````````````````````````````````````````````````````````````` Integrating Weblate into your updating process so that it flushes changes before updating the files outside Weblate can be achieved by using :ref:`api` to force Weblate to push all pending changes and lock the translation while you are doing changes on your side. The script for doing updates can look like this: .. code-block:: sh # Lock Weblate translation wlc lock # Push changes from Weblate to upstream repository wlc push # Pull changes from upstream repository to your local copy git pull # Update translation files, this example is for Django ./manage.py makemessages --keep-pot -a git commit -m 'Locale updates' -- locale # Push changes to upstream repository git push # Tell Weblate to pull changes (not needed if Weblate follows your repo # automatically) wlc pull # Unlock translations wlc unlock If you have multiple components sharing the same repository, you need to lock them all separately: .. code-block:: sh wlc lock foo/bar wlc lock foo/baz wlc lock foo/baj .. note:: The example uses :ref:`wlc`, which needs configuration (API keys) to be able to control Weblate remotely. You can also achieve this using any HTTP client instead of :ref:`wlc`, for example curl, see :ref:`api`. .. _repository-maintenance: Repository maintenance ++++++++++++++++++++++ The :guilabel:`Repository maintenance` view shows repository status for a project, component, or translation and lets privileged users run maintenance operations from the user interface. For shared repositories, permissions are checked on the component that owns the repository, even when the operation is started from a linked component. Users with repository permissions only on a linked component can open this view to see which permissions they need on the owner. Restrictions identify the owning component when it is accessible; otherwise, ask your project administrator to coordinate access with the repository owner. See :doc:`/admin/access` for permission scope. The same actions can also be triggered using :ref:`api` or, for the supported subset, :ref:`wlc`. Availability of individual actions depends on permissions, the configured version control system, whether pushing is configured, and whether the selected object can be locked. Repository actions started from this view are queued for background processing. For a project, Weblate processes the affected repositories sequentially in one task and shows its progress. Repeating the same action opens the existing task; a different action cannot be started for the same repository until that task finishes. The :guilabel:`Synchronize` and :guilabel:`Rescan` repository operations are queued for background processing as described above. The separate :guilabel:`File management` actions are available only for an individual translation. They rewrite that translation file and commit the result during the web request; they are not project-wide or component-wide operations. Operations that read repository content, such as updating, resetting, or rescanning, also reconcile translation files in Weblate. Added or removed translation files are reflected after this processing finishes. Glossary language synchronization and cleanup are described in :ref:`glossary-language-sync`. .. list-table:: :header-rows: 1 * - Action - What it does - Typical use * - :guilabel:`Commit` - Commits pending changes stored in Weblate to the local repository. - Flush pending Weblate changes before doing repository work elsewhere. * - :guilabel:`Push` - Pushes committed local repository changes to the configured upstream. - Send committed translations upstream when automatic push is disabled or delayed. * - :guilabel:`Update` - Fetches upstream changes, integrates them using the component's configured :ref:`component-merge_style`, and reconciles translation files. - Bring Weblate in sync with upstream using the default integration strategy. * - :guilabel:`Update with merge` - Fetches upstream changes and integrates them with an explicit merge. - Override the default merge style for a single update. * - :guilabel:`Update with rebase` - Fetches upstream changes and rebases local Weblate commits on top of upstream. - Keep history linear when that matches your workflow. * - :guilabel:`Update with merge without fast-forward` - Fetches upstream changes and creates an explicit merge commit even when a fast-forward would be possible. - Preserve merge commits for auditing or branch-management reasons. * - :guilabel:`Lock` / :guilabel:`Unlock` - Prevents or allows translators to make further changes in Weblate. - Freeze translation changes while doing repository maintenance outside Weblate. * - :guilabel:`Discard local changes` - Resets Weblate's local repository to upstream, discards local commits and pending translation changes, and reconciles translation files. - Use when upstream should overwrite the local Weblate repository state. * - :guilabel:`Reset and reapply translations` - Resets Weblate's local repository to upstream, reconciles translation files, and reapplies Weblate's translations. See :ref:`manage-vcs-reset-reapply`. - Recover from diverged history while keeping pending Weblate translations. * - :guilabel:`Cleanup` - Removes untracked files and stale branches from the local repository checkout. - Clean up leftover files or stale repository state in Weblate's checkout. * - :guilabel:`Synchronize` - Forces Weblate to write all known translations back to the repository files. - Repair cases where repository files became out of sync with the database state. * - :guilabel:`Rescan` - Re-reads translation files from the local repository into Weblate and removes translations whose files no longer match the component configuration. - Import file changes after manual repository work or file creation. * - :guilabel:`Remove duplicates` - Removes repeated strings with the same identifier from one translation file. - Repair duplicate strings reported by Weblate when the file contains repeated units. * - :guilabel:`Cleanup unused` - Removes strings no longer present in the base file from one translation file. The :ref:`addon-weblate.cleanup.generic` add-on can perform this automatically. - Run a one-time cleanup without installing the add-on. * - :guilabel:`Remove obsolete` - Removes obsolete strings from one PO translation file. - Run a one-time PO cleanup without enabling automatic obsolete string removal. For Git repositories, both reset actions affect only the configured :ref:`component-branch`. They do not reset or remove other local branches. :guilabel:`Cleanup` deletes all other local branches, including any commits that have not been pushed, and removes untracked files. It does not delete branches from the upstream repository. If you replace an upstream branch with unrelated history, switching to it in Weblate can fail because Weblate reuses its existing local branch and tries to merge or rebase it. Resetting while another branch is configured does not fix that inactive local branch. For example, resetting ``master`` leaves an old local ``dev`` branch unchanged. If no local changes on the affected branch need to be kept, configure a working branch, run :guilabel:`Cleanup` from :guilabel:`Repository maintenance`, and wait for it to finish. Then switch to the affected branch again. Weblate creates it afresh from upstream. If the affected branch is already configured, use :guilabel:`Discard local changes` to replace its local history with upstream instead. .. _manage-vcs-reset-reapply: Reset and reapply translations recovery behavior ```````````````````````````````````````````````` The :guilabel:`Reset and reapply translations` operation keeps translations from Weblate while resetting the local repository state to match upstream. If the Git checkout or its entire :file:`.git` directory is missing, this operation reconstructs it before reapplying translations. Remote repositories are cloned from the configured upstream branch. Local repositories are initialized with new Git metadata while retaining any surviving working files. Both then use the standard reapply flow. Symlinked checkout directories are never replaced automatically. For local repositories, reapply can recreate missing strings from the database, including source strings in monolingual base files, when the file format supports adding strings. Missing translation files can also be recreated when the format supports creating them or a valid template for new translations is available. This applies to local glossaries as well as other local components, including when their Git checkout is healthy. Remote reapply does not recreate strings removed upstream. Required files that the format cannot create must be restored from a backup. Weblate reports restoration failures and keeps the database translations and pending changes. Any surviving checkout without a :file:`.git` directory is preserved under :file:`DATA_DIR/repository-recovery///`. Its location is written to the application log. These copies are not removed automatically; inspect and remove them manually after verifying recovery. Reconstruction cannot restore lost Git history or files and metadata that Weblate does not store. Recovery is explicit: background updates do not automatically rebuild checkouts. If a checkout is unexpectedly missing, first verify that the data volume is available to the worker performing recovery. Damaged Git metadata in an existing :file:`.git` directory requires manual inspection and repair by an instance administrator. The operation can restore pending translations only when the target language files still exist after the reset or when Weblate can create them for the component, for example using a valid :ref:`component-new_base`. If neither of these conditions is met, Weblate keeps the pending changes in its database and reports a recovery error instead of failing later with a generic parse error. .. _merge-weblate-git: Avoiding merge conflicts by focusing on Git operations `````````````````````````````````````````````````````` Even when Weblate is the single source of the changes in the translation files, conflicts can appear when using :ref:`addon-weblate.git.squash` add-on, :ref:`component-merge_style` is configured to :guilabel:`Rebase`, or you are squashing commits outside of Weblate (for example, when merging a pull request). The reason for merge conflicts is different in this case. Weblate can have new local commits after you merge earlier Weblate commits upstream. This typically happens if merging is not automated and changes wait for days or weeks for a human review. Git is then sometimes no longer able to identify upstream changes as matching the Weblate ones and refuses to perform a rebase. Squash merging Weblate changes makes this harder to recover from. A squash merge creates a new commit instead of preserving the individual Weblate commits in the upstream history. Weblate still has the original commits in its local repository, and Git can no longer prove that upstream already contains them. If the conflict was also resolved manually, the file contents can differ from both repositories, so Weblate can keep failing to update even after the pull request was merged upstream. If upstream no longer contains Weblate commits because they were squash merged, updating the repository might not be enough. Use :guilabel:`Reset and reapply translations` from :guilabel:`Repository maintenance` to reset Weblate to upstream while keeping pending translations; see :ref:`manage-vcs-reset-reapply`. Use :guilabel:`Discard local changes` only when upstream should fully replace Weblate's local changes. To approach this, you either need to minimize the amount of pending changes in Weblate when you merge a pull request, or avoid the conflicts completely by not squashing changes. Here are few options how to avoid that: * Do not use :ref:`addon-weblate.git.squash` or squash merging for Weblate changes. Squashing is why Git might no longer recognize the changes after merging. * When resolving conflicts outside Weblate, merge the Weblate commits with a regular merge commit and push that result upstream. Do not squash merge the conflict-resolution pull request. * Let Weblate commit pending changes before merging. This will update the pull request with all its changes, and both repositories will be in sync. * Use the review features in Weblate (see :doc:`/workflows`) so that you can automatically merge GitHub pull requests after CI passes. * Use locking in Weblate to avoid changes while GitHub pull request is in review. .. seealso:: :ref:`wlc` Code-hosting notifications ++++++++++++++++++++++++++ Provider-specific app and webhook instructions for GitHub, GitLab, Bitbucket, Pagure, Azure Repos, Gitea, Forgejo, and Gitee are covered in :doc:`/admin/code-hosting`. .. _github-setup: .. _gitlab-setup: .. _bitbucket-setup: .. _pagure-setup: .. _azure-setup: .. _gitea-setup: .. _forgejo-setup: .. _gitee-setup: Provider-specific notifications ``````````````````````````````` These legacy anchors are kept for compatibility. Current provider-specific app and webhook setup is documented in :doc:`/admin/code-hosting`. .. seealso:: * :ref:`GitHub notifications ` * :ref:`GitLab notifications ` * :ref:`Bitbucket notifications ` * :ref:`Pagure notifications ` * :ref:`Azure Repos notifications ` * :ref:`Gitea notifications ` * :ref:`Forgejo notifications ` * :ref:`Gitee notifications ` .. _automatically-updating-repositories-nightly: Automatically updating repositories daily +++++++++++++++++++++++++++++++++++++++++ By default, Weblate automatically fetches remote repositories daily to improve performance when merging changes later. Updates are distributed throughout the day. Set :setting:`AUTO_UPDATE` to ``"full"`` to also merge remote changes into the working copy. See :setting:`AUTO_UPDATE` for scheduling details and other update modes. .. _push-changes: Pushing changes from Weblate ---------------------------- Each translation component can have a push URL set up (see :ref:`component-push`), and in that case Weblate will be able to push changes to the remote repository. Weblate can also be configured to automatically push changes on every commit, see :ref:`component-push_on_commit`. For the push options table and provider-specific pull, merge, and review request workflows, see :ref:`code-hosting-push-options`. .. seealso:: See :ref:`vcs-repos` for setting up SSH keys, and :ref:`lazy-commit` for info about when Weblate decides to commit changes. Protected branches ++++++++++++++++++ If you are using Weblate on protected branch, you can configure it to use pull requests and perform actual review on the translations (what might be problematic for languages you do not know). An alternative approach is to waive this limitation for the Weblate push user. For example on GitHub this can be done in the repository configuration: .. image:: /images/github-protected.png Interacting with others ----------------------- Weblate makes it easy to interact with others using its API. .. seealso:: :ref:`api` .. _lazy-commit: Lazy commits ------------ The behaviour of Weblate is to group commits from the same author into one commit if possible. This greatly reduces the number of commits, however you might need to explicitly tell it to do the commits in case you want to get the VCS repository in sync, e.g. for merge (this is by default allowed for the :guilabel:`Managers` group, see :ref:`privileges`). The changes in this mode are committed once any of the following conditions are fulfilled: * Somebody else changes an already changed string. * A merge from upstream occurs. * An explicit commit is requested. * A file download is requested. * Change is older than period defined as :ref:`component-commit_pending_age` on :ref:`component`. .. hint:: Commits are created for every component. So in case you have many components you will still see lot of commits. You might utilize :ref:`addon-weblate.git.squash` add-on in that case. If you want to commit changes more frequently and without checking of age, you can schedule a regular task to perform a commit. This can be done using :guilabel:`Periodic Tasks` in :ref:`admin-interface`. First create desired :guilabel:`Interval` (for example 120 seconds). Then add new periodic task and choose ``weblate.trans.tasks.commit_pending`` as :guilabel:`Task` with ``{"hours": 0}`` as :guilabel:`Keyword Arguments` and desired interval. .. _processing: Processing repository with scripts ---------------------------------- The way to customize how Weblate interacts with the repository is :ref:`addons`. Consult :ref:`addon-script` for info on how to execute external scripts through add-ons. .. _translation-consistency: Keeping translations same across components ------------------------------------------- Once you have multiple translation components, you might want to ensure that the same strings have same translation. This can be achieved at several levels. .. _translation-propagation: Translation propagation +++++++++++++++++++++++ With :ref:`component-allow_translation_propagation` enabled (what is the default, see :ref:`component`), all new translations are automatically done in all components with matching strings. Such translations are properly credited to currently translating user in all components. Propagation preconditions: - Components must belong to the configured :ref:`workspace propagation scope `. By default, this is a single project (linking a component is not enough). - Enable :ref:`component-allow_translation_propagation` to automatically reuse translations for matching strings. - The translation propagation requires the key to be match for monolingual translation formats, so keep that in mind when creating translation keys. - The strings are propagated while translating, strings loaded from the repository are not propagated. .. tip:: This feature currently has limitations, and we want to make it more universal. Please share your feedback at https://github.com/WeblateOrg/weblate/issues/3166. Consistency check +++++++++++++++++ The :ref:`check-inconsistent` check fires whenever the strings are different. You can utilize this to review such differences manually and choose the right translation. .. _automatic-translation: Automatic translation +++++++++++++++++++++ Automatic translation based on different components can be way to synchronize the translations across components. You can either trigger it manually (see :ref:`auto-translation`) or make it run automatically on repository update using add-on (see :ref:`addon-weblate.autotranslate.autotranslate`).