Profile
Back to NewsBack
GitHub Trending 6 min
Reader Mode
fayharinn/StoreLocalizer: Translate iOS/Android store metadata using AI. Create, localize and send screenshots to stores.

fayharinn/StoreLocalizer: Translate iOS/Android store metadata using AI. Create, localize and send screenshots to stores.

8 hours ago


Why?

Going global is brutal when you do it by hand:

| | The manual way | With StoreLocalizer | |---|---|---| | 🌍 Localizing 40+ languages | Weeks of copy-paste | Minutes — batched AI translation, synced to your stores | | 💸 Pricing in 175 countries | Guesswork | GDP-adjusted recommendations per market | | 📸 Screenshots per language | A designer's nightmare | Generated for every locale from one template | | 🔑 ASO keywords per locale | Spreadsheets | Suggested, scored & reviewed per keyword |

Everything talks directly to App Store Connect and Google Play Console — no exports, no copy-paste.


✨ The toolkit

🤖 The Agent — run the whole pipeline by chat

Tell it what you want in plain words and it calls 24 functions against your real accounts: list apps and versions, audit localizations, translate and push "What's New" to five locales, mine ASO keywords from AppCompete, or find what's missing in your .xcstrings. It can even see your App Store screenshots — ask for feedback and it reviews each one, with an in-chat gallery to switch locales and a lightbox to zoom in.

AI agent reviewing App Store screenshots in chat

🔤 XCStrings Translator

Drop an .xcstrings file from Xcode, pick your target languages, translate everything with AI, and export straight back to your project. Format specifiers (%lld, %@) and protected brand words are preserved, and batched + concurrent requests make 1,000 strings a coffee-break job. Every translation stays one click away from a manual fix:

Edit translation dialog

🔑 ASO keywords that earn their 100 characters

Generate keywords with AI — or plug your AppCompete account and work with real data: suggestions scored by popularity & difficulty with a live capacity gauge, keywords mined from the competitors you track, and a per-keyword review that tells you what to keep, replace, or stop dreaming about:

AppCompete keyword suggestions with popularity and difficulty scores Keyword review verdicts: great, ok, weak, hard, untracked
Suggestions scored by opportunity, capped at Apple's 100 chars One verdict + one advice per keyword — track the missing ones

🏪 App Store Connect & Google Play sync

Connect once with your API keys — then translate descriptions, what's new, keywords and promotional text across every locale, manage screenshots, create versions, and push everything back without leaving the browser.

  • Asset Library (iOS 27) — upload screenshots, app previews and the new creative assets (product page header, search results, In-App Event cards) once, then place them on any surface. Sizes and device groups (iPhone Duo included) come live from Apple's spec catalog, and a dropped /en-US, /fr-FR… folder is validated, uploaded and placed per locale in one go.
  • Custom Product Pages — create, publish/hide and deep-link page variants, AI-translate their promotional text, and fill their media from the library.
  • Product Page Optimization — set up A/B tests with up to 3 treatments (alternate icon + media per locale) and start them once Apple accepts them.
  • In-App Events — create, localize and AI-translate events, with their card and details page artwork.
App Store Connect integration

📸 Screenshot Studio

A device-frame screenshot generator that lives next to your translations. Gradient preset galleries, 2D/3D frames (Three.js), AI-generated marketing headlines, one-click caption translation to every project language — then export all locales as a ZIP, sized for any store format.

Screenshot studio workspace Rendered device frame on gradient background
The studio: projects, languages, style presets, batch export What ships to the store

💰 GDP-fair subscription pricing

Set your USA base price and get a recommended price for every storefront based on local purchasing power — then push them to App Store Connect and translate your subscription display names while you're at it.

GDP-adjusted recommended prices by country


🤖 Bring your own AI

Pick a provider in the sidebar, paste a key, done — keys never leave your browser.

| Provider | Models | Notes | |---|---|---| | OpenAI | gpt-5.6-luna | model list fetched live from your account | | Anthropic (Claude) | haiku-4.5 · sonnet-4.6 · opus-4.8 | direct browser access | | Google (Gemini) | 3.1-flash-lite · 3.5-flash · 3.1-pro | JSON-native responses | | DeepSeek | v4-flash · v4-pro | | | Cloudflare Workers AI | Llama 3.3/4 · GPT-OSS · Mistral… | 13 open-weight LLMs | | AWS Bedrock | Claude family | bearer-token auth | | Azure OpenAI | your deployments | | | GitHub Models | gpt-4o · gpt-4.1 | free-tier friendly |

The Agent needs function calling — it works with OpenAI, Anthropic, Gemini, Azure, Bedrock, GitHub Models and DeepSeek.


🚀 Quick start

