material_localizations.dart 22.3 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 'time.dart';
11
import 'typography.dart';
12

13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
// 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
30 31
//    same directory), listing the translation as `TBD`. After that you have to
//    re-generate lib/src/l10n/localizations.dart by running
32 33
//    `dart dev/tools/gen_localizations.dart --overwrite`. There is a README
//    file with further information in the lib/src/l10n/ directory.
34 35 36 37
//
// 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.

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

  /// The [BackButton]'s tooltip.
51
  String get backButtonTooltip;
52 53

  /// The [CloseButton]'s tooltip.
54
  String get closeButtonTooltip;
55

56 57 58
  /// The tooltip for the delete button on a [Chip].
  String get deleteButtonTooltip;

59
  /// The tooltip for the [MonthPicker]'s "next month" button.
60
  String get nextMonthTooltip;
61 62

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

65
  /// The tooltip for the [PaginatedDataTable]'s "next page" button.
66 67
  String get nextPageTooltip;

68
  /// The tooltip for the [PaginatedDataTable]'s "previous page" button.
69 70 71 72 73
  String get previousPageTooltip;

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

Hans Muller's avatar
Hans Muller committed
74 75 76
  /// The default title for [AboutListTile].
  String aboutListTileTitle(String applicationName);

77 78 79
  /// Title for the [LicensePage] widget.
  String get licensesPageTitle;

80 81 82 83 84 85
  /// 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;

86 87 88 89 90 91 92 93
  /// 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.
  String tabLabel({int tabIndex, int tabCount});

94
  /// Title for the [PaginatedDataTable]'s selected row count header.
95 96
  String selectedRowCountTitle(int selectedRowCount);

97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
  /// 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;

121
  /// Label for the [AboutDialog] button that shows the [LicensePage].
122 123
  String get viewLicensesButtonLabel;

Yegor's avatar
Yegor committed
124 125 126 127 128 129
  /// 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;

130 131 132 133 134 135 136 137
  /// 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
138
  /// Label read out by accessibility tools (TalkBack or VoiceOver) for a modal
139 140
  /// barrier to indicate that a tap dismisses the barrier.
  ///
141
  /// A modal barrier can for example be found behind an alert or popup to block
142 143 144
  /// user interaction with elements behind it.
  String get modalBarrierDismissLabel;

145
  /// Label read out by accessibility tools (TalkBack or VoiceOver) when a
146 147
  /// drawer widget is opened.
  String get drawerLabel;
148 149

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

153
  /// Label read out by accessibility tools (TalkBack or VoiceOver) when a
154 155 156
  /// dialog widget is opened.
  String get dialogLabel;

157
  /// Label read out by accessibility tools (TalkBack or VoiceOver) when an
158 159 160
  /// alert dialog widget is opened.
  String get alertDialogLabel;

161 162 163 164
  /// 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
165 166 167 168
  /// The format used to lay out the time picker.
  ///
  /// The documentation for [TimeOfDayFormat] enum values provides details on
  /// each supported layout.
169
  TimeOfDayFormat timeOfDayFormat({ bool alwaysUse24HourFormat = false });
Yegor's avatar
Yegor committed
170

171 172 173 174
  /// Provides geometric text preferences for the current locale.
  ///
  /// This text theme is incomplete. For example, it lacks text color
  /// information. This theme must be merged with another text theme that
175
  /// provides the missing values.
176 177 178 179
  ///
  /// Typically a complete theme is obtained via [Theme.of], which can be
  /// localized using the [Localizations] widget.
  ///
180 181 182 183 184
  /// The text styles provided by this theme are expected to have their
  /// [TextStyle.inherit] property set to false, so that the [ThemeData]
  /// obtained from [Theme.of] no longer inherits text style properties and
  /// contains a complete set of properties needed to style a [Text] widget.
  ///
185
  /// See also: https://material.io/go/design-typography
186 187
  TextTheme get localTextGeometry;

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

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

  /// 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].
