lokalise-ci-integration

0
0
Source

Configure Lokalise CI/CD integration with GitHub Actions and automated sync. Use when setting up automated translation sync, configuring CI pipelines, or integrating Lokalise into your build process. Trigger with phrases like "lokalise CI", "lokalise GitHub Actions", "lokalise automated sync", "CI lokalise", "lokalise pipeline".

Install

mkdir -p .claude/skills/lokalise-ci-integration && curl -L -o skill.zip "https://mcp.directory/api/skills/download/7120" && unzip -o skill.zip -d .claude/skills/lokalise-ci-integration && rm skill.zip

Installs to .claude/skills/lokalise-ci-integration

About this skill

Lokalise CI Integration

Overview

Automate the full translation lifecycle through GitHub Actions: upload source strings when code is pushed, download translations during builds, block PRs with missing translations, and manage branch-based translation workflows that mirror your Git branching strategy. The goal is zero manual translation file management — developers write code, translators work in Lokalise, and CI keeps everything in sync.

Prerequisites

  • Lokalise project with Project ID (Settings > General > Project ID)
  • Lokalise API token with read/write permissions (Profile > API Tokens), stored as LOKALISE_API_TOKEN GitHub secret
  • LOKALISE_PROJECT_ID stored as GitHub secret (or variable)
  • Lokalise CLI v2 (lokalise2) — installed in CI via curl -sfL https://raw.githubusercontent.com/nicktomlin/lokalise-cli-2-install/master/install.sh | sh
  • Source locale files committed to the repository (e.g., src/locales/en.json)

Instructions

Step 1: Upload Source Strings on Push

Create .github/workflows/lokalise-upload.yml to push source strings to Lokalise whenever the default locale file changes on main:

name: Upload translations to Lokalise
on:
  push:
    branches: [main]
    paths:
      - 'src/locales/en.json'  # Adjust to your source locale path

jobs:
  upload:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Lokalise CLI
        run: |
          curl -sfL https://raw.githubusercontent.com/lokalise/lokalise-cli-2-go/master/install.sh | sh
          sudo mv ./bin/lokalise2 /usr/local/bin/lokalise2

      - name: Upload source strings
        run: |
          lokalise2 file upload \
            --token "${{ secrets.LOKALISE_API_TOKEN }}" \
            --project-id "${{ secrets.LOKALISE_PROJECT_ID }}" \
            --file "src/locales/en.json" \
            --lang-iso "en" \
            --replace-modified \
            --include-path \
            --distinguish-by-file \
            --poll \
            --poll-timeout 120s
        # --replace-modified updates existing keys with new values
        # --poll waits for the async upload to complete before exiting

Step 2: Download Translations During Build

Create .github/workflows/lokalise-build.yml or add a step to your existing build workflow:

name: Build with translations
on:
  push:
    branches: [main, staging]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Lokalise CLI
        run: |
          curl -sfL https://raw.githubusercontent.com/lokalise/lokalise-cli-2-go/master/install.sh | sh
          sudo mv ./bin/lokalise2 /usr/local/bin/lokalise2

      - name: Download translations
        run: |
          lokalise2 file download \
            --token "${{ secrets.LOKALISE_API_TOKEN }}" \
            --project-id "${{ secrets.LOKALISE_PROJECT_ID }}" \
            --format json \
            --original-filenames=true \
            --directory-prefix="" \
            --export-empty-as=base \
            --unzip-to "src/locales/"
        # --export-empty-as=base falls back to source language for untranslated keys
        # --original-filenames preserves the file structure from Lokalise

      - name: Build application
        run: npm run build

Step 3: PR Check for Missing Translations

Add a workflow that comments on PRs when new translation keys lack translations in required locales:

name: Translation coverage check
on:
  pull_request:
    paths:
      - 'src/locales/**'

jobs:
  check-translations:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Check translation coverage
        run: |
          #!/bin/bash
          set -euo pipefail

          REQUIRED_LOCALES=("en" "de" "fr" "es" "ja")
          SOURCE_FILE="src/locales/en.json"
          MISSING=0
          REPORT=""

          source_keys=$(jq -r '[paths(scalars)] | map(join(".")) | .[]' "$SOURCE_FILE" | sort)

          for locale in "${REQUIRED_LOCALES[@]}"; do
            locale_file="src/locales/${locale}.json"
            if [[ ! -f "$locale_file" ]]; then
              REPORT+="- **${locale}**: File missing entirely\n"
              MISSING=1
              continue
            fi

            locale_keys=$(jq -r '[paths(scalars)] | map(join(".")) | .[]' "$locale_file" | sort)
            missing_keys=$(comm -23 <(echo "$source_keys") <(echo "$locale_keys"))

            if [[ -n "$missing_keys" ]]; then
              count=$(echo "$missing_keys" | wc -l)
              REPORT+="- **${locale}**: ${count} missing keys\n"
              MISSING=1
            fi
          done

          if [[ $MISSING -eq 1 ]]; then
            echo "## Translation Coverage Report" >> "$GITHUB_STEP_SUMMARY"
            echo "" >> "$GITHUB_STEP_SUMMARY"
            echo -e "$REPORT" >> "$GITHUB_STEP_SUMMARY"
            echo "" >> "$GITHUB_STEP_SUMMARY"
            echo "Run \`lokalise2 file download\` to pull latest translations." >> "$GITHUB_STEP_SUMMARY"
            exit 1
          fi

          echo "All locales have complete translation coverage." >> "$GITHUB_STEP_SUMMARY"

Step 4: Integration Tests for Key Coverage

Add a test that validates translation files have all required keys at build time:

// tests/i18n-coverage.test.ts
import { describe, it, expect } from 'vitest';
import fs from 'fs';
import path from 'path';

const LOCALES_DIR = path.resolve(__dirname, '../src/locales');
const SOURCE_LOCALE = 'en';
const REQUIRED_LOCALES = ['en', 'de', 'fr', 'es', 'ja'];

function flattenKeys(obj: Record<string, unknown>, prefix = ''): string[] {
  return Object.entries(obj).flatMap(([key, value]) => {
    const fullKey = prefix ? `${prefix}.${key}` : key;
    if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
      return flattenKeys(value as Record<string, unknown>, fullKey);
    }
    return [fullKey];
  });
}

describe('Translation coverage', () => {
  const sourceFile = JSON.parse(
    fs.readFileSync(path.join(LOCALES_DIR, `${SOURCE_LOCALE}.json`), 'utf-8')
  );
  const sourceKeys = flattenKeys(sourceFile).sort();

  for (const locale of REQUIRED_LOCALES) {
    it(`${locale}.json contains all source keys`, () => {
      const localeFile = JSON.parse(
        fs.readFileSync(path.join(LOCALES_DIR, `${locale}.json`), 'utf-8')
      );
      const localeKeys = flattenKeys(localeFile).sort();
      const missing = sourceKeys.filter(k => !localeKeys.includes(k));

      expect(missing, `Missing keys in ${locale}: ${missing.join(', ')}`).toHaveLength(0);
    });
  }

  it('no orphaned keys exist in non-source locales', () => {
    for (const locale of REQUIRED_LOCALES.filter(l => l !== SOURCE_LOCALE)) {
      const localeFile = JSON.parse(
        fs.readFileSync(path.join(LOCALES_DIR, `${locale}.json`), 'utf-8')
      );
      const localeKeys = flattenKeys(localeFile);
      const orphaned = localeKeys.filter(k => !sourceKeys.includes(k));

      expect(orphaned, `Orphaned keys in ${locale}: ${orphaned.join(', ')}`).toHaveLength(0);
    }
  });
});

Step 5: Branch-Based Translation Workflow

Use Lokalise branching to isolate translation work per feature branch. This prevents in-progress translations from leaking into production:

# .github/workflows/lokalise-branch.yml
name: Lokalise branch management
on:
  pull_request:
    types: [opened, synchronize, closed]
    paths:
      - 'src/locales/en.json'

jobs:
  manage-branch:
    runs-on: ubuntu-latest
    env:
      BRANCH_NAME: ${{ github.head_ref }}
    steps:
      - uses: actions/checkout@v4

      - name: Create Lokalise branch on PR open
        if: github.event.action == 'opened'
        run: |
          curl -X POST "https://api.lokalise.com/api2/projects/${{ secrets.LOKALISE_PROJECT_ID }}/branches" \
            -H "X-Api-Token: ${{ secrets.LOKALISE_API_TOKEN }}" \
            -H "Content-Type: application/json" \
            -d "{\"name\": \"${BRANCH_NAME}\"}"

      - name: Upload source to branch
        if: github.event.action == 'opened' || github.event.action == 'synchronize'
        run: |
          # Upload to the branch-specific project
          # Branch project ID format: {project_id}:{branch_name}
          lokalise2 file upload \
            --token "${{ secrets.LOKALISE_API_TOKEN }}" \
            --project-id "${{ secrets.LOKALISE_PROJECT_ID }}:${BRANCH_NAME}" \
            --file "src/locales/en.json" \
            --lang-iso "en" \
            --replace-modified \
            --poll \
            --poll-timeout 120s

      - name: Merge Lokalise branch on PR merge
        if: github.event.action == 'closed' && github.event.pull_request.merged == true
        run: |
          curl -X POST "https://api.lokalise.com/api2/projects/${{ secrets.LOKALISE_PROJECT_ID }}/branches/merge" \
            -H "X-Api-Token: ${{ secrets.LOKALISE_API_TOKEN }}" \
            -H "Content-Type: application/json" \
            -d "{\"source_branch\": \"${BRANCH_NAME}\", \"target_branch\": \"main\", \"force_conflict_resolve_using\": \"source\"}"

      - name: Delete Lokalise branch on PR close (unmerged)
        if: github.event.action == 'closed' && github.event.pull_request.merged == false
        run: |
          # Get branch ID first
          BRANCH_ID=$(curl -s "https://api.lokalise.com/api2/projects/${{ secrets.LOKALISE_PROJECT_ID }}/branches" \
            -H "X-Api-Token: ${{ secrets.LOKALISE_API_TOKEN }}" \
            | jq -r ".branches[] | select(.name == \"${BRANCH_NAME}\") | .branch_id")

          if [[ -n "$BRANCH_ID" ]]; then
            curl -X DELETE "https://api.lokalise.com/api2/projects/${{ secrets.LOKALISE_PROJECT_ID }}/branches/${BRANCH_ID}" \
              -H "X-Api-Token: ${{ secrets.LOKALISE_API_TOKEN }}"
          fi

