[haiku-commits] haiku: hrev47971 - in src: tests/kits/locale servers/mail kits/tracker add-ons/mail_daemon/inbound_filters/notifier kits/locale

  • From: pulkomandy@xxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 7 Oct 2014 10:05:43 +0200 (CEST)

hrev47971 adds 3 changesets to branch 'master'
old head: c9f5d71c97e6a56a81ce3091a581f7a3261623f2
new head: 53382a8aa7d12cc7d72e36acd6ac7c70429eddf0
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=53382a8+%5Ec9f5d71

----------------------------------------------------------------------------

699ddf4: DateFormatTest: fix after ICU upgrade
  
  * Timezone names have changed. Test the medium time format which doesn't
  include them, as we aren't forcing a specific one.
  * French date format also changed to use 4 digit year name.

0da7796: 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.

53382a8: Start making use of BMessageFormat.

                                 [ Adrien Destugues <pulkomandy@xxxxxxxxx> ]

----------------------------------------------------------------------------

15 files changed, 230 insertions(+), 109 deletions(-)
headers/os/locale/MessageFormat.h                | 19 +++++
.../inbound_filters/notifier/filter.cpp          | 26 +++----
src/apps/aboutsystem/AboutSystem.cpp             | 14 ++--
src/apps/pairs/PairsWindow.cpp                   | 14 ++--
src/kits/locale/Jamfile                          |  1 +
src/kits/locale/MessageFormat.cpp                | 41 +++++++++++
src/kits/tracker/CountView.cpp                   | 11 ++-
src/kits/tracker/InfoWindow.cpp                  | 38 +++-------
src/servers/mail/DeskbarView.cpp                 | 18 ++---
src/servers/mail/MailDaemon.cpp                  | 42 ++++-------
src/tests/kits/locale/DateFormatTest.cpp         | 12 ++--
src/tests/kits/locale/Jamfile                    |  1 +
src/tests/kits/locale/LocaleKitTestAddon.cpp     |  2 +
src/tests/kits/locale/MessageFormatTest.cpp      | 76 ++++++++++++++++++++
src/tests/kits/locale/MessageFormatTest.h        | 24 +++++++

############################################################################

Commit:      699ddf447c89331a9927f8e1132159e7737f481d
URL:         http://cgit.haiku-os.org/haiku/commit/?id=699ddf4
Author:      Adrien Destugues <pulkomandy@xxxxxxxxx>
Date:        Tue Oct  7 06:49:45 2014 UTC

DateFormatTest: fix after ICU upgrade

* Timezone names have changed. Test the medium time format which doesn't
include them, as we aren't forcing a specific one.
* French date format also changed to use 4 digit year name.

----------------------------------------------------------------------------

diff --git a/src/tests/kits/locale/DateFormatTest.cpp 
b/src/tests/kits/locale/DateFormatTest.cpp
index 201d2d1..2575eaf 100644
--- a/src/tests/kits/locale/DateFormatTest.cpp
+++ b/src/tests/kits/locale/DateFormatTest.cpp
@@ -40,11 +40,11 @@ DateFormatTest::TestFormat()
 
        static const Value values[] = {
                {"en", "en_US", 12345, "1/1/70", "January 1, 1970",
-                       "4:25 AM", "4:25:45 AM CET"},
-               {"fr", "fr_FR", 12345, "01/01/70", "1 janvier 1970",
-                       "04:25", "04:25:45 HNEC"},
-               {"fr", "fr_FR", 12345678, "23/05/70", "23 mai 1970",
-                       "22:21", "22:21:18 HNEC"},
+                       "4:25 AM", "4:25:45 AM"},
+               {"fr", "fr_FR", 12345, "01/01/1970", "1 janvier 1970",
+                       "04:25", "04:25:45"},
+               {"fr", "fr_FR", 12345678, "23/05/1970", "23 mai 1970",
+                       "22:21", "22:21:18"},
                {NULL}
        };
 
@@ -71,7 +71,7 @@ DateFormatTest::TestFormat()
                CPPUNIT_ASSERT_EQUAL(B_OK, result);
                CPPUNIT_ASSERT_EQUAL(BString(values[i].shortTime), output);
 
-               result = timeFormat.Format(output, values[i].time, 
B_LONG_TIME_FORMAT);
+               result = timeFormat.Format(output, values[i].time, 
B_MEDIUM_TIME_FORMAT);
                CPPUNIT_ASSERT_EQUAL(B_OK, result);
                CPPUNIT_ASSERT_EQUAL(BString(values[i].longTime), output);
        }

