Add BMessageFormat class.
This can be used to format complex messages properly. It moves the complexity of handling plural forms, gender, and anything else needed into the localizable string, rather than hardcoding it in the code. This moves the difficulty of handling these things properly to people doing translations, rather than relying on developers to do it. Fixes #10755, but our localization must now be updated to make use of the feature.
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2014, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _B_MESSAGE_FORMAT_H_
|
||||
#define _B_MESSAGE_FORMAT_H_
|
||||
|
||||
|
||||
#include <Format.h>
|
||||
|
||||
|
||||
class BMessageFormat: public BFormat {
|
||||
public:
|
||||
status_t Format(BString& buffer, const BString message,
|
||||
const int32 arg);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -27,6 +27,7 @@ local sources =
|
||||
DateFormat.cpp
|
||||
DateTimeFormat.cpp
|
||||
DurationFormat.cpp
|
||||
MessageFormat.cpp
|
||||
NumberFormat.cpp
|
||||
TimeFormat.cpp
|
||||
TimeUnitFormat.cpp
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2014, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#include <MessageFormat.h>
|
||||
|
||||
#include <FormattingConventionsPrivate.h>
|
||||
#include <LanguagePrivate.h>
|
||||
|
||||
#include <ICUWrapper.h>
|
||||
|
||||
#include <unicode/msgfmt.h>
|
||||
|
||||
|
||||
status_t
|
||||
BMessageFormat::Format(BString& output, const BString message, const int32 arg)
|
||||
{
|
||||
UnicodeString buffer;
|
||||
UErrorCode error = U_ZERO_ERROR;
|
||||
|
||||
Formattable arguments[] = {
|
||||
(int32_t)arg
|
||||
};
|
||||
|
||||
Locale* icuLocale
|
||||
= fConventions.UseStringsFromPreferredLanguage()
|
||||
? BLanguage::Private(&fLanguage).ICULocale()
|
||||
: BFormattingConventions::Private(&fConventions).ICULocale();
|
||||
|
||||
MessageFormat formatter(UnicodeString::fromUTF8(message.String()),
|
||||
*icuLocale, error);
|
||||
FieldPosition pos;
|
||||
buffer = formatter.format(arguments, 1, buffer, pos, error);
|
||||
if (!U_SUCCESS(error))
|
||||
return B_ERROR;
|
||||
|
||||
BStringByteSink byteSink(&output);
|
||||
buffer.toUTF8(byteSink);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -52,6 +52,7 @@ UnitTestLib localekittest.so :
|
||||
DateFormatTest.cpp
|
||||
DurationFormatTest.cpp
|
||||
LanguageTest.cpp
|
||||
MessageFormatTest.cpp
|
||||
UnicodeCharTest.cpp
|
||||
|
||||
: be [ TargetLibstdc++ ]
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "DateFormatTest.h"
|
||||
#include "DurationFormatTest.h"
|
||||
#include "LanguageTest.h"
|
||||
#include "MessageFormatTest.h"
|
||||
#include "UnicodeCharTest.h"
|
||||
|
||||
|
||||
@@ -23,6 +24,7 @@ getTestSuite()
|
||||
DateFormatTest::AddTests(*suite);
|
||||
DurationFormatTest::AddTests(*suite);
|
||||
LanguageTest::AddTests(*suite);
|
||||
MessageFormatTest::AddTests(*suite);
|
||||
UnicodeCharTest::AddTests(*suite);
|
||||
|
||||
return suite;
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2014 Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "MessageFormatTest.h"
|
||||
|
||||
#include <Locale.h>
|
||||
#include <MessageFormat.h>
|
||||
|
||||
#include <cppunit/TestCaller.h>
|
||||
#include <cppunit/TestSuite.h>
|
||||
|
||||
|
||||
MessageFormatTest::MessageFormatTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
MessageFormatTest::~MessageFormatTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MessageFormatTest::TestFormat()
|
||||
{
|
||||
BString output;
|
||||
BMessageFormat formatter;
|
||||
|
||||
struct Test {
|
||||
const char* locale;
|
||||
const char* pattern;
|
||||
int32 number;
|
||||
const char* expected;
|
||||
};
|
||||
|
||||
static const char* polishTemplate = "{0, plural, one{Wybrano # obiekt} "
|
||||
"few{Wybrano # obiekty} many{Wybrano # obiektów} "
|
||||
"other{Wybrano # obyektu}}";
|
||||
|
||||
static const Test tests[] = {
|
||||
{"en_US", "{0, plural, one{# dog} other{# dogs}}", 1, "1 dog"},
|
||||
{"en_US", "{0, plural, one{# dog} other{# dogs}}", 2, "2 dogs"},
|
||||
{"pl_PL", polishTemplate, 1, "Wybrano 1 obiekt"},
|
||||
{"pl_PL", polishTemplate, 3, "Wybrano 3 obyektu"},
|
||||
{"pl_PL", polishTemplate, 5, "Wybrano 5 obyektu"},
|
||||
{"pl_PL", polishTemplate, 23, "Wybrano 23 obyektu"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
for (int i = 0; tests[i].pattern != NULL; i++) {
|
||||
status_t result;
|
||||
NextSubTest();
|
||||
output.Truncate(0);
|
||||
BLanguage language(tests[i].locale);
|
||||
formatter.SetLanguage(language);
|
||||
|
||||
result = formatter.Format(output, tests[i].pattern, tests[i].number);
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, result);
|
||||
CPPUNIT_ASSERT_EQUAL(BString(tests[i].expected), output);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*static*/ void
|
||||
MessageFormatTest::AddTests(BTestSuite& parent)
|
||||
{
|
||||
CppUnit::TestSuite& suite = *new CppUnit::TestSuite("MessageFormatTest");
|
||||
|
||||
suite.addTest(new CppUnit::TestCaller<MessageFormatTest>(
|
||||
"MessageFormatTest::TestFormat", &MessageFormatTest::TestFormat));
|
||||
|
||||
parent.addTest("MessageFormatTest", &suite);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2014 Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef MESSAGE_FORMAT_TEST_H
|
||||
#define MESSAGE_FORMAT_TEST_H
|
||||
|
||||
|
||||
#include <TestCase.h>
|
||||
#include <TestSuite.h>
|
||||
|
||||
|
||||
class MessageFormatTest: public BTestCase {
|
||||
public:
|
||||
MessageFormatTest();
|
||||
virtual ~MessageFormatTest();
|
||||
|
||||
void TestFormat();
|
||||
|
||||
static void AddTests(BTestSuite& suite);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user