๐Ÿ“… let's chat! explore the endless possibilities creating industries that don't exist. click here

lokalise-cost-tuning

Optimize Lokalise costs through plan selection, usage monitoring, and efficiency. Use when analyzing Lokalise billing, reducing costs, or implementing usage monitoring and budget alerts. Trigger with phrases like "lokalise cost", "lokalise billing", "reduce lokalise costs", "lokalise pricing", "lokalise budget". allowed-tools: Read, Grep version: 1.0.0 license: MIT author: Jeremy Longshore <jeremy@intentsolutions.io>

Allowed Tools

No tools specified

Provided by Plugin

lokalise-pack

Claude Code skill pack for Lokalise (24 skills)

saas packs v1.0.0
View Plugin

Installation

This skill is included in the lokalise-pack plugin:

/plugin install lokalise-pack@claude-code-plugins-plus

Click to copy

Instructions

# Lokalise Cost Tuning ## Overview Optimize Lokalise costs through smart plan selection, usage monitoring, and efficient workflows. ## Prerequisites - Access to Lokalise billing dashboard - Understanding of current usage patterns - Database for usage tracking (optional) - Alerting system configured (optional) ## Lokalise Pricing Overview ### Plans (2025) | Plan | Price | Included | Best For | |------|-------|----------|----------| | Free | $0 | 1 project, 500 keys | Personal/testing | | Essential | $120/mo | Unlimited projects, 2K keys/project | Small teams | | Pro | $400/mo | Unlimited keys, OTA, Figma | Growing teams | | Enterprise | Custom | SSO, dedicated support, SLA | Large organizations | ### Key Cost Factors - Number of translation keys - Number of target languages - Machine translation usage - Professional translation orders - OTA bandwidth (mobile apps) ## Instructions ### Step 1: Analyze Current Usage ```typescript import { LokaliseApi } from "@lokalise/node-api"; async function analyzeUsage(): Promise { const client = new LokaliseApi({ apiKey: process.env.LOKALISE_API_TOKEN!, }); const projects = await client.projects().list(); const usage: UsageReport = { totalProjects: projects.items.length, totalKeys: 0, totalLanguages: 0, projectDetails: [], }; for (const project of projects.items) { const stats = project.statistics; usage.totalKeys += stats.keys_total; usage.totalLanguages += stats.languages; usage.projectDetails.push({ name: project.name, projectId: project.project_id, keys: stats.keys_total, languages: stats.languages, baseWords: stats.base_words, progress: stats.progress_total, }); } return usage; } interface UsageReport { totalProjects: number; totalKeys: number; totalLanguages: number; projectDetails: Array<{ name: string; projectId: string; keys: number; languages: number; baseWords: number; progress: number; }>; } ``` ### Step 2: Identify Cost Optimization Opportunities ```typescript function analyzeOptimizations(usage: UsageReport): Recommendation[] { const recommendations: Recommendation[] = []; // Check for unused projects for (const project of usage.projectDetails) { if (project.keys < 10) { recommendations.push({ type: "unused_project", severity: "low", message: `Project "${project.name}" has only ${project.keys} keys. Consider archiving.`, potentialSavings: "Reduce clutter, potential plan downgrade", }); } // Check for duplicate/similar keys if (project.keys > 1000) { recommendations.push({ type: "key_audit", severity: "medium", message: `Project "${project.name}" has ${project.keys} keys. Review for duplicates.`, potentialSavings: "5-15% key reduction typical", }); } // Check for low-progress languages if (project.progress < 50 && project.languages > 3) { recommendations.push({ type: "unused_languages", severity: "medium", message: `Project "${project.name}" has ${project.languages} languages at ${project.progress}% progress.`, potentialSavings: "Remove unused target languages", }); } } // Plan recommendation if (usage.totalKeys < 2000 && usage.totalProjects <= 3) { recommendations.push({ type: "plan_downgrade", severity: "high", message: "Current usage fits Essential plan", potentialSavings: "Potential $280/mo savings vs Pro", }); } return recommendations; } ``` ### Step 3: Implement Usage Monitoring ```typescript interface UsageMetrics { date: Date; keysCreated: number; keysDeleted: number; translationsUpdated: number; mtCharacters: number; // Machine translation apiCalls: number; } class LokaliseUsageMonitor { private metrics: UsageMetrics[] = []; trackApiCall(operation: string, details?: any) { // Track API usage console.log({ timestamp: new Date().toISOString(), operation, details, }); } async getMonthlyReport(): Promise { const client = new LokaliseApi({ apiKey: process.env.LOKALISE_API_TOKEN!, }); const projects = await client.projects().list(); let totalKeys = 0; let totalMTCharacters = 0; for (const project of projects.items) { totalKeys += project.statistics.keys_total; // Note: MT usage requires checking orders/billing API } return { month: new Date().toISOString().slice(0, 7), totalKeys, estimatedCost: this.estimateCost(totalKeys), }; } private estimateCost(keys: number): number { // Simplified estimation based on plan tiers if (keys <= 500) return 0; // Free tier if (keys <= 2000) return 120; // Essential return 400; // Pro } } ``` ### Step 4: Clean Up Unused Resources ```typescript async function cleanupUnusedKeys(projectId: string, dryRun = true) { const client = new LokaliseApi({ apiKey: process.env.LOKALISE_API_TOKEN!, }); // Find archived keys const archivedKeys = await client.keys().list({ project_id: projectId, filter_archived: "include", limit: 500, }); const toDelete = archivedKeys.items.filter(k => k.is_archived); console.log(`Found ${toDelete.length} archived keys`); if (dryRun) { console.log("DRY RUN - would delete:", toDelete.map(k => k.key_name.web)); return { deleted: 0, archived: toDelete.length }; } // Actually delete for (const key of toDelete) { await client.keys().delete(key.key_id, { project_id: projectId }); } return { deleted: toDelete.length }; } async function removeUnusedLanguages(projectId: string, threshold = 10) { const client = new LokaliseApi({ apiKey: process.env.LOKALISE_API_TOKEN!, }); const languages = await client.languages().list({ project_id: projectId }); const unused = languages.items.filter( lang => (lang.statistics?.progress ?? 0) < threshold && !lang.is_default ); console.log(`Languages below ${threshold}% progress:`, unused.map(l => `${l.lang_name} (${l.statistics?.progress}%)`)); // Don't auto-delete - just report return unused; } ``` ## Output - Usage analysis complete - Cost optimization recommendations - Usage monitoring implemented - Cleanup scripts for unused resources ## Error Handling | Issue | Cause | Solution | |-------|-------|----------| | Unexpected charges | Untracked MT usage | Monitor orders API | | Key limit exceeded | Organic growth | Archive or delete unused | | Overage fees | Wrong plan | Upgrade before hitting limits | | Budget exceeded | No monitoring | Set up usage alerts | ## Examples ### Quick Usage Check ```typescript const report = await analyzeUsage(); console.log(`Total Projects: ${report.totalProjects}`); console.log(`Total Keys: ${report.totalKeys}`); console.log(`Estimated Plan: ${report.totalKeys < 500 ? 'Free' : report.totalKeys < 2000 ? 'Essential' : 'Pro'}`); ``` ### Machine Translation Cost Estimate ```typescript // Lokalise MT pricing varies by provider and language pair function estimateMTCost( characters: number, provider: "google" | "deepl" | "amazon" = "google" ): number { const rates: Record = { google: 0.02, // $20 per million characters deepl: 0.025, // $25 per million characters amazon: 0.015, // $15 per million characters }; return (characters / 1_000_000) * rates[provider]; } ``` ### Budget Alert Script ```typescript async function checkBudget(budgetKeys: number): Promise { const usage = await analyzeUsage(); if (usage.totalKeys > budgetKeys * 0.9) { console.warn(`WARNING: Approaching key limit (${usage.totalKeys}/${budgetKeys})`); // Send alert await sendSlackAlert({ channel: "#billing", text: `Lokalise key usage at ${Math.round((usage.totalKeys / budgetKeys) * 100)}%`, }); return false; } return true; } ``` ### Cost Comparison Report ```markdown ## Lokalise Cost Analysis ### Current Usage - Projects: 5 - Total Keys: 3,500 - Languages: 8 ### Current Plan: Pro ($400/mo) ### Recommendations 1. Archive 2 unused projects (-500 keys) 2. Remove 3 low-progress languages 3. Delete 200 archived keys 4. **Potential: Essential plan at $120/mo** ### Annual Savings: $3,360 ``` ## Resources - [Lokalise Pricing](https://lokalise.com/pricing) - [Lokalise Billing FAQ](https://docs.lokalise.com/en/articles/1400477-billing) ## Next Steps For architecture patterns, see `lokalise-reference-architecture`.

Skill file: plugins/saas-packs/lokalise-pack/skills/lokalise-cost-tuning/SKILL.md