204 205 206 207 208
  ///
  /// 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.
209
  String formatTimeOfDay(TimeOfDay timeOfDay, { bool alwaysUse24HourFormat = false });
210

Yegor's avatar
Yegor committed
211 212 213 214 215 216 217 218 219 220 221 222 223 224
  /// 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);

225 226 227 228 229 230 231 232 233 234 235
  /// 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
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
  /// 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.
254
  List<String> get narrowWeekdays;
Yegor's avatar
Yegor committed
255 256 257 258

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

268 269 270 271 272 273 274 275 276 277 278 279
  /// 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;

280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
  /// The semantics label used for [ReorderableList] to reorder an item in the
  /// list to the start of the list.
  String get reorderItemToStart;

  /// The semantics label used for [ReorderableList] to reorder an item in the
  /// list to the end of the list.
  String get reorderItemToEnd;

  /// The semantics label used for [ReorderableList] to reorder an item in the
  /// list one space up the list.
  String get reorderItemUp;

  /// The semantics label used for [ReorderableList] to reorder an item in the
  /// list one space down the list.
  String get reorderItemDown;

  /// The semantics label used for [ReorderableList] to reorder an item in the
  /// list one space left in the list.
  String get reorderItemLeft;

  /// The semantics label used for [ReorderableList] to reorder an item in the
  /// list one space right in the list.
  String get reorderItemRight;

304 305 306 307 308 309
  /// 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';

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

313 314 315 316 317 318 319 320
  /// 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:
321
  ///
322 323 324 325 326 327 328
  /// ```dart
  /// tooltip: MaterialLocalizations.of(context).backButtonTooltip,
  /// ```
  static MaterialLocalizations of(BuildContext context) {
    return Localizations.of<MaterialLocalizations>(context, MaterialLocalizations);
  }
}
329

330 331 332
class _MaterialLocalizationsDelegate extends LocalizationsDelegate<MaterialLocalizations> {
  const _MaterialLocalizationsDelegate();

333 334 335
  @override
  bool isSupported(Locale locale) => locale.languageCode == 'en';

336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
  @override
  Future<MaterialLocalizations> load(Locale locale) => DefaultMaterialLocalizations.load(locale);

  @override
  bool shouldReload(_MaterialLocalizationsDelegate old) => false;
}

/// 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.
351
class DefaultMaterialLocalizations implements MaterialLocalizations {
Yegor's avatar
Yegor committed
352
  /// Constructs an object that defines the material widgets' localized strings
353
  /// for US English (only).
354 355 356
  ///
  /// [LocalizationsDelegate] implementations typically call the static [load]
  /// function, rather than constructing this class directly.
357 358
  const DefaultMaterialLocalizations();

359
  // Ordered to match DateTime.monday=1, DateTime.sunday=6
360
  static const List<String> _shortWeekdays = <String>[
361 362 363 364 365 366 367 368 369
    'Mon',
    'Tue',
    'Wed',
    'Thu',
    'Fri',
    'Sat',
    'Sun',
  ];

370
  // Ordered to match DateTime.monday=1, DateTime.sunday=6
371
  static const List<String> _weekdays = <String>[
372 373 374 375 376 377 378 379 380
    'Monday',
    'Tuesday',
    'Wednesday',
    'Thursday',
    'Friday',
    'Saturday',
    'Sunday',
  ];

381
  static const List<String> _narrowWeekdays = <String>[
382 383 384 385 386 387 388 389 390
    'S',
    'M',
    'T',
    'W',
    'T',
    'F',
    'S',
  ];

391
  static const List<String> _shortMonths = <String>[
392 393 394 395 396 397 398 399 400 401 402 403 404 405
    'Jan',
    'Feb',
    'Mar',
    'Apr',
    'May',
    'Jun',
    'Jul',
    'Aug',
    'Sep',
    'Oct',
    'Nov',
    'Dec',
  ];

406
  static const List<String> _months = <String>[
407 408 409 410 411 412 413 414 415 416 417 418 419
    'January',
    'February',
    'March',
    'April',
    'May',
    'June',
    'July',
    'August',
    'September',
    'October',
    'November',
    'December',
  ];
420

421
  @override
422
  String formatHour(TimeOfDay timeOfDay, { bool alwaysUse24HourFormat = false }) {
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
    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:
        throw new AssertionError('$runtimeType does not support $format.');
    }
  }

  /// 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';
