material_localizations.dart 22.6 KB
Newer Older
1 2 3 4
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'dart:async';
6

7 8
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
9

10
import 'reorderable_list.dart';
11
import 'text_theme.dart';
12
import 'time.dart';
13
import 'typography.dart';
14

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
// ADDING A NEW STRING
//
// If you (someone contributing to the Flutter framework) want to add a new
// string to the MaterialLocalizations object (e.g. because you've added a new
// widget and it has a tooltip), follow these steps:
//
// 1. Add the new getter to MaterialLocalizations below.
//
// 2. Implement a default value in DefaultMaterialLocalizations below.
//
// 3. Add a test to test/material/localizations_test.dart that verifies that
//    this new value is implemented.
//
// 4. Update the flutter_localizations package. To add a new string to the
//    flutter_localizations package, you must first add it to the English
//    translations (lib/src/l10n/material_en.arb), including a description, then
//    you must add it to every other language (all the other *.arb files in that
32 33
//    same directory), listing the translation as `TBD`. After that you have to
//    re-generate lib/src/l10n/localizations.dart by running
34 35
//    `dart dev/tools/gen_localizations.dart --overwrite`. There is a README
//    file with further information in the lib/src/l10n/ directory.
36 37 38
//
// 5. If you are a Google employee, you should then also follow the instructions
//    at go/flutter-l10n. If you're not, don't worry about it.
39 40 41
//
// 6. If you're adding a String for the sake of Flutter, not for an app-specific
//    version of this interface, you are making a breaking API change. See
42
//    https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes.
43

Yegor's avatar
Yegor committed
44
/// Defines the localized resource values used by the Material widgets.
45 46 47
///
/// See also:
///
48 49 50 51
///  * [DefaultMaterialLocalizations], the default, English-only, implementation
///    of this interface.
///  * [GlobalMaterialLocalizations], which provides material localizations for
///    many languages.
52
abstract class MaterialLocalizations {
53
  /// The tooltip for the leading [AppBar] menu (a.k.a. 'hamburger') button.
54
  String get openAppDrawerTooltip;
55 56

  /// The [BackButton]'s tooltip.
57
  String get backButtonTooltip;
58 59

  /// The [CloseButton]'s tooltip.
60
  String get closeButtonTooltip;
61

62 63 64
  /// The tooltip for the delete button on a [Chip].
  String get deleteButtonTooltip;

65
  /// The tooltip for the [MonthPicker]'s "next month" button.
66
  String get nextMonthTooltip;
67 68

  /// The tooltip for the [MonthPicker]'s "previous month" button.
69
  String get previousMonthTooltip;
70

71
  /// The tooltip for the [PaginatedDataTable]'s "next page" button.
72 73
  String get nextPageTooltip;

74
  /// The tooltip for the [PaginatedDataTable]'s "previous page" button.
75 76 77 78 79
  String get previousPageTooltip;

  /// The default [PopupMenuButton] tooltip.
  String get showMenuTooltip;

Hans Muller's avatar
Hans Muller committed
80 81 82
  /// The default title for [AboutListTile].
  String aboutListTileTitle(String applicationName);

83 84 85
  /// Title for the [LicensePage] widget.
  String get licensesPageTitle;

86 87 88 89 90 91
  /// Title for the [PaginatedDataTable]'s row info footer.
  String pageRowsInfoTitle(int firstRow, int lastRow, int rowCount, bool rowCountIsApproximate);

  /// Title for the [PaginatedDataTable]'s "rows per page" footer.
  String get rowsPerPageTitle;

92 93 94 95 96 97
  /// The accessibility label used on a tab in a [TabBar].
  ///
  /// This message describes the index of the selected tab and how many tabs
  /// there are, e.g. 'Tab 1 of 2' in United States English.
  ///
  /// `tabIndex` and `tabCount` must be greater than or equal to one.
98
  String tabLabel({ int tabIndex, int tabCount });
99

100
  /// Title for the [PaginatedDataTable]'s selected row count header.
101 102
  String selectedRowCountTitle(int selectedRowCount);

103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
  /// Label for "cancel" buttons and menu items.
  String get cancelButtonLabel;

