| /* |
| * Copyright (C) 2012 Google Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following disclaimer |
| * in the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of Google Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "third_party/blink/renderer/platform/text/locale_win.h" |
| |
| #include <memory> |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/blink/renderer/platform/text/date_components.h" |
| #include "third_party/blink/renderer/platform/wtf/date_math.h" |
| #include "third_party/blink/renderer/platform/wtf/math_extras.h" |
| #include "ui/base/ui_base_features.h" |
| |
| namespace blink { |
| |
| class LocaleWinTest : public testing::Test { |
| protected: |
| enum { |
| kJanuary = 0, |
| kFebruary, |
| kMarch, |
| kApril, |
| kMay, |
| kJune, |
| kJuly, |
| kAugust, |
| kSeptember, |
| kOctober, |
| kNovember, |
| kDecember, |
| }; |
| |
| enum { |
| kSunday = 0, |
| kMonday, |
| kTuesday, |
| kWednesday, |
| kThursday, |
| kFriday, |
| kSaturday, |
| }; |
| |
| // See http://msdn.microsoft.com/en-us/goglobal/bb964664.aspx |
| // Note that some locales are country-neutral. |
| enum { |
| kArabicEG = 0x0C01, // ar-eg |
| kChineseCN = 0x0804, // zh-cn |
| kChineseHK = 0x0C04, // zh-hk |
| kChineseTW = 0x0404, // zh-tw |
| kGerman = 0x0407, // de |
| kEnglishUS = 0x409, // en-us |
| kFrenchFR = 0x40C, // fr |
| kJapaneseJP = 0x411, // ja |
| kKoreanKR = 0x0412, // ko |
| kPersian = 0x0429, // fa |
| kSpanish = 0x040A, // es |
| }; |
| |
| DateComponents GetDateComponents(int year, int month, int day) { |
| DateComponents date; |
| date.SetMillisecondsSinceEpochForDate(MsForDate(year, month, day)); |
| return date; |
| } |
| |
| double MsForDate(int year, int month, int day) { |
| return DateToDaysFrom1970(year, month, day) * kMsPerDay; |
| } |
| |
| String FormatDate(LCID lcid, int year, int month, int day) { |
| std::unique_ptr<LocaleWin> locale = |
| LocaleWin::Create(lcid, true /* defaultsForLocale */); |
| return locale->FormatDateTime(GetDateComponents(year, month, day)); |
| } |
| |
| unsigned FirstDayOfWeek(LCID lcid) { |
| std::unique_ptr<LocaleWin> locale = |
| LocaleWin::Create(lcid, true /* defaultsForLocale */); |
| return locale->FirstDayOfWeek(); |
| } |
| |
| String MonthLabel(LCID lcid, unsigned index) { |
| std::unique_ptr<LocaleWin> locale = |
| LocaleWin::Create(lcid, true /* defaultsForLocale */); |
| return locale->MonthLabels()[index]; |
| } |
| |
| String WeekDayShortLabel(LCID lcid, unsigned index) { |
| std::unique_ptr<LocaleWin> locale = |
| LocaleWin::Create(lcid, true /* defaultsForLocale */); |
| return locale->WeekDayShortLabels()[index]; |
| } |
| |
| bool IsRTL(LCID lcid) { |
| std::unique_ptr<LocaleWin> locale = |
| LocaleWin::Create(lcid, true /* defaultsForLocale */); |
| return locale->IsRTL(); |
| } |
| |
| String MonthFormat(LCID lcid) { |
| std::unique_ptr<LocaleWin> locale = |
| LocaleWin::Create(lcid, true /* defaultsForLocale */); |
| return locale->MonthFormat(); |
| } |
| |
| String TimeFormat(LCID lcid) { |
| std::unique_ptr<LocaleWin> locale = |
| LocaleWin::Create(lcid, true /* defaultsForLocale */); |
| return locale->TimeFormat(); |
| } |
| |
| String ShortTimeFormat(LCID lcid) { |
| std::unique_ptr<LocaleWin> locale = |
| LocaleWin::Create(lcid, true /* defaultsForLocale */); |
| return locale->ShortTimeFormat(); |
| } |
| |
| String ShortMonthLabel(LCID lcid, unsigned index) { |
| std::unique_ptr<LocaleWin> locale = |
| LocaleWin::Create(lcid, true /* defaultsForLocale */); |
| return locale->ShortMonthLabels()[index]; |
| } |
| |
| String TimeAMPMLabel(LCID lcid, unsigned index) { |
| std::unique_ptr<LocaleWin> locale = |
| LocaleWin::Create(lcid, true /* defaultsForLocale */); |
| return locale->TimeAMPMLabels()[index]; |
| } |
| |
| String DecimalSeparator(LCID lcid) { |
| std::unique_ptr<LocaleWin> locale = |
| LocaleWin::Create(lcid, true /* defaultsForLocale */); |
| return locale->LocalizedDecimalSeparator(); |
| } |
| }; |
| |
| TEST_F(LocaleWinTest, formatDate) { |
| EXPECT_EQ("04/27/2005", FormatDate(kEnglishUS, 2005, kApril, 27)); |
| EXPECT_EQ("27/04/2005", FormatDate(kFrenchFR, 2005, kApril, 27)); |
| EXPECT_EQ("2005/04/27", FormatDate(kJapaneseJP, 2005, kApril, 27)); |
| } |
| |
| TEST_F(LocaleWinTest, firstDayOfWeek) { |
| EXPECT_EQ(static_cast<unsigned>(kSunday), FirstDayOfWeek(kEnglishUS)); |
| EXPECT_EQ(static_cast<unsigned>(kMonday), FirstDayOfWeek(kFrenchFR)); |
| EXPECT_EQ(static_cast<unsigned>(kSunday), FirstDayOfWeek(kJapaneseJP)); |
| } |
| |
| TEST_F(LocaleWinTest, monthLabels) { |
| EXPECT_EQ("January", MonthLabel(kEnglishUS, kJanuary)); |
| EXPECT_EQ("June", MonthLabel(kEnglishUS, kJune)); |
| EXPECT_EQ("December", MonthLabel(kEnglishUS, kDecember)); |
| |
| EXPECT_EQ("janvier", MonthLabel(kFrenchFR, kJanuary)); |
| EXPECT_EQ("juin", MonthLabel(kFrenchFR, kJune)); |
| EXPECT_EQ( |
| "d\xC3\xA9" |
| "cembre", |
| MonthLabel(kFrenchFR, kDecember).Utf8()); |
| |
| EXPECT_EQ("1\xE6\x9C\x88", MonthLabel(kJapaneseJP, kJanuary).Utf8()); |
| EXPECT_EQ("6\xE6\x9C\x88", MonthLabel(kJapaneseJP, kJune).Utf8()); |
| EXPECT_EQ("12\xE6\x9C\x88", MonthLabel(kJapaneseJP, kDecember).Utf8()); |
| } |
| |
| TEST_F(LocaleWinTest, weekDayShortLabels) { |
| if (features::IsFormControlsRefreshEnabled()) { |
| EXPECT_EQ("Su", WeekDayShortLabel(kEnglishUS, kSunday)); |
| EXPECT_EQ("We", WeekDayShortLabel(kEnglishUS, kWednesday)); |
| EXPECT_EQ("Sa", WeekDayShortLabel(kEnglishUS, kSaturday)); |
| |
| EXPECT_EQ("di", WeekDayShortLabel(kFrenchFR, kSunday)); |
| EXPECT_EQ("me", WeekDayShortLabel(kFrenchFR, kWednesday)); |
| EXPECT_EQ("sa", WeekDayShortLabel(kFrenchFR, kSaturday)); |
| } else { |
| EXPECT_EQ("Sun", WeekDayShortLabel(kEnglishUS, kSunday)); |
| EXPECT_EQ("Wed", WeekDayShortLabel(kEnglishUS, kWednesday)); |
| EXPECT_EQ("Sat", WeekDayShortLabel(kEnglishUS, kSaturday)); |
| |
| EXPECT_EQ("dim.", WeekDayShortLabel(kFrenchFR, kSunday)); |
| EXPECT_EQ("mer.", WeekDayShortLabel(kFrenchFR, kWednesday)); |
| EXPECT_EQ("sam.", WeekDayShortLabel(kFrenchFR, kSaturday)); |
| } |
| EXPECT_EQ("\xE6\x97\xA5", WeekDayShortLabel(kJapaneseJP, kSunday).Utf8()); |
| EXPECT_EQ("\xE6\xB0\xB4", WeekDayShortLabel(kJapaneseJP, kWednesday).Utf8()); |
| EXPECT_EQ("\xE5\x9C\x9F", WeekDayShortLabel(kJapaneseJP, kSaturday).Utf8()); |
| } |
| |
| TEST_F(LocaleWinTest, isRTL) { |
| EXPECT_TRUE(IsRTL(kArabicEG)); |
| EXPECT_FALSE(IsRTL(kEnglishUS)); |
| } |
| |
| TEST_F(LocaleWinTest, dateFormat) { |
| EXPECT_EQ("y-M-d", LocaleWin::DateFormat("y-M-d")); |
| EXPECT_EQ("''yy'-'''MM'''-'dd", LocaleWin::DateFormat("''yy-''MM''-dd")); |
| EXPECT_EQ("yyyy'-''''-'MMM'''''-'dd", |
| LocaleWin::DateFormat("yyyy-''''-MMM''''-dd")); |
| EXPECT_EQ("yyyy'-'''''MMMM-dd", LocaleWin::DateFormat("yyyy-''''MMMM-dd")); |
| } |
| |
| TEST_F(LocaleWinTest, monthFormat) { |
| // Month format for EnglishUS: |
| // "MMMM, yyyy" on Windows 7 or older. |
| // "MMMM yyyy" on Window 8 or later. |
| EXPECT_EQ("MMMM yyyy", MonthFormat(kEnglishUS).Replace(',', "")); |
| EXPECT_EQ("MMMM yyyy", MonthFormat(kFrenchFR)); |
| EXPECT_EQ("yyyy\xE5\xB9\xB4M\xE6\x9C\x88", MonthFormat(kJapaneseJP).Utf8()); |
| } |
| |
| TEST_F(LocaleWinTest, timeFormat) { |
| EXPECT_EQ("h:mm:ss a", TimeFormat(kEnglishUS)); |
| EXPECT_EQ("HH:mm:ss", TimeFormat(kFrenchFR)); |
| EXPECT_EQ("H:mm:ss", TimeFormat(kJapaneseJP)); |
| } |
| |
| TEST_F(LocaleWinTest, shortTimeFormat) { |
| EXPECT_EQ("h:mm a", ShortTimeFormat(kEnglishUS)); |
| EXPECT_EQ("HH:mm", ShortTimeFormat(kFrenchFR)); |
| EXPECT_EQ("H:mm", ShortTimeFormat(kJapaneseJP)); |
| } |
| |
| TEST_F(LocaleWinTest, shortMonthLabels) { |
| EXPECT_EQ("Jan", ShortMonthLabel(kEnglishUS, 0)); |
| EXPECT_EQ("Dec", ShortMonthLabel(kEnglishUS, 11)); |
| EXPECT_EQ("janv.", ShortMonthLabel(kFrenchFR, 0)); |
| EXPECT_EQ( |
| "d\xC3\xA9" |
| "c.", |
| ShortMonthLabel(kFrenchFR, 11).Utf8()); |
| EXPECT_EQ("1", ShortMonthLabel(kJapaneseJP, 0)); |
| EXPECT_EQ("12", ShortMonthLabel(kJapaneseJP, 11)); |
| } |
| |
| TEST_F(LocaleWinTest, timeAMPMLabels) { |
| EXPECT_EQ("AM", TimeAMPMLabel(kEnglishUS, 0)); |
| EXPECT_EQ("PM", TimeAMPMLabel(kEnglishUS, 1)); |
| |
| EXPECT_EQ("", TimeAMPMLabel(kFrenchFR, 0).Utf8()); |
| EXPECT_EQ("", TimeAMPMLabel(kFrenchFR, 1).Utf8()); |
| |
| EXPECT_EQ("\xE5\x8D\x88\xE5\x89\x8D", TimeAMPMLabel(kJapaneseJP, 0).Utf8()); |
| EXPECT_EQ("\xE5\x8D\x88\xE5\xBE\x8C", TimeAMPMLabel(kJapaneseJP, 1).Utf8()); |
| } |
| |
| TEST_F(LocaleWinTest, decimalSeparator) { |
| EXPECT_EQ(".", DecimalSeparator(kEnglishUS)); |
| EXPECT_EQ(",", DecimalSeparator(kFrenchFR)); |
| } |
| |
| static void TestNumberIsReversible(LCID lcid, |
| const char* original, |
| const char* should_have = 0) { |
| std::unique_ptr<LocaleWin> locale = |
| LocaleWin::Create(lcid, true /* defaultsForLocale */); |
| String localized = locale->ConvertToLocalizedNumber(original); |
| if (should_have) |
| EXPECT_TRUE(localized.Contains(should_have)); |
| String converted = locale->ConvertFromLocalizedNumber(localized); |
| EXPECT_EQ(original, converted); |
| } |
| |
| void TestNumbers(LCID lcid) { |
| TestNumberIsReversible(lcid, "123456789012345678901234567890"); |
| TestNumberIsReversible(lcid, "-123.456"); |
| TestNumberIsReversible(lcid, ".456"); |
| TestNumberIsReversible(lcid, "-0.456"); |
| } |
| |
| TEST_F(LocaleWinTest, localizedNumberRoundTrip) { |
| TestNumberIsReversible(kEnglishUS, "123456789012345678901234567890"); |
| TestNumberIsReversible(kEnglishUS, "-123.456", "."); |
| TestNumberIsReversible(kEnglishUS, ".456", "."); |
| TestNumberIsReversible(kEnglishUS, "-0.456", "."); |
| |
| TestNumberIsReversible(kFrenchFR, "123456789012345678901234567890"); |
| TestNumberIsReversible(kFrenchFR, "-123.456", ","); |
| TestNumberIsReversible(kFrenchFR, ".456", ","); |
| TestNumberIsReversible(kFrenchFR, "-0.456", ","); |
| |
| // Test some of major locales. |
| TestNumbers(kArabicEG); |
| TestNumbers(kGerman); |
| TestNumbers(kSpanish); |
| TestNumbers(kPersian); |
| TestNumbers(kJapaneseJP); |
| TestNumbers(kKoreanKR); |
| TestNumbers(kChineseCN); |
| TestNumbers(kChineseHK); |
| TestNumbers(kChineseTW); |
| } |
| |
| } // namespace blink |