// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'locale/locale_implementation.dart'; import 'locale/locale_parser.dart' show LocaleParser; /// A representation of a [Unicode Locale /// Identifier](https://www.unicode.org/reports/tr35/#Unicode_locale_identifier). /// /// To create Locale instances, consider using: /// * [fromSubtags] for language, script and region, /// * [parse] for Unicode Locale Identifier strings (throws exceptions on /// failure), /// * [tryParse] for Unicode Locale Identifier strings (returns null on /// failure). abstract class Locale { /// Constructs a Locale instance that consists of only language, script and /// region subtags. /// /// Throws a [FormatException] if any subtag is syntactically invalid. static Locale fromSubtags( {required String languageCode, String? scriptCode, String? countryCode}) => LocaleImplementation.fromSubtags( languageCode: languageCode, scriptCode: scriptCode, countryCode: countryCode); /// Parses [Unicode Locale Identifiers][localeIds] to produce [Locale] /// instances. /// /// [localeIds]: /// https://www.unicode.org/reports/tr35/#Unicode_locale_identifier /// /// Throws a [FormatException] if [localeIdentifier] is syntactically invalid. static Locale parse(String localeIdentifier) { ArgumentError.checkNotNull(localeIdentifier); var parser = LocaleParser(localeIdentifier); var locale = parser.toLocale(); if (locale == null) { throw FormatException('Locale "$localeIdentifier": ' '${parser.problems.join("; ")}.'); } return locale; } /// Parses [Unicode Locale Identifiers][localeIds] to produce [Locale] /// instances. /// /// [localeIds]: /// https://www.unicode.org/reports/tr35/#Unicode_locale_identifier /// /// Returns `null` if [localeIdentifier] is syntactically invalid. static Locale? tryParse(String localeIdentifier) { ArgumentError.checkNotNull(localeIdentifier); var parser = LocaleParser(localeIdentifier); return parser.toLocale(); } /// The language subtag of the Locale Identifier. /// /// It is syntactically valid, normalized (has correct case) and canonical /// (deprecated tags have been replaced), but not necessarily valid (the /// language might not exist) because the list of valid languages changes with /// time. String get languageCode; /// The script subtag of the Locale Identifier, null if absent. /// /// It is syntactically valid and normalized (has correct case), but not /// necessarily valid (the script might not exist) because the list of valid /// scripts changes with time. String? get scriptCode; /// The region subtag of the Locale Identifier, null if absent. /// /// It is syntactically valid, normalized (has correct case) and canonical /// (deprecated tags have been replaced), but not necessarily valid (the /// region might not exist) because the list of valid regions changes with /// time. String? get countryCode; /// Iterable of variant subtags. /// /// They are syntactically valid, normalized (have correct case) and sorted /// alphabetically, but not necessarily valid (variants might not exist) /// because the list of variants changes with time. Iterable get variants; /// Returns the canonical [Unicode BCP47 Locale /// Identifier](http://www.unicode.org/reports/tr35/#BCP_47_Conformance) for /// this locale. String toLanguageTag(); /// Returns the canonical [Unicode BCP47 Locale /// Identifier](http://www.unicode.org/reports/tr35/#BCP_47_Conformance) for /// this locale. @override String toString() => toLanguageTag(); @override bool operator ==(Object other) { if (identical(this, other)) return true; return other is Locale && toLanguageTag() == other.toLanguageTag(); } @override int get hashCode { return toLanguageTag().hashCode; } }