  /// Label for "close" buttons and menu items.
  String get closeButtonLabel;

  /// Label for "continue" buttons and menu items.
  String get continueButtonLabel;

  /// Label for "copy" edit buttons and menu items.
  String get copyButtonLabel;

  /// Label for "cut" edit buttons and menu items.
  String get cutButtonLabel;

  /// Label for OK buttons and menu items.
  String get okButtonLabel;

  /// Label for "paste" edit buttons and menu items.
  String get pasteButtonLabel;

  /// Label for "select all" edit buttons and menu items.
  String get selectAllButtonLabel;

127
  /// Label for the [AboutDialog] button that shows the [LicensePage].
128 129
  String get viewLicensesButtonLabel;

Yegor's avatar
Yegor committed
130 131 132 133 134 135
  /// The abbreviation for ante meridiem (before noon) shown in the time picker.
  String get anteMeridiemAbbreviation;

  /// The abbreviation for post meridiem (after noon) shown in the time picker.
  String get postMeridiemAbbreviation;

136 137 138 139 140 141 142 143
  /// The text-to-speech announcement made when a time picker invoked using
  /// [showTimePicker] is set to the hour picker mode.
  String get timePickerHourModeAnnouncement;

  /// The text-to-speech announcement made when a time picker invoked using
  /// [showTimePicker] is set to the minute picker mode.
  String get timePickerMinuteModeAnnouncement;

Josh Soref's avatar
Josh Soref committed
144
  /// Label read out by accessibility tools (TalkBack or VoiceOver) for a modal
145 146
  /// barrier to indicate that a tap dismisses the barrier.
  ///
147
  /// A modal barrier can for example be found behind an alert or popup to block
148 149 150
  /// user interaction with elements behind it.
  String get modalBarrierDismissLabel;

151
  /// Label read out by accessibility tools (TalkBack or VoiceOver) when a
152 153
  /// drawer widget is opened.
  String get drawerLabel;
154 155

  /// Label read out by accessibility tools (TalkBack or VoiceOver) when a
156 157 158
  /// popup menu widget is opened.
  String get popupMenuLabel;

159
  /// Label read out by accessibility tools (TalkBack or VoiceOver) when a
160 161 162
  /// dialog widget is opened.
  String get dialogLabel;

163
  /// Label read out by accessibility tools (TalkBack or VoiceOver) when an
164 165 166
  /// alert dialog widget is opened.
  String get alertDialogLabel;

167 168 169 170
  /// Label indicating that a text field is a search field. This will be used
  /// as a hint text in the text field.
  String get searchFieldLabel;

Yegor's avatar
Yegor committed
171 172 173 174
  /// The format used to lay out the time picker.
  ///
  /// The documentation for [TimeOfDayFormat] enum values provides details on
  /// each supported layout.
175
  TimeOfDayFormat timeOfDayFormat({ bool alwaysUse24HourFormat = false });
Yegor's avatar
Yegor committed
176

177
  /// Defines the localized [TextStyle] geometry for [ThemeData.textTheme].
178
  ///
179 180 181
  /// The [scriptCategory] defines the overall geometry of a [TextTheme] for
  /// the static [MaterialTextGeometry.localizedFor] method in terms of the
  /// three language categories defined in https://material.io/go/design-typography.
182
  ///
183 184 185 186 187
  /// Generally speaking, font sizes for [ScriptCategory.tall] and
  /// [ScriptCategory.dense] scripts - for text styles that are smaller than the
  /// title style - are one unit larger than they are for
  /// [ScriptCategory.englishLike] scripts.
  ScriptCategory get scriptCategory;
188

189 190 191 192
  /// Formats [number] as a decimal, inserting locale-appropriate thousands
  /// separators as necessary.
  String formatDecimal(int number);

193 194
  /// Formats [TimeOfDay.hour] in the given time of day according to the value
  /// of [timeOfDayFormat].
195 196 197
  ///
  /// If [alwaysUse24HourFormat] is true, formats hour using [HourFormat.HH]
  /// rather than the default for the current locale.
198
  String formatHour(TimeOfDay timeOfDay, { bool alwaysUse24HourFormat = false });
199 200 201 202 203 204

