Get Started

Import Translations

Quickly migrate existing translations into LangCTL by importing files from popular formats. The import system handles conflict resolution and validates your data.

Supported Import Formats

LangCTL can import from:

  • JSON (flat or nested)
  • i18next JSON files
  • Android XML strings
  • iOS Strings files
  • Flutter ARB files
  • CSV (key, language, value columns)

[IMAGE: import-supported-formats.png - Visual showing all supported import formats]

Quick Import

From Dashboard

  1. Navigate to Import section
  2. Select target project
  3. Choose language
  4. Click “Upload File” or drag-and-drop
  5. Review detected format and key count
  6. Configure import options
  7. Click “Import”

[IMAGE: import-interface.png - Screenshot of import upload interface]

Import Options

Conflict Resolution

Choose how to handle existing keys:

Update Existing (recommended):

  • Updates values for existing keys
  • Creates new keys that don’t exist
  • Preserves other language translations
  • Updates updated_at timestamp

Skip Existing:

  • Only imports new keys
  • Leaves existing keys unchanged
  • Useful for adding new translations without overwriting

Replace All:

  • Deletes all existing keys
  • Imports everything from file
  • ⚠️ Destructive - use with caution
⚠️
Warning

“Replace All” will permanently delete existing keys not in the import file. Always backup before using this option.

Module Assignment

Assign imported keys to a module:

  • Auto-detect: Extract module from key names (e.g., auth.login.title -> auth)
  • Assign All: Put all imported keys in one module
  • No Module: Import without module assignment
auth.login.title -> module: "auth"
auth.signup.button -> module: "auth"
dashboard.welcome.message -> module: "dashboard"

auth.login.title -> module: "imported"
dashboard.welcome.message -> module: "imported"

Choose initial status for imported keys:

  • Draft: Import as unpublished (recommended for review)
  • Published: Mark as ready for export immediately
💡
Tip

Import as draft first to review imported content before publishing. This prevents accidental deployment of incorrect translations.

en.json (flat format)
{
"home.welcome": "Welcome!",
"home.subtitle": "Get started here",
"auth.login.title": "Sign In",
"auth.login.button": "Log in"
}

Keys are used exactly as written. Perfect for migrating from existing systems.

en.json (nested format)
{
"home": {
  "welcome": "Welcome!",
  "subtitle": "Get started here"
},
"auth": {
  "login": {
    "title": "Sign In",
    "button": "Log in"
  }
}
}

LangCTL automatically flattens nested structures:

  • home.welcome -> “Welcome!”
  • auth.login.title -> “Sign In”
strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="auth_login_title">Sign In</string>
<string name="home_welcome">Welcome</string>
</resources>

Import behavior:

  • Converts name to key (underscores to dots)
  • home_welcome -> home.welcome
  • Converts %1$s parameters to &#123;&#123;param1&#125;&#125;
  • Preserves XML entities
ℹ️
Note

Positional parameters (%1$s, %2$d) are converted to generic &#123;&#123;param1&#125;&#125;, &#123;&#123;param2&#125;&#125; format. You may want to rename them after import.

Localizable.strings
/* Welcome message */
"home.welcome" = "Welcome!";

/* Login screen */
"auth.login.title" = "Sign In";
"auth.login.button" = "Log in";

/* With parameters */
"notification.count" = "You have %1$@ messages";

Import behavior:

  • Uses quoted keys as-is
  • Converts %@ to &#123;&#123;param&#125;&#125;
  • Preserves comments as descriptions
  • Handles escaped quotes
app_en.arb
{
"home_welcome": "Welcome!",
"@home_welcome": {
  "description": "Main welcome message"
},
"notification_count": "You have {count} messages",
"@notification_count": {
  "description": "Shows message count",
  "placeholders": {
    "count": {
      "type": "int"
    }
  }
}
}

Import behavior:

  • Converts underscores to dots: home_welcome -> home.welcome
  • Imports @key descriptions
  • Preserves &#123;param&#125; syntax
  • Reads placeholder metadata
translations.csv
key,en,es,fr
home.welcome,"Welcome!","¡Bienvenido!","Bienvenue!"
home.subtitle,"Get started","Comienza aquí","Commencer"
auth.login.title,"Sign In","Iniciar sesión","Se connecter"

CSV Requirements:

  • First row: headers (key + language codes)
  • One key per row
  • Quoted values for strings with commas
  • UTF-8 encoding

Import behavior:

  • Creates one key per row
  • Imports all languages at once
  • Empty cells = no translation for that language
💡
Tip

CSV import is great for bulk updates across multiple languages. Export to CSV, edit in Excel/Sheets, then re-import.

Drag-and-drop or browse for file:

  • Maximum file size: 10 MB
  • Supports .json, .xml, .strings, .arb, .csv
  • Validates format automatically

[IMAGE: import-upload.png - Screenshot of file upload interface with drag-and-drop area]

LangCTL analyzes your file:

File: en.json (45 KB)
Format: JSON (nested)
Keys Detected: 237
Language: en (English)
Module Structure: Auto-detected (5 modules)

Detected Modules:
- auth (42 keys)
- dashboard (85 keys)
- settings (34 keys)
- profile (28 keys)
- common (48 keys)

Verify detection is correct before proceeding.

Step 3: Configure Options

