Qt.locale() and JS locale type extension.
authorMartin Jones <martin.jones@nokia.com>
Thu, 10 Nov 2011 08:33:27 +0000 (18:33 +1000)
committerQt by Nokia <qt-info@nokia.com>
Tue, 22 Nov 2011 02:32:21 +0000 (03:32 +0100)
Task-number: QTBUG-17129

Change-Id: I69cbbe858735b750b4e37ce489f2fa1ad5d8b5d3
Reviewed-by: Martin Jones <martin.jones@nokia.com>
26 files changed:
doc/src/declarative/qdeclarativei18n.qdoc
doc/src/declarative/qmldate.qdoc [new file with mode: 0644]
doc/src/declarative/qmlnumber.qdoc [new file with mode: 0644]
doc/src/qtquick1/declarativeui.qdoc
doc/src/qtquick1/qdeclarativei18n.qdoc
examples/declarative/locale/locale.qml [new file with mode: 0644]
src/declarative/qml/qdeclarativeengine.cpp
src/declarative/qml/qdeclarativeengine_p.h
src/declarative/qml/qdeclarativelocale.cpp [new file with mode: 0644]
src/declarative/qml/qdeclarativelocale_p.h [new file with mode: 0644]
src/declarative/qml/qml.pri
src/declarative/qml/v8/qdeclarativebuiltinfunctions.cpp
src/declarative/qml/v8/qdeclarativebuiltinfunctions_p.h
src/declarative/qml/v8/qjsengine.cpp
src/declarative/qml/v8/qjsengine.h
src/declarative/qml/v8/qjsengine_p.h [new file with mode: 0644]
src/declarative/qml/v8/qv8engine.cpp
src/declarative/qml/v8/qv8engine_p.h
src/declarative/qml/v8/script.pri
tests/auto/declarative/declarative.pro
tests/auto/declarative/qdeclarativelocale/data/date.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativelocale/data/functions.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativelocale/data/number.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativelocale/data/properties.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativelocale/qdeclarativelocale.pro [new file with mode: 0644]
tests/auto/declarative/qdeclarativelocale/tst_qdeclarativelocale.cpp [new file with mode: 0644]

index 0042200..79a9356 100644 (file)
@@ -34,6 +34,7 @@
 \nextpage {QML Features}
 \title QML Internationalization
 
+\section1 Translation
 
 Strings in QML can be marked for translation using the qsTr(), qsTranslate(),
 QT_TR_NOOP(), and QT_TRANSLATE_NOOP() functions.
@@ -55,14 +56,14 @@ capabilities are described more fully in:
 
 You can test a translation with the \l {QML Viewer} using the -translation option.
 
-\section1 Example
+\section2 Example
 
 First we create a simple QML file with text to be translated. The string
 that needs to be translated is enclosed in a call to \c qsTr().
 
 hello.qml:
 \qml
-import QtQuick 1.0
+import QtQuick 2.0
 
 Rectangle {
     width: 200; height: 200
@@ -83,6 +84,15 @@ Finally, we can test the translation:
 qmlviewer -translation hello.qm hello.qml
 \endcode
 
-
 You can see a complete example and source code in the \l{declarative/i18n}{QML Internationalization example}.
+
+\section1 Localization
+
+Localization is the process of adapting to local conventions,
+for example presenting dates and times using the locally preferred formats.
+
+Qt Quick supports localization via the \l {QtQuick2::Locale}{Locale} object and extensions to the
+ECMAScript \l {QtQuick2::Date}{Date} and \l {QtQuick2::Number}{Number} types.
+
+
 */
diff --git a/doc/src/declarative/qmldate.qdoc b/doc/src/declarative/qmldate.qdoc
new file mode 100644 (file)
index 0000000..c0552aa
--- /dev/null
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms
+** and conditions contained in a signed written agreement between you
+** and Nokia.
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+    \qmlclass Date
+    \inqmlmodule QtQuick 2
+    \brief The Date object provides date functions
+
+    The QML Date object extends the JS Date object with
+    locale aware functions.
+
+    Functions that accept a locale format may be either an enumeration
+    value:
+    \table
+    \row \i Locale.LongFormat \i The long version of day and month names; for example, returning "January" as a month name.
+    \row \i Locale.ShortFormat \i The short version of day and month names; for example, returning "Jan" as a month name.
+    \row \i Locale.NarrowFormat \i A special version of day and month names for use when space is limited;
+        for example, returning "J" as a month name. Note that the narrow format might contain
+        the same text for different months and days or it can even be an empty string if the
+        locale doesn't support narrow names, so you should avoid using it for date formatting.
+        Also, for the system locale this format is the same as ShortFormat.
+    \endtable
+
+    or a string specifying the format:
+    \table
+    \header \i Expression \i Output
+    \row \i d \i the day as number without a leading zero (1 to 31)
+    \row \i dd \i the day as number with a leading zero (01 to 31)
+    \row \i ddd
+         \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
+    \row \i dddd
+         \i the long localized day name (e.g. 'Monday' to 'Sunday').
+    \row \i M \i the month as number without a leading zero (1 to 12)
+    \row \i MM \i the month as number with a leading zero (01 to 12)
+    \row \i MMM
+         \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
+    \row \i MMMM
+         \i the long localized month name (e.g. 'January' to 'December').
+    \row \i yy \i the year as two digit number (00 to 99)
+    \row \i yyyy \i the year as four digit number. If the year is negative,
+            a minus sign is prepended in addition.
+    \endtable
+
+    All other input characters will be ignored. Any sequence of characters that
+    are enclosed in singlequotes will be treated as text and not be used as an
+    expression. Two consecutive singlequotes ("''") are replaced by a singlequote
+    in the output.
+
+    Example format strings (assuming that the Date is the 20 July
+    1969):
+
+    \table
+    \header \o Format            \o Result
+    \row    \o dd.MM.yyyy        \o 20.07.1969
+    \row    \o ddd MMMM d yy     \o Sun July 20 69
+    \row    \o 'The day is' dddd \o The day is Sunday
+    \endtable
+
+    \sa {QtQuick2::Locale}{Locale}
+*/
+
+/*!
+    \qmlmethod string Date::toLocaleString(locale,format)
+
+    Converts the Date to a string containing the date and time
+    suitable for the specified \a locale
+    in the specified \a format.
+
+    If the format is not specified Locale.LongFormat will be used.
+
+    If \a locale is not specified, the default locale will be used.
+
+    The following example shows the current date and time formatted
+    for the German locale:
+    \code
+    import QtQuick 2.0
+
+    Text {
+        text: "The date is: " +  Date().toLocaleString(Qt.locale("de_DE"))
+    }
+    \endcode
+*/
+
+/*!
+    \qmlmethod string Date::toLocaleDateString(locale,format)
+
+    Converts the Date to a string containing the date suitable for the specified \a locale
+    in the specified \a format.
+
+    If the format is not specified Locale.LongFormat will be used.
+
+    If \a locale is not specified, the default locale will be used.
+
+    The following example shows the current date formatted
+    for the German locale:
+    \code
+    import QtQuick 2.0
+
+    Text {
+        text: "The date is: " +  Date().toLocaleDateString(Qt.locale("de_DE"))
+    }
+    \endcode
+*/
+
+/*!
+    \qmlmethod string Date::toLocaleTimeString(locale,format)
+
+    Converts the Date to a string containing the time suitable for the specified \a locale
+    in the specified \a format.
+
+    If the format is not specified Locale.LongFormat will be used.
+
+    If \a locale is not specified, the default locale will be used.
+
+    The following example shows the current time formatted
+    for the German locale:
+    \code
+    import QtQuick 2.0
+
+    Text {
+        text: "The date is: " +  Date().toLocaleTimeString(Qt.locale("de_DE"))
+    }
+    \endcode
+*/
+
diff --git a/doc/src/declarative/qmlnumber.qdoc b/doc/src/declarative/qmlnumber.qdoc
new file mode 100644 (file)
index 0000000..0b4341d
--- /dev/null
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms
+** and conditions contained in a signed written agreement between you
+** and Nokia.
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+    \qmlclass Number
+    \inqmlmodule QtQuick 2
+    \brief The Number object provides represents a number value
+
+    The QML Number object extends the JS Number object with
+    locale aware functions.
+
+    \sa {QtQuick2::Locale}{Locale}
+*/
+
+/*!
+    \qmlmethod string Number::toLocaleString(locale,format,precision)
+
+    Converts the Number to a string suitable for the specified \a locale
+    in the specified \a format, with the specified \a precision.
+
+    Valid formats are:
+    \list
+    \o 'f'   Decimal floating point, e.g. 248.65
+    \o 'e'   Scientific notation using e character, e.g. 2.4865e+2
+    \o 'E'   Scientific notation using E character, e.g. 2.4865E+2
+    \o 'g'   Use the shorter of e or f
+    \o 'G'   Use the shorter of E or f
+    \endlist
+
+    If precision is not specified, the precision will be 2.
+
+    If the format is not specified 'f' will be used.
+
+    If \a locale is not specified, the default locale will be used.
+
+    The following example shows a number formatted for the German locale:
+    \code
+    import QtQuick 2.0
+
+    Text {
+        text: "The value is: " +  Number(4742378.423).toLocaleString(Qt.locale("de_DE"))
+    }
+    \endcode
+
+    You can apply toLocaleString() directly to constants, provided the decimal
+    is included in the constant, e.g.
+    \code
+    123.0.toLocaleString(Qt.locale("de_DE")) // OK
+    123..toLocaleString(Qt.locale("de_DE"))  // OK
+    123.toLocaleString(Qt.locale("de_DE"))   // fails
+    \endcode
+*/
+
+/*!
+    \qmlmethod string Number::toLocaleCurrencyString(locale,symbol)
+
+    Converts the Number to a currency using the currency and conventions of the specified
+    \a locale.  If \a symbol is specified it will be used as the currency
+    symbol.
+
+    \sa Locale::currencySymbol()
+*/
+
+/*!
+    \qmlmethod string Number::fromLocaleString(locale,number)
+
+    Returns a Number by parsing \a number using the conventions of the supplied \a locale.
+
+    If \a locale is not supplied the default locale will be used.
+
+    For example, using the German locale:
+    \code
+    var german = Qt.locale("de_DE");
+    var d;
+    d = Number.fromLocaleString(german, "1234,56)   // d == 1234.56
+    d = Number.fromLocaleString(german, "1.234,56") // d == 1234.56
+    d = Number.fromLocaleString(german, "1234.56")  // throws exception
+    d = Number.fromLocaleString(german, "1.234")    // d == 1234.0
+    \endcode
+*/
+
index 41dedec..e1d5755 100644 (file)
@@ -77,7 +77,7 @@ Qt applications.
 \o \l{Integrating QML Code with Existing Qt UI Code}
 \o \l{Dynamic Object Management in QML}{Dynamic Object Management}
 \o \l{Network Transparency}{Loading Resources in QML}
-\o \l{QML Internationalization}{Internationalization}
+\o \l{QML Internationalization}{Qt Quick 1 Internationalization}
 \endlist
 
 \section1 QML Add-Ons
index 7689217..e985abe 100644 (file)
@@ -32,7 +32,7 @@
 \contentspage QML Features
 \previouspage {Network Transparency}{Loading Resources in QML}
 \nextpage {QML Features}
-\title QML Internationalization
+\title Qt Quick 1 Internationalization
 
 
 Strings in QML can be marked for translation using the qsTr(), qsTranslate(),
diff --git a/examples/declarative/locale/locale.qml b/examples/declarative/locale/locale.qml
new file mode 100644 (file)
index 0000000..4d56ecf
--- /dev/null
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+**     the names of its contributors may be used to endorse or promote
+**     products derived from this software without specific prior written
+**     permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+    id: root
+    width: 320
+    height: 480
+    color: "lightgray"
+
+    property string locale: view.currentItem.locale
+
+    Text {
+        id: title
+        text: "Select locale:"
+    }
+
+    Rectangle {
+        id: chooser
+        anchors.top: title.bottom
+        anchors.topMargin: 5
+        width: parent.width-10
+        x: 5
+        height: parent.height/2 - 10
+        color: "#40300030"
+        ListView {
+            id: view
+            clip: true
+            focus: true
+            anchors.fill: parent
+            model: [
+                "en_US",
+                "en_GB",
+                "fi_FI",
+                "de_DE",
+                "ar_SA",
+                "hi_IN",
+                "zh_CN",
+                "th_TH",
+                "fr_FR",
+                "nb_NO",
+                "sv_SE"
+            ]
+            delegate: Text {
+                property string locale: modelData
+                height: 30
+                width: view.width
+                text: Qt.locale(modelData).name + " ("+ Qt.locale(modelData).nativeCountryName + "/" + Qt.locale(modelData).nativeLanguageName + ")"
+                MouseArea {
+                    anchors.fill: parent
+                    onClicked: view.currentIndex = index
+                }
+            }
+            highlight: Rectangle {
+                height: 30
+                color: "#60300030"
+            }
+        }
+    }
+
+    Rectangle {
+        color: "white"
+        anchors.top: chooser.bottom
+        anchors.topMargin: 5
+        anchors.bottom: parent.bottom
+        anchors.bottomMargin: 5
+        x: 5; width: parent.width - 10
+
+        Column {
+            anchors.fill: parent
+            spacing: 5
+            Text {
+                property var date: new Date()
+                text: "Date: " + date.toLocaleDateString(Qt.locale(root.locale))
+            }
+            Text {
+                property var date: new Date()
+                text: "Time: " + date.toLocaleTimeString(Qt.locale(root.locale))
+            }
+            Text {
+                property var dow: Qt.locale(root.locale).firstDayOfWeek
+                text: "First day of week: " + Qt.locale(root.locale).standaloneDayName(dow)
+            }
+            Text {
+                property var num: 10023823
+                text: "Number: " + num.toLocaleString(Qt.locale(root.locale))
+            }
+            Text {
+                property var num: 10023823
+                text: "Currency: " + num.toLocaleCurrencyString(Qt.locale(root.locale))
+            }
+        }
+    }
+}
index 1323669..ef638b4 100644 (file)
@@ -85,6 +85,7 @@
 #include <private/qdeclarativeutilmodule_p.h>
 #include <private/qquickitemsmodule_p.h>
 #include <private/qquickparticlesmodule_p.h>
