translate_key_tool
Translate a specific key in iOS/macOS Localizable.xcstrings files to multiple target languages using Xcode String Catalogs for localization management.
Instructions
MCP tool to translate a specific key to multiple target languages and apply translations.
Args:
file_path (str): Path to the .xcstrings file
key (str): The specific key to translate
target_languages (str): Comma-separated list of target language codes (e.g., "es,fr,de")
app_description (str): Optional description of the app for better translation context
Returns:
str: Translation results or error message
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| app_description | No | ||
| file_path | Yes | ||
| key | Yes | ||
| target_languages | Yes |
Implementation Reference
- Handler function for 'translate_key_tool' decorated with @mcp.tool() for MCP registration. Validates inputs, parses languages, delegates to translate_single_key helper, handles errors, and returns formatted results.def translate_key_tool(file_path: str, key: str, target_languages: str, app_description: str = "") -> str: """ MCP tool to translate a specific key to multiple target languages and apply translations. Args: file_path (str): Path to the .xcstrings file key (str): The specific key to translate target_languages (str): Comma-separated list of target language codes (e.g., "es,fr,de") app_description (str): Optional description of the app for better translation context Returns: str: Translation results or error message """ try: if not validate_xcstrings_file(file_path): return f"Error: Invalid file path or not an .xcstrings file: {file_path}" # Parse target languages languages = [lang.strip() for lang in target_languages.split(',') if lang.strip()] if not languages: return "Error: No target languages provided" # Validate all language codes for lang in languages: if not validate_language_code(lang): return f"Error: Invalid language code: {lang}" # Translate the key app_desc = app_description if app_description else None translations, backup_path, errors = translate_single_key( file_path, key, languages, app_description=app_desc ) if not translations and errors: return f"Error: All translations failed:\n" + "\n".join( f"{lang}: {error}" for lang, error in errors.items() ) result = [ f"Translated key '{key}' to {len(translations)} language(s)", f"Backup created: {backup_path}", ] if translations: result.append("\nSuccessful translations:") for lang, trans_dict in translations.items(): for k, value in trans_dict.items(): result.append(f" {lang}: {value}") if errors: result.append("\nFailed translations:") for lang, error in errors.items(): result.append(f" {lang}: {error}") return "\n".join(result) except KeyError as e: return f"Error: {str(e)}" except Exception as e: return format_error_message(e, "Failed to translate key")
- Core helper function implementing the translation logic for a single key across multiple languages. Handles file I/O, backup creation, OpenAI translation via translate_strings, and applies changes to the xcstrings file structure.def translate_single_key( file_path: str, key: str, target_languages: List[str], source_language: str = "en", app_description: Optional[str] = None ) -> Tuple[Dict[str, Dict[str, str]], str, Dict[str, str]]: """ Translate a single key to multiple target languages and apply translations to a Localizable.xcstrings file. Args: file_path (str): Path to the .xcstrings file key (str): The specific key to translate target_languages (List[str]): List of target language codes source_language (str): Source language code (default: 'en') app_description (Optional[str]): Optional description of the app for better translation context Returns: Tuple[Dict[str, Dict[str, str]], str, Dict[str, str]]: Tuple of (translations by language, backup file path, errors by language) Raises: FileNotFoundError: If the file doesn't exist KeyError: If the key doesn't exist in the file json.JSONDecodeError: If the file is not valid JSON """ if not os.path.exists(file_path): raise FileNotFoundError(f"File not found: {file_path}") # Get base language strings (now returns list of keys) base_keys = get_base_language_strings(file_path) if key not in base_keys: raise KeyError(f"Key '{key}' not found in {file_path}") # For translation, we'll use the key as both key and value single_key_dict = {key: key} # Create backup before modifying the file timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") backup_path = f"{file_path}.bak.{timestamp}" try: shutil.copy2(file_path, backup_path) print(f"Created backup: {backup_path}") except Exception as e: raise Exception(f"Failed to create backup: {str(e)}") # Load the xcstrings file with open(file_path, 'r', encoding='utf-8') as f: data = json.load(f) if 'strings' not in data: data['strings'] = {} # Translate to each target language translations_by_language = {} errors_by_language = {} for target_lang in target_languages: try: # Translate the single key translated, skipped = translate_strings(single_key_dict, target_lang, source_language, app_description) if key in translated: # Apply the translation if key not in data['strings']: data['strings'][key] = {"localizations": {}} if 'localizations' not in data['strings'][key]: data['strings'][key]['localizations'] = {} data['strings'][key]['localizations'][target_lang] = { "stringUnit": { "state": "translated", "value": translated[key] } } translations_by_language[target_lang] = {key: translated[key]} else: error_msg = skipped.get(key, "Translation failed") if skipped else "Translation failed" errors_by_language[target_lang] = error_msg except Exception as e: errors_by_language[target_lang] = str(e) # Write back to file if we have any successful translations if translations_by_language: try: with open(file_path, 'w', encoding='utf-8') as f: json.dump(data, f, indent=2, ensure_ascii=False) except Exception as e: raise Exception(f"Failed to write file: {str(e)}") return translations_by_language, backup_path, errors_by_language