############################################################################

Commit:      0da7796e6c95de168ac77151a520c853c120a968
URL:         http://cgit.haiku-os.org/haiku/commit/?id=0da7796
Author:      Adrien Destugues <pulkomandy@xxxxxxxxx>
Date:        Tue Oct  7 06:51:23 2014 UTC

Ticket:      https://dev.haiku-os.org/ticket/10755

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.

----------------------------------------------------------------------------

diff --git a/headers/os/locale/MessageFormat.h 
b/headers/os/locale/MessageFormat.h
new file mode 100644
index 0000000..ff2a9c2
--- /dev/null
+++ b/headers/os/locale/MessageFormat.h
@@ -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
diff --git a/src/kits/locale/Jamfile b/src/kits/locale/Jamfile
index 5b3f509..c21abba 100644
--- a/src/kits/locale/Jamfile
+++ b/src/kits/locale/Jamfile
@@ -27,6 +27,7 @@ local sources =
        DateFormat.cpp
        DateTimeFormat.cpp
        DurationFormat.cpp
+       MessageFormat.cpp
        NumberFormat.cpp
        TimeFormat.cpp
        TimeUnitFormat.cpp
diff --git a/src/kits/locale/MessageFormat.cpp 
b/src/kits/locale/MessageFormat.cpp
new file mode 100644
index 0000000..b5af3ec
--- /dev/null
+++ b/src/kits/locale/MessageFormat.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;
+}
diff --git a/src/tests/kits/locale/Jamfile b/src/tests/kits/locale/Jamfile
index af5166c..2fd68b6 100644
--- a/src/tests/kits/locale/Jamfile
+++ b/src/tests/kits/locale/Jamfile
@@ -52,6 +52,7 @@ UnitTestLib localekittest.so :
        DateFormatTest.cpp
        DurationFormatTest.cpp
        LanguageTest.cpp
+       MessageFormatTest.cpp
        UnicodeCharTest.cpp
 
        : be [ TargetLibstdc++ ]
diff --git a/src/tests/kits/locale/LocaleKitTestAddon.cpp 
b/src/tests/kits/locale/LocaleKitTestAddon.cpp
index 460f32f..2d04a79 100644
--- a/src/tests/kits/locale/LocaleKitTestAddon.cpp
+++ b/src/tests/kits/locale/LocaleKitTestAddon.cpp
@@ -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;
diff --git a/src/tests/kits/locale/MessageFormatTest.cpp 
b/src/tests/kits/locale/MessageFormatTest.cpp
new file mode 100644
index 0000000..65407cb
--- /dev/null
+++ b/src/tests/kits/locale/MessageFormatTest.cpp
@@ -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);
+}
diff --git a/src/tests/kits/locale/MessageFormatTest.h 
b/src/tests/kits/locale/MessageFormatTest.h
new file mode 100644
index 0000000..924f679
--- /dev/null
+++ b/src/tests/kits/locale/MessageFormatTest.h
@@ -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

############################################################################

Revision:    hrev47971
Commit:      53382a8aa7d12cc7d72e36acd6ac7c70429eddf0
URL:         http://cgit.haiku-os.org/haiku/commit/?id=53382a8
Author:      Adrien Destugues <pulkomandy@xxxxxxxxx>
Date:        Tue Oct  7 07:26:45 2014 UTC

Start making use of BMessageFormat.

----------------------------------------------------------------------------

diff --git a/src/add-ons/mail_daemon/inbound_filters/notifier/filter.cpp 
b/src/add-ons/mail_daemon/inbound_filters/notifier/filter.cpp
index d417ed7..1ad15eb 100644
--- a/src/add-ons/mail_daemon/inbound_filters/notifier/filter.cpp
+++ b/src/add-ons/mail_daemon/inbound_filters/notifier/filter.cpp
@@ -10,6 +10,7 @@
 #include <Beep.h>
 #include <Catalog.h>
 #include <Message.h>
+#include <MessageFormat.h>
 #include <Path.h>
 #include <String.h>
 
