diff --git a/dev/tools/gen_date_localizations.dart b/dev/tools/gen_date_localizations.dart index d60fb5c0ef..8c0023e855 100644 --- a/dev/tools/gen_date_localizations.dart +++ b/dev/tools/gen_date_localizations.dart @@ -43,7 +43,7 @@ Future main(List rawArgs) async { ); } - final File dotPackagesFile = new File(path.join('packages', 'flutter', '.packages')); + final File dotPackagesFile = new File(path.join('packages', 'flutter_localizations', '.packages')); final bool dotPackagesExists = dotPackagesFile.existsSync(); if (!dotPackagesExists) { diff --git a/packages/flutter/lib/src/material/date_picker.dart b/packages/flutter/lib/src/material/date_picker.dart index dff94601e1..7ef040a602 100644 --- a/packages/flutter/lib/src/material/date_picker.dart +++ b/packages/flutter/lib/src/material/date_picker.dart @@ -409,7 +409,7 @@ class DayPicker extends StatelessWidget { Widget dayWidget = new Container( decoration: decoration, child: new Center( - child: new Text(day.toString(), style: itemStyle), + child: new Text(localizations.formatDecimal(day), style: itemStyle), ), ); diff --git a/packages/flutter/lib/src/material/material_localizations.dart b/packages/flutter/lib/src/material/material_localizations.dart index 9b429c2caa..a27674566b 100644 --- a/packages/flutter/lib/src/material/material_localizations.dart +++ b/packages/flutter/lib/src/material/material_localizations.dart @@ -114,6 +114,10 @@ abstract class MaterialLocalizations { /// See also: https://material.io/guidelines/style/typography.html TextTheme get localTextGeometry; + /// Formats [number] as a decimal, inserting locale-appropriate thousands + /// separators as necessary. + String formatDecimal(int number); + /// Formats [TimeOfDay.hour] in the given time of day according to the value /// of [timeOfDayFormat]. String formatHour(TimeOfDay timeOfDay); @@ -314,7 +318,7 @@ class DefaultMaterialLocalizations implements MaterialLocalizations { return null; } - /// Formats an integer, inserting thousands separators as needed. + @override String formatDecimal(int number) { if (number > -1000 && number < 1000) return number.toString(); diff --git a/packages/flutter_localizations/flutter_localizations.iml b/packages/flutter_localizations/flutter_localizations.iml index c2273989ce..5a5ced28c2 100644 --- a/packages/flutter_localizations/flutter_localizations.iml +++ b/packages/flutter_localizations/flutter_localizations.iml @@ -8,5 +8,7 @@ + + \ No newline at end of file diff --git a/packages/flutter_localizations/lib/src/l10n/date_localizations.dart b/packages/flutter_localizations/lib/src/l10n/date_localizations.dart index cc57d6bc83..e278edd638 100644 --- a/packages/flutter_localizations/lib/src/l10n/date_localizations.dart +++ b/packages/flutter_localizations/lib/src/l10n/date_localizations.dart @@ -184,6 +184,7 @@ const Map dateSymbols = const { r'''{1} {0}''', r'''{1} {0}''' ], + 'ZERODIGIT': r'''٠''', }, 'de': const { 'NAME': r'''de''', @@ -899,6 +900,7 @@ const Map dateSymbols = const { r'''{1}،‏ {0}''', r'''{1}،‏ {0}''' ], + 'ZERODIGIT': r'''۰''', }, 'fr': const { 'NAME': r'''fr''', @@ -1615,6 +1617,188 @@ const Map dateSymbols = const { r'''{1} {0}''' ], }, + 'ps': const { + 'NAME': r'''ps''', + 'ERAS': const [r'''له میلاد وړاندې''', r'''م.'''], + 'ERANAMES': const [ + r'''له میلاد څخه وړاندې''', + r'''له میلاد څخه وروسته''' + ], + 'NARROWMONTHS': const [ + r'''1''', + r'''2''', + r'''3''', + r'''4''', + r'''5''', + r'''6''', + r'''7''', + r'''8''', + r'''9''', + r'''10''', + r'''11''', + r'''12''' + ], + 'STANDALONENARROWMONTHS': const [ + r'''1''', + r'''2''', + r'''3''', + r'''4''', + r'''5''', + r'''6''', + r'''7''', + r'''8''', + r'''9''', + r'''10''', + r'''11''', + r'''12''' + ], + 'MONTHS': const [ + r'''جنوري''', + r'''فبروري''', + r'''مارچ''', + r'''اپریل''', + r'''مۍ''', + r'''جون''', + r'''جولای''', + r'''اګست''', + r'''سپتمبر''', + r'''اکتوبر''', + r'''نومبر''', + r'''دسمبر''' + ], + 'STANDALONEMONTHS': const [ + r'''جنوري''', + r'''فبروري''', + r'''مارچ''', + r'''اپریل''', + r'''مۍ''', + r'''جون''', + r'''جولای''', + r'''اګست''', + r'''سپتمبر''', + r'''اکتوبر''', + r'''نومبر''', + r'''دسمبر''' + ], + 'SHORTMONTHS': const [ + r'''جنوري''', + r'''فبروري''', + r'''مارچ''', + r'''اپریل''', + r'''مۍ''', + r'''جون''', + r'''جولای''', + r'''اګست''', + r'''سپتمبر''', + r'''اکتوبر''', + r'''نومبر''', + r'''دسمبر''' + ], + 'STANDALONESHORTMONTHS': const [ + r'''جنوري''', + r'''فبروري''', + r'''مارچ''', + r'''اپریل''', + r'''مۍ''', + r'''جون''', + r'''جولای''', + r'''اګست''', + r'''سپتمبر''', + r'''اکتوبر''', + r'''نومبر''', + r'''دسمبر''' + ], + 'WEEKDAYS': const [ + r'''یکشنبه''', + r'''دوشنبه''', + r'''سه‌شنبه''', + r'''چهارشنبه''', + r'''پنجشنبه''', + r'''جمعه''', + r'''شنبه''' + ], + 'STANDALONEWEEKDAYS': const [ + r'''یکشنبه''', + r'''دوشنبه''', + r'''سه‌شنبه''', + r'''چهارشنبه''', + r'''پنجشنبه''', + r'''جمعه''', + r'''شنبه''' + ], + 'SHORTWEEKDAYS': const [ + r'''یکشنبه''', + r'''دوشنبه''', + r'''سه‌شنبه''', + r'''چهارشنبه''', + r'''پنجشنبه''', + r'''جمعه''', + r'''شنبه''' + ], + 'STANDALONESHORTWEEKDAYS': const [ + r'''یکشنبه''', + r'''دوشنبه''', + r'''سه‌شنبه''', + r'''چهارشنبه''', + r'''پنجشنبه''', + r'''جمعه''', + r'''شنبه''' + ], + 'NARROWWEEKDAYS': const [ + r'''S''', + r'''M''', + r'''T''', + r'''W''', + r'''T''', + r'''F''', + r'''S''' + ], + 'STANDALONENARROWWEEKDAYS': const [ + r'''S''', + r'''M''', + r'''T''', + r'''W''', + r'''T''', + r'''F''', + r'''S''' + ], + 'SHORTQUARTERS': const [ + r'''لومړۍ ربعه''', + r'''۲مه ربعه''', + r'''۳مه ربعه''', + r'''۴مه ربعه''' + ], + 'QUARTERS': const [ + r'''لومړۍ ربعه''', + r'''۲مه ربعه''', + r'''۳مه ربعه''', + r'''۴مه ربعه''' + ], + 'AMPMS': const [r'''غ.م.''', r'''غ.و.'''], + 'DATEFORMATS': const [ + r'''EEEE د y د MMMM d''', + r'''د y د MMMM d''', + r'''y MMM d''', + r'''y/M/d''' + ], + 'TIMEFORMATS': const [ + r'''H:mm:ss (zzzz)''', + r'''H:mm:ss (z)''', + r'''H:mm:ss''', + r'''H:mm''' + ], + 'AVAILABLEFORMATS': null, + 'FIRSTDAYOFWEEK': 5, + 'WEEKENDRANGE': const [3, 4], + 'FIRSTWEEKCUTOFFDAY': 4, + 'DATETIMEFORMATS': const [ + r'''{1} {0}''', + r'''{1} {0}''', + r'''{1} {0}''', + r'''{1} {0}''' + ], + 'ZERODIGIT': r'''۰''', + }, 'pt': const { 'NAME': r'''pt''', 'ERAS': const [r'''a.C.''', r'''d.C.'''], @@ -2749,6 +2933,52 @@ const Map datePatterns = const { 'zzzz': r'''zzzz''', 'ZZZZ': r'''ZZZZ''', }, + 'ps': const { + 'd': r'''d''', + 'E': r'''ccc''', + 'EEEE': r'''cccc''', + 'LLL': r'''LLL''', + 'LLLL': r'''LLLL''', + 'M': r'''L''', + 'Md': r'''M/d''', + 'MEd': r'''MM-dd, EEE''', + 'MMM': r'''LLL''', + 'MMMd': r'''MMM d''', + 'MMMEd': r'''MMM d, EEE''', + 'MMMM': r'''LLLL''', + 'MMMMd': r'''d MMMM''', + 'MMMMEEEEd': r'''MMMM d, EEEE''', + 'QQQ': r'''QQQ''', + 'QQQQ': r'''QQQQ''', + 'y': r'''y''', + 'yM': r'''y/M''', + 'yMd': r'''y-MM-dd''', + 'yMEd': r'''y-MM-dd, EEE''', + 'yMMM': r'''y MMM''', + 'yMMMd': r'''y MMM d''', + 'yMMMEd': r'''y MMM d, EEE''', + 'yMMMM': r'''د y د MMMM''', + 'yMMMMd': r'''د y د MMMM d''', + 'yMMMMEEEEd': r'''EEEE د y د MMMM d''', + 'yQQQ': r'''y QQQ''', + 'yQQQQ': r'''y QQQQ''', + 'H': r'''H''', + 'Hm': r'''H:mm''', + 'Hms': r'''H:mm:ss''', + 'j': r'''H''', + 'jm': r'''H:mm''', + 'jms': r'''H:mm:ss''', + 'jmv': r'''HH:mm v''', + 'jmz': r'''HH:mm z''', + 'jz': r'''H (z)''', + 'm': r'''m''', + 'ms': r'''mm:ss''', + 's': r'''s''', + 'v': r'''v''', + 'z': r'''z''', + 'zzzz': r'''zzzz''', + 'ZZZZ': r'''ZZZZ''', + }, 'pt': const { 'd': r'''d''', 'E': r'''ccc''', @@ -2841,6 +3071,52 @@ const Map datePatterns = const { 'zzzz': r'''zzzz''', 'ZZZZ': r'''ZZZZ''', }, + 'sd': const { + 'd': r'''d''', + 'E': r'''ccc''', + 'EEEE': r'''cccc''', + 'LLL': r'''LLL''', + 'LLLL': r'''LLLL''', + 'M': r'''L''', + 'Md': r'''M/d''', + 'MEd': r'''EEE, M/d''', + 'MMM': r'''LLL''', + 'MMMd': r'''MMM d''', + 'MMMEd': r'''EEE, MMM d''', + 'MMMM': r'''LLLL''', + 'MMMMd': r'''MMMM d''', + 'MMMMEEEEd': r'''EEEE, MMMM d''', + 'QQQ': r'''QQQ''', + 'QQQQ': r'''QQQQ''', + 'y': r'''y''', + 'yM': r'''M/y''', + 'yMd': r'''M/d/y''', + 'yMEd': r'''EEE, M/d/y''', + 'yMMM': r'''MMM y''', + 'yMMMd': r'''MMM d, y''', + 'yMMMEd': r'''EEE, MMM d, y''', + 'yMMMM': r'''MMMM y''', + 'yMMMMd': r'''MMMM d, y''', + 'yMMMMEEEEd': r'''EEEE, MMMM d, y''', + 'yQQQ': r'''QQQ y''', + 'yQQQQ': r'''QQQQ y''', + 'H': r'''HH''', + 'Hm': r'''HH:mm''', + 'Hms': r'''HH:mm:ss''', + 'j': r'''h a''', + 'jm': r'''h:mm a''', + 'jms': r'''h:mm:ss a''', + 'jmv': r'''h:mm a v''', + 'jmz': r'''h:mm a z''', + 'jz': r'''h a z''', + 'm': r'''m''', + 'ms': r'''mm:ss''', + 's': r'''s''', + 'v': r'''v''', + 'z': r'''z''', + 'zzzz': r'''zzzz''', + 'ZZZZ': r'''ZZZZ''', + }, 'ur': const { 'd': r'''d''', 'E': r'''ccc''', @@ -2865,7 +3141,7 @@ const Map datePatterns = const { 'yMMM': r'''MMM y''', 'yMMMd': r'''d MMM، y''', 'yMMMEd': r'''EEE، d MMM، y''', - 'yMMMM': r'''y MMMM''', + 'yMMMM': r'''MMMM y''', 'yMMMMd': r'''d MMMM، y''', 'yMMMMEEEEd': r'''EEEE، d MMMM، y''', 'yQQQ': r'''QQQ y''', diff --git a/packages/flutter_localizations/lib/src/material_localizations.dart b/packages/flutter_localizations/lib/src/material_localizations.dart index c2ec9cf348..6540440251 100644 --- a/packages/flutter_localizations/lib/src/material_localizations.dart +++ b/packages/flutter_localizations/lib/src/material_localizations.dart @@ -8,9 +8,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart' as intl; import 'package:intl/date_symbols.dart' as intl; -// TODO(yjbanov): remove internal import when https://github.com/dart-lang/intl/issues/145 is fixed. -// ignore: implementation_imports -import 'package:intl/src/date_format_internal.dart' as date_format_internal; +import 'package:intl/date_symbol_data_custom.dart' as date_symbol_data_custom; import 'l10n/date_localizations.dart' as date_localizations; import 'l10n/localizations.dart'; @@ -184,9 +182,7 @@ class GlobalMaterialLocalizations implements MaterialLocalizations { @override int get firstDayOfWeekIndex => (_fullYearFormat.dateSymbols.FIRSTDAYOFWEEK + 1) % 7; - /// Formats a [number] using local decimal number format. - /// - /// Inserts locale-appropriate thousands separator, if necessary. + @override String formatDecimal(int number) { return _decimalFormat.format(number); } @@ -416,13 +412,14 @@ bool _dateIntlDataInitialized = false; /// data. Subsequent invocations have no effect. void _loadDateIntlDataIfNotLoaded() { if (!_dateIntlDataInitialized) { - date_format_internal.initializeDatePatterns(() => date_localizations.datePatterns); - date_format_internal.initializeDateSymbols(() { - final Map symbols = {}; - date_localizations.dateSymbols.forEach((String locale, dynamic data) { - symbols[locale] = new intl.DateSymbols.deserializeFromMap(data); - }); - return symbols; + date_localizations.dateSymbols.forEach((String locale, dynamic data) { + assert(date_localizations.datePatterns.containsKey(locale)); + final intl.DateSymbols symbols = new intl.DateSymbols.deserializeFromMap(data); + date_symbol_data_custom.initializeDateFormattingCustom( + locale: locale, + symbols: symbols, + patterns: date_localizations.datePatterns[locale], + ); }); _dateIntlDataInitialized = true; } diff --git a/packages/flutter_localizations/test/date_picker_test.dart b/packages/flutter_localizations/test/date_picker_test.dart index 88f8ddff8d..dfb16a4537 100644 --- a/packages/flutter_localizations/test/date_picker_test.dart +++ b/packages/flutter_localizations/test/date_picker_test.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:intl/intl.dart' as intl; + import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -18,6 +20,7 @@ void main() { }); group(DayPicker, () { + final intl.NumberFormat arabicNumbers = new intl.NumberFormat('0', 'ar'); final Map> testLocales = >{ // Tests the default. const Locale('en', 'US'): { @@ -34,14 +37,11 @@ void main() { 'expectedMonthYearHeader': 'сентябрь 2017 г.', }, // Tests RTL. - // TODO: change to Arabic numerals when these are fixed: - // TODO: https://github.com/dart-lang/intl/issues/143 - // TODO: https://github.com/flutter/flutter/issues/12289 const Locale('ar', 'AR'): { 'textDirection': TextDirection.rtl, 'expectedDaysOfWeek': ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'], - 'expectedDaysOfMonth': new List.generate(30, (int i) => '${i + 1}'), - 'expectedMonthYearHeader': 'سبتمبر 2017', + 'expectedDaysOfMonth': new List.generate(30, (int i) => '${arabicNumbers.format(i + 1)}'), + 'expectedMonthYearHeader': 'سبتمبر ٢٠١٧', }, };