Claude-code-plugins-plus-skills lokalise-upgrade-migration

install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/lokalise-pack/skills/lokalise-upgrade-migration" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-skills-lokalise-upgrade-migration && rm -rf "$T"
manifest: plugins/saas-packs/lokalise-pack/skills/lokalise-upgrade-migration/SKILL.md
source content

Lokalise Upgrade Migration

Current State

!

npm list @lokalise/node-api 2>/dev/null | grep lokalise || echo 'SDK not installed'
!
lokalise2 --version 2>/dev/null || echo 'CLI not installed'
!
node --version 2>/dev/null || echo 'Node.js not available'
!
cat package.json 2>/dev/null | grep -E '"type"|"module"' || echo 'No package.json type field'

Overview

Upgrade the

@lokalise/node-api
SDK between major versions with full breaking change detection, automated code transformation, and verification. The most significant migration is v8 (CommonJS) to v9+ (ESM-only), which requires changes to imports, module configuration, and potentially your build pipeline.

Prerequisites

  • Existing project using
    @lokalise/node-api
    (any version 6.x through 9.x)
  • Node.js 18+ for SDK v9 (Node.js 14+ for v8 and below)
  • Git repository with clean working tree (for safe rollback)
  • Test suite that exercises Lokalise API calls

Instructions

Step 1: Assess Current Version and Target

