Your browser does not support the video tag.
  • Home
  • Blog
  • Talk

© 2026 YIKZERO

Lokalise MCP Automatic Translation Solution

Develop· 1 month ago
This article was translated from Chinese byGemini 3 Pro. If there are any discrepancies, please refer to the Chinese version.

Foreword

As the old saying goes, "laziness" is the primary driver of productivity.

The current i18n internationalization process is quite cumbersome: designs are made with English copy, and after the design is finalized, every word and sentence is translated into up to 20 languages on the Lokalise platform. Then, the Translation Keys are annotated back into Figma for developers to use.

This "Translate -> Annotate -> Code" workflow is extremely time-consuming in app requirement design. Faced with this high-frequency, repetitive, and inefficient labor, I combined our team's previous i18n practical experience to redesign an automated solution.

The multilingual platform we currently use is Lokalise, so the solution I'll be discussing will primarily revolve around Lokalise, though it can serve as a reference for other platforms as well.

Lokalise MCP Automated Translation Solution
Lokalise MCP Automated Translation Solution

Basic Idea

To achieve full automation, it's really a two-step process:

  1. Find an expert translator: AI translation is powerful, but it doesn't understand business-specific terminology (e.g., translating "Gas" as the chemical "gas"). It might also translate words that shouldn't be translated. Therefore, we need to inject business context and set rules for the AI.
  2. Give the AI "hands": After translating, you still have to copy and paste each entry into the Lokalise backend, which is the most tedious part. By using the MCP protocol, we can let the AI call the Lokalise API directly.

The Final Solution

The tech stack I chose is Node.js + MCP SDK + a client-side tool.

The choice of client is flexible, as long as it supports MCP. Initially, I used Claude Desktop, but for those who prefer the command line, it can easily be replaced with Claude Code or Gemini CLI. The experience is just as smooth.

Gemini might be better suited for humanities-related tasks like translation, so I'd recommend it.

1. Core Code (MCP Server)

Lokalise itself provides a comprehensive REST API, which makes it convenient for us to interact with it through code.

To write less boilerplate code, I directly used the official Node.js SDK (@lokalise/node-lokalise-api). Following MCP's official documentation, I wrapped these APIs into an MCP Server.

It mainly exposes two tools to the AI:

  • search-keys: Used to check for duplicates to see if someone has already translated it.
  • create-keys: Used to do the actual work, writing the AI-generated multilingual copy to the backend.
Calling the Lokalise MCP Server
Calling the Lokalise MCP Server

The logic isn't complicated; it's essentially acting as a middleman for the API:

Click to view the core code of index.ts
#!/usr/bin/env node
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { LokaliseApi, SupportedPlatforms } from "@lokalise/node-api";
import { z } from "zod";

const LOKALISE_API_KEY = process.env.LOKALISE_API_KEY;
const DEFAULT_PROJECT_ID = process.env.DEFAULT_PROJECT_ID;
const DEFAULT_PLATFORMS = ["web", "ios", "android", "other"];
const PLATFORMS = (
  process.env.PLATFORMS
    ? process.env.PLATFORMS.split(",").map((p) => p.trim())
    : DEFAULT_PLATFORMS
) as SupportedPlatforms[];

const lokaliseApi = new LokaliseApi({ apiKey: LOKALISE_API_KEY });

const server = new McpServer(
  {
    name: "lokalise-mcp",
    version: "1.0.0",
    author: "yikZero",
  },
  {
    capabilities: {
      tools: {},
    },
  }
);

// ... get-project-info and search-keys tool code omitted ...

server.registerTool(
  "create-keys",
  {
    title: "Create Keys",
    description: "Creates one or more keys in the project",
    inputSchema: {
      projectId: z
        .string()
        .describe(
          "A unique project identifier, if not provide, first use get-project-info tool to get the project id"
        ),
      keys: z.array(
        z.object({
          keyName: z.string().describe("Key identifier"),
          platforms: z
            .array(z.enum(["web", "ios", "android", "other"]))
            .describe(
              "Platforms for the key. If not provided, use the default platforms: " +
                PLATFORMS.join(", ")
            ),
          translations: z
            .array(
              z.object({
                languageIso: z
                  .string()
                  .describe(
                    "Unique code of the language of the translation, get the list from the get-project-info tool"
                  ),
                translation: z
                  .string()
                  .describe("The actual translation. Pass as an object"),
              })
            )
            .describe("Translations for all languages"),
        })
      ),
    },
  },
  async ({ projectId, keys }) => {
    const response = await lokaliseApi.keys().create(
      {
        keys: keys.map((key) => ({
          key_name: key.keyName,
          platforms: key.platforms,
          translations: key.translations.map((t) => ({
            language_iso: t.languageIso,
            translation: t.translation,
          })),
        })),
      },
      { project_id: projectId }
    );

    return {
      content: [
        {
          type: "text",
          text: JSON.stringify(response),
        },
      ],
      structuredContent: response as any,
    };
  }
);

// ... update-keys 工具代码略 ...

async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error("Lokalise MCP Server running on stdio");
}

main().catch((error) => {
  console.error("Fatal error in main():", error);
  process.exit(1);
});

