< Summary

Information
Class: TeleFlow.Telegram.I18n.Locale
Assembly: TeleFlow.Framework.I18n
File(s): /_/src/TeleFlow.Framework.I18n/Locale.cs
Line coverage
85%
Covered lines: 24
Uncovered lines: 4
Coverable lines: 28
Total lines: 95
Line coverage: 85.7%
Branch coverage
60%
Covered branches: 6
Total branches: 10
Branch coverage: 60%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)75%4478.57%
TryCreate(...)100%22100%
Equals(...)50%22100%
Equals(...)0%620%
GetHashCode()100%11100%
ToString()100%11100%

File(s)

/_/src/TeleFlow.Framework.I18n/Locale.cs

#LineLine coverage
 1using System.Diagnostics.CodeAnalysis;
 2using System.Globalization;
 3
 4namespace TeleFlow.Telegram.I18n;
 5
 6/// <summary>
 7/// Represents a validated, normalized locale used by Telegram update resolution and localization engines.
 8/// The value keeps culture identity explicit without changing ambient process or thread cultures.
 9/// </summary>
 10public sealed class Locale : IEquatable<Locale>
 11{
 12    public Locale(string name)
 13    {
 34714        ArgumentException.ThrowIfNullOrWhiteSpace(name);
 15
 34716        var trimmedName = name.Trim();
 17
 34718        if (trimmedName.Contains('_', StringComparison.Ordinal))
 19        {
 320            throw new ArgumentException(
 321                "Locale names must use BCP 47 '-' separators instead of '_'.",
 322                nameof(name));
 23        }
 24
 25        try
 26        {
 34427            Culture = CultureInfo.GetCultureInfo(trimmedName);
 34428        }
 029        catch (CultureNotFoundException exception)
 30        {
 031            throw new ArgumentException($"'{name}' is not a valid locale name.", nameof(name), exception);
 32        }
 33
 34434        if (string.IsNullOrEmpty(Culture.Name))
 35        {
 036            throw new ArgumentException("The invariant culture cannot be used as a locale.", nameof(name));
 37        }
 38
 34439        Name = Culture.Name;
 34440    }
 41
 42    /// <summary>
 43    /// Gets the normalized culture name, for example <c>en</c> or <c>ru-RU</c>.
 44    /// </summary>
 45    public string Name { get; }
 46
 47    /// <summary>
 48    /// Gets the read-only .NET culture represented by this locale.
 49    /// </summary>
 50    public CultureInfo Culture { get; }
 51
 52    /// <summary>
 53    /// Attempts to create a locale without throwing for untrusted language codes such as Telegram user metadata.
 54    /// </summary>
 55    public static bool TryCreate(string? name, [NotNullWhen(true)] out Locale? locale)
 56    {
 3657        if (string.IsNullOrWhiteSpace(name))
 58        {
 159            locale = null;
 160            return false;
 61        }
 62
 63        try
 64        {
 3565            locale = new Locale(name);
 3366            return true;
 67        }
 268        catch (ArgumentException)
 69        {
 270            locale = null;
 271            return false;
 72        }
 3573    }
 74
 75    public bool Equals(Locale? other)
 76    {
 277        return other is not null &&
 278               string.Equals(Name, other.Name, StringComparison.OrdinalIgnoreCase);
 79    }
 80
 81    public override bool Equals(object? obj)
 82    {
 083        return obj is Locale other && Equals(other);
 84    }
 85
 86    public override int GetHashCode()
 87    {
 288        return StringComparer.OrdinalIgnoreCase.GetHashCode(Name);
 89    }
 90
 91    public override string ToString()
 92    {
 193        return Name;
 94    }
 95}