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)