  /// Formats [TimeOfDay.minute] in the given time of day according to the value
  /// of [timeOfDayFormat].
  String formatMinute(TimeOfDay timeOfDay);

  /// Formats [timeOfDay] according to the value of [timeOfDayFormat].
205 206 207 208 209
  ///
  /// If [alwaysUse24HourFormat] is true, formats hour using [HourFormat.HH]
  /// rather than the default for the current locale. This value is usually
  /// passed from [MediaQueryData.alwaysUse24HourFormat], which has platform-
  /// specific behavior.
210
  String formatTimeOfDay(TimeOfDay timeOfDay, { bool alwaysUse24HourFormat = false });
211

Yegor's avatar
Yegor committed
212 213 214 215 216 217 218 219 220 221 222 223 224 225
  /// Full unabbreviated year format, e.g. 2017 rather than 17.
  String formatYear(DateTime date);

  /// Formats the date using a medium-width format.
  ///
  /// Abbreviates month and days of week. This appears in the header of the date
  /// picker invoked using [showDatePicker].
  ///
  /// Examples:
  ///
  /// - US English: Wed, Sep 27
  /// - Russian: ср, сент. 27
  String formatMediumDate(DateTime date);

226 227 228 229 230 231 232 233 234 235 236
  /// Formats day of week, month, day of month and year in a long-width format.
  ///
  /// Does not abbreviate names. Appears in spoken announcements of the date
  /// picker invoked using [showDatePicker], when accessibility mode is on.
  ///
  /// Examples:
  ///
  /// - US English: Wednesday, September 27, 2017
  /// - Russian: Среда, Сентябрь 27, 2017
  String formatFullDate(DateTime date);

Yegor's avatar
Yegor committed
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
  /// Formats the month and the year of the given [date].
  ///
  /// The returned string does not contain the day of the month. This appears
  /// in the date picker invoked using [showDatePicker].
  String formatMonthYear(DateTime date);

  /// List of week day names in narrow format, usually 1- or 2-letter
  /// abbreviations of full names.
  ///
  /// The list begins with the value corresponding to Sunday and ends with
  /// Saturday. Use [firstDayOfWeekIndex] to find the first day of week in this
  /// list.
  ///
  /// Examples:
  ///
  /// - US English: S, M, T, W, T, F, S
  /// - Russian: вс, пн, вт, ср, чт, пт, сб - notice that the list begins with
  ///   вс (Sunday) even though the first day of week for Russian is Monday.
255
  List<String> get narrowWeekdays;
Yegor's avatar
Yegor committed
256 257 258 259

  /// Index of the first day of week, where 0 points to Sunday, and 6 points to
  /// Saturday.
  ///
260
  /// This getter is compatible with [narrowWeekdays]. For example:
Yegor's avatar
Yegor committed
261 262 263 264
  ///
  /// ```dart
  /// var localizations = MaterialLocalizations.of(context);
  /// // The name of the first day of week for the current locale.
265
  /// var firstDayOfWeek = localizations.narrowWeekdays[localizations.firstDayOfWeekIndex];
Yegor's avatar
Yegor committed
266 267 268
  /// ```
  int get firstDayOfWeekIndex;

269 270 271 272 273 274 275 276 277 278 279 280
  /// The semantics label used to indicate which account is signed in in the
  /// [UserAccountsDrawerHeader] widget.
  String get signedInLabel;

  /// The semantics label used for the button on [UserAccountsDrawerHeader] that
  /// hides the list of accounts.
  String get hideAccountsLabel;

