LO

lokalise-multi-env-setup

Manage translations across development, staging, and production using project-based or branch-based isolation.

Install

mkdir -p .claude/skills/lokalise-multi-env-setup && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/7614" && unzip -o skill.zip -d .claude/skills/lokalise-multi-env-setup && rm skill.zip

Installs to .claude/skills/lokalise-multi-env-setup

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Configure Lokalise across development, staging, and production environments.
76 charsno explicit “when” trigger
Intermediate

Key capabilities

  • Configure environment-specific Lokalise projects
  • Implement branching strategies for QA
  • Manage API tokens via secret managers
  • Set environment-aware SDK configurations
  • Promote translations through deployment pipelines

How it works

It establishes isolation by either using separate projects or branches per environment, combined with runtime configuration that selects credentials and settings based on the deployment environment.

Inputs & outputs

You give it
Environment context and secrets
You get back
Isolated Lokalise configuration per environment

When to use lokalise-multi-env-setup

  • Isolating dev and production translation projects
  • Managing secrets for different environments
  • Promoting translations through a dev-to-prod pipeline
  • Configuring environment-aware Lokalise SDK settings

About this skill

Lokalise Multi-Environment Setup

Overview

Configure Lokalise for isolated development, staging, and production environments. Two strategies are covered: separate Lokalise projects per environment (strongest isolation) and Lokalise branching within a single project (simpler management). Both approaches include secret management, environment-aware configuration, and a promotion workflow that moves translations through the pipeline from dev to production without cross-contamination.

Prerequisites

  • Lokalise Team or Enterprise plan (branching requires Team plan or higher)
  • One Lokalise API token per environment, each scoped to minimum required permissions
  • Secret management system: GitHub Secrets, AWS Secrets Manager, GCP Secret Manager, or HashiCorp Vault
  • Node.js 18+ with @lokalise/node-api SDK installed
  • Environment variable NODE_ENV (or equivalent) set in each deployment target

Instructions

Step 1: Choose Your Strategy

Option A — Separate projects per environment (recommended for teams > 5 translators or strict compliance):

EnvironmentLokalise ProjectPurpose
DevelopmentMyApp (Dev)Rapid iteration, machine translations OK
StagingMyApp (Staging)QA review, translator proofing
ProductionMyApp (Prod)Approved translations only

Option B — Single project with Lokalise branching (simpler for small teams):

BranchPurpose
mainProduction translations
stagingQA translations under review
devWork-in-progress translations

Step 2: Environment-Aware Configuration

Create a configuration module that selects the correct Lokalise project and credentials based on the runtime environment:

// src/config/lokalise.ts
interface LokaliseEnvConfig {
  environment: string;
  apiToken: string;
  projectId: string;
  branch?: string;           // Only used with Option B (branching)
  cacheTtlMs: number;
  enableOta: boolean;
  fallbackLocale: string;
  rateLimitPerSec: number;
}

const ENV_CONFIGS: Record<string, Omit<LokaliseEnvConfig, 'apiToken' | 'projectId'>> = {
  development: {
    environment: 'development',
    cacheTtlMs: 0,            // No cache in dev — always fetch fresh
    enableOta: false,
    fallbackLocale: 'en',
    rateLimitPerSec: 6,
  },
  staging: {
    environment: 'staging',
    cacheTtlMs: 5 * 60_000,  // 5 minutes
    enableOta: true,
    fallbackLocale: 'en',
    rateLimitPerSec: 6,
  },
  production: {
    environment: 'production',
    cacheTtlMs: 30 * 60_000, // 30 minutes
    enableOta: true,
    fallbackLocale: 'en',
    rateLimitPerSec: 4,       // Conservative — leave headroom for other integrations
  },
};