@@ -67,15 +68,12 @@ NotifyFilter::MailboxSynced(status_t status)
                system_beep("New E-mail");
 
        if (fStrategy & alert) {
-               BString text, numString;
-               if (fNNewMessages != 1)
-                       text << B_TRANSLATE("You have %num new messages for 
%name.");
-               else
-                       text << B_TRANSLATE("You have %num new message for 
%name.");
+               BString text;
+               BMessageFormat().Format(text, B_TRANSLATE(
+                       "You have {0, plural, one{# new message} other{# new 
messages}} "
+                       "for %account."), fNNewMessages);
 
-               numString << fNNewMessages;
-               text.ReplaceFirst("%num", numString);
-               text.ReplaceFirst("%name", 
fMailProtocol.AccountSettings().Name());
+               text.ReplaceFirst("%account", 
fMailProtocol.AccountSettings().Name());
 
                BAlert *alert = new BAlert(B_TRANSLATE("New messages"), 
text.String(),
                        B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL);
@@ -99,14 +97,10 @@ NotifyFilter::MailboxSynced(status_t status)
        }
 
        if (fStrategy & log_window) {
-               BString message, numString;
-               if (fNNewMessages != 1)
-                       message << B_TRANSLATE("%num new messages");
-               else
-                       message << B_TRANSLATE("%num new message");
-
-               numString << fNNewMessages;
-               message.ReplaceFirst("%num", numString);
+               BString message;
+               BMessageFormat().Format(message, B_TRANSLATE(
+                       "{0, plural, one{# new message} other{# new 
messages}}"),
+                       fNNewMessages);
 
                fMailProtocol.ShowMessage(message.String());
        }
diff --git a/src/apps/aboutsystem/AboutSystem.cpp 
b/src/apps/aboutsystem/AboutSystem.cpp
index ea834d1..fd1a68b 100644
--- a/src/apps/aboutsystem/AboutSystem.cpp
+++ b/src/apps/aboutsystem/AboutSystem.cpp
@@ -29,6 +29,7 @@
 #include <Font.h>
 #include <fs_attr.h>
 #include <LayoutBuilder.h>
+#include <MessageFormat.h>
 #include <MessageRunner.h>
 #include <Messenger.h>
 #include <OS.h>
@@ -442,13 +443,10 @@ AboutView::AboutView()
                B_ALIGN_VERTICAL_UNSET));
 
        // CPU count, type and clock speed
-       char processorLabel[256];
-       if (systemInfo.cpu_count > 1) {
-               snprintf(processorLabel, sizeof(processorLabel),
-                       B_TRANSLATE("%ld Processors:"), systemInfo.cpu_count);
-       } else
-               strlcpy(processorLabel, B_TRANSLATE("Processor:"),
-                       sizeof(processorLabel));
+       BString processorLabel;
+       BMessageFormat().Format(processorLabel, B_TRANSLATE_COMMENT(
+               "{0, plural, one{Processors:} other{# Processors:}}",
+               "\"Processor:\" or \"2 Processors:\""), systemInfo.cpu_count);
 
        uint32 topologyNodeCount = 0;
        cpu_topology_node_info* topology = NULL;
@@ -550,7 +548,7 @@ AboutView::AboutView()
                                .Add(versionView)
                                .Add(abiView)
                                .AddStrut(offset)
-                               .Add(_CreateLabel("cpulabel", processorLabel))
+                               .Add(_CreateLabel("cpulabel", 
processorLabel.String()))
                                .Add(cpuView)
                                .Add(frequencyView)
                                .AddStrut(offset)
diff --git a/src/apps/pairs/PairsWindow.cpp b/src/apps/pairs/PairsWindow.cpp
index 639d883..8a198a2 100644
--- a/src/apps/pairs/PairsWindow.cpp
+++ b/src/apps/pairs/PairsWindow.cpp
@@ -22,6 +22,7 @@
 #include <Menu.h>
 #include <MenuBar.h>
 #include <MenuItem.h>
+#include <MessageFormat.h>
 #include <MessageRunner.h>
 #include <String.h>
 #include <TextView.h>
