namegender 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +49 -4
  3. data/lib/namegender.rb +47 -12
  4. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6579682547f30f447af4b578719b7ea7d4f907be742b6a51359f6ddf0d9732d7
4
- data.tar.gz: a851e53689d40ec42beeffb8c4b71ffb826280b8e51935d0491994481f87e62a
3
+ metadata.gz: c4643c981f5be9a9a9e2e4ebd41d812b466c1e740918d01374daf75c9d1e60ae
4
+ data.tar.gz: b46fa7433ebbae2738c127a4b1446d13d1fa14f98ec3369ad3c6ac7184d1b316
5
5
  SHA512:
6
- metadata.gz: c9dc314525be03ffaff2506f922e6529b6383dfff4c98a14270a525a8c5a5af157fb43d2aa2bcc41daa37845d71a59802dc19cdc7ed47ee73ef03ca1bfc6c55f
7
- data.tar.gz: fc58d715c4215caefe358e9c726702e11621d717d7cf6dfd2c814a80488f9627d7ea01eea571979d2a4d142405147ec0b27b28e797c62082ceb62401a667e3d5
6
+ metadata.gz: 2fcce41ef6af0dab6bb88560310d56d8573d8f2267b95a3b9c669818f679f7b63a1b0f27dd9d77ec329d651b3f14a879d7eaae30f7a58cd5283165f15328e54b
7
+ data.tar.gz: 8a072d1a84da3868b1d170f98b8c90e7210716f91737fb9f3fb30515e50b166706c3d5801edf94e5a63010273beef31143fbe2c3e3da679a5065d35672ba2f3a
data/README.md CHANGED
@@ -12,19 +12,33 @@ puts result["gender"], result["probability"], result["sample_size"]
12
12
 
13
13
  ## Options and response
14
14
 
15
- `name`, `email`, `username` and `bulk` accept `country:`, `ai_fallback:` and
16
- `best_guess:`:
15
+ `name`, `email`, `username` and `bulk` accept `country:`, `locale:`, `ip:`,
16
+ `ai_fallback:` and `best_guess:`:
17
17
 
18
18
  ```ruby
19
19
  result = client.name("Andrea", country: "IT", best_guess: true)
20
20
  ```
21
21
 
22
+ When you do not know the country, pass what you have and the API works it out:
23
+ `locale:` is a language tag such as `"it-IT"` or `"pt_BR"` (its region is used;
24
+ a tag without one, `"en"`, sets no country), and `ip:` is your end user's IP
25
+ address (looked up, not stored). `country:` wins over `locale:`, which wins
26
+ over `ip:`. The response's `country_source` says which one was used:
27
+ `"country"`, `"locale"`, `"ip"` or `nil`.
28
+
29
+ ```ruby
30
+ result = client.name("Andrea", locale: request.env["HTTP_ACCEPT_LANGUAGE"].to_s[/\A[^,;]+/], ip: request.ip)
31
+ puts result["country"], result["country_source"]
32
+ ```
33
+
22
34
  A result carries `query`, `name`, `first_name`, `middle_name`, `last_name`, `name_type`, `gender`, `country`, `probability`,
23
- `sample_size`, `took_ms`, `source`, `confidence` and `matched_as`, alongside
35
+ `sample_size`, `took_ms`, `source`, `confidence`, `matched_as` and `country_source`, alongside
24
36
  `credits_charged`, `credits_remaining`, `data_version` and `request_id`.
25
37
  Success is the HTTP status: any non-2xx response raises `NameGender::Error`
26
38
  with `status` and `body` (`{"error", "message", "request_id", "docs"}`).
27
- Branch on `body["error"]`, not on the message.
39
+ Branch on `body["error"]`, not on the message. A `bulk` response carries
40
+ `country_source` once, at the top level next to `summary`, not on each item
41
+ in `results`.
28
42
 
29
43
  ## Country distribution
30
44
 
@@ -39,6 +53,37 @@ result["registrations"].each { |r| puts "#{r["country"]} #{r["share"]}%" }
39
53
  puts result["attested_in"].join(", ")
