mirror of
https://github.com/SabreTools/SabreTools.RedumpLib.git
synced 2026-09-22 23:14:52 +00:00
Port Languages enum
This commit is contained in:
@@ -425,6 +425,175 @@ namespace SabreTools.RedumpLib.Test.RedumpInfo
|
||||
|
||||
#endregion
|
||||
|
||||
#region Language
|
||||
|
||||
/// <summary>
|
||||
/// Check that every Language has a long name provided
|
||||
/// </summary>
|
||||
/// <param name="language">Language value to check</param>
|
||||
/// <param name="expectNull">True to expect a null value, false otherwise</param>
|
||||
[Theory]
|
||||
[MemberData(nameof(GenerateLanguageTestData))]
|
||||
public void Language_LongName(Language? language, bool expectNull)
|
||||
{
|
||||
var actual = language.LongName();
|
||||
|
||||
if (expectNull)
|
||||
Assert.Null(actual);
|
||||
else
|
||||
Assert.NotNull(actual);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check that every Language has a short name provided
|
||||
/// </summary>
|
||||
/// <param name="language">Language value to check</param>
|
||||
/// <param name="expectNull">True to expect a null value, false otherwise</param>
|
||||
[Theory]
|
||||
[MemberData(nameof(GenerateLanguageTestData))]
|
||||
public void Language_ShortName(Language? language, bool expectNull)
|
||||
{
|
||||
var actual = language.ShortName();
|
||||
|
||||
if (expectNull)
|
||||
Assert.Null(actual);
|
||||
else
|
||||
Assert.NotNull(actual);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check that every Language can be mapped from a string
|
||||
/// </summary>
|
||||
/// <param name="lang">Language value to check</param>
|
||||
/// <param name="expectNull">True to expect a null value, false otherwise</param>
|
||||
[Theory]
|
||||
[MemberData(nameof(GenerateLanguageTestData))]
|
||||
public void Language_ToLanguage(Language? lang, bool expectNull)
|
||||
{
|
||||
string? twoLetterCode = lang.TwoLetterCode();
|
||||
string? threeLetterCode = lang.ThreeLetterCode();
|
||||
string? threeLetterCodeAlt = lang.ThreeLetterCodeAlt();
|
||||
|
||||
var actualTwoLetterCode = twoLetterCode.ToLanguage();
|
||||
var actualThreeLetterCode = threeLetterCode.ToLanguage();
|
||||
var actualThreeLetterCodeAlt = threeLetterCodeAlt.ToLanguage();
|
||||
|
||||
if (expectNull)
|
||||
{
|
||||
Assert.Null(actualTwoLetterCode);
|
||||
Assert.Null(actualThreeLetterCode);
|
||||
Assert.Null(actualThreeLetterCodeAlt);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Equal(lang, actualThreeLetterCode);
|
||||
|
||||
// Not guaranteed to exist
|
||||
if (twoLetterCode is not null)
|
||||
Assert.Equal(lang, actualTwoLetterCode);
|
||||
if (threeLetterCodeAlt is not null)
|
||||
Assert.Equal(lang, actualThreeLetterCodeAlt);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensure that every Language that has a standard/bibliographic ISO 639-2 code is unique
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Language_ThreeLetterCode_NoDuplicates()
|
||||
{
|
||||
var fullLanguages = Enum.GetValues<Language>().Cast<Language?>().ToList();
|
||||
var filteredLanguages = new Dictionary<string, Language?>();
|
||||
|
||||
int totalCount = 0;
|
||||
foreach (Language? language in fullLanguages)
|
||||
{
|
||||
var code = language.ThreeLetterCode();
|
||||
if (string.IsNullOrEmpty(code))
|
||||
continue;
|
||||
|
||||
// Throw if the code already exists
|
||||
if (filteredLanguages.ContainsKey(code))
|
||||
throw new DuplicateNameException($"Code {code} already in dictionary");
|
||||
|
||||
filteredLanguages[code] = language;
|
||||
totalCount++;
|
||||
}
|
||||
|
||||
Assert.Equal(totalCount, filteredLanguages.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensure that every Language that has a terminology ISO 639-2 code is unique
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Language_ThreeLetterCodeAlt_NoDuplicates()
|
||||
{
|
||||
var fullLanguages = Enum.GetValues<Language>().Cast<Language?>().ToList();
|
||||
var filteredLanguages = new Dictionary<string, Language?>();
|
||||
|
||||
int totalCount = 0;
|
||||
foreach (Language? language in fullLanguages)
|
||||
{
|
||||
var code = language.ThreeLetterCodeAlt();
|
||||
if (string.IsNullOrEmpty(code))
|
||||
continue;
|
||||
|
||||
// Throw if the code already exists
|
||||
if (filteredLanguages.ContainsKey(code))
|
||||
throw new DuplicateNameException($"Code {code} already in dictionary");
|
||||
|
||||
filteredLanguages[code] = language;
|
||||
totalCount++;
|
||||
}
|
||||
|
||||
Assert.Equal(totalCount, filteredLanguages.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensure that every Language that has an ISO 639-1 code is unique
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Language_TwoLetterCode_NoDuplicates()
|
||||
{
|
||||
var fullLanguages = Enum.GetValues<Language>().Cast<Language?>().ToList();
|
||||
var filteredLanguages = new Dictionary<string, Language?>();
|
||||
|
||||
int totalCount = 0;
|
||||
foreach (Language? language in fullLanguages)
|
||||
{
|
||||
var code = language.TwoLetterCode();
|
||||
if (string.IsNullOrEmpty(code))
|
||||
continue;
|
||||
|
||||
// Throw if the code already exists
|
||||
if (filteredLanguages.ContainsKey(code))
|
||||
throw new DuplicateNameException($"Code {code} already in dictionary");
|
||||
|
||||
filteredLanguages[code] = language;
|
||||
totalCount++;
|
||||
}
|
||||
|
||||
Assert.Equal(totalCount, filteredLanguages.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a test set of Language values
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of Language values</returns>
|
||||
public static TheoryData<Language?, bool> GenerateLanguageTestData()
|
||||
{
|
||||
var testData = new TheoryData<Language?, bool>() { { null, true } };
|
||||
foreach (Language? language in Enum.GetValues<Language>().Cast<Language?>())
|
||||
{
|
||||
testData.Add(language, false);
|
||||
}
|
||||
|
||||
return testData;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Media Type
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using SabreTools.RedumpLib.RedumpInfo.Data;
|
||||
|
||||
namespace SabreTools.RedumpLib.RedumpInfo.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Serialize Language enum values
|
||||
/// </summary>
|
||||
public class LanguageConverter : JsonConverter<Language?[]>
|
||||
{
|
||||
public override bool CanRead { get { return true; } }
|
||||
|
||||
public override Language?[] ReadJson(JsonReader reader, Type objectType, Language?[]? existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
// If we have a value already, don't overwrite it
|
||||
if (hasExistingValue)
|
||||
return existingValue ?? [];
|
||||
|
||||
// Get the current depth for checking
|
||||
int currentDepth = reader.Depth;
|
||||
|
||||
// Read the array while it exists
|
||||
List<Language> languages = [];
|
||||
while (reader.Read() && reader.Depth > currentDepth)
|
||||
{
|
||||
if (reader.Value is not string value)
|
||||
continue;
|
||||
|
||||
Language? lang = value.ToLanguage();
|
||||
if (lang is not null)
|
||||
languages.Add(lang.Value);
|
||||
}
|
||||
|
||||
return [.. languages];
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, Language?[]? value, JsonSerializer serializer)
|
||||
{
|
||||
if (value is null)
|
||||
return;
|
||||
|
||||
JArray array = [];
|
||||
foreach (var val in value)
|
||||
{
|
||||
JToken t = JToken.FromObject(val.ShortName() ?? string.Empty);
|
||||
array.Add(t);
|
||||
}
|
||||
|
||||
array.WriteTo(writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1037,6 +1037,128 @@ namespace SabreTools.RedumpLib.RedumpInfo.Data
|
||||
|
||||
#endregion
|
||||
|
||||
#region Language
|
||||
|
||||
/// <summary>
|
||||
/// Get the Redump longnames for each known language
|
||||
/// </summary>
|
||||
public static string? LongName(this Language language)
|
||||
=> ((Language?)language).LongName();
|
||||
|
||||
/// <summary>
|
||||
/// Get the Redump longnames for each known language
|
||||
/// </summary>
|
||||
public static string? LongName(this Language? language)
|
||||
=> AttributeHelper<Language?>.GetHumanReadableAttribute(language)?.LongName;
|
||||
|
||||
/// <summary>
|
||||
/// Get the Redump shortnames for each known language
|
||||
/// </summary>
|
||||
public static string? ShortName(this Language language)
|
||||
=> ((Language?)language).ShortName();
|
||||
|
||||
/// <summary>
|
||||
/// Get the Redump shortnames for each known language
|
||||
/// </summary>
|
||||
public static string? ShortName(this Language? language)
|
||||
{
|
||||
// Some languages need to use the alternate code instead
|
||||
#pragma warning disable IDE0072 // Add missing cases
|
||||
return language switch
|
||||
{
|
||||
Language.Albanian
|
||||
or Language.Armenian
|
||||
or Language.Icelandic
|
||||
or Language.Macedonian
|
||||
or Language.Romanian
|
||||
or Language.Slovak => language.ThreeLetterCodeAlt(),
|
||||
_ => language.ThreeLetterCode(),
|
||||
};
|
||||
#pragma warning restore IDE0072 // Add missing cases
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the Language enum value for a given string
|
||||
/// </summary>
|
||||
/// <param name="lang">String value to convert</param>
|
||||
/// <returns>Language represented by the string, if possible</returns>
|
||||
public static Language? ToLanguage(this string? lang)
|
||||
{
|
||||
// No value means no match
|
||||
if (lang is null || lang.Length == 0)
|
||||
return null;
|
||||
|
||||
lang = lang.ToLowerInvariant();
|
||||
var languages = (Language[])Enum.GetValues(typeof(Language));
|
||||
|
||||
// Check ISO 639-1 codes
|
||||
int index = Array.FindIndex(languages, l => lang == l.TwoLetterCode());
|
||||
if (index > -1)
|
||||
return languages[index];
|
||||
|
||||
// Check standard ISO 639-2 codes
|
||||
index = Array.FindIndex(languages, l => lang == l.ThreeLetterCode());
|
||||
if (index > -1)
|
||||
return languages[index];
|
||||
|
||||
// Check alternate ISO 639-2 codes
|
||||
index = Array.FindIndex(languages, l => lang == l.ThreeLetterCodeAlt());
|
||||
if (index > -1)
|
||||
return languages[index];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the ISO 639-2 code for each known language
|
||||
/// </summary>
|
||||
/// <param name="language"></param>
|
||||
/// <returns></returns>
|
||||
public static string? ThreeLetterCode(this Language language)
|
||||
=> (AttributeHelper<Language>.GetHumanReadableAttribute(language) as LanguageAttribute)?.ThreeLetterCode;
|
||||
|
||||
/// <summary>
|
||||
/// Get the ISO 639-2 code for each known language
|
||||
/// </summary>
|
||||
/// <param name="language"></param>
|
||||
/// <returns></returns>
|
||||
public static string? ThreeLetterCode(this Language? language)
|
||||
=> (AttributeHelper<Language?>.GetHumanReadableAttribute(language) as LanguageAttribute)?.ThreeLetterCode;
|
||||
|
||||
/// <summary>
|
||||
/// Get the ISO 639-2 alternate code for each known language
|
||||
/// </summary>
|
||||
/// <param name="language"></param>
|
||||
/// <returns></returns>
|
||||
public static string? ThreeLetterCodeAlt(this Language language)
|
||||
=> (AttributeHelper<Language>.GetHumanReadableAttribute(language) as LanguageAttribute)?.ThreeLetterCodeAlt;
|
||||
|
||||
/// <summary>
|
||||
/// Get the ISO 639-2 alternate code for each known language
|
||||
/// </summary>
|
||||
/// <param name="language"></param>
|
||||
/// <returns></returns>
|
||||
public static string? ThreeLetterCodeAlt(this Language? language)
|
||||
=> (AttributeHelper<Language?>.GetHumanReadableAttribute(language) as LanguageAttribute)?.ThreeLetterCodeAlt;
|
||||
|
||||
/// <summary>
|
||||
/// Get the ISO 639-1 code for each known language
|
||||
/// </summary>
|
||||
/// <param name="language"></param>
|
||||
/// <returns></returns>
|
||||
public static string? TwoLetterCode(this Language language)
|
||||
=> (AttributeHelper<Language>.GetHumanReadableAttribute(language) as LanguageAttribute)?.TwoLetterCode;
|
||||
|
||||
/// <summary>
|
||||
/// Get the ISO 639-1 code for each known language
|
||||
/// </summary>
|
||||
/// <param name="language"></param>
|
||||
/// <returns></returns>
|
||||
public static string? TwoLetterCode(this Language? language)
|
||||
=> (AttributeHelper<Language?>.GetHumanReadableAttribute(language) as LanguageAttribute)?.TwoLetterCode;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Media Type
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user