Software Localization Best Practices: Complete Developer Guide

Learn software localization best practices: prepare code, handle dynamic content, and create flexible UI layouts for global markets. Complete guide with examples and a free translation tool.

Your app just launched in France. Traffic is up, sign-ups are rolling in, and then the support tickets start flooding your inbox. Users can’t click the “Buy now” button because it’s been cut off. Forms won’t submit. Navigation menus are breaking across two lines. Your carefully-designed UI looks completely broken.

This is what happens when you skip the software localization process and jump straight to translation. The text gets translated, but your app wasn’t built to handle it.

Here’s what the problem might look like:

The reason? Because your code looks something like this:

CSS
<button style="width: 120px">Save Changes</button>

This guide walks you through exactly what to do before you translate a single string. You’ll learn how to:

By the end, you’ll know how to ship localized software that actually works—not just software that’s been translated.

Step 1: Start Using Separate Files for Localizable Content

Here’s what happens when you hard-code strings: Translation tools scan your codebase looking for text to translate in resource files like JSON, PO, or YAML. They find… nothing. Because they can’t detect strings buried inside your JavaScript, PHP, or Ruby files.

This is the most common mistake in software localization. Most failed localization projects die right here because teams realize too late that they need to refactor thousands of hard-coded strings.

What Counts as User-Facing Text?

Everything your users can see:

  • UI labels, buttons, and menu items
  • Error messages and validation text
  • Email templates and notifications
  • Help text, tooltips, and placeholder text
  • Success/confirmation messages

All of this needs to go into separate files.

React example:

JSX
// Wrong - hard-coded
<button>Submit</button>

// Right - using react-intl
<button>{t('submit_button')}</button>

WordPress example:

PHP
// Wrong - hard-coded
echo 'Submit';

// Right - using WordPress i18n
echo __( 'Submit', 'your-textdomain' );

Rails example:

Ruby
# Wrong - hard-coded
flash[:notice] = "Profile updated successfully"

# Right - using Rails I18n
flash[:notice] = t('profile.update_success')

Which File Format Should You Use?

Select the resource file format based on your framework:

  • .json – JavaScript frameworks (React, Vue, Angular)
  • .po/.pot – WordPress, PHP, Python (gettext)
  • .yaml/.yml – Ruby on Rails
  • .xml – Android (strings.xml)
  • .xcstrings – iOS/macOS

Step 2: Handle Placeholders and Dynamic Content Properly

When you include user data in strings—like names, numbers, or dates—don’t use string concatenation.

Different languages have different word orders. Concatenation breaks this by splitting sentences into fragments that can’t be reordered.

The example below creates three separate pieces that translators can’t rearrange. In languages like Japanese where word order differs from English, the translation becomes grammatically incorrect.

Incorrect Example (String Concatenation)

const name = 'John';
const message = 'Hello, ' + name + '!';

Instead, use placeholders that let translators control the full sentence:

Correct Examples

PO File:

msgid "Hello, %s!"
msgstr ""

JSON File:

{
  "greeting": "Hello, {name}!"
}

YAML File:

greeting: "Hello, %{name}!"

Make sure to use placeholder syntax that works with your framework:

File FormatCommon Placeholder SyntaxUsed In
.json{name}JavaScript (React, Vue)
.yaml%{name}Ruby on Rails
.po%s, %d, %1$s, %2$dWordPress, PHP
.xml%1$s, %2$dAndroid
.strings%@, %d, %fiOS/macOS

Step 3: Design for Text Expansion

Remember that button from the intro? The one that said “Save” in English but got cut off in French?

That’s text expansion, and it’s not rare. Here’s what you’re up against:

  • German text is typically 30% longer than English
  • French runs about 20% longer
  • Chinese and Japanese are often shorter (but have other problems)

These are averages, and individual words can balloon. “FAQ” becomes “Preguntas frecuentes” in Spanish—that’s a 567% expansion.

Before you start coding, think through how different languages impact space during the design phase. Use flexible patterns, so that buttons can grow with the text instead of getting cut off. This saves time debugging layout issues later.

