{
  "openapi": "3.0.3",
  "info": {
    "title": "i18n Manager API",
    "version": "1.0.0",
    "description": "REST endpoints for the i18n Manager app (PHP + PostgreSQL).\n\nGET endpoints use query parameters. POST endpoints read `$_POST`, so they accept `application/x-www-form-urlencoded` bodies. JSON-valued fields (`translations`, `data`) are sent as a string containing JSON."
  },
  "servers": [
    { "url": "/", "description": "Same origin as this page" }
  ],
  "tags": [
    { "name": "Languages", "description": "Language reference data" },
    { "name": "Translations", "description": "Translation keys, values, import/export" }
  ],
  "paths": {
    "/api/languages_list.php": {
      "get": {
        "tags": ["Languages"],
        "summary": "List languages",
        "description": "Returns every language with its code, name, and active flag.",
        "responses": {
          "200": {
            "description": "Language list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": { "type": "boolean", "example": true },
                    "languages": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/Language" }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/language_toggle.php": {
      "post": {
        "tags": ["Languages"],
        "summary": "Toggle language active state",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": ["code", "is_active"],
                "properties": {
                  "code": { "type": "string", "minLength": 2, "maxLength": 2, "example": "de", "description": "ISO 639-1 2-letter language code." },
                  "is_active": { "type": "integer", "enum": [0, 1], "example": 1, "description": "1 = active, 0 = inactive." }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SuccessResult" } } } },
          "400": { "description": "Invalid language code", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResult" } } } }
        }
      }
    },
    "/api/translations_list.php": {
      "get": {
        "tags": ["Translations"],
        "summary": "List translation keys (paginated)",
        "description": "Paginated list of keys with per-language translations aggregated as JSON. Also returns the distinct namespaces for the filter dropdown.",
        "parameters": [
          { "name": "namespace", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter by namespace (e.g. nav, btn)." },
          { "name": "search", "in": "query", "required": false, "schema": { "type": "string" }, "description": "ILIKE match on key or description." },
          { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "default": 1, "minimum": 1 } },
          { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "default": 50, "minimum": 1, "maximum": 200 } }
        ],
        "responses": {
          "200": {
            "description": "Paginated keys",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": { "type": "boolean" },
                    "total": { "type": "integer" },
                    "page": { "type": "integer" },
                    "limit": { "type": "integer" },
                    "namespaces": { "type": "array", "items": { "type": "string" } },
                    "keys": { "type": "array", "items": { "$ref": "#/components/schemas/TranslationKey" } }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/translations_i18n.php": {
      "get": {
        "tags": ["Translations"],
        "summary": "Export flat i18n map",
        "description": "Returns all keys (active languages only) as a flat `{ key: { lang: value } }` map — the shape used by hold_files/i18n.json and consumed by the in-app language switcher.",
        "parameters": [
          { "name": "namespace", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter by namespace." },
          { "name": "search", "in": "query", "required": false, "schema": { "type": "string" }, "description": "ILIKE match on key or description." },
          { "name": "format", "in": "query", "required": false, "schema": { "type": "string", "enum": ["json", "js"], "default": "json" }, "description": "`json` returns an object; `js` returns `var i18n = {…};` as application/javascript." }
        ],
        "responses": {
          "200": {
            "description": "Flat i18n map",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": { "type": "object", "additionalProperties": { "type": "string" } },
                  "example": { "nav.home": { "en": "Home", "de": "Startseite" } }
                }
              },
              "application/javascript": {
                "schema": { "type": "string", "example": "var i18n = { \"nav.home\": { \"en\": \"Home\" } };" }
              }
            }
          }
        }
      }
    },
    "/api/translations_export.php": {
      "get": {
        "tags": ["Translations"],
        "summary": "Export translations as a downloadable file",
        "description": "Triggers a file download (Content-Disposition: attachment). JSON output matches the Bulk Import format; CSV includes a UTF-8 BOM and an empty translation column.",
        "parameters": [
          { "name": "language", "in": "query", "required": true, "schema": { "type": "string", "minLength": 2, "maxLength": 2 }, "example": "en", "description": "2-letter language code to export." },
          { "name": "format", "in": "query", "required": false, "schema": { "type": "string", "enum": ["json", "csv"], "default": "json" } },
          { "name": "namespace", "in": "query", "required": false, "schema": { "type": "string" } },
          { "name": "search", "in": "query", "required": false, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "File download",
            "content": {
              "application/json": { "schema": { "type": "object" } },
              "text/csv": { "schema": { "type": "string", "format": "binary" } }
            }
          },
          "400": { "description": "Missing/invalid language or format", "content": { "text/plain": { "schema": { "type": "string" } } } },
          "404": { "description": "Language not found", "content": { "text/plain": { "schema": { "type": "string" } } } }
        }
      }
    },
    "/api/translation_key_save.php": {
      "post": {
        "tags": ["Translations"],
        "summary": "Create or update a translation key",
        "description": "Creates a key (id=0) or updates it, then upserts its translations in a transaction.",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": ["key"],
                "properties": {
                  "id": { "type": "integer", "default": 0, "description": "0 to create; existing id to update." },
                  "key": { "type": "string", "example": "nav.home", "description": "Key name (namespace.identifier)." },
                  "description": { "type": "string", "description": "Optional translator hint." },
                  "contains_html": { "type": "integer", "enum": [0, 1], "default": 0 },
                  "mark_reviewed": { "type": "integer", "enum": [0, 1], "default": 0 },
                  "translations": { "type": "string", "example": "{\"en\":\"Home\",\"de\":\"Startseite\"}", "description": "JSON string of { langCode: value }." }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved",
            "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean" }, "id": { "type": "integer" } } } } }
          },
          "400": { "description": "Key name required", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResult" } } } }
        }
      }
    },
    "/api/translations_import.php": {
      "post": {
        "tags": ["Translations"],
        "summary": "Bulk import translations",
        "description": "Imports a JSON map of translations, creating missing keys.",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": ["data"],
                "properties": {
                  "data": { "type": "string", "example": "{\"nav.home\":{\"en\":\"Home\",\"de\":\"Startseite\"}}", "description": "JSON string: { key: { langCode: value } }." },
                  "overwrite": { "type": "integer", "enum": [0, 1], "default": 0, "description": "1 to overwrite existing translations." },
                  "is_reviewed": { "type": "integer", "enum": [0, 1], "default": 0, "description": "1 to mark imported as reviewed." }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Import result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": { "type": "boolean" },
                    "imported": { "type": "integer" },
                    "skipped": { "type": "integer" },
                    "created_keys": { "type": "integer" }
                  }
                }
              }
            }
          },
          "400": { "description": "Invalid or empty JSON data", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResult" } } } }
        }
      }
    },
    "/api/translation_key_delete.php": {
      "post": {
        "tags": ["Translations"],
        "summary": "Delete a translation key",
        "description": "Deletes a key and ALL its translations (cascade).",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": ["id"],
                "properties": {
                  "id": { "type": "integer", "example": 1, "description": "id of the key to delete." }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Deleted (or not found)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SuccessResult" } } } },
          "400": { "description": "Invalid ID", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResult" } } } }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Language": {
        "type": "object",
        "properties": {
          "code": { "type": "string", "example": "en" },
          "name": { "type": "string", "example": "English" },
          "is_active": { "type": "boolean", "example": true }
        }
      },
      "TranslationKey": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "key": { "type": "string", "example": "nav.home" },
          "namespace": { "type": "string", "example": "nav" },
          "contains_html": { "type": "boolean" },
          "description": { "type": "string" },
          "translations": {
            "type": "object",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "value": { "type": "string" },
                "is_reviewed": { "type": "boolean" }
              }
            }
          }
        }
      },
      "SuccessResult": {
        "type": "object",
        "properties": { "success": { "type": "boolean", "example": true } }
      },
      "ErrorResult": {
        "type": "object",
        "properties": {
          "success": { "type": "boolean", "example": false },
          "error": { "type": "string" }
        }
      }
    }
  }
}
