diff --git a/.docfx/Dockerfile.docfx b/.docfx/Dockerfile.docfx
index 3897848..0e78ce5 100644
--- a/.docfx/Dockerfile.docfx
+++ b/.docfx/Dockerfile.docfx
@@ -1,4 +1,4 @@
-FROM nginx:1.27.1-alpine AS base
+FROM nginx:1.27.3-alpine AS base
RUN rm -rf /usr/share/nginx/html/*
FROM codebeltnet/docfx:2.77.0 AS build
diff --git a/.docfx/docfx.json b/.docfx/docfx.json
index a3d34f5..1fce029 100644
--- a/.docfx/docfx.json
+++ b/.docfx/docfx.json
@@ -12,7 +12,7 @@
"dest": "api",
"filter": "filterConfig.yml",
"properties": {
- "TargetFramework": "net8.0"
+ "TargetFramework": "net9.0"
}
}
],
@@ -45,7 +45,7 @@
],
"globalMetadata": {
"_appTitle": "Extensions for Globalization by Codebelt",
- "_appFooter": "Generated by DocFX. Copyright 2024 ClassLibrary1. All rights reserved.",
+ "_appFooter": "Generated by DocFX. Copyright 2024-2025 Geekle. All rights reserved.",
"_appLogoPath": "images/50x50.png",
"_appFaviconPath": "images/favicon.ico",
"_googleAnalyticsTagId": "G-R07CSX4Z91",
diff --git a/.github/workflows/pipelines.yml b/.github/workflows/pipelines.yml
index 37bebd6..70e34f8 100644
--- a/.github/workflows/pipelines.yml
+++ b/.github/workflows/pipelines.yml
@@ -26,7 +26,7 @@ jobs:
strategy:
matrix:
configuration: [Debug, Release]
- framework: [net8.0,net6.0,netstandard2.0]
+ framework: [net9.0,net8.0,netstandard2.0]
outputs:
version: ${{ steps.minver-calculate.outputs.version }}
steps:
diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml
new file mode 100644
index 0000000..aabea97
--- /dev/null
+++ b/.github/workflows/scorecard.yml
@@ -0,0 +1,42 @@
+name: Scorecard supply-chain security
+on:
+ branch_protection_rule:
+ schedule:
+ - cron: '45 17 * * 2'
+ push:
+ branches: [ "main" ]
+
+permissions: read-all
+
+jobs:
+ analysis:
+ name: Scorecard analysis
+ runs-on: ubuntu-latest
+ permissions:
+ security-events: write
+ id-token: write
+
+ steps:
+ - name: "Checkout code"
+ uses: actions/checkout@v4
+ with:
+ persist-credentials: false
+
+ - name: "Run analysis"
+ uses: ossf/scorecard-action@v2.4.0
+ with:
+ results_file: results.sarif
+ results_format: sarif
+ publish_results: true
+
+ - name: "Upload artifact"
+ uses: actions/upload-artifact@v4
+ with:
+ name: SARIF file
+ path: results.sarif
+ retention-days: 5
+
+ - name: "Upload to code-scanning"
+ uses: github/codeql-action/upload-sarif@v3
+ with:
+ sarif_file: results.sarif
diff --git a/.nuget/Codebelt.Extensions.Globalization/PackageReleaseNotes.txt b/.nuget/Codebelt.Extensions.Globalization/PackageReleaseNotes.txt
index cfcf325..bdb5d66 100644
--- a/.nuget/Codebelt.Extensions.Globalization/PackageReleaseNotes.txt
+++ b/.nuget/Codebelt.Extensions.Globalization/PackageReleaseNotes.txt
@@ -1,4 +1,11 @@
-Version 8.4.0
+Version 9.0.1
+Availability: .NET 9, .NET 8 and .NET Standard 2.0
+
+# ALM
+- CHANGED Dependencies to latest and greatest with respect to TFMs
+- REMOVED Support for TFM .NET 6 (LTS)
+
+Version 8.4.0
Availability: .NET 8, .NET 6 and .NET Standard 2.0
# ALM
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9e84b36..1f59665 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
For more details, please refer to `PackageReleaseNotes.txt` on a per assembly basis in the `.nuget` folder.
+> [!NOTE]
+> Changelog entries prior to version 9.0.1 was migrated from previous versions of Cuemon.Extensions.Globalization.
+
+## [9.0.1] - 2025-01-29
+
+This is a service update that primarily focuses on package dependencies and minor improvements.
+
## [8.4.0] - 2024-09-28
### Changed
diff --git a/Directory.Build.props b/Directory.Build.props
index f8a4bde..17dc0f7 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -15,8 +15,8 @@
- net8.0;net6.0;netstandard2.0
- Copyright © Geekle 2024. All rights reserved.
+ net9.0;net8.0;netstandard2.0
+ Copyright © Geekle 2025. All rights reserved.
gimlichael
Geekle
Extensions for Globalization API by Codebelt
@@ -35,6 +35,7 @@
true
$(MSBuildThisFileDirectory)globalization.snk
7035,CA2260
+ v
@@ -42,18 +43,17 @@
-
-
+
- net8.0;net6.0
+ net9.0;net8.0
- net8.0;net6.0;net48
+ net9.0;net8.0;net48
@@ -69,19 +69,19 @@
-
-
-
-
-
+
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/Directory.Build.targets b/Directory.Build.targets
index bf44e11..05374a0 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -14,8 +14,8 @@
- 00000
- $(MinVerMajor).$(MinVerMinor).$(MinVerPatch).$(BUILD_BUILDNUMBER)
+ 0
+ $(MinVerMajor).$(MinVerMinor).$(MinVerPatch).$(GITHUB_RUN_NUMBER)
diff --git a/Directory.Packages.props b/Directory.Packages.props
new file mode 100644
index 0000000..f1b9a41
--- /dev/null
+++ b/Directory.Packages.props
@@ -0,0 +1,16 @@
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
index d188e75..fd45efc 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2024 Geekle
+Copyright (c) 2024-2025 Geekle
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/src/Codebelt.Extensions.Globalization/Codebelt.Extensions.Globalization.csproj b/src/Codebelt.Extensions.Globalization/Codebelt.Extensions.Globalization.csproj
index 204afd7..fe2cd92 100644
--- a/src/Codebelt.Extensions.Globalization/Codebelt.Extensions.Globalization.csproj
+++ b/src/Codebelt.Extensions.Globalization/Codebelt.Extensions.Globalization.csproj
@@ -1200,8 +1200,7 @@
-
-
+
diff --git a/test/Codebelt.Extensions.Globalization.Tests/YamlSerializerTest.cs b/test/Codebelt.Extensions.Globalization.Tests/YamlSerializerTest.cs
new file mode 100644
index 0000000..ab77a2c
--- /dev/null
+++ b/test/Codebelt.Extensions.Globalization.Tests/YamlSerializerTest.cs
@@ -0,0 +1,441 @@
+using System;
+using System.Globalization;
+using System.Linq;
+using System.Runtime.InteropServices;
+using Codebelt.Extensions.Xunit;
+using Codebelt.Extensions.YamlDotNet;
+using Codebelt.Extensions.YamlDotNet.Formatters;
+using Cuemon;
+using Cuemon.Extensions.IO;
+using Xunit;
+using Xunit.Abstractions;
+using YamlDotNet.Core;
+using YamlDotNet.Serialization.NamingConventions;
+
+namespace Codebelt.Extensions.Globalization
+{
+ public class YamlSerializerTest : Test
+ {
+ private static readonly CultureInfo DanishCulture = new CultureInfo("da-DK").UseNationalLanguageSupport(); // from .NET6+ this is needed for both Windows and Linux; at least from pipeline (worked locally for Windows without Merge ...)
+
+ public YamlSerializerTest(ITestOutputHelper output) : base(output)
+ {
+ }
+
+ [Fact]
+ public void Serialize_ShouldSerializeDateFormatInfo()
+ {
+ var sut2 = DanishCulture;
+ var sut3 = YamlFormatter.SerializeObject(sut2.DateTimeFormat, o =>
+ {
+ o.Settings.NamingConvention = PascalCaseNamingConvention.Instance;
+ o.Settings.ScalarStyle = ScalarStyle.Plain;
+ o.Settings.IndentSequences = false;
+ o.Settings.FormatProvider = DanishCulture;
+ o.Settings.Converters.Add(YamlConverterFactory.Create((writer, dt, _) => writer.WriteValue(dt.ToString(DanishCulture))));
+ });
+ var sut4 = sut3.ToEncodedString();
+
+ TestOutput.WriteLine(sut4);
+
+ var expected = @"AMDesignator: ''
+Calendar:
+ MinSupportedDateTime: 01-01-0001 00:00:00
+ MaxSupportedDateTime: 31-12-9999 23:59:59
+ AlgorithmType: SolarCalendar
+ CalendarType: Localized
+ Eras:
+ - 1
+ TwoDigitYearMax: {0}
+DateSeparator: '-'
+FirstDayOfWeek: Monday
+CalendarWeekRule: FirstFourDayWeek
+FullDateTimePattern: d. MMMM yyyy HH:mm:ss
+LongDatePattern: d. MMMM yyyy
+LongTimePattern: HH:mm:ss
+MonthDayPattern: d. MMMM
+PMDesignator: ''
+RFC1123Pattern: ddd, dd MMM yyyy HH':'mm':'ss 'GMT'
+ShortDatePattern: dd-MM-yyyy
+ShortTimePattern: HH:mm
+SortableDateTimePattern: yyyy'-'MM'-'dd'T'HH':'mm':'ss
+TimeSeparator: ':'
+UniversalSortableDateTimePattern: yyyy'-'MM'-'dd HH':'mm':'ss'Z'
+YearMonthPattern: MMMM yyyy
+AbbreviatedDayNames:
+- sø
+- ma
+- ti
+- on
+- to
+- fr
+- lø
+ShortestDayNames:
+- sø
+- ma
+- ti
+- on
+- to
+- fr
+- lø
+DayNames:
+- søndag
+- mandag
+- tirsdag
+- onsdag
+- torsdag
+- fredag
+- lørdag
+AbbreviatedMonthNames:
+- jan
+- feb
+- mar
+- apr
+- maj
+- jun
+- jul
+- aug
+- sep
+- okt
+- nov
+- dec
+- ''
+MonthNames:
+- januar
+- februar
+- marts
+- april
+- maj
+- juni
+- juli
+- august
+- september
+- oktober
+- november
+- december
+- ''
+NativeCalendarName: gregoriansk kalender
+AbbreviatedMonthGenitiveNames:
+- jan
+- feb
+- mar
+- apr
+- maj
+- jun
+- jul
+- aug
+- sep
+- okt
+- nov
+- dec
+- ''
+MonthGenitiveNames:
+- januar
+- februar
+- marts
+- april
+- maj
+- juni
+- juli
+- august
+- september
+- oktober
+- november
+- december
+- ''
+".ReplaceLineEndings();
+
+#if NET8_0_OR_GREATER
+ expected = string.Format(expected, "2049");
+#elif NET48_OR_GREATER
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
+ {
+ expected = StringReplacePair.ReplaceAll(expected, "gregoriansk kalender", "dansk (Danmark)", StringComparison.Ordinal);
+ expected = string.Format(expected, "2029");
+ }
+ else
+ {
+ expected = StringReplacePair.ReplaceAll(expected, "gregoriansk", "Gregoriansk", StringComparison.Ordinal);
+ expected = string.Format(expected, "2049");
+ }
+#endif
+
+ Assert.Equal(expected, sut4);
+ }
+
+ [Fact]
+ public void Serialize_ShouldSerializeNumberFormatInfo()
+ {
+ var sut2 = DanishCulture;
+ var sut3 = YamlFormatter.SerializeObject(sut2.NumberFormat, o =>
+ {
+ o.Settings.ScalarStyle = ScalarStyle.DoubleQuoted;
+ o.Settings.IndentSequences = false;
+ o.Settings.FormatProvider = DanishCulture;
+ o.Settings.NamingConvention = PascalCaseNamingConvention.Instance;
+ });
+ var sut4 = sut3.ToEncodedString();
+
+ TestOutput.WriteLine(sut4);
+
+ Assert.Equal(@"CurrencyDecimalDigits: 2
+CurrencyDecimalSeparator: "",""
+CurrencyGroupSizes:
+- 3
+NumberGroupSizes:
+- 3
+PercentGroupSizes:
+- 3
+CurrencyGroupSeparator: "".""
+CurrencySymbol: ""kr.""
+NaNSymbol: ""NaN""
+CurrencyNegativePattern: 8
+NumberNegativePattern: 1
+PercentPositivePattern: 0
+PercentNegativePattern: 0
+NegativeInfinitySymbol: ""-∞""
+NegativeSign: ""-""
+NumberDecimalDigits: 2
+NumberDecimalSeparator: "",""
+NumberGroupSeparator: "".""
+CurrencyPositivePattern: 3
+PositiveInfinitySymbol: ""∞""
+PositiveSign: ""+""
+PercentDecimalDigits: 2
+PercentDecimalSeparator: "",""
+PercentGroupSeparator: "".""
+PercentSymbol: ""%""
+PerMilleSymbol: ""‰""
+NativeDigits:
+- ""0""
+- ""1""
+- ""2""
+- ""3""
+- ""4""
+- ""5""
+- ""6""
+- ""7""
+- ""8""
+- ""9""
+DigitSubstitution: ""None""
+".ReplaceLineEndings(), sut4);
+ }
+
+
+ [Fact]
+ public void Serialize_ShouldSerializeCultureInfo()
+ {
+ var sut2 = DanishCulture;
+ var sut3 = YamlFormatter.SerializeObject(sut2, o =>
+ {
+ o.Settings.IndentSequences = false;
+ o.Settings.NamingConvention = PascalCaseNamingConvention.Instance;
+ o.Settings.Converters.Add(YamlConverterFactory.Create((writer, dt, _) => writer.WriteValue(dt.ToString(DanishCulture))));
+ });
+ var sut4 = sut3.ToEncodedString().ReplaceLineEndings().Split(new[] { Environment.NewLine }, StringSplitOptions.None).ToList();
+
+ sut4.RemoveRange(sut4.FindIndex(s => s.StartsWith("CompareInfo")), 6);
+ sut4.RemoveRange(sut4.FindIndex(s => s.StartsWith("CultureTypes")), 1);
+
+ var expected = @"LCID: 1030
+KeyboardLayoutId: 1030
+Name: da-DK
+IetfLanguageTag: da-DK
+DisplayName: Danish (Denmark)
+NativeName: dansk (Danmark)
+EnglishName: Danish (Denmark)
+TwoLetterISOLanguageName: da
+ThreeLetterISOLanguageName: dan
+ThreeLetterWindowsLanguageName: DAN
+TextInfo:
+ ANSICodePage: 1252
+ OEMCodePage: 850
+ MacCodePage: 10000
+ EBCDICCodePage: 20277
+ LCID: 1030
+ CultureName: da-DK
+ ListSeparator: ;
+ IsRightToLeft: false
+IsNeutralCulture: false
+NumberFormat:
+ CurrencyDecimalDigits: 2
+ CurrencyDecimalSeparator: ','
+ CurrencyGroupSizes:
+ - 3
+ NumberGroupSizes:
+ - 3
+ PercentGroupSizes:
+ - 3
+ CurrencyGroupSeparator: .
+ CurrencySymbol: kr.
+ NaNSymbol: NaN
+ CurrencyNegativePattern: 8
+ NumberNegativePattern: 1
+ PercentPositivePattern: 0
+ PercentNegativePattern: 0
+ NegativeInfinitySymbol: -∞
+ NegativeSign: '-'
+ NumberDecimalDigits: 2
+ NumberDecimalSeparator: ','
+ NumberGroupSeparator: .
+ CurrencyPositivePattern: 3
+ PositiveInfinitySymbol: ∞
+ PositiveSign: +
+ PercentDecimalDigits: 2
+ PercentDecimalSeparator: ','
+ PercentGroupSeparator: .
+ PercentSymbol: '%'
+ PerMilleSymbol: ‰
+ NativeDigits:
+ - 0
+ - 1
+ - 2
+ - 3
+ - 4
+ - 5
+ - 6
+ - 7
+ - 8
+ - 9
+ DigitSubstitution: None
+DateTimeFormat:
+ AMDesignator: ''
+ Calendar:
+ MinSupportedDateTime: 01-01-0001 00:00:00
+ MaxSupportedDateTime: 31-12-9999 23:59:59
+ AlgorithmType: SolarCalendar
+ CalendarType: Localized
+ Eras:
+ - 1
+ TwoDigitYearMax: {0}
+ DateSeparator: '-'
+ FirstDayOfWeek: Monday
+ CalendarWeekRule: FirstFourDayWeek
+ FullDateTimePattern: d. MMMM yyyy HH:mm:ss
+ LongDatePattern: d. MMMM yyyy
+ LongTimePattern: HH:mm:ss
+ MonthDayPattern: d. MMMM
+ PMDesignator: ''
+ RFC1123Pattern: ddd, dd MMM yyyy HH':'mm':'ss 'GMT'
+ ShortDatePattern: dd-MM-yyyy
+ ShortTimePattern: HH:mm
+ SortableDateTimePattern: yyyy'-'MM'-'dd'T'HH':'mm':'ss
+ TimeSeparator: ':'
+ UniversalSortableDateTimePattern: yyyy'-'MM'-'dd HH':'mm':'ss'Z'
+ YearMonthPattern: MMMM yyyy
+ AbbreviatedDayNames:
+ - sø
+ - ma
+ - ti
+ - on
+ - to
+ - fr
+ - lø
+ ShortestDayNames:
+ - sø
+ - ma
+ - ti
+ - on
+ - to
+ - fr
+ - lø
+ DayNames:
+ - søndag
+ - mandag
+ - tirsdag
+ - onsdag
+ - torsdag
+ - fredag
+ - lørdag
+ AbbreviatedMonthNames:
+ - jan
+ - feb
+ - mar
+ - apr
+ - maj
+ - jun
+ - jul
+ - aug
+ - sep
+ - okt
+ - nov
+ - dec
+ - ''
+ MonthNames:
+ - januar
+ - februar
+ - marts
+ - april
+ - maj
+ - juni
+ - juli
+ - august
+ - september
+ - oktober
+ - november
+ - december
+ - ''
+ NativeCalendarName: gregoriansk kalender
+ AbbreviatedMonthGenitiveNames:
+ - jan
+ - feb
+ - mar
+ - apr
+ - maj
+ - jun
+ - jul
+ - aug
+ - sep
+ - okt
+ - nov
+ - dec
+ - ''
+ MonthGenitiveNames:
+ - januar
+ - februar
+ - marts
+ - april
+ - maj
+ - juni
+ - juli
+ - august
+ - september
+ - oktober
+ - november
+ - december
+ - ''
+Calendar:
+ MinSupportedDateTime: 01-01-0001 00:00:00
+ MaxSupportedDateTime: 31-12-9999 23:59:59
+ AlgorithmType: SolarCalendar
+ CalendarType: Localized
+ Eras:
+ - 1
+ TwoDigitYearMax: {0}
+OptionalCalendars:
+- MinSupportedDateTime: 01-01-0001 00:00:00
+ MaxSupportedDateTime: 31-12-9999 23:59:59
+ AlgorithmType: SolarCalendar
+ CalendarType: Localized
+ Eras:
+ - 1
+ TwoDigitYearMax: {0}
+UseUserOverride: true
+";
+
+#if NET8_0_OR_GREATER || NET48_OR_GREATER
+ expected = string.Format(expected, "2049");
+#else
+ expected = string.Format(expected, "2029");
+#endif
+
+#if NET48_OR_GREATER
+ expected = StringReplacePair.ReplaceAll(expected, "gregoriansk", "Gregoriansk", StringComparison.Ordinal);
+#endif
+
+ TestOutput.WriteLines(sut4);
+
+ Assert.Equal(expected.ReplaceLineEndings().Split(new[] { Environment.NewLine }, StringSplitOptions.None).ToList(), sut4);
+ }
+ }
+}
diff --git a/testenvironments.json b/testenvironments.json
index 046978a..e296d68 100644
--- a/testenvironments.json
+++ b/testenvironments.json
@@ -9,7 +9,7 @@
{
"name": "Docker-Ubuntu",
"type": "docker",
- "dockerImage": "gimlichael/ubuntu-testrunner:net6.0.424-net8.0.303"
+ "dockerImage": "gimlichael/ubuntu-testrunner:net8.0.405-9.0.102"
}
]
}
diff --git a/tooling/gse/gse.csproj b/tooling/gse/gse.csproj
index c4734f3..2ff16da 100644
--- a/tooling/gse/gse.csproj
+++ b/tooling/gse/gse.csproj
@@ -19,7 +19,7 @@
-
+