Translate your app with XCStringsLocalizer
By Tyler Hillsman
November 20, 2025

We’re living in a golden age of seemingly magical robots being able to read human-written words, and one of the thing that LLMs are relatively incredible at is language translation. A couple years ago, I introduced localization in Sticky Widgets. I took a look at my analytics to see what locales users’ devices reported and translated my top six non-English locales. Relatively straight-forward (assuming you’re doing the Apple-suggested thing of using LocalizedStringKey instead of raw Strings, etc) and Xcode’s relatively new XCStrings catalog made it clear what I’d translated and what I had yet to do. Unfortunately, getting the actual strings in the catalog was a bit monotonous and - in this world of AI agents helping me streamline the monotonous, it was only a matter of time before I improved this process.

Enter XCStringsLocalizer, my new command line tool that does all the work for me. I built this to scratch my own itch and solve this problem, but realized I’m certainly not the only one with it. Enough justifying, here’s how you use it:

  • You’re going to need an OpenAI API key. Sorry, you can’t use mine. This, of course, costs money, but it’s pennies and nickels instead of much more costlier services. Create an account and make an API key on OpenAI’s console. (Yes, I can and probably will add other providers, but I had to start somewhere.)
  • As I mentioned up top, you’re going to need an Xcode project with localization turned on and an XCStrings catalog file. New projects should get them, old ones may need you to click Edit > Convert > To String Catalogs… (Yes, I can and probably will make it work with older-style .strings files or maybe the .xliff files Xcode can output, but I had to start somewhere.)
  • Ideally, you’ll have also provided comments to your strings catalog as well. When a button says “Save note”, what does it mean? A document, an internal comment, a music note? The better the comment, the more accurate the translation.
  • Once your project is all good to go, you’ll need the tool. Open Terminal and run curl -fsSL https://raw.githubusercontent.com/thillsman/XCStringsLocalizer/main/install.sh | bash. (There are many other ways to get it as well, but I wanted a handy one-liner. See more installation options in the README.) You’ll probably have to enter your password. This is making the tool accessible from anywhere on your system.
  • Make a simple text file in your project called .env and add this text to it: OPENAI_API_KEY='your-api-key-here' except with your actual API key from above. You can (and probably should) add a new line with APP_DESCRIPTION='Some description of your app' on a new line as well. This will provide context about your app to the LLM so it can make better translations. Add .env to your .gitignore file so you’re not committing your API key.
  • Now open your app directory in your terminal application of choice and run xcstrings-localizer.

Did that work? I hope it worked. It should be zooming through your untranslated strings and updating your file for you. …or maybe your project is already good to go and it says there’s nothing for it to do.

There are a ton of customization options: Want to pass in xcstrings files instead of having it auto-detect them? Sure, it can do that. What if you want to just do a language at a time? Yep, easy peasy. What if you want the full size gpt-5 model instead of lil gpt-5-mini? Whoa, big spender, you can do that if you want.

There are also a few extra features: When our apps are localized, we should also localize our App Store descriptions and release notes. With this tool, you can make a /localized-extras directory and put any text file in it, and xcstrings-localizer will pick it up and translate it as well. Also, if you have already translated some strings but want a second opinion, try the “suggest” command to have the tool translate your base string, then compare its translation against what you already have, providing rationale if it’s better.

There is a lot more to come. I’ve got some ideas that I might add to this, but for now, here’s what I’ve got for you. Check it out, see how it works, and go forth and localize!