
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
Translation management CLI for developers. Manage i18n translations, export to 6 formats (iOS, Android, Flutter, i18next), import translations, and collaborate with teams. Affordable alternative to Lokalise and Crowdin.
Langctl is a powerful command-line tool that lets you manage translations directly from your terminal. Create projects, manage translation keys, invite team members, export in multiple formats, and integrate seamlessly into your CI/CD pipeline.
npm install -g langctl
Or use with npx (no installation required):
npx langctl --help
📌 First time here? Check out our Getting Started Guide on the website for a complete walkthrough!
💡 Tip: Learn more about API keys and authentication at langctl.com/docs/cli/authentication
# Interactive setup
langctl init
# Or authenticate directly
langctl auth lc_your_api_key_here
# View organization info
langctl org info
# Check statistics
langctl org stats
# List your projects
langctl projects list
# List translation keys
langctl keys list my-project
# Export translations
langctl export my-project --language en --format json
# Create a new key
langctl keys create my-project home.welcome \
--value-en "Welcome!" \
--value-es "¡Bienvenido!"
langctl init - Interactive setup wizardlangctl auth <api-key> - Authenticate with API keylangctl logout - Clear credentialslangctl config - View current configurationlangctl org info - View organization detailslangctl org stats - View organization statisticslangctl org plan - View subscription plan and limitslangctl projects list - List all projectslangctl projects create <name> - Create new projectlangctl projects get <slug> - Get project detailslangctl projects update <slug> - Update projectlangctl projects delete <slug> - Delete projectlangctl projects add-language <slug> <language> - Add languagelangctl projects remove-language <slug> <language> - Remove languagelangctl projects stats <slug> - View project statisticslangctl keys list <project> - List translation keyslangctl keys get <project> <key> - Get key detailslangctl keys create <project> <key> - Create new keylangctl keys delete <project> <key> - Delete keylangctl keys translate <project> <key> - Update translationlangctl keys publish <project> <keys...> - Publish/unpublish keyslangctl team list - List team memberslangctl team get <email> - Get member detailslangctl team invite <email> - Invite team memberlangctl team remove <email> - Remove team memberlangctl team update-role <email> <role> - Update member rolelangctl team invitations - List invitationslangctl team revoke-invitation <email> - Revoke invitationlangctl export <project> - Export translationslangctl import <project> <file> - Import translationslangctl initInteractive setup wizard that guides you through authentication and configuration.
langctl init
langctl auth <api-key>Authenticate with an API key from your dashboard.
langctl auth lc_abc123...
langctl logoutClear stored authentication credentials.
langctl logout
langctl configDisplay current configuration (API key, organization, etc.).
langctl config
langctl org infoView your organization details.
langctl org info
Output:
langctl org statsView comprehensive organization statistics.
langctl org stats
Output:
langctl org planView subscription plan details and resource limits.
langctl org plan
Output:
langctl projects listList all projects you have access to.
langctl projects list
Output:
langctl projects create <name>Create a new translation project.
langctl projects create "Mobile App" \
--description "iOS and Android translations" \
--languages en,es,fr,de \
--default-language en
Options:
-d, --description <text> - Project description-l, --languages <langs> - Comma-separated language codes (default: en)--default-language <code> - Default language (default: first language)Examples:
# Simple project with English only
langctl projects create "My App"
# Multi-language project
langctl projects create "Global App" \
-l en,es,fr,de,ja \
--default-language en
# With description
langctl projects create "Mobile App" \
-d "Translation keys for mobile application" \
-l en,es
langctl projects get <slug>Get detailed information about a specific project.
langctl projects get my-app
Output:
langctl projects update <slug>Update project details.
langctl projects update my-app \
--name "New Name" \
--description "Updated description" \
--languages en,es,fr,de,ja \
--default-language en
Options:
-n, --name <name> - Update project name-d, --description <text> - Update description-l, --languages <langs> - Update supported languages--default-language <code> - Update default languageExamples:
# Change project name
langctl projects update my-app --name "Better Name"
# Add more languages
langctl projects update my-app -l en,es,fr,de,ja,zh
# Update description only
langctl projects update my-app -d "New project description"
langctl projects delete <slug>Delete a project (soft delete - can be recovered).
langctl projects delete my-app
Warning: This will mark the project as deleted. Contact support to recover deleted projects.
langctl projects add-language <slug> <language>Add a new language to an existing project.
langctl projects add-language my-app de
Examples:
# Add German
langctl projects add-language my-app de
# Add Japanese
langctl projects add-language my-app ja
# Add Chinese
langctl projects add-language my-app zh
langctl projects remove-language <slug> <language>Remove a language from a project.
langctl projects remove-language my-app de
Note: Cannot remove the default language. Change default language first if needed.
langctl projects stats <slug>View project statistics.
langctl projects stats my-app
Output:
langctl keys list <project>List translation keys for a project.
langctl keys list my-app
Options:
-m, --module <name> - Filter by module-p, --published - Show only published keys-s, --search <term> - Search in key names--limit <number> - Limit results (default: 100)--offset <number> - Offset for pagination (default: 0)Examples:
# List all keys
langctl keys list my-app
# Filter by module
langctl keys list my-app --module auth
# Show only published keys
langctl keys list my-app --published
# Search for specific keys
langctl keys list my-app --search "welcome"
# Pagination
langctl keys list my-app --limit 50 --offset 0
langctl keys list my-app --limit 50 --offset 50
langctl keys get <project> <key>Get detailed information about a specific translation key.
langctl keys get my-app home.welcome
Output:
langctl keys create <project> <key>Create a new translation key with values for multiple languages.
langctl keys create my-app home.welcome \
--description "Welcome message on homepage" \
--module home \
--value-en "Welcome to our app!" \
--value-es "¡Bienvenido a nuestra aplicación!" \
--value-fr "Bienvenue dans notre application!" \
--value-de "Willkommen in unserer App!"
Options:
-d, --description <text> - Key description-m, --module <name> - Module/namespace for organization--value-en <value> - English translation--value-es <value> - Spanish translation--value-fr <value> - French translation--value-de <value> - German translation--tags <tags> - Comma-separated tagsSupported language options:
You can use --value-{language} for any language code in your project.
Examples:
# Simple key with one language
langctl keys create my-app button.submit --value-en "Submit"
# Multi-language key
langctl keys create my-app home.title \
--module home \
--value-en "Home" \
--value-es "Inicio" \
--value-fr "Accueil"
# With description and tags
langctl keys create my-app error.network \
--description "Network connection error" \
--module errors \
--value-en "Network error occurred" \
--tags error,network
langctl keys delete <project> <key>Delete a translation key.
langctl keys delete my-app home.welcome
langctl keys translate <project> <key>Update the translation value for a specific language.
langctl keys translate my-app home.welcome \
--language es \
--value "¡Bienvenido!"
Options:
-l, --language <code> - Language code (required)-v, --value <text> - Translation value (required)Examples:
# Update Spanish translation
langctl keys translate my-app home.title -l es -v "Inicio"
# Update French translation
langctl keys translate my-app button.submit -l fr -v "Soumettre"
# Add translation for new language
langctl keys translate my-app home.welcome -l de -v "Willkommen"
langctl keys publish <project> <keys...>Publish or unpublish translation keys.
# Publish keys
langctl keys publish my-app home.welcome home.title button.submit
# Unpublish keys
langctl keys publish my-app home.welcome --unpublish
Options:
--unpublish - Unpublish instead of publishExamples:
# Publish single key
langctl keys publish my-app home.welcome
# Publish multiple keys
langctl keys publish my-app home.welcome home.title home.subtitle
# Unpublish keys
langctl keys publish my-app test.key --unpublish
langctl team listList all team members in your organization.
langctl team list
Output:
langctl team get <email>Get details about a specific team member.
langctl team get user@example.com
langctl team invite <email>Invite a new team member.
langctl team invite user@example.com --role member
Options:
-r, --role <role> - Member role (default: member)
viewer - Read-only accessmember - Can manage translationsadmin - Full project and team managementExamples:
# Invite as member (default)
langctl team invite user@example.com
# Invite as admin
langctl team invite admin@example.com --role admin
# Invite as viewer
langctl team invite viewer@example.com --role viewer
langctl team remove <email>Remove a team member from your organization.
langctl team remove user@example.com
Note: Cannot remove the organization owner. Cannot remove yourself (use appropriate UI for that).
langctl team update-role <email> <role>Update a team member's role.
langctl team update-role user@example.com admin
Valid roles: viewer, member, admin
Examples:
# Promote to admin
langctl team update-role user@example.com admin
# Demote to viewer
langctl team update-role user@example.com viewer
langctl team invitationsList all invitations (pending, accepted, or cancelled).
# List all invitations
langctl team invitations
# List only pending invitations
langctl team invitations --pending
Options:
-p, --pending - Show only pending invitationslangctl team revoke-invitation <email>Revoke a pending invitation.
langctl team revoke-invitation user@example.com
langctl export <project>Export translations in various formats.
langctl export my-app --language en --format flat-json
Options:
-l, --language <code> - Language to export (default: exports all languages)-f, --format <type> - Export format (default: flat-json)-o, --output <path> - Output file path (optional)-m, --module <name> - Export only specific module--include-unpublished - Include unpublished keys (default: published only)Supported formats:
flat-json - Flat key-value JSON (default)nested-json - Nested JSON structurei18n-json - i18next compatible formatandroid-xml - Android strings.xml formatios-strings - iOS Localizable.strings formatflutter-arb - Flutter ARB formatExamples:
# Export single language as JSON
langctl export my-app -l en -f flat-json
# Export all languages
langctl export my-app
# Export for iOS
langctl export my-app -l en -f ios-strings -o ./ios/en.lproj/Localizable.strings
# Export for Android
langctl export my-app -l es -f android-xml -o ./android/res/values-es/strings.xml
# Export for Flutter
langctl export my-app -l fr -f flutter-arb -o ./lib/l10n/app_fr.arb
# Export specific module
langctl export my-app -l en --module auth
# Include unpublished translations
langctl export my-app -l en --include-unpublished
langctl import <project> <file>Import translations from a JSON file.
langctl import my-app translations.json --language en
Options:
-l, --language <code> - Target language (required)--overwrite - Overwrite existing translations--publish - Auto-publish imported keysExamples:
# Import English translations
langctl import my-app en.json -l en
# Import and overwrite existing
langctl import my-app en.json -l en --overwrite
# Import and auto-publish
langctl import my-app en.json -l en --publish
# Import multiple languages
langctl import my-app en.json -l en --publish
langctl import my-app es.json -l es --publish
langctl import my-app fr.json -l fr --publish
Supported JSON formats:
// Flat format (recommended)
{
"home.welcome": "Welcome!",
"home.subtitle": "Get started",
"button.submit": "Submit"
}
// Nested format (auto-flattened)
{
"home": {
"welcome": "Welcome!",
"subtitle": "Get started"
},
"button": {
"submit": "Submit"
}
}
{
"home.welcome": "Welcome!",
"home.subtitle": "Get started with {{appName}}",
"button.submit": "Submit"
}
{
"home": {
"welcome": "Welcome!",
"subtitle": "Get started with {{appName}}"
},
"button": {
"submit": "Submit"
}
}
{
"home": {
"welcome": "Welcome!",
"subtitle": "Get started with {{appName}}"
}
}
/* Welcome message */
"home.welcome" = "Welcome!";
/* Homepage subtitle with app name placeholder */
"home.subtitle" = "Get started with %@";
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Welcome message -->
<string name="home.welcome">Welcome!</string>
<!-- Homepage subtitle with app name placeholder -->
<string name="home.subtitle">Get started with %1$s</string>
</resources>
{
"@@locale": "en",
"home.welcome": "Welcome!",
"@home.welcome": {
"description": "Welcome message"
},
"home.subtitle": "Get started with {appName}",
"@home.subtitle": {
"description": "Homepage subtitle",
"placeholders": {
"appName": {
"type": "String"
}
}
}
}
# 1. Authenticate
langctl auth lc_your_api_key_here
# 2. Create project
langctl projects create "Mobile App" \
-l en,es,fr,de \
--default-language en \
-d "iOS and Android application"
# 3. Add translation keys
langctl keys create mobile-app home.welcome \
--module home \
--value-en "Welcome!" \
--value-es "¡Bienvenido!" \
--value-fr "Bienvenue!"
langctl keys create mobile-app button.submit \
--module common \
--value-en "Submit" \
--value-es "Enviar" \
--value-fr "Soumettre"
# 4. Publish keys
langctl keys publish mobile-app home.welcome button.submit
# 5. Export for platforms
langctl export mobile-app -l en -f ios-strings -o ./ios/en.lproj/
langctl export mobile-app -l en -f android-xml -o ./android/res/values/
# 1. Prepare JSON files (en.json, es.json, fr.json)
# 2. Import all languages
langctl import my-app en.json -l en --publish
langctl import my-app es.json -l es --publish
langctl import my-app fr.json -l fr --publish
# 3. Verify imports
langctl keys list my-app --published
langctl projects stats my-app
# 1. Invite team members
langctl team invite developer@example.com --role member
langctl team invite manager@example.com --role admin
# 2. Check invitations
langctl team invitations --pending
# 3. Manage roles
langctl team update-role developer@example.com admin
# 4. View team
langctl team list
# Export for all platforms
PROJECT="my-app"
LANG="en"
# Web (i18next)
langctl export $PROJECT -l $LANG -f i18n-json -o ./src/locales/$LANG.json
# iOS
langctl export $PROJECT -l $LANG -f ios-strings -o ./ios/$LANG.lproj/Localizable.strings
# Android
langctl export $PROJECT -l $LANG -f android-xml -o ./android/res/values/strings.xml
# Flutter
langctl export $PROJECT -l $LANG -f flutter-arb -o ./lib/l10n/app_$LANG.arb
Automated translation sync workflow:
name: Sync Translations
on:
schedule:
- cron: '0 0 * * *' # Daily at midnight
workflow_dispatch: # Manual trigger
jobs:
sync-translations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install Langctl
run: npm install -g langctl
- name: Authenticate
env:
LANGCTL_API_KEY: ${{ secrets.LANGCTL_API_KEY }}
run: langctl auth $LANGCTL_API_KEY
- name: Export Translations
run: |
langctl export my-project -l en -f i18n-json -o ./locales/en.json
langctl export my-project -l es -f i18n-json -o ./locales/es.json
langctl export my-project -l fr -f i18n-json -o ./locales/fr.json
- name: Commit Changes
run: |
git config user.name "Langctl Bot"
git config user.email "bot@langctl.com"
git add locales/
git diff --staged --quiet || git commit -m "chore: update translations [skip ci]"
git push
sync-translations:
image: node:18
script:
- npm install -g langctl
- langctl auth $LANGCTL_API_KEY
- langctl export my-project -l en -f json -o ./locales/en.json
- langctl export my-project -l es -f json -o ./locales/es.json
- git config user.name "Langctl Bot"
- git config user.email "bot@langctl.com"
- git add locales/
- git diff --staged --quiet || git commit -m "chore: update translations"
- git push origin $CI_COMMIT_BRANCH
only:
- schedules
FROM node:18-alpine
RUN npm install -g langctl
WORKDIR /app
COPY . .
# Set API key via environment variable
ENV LANGCTL_API_KEY=""
# Example: Export translations on build
RUN langctl auth $LANGCTL_API_KEY && \
langctl export my-project -l en -f json -o ./public/locales/en.json
Use modules to organize keys by feature:
langctl keys create app auth.login.title --module auth
langctl keys create app home.hero.title --module home
langctl keys create app settings.profile.name --module settings
Follow naming conventions:
module.screen.element
auth.login.title
home.hero.subtitle
Add descriptions to keys:
langctl keys create app button.submit \
--description "Primary action button across the app" \
--value-en "Submit"
Create keys unpublished (draft mode)
Add translations for all languages
Review and test translations
Publish when ready:
langctl keys publish my-app key1 key2 key3
Export published translations only:
langctl export my-app -l en
Use appropriate roles:
viewer - Stakeholders, reviewers (read-only)member - Translators, content writersadmin - Project managers, team leadsRegular access reviews:
langctl team list
langctl team invitations
Never commit API keys to version control
Use environment variables:
export LANGCTL_API_KEY="lc_..."
langctl auth $LANGCTL_API_KEY
Rotate keys periodically from app.langctl.com
Use different keys for different environments:
"Not authenticated" error:
# Solution: Authenticate with your API key
langctl auth lc_your_api_key_here
"Invalid API key" error:
lc_, 67 characters total)"Project not found" error:
# Check project slug (not name)
langctl projects list
# Use the slug shown in the list
langctl keys list correct-slug-here
Cannot remove language:
langctl projects update my-app --default-language en
langctl projects remove-language my-app fr
Import fails with format error:
Export shows no keys:
langctl keys list my-app --published
langctl export my-app -l en --include-unpublished
If experiencing connectivity problems:
Q: What's the difference between slug and name?
A: The slug is the URL-friendly identifier (e.g., my-app), while the name is the display name (e.g., "My App"). Use slugs in CLI commands.
Q: Can I use the CLI without installing it?
A: Yes! Use npx langctl instead of langctl for any command.
Q: How do I get my project slug?
A: Run langctl projects list to see all project slugs.
Q: Can I export multiple languages at once?
A: Yes, run langctl export my-app without -l flag to export all languages.
Q: What happens to unpublished keys?
A: They're excluded from exports by default. Use --include-unpublished to include them.
Q: Can I undo a delete operation? A: Projects and keys use soft deletes. Contact support to recover deleted items.
Q: How do I change my default language?
A: Run: langctl projects update my-app --default-language <new-language>
Q: Can I use the CLI in CI/CD? A: Yes! Store your API key as a secret and use it in your workflow. See CI/CD Integration.
Tired of expensive translation management tools? Langctl offers:
See pricing and compare features →
We welcome contributions! This is an open-source project and we'd love your help making it better.
MIT License - see LICENSE file for details.
Copyright © 2026 Litcode Private Limited. All rights reserved.
Built with ❤️ by the Langctl team
Making translation management simple, fast, and developer-friendly.
FAQs
Translation management CLI for developers. Manage i18n translations, export to 6 formats (iOS, Android, Flutter, i18next), import translations, and collaborate with teams. Affordable alternative to Lokalise and Crowdin.
We found that langctl demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.