C++ std::locale | Internationalization and formatting guide
이 글의 핵심
Practical notes on std::locale: imbue on streams, parsing locale-dependent numbers, avoiding global locale changes, and when to prefer ICU or fixed protocols.
Basic usage
#include <locale>
#include <iostream>
using namespace std;
int main() {
// Current locale
locale currentLocale;
cout << currentLocale.name() << endl;
// Set global locale (example name — adjust to your system)
locale::global(locale("en_US.UTF-8"));
// Apply to stream
cout.imbue(locale());
}
Number formatting
#include <locale>
#include <iomanip>
int main() {
// Thousands separators
cout.imbue(locale("en_US.UTF-8"));
cout << 1234567 << endl; // 1,234,567
// Money
cout << showbase << put_money(123456) << endl; // e.g. $1,234.56
}
Date and time
#include <locale>
#include <iomanip>
int main() {
auto now = chrono::system_clock::now();
auto time = chrono::system_clock::to_time_t(now);
// Example locale
cout.imbue(locale("ko_KR.UTF-8"));
cout << put_time(localtime(&time), "%c") << endl;
cout.imbue(locale("en_US.UTF-8"));
cout << put_time(localtime(&time), "%c") << endl;
}
Practical examples
Example 1: Simple message map (i18n sketch)
#include <map>
class I18n {
private:
map<string, map<string, string>> messages;
string currentLang = "en";
public:
void addMessage(const string& lang, const string& key, const string& value) {
messages[lang][key] = value;
}
void setLanguage(const string& lang) {
currentLang = lang;
}
string get(const string& key) const {
auto langIt = messages.find(currentLang);
if (langIt != messages.end()) {
auto msgIt = langIt->second.find(key);
if (msgIt != langIt->second.end()) {
return msgIt->second;
}
}
return key; // fallback
}
};
int main() {
I18n i18n;
i18n.addMessage("en", "hello", "Hello");
i18n.addMessage("en", "goodbye", "Goodbye");
i18n.addMessage("ko", "hello", "안녕하세요");
i18n.addMessage("ko", "goodbye", "안녕히 가세요");
i18n.setLanguage("ko");
cout << i18n.get("hello") << endl;
cout << i18n.get("goodbye") << endl;
}
Example 2: Parsing numbers with a locale
double parseNumber(const string& str, const locale& loc) {
istringstream iss(str);
iss.imbue(loc);
double value;
iss >> value;
return value;
}
int main() {
double us = parseNumber("1,234.56", locale("en_US.UTF-8"));
cout << us << endl; // 1234.56
double eu = parseNumber("1.234,56", locale("de_DE.UTF-8"));
cout << eu << endl; // 1234.56
}
Example 3: Character classification
#include <locale>
int main() {
locale loc("en_US.UTF-8");
char c = 'A';
if (isalpha(c, loc)) {
cout << c << " is alphabetic" << endl;
}
if (isupper(c, loc)) {
cout << c << " is uppercase" << endl;
}
char lower = tolower(c, loc);
cout << "lower: " << lower << endl; // a
}
Currency formatting
#include <iomanip>
int main() {
cout.imbue(locale("en_US.UTF-8"));
cout << showbase << put_money(123456) << endl;
cout.imbue(locale("ko_KR.UTF-8"));
cout << showbase << put_money(123456) << endl;
}
Common pitfalls
Pitfall 1: Locale not installed
try {
locale loc("ko_KR.UTF-8");
} catch (const runtime_error& e) {
cout << "locale not available" << endl;
}
// Install locales on Linux: locale-gen, etc.
Pitfall 2: Changing the global locale
// ❌ Affects unrelated code
locale::global(locale("ko_KR.UTF-8"));
// ✅ Per-stream
cout.imbue(locale("ko_KR.UTF-8"));
Pitfall 3: Performance
// ❌ Constructing a locale each iteration
for (int i = 0; i < 1000; i++) {
locale loc("en_US.UTF-8");
}
// ✅ Reuse
locale loc("en_US.UTF-8");
for (int i = 0; i < 1000; i++) {
}
FAQ
Q1: When do I use locale?
A:
- Multilingual UI strings (often with higher-level i18n systems)
- Locale-specific number and date display
- Currency formatting
- Character classification
Q2: Performance overhead?
A: Some. For tight loops, consider fixed formats or custom formatting.
Q3: UTF-8 support?
A: Improved in newer standards; legacy behavior can still be limited—verify on your targets.
Q4: Which locale strings?
A: Common examples: en_US.UTF-8, ko_KR.UTF-8, ja_JP.UTF-8—availability depends on the OS.
Q5: How do I list locales?
A: On Unix, locale -a.
Q6: Learning resources?
A:
- cppreference.com — std::locale
- The C++ Standard Library
- ICU documentation for full Unicode handling
Related posts (internal)
- C++ string_view
- C++ Allocator guide
- C++ Chrono guide
Practical tips
Debugging
- Fix compiler warnings first.
- Reproduce with a small test.
Performance
- Profile before optimizing.
- Set measurable targets.
Code review
- Follow team conventions.
Production checklist
Before coding
- Right tool for the job?
- Maintainable by the team?
- Meets performance needs?
While coding
- Warnings cleared?
- Edge cases covered?
- Error handling OK?
At review
- Intent clear?
- Tests enough?
- Documented?
Keywords
C++, locale, i18n, localization, formatting
Related posts
- Arrays and lists (algo series)
- C++ Adapter Pattern
- C++ ADL |
- C++ Aggregate Initialization |
- C++ Aggregate Initialization guide