Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fixes: NB#288840 - Song properties, Date format is wrong according to…
… wikipedia KW date format

RevBy: Berthold Krevert

Details:

If the message locale and the time locale have different script directions,
it may happen that the date format gets reordered in an unexpected way if
it is not used on its own but together with text from the message
locale. Protect the date format against such unexpected reordering by
wrapping it in RLE...PDF or LRE...PDF.
  • Loading branch information
Mike FABIAN committed Dec 5, 2011
1 parent 892f025 commit b23283e
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 1 deletion.
41 changes: 41 additions & 0 deletions src/mlocale.cpp
Expand Up @@ -746,6 +746,46 @@ void MLocalePrivate::simplifyDateFormatForMixing(icu::DateFormat *df) const
}
#endif


#ifdef HAVE_ICU
void MLocalePrivate::maybeEmbedDateFormat(icu::DateFormat *df, const QString &categoryNameMessages, const QString &categoryNameTime) const
{
// If the message locale and the time locale have different script directions,
// it may happen that the date format gets reordered in an unexpected way if
// it is not used on its own but together with text from the message
// locale. Protect the date format against such unexpected reordering by
// wrapping it in RLE...PDF or LRE...PDF.
if (df) {
QString categoryScriptTime = MLocale::localeScript(categoryNameTime);
QString categoryScriptMessages = MLocale::localeScript(categoryNameMessages);
bool timeIsRtl = (categoryScriptTime == QLatin1String("Arab")
|| categoryScriptTime == QLatin1String("Hebr"));
bool messagesIsRtl = (categoryScriptMessages == QLatin1String("Arab")
|| categoryScriptMessages == QLatin1String("Hebr"));
if (timeIsRtl != messagesIsRtl) {
icu::UnicodeString icuFormatString;
QString icuFormatQString;
static_cast<SimpleDateFormat *>(df)->toPattern(icuFormatString);
icuFormatQString
= MIcuConversions::unicodeStringToQString(icuFormatString);
if(!icuFormatQString.isEmpty()) {
if (timeIsRtl && !messagesIsRtl) {
icuFormatQString.prepend(QChar(0x202B)); // RIGHT-TO-LEFT EMBEDDING
icuFormatQString.append(QChar(0x202C)); // POP DIRECTIONAL FORMATTING
}
else if (!timeIsRtl && messagesIsRtl) {
icuFormatQString.prepend(QChar(0x202A)); // LEFT-TO-RIGHT EMBEDDING
icuFormatQString.append(QChar(0x202C)); // POP DIRECTIONAL FORMATTING
}
icuFormatString
= MIcuConversions::qStringToUnicodeString(icuFormatQString);
static_cast<SimpleDateFormat *>(df)->applyPattern(icuFormatString);
}
}
}
}
#endif

QString MLocalePrivate::fixCategoryNameForNumbers(const QString &categoryName) const
{
#ifdef HAVE_ICU
Expand Down Expand Up @@ -935,6 +975,7 @@ icu::DateFormat *MLocalePrivate::createDateFormat(MLocale::DateType dateType,
// symbols with the public API
static_cast<SimpleDateFormat *>(df)->adoptDateFormatSymbols(dfs);
}
MLocalePrivate::maybeEmbedDateFormat(df, categoryNameMessages, categoryNameTime);
_dateFormatCache.insert(key, df);
return df;
}
Expand Down
3 changes: 3 additions & 0 deletions src/mlocale_p.h
Expand Up @@ -137,6 +137,9 @@ class MLocalePrivate
// mixing in the month names and weekday names from a different
// language less bad
void simplifyDateFormatForMixing(icu::DateFormat *df) const;
// wrap an ICU date format in LRE...PDF or RLE...PDF
// according to to the direction given as a parameter
void maybeEmbedDateFormat(icu::DateFormat *df, const QString &categoryNameMessages, const QString &categoryNameTime) const;

bool mixingSymbolsWanted(const QString &categoryNameMessages, const QString &categoryNameTime) const;
/*!
Expand Down
27 changes: 26 additions & 1 deletion tests/ut_mcalendar/ut_mcalendar.cpp
Expand Up @@ -30,6 +30,28 @@
using ML10N::MLocale;
using ML10N::MCalendar;

static QString maybeEmbedDateTimeString(const QString &dateTimeString, const MLocale &locale)
{
if (dateTimeString.isEmpty())
return dateTimeString;
QString embeddedDateTimeString = dateTimeString;
QString categoryScriptTime = MLocale::localeScript(locale.categoryName(MLocale::MLcTime));
QString categoryScriptMessages = MLocale::localeScript(locale.categoryName(MLocale::MLcMessages));
bool timeIsRtl = (categoryScriptTime == QLatin1String("Arab")
|| categoryScriptTime == QLatin1String("Hebr"));
bool messagesIsRtl = (categoryScriptMessages == QLatin1String("Arab")
|| categoryScriptMessages == QLatin1String("Hebr"));
if (timeIsRtl && !messagesIsRtl) {
embeddedDateTimeString.prepend(QChar(0x202B)); // RIGHT-TO-LEFT EMBEDDING
embeddedDateTimeString.append(QChar(0x202C)); // POP DIRECTIONAL FORMATTING
}
else if (!timeIsRtl && messagesIsRtl) {
embeddedDateTimeString.prepend(QChar(0x202A)); // LEFT-TO-RIGHT EMBEDDING
embeddedDateTimeString.append(QChar(0x202C)); // POP DIRECTIONAL FORMATTING
}
return embeddedDateTimeString;
}

void Ut_MCalendar::initTestCase()
{
static int argc = 0;
Expand Down Expand Up @@ -889,6 +911,7 @@ void Ut_MCalendar::testIcuFormatString()
expectedResult = dateResults[dateType] + ", " + timeResults[timeType];
else
expectedResult = dateResults[dateType] + ' ' + timeResults[timeType];
expectedResult = maybeEmbedDateTimeString(expectedResult, locale);
QString result = locale.icuFormatString(
static_cast<MLocale::DateType>(dateType),
static_cast<MLocale::TimeType>(timeType),
Expand All @@ -901,7 +924,7 @@ void Ut_MCalendar::testIcuFormatString()
<< " expectedResult: " << expectedResult
<< " result: " << result
<< "\n";
if (expectedResult != "irrelevant")
if (!expectedResult.contains("irrelevant"))
QCOMPARE(result, expectedResult);
}
}
Expand Down Expand Up @@ -1538,6 +1561,7 @@ void Ut_MCalendar::testMLocaleCalendarConversionsFromLocaltimeQDateTime()
expectedResult = dateResults[dateType];
else
expectedResult = dateResults[dateType] + ' ' + timeResults[timeType];
expectedResult = maybeEmbedDateTimeString(expectedResult, locale);
#if defined(VERBOSE_OUTPUT)
QTextStream debugStream(stdout);
debugStream.setCodec("UTF-8");
Expand Down Expand Up @@ -2651,6 +2675,7 @@ void Ut_MCalendar::testMLocaleCalendarConversionsFromMCalendar()
}
else
expectedResult = dateResults[dateType] + ' ' + timeResults[timeType];
expectedResult = maybeEmbedDateTimeString(expectedResult, locale);
#if defined(VERBOSE_OUTPUT)
QTextStream debugStream(stdout);
debugStream.setCodec("UTF-8");
Expand Down

0 comments on commit b23283e

Please sign in to comment.