  /// The semantics label used for the button on [UserAccountsDrawerHeader] that
  /// shows the list of accounts.
  String get showAccountsLabel;

281
  /// The semantics label used for [ReorderableListView] to reorder an item in the
282 283 284
  /// list to the start of the list.
  String get reorderItemToStart;

285
  /// The semantics label used for [ReorderableListView] to reorder an item in the
286 287 288
  /// list to the end of the list.
  String get reorderItemToEnd;

289
  /// The semantics label used for [ReorderableListView] to reorder an item in the
290 291 292
  /// list one space up the list.
  String get reorderItemUp;

293
  /// The semantics label used for [ReorderableListView] to reorder an item in the
294 295 296
  /// list one space down the list.
  String get reorderItemDown;

297
  /// The semantics label used for [ReorderableListView] to reorder an item in the
298 299 300
  /// list one space left in the list.
  String get reorderItemLeft;

301
  /// The semantics label used for [ReorderableListView] to reorder an item in the
302 303 304
  /// list one space right in the list.
  String get reorderItemRight;

305 306 307 308 309 310
  /// The semantics hint to describe the tap action on an expanded [ExpandIcon].
  String get expandedIconTapHint => 'Collapse';

  /// The semantics hint to describe the tap action on a collapsed [ExpandIcon].
  String get collapsedIconTapHint => 'Expand';

311 312 313
  /// The label for the [TextField]'s character counter.
  String remainingTextFieldCharacterCount(int remaining);

314 315 316
  /// The default semantics label for a [RefreshIndicator].
  String get refreshIndicatorSemanticLabel;

317 318 319 320 321 322 323 324
  /// The `MaterialLocalizations` from the closest [Localizations] instance
  /// that encloses the given context.
  ///
  /// This method is just a convenient shorthand for:
  /// `Localizations.of<MaterialLocalizations>(context, MaterialLocalizations)`.
  ///
  /// References to the localized resources defined by this class are typically
  /// written in terms of this method. For example:
325
  ///
326 327 328 329 330 331 332
  /// ```dart
  /// tooltip: MaterialLocalizations.of(context).backButtonTooltip,
  /// ```
  static MaterialLocalizations of(BuildContext context) {
    return Localizations.of<MaterialLocalizations>(context, MaterialLocalizations);
  }
}
333

334 335 336
class _MaterialLocalizationsDelegate extends LocalizationsDelegate<MaterialLocalizations> {
  const _MaterialLocalizationsDelegate();

337 338 339
  @override
  bool isSupported(Locale locale) => locale.languageCode == 'en';

340 341 342 343 344
  @override
  Future<MaterialLocalizations> load(Locale locale) => DefaultMaterialLocalizations.load(locale);

  @override
  bool shouldReload(_MaterialLocalizationsDelegate old) => false;
345 346 347

  @override
  String toString() => 'DefaultMaterialLocalizations.delegate(en_US)';
348 349 350 351 352 353 354 355 356 357
}

