Subject: Re: [Boost-bugs] [Boost C++ Libraries] #7266: Gettext path formats.
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2013-01-07 06:37:56
#7266: Gettext path formats.
--------------------------------------+-------------------------------------
Reporter: 166291@⦠| Owner: artyom
Type: Patches | Status: assigned
Milestone: Boost 1.54.0 | Component: locale
Version: Boost Development Trunk | Severity: Not Applicable
Resolution: | Keywords:
--------------------------------------+-------------------------------------
Comment (by 166291@â¦):
Okay, I've thought about this a lot and concluded that path formats are
the wrong way to go about this in the short term, and only end up with
technical debt. It should be handled by a callback class that receives
information about the wanted catalog (locale name. category, etc) and
returns the bytes of the file, as this is technically about custom file
system support.
I haven't actually coded anything yet, but this is how I'll think it'd
work, and more importantly, why it'd be better:
{{{
// --- BOOST.LOCALE CODE
//! Information about a single catalog we want to find.
class catalog_info
{
string language;
string country;
string variant;
string encoding;
string locale_category;
string domain;
};
//! Searches for, and loads a catalog.
class default_catalog_loader
{
public:
void add_search_path(string const& path);
void add_path_format(string const& path);
vector<byte> callback(catalog_info& info)
{
vector<string> paths;
paths += language;
paths += language + "_" + country + "@" + variant;
paths += language + "@" + variant;
paths += language + "_" + country;
foreach(search_path in search_paths)
{
foreach(path_format in path_formats)
{
foreach(path in paths)
{
string formatted = format(insert uber long line from existing
code);
if(FILE_EXISTS(formatted))
{
// LOAD_FILE is hypothetical and utopian, thus UTF-8
encoded.
return LOAD_FILE(formatted));
}
}
}
}
return vector<byte>(); // Empty vector.
}
}
// --- USER CODE
std::locale init_locale(void)
{
default_catalog_loader loader;
loader.add_search_path("/usr/share/locale/");
loader.add_path_format("{1}/{2}/{3}/{4}.mo");
generator gen;
std::locale genLoc = gen("en_US.UTF-8");
blg::messages_info info;
info.language = "en";
info.country = "US";
info.encoding = "UTF-8";
info.variant = "@euro";
info.callback = boost::bind(loader::callback, &loader, _1, _2);
std::locale gettextLoc(genLoc, blg::create_messages_facet<char>(info));
return gettextLoc;
}
}}}
That would do what the existing code does (kind of, I'm sure I've
forgotten something). Plus it means people could do things like this:
{{{
// --- USER CODE
// Include generated headers using bin2hex or something interesting.
#include "en_US.mo.h"
#include "en_at_euro.mo.h"
vector<byte> memory_callback(catalog_info& info)
{
vector<string> paths;
paths += language;
paths += language + "_" + country + "@" + variant;
paths += language + "@" + variant;
paths += language + "_" + country;
foreach(path in paths)
{
byte* file_bytes = GET_MEMORY_FILE(path + ".mo");
if(file_bytes)
{
return VECTOR_FROM_BYTES(file_bytes);
}
}
return vector<byte>(); // Empty vector.
}
}}}
Which implements a simple memory-based file loader. Personally I'd use
this for my projects, as I already use a callback.
I have a few notes on this approach however:
There is shared repetition when looking for paths in multiple callback
code. I don't know how to remove this without calling the callback
multiple times, which is against this design (EXCEPT when we're trying to
load multiple catalogs for multiple domains).
It'd be stupidly easy to have a get_loaded_catalogs method that implements
#7727 in the library side, but it'd be best if it had some 'user' callback
data. In the first case, which path format and search path and formatted
path, in the second case, a pointer to the memory file.
messages_info's callback would need to be changed, breaking the ABI.
However, having a create_messages_facet that ONLY takes a callback in this
case would work.
Another thing is whether callbacks be classes?
While the second example is one function long, making it a class would
remove the horrible bind for class members, it'd allow the loader to be an
interface which would be extendable if done right, I imagine callback data
for catalog_info could be an abstract class defined by the loader too.
What it'd also allow to do is custom file FORMATS, by returning something
that mo_messages could use as a string table. This means for example, I
could write a parser that loads po files uncompiled, or somebody
completely insane could use XML, which I imagine could help transition.
What're your thoughts on this?
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/7266#comment:7> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.
This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:11 UTC