browserino 4.3.0 → 4.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -18,63 +18,68 @@ about their browser / OS versions.
18
18
  <details>
19
19
  <summary>Click to expand Table of Contents</summary>
20
20
  <ul>
21
+ <li><a href="#browserino">Browserino</a></li>
21
22
  <li><a href="#status">Status</a></li>
22
23
  <li><a href="#table-of-contents">Table of Contents</a></li>
23
24
  <li><a href="#sources">Sources</a></li>
24
25
  <li><a href="#changelog">Changelog</a><ul>
25
- <li><a href="#23-06-2018-version-424">23-06-2018 VERSION 4.2.4</a></li>
26
+ <li><a href="#23-06-2018-version-440">23-06-2018 VERSION 4.4.0</a></li>
27
+ <li><a href="#23-06-2018-version-430">23-06-2018 VERSION 4.3.0</a></li>
26
28
  <li><a href="#24-12-2017-version-423">24-12-2017 VERSION 4.2.3</a></li>
27
- <li><a href="#12-10-2017-version-422">12-10-2017 VERSION 4.2.2</a></li>
28
29
  </ul></li>
29
30
  <li><a href="#installation">Installation</a></li>
31
+ <li><a href="#rails--320">Rails (>= 3.2.0)</a><ul>
32
+ <li><a href="#initializer">Initializer</a></li>
33
+ </ul></li>
30
34
  <li><a href="#usage">Usage</a><ul>
31
- <li><a href="#rails--320">Rails (>= 3.2.0)</a><ul>
32
- <li><a href="#initializer">Initializer</a></li>
35
+ <li><a href="#client">Client</a></li>
36
+ <li><a href="#formatting">Formatting</a><ul>
37
+ <li><a href="#non-version-like-properties">Non version-like properties</a></li>
38
+ <li><a href="#version-like-properties">Version-like properties</a></li>
39
+ </ul></li>
40
+ <li><a href="#config">Config</a><ul>
41
+ <li><a href="#matchers">Matchers</a></li>
42
+ <li><a href="#aliasses">Aliasses</a></li>
43
+ <li><a href="#labels">Labels</a></li>
44
+ <li><a href="#http-headers">HTTP headers</a></li>
45
+ </ul></li>
46
+ <li><a href="#methods">Methods</a><ul>
47
+ <li><a href="#name">name</a></li>
48
+ <li><a href="#namesym-opts--">name?(sym, opts = {})</a></li>
49
+ <li><a href="#version">version</a></li>
50
+ <li><a href="#versionversion">version?(version)</a></li>
51
+ <li><a href="#engine">engine</a></li>
52
+ <li><a href="#enginesym-opts--">engine?(sym, opts = {})</a></li>
53
+ <li><a href="#engine_version">engine_version</a></li>
54
+ <li><a href="#engine_versionversion">engine_version?(version)</a></li>
55
+ <li><a href="#platform">platform</a></li>
56
+ <li><a href="#platformsym-opts--">platform?(sym, opts = {})</a></li>
57
+ <li><a href="#platform_label">platform_label</a></li>
58
+ <li><a href="#platform_version">platform_version</a></li>
59
+ <li><a href="#platform_versionversion">platform_version?(version)</a></li>
60
+ <li><a href="#device">device</a></li>
61
+ <li><a href="#devicesym">device?(sym)</a></li>
62
+ <li><a href="#architecture">architecture</a></li>
63
+ <li><a href="#architecturesym">architecture?(sym)</a></li>
64
+ <li><a href="#locale">locale</a></li>
65
+ <li><a href="#locale-1">locale?</a></li>
66
+ <li><a href="#locales">locales</a></li>
67
+ <li><a href="#locales-1">locales?</a></li>
68
+ <li><a href="#x64">x64?</a></li>
69
+ <li><a href="#x32">x32?</a></li>
70
+ <li><a href="#mobile-and-mobile">mobile and #mobile?</a></li>
71
+ <li><a href="#type">type</a></li>
72
+ <li><a href="#typesym">type?(sym)</a></li>
73
+ <li><a href="#like">like</a></li>
74
+ <li><a href="#likesym-opts--">like?(sym, opts = {})</a></li>
75
+ <li><a href="#issym-opts--">is?(sym, opts = {})</a></li>
76
+ <li><a href="#not">not</a></li>
77
+ <li><a href="#notsym-opts--">not?(sym, opts = {})</a></li>
33
78
  </ul></li>
34
- <li><a href="#general">General</a><ul>
35
- <li><a href="#client">Client</a></li>
36
- <li><a href="#formatting">Formatting</a><ul>
37
- <li><a href="#non-version-like-properties">Non version-like properties</a></li>
38
- <li><a href="#version-like-properties">Version-like properties</a></li>
39
- </ul></li>
40
- <li><a href="#config">Config</a><ul>
41
- <li><a href="#matchers">Matchers</a></li>
42
- <li><a href="#aliasses">Aliasses</a></li>
43
- <li><a href="#labels">Labels</a></li>
44
- </ul></li>
45
- <li><a href="#methods">Methods</a><ul>
46
- <li><a href="#name">\#name</a></li>
47
- <li><a href="#namesym-opts--">\#name?(sym, opts = {})</a></li>
48
- <li><a href="#version">\#version</a></li>
49
- <li><a href="#versionversion">\#version?(version)</a></li>
50
- <li><a href="#engine">\#engine</a></li>
51
- <li><a href="#enginesym-opts--">\#engine?(sym, opts = {})</a></li>
52
- <li><a href="#engine_version">\#engine_version</a></li>
53
- <li><a href="#engine_versionversion">\#engine_version?(version)</a></li>
54
- <li><a href="#platform">\#platform</a></li>
55
- <li><a href="#platformsym-opts--">\#platform?(sym, opts = {})</a></li>
56
- <li><a href="#platform_label">\#platform_label</a></li>
57
- <li><a href="#platform_version">\#platform_version</a></li>
58
- <li><a href="#platform_versionversion">\#platform_version?(version)</a></li>
59
- <li><a href="#device">\#device</a></li>
60
- <li><a href="#devicesym">\#device?(sym)</a></li>
61
- <li><a href="#architecture">\#architecture</a></li>
62
- <li><a href="#architecturesym">\#architecture?(sym)</a></li>
63
- <li><a href="#x64">\#x64?</a></li>
64
- <li><a href="#x32">\#x32?</a></li>
65
- <li><a href="#mobile-and-mobile">\#mobile and #mobile?</a></li>
66
- <li><a href="#type">\#type</a></li>
67
- <li><a href="#typesym">\#type?(sym)</a></li>
68
- <li><a href="#like">\#like</a></li>
69
- <li><a href="#likesym-opts--">\#like?(sym, opts = {})</a></li>
70
- <li><a href="#issym-opts--">\#is?(sym, opts = {})</a></li>
71
- <li><a href="#not">\#not</a></li>
72
- <li><a href="#notsym-opts--">\#not?(sym, opts = {})</a></li>
73
- </ul></li>
74
- <li><a href="#magic-methods">Magic methods</a><ul>
75
- <li><a href="#names">Names</a></li>
76
- <li><a href="#aliasses-1">Aliasses</a></li>
77
- </ul></li></ul></li></ul></li>
79
+ <li><a href="#magic-methods">Magic methods</a><ul>
80
+ <li><a href="#names">Names</a></li>
81
+ <li><a href="#aliasses-1">Aliasses</a></li>
82
+ </ul></li></ul></li>
78
83
  <li><a href="#supported">Supported</a><ul>