/// US English strings for the material widgets.
///
/// See also:
///
///  * [GlobalMaterialLocalizations], which provides material localizations for
///    many languages.
///  * [MaterialApp.delegates], which automatically includes
///    [DefaultMaterialLocalizations.delegate] by default.
358
class DefaultMaterialLocalizations implements MaterialLocalizations {
Yegor's avatar
Yegor committed
359
  /// Constructs an object that defines the material widgets' localized strings
360
  /// for US English (only).
361 362 363
  ///
  /// [LocalizationsDelegate] implementations typically call the static [load]
  /// function, rather than constructing this class directly.
364 365
  const DefaultMaterialLocalizations();

366
  // Ordered to match DateTime.monday=1, DateTime.sunday=6
367
  static const List<String> _shortWeekdays = <String>[
368 369 370 371 372 373 374 375 376
    'Mon',
    'Tue',
    'Wed',
    'Thu',
    'Fri',
    'Sat',
    'Sun',
  ];

377
  // Ordered to match DateTime.monday=1, DateTime.sunday=6
378
  static const List<String> _weekdays = <String>[
379 380 381 382 383 384 385 386 387
    'Monday',
    'Tuesday',
    'Wednesday',
    'Thursday',
    'Friday',
    'Saturday',
    'Sunday',
  ];

388
  static const List<String> _narrowWeekdays = <String>[
389 390 391 392 393 394 395 396 397
    'S',
    'M',
    'T',
    'W',
    'T',
    'F',
    'S',
  ];

398
  static const List<String> _shortMonths = <String>[
399 400 401 402 403 404 405 406 407 408 409 410 411 412
    'Jan',
    'Feb',
    'Mar',
    'Apr',
    'May',
    'Jun',
    'Jul',
    'Aug',
    'Sep',
    'Oct',
    'Nov',
    'Dec',
  ];

413
  static const List<String> _months = <String>[
414 415 416 417 418 419 420 421 422 423 424 425 426
    'January',
    'February',
    'March',
    'April',
    'May',
    'June',
    'July',
    'August',
    'September',
    'October',
    'November',
    'December',
  ];
427

428
  @override
429
  String formatHour(TimeOfDay timeOfDay, { bool alwaysUse24HourFormat = false }) {
430 431 432 433 434 435 436
    final TimeOfDayFormat format = timeOfDayFormat(alwaysUse24HourFormat: alwaysUse24HourFormat);
    switch (format) {
      case TimeOfDayFormat.h_colon_mm_space_a:
        return formatDecimal(timeOfDay.hourOfPeriod == 0 ? 12 : timeOfDay.hourOfPeriod);
      case TimeOfDayFormat.HH_colon_mm:
        return _formatTwoDigitZeroPad(timeOfDay.hour);
      default:
437
        throw AssertionError('$runtimeType does not support $format.');
438 439 440 441 442 443 444 445 446 447 448 449
    }
  }

  /// Formats [number] using two digits, assuming it's in the 0-99 inclusive
  /// range. Not designed to format values outside this range.
  String _formatTwoDigitZeroPad(int number) {
    assert(0 <= number && number < 100);

    if (number < 10)
      return '0$number';

    return '$number';
450 451 452 453
  }

  @override
  String formatMinute(TimeOfDay timeOfDay) {
454 455
    final int minute = timeOfDay.minute;
    return minute < 10 ? '0$minute' : minute.toString();
456 457
  }

Yegor's avatar
Yegor committed
458
  @override
459
  String formatYear(DateTime date) => date.year.toString();
Yegor's avatar
Yegor committed
460 461 462

  @override
  String formatMediumDate(DateTime date) {
463 464
    final String day = _shortWeekdays[date.weekday - DateTime.monday];
    final String month = _shortMonths[date.month - DateTime.january];
465
    return '$day, $month ${date.day}';
Yegor's avatar
Yegor committed
466 467
  }

468 469
  @override
  String formatFullDate(DateTime date) {
470 471
    final String month = _months[date.month - DateTime.january];
    return '${_weekdays[date.weekday - DateTime.monday]}, $month ${date.day}, ${date.year}';
472 473
  }

Yegor's avatar
Yegor committed
474 475
  @override
  String formatMonthYear(DateTime date) {
476
    final String year = formatYear(date);
477
    final String month = _months[date.month - DateTime.january];
478
    return '$month $year';
Yegor's avatar
Yegor committed
479 480 481
  }

  @override
482
  List<String> get narrowWeekdays => _narrowWeekdays;
Yegor's avatar
Yegor committed
483 484

