boost::locale 和 std::locale 之间的权衡是什么?

What are the tradeoffs between boost::locale and std::locale?

我正在使用 C++ 对大型遗留代码库进行国际化,我面临着一个艰难的决定:我应该使用 boost::locale 还是标准 c++ 语言环境?

我承诺使用 utf-8。我们必须进行相当广泛的文本处理,虽然这不是我们代码的核心,但它很重要。我们可以期望完成大部分可能需要做的事情:时间、日期、数字和货币格式、整理、正则表达式、子字符串隔离、与 boost::filesystem 的交互、数据库访问等

introduction to boost::locale我明白了

  1. 设置全局语言环境有副作用(csv 示例)。它影响 printf 和 boolst lexical_cast。一些第三方库可能会损坏。
  2. 数字格式在某些语言环境中被破坏。
  3. 区域名称未标准化。
  4. 很多厂商只提供C和POSIX,所以GCC只支持Linux下的本地化。

我无法评估第 1 点的影响我猜第 2 点如果对我们有影响的话会相当严重,广告 3 和 4 对我们来说不是什么大问题。

社区是否一致认为 Boost::locale 是更好的选择?标准承诺中是否有任何动议来解决 std::locale 的问题?谁能帮我做出更明智的决定?

也许最重要的是,从一个迁移到另一个是否简单?两人的配合如何?使用 boost locale 设置全局 locale,然后使用 std 设施是否合法?

Boost.Locale 基于 std::locale 框架,但以更正确的语言方式提供了更多选项。

此外,如果您想在 windows/MSVC 上使用 utf-8,std::locale 是不行的。

最后,boost 文档很好地回答了我的问题,但您必须阅读一些内容,这有助于比我在发帖时更好地理解 std::locale

与 std 完美搭配

一个std::localefacet的集合。该标准定义了每个语言环境必须提供的一组方面,但除此之外似乎大部分都留给了实现。这包括语言环境行为和语言环境的名称。

boost::locale 所做的是提供一堆方面,收集到语言环境中,无论平台如何,它们的行为都相同(至少如果您使用默认的 ICU 后端)。

因此 boost::locale 提供了一组标准化的 std::locale,它们可以跨平台一致地运行,为广泛的文化规范提供完整的 Unicode 支持,并具有一致的命名。在使用非 boost std::locale(即提供语言环境的实现)和 boost::locale 之间切换是微不足道的,因为它们是相同的类型——尽管实现不同,但它们都是 std::facets 的集合. boost::locale 很可能会更好地完成您想要的工作。

在所有平台上为所有编码提供完整的 Unicode 支持
此外,boost::locale 提供了一种通过 ICU 访问完整 unicode 支持的方法,它允许您获得 ICU 的好处,而无需 ICU 的糟糕(不是 C++ish)接口。

这是有利的,因为任何对 Unicode 的标准支持很可能来自语言环境框架,并且任何支持 Unicode 的程序也可能需要支持语言环境(例如用于整理)。

关于数字的理智行为 最后,boost::locale 解决了在 std::locales 的通常实现中可以合法地称为重大缺陷的问题——任何流格式的数字都会受到区域设置的影响,无论这是否可取——请参阅boost documentation 进行详细讨论。

因此,如果您使用 ofstream 来读取或写入文件,并且已将全局设置 locale 设置为您平台的德语语言环境,您将使用逗号分隔浮点数的小数部分。如果您是 reading/writing 一个 csv 文件,那可能是个问题。如果您使用 boost::locale 作为您的全局语言环境,只有当您明确告诉它为您的数字 input/output 使用语言环境约定时才会发生这种情况。请注意,许多库在后台使用区域设置信息,包括 boost::lexical_cast。 std::to_string 就此而言也是如此。因此请考虑以下示例:

std::locale::global(std::locale("de_DE"));

auto demo = [](const std::string& label)
{
    std::cout.imbue(std::locale()); // imbue cout with the global locale.
    float f = 1234.567890;
    std::cout << label << "\n";
    std::cout << "\t streamed:  " << f << "\n";
    std::cout << "\t to_string: " << std::to_string(f) << "\n";
};

std::locale::global(std::locale("C"));//default.
demo("c locale");

std::locale::global(std::locale("de_DE"));//default.
demo("std de locale");

boost::locale::generator gen;
std::locale::global(gen("de_DE.UTF-8"));
demo("boost de locale");

给出以下输出:

c locale
     streamed:  1234.57
     to_string: 1234.567871
std de locale
     streamed:  1.234,57
     to_string: 1234,567871
boost de locale
     streamed:  1234.57
     to_string: 1234,567871

在实现人类通信(输出到 gui 或终端)和机器间通信(csv 文件、xml 等)的代码中,这可能是不受欢迎的行为。使用 boost 语言环境时,您明确指定何时需要语言环境格式,ala:

cout << boost::locale::as::currency << 123.45 << "\n";
cout << boost::locale::as::number << 12345.666 << "\n"

结论

boost::locale 似乎比系统提供的语言环境更受欢迎。