I was reviewing the Google I/O Session 2012 app and came across this TODO
public static String getTimeAgo(long time, Context ctx) {
if (time < 1000000000000L) {
// if timestamp given in seconds, convert to millis
time *= 1000;
}
long now = getCurrentTime(ctx);
if (time > now || time <= 0) {
return null;
}
// TODO: localize
final long diff = now - time;
if (diff < MINUTE_MILLIS) {
return "just now";
} else if (diff < 2 * MINUTE_MILLIS) {
return "a minute ago";
} else if (diff < 50 * MINUTE_MILLIS) {
return diff / MINUTE_MILLIS + " minutes ago";
} else if (diff < 90 * MINUTE_MILLIS) {
return "an hour ago";
} else if (diff < 24 * HOUR_MILLIS) {
return diff / HOUR_MILLIS + " hours ago";
} else if (diff < 48 * HOUR_MILLIS) {
return "yesterday";
} else {
return diff / DAY_MILLIS + " days ago";
}
}
Which made me wonder what would be the steps to localizing it.
If you don't need custom strings, you can also use DateUtils.getRelativeTimeSpanString, which produces strings such as:
Sample usage:
final CharSequence relativeTimeSpan = DateUtils.getRelativeTimeSpanString(time, now, 0);
From Ian Lake's answer:
final CharSequence relativeTimeSpan = DateUtils.getRelativeTimeSpanString(time, now, 0);
DateUtils.getRelativeTimeSpanString produces things such as the following:
Alternatively, this would allow translations to be provided through the Android res
framework using the given Context
, useful if your desired messaging difference from what you can get out of the framework method.
public static String getTimeAgo(long time, Context context) {
if (time < 1000000000000L)
// if timestamp given in seconds, convert to millis
time *= 1000;
final long now = getCurrentTime(context);
if (time > now || time <= 0) return "";
final Resources res = context.getResources();
final long time_difference = now - time;
if (time_difference < _A_MINUTE)
return res.getString(R.string.just_now);
else if (time_difference < 50 * _A_MINUTE)
return res.getString(R.string.time_ago,
res.getQuantityString(R.plurals.minutes, (int) time_difference / _A_MINUTE, time_difference / _A_MINUTE));
else if (time_difference < 24 * _AN_HOUR)
return res.getString(R.string.time_ago,
res.getQuantityString(R.plurals.hours, (int) time_difference / _AN_HOUR, time_difference / _AN_HOUR));
else if (time_difference < 48 * _AN_HOUR)
return res.getString(R.string.yesterday);
else
return res.getString(R.string.time_ago,
res.getQuantityString(R.plurals.days, (int) time_difference / _A_DAY, time_difference / _A_DAY));
}
where I defined the constants as:
/** One second (in milliseconds) */
private static final int _A_SECOND = 1000;
/** One minute (in milliseconds) */
private static final int _A_MINUTE = 60 * _A_SECOND;
/** One hour (in milliseconds) */
private static final int _AN_HOUR = 60 * _A_MINUTE;
/** One day (in milliseconds) */
private static final int _A_DAY = 24 * _AN_HOUR;
Then the rest of the work is in the structure of the plurals and string resources.
My default local is en, so res/values/strings.xml
:
<!-- time ago strings -->
<string name="just_now">just now</string>
<string name="time_ago">%s ago</string>
<string name="yesterday">yesterday</string>
Then res/values/plurals.xml
:
<plurals name="minutes">
<item quantity="one">a minute</item>
<item quantity="other">%d minutes</item>
</plurals>
<plurals name="hours">
<item quantity="one">an hour</item>
<item quantity="other">%d hours</item>
</plurals>
<plurals name="days">
<item quantity="one">a day</item>
<item quantity="other">%d days</item>
</plurals>
This approach should allow you to localize on the vocabulary and the grammar of the language, as different languages not only have different words for words like "minute", but they also have different rules about how to pluralize words based on the quantity. So the plurals resource utilizes the Android frameworks support of localizing on pluralizations. All that is left is to provide the translations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With