+#include <private/qdeclarativelocale_p.h>
 
 #ifdef Q_OS_WIN // for %APPDATA%
 #include <qt_windows.h>
@@ -174,6 +175,7 @@ void QDeclarativeEnginePrivate::defineModule()
 {
     registerBaseTypes("QtQuick", 2, 0);
     qmlRegisterType<QDeclarativeBinding>();
+    qmlRegisterUncreatableType<QDeclarativeLocale>("QtQuick",2,0,"Locale",QDeclarativeEngine::tr("Locale cannot be instantiated.  Use Qt.locale()"));
 }
 
 /*!
index a678a45..14ee628 100644 (file)
@@ -81,6 +81,7 @@
 #include <private/qobject_p.h>
 
 #include <private/qv8engine_p.h>
+#include <private/qjsengine_p.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -119,7 +120,7 @@ public:
     QDeclarativeJavaScriptExpressionGuard *next;
 };
 
-class Q_DECLARATIVE_EXPORT QDeclarativeEnginePrivate : public QObjectPrivate
+class Q_DECLARATIVE_EXPORT QDeclarativeEnginePrivate : public QJSEnginePrivate
 {
     Q_DECLARE_PUBLIC(QDeclarativeEngine)
 public:
diff --git a/src/declarative/qml/qdeclarativelocale.cpp b/src/declarative/qml/qdeclarativelocale.cpp
new file mode 100644 (file)
index 0000000..bbde2d8
--- /dev/null
@@ -0,0 +1,1095 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativelocale_p.h"
+#include "qdeclarativeengine_p.h"
+#include <private/qdeclarativecontext_p.h>
+#include <private/qjsconverter_impl_p.h>
+#include <QtCore/qnumeric.h>
+#include <QtCore/qdatetime.h>
+
+#include <private/qlocale_p.h>
+#include <private/qlocale_data_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV8LocaleDataResource : public QV8ObjectResource
+{
+    V8_RESOURCE_TYPE(LocaleDataType)
+public:
+    QV8LocaleDataResource(QV8Engine *e) : QV8ObjectResource(e) {}
+    QLocale locale;
+};
+
+#define GET_LOCALE_DATA_RESOURCE(OBJECT) \
+QV8LocaleDataResource *r = v8_resource_cast<QV8LocaleDataResource>(OBJECT); \
+if (!r) \
+    V8THROW_ERROR("Not a valid Locale object")
+
+static bool isLocaleObject(v8::Handle<v8::Value> val)
+{
+    if (!val->IsObject())
+        return false;
+
+    v8::Handle<v8::Object> localeObj = val->ToObject();
+    return localeObj->Has(v8::String::New("nativeLanguageName")); //XXX detect locale object properly
+}
+
+//--------------
+// Date extension
+
+static const char *dateToLocaleStringFunction =
+        "(function(toLocaleStringFunc) { "
+        "  var orig_toLocaleString;"
+        "  orig_toLocaleString = Date.prototype.toLocaleString;"
+        "  Date.prototype.toLocaleString = (function() {"
+        "    var val = toLocaleStringFunc.apply(this, arguments);"
+        "    if (val == undefined) val = orig_toLocaleString.call(this);"
+        "    return val;"
+        "  })"
+        "})";
+
+static const char *dateToLocaleTimeStringFunction =
+        "(function(toLocaleTimeStringFunc) { "
+        "  var orig_toLocaleTimeString;"
+        "  orig_toLocaleTimeString = Date.prototype.toLocaleTimeString;"
+        "  Date.prototype.toLocaleTimeString = (function() {"
+        "    var val = toLocaleTimeStringFunc.apply(this, arguments);"
+        "    if (val == undefined) val = orig_toLocaleTimeString.call(this);"
+        "    return val;"
+        "  })"
+        "})";
+
+static const char *dateToLocaleDateStringFunction =
+        "(function(toLocaleDateStringFunc) { "
+        "  var orig_toLocaleDateString;"
+        "  orig_toLocaleDateString = Date.prototype.toLocaleDateString;"
+        "  Date.prototype.toLocaleDateString = (function() {"
+        "    var val = toLocaleDateStringFunc.apply(this, arguments);"
+        "    if (val == undefined) val = orig_toLocaleDateString.call(this);"
+        "    return val;"
+        "  })"
+        "})";
+
+
+static const char *dateFromLocaleStringFunction =
+        "(function(fromLocaleStringFunc) { "
+        "  Date.fromLocaleString = (function() {"
+        "    return fromLocaleStringFunc.apply(null, arguments);"
+        "  })"
+        "})";
+
+static const char *dateFromLocaleTimeStringFunction =
+        "(function(fromLocaleTimeStringFunc) { "
+        "  Date.fromLocaleTimeString = (function() {"
+        "    return fromLocaleTimeStringFunc.apply(null, arguments);"
+        "  })"
+        "})";
+
+static const char *dateFromLocaleDateStringFunction =
+        "(function(fromLocaleDateStringFunc) { "
+        "  Date.fromLocaleDateString = (function() {"
+        "    return fromLocaleDateStringFunc.apply(null, arguments);"
+        "  })"
+        "})";
+
+
+static void registerFunction(QV8Engine *engine, const char *script, v8::InvocationCallback func)
+{
+    v8::Local<v8::Script> registerScript = v8::Script::New(v8::String::New(script), 0, 0, v8::Handle<v8::String>(), v8::Script::NativeMode);
+    v8::Local<v8::Value> result = registerScript->Run();
+    Q_ASSERT(result->IsFunction());
+    v8::Local<v8::Function> registerFunc = v8::Local<v8::Function>::Cast(result);
+    v8::Handle<v8::Value> args = V8FUNCTION(func, engine);
+    registerFunc->Call(v8::Local<v8::Object>::Cast(registerFunc), 1, &args);
+}
+
+void QDeclarativeDateExtension::registerExtension(QV8Engine *engine)
+{
+    registerFunction(engine, dateToLocaleStringFunction, toLocaleString);
+    registerFunction(engine, dateToLocaleTimeStringFunction, toLocaleTimeString);
+    registerFunction(engine, dateToLocaleDateStringFunction, toLocaleDateString);
+    registerFunction(engine, dateFromLocaleStringFunction, fromLocaleString);
+    registerFunction(engine, dateFromLocaleTimeStringFunction, fromLocaleTimeString);
+    registerFunction(engine, dateFromLocaleDateStringFunction, fromLocaleDateString);
+}
+
+v8::Handle<v8::Value> QDeclarativeDateExtension::toLocaleString(const v8::Arguments& args)
+{
+    if (args.Length() > 2)
+        return v8::Undefined();
+
+    if (!args.This()->IsDate())
+        return v8::Undefined();
+
+    QDateTime dt = QV8Engine::qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(args.This())->NumberValue());
+
+    if (args.Length() == 0) {
+        // Use QLocale for standard toLocaleString() function
+        QLocale locale;
+        return QJSConverter::toString(locale.toString(dt));
+    }
+
+    if (!isLocaleObject(args[0]))
+        return v8::Undefined(); // Use the default Date toLocaleString()
+
+    GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
+
+    QLocale::FormatType enumFormat = QLocale::LongFormat;
+    QString formattedDt;
+    if (args.Length() == 2) {
+        if (args[1]->IsString()) {
+            QString format = r->engine->toVariant(args[1], -1).toString();
+            formattedDt = r->locale.toString(dt, format);
+        } else if (args[1]->IsNumber()) {
+            quint32 intFormat = args[1]->ToNumber()->Value();
+            QLocale::FormatType format = QLocale::FormatType(intFormat);
+            formattedDt = r->locale.toString(dt, format);
+        } else {
+            V8THROW_ERROR("Locale: Date.toLocaleString(): Invalid datetime format");
+        }
+    } else {
+         formattedDt = r->locale.toString(dt, enumFormat);
+    }
+
+    return r->engine->toString(formattedDt);
+}
+
+v8::Handle<v8::Value> QDeclarativeDateExtension::toLocaleTimeString(const v8::Arguments& args)
+{
+    if (args.Length() > 2)
+        return v8::Undefined();
+
+    if (!args.This()->IsDate())
+        return v8::Undefined();
+
+    QDateTime dt = QV8Engine::qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(args.This())->NumberValue());
+    QTime time = dt.time();
+
+    if (args.Length() == 0) {
+        // Use QLocale for standard toLocaleString() function
+        QLocale locale;
+        return QJSConverter::toString(locale.toString(time));
+    }
+
+    if (!isLocaleObject(args[0]))
+        return v8::Undefined(); // Use the default Date toLocaleTimeString()
+
+    GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
+
+    QLocale::FormatType enumFormat = QLocale::LongFormat;
+    QString formattedTime;
+    if (args.Length() == 2) {
+        if (args[1]->IsString()) {
+            QString format = r->engine->toVariant(args[1], -1).toString();
+            formattedTime = r->locale.toString(time, format);
+        } else if (args[1]->IsNumber()) {
+            quint32 intFormat = args[1]->ToNumber()->Value();
+            QLocale::FormatType format = QLocale::FormatType(intFormat);
+            formattedTime = r->locale.toString(time, format);
+        } else {
+            V8THROW_ERROR("Locale: Date.toLocaleTimeString(): Invalid time format");
+        }
+    } else {
+         formattedTime = r->locale.toString(time, enumFormat);
+    }
+
+    return r->engine->toString(formattedTime);
+}
+
+v8::Handle<v8::Value> QDeclarativeDateExtension::toLocaleDateString(const v8::Arguments& args)
+{
+    if (args.Length() > 2)
+        return v8::Undefined();
+
+    if (!args.This()->IsDate())
+        return v8::Undefined();
+
+    QDateTime dt = QV8Engine::qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(args.This())->NumberValue());
+    QDate date = dt.date();
+
+    if (args.Length() == 0) {
+        // Use QLocale for standard toLocaleString() function
+        QLocale locale;
+        return QJSConverter::toString(locale.toString(date));
+    }
+
+    if (!isLocaleObject(args[0]))
+        return v8::Undefined(); // Use the default Date toLocaleDateString()
+
+    GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
+
+    QLocale::FormatType enumFormat = QLocale::LongFormat;
+    QString formattedDate;
+    if (args.Length() == 2) {
+        if (args[1]->IsString()) {
+            QString format = r->engine->toVariant(args[1], -1).toString();
+            formattedDate = r->locale.toString(date, format);
+        } else if (args[1]->IsNumber()) {
+            quint32 intFormat = args[1]->ToNumber()->Value();
+            QLocale::FormatType format = QLocale::FormatType(intFormat);
+            formattedDate = r->locale.toString(date, format);
+        } else {
+            V8THROW_ERROR("Locale: Date.loLocaleDateString(): Invalid date format");
+        }
+    } else {
+         formattedDate = r->locale.toString(date, enumFormat);
+    }
+
+    return r->engine->toString(formattedDate);
+}
+
+v8::Handle<v8::Value> QDeclarativeDateExtension::fromLocaleString(const v8::Arguments& args)
+{
+    if (args.Length() == 1 && args[0]->IsString()) {
+        QLocale locale;
+        QString dateString = QJSConverter::toString(args[0]->ToString());
+        QDateTime dt = locale.toDateTime(dateString);
+        return QJSConverter::toDateTime(dt);
+    }
+
+    if (args.Length() < 1 || args.Length() > 3 || !isLocaleObject(args[0]))
+        V8THROW_ERROR("Locale: Date.fromLocaleString(): Invalid arguments");
+
+    GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
+
+    QLocale::FormatType enumFormat = QLocale::LongFormat;
+    QDateTime dt;
+    QString dateString = r->engine->toString(args[1]->ToString());
+    if (args.Length() == 3) {
+        if (args[2]->IsString()) {
+            QString format = r->engine->toString(args[2]->ToString());
+            dt = r->locale.toDateTime(dateString, format);
+        } else if (args[2]->IsNumber()) {
+            quint32 intFormat = args[2]->ToNumber()->Value();
+            QLocale::FormatType format = QLocale::FormatType(intFormat);
+            dt = r->locale.toDateTime(dateString, format);
+        } else {
+            V8THROW_ERROR("Locale: Date.fromLocaleString(): Invalid datetime format");
+        }
+    } else {
+        dt = r->locale.toDateTime(dateString, enumFormat);
+    }
+
+    return QJSConverter::toDateTime(dt);
+}
+
+v8::Handle<v8::Value> QDeclarativeDateExtension::fromLocaleTimeString(const v8::Arguments& args)
+{
+    if (args.Length() == 1 && args[0]->IsString()) {
+        QLocale locale;
+        QString timeString = QJSConverter::toString(args[0]->ToString());
+        QTime time = locale.toTime(timeString);
+        QDateTime dt = QDateTime::currentDateTime();
+        dt.setTime(time);
+        return QJSConverter::toDateTime(dt);
+    }
+
+    if (args.Length() < 1 || args.Length() > 3 || !isLocaleObject(args[0]))
+        V8THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid arguments");
+
+    GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
+
+    QLocale::FormatType enumFormat = QLocale::LongFormat;
+    QTime tm;
+    QString dateString = r->engine->toString(args[1]->ToString());
+    if (args.Length() == 3) {
+        if (args[2]->IsString()) {
+            QString format = r->engine->toString(args[2]->ToString());
+            tm = r->locale.toTime(dateString, format);
+        } else if (args[2]->IsNumber()) {
+            quint32 intFormat = args[2]->ToNumber()->Value();
+            QLocale::FormatType format = QLocale::FormatType(intFormat);
+            tm = r->locale.toTime(dateString, format);
+        } else {
+            V8THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid datetime format");
+        }
+    } else {
+        tm = r->locale.toTime(dateString, enumFormat);
+    }
+
+    QDateTime dt = QDateTime::currentDateTime();
+    dt.setTime(tm);
+
+    return QJSConverter::toDateTime(dt);
+}
+
+v8::Handle<v8::Value> QDeclarativeDateExtension::fromLocaleDateString(const v8::Arguments& args)
+{
+    if (args.Length() == 1 && args[0]->IsString()) {
+        QLocale locale;
+        QString dateString = QJSConverter::toString(args[0]->ToString());
+        QDate date = locale.toDate(dateString);
+        return QJSConverter::toDateTime(QDateTime(date));
+    }
+
+    if (args.Length() < 1 || args.Length() > 3 || !isLocaleObject(args[0]))
+        V8THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid arguments");
+
+    GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
+
+    QLocale::FormatType enumFormat = QLocale::LongFormat;
+    QDate dt;
+    QString dateString = r->engine->toString(args[1]->ToString());
+    if (args.Length() == 3) {
+        if (args[2]->IsString()) {
+            QString format = r->engine->toString(args[2]->ToString());
+            dt = r->locale.toDate(dateString, format);
+        } else if (args[2]->IsNumber()) {
+            quint32 intFormat = args[2]->ToNumber()->Value();
+            QLocale::FormatType format = QLocale::FormatType(intFormat);
+            dt = r->locale.toDate(dateString, format);
+        } else {
+            V8THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid datetime format");
+        }
+    } else {
+        dt = r->locale.toDate(dateString, enumFormat);
+    }
+
+    return QJSConverter::toDateTime(QDateTime(dt));
+}
+
+//-----------------
+// Number extension
+
+static const char *numberToLocaleStringFunction =
+        "(function(toLocaleStringFunc) { "
+        "  var orig_toLocaleString;"
+        "  orig_toLocaleString = Number.prototype.toLocaleString;"
+        "  Number.prototype.toLocaleString = (function() {"
+        "    var val = toLocaleStringFunc.apply(this, arguments);"
+        "    if (val == undefined) val = orig_toLocaleString.call(this);"
+        "    return val;"
+        "  })"
+        "})";
+
+static const char *numberToLocaleCurrencyStringFunction =
+        "(function(toLocaleCurrencyStringFunc) { "
+        "  Number.prototype.toLocaleCurrencyString = (function() {"
+        "    return toLocaleCurrencyStringFunc.apply(this, arguments);"
+        "  })"
+        "})";
+
+static const char *numberFromLocaleStringFunction =
+        "(function(fromLocaleStringFunc) { "
+        "  Number.fromLocaleString = (function() {"
+        "    return fromLocaleStringFunc.apply(null, arguments);"
+        "  })"
+        "})";
+
+
+void QDeclarativeNumberExtension::registerExtension(QV8Engine *engine)
+{
+    registerFunction(engine, numberToLocaleStringFunction, toLocaleString);
+    registerFunction(engine, numberToLocaleCurrencyStringFunction, toLocaleCurrencyString);
+    registerFunction(engine, numberFromLocaleStringFunction, fromLocaleString);
+}
+
+v8::Handle<v8::Value> QDeclarativeNumberExtension::toLocaleString(const v8::Arguments& args)
+{
+    if (args.Length() > 3)
+        V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
+
+    double number = args.This()->ToNumber()->Value();
+
+    if (args.Length() == 0) {
+        // Use QLocale for standard toLocaleString() function
+        QLocale locale;
+        return QJSConverter::toString(locale.toString(number));
+    }
+
+    if (!isLocaleObject(args[0]))
+        return v8::Undefined(); // Use the default Number toLocaleString()
+
+    GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
+
+    uint16_t format = 'f';
+    if (args.Length() > 1) {
+        if (!args[1]->IsString())
+            V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
+        v8::Local<v8::String> fs = args[1]->ToString();
+        if (!fs.IsEmpty() && fs->Length())
+            format = fs->GetCharacter(0);
+    }
+    int prec = 2;
+    if (args.Length() > 2) {
+        if (!args[2]->IsNumber())
+            V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
+         prec = args[2]->IntegerValue();
+    }
+
+    return r->engine->toString(r->locale.toString(number, (char)format, prec));
+}
+
+v8::Handle<v8::Value> QDeclarativeNumberExtension::toLocaleCurrencyString(const v8::Arguments& args)
+{
+    if (args.Length() > 2)
+        V8THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments");
+
+    double number = args.This()->ToNumber()->Value();
+
+    if (args.Length() == 0) {
+        // Use QLocale for standard toLocaleString() function
+        QLocale locale;
+        return QJSConverter::toString(locale.toString(number));
+    }
+
+    if (!isLocaleObject(args[0]))
+        V8THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments");
+
+    GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
+
+    QString symbol;
+    if (args.Length() > 1) {
+        if (!args[1]->IsString())
+            V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
+        symbol = r->engine->toString(args[1]->ToString());
+    }
+
+    return r->engine->toString(r->locale.toCurrencyString(number, symbol));
+}
+
+v8::Handle<v8::Value> QDeclarativeNumberExtension::fromLocaleString(const v8::Arguments& args)
+{
+    if (args.Length() < 1 || args.Length() > 2)
+        V8THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments");
+
+    int numberIdx = 0;
+    QLocale locale;
+
+    if (args.Length() == 2) {
+        if (!isLocaleObject(args[0]))
+            V8THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments");
+
+        GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
+        locale = r->locale;
+
+        numberIdx = 1;
+    }
+
+    v8::Local<v8::String> ns = args[numberIdx]->ToString();
+    if (ns.IsEmpty() || ns->Length() == 0)
+        return v8::Number::New(Q_QNAN);
+
+    bool ok = false;
+    double val = locale.toDouble(QJSConverter::toString(ns), &ok);
+
+    if (!ok)
+        V8THROW_ERROR("Locale: Number.fromLocaleString(): Invalid format")
+
+    return v8::Number::New(val);
+}
+
+//--------------
+// Locale object
+
+static v8::Handle<v8::Value> locale_get_firstDayOfWeek(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+    GET_LOCALE_DATA_RESOURCE(info.This());
+    return v8::Integer::New(r->locale.firstDayOfWeek());
+}
+
+static v8::Handle<v8::Value> locale_get_measurementSystem(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+    GET_LOCALE_DATA_RESOURCE(info.This());
+    return v8::Integer::New(r->locale.measurementSystem());
+}
+
+static v8::Handle<v8::Value> locale_get_textDirection(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+    GET_LOCALE_DATA_RESOURCE(info.This());
+    return v8::Integer::New(r->locale.textDirection());
+}
+
+static v8::Handle<v8::Value> locale_get_weekDays(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+    GET_LOCALE_DATA_RESOURCE(info.This());
+
+    QList<Qt::DayOfWeek> days = r->locale.weekdays();
+
+    v8::Handle<v8::Array> result = v8::Array::New(days.size());
+    for (int i = 0; i < days.size(); ++i) {
+        int day = days.at(i);
+        if (day == 7) // JS Date days in range 0(Sunday) to 6(Saturday)
+            day = 0;
+        result->Set(i, v8::Integer::New(day));
+    }
+
+    return result;
+}
+
+static v8::Handle<v8::Value> locale_currencySymbol(const v8::Arguments &args)
+{
+    GET_LOCALE_DATA_RESOURCE(args.This());
+
+    if (args.Length() > 1)
+        V8THROW_ERROR("Locale: currencySymbol(): Invalid arguments");
+
+    QLocale::CurrencySymbolFormat format = QLocale::CurrencySymbol;
+    if (args.Length() == 1) {
+        quint32 intFormat = args[0]->ToNumber()->Value();
+        format = QLocale::CurrencySymbolFormat(intFormat);
+    }
+
+    return r->engine->toString(r->locale.currencySymbol(format));
+}
+
+#define LOCALE_FORMAT(FUNC) \
+static v8::Handle<v8::Value> locale_ ##FUNC (const v8::Arguments &args) { \
+    GET_LOCALE_DATA_RESOURCE(args.This());\
+    if (args.Length() > 1) \
+        V8THROW_ERROR("Locale: " #FUNC "(): Invalid arguments"); \
+    QLocale::FormatType format = QLocale::LongFormat;\
+    if (args.Length() == 1) { \
+        quint32 intFormat = args[0]->Uint32Value(); \
+        format = QLocale::FormatType(intFormat); \
+    } \
+    return r->engine->toString(r->locale. FUNC (format)); \
+}
+
+LOCALE_FORMAT(dateTimeFormat)
+LOCALE_FORMAT(timeFormat)
+LOCALE_FORMAT(dateFormat)
+
+// +1 added to idx because JS is 0-based, whereas QLocale months begin at 1.
+#define LOCALE_FORMATTED_MONTHNAME(VARIABLE) \
+static v8::Handle<v8::Value> locale_ ## VARIABLE (const v8::Arguments &args) {\
+    GET_LOCALE_DATA_RESOURCE(args.This()); \
+    if (args.Length() < 1 || args.Length() > 2) \
+        V8THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \
+    QLocale::FormatType enumFormat = QLocale::LongFormat; \
+    int idx = args[0]->IntegerValue() + 1; \
+    if (idx < 1 || idx > 12) \
+        V8THROW_ERROR("Locale: Invalid month"); \
+    QString name; \
+    if (args.Length() == 2) { \
+        if (args[1]->IsNumber()) { \
+            quint32 intFormat = args[1]->IntegerValue(); \
+            QLocale::FormatType format = QLocale::FormatType(intFormat); \
+            name = r->locale. VARIABLE(idx, format); \
+        } else { \
+            V8THROW_ERROR("Locale: Invalid datetime format"); \
+        } \
+    } else { \
+        name = r->locale. VARIABLE(idx, enumFormat); \
+    } \
+    return r->engine->toString(name); \
+}
+
+// 0 -> 7 as Qt::Sunday is 7, but Sunday is 0 in JS Date
+#define LOCALE_FORMATTED_DAYNAME(VARIABLE) \
+static v8::Handle<v8::Value> locale_ ## VARIABLE (const v8::Arguments &args) {\
+    GET_LOCALE_DATA_RESOURCE(args.This()); \
+    if (args.Length() < 1 || args.Length() > 2) \
+        V8THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \
+    QLocale::FormatType enumFormat = QLocale::LongFormat; \
+    int idx = args[0]->IntegerValue(); \
+    if (idx < 0 || idx > 7) \
+        V8THROW_ERROR("Locale: Invalid day"); \
+    if (idx == 0) idx = 7; \
+    QString name; \
+    if (args.Length() == 2) { \
+        if (args[1]->IsNumber()) { \
+            quint32 intFormat = args[1]->ToNumber()->Value(); \
+            QLocale::FormatType format = QLocale::FormatType(intFormat); \
+            name = r->locale. VARIABLE(idx, format); \
+        } else { \
+            V8THROW_ERROR("Locale: Invalid datetime format"); \
+        } \
+    } else { \
+        name = r->locale. VARIABLE(idx, enumFormat); \
+    } \
+    return r->engine->toString(name); \
+}
+
+
+#define LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(FT, VARIABLE, ENGINE) \
+    FT->PrototypeTemplate()->Set(v8::String::New( #VARIABLE ), V8FUNCTION(locale_ ## VARIABLE, ENGINE));
+
+LOCALE_FORMATTED_MONTHNAME(monthName)
+LOCALE_FORMATTED_MONTHNAME(standaloneMonthName)
+LOCALE_FORMATTED_DAYNAME(dayName)
+LOCALE_FORMATTED_DAYNAME(standaloneDayName)
+
+#define LOCALE_STRING_PROPERTY(VARIABLE) static v8::Handle<v8::Value> locale_get_ ## VARIABLE (v8::Local<v8::String>, const v8::AccessorInfo &info) \
+{ \
+    GET_LOCALE_DATA_RESOURCE(info.This()); \
+    return r->engine->toString(r->locale. VARIABLE());\
+}
+
+#define LOCALE_REGISTER_STRING_ACCESSOR(FT, VARIABLE) \
+    FT ->PrototypeTemplate()->SetAccessor( v8::String::New( #VARIABLE ), locale_get_ ## VARIABLE )
+
+
+LOCALE_STRING_PROPERTY(name)
+LOCALE_STRING_PROPERTY(nativeLanguageName)
+LOCALE_STRING_PROPERTY(nativeCountryName)
+LOCALE_STRING_PROPERTY(decimalPoint)
+LOCALE_STRING_PROPERTY(groupSeparator)
+LOCALE_STRING_PROPERTY(percent)
+LOCALE_STRING_PROPERTY(zeroDigit)
+LOCALE_STRING_PROPERTY(negativeSign)
+LOCALE_STRING_PROPERTY(positiveSign)
+LOCALE_STRING_PROPERTY(exponential)
+LOCALE_STRING_PROPERTY(amText)
+LOCALE_STRING_PROPERTY(pmText)
+
+class QV8LocaleDataDeletable : public QV8Engine::Deletable
+{
+public:
+    QV8LocaleDataDeletable(QV8Engine *engine);
+    ~QV8LocaleDataDeletable();
+
+    v8::Persistent<v8::Function> constructor;
+};
+
+QV8LocaleDataDeletable::QV8LocaleDataDeletable(QV8Engine *engine)
+{
+    v8::HandleScope handle_scope;
+    v8::Context::Scope scope(engine->context());
+
+    v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+    ft->InstanceTemplate()->SetHasExternalResource(true);
+
+    LOCALE_REGISTER_STRING_ACCESSOR(ft, name);
+    LOCALE_REGISTER_STRING_ACCESSOR(ft, nativeLanguageName);
+    LOCALE_REGISTER_STRING_ACCESSOR(ft, nativeCountryName);
+    LOCALE_REGISTER_STRING_ACCESSOR(ft, decimalPoint);
+    LOCALE_REGISTER_STRING_ACCESSOR(ft, groupSeparator);
+    LOCALE_REGISTER_STRING_ACCESSOR(ft, percent);
+    LOCALE_REGISTER_STRING_ACCESSOR(ft, zeroDigit);
+    LOCALE_REGISTER_STRING_ACCESSOR(ft, negativeSign);
+    LOCALE_REGISTER_STRING_ACCESSOR(ft, positiveSign);
+    LOCALE_REGISTER_STRING_ACCESSOR(ft, exponential);
+    LOCALE_REGISTER_STRING_ACCESSOR(ft, amText);
+    LOCALE_REGISTER_STRING_ACCESSOR(ft, pmText);
+
+    ft->PrototypeTemplate()->Set(v8::String::New("currencySymbol"), V8FUNCTION(locale_currencySymbol, engine));
+
+    ft->PrototypeTemplate()->Set(v8::String::New("dateTimeFormat"), V8FUNCTION(locale_dateTimeFormat, engine));
+    ft->PrototypeTemplate()->Set(v8::String::New("dateFormat"), V8FUNCTION(locale_dateFormat, engine));
+    ft->PrototypeTemplate()->Set(v8::String::New("timeFormat"), V8FUNCTION(locale_timeFormat, engine));
+
+    LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, monthName, engine);
+    LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, standaloneMonthName, engine);
+    LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, dayName, engine);
+    LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, standaloneDayName, engine);
+
+    ft->PrototypeTemplate()->SetAccessor(v8::String::New("firstDayOfWeek"), locale_get_firstDayOfWeek);
+    ft->PrototypeTemplate()->SetAccessor(v8::String::New("weekDays"), locale_get_weekDays);
+    ft->PrototypeTemplate()->SetAccessor(v8::String::New("measurementSystem"), locale_get_measurementSystem);
+    ft->PrototypeTemplate()->SetAccessor(v8::String::New("textDirection"), locale_get_textDirection);
+
+    constructor = qPersistentNew(ft->GetFunction());
+}
+
+QV8LocaleDataDeletable::~QV8LocaleDataDeletable()
+{
+    qPersistentDispose(constructor);
+}
+
+V8_DEFINE_EXTENSION(QV8LocaleDataDeletable, localeV8Data);
+
+class QV8LocaleData {
+public:
+    QV8LocaleData(QV8Engine*,const QLocale &);
+    ~QV8LocaleData();
+    QDeclarativeV8Handle v8Value();
+private:
+    v8::Persistent<v8::Object> m_v8Value;
+};
+
+QV8LocaleData::QV8LocaleData(QV8Engine *engine, const QLocale &locale)
+{
+    if (!engine)
+        return;
+
+    QV8LocaleDataDeletable *d = localeV8Data(engine);
+    m_v8Value = qPersistentNew(d->constructor->NewInstance());
+    QV8LocaleDataResource *r = new QV8LocaleDataResource(engine);
+    r->locale = locale;
+    m_v8Value->SetExternalResource(r);
+}
+
+QV8LocaleData::~QV8LocaleData()
+{
+    qPersistentDispose(m_v8Value);
+}
+
+QDeclarativeV8Handle QV8LocaleData::v8Value()
+{
+    return QDeclarativeV8Handle::fromHandle(m_v8Value);
+}
+
+/*!
+    \qmlclass Locale QDeclarativeLocale
+    \inqmlmodule QtQuick 2
+    \brief The Locale object provides locale specific properties and formatted data.
+
+    The Locale object is created via the \l{QML:Qt::locale()}{Qt.locale()} function.  It cannot be created
+    directly.
+
+    The \l{QML:Qt::locale()}{Qt.locale()} function returns a JS Locale object representing the
+    locale with the specified name, which has the format
+    "language[_territory][.codeset][@modifier]" or "C".
+
+    Locale supports the concept of a default locale, which is
+    determined from the system's locale settings at application
+    startup.  If no parameter is passed to Qt.locale() the default
+    locale object is returned.
+
+    The Locale object provides a number of functions and properties
+    providing data for the specified locale.
+
+    The Locale object may also be passed to the \l Date and \l Number toLocaleString()
+    and fromLocaleString() methods in order to convert to/from strings using
+    the specified locale.
+
+    This example shows the current date formatted for the German locale:
+
+    \code
+    import QtQuick 2.0
+
+    Text {
+        text: "The date is: " + Date().toLocaleString(Qt.locale("de_DE"))
+    }
+    \endcode
+
+    The following example displays the specified number
+    in the correct format for the default locale:
+
+    \code
+    import QtQuick 2.0
+
+    Text {
+        text: "The value is: " + Number(23443.34).toLocaleString(Qt.locale())
+    }
+    \endcode
+
+    QtQuick Locale's data is based on Common Locale Data Repository v1.8.1.
+
+    The double-to-string and string-to-double conversion functions are
+    covered by the following licenses:
+
+    \legalese
+    Copyright (c) 1991 by AT&T.
+
+    Permission to use, copy, modify, and distribute this software for any
+    purpose without fee is hereby granted, provided that this entire notice
+    is included in all copies of any software which is or includes a copy
+    or modification of this software and in all copies of the supporting
+    documentation for such software.
+
+    THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+    WARRANTY.  IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
+    REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+    OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+
+    This product includes software developed by the University of
+    California, Berkeley and its contributors.
+
+    \sa {QtQuick2::Date}{Date} {QtQuick2::Number}{Number}
+*/
+
+QDeclarativeLocale::QDeclarativeLocale()
+{
+}
+
+QDeclarativeLocale::~QDeclarativeLocale()
+{
+}
+
+v8::Handle<v8::Value> QDeclarativeLocale::locale(QV8Engine *v8engine, const QString &locale)
+{
+    QV8LocaleDataDeletable *d = localeV8Data(v8engine);
+    v8::Local<v8::Object> v8Value = d->constructor->NewInstance();
+    QV8LocaleDataResource *r = new QV8LocaleDataResource(v8engine);
+    r->locale = QLocale(locale);
+    v8Value->SetExternalResource(r);
+
+    return v8Value;
+}
+
+/*!
+    \enum QtQuick2::Locale::FormatType
+
+    This enumeration describes the types of format that can be used when
+    converting Date objects to strings.
+
+    \value LongFormat The long version of day and month names; for
+    example, returning "January" as a month name.
+
+    \value ShortFormat The short version of day and month names; for
+    example, returning "Jan" as a month name.
+
+    \value NarrowFormat A special version of day and month names for
+    use when space is limited; for example, returning "J" as a month
+    name. Note that the narrow format might contain the same text for
+    different months and days or it can even be an empty string if the
+    locale doesn't support narrow names, so you should avoid using it
+    for date formatting. Also, for the system locale this format is
+    the same as ShortFormat.
+*/
+
+/*!
+    \qmlproperty string QtQuick2::Locale::name
+
+    Holds the language and country of this locale as a
+    string of the form "language_country", where
+    language is a lowercase, two-letter ISO 639 language code,
+    and country is an uppercase, two- or three-letter ISO 3166 country code.
+*/
+
+/*!
+    \qmlproperty string QtQuick2::Locale::decimalPoint
+
+    Holds the decimal point character of this locale.
+*/
+
+/*!
+    \qmlproperty string QtQuick2::Locale::groupSeparator
+
+    Holds the group separator character of this locale.
+*/
+
+/*!
+    \qmlproperty string QtQuick2::Locale::percent
+
+    Holds the percent character of this locale.
+*/
+
+
+/*!
+    \qmlproperty string QtQuick2::Locale::zeroDigit
+
+    Holds Returns the zero digit character of this locale.
+*/
+
+/*!
+    \qmlproperty string QtQuick2::Locale::negativeSign
+
+    Holds the negative sign character of this locale.
+*/
+
+/*!
+    \qmlproperty string QtQuick2::Locale::positiveSign
+
+    Holds the positive sign character of this locale.
+*/
+
+/*!
+    \qmlproperty string QtQuick2::Locale::exponential
+
+    Holds the exponential character of this locale.
+*/
+
+/*!
+    \qmlmethod string QtQuick2::Locale::dateTimeFormat(type)
+
+    Returns the date time format used for the current locale.
+    \a type specifies the FormatType to return.
+
+    \sa {QtQuick2::Date}{Date}
+*/
+
+/*!
+    \qmlmethod string QtQuick2::Locale::dateFormat(type)
+
+    Returns the date format used for the current locale.
+    \a type specifies the FormatType to return.
+
+    \sa {QtQuick2::Date}{Date}
+*/
+
+/*!
+    \qmlmethod string QtQuick2::Locale::timeFormat(type)
+
+    Returns the time format used for the current locale.
+    \a type specifies the FormatType to return.
+
+    \sa {QtQuick2::Date}{Date}
+*/
+
+/*!
+    \qmlmethod string QtQuick2::Locale::monthName(month, type)
+
+    Returns the localized name of \a month (0-11), in the optional
+    \l FortmatType specified by \a type.
+
+    \note the QLocale C++ API expects a range of (1-12), however Locale.monthName()
+    expects 0-11 as per the JS Date object.
+
+    \sa dayName(), standaloneMonthName()
+*/
+
+/*!
+    \qmlmethod string QtQuick2::Locale::standaloneMonthName(month, type)
+
+    Returns the localized name of \a month (0-11) that is used as a
+    standalone text, in the optional \l FormatType specified by \a type.
+
+    If the locale information doesn't specify the standalone month
+    name then return value is the same as in monthName().
+
+    \note the QLocale C++ API expects a range of (1-12), however Locale.standaloneMonthName()
+    expects 0-11 as per the JS Date object.
+
+    \sa monthName(), standaloneDayName()
+*/
+
+/*!
+    \qmlmethod string QtQuick2::Locale::dayName(day, type)
+
+    Returns the localized name of the \a day (where 0 represents
+    Sunday, 1 represents Monday and so on), in the optional
+    \l FormatType specified by \a type.
+
+    \sa monthName(), standaloneDayName()
+*/
+
+/*!
+    \qmlmethod string QtQuick2::Locale::standaloneDayName(day, type)
+
+    Returns the localized name of the \a day (where 0 represents
+    Sunday, 1 represents Monday and so on) that is used as a
+    standalone text, in the \l FormatType specified by \a type.
+
+    If the locale information does not specify the standalone day
+    name then return value is the same as in dayName().
+
+    \sa dayName(), standaloneMonthName()
+*/
+
+/*!
+    \qmlproperty enumeration QtQuick2::Locale::firstDayOfWeek
+
+    Holds the first day of the week according to the current locale.
+
+    \list
+    \o Locale.Sunday = 0
+    \o Locale.Monday = 1
+    \o Locale.Tuesday = 2
+    \o Locale.Wednesday = 3
+    \o Locale.Thursday = 4
+    \o Locale.Friday = 5
+    \o Locale.Saturday = 6
+    \endlist
+
+    \note that these values match the JS Date API which is different
+    from the Qt C++ API where Qt::Sunday = 7.
+*/
+
+/*!
+    \qmlproperty Array<int> QtQuick2::Locale::weekdays
+
+    Holds an array of days that are considered weekdays according to the current locale,
+    where Sunday is 0 and Saturday is 6.
+
+    \sa firstDayOfWeek
+*/
+
+
+/*!
+    \qmlproperty enumeration QtQuick2::Locale::textDirection
+
+    Holds the text direction of the language:
+    \list
+    \o Qt.LeftToRight
+    \o Qt.RightToLeft
+    \endlist
+*/
+
+/*!
+    \qmlproperty string QtQuick2::Locale::amText
+
+    The localized name of the "AM" suffix for times specified using the conventions of the 12-hour clock.
+*/
+
+/*!
+    \qmlproperty string QtQuick2::Locale::pmText
+
+    The localized name of the "PM" suffix for times specified using the conventions of the 12-hour clock.
+*/
+
+/*!
+    \qmlmethod string QtQuick2::Locale::currencySymbol(format)
+
+    Returns the currency symbol for the specified \a format:
+    \list
+    \o Locale.CurrencyIsoCode a ISO-4217 code of the currency.
+    \o Locale.CurrencySymbol a currency symbol.
+    \o Locale.CurrencyDisplayName a user readable name of the currency.
+    \endlist
+*/
+
+/*!
+    \qmlproperty string QtQuick2::Locale::nativeLanguageName
+
+    Holds a native name of the language for the locale. For example
+    "Schwiizertüütsch" for Swiss-German locale.
+
+    \sa nativeCountryName
+*/
+
+/*!
+    \qmlproperty string QtQuick2::Locale::nativeCountryName
+
+    Holds a native name of the country for the locale. For example
+    "España" for Spanish/Spain locale.
+
+    \sa nativeLanguageName
+*/
+
+/*!
+    \qmlproperty enumeration QtQuick2::Locale::measurementSystem
+
+    This property defines which units are used for measurement.
+
+    \list
+    \o Locale.MetricSystem This value indicates metric units, such as meters,
+        centimeters and millimeters.
+    \o Locale.ImperialSystem This value indicates imperial units, such as inches and
+        miles. There are several distinct imperial systems in the world; this
+        value stands for the official United States imperial units.
+    \endlist
+*/
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativelocale_p.h b/src/declarative/qml/qdeclarativelocale_p.h
new file mode 100644 (file)
index 0000000..948729d
--- /dev/null
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVELOCALE_H
+#define QDECLARATIVELOCALE_H
+
+#include <qdeclarative.h>
+
+#include <QtCore/qlocale.h>
+#include <QtCore/qobject.h>
+#include <private/qv8engine_p.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeDateExtension
+{
+public:
+    static void registerExtension(QV8Engine *engine);
+
+private:
+    static v8::Handle<v8::Value> toLocaleString(const v8::Arguments& args);
+    static v8::Handle<v8::Value> toLocaleTimeString(const v8::Arguments& args);
+    static v8::Handle<v8::Value> toLocaleDateString(const v8::Arguments& args);
+    static v8::Handle<v8::Value> fromLocaleString(const v8::Arguments& args);
+    static v8::Handle<v8::Value> fromLocaleTimeString(const v8::Arguments& args);
+    static v8::Handle<v8::Value> fromLocaleDateString(const v8::Arguments& args);
+};
+
+
+class QDeclarativeNumberExtension
+{
+public:
+    static void registerExtension(QV8Engine *engine);
+
+private:
+    static v8::Handle<v8::Value> toLocaleString(const v8::Arguments& args);
+    static v8::Handle<v8::Value> fromLocaleString(const v8::Arguments& args);
+    static v8::Handle<v8::Value> toLocaleCurrencyString(const v8::Arguments&  args);
+};
+
+
+class Q_AUTOTEST_EXPORT QDeclarativeLocale
+{
+    Q_GADGET
+    Q_ENUMS(MeasurementSystem)
+    Q_ENUMS(FormatType)
+    Q_ENUMS(CurrencySymbolFormat)
+    Q_ENUMS(DayOfWeek)
+
+public:
+    ~QDeclarativeLocale();
+
+    enum MeasurementSystem {
+        MetricSystem = QLocale::MetricSystem,
+        ImperialSystem = QLocale::ImperialSystem
+    };
+    enum FormatType {
+        LongFormat = QLocale::LongFormat,
+        ShortFormat = QLocale::ShortFormat,
+        NarrowFormat = QLocale::NarrowFormat
+    };
+    enum CurrencySymbolFormat {
+        CurrencyIsoCode = QLocale::CurrencyIsoCode,
+        CurrencySymbol = QLocale::CurrencySymbol,
+        CurrencyDisplayName = QLocale::CurrencyDisplayName
+    };
+    // Qt defines Sunday as 7, but JS Date assigns Sunday 0
+    enum DayOfWeek {
+        Sunday = 0,
+        Monday = Qt::Monday,
+        Tuesday = Qt::Tuesday,
+        Wednesday = Qt::Wednesday,
+        Thursday = Qt::Thursday,
+        Friday = Qt::Friday,
+        Saturday = Qt::Saturday
+    };
+
+    static v8::Handle<v8::Value> locale(QV8Engine *v8engine, const QString &lang);
+
+private:
+    QDeclarativeLocale();
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
index b14e547..a920d62 100644 (file)
@@ -43,6 +43,7 @@ SOURCES += \
     $$PWD/qdeclarativeextensionplugin.cpp \
     $$PWD/qdeclarativeimport.cpp \
     $$PWD/qdeclarativelist.cpp \
+    $$PWD/qdeclarativelocale.cpp \
 
 HEADERS += \
     $$PWD/qdeclarativeglobal_p.h \
@@ -104,7 +105,8 @@ HEADERS += \
     $$PWD/qdeclarativeimport_p.h \
     $$PWD/qdeclarativeextensionplugin.h \
     $$PWD/qdeclarativenullablevalue_p_p.h \
-    $$PWD/qdeclarativescriptstring_p.h
+    $$PWD/qdeclarativescriptstring_p.h \
+    $$PWD/qdeclarativelocale_p.h \
 
 QT += sql
 include(parser/parser.pri)
index 84b42f6..a822eb8 100644 (file)
@@ -45,6 +45,7 @@
 #include <private/qdeclarativeengine_p.h>
 #include <private/qdeclarativecomponent_p.h>
 #include <private/qdeclarativestringconverters_p.h>
+#include <private/qdeclarativelocale_p.h>
 #include <private/qv8engine_p.h>
 
 #include <QtCore/qstring.h>
@@ -521,6 +522,8 @@ the possible format values as described for
 
 If \a format is not specified, \a date is formatted using
 \l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
+
+\sa Locale
 */
 v8::Handle<v8::Value> formatDate(const v8::Arguments &args)
 {
@@ -560,6 +563,8 @@ described for \l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}.
 
 If \a format is not specified, \a time is formatted using
 \l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
+
+\sa Locale
 */
 v8::Handle<v8::Value> formatTime(const v8::Arguments &args)
 {
@@ -680,6 +685,8 @@ with the \a format values below to produce the following results:
     \row \i "hh:mm:ss.zzz"    \i 14:13:09.042
     \row \i "h:m:s ap"        \i 2:13:9 pm
     \endtable
+
+    \sa Locale
 */
 v8::Handle<v8::Value> formatDateTime(const v8::Arguments &args)
 {
@@ -1087,6 +1094,42 @@ v8::Handle<v8::Value> qsTrIdNoOp(const v8::Arguments &args)
     return args[0];
 }
 
+
+/*!
+    \qmlmethod Qt::locale(name)
+
+    Returns a JS object representing the locale with the specified
+    name, which has the format "language[_territory][.codeset][@modifier]"
+    or "C", where:
+
+    \list
+    \o language is a lowercase, two-letter, ISO 639 language code,
+    \o territory is an uppercase, two-letter, ISO 3166 country code,
+    \o and codeset and modifier are ignored.
+    \endlist
+
+    If the string violates the locale format, or language is not a
+    valid ISO 369 code, the "C" locale is used instead. If country
+    is not present, or is not a valid ISO 3166 code, the most
+    appropriate country is chosen for the specified language.
+
+    \sa QtQuick2::Locale
+*/
+v8::Handle<v8::Value> locale(const v8::Arguments &args)
+{
+    QString code;
+    if (args.Length() > 1)
+        V8THROW_ERROR("locale() requires 0 or 1 argument");
+    if (args.Length() == 1 && !args[0]->IsString())
+        V8THROW_TYPE("locale(): argument (locale code) must be a string");
+
+    QV8Engine *v8engine = V8ENGINE();
+    if (args.Length() == 1)
+        code = v8engine->toString(args[0]);
+
+    return QDeclarativeLocale::locale(v8engine, code);
+}
+
 } // namespace QDeclarativeBuiltinFunctions
 
 QT_END_NAMESPACE
index 8810f77..8a4ac06 100644 (file)
@@ -96,6 +96,7 @@ v8::Handle<v8::Value> qsTrNoOp(const v8::Arguments &args);
 v8::Handle<v8::Value> qsTrId(const v8::Arguments &args);
 v8::Handle<v8::Value> qsTrIdNoOp(const v8::Arguments &args);
 v8::Handle<v8::Value> stringArg(const v8::Arguments &args);
+v8::Handle<v8::Value> locale(const v8::Arguments &args);
 }
 
 QT_END_NAMESPACE
