Managing 80+ Google Play locales from the terminal
Google Play supports more than 80 store-listing locales — from af (Afrikaans) to zu (Zulu), including regional variants like es-419 (Latin American Spanish), pt-BR (Brazilian Portuguese), and zh-TW (Traditional Chinese). Setting them all up in the Play Console web UI means clicking through a language dropdown once per locale, per app, and re-doing it for every listing change.
gplay turns that into a scriptable batch job. Here’s the full toolkit.
Discover the supported locales
Section titled “Discover the supported locales”gplay listings localesReturns the full list Google Play accepts, as JSON:
[ { "code": "af", "name": "Afrikaans" }, { "code": "am", "name": "Amharic" }, { "code": "ar", "name": "Arabic" }, { "code": "az-AZ", "name": "Azerbaijani" }, ... { "code": "zh-TW", "name": "Chinese (Traditional)" }, { "code": "zu", "name": "Zulu" }]Or as a table:
gplay listings locales --output tableValidate a code before you use it (avoid typos wasting a Play API round-trip):
gplay listings locales --validate ar-XB# → error: unknown locale 'ar-XB'. Did you mean 'ar'?See what you currently have
Section titled “See what you currently have”Which locales does your app currently have listings for?
gplay listings list --package com.example.app --output tableDiff against the full supported set to find gaps:
CURRENT=$(gplay listings list --package com.example.app | jq -r '.[].language' | sort)SUPPORTED=$(gplay listings locales | jq -r '.[].code' | sort)comm -23 <(echo "$SUPPORTED") <(echo "$CURRENT")That tells you exactly which of the 80+ locales you’re missing.
Get a single locale’s full listing
Section titled “Get a single locale’s full listing”gplay listings get \ --package com.example.app \ --locale de-DEReturns title, short description, full description, video URL. Perfect for pulling translations into a review tool.
Bulk-create listings from a directory
Section titled “Bulk-create listings from a directory”The --listings-dir flag reads Fastlane-format metadata:
metadata/├── en-US/│ ├── title.txt│ ├── short_description.txt│ ├── full_description.txt│ └── changelogs/default.txt├── fr-FR/│ └── ...├── de-DE/├── es-ES/├── ja-JP/├── ko/├── pt-BR/└── zh-TW/Push them all in one shot:
gplay listings push \ --package com.example.app \ --listings-dir ./metadataEvery locale that has a directory gets its listing created or updated inside a single edit session — atomic commit.
Preview before pushing
Section titled “Preview before pushing”--dry-run intercepts the write and shows you the payload:
gplay listings push \ --package com.example.app \ --listings-dir ./metadata \ --dry-runYou see exactly what will be sent to Google, per locale, without touching production.
Per-locale release notes
Section titled “Per-locale release notes”Release notes shipped alongside a track update. YAML format:
en-US: "New Pro features and bug fixes"en-GB: "New Pro features and bug fixes"fr-FR: "Nouvelles fonctionnalités Pro et corrections de bugs"de-DE: "Neue Pro-Funktionen und Fehlerbehebungen"es-ES: "Nuevas funciones Pro y correcciones de errores"es-419: "Nuevas funciones Pro y correcciones de errores"pt-BR: "Novas funcionalidades Pro e correções de bugs"ja-JP: "新しいProの機能とバグ修正"ko: "새로운 Pro 기능 및 버그 수정"zh-TW: "新 Pro 功能與錯誤修正"zh-CN: "新 Pro 功能与错误修复"ar: "ميزات Pro الجديدة وإصلاحات الأخطاء"Apply on release:
gplay release \ --package com.example.app \ --track internal \ --bundle app-release.aab \ --release-notes-file release-notes.yamlOr generate the whole file from git history in your default locale, then translate:
gplay release-notes generate --since v4.1.0 --output release-notes.yamlIf you pass a plain string as --release-notes, gplay auto-assigns it to en-US. Explicit is better — but this shortcut is handy for internal builds.
Locale-aware validation
Section titled “Locale-aware validation”Google will reject a release if:
- Any locale has an empty title.
- Full description exceeds 4,000 characters.
- Short description exceeds 80 characters.
- A locale exists in your listings but not in the supported set (typo, stale data).
Preflight:
gplay listings validate \ --package com.example.app \ --listings-dir ./metadataAI-agent-driven localization
Section titled “AI-agent-driven localization”Combine gplay with your AI agent for the tedious parts. Prompt:
Pull the
en-USlisting and full description forcom.example.app. Translate the short and full descriptions into French, German, Spanish (both es-ES and es-419), Portuguese (both pt-BR and pt-PT), Japanese, Korean, Chinese (both zh-CN and zh-TW), and Arabic. Preserve technical terms (product names, feature names). Write each tometadata/<locale>/short_description.txtandfull_description.txt. When done, dry-rungplay listings pushso I can review.
Chains: gplay listings get --locale en-US → LLM translations to files → gplay listings push --dry-run. You review, then run without --dry-run.
Every one of the 12 supported agents — Claude Code, Cursor, Codex, Gemini CLI, Aider, Cline, Windsurf, Continue, GitHub Copilot CLI, Amazon Q Developer, OpenClaw, Hermes Agent — can do this. Install the metadata-sync skill and they’ll know the file layout by default.
Screenshots per locale
Section titled “Screenshots per locale”Localized listings often need localized screenshots (screenshots with translated in-image text). gplay listings push --screenshots-dir reads the same Fastlane-format tree:
screenshots/├── en-US/│ └── phoneScreenshots/│ ├── 1.png│ ├── 2.png│ └── ...├── fr-FR/│ └── phoneScreenshots/│ └── ...Or use --skip-screenshots if you only want to update text.
Getting started
Section titled “Getting started”brew install tamtom/tap/gplaygplay setup --autogplay listings locales --output tablegplay listings list --package com.example.app --output tableFull listings reference at /reference/listings/. If you’re maintaining a large locale matrix, install the metadata-sync skill and let your AI agent drive the day-to-day translation-review-push cycle.