Contents

ryu0118/xcstrings-crud

CLI tool and MCP server for CRUD operations on xcstrings (String Catalog) files.

Motivation

Large xcstrings files can contain thousands of localization keys across multiple languages, resulting in massive JSON files. When AI assistants (like Claude Code) read these files directly, they consume a significant amount of tokens—potentially exceeding context limits or rapidly depleting token budgets.

This tool provides a token-efficient approach by offering targeted CRUD operations:

  • Query only what you need: Fetch specific keys or languages instead of loading the entire file
  • Incremental updates: Add or update individual translations without reading the full content
  • Quick stats: Get coverage and progress summaries without parsing all entries
  • String Catalog semantics: Preserve Xcode metadata such as shouldTranslate, and exclude non-translatable keys from untranslated lists and coverage totals
  • String Catalog metadata: Preserve Xcode metadata such as autogenerated comments during read and write operations

By using the MCP server or CLI, AI assistants can work with xcstrings files of any size while keeping token usage minimal.

Installation

Using Mise

mise use -g ubi:Ryu0118/xcstrings-crud

Using nest (mtj0928/nest)

nest install Ryu0118/xcstrings-crud

Build from source

git clone https://github.com/Ryu0118/xcstrings-crud.git
cd xcstrings-crud
swift build -c release

Binary will be at .build/release/xcstrings-crud.

MCP Server

The MCP server is available as a subcommand:

xcstrings-crud mcp

Configuration

Add to your Claude Code MCP settings:

{
  "mcpServers": {
    "xcstrings-crud": {
      "command": "xcstrings-crud",
      "args": ["mcp"]
    }
  }
}

Available Tools

| Tool | Description | |------|-------------| | xcstrings_create_file | Create a new xcstrings file | | xcstrings_list_keys | List all keys | | xcstrings_list_languages | List supported languages | | xcstrings_list_untranslated | List untranslated keys | | xcstrings_list_stale | List keys with stale extraction state | | xcstrings_batch_list_stale | List stale keys across multiple files | | xcstrings_get_source_language | Get source language | | xcstrings_get_key | Get translations for a key | | xcstrings_check_key | Check if key exists; suggests NFKC-equivalent keys when not found | | xcstrings_check_coverage | Check key language coverage | | xcstrings_stats_coverage | Get overall coverage statistics | | xcstrings_stats_progress | Get translation progress by language | | xcstrings_batch_stats_coverage | Get coverage for multiple files at once | | xcstrings_batch_check_keys | Check if multiple keys exist | | xcstrings_batch_add_translations | Add translations for multiple keys at once | | xcstrings_batch_update_translations | Update translations for multiple keys at once | | xcstrings_add_translation | Add translation for single language | | xcstrings_add_translations | Add translations for multiple languages | | xcstrings_update_translation | Update translation for single language | | xcstrings_update_translations | Update translations for multiple languages | | xcstrings_rename_key | Rename key | | xcstrings_delete_key | Delete entire key | | xcstrings_delete_translation | Delete translation for single language | | xcstrings_delete_translations | Delete translations for multiple languages |

CLI Usage

Create Operations

# Create a new xcstrings file
xcstrings-crud create path/to/Localizable.xcstrings

# Create with specific source language
xcstrings-crud create path/to/Localizable.xcstrings --source-language ja

# Overwrite existing file
xcstrings-crud create path/to/Localizable.xcstrings --overwrite

Read Operations

# List all keys
xcstrings-crud list keys --file path/to/Localizable.xcstrings

# List languages
xcstrings-crud list languages --file path/to/Localizable.xcstrings

# List untranslated keys for a language
xcstrings-crud list untranslated --file path/to/Localizable.xcstrings --lang ja
# Keys marked `"shouldTranslate": false` are omitted from untranslated results.

# List stale keys (potentially unused)
xcstrings-crud list stale --file path/to/Localizable.xcstrings

# List stale keys across multiple files
xcstrings-crud batch stale -f file1.xcstrings file2.xcstrings file3.xcstrings

# Get source language
xcstrings-crud get source-language --file path/to/Localizable.xcstrings