export function getLokaliseConfig(): LokaliseEnvConfig {
  const env = process.env.NODE_ENV || 'development';
  const base = ENV_CONFIGS[env];

  if (!base) {
    throw new Error(`Unknown environment: ${env}. Expected: ${Object.keys(ENV_CONFIGS).join(', ')}`);
  }

  const apiToken = process.env.LOKALISE_API_TOKEN;
  const projectId = process.env.LOKALISE_PROJECT_ID;

  if (!apiToken) {
    throw new Error('LOKALISE_API_TOKEN is not set');
  }
  if (!projectId) {
    throw new Error('LOKALISE_PROJECT_ID is not set');
  }

  return {
    ...base,
    apiToken,
    projectId,
    branch: process.env.LOKALISE_BRANCH,  // Optional: for branching strategy
  };
}

Step 3: Secret Management

Store API tokens securely in each environment. Never commit tokens to source control.

GitHub Actions (CI/CD):

# .github/workflows/deploy.yml
jobs:
  deploy-staging:
    environment: staging
    env:
      LOKALISE_API_TOKEN: ${{ secrets.LOKALISE_API_TOKEN_STAGING }}
      LOKALISE_PROJECT_ID: ${{ vars.LOKALISE_PROJECT_ID_STAGING }}
    steps:
      - run: npm run build

  deploy-production:
    environment: production
    env:
      LOKALISE_API_TOKEN: ${{ secrets.LOKALISE_API_TOKEN_PROD }}
      LOKALISE_PROJECT_ID: ${{ vars.LOKALISE_PROJECT_ID_PROD }}
    steps:
      - run: npm run build

AWS Secrets Manager:

import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';

async function getLokaliseToken(environment: string): Promise<string> {
  const client = new SecretsManagerClient({ region: 'us-east-1' });
  const command = new GetSecretValueCommand({
    SecretId: `lokalise/${environment}/api-token`,
  });
  const response = await client.send(command);
  return response.SecretString!;
}

GCP Secret Manager:

import { SecretManagerServiceClient } from '@google-cloud/secret-manager';

async function getLokaliseToken(environment: string): Promise<string> {
  const client = new SecretManagerServiceClient();
  const [version] = await client.accessSecretVersion({
    name: `projects/my-project/secrets/lokalise-token-${environment}/versions/latest`,
  });
  return version.payload!.data!.toString();
}

HashiCorp Vault:

# Read token from Vault
vault kv get -field=api_token secret/lokalise/production

Step 4: Lokalise Branching (Option B Alternative)

If using a single project with branching instead of separate projects:

import { LokaliseApi } from '@lokalise/node-api';

const lokalise = new LokaliseApi({ apiKey: process.env.LOKALISE_API_TOKEN! });
const projectId = process.env.LOKALISE_PROJECT_ID!;

// Create a branch for a new environment or feature
async function createBranch(branchName: string): Promise<void> {
  await lokalise.branches().create({ name: branchName }, { project_id: projectId });
  console.log(`Created branch: ${branchName}`);
}

// Download translations from a specific branch
async function downloadFromBranch(branchName: string, outputDir: string): Promise<void> {
  const response = await lokalise.files().download(`${projectId}:${branchName}`, {
    format: 'json',
    original_filenames: true,
    directory_prefix: '',
    export_empty_as: 'base',
  });

  console.log(`Download URL: ${response.bundle_url}`);
  // Fetch and extract the zip from response.bundle_url into outputDir
}

// Merge a branch into main after QA approval
async function mergeBranch(sourceBranch: string, targetBranch = 'main'): Promise<void> {
  await lokalise.branches().merge(
    { project_id: projectId },
    {
      source_branch_id: sourceBranch,
      target_branch_id: targetBranch,
      force_conflict_resolve_using: 'source',
    }
  );
  console.log(`Merged ${sourceBranch} → ${targetBranch}`);
}

Step 5: Promotion Workflow (Dev to Staging to Production)

Promote translations through environments with validation at each gate:

#!/bin/bash
# scripts/promote-translations.sh
# Usage: ./promote-translations.sh staging   (promote dev → staging)
# Usage: ./promote-translations.sh production (promote staging → production)
set -euo pipefail

TARGET_ENV="${1:?Usage: promote-translations.sh <staging|production>}"