  @override
485
  int get firstDayOfWeekIndex => 0; // narrowWeekdays[0] is 'S' for Sunday
Yegor's avatar
Yegor committed
486

487 488 489 490 491 492 493 494 495 496
  String _formatDayPeriod(TimeOfDay timeOfDay) {
    switch (timeOfDay.period) {
      case DayPeriod.am:
        return anteMeridiemAbbreviation;
      case DayPeriod.pm:
        return postMeridiemAbbreviation;
    }
    return null;
  }

497
  @override
498
  String formatDecimal(int number) {
499 500 501 502
    if (number > -1000 && number < 1000)
      return number.toString();

    final String digits = number.abs().toString();
503
    final StringBuffer result = StringBuffer(number < 0 ? '-' : '');
504 505 506 507 508 509 510
    final int maxDigitIndex = digits.length - 1;
    for (int i = 0; i <= maxDigitIndex; i += 1) {
      result.write(digits[i]);
      if (i < maxDigitIndex && (maxDigitIndex - i) % 3 == 0)
        result.write(',');
    }
    return result.toString();
511 512 513
  }

  @override
514
  String formatTimeOfDay(TimeOfDay timeOfDay, { bool alwaysUse24HourFormat = false }) {
515 516 517 518 519 520 521 522
    // Not using intl.DateFormat for two reasons:
    //
    // - DateFormat supports more formats than our material time picker does,
    //   and we want to be consistent across time picker format and the string
    //   formatting of the time of day.
    // - DateFormat operates on DateTime, which is sensitive to time eras and
    //   time zones, while here we want to format hour and minute within one day
    //   no matter what date the day falls on.
523
    final StringBuffer buffer = StringBuffer();
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540

    // Add hour:minute.
    buffer
      ..write(formatHour(timeOfDay, alwaysUse24HourFormat: alwaysUse24HourFormat))
      ..write(':')
      ..write(formatMinute(timeOfDay));

    if (alwaysUse24HourFormat) {
      // There's no AM/PM indicator in 24-hour format.
      return '$buffer';
    }

    // Add AM/PM indicator.
    buffer
      ..write(' ')
      ..write(_formatDayPeriod(timeOfDay));
    return '$buffer';
541 542
  }

543
  @override
544
  String get openAppDrawerTooltip => 'Open navigation menu';
545 546

  @override
547
  String get backButtonTooltip => 'Back';
548 549

  @override
550
  String get closeButtonTooltip => 'Close';
551

552 553 554
  @override
  String get deleteButtonTooltip => 'Delete';

555
  @override
556
  String get nextMonthTooltip => 'Next month';
557 558

  @override
559
  String get previousMonthTooltip => 'Previous month';
560

561
  @override
562
  String get nextPageTooltip => 'Next page';
563 564

  @override
565
  String get previousPageTooltip => 'Previous page';
566 567

  @override
568
  String get showMenuTooltip => 'Show menu';
569

570 571 572 573 574 575 576 577 578 579 580 581
  @override
  String get drawerLabel => 'Navigation menu';

  @override
  String get popupMenuLabel => 'Popup menu';

  @override
  String get dialogLabel => 'Dialog';

  @override
  String get alertDialogLabel => 'Alert';

582 583 584
  @override
  String get searchFieldLabel => 'Search';

Hans Muller's avatar
Hans Muller committed
585
  @override
586
  String aboutListTileTitle(String applicationName) => 'About $applicationName';
Hans Muller's avatar
Hans Muller committed
587

588
  @override
589
  String get licensesPageTitle => 'Licenses';
590 591 592

  @override
  String pageRowsInfoTitle(int firstRow, int lastRow, int rowCount, bool rowCountIsApproximate) {
593 594 595
    return rowCountIsApproximate
      ? '$firstRow$lastRow of about $rowCount'
      : '$firstRow$lastRow of $rowCount';
596 597 598
  }

  @override
599
  String get rowsPerPageTitle => 'Rows per page:';
600

601
  @override
602
  String tabLabel({ int tabIndex, int tabCount }) {
603 604 605 606 607
    assert(tabIndex >= 1);
    assert(tabCount >= 1);
    return 'Tab $tabIndex of $tabCount';
  }

608 609
  @override
  String selectedRowCountTitle(int selectedRowCount) {
610 611 612 613 614 615 616 617
    switch (selectedRowCount) {
      case 0:
        return 'No items selected';
      case 1:
        return '1 item selected';
      default:
        return '$selectedRowCount items selected';
    }
618
  }
619 620