# Get translations for a key
xcstrings-crud get key "Hello" --file path/to/Localizable.xcstrings
xcstrings-crud get key "Hello" --file path/to/Localizable.xcstrings --lang ja

# Check if key exists
xcstrings-crud check key "Hello" --file path/to/Localizable.xcstrings

# Check key coverage
xcstrings-crud check coverage "Hello" --file path/to/Localizable.xcstrings
# Non-translatable keys are treated as complete.

# Check untranslated entries across specific files and languages
xcstrings-crud check untranslated \
  --files App/Localizable.xcstrings Package/Localizable.xcstrings \
  --languages ja de fr
# Emits JSON and exits with status 1 when untranslated entries are found.
# Keys marked `"shouldTranslate": false` are omitted from untranslated results.

# Emit hook-compatible blocking JSON instead of failing the command.
xcstrings-crud check untranslated \
  --files App/Localizable.xcstrings \
  --languages ja \
  --codex-hook
xcstrings-crud check untranslated \
  --files App/Localizable.xcstrings \
  --languages ja \
  --claude-hook

# Get overall statistics
xcstrings-crud stats coverage --file path/to/Localizable.xcstrings
# Coverage totals exclude keys marked `"shouldTranslate": false`.

# Get progress for a language
xcstrings-crud stats progress --file path/to/Localizable.xcstrings --lang ja

# Get batch coverage for multiple files
xcstrings-crud stats batch-coverage -f file1.xcstrings file2.xcstrings file3.xcstrings

Update Operations

# Add translation (single language)
xcstrings-crud add key "Hello" --file path/to/Localizable.xcstrings --lang ja --value "こんにちは"

# Add translation (multiple languages)
xcstrings-crud add key "Hello" --file path/to/Localizable.xcstrings -t ja:こんにちは en:Hello

# Update translation (single language)
xcstrings-crud update key "Hello" --file path/to/Localizable.xcstrings --lang ja --value "こんにちは!"

# Update translations (multiple languages)
xcstrings-crud update key "Hello" --file path/to/Localizable.xcstrings -t ja:こんにちは en:Hello de:Hallo

# Rename key
xcstrings-crud rename key "Hello" --file path/to/Localizable.xcstrings --to "Greeting"

Delete Operations

# Delete entire key
xcstrings-crud delete key "Hello" --file path/to/Localizable.xcstrings

# Delete translation for specific language only
xcstrings-crud delete key "Hello" --file path/to/Localizable.xcstrings -l ja

# Delete translations for multiple languages
xcstrings-crud delete key "Hello" --file path/to/Localizable.xcstrings -l ja en fr

Batch Operations

# List stale keys across multiple files
xcstrings-crud batch stale -f file1.xcstrings file2.xcstrings file3.xcstrings

# Check if multiple keys exist
xcstrings-crud batch check --file path/to/Localizable.xcstrings -k Hello Goodbye Welcome

# Check with specific language
xcstrings-crud batch check --file path/to/Localizable.xcstrings -k Hello Goodbye -l ja

# Add translations for multiple keys at once
xcstrings-crud batch add --file path/to/Localizable.xcstrings \
  -e "Hello=ja:こんにちは,en:Hello" \
  -e "Goodbye=ja:さようなら,en:Goodbye"

# Add with overwrite (replace existing translations)
xcstrings-crud batch add --file path/to/Localizable.xcstrings --overwrite \
  -e "Hello=ja:こんにちは,en:Hello"

# Update translations for multiple keys at once
xcstrings-crud batch update --file path/to/Localizable.xcstrings \
  -e "Hello=ja:こんにちは!,en:Hello!" \
  -e "Goodbye=ja:さようなら!"

Common Options

  • --file <path>: xcstrings file path (required)
  • --pretty: Pretty-printed JSON output

For check untranslated, --files <paths...> and --languages <codes...> are required. --codex-hook and --claude-hook are mutually exclusive and intended for CLI hook integrations only.

Requirements

  • macOS 13+
  • Swift 6.0+

License

MIT

Package Metadata

Repository: ryu0118/xcstrings-crud

Default branch: main

README: README.md