---
title: "Integrate Crowdin in your extension"
manual: "TYPO3 Explained"
version: "main"
permalink: "https://docs.typo3.org/permalink/t3coreapi:crowdin-extension-integration@main"
source: "ApiOverview/Localization/TranslationServer/Crowdin/ExtensionIntegration.rst"
rendered: "2026-10-11T16:25:05+00:00"
---

# Integrate Crowdin in your extension {#crowdin-extension-integration}

This section describes how an extension author can get his extension set up at
[Crowdin](https://docs.typo3.org/permalink/t3coreapi:xliff-translating-server-crowdin@main).

> [!NOTE]
> -   Your extension must be on GitHub, GitLab
>     (SaaS or self-managed) or BitBucket.
> -   Currently, TYPO3 can only handle one branch/version for languages.
>     Typically you should select the "main" branch.

## Setup Crowdin {#crowdin-extension-integration-setup}

Get in contact with the team in the TYPO3 Slack channel
[#typo3-localization-team](https://typo3.slack.com/app_redirect?channel=CR75200FL) with the following information:

1.  Extension name
1.  Your email address for an invitation to Crowdin, so you will get the correct
    role for your project.

## Integration in GitHub or GitLab {#crowdin-extension-integration-github}

In a next step you need to configure the integration of your Git provider into
Crowdin. Have a look at the documentation on how to connect your repository with
Crowdin:

-   [GitHub integration](https://support.crowdin.com/github-integration/)
-   [GitLab integration](https://support.crowdin.com/gitlab-integration/)
-   [BitBucket integration](https://support.crowdin.com/bitbucket-integration/)

### Step-by-step instructions for GitHub {#crowdin-extension-integration-github-configure}

1.  Create a Crowdin configuration file

    Within your TYPO3 extension repository, create a `.crowdin.yml` file at root
    with the following content:

    **EXT:my_extension/.crowdin.yml**

    ```yaml
    preserve_hierarchy: 1
    files:
      - source: /Resources/Private/Language/*.xlf
        translation: /%original_path%/%two_letters_code%.%original_file_name%
        ignore:
          - /**/%two_letters_code%.%original_file_name%

    ```

    If you provide a `labels.xlf` file for the
    [site settings](https://docs.typo3.org/permalink/t3coreapi:site-settings-definition-translation@main),
    the `/Configuration/Sets/` folder should be added:

    **EXT:my_extension/.crowdin.yml**

    ```yaml
    preserve_hierarchy: 1
    files:
      - source: /Configuration/Sets/*/*.xlf
        translation: /%original_path%/%two_letters_code%.%original_file_name%
        ignore:
          - /**/%two_letters_code%.%original_file_name%
      - source: /Resources/Private/Language/*.xlf
        translation: /%original_path%/%two_letters_code%.%original_file_name%
        ignore:
          - /**/%two_letters_code%.%original_file_name%

    ```

    > [!NOTE]
    > If you use the configuration with the `/Configuration/Sets/*/*.xlf`
    > source and do not provide labels, the GitHub action returns an error.
    > However, your files from the `/Resources/Private/Language/` folder
    > will still be uploaded.
1.  Connect your GitHub repository

    In order for Crowdin to manage translations, you need to somehow push the
    translation sources from GitHub to Crowdin. Crowdin provides **two different
    connection options**, which are described below.

    **Option A: Create a GitHub workflow (recommended)**

    When working with GitHub Actions, you can integrate the
    [Crowdin GitHub Action](https://github.com/marketplace/actions/crowdin-action)
    into your CI workflow.

    1.  Configure GitHub secrets

        First, add the following GitHub secrets to your GitHub repository:

        -   **`CROWDIN_PROJECT_ID`**

            Project ID, can be found in **project settings** when
            navigating to **Tools > API**.

        -   **`CROWDIN_PERSONAL_TOKEN`**

            API key used for authentication at Crowdin, can be
            generated in **personal settings** at
            **API > Personal Access Tokens**.

        > [!TIP]
        > When creating a personal access token in Crowdin, you will need to select some scopes.
        > For this workflow, set at least the following basic `Project` scopes:
        >
        > -   **Projects (List, Get, Create, Edit)**: `Read Only`
        > -   **Translation Status**: `Read Only`
        > -   **Source files & strings**: `Read and Write`
        > -   **Translations**: `Read and Write`
    1.  Create GitHub workflow

        Now create a new GitHub workflow `crowdin.yaml`:

        **EXT:my_extension/.github/workflows/crowdin.yaml**

        ```yaml
        name: Crowdin

        on:
          push:
            branches:
              - main
            paths:
              - '**.xlf'

        jobs:
          sync:
            name: Synchronize with Crowdin
            runs-on: ubuntu-latest
            steps:
              - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd

              - name: Upload sources
                uses: crowdin/github-action@v2
                env:
                  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
                with:
                  config: '.crowdin.yml'
                  project_id: ${{ secrets.CROWDIN_PROJECT_ID }}
                  token: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
                  crowdin_branch_name: 'main'
                  upload_sources: true
                  upload_translations: false
                  download_sources: false
                  download_translations: false

        ```

        > [!IMPORTANT]
        > Make sure to configure a Crowdin branch name using the
        > `crowdin_branch_name` configuration option of the GitHub
        > action. Otherwise, translations are delivered incomplete
        > by TYPO3's Crowdin Bridge.

        > [!NOTE]
        > **See also**
        >
        > For more information about available configuration options,
        > consult the [official GitHub action documentation](https://github.com/marketplace/actions/crowdin-action).
    1.  Push sources

        For each push in your `main` branch, the workflow will now
        transfer all your translation sources to Crowdin.

    **Option B: Use the Crowdin <> GitHub integration (legacy)**

    1.  Configure the GitHub integration

        In the Crowdin project settings, go to the Integrations tab and click
        on the button "Browse Integrations", then choose "GitHub". Follow the
        instructions to connect your GitHub repository to Crowdin.

        Once installed, the Integrations tab will show the GitHub integration
        with a button to "Set Up Integration". Click on it and choose the mode
        "Source and translation files mode".

        At this point, Crowdin will request additional permissions to access
        your repository. You should accept the default permissions and click
        on the "Authorize crowdin" button.

        Then follow the instructions to configure the integration:

        1.  Select the repository from the list of your GitHub repositories.
        1.  Select the branch to use for synchronization (usually `main` or
            `master`). When ticking the branch, Crowdin will suggest a
            "Service Branch Name" `l10n_main` (or `l10n_master`), which
            is the branch where Crowdin will push the translations. You can
            keep the default value.
        1.  Click the pencil icon next to the Service Branch Name to edit
            configuration.
        1.  When asked for the Configuration file name, change it from
            `crowdin.yml` to `.crowdin.yml` and click "Continue". This
            will effectively use the configuration we created in Step 1 and
            ensure that everything is properly configured for your TYPO3
            extension.
        1.  Click the "Save" button to save the configuration.
        1.  Back to the main GitHub integration page, you should see a circled
            checkmark next to the Service Branch Name, indicating that the
            integration is correctly set up.
        1.  Ensure the checkbox "One-time translation import after the branch
            is connected" is ticked.
        1.  Do not tick the checkbox "Push Sources" as the sources are already
            in the repository and changes are managed within the extension
            repository **and not in Crowdin**.
        1.  Click the "Save" button to save the configuration of the integration.
    1.  Import existing translations

        In case you have local translations, you may do a one-time import by using the Crowdin
        web interface and manually importing a zip file with the existing translations.

        To prepare the zip file, you can use the following command:

        ```bash
        zip translations.zip Resources/Private/Language/*.*.xlf
        ```

        Then go to the Crowdin project, click on the "Translations" tab and drag and drop
        the zip file into the area "Upload existing translations".

        > [!NOTE]
        > The import will work best only if the translation files contain both the
        > `<source>` and `<target>` elements. If the `<source>` elements are missing,
        > Crowdin will not be able to match the translations with the original English labels.

    > [!IMPORTANT]
    > Using the recommended GitHub workflow the GitHub default branch can be
    > mapped to the Crowdin branch name via the attribute `crowdin_branch_name`.
    > It is recommended that you always use `main` as the Crowdin branch name.
    > **More than one Crowdin branch (for example via different
    > GitHub branches) is not supported by the Crowdin Bridge!**
1.  Approve imported translations

    After importing existing translations, they will arrive in Crowdin in an
    **unapproved state**. These translations need to be explicitly approved in
    Crowdin before they become available for export and use in TYPO3 installations.

    See [Mass approval on Crowdin](https://docs.typo3.org/permalink/t3coreapi:crowdin-mass-approval@main) for instructions
    on how to approve translations programmatically using the Crowdin API, or
    use Crowdin's web interface bulk approval feature.

Happy translating!

> [!TIP]
> Checkout the [Frequently asked questions (FAQ)](https://docs.typo3.org/permalink/t3coreapi:crowdin-faq@main) for
> solutions to common pitfalls.