443 444 445 446
  }

  @override
  String formatMinute(TimeOfDay timeOfDay) {
447 448
    final int minute = timeOfDay.minute;
    return minute < 10 ? '0$minute' : minute.toString();
449 450
  }

Yegor's avatar
Yegor committed
451
  @override
452
  String formatYear(DateTime date) => date.year.toString();
Yegor's avatar
Yegor committed
453 454 455

  @override
  String formatMediumDate(DateTime date) {
456 457
    final String day = _shortWeekdays[date.weekday - DateTime.monday];
    final String month = _shortMonths[date.month - DateTime.january];
458
    return '$day, $month ${date.day}';
Yegor's avatar
Yegor committed
459 460
  }

461 462
  @override
  String formatFullDate(DateTime date) {
463 464
    final String month = _months[date.month - DateTime.january];
    return '${_weekdays[date.weekday - DateTime.monday]}, $month ${date.day}, ${date.year}';
465 466
  }

Yegor's avatar
Yegor committed
467 468
  @override
  String formatMonthYear(DateTime date) {
469
    final String year = formatYear(date);
470
    final String month = _months[date.month - DateTime.january];
471
    return '$month $year';
Yegor's avatar
Yegor committed
472 473 474
  }

  @override
475
  List<String> get narrowWeekdays => _narrowWeekdays;
Yegor's avatar
Yegor committed
476 477

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

480 481 482 483 484 485 486 487 488 489
  String _formatDayPeriod(TimeOfDay timeOfDay) {
    switch (timeOfDay.period) {
      case DayPeriod.am:
        return anteMeridiemAbbreviation;
      case DayPeriod.pm:
        return postMeridiemAbbreviation;
    }
    return null;
  }

490
  @override
491
  String formatDecimal(int number) {
492 493 494 495 496 497 498 499 500 501 502 503
    if (number > -1000 && number < 1000)
      return number.toString();

    final String digits = number.abs().toString();
    final StringBuffer result = new StringBuffer(number < 0 ? '-' : '');
    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();
504 505 506
  }

  @override
507
  String formatTimeOfDay(TimeOfDay timeOfDay, { bool alwaysUse24HourFormat = false }) {
508 509 510 511 512 513 514 515
    // 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.
516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
    final StringBuffer buffer = new StringBuffer();

    // 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';
534 535
  }

536
  @override
537
  String get openAppDrawerTooltip => 'Open navigation menu';
538 539

  @override
540
  String get backButtonTooltip => 'Back';
541 542

  @override
543
  String get closeButtonTooltip => 'Close';
544

545 546 547
  @override
  String get deleteButtonTooltip => 'Delete';

548
  @override
549
  String get nextMonthTooltip => 'Next month';
550 551

  @override
552
  String get previousMonthTooltip => 'Previous month';
553

554
  @override
555
  String get nextPageTooltip => 'Next page';
556 557

  @override
558
  String get previousPageTooltip => 'Previous page';
559 560

  @override
561
  String get showMenuTooltip => 'Show menu';
562

563 564 565 566 567 568 569 570 571 572 573 574
  @override
  String get drawerLabel => 'Navigation menu';

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

  @override
  String get dialogLabel => 'Dialog';

  @override
  String get alertDialogLabel => 'Alert';

575 576 577
  @override
  String get searchFieldLabel => 'Search';

Hans Muller's avatar
Hans Muller committed
578
  @override
579
  String aboutListTileTitle(String applicationName) => 'About $applicationName';
Hans Muller's avatar
Hans Muller committed
580

581
  @override
582
  String get licensesPageTitle => 'Licenses';