Set import preferences:

  • ✓ Update existing keys
  • ☐ Skip existing keys
  • ☐ Replace all keys
  • ✓ Auto-detect modules
  • ☐ Import as published

Step 4: Confirm Import

Review summary before importing:

Ready to Import

Will create: 45 new keys
Will update: 192 existing keys
Will skip: 0 keys
Total operations: 237

Estimated time: ~15 seconds

Step 5: Monitor Progress

Watch real-time progress:

Importing... 156/237 complete (66%)

✓ Created 32 keys
✓ Updated 124 keys
⏳ Processing...

[IMAGE: import-progress.png - Screenshot of import progress indicator]

Step 6: Review Results

Check import summary:

Import Complete ✓

Created: 45 keys
Updated: 192 keys
Skipped: 0 keys
Errors: 0

Total: 237 translations imported
Duration: 12 seconds

Next steps:
- Review imported translations
- Check module assignments
- Publish when ready

Import several language files at once:

  1. Click “Batch Import”
  2. Upload multiple files
  3. Assign language to each file
  4. Configure shared options
  5. Import all simultaneously

[IMAGE: batch-import.png - Screenshot of batch import interface]

Import all languages from one CSV:

key,en,es,fr,de
home.welcome,"Welcome","Bienvenido","Bienvenue","Willkommen"
auth.login.title,"Sign In","Iniciar sesión","Se connecter","Anmelden"

One CSV import creates translations for all included languages.

LangCTL converts platform-specific parameters to universal &#123;&#123;param&#125;&#125; format:

Source FormatSource SyntaxConverted To
Android XML%1$s, %2$d&#123;&#123;param1&#125;&#125;, &#123;&#123;param2&#125;&#125;
iOS Strings%@, %1$@&#123;&#123;param&#125;&#125;, &#123;&#123;param1&#125;&#125;
Flutter ARB&#123;count&#125;&#123;&#123;count&#125;&#125;
i18next&#123;&#123;username&#125;&#125;&#123;&#123;username&#125;&#125; (preserved)

Generic names like &#123;&#123;param1&#125;&#125; should be renamed:

Before: "Welcome, {{param1}}!"
After:  "Welcome, {{username}}!"

Use bulk edit to rename parameters across keys.

“Invalid JSON format”:

  • Check for syntax errors (missing commas, brackets)
  • Validate with jsonlint.com
  • Ensure UTF-8 encoding

“Duplicate keys found”:

  • Same key appears multiple times in file
  • Choose which value to use
  • Clean up duplicates before importing

“Invalid character in key name”:

  • Keys must be alphanumeric + dots/underscores
  • Remove special characters
  • Replace spaces with underscores

“Language not configured”:

  • Add target language to project first
  • Check language code is correct (use ISO 639-1)

During import, LangCTL validates:

  • ✓ Key names are valid
  • ✓ Values are strings (not numbers/booleans)
  • ✓ Parameters are properly formatted
  • ✓ Language codes are valid
  • ✓ File structure is correct

Failed validations are shown before import starts.

After import:

  1. Filter by “Recently Added”
  2. Check module assignments
  3. Verify parameter syntax
  4. Review translations for accuracy
  5. Test export in target format

Search for generic parameter names:

  • &#123;&#123;param1&#125;&#125;, &#123;&#123;param2&#125;&#125; (from Android)
  • &#123;&#123;param&#125;&#125; (from iOS)

Rename to descriptive names like &#123;&#123;username&#125;&#125;, &#123;&#123;count&#125;&#125;.

Once verified:

  1. Select imported keys
  2. Bulk publish
  3. Export to test in your app
  4. Deploy when ready

Backup your project:

  • Export current translations
  • Save export files
  • Store in version control

Clean your source files:

  • Remove test/debug keys
  • Fix formatting issues
  • Validate JSON/XML syntax

Plan module structure:

  • Decide on module naming
  • Use consistent prefixes in keys
  • Enable auto-detect for structured keys

Start small:

  • Import a subset first (10-20 keys)
  • Verify results
  • Then import full file

Use draft mode:

  • Import as drafts initially
  • Review before publishing
  • Easier to fix issues

Check module detection:

  • Verify auto-detected modules
  • Adjust if structure isn’t ideal
  • Consider manual module assignment

Review thoroughly:

  • Check for missing translations
  • Verify parameter syntax
  • Test special characters
  • Validate in actual app

Document changes:

  • Note what was imported
  • Document any manual fixes
  • Update team on new keys
langctl import my-project -l en -f json ./lokalise/en.json --update
langctl import my-project -l es -f json ./lokalise/es.json --update

From Phrase

Export as JSON or CSV from Phrase, then import to LangCTL using the same process.

From Custom System

If you have a custom format:

  1. Export to flat JSON or CSV
  2. Transform to LangCTL format
  3. Import using standard JSON import

Troubleshooting

Import Stuck at 0%

  • Check file size (max 10 MB)
  • Verify file format is supported
  • Try smaller batch
  • Check network connection

Some Keys Not Imported

  • Check validation errors log
  • Look for duplicate keys
  • Verify key name format
  • Check for empty values

Parameters Look Wrong

  • Review parameter conversion rules
  • Manually fix generic names
  • Use search/replace for bulk fixes

Module Assignment Incorrect

  • Disable auto-detect
  • Manually assign module
  • Or bulk edit after import

Next Steps