| name | lokalise-core-workflow-a |
| description | Execute Lokalise primary workflow: Upload source files and manage translation keys.
Use when uploading translation files, creating/updating keys,
or managing source strings in Lokalise projects.
Trigger with phrases like "lokalise upload", "lokalise push keys",
"lokalise source strings", "add translations to lokalise".
|
| allowed-tools | Read, Write, Edit, Bash(lokalise2:*), Bash(npm:*), Grep |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
Lokalise Core Workflow A: Upload & Key Management
Overview
Primary workflow for uploading source translation files and managing keys in Lokalise.
Prerequisites
- Completed
lokalise-install-auth setup
- Lokalise project created
- Source translation file (JSON, XLIFF, PO, etc.)
Instructions
Step 1: Upload Source File via CLI
lokalise2 \
--token "$LOKALISE_API_TOKEN" \
--project-id "$LOKALISE_PROJECT_ID" \
file upload \
--file "./locales/en.json" \
--lang-iso en \
--replace-modified \
--distinguish-by-file \
--poll \
--poll-timeout 120s
lokalise2 \
--token "$LOKALISE_API_TOKEN" \
--project-id "$LOKALISE_PROJECT_ID" \
file upload \
--file "./locales/en.json" \
--lang-iso en \
--tags "web,v2.0" \
--tag-inserted-keys \
--tag-updated-keys \
--poll
Step 2: Upload via SDK (Async Process)
import { LokaliseApi } from "@lokalise/node-api";
import fs from "fs";
import path from "path";
const lokaliseApi = new LokaliseApi({
apiKey: process.env.LOKALISE_API_TOKEN!,
});
async function uploadFile(projectId: string, filePath: string, langIso: string) {
const fileContent = fs.readFileSync(filePath);
const base64Content = fileContent.toString("base64");
const fileName = path.basename(filePath);
const process = await lokaliseApi.files().upload(projectId, {
data: base64Content,
filename: fileName,
lang_iso: langIso,
replace_modified: true,
convert_placeholders: true,
detect_icu_plurals: true,
tags: ["uploaded-via-sdk"],
});
.();
(projectId, process.);
}
() {
maxAttempts = ;
delayMs = ;
( i = ; i < maxAttempts; i++) {
status = lokaliseApi.().(processId, {
: projectId,
});
.();
(status. === ) {
.();
status;
}
(status. === || status. === ) {
();
}
( (r, delayMs));
}
();
}
Step 3: Create Keys Programmatically
async function createKeys(projectId: string) {
const keys = await lokaliseApi.keys().create({
project_id: projectId,
keys: [
{
key_name: "common.buttons.submit",
description: "Submit button text",
platforms: ["web", "ios", "android"],
tags: ["buttons", "common"],
translations: [
{ language_iso: "en", translation: "Submit" },
{ language_iso: "es", translation: "Enviar" },
],
},
{
key_name: "common.buttons.cancel",
description: "Cancel button text",
platforms: ["web", "ios", "android"],
tags: ["buttons", "common"],
translations: [
{ language_iso: "en", translation: "Cancel" },
],
},
{
key_name: "errors.network",
description: ,
: [],
: ,
: [],
: [
{ : , : },
],
},
],
});
.();
keys;
}
Step 4: Update Existing Keys
async function updateKey(projectId: string, keyId: number) {
const updated = await lokaliseApi.keys().update(keyId, {
project_id: projectId,
description: "Updated description",
tags: ["updated", "v2"],
is_archived: false,
});
console.log(`Updated key: ${updated.key_name.web}`);
return updated;
}
async function bulkUpdateKeys(projectId: string, keyIds: number[], updates: object) {
const result = await lokaliseApi.keys().bulk_update({
project_id: projectId,
keys: keyIds.map(id => ({
key_id: id,
...updates,
})),
});
console.log(`Updated ${result.items.length} keys`);
return result;
}
Step 5: Manage Key Tags
async function tagKeys(projectId: string, keyIds: number[], tags: string[]) {
const result = await lokaliseApi.keys().bulk_update({
project_id: projectId,
keys: keyIds.map(id => ({
key_id: id,
tags,
})),
});
return result;
}
async function getKeysByTag(projectId: string, tag: string) {
const keys = await lokaliseApi.keys().list({
project_id: projectId,
filter_tags: tag,
limit: 500,
});
return keys.items;
}
Output
- Source file uploaded to Lokalise
- Keys created with translations
- Keys tagged for organization
- Bulk operations completed
Error Handling
| Error | Cause | Solution |
|---|
400 Invalid file format | Unsupported format | Check supported formats |
400 Key already exists | Duplicate key name | Use replace_modified or unique names |
413 Payload too large | File too big | Split into smaller files |
429 Rate limited | Too many requests | Use --poll flag, wait between uploads |
Examples
Supported File Formats
const supportedFormats = [
"json",
"xliff",
"po",
"strings",
"xml",
"properties",
"yaml",
"csv",
"xlsx",
"resx",
"arb",
];
Upload with Cleanup Options
lokalise2 file upload \
--token "$LOKALISE_API_TOKEN" \
--project-id "$LOKALISE_PROJECT_ID" \
--file "./locales/en.json" \
--lang-iso en \
--cleanup-mode
--replace-modified
--fill-empty
--poll
Batch File Upload
async function uploadAllLocales(projectId: string, localesDir: string) {
const files = fs.readdirSync(localesDir)
.filter(f => f.endsWith(".json"));
for (const file of files) {
const langIso = path.basename(file, ".json");
const filePath = path.join(localesDir, file);
console.log(`Uploading ${file}...`);
await uploadFile(projectId, filePath, langIso);
await new Promise(r => setTimeout(r, 200));
}
}
Resources
Next Steps
For downloading translations, see lokalise-core-workflow-b.