40
54
  ```
41
55
 
56
+ ## Salutation
57
+
58
+ A ready-to-use salutation for a letter or an email, in `en`, `de`, `fr`, `es`,
59
+ `it`, `pt`, `nl`, `tr`, `pl` or `ja` (and regional variants such as `de-AT`
60
+ or `pt-BR`). Without `language:` it follows `locale:`, then the country, then
61
+ English.
62
+
63
+ ```ruby
64
+ result = client.salutation("Dr. Anna Müller", language: "de")
65
+ puts result["salutation"]["formal"] # Sehr geehrte Frau Dr. Müller,
66
+ puts result["salutation"]["informal"] # Liebe Anna,
67
+
68
+ client.salutation("Ahmet Yılmaz", language: "tr")["salutation"]["formal"] # Sayın Ahmet Bey,
69
+
70
+ # Names stored in separate fields are used as they are, not parsed:
71
+ client.salutation(first_name: "Anna", last_name: "Müller", title: "Dr.", language: "de")
72
+
73
+ result = client.salutation_bulk(["Dr. Anna Müller", "Müller GmbH"], language: "de")
74
+ result["results"].each { |r| puts r["salutation"]["formal"] }
75
+ puts result["summary"] # total, gendered, neutral, organization
76
+ ```
77
+
78
+ One credit per name. When the gender is not certain enough (`min_probability:`,
79
+ default 90), you get the neutral form rather than a guess: `form` is
80
+ `"gendered"`, `"neutral"` or `"organization"`, and `reason` says why it is not
81
+ gendered (`"gender_unknown"`, `"below_min_probability"`, ...). `best_guess`
82
+ does not apply here. If you already know the gender, pass
83
+ `gender: "female"`, `"male"` or `"neutral"`. `salutation_bulk` takes up to 100
84
+ names and returns `results` in input order. An unsupported language raises
85
+ `NameGender::Error` with status 422 and `body["supported"]`.
86
+
42
87
  ## File jobs
43
88
 
44
89
  Upload a CSV or XLSX file (up to 100 MB and 1,000,000 rows) and get it back
data/lib/namegender.rb CHANGED
@@ -21,21 +21,28 @@ module NameGender
21
21
  @api_key, @base_url = api_key, base_url.sub(%r{/$}, "")
22
22
  end
23
23
 
24
- # `options` are sent as-is: `ai_fallback: true` falls back to a language
25
- # model for names not in the database (needs AI consent on the account),
26
- # `best_guess: true` returns the most likely gender even below the
27
- # probability threshold. Any non-2xx response raises NameGender::Error.
28
- def name(value, country: nil, **options)
29
- post("/gender", { name: value, country: country }.merge(options).compact)
24
+ # `country` is an ISO 3166-1 alpha-2 code. Without it, `locale` (a
25
+ # language tag such as "it-IT" or "pt_BR"; a tag without a region, "en",
26
+ # sets no country) and then `ip` (the end user's IP address, not stored by
27
+ # the API) supply one: country > locale > ip. The result's
28
+ # "country_source" says which was used ("country", "locale", "ip" or nil).
29
+ #
30
+ # Other `options` are sent as-is: `ai_fallback: true` falls back to a
31
+ # language model for names not in the database (needs AI consent on the
32
+ # account), `best_guess: true` returns the most likely gender even below
33
+ # the probability threshold. Any non-2xx response raises NameGender::Error.
34
+ def name(value, country: nil, locale: nil, ip: nil, **options)
35
+ post("/gender", { name: value, country: country, locale: locale, ip: ip }.merge(options).compact)
30
36
  end
31
- def email(value, country: nil, **options)
32
- post("/gender/email", { email: value, country: country }.merge(options).compact)
37
+ def email(value, country: nil, locale: nil, ip: nil, **options)
38
+ post("/gender/email", { email: value, country: country, locale: locale, ip: ip }.merge(options).compact)
33
39
  end
34
- def username(value, country: nil, **options)
35
- post("/gender/username", { username: value, country: country }.merge(options).compact)
40
+ def username(value, country: nil, locale: nil, ip: nil, **options)
41
+ post("/gender/username", { username: value, country: country, locale: locale, ip: ip }.merge(options).compact)
36
42
  end
37
- def bulk(values, country: nil, type: "name", **options)
38
- post("/gender/bulk", { names: Array(values), country: country, type: type }.merge(options).compact)
43
+ # `country`, `locale` and `ip` apply to every name in the list.
44
+ def bulk(values, country: nil, locale: nil, ip: nil, type: "name", **options)
45
+ post("/gender/bulk", { names: Array(values), country: country, locale: locale, ip: ip, type: type }.merge(options).compact)
39
46
  end
40
47
  # Country distribution of a name. Not a country-of-origin or ethnicity
41
48
  # inference: "registrations" is counted volume, comparable only among the
@@ -45,6 +52,34 @@ module NameGender
45
52
  def countries(value, limit: nil)
46
53
  post("/gender/countries", { name: value, limit: limit }.compact)
47
54
  end
55
+ # A salutation for a letter or an email: "Sehr geehrte Frau Dr. Müller,",
56
+ # "Sayın Ahmet Bey,". `value` is the full name, titles included; pass
57
+ # `first_name:` and `last_name:` instead when they are stored separately
58
+ # (they are not parsed). `language` defaults to the language of `locale`,
59
+ # then the main language of the country, then "en"; an unsupported one is
60
+ # a 422. `gender:` ("male", "female", "neutral") is a known gender and
61
+ # skips the lookup; `min_probability:` (50-100, server default 90) is the
62
+ # certainty below which the neutral form is used; `title:` is an academic
63
+ # title kept in a separate field ("Dr."). "form" and "reason" in the result
64
+ # say why a neutral form was chosen. One credit per name. `best_guess` and
65
+ # `ai_fallback` do not apply here and are not accepted.
66
+ def salutation(value = nil, first_name: nil, last_name: nil, language: nil, country: nil, locale: nil, ip: nil,
67
+ gender: nil, min_probability: nil, title: nil)
68
+ post("/salutation", {
69
+ name: value, first_name: first_name, last_name: last_name, language: language, country: country,
70
+ locale: locale, ip: ip, gender: gender, min_probability: min_probability, title: title
71
+ }.compact)
72
+ end
73
+ # Up to 100 names; every option applies to all of them. "results" keeps
74
+ # the input order, "summary" counts the gendered, neutral and organization
75
+ # forms.
76
+ def salutation_bulk(values, language: nil, country: nil, locale: nil, ip: nil, gender: nil, min_probability: nil,
77
+ title: nil)
78
+ post("/salutation/bulk", {
79
+ names: Array(values), language: language, country: country, locale: locale, ip: ip, gender: gender,
80
+ min_probability: min_probability, title: title
81
+ }.compact)
82
+ end
48
83
  def account
49
84
  request(Net::HTTP::Get, "/me")
50
85
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: namegender
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - NameGender
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-09-24 00:00:00.000000000 Z
11
+ date: 2026-10-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: A dependency-free Ruby client for name, email, username, bulk and country
14
- distribution lookups through NameGender.
13
+ description: A dependency-free Ruby client for name, email, username, bulk, country
14
+ distribution and salutation lookups through NameGender.
15
15
  email:
16
16
  - support@namegender.com
17
17
  executables: []