Skip to content

Instantly share code, notes, and snippets.

@lrhn
Created September 28, 2018 08:58
Show Gist options
  • Save lrhn/a0eee79f758d6319f21b10f411c43a00 to your computer and use it in GitHub Desktop.
Save lrhn/a0eee79f758d6319f21b10f411c43a00 to your computer and use it in GitHub Desktop.
Expando Locale Example
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