Output

After applying this skill, the project will have:

  • GitHub Actions workflow files for u

Content truncated.

svg-icon-generator

jeremylongshore

Svg Icon Generator - Auto-activating skill for Visual Content. Triggers on: svg icon generator, svg icon generator Part of the Visual Content skill category.

7824

automating-mobile-app-testing

jeremylongshore

This skill enables automated testing of mobile applications on iOS and Android platforms using frameworks like Appium, Detox, XCUITest, and Espresso. It generates end-to-end tests, sets up page object models, and handles platform-specific elements. Use this skill when the user requests mobile app testing, test automation for iOS or Android, or needs assistance with setting up device farms and simulators. The skill is triggered by terms like "mobile testing", "appium", "detox", "xcuitest", "espresso", "android test", "ios test".

13615

d2-diagram-creator

jeremylongshore

D2 Diagram Creator - Auto-activating skill for Visual Content. Triggers on: d2 diagram creator, d2 diagram creator Part of the Visual Content skill category.

3114

performing-penetration-testing

jeremylongshore

This skill enables automated penetration testing of web applications. It uses the penetration-tester plugin to identify vulnerabilities, including OWASP Top 10 threats, and suggests exploitation techniques. Use this skill when the user requests a "penetration test", "pentest", "vulnerability assessment", or asks to "exploit" a web application. It provides comprehensive reporting on identified security flaws.

4311

performing-security-audits

jeremylongshore

This skill allows Claude to conduct comprehensive security audits of code, infrastructure, and configurations. It leverages various tools within the security-pro-pack plugin, including vulnerability scanning, compliance checking, cryptography review, and infrastructure security analysis. Use this skill when a user requests a "security audit," "vulnerability assessment," "compliance review," or any task involving identifying and mitigating security risks. It helps to ensure code and systems adhere to security best practices and compliance standards.

109

designing-database-schemas

jeremylongshore

Design and visualize efficient database schemas, normalize data, map relationships, and generate ERD diagrams and SQL statements.

1128

You might also like

flutter-development

aj-geddes

Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.

9521,094

drawio-diagrams-enhanced

jgtolentino

Create professional draw.io (diagrams.net) diagrams in XML format (.drawio files) with integrated PMP/PMBOK methodologies, extensive visual asset libraries, and industry-standard professional templates. Use this skill when users ask to create flowcharts, swimlane diagrams, cross-functional flowcharts, org charts, network diagrams, UML diagrams, BPMN, project management diagrams (WBS, Gantt, PERT, RACI), risk matrices, stakeholder maps, or any other visual diagram in draw.io format. This skill includes access to custom shape libraries for icons, clipart, and professional symbols.

846846

ui-ux-pro-max

nextlevelbuilder

"UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 8 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient."

571700

godot

bfollington

This skill should be used when working on Godot Engine projects. It provides specialized knowledge of Godot's file formats (.gd, .tscn, .tres), architecture patterns (component-based, signal-driven, resource-based), common pitfalls, validation tools, code templates, and CLI workflows. The `godot` command is available for running the game, validating scripts, importing resources, and exporting builds. Use this skill for tasks involving Godot game development, debugging scene/resource files, implementing game systems, or creating new Godot components.

548492

nano-banana-pro

garg-aayush

Generate and edit images using Google's Nano Banana Pro (Gemini 3 Pro Image) API. Use when the user asks to generate, create, edit, modify, change, alter, or update images. Also use when user references an existing image file and asks to modify it in any way (e.g., "modify this image", "change the background", "replace X with Y"). Supports both text-to-image generation and image-to-image editing with configurable resolution (1K default, 2K, or 4K for high resolution). DO NOT read the image file first - use this skill directly with the --input-image parameter.

673466

fastapi-templates

wshobson

Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.

514280

Stay ahead of the MCP ecosystem

Get weekly updates on new skills and servers.