case "$TARGET_ENV" in
  staging)
    SOURCE_TOKEN="$LOKALISE_API_TOKEN_DEV"
    SOURCE_PROJECT="$LOKALISE_PROJECT_ID_DEV"
    TARGET_TOKEN="$LOKALISE_API_TOKEN_STAGING"
    TARGET_PROJECT="$LOKALISE_PROJECT_ID_STAGING"
    ;;
  production)
    SOURCE_TOKEN="$LOKALISE_API_TOKEN_STAGING"
    SOURCE_PROJECT="$LOKALISE_PROJECT_ID_STAGING"
    TARGET_TOKEN="$LOKALISE_API_TOKEN_PROD"
    TARGET_PROJECT="$LOKALISE_PROJECT_ID_PROD"
    ;;
  *)
    echo "Invalid target: $TARGET_ENV (expected staging or production)"
    exit 1
    ;;
esac

TEMP_DIR=$(mktemp -d)
trap 'rm -rf "$TEMP_DIR"' EXIT

echo "=== Step 1: Download from source ==="
lokalise2 file download \
  --token "$SOURCE_TOKEN" \
  --project-id "$SOURCE_PROJECT" \
  --format json \
  --original-filenames=true \
  --directory-prefix="" \
  --export-empty-as=skip \
  --unzip-to "$TEMP_DIR/"

echo "=== Step 2: Validate completeness ==="
SOURCE_FILE="$TEMP_DIR/en.json"
if [[ ! -f "$SOURCE_FILE" ]]; then
  echo "ERROR: Source locale file not found"
  exit 1
fi

SOURCE_KEY_COUNT=$(jq '[paths(scalars)] | length' "$SOURCE_FILE")
echo "Source has $SOURCE_KEY_COUNT keys"