2. Fine-tuning the AI (Prompt)

This is similar to the Project feature in the Claude web interface, where you can preset some system prompts and provide materials. This is all about giving the AI background knowledge to help it work better.

So, to make the AI work like a seasoned employee, I put all the OneKey glossaries and key naming conventions (Snake Case) into a GEMINI.md file. If you're using Claude Code, you can also create a CLAUDE.md.

There's now also a unified AGENTS.md, although it hasn't yet achieved total unification.

View GEMINI.md Prompt Details
You are a professional web3 project i18n translation expert specializing in translating word/sentence into multiple languages for software localization.

<onekey_background>
OneKey is a comprehensive cryptocurrency wallet solution...
</onekey_background>

<i18n_supported_languages>
English (United States), Bengali, Chinese Simplified...
</i18n_supported_languages>

<technical_terms>
OneKey, WalletConnect, iCloud, Google Drive, OneKey Lite, OneKey KeyTag, Face ID, Touch ID...
</technical_terms>

<translation_namespaces>
global, onboarding, wallet, swap, earn, market, browser, settings, prime
</translation_namespaces>

Translation Process:

1. Direct Translation:
   - Provide a literal translation of the word/sentence into all supported languages
   - If the text contains a number, replace it with {number}
   - Preserve all technical terms and variables, like {variableName}, HTML tags, etc

2. Refined Translation:
   - Create an optimized version that enhances clarity and natural flow in each language
   - Ensure cultural appropriateness while preserving the original meaning
   - When translating, take cultural factors into account and try to use expressions that fit the cultural habits of the target language, especially when dealing with metaphors, slang, or idioms
   - Preserve specific professional terminologies within certain industries or fields unchanged, unless there is a widely accepted equivalent expression in the target language
   - The title needs to be used Sentence case
   - A space (half-width space) between a full-width character (Kanji) and a half-width character (letter, number, or symbol)

3. Key Generation:
   - Create a self-explanatory key in snake_case format
   - Structure as namespace::descriptive_key_name
   - When recognized as a common term, please use global namespace
   - Key must accurately represent the content's purpose
   - Avoid hyphens (-) and curly braces ({})

Output Format:
1. Key: [namespace::descriptive_key_name]
2. Direct Translation Table (brief reference)
3. Refined Translation Table (primary focus)

Items need checked:
1. If the user provides the Key, use the user-provided Key.
2. If there is an obvious spelling error, I need your help to correct it and inform you.
3. After the translation is completed, need to call the tool to create/update the corresponding key.
4. First, provide the Table, then create or update the Key based on the translations in the Refined Table.

3. Configuration File

Finally, in the MCP configuration file (e.g., claude_desktop_config.json or .mcp.json), we mount the server we've written.

{
  "mcpServers": {
    "lokalise": {
      "command": "node",
      "args": ["/Users/yikzero/Code/lokalise-mcp/build/index.js"],
      "env": {
        "LOKALISE_API_KEY": "xxxx969xxxxxxxx7c18760c",
        "DEFAULT_PROJECT_ID": "44xxxxxe4ef8.8099xx5",
        "PLATFORMS": "ios,android,web,other"
      }
    }
  }
}

Practical Examples

Fully Automated Workflow from Design to Code

Let's take the "Network Detection Feature" we recently developed as an example. This is a relatively complex business scenario involving various network error status prompts. Each error message needs to be internationalized, totaling over 50 text strings to be translated. If handled manually, just the translation, key insertion, and copy alignment would likely take a full day.

Here's how I solved it:

  1. Claude Code to Organize Requirements: Have Claude analyze the code logic, identify all scenarios that need translation, and output a Markdown list.
  2. Gemini for Translation: Feed the Markdown list to Gemini 2.5 Pro (CLI) and have it translate based on our custom prompt. It will properly handle technical terms like "VPN" and "Proxy" according to the rules in <technical_terms> and automatically generate standardized keys (e.g., settings::network_error_timeout).
  3. Claude Code to Replace Code: After getting the translated copy with the keys, feed it back to Claude Code to replace the hardcoded strings in the code with a single command.

Claude excels at code analysis, Gemini excels at multilingual translation, and MCP bridges the data silos. With each performing its specific role, the efficiency boost is significant.

Daily Ad-Hoc Translations

For daily small tasks, using it with design mockups is also very effective.

For example, after I finish designing a new Onboarding pop-up in Figma, I can just take a screenshot, send it to the AI, and say:

"This is a new import wallet pop-up. Process the copy inside and place the keys under the onboarding namespace."

The AI will automatically execute: Visual Recognition (extracting copy) -> Dual Translation (literal + refined) -> Automatic Entry (writing to the database via MCP).

All you have to do is grab a coffee and wait to review the results.

Conclusion

Use Claude to write an MCP Server, then provide it for Gemini CLI to call, letting them do the work better. I'm not sure who the real capitalist is here (just kidding).

The related code mentioned in this article is open-source. Interested friends can check it out:

  • MCP Server: lokalise-mcp
  • Integration Configuration Example: onekey-translate
A 2025 Guide to New Internet Jobs