Nut 4.0.0

dotnet add package Nut --version 4.0.0
                    
NuGet\Install-Package Nut -Version 4.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Nut" Version="4.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Nut" Version="4.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Nut" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Nut --version 4.0.0
                    
#r "nuget: Nut, 4.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Nut@4.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Nut&version=4.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Nut&version=4.0.0
                    
Install as a Cake Tool

NUT — Number To Text

NuGet Downloads CI License: MIT

Writes numbers and money amounts as words, in 14 languages — for the amount in words field on invoices, cheques and contracts.

using Nut;

123456.ToText();                                    // one hundred twenty-three thousand four hundred fifty-six
123456.78m.ToText(Currency.USD, Language.English);  // one hundred twenty-three thousand four hundred fifty-six dollars seventy-eight cents
123456.78m.ToText(Currency.TRY, Language.Turkish);  // yüz yirmi üç bin dört yüz elli altı türk lirası yetmiş sekiz kuruş

Install

dotnet add package Nut

Targets .NET Standard 2.0, so it runs on .NET Framework 4.6.1+, .NET Core 2.0+ and .NET 5 and later. No dependencies.

Languages

Pass either the short code or the culture code. Matching ignores case.

Language Codes Language Codes
English (US) en, en-US Latvian lv, lv-LV
English (UK) en-GB Polish pl, pl-PL
French fr, fr-FR Portuguese pt, pt-BR
German de, de-DE Russian ru, ru-RU
Spanish es, es-ES Turkish tr, tr-TR
Amharic am, am-ET Ukrainian uk, uk-UA
Belarusian be, be-BY Uzbek uz, uz-UZ
Bulgarian bg, bg-BG

en-GB differs from en-US: 101 reads as one hundred and one rather than one hundred one.

Ukrainian and Belarusian used to be keyed by their ccTLDs, ua and by. Those still resolve, but the codes above are the ones CultureInfo hands you.

Extensions.SupportedLanguages returns the full list at runtime.

Currencies

EUR USD GBP RUB TRY UAH BGN ETB PLN BYN ARS BRL UZS

Also accepted: TL for TRY, RUR for RUB.

Not every language covers every currency, and a combination a language does not cover raises NotSupportedException rather than guessing at the wording:

Language Missing
Uzbek everything but UZS, USD and RUB
Amharic ARS, BRL, GBP, UZS
Belarusian UZS, ETB
Polish, Bulgarian, Latvian UZS

These are gaps of evidence rather than of effort. Each one is a word nobody could source, and this text goes on documents people sign.

2575.50m.ToText(Currency.EUR, Language.German);   // zweitausendfünfhundertfünfundsiebzig Euro fünfzig Cent
2575.50m.ToText(Currency.EUR, Language.French);   // deux mille cinq cent soixante-quinze euros cinquante centimes
2575.50m.ToText(Currency.EUR, Language.Russian);  // две тысячи пятьсот семьдесят пять евро пятьдесят евроцентов
2575.50m.ToText(Currency.EUR, Language.Latvian);  // divi tūkstoši pieci simti septiņdesmit pieci eiro un piecdesmit centi

Options

var options = new Options { MainUnitFirstCharUpper = true, CurrencyFirstCharUpper = true };
2575.50m.ToText(Currency.USD, Language.English, options);
// Two thousand five hundred seventy-five Dollars fifty Cents
Option Effect
MainUnitFirstCharUpper Capitalises the first word. On a negative amount the capital goes on the sign: Minus two thousand…
SubUnitFirstCharUpper Capitalises the fractional part
CurrencyFirstCharUpper Capitalises the currency names
MainUnitNotConvertedToText Leaves the whole part as digits
SubUnitZeroNotDisplayed Drops the fractional part when it is zero
SubUnitFormat Words (default), Digits, or Fraction — see below
SubUnitTruncated Cuts extra decimals instead of rounding them

Writing the fraction the way cheques do

new Options { SubUnitFormat = SubUnitFormat.Fraction }
// two thousand five hundred seventy-five dollars and 50/100

Zero is written as 00/100 rather than dropped, so nothing can be added to the amount afterwards.

Writing the sub-unit over a hundred is an anglophone cheque convention rather than a rule of any language, so English is the only language it is available in. Asking for it in any other raises NotSupportedException rather than borrowing the English and.

Behaviour worth knowing

Rounding. Amounts carrying more decimals than the currency has are rounded to the sub-unit, half away from zero — the same result decimal.ToString("C") gives, so the figures and the words on a document agree.

123.456m.ToText(Currency.USD, Language.English);  // one hundred twenty-three dollars forty-six cents

Set SubUnitTruncated to cut the digits instead.

Negative amounts use the language's own word — minus, moins, menos, eksi, минус, mīnus, ሲቀነስ.

(-2575.50m).ToText(Currency.USD, Language.English);  // minus two thousand five hundred seventy-five dollars fifty cents

Unsupported input throws. An unknown language, or a currency a language does not cover, raises NotSupportedException naming what was asked for. It does not return an empty string: a blank amount field on a document is not noticed until the document has gone out.

Ukrainian paper payment instructions require the amount in words to start with a capital letter — NBU Board Resolution 29.07.2022 №163, Annex, field 4. Pass MainUnitFirstCharUpper when printing one. The same resolution says the field is left empty on electronic instructions.

var options = new Options { MainUnitFirstCharUpper = true };
105.50m.ToText(Currency.UAH, Language.Ukrainian, options);
// Сто п'ять гривень п'ятдесят копійок

Range. Magnitudes below one trillion. Beyond that raises ArgumentOutOfRangeException. Rounding counts: an amount that crosses the limit only after being rounded to the sub-unit raises it too.

Thread safety. Conversions are independent and safe to run in parallel.

Contributing

Pull requests are welcome. Two things make them much easier to accept:

  • Add tests for what you change. dotnet test src/Nut.sln runs the suite; CI runs it on every pull request and fails on warnings.
  • A new language or currency needs expected outputs written by someone who reads it. Nobody here can check wording in a language they do not speak, and this text ends up on financial documents. A table of expected results is what makes such a contribution reviewable. Cover at least 0, 1, 2, 11, 21, 100, 1000, 2000, 41000, 1000000 plus one decimal amount, and say where the forms come from.

src/Nut.Tests/behaviour-snapshot.tsv pins every language × currency × amount combination. If a change is meant to alter output, regenerate it with UPDATE_SNAPSHOT=1 dotnet test — the diff of that file becomes the record of what changed.

Changelog

See CHANGELOG.md.

Thanks

Licence

MIT — see LICENCE.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
4.0.0 154 7/29/2026
3.5.0 89 7/28/2026
3.4.1 169,432 6/2/2023
3.3.0 97,475 5/24/2022
3.2.4 56,408 9/27/2021
3.2.3 1,098 9/19/2021
3.1.1 14,412 1/27/2021
3.1.0 1,084 1/27/2021
3.0.0 66,393 7/3/2020
2.4.2 60,299 5/27/2016
2.4.1 2,494 1/15/2016
2.4.0 1,990 1/15/2016
2.3.3 2,169 4/14/2015
2.3.2 2,027 4/7/2015
2.3.1 2,042 4/7/2015
Loading failed