set -euo pipefail
echo "=== Current SDK Version ==="
CURRENT=$(npm list @lokalise/node-api --json 2>/dev/null | node -e "
  const d = JSON.parse(require('fs').readFileSync(0,'utf8'));
  const v = d.dependencies?.['@lokalise/node-api']?.version || 'not found';
  console.log(v);
")
echo "Installed: ${CURRENT}"

echo -e "\n=== Latest Available ==="
LATEST=$(npm view @lokalise/node-api version)
echo "Latest: ${LATEST}"

echo -e "\n=== All Major Versions ==="
npm view @lokalise/node-api versions --json | node -e "
  const versions = JSON.parse(require('fs').readFileSync(0,'utf8'));
  const majors = {};
  versions.forEach(v => { const m = v.split('.')[0]; majors[m] = v; });
  Object.entries(majors).forEach(([m, v]) => console.log('  v' + m + '.x latest: ' + v));
"

Step 2: Review Breaking Changes by Version

VersionNode.jsModule SystemKey Breaking Changes
9.x18+ESM only
require()
removed,
import
only. Pagination returns typed cursors.
ApiError
export path changed.
8.x14+CJS + ESMLast version supporting
require()
. Constructor accepts
apiKey
(not
token
).
7.x14+CJSCursor pagination introduced.
list()
methods return paginated objects.
6.x12+CJSTypeScript rewrite. Method signatures changed from callbacks to promises.

Step 3: Migrate Imports (v8 CJS to v9 ESM)

This is the most impactful change. Every

require()
call must become an
import
.

Find all Lokalise imports in your codebase:

set -euo pipefail
grep -rn "require.*lokalise\|from.*lokalise" --include="*.ts" --include="*.js" --include="*.mjs" . || echo "No imports found"

Transform patterns:

// BEFORE (v8 CommonJS)
const { LokaliseApi } = require('@lokalise/node-api');
const lok = new LokaliseApi({ apiKey: process.env.LOKALISE_API_TOKEN });

// AFTER (v9 ESM)
import { LokaliseApi } from '@lokalise/node-api';
const lok = new LokaliseApi({ apiKey: process.env.LOKALISE_API_TOKEN });

Update

package.json
for ESM:

{
  "type": "module"
}

Update

tsconfig.json
if using TypeScript:

{
  "compilerOptions": {
    "module": "ES2022",
    "moduleResolution": "bundler",
    "target": "ES2022"
  }
}

Step 4: Update Pagination Code (v6/v7 to v9)

// BEFORE (v6 offset pagination)
const keys = await lok.keys().list({
  project_id: projectId,
  page: 2,
  limit: 100,
});

// AFTER (v9 cursor pagination — preferred for large datasets)
const keys = await lok.keys().list({
  project_id: projectId,
  limit: 500,
  pagination: 'cursor',
  cursor: previousCursor,
});
// Access next cursor: keys.nextCursor
// Check for more: keys.hasNextCursor()

Step 5: Update Error Handling

// BEFORE (v8)
const { ApiError } = require('@lokalise/node-api');
try {
  await lok.projects().get(projectId);
} catch (e) {
  if (e instanceof ApiError) {
    console.error(e.message, e.code);
  }
}

// AFTER (v9 — ApiError import path unchanged, but must use import)
import { ApiError } from '@lokalise/node-api';
try {
  await lok.projects().get(projectId);
} catch (e) {
  if (e instanceof ApiError) {
    console.error(e.message, e.code);
  }
}

Step 6: Install and Verify

set -euo pipefail
# Create a safety branch
git checkout -b upgrade/lokalise-sdk-v9

# Install the target version
npm install @lokalise/node-api@latest

# Run TypeScript compilation check
npx tsc --noEmit 2>&1 | head -40 || true

# Run tests
npm test

Step 7: Verify API Compatibility

// Quick smoke test after upgrade
import { LokaliseApi } from '@lokalise/node-api';

const lok = new LokaliseApi({ apiKey: process.env.LOKALISE_API_TOKEN! });

// Test basic operations still work
const projects = await lok.projects().list({ limit: 1 });
console.log('API connection OK:', projects.items[0]?.name ?? 'no projects');

const keys = await lok.keys().list({
  project_id: projects.items[0].project_id,
  limit: 5,
  pagination: 'cursor',
});
console.log('Cursor pagination OK:', keys.items.length, 'keys fetched');

Output

  • Updated
    @lokalise/node-api
    to target version
  • All
    require()
    calls converted to ESM
    import
    (if upgrading to v9)
  • package.json
    and
    tsconfig.json
    updated for ESM compatibility
  • Pagination code migrated to cursor-based pattern
  • Tests passing against the new SDK version
  • Git branch with all changes for review

Error Handling

IssueCauseSolution
ERR_REQUIRE_ESM
Using
require()
with v9 SDK
Convert to
import
syntax and set
"type": "module"
in package.json
SyntaxError: Cannot use import
Node.js file not recognized as ESMRename
.js
to
.mjs
or add
"type": "module"
TypeError: lok.keys is not a function
API changed between major versionsCheck SDK changelog for renamed methods
ERR_UNKNOWN_FILE_EXTENSION .ts
TypeScript not configured for ESMUse
tsx
runner or configure
ts-node
with
"esm": true
Tests fail after upgradeBreaking API changesCheck test against the version-specific migration notes above

Examples

Rollback Procedure

set -euo pipefail
# If the upgrade causes issues, revert immediately
git stash  # Save any work in progress
npm install @lokalise/node-api@8  # Last CJS version
git checkout HEAD -- tsconfig.json package.json
npm test
echo "Rolled back to v8. Investigate failures before retrying."

CLI Upgrade (Separate from SDK)

set -euo pipefail
# macOS
brew upgrade lokalise2

# Linux — download latest release binary
LATEST_CLI=$(curl -s https://api.github.com/repos/lokalise/lokalise-cli-2-go/releases/latest | grep -oP '"tag_name": "\K[^"]+')
curl -sL "https://github.com/lokalise/lokalise-cli-2-go/releases/download/${LATEST_CLI}/lokalise2_linux_x86_64.tar.gz" | tar xz
sudo mv lokalise2 /usr/local/bin/

# Verify
lokalise2 --version

Check for Deprecated API Usage

set -euo pipefail
# Patterns that indicate outdated SDK usage
echo "=== Deprecated Patterns ==="
grep -rn "\.page\s*:" --include="*.ts" --include="*.js" . && echo "^ Offset pagination — migrate to cursor" || echo "No offset pagination found"
grep -rn "require.*lokalise" --include="*.ts" --include="*.js" . && echo "^ CommonJS require — migrate to ESM import" || echo "No CJS requires found"
grep -rn "new LokaliseApi.*token:" --include="*.ts" --include="*.js" . && echo "^ Old constructor — use apiKey instead of token" || echo "No old constructor pattern found"

Resources

Next Steps

  • For CI pipeline changes needed after ESM migration, see
    lokalise-ci-integration
    .
  • For performance improvements with the new cursor pagination, see
    lokalise-performance-tuning
    .
  • Run
    lokalise-debug-bundle
    if the upgrade causes unexpected API errors.