git clone https://github.com/fayharinn/StoreLocalizer.git
cd StoreLocalizer
bun install        # or npm install
bun run dev        # → http://localhost:5173

That's it for local use — the dev server proxies all App Store Connect / Google Play calls for you.

No install? Use the hosted version at storelocalizer.com.

Desktop app (Tauri 2, Rust toolchain required):

bun run tauri:dev      # develop
bun run tauri:build    # package

⚙️ Connect your stores

App Store Connect API key

  1. Go to App Store Connect → Integrations → API Keys
  2. Create a key with Admin or App Manager role
  3. Note your Key ID and Issuer ID, download the .p8 file
  4. Drop everything in the app sidebar — the .p8 is encrypted with your password before being stored

Google Play service account

  1. In Google Cloud Console, create a service account with the Google Play Developer API enabled and download its JSON key
  2. In Play Console → Users and permissions, invite the service account email
  3. Grant Admin or Release manager for your app
  4. Upload the JSON key in the app sidebar

App Store Connect auth flow (how your .p8 stays safe)

┌─────────────────────────────────────────────────────────────────────────────┐
│                         App Store Connect Auth Flow                         │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  ┌──────────┐    password     ┌──────────────┐                              │
│  │  .p8 Key │ ──────────────► │  Encrypted   │ ◄─── Stored in localStorage  │
│  │  (file)  │    encrypt      │   .p8 Key    │      (persistent)            │
│  └────┬─────┘                 └──────┬───────┘                              │
│       │                              │                                      │
│       │ sign                         │ password                             │
│       │                              │ decrypt                              │
│       ▼                              ▼                                      │
│  ┌──────────┐                 ┌──────────────┐                              │
│  │   JWT    │ ◄───────────────│  Decrypted   │                              │
│  │  Token   │     sign        │   .p8 Key    │ ◄─── In memory only          │
│  └────┬─────┘                 └──────────────┘      (cleared on reload)     │
│       │                                                                     │
│       │ cache                                                               │
│       ▼                                                                     │
│  ┌──────────────┐                                                           │
│  │ sessionStorage│ ◄─── JWT cached for ~19 min                              │
│  │  (JWT only)   │      Auto-reconnect on page reload                       │
│  └──────┬───────┘                                                           │
│         │                                                                   │
│         │ Bearer token                                                      │
│         ▼                                                                   │
│  ┌──────────────┐                                                           │
│  │  App Store   │                                                           │
│  │ Connect API  │                                                           │
│  └──────────────┘                                                           │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Security model in one paragraph: your .p8 key is encrypted in-browser (AES-GCM, PBKDF2 100k iterations) before touching localStorage; the decrypted key only ever exists in memory. JWTs are signed client-side with jose. AI provider keys go straight from your browser to the provider. The only backend is a thin CORS proxy that forwards your Authorization header — it stores nothing. It's all open source: audit it.


🛠️ Production deployment

The web app is static (Vite). Apple & Google block browser CORS, so production needs the bundled Cloudflare Worker as a proxy:

# 1. Deploy the CORS proxy worker
wrangler deploy -c wrangler.proxy.jsonc

2. Point the site at it

echo 'VITE_ASC_PROXY_URL=https://your-worker.workers.dev' >> .env.production echo 'VITE_GP_PROXY_URL=https://your-worker.workers.dev' >> .env.production

3. Ship the site

bun run deploy:cloudflare # Cloudflare Pages bun run deploy # …or GitHub Pages

Remember to add your domain to ALLOWED_ORIGINS in worker/index.js.


🧱 Tech stack

React 19 + Vite · Tailwind + shadcn/ui · Three.js (3D device frames) · jose (ES256 JWT signing in-browser) · Tauri 2 (desktop) · Cloudflare Workers (CORS proxy)

src/
├── components/        # six pages: agent · xcstrings · appstore · googleplay · screenshots · subscriptions
├── hooks/             # top-level state (useAppState, useTranslation, …)
├── services/          # every external call: ASC, Google Play, 8 AI providers, AppCompete + the agent's tool registry
└── utils/             # xcstrings parser, AES-GCM crypto

🤝 Contributing

Issues and PRs are welcome! Run bun run lint before submitting. The screenshots in this README are generated with node scripts/take-screenshots.mjs against the dev server (scripts/take-agent-screenshot.mjs for the agent shot).

Contributors

fayharinn
fayharinn
krrskl
krrskl
jtaxiexpress
jtaxiexpress
isnine
isnine
mashegoindustries
mashegoindustries

This grid refreshes automatically on every push.

Credits: screenshot generator originally based on appscreen by Stefan from yuzuhub.com.

📄 License

AGPLv3 — free to use, modify and self-host; derivatives must stay open source.

Crafted with ❤️ by Fayhe

⭐ If this saves you a localization weekend, a star helps others find it.

Chat with me