79
84
  <li><a href="#browsers">Browsers</a></li>
80
85
  <li><a href="#bots">Bots</a></li>
@@ -104,15 +109,51 @@ Many thanks to the creators and maintainers of the following sources of user age
104
109
  - [whatismybrowser.com](https://www.whatismybrowser.com/developers/tools/user-agent-parser/browse)
105
110
  - [mobile247.eu](http://www.mobile247.eu/online-tools/user-agent-strings)
106
111
  - [commons.wikimedia.org browser timeline](https://commons.wikimedia.org/wiki/File:Timeline_of_web_browsers.svg)
107
-
108
- ---
112
+ - [browscap database (github repo)](https://github.com/browscap/browscap/tree/master/resources/user-agents)
109
113
 
110
114
  ## Changelog
111
115
 
112
116
  _dates are in dd-mm-yyyy format_
113
117
  older changes can be found in the [changelog](/projects/browserino/changelog/)
114
118
 
115
- ### 23-06-2018 VERSION 4.2.4
119
+ ### 23-06-2018 VERSION 4.4.0
120
+
121
+ - Update: Gem dependencies
122
+ - Add: ability to supply HTTP headers to Browserino for extra information
123
+ - Improve: location will be detected from HTTP headers when available (on by default in Rails)
124
+ - Add: [`prop_missing`](#http-headers) DSL for last-minute info gathering
125
+ - Add: Android `:pie` label
126
+ - Add: `:falkon` alias for `:qupzilla`
127
+ `orange_browser`
128
+ - Add: `:alohabrowser`
129
+ - Add: `:iris`
130
+ - Add: `:otter`
131
+ - Add: `:chedot`
132
+ - Add: `:cm_browser`
133
+ - Add: `:diglo`
134
+ - Add: `:diigo_browser`
135
+ - Add: `:flyflow`
136
+ - Add: `:freebox`
137
+ - Add: `:kuaiso`
138
+ - Add: `:lovense`
139
+ - Add: `:slimjet`
140
+ - Add: `:zetakey`
141
+ - Add: `:wkbrowser`
142
+ - Add: `:yolobrowser`
143
+ - Add: `:whale`
144
+ - Add: `:vivo`
145
+ - Add: `:jasmine`
146
+ - Add: `:seraphic_sraf`
147
+ - Add: `:phantomjs`
148
+ - Add: `:slimerjs`
149
+ - Add: `:liebao`
150
+ - Add: `:w3m`
151
+ - Add: `:charon`
152
+ - Add: `:cent`
153
+ - Add: `:jig_browser_web`
154
+ - Add: `:blazer`
155
+
156
+ ### 23-06-2018 VERSION 4.3.0
116
157
 
117
158
  - Add macOS `mojave` label
118
159
  - Add generic `android_*` labels for android versions `p` through `z`.
@@ -122,10 +163,6 @@ older changes can be found in the [changelog](/projects/browserino/changelog/)
122
163
  - Loosened some Android label version ranges
123
164
  - `Browserino::Version` can now also parse floats float `1.1` equals major version 1, minor version 1, patch level 0
124
165
 
125
- ### 12-10-2017 VERSION 4.2.2
126
-
127
- - Added support for `high_sierra`
128
-
129
166
  ## Installation
130
167
 
131
168
  Add this line to your application's Gemfile:
@@ -146,16 +183,6 @@ Or install it yourself with:
146
183
  $ gem install browserino
147
184
  ```
148
185
 
149
- Browserino is tested with the following ruby versions
150
-
151
- - 2.0.0
152
- - 2.1.0
153
- - 2.2.0
154
- - 2.3.0
155
- - 2.4.0
156
-
157
- ## Usage
158
-
159
186
  After installing the gem globally or in your application you'll have to `require` the gem before being able to use it.
160
187
 
161
188
  ```ruby
@@ -165,12 +192,27 @@ require 'browserino'
165
192
  Afterwards, the gem is loaded and you can proceed by calling:
166
193
 
167
194
  ```ruby
168
- Browserino.parse '<user agent>'
195
+ Browserino.parse '<user agent>'[, {'request-header' => 'header-value', ...}]
169
196
  ```
170
197
 
171
- ### Rails (>= 3.2.0)
198
+ The first argument to `Browserino.parse` is a _user agent_ string. This is the string that browsers send to webservers for identification.
199
+ The second (optional) argument to `Browserino.parse` is a hash that contains HTTP headers. When a property could not be found, these headers
200
+ will be used by Browserino to attempt to extract it from there if a `prop_missing` handler is defined for it.
201
+
172
202
 
173
- If you're using Rails (>= 3.2.0) you'll have access to a `client` object. Browserino will initialize itself using the `request.headers['User-Agent']`
203
+ Browserino is tested with the following ruby versions
204
+
205
+ - 2.0.0
206
+ - 2.1.0
207
+ - 2.2.0
208
+ - 2.3.0
209
+ - 2.4.0
210
+ - 2.5.0
211
+
212
+ ## Rails (>= 3.2.0)
213
+
214
+ If you're using Rails (>= 3.2.0) you'll have access to a `client` object. Browserino will initialize itself using `request.headers['User-Agent']` and will also use Rails `request.headers` to find
215
+ extra information that could not be found in the user agent (e.g. user locales).
174
216
 
175
217
 
176
218
  A quick example on how to get going:
@@ -183,7 +225,7 @@ class ExampleController < ApplicationController
183
225
  end
184
226
  ```
185
227
 
186
- #### Initializer
228
+ ### Initializer
187
229
 
188
230
  If you would like to extend Browserino within your rails app, this is certainly possible.
189
231
  Create a file _config/initializers/browserino.rb_ and add the following:
@@ -196,9 +238,9 @@ end
196
238
 
197
239
  Please skip ahead to the [**Config**](#config) part of the documentation, that section contains information on how to make use of Browserino's builtin DSL
198
240
 
199
- ### General
241
+ ## Usage
200
242
 
201
- #### Client
243
+ ### Client
202
244
 
203
245
  the `parse` method will **always** return a `Browserino::Client` object. This object is special in that it simply resonds to everything. If a property does not exist or isn't defined on the current instance of `client` then it will simply return `nil`. Parsing an empty user agent will result in the following output:
204
246
 
@@ -207,15 +249,17 @@ client = Browserino.parse ''
207
249
  client.is_a? Browserino::Client # => true
208
250
  ```
209
251
 
210
- #### Formatting
252
+ ### Formatting
211
253
 
212
254
  This section explains the output / return values given by calling a method on an instantiated `Browserino::client` object.
213
255
 
214
- ##### Non version-like properties
256
+ #### Non version-like properties
215
257
 
216
- Non-version-like properties are properties that are not solely digits seperated by a delimiter like '.' or '_'.
217
- All the non-version-like property values will be formatted in the following order:
258
+ Non-version-like properties are properties that are not solely digits seperated by a delimiter like '.' or '\_'.
259
+ All the non-version-like property values (which aren't `Array` or `Hash` instances) will be formatted in the following order:
218
260
 
261
+ - skip following steps if `Array` or `Hash`
262
+ - stringify value
219
263
  - lowercase all characters
220
264
  - strip spaces on either side
221
265
  - replace one or more spaces or dashes with a single underscore (`_`)
@@ -231,7 +275,7 @@ client.engine # => :gecko
231
275
  client.platform_label # => :windows7
232
276
  ```
233
277
 
234
- ##### Version-like properties
278
+ #### Version-like properties
235
279
 
236
280
  All the version-like property values will be converted to `Browserino::Version` objects.
237
281
  These objects are comparable to numbers and version-like strings (e.g. `'1.2.4'`)
@@ -261,9 +305,9 @@ client.version >= '37.0.2000' # => true
261
305
  client.version > '37.1.2000' # => false
262
306
  ```
263
307
 
264
- #### Config
308
+ ### Config
265
309
 
266
- ##### Matchers
310
+ #### Matchers
267
311
 
268
312
  Browserino is based on a concept of _matchers_, a matcher is a single client entity.
269
313
  They are defined in a `Browserino.config.define { ... }` block. A small example:
@@ -282,6 +326,7 @@ client.to_h
282
326
  # => { :name => :mybrowser,
283
327
  # :type => :browser,
284
328
  # :locale => nil,
329
+ # :locales => [],
285
330
  # :architecture => nil,
286
331
  # :mobile => false,
287
332
  # :smarttv => false,
@@ -453,7 +498,7 @@ What the above code does is, if no `version` property has been supplied to a mat
453
498
 
454
499
  If you supply your own `version` property, this `smart_matcher` will not be applied.
455
500
 
456
- ##### Aliasses
501
+ #### Aliasses
457
502
 
458
503
  Aliasses are a bit simpler than `Matchers`, they look like this taken from the [source](https://github.com/SidOfc/browserino/blob/master/lib/browserino/definitions/aliasses.rb):
459
504
 
@@ -478,7 +523,7 @@ end
478
523
  What they do is they look for a value within the properties of a specific client and if found, all the aliasses specified will also be applied to that client.
479
524
  This means that for a `client.is? :firefox` you can do `client.is? :ff` or `client.ff?` instead. This works for all the names like `name, label`, `engine`, `engine_label`, `platform` and `platform_label`
480
525
 
481
- ##### Labels
526
+ #### Labels
482
527
 
483
528
  A label could be a codename or a specific OS name for instance, it applies to a name and it's respective version combination.
484
529
  It autodetects against which version it should match, this will always be the correct version. Here are some examples (also not the complete file - [source](https://github.com/SidOfc/browserino/blob/master/lib/browserino/definitions/labels.rb)):
@@ -494,11 +539,59 @@ end
494
539
 
495
540
  So now it looks for a value of `:macintosh` in the properties gathered from a client, if it finds it, it will remember it's key (e.g. `platform` in this case.) and use it to find out the current version (e.g. `platform_version` in this case). If a version is supplied it will be compared to be `>= min` and `<= max` (which is inclusive) where `min` and `max` are the left and right values of the `range` option respectively.
496
541
 
497
- #### Methods
542
+ #### HTTP headers
543
+
544
+ Browserino as of version `4.4.0` accepts a hash of HTTP headers as a second argument. This adds more detailed information (primarily `#locales` property is added and `#locale` is read from it when not found).
545
+ For Rails, this is already implemented and will work out of the box, adding support for it is as simple as supplying a `Hash` of HTTP headers (say, what you get from a `request.headers` in Rails or `request` from Sinatra) as second argument to `Browserino.parse`.
546
+
547
+ This user agent does not have a locale but when we supply the `HTTP_ACCEPT_LANGUAGE` (or just `Accept-Language`) header it will find _all_ languages ordered by _user preference_ in a `#locales` property.
548
+ For the [`#locale`](#locale) itself, if it is not found it will attempt to use [`#locales.first`](#locales):
549
+
550
+ ```ruby
551
+ client = Browserino.parse(
552
+ 'Mozilla/5.0 (Linux; Android 5.1; ZTE Blade L6 Build/LMY47I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.91 Mobile Safari/537.36',
553
+ {'HTTP_ACCEPT_LANGUAGE' => 'en-US,en;q=0.9,nl-NL;q=0.6,nl;q=0.7'}
554
+ )
555
+
556
+ client.locales
557
+ # => [:en_us :en :nl :nl_nl]
558
+
559
+ client.locale
560
+ # => :en_us
561
+ ```
562
+
563
+ The behavior is defined by `prop_missing` hooks which will be run _just_ before a new `Client` (and _after_ all data gathering / processing is done) is initialized.
564
+ The hooks for `:locales` and `:locale` look like this:
565
+
566
+ ```ruby
567
+ Browserino.config.define do
568
+ prop_missing :locales do |http_headers|
569
+ http_headers[:accept_language]
570
+ .to_s.scan(/(\w{2}(?:[_\-]\w{2})?)(?:;q=([\d.]+))?/i)
571
+ .map { |(locale, quality)| [locale, (quality || 1).to_f] }
572
+ .sort_by { |a| -a[1] }
573
+ .map(&:first)
574
+ end
575
+
576
+ prop_missing :locale do |_http_headers, props|
577
+ props[:locales].first
578
+ end
579
+ end
580
+ ```
581
+
582
+ The first block argument is a processed version of a hash with HTTP headers.
583
+ Keys of this hash are "normalized", any `HTTP_` prefix is removed, `-` is replaced with `_` and finally the key is lowercased and converted to a symbol.
584
+ This allows you to pass in raw header names as seen in the request like `Accept-Language` or Rails / Sinatra (read: rack) HTTP headers like `HTTP_ACCEPT_LANGUAGE`. Both will end up as `:accept_language` allowing for easy usage.
585
+
586
+ The second block argument are the processed properties. This is _all_ the information from the UA / HTTP headers that Browserino could find combined.
587
+
588
+ What you may also notice here is that in the second `prop_missing` we are leveraging the first `prop_missing`. They are executed in order of definition to make it easy to "chain" property fallbacks.
589
+
590
+ ### Methods
498
591
 
499
592
  The below methods are available by default, all methods with a questionmark at the end return either boolean `true` or `false` or `nil`.
500
593
 
501
- ##### \#name
594
+ #### #name
502
595
 
503
596
  Returns either a symbol containing the name of the agent or `nil` otherwise.
504
597
 
@@ -509,7 +602,7 @@ client.name
509
602
  # => :colibri
510
603
  ```
511
604
 
512
- ##### \#name?(sym, opts = {})
605
+ #### #name?(sym, opts = {})
513
606
 
514
607
  Returns true if supplied `sym` equals (`==`) the current `client.name`, if `opts` contains a `:version` key, it will be compared against `#version`
515
608
  Returns false if the supplied criteria doesn't match the current client.
@@ -534,7 +627,7 @@ client.name? :not_colibri, version: '1.0.0'
534
627
  # => nil
535
628
  ```
536
629
 
537
- ##### \#version
630
+ #### #version
538
631
 
539
632
  Returns a `Browserino::Version` object. This object allows for more flexible comparing of long version numbers where simple numbers or floats don't suffice.
540
633
 
@@ -563,7 +656,7 @@ client.version.full
563
656
  # => '1.0.0'
564
657
  ```
565
658
 
566
- ##### \#version?(version)
659
+ #### #version?(version)
567
660
 
568
661
  Returns true if the supplied version equals (`==`) the current clients version.
569
662
  Returns false otherwise
@@ -584,7 +677,7 @@ client.version? '1.0.1'
584
677
  # false
585
678
  ```
586
679
 
587
- ##### \#engine
680
+ #### #engine
588
681
 
589
682
  Returns either a symbol containing the engine of the agent or `nil` otherwise.
590
683
 
@@ -595,7 +688,7 @@ client.engine
595
688
  # => :webkit
596
689
  ```
597
690
 
598
- ##### \#engine?(sym, opts = {})
691
+ #### #engine?(sym, opts = {})
599
692
 
600
693
  Returns true if supplied `sym` equals (`==`) the current `client.version`, if `opts` contains a `:version` key, it will be compared against `#engine_version`
601
694
  Returns false if the supplied criteria doesn't match the current client.
@@ -620,7 +713,7 @@ client.engine? :not_webkit, version: '537.36'
620
713
  # => nil
621
714
  ```
622
715
 
623
- ##### \#engine_version
716
+ #### #engine_version
624
717
 
625
718
  Returns a [`Browserino::Version`](#version) object.
626
719
 
@@ -639,7 +732,7 @@ client.engine_version.full
639
732
  # => '537.36'
640
733
  ```
641
734
 
642
- ##### \#engine_version?(version)
735
+ #### #engine_version?(version)
643
736
 
644
737
  Returns true if the supplied version equals (`==`) the current clients engine_version.
645
738
  Returns false otherwise
@@ -651,7 +744,7 @@ client.engine_version? '537.36'
651
744
  # true
652
745
  ```
653
746
 
654
- ##### \#platform
747
+ #### #platform
655
748
 
656
749
  Returns either a symbol containing the platform of the agent or `nil` otherwise.
657
750
 
@@ -662,7 +755,7 @@ client.platform
662
755
  # => :macintosh
663
756
  ```
664
757
 
665
- ##### \#platform?(sym, opts = {})
758
+ #### #platform?(sym, opts = {})
666
759
 
667
760
  Returns true if supplied `sym` equals (`==`) the current `client.platform`, if `opts` contains a `:version` key, it will be compared against `#platform_version`
668
761
  Returns false if the supplied criteria doesn't match the current client.
@@ -687,7 +780,7 @@ client.platform? :not_macintosh, version: '10.12.1'
687
780
  # => nil
688
781
  ```
689
782
 
690
- ##### \#platform_label
783
+ #### #platform_label
691
784
 
692
785
  Returns either a symbol containing the platform_label of the agent or `nil` otherwise.
693
786
 
@@ -704,7 +797,7 @@ client2.platform_label
704
797
  # => :nougat
705
798
  ```
706
799
 
707
- ##### \#platform_version
800
+ #### #platform_version
708
801
 
709
802
  Returns a [`Browserino::Version`](#version) object.
710
803
 
@@ -723,7 +816,7 @@ client.platform_version.full
723
816
  # => '10.12.1'
724
817
  ```
725
818
 
726
- ##### \#platform_version?(version)
819
+ #### #platform_version?(version)
727
820
 
728
821
  Returns true if the supplied version equals (`==`) the current clients platform_version.
729
822
  Returns false otherwise
@@ -734,7 +827,7 @@ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) Apple
734
827
  client.platform_version? '10.12'
735
828
  # => true
736
829
  ```
737
- ##### \#device
830
+ #### #device
738
831
 
739
832
  Returns either a symbol containing the device of the client or `nil` otherwise
740
833
 
@@ -745,7 +838,7 @@ client.device
745
838
  # => :zte
746
839
  ```
747
840
 
748
- ##### \#device?(sym)
841
+ #### #device?(sym)
749
842
 
750
843
  Returns true if the supplied sym equals (`==`) the current clients device.
751
844
 
@@ -756,7 +849,7 @@ client.device
756
849
  # => :zte
757
850
  ```
758
851
 
759
- ##### \#architecture
852
+ #### #architecture
760
853
 
761
854
  Returns either `nil`, `:x32` or `:x64` depending on wether it could be found in the user agent
762
855
 
@@ -771,7 +864,7 @@ client2.architecture
771
864
  # => :x64
772
865
  ```
773
866
 
774
- ##### \#architecture?(sym)
867
+ #### #architecture?(sym)
775
868
 
776
869
  sym must be one of `:x32` or `:x64`, returns `true` if it matches the current client architecture, false otherwise.
777
870
 
@@ -781,8 +874,57 @@ client = Browserino.parse 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) Apple
781
874
  client.architecture? :x64
782
875
  # => false
783
876
  ```
877
+ #### #locale
878
+
879
+ Returns either `nil` or a locale if present. Locales are formatted like `:en_us` for `en-US` and `en_US` and just `:en` for `en`.
880
+
881
+ ```ruby
882
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; U; Macintosh; en-US; Valve Steam GameOverlay/1329175982; ) AppleWebKit/534.1 (KHTML, like Gecko) Chrome/6.0.444.0 Safari/534.1'
883
+
884
+ client.locale
885
+ # => :en_us
886
+ ```
887
+ #### #locale?
888
+
889
+ Returns `true` or `false` based on locale presence.
890
+
891
+ ```ruby
892
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; U; Macintosh; en-US; Valve Steam GameOverlay/1329175982; ) AppleWebKit/534.1 (KHTML, like Gecko) Chrome/6.0.444.0 Safari/534.1'
893
+
894
+ client.locale?
895
+ # => true
896
+ ```
897
+ #### #locales
898
+
899
+ Returns an array of locales found in `Accept-Language` HTTP header. This only works when `Browserino.parse` is invoked with a hash containing the headers as second argument.
900
+ When locales are found using this method, they will be used instead of the [`#locale`](#locale) found in the user agent (the locale will be replaced with the highest quality locale from the header).
901
+
902
+ ```ruby
903
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; U; Macintosh; pt-BR; Valve Steam GameOverlay/1329175982; ) AppleWebKit/534.1 (KHTML, like Gecko) Chrome/6.0.444.0 Safari/534.1',
904
+ {'HTTP_ACCEPT_LANGUAGE' => 'en-US,en;q=0.9,nl-NL;q=0.8,nl;q=0.7'}
905
+
906
+ # locale is :en_us because it is present in headers and thus overwrites :pt_br
907
+ client.locale
908
+ # => :en_us
909
+
910
+ # the :pt_br locale gets added as the least preferred locale instead
911
+ client.locales
912
+ # => [:en_us, :en, :nl_nl, :nl, :pt_br]
913
+ ```
914
+
915
+ #### #locales?
916
+
917
+ Returns `true` or `false` depending on wether any locales were found at all (e.g. from UA and/or HTTP headers).
918
+
919
+ ```ruby
920
+ client = Browserino.parse 'Mozilla/5.0 (Macintosh; U; Macintosh; pt-BR; Valve Steam GameOverlay/1329175982; ) AppleWebKit/534.1 (KHTML, like Gecko) Chrome/6.0.444.0 Safari/534.1',
921
+ {'HTTP_ACCEPT_LANGUAGE' => 'en-US,en;q=0.9,nl-NL;q=0.8,nl;q=0.7'}
922
+
923
+ client.locales?
924
+ # => true
925
+ ```
784
926
 
785
- ##### \#x64?
927
+ #### #x64?
786
928
 
787
929
  A shorthand for `client.architecture? :x64` returns a boolean value
788
930
 
@@ -793,7 +935,7 @@ client.x64?
793
935
  # => false
794
936
  ```
795
937
 
796
- ##### \#x32?
938
+ #### #x32?
797
939
 
798
940
  A shorthand for `client.architecture? :x32` returns a boolean value
799
941
 
@@ -804,7 +946,7 @@ client.x32?
804
946
  # => false
805
947
  ```
806
948
 
807
- ##### \#mobile and #mobile?
949
+ #### #mobile and #mobile?
808
950
 
809
951
  Returns boolean `true` or `false` depending on wether the device user agent is a mobile device
810
952
 
@@ -817,7 +959,7 @@ client.mobile?
817
959
  # => false
818
960
  ```
819
961
 
820
- ##### \#type
962
+ #### #type
821
963
 
822
964
  There are currently 6 types defined, `:browser`, `:bot`, `:library`, `:validator`, `:email` and `:unknown` _(default)_
823
965
  This method simply returns the type of the current client, e.g.
@@ -829,7 +971,7 @@ client.type
829
971
  # => :browser
830
972
  ```
831
973
 
832
- ##### \#type?(sym)
974
+ #### #type?(sym)
833
975
 
834
976
  Returns true if `sym` equals (`==`) the current clients type
835
977
 
@@ -843,7 +985,7 @@ client.type? :bot
843
985
  # => false
844
986
  ```
845
987
 
846
- ##### \#like
988
+ #### #like
847
989
 
848
990
  Like is something different. Within the defaults a few browsers are defined to be `like` others. This is the full list:
849
991
 
@@ -980,7 +1122,7 @@ client == client.like
980
1122
  # => true
981
1123
  ```
982
1124
 
983
- ##### \#like?(sym, opts = {})
1125
+ #### #like?(sym, opts = {})
984
1126
 
985
1127
  This method acts much like the `name?` method on a client except that like `like` method will match a broader set of things like it.
986
1128
  Additionally, you can also supply an optional `:version` option which will then be compared to the `like.version` property.
@@ -1008,16 +1150,16 @@ client.like? :firefox
1008
1150
  # => false
1009
1151
  ```
1010
1152
 
1011
- ##### \#is?(sym, opts = {})
1153
+ #### #is?(sym, opts = {})
1012
1154
 
1013
1155
  The `is?` method is a bit more loose, it will recognize what it is and what it isn't automagically depending on what's passed in.
1014
1156
  It can be a more general replacement for [#name?](#name), [#engine?](#engine) and [#platform?](#platform)
1015
1157
 
1016
- ##### \#not
1158
+ #### #not
1017
1159
 
1018
1160
  Inverts the result returned by any method ending in a question mark (e.g. `client.version? == true && client.not.version? == false`)
1019
1161
 
1020
- ##### \#not?(sym, opts = {})
1162
+ #### #not?(sym, opts = {})
1021
1163
 
1022
1164
  An inverted version of `#is?`
1023
1165
 
@@ -1065,9 +1207,9 @@ client.not? :webkit, version: 537
1065
1207
  # => false
1066
1208
  ```
1067
1209
 
1068
- #### Magic methods
1210
+ ### Magic methods
1069
1211
 
1070
- ##### Names
1212
+ #### Names
1071
1213
 
1072
1214
  For each of `#name`, `#engine`, `#platform`, `#platform_label` and `#device`, upon instantiation of the current client object, the **results** of these methods will also be defined as methods if they aren't nil e.g:
1073
1215
 
@@ -1159,7 +1301,7 @@ client.el_capitan? '10.10'
1159
1301
  # => true
1160
1302
  ```
1161
1303
 
1162
- ##### Aliasses
1304
+ #### Aliasses
1163
1305
 
1164
1306
  For each of the defined keys in `Browserino.config.aliasses` that matches with any value of `#name`, `#engine`, `#platform` or `#platform_label`, define every alias as a method.
1165
1307
 
@@ -1253,11 +1395,12 @@ client.platform? :macos, version: '10.10'
1253
1395
 
1254
1396
  ### Browsers
1255
1397
 
1256
- `aol`, `ion`, `foxy`, `lobo`, `kkman`, `irider`, `sleipnir`, `netcaptor`, `sitekiosk`, `gomezagent`, `solid_core`, `simulbrowse`, `crazy_browser`, `enigma_browser`, `tencenttraveler`, `deepnet_explorer`, `sogou_browser`, `netflix_desktop`, `browzar`, `theworld`, `smart_bro`, `slimbrowser`, `greenbrowser`, `avant_browser`, `orca`, `pogo`, `epic`, `kylo`, `wyzo`, `light`, `prism`, `strata`, `vision`, `galeon`, `icecat`, `minimo`, `beonex`, `kmlite`, `kapiko`, `madfox`, `iceape`, `fennec`, `sylera`, `myibrow`, `lorentz`, `lolifox`, `chimera`, `sundial`, `bonecho`, `k_ninja`, `k_meleon`, `netscape`, `conkeror`, `vonkeror`, `firebird`, `songbird`, `namoroka`, `cyberfox`, `palemoon`, `swiftfox`, `cunaguaro`, `icedragon`, `blackbird`, `cometbird`, `classilla`, `shiretoko`, `lunascape`, `superswan`, `lightning`, `multizilla`, `seamonkey`, `iceweasel`, `enigmafox`, `kazehakase`, `tenfourfox`, `swiftweasel`, `granparadiso`, `maemo_browser`, `sailfishbrowser`, `monyq`, `waterfox`, `minefield`, `fireweb_navigator`, `camino`, `maemo`, `opera_mobile`, `blackberry_browser`, `webosbrowser`, `leechcraft`, `kindle`, `nook`, `xiaomi_miui`, `qt`, `coda`, `silk`, `bolt`, `icab`, `raptr`, `maple`, `arora`, `coast`, `rekonq`, `mercury`, `skyfire`, `omniweb`, `teashark`, `cheshire`, `stainless`, `webbrowser`, `mqqbrowser`, `nokiabrowser`, `samsungbrowser`, `playbook_browser`, `obigo`, `qtweb_browser`, `maxthon_nitro`, `nichrome`, `iron`, `hana`, `perk`, `brave`, `swing`, `kinza`, `fluid`, `amigo`, `puffin`, `origin`, `yowser`, `iridium`, `colibri`, `vivaldi`, `safepay`, `slimboat`, `coolnovo`, `rockmelt`, `polarity`, `chromeum`, `yabrowser`, `qqbrowser`, `awesomium`, `mxbrowser`, `fabrowser`, `blackhawk`, `taobrowser`, `bluechrome`, `chromeplus`, `comodo_dragon`, `coc_coc_browser`, `whitehat_aviator`, `steam`, `maxthon`, `ucbrowser`, `edge`, `opera_mini`, `opera`, `escape`, `flock`, `sunrise`, `ie`, `origyn`, `webpositive`, `nintendobrowser`, `deskbrowse`, `qupzilla`, `midori`, `shiira`, `element_browser`, `amigavoyager`, `browse`, `mothra`, `surf`, `spray_can`, `bunjalloo`, `inet_browser`, `webpro`, `sundance`, `ibm_webexplorer`, `navscape`, `firefox`, `chrome`, `safari`, `tizenbrowser`, `epiphany`, `uzbl`, `roccat`, `dolfin`, `dooble`, `adobeair`, `abrowse`, `vimprobable`, `osb_browser`, `edbrowse`, `amaya`, `lynx`, `linemode`, `elinks`, `netpositive`, `mucommander`, `onebrowser`, `flashfire`, `konqueror`, `cyberdog`, `offbyone`, `hotjava`, `netsurf`, `contiki`, `mosaic`, `netbox`, `dillo`, `ice_browser`, `emacs`, `openwave_browser`, `alienblue`, `ovibrowser`, `links`, `oregano`, `browsex`, `doris`, `retawq`
1398
+ `aol`, `ion`, `foxy`, `lobo`, `kkman`, `irider`, `sleipnir`, `netcaptor`, `sitekiosk`, `gomezagent`, `solid_core`, `simulbrowse`, `crazy_browser`, `enigma_browser`, `tencenttraveler`, `deepnet_explorer`, `sogou_browser`, `netflix_desktop`, `browzar`, `theworld`, `smart_bro`, `slimbrowser`, `greenbrowser`, `avant_browser`, `orca`, `pogo`, `epic`, `kylo`, `wyzo`, `light`, `prism`, `strata`, `vision`, `galeon`, `icecat`, `minimo`, `beonex`, `kmlite`, `kapiko`, `madfox`, `iceape`, `fennec`, `sylera`, `myibrow`, `lorentz`, `lolifox`, `chimera`, `sundial`, `bonecho`, `k_ninja`, `k_meleon`, `netscape`, `conkeror`, `vonkeror`, `firebird`, `songbird`, `namoroka`, `cyberfox`, `palemoon`, `swiftfox`, `cunaguaro`, `icedragon`, `blackbird`, `cometbird`, `classilla`, `shiretoko`, `lunascape`, `superswan`, `lightning`, `multizilla`, `seamonkey`, `iceweasel`, `enigmafox`, `kazehakase`, `tenfourfox`, `swiftweasel`, `granparadiso`, `maemo_browser`, `sailfishbrowser`, `monyq`, `waterfox`, `minefield`, `fireweb_navigator`, `camino`, `maemo`, `opera_mobile`, `blackberry_browser`, `webosbrowser`, `leechcraft`, `kindle`, `nook`, `xiaomi_miui`, `qt`, `coda`, `silk`, `bolt`, `icab`, `raptr`, `maple`, `arora`, `coast`, `rekonq`, `mercury`, `skyfire`, `omniweb`, `teashark`, `cheshire`, `stainless`, `webbrowser`, `mqqbrowser`, `nokiabrowser`, `samsungbrowser`, `playbook_browser`, `obigo`, `qtweb_browser`, `maxthon_nitro`, `nichrome`, `iron`, `hana`, `perk`,
1399
+ `brave`, `swing`, `kinza`, `fluid`, `amigo`, `puffin`, `origin`, `yowser`, `iridium`, `colibri`, `vivaldi`, `safepay`, `slimboat`, `coolnovo`, `rockmelt`, `polarity`, `chromeum`, `yabrowser`, `qqbrowser`, `awesomium`, `mxbrowser`, `fabrowser`, `blackhawk`, `taobrowser`, `bluechrome`, `chromeplus`, `comodo_dragon`, `coc_coc_browser`, `whitehat_aviator`, `steam`, `maxthon`, `ucbrowser`, `edge`, `opera_mini`, `opera`, `escape`, `flock`, `sunrise`, `ie`, `origyn`, `webpositive`, `nintendobrowser`, `deskbrowse`, `qupzilla`, `midori`, `shiira`, `element_browser`, `amigavoyager`, `browse`, `mothra`, `surf`, `spray_can`, `bunjalloo`, `inet_browser`, `webpro`, `sundance`, `ibm_webexplorer`, `navscape`, `firefox`, `chrome`, `safari`, `tizenbrowser`, `epiphany`, `uzbl`, `roccat`, `dolfin`, `dooble`, `adobeair`, `abrowse`, `vimprobable`, `osb_browser`, `edbrowse`, `amaya`, `lynx`, `linemode`, `elinks`, `netpositive`, `mucommander`, `onebrowser`, `flashfire`, `konqueror`, `cyberdog`, `offbyone`, `hotjava`, `netsurf`, `contiki`, `mosaic`, `netbox`, `dillo`, `ice_browser`, `emacs`, `openwave_browser`, `alienblue`, `ovibrowser`, `links`, `oregano`, `browsex`, `doris`, `retawq`, `orange_browser`, `alohabrowser`, `iris`, `otter`, `chedot`, `cm_browser`, `diglo`, `diigo_browser`, `flyflow`, `freebox`, `kuaiso`, `lovense`, `slimjet`, `zetakey`, `wkbrowser`, `yolobrowser`, `whale`, `vivo`, `jasmine`, `seraphic_sraf`, `phantomjs`, `slimerjs`, `liebao`, `w3m`, `charon`, `cent`, `jig_browser_web`, `blazer`
1257
1400
 
1258
1401
  ### Bots
1259
1402
 
1260
- `huaweisymantecspider`, `atomic_email_hunter`, `netresearchserver`, `auto_email_spider`, `flaming_attackbot`, `addsugarspiderbot`, `semanticdiscovery`, `xaldon_webspider`, `yooglifetchagent`, `keyword_density`, `mass_downloader`, `safetynet_robot`, `download_demon`, `internet_ninja`, `dataparksearch`, `boston_project`, `emailcollector`, `webemailextrac`, `sitelockspider`, `morning_paper`, `four_anything`, `aqua_products`, `arachnophilia`, `smartdownload`, `emeraldshield`, `womlpefactory`, `israelisearch`, `issuecrawler`, `jaxified_bot`, `stackrambler`, `turnitinbot`, `covario_ids`, `alkalinebot`, `yahoo_slurp`, `propowerbot`, `emailsiphon`, `backdoorbot`, `terrawizbot`, `searchsight`, `baiduspider`, `sandcrawler`, `fyberspider`, `linguee_bot`, `big_brother`, `yahooseeker`, `noxtrumbot`, `black_hole`, `blackwidow`, `sosospider`, `duckduckgo`, `beslistbot`, `twitterbot`, `linkdexbot`, `aitcsrobot`, `litefinder`, `mabontland`, `yasaklibot`, `httpclient`, `ahrefsbot`, `mojeekbot`, `incywincy`, `seznambot`, `girafabot`, `becomebot`, `dts_agent`, `emailwolf`, `googlebot`, `omgilibot`, `labelgrab`, `altavista`, `yandexbot`, `newsgator`, `instagram`, `pinterest`, `gurujibot`, `lapozzbot`, `mvaclient`, `ng_search`, `youdaobot`, `webcopier`, `ips_agent`, `yodaobot`, `ldspider`, `lexxebot`, `scoutjet`, `linkedin`, `bullseye`, `alexibot`, `whatsapp`, `facebook`, `getright`, `asterias`, `catchbot`, `discobot`, `geniebot`, `koepabot`, `synoobot`, `rufusbot`, `rampybot`, `mogimogi`, `lmspider`, `blowfish`, `superbot`, `valkyrie`, `yacybot`, `jyxobot`, `orbiter`, `polybot`, `accoona`, `mj12bot`, `aspider`, `blexbot`, `bspider`, `auresys`, `bingbot`, `gaisbot`, `zealbot`, `zspider`, `backrub`, `harvest`, `nymesis`, `radian6`, `scrubby`, `gcreep`, `snappy`, `vortex`, `tineye`, `zyborg`, `sqworm`, `qseero`, `pompos`, `solbot`, `ichiro`, `bizbot`, `msnbot`, `exabot`, `msrbot`, `dotbot`, `cosmos`, `ecatch`, `scrapy`, `tumblr`, `holmes`, `okhttp`, `mxbot`, `moget`, `occam`, `acoon`, `nutch`, `alexa`, `atomz`, `htdig`, `peew`, `yeti`, `wf84`, `vyu2`, `acoi`, `obot`, `ask`, `b2w`, `ipd`, `zao`, `furlbot`, `jakarta`, `oegp`, `lwebis`, `cerberian_drtrs`, `gigamega`, `sogou_spider`, `megaindex`, `gozilla`, `larbin`, `netseer`
1403
+ `huaweisymantecspider`, `atomic_email_hunter`, `netresearchserver`, `auto_email_spider`, `flaming_attackbot`, `addsugarspiderbot`, `semanticdiscovery`, `xaldon_webspider`, `yooglifetchagent`, `keyword_density`, `mass_downloader`, `safetynet_robot`, `download_demon`, `internet_ninja`, `dataparksearch`, `boston_project`, `emailcollector`, `webemailextrac`, `sitelockspider`, `morning_paper`, `four_anything`, `aqua_products`, `arachnophilia`, `smartdownload`, `emeraldshield`, `womlpefactory`, `israelisearch`, `issuecrawler`, `jaxified_bot`, `stackrambler`, `turnitinbot`, `covario_ids`, `alkalinebot`, `yahoo_slurp`, `propowerbot`, `emailsiphon`, `backdoorbot`, `terrawizbot`, `searchsight`, `baiduspider`, `sandcrawler`, `fyberspider`, `linguee_bot`, `big_brother`, `yahooseeker`, `noxtrumbot`, `black_hole`, `blackwidow`, `sosospider`, `duckduckgo`, `beslistbot`, `twitterbot`, `linkdexbot`, `aitcsrobot`, `litefinder`, `mabontland`, `yasaklibot`, `httpclient`, `ahrefsbot`, `mojeekbot`, `incywincy`, `seznambot`, `girafabot`, `becomebot`, `dts_agent`, `emailwolf`, `googlebot`, `omgilibot`, `labelgrab`, `altavista`, `yandexbot`, `newsgator`, `instagram`, `pinterest`, `gurujibot`, `lapozzbot`, `mvaclient`, `ng_search`, `youdaobot`, `webcopier`, `ips_agent`, `yodaobot`, `ldspider`, `lexxebot`, `scoutjet`, `linkedin`, `bullseye`, `alexibot`, `whatsapp`, `facebook`, `getright`, `asterias`, `catchbot`, `discobot`, `geniebot`, `koepabot`, `synoobot`, `rufusbot`, `rampybot`, `mogimogi`, `lmspider`, `blowfish`, `superbot`, `valkyrie`, `yacybot`, `jyxobot`, `orbiter`, `polybot`, `accoona`, `mj12bot`, `aspider`, `blexbot`, `bspider`, `auresys`, `bingbot`, `gaisbot`, `zealbot`, `zspider`, `backrub`, `harvest`, `nymesis`, `radian6`, `scrubby`, `gcreep`, `snappy`, `vortex`, `tineye`, `zyborg`, `sqworm`, `qseero`, `pompos`, `solbot`, `ichiro`, `bizbot`, `msnbot`, `exabot`, `msrbot`, `dotbot`, `cosmos`, `ecatch`, `scrapy`, `tumblr`, `holmes`, `okhttp`, `mxbot`, `moget`, `occam`, `acoon`, `nutch`, `alexa`, `atomz`, `htdig`, `peew`, `yeti`, `wf84`, `vyu2`, `acoi`, `obot`, `ask`, `b2w`, `ipd`, `zao`, `furlbot`, `jakarta`, `oegp`, `lwebis`, `cerberian_drtrs`, `gigamega`, `sogou_spider`, `megaindex`, `gozilla`, `larbin`, `netseer`, `ntent`, `sheenbot`
1261
1404
 
1262
1405
  ### Validators
1263
1406
 
@@ -1269,7 +1412,7 @@ client.platform? :macos, version: '10.10'
1269
1412
 
1270
1413
  ### Email Clients
1271
1414
 
1272
- `:outlook`, `:airmail`, `:barca`, `:gmail`, `:thunderbird`, `:postbox`, `spicebird`
1415
+ `:outlook`, `:airmail`, `:barca`, `:gmail`, `:thunderbird`, `:postbox`, `spicebird`, `icedove`
1273
1416
 
1274
1417
  ### RSS
1275
1418
 
@@ -1278,7 +1421,7 @@ client.platform? :macos, version: '10.10'
1278
1421
  ### Platforms
1279
1422
 
1280
1423
  In addition to just supporting regular platform names as `client.android?`, there are also specific methods that get added if a certain version matches a platform.
1281
- This is the _platform_label_ property and allows you to do things like `client.froyo?` for instance.
1424
+ This is the _platform\_label_ property and allows you to do things like `client.froyo?` for instance.
1282
1425
 
1283
1426
  Below are a list of versions the agent can identify so far
1284
1427
 
@@ -1286,7 +1429,7 @@ Below are a list of versions the agent can identify so far
1286
1429
 
1287
1430
  Regular: `:android`
1288
1431
 
1289
- `:android`, `:cupcake`, `:eclair`, `:froyo`, `:gingerbread`, `:honeycomb`, `:ice_cream_sandwich`, `:jelly_bean`, `:kitkat`, `:lollipop`, `:marshmallow`, `:nougat`, `oreo`
1432
+ `:android`, `:cupcake`, `:eclair`, `:froyo`, `:gingerbread`, `:honeycomb`, `:ice_cream_sandwich`, `:jelly_bean`, `:kitkat`, `:lollipop`, `:marshmallow`, `:nougat`, `:oreo`, `:pie`
1290
1433
 
1291
1434
  Since android version releases follow the alphabet and since every new version since android `5` is contained within a single major version number,
1292
1435
  additional methods are defined for all "future" android releases e.g:
@@ -1300,7 +1443,7 @@ label :android_z, for: :android, version: '19'..'19.9.9'
1300
1443
  ```
1301
1444
 
1302
1445
  So for every unreleased version of android, you can identify it by using `:android_` followed by the letter for that version: `client.android_p?`.
1303
- This method will stay supported even after the name is known (the actual name will be added too). Since some android versions are already known, this system is supported from the letter `p` up to and including `z`.
1446
+ Since some android versions are already known, this system is supported from the letter `p` up to and including `z`.
1304
1447
 
1305
1448
  #### Windows
1306
1449
 
@@ -1322,4 +1465,4 @@ Regular: `:macintosh`
1322
1465
 
1323
1466
  Finally, Browserino can also detect devices in addition to the above.
1324
1467
 
1325
- `htc`, `kindle`, `alcatel`, `appletv`, `iphone`, `ipad`, `archos`, `asus`, `zte`, `blackberry`, `oneplus`, `lenovo`, `nokia`, `motorola`, `huawei`, `nexus`, `hp`, `lg`, `dell`
1468
+ `htc`, `kindle`, `alcatel`, `appletv`, `iphone`, `ipad`, `archos`, `asus`, `zte`, `blackberry`, `oneplus`, `lenovo`, `nokia`, `motorola`, `huawei`, `nexus`, `hp`, `lg`, `dell`, `oppo`