Question: I'm playing around with the locale and I18N stuff in c++ and have been looking for real world examples. I've read through the Josuttis chapter on I18N in his [book](http://www.josuttis.com/libbook/) (2nd Edition for C++11 to be released April 2012), and found it useful but with no real world examples to draw from I've no idea if I'm following best practices are committing beginner mistakes. What resources can StackOverflow point me towards both on the web and in print for doing I18N stuff in C++?

Also what libraries are available for C++ that makes i18n easier? What's not in the standard library that needs to be? At first glance, it seems that UTF8 support doesn't exist in the standard library.

Edit:

After doing some more reading, it seems that C and C++ are both Unicode "agnostic". It also seems that for dealing with data encoded in Unicode/UTF8/16/32 one needs to use a third party library. The crux of this is that the standard library itself only thinks about ISO 8859 and related character pages, which change based on what you're locale is set to. That means I probably want to use the ICU library for strings rather than using `std::string` or even `std::wstring`.

Answer: 
Take a look at [wxWidgets](http://wxwidgets.org/) examples of internationalization. It has a non-gnu implementation of the translation mechanism used in [gettext](http://www.gnu.org/software/gettext/) (mentioned previously). You can use it even in commercial application because the wxWidgets license allows you to do so.

If you are just looking at a method for internationalizing the application gettext is the starting point.
Why not keep it simple and roll your own with modern C++:

`Internationalization.hpp`:

```
#pragma once

#include <map>
#include <string>

enum class supported_language_t
{
    english,
    chinese
};

inline std::string hello_world_map_key = "hello-world";
inline std::string hello_map_key = "hello";

inline supported_language_t supported_language = supported_language_t::chinese;

std::string get_translated_string(const std::string& key);

```

`Internationalization.cpp`:

```
#include "Internationalization.hpp"
#include <stdexcept>
#include <magic_enum.hpp>

std::map<std::string, std::string> english_translations =
{
    {hello_world_map_key, "Hello, world!"},
    {hello_map_key, "Hello {}!"}
};

std::map<std::string, std::string> chinese_translations =
{
    {hello_world_map_key, "你好，世界!"},
    {hello_map_key, "你好 {}!"}
};

std::string get_translated_string(const std::string& key)
{
    switch (supported_language)
    {
        case supported_language_t::chinese:
            return chinese_translations.at(key);

        case supported_language_t::english:
            return english_translations.at(key);

        default:
            throw std::runtime_error("Unsupported language: " + std::string(magic_enum::enum_name(supported_language)));
    }
}

```

How to use it:

```
const auto hello_world_transated = get_translated_string(hello_world_map_key); // "你好，世界!"
const auto hello_translated = std::format(get_translated_string(hello_map_key), "StackOverflow"); // "你好 StackOverflow!"

```

As you can see it works even with placeholders thanks to C++20's `std::format`.