Created
September 28, 2018 08:58
-
-
Save lrhn/a0eee79f758d6319f21b10f411c43a00 to your computer and use it in GitHub Desktop.
Expando Locale Example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
abstract class Locale { | |
String get languageCode; | |
String get scriptCode; | |
String get regionCode; | |
const factory Locale(String languageCode, | |
[String regionOrScriptCode, String regionCode]) = _Locale._select; | |
} | |
class _Locale implements Locale { | |
static Expando<_Locale> _normalized = Expando(); | |
final String _language; | |
final String _region; | |
final String _script; | |
const _Locale._select(String language, [String regionOrScript, String region]) : | |
this.validate(language, | |
region == null ? null : regionOrScript, | |
region == null ? regionOrScript : region); | |
const _Locale.validate(this._language, this._script, this._region) | |
: assert(_language != null), | |
assert(_language.length >= 2), | |
assert(_language.length <= 8), | |
assert(_language.length != 4), | |
assert((_script ?? "xxxx").length == 4), | |
assert((_region ?? "xx").length >= 2), | |
assert((_region ?? "xx").length <= 3); | |
String get languageCode => _normal._language; | |
String get scriptCode => _normal._script; | |
String get regionCode => _normal._region; | |
_Locale _normalize() { | |
var language = _language.toLowerCase(); | |
var script = _script == null ? null : _capitalize(_script); | |
var region = _region?.toUpperCase(); | |
// Add any other normalization desired here. | |
if (identical(language, _language) && | |
identical(script, _script) && | |
identical(region, _region)) { | |
return this; | |
} | |
return _Locale.validate(language, script, region); | |
} | |
_Locale get _normal => _normalized[this] ??= _normalize(); | |
Locale normalize() => _normal; | |
int get hashCode => _normal.toString().hashCode; | |
bool operator==(Object other) { | |
if (other is Locale) { | |
var normal = _normal; | |
return normal._language == other.languageCode && | |
normal._script == other.scriptCode && | |
normal._region == other.regionCode; | |
} | |
return false; | |
} | |
String toString() { | |
var normal = _normal; | |
var builder = new StringBuffer(normal._language); | |
if (normal._script != null) { | |
builder.write("_"); | |
builder.write(normal._script); | |
} | |
if (normal._region != null) { | |
builder.write("_"); | |
builder.write(normal._region); | |
} | |
return builder.toString(); | |
} | |
} | |
String _capitalize(String word) { | |
assert(word.length == 4); | |
invalid: { | |
if (word.codeUnitAt(0) & 0x20 != 0) break invalid; | |
for (int i = 0; i < word.length; i++) { | |
if (word.codeUnitAt(0) & 0x20 == 0) break invalid; | |
} | |
return word; | |
} | |
return word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase(); | |
} | |
main() { | |
print(const Locale("zh")); | |
print(const Locale("zh", "TW")); | |
var l1 = const Locale("zh", "Hant", "TW"); | |
var l2 = const Locale("ZH", "HANT", "tw"); | |
print(l1); | |
print(l2); | |
print(l1 == l2); | |
print(l1.hashCode - l2.hashCode); | |
try { | |
Locale("zhzh"); | |
} catch (e) { | |
print(e); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment