docs/migration-v3.md
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).
Validated against:
v2.14.1v3.0.13.0.8:
3.0.1, upgrade to 3.0.8 to pick up patch-line compatibility fixes (#1655, #1665, #1672, #1652, #1658).using Humanizer.* directives.FormatWith, obsolete ToMetric overloads, etc.).IFormatter, DefaultFormatter), update those implementations.Titleize, Pascalize, Dehumanize, and enum humanization.All Humanizer APIs were consolidated into the root Humanizer namespace.
Related:
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:
Before:
"{0:N2}".FormatWith(culture, value);
After:
string.Format(culture, "{0:N2}", value);
ToMetric overloads 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:
ToQuantity(this string, int, ...) overloads were removed in early v3 and later restored in the patch line (3.0.6+, including 3.0.8).Related:
EnglishArticles enum was removed.Related:
Configurator.EnumDescriptionPropertyLocator public 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:
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, IFormattable
After (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, Enum
Impact:
Enum (not a concrete enum type) and then calls .Humanize() no longer compiles.DehumanizeTo<T> no longer compile.Related:
IFormatter / DefaultFormatter)If you implement or subclass formatting infrastructure, update your code:
IFormatter now requires:string TimeSpanHumanize_Age();
DefaultFormatter override surface changed:Before:
protected virtual string Format(string resourceKey, int number, bool toWords = false)
After:
protected virtual string Format(TimeUnit unit, string resourceKey, int number, bool toWords = false)
If you had custom DefaultFormatter subclasses overriding the old signature, they must be migrated.
Related:
Compared to 2.14.1, v3 removed support for:
netstandard1.0net462net472net6.0 assets (consumers on net6.0/net7.0 now resolve netstandard2.0 assets)3.0.8 package assets target:
netstandard2.0net48net8.0net10.0Related:
netstandard1.0 removal: PR #1322net462/net472 removal: PR #1482The Humanizer metapackage requires NuGet locale parsing support from newer tooling.
You need:
9.0.200+, orOn older tooling, restore can fail for the metapackage. Workaround: reference Humanizer.Core directly and install needed locale packages explicitly.
Related:
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-BERelated:
Pascalize now treats hyphens (-) as delimiters.Dehumanize output can differ because it is based on Humanize().Pascalize() and inherits Pascalize changes.Humanize / Titleize preserve strings with no recognized letters instead of returning empty string.Related:
Pascalize hyphen behavior change: issue #1282, PR #1299Dehumanize/spacing impact reports: issue #1656, issue #1668Titleize no-letter preservation: issue #385, PR #1611TitleCase first-word casing regression: issue #16583.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: