Commit e6d63237 authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

Fallback hyphenation locale

When the `lang` attribute does not match the hyphenation
dictionary exactly, this patch computes fallback languages,
by incrementally removing the last component separated by
U+002D HYPHEN-MINUS character.

This allows, for instance, `lang="fr-fr"` or `lang=`fr-ca`"
to find the `fr` dictionary.

Bug: 815059
Change-Id: Ia4b76621dfb18b5aef604e8c7351ed9322f056dc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2505353
Commit-Queue: Koji Ishii <kojii@chromium.org>
Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Reviewed-by: default avatarKent Tamura <tkent@chromium.org>
Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#822059}
parent 2e1c8b45
......@@ -199,6 +199,15 @@ static LocaleMap CreateLocaleFallbackMap() {
{"und-Orya", "or"}, // Oriya
{"und-Taml", "ta"}, // Tamil
{"und-Telu", "te"}, // Telugu
// List of locales with hyphens not to fall back.
{"de-1901", nullptr},
{"de-1996", nullptr},
{"de-ch-1901", nullptr},
{"en-gb", nullptr},
{"en-us", nullptr},
{"mn-cyrl", nullptr},
{"und-ethi", nullptr},
};
LocaleMap map;
for (const auto& it : locale_fallback_data)
......@@ -206,12 +215,28 @@ static LocaleMap CreateLocaleFallbackMap() {
return map;
}
// static
AtomicString HyphenationMinikin::MapLocale(const AtomicString& locale) {
DEFINE_STATIC_LOCAL(LocaleMap, locale_fallback, (CreateLocaleFallbackMap()));
for (AtomicString mapped_locale = locale;;) {
const auto& it = locale_fallback.find(mapped_locale);
if (it != locale_fallback.end()) {
if (it->value)
return it->value;
return mapped_locale;
}
const wtf_size_t last_hyphen = mapped_locale.ReverseFind('-');
if (last_hyphen == kNotFound || !last_hyphen)
return mapped_locale;
mapped_locale = AtomicString(mapped_locale.GetString().Left(last_hyphen));
}
}
scoped_refptr<Hyphenation> Hyphenation::PlatformGetHyphenation(
const AtomicString& locale) {
DEFINE_STATIC_LOCAL(LocaleMap, locale_fallback, (CreateLocaleFallbackMap()));
const auto& it = locale_fallback.find(locale);
if (it != locale_fallback.end())
return LayoutLocale::Get(it->value)->GetHyphenation();
const AtomicString mapped_locale = HyphenationMinikin::MapLocale(locale);
if (mapped_locale.Impl() != locale.Impl())
return LayoutLocale::Get(mapped_locale)->GetHyphenation();
scoped_refptr<HyphenationMinikin> hyphenation(
base::AdoptRef(new HyphenationMinikin));
......
......@@ -28,6 +28,8 @@ class PLATFORM_EXPORT HyphenationMinikin final : public Hyphenation {
wtf_size_t before_index) const override;
Vector<wtf_size_t, 8> HyphenLocations(const StringView&) const override;
static AtomicString MapLocale(const AtomicString& locale);
static scoped_refptr<HyphenationMinikin> FromFileForTesting(base::File);
private:
......
......@@ -72,6 +72,33 @@ TEST_F(HyphenationTest, Get) {
EXPECT_EQ(nullptr, LayoutLocale::Get("en-UK")->GetHyphenation());
}
#if defined(USE_MINIKIN_HYPHENATION)
TEST_F(HyphenationTest, MapLocale) {
EXPECT_EQ(HyphenationMinikin::MapLocale("de-de"), "de-1996");
EXPECT_EQ(HyphenationMinikin::MapLocale("de-de-xyz"), "de-1996");
EXPECT_EQ(HyphenationMinikin::MapLocale("de-li"), "de-1996");
EXPECT_EQ(HyphenationMinikin::MapLocale("de-li-1901"), "de-ch-1901");
EXPECT_EQ(HyphenationMinikin::MapLocale("en"), "en-gb");
EXPECT_EQ(HyphenationMinikin::MapLocale("en-gu"), "en-us");
EXPECT_EQ(HyphenationMinikin::MapLocale("en-gu-xyz"), "en-us");
EXPECT_EQ(HyphenationMinikin::MapLocale("en-xyz"), "en-gb");
EXPECT_EQ(HyphenationMinikin::MapLocale("en-xyz-xyz"), "en-gb");
EXPECT_EQ(HyphenationMinikin::MapLocale("fr-ca"), "fr");
EXPECT_EQ(HyphenationMinikin::MapLocale("fr-fr"), "fr");
EXPECT_EQ(HyphenationMinikin::MapLocale("fr-fr-xyz"), "fr");
EXPECT_EQ(HyphenationMinikin::MapLocale("mn-xyz"), "mn-cyrl");
EXPECT_EQ(HyphenationMinikin::MapLocale("und-Deva-xyz"), "hi");
const char* no_map_locales[] = {"en-us", "fr"};
for (const char* locale_str : no_map_locales) {
AtomicString locale(locale_str);
AtomicString mapped_locale = HyphenationMinikin::MapLocale(locale);
// If no mapping, the same instance should be returned.
EXPECT_EQ(locale.Impl(), mapped_locale.Impl());
}
}
#endif
#if defined(USE_MINIKIN_HYPHENATION) || defined(OS_MAC)
TEST_F(HyphenationTest, HyphenLocations) {
scoped_refptr<Hyphenation> hyphenation = GetHyphenation("en-us");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment