2
0
mirror of https://github.com/boostorg/locale.git synced 2026-01-19 04:22:08 +00:00
Files
locale/doc/localized_text_formatting.txt
2022-10-27 20:33:32 +02:00

164 lines
6.2 KiB
Plaintext

//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
/*!
\page localized_text_formatting Localized Text Formatting
The \c iostream manipulators are very useful, but when we create messages for the user, sometimes we need something
like good old \c printf or \c boost::format.
Unfortunately \c boost::format has several limitations in the context of localization:
-# It renders all parameters using global locale rather than target \c ostream locale. For example:
\n
\code
std::locale::global(std::locale("en_US.UTF-8"));
output.imbue(std::locale("de_DE.UTF-8"))
output << boost::format("%1%") % 1234.345;
\endcode
\n
This would write "1,234.235" to output, instead of the "1.234,234" that is expected for "de_DE" locale.
-# It knows nothing about the Boost.Locale manipulators.
-# The \c printf-like syntax is very limited for formatting complex localized data, not allowing
the formatting of dates, times, or currencies
Thus a new class, boost::locale::format, is introduced. For example:
\code
wcout << wformat(L"Today {1,date} I would meet {2} at home") % time(0) % name <<endl;
\endcode
Each format specifier is enclosed within \c {} brackets, is separated with a comma ",", and
may have an additional option after an equals symbol '='. This option may be simple ASCII text or single-quoted localized text.
If a single-quote should be inserted within the text, it may be represented with a pair of single-quote characters.
Here is an example of a format string:
\verbatim
"Ms. {1} had arrived at {2,ftime='%I o''clock'} at home. The exact time is {2,time=full}"
\endverbatim
The syntax is described by the following grammar:
\verbatim
format : '{' parameters '}'
parameters: parameter | parameter ',' parameters;
parameter : key ["=" value] ;
key : [0-9a-zA-Z<>]+ ;
value : ascii-string-excluding-"}"-and="," | local-string ;
local-string : quoted-text | quoted-text local-string;
quoted-text : '[^']*' ;
\endverbatim
You can include a literal '{' and '}' by inserting double "{{" or "}}"
into the text.
\code
cout << format(translate("Unexpected `{{' in line {1} in file {2}")) % pos % file;
\endcode
Would display something like:
\verbatim
Unexpected `{' in line 5 in file source.cpp
\endverbatim
The following format key-value pairs are supported:
- <tt>[0-9]+</tt> -- digits, the index of the formatted parameter -- required.
- \c num or \c number -- format a number. Options are:
\n
- \c hex -- display in hexadecimal format
- \c oct -- display in octal format
- \c sci or \c scientific -- display in scientific format
- \c fix or \c fixed -- display in fixed format
\n
For example, \c number=sci
- \c cur or \c currency -- format currency. Options are:
\n
- \c iso -- display using ISO currency symbol.
- \c nat or \c national -- display using national currency symbol.
\n
- \c per or \c percent -- format a percentage value.
- \c date, \c time, \c datetime or \c dt -- format a date, a time, or a date and time. Options are:
\n
- \c s or \c short -- display in short format.
- \c m or \c medium -- display in medium format.
- \c l or \c long -- display in long format.
- \c f or \c full -- display in full format.
- \c ftime with string (quoted) parameter -- display as with \c strftime. See \c as::ftime manipulator.
- \c spell or \c spellout -- spell the number.
- \c ord or \c ordinal -- format an ordinal number (1st, 2nd... etc)
- \c left or \c < -- align-left.
- \c right or \c > -- align-right.
- \c width or \c w -- set field width (requires parameter).
- \c precision or \c p -- set precision (requires parameter).
- \c locale -- with parameter -- switch locales for the current operation. This command generates a locale
with formatting facets, giving more fine grained control of formatting. For example:
\n
\code
cout << format("This article was published at {1,date=l} (Gregorian) {1,locale=he_IL@calendar=hebrew,date=l} (Hebrew)") % date;
\endcode
- \c timezone or \c tz -- the name of the timezone to display the time in. For example:\n
\code
cout << format("Time is: Local {1,time}, ({1,time,tz=EET} Eastern European Time)") % date;
\endcode
- \c local - display the time in local time
- \c gmt - display the time in UTC time scale
\code
cout << format("Local time is: {1,time,local}, universal time is {1,time,gmt}") % time;
\endcode
The constructor for the \ref boost::locale::format "format" class can take an object of type \ref boost::locale::message "message", simplifying integration with message translation code.
For example:
\code
cout<< format(translate("Adding {1} to {2}, we get {3}")) % a % b % (a+b) << endl;
\endcode
A formatted string can be fetched directly by using the \ref boost::locale::format::str() "str(std::locale const &loc=std::locale())" member function. For example:
\code
std::wstring de = (wformat(translate("Adding {1} to {2}, we get {3}")) % a % b % (a+b)).str(de_locale);
std::wstring fr = (wformat(translate("Adding {1} to {2}, we get {3}")) % a % b % (a+b)).str(fr_locale);
\endcode
\note There is one significant difference between \c boost::format and \c boost::locale::format: Boost.Locale's format converts its
parameters only when written to an \c ostream or when the `str()` member function is called. It only saves references to the objects that
can be written to a stream.
This is generally not a problem when all operations are done in one statement, such as:
\code
cout << format("Adding {1} to {2}, we get {3}") % a % b % (a+b);
\endcode
Because the temporary value of \c (a+b) exists until the formatted data is actually written to the stream. But following code is wrong:
\code
format fmt("Adding {1} to {2}, we get {3}");
fmt % a;
fmt % b;
fmt % (a+b);
cout << fmt;
\endcode
Because the temporary value of \c (a+b) no longer exists when \c fmt is written to the stream. A correct solution would be:
\code
format fmt("Adding {1} to {2}, we get {3}");
fmt % a;
fmt % b;
int a_plus_b = a+b;
fmt % a_plus_b;
cout << fmt;
\endcode
*/