1 | # google-libphonenumber
|
2 |
|
3 | The up-to-date and reliable Google's libphonenumber package for node.js. Zero dependencies.
|
4 |
|
5 | ## Status
|
6 |
|
7 | [![npm version][npm-image]][npm-url]
|
8 | [![build status][travis-image]][travis-url]
|
9 | [![install size][packagephobia-image]][packagephobia-url]
|
10 |
|
11 | ## Introduction
|
12 |
|
13 | Google's [libphonenumber](https://github.com/googlei18n/libphonenumber) is a library that parses, formats, stores and validates international phone numbers. It is used by Android since version 4.0 and is a phenomenal repository of carrier metadata.
|
14 |
|
15 | Although it compiles down to Java, C++ and JS, its JS port is tightly coupled to the Google Closure library. This makes it more difficult to directly require and use the code on a node.js project.
|
16 |
|
17 | Google eventually started publishing [google-closure-library](https://www.npmjs.com/package/google-closure-library) directly to NPM, ending years of ill-maintained community packages. However, running the original library on node.js [remains a cumbersome process](https://github.com/googlei18n/libphonenumber/tree/master/javascript).
|
18 |
|
19 | After all these years, Google's libphonenumber is still not officially available on NPM. What is the best way to use Google's libphonenumber on node.js then? If you're looking for a convenient and easy method, that's what this package is all about.
|
20 |
|
21 | ## Installation
|
22 |
|
23 | Install the package via `npm`:
|
24 |
|
25 | ```sh
|
26 | npm install --save-prod google-libphonenumber
|
27 | ```
|
28 |
|
29 | ## Usage
|
30 |
|
31 | The following is a simple phone information extraction example similar to what can be viewed on the official demo page.
|
32 |
|
33 | ⚠️ _Most libphonenumber functions expect to receive an instance of `libphonenumber.PhoneNumber` which can be obtained by calling `phoneUtil.parse` or `phoneUtil.parseAndKeepRawInput` on a raw (string) number, otherwise it will throw errors like `TypeError: a.getCountryCodeOrDefault is not a function`._
|
34 |
|
35 | This **will** work:
|
36 |
|
37 | ```js
|
38 | phoneUtil.isValidNumberForRegion(phoneUtil.parse('202-456-1414', 'US'), 'US');
|
39 | ```
|
40 |
|
41 | This **will not** work:
|
42 |
|
43 | ```js
|
44 | phoneUtil.isValidNumberForRegion('202-456-1414', 'US');
|
45 | ```
|
46 |
|
47 | More API examples after parsing the raw string:
|
48 |
|
49 | ```js
|
50 | // Require `PhoneNumberFormat`.
|
51 | const PNF = require('google-libphonenumber').PhoneNumberFormat;
|
52 |
|
53 | // Get an instance of `PhoneNumberUtil`.
|
54 | const phoneUtil = require('google-libphonenumber').PhoneNumberUtil.getInstance();
|
55 |
|
56 | // Parse number with country code and keep raw input.
|
57 | const number = phoneUtil.parseAndKeepRawInput('202-456-1414', 'US');
|
58 |
|
59 | // Print the phone's country code.
|
60 | console.log(number.getCountryCode());
|
61 | // => 1
|
62 |
|
63 | // Print the phone's national number.
|
64 | console.log(number.getNationalNumber());
|
65 | // => 2024561414
|
66 |
|
67 | // Print the phone's extension.
|
68 | console.log(number.getExtension());
|
69 | // =>
|
70 |
|
71 | // Print the phone's extension when compared to i18n.phonenumbers.CountryCodeSource.
|
72 | console.log(number.getCountryCodeSource());
|
73 | // => FROM_DEFAULT_COUNTRY
|
74 |
|
75 | // Print the phone's italian leading zero.
|
76 | console.log(number.getItalianLeadingZero());
|
77 | // => false
|
78 |
|
79 | // Print the phone's raw input.
|
80 | console.log(number.getRawInput());
|
81 | // => 202-456-1414
|
82 |
|
83 | // Result from isPossibleNumber().
|
84 | console.log(phoneUtil.isPossibleNumber(number));
|
85 | // => true
|
86 |
|
87 | // Result from isValidNumber().
|
88 | console.log(phoneUtil.isValidNumber(number));
|
89 | // => true
|
90 |
|
91 | // Result from isValidNumberForRegion().
|
92 | console.log(phoneUtil.isValidNumberForRegion(number, 'US'));
|
93 | // => true
|
94 |
|
95 | // Result from getRegionCodeForNumber().
|
96 | console.log(phoneUtil.getRegionCodeForNumber(number));
|
97 | // => US
|
98 |
|
99 | // Result from getNumberType() when compared to i18n.phonenumbers.PhoneNumberType.
|
100 | console.log(phoneUtil.getNumberType(number));
|
101 | // => FIXED_LINE_OR_MOBILE
|
102 |
|
103 | // Format number in the E164 format.
|
104 | console.log(phoneUtil.format(number, PNF.E164));
|
105 | // => +12024561414
|
106 |
|
107 | // Format number in the original format.
|
108 | console.log(phoneUtil.formatInOriginalFormat(number, 'US'));
|
109 | // => (202) 456-1414
|
110 |
|
111 | // Format number in the national format.
|
112 | console.log(phoneUtil.format(number, PNF.NATIONAL));
|
113 | // => (202) 456-1414
|
114 |
|
115 | // Format number in the international format.
|
116 | console.log(phoneUtil.format(number, PNF.INTERNATIONAL));
|
117 | // => +1 202-456-1414
|
118 |
|
119 | // Format number in the out-of-country format from US.
|
120 | console.log(phoneUtil.formatOutOfCountryCallingNumber(number, 'US'));
|
121 | // => 1 (202) 456-1414
|
122 |
|
123 | // Format number in the out-of-country format from CH.
|
124 | console.log(phoneUtil.formatOutOfCountryCallingNumber(number, 'CH'));
|
125 | // => 00 1 202-456-1414
|
126 | ```
|
127 |
|
128 | #### Using the "As You Type" Formatter
|
129 |
|
130 | The "As You Type" formatter is a specialized tool that show the formatting *progress* as it attempts to discover the right format for the given number. It requires registering every keystroke (input digit) on a new instance of the `AsYouTypeFormatter` as shown below.
|
131 |
|
132 | ```js
|
133 | // Require `AsYouTypeFormatter`.
|
134 | const AsYouTypeFormatter = require('google-libphonenumber').AsYouTypeFormatter;
|
135 | const formatter = new AsYouTypeFormatter('US');
|
136 |
|
137 | console.log(formatter.inputDigit('2')); // => 2
|
138 | console.log(formatter.inputDigit('0')); // => 20
|
139 | console.log(formatter.inputDigit('2')); // => 202
|
140 | console.log(formatter.inputDigit('-')); // => 202-
|
141 | console.log(formatter.inputDigit('4')); // => 202-4
|
142 | console.log(formatter.inputDigit('5')); // => 202-45
|
143 | console.log(formatter.inputDigit('6')); // => 202-456
|
144 | console.log(formatter.inputDigit('-')); // => 202-456-
|
145 | console.log(formatter.inputDigit('1')); // => 202-456-1
|
146 | console.log(formatter.inputDigit('4')); // => 202-456-14
|
147 | console.log(formatter.inputDigit('1')); // => 202-456-141
|
148 | console.log(formatter.inputDigit('4')); // => 202-456-1414
|
149 |
|
150 | // Cleanup all input digits from instance.
|
151 | formatter.clear();
|
152 | ```
|
153 |
|
154 | ## Methods
|
155 |
|
156 | A quick glance at Google's libphonenumber rich API. Descriptions sourced from original files.
|
157 |
|
158 | ### i18n.phonenumbers.PhoneNumberUtil
|
159 |
|
160 | The class that offers the main utilities to work with phone numbers, such as formatting, parsing and validating.
|
161 |
|
162 | Highlights:
|
163 |
|
164 | * **format(number, numberFormat)** - formats a phone number in the specified format using default rules.
|
165 | * **formatInOriginalFormat(number, regionCallingFrom)** - formats a phone number using the original phone number format that the number is parsed from.
|
166 | * **formatOutOfCountryCallingNumber(number, regionCallingFrom)** - formats a phone number for out-of-country dialing purposes.
|
167 | * **getNumberType(number)** - gets the type of a valid phone number.
|
168 | * **getRegionCodeForNumber(number)** - returns the region where a phone number is from.
|
169 | * **isPossibleNumber(number)** - returns true if the number is either a possible fully-qualified number (containing the area code and country code), or if the number could be a possible local number (with a country code, but missing an area code).
|
170 | * **isValidNumber(number)** - tests whether a phone number matches a valid pattern.
|
171 | * **isValidNumberForRegion(number, regionCode)** - tests whether a phone number is valid for a certain region.
|
172 | * **parseAndKeepRawInput(numberToParse, defaultRegion)** - parses a string and returns it in proto buffer format while keeping the raw input value.
|
173 | * **parse(numberToParse, defaultRegion)** - parses a string and returns it in proto buffer format.
|
174 |
|
175 | ### i18n.phonenumbers.PhoneNumber
|
176 |
|
177 | The type of the phone returned after a string number has been parsed via `PhoneNumberUtil.parse()` or `PhoneNumberUtil.parseAndKeepRawInput()`.
|
178 |
|
179 | Highlights:
|
180 |
|
181 | * **getCountryCode()**
|
182 | * **getCountryCodeSource()**
|
183 | * **getExtension()**
|
184 | * **getItalianLeadingZero()**
|
185 | * **getNationalNumber()**
|
186 | * **getRawInput()**
|
187 |
|
188 | ## i18n.phonenumbers.CountryCodeSource
|
189 |
|
190 | Lists the following enums in order to compare them with the output of `Phone.getCountryCodeSource()`:
|
191 |
|
192 | * `CountryCodeSource.UNSPECIFIED`
|
193 | * `CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN`
|
194 | * `CountryCodeSource.FROM_NUMBER_WITH_IDD`
|
195 | * `CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN`
|
196 | * `CountryCodeSource.FROM_DEFAULT_COUNTRY`
|
197 |
|
198 | ## i18n.phonenumbers.PhoneNumberFormat
|
199 |
|
200 | Lists the following enums in order to pass them to `PhoneNumberUtil.format()`:
|
201 |
|
202 | * `PhoneNumberFormat.E164`
|
203 | * `PhoneNumberFormat.INTERNATIONAL`
|
204 | * `PhoneNumberFormat.NATIONAL`
|
205 | * `PhoneNumberFormat.RFC3966`
|
206 |
|
207 | ## i18n.phonenumbers.PhoneNumberType
|
208 |
|
209 | Lists the following enums in order to compare them with the output of `PhoneNumberUtil.getNumberType()`:
|
210 |
|
211 | * `PhoneNumberType.FIXED_LINE`
|
212 | * `PhoneNumberType.MOBILE`
|
213 | * `PhoneNumberType.FIXED_LINE_OR_MOBILE`
|
214 | * `PhoneNumberType.TOLL_FREE`
|
215 | * `PhoneNumberType.PREMIUM_RATE`
|
216 | * `PhoneNumberType.SHARED_COST`
|
217 | * `PhoneNumberType.VOIP`
|
218 | * `PhoneNumberType.PERSONAL_NUMBER`
|
219 | * `PhoneNumberType.PAGER`
|
220 | * `PhoneNumberType.UAN`
|
221 | * `PhoneNumberType.VOICEMAIL`
|
222 | * `PhoneNumberType.UNKNOWN`
|
223 |
|
224 | ### i18n.phonenumbers.ShortNumberInfo
|
225 |
|
226 | Highlights:
|
227 |
|
228 | * **connectsToEmergencyNumber(number, regionCode)** - tests whether the short number can be used to connect to emergency services when dialed from the given region.
|
229 | * **isPossibleShortNumber(number)** - tests whether a short number is a possible number.
|
230 | * **isPossibleShortNumberForRegion(number, regionDialingFrom)** - tests whether a short number is a possible number when dialed from the given region.
|
231 | * **isValidShortNumber(number)** - tests whether a short number is a possible number.
|
232 | * **isValidShortNumberForRegion(number, regionDialingFrom)** - tests whether a short number matches a valid pattern in a region.
|
233 |
|
234 | ```js
|
235 | // Get an instance of `ShortNumberInfo`.
|
236 | const shortInfo = require('google-libphonenumber').ShortNumberInfo.getInstance();
|
237 |
|
238 | // Get an instance of `PhoneNumberUtil`.
|
239 | const phoneUtil = require('google-libphonenumber').PhoneNumberUtil.getInstance();
|
240 |
|
241 | // Result from connectsToEmergencyNumber().
|
242 | console.log(shortInfo.connectsToEmergencyNumber('911', 'US'));
|
243 | // => true
|
244 |
|
245 | // Result from isPossibleShortNumber().
|
246 | console.log(shortInfo.isPossibleShortNumber(phoneUtil.parse('123456', 'FR')));
|
247 | // => true
|
248 |
|
249 | // Result from isPossibleShortNumberForRegion().
|
250 | console.log(shortInfo.isPossibleShortNumberForRegion(phoneUtil.parse('123456', 'FR'), 'FR'));
|
251 | // => true
|
252 | ```
|
253 |
|
254 | ### Unavailable methods and classes
|
255 |
|
256 | The following methods or classes are unavailable on the original JS port of Google's libphonenumber:
|
257 |
|
258 | * findNumbers - finds numbers in text (useful for highlighting or linking phone numbers inside text messages).
|
259 | * PhoneNumberOfflineGeocoder - provides geographical information related to a phone number.
|
260 | * PhoneNumberToCarrierMapper - provides carrier information related to a phone number.
|
261 | * PhoneNumberToTimeZonesMapper - provides timezone information related to a phone number.
|
262 |
|
263 | ## Notes
|
264 |
|
265 | ### Metadata issues
|
266 |
|
267 | Most of the issues submitted to this repository are related to carrier metadata - things like unexpected phone validations, errors in formatting numbers, unknown carriers and so on.
|
268 |
|
269 | First, try the same input using the [official demo page](http://libphonenumber.appspot.com). If the result is different, then it might mean that a metadata update is due on this package, as the demo page always runs on the latest and official metadata version.
|
270 |
|
271 | If the result is the same, it means there might be an issue with the currently available metadata. In that case, you should report your issue in the original project's [issue tracker](https://issuetracker.google.com/issues?q=componentid:192347) ([moved out of GitHub on 05/12/2017](https://groups.google.com/forum/#!topic/libphonenumber-discuss/bcCh0175LME)).
|
272 |
|
273 | This note will be posted on every issue regarding metadata troubles and it will be automatically closed.
|
274 |
|
275 | ### Differences from other packages
|
276 |
|
277 | `google-libphonenumber` does not try to be more than what it really is - a pre-compiled Google libphonenumber bundle that works on node.js. It is a **1:1 mirror** of the original library without any further simplifications or optimizations.
|
278 |
|
279 | * All classes available from `libphonenumber` are exported as-is. No magic methods.
|
280 | * Always based on the latest `google-closure` library version available from Google with performance and bug fixes.
|
281 | * Relies on a simplified and [well-documented update process](https://github.com/ruimarinho/google-libphonenumber/blob/master/bin/update.sh) to keep the underlying `libphonenumber` library always up-to-date.
|
282 |
|
283 | If you're looking for a slightly simpler API, you should try [awesome-phonenumber](https://www.npmjs.com/package/awesome-phonenumber). It is based on the same concepts of this package but changes the API in order to make it more user friendly. You run the risk of bumping into [other](https://github.com/grantila/awesome-phonenumber/issues/14) [bugs](https://github.com/grantila/awesome-phonenumber/issues/17) and you'll have to [learn new API types](https://github.com/grantila/awesome-phonenumber#api-types), but that's the necessary trade-off that the author made for achieving a generally better looking API.
|
284 |
|
285 | [libphonenumber-js](https://www.npmjs.com/package/libphonenumber-js) is a much more radical approach to Google's libphonenumber. It is a rewrite of the original library based on its source phone metadata but implemented without depending on the Google Closure library. It also offers a tool to reduce the metadata to a set of countries which might be useful for frontend projects. It has several [caveats](https://github.com/catamphetamine/libphonenumber-js#difference-from-googles-libphonenumber), many of which make a lot of sense depending on the project, but you will have to ascertain those yourself.
|
286 |
|
287 | ## Webpack
|
288 |
|
289 | There have been some users reporting successful but also unsuccessful usage with Webpack. While I don't personally use it, I'm 100% supportive of pull requests adding modifications that allow this package to better interact with it.
|
290 |
|
291 | ### Chrome Extensions
|
292 |
|
293 | Google Closure Compiler API, a serviced provided by Google to compile code online via its Closure library, may not always return fully compliant UTF-8-encoded output.
|
294 |
|
295 | Loading extensions using this library on Google Chrome and other Chromium-based browsers may result in the following error when compiled with webpack:
|
296 |
|
297 | `Could not load file 'file.js' for content script. It isn't UTF-8 encoded.`
|
298 |
|
299 | While the local Java-based version supports a parameter which would let us workaround this issue at the source using `--charset=US-ASCII`, the online API version, which is a lot more convenient to use, does not offer support for an equivalent parameter (e.g. `output_charset=US-ASCII`).
|
300 |
|
301 | In order to workaround this issue when using webpack, make sure to output US-ASCII characters only when defining `TerserPlugin` options, as demonstrated below:
|
302 |
|
303 | ```js
|
304 | optimization: {
|
305 | minimize: process.env.NODE_ENV !== 'development',
|
306 | minimizer: [
|
307 | new TerserPlugin({
|
308 | terserOptions: {
|
309 | output: {
|
310 | ascii_only: true
|
311 | }
|
312 | },
|
313 | }),
|
314 | ]
|
315 | }
|
316 | ```
|
317 |
|
318 | ## Tests
|
319 |
|
320 | A small subset of tests guarantees that the main library functions are working as expected and are correctly exported. The actual heavy lifting is done by `libphonenumber`'s extensive test suite.
|
321 |
|
322 | ```sh
|
323 | npm test
|
324 | ```
|
325 |
|
326 | ## Release
|
327 |
|
328 | ```sh
|
329 | npm version [<newversion> | major | minor | patch] -m "Release %s"
|
330 | ```
|
331 |
|
332 | ## Acknowledgments
|
333 |
|
334 | The exceptional work on `libphonenumber` was made possible by these [committers and contributors](https://github.com/googlei18n/libphonenumber/graphs/contributors).
|
335 |
|
336 | ## Licenses
|
337 |
|
338 | This package is licensed under MIT. The bundled [libphonenumber](https://github.com/googlei18n/libphonenumber/blob/master/LICENSE) library is licensed under Apache 2.0.
|
339 |
|
340 | [npm-image]: https://flat.badgen.net/npm/v/google-libphonenumber
|
341 | [npm-url]: https://npmjs.org/package/google-libphonenumber
|
342 | [travis-image]: https://flat.badgen.net/travis/ruimarinho/google-libphonenumber
|
343 | [travis-url]: https://travis-ci.org/ruimarinho/google-libphonenumber
|
344 | [packagephobia-image]: https://flat.badgen.net/packagephobia/install/google-libphonenumber
|
345 | [packagephobia-url]: https://packagephobia.now.sh/result?p=google-libphonenumber
|