Releases: axuno/SmartFormat
v3.4.0
What's Changed
.NET Framework 4.6.2
SmartFormat has transitioned to using .NET Framework 4.6.2 (net462)
as its target framework, replacing the now unsupported .NET Framework 4.6.1 (net461)
. The support for net461
ended in 2022, while net462
will continue to receive support until January 2027.
Switching to a different patch version of a target framework is generally not considered a breaking change. This is referred to as an in-place update by Microsoft. In the case of SmartFormat, we have not encountered any runtime issues with the existing API after this transition.
The same holds true for the new netstandard2.0
reference to ZString.
.NET 6.0 and .NET 8.0
SmartFormat has expanded its compatibility by adding .NET 6.0 (net60)
and .NET 8.0 (net80)
as additional target frameworks. You can find details about their end of support here.
All Target Frameworks
We have removed the SmartFormat.ZString
assembly and replaced it with a reference to the ZString package. This change does not affect the API.
Commits in detail
- Fix: Update nuget api key in #378
- Target Framework Updates in #389 (merged the version/3.4.0 branch)
Thanks to @thompson-tomo for his first contribution with #377
Full Changelog: v3.3.2...v3.4.0
v3.3.2
Reasoning for the Update
- Regression caused by #368
- If there are namespace collisions with Cysharp.Text using v3.3.1 please update to v3.2.2
What's Changed
- Change all public types in namespace Cysharp.Text to internal in #372
- Stop namespace collisions with Cysharp.ZString nuget package
- Affects: class, struct, interface, delegate, enum
- using https://github.com/zzzprojects/findandreplace on command line, so we can automate this step:
"fnr.exe" --cl --dir "SmartFormat.ZString\repo\src\ZString" --fileMask ".cs,.tt" --includeSubDirectories --caseSensitive --useRegEx --find "public (?=.*(class |struct |enum |interface |delegate ))" --replace "internal " - Add a unit test to get an alert when Cysharp.Text objects are public (e.g. after an update)
- Bump version to v3.3.2
Full Changelog: v3.3.1...v3.3.2
v3.3.1
Fix
PluralRule for DualFromZeroToTwo: Now a value of 2 is covered and will not throw. Frend is one of the affected languages. Closes #369 in #370
Enhancement
Dictionary<string, PluralRuleDelegate> PluralRule.IsoLangToDelegate
holds delegate
s with the pluralization rule per language. Changing a value of this dictionary will change the pluralization rules globally. This is not recommended, but possible. After a change calling PluralRules.RestoreDefault()
will restore the default rules.
Other Changes
- Unit tests: Convert NUnit Classic Assert to Constraint Model in #364
- Bump NUnit package reference to v4.0.1 in #367
- Linq optimizations in #366
- Update package Cysharp.ZString to v2.5.1 in #368
- Bump version to v3.3.1 in #371
Full Changelog: v3.3.0...v3.3.1
v3.3.0
What's Changed
- Add support for nested formats in
LocalizationFormatter
by @zacateras in #350. This is useful, if the string to localize contains a SmartFormat placeholder instead of a pure text. Example: If the format is"{:L:{ProductType}}"
, theProductType
placeholder will be replaced with the variable content "pen". "pen" will in turn be localiced to "bic" for theFR
locale. DictionarySource
has an option to evaluateIReadOnlyDictionary<TKey,TValue>
sources by @axunonb in #353. To enable, setDictionarySource.IsIReadOnlyDictionarySupported
totrue
(default isfalse
). This is for types that only implementIReadOnlyDictionary<TKey,TValue>
, but notIDictionary
.- Bump version to v3.3.0 in #356
New Contributors
- Thanks to @zacateras for the first contribution in #350
Full Changelog: v3.2.2...v3.3.0
v3.2.2
What's Changed
Fix
-
PluralLocalizationFormatter
does not treat a numeric string as valid argument (resolves #345, restore behavior of v3.1.0 and before) in #346 -
Bump version to v3.2.2
Meaning:
Smart.Format("{0:{}|is null or empty}", "1234");
will not implicitly invokePluralLocalizationFormatter
but insteadConditionalFormatter
. So the result is "1234" as to be expected. A string argument toPluralLocalizationFormatter
is never accepted, even if it could be converted to a number.
Chore
- Update appveyor and github CI scripts
- Update change log for v3.2.1 in #331
- Update NuGet API Key in #335
- Update link to pluralization rules we use as a reference in #338
- Add unit test for DateOnly and TimeOnly types (NET6.0+) in #341
Full Changelog: v3.2.1...v3.2.2
v3.2.1
What's Changed
PluralLocalizationFormatter
-
Fix: Auto-detection of PluralLocalizationFormatter does not throw for values not convertible to decimal by @axunonb in #330 Resolves #329 (Thanks to @BtbN)
-
Current behavior, introduced in v3.2.0:
WhenPluralLocalizationFormatter.CanAutoDetect == true
, values that are not convertible todecimal
will throw then trying toIConvertible.ToDecimal(...)
-
New behavior, equivalent to v3.1.0:
WhenPluralLocalizationFormatter.CanAutoDetect == true
, for values that are not convertible todecimal
,IFormatter.TryEvaluateFormat(...)
will returnfalse
-
Other Changes
- EditorConfig and appveyor.yml by @axunonb in #319
- Integrate Cysharp.ZString release v2.5.0 (26 Oct 2022) by @axunonb in #323
- Fix: PluralRules for Czech locale by @alexheb in #325
- Fixes for Demo App and NUnit TestAdapter by @axunonb in #328
New Contributors
Full Changelog: v3.2.0...v3.2.1
v3.2.0
Enhancements
- Remove usage of Linq for less GC
- Add
IConvertable
support forPluralLocalizationFormatter
andConditionalFormatter
ListFormatter
- ListFormatter handles selector name "Index" in
IEnumerable
s andIList
s: Inv1.6.1
a Selector was tested for having the name "index", even if data was not anIList
, and returned theCollectionIndex
. This is now implemented again in theListFormatter.TryEvaluateSelector(...)
- Set the
ParentPlaceholder
property for itemFormat
s - Use
PooledObject<T>
where possible, so objects will be returned toObjectPool
also in case of exceptions
- ListFormatter handles selector name "Index" in
Fixes
FormatItem.AsSpan()
returns the correct name- Remove potential namespace collisions: All public types in namespace
Cysharp.Text
are now internal
What's Changed
- Upgrade projects targeting NET5.0 to NET6.0 by @axunonb in #286
- Refactor suggestions by @karljj1 in #290
- Refactored unit tests for ReflectionSource and thread-safe mode by @axunonb in #291
- Convert solution to file-scoped namespacing by @axunonb in #292
- Use
is
instead of checking the type info. by @karljj1 in #293 - SonarCloud do not support analysis of forked PRs by @axunonb in #294
- Avoid using Linq as it generates GC each time. by @karljj1 in #296
- IConvertible support for plural and conditional formatters by @karljj1 in #300
- Fixed: FormatItem.AsSpan() by @axunonb in #304
- Refactor ListFormatter by @axunonb in #305
- Ignore bools in plurals formatter. by @karljj1 in #306
- Change all public types in namespace Cysharp.Text to internal by @axunonb in #309
- ListFormatter handles selector name "Index" in IEnumerable and IList by @axunonb in #314
- Bump version to v3.2.0 by @axunonb in #315
Full Changelog: v3.1.0...v3.2.0
v2.7.3
Fix: Newtonsoft.Json prior to version 13.0.1 is vulnerable
Newtonsoft.Json prior to version 13.0.1 is vulnerable to Insecure Defaults due to improper handling of expressions with high nesting level that lead to StackOverFlow exception or high CPU and RAM usage. Exploiting this vulnerability results in Denial Of Service (DoS).
Package reference updated to a minimum version 13.0.1
v3.1.0
This is a feature update, that is released upon feedback from the community.
Thread-safe Mode
Thread-safe mode is now enabled by default:
SmartSettings.IsThreadSafeMode == true
.
This has no impact on the API.
In case SmartFormat is exclusively utilized in a single-threaded context, SmartSettings.IsThreadSafeMode=false
should be considered for enhanced performance.
Static Smart
Methods for Formatting
Static Smart
methods like Smart.Format(format, args) can now be called in an async
/ multi-threaded context.
The SmartFormatter
instance returned by Smart.Default
is flagged with the ThreadStatic
attribute.
See more details in the Wiki: Async and Thread Safety
ListFormatter
may have Placeholders in "spacers"
Thanks to karljj1 for the PR.
Before v3.1.0 the format options for ListFormatter
could only contain literal text. Now Placeholder
s are allowed.
Example:
var args = new {
Names = new[] { "John", "Mary", "Amy" },
IsAnd = true, // true or false
Split = ", " // comma and space as list separator
};
_ = Smart.Format("{Names:list:{}|{Split}| {IsAnd:and|nor} }", args);
// Output for "IsAnd=true": "John, Mary and Amy"
// Output for "IsAnd=false": "John, Mary nor Amy"
v3.0.0
Changes since v3.0.0-rc.2
SubStringFormatter
The formatter now accecpts a format argument with a nested Placeholder
that lets you format the result of the sub-string operation.
Example: Convert the sub-string to lower-case:
Smart.Format("{0:substr(0,2):{ToLower}}", "ABC");
Reasoning: Enhancement
Nullable Notation
KeyValuePairSource
, PersistentVariablesSource
and GlobalVariablesSource
can now process "null if nullable"
Reasoning: Enhancement
TemplateFormatter
The name of the formatter is now "t"
(was "template" before).
Reasoning: Minimize the format string
Char to split options and formats is limited to pipe, comma, tilde
- Char to split options and formats is limited to pipe, comma, tilde
- SplitChar for formatters is unified and checked for validity
- Affects
ChooseFormatter
,ConditionalFormatter
,IsMatchFormatter
,ListFormatter
,PluralLocalizationFormatter
,SubStringFormatter
Reasoning: Avoid conflicts with reserved characters
Modified ChooseFormatter case-sensitivity for option strings
- bool and null: always case-insensitive
- using SmartSettings.CaseSensitivity unless overridden with ChooseFormatter.CaseSensitivity
- option strings comparison is culture-aware, using CultureInfo if supplied in Smart.Format(...) or CurrentUICulture
Reasoning: Enhancement
Magic Leading Colon
An implementation of a magic leading colon in order to identify whether ConditionalFormatter
or PluralLocalizationFormatter
should be invoked, was removed.
Reasoning:
This is undocumented and unnecessary.
Adding the formatter name in the format string achieves the same target.