Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expand Locale parser to support three-character language codes #6124

Merged
merged 3 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ private static object CodeLanguage_Parser(ReadOnlyMemory<char> name, PatternTabl
/// If matchOnly is true, then an empty string may be returned as a performance optimization.
/// If matchOnly is false, the parsed result will be returned.
/// </summary>
private static object Locale_Parser(ReadOnlyMemory<char> name, PatternTable table, bool matchOnly)
internal static object Locale_Parser(ReadOnlyMemory<char> name, PatternTable table, bool matchOnly)
{
if (table != null)
{
Expand All @@ -171,22 +171,40 @@ private static object Locale_Parser(ReadOnlyMemory<char> name, PatternTable tabl
}
baronfel marked this conversation as resolved.
Show resolved Hide resolved
}

if (name.Length == 2)
// We use a heuristic here for common locale codes. Locale codes are often
// * two characters for the language: en, es, fr, de
// * three characters for the language: agq
if (name.Length == 2 || name.Length == 3)
nkolev92 marked this conversation as resolved.
Show resolved Hide resolved
{
if (matchOnly)
{
return string.Empty;
}
return name.ToString();
}
else if (name.Length >= 4 && name.Span[2] == '-')

// * a language portion that is two or three characters followed by a '-' and a country code
else if (name.Length >= 4 && name.Span[2] == '-') // e.g. en-US
{
if (matchOnly)
{
return string.Empty;
}
return name.ToString();
}
else if (name.Length >= 5 && name.Span[3] == '-') // e.g agq-CM
{
if (matchOnly)
{
return string.Empty;
}
return name.ToString();
}

// there are other variations, but this heuristic doesn't cover them all. A future-proof implementation would make
// use of the .NET CultureInfo APIs to compare the locale against the underlying system ICU database. This would
// be correct, but potentially more expensive because the CultureInfo APIs are lazily-loaded and throw if an
// invalid/unknown locale is used.

return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Xunit;

namespace NuGet.Client.Test
{
public class ContentModelResourceTests
{
[MemberData(nameof(AllCultures))]
[Theory]
public void CanParseEverySystemKnownCultureResource(CultureInfo culture)
{
var result = ManagedCodeConventions.Locale_Parser(culture.Name.AsMemory(), null, false);
Assert.Equal(culture.Name, result as string);
}

public static IEnumerable<object[]> AllCultures()
{
return CultureInfo.GetCultures(CultureTypes.AllCultures).Where(c => !string.IsNullOrEmpty(c.Name)).Select(culture => new[] { culture });
}
}
}