@@ -294,17 +295,20 @@ PairsWindow::MessageReceived(BMessage* message)
 
                        // game end and results
                        if (fFinishPairs == pairsButtonList->CountItems() / 2) {
-                               BString score;
-                               score << fButtonClicks;
                                BString strAbout = B_TRANSLATE("%app%\n"
                                        "\twritten by Ralf Schülke\n"
                                        "\tCopyright 2008-2010, Haiku Inc.\n"
-                                       "\n"
-                                       "You completed the game in %num% 
clicks.\n");
+                                       "\n");
 
                                strAbout.ReplaceFirst("%app%",
                                        B_TRANSLATE_SYSTEM_NAME("Pairs"));
-                               strAbout.ReplaceFirst("%num%", score);
+
+                               // Note: in english the singular form is never 
used, but other
+                               // languages behave differently.
+                               BMessageFormat().Format(strAbout, B_TRANSLATE(
+                                       "You completed the game in "
+                                       "{0, plural, one{# click} other{# 
clicks}}.\n"),
+                                       fButtonClicks);
 
                                BAlert* alert = new BAlert("about",
                                        strAbout.String(),
diff --git a/src/kits/tracker/CountView.cpp b/src/kits/tracker/CountView.cpp
index 711ebde..195ac4f 100644
--- a/src/kits/tracker/CountView.cpp
+++ b/src/kits/tracker/CountView.cpp
@@ -41,6 +41,7 @@ All rights reserved.
 #include <Catalog.h>
 #include <ControlLook.h>
 #include <Locale.h>
+#include <MessageFormat.h>
 
 #include "AutoLock.h"
 #include "Bitmaps.h"
@@ -230,13 +231,11 @@ BCountView::Draw(BRect updateRect)
        } else {
                if (fLastCount == 0)
                        itemString << B_TRANSLATE("no items");
-               else if (fLastCount == 1)
-                       itemString << B_TRANSLATE("1 item");
                else {
-                       itemString.SetTo(B_TRANSLATE("%num items"));
-                       char numString[256];
-                       snprintf(numString, sizeof(numString), "%" B_PRId32, 
fLastCount);
-                       itemString.ReplaceFirst("%num", numString);
+                       BMessageFormat().Format(itemString, B_TRANSLATE_COMMENT(
+                               "{0, plural, one{# item} other{# items}}",
+                               "Number of selected items: \"1 item\" or \"2 
items\""),
+                               fLastCount);
                }
        }
 
diff --git a/src/kits/tracker/InfoWindow.cpp b/src/kits/tracker/InfoWindow.cpp
index 37061ec..0e311e5 100644
--- a/src/kits/tracker/InfoWindow.cpp
+++ b/src/kits/tracker/InfoWindow.cpp
@@ -47,6 +47,7 @@ All rights reserved.
 #include <Font.h>
 #include <Locale.h>
 #include <MenuField.h>
+#include <MessageFormat.h>
 #include <Mime.h>
 #include <NodeInfo.h>
 #include <NodeMonitor.h>
@@ -675,43 +676,22 @@ void
 BInfoWindow::GetSizeString(BString &result, off_t size, int32 fileCount)
 {
        char sizeBuffer[128];
+       BMessageFormat messageFormat;
+
        result << string_for_size((double)size, sizeBuffer, sizeof(sizeBuffer));
 
-       // when we show the byte size, format it with a thousands delimiter
-       // TODO: use BCountry::FormatNumber
        if (size >= kKBSize) {
-               char numStr[128];
-               snprintf(numStr, sizeof(numStr), "%" B_PRIdOFF, size);
-               BString bytes;
-
-               uint32 length = strlen(numStr);
-               if (length >= 4) {
-                       uint32 charsTillComma = length % 3;
-                       if (charsTillComma == 0)
-                               charsTillComma = 3;
-
-                       uint32 numberIndex = 0;
-
-                       while (numStr[numberIndex]) {
-                               bytes += numStr[numberIndex++];
-                               if (--charsTillComma == 0 && 
numStr[numberIndex]) {
-                                       bytes += ',';
-                                       charsTillComma = 3;
-                               }
-                       }
-               }
-
-               result << " " << B_TRANSLATE("(%bytes bytes)");
+               result << " ";
+               messageFormat.Format(result, B_TRANSLATE(
+                       "{0, plural, one{(# byte)} other{(# bytes)}}"), size);
                        // "bytes" translation could come from string_for_size
                        // which could be part of the localekit itself
-               result.ReplaceFirst("%bytes", bytes);
        }
 
        if (fileCount != 0) {
-               result << " " << B_TRANSLATE("for %num files");
-               BString countString;
-               countString << fileCount;
-               result.ReplaceFirst("%num", countString);
+               result << " ";
+               messageFormat.Format(result, B_TRANSLATE(
+                       "{0, plural, one{for # file} other{for # files}}"), 
fileCount);
        }
 }
 
diff --git a/src/servers/mail/DeskbarView.cpp b/src/servers/mail/DeskbarView.cpp
index eca435c..520c5b9 100644
--- a/src/servers/mail/DeskbarView.cpp
+++ b/src/servers/mail/DeskbarView.cpp
@@ -19,6 +19,7 @@
 #include <kernel/fs_info.h>
 #include <kernel/fs_index.h>
 #include <MenuItem.h>
