HubSpot/humanize · 上手攻略

  • 仓库:HubSpot/humanize
  • 链接:https://github.com/HubSpot/humanize
  • 分类:javascript · utility · formatting
  • 作者:Tom
  • 更新:2026-08-23

是什么

Humanize(npm 包名 humanize-plus)是 HubSpot 开源的 JavaScript 工具库,专注把机器数字和原始字符串格式化成人类可读的友好文本。比如把 123456789 变成 "123.5M",把 "hello world" 首字母大写成 "Hello world",把文件字节数 1024 * 2000 变成 "1.95 Mb"

官方自称"making the web more humane",定位是前端展示层的数值/文本格式化辅助函数,适用于 Dashboard、报表、聊天界面等需要把原始数据变成可读文本的场景。

解决什么问题

前端开发中,把数字直接展示给用户往往体验很差:

  • 数字没有千分位分隔符,阅读长数字困难(如 123456789 vs 123,456,789
  • 字节数直接展示 1048576 而不是 1 Mb
  • 英文单词复数需要手写三元表达式(如 count === 1 ? 'duck' : 'ducks'
  • 列表展示手写 apple, orange, banana and 2 others 格式繁琐
  • 截断字符串手算字符数容易出 bug

Humanize 把这些格式化需求封装成 20+ 个独立函数,一行调用,无需手写重复逻辑。

快速安装

# npm 安装
npm install humanize-plus

# 或直接下载单文件(无依赖)
# 完整版:https://raw.github.com/HubSpot/humanize/master/src/humanize.js
# 压缩版:https://raw.github.com/HubSpot/humanize/master/dist/humanize.min.js

Web 页面直接引用(全局 Humanize 对象):

<script src="public/humanize.min.js"></script>
<script>
  var capitalized = Humanize.capitalize("ten tiny ducklings.")
  // "Ten tiny ducklings."
</script>

Node.js 项目在 package.json 添加依赖:

"dependencies": {
  "humanize-plus": "^1.7.0"
}

然后:

const Humanize = require('humanize-plus');
// 或 ESM
import Humanize from 'humanize-plus';

⚠️ 包名是 humanize-plus,不是 humanize(后者是另一个不相关的包);版本 ^1.7.0 发布于 2016 年,后续无大版本更新,API 稳定。

核心用法

1. 数字格式化

// 精确小数位格式化(带千分位)
Humanize.formatNumber(123456789, 2)
// "123,456,789.00"

// 整数千分位(无小数)
Humanize.intComma(123456789)
// "123,456,789"

2. 大数字缩写

// 整数缩写(自动选择 K/M/B/T 单位)
Humanize.intWord(123456789)
// "123.5M"   (注意:实际调用 compactInteger,效果相同)

// 科学计数法超大数字
Humanize.compactInteger(-7832186132456328967, 4)
// "-7.8322x10^18"

3. 文件大小

Humanize.fileSize(1024 * 20)
// "20 Kb"

Humanize.fileSize(1024 * 2000)
// "1.95 Mb"

Humanize.fileSize(Math.pow(1000, 4))
// "931.32 Gb"

⚠️ fileSize 的基准是 1024(KiB / MiB / GiB),不是 1000;这是存储行业的惯例,注意和部分系统用的十进制区分。

4. boundedNumber(上限标注)

Humanize.boundedNumber(110, 100)
// "100+"

Humanize.boundedNumber(50, 100)
// "50"

5. ordinal(序数词)

Humanize.ordinal(22)
// "22nd"

Humanize.ordinal(1)
// "1st"

Humanize.ordinal(3)
// "3rd"

6. times(次数的友好表达)

for (let i = 0; i < 5; i++) {
  Humanize.times(i, {"4": "too many"});
  if (i === 1) Humanize.times(1.1);
}
// never
// once
// 1.1 times
// twice
// 3 times
// too many times

支持自定义映射和 override 数组。

7. pace(速度友好描述)

const second = 1000;
const week = 6.048e8;

Humanize.pace(1.5, second, "heartbeat")
// "Approximately 2 heartbeats per second"

Humanize.pace(4, week)
// "Approximately 4 times per week"

8. pluralize(复数处理)

Humanize.pluralize(1, "duck")
// "duck"

Humanize.pluralize(3, "duck")
// "ducks"

Humanize.pluralize(3, "duck", "duckies")
// "duckies"   (自定义复数后缀)

9. truncate / truncateWords(字符串截断)

Humanize.truncate('long text is good for you')
// "long text is good for you"   (未超长,不截断)

Humanize.truncate('long text is good for you', 19)
// "long text is goo..."

Humanize.truncate('long text is good for you', 19, '... etc')
// "long text is... etc"

Humanize.truncateWords('long text is good for you', 5)
// "long text is good for ..."

10. capitalize / capitalizeAll / titleCase(大小写)

Humanize.capitalize("some boring string")
// "Some boring string"

Humanize.capitalize("wHoOaA!")
// "WHoOaA!"   (仅首字母大写,不动其余字符)

Humanize.capitalize("wHoOaA!", true)
// "Whooaa!"   (第二个参数 true = 其余字符转小写)

Humanize.capitalizeAll("some boring string")
// "Some Boring String"

Humanize.titleCase("some of a boring string")
// "Some of a Boring String"   (虚词小写,iTunes 等特殊处理)

11. oxford(牛津列表格式)

const items = ['apple', 'orange', 'banana', 'pear', 'pineapple'];

Humanize.oxford(items)
// "apple, orange, banana, pear, and pineapple"

Humanize.oxford(items, 3)
// "apple, orange, banana, and 2 others"

Humanize.oxford(items, 4)
// "apple, orange, banana, pear, and 1 other"

Humanize.oxford(items, 3, "and some other fruits")
// "apple, orange, banana, and some other fruits"

12. frequency(出现次数描述)

const catPics = [
  'https://media2.giphy.com/media/JIX9t2j0ZTN9S/giphy.gif',
  'https://media3.giphy.com/media/uzglgIsyY1Cgg/giphy.gif'
];

"Cats " + Humanize.frequency(catPics, "typed on keyboards")
// "Cats typed on keyboards 3 times"

const dogPics = [];
"Dogs " + Humanize.frequency(dogPics, "typed on keyboards")
// "Dogs never typed on keyboards"

13. toFixed(修复浮点精度问题)

Humanize.toFixed(0.615, 2)
// "0.62"   (解决了 (0.615).toFixed(2) === "0.61" 的二进制舍入问题)

Humanize.normalizePrecision(-232.231)
// 232   (取正整数精度值)

典型适用场景

  • Dashboard 数值展示:把原始字节数、毫秒级延迟、用户数等直接展示为友好格式。
  • 聊天机器人回复:生成"处理了 3 个文件"而不是"处理了 3 个文件(复数)"这类文字。
  • 通知/推送文案:邮件/推送里需要动态拼接用户数据,一行调用解决复数和格式化。
  • 数据分析报告:导出 CSV/Excel 前在 JS 层做格式化,保证前端展示和导出数据一致。
  • SEO 友好的 URL 文本:titleCase 生成页面标题、描述文字。

坑与注意

坑点 说明
包名是 humanize-plus npm 上搜索 humanize 会找到另一个不相关的包,注意甄别
版本停留在 1.7.x 最后更新约 2016 年,无 ESM 原生支持、无 Tree-shaking;现代项目建议自行打包
fileSize 用 1024 基准 存储行业惯例,部分 UI 需要显示十进制(1000 基准)时需要自己换算
capitalize 不自动转小写余部 除非传第二个参数 true,否则 wHoOaA!WHoOaA! 而非 Whooaa!
中文场景直接用价值有限 titleCase 对英文效果显著;中文场景主要靠 intCommafileSizepluralize
不支持复数语言本地化 pluralize 只支持英语单复数,多语言项目需要 i18n 方案
cdnjs 版本可能旧 如用 CDN 引入,确认 cdnjs 上版本号;建议直接 npm 安装

与同类对比

工具 体积 功能覆盖 特殊能力 适合场景
humanize-plus ~4 KB gzip 数字+文本格式化 toFixed 精度修复、oxford 列表 轻量仪表盘、展示层
Numeral.js ~6 KB 数字格式化为主 多语言数字格式 需要复杂数字格式
Moment.js / dayjs 较大 时间处理 时间计算/解析/本地化 时间相关场景
date-fns 中等 时间处理 函数式组合 时间场景(无复数/文本处理)
lodash 较大 通用工具 一切 庞大项目,多处用到工具函数
Intl API(原生) 0 KB 数字/日期本地化 浏览器原生无依赖 现代浏览器环境

Humanize-plus 的核心优势是轻量 + 即插即用,一个文件覆盖前端展示层 80% 的格式化需求,无需引入 Moment/lodash 这类重型库。

一句话推荐结论

一个小于 4 KB 的前端格式化工具库,intCommafileSizepluralizeoxford 等 20+ 函数覆盖 Dashboard / 聊天机器人 / 推送文案等场景的常见需求——直接 npm 装,不需要为这些简单需求引入 lodash 或 moment。

源码编译(如需贡献)

npm run install && npm run build
# 编译 CoffeeScript 源码到 dist/

npm run test
# 运行测试