Execute Lokalise production deployment checklist and rollback procedures.
Use when deploying Lokalise integrations to production, preparing for launch,
or implementing go-live procedures.
Trigger with phrases like "lokalise production", "deploy lokalise",
"lokalise go-live", "lokalise launch checklist".
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Execute Lokalise production deployment checklist and rollback procedures.
Use when deploying Lokalise integrations to production, preparing for launch,
or implementing go-live procedures.
Trigger with phrases like "lokalise production", "deploy lokalise",
"lokalise go-live", "lokalise launch checklist".
allowed-tools
Read, Bash(lokalise2:*), Bash(curl:*), Grep
version
1.14.0
license
MIT
author
Jeremy Longshore <jeremy@intentsolutions.io>
tags
["saas","lokalise","deployment"]
compatibility
Designed for Claude Code, also compatible with Codex and OpenClaw
Lokalise Production Checklist
Overview
A structured pre-deployment checklist for Lokalise integrations covering nine verification areas: translation coverage, missing key detection, format validation, API token security, rate limit preparedness, fallback language configuration, download verification, OTA configuration, and contributor access review. Run through each section before any production deployment.
Prerequisites
Lokalise project with production API token
lokalise2 CLI installed and authenticated
curl and jq available in your environment
Access to the Lokalise dashboard (Team Owner or Admin role)
Application codebase with i18n integration ready for deployment
Instructions
Step 1: Translation Coverage Audit
Verify that every supported locale meets the coverage threshold before deploying.
echo"=== API Token Security Audit ==="# Verify token is not hardcoded in source
HARDCODED=$(grep -r "X-Api-Token" --include="*.ts" --include="*.js" --include="*.json" \
-l src/ 2>/dev/null | grep -v node_modules || true)
if [[ -n "$HARDCODED" ]]; thenecho"FAIL: API token may be hardcoded in: $HARDCODED"exit 1
fi# Verify token is not in version control
GIT_SECRETS=$(git log --all -p --diff-filter=A -- '*.env''*.env.*' 2>/dev/null \
| grep -i "LOKALISE_API_TOKEN=" | head -5 || true)
if [[ -n "$GIT_SECRETS" ]]; thenecho"FAIL: Token found in git history. Rotate immediately."exit 1
fi# Verify .env files are gitignoredif ! grep -q "\.env" .gitignore 2>/dev/null; thenecho"WARN: .env not in .gitignore"fi# Verify token permissions are minimal
TOKEN_RESPONSE=$(curl -sf "https://api.lokalise.com/api2/projects/${LOKALISE_PROJECT_ID}" \
-H "X-Api-Token: ${LOKALISE_API_TOKEN}" -o /dev/null -w "%{http_code}")
if [[ "$TOKEN_RESPONSE" == "200" ]]; thenecho"PASS: Token is valid and has project access"elseecho"FAIL: Token returned HTTP $TOKEN_RESPONSE"exit 1
fiecho"PASS: No hardcoded tokens detected"
Step 5: Rate Limit Preparedness
echo"=== Rate Limit Readiness ==="# Lokalise enforces 6 requests/second per token# Check if your code handles 429 responses
RATE_LIMIT_HANDLING=$(grep -r "429\|rate.limit\|retry-after\|rateLimitRetry" \
--include="*.ts" --include="*.js" src/ 2>/dev/null | head -5 || true)
if [[ -z "$RATE_LIMIT_HANDLING" ]]; thenecho"WARN: No rate limit handling detected in source code."echo" Add retry logic with exponential backoff for 429 responses."echo" Lokalise limit: 6 requests/second per API token."elseecho"PASS: Rate limit handling detected"echo"$RATE_LIMIT_HANDLING"fi
Step 6: Fallback Language Configuration
Verify the application gracefully falls back when a translation is missing.
// Verify in your i18n configuration:// i18next exampleimport i18next from'i18next';
// Correct fallback configuration
i18next.init({
fallbackLng: 'en', // Always fall back to Englishload: 'languageOnly', // 'de' not 'de-DE' unless regional variants existreturnEmptyString: false, // Treat empty strings as missingmissingKeyHandler: (lngs, ns, key) => {
console.warn(`Missing translation: ${key} for ${lngs.join(', ')}`);
// In production, report to monitoring (Sentry, Datadog, etc.)
},
interpolation: {
escapeValue: false, // React already escapes
},
});
Step 7: Download Verification
Test that the full download-build cycle works end-to-end.
echo"=== Download Verification ==="
TEMP_DIR=$(mktemp -d)
trap'rm -rf "$TEMP_DIR"' EXIT
# Download with production settings
lokalise2 file download \
--token "$LOKALISE_API_TOKEN" \
--project-id "$LOKALISE_PROJECT_ID" \
--format json \
--original-filenames=true \
--directory-prefix="" \
--export-empty-as=base \
--unzip-to "$TEMP_DIR/" 2>&1
# Verify files exist and are non-empty
FILE_COUNT=$(find "$TEMP_DIR" -name "*.json" | wc -l)
echo"Downloaded $FILE_COUNT locale files"if [[ $FILE_COUNT -eq 0 ]]; thenecho"FAIL: No files downloaded"exit 1
fi# Verify each file is valid JSONfor f in"$TEMP_DIR"/*.json; doif ! jq empty "$f" 2>/dev/null; thenecho"FAIL: Invalid JSON: $f"exit 1
fi
keys=$(jq '[paths(scalars)] | length'"$f")
locale=$(basename"$f" .json)
echo" $locale: $keys keys"doneecho"PASS: All downloaded files are valid"
Step 8: OTA Configuration (If Applicable)
If using Lokalise OTA (over-the-air) translations for mobile or web:
echo"=== OTA Configuration Check ==="# Verify OTA SDK token (separate from API token)if [[ -z "${LOKALISE_OTA_TOKEN:-}" ]]; thenecho"INFO: OTA not configured (LOKALISE_OTA_TOKEN not set). Skip if not using OTA."else# Test OTA bundle endpoint
OTA_STATUS=$(curl -sf -o /dev/null -w "%{http_code}" \
"https://ota.lokalise.com/v3/public/${LOKALISE_OTA_TOKEN}/")
if [[ "$OTA_STATUS" == "200" ]]; thenecho"PASS: OTA endpoint reachable"elseecho"FAIL: OTA endpoint returned HTTP $OTA_STATUS"fi# Verify OTA freeze window is not activeecho"INFO: Check Lokalise dashboard > OTA > Settings for freeze windows before deploy"fi
Step 9: Contributor Access Review
echo"=== Contributor Access Review ==="
CONTRIBUTORS=$(curl -sf "https://api.lokalise.com/api2/teams" \
-H "X-Api-Token: ${LOKALISE_API_TOKEN}")
echo"Review the following in the Lokalise dashboard before go-live:"echo" 1. Remove any test/demo contributors from the production project"echo" 2. Verify all contributors have the minimum required role"echo" 3. Ensure no shared/generic accounts exist"echo" 4. Confirm two-factor authentication is enabled for admins"echo" 5. Review and remove any unused API tokens"echo""echo"Roles reference:"echo" - Admin: Full access (limit to 2-3 people)"echo" - Manager: Can manage contributors and keys"echo" - Developer: Upload/download, no contributor management"echo" - Translator: Translate only, no key management"echo""echo"ACTION: Manually verify in Lokalise dashboard > Team > Members"
Output
A complete pre-deployment report covering:
Translation coverage percentage per locale (must be 100% for production)
Missing and orphaned key counts
Format validation results (JSON validity, placeholder consistency)
Security audit results (no hardcoded tokens, proper gitignore)
Rate limit handling confirmation
Fallback language configuration status
Download verification (end-to-end test)
OTA readiness (if applicable)
Contributor access review action items
Error Handling
Alert
Condition
Severity
Action
Incomplete translations
Any locale < 100%
P1 — Blocks deploy
Complete translations or add missing keys
Hardcoded API token
Token found in source
P1 — Blocks deploy
Remove from code, rotate token immediately
Token in git history
Token committed previously
P1 — Blocks deploy
Rotate token, consider git filter-repo
Download produces 0 files
API error or empty project
P1 — Blocks deploy
Check project ID, token permissions, Lokalise status
Placeholder mismatch
{{name}} missing in translation
P2 — Warning
Fix in Lokalise, re-download
No rate limit handling
Missing 429 retry logic
P2 — Warning
Add retry with backoff before high-traffic launch
Empty string values
Untranslated keys exported as ""
P3 — Info
Use --export-empty-as=base or skip
Examples
Quick Spot-Check (Single Locale)
# Fast check for a single locale before hotfix deploy
curl -sf "https://api.lokalise.com/api2/projects/${LOKALISE_PROJECT_ID}/languages" \
-H "X-Api-Token: ${LOKALISE_API_TOKEN}" \
| jq '.languages[] | select(.lang_iso == "de") | {locale: .lang_iso, progress: .statistics.progress, words_remaining: .statistics.words_to_do}'