# GitLab CI/CD > Automate your frequent localization tasks such as uploading source files and downloading translations. URL: https://store.crowdin.com/gitlab-ci Category: Development Type: Guide Author: Andrii Bodnar Use [GitLab CI/CD](https://docs.gitlab.com/ee/ci/) to automate your common localization tasks such as uploading source files, downloading translations or anything else you can do with Crowdin CLI. ### Preparing the repository Push the `crowdin.yml` [configuration file](https://developer.crowdin.com/configuration-file/) to the repository. Use [Environment Variables](https://developer.crowdin.com/configuration-file/#api-credentials-from-environment-variables) for API Credentials: ```yml "project_id_env": "CROWDIN_PROJECT_ID" "api_token_env": "CROWDIN_PERSONAL_TOKEN" ``` See the [GitLab CI/CD variables](https://docs.gitlab.com/ee/ci/variables/) to learn more about defining variables in GitLab CI/CD. ### Pipeline configuration You need to set up the `.gitlab-ci.yml` configuration file for GitLab CI/CD (or extend the existing one): ```yml stages: - translations variables: CROWDIN_PROJECT_ID: $CROWDIN_PROJECT_ID CROWDIN_PERSONAL_TOKEN: $CROWDIN_PERSONAL_TOKEN translations: stage: translations image: crowdin/cli:latest script: - crowdin -V - crowdin download --no-progress ``` **Tip**: It's recommended to use the `--no-progress` flag for the CLI execution in CI/CD environment. There is a possibility to store the downloaded translations as an artifacts using the `--keep-archive` option with the [`crowdin download`](https://crowdin.github.io/crowdin-cli/commands/crowdin-download) command: ```yml stages: - translations variables: CROWDIN_PROJECT_ID: $CROWDIN_PROJECT_ID CROWDIN_PERSONAL_TOKEN: $CROWDIN_PERSONAL_TOKEN translations: stage: translations image: crowdin/cli:latest script: - crowdin download --no-progress --keep-archive artifacts: paths: - CrowdinTranslations_*.zip ``` The examples above use the official [`crowdin/cli`](https://hub.docker.com/r/crowdin/cli) Docker image. Alternatively, you can use the Node.js CLI package: ```yml stages: - translations variables: CROWDIN_PROJECT_ID: $CROWDIN_PROJECT_ID CROWDIN_PERSONAL_TOKEN: $CROWDIN_PERSONAL_TOKEN translations: stage: translations image: node:latest script: - npm install -g @crowdin/cli - crowdin -V - crowdin status --no-progress ``` In this example, the job runs on the Node image and installs the [Crowdin CLI NPM package](https://www.npmjs.com/package/@crowdin/cli) globally. Once the CLI is installed, you can run any CLI command. For more information about Crowdin CLI commands, please visit the official [Crowdin CLI website](https://crowdin.github.io/crowdin-cli/). ### Creating Merge Requests with Translations You can automate the process of creating merge requests with downloaded translations. This example shows how to download translations, commit them to a new branch, and create a merge request automatically. Set up the following environment variables in your GitLab project: - `CROWDIN_PROJECT_ID` - Your Crowdin project ID - `CROWDIN_PERSONAL_TOKEN` - Your Crowdin personal access token - `GITLAB_API_TOKEN` - GitLab token with API access and write permissions (`api`, `write_repository` scopes) Add the job to your `.gitlab-ci.yml`: ```yml stages: - translations variables: CROWDIN_PROJECT_ID: $CROWDIN_PROJECT_ID CROWDIN_PERSONAL_TOKEN: $CROWDIN_PERSONAL_TOKEN GITLAB_API_TOKEN: $GITLAB_API_TOKEN download_translations: stage: translations image: node:latest before_script: - npm install -g @crowdin/cli script: - git config user.email "translations-bot@example.com" - git config user.name "Translations Bot" - git remote set-url origin "https://gitlab-ci-token:${GITLAB_API_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" - export NEW_BRANCH_NAME="translations-update-${CI_COMMIT_REF_NAME}" - git checkout -b $NEW_BRANCH_NAME - echo "Downloading translations..." - crowdin download --no-progress - | if [[ -z $(git status --porcelain) ]]; then echo "No translation updates. Exiting." exit 0 fi - git add . - git commit -m "chore: update translations" - | if git ls-remote --exit-code --heads origin $NEW_BRANCH_NAME >/dev/null 2>&1; then git push origin $NEW_BRANCH_NAME -f else git push origin $NEW_BRANCH_NAME curl --request POST "https://${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/merge_requests" \ --header "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \ --header "Content-Type: application/json" \ --data '{ "source_branch": "'"${NEW_BRANCH_NAME}"'", "target_branch": "'"${CI_COMMIT_REF_NAME}"'", "title": "Update translations", "description": "This merge request is automatically created by the GitLab CI/CD pipeline.", "labels": "translations,ci", "remove_source_branch": true }' fi - echo "Translations updated successfully." only: - main ``` This workflow will: 1. Install Crowdin CLI on a Node.js image (which includes git and curl) 2. Configure git with bot credentials 3. Create a new branch for translations 4. Download all translations from Crowdin 5. Commit changes if any translations were updated 6. Push to the remote branch 7. Create a merge request automatically (or update existing branch if MR already exists)