index 084640b..e0fc367 100644 (file)
@@ -22,6 +22,7 @@
 ****************************************************************************/
 
 #include "qjsengine.h"
+#include "qjsengine_p.h"
 #include "qjsvalue.h"
 #include "qjsvalue_p.h"
 #include "qscriptisolate_p.h"
@@ -178,7 +179,7 @@ QJSEngine::QJSEngine(QObject *parent)
 {
 }
 
-QJSEngine::QJSEngine(QObjectPrivate &dd, QObject *parent)
+QJSEngine::QJSEngine(QJSEnginePrivate &dd, QObject *parent)
     : QObject(dd, parent)
     , d(new QV8Engine(this))
 {
index 759363a..c941d0c 100644 (file)
@@ -45,6 +45,7 @@ class QRegExp;
 template <typename T>
 inline T qjsvalue_cast(const QJSValue &);
 
+class QJSEnginePrivate;
 class Q_DECLARATIVE_EXPORT QJSEngine
     : public QObject
 {
@@ -111,11 +112,12 @@ private:
     friend inline bool qjsvalue_cast_helper(const QJSValue &, int, void *);
 
 protected:
-    QJSEngine(QObjectPrivate &dd, QObject *parent = 0);
+    QJSEngine(QJSEnginePrivate &dd, QObject *parent = 0);
 
 private:
     QV8Engine *d;
     Q_DISABLE_COPY(QJSEngine)
+    Q_DECLARE_PRIVATE(QJSEngine)
     friend class QV8Engine;
 };
 
diff --git a/src/declarative/qml/v8/qjsengine_p.h b/src/declarative/qml/v8/qjsengine_p.h
new file mode 100644 (file)
index 0000000..46f8754
--- /dev/null
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL-ONLY$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QJSENGINE_P_H
+#define QJSENGINE_P_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/private/qobject_p.h>
+#include "qjsengine.h"
+
+
+QT_BEGIN_NAMESPACE
+
+
+class QJSEnginePrivate : public QObjectPrivate
+{
+    Q_DECLARE_PUBLIC(QJSEngine)
+
+public:
+    static QJSEnginePrivate* get(QJSEngine*e) { return e->d_func(); }
+
+    QJSEnginePrivate() {}
+};
+
+QT_END_NAMESPACE
+
+#endif // QJSENGINE_P_H
index 791c972..7c4ebff 100644 (file)
@@ -47,6 +47,7 @@
 #include "qv8gccallback_p.h"
 #include "qv8sequencewrapper_p.h"
 #include "qv8include_p.h"
+#include "qjsengine_p.h"
 #include "../../../3rdparty/javascriptcore/DateMath.h"
 
 #include <private/qdeclarativebuiltinfunctions_p.h>
@@ -55,6 +56,7 @@
 #include <private/qdeclarativeapplication_p.h>
 #include <private/qdeclarativexmlhttprequest_p.h>
 #include <private/qdeclarativesqldatabase_p.h>
+#include <private/qdeclarativelocale_p.h>
 
 #include "qscript_impl_p.h"
 #include "qv8domerrors_p.h"
@@ -113,6 +115,7 @@ static bool ObjectComparisonCallback(v8::Local<v8::Object> lhs, v8::Local<v8::Ob
     return false;
 }
 
+
 QV8Engine::QV8Engine(QJSEngine* qq, QJSEngine::ContextOwnership ownership)
     : q(qq)
     , m_engine(0)
@@ -226,6 +229,7 @@ QVariant QV8Engine::toVariant(v8::Handle<v8::Value> value, int typeHint)
             case QV8ObjectResource::ListModelType:
             case QV8ObjectResource::Context2DType:
             case QV8ObjectResource::ParticleDataType:
+            case QV8ObjectResource::LocaleDataType:
                 return QVariant();
             case QV8ObjectResource::TypeType:
                 return m_typeWrapper.toVariant(r);
@@ -565,6 +569,7 @@ void QV8Engine::initializeGlobal(v8::Handle<v8::Object> global)
     qt->Set(v8::String::New("btoa"), V8FUNCTION(btoa, this));
     qt->Set(v8::String::New("atob"), V8FUNCTION(atob, this));
     qt->Set(v8::String::New("resolvedUrl"), V8FUNCTION(resolvedUrl, this));
+    qt->Set(v8::String::New("locale"), V8FUNCTION(locale, this));
 
     if (m_engine) {
         qt->Set(v8::String::New("application"), newQObject(new QDeclarativeApplication(m_engine)));
@@ -604,6 +609,9 @@ void QV8Engine::initializeGlobal(v8::Handle<v8::Object> global)
 #undef STRING_ARG
     }
 
+    QDeclarativeDateExtension::registerExtension(this);
+    QDeclarativeNumberExtension::registerExtension(this);
+
     qt_add_domexceptions(this);
     m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(this);
     m_sqlDatabaseData = qt_add_qmlsqldatabase(this);
index 7b85cfc..acf7ec8 100644 (file)
@@ -139,7 +139,7 @@ public:
                         ValueTypeType, XMLHttpRequestType, DOMNodeType, SQLDatabaseType,
                         ListModelType, Context2DType, Context2DStyleType, Context2DPixelArrayType, 
                         ParticleDataType, SignalHandlerType, IncubatorType, VisualDataItemType,
-                        SequenceType };
+                        SequenceType, LocaleDataType };
     virtual ResourceType resourceType() const = 0;
 
     QV8Engine *engine;
