使用ICU在OS X上编译boost :: locale时更正to_upper()

时间:2015-11-10 00:40:55

标签: macos boost unicode locale icu

使用OS X上的默认设置编译Boost 1.59.0使用iconv库。当使用boost::locale::to_upper()等带有UTF8字符的内容时,iconv会为"GRüßEN”之类的输入生成"grüßEN”之类的结果。正如您所看到的,某些角色无法正确上装。

我看到修复是使用ICU而不是iconv,所以我开始用ICU构建Boost。对于我的用例,我遵循的方法如下:

  1. 下载unix tar ball(不是ZIP,有CR / LF行结尾,不起作用)。取消焦油。
  2. 修改第1414行的文件boost/libs/filesystem/src/operations.cpp中的代码以读取# if 0,以便始终执行回退代码。否则,我收到一个链接错误,告诉您在OS X 10.9中没有fchmodat
  3. http://site.icu-project.org/download/56#TOC-ICU4C-Download下载ICU 56.1。取消焦油。
  4. cd to``icu / source```。
  5. 运行./configure --enable-static --disable-shared CXXFLAGS="-std=c++14" --prefix="<path to install ICU>"
  6. 运行gnumake && gnumake install
  7. cd to boost_1_59_0/
  8. 运行./bootstrap.sh toolset=darwin macosx-version=10.11 macosx-version-min=10.8 --with-icu=<path where icu was installed>
  9. 运行./b2 toolset=darwin --without-mpi optimization=speed cxxflags="-arch x86_64 -fvisibility=hidden -fvisibility-inlines-hidden -std=c++14 -stdlib=libc++ -ftemplate-depth=512" linkflags="-stdlib=libc++" --reconfigure boost.locale.iconv=off boost.locale.icu=on -sICU_PATH=<path to my icu install dir> -link=static stage
  10. 现在这正确编译了Boost库的一个版本,但在使用此版本时,boost::locale::to_upper()现在完全跳过UTF8字符,并为"GREN”等输入返回"grüßEN”

    测试代码如下所示:

    static boolean defaultLocaleWasInitialized = false;
    ...
    void String::p_initDefaultLocale(void)
    {
        boost::locale::generator gen;
        std::locale defaultLocale = gen("");
        std::locale::global(defaultLocale);
        std::wcout.imbue(defaultLocale);
    }
    ...
    String::Pointer String::uppperCaseString(void) const
    {
        if (!defaultLocaleWasInitialized) {
            String::p_initDefaultLocale();
            defaultLocaleWasInitialized = true;
        }
        auto result = boost::locale::to_upper(*this);
        auto newString = String::stringWith(result.c_str());
        return newString;
    }
    ...
    TEST(Base_String, UpperCaseString_StringWithLowerCaseCharacters_ReturnsOneWithUpperCaseCharacters)
    {
        auto test = String::stringWith("Mp3 grüßEN");
        auto result = test->uppperCaseString();
        ASSERT_STREQ("MP3 GRÜSSEN", result->toUTF8());
    }
    

    关于我哪里出错的任何建议?

1 个答案:

答案 0 :(得分:-1)

AFAIK,这是正确的Boost行为。 Boost在其本地化方面存在局限性,例如它将ß视为单个代码点,而不能将其大写为SS。因此,您的代码不会出错,这只是Boost库的一个问题:当涉及到某些UTF8字符时,确切的行为取决于平台。

提升ß限制:boost to_upper function of string_algo doesn't take into account the localeboost::algorithm::to_upper/to_lower ok for utf8? boost::locale not necessary?(尤其是评论)。

平台依赖:string conversion with boost locale: different behaviour on windows and linux

如果您希望正确翻译它,您可能需要另一个库。本地化很难!