  @override
621
  String get cancelButtonLabel => 'CANCEL';
622 623

  @override
624
  String get closeButtonLabel => 'CLOSE';
625 626

  @override
627
  String get continueButtonLabel => 'CONTINUE';
628 629

  @override
630
  String get copyButtonLabel => 'COPY';
631 632

  @override
633
  String get cutButtonLabel => 'CUT';
634 635

  @override
636
  String get okButtonLabel => 'OK';
637 638

  @override
639
  String get pasteButtonLabel => 'PASTE';
640 641

  @override
642
  String get selectAllButtonLabel => 'SELECT ALL';
643 644

  @override
645
  String get viewLicensesButtonLabel => 'VIEW LICENSES';
646

Yegor's avatar
Yegor committed
647
  @override
648
  String get anteMeridiemAbbreviation => 'AM';
Yegor's avatar
Yegor committed
649 650

  @override
651
  String get postMeridiemAbbreviation => 'PM';
Yegor's avatar
Yegor committed
652

653 654 655 656 657 658
  @override
  String get timePickerHourModeAnnouncement => 'Select hours';

  @override
  String get timePickerMinuteModeAnnouncement => 'Select minutes';

659 660 661
  @override
  String get modalBarrierDismissLabel => 'Dismiss';

662 663 664
  @override
  ScriptCategory get scriptCategory => ScriptCategory.englishLike;

665
  @override
666
  TimeOfDayFormat timeOfDayFormat({ bool alwaysUse24HourFormat = false }) {
667 668 669 670
    return alwaysUse24HourFormat
      ? TimeOfDayFormat.HH_colon_mm
      : TimeOfDayFormat.h_colon_mm_space_a;
  }
Yegor's avatar
Yegor committed
671

672 673 674 675 676 677 678 679 680
  @override
  String get signedInLabel => 'Signed in';

  @override
  String get hideAccountsLabel => 'Hide accounts';

  @override
  String get showAccountsLabel => 'Show accounts';

681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698
  @override
  String get reorderItemUp => 'Move up';

  @override
  String get reorderItemDown => 'Move down';

  @override
  String get reorderItemLeft => 'Move left';

  @override
  String get reorderItemRight => 'Move right';

  @override
  String get reorderItemToEnd => 'Move to the end';

  @override
  String get reorderItemToStart => 'Move to the start';

699 700 701 702 703 704
  @override
  String get expandedIconTapHint => 'Collapse';

  @override
  String get collapsedIconTapHint => 'Expand';

705 706 707
  @override
  String get refreshIndicatorSemanticLabel => 'Refresh';

708 709 710 711
  /// Creates an object that provides US English resource values for the material
  /// library widgets.
  ///
  /// The [locale] parameter is ignored.
712 713 714 715
  ///
  /// This method is typically used to create a [LocalizationsDelegate].
  /// The [MaterialApp] does so by default.
  static Future<MaterialLocalizations> load(Locale locale) {
716
    return SynchronousFuture<MaterialLocalizations>(const DefaultMaterialLocalizations());
717
  }
Yegor's avatar
Yegor committed
718

719 720 721 722
  /// A [LocalizationsDelegate] that uses [DefaultMaterialLocalizations.load]
  /// to create an instance of this class.
  ///
  /// [MaterialApp] automatically adds this value to [MaterialApp.localizationsDelegates].
723
  static const LocalizationsDelegate<MaterialLocalizations> delegate = _MaterialLocalizationsDelegate();
724 725 726 727 728 729 730 731 732 733 734 735

  @override
  String remainingTextFieldCharacterCount(int remaining) {
    switch (remaining) {
      case 0:
        return 'No characters remaining';
      case 1:
        return '1 character remaining';
      default:
        return '$remaining characters remaining';
    }
  }
Yegor's avatar
Yegor committed
736
}