1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #include "qqmllocale_p.h"
43 #include "qqmlengine_p.h"
44 #include <private/qqmlcontext_p.h>
45 #include <private/qjsconverter_impl_p.h>
46 #include <QtCore/qnumeric.h>
47 #include <QtCore/qdatetime.h>
49 #include <private/qlocale_p.h>
50 #include <private/qlocale_data_p.h>
54 class QV8LocaleDataResource : public QV8ObjectResource
56 V8_RESOURCE_TYPE(LocaleDataType)
58 QV8LocaleDataResource(QV8Engine *e) : QV8ObjectResource(e) {}
62 #define GET_LOCALE_DATA_RESOURCE(OBJECT) \
63 QV8LocaleDataResource *r = v8_resource_cast<QV8LocaleDataResource>(OBJECT); \
65 V8THROW_ERROR("Not a valid Locale object")
67 static bool isLocaleObject(v8::Handle<v8::Value> val)
72 v8::Handle<v8::Object> localeObj = val->ToObject();
73 return localeObj->Has(v8::String::New("nativeLanguageName")); //XXX detect locale object properly
79 static const char *dateToLocaleStringFunction =
80 "(function(toLocaleStringFunc) { "
81 " var orig_toLocaleString;"
82 " orig_toLocaleString = Date.prototype.toLocaleString;"
83 " Date.prototype.toLocaleString = (function() {"
84 " var val = toLocaleStringFunc.apply(this, arguments);"
85 " if (val == undefined) val = orig_toLocaleString.call(this);"
90 static const char *dateToLocaleTimeStringFunction =
91 "(function(toLocaleTimeStringFunc) { "
92 " var orig_toLocaleTimeString;"
93 " orig_toLocaleTimeString = Date.prototype.toLocaleTimeString;"
94 " Date.prototype.toLocaleTimeString = (function() {"
95 " var val = toLocaleTimeStringFunc.apply(this, arguments);"
96 " if (val == undefined) val = orig_toLocaleTimeString.call(this);"
101 static const char *dateToLocaleDateStringFunction =
102 "(function(toLocaleDateStringFunc) { "
103 " var orig_toLocaleDateString;"
104 " orig_toLocaleDateString = Date.prototype.toLocaleDateString;"
105 " Date.prototype.toLocaleDateString = (function() {"
106 " var val = toLocaleDateStringFunc.apply(this, arguments);"
107 " if (val == undefined) val = orig_toLocaleDateString.call(this);"
113 static const char *dateFromLocaleStringFunction =
114 "(function(fromLocaleStringFunc) { "
115 " Date.fromLocaleString = (function() {"
116 " return fromLocaleStringFunc.apply(null, arguments);"
120 static const char *dateFromLocaleTimeStringFunction =
121 "(function(fromLocaleTimeStringFunc) { "
122 " Date.fromLocaleTimeString = (function() {"
123 " return fromLocaleTimeStringFunc.apply(null, arguments);"
127 static const char *dateFromLocaleDateStringFunction =
128 "(function(fromLocaleDateStringFunc) { "
129 " Date.fromLocaleDateString = (function() {"
130 " return fromLocaleDateStringFunc.apply(null, arguments);"
134 static const char *dateTimeZoneUpdatedFunction =
135 "(function(timeZoneUpdatedFunc) { "
136 " Date.timeZoneUpdated = (function() {"
137 " return timeZoneUpdatedFunc.apply(null, arguments);"
142 static void registerFunction(QV8Engine *engine, const char *script, v8::InvocationCallback func)
144 v8::Local<v8::Script> registerScript = v8::Script::New(v8::String::New(script), 0, 0, v8::Handle<v8::String>(), v8::Script::NativeMode);
145 v8::Local<v8::Value> result = registerScript->Run();
146 Q_ASSERT(result->IsFunction());
147 v8::Local<v8::Function> registerFunc = v8::Local<v8::Function>::Cast(result);
148 v8::Handle<v8::Value> args = V8FUNCTION(func, engine);
149 registerFunc->Call(v8::Local<v8::Object>::Cast(registerFunc), 1, &args);
152 void QQmlDateExtension::registerExtension(QV8Engine *engine)
154 registerFunction(engine, dateToLocaleStringFunction, toLocaleString);
155 registerFunction(engine, dateToLocaleTimeStringFunction, toLocaleTimeString);
156 registerFunction(engine, dateToLocaleDateStringFunction, toLocaleDateString);
157 registerFunction(engine, dateFromLocaleStringFunction, fromLocaleString);
158 registerFunction(engine, dateFromLocaleTimeStringFunction, fromLocaleTimeString);
159 registerFunction(engine, dateFromLocaleDateStringFunction, fromLocaleDateString);
160 registerFunction(engine, dateTimeZoneUpdatedFunction, timeZoneUpdated);
163 v8::Handle<v8::Value> QQmlDateExtension::toLocaleString(const v8::Arguments& args)
165 if (args.Length() > 2)
166 return v8::Undefined();
168 if (!args.This()->IsDate())
169 return v8::Undefined();
171 QDateTime dt = QV8Engine::qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(args.This())->NumberValue());
173 if (args.Length() == 0) {
174 // Use QLocale for standard toLocaleString() function
176 return QJSConverter::toString(locale.toString(dt));
179 if (!isLocaleObject(args[0]))
180 return v8::Undefined(); // Use the default Date toLocaleString()
182 GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
184 QLocale::FormatType enumFormat = QLocale::LongFormat;
186 if (args.Length() == 2) {
187 if (args[1]->IsString()) {
188 QString format = r->engine->toVariant(args[1], -1).toString();
189 formattedDt = r->locale.toString(dt, format);
190 } else if (args[1]->IsNumber()) {
191 quint32 intFormat = args[1]->ToNumber()->Value();
192 QLocale::FormatType format = QLocale::FormatType(intFormat);
193 formattedDt = r->locale.toString(dt, format);
195 V8THROW_ERROR("Locale: Date.toLocaleString(): Invalid datetime format");
198 formattedDt = r->locale.toString(dt, enumFormat);
201 return r->engine->toString(formattedDt);
204 v8::Handle<v8::Value> QQmlDateExtension::toLocaleTimeString(const v8::Arguments& args)
206 if (args.Length() > 2)
207 return v8::Undefined();
209 if (!args.This()->IsDate())
210 return v8::Undefined();
212 QDateTime dt = QV8Engine::qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(args.This())->NumberValue());
213 QTime time = dt.time();
215 if (args.Length() == 0) {
216 // Use QLocale for standard toLocaleString() function
218 return QJSConverter::toString(locale.toString(time));
221 if (!isLocaleObject(args[0]))
222 return v8::Undefined(); // Use the default Date toLocaleTimeString()
224 GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
226 QLocale::FormatType enumFormat = QLocale::LongFormat;
227 QString formattedTime;
228 if (args.Length() == 2) {
229 if (args[1]->IsString()) {
230 QString format = r->engine->toVariant(args[1], -1).toString();
231 formattedTime = r->locale.toString(time, format);
232 } else if (args[1]->IsNumber()) {
233 quint32 intFormat = args[1]->ToNumber()->Value();
234 QLocale::FormatType format = QLocale::FormatType(intFormat);
235 formattedTime = r->locale.toString(time, format);
237 V8THROW_ERROR("Locale: Date.toLocaleTimeString(): Invalid time format");
240 formattedTime = r->locale.toString(time, enumFormat);
243 return r->engine->toString(formattedTime);
246 v8::Handle<v8::Value> QQmlDateExtension::toLocaleDateString(const v8::Arguments& args)
248 if (args.Length() > 2)
249 return v8::Undefined();
251 if (!args.This()->IsDate())
252 return v8::Undefined();
254 QDateTime dt = QV8Engine::qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(args.This())->NumberValue());
255 QDate date = dt.date();
257 if (args.Length() == 0) {
258 // Use QLocale for standard toLocaleString() function
260 return QJSConverter::toString(locale.toString(date));
263 if (!isLocaleObject(args[0]))
264 return v8::Undefined(); // Use the default Date toLocaleDateString()
266 GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
268 QLocale::FormatType enumFormat = QLocale::LongFormat;
269 QString formattedDate;
270 if (args.Length() == 2) {
271 if (args[1]->IsString()) {
272 QString format = r->engine->toVariant(args[1], -1).toString();
273 formattedDate = r->locale.toString(date, format);
274 } else if (args[1]->IsNumber()) {
275 quint32 intFormat = args[1]->ToNumber()->Value();
276 QLocale::FormatType format = QLocale::FormatType(intFormat);
277 formattedDate = r->locale.toString(date, format);
279 V8THROW_ERROR("Locale: Date.loLocaleDateString(): Invalid date format");
282 formattedDate = r->locale.toString(date, enumFormat);
285 return r->engine->toString(formattedDate);
288 v8::Handle<v8::Value> QQmlDateExtension::fromLocaleString(const v8::Arguments& args)
290 if (args.Length() == 1 && args[0]->IsString()) {
292 QString dateString = QJSConverter::toString(args[0]->ToString());
293 QDateTime dt = locale.toDateTime(dateString);
294 return QJSConverter::toDateTime(dt);
297 if (args.Length() < 1 || args.Length() > 3 || !isLocaleObject(args[0]))
298 V8THROW_ERROR("Locale: Date.fromLocaleString(): Invalid arguments");
300 GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
302 QLocale::FormatType enumFormat = QLocale::LongFormat;
304 QString dateString = r->engine->toString(args[1]->ToString());
305 if (args.Length() == 3) {
306 if (args[2]->IsString()) {
307 QString format = r->engine->toString(args[2]->ToString());
308 dt = r->locale.toDateTime(dateString, format);
309 } else if (args[2]->IsNumber()) {
310 quint32 intFormat = args[2]->ToNumber()->Value();
311 QLocale::FormatType format = QLocale::FormatType(intFormat);
312 dt = r->locale.toDateTime(dateString, format);
314 V8THROW_ERROR("Locale: Date.fromLocaleString(): Invalid datetime format");
317 dt = r->locale.toDateTime(dateString, enumFormat);
320 return QJSConverter::toDateTime(dt);
323 v8::Handle<v8::Value> QQmlDateExtension::fromLocaleTimeString(const v8::Arguments& args)
325 if (args.Length() == 1 && args[0]->IsString()) {
327 QString timeString = QJSConverter::toString(args[0]->ToString());
328 QTime time = locale.toTime(timeString);
329 QDateTime dt = QDateTime::currentDateTime();
331 return QJSConverter::toDateTime(dt);
334 if (args.Length() < 1 || args.Length() > 3 || !isLocaleObject(args[0]))
335 V8THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid arguments");
337 GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
339 QLocale::FormatType enumFormat = QLocale::LongFormat;
341 QString dateString = r->engine->toString(args[1]->ToString());
342 if (args.Length() == 3) {
343 if (args[2]->IsString()) {
344 QString format = r->engine->toString(args[2]->ToString());
345 tm = r->locale.toTime(dateString, format);
346 } else if (args[2]->IsNumber()) {
347 quint32 intFormat = args[2]->ToNumber()->Value();
348 QLocale::FormatType format = QLocale::FormatType(intFormat);
349 tm = r->locale.toTime(dateString, format);
351 V8THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid datetime format");
354 tm = r->locale.toTime(dateString, enumFormat);
357 QDateTime dt = QDateTime::currentDateTime();
360 return QJSConverter::toDateTime(dt);
363 v8::Handle<v8::Value> QQmlDateExtension::fromLocaleDateString(const v8::Arguments& args)
365 if (args.Length() == 1 && args[0]->IsString()) {
367 QString dateString = QJSConverter::toString(args[0]->ToString());
368 QDate date = locale.toDate(dateString);
369 return QJSConverter::toDateTime(QDateTime(date));
372 if (args.Length() < 1 || args.Length() > 3 || !isLocaleObject(args[0]))
373 V8THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid arguments");
375 GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
377 QLocale::FormatType enumFormat = QLocale::LongFormat;
379 QString dateString = r->engine->toString(args[1]->ToString());
380 if (args.Length() == 3) {
381 if (args[2]->IsString()) {
382 QString format = r->engine->toString(args[2]->ToString());
383 dt = r->locale.toDate(dateString, format);
384 } else if (args[2]->IsNumber()) {
385 quint32 intFormat = args[2]->ToNumber()->Value();
386 QLocale::FormatType format = QLocale::FormatType(intFormat);
387 dt = r->locale.toDate(dateString, format);
389 V8THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid datetime format");
392 dt = r->locale.toDate(dateString, enumFormat);
395 return QJSConverter::toDateTime(QDateTime(dt));
398 v8::Handle<v8::Value> QQmlDateExtension::timeZoneUpdated(const v8::Arguments& args)
400 if (args.Length() != 0)
401 V8THROW_ERROR("Locale: Date.timeZoneUpdated(): Invalid arguments");
403 v8::Date::DateTimeConfigurationChangeNotification();
405 return v8::Undefined();
411 static const char *numberToLocaleStringFunction =
412 "(function(toLocaleStringFunc) { "
413 " var orig_toLocaleString;"
414 " orig_toLocaleString = Number.prototype.toLocaleString;"
415 " Number.prototype.toLocaleString = (function() {"
416 " var val = toLocaleStringFunc.apply(this, arguments);"
417 " if (val == undefined) val = orig_toLocaleString.call(this);"
422 static const char *numberToLocaleCurrencyStringFunction =
423 "(function(toLocaleCurrencyStringFunc) { "
424 " Number.prototype.toLocaleCurrencyString = (function() {"
425 " return toLocaleCurrencyStringFunc.apply(this, arguments);"
429 static const char *numberFromLocaleStringFunction =
430 "(function(fromLocaleStringFunc) { "
431 " Number.fromLocaleString = (function() {"
432 " return fromLocaleStringFunc.apply(null, arguments);"
437 void QQmlNumberExtension::registerExtension(QV8Engine *engine)
439 registerFunction(engine, numberToLocaleStringFunction, toLocaleString);
440 registerFunction(engine, numberToLocaleCurrencyStringFunction, toLocaleCurrencyString);
441 registerFunction(engine, numberFromLocaleStringFunction, fromLocaleString);
444 v8::Handle<v8::Value> QQmlNumberExtension::toLocaleString(const v8::Arguments& args)
446 if (args.Length() > 3)
447 V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
449 double number = args.This()->ToNumber()->Value();
451 if (args.Length() == 0) {
452 // Use QLocale for standard toLocaleString() function
454 return QJSConverter::toString(locale.toString(number));
457 if (!isLocaleObject(args[0]))
458 return v8::Undefined(); // Use the default Number toLocaleString()
460 GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
462 uint16_t format = 'f';
463 if (args.Length() > 1) {
464 if (!args[1]->IsString())
465 V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
466 v8::Local<v8::String> fs = args[1]->ToString();
467 if (!fs.IsEmpty() && fs->Length())
468 format = fs->GetCharacter(0);
471 if (args.Length() > 2) {
472 if (!args[2]->IsNumber())
473 V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
474 prec = args[2]->IntegerValue();
477 return r->engine->toString(r->locale.toString(number, (char)format, prec));
480 v8::Handle<v8::Value> QQmlNumberExtension::toLocaleCurrencyString(const v8::Arguments& args)
482 if (args.Length() > 2)
483 V8THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments");
485 double number = args.This()->ToNumber()->Value();
487 if (args.Length() == 0) {
488 // Use QLocale for standard toLocaleString() function
490 return QJSConverter::toString(locale.toString(number));
493 if (!isLocaleObject(args[0]))
494 V8THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments");
496 GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
499 if (args.Length() > 1) {
500 if (!args[1]->IsString())
501 V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
502 symbol = r->engine->toString(args[1]->ToString());
505 return r->engine->toString(r->locale.toCurrencyString(number, symbol));
508 v8::Handle<v8::Value> QQmlNumberExtension::fromLocaleString(const v8::Arguments& args)
510 if (args.Length() < 1 || args.Length() > 2)
511 V8THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments");
516 if (args.Length() == 2) {
517 if (!isLocaleObject(args[0]))
518 V8THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments");
520 GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
526 v8::Local<v8::String> ns = args[numberIdx]->ToString();
527 if (ns.IsEmpty() || ns->Length() == 0)
528 return v8::Number::New(Q_QNAN);
531 double val = locale.toDouble(QJSConverter::toString(ns), &ok);
534 V8THROW_ERROR("Locale: Number.fromLocaleString(): Invalid format")
536 return v8::Number::New(val);
542 static v8::Handle<v8::Value> locale_get_firstDayOfWeek(v8::Local<v8::String>, const v8::AccessorInfo &info)
544 GET_LOCALE_DATA_RESOURCE(info.This());
545 int fdow = int(r->locale.firstDayOfWeek());
547 fdow = 0; // Qt::Sunday = 7, but Sunday is 0 in JS Date
548 return v8::Integer::New(fdow);
551 static v8::Handle<v8::Value> locale_get_measurementSystem(v8::Local<v8::String>, const v8::AccessorInfo &info)
553 GET_LOCALE_DATA_RESOURCE(info.This());
554 return v8::Integer::New(r->locale.measurementSystem());
557 static v8::Handle<v8::Value> locale_get_textDirection(v8::Local<v8::String>, const v8::AccessorInfo &info)
559 GET_LOCALE_DATA_RESOURCE(info.This());
560 return v8::Integer::New(r->locale.textDirection());
563 static v8::Handle<v8::Value> locale_get_weekDays(v8::Local<v8::String>, const v8::AccessorInfo &info)
565 GET_LOCALE_DATA_RESOURCE(info.This());
567 QList<Qt::DayOfWeek> days = r->locale.weekdays();
569 v8::Handle<v8::Array> result = v8::Array::New(days.size());
570 for (int i = 0; i < days.size(); ++i) {
571 int day = days.at(i);
572 if (day == 7) // JS Date days in range 0(Sunday) to 6(Saturday)
574 result->Set(i, v8::Integer::New(day));
580 static v8::Handle<v8::Value> locale_get_uiLanguages(v8::Local<v8::String>, const v8::AccessorInfo &info)
582 GET_LOCALE_DATA_RESOURCE(info.This());
584 QStringList langs = r->locale.uiLanguages();
585 v8::Handle<v8::Array> result = v8::Array::New(langs.size());
586 for (int i = 0; i < langs.size(); ++i) {
587 result->Set(i, r->engine->toString(langs.at(i)));
593 static v8::Handle<v8::Value> locale_currencySymbol(const v8::Arguments &args)
595 GET_LOCALE_DATA_RESOURCE(args.This());
597 if (args.Length() > 1)
598 V8THROW_ERROR("Locale: currencySymbol(): Invalid arguments");
600 QLocale::CurrencySymbolFormat format = QLocale::CurrencySymbol;
601 if (args.Length() == 1) {
602 quint32 intFormat = args[0]->ToNumber()->Value();
603 format = QLocale::CurrencySymbolFormat(intFormat);
606 return r->engine->toString(r->locale.currencySymbol(format));
609 #define LOCALE_FORMAT(FUNC) \
610 static v8::Handle<v8::Value> locale_ ##FUNC (const v8::Arguments &args) { \
611 GET_LOCALE_DATA_RESOURCE(args.This());\
612 if (args.Length() > 1) \
613 V8THROW_ERROR("Locale: " #FUNC "(): Invalid arguments"); \
614 QLocale::FormatType format = QLocale::LongFormat;\
615 if (args.Length() == 1) { \
616 quint32 intFormat = args[0]->Uint32Value(); \
617 format = QLocale::FormatType(intFormat); \
619 return r->engine->toString(r->locale. FUNC (format)); \
622 LOCALE_FORMAT(dateTimeFormat)
623 LOCALE_FORMAT(timeFormat)
624 LOCALE_FORMAT(dateFormat)
626 // +1 added to idx because JS is 0-based, whereas QLocale months begin at 1.
627 #define LOCALE_FORMATTED_MONTHNAME(VARIABLE) \
628 static v8::Handle<v8::Value> locale_ ## VARIABLE (const v8::Arguments &args) {\
629 GET_LOCALE_DATA_RESOURCE(args.This()); \
630 if (args.Length() < 1 || args.Length() > 2) \
631 V8THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \
632 QLocale::FormatType enumFormat = QLocale::LongFormat; \
633 int idx = args[0]->IntegerValue() + 1; \
634 if (idx < 1 || idx > 12) \
635 V8THROW_ERROR("Locale: Invalid month"); \
637 if (args.Length() == 2) { \
638 if (args[1]->IsNumber()) { \
639 quint32 intFormat = args[1]->IntegerValue(); \
640 QLocale::FormatType format = QLocale::FormatType(intFormat); \
641 name = r->locale. VARIABLE(idx, format); \
643 V8THROW_ERROR("Locale: Invalid datetime format"); \
646 name = r->locale. VARIABLE(idx, enumFormat); \
648 return r->engine->toString(name); \
651 // 0 -> 7 as Qt::Sunday is 7, but Sunday is 0 in JS Date
652 #define LOCALE_FORMATTED_DAYNAME(VARIABLE) \
653 static v8::Handle<v8::Value> locale_ ## VARIABLE (const v8::Arguments &args) {\
654 GET_LOCALE_DATA_RESOURCE(args.This()); \
655 if (args.Length() < 1 || args.Length() > 2) \
656 V8THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \
657 QLocale::FormatType enumFormat = QLocale::LongFormat; \
658 int idx = args[0]->IntegerValue(); \
659 if (idx < 0 || idx > 7) \
660 V8THROW_ERROR("Locale: Invalid day"); \
661 if (idx == 0) idx = 7; \
663 if (args.Length() == 2) { \
664 if (args[1]->IsNumber()) { \
665 quint32 intFormat = args[1]->ToNumber()->Value(); \
666 QLocale::FormatType format = QLocale::FormatType(intFormat); \
667 name = r->locale. VARIABLE(idx, format); \
669 V8THROW_ERROR("Locale: Invalid datetime format"); \
672 name = r->locale. VARIABLE(idx, enumFormat); \
674 return r->engine->toString(name); \
678 #define LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(FT, VARIABLE, ENGINE) \
679 FT->PrototypeTemplate()->Set(v8::String::New( #VARIABLE ), V8FUNCTION(locale_ ## VARIABLE, ENGINE));
681 LOCALE_FORMATTED_MONTHNAME(monthName)
682 LOCALE_FORMATTED_MONTHNAME(standaloneMonthName)
683 LOCALE_FORMATTED_DAYNAME(dayName)
684 LOCALE_FORMATTED_DAYNAME(standaloneDayName)
686 #define LOCALE_STRING_PROPERTY(VARIABLE) static v8::Handle<v8::Value> locale_get_ ## VARIABLE (v8::Local<v8::String>, const v8::AccessorInfo &info) \
688 GET_LOCALE_DATA_RESOURCE(info.This()); \
689 return r->engine->toString(r->locale. VARIABLE());\
692 #define LOCALE_REGISTER_STRING_ACCESSOR(FT, VARIABLE) \
693 FT ->PrototypeTemplate()->SetAccessor( v8::String::New( #VARIABLE ), locale_get_ ## VARIABLE )
696 LOCALE_STRING_PROPERTY(name)
697 LOCALE_STRING_PROPERTY(nativeLanguageName)
698 LOCALE_STRING_PROPERTY(nativeCountryName)
699 LOCALE_STRING_PROPERTY(decimalPoint)
700 LOCALE_STRING_PROPERTY(groupSeparator)
701 LOCALE_STRING_PROPERTY(percent)
702 LOCALE_STRING_PROPERTY(zeroDigit)
703 LOCALE_STRING_PROPERTY(negativeSign)
704 LOCALE_STRING_PROPERTY(positiveSign)
705 LOCALE_STRING_PROPERTY(exponential)
706 LOCALE_STRING_PROPERTY(amText)
707 LOCALE_STRING_PROPERTY(pmText)
709 class QV8LocaleDataDeletable : public QV8Engine::Deletable
712 QV8LocaleDataDeletable(QV8Engine *engine);
713 ~QV8LocaleDataDeletable();
715 v8::Persistent<v8::Function> constructor;
718 QV8LocaleDataDeletable::QV8LocaleDataDeletable(QV8Engine *engine)
720 v8::HandleScope handle_scope;
721 v8::Context::Scope scope(engine->context());
723 v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
724 ft->InstanceTemplate()->SetHasExternalResource(true);
726 LOCALE_REGISTER_STRING_ACCESSOR(ft, name);
727 LOCALE_REGISTER_STRING_ACCESSOR(ft, nativeLanguageName);
728 LOCALE_REGISTER_STRING_ACCESSOR(ft, nativeCountryName);
729 LOCALE_REGISTER_STRING_ACCESSOR(ft, decimalPoint);
730 LOCALE_REGISTER_STRING_ACCESSOR(ft, groupSeparator);
731 LOCALE_REGISTER_STRING_ACCESSOR(ft, percent);
732 LOCALE_REGISTER_STRING_ACCESSOR(ft, zeroDigit);
733 LOCALE_REGISTER_STRING_ACCESSOR(ft, negativeSign);
734 LOCALE_REGISTER_STRING_ACCESSOR(ft, positiveSign);
735 LOCALE_REGISTER_STRING_ACCESSOR(ft, exponential);
736 LOCALE_REGISTER_STRING_ACCESSOR(ft, amText);
737 LOCALE_REGISTER_STRING_ACCESSOR(ft, pmText);
739 ft->PrototypeTemplate()->Set(v8::String::New("currencySymbol"), V8FUNCTION(locale_currencySymbol, engine));
741 ft->PrototypeTemplate()->Set(v8::String::New("dateTimeFormat"), V8FUNCTION(locale_dateTimeFormat, engine));
742 ft->PrototypeTemplate()->Set(v8::String::New("dateFormat"), V8FUNCTION(locale_dateFormat, engine));
743 ft->PrototypeTemplate()->Set(v8::String::New("timeFormat"), V8FUNCTION(locale_timeFormat, engine));
745 LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, monthName, engine);
746 LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, standaloneMonthName, engine);
747 LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, dayName, engine);
748 LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, standaloneDayName, engine);
750 ft->PrototypeTemplate()->SetAccessor(v8::String::New("firstDayOfWeek"), locale_get_firstDayOfWeek);
751 ft->PrototypeTemplate()->SetAccessor(v8::String::New("weekDays"), locale_get_weekDays);
752 ft->PrototypeTemplate()->SetAccessor(v8::String::New("measurementSystem"), locale_get_measurementSystem);
753 ft->PrototypeTemplate()->SetAccessor(v8::String::New("textDirection"), locale_get_textDirection);
754 ft->PrototypeTemplate()->SetAccessor(v8::String::New("uiLanguages"), locale_get_uiLanguages);
756 constructor = qPersistentNew(ft->GetFunction());
759 QV8LocaleDataDeletable::~QV8LocaleDataDeletable()
761 qPersistentDispose(constructor);
764 V8_DEFINE_EXTENSION(QV8LocaleDataDeletable, localeV8Data);
768 \instantiates QQmlLocale
769 \inqmlmodule QtQuick 2
770 \brief Provides locale specific properties and formatted data
772 The Locale object may only be created via the \l{QML:Qt::locale()}{Qt.locale()} function.
773 It cannot be created directly.
775 The \l{QML:Qt::locale()}{Qt.locale()} function returns a JS Locale object representing the
776 locale with the specified name, which has the format
777 "language[_territory][.codeset][@modifier]" or "C".
779 Locale supports the concept of a default locale, which is
780 determined from the system's locale settings at application
781 startup. If no parameter is passed to Qt.locale() the default
782 locale object is returned.
784 The Locale object provides a number of functions and properties
785 providing data for the specified locale.
787 The Locale object may also be passed to the \l Date and \l Number toLocaleString()
788 and fromLocaleString() methods in order to convert to/from strings using
789 the specified locale.
791 This example shows the current date formatted for the German locale:
797 text: "The date is: " + Date().toLocaleString(Qt.locale("de_DE"))
801 The following example displays the specified number
802 in the correct format for the default locale:
808 text: "The value is: " + Number(23443.34).toLocaleString(Qt.locale())
812 QtQuick Locale's data is based on Common Locale Data Repository v1.8.1.
816 \section2 Locale String Format Types
818 The monthName(), standaloneMonthName(), dayName() and standaloneDayName()
819 can use the following enumeration values to specify the formatting of
820 the string representation for a Date object.
823 \li Locale.LongFormat The long version of day and month names; for
824 example, returning "January" as a month name.
825 \li Locale.ShortFormat The short version of day and month names; for
826 example, returning "Jan" as a month name.
827 \li Locale.NarrowFormat A special version of day and month names for
828 use when space is limited; for example, returning "J" as a month
829 name. Note that the narrow format might contain the same text for
830 different months and days or it can even be an empty string if the
831 locale doesn't support narrow names, so you should avoid using it
832 for date formatting. Also, for the system locale this format is
833 the same as ShortFormat.
837 Additionally the double-to-string and string-to-double conversion functions are
838 covered by the following licenses:
841 Copyright (c) 1991 by AT&T.
843 Permission to use, copy, modify, and distribute this software for any
844 purpose without fee is hereby granted, provided that this entire notice
845 is included in all copies of any software which is or includes a copy
846 or modification of this software and in all copies of the supporting
847 documentation for such software.
849 THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
850 WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
851 REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
852 OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
854 This product includes software developed by the University of
855 California, Berkeley and its contributors.
857 \sa {QtQuick2::Date}{Date}, {QtQuick2::Number}{Number}
860 QQmlLocale::QQmlLocale()
864 QQmlLocale::~QQmlLocale()
868 v8::Handle<v8::Value> QQmlLocale::locale(QV8Engine *v8engine, const QString &locale)
870 QV8LocaleDataDeletable *d = localeV8Data(v8engine);
871 v8::Local<v8::Object> v8Value = d->constructor->NewInstance();
872 QV8LocaleDataResource *r = new QV8LocaleDataResource(v8engine);
873 if (locale.isEmpty())
874 r->locale = QLocale();
876 r->locale = QLocale(locale);
877 v8Value->SetExternalResource(r);
882 static const char *localeCompareFunction =
883 "(function(localeCompareFunc) { "
884 " var orig_localeCompare;"
885 " orig_localeCompare = String.prototype.localeCompare;"
886 " String.prototype.localeCompare = (function() {"
887 " var val = localeCompareFunc.apply(this, arguments);"
888 " if (val == undefined) val = orig_localeCompare.call(this);"
893 void QQmlLocale::registerStringLocaleCompare(QV8Engine *engine)
895 registerFunction(engine, localeCompareFunction, localeCompare);
898 v8::Handle<v8::Value> QQmlLocale::localeCompare(const v8::Arguments &args)
900 if (args.Length() != 1 || (!args[0]->IsString() && !args[0]->IsStringObject()))
901 return v8::Undefined();
903 if (!args.This()->IsString() && !args.This()->IsStringObject())
904 return v8::Undefined();
906 QString thisString = QJSConverter::toString(args.This()->ToString());
907 QString thatString = QJSConverter::toString(args[0]->ToString());
909 return v8::Integer::New(QString::localeAwareCompare(thisString, thatString));
913 \qmlproperty string QtQuick2::Locale::name
915 Holds the language and country of this locale as a
916 string of the form "language_country", where
917 language is a lowercase, two-letter ISO 639 language code,
918 and country is an uppercase, two- or three-letter ISO 3166 country code.
922 \qmlproperty string QtQuick2::Locale::decimalPoint
924 Holds the decimal point character of this locale.
928 \qmlproperty string QtQuick2::Locale::groupSeparator
930 Holds the group separator character of this locale.
934 \qmlproperty string QtQuick2::Locale::percent
936 Holds the percent character of this locale.
941 \qmlproperty string QtQuick2::Locale::zeroDigit
943 Holds Returns the zero digit character of this locale.
947 \qmlproperty string QtQuick2::Locale::negativeSign
949 Holds the negative sign character of this locale.
953 \qmlproperty string QtQuick2::Locale::positiveSign
955 Holds the positive sign character of this locale.
959 \qmlproperty string QtQuick2::Locale::exponential
961 Holds the exponential character of this locale.
965 \qmlmethod string QtQuick2::Locale::dateTimeFormat(type)
967 Returns the date time format used for the current locale.
968 \a type specifies the FormatType to return.
970 \sa {QtQuick2::Date}{Date}
974 \qmlmethod string QtQuick2::Locale::dateFormat(type)
976 Returns the date format used for the current locale.
977 \a type specifies the FormatType to return.
979 \sa {QtQuick2::Date}{Date}
983 \qmlmethod string QtQuick2::Locale::timeFormat(type)
985 Returns the time format used for the current locale.
986 \a type specifies the FormatType to return.
988 \sa {QtQuick2::Date}{Date}
992 \qmlmethod string QtQuick2::Locale::monthName(month, type)
994 Returns the localized name of \a month (0-11), in the optional
995 \l FormatType specified by \a type.
997 \note the QLocale C++ API expects a range of (1-12), however Locale.monthName()
998 expects 0-11 as per the JS Date object.
1000 \sa dayName(), standaloneMonthName()
1004 \qmlmethod string QtQuick2::Locale::standaloneMonthName(month, type)
1006 Returns the localized name of \a month (0-11) that is used as a
1007 standalone text, in the optional \l FormatType specified by \a type.
1009 If the locale information doesn't specify the standalone month
1010 name then return value is the same as in monthName().
1012 \note the QLocale C++ API expects a range of (1-12), however Locale.standaloneMonthName()
1013 expects 0-11 as per the JS Date object.
1015 \sa monthName(), standaloneDayName()
1019 \qmlmethod string QtQuick2::Locale::dayName(day, type)
1021 Returns the localized name of the \a day (where 0 represents
1022 Sunday, 1 represents Monday and so on), in the optional
1023 \l FormatType specified by \a type.
1025 \sa monthName(), standaloneDayName()
1029 \qmlmethod string QtQuick2::Locale::standaloneDayName(day, type)
1031 Returns the localized name of the \a day (where 0 represents
1032 Sunday, 1 represents Monday and so on) that is used as a
1033 standalone text, in the \l FormatType specified by \a type.
1035 If the locale information does not specify the standalone day
1036 name then return value is the same as in dayName().
1038 \sa dayName(), standaloneMonthName()
1042 \qmlproperty enumeration QtQuick2::Locale::firstDayOfWeek
1044 Holds the first day of the week according to the current locale.
1047 \li Locale.Sunday = 0
1048 \li Locale.Monday = 1
1049 \li Locale.Tuesday = 2
1050 \li Locale.Wednesday = 3
1051 \li Locale.Thursday = 4
1052 \li Locale.Friday = 5
1053 \li Locale.Saturday = 6
1056 \note that these values match the JS Date API which is different
1057 from the Qt C++ API where Qt::Sunday = 7.
1061 \qmlproperty Array<int> QtQuick2::Locale::weekDays
1063 Holds an array of days that are considered week days according to the current locale,
1064 where Sunday is 0 and Saturday is 6.
1070 \qmlproperty Array<string> QtQuick2::Locale::uiLanguages
1072 Returns an ordered list of locale names for translation purposes in
1075 The return value represents locale names that the user expects to see the
1078 The first item in the list is the most preferred one.
1082 \qmlproperty enumeration QtQuick2::Locale::textDirection
1084 Holds the text direction of the language:
1092 \qmlproperty string QtQuick2::Locale::amText
1094 The localized name of the "AM" suffix for times specified using the conventions of the 12-hour clock.
1098 \qmlproperty string QtQuick2::Locale::pmText
1100 The localized name of the "PM" suffix for times specified using the conventions of the 12-hour clock.
1104 \qmlmethod string QtQuick2::Locale::currencySymbol(format)
1106 Returns the currency symbol for the specified \a format:
1108 \li Locale.CurrencyIsoCode a ISO-4217 code of the currency.
1109 \li Locale.CurrencySymbol a currency symbol.
1110 \li Locale.CurrencyDisplayName a user readable name of the currency.
1112 \sa Number::toLocaleCurrencyString()
1116 \qmlproperty string QtQuick2::Locale::nativeLanguageName
1118 Holds a native name of the language for the locale. For example
1119 "Schwiizertüütsch" for Swiss-German locale.
1121 \sa nativeCountryName
1125 \qmlproperty string QtQuick2::Locale::nativeCountryName
1127 Holds a native name of the country for the locale. For example
1128 "España" for Spanish/Spain locale.
1130 \sa nativeLanguageName
1134 \qmlproperty enumeration QtQuick2::Locale::measurementSystem
1136 This property defines which units are used for measurement.
1139 \li Locale.MetricSystem This value indicates metric units, such as meters,
1140 centimeters and millimeters.
1141 \li Locale.ImperialSystem This value indicates imperial units, such as inches and
1142 miles. There are several distinct imperial systems in the world; this
1143 value stands for the official United States imperial units.