app-localization
Skill0 starsChanged 35 days agoMITView on GitHub
Translate an app into new languages end to end - the app's string files, the server's push notification and email texts, server-side content, native strings such as permission prompts, and the wiring that makes a language selectable and listed on the App Store - using one translating agent per language and a checker each one must pass. Use this whenever the user asks to add a language, translate or localize the app, support German/French/Spanish or any other language, or when a launch plan adds store locales the app itself does not speak yet. Not for App Store listing text (store-listing) or screenshot captions (store-screenshots).
In this repository8 other files it gives its agents.
- app-launchSkill
- app-review-readinessSkill
- app-store-connectSkill
- aso-researchSkill
- eas-releaseSkill
- revenuecat-setupSkill
- store-listingSkill
- store-screenshotsSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 2 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 29
Run the languages in parallel.
- Distinctive: line 63
Run the checker once more on every file after wiring.
- Distinctive: line 66
Ask the owner to switch the test build to one new language and walk the main flow.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
App localization
A localized listing that opens an English app converts badly and reads as a bait and switch. When the store listing is going into a language, the app should be going with it. This skill adds languages without a native speaker on the team, which means the process has to catch the mistakes a reviewer would.
Paths are relative to this skill's folder.
1. Find every place words live
Strings hide in more places than the translation folder. Search before promising a language:
| Where | What to look for | Often forgotten |
| App string files | i18n/, locales/, translations/, *.strings, Localizable.xcstrings | Strings hard-coded in components: grep for JSX text and Alert.alert( |
| Constants shown to users | Unit names, category names, default list names, onboarding samples | Values stored in the database in English and printed as-is |
| Native layer | Permission purpose strings (NSCameraUsageDescription…), app display name, Siri phrases, widgets, Live Activities, notification action titles | In Expo these sit in app.config (ios.infoPlist, locales) and in plugin folders |
| Server | Push notification texts, emails, SMS, server-generated lists or catalogues, error messages returned to the app | The server decides the language from a stored user setting or a header; check which |
| Third parties | Paywall and customer-centre language (RevenueCat), auth screens, in-app review prompt (the system translates that one) | A locale map that falls back to English for languages it does not list |
| Formatting | Dates, numbers, currency, plural rules, sorting | Hand-built strings like count + " items" |
Write the inventory down in store/launch.md with a decision for each: translate now, or leave in English and say so. Report honestly what stays untranslated; "units and Siri replies remain English" is a fine thing to tell the owner, and a bad thing for them to discover.
2. Translate with one agent per language
Run the languages in parallel. Each agent writes exactly one file (plus its server counterparts) and may not stop until the checker prints OK:
node scripts/check-locale.mjs <base file> <locale file>It compares keys, placeholders ({{name}}, {name}, %s, tags), plural families and line breaks, and lists strings identical to the base and short labels that grew a lot. It reads .json and .ts/.js modules.
Brief each agent with:
- The base file, and one existing translation as a format example (same file layout, same export name, same casts).
- What the app is and who uses it, in two sentences, and the register to use (informal "du"/"tu" for a consumer app is usual; say which).
- A glossary of the app's own nouns with the chosen translation, so "list", "household", "trip" are the same word on every screen. Have the first agent propose it if none exists.
- "Buttons, tabs and chips are narrow. Keep them as short as the English or shorter. Never translate the brand name or placeholders."
- "Use the words the platform uses": the iOS system's own translations for Settings, Share, Delete, Cancel, Done.
- "Nobody on the team reads this language. You are the native-speaker check. End with a list of strings you are unsure about, and why."
- For server content with length caps (catalogue items, notification titles), the cap.
Spain's Spanish and Mexico's differ in everyday nouns (zumo/jugo, patatas/papas, coche/carro). One app language usually serves both, so choose one deliberately and note it.
3. Wire the language in
A translated file does nothing until the app knows about it:
- Register it in the i18n setup (resources, supported-language list, fallback).
- Language detection: the device language should select any supported language, not only the original two. Replace hard-coded checks (
lang === "ar" ? … : "en") with a lookup in the supported list. - The in-app language picker: it will now be longer. A fixed-height sheet that fitted two rows will clip seven; make it scroll.
CFBundleLocalizations(Expo:ios.infoPlist.CFBundleLocalizations, or thelocalesconfig). Without it iOS does not offer the app's language in Settings and the App Store does not list the language on the product page. This is a native change: it needs a new build, not an over-the-air update.- Third-party locale maps (paywall, auth) and the server's language enum, validation and fallback.
- Right-to-left languages need layout work as well as words. Treat adding the first RTL language as a feature, not a translation.
4. Verify what can be verified
- Type-check and run the app's tests; a missing key in a typed locale file should fail the build.
- Run the checker once more on every file after wiring.
- Render or open the busiest screens in the longest language (usually German) and look for clipping.
- The server ships first. An app that asks for German pushes from a server that only knows English and Arabic falls back at best and errors at worst. Deploy to staging, test, then production, per
../app-launch/references/release-sequencing.md. - Ask the owner to switch the test build to one new language and walk the main flow. This is an owner input: they are the only one with the device. Say exactly which screens to look at.
State plainly in the report what no one has checked: "no native speaker has read any of these" is true until someone has.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