for locale_file in "$TEMP_DIR"/*.json; do
  locale=$(basename "$locale_file" .json)
  key_count=$(jq '[paths(scalars)] | length' "$locale_file")
  coverage=$((key_count * 100 / SOURCE_KEY_COUNT))

  if [[ "$TARGET_ENV" == "production" && $coverage -lt 100 ]]; then
    echo "BLOCKED: ${locale} is ${coverage}% translated (production requires 100%)"
    exit 1
  elif [[ "$TARGET_ENV" == "staging" && $coverage -lt 80 ]]; then
    echo "WARNING: ${locale} is ${coverage}% translated"
  fi
  echo "  ${locale}: ${coverage}% (${key_count}/${SOURCE_KEY_COUNT} keys)"
done

echo "=== Step 3: Upload to target ==="
for locale_file in "$TEMP_DIR"/*.json; do
  locale=$(basename "$locale_file" .json)
  lokalise2 file upload \
    --token "$TARGET_TOKEN" \
    --project-id "$TARGET_PROJECT" \
    --file "$locale_file" \
    --lang-iso "$locale" \
    --replace-modified \
    --poll \
    --poll-timeout 120s
  echo "  Uploaded ${locale}"
  sleep 0.2  # Stay under 6 req/sec rate limit
done

echo "=== Promotion to ${TARGET_ENV} complete ==="

Output

After applying this skill, the project will have:

  • Environment-aware Lokalise configuration module (src/config/lokalise.ts)
  • Per-environment API tokens stored in the chosen secret manager
  • GitHub Actions workflows with environment-specific secrets
  • Promotion script for moving translations through the dev/staging/prod pipeline
  • (If using branching) Branch management utilities for the single-project approach

Error Handling

IssueCauseSolution
LOKALISE_API_TOKEN is not setMissing environment variableVerify secret injection in deployment config
Wrong translations in productionUsing dev project IDAudit LOKALISE_PROJECT_ID per environment; never share project IDs across environments
Cross-env data leakShared API token with write access to multiple projectsCrea

Content truncated.

Prerequisites

Lokalise Team or Enterprise planSecret management systemNode.js 18+ with @lokalise/node-api

Limitations

  • Branching requires Team plan or higher

How it compares

It provides a systematic approach to environment isolation that prevents cross-contamination of translation data, unlike a single-project setup.

Compared to similar skills

lokalise-multi-env-setup side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
lokalise-multi-env-setup (this skill)127dReviewIntermediate
cloudflare-manager259moReviewIntermediate
azure-functions105moReviewIntermediate
flow-nexus-platform64moReviewBeginner

Try saying

Example prompts that trigger this skill in your AI assistant.

More by jeremylongshore

View all by jeremylongshore

analyzing-logs

jeremylongshore

Analyze application logs to detect performance issues, identify error patterns, and improve stability by extracting key insights.

14123

ollama-setup

jeremylongshore

Configure auto-configure Ollama when user needs local LLM deployment, free AI alternatives, or wants to eliminate hosted API costs. Trigger phrases: "install ollama", "local AI", "free LLM", "self-hosted AI", "replace OpenAI", "no API costs". Use when appropriate context detected. Trigger with relevant phrases based on skill purpose.

1167

backtesting-trading-strategies

jeremylongshore

Backtest crypto and traditional trading strategies against historical data. Calculates performance metrics (Sharpe, Sortino, max drawdown), generates equity curves, and optimizes strategy parameters. Use when user wants to test a trading strategy, validate signals, or compare approaches. Trigger with phrases like "backtest strategy", "test trading strategy", "historical performance", "simulate trades", "optimize parameters", or "validate signals".

1071

generating-database-seed-data

jeremylongshore

Process this skill enables AI assistant to generate realistic test data and database seed scripts for development and testing environments. it uses faker libraries to create realistic data, maintains relational integrity, and allows configurable data volumes. u... Use when working with databases or data models. Trigger with phrases like 'database', 'query', or 'schema'.

1033

cursor-codebase-indexing

jeremylongshore

Execute set up and optimize Cursor codebase indexing. Triggers on "cursor index setup", "codebase indexing", "index codebase", "cursor semantic search". Use when working with cursor codebase indexing functionality. Trigger with phrases like "cursor codebase indexing", "cursor indexing", "cursor".

885

testing-mobile-apps

jeremylongshore

Execute mobile app testing on iOS and Android devices/simulators. Use when performing specialized testing. Trigger with phrases like "test mobile app", "run iOS tests", or "validate Android functionality".

810

You might also like

cloudflare-manager

qdhenry

Comprehensive Cloudflare account management for deploying Workers, KV Storage, R2, Pages, DNS, and Routes. Use when deploying cloudflare services, managing worker containers, configuring KV/R2 storage, or setting up DNS/routing. Requires CLOUDFLARE_API_KEY in .env and Bun runtime with dependencies installed.

25135

azure-functions

aj-geddes

Create serverless functions on Azure with triggers, bindings, authentication, and monitoring. Use for event-driven computing without managing infrastructure.

10104

flow-nexus-platform

ruvnet

Comprehensive Flow Nexus platform management - authentication, sandboxes, app deployment, payments, and challenges

691

nuxthub-migration

onmax

Use when migrating NuxtHub projects or when user mentions NuxtHub Admin sunset, GitHub Actions deployment removal, self-hosting NuxtHub, or upgrading to v1/nightly. Covers v0.9.X self-hosting (stable) and v1/nightly multi-cloud (experimental, database/blob not ready).

589

ollama-setup

jeremylongshore

Configure auto-configure Ollama when user needs local LLM deployment, free AI alternatives, or wants to eliminate hosted API costs. Trigger phrases: "install ollama", "local AI", "free LLM", "self-hosted AI", "replace OpenAI", "no API costs". Use when appropriate context detected. Trigger with relevant phrases based on skill purpose.

1167

netlify-deploy

openai

Deploy web projects to Netlify using the Netlify CLI (`npx netlify`). Use when the user asks to deploy, host, publish, or link a site/repo on Netlify, including preview and production deploys.

740

Search skills

Search the agent skills registry