/** Read/write Apple String Catalog (.xcstrings) — a single JSON file, all languages nested. */ export type XcState = "new" | "translated" | "needs_review" | "stale"; export interface XcStringUnit { state: XcState; value: string; } export interface XcVariations { plural?: Record; } export interface XcLocalization { stringUnit?: XcStringUnit; variations?: XcVariations; } export interface XcEntry { comment?: string; extractionState?: string; localizations?: Record; } export interface XcCatalog { sourceLanguage: string; strings: Record; version: string; } export function parseXcstrings(json: string): XcCatalog { return JSON.parse(json) as XcCatalog; } /** Stable, Xcode-compatible serialization: 2-space indent, keys sorted, trailing newline. */ export function renderXcstrings(cat: XcCatalog): string { const sortDeep = (v: unknown): unknown => { if (Array.isArray(v)) return v.map(sortDeep); if (v && typeof v === "object") { const out: Record = {}; for (const k of Object.keys(v as Record).sort()) { out[k] = sortDeep((v as Record)[k]); } return out; } return v; }; return JSON.stringify(sortDeep(cat), null, 2) + "\n"; }