[GH-ISSUE #23] Phase 5: Localization commands (list/download/upload) #3

Closed
opened 2026-02-26 21:32:41 +03:00 by kerem · 1 comment
Owner

Originally created by @rudrankriyam on GitHub (Jan 20, 2026).
Original GitHub issue: https://github.com/rudrankriyam/App-Store-Connect-CLI/issues/23

PRD: App Store Connect Localizations Management

Goal

Enable developers and AI agents to manage App Store localization metadata (descriptions, keywords, release notes, app names, privacy URLs) via CLI commands. Support both version-specific localizations (appStoreVersionLocalizations) and app-level localizations (appInfoLocalizations) with list, download, and upload operations.

Background

App Store Connect API provides two localization resource types:

  1. appStoreVersionLocalizations - Version-specific metadata:

    • description - App description
    • keywords - Search keywords
    • marketingUrl - Marketing website URL
    • promotionalText - Promotional text (170 chars max)
    • supportUrl - Support website URL
    • whatsNew - Release notes ("What's New")
    • locale - Language tag (e.g., "en-US", "ja")
  2. appInfoLocalizations - App-level metadata:

    • name - App name (required for app record)
    • subtitle - App subtitle
    • privacyPolicyUrl - Privacy policy URL
    • privacyChoicesUrl - Privacy choices URL
    • privacyPolicyText - Privacy policy text
    • locale - Language tag

CLI Commands

Command Structure

# Version localizations (appStoreVersionLocalizations)
asc localizations list --version "VERSION_ID" [flags]
asc localizations download --version "VERSION_ID" [flags]
asc localizations upload --version "VERSION_ID" --file "localizations.json" [flags]

# App info localizations (appInfoLocalizations)
asc localizations list --app "APP_ID" --type app-info [flags]
asc localizations download --app "APP_ID" --type app-info [flags]
asc localizations upload --app "APP_ID" --type app-info --file "app-info-localizations.json" [flags]

Subcommands

list - List localizations

Lists all localizations for a given app version or app info.

Flags:

  • --version - App Store Version ID (required for version localizations)
  • --app - App ID (required for app-info localizations)
  • --type - Localization type: version (default) or app-info
  • --output - Output format: json (default), table, markdown
  • --pretty - Pretty-print JSON output
  • --locale - Filter by locale (e.g., "en-US", "ja")

Examples:

# List version localizations
asc localizations list --version "abc123"

# List app-info localizations
asc localizations list --app "123456789" --type app-info

# Filter by locale
asc localizations list --version "abc123" --locale "en-US"

Output (JSON):

{
  "data": [
    {
      "type": "appStoreVersionLocalizations",
      "id": "loc-id-123",
      "attributes": {
        "locale": "en-US",
        "description": "App description...",
        "keywords": "keyword1, keyword2",
        "marketingUrl": "https://example.com",
        "promotionalText": "Promo text",
        "supportUrl": "https://support.example.com",
        "whatsNew": "What's new in this version"
      }
    }
  ],
  "links": {
    "self": "...",
    "next": "..."
  }
}

download - Download localizations to file

Downloads all localizations for a version or app-info to a JSON file.

Flags:

  • --version - App Store Version ID (required for version localizations)
  • --app - App ID (required for app-info localizations)
  • --type - Localization type: version (default) or app-info
  • --file - Output file path (default: localizations.json or app-info-localizations.json)
  • --locale - Download specific locale only (optional)

Examples:

# Download all version localizations
asc localizations download --version "abc123"

# Download app-info localizations
asc localizations download --app "123456789" --type app-info --file "app-info.json"

# Download specific locale
asc localizations download --version "abc123" --locale "ja" --file "ja-localization.json"

Output File Format:

{
  "version": "abc123",
  "type": "appStoreVersionLocalizations",
  "localizations": [
    {
      "id": "loc-id-123",
      "locale": "en-US",
      "description": "...",
      "keywords": "...",
      "whatsNew": "..."
    },
    {
      "id": "loc-id-456",
      "locale": "ja",
      "description": "...",
      "keywords": "...",
      "whatsNew": "..."
    }
  ]
}

upload - Upload localizations from file

Uploads or updates localizations from a JSON file. Creates new localizations if locale doesn't exist, updates existing ones if locale exists.

Flags:

  • --version - App Store Version ID (required for version localizations)
  • --app - App ID (required for app-info localizations)
  • --type - Localization type: version (default) or app-info
  • --file - Input JSON file path (required)
  • --dry-run - Validate file without uploading
  • --locale - Upload specific locale only (optional, filters file)

Examples:

# Upload version localizations
asc localizations upload --version "abc123" --file "localizations.json"

# Upload app-info localizations
asc localizations upload --app "123456789" --type app-info --file "app-info.json"

# Dry run to validate
asc localizations upload --version "abc123" --file "localizations.json" --dry-run

# Upload specific locale
asc localizations upload --version "abc123" --file "localizations.json" --locale "ja"

Input File Format:

{
  "localizations": [
    {
      "locale": "en-US",
      "description": "Updated description",
      "keywords": "new, keywords",
      "whatsNew": "Bug fixes and improvements"
    },
    {
      "locale": "ja",
      "description": "説明文",
      "keywords": "キーワード1, キーワード2",
      "whatsNew": "バグ修正と改善"
    }
  ]
}

Note: If a localization with the same locale already exists, the command will update it (PATCH). If it doesn't exist, it will create a new one (POST).

API Endpoints

Version Localizations (appStoreVersionLocalizations)

Method Endpoint Description
GET /v1/appStoreVersions/{id}/appStoreVersionLocalizations List all localizations for a version
GET /v1/appStoreVersionLocalizations/{id} Get specific localization
POST /v1/appStoreVersionLocalizations Create new localization
PATCH /v1/appStoreVersionLocalizations/{id} Update existing localization
DELETE /v1/appStoreVersionLocalizations/{id} Delete localization

Required Fields (POST):

  • type: "appStoreVersionLocalizations"
  • attributes.locale: Language tag (e.g., "en-US")
  • relationships.appStoreVersion: Version ID and type

Optional Fields:

  • description - App description
  • keywords - Comma-separated keywords
  • marketingUrl - Marketing URL
  • promotionalText - Promotional text (170 chars max)
  • supportUrl - Support URL
  • whatsNew - Release notes

App Info Localizations (appInfoLocalizations)

Method Endpoint Description
GET /v1/apps/{id}/appInfos Resolve appInfo ID(s) for an app
GET /v1/appInfos/{id}/appInfoLocalizations List all localizations for app info
GET /v1/appInfoLocalizations/{id} Get specific localization
POST /v1/appInfoLocalizations Create new localization
PATCH /v1/appInfoLocalizations/{id} Update existing localization
DELETE /v1/appInfoLocalizations/{id} Delete localization

Required Fields (POST):

  • type: "appInfoLocalizations"
  • attributes.locale: Language tag
  • relationships.appInfo: App Info ID and type

Optional Fields:

  • name - App name (required for app record, but not API request)
  • subtitle - App subtitle
  • privacyPolicyUrl - Privacy policy URL
  • privacyChoicesUrl - Privacy choices URL
  • privacyPolicyText - Privacy policy text

Request/Response Shapes

Create Version Localization (POST)

Request:

{
  "data": {
    "type": "appStoreVersionLocalizations",
    "attributes": {
      "locale": "en-US",
      "description": "App description",
      "keywords": "keyword1, keyword2",
      "whatsNew": "What's new"
    },
    "relationships": {
      "appStoreVersion": {
        "data": {
          "type": "appStoreVersions",
          "id": "abc123"
        }
      }
    }
  }
}

Response:

{
  "data": {
    "type": "appStoreVersionLocalizations",
    "id": "loc-id-123",
    "attributes": {
      "locale": "en-US",
      "description": "App description",
      "keywords": "keyword1, keyword2",
      "marketingUrl": null,
      "promotionalText": null,
      "supportUrl": null,
      "whatsNew": "What's new"
    },
    "relationships": {
      "appStoreVersion": {
        "data": {
          "type": "appStoreVersions",
          "id": "abc123"
        }
      }
    }
  },
  "links": {
    "self": "https://api.appstoreconnect.apple.com/v1/appStoreVersionLocalizations/loc-id-123"
  }
}

Update Version Localization (PATCH)

Request:

{
  "data": {
    "type": "appStoreVersionLocalizations",
    "id": "loc-id-123",
    "attributes": {
      "description": "Updated description",
      "whatsNew": "Updated release notes"
    }
  }
}

Create App Info Localization (POST)

Request:

{
  "data": {
    "type": "appInfoLocalizations",
    "attributes": {
      "locale": "en-US",
      "name": "My App",
      "subtitle": "App subtitle",
      "privacyPolicyUrl": "https://example.com/privacy"
    },
    "relationships": {
      "appInfo": {
        "data": {
          "type": "appInfos",
          "id": "app-info-id-123"
        }
      }
    }
  }
}

Typical Update Flow

  1. List existing localizations:

    asc localizations list --version "abc123"
    
  2. Download current state:

    asc localizations download --version "abc123" --file "current.json"
    
  3. Edit JSON file (manually or via script)

  4. Upload updates:

    asc localizations upload --version "abc123" --file "updated.json"
    

Internal Flow:

  1. For app-info localizations, resolve appInfo ID via /v1/apps/{id}/appInfos
  2. Parse JSON file
  3. For each localization in file:
    • Check if locale exists (GET /v1/appStoreVersions/{id}/appStoreVersionLocalizations?filter[locale]={locale})
    • If exists: PATCH /v1/appStoreVersionLocalizations/{id} with updated fields
    • If not exists: POST /v1/appStoreVersionLocalizations with new localization
  4. Report success/failure for each locale

Validation

File Format Validation

  • JSON must be valid
  • localizations array must be present
  • Each localization must have locale field
  • Locale must be valid language tag (e.g., "en-US", "ja", "zh-Hans")
  • Field length limits:
    • promotionalText: 170 characters max
    • keywords: Typically 100 characters max (comma-separated)
    • description: Typically 4000 characters max
    • whatsNew: Typically 4000 characters max

API Validation

  • Version must exist and be in editable state (e.g., PREPARE_FOR_SUBMISSION)
  • App Info must exist
  • Locale must be valid and supported by App Store Connect
  • URLs must be valid HTTP/HTTPS URLs
  • Cannot create duplicate locale (409 Conflict if locale exists)

CLI Validation

  • --version or --app must be provided (depending on type)
  • --file must exist and be readable (for upload)
  • --type must be version or app-info
  • Cannot use both --version and --app for same command
  • Must specify either --version or --app (not neither)

Error Cases

File Errors

  • File not found: Error: file not found: localizations.json
  • Invalid JSON: Error: invalid JSON: unexpected token at line X
  • Missing locale: Error: localization at index 0 missing required field 'locale'
  • Invalid locale format: Error: invalid locale format: 'invalid'. Expected format: 'en-US' or 'ja'

API Errors

  • Version not found: Error: version not found: abc123
  • Version not editable: Error: version 'abc123' is not in an editable state (current: READY_FOR_SALE)
  • Locale already exists (on POST): Error: locale 'en-US' already exists for this version. Use update instead.
  • Locale not found (on PATCH): Error: localization not found for locale 'en-US'
  • Invalid URL: Error: invalid URL format: 'not-a-url'
  • Field too long: Error: promotionalText exceeds 170 character limit (current: 200)
  • Unauthorized: Error: unauthorized. Check your API credentials.

CLI Errors

  • Missing required flag: Error: --version is required for version localizations
  • Conflicting flags: Error: cannot use both --version and --app. Use --type to specify localization type.
  • Invalid type: Error: --type must be 'version' or 'app-info', got 'invalid'

Testing

Unit Tests

  1. File parsing:

    • Valid JSON with all fields
    • Valid JSON with partial fields
    • Invalid JSON
    • Missing localizations array
    • Missing locale in localization
  2. Validation:

    • Locale format validation
    • URL format validation
    • Field length validation
    • Required field validation
  3. API client methods:

    • ListVersionLocalizations(ctx, versionID, opts...)
    • GetVersionLocalization(ctx, localizationID)
    • CreateVersionLocalization(ctx, versionID, locale, attrs)
    • UpdateVersionLocalization(ctx, localizationID, attrs)
    • DeleteVersionLocalization(ctx, localizationID)
    • Similar methods for app-info localizations

Integration Tests

  1. List command:

    • List all localizations
    • Filter by locale
    • Handle empty results
    • Handle API errors
  2. Download command:

    • Download to file
    • Download specific locale
    • Handle file write errors
    • Verify file format
  3. Upload command:

    • Create new localization
    • Update existing localization
    • Handle duplicate locale error
    • Handle validation errors
    • Dry-run mode

CLI Tests

  1. Command parsing:

    • Valid flags
    • Missing required flags
    • Invalid flag values
    • Conflicting flags
  2. Output formats:

    • JSON output (minified)
    • JSON output (pretty)
    • Table output
    • Markdown output
  3. Error handling:

    • File errors
    • API errors
    • Validation errors
    • Network errors

References

Official Documentation

Implementation Notes

  1. Resource Type Detection:

    • Use --type flag to distinguish between version and app-info localizations
    • Default to version if not specified
  2. Locale Handling:

    • Support both full locale codes ("en-US") and language codes ("en")
    • Validate locale format before API calls
    • Handle locale case sensitivity (API may normalize)
  3. Update vs Create:

    • Check if localization exists before creating
    • Use PATCH for updates, POST for creates
    • Handle 409 Conflict errors gracefully
  4. File Format:

    • Use simple JSON structure for download/upload
    • Include metadata (version ID, type) in downloaded files
    • Support partial updates (only include fields to update)
  5. Error Recovery:

    • Continue processing other localizations if one fails
    • Report all errors at end
    • Provide clear error messages with actionable guidance
  6. Performance:

    • Batch operations where possible
    • Cache version/app-info lookups
    • Minimize API calls (check existence before create)
Originally created by @rudrankriyam on GitHub (Jan 20, 2026). Original GitHub issue: https://github.com/rudrankriyam/App-Store-Connect-CLI/issues/23 # PRD: App Store Connect Localizations Management ## Goal Enable developers and AI agents to manage App Store localization metadata (descriptions, keywords, release notes, app names, privacy URLs) via CLI commands. Support both version-specific localizations (`appStoreVersionLocalizations`) and app-level localizations (`appInfoLocalizations`) with list, download, and upload operations. ## Background App Store Connect API provides two localization resource types: 1. **`appStoreVersionLocalizations`** - Version-specific metadata: - `description` - App description - `keywords` - Search keywords - `marketingUrl` - Marketing website URL - `promotionalText` - Promotional text (170 chars max) - `supportUrl` - Support website URL - `whatsNew` - Release notes ("What's New") - `locale` - Language tag (e.g., "en-US", "ja") 2. **`appInfoLocalizations`** - App-level metadata: - `name` - App name (required for app record) - `subtitle` - App subtitle - `privacyPolicyUrl` - Privacy policy URL - `privacyChoicesUrl` - Privacy choices URL - `privacyPolicyText` - Privacy policy text - `locale` - Language tag ## CLI Commands ### Command Structure ```bash # Version localizations (appStoreVersionLocalizations) asc localizations list --version "VERSION_ID" [flags] asc localizations download --version "VERSION_ID" [flags] asc localizations upload --version "VERSION_ID" --file "localizations.json" [flags] # App info localizations (appInfoLocalizations) asc localizations list --app "APP_ID" --type app-info [flags] asc localizations download --app "APP_ID" --type app-info [flags] asc localizations upload --app "APP_ID" --type app-info --file "app-info-localizations.json" [flags] ``` ### Subcommands #### `list` - List localizations Lists all localizations for a given app version or app info. **Flags:** - `--version` - App Store Version ID (required for version localizations) - `--app` - App ID (required for app-info localizations) - `--type` - Localization type: `version` (default) or `app-info` - `--output` - Output format: `json` (default), `table`, `markdown` - `--pretty` - Pretty-print JSON output - `--locale` - Filter by locale (e.g., "en-US", "ja") **Examples:** ```bash # List version localizations asc localizations list --version "abc123" # List app-info localizations asc localizations list --app "123456789" --type app-info # Filter by locale asc localizations list --version "abc123" --locale "en-US" ``` **Output (JSON):** ```json { "data": [ { "type": "appStoreVersionLocalizations", "id": "loc-id-123", "attributes": { "locale": "en-US", "description": "App description...", "keywords": "keyword1, keyword2", "marketingUrl": "https://example.com", "promotionalText": "Promo text", "supportUrl": "https://support.example.com", "whatsNew": "What's new in this version" } } ], "links": { "self": "...", "next": "..." } } ``` #### `download` - Download localizations to file Downloads all localizations for a version or app-info to a JSON file. **Flags:** - `--version` - App Store Version ID (required for version localizations) - `--app` - App ID (required for app-info localizations) - `--type` - Localization type: `version` (default) or `app-info` - `--file` - Output file path (default: `localizations.json` or `app-info-localizations.json`) - `--locale` - Download specific locale only (optional) **Examples:** ```bash # Download all version localizations asc localizations download --version "abc123" # Download app-info localizations asc localizations download --app "123456789" --type app-info --file "app-info.json" # Download specific locale asc localizations download --version "abc123" --locale "ja" --file "ja-localization.json" ``` **Output File Format:** ```json { "version": "abc123", "type": "appStoreVersionLocalizations", "localizations": [ { "id": "loc-id-123", "locale": "en-US", "description": "...", "keywords": "...", "whatsNew": "..." }, { "id": "loc-id-456", "locale": "ja", "description": "...", "keywords": "...", "whatsNew": "..." } ] } ``` #### `upload` - Upload localizations from file Uploads or updates localizations from a JSON file. Creates new localizations if locale doesn't exist, updates existing ones if locale exists. **Flags:** - `--version` - App Store Version ID (required for version localizations) - `--app` - App ID (required for app-info localizations) - `--type` - Localization type: `version` (default) or `app-info` - `--file` - Input JSON file path (required) - `--dry-run` - Validate file without uploading - `--locale` - Upload specific locale only (optional, filters file) **Examples:** ```bash # Upload version localizations asc localizations upload --version "abc123" --file "localizations.json" # Upload app-info localizations asc localizations upload --app "123456789" --type app-info --file "app-info.json" # Dry run to validate asc localizations upload --version "abc123" --file "localizations.json" --dry-run # Upload specific locale asc localizations upload --version "abc123" --file "localizations.json" --locale "ja" ``` **Input File Format:** ```json { "localizations": [ { "locale": "en-US", "description": "Updated description", "keywords": "new, keywords", "whatsNew": "Bug fixes and improvements" }, { "locale": "ja", "description": "説明文", "keywords": "キーワード1, キーワード2", "whatsNew": "バグ修正と改善" } ] } ``` **Note:** If a localization with the same locale already exists, the command will update it (PATCH). If it doesn't exist, it will create a new one (POST). ## API Endpoints ### Version Localizations (`appStoreVersionLocalizations`) | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/v1/appStoreVersions/{id}/appStoreVersionLocalizations` | List all localizations for a version | | GET | `/v1/appStoreVersionLocalizations/{id}` | Get specific localization | | POST | `/v1/appStoreVersionLocalizations` | Create new localization | | PATCH | `/v1/appStoreVersionLocalizations/{id}` | Update existing localization | | DELETE | `/v1/appStoreVersionLocalizations/{id}` | Delete localization | **Required Fields (POST):** - `type`: `"appStoreVersionLocalizations"` - `attributes.locale`: Language tag (e.g., "en-US") - `relationships.appStoreVersion`: Version ID and type **Optional Fields:** - `description` - App description - `keywords` - Comma-separated keywords - `marketingUrl` - Marketing URL - `promotionalText` - Promotional text (170 chars max) - `supportUrl` - Support URL - `whatsNew` - Release notes ### App Info Localizations (`appInfoLocalizations`) | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/v1/apps/{id}/appInfos` | Resolve appInfo ID(s) for an app | | GET | `/v1/appInfos/{id}/appInfoLocalizations` | List all localizations for app info | | GET | `/v1/appInfoLocalizations/{id}` | Get specific localization | | POST | `/v1/appInfoLocalizations` | Create new localization | | PATCH | `/v1/appInfoLocalizations/{id}` | Update existing localization | | DELETE | `/v1/appInfoLocalizations/{id}` | Delete localization | **Required Fields (POST):** - `type`: `"appInfoLocalizations"` - `attributes.locale`: Language tag - `relationships.appInfo`: App Info ID and type **Optional Fields:** - `name` - App name (required for app record, but not API request) - `subtitle` - App subtitle - `privacyPolicyUrl` - Privacy policy URL - `privacyChoicesUrl` - Privacy choices URL - `privacyPolicyText` - Privacy policy text ## Request/Response Shapes ### Create Version Localization (POST) **Request:** ```json { "data": { "type": "appStoreVersionLocalizations", "attributes": { "locale": "en-US", "description": "App description", "keywords": "keyword1, keyword2", "whatsNew": "What's new" }, "relationships": { "appStoreVersion": { "data": { "type": "appStoreVersions", "id": "abc123" } } } } } ``` **Response:** ```json { "data": { "type": "appStoreVersionLocalizations", "id": "loc-id-123", "attributes": { "locale": "en-US", "description": "App description", "keywords": "keyword1, keyword2", "marketingUrl": null, "promotionalText": null, "supportUrl": null, "whatsNew": "What's new" }, "relationships": { "appStoreVersion": { "data": { "type": "appStoreVersions", "id": "abc123" } } } }, "links": { "self": "https://api.appstoreconnect.apple.com/v1/appStoreVersionLocalizations/loc-id-123" } } ``` ### Update Version Localization (PATCH) **Request:** ```json { "data": { "type": "appStoreVersionLocalizations", "id": "loc-id-123", "attributes": { "description": "Updated description", "whatsNew": "Updated release notes" } } } ``` ### Create App Info Localization (POST) **Request:** ```json { "data": { "type": "appInfoLocalizations", "attributes": { "locale": "en-US", "name": "My App", "subtitle": "App subtitle", "privacyPolicyUrl": "https://example.com/privacy" }, "relationships": { "appInfo": { "data": { "type": "appInfos", "id": "app-info-id-123" } } } } } ``` ## Typical Update Flow 1. **List existing localizations:** ```bash asc localizations list --version "abc123" ``` 2. **Download current state:** ```bash asc localizations download --version "abc123" --file "current.json" ``` 3. **Edit JSON file** (manually or via script) 4. **Upload updates:** ```bash asc localizations upload --version "abc123" --file "updated.json" ``` **Internal Flow:** 1. For app-info localizations, resolve appInfo ID via `/v1/apps/{id}/appInfos` 1. Parse JSON file 2. For each localization in file: - Check if locale exists (GET `/v1/appStoreVersions/{id}/appStoreVersionLocalizations?filter[locale]={locale}`) - If exists: PATCH `/v1/appStoreVersionLocalizations/{id}` with updated fields - If not exists: POST `/v1/appStoreVersionLocalizations` with new localization 3. Report success/failure for each locale ## Validation ### File Format Validation - JSON must be valid - `localizations` array must be present - Each localization must have `locale` field - Locale must be valid language tag (e.g., "en-US", "ja", "zh-Hans") - Field length limits: - `promotionalText`: 170 characters max - `keywords`: Typically 100 characters max (comma-separated) - `description`: Typically 4000 characters max - `whatsNew`: Typically 4000 characters max ### API Validation - Version must exist and be in editable state (e.g., `PREPARE_FOR_SUBMISSION`) - App Info must exist - Locale must be valid and supported by App Store Connect - URLs must be valid HTTP/HTTPS URLs - Cannot create duplicate locale (409 Conflict if locale exists) ### CLI Validation - `--version` or `--app` must be provided (depending on type) - `--file` must exist and be readable (for upload) - `--type` must be `version` or `app-info` - Cannot use both `--version` and `--app` for same command - Must specify either `--version` or `--app` (not neither) ## Error Cases ### File Errors - **File not found**: `Error: file not found: localizations.json` - **Invalid JSON**: `Error: invalid JSON: unexpected token at line X` - **Missing locale**: `Error: localization at index 0 missing required field 'locale'` - **Invalid locale format**: `Error: invalid locale format: 'invalid'. Expected format: 'en-US' or 'ja'` ### API Errors - **Version not found**: `Error: version not found: abc123` - **Version not editable**: `Error: version 'abc123' is not in an editable state (current: READY_FOR_SALE)` - **Locale already exists** (on POST): `Error: locale 'en-US' already exists for this version. Use update instead.` - **Locale not found** (on PATCH): `Error: localization not found for locale 'en-US'` - **Invalid URL**: `Error: invalid URL format: 'not-a-url'` - **Field too long**: `Error: promotionalText exceeds 170 character limit (current: 200)` - **Unauthorized**: `Error: unauthorized. Check your API credentials.` ### CLI Errors - **Missing required flag**: `Error: --version is required for version localizations` - **Conflicting flags**: `Error: cannot use both --version and --app. Use --type to specify localization type.` - **Invalid type**: `Error: --type must be 'version' or 'app-info', got 'invalid'` ## Testing ### Unit Tests 1. **File parsing:** - Valid JSON with all fields - Valid JSON with partial fields - Invalid JSON - Missing `localizations` array - Missing `locale` in localization 2. **Validation:** - Locale format validation - URL format validation - Field length validation - Required field validation 3. **API client methods:** - `ListVersionLocalizations(ctx, versionID, opts...)` - `GetVersionLocalization(ctx, localizationID)` - `CreateVersionLocalization(ctx, versionID, locale, attrs)` - `UpdateVersionLocalization(ctx, localizationID, attrs)` - `DeleteVersionLocalization(ctx, localizationID)` - Similar methods for app-info localizations ### Integration Tests 1. **List command:** - List all localizations - Filter by locale - Handle empty results - Handle API errors 2. **Download command:** - Download to file - Download specific locale - Handle file write errors - Verify file format 3. **Upload command:** - Create new localization - Update existing localization - Handle duplicate locale error - Handle validation errors - Dry-run mode ### CLI Tests 1. **Command parsing:** - Valid flags - Missing required flags - Invalid flag values - Conflicting flags 2. **Output formats:** - JSON output (minified) - JSON output (pretty) - Table output - Markdown output 3. **Error handling:** - File errors - API errors - Validation errors - Network errors ## References ### Official Documentation - **App Store Version Localizations:** - [App Store Version Localizations Resource](https://developer.apple.com/documentation/appstoreconnectapi/app-store-version-localizations) - [List All App Store Version Localizations](https://developer.apple.com/documentation/appstoreconnectapi/get-v1-appstoreversions-_id_-appstoreversionlocalizations) - [Create an App Store Version Localization](https://developer.apple.com/documentation/appstoreconnectapi/post-v1-appstoreversionlocalizations) - [Modify an App Store Version Localization](https://developer.apple.com/documentation/appstoreconnectapi/patch-v1-appstoreversionlocalizations-_id_) - **App Info Localizations:** - [App Info Localizations Resource](https://developer.apple.com/documentation/appstoreconnectapi/app-info-localizations) - [List All App Info Localizations](https://developer.apple.com/documentation/appstoreconnectapi/get-v1-appinfos-_id_-appinfolocalizations) - [Create an App Info Localization](https://developer.apple.com/documentation/appstoreconnectapi/post-v1-appinfolocalizations) - [Modify an App Info Localization](https://developer.apple.com/documentation/appstoreconnectapi/patch-v1-appinfolocalizations-_id_) - **General:** - [App Store Connect API](https://developer.apple.com/documentation/appstoreconnectapi) - [Required, Localizable, and Editable Properties](https://developer.apple.com/help/app-store-connect/reference/required-localizable-and-editable-properties/) - [Localize App Information](https://developer.apple.com/help/app-store-connect/manage-app-information/localize-app-store-information) ### Related Resources - [App Store Connect API Reference](https://developer.apple.com/documentation/appstoreconnectapi) - [App Store Connect API Authentication](https://developer.apple.com/documentation/appstoreconnectapi/generating_tokens_for_api_requests) - [App Store Connect API Error Responses](https://developer.apple.com/documentation/appstoreconnectapi/errorresponse) ## Implementation Notes 1. **Resource Type Detection:** - Use `--type` flag to distinguish between version and app-info localizations - Default to `version` if not specified 2. **Locale Handling:** - Support both full locale codes ("en-US") and language codes ("en") - Validate locale format before API calls - Handle locale case sensitivity (API may normalize) 3. **Update vs Create:** - Check if localization exists before creating - Use PATCH for updates, POST for creates - Handle 409 Conflict errors gracefully 4. **File Format:** - Use simple JSON structure for download/upload - Include metadata (version ID, type) in downloaded files - Support partial updates (only include fields to update) 5. **Error Recovery:** - Continue processing other localizations if one fails - Report all errors at end - Provide clear error messages with actionable guidance 6. **Performance:** - Batch operations where possible - Cache version/app-info lookups - Minimize API calls (check existence before create)
kerem closed this issue 2026-02-26 21:32:42 +03:00
Author
Owner

@rudrankriyam commented on GitHub (Jan 21, 2026):

Implemented in #28 (localization commands) and merged.

<!-- gh-comment-id:3776314129 --> @rudrankriyam commented on GitHub (Jan 21, 2026): Implemented in #28 (localization commands) and merged.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/App-Store-Connect-CLI#3
No description provided.