google-libphonenumber
适用于 node.js 的最新的、可靠的 Google libphonenumber 包。零依赖。
介紹
谷歌的 libphonenumber 是一个解析、格式化、存储和验证国际电话号码的库。Android 从 4.0 版本开始使用它,它是一个出色的运营商元数据存储库。
虽然它可以编译成 Java、C++ 和 JS,但它的 JS 移植是与 Google Closure 库紧密耦合的。这使得在 node.js 项目上直接 'require' 和使用代码变得更加困难。
谷歌最终开始直接向 NPM 发布 google-closure-library,结束了多年来维护不善的社区包。然而,在 node.js 上运行原始库仍然是一个繁琐的过程。
这么多年过去了,Google 的 libphonenumber 仍然不能在 NPM 上正式使用。那么在 node.js 上使用 Google 的 libphonenumber 的最佳方法是什么呢?如果您正在寻找一种方便简单的方法,这就是这个软件包的全部内容。
安装
通过 npm 安装软件包。
npm install --save-prod google-libphonenumber
使用方法
下面是一个简单的电话信息提取的例子,类似于在官方演示页面上可以看到的内容。
警告:大多数 libphonenumber 函数都期望收到 libphonenumber.PhoneNumber 的实例,这个实例可以通过调用 phoneUtil.parse 或 phoneUtil.parseAndKeepRawInput 对一个原始(字符串)号码进行获取,否则会抛出 TypeError: a.getCountryCodeOrDefault 不是函数等错误。
这样可以工作:
phoneUtil.isValidNumberForRegion(phoneUtil.parse('202-456-1414', 'US'), 'US');
这将不工作:
phoneUtil.isValidNumberForRegion('202-456-1414', 'US');
解析原始字符串后的更多 API 示例。
// Require `PhoneNumberFormat`. const PNF = require('google-libphonenumber').PhoneNumberFormat; // Get an instance of `PhoneNumberUtil`. const phoneUtil = require('google-libphonenumber').PhoneNumberUtil.getInstance(); // Parse number with country code and keep raw input. const number = phoneUtil.parseAndKeepRawInput('202-456-1414', 'US'); // Print the phone's country code. console.log(number.getCountryCode()); // => 1 // Print the phone's national number. console.log(number.getNationalNumber()); // => 2024561414 // Print the phone's extension. console.log(number.getExtension()); // => // Print the phone's extension when compared to i18n.phonenumbers.CountryCodeSource. console.log(number.getCountryCodeSource()); // => FROM_DEFAULT_COUNTRY // Print the phone's italian leading zero. console.log(number.getItalianLeadingZero()); // => false // Print the phone's raw input. console.log(number.getRawInput()); // => 202-456-1414 // Result from isPossibleNumber(). console.log(phoneUtil.isPossibleNumber(number)); // => true // Result from isValidNumber(). console.log(phoneUtil.isValidNumber(number)); // => true // Result from isValidNumberForRegion(). console.log(phoneUtil.isValidNumberForRegion(number, 'US')); // => true // Result from getRegionCodeForNumber(). console.log(phoneUtil.getRegionCodeForNumber(number)); // => US // Result from getNumberType() when compared to i18n.phonenumbers.PhoneNumberType. console.log(phoneUtil.getNumberType(number)); // => FIXED_LINE_OR_MOBILE // Format number in the E164 format. console.log(phoneUtil.format(number, PNF.E164)); // => +12024561414 // Format number in the original format. console.log(phoneUtil.formatInOriginalFormat(number, 'US')); // => (202) 456-1414 // Format number in the national format. console.log(phoneUtil.format(number, PNF.NATIONAL)); // => (202) 456-1414 // Format number in the international format. console.log(phoneUtil.format(number, PNF.INTERNATIONAL)); // => +1 202-456-1414 // Format number in the out-of-country format from US. console.log(phoneUtil.formatOutOfCountryCallingNumber(number, 'US')); // => 1 (202) 456-1414 // Format number in the out-of-country format from CH. console.log(phoneUtil.formatOutOfCountryCallingNumber(number, 'CH')); // => 00 1 202-456-1414
使用“As You Type(边打边用)”格式器
"As You Type" 格式化器是一个专门的工具,它在试图发现给定数字的正确格式时显示格式化进度。它需要在AsYouTypeFormatter的新实例上注册每一个击键(输入数字),如下图所示。
// Require `AsYouTypeFormatter`. const AsYouTypeFormatter = require('google-libphonenumber').AsYouTypeFormatter; const formatter = new AsYouTypeFormatter('US'); console.log(formatter.inputDigit('2')); // => 2 console.log(formatter.inputDigit('0')); // => 20 console.log(formatter.inputDigit('2')); // => 202 console.log(formatter.inputDigit('-')); // => 202- console.log(formatter.inputDigit('4')); // => 202-4 console.log(formatter.inputDigit('5')); // => 202-45 console.log(formatter.inputDigit('6')); // => 202-456 console.log(formatter.inputDigit('-')); // => 202-456- console.log(formatter.inputDigit('1')); // => 202-456-1 console.log(formatter.inputDigit('4')); // => 202-456-14 console.log(formatter.inputDigit('1')); // => 202-456-141 console.log(formatter.inputDigit('4')); // => 202-456-1414 // Cleanup all input digits from instance. formatter.clear();
方法(Methods)
快速浏览谷歌的 libphonenumber 丰富的 API。描述来源于原始文件。
i18n.phonenumbers.PhoneNumberUtil
该类提供了处理电话号码的主要实用程序,如格式化、解析和验证。
重点介绍:
- format(number, numberFormat) -- 使用默认规则以指定的格式格式化一个电话号码。
- formatInOriginalFormat(number, regionCallingFrom) -- 使用原始电话号码格式格式化一个电话号码,该号码是从该号码解析出来的。
- formatOutOfCountryCallingNumber(number, regionCallingFrom) -- 格式化一个用于境外拨号的电话号码。
- getNumberType(number) -- 获取一个有效电话号码的类型。
- getRegionCodeForNumber(number) -- 返回一个电话号码所在的地区。
- isPossibleNumber(number) -- 如果该号码是一个可能的完全合格的号码(包含区号和国家代码),或者该号码可能是一个可能的本地号码(有国家代码,但缺少区号),则返回true。
- isValidNumber(number) -- 测试一个电话号码是否匹配一个有效的模式。
- isValidNumberForRegion(number, regionCode) -- 测试一个电话号码是否对某个地区有效。
- parseAndKeepRawInput(numberToParse, defaultRegion) -- 解析一个字符串并以proto buffer格式返回,同时保留原始输入值。
- parse(numberToParse, defaultRegion) -- 解析一个字符串并以原缓冲区格式返回。
i18n.phonenumbers.PhoneNumber.PhoneNumber
解析一个字符串并以原缓冲区格式返回。
通过PhoneNumberUtil.parse()或PhoneNumberUtil.parseAndKeepRawInput()解析字符串号码后返回的手机类型。
重点介绍:
- getCountryCode()
- getCountryCodeSource()
- getExtension()
- getItalianLeadingZero()
- getNationalNumber()
- getRawInput()
i18n.phonenumbers.CountryCodeSource
列出以下枚举,以便与 Phone.getCountryCodeSource() 的输出进行比较。
- CountryCodeSource.UNSPECIFIED
- CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN
- CountryCodeSource.FROM_NUMBER_WITH_IDD
- CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN
- CountryCodeSource.FROM_DEFAULT_COUNTRY
i18n.phonenumbers.PhoneNumberFormat
列出以下枚举,以便将它们传递给 PhoneNumberUtil.format()。
- PhoneNumberFormat.E164
- PhoneNumberFormat.INTERNATIONAL
- PhoneNumberFormat.NATIONAL
- PhoneNumberFormat.RFC3966
i18n.phonenumbers.PhoneNumberType
列出以下枚举,以便与 PhoneNumberUtil.getNumberType() 的输出进行比较。
- PhoneNumberType.FIXED_LINE
- PhoneNumberType.MOBILE
- PhoneNumberType.FIXED_LINE_OR_MOBILE
- PhoneNumberType.TOLL_FREE
- PhoneNumberType.PREMIUM_RATE
- PhoneNumberType.SHARED_COST
- PhoneNumberType.VOIP
- PhoneNumberType.PERSONAL_NUMBER
- PhoneNumberType.PAGER
- PhoneNumberType.UAN
- PhoneNumberType.VOICEMAIL
- PhoneNumberType.UNKNOWN
i18n.phonenumbers.ShortNumberInfo
重点介绍:
- connectsToEmergencyNumber(number, regionCode) -- 测试当从给定区域拨打时,短号码是否可以用来连接到紧急服务。
- isPossibleShortNumber(number) -- 测试一个短号码是否是一个可能的号码。
- isPossibleShortNumberForRegion(number, regionDialingFrom) -- 测试当从给定区域拨打时,短号码是否是一个可能的号码。
- isValidShortNumber(number) -- 测试一个短号码是否是一个可能的号码。
- isValidShortNumberForRegion(number, regionDialingFrom) -- 测试一个短号码是否符合一个区域的有效模式。
// 获取一个`ShortNumberInfo`的实例。 const shortInfo = require('google-libphonenumber').ShortNumberInfo.getInstance(); //获取`PhoneNumberUtil`的实例。 const phoneUtil = require('google-libphonenumber').PhoneNumberUtil.getInstance(); // connectsToEmergencyNumber() 的结果。console.log(shortInfo.connectsToEmergencyNumber('911', 'US')); // => true // isPossibleShortNumber() 的结果。console.log(shortInfo.isPossibleShortNumber(phoneUtil.parse('123456', 'FR')) // => true // isPossibleShortNumberForRegion() 的结果。 console.log(shortInfo.isPossibleShortNumberForRegion(phoneUtil.parse('123456', 'FR'), 'FR')); // => true
不可用的方法和类
以下方法或类在 Google 的 libphonenumber 的原始 JS 移植中不可用。
- findNumbers -- 在文本中查找号码(对于在文本信息中突出显示或链接电话号码很有用)。
- PhoneNumberOfflineGeocoder -- 提供与电话号码相关的地理信息。
- PhoneNumberToCarrierMapper -- 提供与电话号码相关的运营商信息。
- PhoneNumberToTimeZonesMapper -- 提供与电话号码相关的时区信息。
说明
元数据问题
提交到这个资源库的大部分问题都与运营商元数据有关 -- 比如手机验证意外、格式号错误、未知运营商等等。
首先,使用官方演示页面尝试同样的输入。如果结果不同,那么可能意味着这个包的元数据更新到期了,因为演示页面总是在最新的官方元数据版本上运行。
如果结果是一样的,这意味着可能是当前可用的元数据有问题。在这种情况下,你应该在原项目的问题跟踪器中报告你的问题(已于2017年12月5日移出 GitHub)。
这个说明将发布在每一个关于元数据麻烦的问题上,它将自动关闭。
与其他包的区别
google-libphonenumber 并没有试图成为比它真正的东西更多的东西 -- 一个在 node.js 上工作的预编译的 Google libphonenumber bundle。它是原始库的 1:1 镜像,没有任何进一步的简化或优化。
- 所有从 libphonenumber 中获得的类都是按原样导出的。没有神奇的方法。
- 始终基于 Google 提供的最新 google-closure 库版本,并进行了性能和 bug 修复。
- 依靠一个简化的、有良好文档的更新过程来保持底层的 libphonenumber 库始终是最新的。
如果你正在寻找一个稍微简单的 API,你应该尝试 awesome-phonenumber。它基于这个包的相同概念,但改变了 API 以使其更加用户友好。你有可能会遇到其他的 bugs,而且你必须学习新的 API 类型,但这是作者为了实现一个总体上更好看的 API 而做出的必要权衡。
libphonenumber-js 是 Google 的 libphonenumber 更激进的方法。它是在原库的基础上重写了它的源手机元数据,但不依赖于 Google Closure 库来实现。它还提供了一个工具,可以将元数据减少到一组国家,这对于前端项目来说可能是有用的。它有几个注意事项,其中很多都是根据项目的不同而有意义的,但你必须自己确定这些。
Webpack
有一些用户报告说使用 Webpack 成功了,但也有不成功的。虽然我个人并没有使用它,但我 100% 支持添加修改的 pull 请求,让这个包能够更好地与之交互。
浏览器扩展程序
Google Closure Compiler API 是 Google 提供的一种服务,用于通过其 Closure 库在线编译代码,但它可能并不总是返回完全符合 UTF-8 编码的输出。
在 Google Chrome 和其他基于 Chromium 的浏览器上加载使用该库的扩展,在使用 webpack 编译时可能会导致以下错误。
// 无法为内容脚本加载文件 'file.js'。它不是 UTF-8 编码的。 Could not load file 'file.js' for content script. It isn't UTF-8 encoded.
虽然基于 Java 的本地版本支持一个参数,可以让我们在源码中使用 --charset=US-ASCII 来解决这个问题,但在线 API 版本,使用起来更方便,并没有提供等价的参数支持(例如 output_charset=US-ASCII)。
为了在使用 webpack 时解决这个问题,在定义 TerserPlugin 选项时一定要只输出 US-ASCII 字符,如下所示。
optimization: { minimize: process.env.NODE_ENV !== 'development', minimizer: [ new TerserPlugin({ terserOptions: { output: { ascii_only: true } }, }), ] }
测试
一个小的测试子集可以保证主要的库函数按照预期工作,并且正确导出。实际的繁重工作是由 libphonenumber 的测试套件完成的。
npm test
发布
npm version [<newversion> | major | minor | patch] -m "Release %s" </newversion>
鸣谢
libphonenumber 的卓越工作是由这些提交者和贡献者所促成的。
许可证
本软件包采用 MIT 授权。捆绑的 libphonenumber 库采用 Apache 2.0 授权。
(The first version translated by vz on 2020.08.30)