mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-21 12:40:02 +00:00
ICU-10553 Implement context-sensitive capitalization for relative dates (J)
X-SVN-Rev: 34896
This commit is contained in:
parent
f12f43b80e
commit
fce9b6ba8c
2 changed files with 123 additions and 5 deletions
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2007-2013, International Business Machines Corporation and *
|
||||
* Copyright (C) 2007-2014, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
@ -14,7 +14,10 @@ import java.util.MissingResourceException;
|
|||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import com.ibm.icu.lang.UCharacter;
|
||||
import com.ibm.icu.lang.UProperty;
|
||||
import com.ibm.icu.text.DateFormat;
|
||||
import com.ibm.icu.text.DisplayContext;
|
||||
import com.ibm.icu.text.MessageFormat;
|
||||
import com.ibm.icu.text.SimpleDateFormat;
|
||||
import com.ibm.icu.util.Calendar;
|
||||
|
@ -102,6 +105,8 @@ public class RelativeDateFormat extends DateFormat {
|
|||
FieldPosition fieldPosition) {
|
||||
|
||||
String relativeDayString = null;
|
||||
DisplayContext capitalizationContext = getContext(DisplayContext.Type.CAPITALIZATION);
|
||||
|
||||
if (fDateStyle != DateFormat.NONE) {
|
||||
// calculate the difference, in days, between 'cal' and now.
|
||||
int dayDiff = dayDifference(cal);
|
||||
|
@ -110,6 +115,47 @@ public class RelativeDateFormat extends DateFormat {
|
|||
relativeDayString = getStringForDay(dayDiff);
|
||||
}
|
||||
|
||||
if ( relativeDayString != null && fDatePattern != null &&
|
||||
(fTimePattern == null || fCombinedFormat == null || combinedFormatHasDateAtStart) ) {
|
||||
// capitalize relativeDayString according to context for tense, set formatter no context
|
||||
if ( capitalizationContext == DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
|
||||
(capitalizationContext == DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU && capitalizationForRelativeUnitsListOrMenu) ||
|
||||
(capitalizationContext == DisplayContext.CAPITALIZATION_FOR_STANDALONE && capitalizationForRelativeUnitsStandAlone) ) {
|
||||
// titlecase first word of relativeDayString, do like LocaleDisplayNamesImpl.adjustForUsageAndContext
|
||||
// Note that for languages that *have* case, using the word break properties here works reasonably
|
||||
// well (CLDR word break tailoring is for non-casing languages, and the POSIX locale).
|
||||
int stopPos, stopPosLimit = 8, len = relativeDayString.length();
|
||||
if ( stopPosLimit > len ) {
|
||||
stopPosLimit = len;
|
||||
}
|
||||
for ( stopPos = 0; stopPos < stopPosLimit; stopPos++ ) {
|
||||
int ch = relativeDayString.codePointAt(stopPos);
|
||||
int wb = UCharacter.getIntPropertyValue(ch, UProperty.WORD_BREAK);
|
||||
if ( !(UCharacter.isLowerCase(ch) || wb==UCharacter.WordBreak.EXTEND || wb==UCharacter.WordBreak.SINGLE_QUOTE ||
|
||||
wb==UCharacter.WordBreak.MIDNUMLET || wb==UCharacter.WordBreak.MIDLETTER) ) {
|
||||
break;
|
||||
}
|
||||
if (ch >= 0x10000) {
|
||||
stopPos++;
|
||||
}
|
||||
}
|
||||
if ( stopPos > 0 && stopPos < len ) {
|
||||
String firstWord = relativeDayString.substring(0, stopPos);
|
||||
firstWord = UCharacter.toTitleCase(fLocale, firstWord, null,
|
||||
UCharacter.TITLECASE_NO_LOWERCASE | UCharacter.TITLECASE_NO_BREAK_ADJUSTMENT);
|
||||
relativeDayString = firstWord.concat(relativeDayString.substring(stopPos));
|
||||
} else {
|
||||
// no stopPos, titlecase the whole text
|
||||
relativeDayString = UCharacter.toTitleCase(fLocale, relativeDayString, null,
|
||||
UCharacter.TITLECASE_NO_LOWERCASE | UCharacter.TITLECASE_NO_BREAK_ADJUSTMENT);
|
||||
}
|
||||
}
|
||||
fDateTimeFormat.setContext(DisplayContext.CAPITALIZATION_NONE);
|
||||
} else {
|
||||
// set our context for the formatter
|
||||
fDateTimeFormat.setContext(capitalizationContext);
|
||||
}
|
||||
|
||||
if (fDateTimeFormat != null && (fDatePattern != null || fTimePattern != null)) {
|
||||
// The new way
|
||||
if (fDatePattern == null) {
|
||||
|
@ -169,6 +215,10 @@ public class RelativeDateFormat extends DateFormat {
|
|||
|
||||
private transient URelativeString fDates[] = null; // array of strings
|
||||
|
||||
private transient boolean capitalizationForRelativeUnitsListOrMenu = false;
|
||||
private transient boolean capitalizationForRelativeUnitsStandAlone = false;
|
||||
private transient boolean combinedFormatHasDateAtStart = false;
|
||||
|
||||
|
||||
/**
|
||||
* Get the string at a specific offset.
|
||||
|
@ -216,6 +266,17 @@ public class RelativeDateFormat extends DateFormat {
|
|||
datesSet.add(rs);
|
||||
}
|
||||
fDates = datesSet.toArray(new URelativeString[0]);
|
||||
|
||||
try {
|
||||
rdb = rb.getWithFallback("contextTransforms/tense");
|
||||
int[] intVector = rdb.getIntVector();
|
||||
if (intVector.length >= 2) {
|
||||
capitalizationForRelativeUnitsListOrMenu = (intVector[0] != 0);
|
||||
capitalizationForRelativeUnitsStandAlone = (intVector[1] != 0);
|
||||
}
|
||||
} catch (MissingResourceException e) {
|
||||
// use default
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -284,6 +345,7 @@ public class RelativeDateFormat extends DateFormat {
|
|||
} catch (MissingResourceException e) {
|
||||
// use default
|
||||
}
|
||||
combinedFormatHasDateAtStart = pattern.startsWith("{1}");
|
||||
fCombinedFormat = new MessageFormat(pattern, locale);
|
||||
return fCombinedFormat;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2001-2013, International Business Machines Corporation and *
|
||||
* Copyright (C) 2001-2014, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
@ -4200,6 +4200,32 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
|
|||
new TestContextItem( "cs", "LLLL y", DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU, "\u010Cervenec 2008" ),
|
||||
new TestContextItem( "cs", "LLLL y", DisplayContext.CAPITALIZATION_FOR_STANDALONE, "\u010Dervenec 2008" ),
|
||||
};
|
||||
class TestRelativeContextItem {
|
||||
public String locale;
|
||||
public DisplayContext capitalizationContext;
|
||||
public String expectedFormatToday;
|
||||
public String expectedFormatYesterday;
|
||||
// Simple constructor
|
||||
public TestRelativeContextItem(String loc, DisplayContext capCtxt, String expFmtToday, String expFmtYesterday) {
|
||||
locale = loc;
|
||||
capitalizationContext = capCtxt;
|
||||
expectedFormatToday = expFmtToday;
|
||||
expectedFormatYesterday = expFmtYesterday;
|
||||
}
|
||||
};
|
||||
final TestRelativeContextItem[] relItems = {
|
||||
new TestRelativeContextItem( "en", DisplayContext.CAPITALIZATION_NONE, "today", "yesterday" ),
|
||||
new TestRelativeContextItem( "en", DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, "today", "yesterday" ),
|
||||
new TestRelativeContextItem( "en", DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, "Today", "Yesterday" ),
|
||||
new TestRelativeContextItem( "en", DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU, "Today", "Yesterday" ),
|
||||
new TestRelativeContextItem( "en", DisplayContext.CAPITALIZATION_FOR_STANDALONE, "Today", "Yesterday" ),
|
||||
new TestRelativeContextItem( "nb", DisplayContext.CAPITALIZATION_NONE, "i dag", "i g\u00E5r" ),
|
||||
new TestRelativeContextItem( "nb", DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, "i dag", "i g\u00E5r" ),
|
||||
new TestRelativeContextItem( "nb", DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, "I dag", "I g\u00E5r" ),
|
||||
new TestRelativeContextItem( "nb", DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU, "i dag", "i g\u00E5r" ),
|
||||
new TestRelativeContextItem( "nb", DisplayContext.CAPITALIZATION_FOR_STANDALONE, "I dag", "I g\u00E5r" ),
|
||||
};
|
||||
|
||||
Calendar cal = new GregorianCalendar(2008, Calendar.JULY, 2);
|
||||
for (TestContextItem item: items) {
|
||||
ULocale locale = new ULocale(item.locale);
|
||||
|
@ -4211,14 +4237,44 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
|
|||
FieldPosition fpos2 = new FieldPosition(0);
|
||||
sdfmt.format(cal, result2, fpos2);
|
||||
if (result2.toString().compareTo(item.expectedFormat) != 0) {
|
||||
errln("FAIL: format (default context) for locale " + item.locale + ", capitalizationContext " + item.capitalizationContext +
|
||||
errln("FAIL: format for locale " + item.locale + ", capitalizationContext " + item.capitalizationContext +
|
||||
", expected \"" + item.expectedFormat + "\", got \"" + result2 + "\"");
|
||||
}
|
||||
|
||||
// now read back context, make sure it is what we set
|
||||
// now read back context, make sure it is what we set (testing with DateFormat subclass)
|
||||
DisplayContext capitalizationContext = sdfmt.getContext(DisplayContext.Type.CAPITALIZATION);
|
||||
if (capitalizationContext != item.capitalizationContext) {
|
||||
errln("FAIL: getDefaultContext for locale " + item.locale + ", capitalizationContext " + item.capitalizationContext +
|
||||
errln("FAIL: getContext for locale " + item.locale + ", capitalizationContext " + item.capitalizationContext +
|
||||
", but got context " + capitalizationContext);
|
||||
}
|
||||
}
|
||||
for (TestRelativeContextItem relItem: relItems) {
|
||||
ULocale locale = new ULocale(relItem.locale);
|
||||
DateFormat dfmt = DateFormat.getDateInstance(DateFormat.RELATIVE_LONG, locale);
|
||||
Date today = new Date();
|
||||
|
||||
// now try context & standard format call
|
||||
dfmt.setContext(relItem.capitalizationContext);
|
||||
cal.setTime(today);
|
||||
StringBuffer result2 = new StringBuffer();
|
||||
FieldPosition fpos2 = new FieldPosition(0);
|
||||
dfmt.format(cal, result2, fpos2);
|
||||
if (result2.toString().compareTo(relItem.expectedFormatToday) != 0) {
|
||||
errln("FAIL: format today for locale " + relItem.locale + ", capitalizationContext " + relItem.capitalizationContext +
|
||||
", expected \"" + relItem.expectedFormatToday + "\", got \"" + result2 + "\"");
|
||||
}
|
||||
cal.add(Calendar.DATE, -1);
|
||||
result2.setLength(0);
|
||||
dfmt.format(cal, result2, fpos2);
|
||||
if (result2.toString().compareTo(relItem.expectedFormatYesterday) != 0) {
|
||||
errln("FAIL: format yesterday for locale " + relItem.locale + ", capitalizationContext " + relItem.capitalizationContext +
|
||||
", expected \"" + relItem.expectedFormatYesterday + "\", got \"" + result2 + "\"");
|
||||
}
|
||||
|
||||
// now read back context, make sure it is what we set (testing with DateFormat itself)
|
||||
DisplayContext capitalizationContext = dfmt.getContext(DisplayContext.Type.CAPITALIZATION);
|
||||
if (capitalizationContext != relItem.capitalizationContext) {
|
||||
errln("FAIL: getContext for locale " + relItem.locale + ", capitalizationContext " + relItem.capitalizationContext +
|
||||
", but got context " + capitalizationContext);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue