Execute major migration to Lokalise from other TMS platforms with data migration strategies.
Use when migrating to Lokalise from competitors, performing data imports,
or re-platforming existing translation management to Lokalise.
Trigger with phrases like "migrate to lokalise", "lokalise migration",
"switch to lokalise", "lokalise import", "lokalise replatform".
!lokalise2 --version 2>/dev/null || echo 'CLI not installed'
!npm list @lokalise/node-api 2>/dev/null | grep lokalise || echo 'SDK not installed'
!node --version 2>/dev/null || echo 'Node.js not available'
Overview
Migrate translations from another TMS (Crowdin, Phrase, POEditor) into Lokalise — export from the source platform, transform key names and variable syntax to match Lokalise conventions, bulk upload via API, validate translation coverage, and handle key conflicts with format-aware tooling.
Prerequisites
Admin or export access to the source TMS platform
Lokalise account with a plan that supports the target key count (Free: 500 keys, Pro: unlimited)
LOKALISE_API_TOKEN environment variable set (read-write token)
lokalise2 CLI or @lokalise/node-api SDK installed
for JSON manipulation during transformation
jq
Instructions
Step 1: Export from Source Platform
Each TMS has its own export format. Export to a Lokalise-compatible format when possible (JSON, XLIFF, or the platform's native format).
From Crowdin:
set -euo pipefail
# Export all translations as JSON (flat key-value structure)
# Use Crowdin CLI or API to download
curl -X POST "https://api.crowdin.com/api/v2/projects/${CROWDIN_PROJECT_ID}/translations/builds" \
-H "Authorization: Bearer ${CROWDIN_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"targetLanguageIds": [], "exportApprovedOnly": false}'
# Download the build when ready (poll build status first)
curl -X GET "https://api.crowdin.com/api/v2/projects/${CROWDIN_PROJECT_ID}/translations/builds/${BUILD_ID}/download" \
-H "Authorization: Bearer ${CROWDIN_TOKEN}" -o crowdin-export.zip
unzip crowdin-export.zip -d crowdin-export/
echo "Exported $(find crowdin-export/ -name '*.json' | wc -l) translation files"
From Phrase (formerly PhraseApp):
set -euo pipefail
# Export all locales as JSON
for LOCALE in en fr de es ja; do
curl -X GET "https://api.phrase.com/v2/projects/${PHRASE_PROJECT_ID}/locales/${LOCALE}/download?file_format=simple_json" \
-H "Authorization: token ${PHRASE_TOKEN}" \
-o "phrase-export/${LOCALE}.json"
sleep 0.5
done
echo "Exported locales: $(ls phrase-export/)"
From POEditor:
set -euo pipefail
# Export via POEditor API (returns a download URL)
EXPORT_URL=$(curl -s -X POST "https://api.poeditor.com/v2/projects/export" \
-d "api_token=${POEDITOR_TOKEN}&id=${POEDITOR_PROJECT_ID}&language=en&type=json" \
| jq -r '.result.url')
curl -s "$EXPORT_URL" -o poeditor-export/en.json
echo "Downloaded $(wc -c < poeditor-export/en.json) bytes"
Step 2: Transform Keys and Variable Syntax
Different TMS platforms use different interpolation syntax. Lokalise supports multiple formats, but consistency matters.
Use the transform script in Step 2 to normalize interpolation tokens before upload
Upload process stuck
Large file processing on Lokalise side
Poll process status; files over 50MB should be split by namespace
Plural forms missing
Source platform uses different plural rules
Manually map CLDR plural categories after import
Examples
Quick Migration Inventory
Before starting a migration, assess the scope:
set -euo pipefail
echo "=== Source Platform Inventory ==="
echo "Translation files:"
find source-export/ -name "*.json" -o -name "*.xliff" -o -name "*.po" | head -20
echo ""
echo "Languages found:"
ls source-export/ | head -20
echo ""
echo "Sample key count (first file):"
FIRST_FILE=$(find source-export/ -name "*.json" -type f | head -1)
jq 'keys | length' "$FIRST_FILE" 2>/dev/null || echo "Not a flat JSON file"
Dry Run — Validate Without Importing
set -euo pipefail
# Upload with --cleanup-mode to see what would happen without committing
lokalise2 --token "${LOKALISE_API_TOKEN}" \
file upload \
--project-id "${PROJECT_ID}" \
--file lokalise-import/en.json \
--lang-iso en \
--poll \
--detect-icu-plurals
# Review the process result before uploading remaining languages