{"id":13394983,"url":"https://github.com/daddyz/phonelib","last_synced_at":"2025-05-12T20:50:32.916Z","repository":{"id":4968017,"uuid":"6125728","full_name":"daddyz/phonelib","owner":"daddyz","description":"Ruby gem for phone validation and formatting using google libphonenumber library data","archived":false,"fork":false,"pushed_at":"2025-04-23T04:32:31.000Z","size":47405,"stargazers_count":1110,"open_issues_count":14,"forks_count":134,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-05-08T11:02:36.837Z","etag":null,"topics":["google-libphonenumber","parsing","phone-number","phone-parse","phone-validation","ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"ding2/ting_sfx","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/daddyz.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2012-10-08T14:30:58.000Z","updated_at":"2025-05-08T07:42:10.000Z","dependencies_parsed_at":"2023-01-13T13:19:11.104Z","dependency_job_id":"e367cd0c-e2d2-4cda-ac42-485cf3b2331c","html_url":"https://github.com/daddyz/phonelib","commit_stats":{"total_commits":599,"total_committers":58,"mean_commits":"10.327586206896552","dds":0.3071786310517529,"last_synced_commit":"ccf0cc710ede77f3e86dfe61cfaab6f3d66598e7"},"previous_names":[],"tags_count":129,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daddyz%2Fphonelib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daddyz%2Fphonelib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daddyz%2Fphonelib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daddyz%2Fphonelib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/daddyz","download_url":"https://codeload.github.com/daddyz/phonelib/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253240350,"owners_count":21876593,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["google-libphonenumber","parsing","phone-number","phone-parse","phone-validation","ruby"],"created_at":"2024-07-30T17:01:38.210Z","updated_at":"2025-05-12T20:50:32.865Z","avatar_url":"https://github.com/daddyz.png","language":"Ruby","readme":"## Phonelib\n\n[![Built in integration with JetBrains RubyMine](https://github.com/daddyz/phonelib/blob/master/icon_RubyMine.png?raw=true)](https://www.jetbrains.com/ruby/)\n[![Gem Version](https://badge.fury.io/rb/phonelib.svg)](http://badge.fury.io/rb/phonelib)\n[![CircleCI](https://dl.circleci.com/status-badge/img/gh/daddyz/phonelib/tree/master.svg?style=shield)](https://dl.circleci.com/status-badge/redirect/gh/daddyz/phonelib/tree/master)\n[![](https://codeclimate.com/github/daddyz/phonelib/badges/coverage.svg)](https://codeclimate.com/github/daddyz/phonelib/coverage)\n[![](https://codeclimate.com/github/daddyz/phonelib/badges/gpa.svg)](https://codeclimate.com/github/daddyz/phonelib)\n[![Inline docs](http://inch-ci.org/github/daddyz/phonelib.svg?branch=master)](http://inch-ci.org/github/daddyz/phonelib)\n\nPhonelib is a gem allowing you to validate phone number. All validations are based on [Google libphonenumber](https://github.com/googlei18n/libphonenumber).\nCurrently it can make basic validations and formatting to e164 international number format and national number format with prefix.\nBut it still doesn't include all Google's library functionality.\n\n## Incorrect parsing or validation\n\nIn case your phone number is incorrectly parsed, you can check original libphonenumber for result [here](https://htmlpreview.github.io/?https://github.com/google/libphonenumber/blob/master/javascript/i18n/phonenumbers/demo-compiled.html) and in case of same parse result [open an issue for them](http://issuetracker.google.com/issues/new?component=192347). This gem's data is based on it.\nIf you can't wait for libphonenumber to resolve the issue, try to use ```Phonelib.add_additional_regex``` and ```Phonelib.additional_regexes``` methods.\n\n## Information\n\n### Change Log\n\nChange log can be found in repo's releases page\nhttps://github.com/daddyz/phonelib/releases\n\n### Bug reports\n\nIf you discover a problem with Phonelib gem, let us know about it.\nhttps://github.com/daddyz/phonelib/issues\n\n### Example application\n\nYou can see an example of ActiveRecord validation by phonelib working in spec/dummy application of this gem\n\n## Getting started\n\nPhonelib was written and tested on Rails \u003e= 3.1. You can install it by adding in to your Gemfile with:\n\n``` ruby\ngem 'phonelib'\n```\n\nRun the bundle command to install it.\n\nTo set the default country or several default countries for parsing (country names are [ISO 3166-1 Alpha-2](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) codes), create a initializer in \u003ctt\u003econfig/initializers/phonelib.rb\u003c/tt\u003e:\n\n``` ruby\nPhonelib.default_country = \"CN\"\nPhonelib.default_country = ['CN', 'FR']\n```\n\nTo use the ability to parse special numbers (Short Codes, Emergency etc.) you can set ```Phonelib.parse_special```. This is disabled by default\n\n``` ruby\nPhonelib.parse_special = true\n```\n\nTo allow vanity phone numbers conversion you can set ```Phonelib.vanity_conversion``` to ```true```. This will convert characters in passed phone number to their numeric representation (800-CALL-NOW will be 800-225-5669).\n\n``` ruby\nPhonelib.vanity_conversion = true\n```\n\nTo disable sanitizing of passed phone number (keeping digits only)\n\n``` ruby\nPhonelib.strict_check = true\n```\n\nTo disable country reset during parsing in case phone starts with + sign and country specified but country phone prefix doesn't match phone's prefix\n\n``` ruby\nPhonelib.ignore_plus = true\n```\n\nTo change sanitized symbols on parsed number, so non-specified symbols won't be wiped and will fail the parsing\n\n``` ruby\nPhonelib.sanitize_regex = '[\\.\\-\\(\\) \\;\\+]'\n```\n\nTo disable sanitizing of double prefix on passed phone number\n\n```ruby\nPhonelib.strict_double_prefix_check = true\n```\n\nTo set different extension separator on formatting, this setting doesn't affect parsing. Default setting is ';'\n\n``` ruby\nPhonelib.extension_separator = ';'\n```\n\nTo set symbols that are used for separating extension from phone number for parsing use ```Phonelib.extension_separate_symbols``` method. Default value is '#;'. In case string is passed each one of the symbols in the string will be treated as possible separator, in case array was passed each string in array will be treated as possible separator.\n\n``` ruby\nPhonelib.extension_separate_symbols = '#;'           # for single symbol separator\nPhonelib.extension_separate_symbols = %w(ext # ; extension) # each string will be treated as separator\n```\n\nIn case you need to overwrite some Google's libphonenumber library data, you need to assign file path to this setter. File should be Marshal.dump'ed with existing structure like in ```Phonelib.phone_data```. Gem is simply doing ```merge``` between hashes.\n\n``` ruby\nPhonelib.override_phone_data = '/path/to/override_phone_data.dat'\n```\n\nIn case you want to add some custom or still not updated regex patterns for certain type you can use additional regexes feature in a following way:\n\n``` ruby\nPhonelib.add_additional_regex :us, Phonelib::Core::MOBILE, '[5]{10}' # this will add number 1-555-555-5555 to be valid\nPhonelib.add_additional_regex :gb, Phonelib::Core::MOBILE, '[1]{5}' # this will add number 44-11-111 to be valid\n# you can also specify all regexes using this method\nPhonelib.additional_regexes = [[:us, :mobile, \"[5]{10}\"], [:gb, :mobile, \"[1]{5}\"]]\n# or just use dump method to keep them altogether\nPhonelib.dump_additional_regexes # =\u003e [[\"US\", :mobile, \"[5]{10}\"], [\"GB\", :mobile, \"[1]{5}\"]\n```\n\n(!) For a list of available types refer to this readme.\n\n(!) Please note that regex should be added as string\n\nIn case phone number that was passed for parsing has \"+\" sign in the beginning, library will try to detect a country regarding the provided one.\n\n### ActiveRecord Integration\n\nThis gem adds validator for active record.\nBasic usage:\n\n``` ruby\nvalidates :attribute, phone: true\n```\n\nThis will enable Phonelib validator for field \"attribute\". This validator checks that passed value is valid phone number.\nPlease note that passing blank value also fails.\n\nAdditional options:\n\n``` ruby\nvalidates :attribute, phone: { possible: true, allow_blank: true, types: [:voip, :mobile], country_specifier: -\u003e phone { phone.country.try(:upcase) } }\n```\n\n\u003ctt\u003epossible: true\u003c/tt\u003e - enables validation to check whether the passed number is a possible phone number (not strict check).\nRefer to [Google libphonenumber](http://code.google.com/p/libphonenumber/) for more information on it.\n\n\u003ctt\u003eallow_blank: true\u003c/tt\u003e - when no value passed then validation passes\n\n\u003ctt\u003etypes: :mobile\u003c/tt\u003e or \u003ctt\u003etypes: [:voip, :mobile]\u003c/tt\u003e - allows to validate against specific phone types patterns,\nif mixed with \u003ctt\u003epossible\u003c/tt\u003e will check if number is possible for specified type\n\n\u003ctt\u003ecountries: :us\u003c/tt\u003e or \u003ctt\u003ecountries: [:us, :ca]\u003c/tt\u003e - allows to validate against specific countries, \nif mixed with \u003ctt\u003epossible\u003c/tt\u003e will check if number is possible for specified countries\n\n\u003ctt\u003ecountry_specifier: :method_name\u003c/tt\u003e or \u003ctt\u003ecountry_specifier: -\u003e instance { instance.country.try(:upcase) }\u003c/tt\u003e - allows to specify country for validation dynamically for each validation. Usefull when phone is stored as national number without country prefix.\n\n\u003ctt\u003eextensions: false\u003c/tt\u003e - set to perform check for phone extension to be blank\n\n### Basic usage\n\nTo check if phone number is valid simply run:\n\n``` ruby\nPhonelib.valid?('123456789') # returns true or false\n```\n\nAdditional methods:\n\n``` ruby\nPhonelib.valid? '123456789'      # checks if passed value is valid number\nPhonelib.invalid? '123456789'    # checks if passed value is invalid number\nPhonelib.possible? '123456789'   # checks if passed value is possible number\nPhonelib.impossible? '123456789' # checks if passed value is impossible number\n```\n\nThere is also option to check if provided phone is valid for specified country.\nCountry should be specified as two letters country code (like \"US\" for United States).\nCountry can be specified as String \u003ctt\u003e'US'\u003c/tt\u003e or \u003ctt\u003e'us'\u003c/tt\u003e as well as symbol \u003ctt\u003e:us\u003c/tt\u003e.\n\n``` ruby\nPhonelib.valid_for_country? '123456789', 'XX'   # checks if passed value is valid number for specified country\nPhonelib.invalid_for_country? '123456789', 'XX' # checks if passed value is invalid number for specified country\n```\n\nAdditionally you can run:\n\n``` ruby\nphone = Phonelib.parse('123456789')\nphone = Phonelib.parse('+1 (972) 123-4567', 'US')\n```\n\nYou can pass phone number with extension, it should be separated with \u003ctt\u003e;\u003c/tt\u003e or \u003ctt\u003e#\u003c/tt\u003e signs from the phone number.\n\nReturned value is object of \u003ctt\u003ePhonelib::Phone\u003c/tt\u003e class which have following methods:\n\n``` ruby\n# basic validation methods\nphone.valid?\nphone.invalid?\nphone.possible?\nphone.impossible?\n\n# validations for countries\nphone.valid_for_country? 'XX'\nphone.invalid_for_country? 'XX'\n```\n\nYou can also fetch matched valid phone types\n\n``` ruby\nphone.types          # returns array of all valid types\nphone.type           # returns first element from array of all valid types\nphone.possible_types # returns array of all possible types\n```\n\nPossible types:\n* \u003ctt\u003e:premium_rate\u003c/tt\u003e - Premium Rate\n* \u003ctt\u003e:toll_free\u003c/tt\u003e - Toll Free\n* \u003ctt\u003e:shared_cost\u003c/tt\u003e - Shared Cost\n* \u003ctt\u003e:voip\u003c/tt\u003e - VoIP\n* \u003ctt\u003e:personal_number\u003c/tt\u003e - Personal Number\n* \u003ctt\u003e:pager\u003c/tt\u003e - Pager\n* \u003ctt\u003e:uan\u003c/tt\u003e - UAN\n* \u003ctt\u003e:voicemail\u003c/tt\u003e - VoiceMail\n* \u003ctt\u003e:fixed_line\u003c/tt\u003e - Fixed Line\n* \u003ctt\u003e:mobile\u003c/tt\u003e - Mobile\n* \u003ctt\u003e:fixed_or_mobile\u003c/tt\u003e - Fixed Line or Mobile (if both mobile and fixed pattern matches)\n* \u003ctt\u003e:short_code\u003c/tt\u003e\n* \u003ctt\u003e:emergency\u003c/tt\u003e\n* \u003ctt\u003e:carrier_specific\u003c/tt\u003e\n* \u003ctt\u003e:sms_services\u003c/tt\u003e\n* \u003ctt\u003e:expanded_emergency\u003c/tt\u003e\n* \u003ctt\u003e:no_international_dialling\u003c/tt\u003e\n* \u003ctt\u003e:carrier_services\u003c/tt\u003e\n* \u003ctt\u003e:directory_services\u003c/tt\u003e\n* \u003ctt\u003e:standard_rate\u003c/tt\u003e\n* \u003ctt\u003e:carrier_selection_codes\u003c/tt\u003e\n* \u003ctt\u003e:area_code_optional\u003c/tt\u003e\n\nOr you can get human representation of matched types\n\n``` ruby\nphone.human_types # return array of human representations of valid types\nphone.human_type  # return human representation of first valid type\n```\n\nAlso you can fetch all matched countries\n\n``` ruby\nphone.countries       # returns array of all matched countries\nphone.country         # returns first element from array of all matched countries\nphone.valid_countries # returns array of countries where phone was matched against valid pattern\nphone.valid_country   # returns first valid country from array of valid countries\nphone.country_code    # returns country phone prefix\n```\n\nAlso it is possible to get formatted phone number\n\n``` ruby\nphone.international      # returns formatted e164 international phone number\nphone.national           # returns formatted national number with national prefix\nphone.area_code          # returns area code of parsed number or nil\nphone.local_number       # returns local number\nphone.extension          # returns extension provided with phone\nphone.full_e164          # returns e164 phone representation with extension\nphone.full_international # returns formatted international number with extension\n```\n\nYou can pass \u003ctt\u003efalse\u003c/tt\u003e to \u003ctt\u003enational\u003c/tt\u003e and \u003ctt\u003einternational\u003c/tt\u003e methods in order to get unformatted representations\n\n``` ruby\nphone.international(false) # returns unformatted international phone\nphone.national(false)      # returns unformatted national phone\n```\n\nYou can get E164 formatted number\n\n``` ruby\nphone.e164 # returns number in E164 format\n```\n\nYou can define prefix for ```international``` and ```e164``` related methods to get formatted number prefixed with anything you need.\n\n``` ruby\nphone.international('00')      # returns formatted international number prefixed by 00 instead of +\nphone.e164('00')               # returns e164 represantation of a number prefixed by 00 instead of +\nphone.full_international('00') # returns formatted international number with extension prefixed by 00 instead of +\nphone.full_e164('00')          # returns e164 represantation of a number with extension prefixed by 00 instead of +\nphone.international_00         # same as phone.international('00'). 00 can be replaced with whatever you need\nphone.e164_00                  # same as phone.international('00') \n```\n\nThere is a ```to_s``` method, it will return ```e164``` in case number is valid and ```original``` otherwise\n\n``` ruby\nphone.to_s # returns number in E164 format if number is valid or original otherwise\n```\n\nYou can compare 2 instances of ```Phonelib::Phone``` with ```==``` method or just use it with string\n\n```ruby \nphone1 = Phonelib.parse('+12125551234') # Phonelib::Phone instance\nphone2 = Phonelib.parse('+12125551234') # Phonelib::Phone instance\nphone1 == phone2                        # returns true\nphone1 == '+12125551234'                # returns true\nphone1 == '12125551234;123'             # returns true\n```\n\nThere is extended data available for numbers. It will return \u003ctt\u003enil\u003c/tt\u003e in case there is no data or phone is impossible.\nCan return array of values in case there are some results for specified number\n\n``` ruby\nphone.geo_name # returns geo name of parsed phone\nphone.timezone # returns timezone name of parsed phone\nphone.carrier  # returns carrier name of parsed phone\n```\n\nPhone class has following attributes\n\n``` ruby\nphone.original        # string that was passed as phone number\nphone.sanitized       # sanitized phone number (only digits left)\n```\n\n### How it works\n\nGem includes data from Google libphonenumber which has regex patterns for validations.\nValid patterns are more specific to phone type and country.\nPossible patterns as usual are patterns with number of digits in number.\n\n### Development and tests\n\nEveryone can do whatever he wants, the only limit is your imagination.\nJust don't forget to write test before the pull request.\nIn order to run test without Rails functionality simply use\n\n```\nbundle exec rake spec\n```\n\nIf you want to run including Rails environment, you need to set \u003ctt\u003eBUNDLE_GEMFILE\u003c/tt\u003e while running the spec task, for example:\n\n```\nBUNDLE_GEMFILE=gemfiles/Gemfile.rails-3.2.x bundle exec rake spec\n```\n\nGemfiles can be found in \u003ctt\u003egemfiles\u003c/tt\u003e folder, there are gemfiles for Rails 3.1, 3.2, 4, 5 and 5.1.\n","funding_links":[],"categories":["Country Data","Ruby","ActiveRecord Validations"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaddyz%2Fphonelib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdaddyz%2Fphonelib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaddyz%2Fphonelib/lists"}