45 lines
4.2 KiB
Markdown
45 lines
4.2 KiB
Markdown
---
|
|
name: listing-localization
|
|
description: Translate the store listing of a mobile app or game into more languages - App Store name, subtitle, promotional text, keywords and description, Google Play title, short and full description - as per-language drafts in store/appstore.md and store/listing.md, translated by the agent (or a provider hook the owner sets), checked against each store's character limits and keyword rules, and marked as machine-translated until a human reviewed them. Use when the user wants the listing in new languages, asks to localize or translate the store page, or adds a language to the config.
|
|
---
|
|
|
|
# Listing localization
|
|
|
|
CLI: `storebound listing translate --to <languages> [--from <language>] [--store apple|play] [--translate "<command>"] [--force] [--dry]`,
|
|
`storebound listing check`, `storebound listing reviewed --lang <ids>`. MCP: `listing_translate`, `listing_check`.
|
|
Local files only: nothing is sent to a store until the owner pushes with `apple listing` / `play listing`.
|
|
|
|
## Steps
|
|
1. The target language must be in `languages[]` of `storebound.config.ts` (id, Play code, App Store locale). Add it
|
|
there first; ask the owner which stores the language goes on.
|
|
2. `storebound listing translate --to de,ja --dry`, then without `--dry`. Values are config ids or store codes; the
|
|
source is `--from` or the primary language. Per target it writes the App Store section (`## de-DE · de`) and the
|
|
Play section (`<!-- play: de-DE -->`) with the **source text** and the marker
|
|
`<!-- storebound-translation from=en-US status=translate -->`. A section without a marker (reviewed) is kept
|
|
unless `--force`; a section's What's new block is kept (release notes: whats-new skill).
|
|
3. **You translate** every field of each `status=translate` section in place, then set the marker to `status=draft`:
|
|
- Natural, native wording for that market, the app's own terms; not word by word. Keep product names and numbers.
|
|
- Limits (characters): App Store name 30, subtitle 30, promotional text 170, keywords 100, description 4000;
|
|
Google Play title 30, short description 80, full description 4000. Shorten, never cut mid-word.
|
|
- **Keywords are researched, not translated:** the words people in that market search for, comma separated,
|
|
no spaces after commas, no duplicates, no words already in the name or subtitle (they are indexed anyway), no
|
|
competitor or trademark names, 100 characters (characters in every script, not bytes) used well (aso-basics).
|
|
- Subtitle and short description: the benefit in plain words, no "best / #1 / free", no prices, no other platforms.
|
|
- Arabic and Hebrew stay RTL; Chinese / Japanese / Korean need no spaces in keywords.
|
|
4. Optional provider hook (the owner's choice): `--translate "<command>"` runs the command once per field with the
|
|
source text on stdin and `STOREBOUND_SOURCE_LANG`, `STOREBOUND_TARGET_LANG`, `STOREBOUND_STORE` (apple | play),
|
|
`STOREBOUND_FIELD` and `STOREBOUND_LIMIT` in the environment; stdout becomes the field and the section gets
|
|
`status=draft`. Keywords from a hook are cleaned up (duplicates, name / subtitle words, the 100 limit). Any key the
|
|
hook needs lives in the owner's environment, never in the config.
|
|
5. `storebound listing check` (MCP `listing_check`): every section against the limits and keyword rules, untranslated
|
|
sections, text identical to the source; exit 1 on a problem. `storebound check` also warns about drafts.
|
|
6. **The owner reviews** each draft (ideally a native speaker), then `storebound listing reviewed --lang de,ja`
|
|
removes the markers. Only then push: `storebound apple listing --version x` / `storebound play listing`.
|
|
|
|
## Gotchas
|
|
- Machine-translated store text that reads badly costs conversion; keep the draft marker until a human read it.
|
|
- The App Store keyword field of one locale also counts in other storefronts of that language (aso-basics: free
|
|
keyword room), so do not repeat the same keywords across en-US / en-GB / en-AU.
|
|
- Screenshots captions are separate (`store/shots/copy.json`, store-screenshots skill); in-app product texts are in
|
|
the config (`products[].listings`).
|
|
- A store rejects the whole listing update when one field is over its limit: run `listing check` before pushing.
|