+#include <MessageFormat.h>
 #include <Messenger.h>
 #include <NodeInfo.h>
 #include <NodeMonitor.h>
@@ -525,7 +526,7 @@ DeskbarView::_BuildMenu()
                                item = new BMenuItem(path.Leaf(), msg);
 
                        menu->AddItem(item);
-                       if(entry.InitCheck() != B_OK)
+                       if (entry.InitCheck() != B_OK)
                                item->SetEnabled(false);
                }
                if (count > 0)
@@ -541,14 +542,10 @@ DeskbarView::_BuildMenu()
        // The New E-mail query
 
        if (fNewMessages > 0) {
-               BString string, numString;
-               if (fNewMessages != 1)
-                       string << B_TRANSLATE("%num new messages");
-               else
-                       string << B_TRANSLATE("%num new message");
-
-               numString << fNewMessages;
-               string.ReplaceFirst("%num", numString);
+               BString string;
+               BMessageFormat().Format(string, B_TRANSLATE(
+                       "{0, plural, one{# new message} other{# new 
messages}}"),
+                       fNewMessages);
 
                _GetNewQueryRef(ref);
 
@@ -559,8 +556,7 @@ DeskbarView::_BuildMenu()
                navMenu->SetNavDir(&ref);
 
                menu->AddItem(item);
-       }
-       else {
+       } else {
                menu->AddItem(item = new BMenuItem(B_TRANSLATE("No new 
messages"),
                        NULL));
                item->SetEnabled(false);
diff --git a/src/servers/mail/MailDaemon.cpp b/src/servers/mail/MailDaemon.cpp
index 05586c5..f1e5dab 100644
--- a/src/servers/mail/MailDaemon.cpp
+++ b/src/servers/mail/MailDaemon.cpp
@@ -20,6 +20,7 @@
 #include <FindDirectory.h>
 #include <fs_index.h>
 #include <IconUtils.h>
+#include <MessageFormat.h>
 #include <NodeMonitor.h>
 #include <Notification.h>
 #include <Path.h>
@@ -175,17 +176,12 @@ MailDaemonApp::ReadyToRun()
                fQueries.AddItem(query);
        }
 
-       BString string, numString;
+       BString string;
        if (fNewMessages > 0) {
-               if (fNewMessages != 1)
-                       string << B_TRANSLATE("%num new messages.");
-               else
-                       string << B_TRANSLATE("%num new message.");
-
-               numString << fNewMessages;
-               string.ReplaceFirst("%num", numString);
-       }
-       else
+               BMessageFormat().Format(string, B_TRANSLATE(
+                       "{0, plural, one{# new message} other{# new 
messages}}"),
+                       fNewMessages);
+       } else
                string = B_TRANSLATE("No new messages");
 
        fCentralBeep = false;
@@ -349,15 +345,10 @@ MailDaemonApp::MessageReceived(BMessage* msg)
                case 'numg':
                {
                        int32 numMessages = msg->FindInt32("num_messages");
-                       BString numString;
-
-                       if (numMessages > 1)
-                               fAlertString << B_TRANSLATE("%num new messages 
for %name\n");
-                       else
-                               fAlertString << B_TRANSLATE("%num new message 
for %name\n");
+                       BMessageFormat().Format(fAlertString, B_TRANSLATE(
+                               "{0, plural, one{# new message} other{# new 
messages}} "
+                               "for %name\n"), numMessages);
 
-                       numString << numMessages;
-                       fAlertString.ReplaceFirst("%num", numString);
                        fAlertString.ReplaceFirst("%name", 
msg->FindString("name"));
                        break;
                }
@@ -375,18 +366,13 @@ MailDaemonApp::MessageReceived(BMessage* msg)
                                        break;
                        }
 
-                       BString string, numString;
+                       BString string;
 
                        if (fNewMessages > 0) {
-                               if (fNewMessages != 1)
-                                       string << B_TRANSLATE("%num new 
messages.");
-                               else
-                                       string << B_TRANSLATE("%num new 
message.");
-
-                       numString << fNewMessages;
-                       string.ReplaceFirst("%num", numString);
-                       }
-                       else
+                               BMessageFormat().Format(string, B_TRANSLATE(
+                                       "{0, plural, one{# new message.} 
other{# new messages.}}"),
+                                       fNewMessages);
+                       } else
                                string << B_TRANSLATE("No new messages.");
 
                        fNotification->SetTitle(string.String());


Other related posts: