This guide is for teams upgrading directly from 2.14.1 to 3.0.8.
This document was added to address issue #1656 (undocumented v3 breaking changes).
The current 3.0.8 package also ships generated locale data in the main Humanizer package, so locale support and analyzer support are both part of the same restore path.
Validated against:
- Git tag
v2.14.1 - v3 breaking-change commits through
v3.0.1 - v3 patch-line fixes included in
3.0.8:
- Update package/tooling prerequisites first (framework and restore requirements).
- If you are on
3.0.1, upgrade to3.0.8to pick up patch-line compatibility fixes (#1655, #1665, #1672, #1652, #1658). - Run the namespace migration analyzer and replace old
using Humanizer.*directives. - Replace removed APIs (
FormatWith, obsoleteToMetricoverloads, etc.). - Rebuild all assemblies that reference Humanizer (binary compatibility changed in a few APIs).
- If you implement extensibility points (
IFormatter,DefaultFormatter), update those implementations. - Run behavioral regression tests for
Titleize,Pascalize,Dehumanize, and enum humanization.
All Humanizer APIs were consolidated into the root Humanizer namespace.
Related:
- PR #1351
- Upgrade impact report: issue #1656
Before:
using Humanizer.Bytes;
using Humanizer.Localisation;
using Humanizer.Configuration;After:
using Humanizer;Use the built-in analyzer (HUMANIZER001) to automate this migration.
See also: Namespace-only migration guide.
StringExtensions.FormatWith(...)was removed.
Related:
- PR #1395
- Upgrade impact report: issue #1656
Before:
"{0:N2}".FormatWith(culture, value);After:
string.Format(culture, "{0:N2}", value);- Obsolete
ToMetricoverloads were removed:
ToMetric(this int input, bool hasSpace, bool useSymbol = true, int? decimals = null)ToMetric(this double input, bool hasSpace, bool useSymbol = true, int? decimals = null)
Use MetricNumeralFormats instead:
// Equivalent to: value.ToMetric(hasSpace: true, useSymbol: true, decimals: 2);
value.ToMetric(MetricNumeralFormats.WithSpace, decimals: 2);
// If you previously passed useSymbol: false:
value.ToMetric(MetricNumeralFormats.WithSpace | MetricNumeralFormats.UseName, decimals: 2);Related:
- PR #1389
- Upgrade impact report: issue #1656
ToQuantity(this string, int, ...)overloads were removed in early v3 and later restored in the patch line (3.0.6+, including3.0.8).
Related:
- PR #1338
- Follow-up request and resolution: issue #1652, PR #1679
EnglishArticlesenum was removed.
Related:
Configurator.EnumDescriptionPropertyLocatorpublic property was removed.
Use Configurator.UseEnumDescriptionPropertyLocator(...) instead, and call it early during startup:
Configurator.UseEnumDescriptionPropertyLocator(p => p.Name == "Info");UseEnumDescriptionPropertyLocator(...) now throws if you call it after enum humanization has already occurred.
Related:
- Upgrade impact report: issue #1656
- Legacy localized resource-key lookup APIs were removed.
The string-keyed resource model is no longer part of Humanizer's supported surface. Locale data is now generated from YAML locale definitions rather than .resx files.
Removed APIs:
Resources.GetResource(...)Resources.TryGetResource(...)ResourceKeysResourceKeys.DateHumanizeResourceKeys.TimeSpanHumanizeResourceKeys.TimeUnitSymbolDefaultFormatterprotected resource-key override helpers:Format(string resourceKey)Format(TimeUnit unit, string resourceKey, int number, bool toWords = false)GetResourceKey(string resourceKey)GetResourceKey(string resourceKey, int number)
Before:
var key = ResourceKeys.DateHumanize.GetResourceKey(TimeUnit.Day, Tense.Past, 2);
var text = Resources.GetResource(key, culture);After:
var text = DateTime.UtcNow.AddDays(-2).Humanize(culture: culture);Use the typed Humanizer APIs (Humanize, ToAge, ToFullWords, ToSymbol, and formatter implementations based on IFormatter) instead of string resource-key lookup.
Enum APIs moved from Enum-based extension signatures to constrained generics:
Before (2.14.1):
public static string Humanize(this Enum input)
public static string Humanize(this Enum input, LetterCasing casing)
public static TTargetEnum DehumanizeTo<TTargetEnum>(this string input)
where TTargetEnum : struct, IComparable, IFormattableAfter (3.0.8):
public static string Humanize<T>(this T input) where T : struct, Enum
public static string Humanize<T>(this T input, LetterCasing casing) where T : struct, Enum
public static TTargetEnum DehumanizeTo<TTargetEnum>(this string input)
where TTargetEnum : struct, EnumImpact:
- Code that stores values as
Enum(not a concrete enum type) and then calls.Humanize()no longer compiles. - Generic callers with non-enum constraints for
DehumanizeTo<T>no longer compile.
Related:
- Upgrade impact report: issue #1656
If you implement or subclass formatting infrastructure, update your code:
IFormatternow requires:
string TimeSpanHumanize_Age();DefaultFormatteroverride surface changed:
Before:
protected virtual string Format(string resourceKey, int number, bool toWords = false)Intermediate v3 shape:
protected virtual string Format(TimeUnit unit, string resourceKey, int number, bool toWords = false)Current shape:
Those legacy resource-key override hooks are now removed entirely. DefaultFormatter implementations should override the typed formatter members such as DateHumanize(...), TimeSpanHumanize(...), TimeUnitHumanize(...), DataUnitHumanize(...), DateHumanize_Now(), DateHumanize_Never(), TimeSpanHumanize_Zero(), and TimeSpanHumanize_Age() instead.
Related:
- API introduction that expanded formatter contract: PR #1068
- Upgrade impact report: issue #1656
Compared to 2.14.1, v3 removed support for:
netstandard1.0net462net472- dedicated
net6.0assets (consumers onnet6.0/net7.0now resolvenetstandard2.0assets)
3.0.8 package assets target:
netstandard2.0net48net8.0net10.0
Related:
netstandard1.0removal: PR #1322net462/net472removal: PR #1482- Upgrade impact report: issue #1656
The Humanizer metapackage requires NuGet locale parsing support from newer tooling.
You need:
- .NET SDK
9.0.200+, or - Visual Studio/MSBuild that includes the same NuGet locale parsing fix.
On older tooling, restore can fail for the metapackage. Workaround: reference Humanizer.Core directly and install needed locale packages explicitly.
Related:
- NuGet locale parsing fix dependency note: NuGet.Client discussion
Several locale package IDs changed between 2.14.1 and 3.0.8:
2.14.1 package |
3.0.8 package |
|---|---|
Humanizer.Core.bn-BD |
Humanizer.Core.bn |
Humanizer.Core.fi-FI |
Humanizer.Core.fi |
Humanizer.Core.ko-KR |
Humanizer.Core.ko |
Humanizer.Core.ms-MY |
Humanizer.Core.ms |
Humanizer.Core.nb-NO |
Humanizer.Core.nb |
Humanizer.Core.th-TH |
Humanizer.Core.th |
Removed from the metapackage dependency list (no direct one-to-one replacement):
Humanizer.Core.fr-BE
Related:
- Locale ID normalization change: commit 7b14ef6f
- Upgrade impact report: issue #1656
Pascalizenow treats hyphens (-) as delimiters.Dehumanizeoutput can differ because it is based onHumanize().Pascalize()and inheritsPascalizechanges.Humanize/Titleizepreserve strings with no recognized letters instead of returning empty string.
Related:
Pascalizehyphen behavior change: issue #1282, PR #1299Dehumanize/spacing impact reports: issue #1656, issue #1668Titleizeno-letter preservation: issue #385, PR #1611TitleCasefirst-word casing regression: issue #1658
3.0.8 includes analyzer loading compatibility fixes from PR #1676.
| Issue | Status | Impact in 3.0.1 | 3.0.8 result |
|---|---|---|---|
| #1655 | Closed | Analyzer could fail to load on .NET 8 SDK hosts. | Fixed |
| #1665 | Closed | Analyzer load failure due to System.Memory binding mismatch. |
Fixed |
| #1672 | Closed | Analyzer load failure due to System.Collections.Immutable dependency mismatch. |
Fixed |
| Issue | Status | Patch-line fix |
|---|---|---|
| #1652 | Closed | ToQuantity(int, ...) compatibility restored via PR #1679 (in 3.0.6+, included in 3.0.8). |
| #1658 | Closed | TitleCase first-word capitalization fixed via PR #1678 (in 3.0.6+, included in 3.0.8). |
| Issue | Status | Impact | Suggested mitigation |
|---|---|---|---|
| #1668 | Open | Some Dehumanize() cases retain underscore before digits (for example everything_0). |
Pre-normalize affected inputs before Dehumanize(), or use custom conversion logic for these patterns. |
After migration:
- Full clean restore with your actual CI SDK image.
- Full rebuild of all projects that reference Humanizer.
- Integration tests around string casing, enum formatting/dehumanization, and quantity formatting.
- Spot-check localized output if you depended on renamed locale packages.