ICU BreakIterator::createWordInstance 始终将错误代码设置为“U_USING_DEFAULT_WARNING”

问题描述 投票:0回答:1

我正在尝试为 ICU 的 BreakIterator 类设置一个包装器来进行边界分析,但在初始化过程中遇到了一个奇怪的问题。

设置 Break Iterator 后,错误代码状态始终设置为 U_USING_DEFAULT_WARNING。

根据文档:

U_USING_DEFAULT_WARNING 表示使用了默认的语言环境数据;找不到所请求的语言环境及其任何后备语言环境。

但是我尝试过的语言环境(en_US、ja_JP)绝对有效并且存在于我的系统上。它们甚至会通过 getAvailableLocales 显示在 ICU 列表中。但错误仍然存在。

这是我的代码,或多或少:

#include <iostream>
#include <memory>
#include <stdexcept>
#include <algorithm>
#include <unicode/brkiter.h>
#include <unicode/locid.h>


class WordIterator
{
    icu::UnicodeString _u16Data;
    std::unique_ptr<icu::BreakIterator> _itr = nullptr;
    bool _word;
    int32_t _begin, _cur, _next;
    UErrorCode _err;
public:
    WordIterator(const std::string& data, const icu::Locale& locale)
    {
        _u16Data = icu::UnicodeString::fromUTF8(data);
        _err = U_ZERO_ERROR;
        _itr.reset(icu::BreakIterator::createWordInstance(locale, _err));
        if (U_FAILURE(_err)) {
            throw std::runtime_error("Failed to create iterator");
        }

        _itr->setText(_u16Data);
        _begin = _itr->first();
        _cur = _begin;
        _next = _itr->next();
    }
    auto getError() const {
        return _err;
    }
};


int main()
{
    int count = 0;
    auto locales = icu::Locale::getAvailableLocales(count);
    auto lc = std::find_if(locales, locales+count, [](icu::Locale search) {
            auto name = search.getName();
            auto code = std::string{name};
            return code == "en_US";
    });
    if (lc != locales+count) {
        std::cerr << "Locale was found.\n";
    }
    WordIterator br{"This is a test.", icu::Locale::createCanonical("en_US")};
    if (br.getError() == U_USING_DEFAULT_WARNING) {
        std::cerr << "Default warning.\n";
    }

    return 0;
}

知道我做错了什么吗?我需要在某处做一些额外的初始化吗? U_FAILURE 认为至少是成功的。

我应该提到,我正在 Ubuntu 22.04 和 ICU 70.1 上进行测试,如果这有什么区别的话。

c++ icu
1个回答
0
投票

调用

icu::BreakIterator::createWordInstance
时,库会在其内部资源包中搜索所需的
"boundaries"
规则集(类型为
"word"
的规则集)。此步骤还在给定区域设置上执行fallback以查找这样的规则集。

您可以在返回的中断迭代器实例上调用方法

getLocale(ULOC_ACTUAL_LOCALE, get_status)
,以评估正在使用的实际语言环境。 99% 的情况下,您会发现该区域设置的名称为空(正在应用根规则)。

您不应将 U_USING_DEFAULT_WARNING 的结果代码

BreakIterator::createXxxInstance
视为
警告
,因为 只有少数语言环境具有 存储的规则集

大多数语言环境都会退回到根规则,这些规则分别来自 char.txt、word.txt、line.txt 和 sent.txt,分别表示字素簇、单词、行和句子中断。

对于单词迭代器,我可以找到仅为“瑞典语(芬兰)”定义的规则集(

sv_FI
)。如果您用您的代码尝试它,您将不会收到警告。

© www.soinside.com 2019 - 2024. All rights reserved.