583 584 585

  @override
  String pageRowsInfoTitle(int firstRow, int lastRow, int rowCount, bool rowCountIsApproximate) {
586 587 588
    return rowCountIsApproximate
      ? '$firstRow$lastRow of about $rowCount'
      : '$firstRow$lastRow of $rowCount';
589 590 591
  }

  @override
592
  String get rowsPerPageTitle => 'Rows per page:';
593

594 595 596 597 598 599 600
  @override
  String tabLabel({int tabIndex, int tabCount}) {
    assert(tabIndex >= 1);
    assert(tabCount >= 1);
    return 'Tab $tabIndex of $tabCount';
  }

601 602
  @override
  String selectedRowCountTitle(int selectedRowCount) {
603 604 605 606 607 608 609 610
    switch (selectedRowCount) {
      case 0:
        return 'No items selected';
      case 1:
        return '1 item selected';
      default:
        return '$selectedRowCount items selected';
    }
611
  }
612 613

  @override
614
  String get cancelButtonLabel => 'CANCEL';
615 616

  @override
617
  String get closeButtonLabel => 'CLOSE';
618 619

  @override
620
  String get continueButtonLabel => 'CONTINUE';
621 622

  @override
623
  String get copyButtonLabel => 'COPY';
624 625

  @override
626
  String get cutButtonLabel => 'CUT';
627 628

  @override
629
  String get okButtonLabel => 'OK';
630 631

  @override
632
  String get pasteButtonLabel => 'PASTE';
633 634

  @override
635
  String get selectAllButtonLabel => 'SELECT ALL';
636 637

  @override
638
  String get viewLicensesButtonLabel => 'VIEW LICENSES';
639

Yegor's avatar
Yegor committed
640
  @override
641
  String get anteMeridiemAbbreviation => 'AM';
Yegor's avatar
Yegor committed
642 643

  @override
644
  String get postMeridiemAbbreviation => 'PM';
Yegor's avatar
Yegor committed
645

646 647 648 649 650 651
  @override
  String get timePickerHourModeAnnouncement => 'Select hours';

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

652 653 654
  @override
  String get modalBarrierDismissLabel => 'Dismiss';

655
  @override
656
  TimeOfDayFormat timeOfDayFormat({ bool alwaysUse24HourFormat = false }) {
657 658 659 660
    return alwaysUse24HourFormat
      ? TimeOfDayFormat.HH_colon_mm
      : TimeOfDayFormat.h_colon_mm_space_a;
  }
Yegor's avatar
Yegor committed
661

662 663
  /// Looks up text geometry defined in [MaterialTextGeometry].
  @override
664
  TextTheme get localTextGeometry => MaterialTextGeometry.englishLike;
665

666 667 668 669 670 671 672 673 674
  @override
  String get signedInLabel => 'Signed in';

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

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

675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
  @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';

693 694 695 696 697 698
  @override
  String get expandedIconTapHint => 'Collapse';

  @override
  String get collapsedIconTapHint => 'Expand';

699 700 701 702
  /// Creates an object that provides US English resource values for the material
  /// library widgets.
  ///
  /// The [locale] parameter is ignored.
703 704 705 706
  ///
  /// This method is typically used to create a [LocalizationsDelegate].
  /// The [MaterialApp] does so by default.
  static Future<MaterialLocalizations> load(Locale locale) {
707
    return new SynchronousFuture<MaterialLocalizations>(const DefaultMaterialLocalizations());
708
  }
Yegor's avatar
Yegor committed
709

710 711 712 713
  /// A [LocalizationsDelegate] that uses [DefaultMaterialLocalizations.load]
  /// to create an instance of this class.
  ///
  /// [MaterialApp] automatically adds this value to [MaterialApp.localizationsDelegates].
714
  static const LocalizationsDelegate<MaterialLocalizations> delegate = _MaterialLocalizationsDelegate();
715 716 717 718 719 720 721 722 723 724 725 726

  @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
727
}