localized property
Returns the human readable name of this UserAgent, if any, or otherwise returns the whole UserAgent.
The retrieved value depends on the operating system:
- For Android it outputs the device manufacturer and identifier:
Xiaomi M2101K7BNY
- For iOS it outputs the device name and model:
iPad Pro (12.9-inch) (5th generation)
iPhone 14 Pro
- For macOS it outputs the device name and model:
MacBook Air (M2, 2022)
- For Linux/Windows it outputs the OS name and version:
Ubuntu 22.04 LTS
Windows 11 Home
- For browsers it returns the browser name and version:
Safari 17.4.1
Chrome 124
Microsoft Edge 111
Implementation
String get localized {
// If [UserAgent] starts with [Config.userAgentProduct], then it's probably
// the one generated by us via [WebUtils.userAgent] method.
if (val.startsWith(Config.userAgentProduct)) {
// Retrieve `.../... (this part)` from the header.
final String meta = val.substring(
max(val.indexOf('(') + 1, 0),
val.endsWith(')') ? val.length - 1 : val.length,
);
// Header values are separated by semicolons.
final List<String> parts = meta.split(';');
// First part should have the name of operating system.
final String system = parts.first.trim();
// If there's no second part at all, return the first one right away.
if (parts.length < 2) {
return system;
}
// Android devices have an identifier that should be embedded into the
// second part of the header, thus should return it.
if (system.startsWith('Android')) {
return parts.elementAt(1).trim();
}
// The following systems have a device identifier that should be embedded
// into the second part of the header, thus should parse it with
// [AppleProductName] and return it.
if (system.startsWith('macOS') ||
system.startsWith('iOS') ||
system.startsWith('iPadOS') ||
system.startsWith('visionOS') ||
system.startsWith('watchOS') ||
system.startsWith('tvOS')) {
return AppleProductName().lookup(parts.elementAt(1).trim());
}
return system;
}
// Otherwise it may be a browser's `User-Agent` header.
else {
// Header values are separated by spaces.
final List<String> parts = val.split(' ');
// Browser's `User-Agent` may contain the `Version` tag.
final String? versionPart = parts.firstWhereOrNull(
(e) => e.startsWith('Version/'),
);
for (final BrowserRule e in _rules) {
// Lookup the part that is identifiable by any [BrowserRule] out there.
final int i = parts.indexWhere((p) => p.startsWith(e.rule));
if (i != -1) {
// `User-Agent` tag should be something like `Label/1.0.0`, and we
// need the number part, so try to retrieve it.
final List<String> tag = (versionPart ?? parts[i]).split('/');
if (tag.length > 1) {
String version = tag[1];
// If the [BrowserRule] requests the version to contain only
// specified depth, then trim it.
if (e.versionDepth != null) {
version =
version = version.split('.').take(e.versionDepth!).join('.');
}
return '${e.name} $version';
} else {
return e.name;
}
}
}
}
return val;
}