@@ -412,6 +412,9 @@ public:
 
     QObject *qtObjectFromJS(v8::Handle<v8::Value> value);
     QSet<int> visitedConversionObjects;
+
+    static QDateTime qtDateTimeFromJsDate(double jsDate);
+
 protected:
     QJSEngine* q;
     QDeclarativeEngine *m_engine;
@@ -449,7 +452,6 @@ protected:
     void initializeGlobal(v8::Handle<v8::Object>);
 
     double qtDateTimeToJsDate(const QDateTime &dt);
-    QDateTime qtDateTimeFromJsDate(double jsDate);
 
 private:
     typedef QScriptIntrusiveList<QJSValuePrivate, &QJSValuePrivate::m_node> ValueList;
index 587ab6f..3439413 100644 (file)
@@ -5,6 +5,7 @@ SOURCES += \
 
 HEADERS += \
     $$PWD/qjsengine.h \
+    $$PWD/qjsengine_p.h \
     $$PWD/qjsvalue.h \
     $$PWD/qjsvalue_p.h \
     $$PWD/qjsvalueiterator.h \
index 7cb9d33..0d19af9 100644 (file)
@@ -22,6 +22,7 @@ PUBLICTESTS += \
     qdeclarativeqt \
     qdeclarativetranslation \
     qdeclarativexmlhttprequest \
+    qdeclarativelocale \
     qjsvalue \
     qjsvalueiterator \
     qjsengine \
diff --git a/tests/auto/declarative/qdeclarativelocale/data/date.qml b/tests/auto/declarative/qdeclarativelocale/data/date.qml
new file mode 100644 (file)
index 0000000..3f58497
--- /dev/null
@@ -0,0 +1,45 @@
+import QtQuick 2.0
+
+QtObject {
+    property var locale: Qt.locale()
+
+    function setLocale(l) {
+        locale = Qt.locale(l)
+    }
+
+    function toLocaleString(fmt) {
+        var d = new Date(2011, 9, 7, 18, 53, 48, 345);
+        if (fmt < 0)
+            return d.toLocaleString(locale);
+        else
+            return d.toLocaleString(locale, fmt);
+    }
+
+    function toLocaleDateString(fmt) {
+        var d = new Date(2011, 9, 7, 18, 53, 48, 345);
+        if (fmt < 0)
+            return d.toLocaleDateString(locale);
+        else
+            return d.toLocaleDateString(locale, fmt);
+    }
+
+    function toLocaleTimeString(fmt) {
+        var d = new Date(2011, 9, 7, 18, 53, 48, 345);
+        if (fmt < 0)
+            return d.toLocaleTimeString(locale);
+        else
+            return d.toLocaleTimeString(locale, fmt);
+    }
+
+    function fromLocaleString(d,fmt) {
+        return Date.fromLocaleString(locale, d, fmt)
+    }
+
+    function fromLocaleDateString(d,fmt) {
+        return Date.fromLocaleDateString(locale, d, fmt)
+    }
+
+    function fromLocaleTimeString(d,fmt) {
+        return Date.fromLocaleTimeString(locale, d, fmt)
+    }
+}
diff --git a/tests/auto/declarative/qdeclarativelocale/data/functions.qml b/tests/auto/declarative/qdeclarativelocale/data/functions.qml
new file mode 100644 (file)
index 0000000..5fef6a2
--- /dev/null
@@ -0,0 +1,65 @@
+import QtQuick 2.0
+
+QtObject {
+    property var locale: Qt.locale()
+
+    function setLocale(l) {
+        locale = Qt.locale(l)
+    }
+
+    function currencySymbol(type) {
+        if (type < 0)
+            return locale.currencySymbol()
+        else
+            return locale.currencySymbol(type)
+    }
+
+    function monthName(month,type) {
+        if (type < 0)
+            return locale.monthName(month)
+        else
+            return locale.monthName(month, type)
+    }
+
+    function standaloneMonthName(month,type) {
+        if (type < 0)
+            return locale.standaloneMonthName(month)
+        else
+            return locale.standaloneMonthName(month, type)
+    }
+
+    function dayName(month,type) {
+        if (type < 0)
+            return locale.dayName(month)
+        else
+            return locale.dayName(month, type)
+    }
+
+    function standaloneDayName(month,type) {
+        if (type < 0)
+            return locale.standaloneDayName(month)
+        else
+            return locale.standaloneDayName(month, type)
+    }
+
+    function dateTimeFormat(fmt) {
+        if (fmt < 0)
+            return locale.dateTimeFormat()
+        else
+            return locale.dateTimeFormat(fmt)
+    }
+
+    function dateFormat(fmt) {
+        if (fmt < 0)
+            return locale.dateFormat()
+        else
+            return locale.dateFormat(fmt)
+    }
+
+    function timeFormat(fmt) {
+        if (fmt < 0)
+            return locale.timeFormat()
+        else
+            return locale.timeFormat(fmt)
+    }
+}
diff --git a/tests/auto/declarative/qdeclarativelocale/data/number.qml b/tests/auto/declarative/qdeclarativelocale/data/number.qml
new file mode 100644 (file)
index 0000000..51a6c15
--- /dev/null
@@ -0,0 +1,30 @@
+import QtQuick 2.0
+
+QtObject {
+    property var locale: Qt.locale()
+
+    function setLocale(l) {
+        locale = Qt.locale(l)
+    }
+
+    function toLocaleString(n,fmt,prec) {
+        if (prec < 0)
+            return n.toLocaleString(locale, fmt);
+        else
+            return n.toLocaleString(locale, fmt, prec);
+    }
+
+    function toLocaleCurrencyString(n,symbol) {
+        if (symbol.length == 0)
+            return n.toLocaleCurrencyString(locale);
+        else
+            return n.toLocaleCurrencyString(locale, symbol);
+    }
+
+    function fromLocaleString(n) {
+        return Number.fromLocaleString(locale, n)
+    }
+
+    property var const1: 1234.56.toLocaleString(locale);
+    property var const2: 1234..toLocaleString(locale);
+}
diff --git a/tests/auto/declarative/qdeclarativelocale/data/properties.qml b/tests/auto/declarative/qdeclarativelocale/data/properties.qml
new file mode 100644 (file)
index 0000000..1d2968b
--- /dev/null
@@ -0,0 +1,26 @@
+import QtQuick 2.0
+
+QtObject {
+    property var locale: Qt.locale()
+
+    function setLocale(l) {
+        locale = Qt.locale(l);
+    }
+
+    property var name: locale.name
+    property var amText: locale.amText
+    property var pmText: locale.pmText
+    property var nativeLanguageName: locale.nativeLanguageName
+    property var nativeCountryName: locale.nativeCountryName
+    property var decimalPoint: locale.decimalPoint
+    property var groupSeparator: locale.groupSeparator
+    property var percent: locale.percent
+    property var zeroDigit: locale.zeroDigit
+    property var negativeSign: locale.negativeSign
+    property var positiveSign: locale.positiveSign
+    property var exponential: locale.exponential
+    property var firstDayOfWeek: locale.firstDayOfWeek
+    property var measurementSystem: locale.measurementSystem
+    property var textDirection: locale.textDirection
+    property var weekDays: locale.weekDays
+}
diff --git a/tests/auto/declarative/qdeclarativelocale/qdeclarativelocale.pro b/tests/auto/declarative/qdeclarativelocale/qdeclarativelocale.pro
new file mode 100644 (file)
index 0000000..05ce0fe
--- /dev/null
@@ -0,0 +1,13 @@
+CONFIG += testcase
+TARGET = tst_qdeclarativelocale
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qdeclarativelocale.cpp
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+
+QT += declarative testlib
diff --git a/tests/auto/declarative/qdeclarativelocale/tst_qdeclarativelocale.cpp b/tests/auto/declarative/qdeclarativelocale/tst_qdeclarativelocale.cpp
new file mode 100644 (file)
index 0000000..54139a2
--- /dev/null
@@ -0,0 +1,1090 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QDebug>
+
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtDeclarative/qquickitem.h>
+#include <QtCore/QDateTime>
+#include <qcolor.h>
+#include "../shared/util.h"
+
+class tst_qdeclarativelocale : public QObject
+{
+    Q_OBJECT
+public:
+    tst_qdeclarativelocale() { }
+
+private slots:
+    void properties_data();
+    void properties();
+    void currencySymbol_data();
+    void currencySymbol();
+    void monthName_data();
+    void monthName();
+    void standaloneMonthName_data();
+    void standaloneMonthName();
+    void dayName_data();
+    void dayName();
+    void standaloneDayName_data();
+    void standaloneDayName();
+    void weekDays_data();
+    void weekDays();
+    void dateFormat_data();
+    void dateFormat();
+    void dateTimeFormat_data();
+    void dateTimeFormat();
+    void timeFormat_data();
+    void timeFormat();
+
+    void dateToLocaleString_data();
+    void dateToLocaleString();
+    void dateToLocaleStringFormatted_data();
+    void dateToLocaleStringFormatted();
+    void dateToLocaleDateString_data();
+    void dateToLocaleDateString();
+    void dateToLocaleDateStringFormatted_data();
+    void dateToLocaleDateStringFormatted();
+    void dateToLocaleTimeString_data();
+    void dateToLocaleTimeString();
+    void dateToLocaleTimeStringFormatted_data();
+    void dateToLocaleTimeStringFormatted();
+    void dateFromLocaleString_data();
+    void dateFromLocaleString();
+    void dateFromLocaleDateString_data();
+    void dateFromLocaleDateString();
+    void dateFromLocaleTimeString_data();
+    void dateFromLocaleTimeString();
+
+    void numberToLocaleString_data();
+    void numberToLocaleString();
+    void numberToLocaleCurrencyString_data();
+    void numberToLocaleCurrencyString();
+    void numberFromLocaleString_data();
+    void numberFromLocaleString();
+    void numberConstToLocaleString();
+
+private:
+    void addPropertyData(const QString &l);
+    QVariant getProperty(QObject *obj, const QString &locale, const QString &property);
+    void addCurrencySymbolData(const QString &locale);
+    void addStandardFormatData();
+    void addFormatNameData(const QString &locale);
+    void addDateTimeFormatData(const QString &l);
+    void addDateFormatData(const QString &l);
+    void addTimeFormatData(const QString &l);
+    QDeclarativeEngine engine;
+};
+
+#define LOCALE_PROP(type,prop) { #prop, QVariant(type(qlocale.prop())) }
+
+void tst_qdeclarativelocale::addPropertyData(const QString &l)
+{
+    QLocale qlocale(l);
+
+    struct {
+        const char *name;
+        QVariant value;
+    }
+    values[] = {
+        LOCALE_PROP(QString,name),
+        LOCALE_PROP(QString,amText),
+        LOCALE_PROP(QString,pmText),
+        LOCALE_PROP(QString,nativeLanguageName),
+        LOCALE_PROP(QString,nativeCountryName),
+        LOCALE_PROP(QString,decimalPoint),
+        LOCALE_PROP(QString,groupSeparator),
+        LOCALE_PROP(QString,percent),
+        LOCALE_PROP(QString,zeroDigit),
+        LOCALE_PROP(QString,negativeSign),
+        LOCALE_PROP(QString,positiveSign),
+        LOCALE_PROP(QString,exponential),
+        LOCALE_PROP(int,firstDayOfWeek),
+        LOCALE_PROP(int,measurementSystem),
+        LOCALE_PROP(int,textDirection),
+        { 0, QVariant() }
+    };
+
+    int i = 0;
+    while (values[i].name) {
+        QByteArray n = l.toLatin1() + ':' + values[i].name;
+        QTest::newRow(n.constData()) << l << QByteArray(values[i].name) << values[i].value;
+        ++i;
+    }
+}
+
+void tst_qdeclarativelocale::properties_data()
+{
+    QTest::addColumn<QString>("locale");
+    QTest::addColumn<QByteArray>("property");
+    QTest::addColumn<QVariant>("value");
+
+    addPropertyData("en_US");
+    addPropertyData("de_DE");
+    addPropertyData("ar_SA");
+    addPropertyData("hi_IN");
+    addPropertyData("zh_CN");
+    addPropertyData("th_TH");
+}
+
+void tst_qdeclarativelocale::properties()
+{
+    QFETCH(QString, locale);
+    QFETCH(QByteArray, property);
+    QFETCH(QVariant, value);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("properties.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    QCOMPARE(obj->property(property), value);
+
+    delete obj;
+}
+
+void tst_qdeclarativelocale::addCurrencySymbolData(const QString &l)
+{
+    QByteArray locale = l.toLatin1();
+    QTest::newRow(locale.constData()) << l << -1;
+    QByteArray t(locale);
+    t += " CurrencyIsoCode";
+    QTest::newRow(t.constData()) << l << (int)QLocale::CurrencyIsoCode;
+    t = locale + " CurrencySymbol";
+    QTest::newRow(t.constData()) << l << (int)QLocale::CurrencySymbol;
+    t = locale + " CurrencyDisplayName";
+    QTest::newRow(t.constData()) << l << (int)QLocale::CurrencyDisplayName;
+}
+
+void tst_qdeclarativelocale::currencySymbol_data()
+{
+    QTest::addColumn<QString>("locale");
+    QTest::addColumn<int>("param");
+
+    addCurrencySymbolData("en_US");
+    addCurrencySymbolData("de_DE");
+    addCurrencySymbolData("ar_SA");
+    addCurrencySymbolData("hi_IN");
+    addCurrencySymbolData("zh_CN");
+    addCurrencySymbolData("th_TH");
+}
+
+void tst_qdeclarativelocale::currencySymbol()
+{
+    QFETCH(QString, locale);
+    QFETCH(int, param);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("functions.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QLocale l(locale);
+    QVariant val;
+    QLocale::CurrencySymbolFormat format = QLocale::CurrencySymbol;
+
+    if (param >= 0)
+        format = QLocale::CurrencySymbolFormat(param);
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    QMetaObject::invokeMethod(obj, "currencySymbol", Qt::DirectConnection,
+            Q_RETURN_ARG(QVariant, val),
+            Q_ARG(QVariant, QVariant(int(format))));
+
+    QCOMPARE(val.toString(), l.currencySymbol(format));
+
+    delete obj;
+}
+
+void tst_qdeclarativelocale::addFormatNameData(const QString &l)
+{
+    QByteArray locale = l.toLatin1();
+    QTest::newRow(locale.constData()) << l << -1;
+    QByteArray t(locale);
+    t += " LongFormat";
+    QTest::newRow(t.constData()) << l << (int)QLocale::LongFormat;
+    t = locale + " ShortFormat";
+    QTest::newRow(t.constData()) << l << (int)QLocale::ShortFormat;
+    t = locale + " NarrowFormat";
+    QTest::newRow(t.constData()) << l << (int)QLocale::NarrowFormat;
+}
+
+void tst_qdeclarativelocale::addStandardFormatData()
+{
+    QTest::addColumn<QString>("locale");
+    QTest::addColumn<int>("param");
+
+    addFormatNameData("en_US");
+    addFormatNameData("de_DE");
+    addFormatNameData("ar_SA");
+    addFormatNameData("hi_IN");
+    addFormatNameData("zh_CN");
+    addFormatNameData("th_TH");
+}
+
+void tst_qdeclarativelocale::monthName_data()
+{
+    addStandardFormatData();
+}
+
+void tst_qdeclarativelocale::monthName()
+{
+    QFETCH(QString, locale);
+    QFETCH(int, param);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("functions.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QLocale l(locale);
+    QVariant val;
+    QLocale::FormatType format = QLocale::LongFormat;
+    if (param >= 0)
+        format = QLocale::FormatType(param);
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    for (int i = 0; i <= 11; ++i) {
+        QMetaObject::invokeMethod(obj, "monthName", Qt::DirectConnection,
+            Q_RETURN_ARG(QVariant, val),
+            Q_ARG(QVariant, QVariant(i)),
+            Q_ARG(QVariant, QVariant(int(format))));
+
+        // QLocale January == 1, JS Date January == 0
+        QCOMPARE(val.toString(), l.monthName(i+1, format));
+    }
+
+    delete obj;
+}
+
+void tst_qdeclarativelocale::standaloneMonthName_data()
+{
+    addStandardFormatData();
+}
+
+void tst_qdeclarativelocale::standaloneMonthName()
+{
+    QFETCH(QString, locale);
+    QFETCH(int, param);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("functions.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QLocale l(locale);
+    QVariant val;
+    QLocale::FormatType format = QLocale::LongFormat;
+    if (param >= 0)
+        format = QLocale::FormatType(param);
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    for (int i = 0; i <= 11; ++i) {
+        QMetaObject::invokeMethod(obj, "standaloneMonthName", Qt::DirectConnection,
+            Q_RETURN_ARG(QVariant, val),
+            Q_ARG(QVariant, QVariant(i)),
+            Q_ARG(QVariant, QVariant(int(format))));
+
+        // QLocale January == 1, JS Date January == 0
+        QCOMPARE(val.toString(), l.standaloneMonthName(i+1, format));
+    }
+
+    delete obj;
+}
+
+void tst_qdeclarativelocale::dayName_data()
+{
+    addStandardFormatData();
+}
+
+void tst_qdeclarativelocale::dayName()
+{
+    QFETCH(QString, locale);
+    QFETCH(int, param);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("functions.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QLocale l(locale);
+    QVariant val;
+    QLocale::FormatType format = QLocale::LongFormat;
+    if (param >= 0)
+        format = QLocale::FormatType(param);
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    for (int i = 1; i <= 7; ++i) {
+        QMetaObject::invokeMethod(obj, "dayName", Qt::DirectConnection,
+            Q_RETURN_ARG(QVariant, val),
+            Q_ARG(QVariant, QVariant(i)),
+            Q_ARG(QVariant, QVariant(int(format))));
+
+        QCOMPARE(val.toString(), l.dayName(i, format));
+    }
+
+    delete obj;
+}
+
+void tst_qdeclarativelocale::standaloneDayName_data()
+{
+    addStandardFormatData();
+}
+
+void tst_qdeclarativelocale::standaloneDayName()
+{
+    QFETCH(QString, locale);
+    QFETCH(int, param);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("functions.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QLocale l(locale);
+    QVariant val;
+    QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param);
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    for (int i = 1; i <= 7; ++i) {
+        QMetaObject::invokeMethod(obj, "standaloneDayName", Qt::DirectConnection,
+                Q_RETURN_ARG(QVariant, val),
+                Q_ARG(QVariant, QVariant(i)),
+                Q_ARG(QVariant, QVariant(int(format))));
+
+        QCOMPARE(val.toString(), l.standaloneDayName(i, format));
+    }
+
+    delete obj;
+}
+
+void tst_qdeclarativelocale::weekDays_data()
+{
+    QTest::addColumn<QString>("locale");
+
+    QTest::newRow("en_US") << "en_US";
+    QTest::newRow("de_DE") << "de_DE";
+    QTest::newRow("ar_SA") << "ar_SA";
+    QTest::newRow("hi_IN") << "hi_IN";
+    QTest::newRow("zh_CN") << "zh_CN";
+    QTest::newRow("th_TH") << "th_TH";
+}
+
+void tst_qdeclarativelocale::weekDays()
+{
+    QFETCH(QString, locale);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("properties.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    QVariant val = obj->property("weekDays");
+    QVERIFY(val.type() == QVariant::List);
+
+    QList<QVariant> qmlDays = val.toList();
+    QList<Qt::DayOfWeek> days = QLocale(locale).weekdays();
+
+    QVERIFY(days.count() == qmlDays.count());
+
+    for (int i = 0; i < days.count(); ++i) {
+        int day = int(days.at(i));
+        if (day == 7) // JS Date days in range 0(Sunday) to 6(Saturday)
+            day = 0;
+        QCOMPARE(day, qmlDays.at(i).toInt());
+    }
+
+    delete obj;
+}
+
+
+void tst_qdeclarativelocale::dateTimeFormat_data()
+{
+    addStandardFormatData();
+}
+
+void tst_qdeclarativelocale::dateTimeFormat()
+{
+    QFETCH(QString, locale);
+    QFETCH(int, param);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("functions.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QLocale l(locale);
+    QVariant val;
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param);
+    QMetaObject::invokeMethod(obj, "dateTimeFormat", Qt::DirectConnection,
+            Q_RETURN_ARG(QVariant, val),
+            Q_ARG(QVariant, QVariant(param)));
+
+    QCOMPARE(val.toString(), l.dateTimeFormat(format));
+}
+
+void tst_qdeclarativelocale::dateFormat_data()
+{
+    addStandardFormatData();
+}
+
+void tst_qdeclarativelocale::dateFormat()
+{
+    QFETCH(QString, locale);
+    QFETCH(int, param);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("functions.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QLocale l(locale);
+    QVariant val;
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param);
+    QMetaObject::invokeMethod(obj, "dateFormat", Qt::DirectConnection,
+            Q_RETURN_ARG(QVariant, val),
+            Q_ARG(QVariant, QVariant(param)));
+
+    QCOMPARE(val.toString(), l.dateFormat(format));
+}
+
+void tst_qdeclarativelocale::timeFormat_data()
+{
+    addStandardFormatData();
+}
+
+void tst_qdeclarativelocale::timeFormat()
+{
+    QFETCH(QString, locale);
+    QFETCH(int, param);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("functions.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QLocale l(locale);
+    QVariant val;
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param);
+    QMetaObject::invokeMethod(obj, "timeFormat", Qt::DirectConnection,
+            Q_RETURN_ARG(QVariant, val),
+            Q_ARG(QVariant, QVariant(param)));
+
+    QCOMPARE(val.toString(), l.timeFormat(format));
+}
+
+void tst_qdeclarativelocale::dateToLocaleString_data()
+{
+    addStandardFormatData();
+}
+
+void tst_qdeclarativelocale::dateToLocaleString()
+{
+    QFETCH(QString, locale);
+    QFETCH(int, param);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("date.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QDateTime dt;
+    dt.setDate(QDate(2011, 10, 7)); // weirdly, JS Date month range is 0-11
+    dt.setTime(QTime(18, 53, 48, 345));
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param);
+
+    QVariant val;
+    QMetaObject::invokeMethod(obj, "toLocaleString", Qt::DirectConnection,
+        Q_RETURN_ARG(QVariant, val),
+        Q_ARG(QVariant, QVariant(param)));
+
+    QLocale l(locale);
+    QCOMPARE(val.toString(), l.toString(dt, format));
+}
+
+void tst_qdeclarativelocale::addDateTimeFormatData(const QString &l)
+{
+    const char *formats[] = {
+        "hh:mm dd.MM.yyyy",
+        "h:m:sap ddd MMMM d yy",
+        "'The date and time is: 'H:mm:ss:zzz dd/MM/yy",
+        "MMM d yyyy HH:mm t",
+        0
+    };
+    QByteArray locale = l.toLatin1();
+    int i = 0;
+    while (formats[i]) {
+        QByteArray t(locale);
+        t += " ";
+        t += formats[i];
+        QTest::newRow(t.constData()) << l << QString(formats[i]);
+        ++i;
+    }
+}
+
+void tst_qdeclarativelocale::dateToLocaleStringFormatted_data()
+{
+    QTest::addColumn<QString>("locale");
+    QTest::addColumn<QString>("format");
+
+    addDateTimeFormatData("en_US");
+    addDateTimeFormatData("de_DE");
+    addDateTimeFormatData("ar_SA");
+    addDateTimeFormatData("hi_IN");
+    addDateTimeFormatData("zh_CN");
+    addDateTimeFormatData("th_TH");
+}
+
+void tst_qdeclarativelocale::dateToLocaleStringFormatted()
+{
+    QFETCH(QString, locale);
+    QFETCH(QString, format);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("date.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QDateTime dt;
+    dt.setDate(QDate(2011, 10, 7)); // weirdly, JS Date month range is 0-11
+    dt.setTime(QTime(18, 53, 48, 345));
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    QVariant val;
+    QMetaObject::invokeMethod(obj, "toLocaleString", Qt::DirectConnection,
+        Q_RETURN_ARG(QVariant, val),
+        Q_ARG(QVariant, QVariant(format)));
+
+    QLocale l(locale);
+    QCOMPARE(val.toString(), l.toString(dt, format));
+}
+
+void tst_qdeclarativelocale::dateToLocaleDateString_data()
+{
+    addStandardFormatData();
+}
+
+void tst_qdeclarativelocale::dateToLocaleDateString()
+{
+    QFETCH(QString, locale);
+    QFETCH(int, param);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("date.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QDateTime dt;
+    dt.setDate(QDate(2011, 10, 7)); // weirdly, JS Date month range is 0-11
+    dt.setTime(QTime(18, 53, 48, 345));
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param);
+
+    QVariant val;
+    QMetaObject::invokeMethod(obj, "toLocaleDateString", Qt::DirectConnection,
+        Q_RETURN_ARG(QVariant, val),
+        Q_ARG(QVariant, QVariant(param)));
+
+    QLocale l(locale);
+    QCOMPARE(val.toString(), l.toString(dt.date(), format));
+}
+
+void tst_qdeclarativelocale::addDateFormatData(const QString &l)
+{
+    const char *formats[] = {
+        "dd.MM.yyyy",
+        "ddd MMMM d yy",
+        "'The date is: 'dd/MM/yy",
+        "MMM d yyyy",
+        0
+    };
+    QByteArray locale = l.toLatin1();
+    int i = 0;
+    while (formats[i]) {
+        QByteArray t(locale);
+        t += " ";
+        t += formats[i];
+        QTest::newRow(t.constData()) << l << QString(formats[i]);
+        ++i;
+    }
+}
+
+void tst_qdeclarativelocale::dateToLocaleDateStringFormatted_data()
+{
+    QTest::addColumn<QString>("locale");
+    QTest::addColumn<QString>("format");
+
+    addDateFormatData("en_US");
+    addDateFormatData("de_DE");
+    addDateFormatData("ar_SA");
+    addDateFormatData("hi_IN");
+    addDateFormatData("zh_CN");
+    addDateFormatData("th_TH");
+}
+
+void tst_qdeclarativelocale::dateToLocaleDateStringFormatted()
+{
+    QFETCH(QString, locale);
+    QFETCH(QString, format);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("date.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QDateTime dt;
+    dt.setDate(QDate(2011, 10, 7)); // weirdly, JS Date month range is 0-11
+    dt.setTime(QTime(18, 53, 48, 345));
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    QVariant val;
+    QMetaObject::invokeMethod(obj, "toLocaleString", Qt::DirectConnection,
+        Q_RETURN_ARG(QVariant, val),
+        Q_ARG(QVariant, QVariant(format)));
+
+    QLocale l(locale);
+    QCOMPARE(val.toString(), l.toString(dt.date(), format));
+}
+
+void tst_qdeclarativelocale::dateToLocaleTimeString_data()
+{
+    addStandardFormatData();
+}
+
+void tst_qdeclarativelocale::dateToLocaleTimeString()
+{
+    QFETCH(QString, locale);
+    QFETCH(int, param);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("date.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QDateTime dt;
+    dt.setDate(QDate(2011, 10, 7)); // weirdly, JS Date month range is 0-11
+    dt.setTime(QTime(18, 53, 48, 345));
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param);
+
+    QVariant val;
+    QMetaObject::invokeMethod(obj, "toLocaleTimeString", Qt::DirectConnection,
+        Q_RETURN_ARG(QVariant, val),
+        Q_ARG(QVariant, QVariant(param)));
+
+    QLocale l(locale);
+    QCOMPARE(val.toString(), l.toString(dt.time(), format));
+}
+
+void tst_qdeclarativelocale::addTimeFormatData(const QString &l)
+{
+    const char *formats[] = {
+        "hh:mm",
+        "h:m:sap",
+        "'The time is: 'H:mm:ss:zzz",
+        "HH:mm t",
+        0
+    };
+    QByteArray locale = l.toLatin1();
+    int i = 0;
+    while (formats[i]) {
+        QByteArray t(locale);
+        t += " ";
+        t += formats[i];
+        QTest::newRow(t.constData()) << l << QString(formats[i]);
+        ++i;
+    }
+}
+
+void tst_qdeclarativelocale::dateToLocaleTimeStringFormatted_data()
+{
+    QTest::addColumn<QString>("locale");
+    QTest::addColumn<QString>("format");
+
+    addTimeFormatData("en_US");
+    addTimeFormatData("de_DE");
+    addTimeFormatData("ar_SA");
+    addTimeFormatData("hi_IN");
+    addTimeFormatData("zh_CN");
+    addTimeFormatData("th_TH");
+}
+
+void tst_qdeclarativelocale::dateToLocaleTimeStringFormatted()
+{
+    QFETCH(QString, locale);
+    QFETCH(QString, format);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("date.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QDateTime dt;
+    dt.setDate(QDate(2011, 10, 7)); // weirdly, JS Date month range is 0-11
+    dt.setTime(QTime(18, 53, 48, 345));
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    QVariant val;
+    QMetaObject::invokeMethod(obj, "toLocaleString", Qt::DirectConnection,
+        Q_RETURN_ARG(QVariant, val),
+        Q_ARG(QVariant, QVariant(format)));
+
+    QLocale l(locale);
+    QCOMPARE(val.toString(), l.toString(dt.time(), format));
+}
+
+void tst_qdeclarativelocale::dateFromLocaleString_data()
+{
+    QTest::addColumn<QString>("locale");
+    QTest::addColumn<QString>("format");
+
+    QTest::newRow("en_US 1") << "en_US" << "dddd, MMMM d, yyyy h:mm:ss AP";
+    QTest::newRow("en_US long") << "en_US" << QLocale("en_US").dateTimeFormat();
+    QTest::newRow("en_US short") << "en_US" << QLocale("en_US").dateTimeFormat(QLocale::ShortFormat);
+    QTest::newRow("de_DE long") << "de_DE" << QLocale("de_DE").dateTimeFormat();
+    QTest::newRow("de_DE short") << "de_DE" << QLocale("de_DE").dateTimeFormat(QLocale::ShortFormat);
+    QTest::newRow("ar_SA long") << "ar_SA" << QLocale("ar_SA").dateTimeFormat();
+    QTest::newRow("ar_SA short") << "ar_SA" << QLocale("ar_SA").dateTimeFormat(QLocale::ShortFormat);
+    QTest::newRow("zh_CN long") << "zh_CN" << QLocale("zh_CN").dateTimeFormat();
+    QTest::newRow("zh_CN short") << "zh_CN" << QLocale("zh_CN").dateTimeFormat(QLocale::ShortFormat);
+}
+
+void tst_qdeclarativelocale::dateFromLocaleString()
+{
+    QFETCH(QString, locale);
+    QFETCH(QString, format);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("date.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QDateTime dt;
+    dt.setDate(QDate(2011, 10, 7));
+    dt.setTime(QTime(18, 53, 48, 345));
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    QLocale l(locale);
+    QVariant val;
+    QMetaObject::invokeMethod(obj, "fromLocaleString", Qt::DirectConnection,
+        Q_RETURN_ARG(QVariant, val),
+        Q_ARG(QVariant, QVariant(l.toString(dt, format))),
+        Q_ARG(QVariant, QVariant(format)));
+
+    QDateTime pd = l.toDateTime(l.toString(dt, format), format);
+    QCOMPARE(val.toDateTime(), pd);
+}
+
+void tst_qdeclarativelocale::dateFromLocaleDateString_data()
+{
+    QTest::addColumn<QString>("locale");
+    QTest::addColumn<QString>("format");
+
+    QTest::newRow("en_US 1") << "en_US" << "dddd, MMMM d, yyyy h:mm:ss AP";
+    QTest::newRow("en_US long") << "en_US" << QLocale("en_US").dateTimeFormat();
+    QTest::newRow("en_US short") << "en_US" << QLocale("en_US").dateTimeFormat(QLocale::ShortFormat);
+    QTest::newRow("de_DE long") << "de_DE" << QLocale("de_DE").dateTimeFormat();
+    QTest::newRow("de_DE short") << "de_DE" << QLocale("de_DE").dateTimeFormat(QLocale::ShortFormat);
+    QTest::newRow("ar_SA long") << "ar_SA" << QLocale("ar_SA").dateTimeFormat();
+    QTest::newRow("ar_SA short") << "ar_SA" << QLocale("ar_SA").dateTimeFormat(QLocale::ShortFormat);
+    QTest::newRow("zh_CN long") << "zh_CN" << QLocale("zh_CN").dateTimeFormat();
+    QTest::newRow("zh_CN short") << "zh_CN" << QLocale("zh_CN").dateTimeFormat(QLocale::ShortFormat);
+}
+
+void tst_qdeclarativelocale::dateFromLocaleDateString()
+{
+    QFETCH(QString, locale);
+    QFETCH(QString, format);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("date.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QDateTime dt;
+    dt.setDate(QDate(2011, 10, 7));
+    dt.setTime(QTime(18, 53, 48, 345));
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    QLocale l(locale);
+    QVariant val;
+    QMetaObject::invokeMethod(obj, "fromLocaleDateString", Qt::DirectConnection,
+        Q_RETURN_ARG(QVariant, val),
+        Q_ARG(QVariant, QVariant(l.toString(dt, format))),
+        Q_ARG(QVariant, QVariant(format)));
+
+    QDate pd = l.toDate(l.toString(dt, format), format);
+    QCOMPARE(val.toDate(), pd);
+}
+
+void tst_qdeclarativelocale::dateFromLocaleTimeString_data()
+{
+    QTest::addColumn<QString>("locale");
+    QTest::addColumn<QString>("format");
+
+    QTest::newRow("en_US 1") << "en_US" << "dddd, MMMM d, yyyy h:mm:ss AP";
+    QTest::newRow("en_US long") << "en_US" << QLocale("en_US").dateTimeFormat();
+    QTest::newRow("en_US short") << "en_US" << QLocale("en_US").dateTimeFormat(QLocale::ShortFormat);
+    QTest::newRow("de_DE long") << "de_DE" << QLocale("de_DE").dateTimeFormat();
+    QTest::newRow("de_DE short") << "de_DE" << QLocale("de_DE").dateTimeFormat(QLocale::ShortFormat);
+    QTest::newRow("ar_SA long") << "ar_SA" << QLocale("ar_SA").dateTimeFormat();
+    QTest::newRow("ar_SA short") << "ar_SA" << QLocale("ar_SA").dateTimeFormat(QLocale::ShortFormat);
+    QTest::newRow("zh_CN long") << "zh_CN" << QLocale("zh_CN").dateTimeFormat();
+    QTest::newRow("zh_CN short") << "zh_CN" << QLocale("zh_CN").dateTimeFormat(QLocale::ShortFormat);
+}
+
+void tst_qdeclarativelocale::dateFromLocaleTimeString()
+{
+    QFETCH(QString, locale);
+    QFETCH(QString, format);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("date.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QDateTime dt;
+    dt.setDate(QDate(2011, 10, 7));
+    dt.setTime(QTime(18, 53, 48, 345));
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    QLocale l(locale);
+    QVariant val;
+    QMetaObject::invokeMethod(obj, "fromLocaleTimeString", Qt::DirectConnection,
+        Q_RETURN_ARG(QVariant, val),
+        Q_ARG(QVariant, QVariant(l.toString(dt, format))),
+        Q_ARG(QVariant, QVariant(format)));
+
+    QTime pd = l.toTime(l.toString(dt, format), format);
+    QCOMPARE(val.toTime(), pd);
+}
+
+void tst_qdeclarativelocale::numberToLocaleString_data()
+{
+    QTest::addColumn<QString>("locale");
+    QTest::addColumn<char>("format");
+    QTest::addColumn<int>("prec");
+
+    QTest::newRow("en_US 1") << "en_US" << 'f' << 2;
+    QTest::newRow("en_US 2") << "en_US" << 'g' << 3;
+    QTest::newRow("en_US 3") << "en_US" << 'f' << 0;
+    QTest::newRow("en_US 4") << "en_US" << 'f' << -1;
+    QTest::newRow("de_DE 1") << "de_DE" << 'f' << 2;
+    QTest::newRow("de_DE 2") << "de_DE" << 'g' << 3;
+    QTest::newRow("ar_SA 1") << "ar_SA" << 'f' << 2;
+    QTest::newRow("ar_SA 2") << "ar_SA" << 'g' << 3;
+}
+
+void tst_qdeclarativelocale::numberToLocaleString()
+{
+    QFETCH(QString, locale);
+    QFETCH(char, format);
+    QFETCH(int, prec);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("number.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    double number = 2344423.3289;
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    QLocale l(locale);
+    QVariant val;
+    QMetaObject::invokeMethod(obj, "toLocaleString", Qt::DirectConnection,
+        Q_RETURN_ARG(QVariant, val),
+        Q_ARG(QVariant, QVariant(number)),
+        Q_ARG(QVariant, QVariant(QString(format))),
+        Q_ARG(QVariant, QVariant(prec)));
+
+    if (prec < 0) prec = 2;
+    QCOMPARE(val.toString(), l.toString(number, format, prec));
+}
+
+void tst_qdeclarativelocale::numberToLocaleCurrencyString_data()
+{
+    QTest::addColumn<QString>("locale");
+    QTest::addColumn<QString>("symbol");
+
+    QTest::newRow("en_US 1") << "en_US" << QString();
+    QTest::newRow("en_US 2") << "en_US" << "USD";
+    QTest::newRow("de_DE") << "de_DE" << QString();
+    QTest::newRow("ar_SA") << "ar_SA" << QString();
+    QTest::newRow("hi_IN") << "hi_IN" << QString();
+    QTest::newRow("zh_CN") << "zh_CN" << QString();
+    QTest::newRow("th_TH") << "th_TH" << QString();
+}
+
+void tst_qdeclarativelocale::numberToLocaleCurrencyString()
+{
+    QFETCH(QString, locale);
+    QFETCH(QString, symbol);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("number.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    double number = 2344423.3289;
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    QLocale l(locale);
+    QVariant val;
+    QMetaObject::invokeMethod(obj, "toLocaleCurrencyString", Qt::DirectConnection,
+        Q_RETURN_ARG(QVariant, val),
+        Q_ARG(QVariant, QVariant(number)),
+        Q_ARG(QVariant, QVariant(symbol)));
+
+    QCOMPARE(val.toString(), l.toCurrencyString(number, symbol));
+}
+
+void tst_qdeclarativelocale::numberFromLocaleString_data()
+{
+    QTest::addColumn<QString>("locale");
+    QTest::addColumn<double>("number");
+
+    QTest::newRow("en_US 1") << "en_US" << 1234567.2345;
+    QTest::newRow("en_US 2") << "en_US" << 0.234;
+    QTest::newRow("en_US 3") << "en_US" << 234.0;
+    QTest::newRow("de_DE") << "de_DE" << 1234567.2345;
+    QTest::newRow("ar_SA") << "ar_SA" << 1234567.2345;
+    QTest::newRow("hi_IN") << "hi_IN" << 1234567.2345;
+    QTest::newRow("zh_CN") << "zh_CN" << 1234567.2345;
+    QTest::newRow("th_TH") << "th_TH" << 1234567.2345;
+}
+
+void tst_qdeclarativelocale::numberFromLocaleString()
+{
+    QFETCH(QString, locale);
+    QFETCH(double, number);
+
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("number.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QLocale l(locale);
+    QString strNumber = l.toString(number, 'f');
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant(locale)));
+
+    QVariant val;
+    QMetaObject::invokeMethod(obj, "fromLocaleString", Qt::DirectConnection,
+        Q_RETURN_ARG(QVariant, val),
+        Q_ARG(QVariant, QVariant(strNumber)));
+
+    QCOMPARE(val.toDouble(), l.toDouble(strNumber));
+}
+
+void tst_qdeclarativelocale::numberConstToLocaleString()
+{
+    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("number.qml")));
+
+    QObject *obj = c.create();
+    QVERIFY(obj);
+
+    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
+        Q_ARG(QVariant, QVariant("en_US")));
+
+    QLocale l("en_US");
+    QCOMPARE(obj->property("const1").toString(), l.toString(1234.56, 'f', 2));
+    QCOMPARE(obj->property("const2").toString(), l.toString(1234., 'f', 2));
+}
+
+QTEST_MAIN(tst_qdeclarativelocale)
+
+#include "tst_qdeclarativelocale.moc"