For a deeper dive into layout patterns, see how to prevent layout issues with long translations.

Step 4: Write Content That’s Actually Translatable

Your writing style matters more than you think. Vague, clever, or idiomatic English can become nonsense in other languages.

Write Full Sentences

A string like “No cart items” could mean multiple things. There is no cart? Items aren’t in the cart? Your translator (or translation tool) has to guess.

A clear subject with a clear verb makes the meaning clear, which also makes the string easy to translate.

Correct Example

"You have no saved items in your cart."

This clearly states what’s empty (cart) and what it should contain (saved items).

Avoid Idioms

“This is a piece of cake” is often used in English, but doesn’t translate well into other languages. If translated literally, your German users will be very confused about why your app is talking about dessert.

Keep It Simple

Don’t say “eliminate” when “remove” works. Don’t say “utilize” when you can say “use”. Simple words translate more reliably and clearly.

Step 5: Set Up Language Detection

Once your strings are externalized and your UI is flexible, you need to detect which language to show each user.

Most frameworks include i18n libraries that handle this automatically:

  • React with react-i18next

Install react-i18next with npm, then configure it to detect the browser language and load your translation files.

  • Ruby on Rails

Rails includes I18n by default. Configure it in config/application.rb. Then, detect the user’s language in your ApplicationController.

  • WordPress

WordPress handles language detection automatically. Users set their site language in Settings → General, and WordPress loads the corresponding .mo file from wp-content/languages/. For multilingual sites where different users need different languages, you’ll need a plugin like WPML to handle per-user language selection.

Set a Fallback Language

Set your fallback language to your primary language. When a translation file doesn’t exist or strings are missing, users see the fallback instead of broken text or translation keys.

Add a Language Switcher (If Needed)

Most applications should respect the user’s browser or device language settings automatically. But if you want to let users manually override this—common for web applications—add a language switcher and store their choice:

JavaScript
// Save user's manual language selection
localStorage.setItem('userLanguage', selectedLanguage);

// Check for manual selection first, then use browser default
const userLanguage = localStorage.getItem('userLanguage') || navigator.language;

Mobile apps typically don’t include language switchers since users expect apps to follow their device settings.

Step 6: Automate Your Software Translation Process

If your localization process looks like this, you’re doing it wrong:

  1. Export strings to spreadsheet
  2. Email spreadsheet to translator
  3. Wait 3 days
  4. Get spreadsheet back
  5. Manually copy translations into JSON files
  6. Discover you missed 12 strings
  7. Repeat

This is slow, error-prone, and doesn’t scale.

Here’s what you should do instead: use a translation tool that provides continuous localization.

PTC is an AI translation tool that automates the translation process. You can integrate it with your GitHub, GitLab, or Bitbucket repository, or use the API for CI/CD integration. When you update strings, translations happen automatically.

It’s free for 10,000 words in 2 languages, then you pay only for what you translate. No subscription, and getting started takes less than 5 minutes.

Step 7: Test Localized Versions Before Launch

You shouldn’t stop at just checking if the translated text shows up. Test the actual functionality in each language.

  • Layout: Does text fit without getting cut off? Does the navigation still work, or are you seeing overflow?
  • Functionality: Do forms submit? Do error messages show in the right language? Does search handle accented characters (é, ñ, ü)?
  • Formatting: Are dates in the right format (DD/MM vs MM/DD)? Are numbers formatted correctly (1,000.00 vs 1.000,00)? Is currency in the right position (€100 vs 100€)?

Test this before you ship to production. Finding out your German checkout flow is broken when users start leaving negative reviews is not the way you want to discover localization bugs.

You’re Ready for Software Localization

That’s it. If you’ve done these 7 things, your app is ready for localization. Now translate your resource files with PTC and ship software that works in every language.

Translate Your Software Using AI

Get context-aware translations in minutes

Upload files, or automate via API or Git integration


1

Start a free trial

Translate 10,000 words for free.

2

Add quick project details

Give context about your app and users.

3

Get translations

Download a ZIP, or merge in your repo.

Scroll to Top