summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/generated_resources.grd244
-rw-r--r--chrome/common/time_format.cc242
-rw-r--r--chrome/common/time_format.h15
-rw-r--r--chrome/common/time_format_unittest.cc37
4 files changed, 440 insertions, 98 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 8b68334..ec03868 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -1209,6 +1209,250 @@ each locale. -->
</message>
</if>
+ <message name="IDS_TIME_ELAPSED_SECS_DEFAULT"
+ desc="This is necessary for every language. This is the default for all the numbers NOT covered by special cases (singular, dual/two, few, many) some languages need. For CJK, Vietnamese, and Turkish, this is the only string necessary. For languages with singular-plural distinction, this is generic plural. For Lithuanian, NUMBER_DEFAULT is 11 .. 19.">
+ <ph name="NUMBER_DEFAULT"><ex>37</ex>#</ph> secs ago
+ </message>
+
+ <if expr="lang not in ['zh-CN', 'zh-TW', 'ko', 'ja', 'vi', 'tr']">
+ <message name="IDS_TIME_ELAPSED_SEC_SINGULAR"
+ desc="NUMBER_ONE is one or one-like numbers : 1 (many European languages), 1 and 0 (French and Brazillian Portugese), 1,21,31, .. (Russian, Ukrainian, Croatian, Servian, Latvian, Lithuanian), or 1, 101, 201, .. (Slovenian). Do NOT translate this for CJK, Vietnamese and Turkish, but just copy the source string.">
+ <ph name="NUMBER_ONE"><ex>1</ex>#</ph> sec ago
+ </message>
+ </if>
+ <if expr="lang in ['zh-CN', 'zh-TW', 'ko', 'ja', 'vi', 'tr']">
+ <message translateable="false" name="IDS_TIME_ELAPSED_SEC_SINGULAR"
+ desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang in ['ar', 'ro', 'lv']">
+ <message name="IDS_TIME_ELAPSED_SECS_ZERO"
+ desc="NUMBER_ZERO is 0 (Arabic, Latvian) or 0, 2..19, 101..119, ... (Romanian). For other languages, just copy the source string.">
+ <ph name="NUMBER_ZERO"><ex>0</ex>#</ph> secs ago
+ </message>
+ </if>
+ <if expr="lang not in ['ar', 'ro', 'lv']">
+ <message translateable="false" name="IDS_TIME_ELAPSED_SECS_ZERO"
+ desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang in ['ga', 'sl', 'ar']">
+ <message name="IDS_TIME_ELAPSED_SECS_TWO"
+ desc="NUMBER_TWO is two or two-like/dual numbers : 2 (Arabic and Irish) or 2, 102, 202 ... (Slovenian). For other languages, just copy the source string.">
+ <ph name="NUMBER_TWO"><ex>2</ex>#</ph> secs ago
+ </message>
+ </if>
+ <if expr="lang not in ['ga', 'sl', 'ar']">
+ <message translateable="false" name="IDS_TIME_ELAPSED_SECS_TWO"
+ desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang in ['ru', 'lt', 'hr', 'uk', 'cs', 'sk', 'pl', 'sl', 'ar']">
+ <message name="IDS_TIME_ELAPSED_SECS_FEW"
+ desc="NUMBER_FEW is few or few-like numbers in Arabic, Russian, Polish, Croatian, Serbian, Ukrainian, Czech, Slovak, Slovenian, Latvian. For other languages, just copy the source string.">
+ <ph name="NUMBER_FEW"><ex>3</ex>#</ph> secs ago
+ </message>
+ </if>
+ <if expr="lang not in ['ru', 'lt', 'hr', 'uk', 'cs', 'sk', 'pl', 'sl', 'ar']">
+ <message translateable="false" name="IDS_TIME_ELAPSED_SECS_FEW"
+ desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang == 'ar'">
+ <message name="IDS_TIME_ELAPSED_SECS_MANY"
+ desc="NUMBER_MANY is 11 through 99 in Arabic. For all other languages, just copy the source string.">
+ <ph name="NUMBER_MANY"><ex>23</ex>#</ph> secs ago
+ </message>
+ </if>
+ <if expr="lang != 'ar'">
+ <message translateable="false" name="IDS_TIME_ELAPSED_SECS_MANY"
+ desc="">
+ NA
+ </message>
+ </if>
+
+
+ <message name="IDS_TIME_ELAPSED_MINS_DEFAULT"
+ desc="This is necessary for every language. This is the default for all the numbers NOT covered by special cases (singular, dual/two, few, many) some languages need. For CJK, Vietnamese, and Turkish, this is the only string necessary. For languages with singular-plural distinction, this is generic plural. For Lithuanian, NUMBER_DEFAULT is 11 .. 19.">
+ <ph name="NUMBER_DEFAULT"><ex>37</ex>#</ph> mins ago
+ </message>
+
+ <if expr="lang not in ['zh-CN', 'zh-TW', 'ko', 'ja', 'vi', 'tr']">
+ <message name="IDS_TIME_ELAPSED_MIN_SINGULAR"
+ desc="NUMBER_ONE is one or one-like numbers : 1 (many European languages), 1 and 0 (French and Brazillian Portugese), 1,21,31, .. (Russian, Ukrainian, Croatian, Servian, Latvian, Lithuanian), or 1, 101, 201, .. (Slovenian). Do NOT translate this for CJK, Vietnamese and Turkish, but just copy the source string.">
+ <ph name="NUMBER_ONE"><ex>1</ex>#</ph> min ago
+ </message>
+ </if>
+ <if expr="lang in ['zh-CN', 'zh-TW', 'ko', 'ja', 'vi', 'tr']">
+ <message translateable="false" name="IDS_TIME_ELAPSED_MIN_SINGULAR"
+ desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang in ['ga', 'sl', 'ar']">
+ <message name="IDS_TIME_ELAPSED_MINS_TWO"
+ desc="NUMBER_TWO is two or two-like/dual numbers : 2 (Arabic and Irish) or 2, 102, 202 ... (Slovenian). For other languages, just copy the source string.">
+ <ph name="NUMBER_TWO"><ex>2</ex>#</ph> mins ago
+ </message>
+ </if>
+ <if expr="lang not in ['ga', 'sl', 'ar']">
+ <message translateable="false" name="IDS_TIME_ELAPSED_MINS_TWO"
+ desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang in ['ru', 'lt', 'hr', 'uk', 'cs', 'sk', 'pl', 'sl', 'ar']">
+ <message name="IDS_TIME_ELAPSED_MINS_FEW"
+ desc="NUMBER_FEW is few or few-like numbers in Arabic, Russian, Polish, Croatian, Serbian, Ukrainian, Czech, Slovak, Slovenian, Latvian. For other languages, just copy the source string.">
+ <ph name="NUMBER_FEW"><ex>3</ex>#</ph> mins ago
+ </message>
+ </if>
+ <if expr="lang not in ['ru', 'lt', 'hr', 'uk', 'cs', 'sk', 'pl', 'sl', 'ar']">
+ <message translateable="false" name="IDS_TIME_ELAPSED_MINS_FEW"
+ desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang == 'ar'">
+ <message name="IDS_TIME_ELAPSED_MINS_MANY"
+ desc="NUMBER_MANY is 11 through 99 in Arabic. For all other languages, just copy the source string.">
+ <ph name="NUMBER_MANY"><ex>23</ex>#</ph> mins ago
+ </message>
+ </if>
+ <if expr="lang != 'ar'">
+ <message translateable="false" name="IDS_TIME_ELAPSED_MINS_MANY"
+ desc="">
+ NA
+ </message>
+ </if>
+
+
+ <message name="IDS_TIME_ELAPSED_HOURS_DEFAULT"
+ desc="This is necessary for every language. This is the default for all the numbers NOT covered by special cases (singular, dual/two, few, many) some languages need. For CJK, Vietnamese, and Turkish, this is the only string necessary. For languages with singular-plural distinction, this is generic plural. For Lithuanian, NUMBER_DEFAULT is 11 .. 19.">
+ <ph name="NUMBER_DEFAULT"><ex>37</ex>#</ph> hours ago
+ </message>
+
+ <if expr="lang not in ['zh-CN', 'zh-TW', 'ko', 'ja', 'vi', 'tr']">
+ <message name="IDS_TIME_ELAPSED_HOUR_SINGULAR"
+ desc="NUMBER_ONE is one or one-like numbers : 1 (many European languages), 1 and 0 (French and Brazillian Portugese), 1,21,31, .. (Russian, Ukrainian, Croatian, Servian, Latvian, Lithuanian), or 1, 101, 201, .. (Slovenian). Do NOT translate this for CJK, Vietnamese and Turkish, but just copy the source string.">
+ <ph name="NUMBER_ONE"><ex>1</ex>#</ph> hour ago
+ </message>
+ </if>
+ <if expr="lang in ['zh-CN', 'zh-TW', 'ko', 'ja', 'vi', 'tr']">
+ <message translateable="false" name="IDS_TIME_ELAPSED_HOUR_SINGULAR"
+ desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang in ['ga', 'sl', 'ar']">
+ <message name="IDS_TIME_ELAPSED_HOURS_TWO"
+ desc="NUMBER_TWO is two or two-like/dual numbers : 2 (Arabic and Irish) or 2, 102, 202 ... (Slovenian). For other languages, just copy the source string.">
+ <ph name="NUMBER_TWO"><ex>2</ex>#</ph> hours ago
+ </message>
+ </if>
+ <if expr="lang not in ['ga', 'sl', 'ar']">
+ <message translateable="false" name="IDS_TIME_ELAPSED_HOURS_TWO"
+ desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang in ['ru', 'lt', 'hr', 'uk', 'cs', 'sk', 'pl', 'sl', 'ar']">
+ <message name="IDS_TIME_ELAPSED_HOURS_FEW"
+ desc="NUMBER_FEW is few or few-like numbers in Arabic, Russian, Polish, Croatian, Serbian, Ukrainian, Czech, Slovak, Slovenian, Latvian. For other languages, just copy the source string.">
+ <ph name="NUMBER_FEW"><ex>3</ex>#</ph> hours ago
+ </message>
+ </if>
+ <if expr="lang not in ['ru', 'lt', 'hr', 'uk', 'cs', 'sk', 'pl', 'sl', 'ar']">
+ <message translateable="false" name="IDS_TIME_ELAPSED_HOURS_FEW"
+ desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang == 'ar'">
+ <message name="IDS_TIME_ELAPSED_HOURS_MANY"
+ desc="NUMBER_MANY is 11 through 99 in Arabic. For all other languages, just copy the source string.">
+ <ph name="NUMBER_MANY"><ex>23</ex>#</ph> hours ago
+ </message>
+ </if>
+ <if expr="lang != 'ar'">
+ <message translateable="false" name="IDS_TIME_ELAPSED_HOURS_MANY"
+ desc="">
+ NA
+ </message>
+ </if>
+
+
+ <message name="IDS_TIME_ELAPSED_DAYS_DEFAULT"
+ desc="This is necessary for every language. This is the default for all the numbers NOT covered by special cases (singular, dual/two, few, many) some languages need. For CJK, Vietnamese, and Turkish, this is the only string necessary. For languages with singular-plural distinction, this is generic plural. For Lithuanian, NUMBER_DEFAULT is 11 .. 19.">
+ <ph name="NUMBER_DEFAULT"><ex>37</ex>#</ph> days ago
+ </message>
+
+ <if expr="lang not in ['zh-CN', 'zh-TW', 'ko', 'ja', 'vi', 'tr']">
+ <message name="IDS_TIME_ELAPSED_DAY_SINGULAR"
+ desc="NUMBER_ONE is one or one-like numbers : 1 (many European languages), 1 and 0 (French and Brazillian Portugese), 1,21,31, .. (Russian, Ukrainian, Croatian, Servian, Latvian, Lithuanian), or 1, 101, 201, .. (Slovenian). Do NOT translate this for CJK, Vietnamese and Turkish, but just copy the source string.">
+ <ph name="NUMBER_ONE"><ex>1</ex>#</ph> day ago
+ </message>
+ </if>
+ <if expr="lang in ['zh-CN', 'zh-TW', 'ko', 'ja', 'vi', 'tr']">
+ <message translateable="false" name="IDS_TIME_ELAPSED_DAY_SINGULAR"
+ desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang in ['ga', 'sl', 'ar']">
+ <message name="IDS_TIME_ELAPSED_DAYS_TWO"
+ desc="NUMBER_TWO is two or two-like/dual numbers : 2 (Arabic and Irish) or 2, 102, 202 ... (Slovenian). For other languages, just copy the source string.">
+ <ph name="NUMBER_TWO"><ex>2</ex>#</ph> days ago
+ </message>
+ </if>
+ <if expr="lang not in ['ga', 'sl', 'ar']">
+ <message translateable="false" name="IDS_TIME_ELAPSED_DAYS_TWO"
+ desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang in ['ru', 'lt', 'hr', 'uk', 'cs', 'sk', 'pl', 'sl', 'ar']">
+ <message name="IDS_TIME_ELAPSED_DAYS_FEW"
+ desc="NUMBER_FEW is few or few-like numbers in Arabic, Russian, Polish, Croatian, Serbian, Ukrainian, Czech, Slovak, Slovenian, Latvian. For other languages, just copy the source string.">
+ <ph name="NUMBER_FEW"><ex>3</ex>#</ph> days ago
+ </message>
+ </if>
+ <if expr="lang not in ['ru', 'lt', 'hr', 'uk', 'cs', 'sk', 'pl', 'sl', 'ar']">
+ <message translateable="false" name="IDS_TIME_ELAPSED_DAYS_FEW"
+ desc="">
+ NA
+ </message>
+ </if>
+
+ <if expr="lang == 'ar'">
+ <message name="IDS_TIME_ELAPSED_DAYS_MANY"
+ desc="NUMBER_MANY is 11 through 99 in Arabic. For all other languages, just copy the source string.">
+ <ph name="NUMBER_MANY"><ex>23</ex>#</ph> days ago
+ </message>
+ </if>
+ <if expr="lang != 'ar'">
+ <message translateable="false" name="IDS_TIME_ELAPSED_DAYS_MANY"
+ desc="">
+ NA
+ </message>
+ </if>
+
<message name="IDS_PAST_TIME_TODAY" desc="Relative day today">
Today
</message>
diff --git a/chrome/common/time_format.cc b/chrome/common/time_format.cc
index 70f173d..5fd9485 100644
--- a/chrome/common/time_format.cc
+++ b/chrome/common/time_format.cc
@@ -24,82 +24,169 @@
using base::Time;
using base::TimeDelta;
-class TimeRemainingFormat {
+namespace {
+
+static const char kFallbackFormatSuffixShort[] = "}";
+static const char kFallbackFormatSuffixLeft[] = " left}";
+static const char kFallbackFormatSuffixAgo[] = " ago}";
+
+static const int kInvalidMsgId = -1;
+
+// Contains message IDs for various time units and pluralities.
+struct MessageIDs {
+ // There are 4 different time units and 6 different pluralities.
+ int ids[4][6];
+};
+
+// Message IDs for different time formats.
+static const MessageIDs kTimeShortMessageIDs = { {
+ {
+ IDS_TIME_SECS_DEFAULT, IDS_TIME_SEC_SINGULAR, IDS_TIME_SECS_ZERO,
+ IDS_TIME_SECS_TWO, IDS_TIME_SECS_FEW, IDS_TIME_SECS_MANY
+ },
+ {
+ IDS_TIME_MINS_DEFAULT, IDS_TIME_MIN_SINGULAR, kInvalidMsgId,
+ IDS_TIME_MINS_TWO, IDS_TIME_MINS_FEW, IDS_TIME_MINS_MANY
+ },
+ {
+ IDS_TIME_HOURS_DEFAULT, IDS_TIME_HOUR_SINGULAR, kInvalidMsgId,
+ IDS_TIME_HOURS_TWO, IDS_TIME_HOURS_FEW, IDS_TIME_HOURS_MANY
+ },
+ {
+ IDS_TIME_DAYS_DEFAULT, IDS_TIME_DAY_SINGULAR, kInvalidMsgId,
+ IDS_TIME_DAYS_TWO, IDS_TIME_DAYS_FEW, IDS_TIME_DAYS_MANY
+ }
+} };
+
+static const MessageIDs kTimeRemainingMessageIDs = { {
+ {
+ IDS_TIME_REMAINING_SECS_DEFAULT, IDS_TIME_REMAINING_SEC_SINGULAR,
+ IDS_TIME_REMAINING_SECS_ZERO, IDS_TIME_REMAINING_SECS_TWO,
+ IDS_TIME_REMAINING_SECS_FEW, IDS_TIME_REMAINING_SECS_MANY
+ },
+ {
+ IDS_TIME_REMAINING_MINS_DEFAULT, IDS_TIME_REMAINING_MIN_SINGULAR,
+ kInvalidMsgId, IDS_TIME_REMAINING_MINS_TWO,
+ IDS_TIME_REMAINING_MINS_FEW, IDS_TIME_REMAINING_MINS_MANY
+ },
+ {
+ IDS_TIME_REMAINING_HOURS_DEFAULT, IDS_TIME_REMAINING_HOUR_SINGULAR,
+ kInvalidMsgId, IDS_TIME_REMAINING_HOURS_TWO,
+ IDS_TIME_REMAINING_HOURS_FEW, IDS_TIME_REMAINING_HOURS_MANY
+ },
+ {
+ IDS_TIME_REMAINING_DAYS_DEFAULT, IDS_TIME_REMAINING_DAY_SINGULAR,
+ kInvalidMsgId, IDS_TIME_REMAINING_DAYS_TWO,
+ IDS_TIME_REMAINING_DAYS_FEW, IDS_TIME_REMAINING_DAYS_MANY
+ }
+} };
+
+static const MessageIDs kTimeElapsedMessageIDs = { {
+ {
+ IDS_TIME_ELAPSED_SECS_DEFAULT, IDS_TIME_ELAPSED_SEC_SINGULAR,
+ IDS_TIME_ELAPSED_SECS_ZERO, IDS_TIME_ELAPSED_SECS_TWO,
+ IDS_TIME_ELAPSED_SECS_FEW, IDS_TIME_ELAPSED_SECS_MANY
+ },
+ {
+ IDS_TIME_ELAPSED_MINS_DEFAULT, IDS_TIME_ELAPSED_MIN_SINGULAR,
+ kInvalidMsgId, IDS_TIME_ELAPSED_MINS_TWO,
+ IDS_TIME_ELAPSED_MINS_FEW, IDS_TIME_ELAPSED_MINS_MANY
+ },
+ {
+ IDS_TIME_ELAPSED_HOURS_DEFAULT, IDS_TIME_ELAPSED_HOUR_SINGULAR,
+ kInvalidMsgId, IDS_TIME_ELAPSED_HOURS_TWO,
+ IDS_TIME_ELAPSED_HOURS_FEW, IDS_TIME_ELAPSED_HOURS_MANY
+ },
+ {
+ IDS_TIME_ELAPSED_DAYS_DEFAULT, IDS_TIME_ELAPSED_DAY_SINGULAR,
+ kInvalidMsgId, IDS_TIME_ELAPSED_DAYS_TWO,
+ IDS_TIME_ELAPSED_DAYS_FEW, IDS_TIME_ELAPSED_DAYS_MANY
+ }
+} };
+
+// Different format types.
+enum FormatType {
+ FORMAT_SHORT,
+ FORMAT_REMAINING,
+ FORMAT_ELAPSED,
+};
+
+} // namespace
+
+class TimeFormatter {
public:
- const std::vector<PluralFormat*>& formatter(bool short_version) {
- return short_version ? short_formatter_ : long_formatter_;
+ const std::vector<PluralFormat*>& formatter(FormatType format_type) {
+ switch (format_type) {
+ case FORMAT_SHORT:
+ return short_formatter_;
+ case FORMAT_REMAINING:
+ return time_left_formatter_;
+ case FORMAT_ELAPSED:
+ return time_elapsed_formatter_;
+ default:
+ NOTREACHED();
+ return short_formatter_;
+ }
}
private:
- TimeRemainingFormat() {
- BuildFormats(true, &short_formatter_);
- BuildFormats(false, &long_formatter_);
+ static const MessageIDs& GetMessageIDs(FormatType format_type) {
+ switch (format_type) {
+ case FORMAT_SHORT:
+ return kTimeShortMessageIDs;
+ case FORMAT_REMAINING:
+ return kTimeRemainingMessageIDs;
+ case FORMAT_ELAPSED:
+ return kTimeElapsedMessageIDs;
+ default:
+ NOTREACHED();
+ return kTimeShortMessageIDs;
+ }
}
- ~TimeRemainingFormat() {
+
+ static const char* GetFallbackFormatSuffix(FormatType format_type) {
+ switch (format_type) {
+ case FORMAT_SHORT:
+ return kFallbackFormatSuffixShort;
+ case FORMAT_REMAINING:
+ return kFallbackFormatSuffixLeft;
+ case FORMAT_ELAPSED:
+ return kFallbackFormatSuffixAgo;
+ default:
+ NOTREACHED();
+ return kFallbackFormatSuffixShort;
+ }
+ }
+
+ TimeFormatter() {
+ BuildFormats(FORMAT_SHORT, &short_formatter_);
+ BuildFormats(FORMAT_REMAINING, &time_left_formatter_);
+ BuildFormats(FORMAT_ELAPSED, &time_elapsed_formatter_);
+ }
+ ~TimeFormatter() {
STLDeleteContainerPointers(short_formatter_.begin(),
short_formatter_.end());
- STLDeleteContainerPointers(long_formatter_.begin(),
- long_formatter_.end());
+ STLDeleteContainerPointers(time_left_formatter_.begin(),
+ time_left_formatter_.end());
+ STLDeleteContainerPointers(time_elapsed_formatter_.begin(),
+ time_elapsed_formatter_.end());
}
- friend class Singleton<TimeRemainingFormat>;
- friend struct DefaultSingletonTraits<TimeRemainingFormat>;
+ friend class Singleton<TimeFormatter>;
+ friend struct DefaultSingletonTraits<TimeFormatter>;
- std::vector<PluralFormat*> long_formatter_;
std::vector<PluralFormat*> short_formatter_;
- static void BuildFormats(bool short_version,
+ std::vector<PluralFormat*> time_left_formatter_;
+ std::vector<PluralFormat*> time_elapsed_formatter_;
+ static void BuildFormats(FormatType format_type,
std::vector<PluralFormat*>* time_formats);
static PluralFormat* createFallbackFormat(const PluralRules& rules,
int index,
- bool short_version);
+ FormatType format_type);
- DISALLOW_EVIL_CONSTRUCTORS(TimeRemainingFormat);
+ DISALLOW_EVIL_CONSTRUCTORS(TimeFormatter);
};
-void TimeRemainingFormat::BuildFormats(
- bool short_version,
- std::vector<PluralFormat*>* time_formats) {
- const static int kInvalidMsgId = -1;
- const static int kTimeMsgIds[][6] = {
- {
- IDS_TIME_SECS_DEFAULT, IDS_TIME_SEC_SINGULAR, IDS_TIME_SECS_ZERO,
- IDS_TIME_SECS_TWO, IDS_TIME_SECS_FEW, IDS_TIME_SECS_MANY
- },
- {
- IDS_TIME_MINS_DEFAULT, IDS_TIME_MIN_SINGULAR, kInvalidMsgId,
- IDS_TIME_MINS_TWO, IDS_TIME_MINS_FEW, IDS_TIME_MINS_MANY
- },
- {
- IDS_TIME_HOURS_DEFAULT, IDS_TIME_HOUR_SINGULAR, kInvalidMsgId,
- IDS_TIME_HOURS_TWO, IDS_TIME_HOURS_FEW, IDS_TIME_HOURS_MANY
- },
- {
- IDS_TIME_DAYS_DEFAULT, IDS_TIME_DAY_SINGULAR, kInvalidMsgId,
- IDS_TIME_DAYS_TWO, IDS_TIME_DAYS_FEW, IDS_TIME_DAYS_MANY
- }
- };
-
- const static int kTimeLeftMsgIds[][6] = {
- {
- IDS_TIME_REMAINING_SECS_DEFAULT, IDS_TIME_REMAINING_SEC_SINGULAR,
- IDS_TIME_REMAINING_SECS_ZERO, IDS_TIME_REMAINING_SECS_TWO,
- IDS_TIME_REMAINING_SECS_FEW, IDS_TIME_REMAINING_SECS_MANY
- },
- {
- IDS_TIME_REMAINING_MINS_DEFAULT, IDS_TIME_REMAINING_MIN_SINGULAR,
- kInvalidMsgId, IDS_TIME_REMAINING_MINS_TWO,
- IDS_TIME_REMAINING_MINS_FEW, IDS_TIME_REMAINING_MINS_MANY
- },
- {
- IDS_TIME_REMAINING_HOURS_DEFAULT, IDS_TIME_REMAINING_HOUR_SINGULAR,
- kInvalidMsgId, IDS_TIME_REMAINING_HOURS_TWO,
- IDS_TIME_REMAINING_HOURS_FEW, IDS_TIME_REMAINING_HOURS_MANY
- },
- {
- IDS_TIME_REMAINING_DAYS_DEFAULT, IDS_TIME_REMAINING_DAY_SINGULAR,
- kInvalidMsgId, IDS_TIME_REMAINING_DAYS_TWO,
- IDS_TIME_REMAINING_DAYS_FEW, IDS_TIME_REMAINING_DAYS_MANY
- }
- };
-
+void TimeFormatter::BuildFormats(FormatType format_type,
+ std::vector<PluralFormat*>* time_formats) {
const static UnicodeString kKeywords[] = {
UNICODE_STRING_SIMPLE("other"), UNICODE_STRING_SIMPLE("one"),
UNICODE_STRING_SIMPLE("zero"), UNICODE_STRING_SIMPLE("two"),
@@ -114,10 +201,13 @@ void TimeRemainingFormat::BuildFormats(
rules.reset(PluralRules::createRules(fallback_rules, err));
DCHECK(U_SUCCESS(err));
}
+
+ const MessageIDs& message_ids = GetMessageIDs(format_type);
+
for (int i = 0; i < 4; ++i) {
UnicodeString pattern;
for (size_t j = 0; j < arraysize(kKeywords); ++j) {
- int msg_id = short_version ? kTimeMsgIds[i][j] : kTimeLeftMsgIds[i][j];
+ int msg_id = message_ids.ids[i][j];
if (msg_id == kInvalidMsgId) continue;
std::string sub_pattern = WideToUTF8(l10n_util::GetString(msg_id));
// NA means this keyword is not used in the current locale.
@@ -138,7 +228,7 @@ void TimeRemainingFormat::BuildFormats(
time_formats->push_back(format);
} else {
delete format;
- time_formats->push_back(createFallbackFormat(*rules, i, short_version));
+ time_formats->push_back(createFallbackFormat(*rules, i, format_type));
// Reset it so that next ICU call can proceed.
err = U_ZERO_ERROR;
}
@@ -147,17 +237,16 @@ void TimeRemainingFormat::BuildFormats(
// Create a hard-coded fallback plural format. This will never be called
// unless translators make a mistake.
-PluralFormat* TimeRemainingFormat::createFallbackFormat(
- const PluralRules& rules,
- int index,
- bool short_version) {
+PluralFormat* TimeFormatter::createFallbackFormat(const PluralRules& rules,
+ int index,
+ FormatType format_type) {
const static UnicodeString kUnits[4][2] = {
{ UNICODE_STRING_SIMPLE("sec"), UNICODE_STRING_SIMPLE("secs") },
{ UNICODE_STRING_SIMPLE("min"), UNICODE_STRING_SIMPLE("mins") },
{ UNICODE_STRING_SIMPLE("hour"), UNICODE_STRING_SIMPLE("hours") },
{ UNICODE_STRING_SIMPLE("day"), UNICODE_STRING_SIMPLE("days") }
};
- UnicodeString suffix(short_version ? "}" : " left}", -1, US_INV);
+ UnicodeString suffix(GetFallbackFormatSuffix(format_type), -1, US_INV);
UnicodeString pattern;
if (rules.isKeyword(UNICODE_STRING_SIMPLE("one"))) {
pattern += UNICODE_STRING_SIMPLE("one{# ") + kUnits[index][0] + suffix;
@@ -169,10 +258,10 @@ PluralFormat* TimeRemainingFormat::createFallbackFormat(
return format;
}
-Singleton<TimeRemainingFormat> time_remaining_format;
+Singleton<TimeFormatter> time_formatter;
-static std::wstring TimeRemainingImpl(const TimeDelta& delta,
- bool short_version) {
+static std::wstring FormatTimeImpl(const TimeDelta& delta,
+ FormatType format_type) {
if (delta.ToInternalValue() < 0) {
NOTREACHED() << "Negative duration";
return std::wstring();
@@ -181,7 +270,7 @@ static std::wstring TimeRemainingImpl(const TimeDelta& delta,
int number;
const std::vector<PluralFormat*>& formatters =
- time_remaining_format->formatter(short_version);
+ time_formatter->formatter(format_type);
UErrorCode error = U_ZERO_ERROR;
UnicodeString time_string;
@@ -222,13 +311,18 @@ static std::wstring TimeRemainingImpl(const TimeDelta& delta,
}
// static
+std::wstring TimeFormat::TimeElapsed(const TimeDelta& delta) {
+ return FormatTimeImpl(delta, FORMAT_ELAPSED);
+}
+
+// static
std::wstring TimeFormat::TimeRemaining(const TimeDelta& delta) {
- return TimeRemainingImpl(delta, false);
+ return FormatTimeImpl(delta, FORMAT_REMAINING);
}
// static
std::wstring TimeFormat::TimeRemainingShort(const TimeDelta& delta) {
- return TimeRemainingImpl(delta, true);
+ return FormatTimeImpl(delta, FORMAT_SHORT);
}
// static
diff --git a/chrome/common/time_format.h b/chrome/common/time_format.h
index 252599b..c04ed62 100644
--- a/chrome/common/time_format.h
+++ b/chrome/common/time_format.h
@@ -18,13 +18,18 @@ class TimeDelta;
class TimeFormat {
public:
- // Returns a localized string of approximate time remaining. The conditions
- // are simpler than PastTime since this is used for in-progress operations
- // and users have different expectations of units.
- // Ex: "3 mins left", "2 days left".
+ // TimeElapsed, TimeRemaining and TimeRemainingShort functions:
+ // These functions return a localized string of approximate time duration. The
+ // conditions are simpler than PastTime since these functions are used for
+ // in-progress operations and users have different expectations of units.
+
+ // Returns times in elapsed-format: "3 mins ago", "2 days ago".
+ static std::wstring TimeElapsed(const base::TimeDelta& delta);
+
+ // Returns times in remaining-format: "3 mins left", "2 days left".
static std::wstring TimeRemaining(const base::TimeDelta& delta);
- // Same as TimeRemaining without the "left".
+ // Returns times in short-format: "3 mins", "2 days".
static std::wstring TimeRemainingShort(const base::TimeDelta& delta);
// For displaying a relative time in the past. This method returns either
diff --git a/chrome/common/time_format_unittest.cc b/chrome/common/time_format_unittest.cc
index 56f38f3..c910209 100644
--- a/chrome/common/time_format_unittest.cc
+++ b/chrome/common/time_format_unittest.cc
@@ -32,16 +32,17 @@ TEST(TimeFormat, RelativeDate) {
}
namespace {
-void TestRemainingTime(const TimeDelta delta,
- const std::wstring& expected_short,
- const std::wstring& expected_long) {
- EXPECT_EQ(expected_short, TimeFormat::TimeRemainingShort(delta));
- EXPECT_EQ(expected_long, TimeFormat::TimeRemaining(delta));
+void TestTimeFormats(const TimeDelta delta, const std::wstring& expected) {
+ std::wstring expected_left = expected + L" left";
+ std::wstring expected_ago = expected + L" ago";
+ EXPECT_EQ(expected, TimeFormat::TimeRemainingShort(delta));
+ EXPECT_EQ(expected_left, TimeFormat::TimeRemaining(delta));
+ EXPECT_EQ(expected_ago, TimeFormat::TimeElapsed(delta));
}
} // namespace
-TEST(TimeFormat, RemainingTime) {
+TEST(TimeFormat, FormatTime) {
const TimeDelta one_day = TimeDelta::FromDays(1);
const TimeDelta three_days = TimeDelta::FromDays(3);
const TimeDelta one_hour = TimeDelta::FromHours(1);
@@ -54,17 +55,15 @@ TEST(TimeFormat, RemainingTime) {
// TODO(jungshik) : These test only pass when the OS locale is 'en'.
// We need to add SetUp() and TearDown() to set the locale to 'en'.
- TestRemainingTime(twohundred_millisecs, L"0 secs", L"0 secs left");
- TestRemainingTime(one_sec - twohundred_millisecs, L"0 secs", L"0 secs left");
- TestRemainingTime(one_sec + twohundred_millisecs, L"1 sec", L"1 sec left");
- TestRemainingTime(five_secs + twohundred_millisecs, L"5 secs",
- L"5 secs left");
- TestRemainingTime(one_min + five_secs, L"1 min", L"1 min left");
- TestRemainingTime(three_mins + twohundred_millisecs,
- L"3 mins", L"3 mins left");
- TestRemainingTime(one_hour + five_secs, L"1 hour", L"1 hour left");
- TestRemainingTime(four_hours + five_secs, L"4 hours", L"4 hours left");
- TestRemainingTime(one_day + five_secs, L"1 day", L"1 day left");
- TestRemainingTime(three_days, L"3 days", L"3 days left");
- TestRemainingTime(three_days + four_hours, L"3 days", L"3 days left");
+ TestTimeFormats(twohundred_millisecs, L"0 secs");
+ TestTimeFormats(one_sec - twohundred_millisecs, L"0 secs");
+ TestTimeFormats(one_sec + twohundred_millisecs, L"1 sec");
+ TestTimeFormats(five_secs + twohundred_millisecs, L"5 secs");
+ TestTimeFormats(one_min + five_secs, L"1 min");
+ TestTimeFormats(three_mins + twohundred_millisecs, L"3 mins");
+ TestTimeFormats(one_hour + five_secs, L"1 hour");
+ TestTimeFormats(four_hours + five_secs, L"4 hours");
+ TestTimeFormats(one_day + five_secs, L"1 day");
+ TestTimeFormats(three_days, L"3 days");
+ TestTimeFormats(three_days + four_hours, L"3 days");
}