One Tuesday afternoon in May 2026, the new feature I had just added to one of my iOS wallpaper apps left another set of strings waiting for translation across eight languages. Opening Localizable.xcstrings showed a row of empty cells stretching across English, Simplified Chinese, Traditional Chinese, Korean, Spanish, French, German, and Portuguese — each waiting to be filled in. A typical release adds 8–12 new keys, and once you multiply that by eight languages, an hour disappears before you realize.
I have been shipping iOS apps on my own since 2014, and the wallpaper, calm, and inspiration apps I run have grown to a combined 50 million downloads. International users make up a large share of that base. English speakers dominate, of course, but reviews from Germany, Brazil, and Taiwan reach me every week. Because of that, I have always wanted to avoid leaving localization in a purely mechanical state — the wording should feel natural in each language.
Two weeks ago I started letting Antigravity handle the first pass. Full automation was never the goal. I wanted to move from "filling each cell of the xcstrings editor by hand" to "letting the AI draft, and stepping in only for final adjustments." Here are the workflow that settled in, the unexpected behaviors I ran into, and what I noticed once existing translations were brought into the loop.
Why I started — separating the "mechanical" part from the "judgment" part
A mentor I met online when I was 17 once told me that art is a natural language open to everyone. That memory comes back every time I work on localization. Even a single string in an app should reach speakers of that language naturally — otherwise I have not really put that lesson into practice.
That said, deciding whether "Continue" should be "Fortsetzen" or "Weiter", or how to say "You're all set" naturally in Korean, from scratch each time, feels closer to dictionary lookup than to judgment. If you simply remembered the phrasing from past releases or Apple's guidelines, the choice would take a second. Instead, every release was a slow re-derivation. That repetition started feeling like the "mechanical" part to me earlier this spring.
Both of my grandfathers were temple carpenters in Japan, and I have always resisted the idea of treating handwork lightly. But those grandfathers separated marking out the wood from the carving — two different rhythms, two different concentrations. I was the one mixing the two together.
What I delegated and what I kept
The first thing I decided was where to draw the line for Antigravity. Localizable.xcstrings is a JSON-based file, so Antigravity can read and write it directly. But handing everything to the AI would risk drift from the phrasing I had used in prior releases. So I split it like this.
- Delegated to the AI: first-pass translation for newly added keys across all 8 languages, generation of context comments, lookups for similar prior keys to keep phrasing consistent, and flipping
statetotranslatedinside the xcstrings file. - Kept under my final judgment: brand-flavored strings (app names, mode names, paid feature names), any alert wording that App Review tends to scrutinize, final approval of every first draft, and release-notes translation.
- Shared between us: cases where a new draft conflicts in nuance with an existing translation — whether to follow precedent or rephrase both.
In short, I let the AI handle the draft and the consistency check, while the final string that ships to users stays with me. The boundary shifted a few times in the first few days but settled by the middle of the second week.
The workflow that emerged after two weeks
The routine runs whenever I add new keys.
- In Xcode, I add the new keys to
Localizable.xcstringsand finalize the English source. - In Antigravity's chat, I drop the xcstrings file and say: "Translate only the new untranslated cells into the eight target languages. If similar phrasing exists in past keys, follow it."
- Antigravity reads the file, picks out keys whose
stateisnew, and drafts translations for each language. - When something might conflict with existing wording, Antigravity comes back asking: "Should this align with the phrasing in key XXX, or use a different one?"
- I reply with a direction, and Antigravity writes the diff back into the xcstrings file (still unstaged in git).
- I open the xcstrings editor in Xcode and review every generated cell visually, fixing only the ones that feel off.
- I build and run on a device to confirm there are no truncations or layout breaks, then commit.
On the first day, 8 keys × 8 languages — 64 cells in total — went from draft to final in about 20 minutes. By the second week the routine settled at 10–15 minutes. The same work used to take me 45–60 minutes, so the saved time goes straight back into actual implementation.
Unexpected behaviors and how I handled them
Not everything went smoothly. Three issues in particular are worth recording.
First, the handling of Plural Variations. Plural support in xcstrings is more organized than the older .stringsdict setup, but several languages need categories beyond one and other — zero, two, few, many. My first request to Antigravity left only other populated in Russian, leaving few empty. Once I added "if the target language requires the zero, two, few, or many categories, fill those in as well" to the prompt, the gaps disappeared.
Second, format specifiers like %@ and %lld. Antigravity rearranged %@ to fit the natural word order of each language, which was useful, but in a few early cases it rewrote %@ as %s. That fails at compile time, so it is not catastrophic, but catching it in CI is a frustrating timesink. I added "do not change format specifiers (%@, %lld, %.2f, etc.) — only their position may move to fit word order" and the issue went away.
Third, consistency checks against existing translations. This got better over time, but at first the AI could not decide what to do when a past release had translated the same concept inconsistently — "閉じる" versus "閉じる" versus "とじる" in Japanese, for example. I now keep a phrasing glossary at _documents/style_glossary.md for the project and have Antigravity reference it on every run. The drift has nearly disappeared.
Reconciling against existing translations
This took the most thought before going into the routine. Since Localizable.xcstrings itself functions as a database of past translations, I wanted the AI to check against precedent every time.
The implementation is simple: I paste the full xcstrings into every prompt sent to Antigravity. The context grows, but my xcstrings files sit between 3 and 8 KB across all four apps, so context pressure has not been an issue.
For the day when xcstrings inevitably grows larger, I have prepared a separate sub-agent in Antigravity's Workspace whose sole job is to look up related past keys and quote them. It barely fires today, but I expect to switch to it once any project crosses a few hundred keys.
What the recovered time has shown me
Net savings come out to roughly 30–40 minutes per round of new keys. With 4–6 releases a month, that totals 2–4 hours. That alone is not dramatic, but the bigger shift is that the time has eliminated my habit of postponing releases simply because localization had not caught up.
Before this, two or three times a month I would push a release back a week because "the feature is ready, but the translations are not." That rarely happens now. Once the feature is done, the release can ship the same day.
A side effect: the context comments inside the xcstrings file are now written with more care. I add them as background for the AI, and the result is that a future reader — quite often my future self — has an easier time. I sometimes think about my children, who live apart from me, and quietly hope that something of what I make reaches them someday. It turns out that "future reader" is also future me, and that has been a gentle realization.
What comes next
In the short term, I plan to add two or three more languages. Turkish and Arabic have started appearing more in recent reviews, and now that the drafting layer is in place, the addition feels less costly. Arabic will need an RTL layout pass, so the next two weeks will mostly be about splitting that work cleanly between Antigravity and myself.
Longer term, I want to apply the same pattern — AI drafts, human finalizes — to App Store Connect metadata: descriptions, keywords, screenshot captions. If the rhythm that worked for xcstrings carries over, another chunk of release time should come back.
I hope some of this is useful if you are working through multi-language support on your own apps. Thank you for reading along.