<p>How have you implemented Internationalization (i18n) in actual projects you've worked on?</p>

<p>I took an interest in making software cross-cultural after I read the famous post by Joel, <a href="http://www.joelonsoftware.com/articles/Unicode.html" rel="noreferrer">The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)</a>. However, I have yet to able to take advantage of this in a real project, besides making sure I used Unicode strings where possible. But making all your strings Unicode and ensuring you understand what encoding everything you work with is in is just the tip of the i18n iceberg.</p>

<p>Everything I have worked on to date has been for use by a controlled set of US English speaking people, or i18n just wasn't something we had time to work on before pushing the project live. So I am looking for any tips or war stories people have about making software more localized in real world projects.</p>

I worked on a project for my previous employer that used .NET, and there was a built in .resx format we used.  We basically had a file that had all translations in the .resx file, and then multiple files with different translations.  The consequence of this is that you have to be very diligent about ensuring that all strings visible in the application are stored in the .resx, and anytime one is changed you have to update all languages you support.
If you get lazy and don't notify the people in charge of translations, or you embed strings without going through your localization system, it will be a nightmare to try and fix it later.  Similarly, if localization is an afterthought, it will be very difficult to put in place.  Bottom line, if you don't have all visible strings stored externally in a standard place, it will be very difficult to find all that need to be localized.
One other note, very strictly avoid concatenating visible strings directly, such as
```
```
String message = "The " + item + " is on sale!";
```
```
Instead, you must use something like
```
```
String message = String.Format("The {0} is on sale!", item);
```
```
The reason for this is that different languages often order the words differently, and concatenating strings directly will need a new build to fix, but if you used some kind of string replacement mechanism like above, you can modify your .resx file (or whatever localization files you use) for the specific language that needs to reorder the words.