Change culture fallback to depth-first:

- #112
This commit is contained in:
damianedwards 2015-12-16 13:10:04 -08:00
parent e72d3cb249
commit b041a07652
2 changed files with 36 additions and 42 deletions

View File

@ -78,8 +78,7 @@ namespace Microsoft.AspNet.Localization
cultureInfo = GetCultureInfo( cultureInfo = GetCultureInfo(
cultures, cultures,
_options.SupportedCultures, _options.SupportedCultures,
_options.FallBackToParentCultures, _options.FallBackToParentCultures);
currentDepth: 0);
} }
if (_options.SupportedUICultures != null) if (_options.SupportedUICultures != null)
@ -87,8 +86,7 @@ namespace Microsoft.AspNet.Localization
uiCultureInfo = GetCultureInfo( uiCultureInfo = GetCultureInfo(
uiCultures, uiCultures,
_options.SupportedUICultures, _options.SupportedUICultures,
_options.FallBackToParentUICultures, _options.FallBackToParentUICultures);
currentDepth: 0);
} }
if (cultureInfo == null && uiCultureInfo == null) if (cultureInfo == null && uiCultureInfo == null)
@ -139,8 +137,7 @@ namespace Microsoft.AspNet.Localization
private static CultureInfo GetCultureInfo( private static CultureInfo GetCultureInfo(
IList<string> cultureNames, IList<string> cultureNames,
IList<CultureInfo> supportedCultures, IList<CultureInfo> supportedCultures,
bool fallbackToAncestorCulture, bool fallbackToAncestorCulture)
int currentDepth)
{ {
foreach (var cultureName in cultureNames) foreach (var cultureName in cultureNames)
{ {
@ -148,7 +145,7 @@ namespace Microsoft.AspNet.Localization
// the CultureInfo ctor // the CultureInfo ctor
if (cultureName != null) if (cultureName != null)
{ {
var cultureInfo = CultureInfoCache.GetCultureInfo(cultureName, supportedCultures); var cultureInfo = GetCultureInfo(cultureName, supportedCultures, fallbackToAncestorCulture, currentDepth: 0);
if (cultureInfo != null) if (cultureInfo != null)
{ {
return cultureInfo; return cultureInfo;
@ -156,40 +153,31 @@ namespace Microsoft.AspNet.Localization
} }
} }
if (fallbackToAncestorCulture & currentDepth < MaxCultureFallbackDepth) return null;
{ }
// Walk backwards through the culture list and remove any root cultures (those with no parent)
for (var i = cultureNames.Count - 1; i >= 0; i--)
{
var cultureName = cultureNames[i];
if (cultureName != null)
{
var lastIndexOfHyphen = cultureName.LastIndexOf('-');
if (lastIndexOfHyphen > 0)
{
// Trim the trailing section from the culture name, e.g. "fr-FR" becomes "fr"
cultureNames[i] = cultureName.Substring(0, lastIndexOfHyphen);
}
else
{
// The culture had no sections left to trim so remove it from the list of candidates
cultureNames.RemoveAt(i);
}
}
else
{
// Culture name was null so just remove it
cultureNames.RemoveAt(i);
}
}
if (cultureNames.Count > 0) private static CultureInfo GetCultureInfo(
string cultureName,
IList<CultureInfo> supportedCultures,
bool fallbackToAncestorCulture,
int currentDepth)
{
var culture = CultureInfoCache.GetCultureInfo(cultureName, supportedCultures);
if (culture == null && fallbackToAncestorCulture && currentDepth < MaxCultureFallbackDepth)
{
var lastIndexOfHyphen = cultureName.LastIndexOf('-');
if (lastIndexOfHyphen > 0)
{ {
return GetCultureInfo(cultureNames, supportedCultures, fallbackToAncestorCulture, currentDepth + 1); // Trim the trailing section from the culture name, e.g. "fr-FR" becomes "fr"
var parentCultureName = cultureName.Substring(0, lastIndexOfHyphen);
culture = GetCultureInfo(parentCultureName, supportedCultures, fallbackToAncestorCulture, currentDepth + 1);
} }
} }
return null; return culture;
} }
} }
} }

View File

@ -51,28 +51,34 @@ namespace Microsoft.AspNet.Localization
} }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether to set a request culture to an ancestor culture in the case the /// Gets or sets a value indicating whether to set a request culture to an parent culture in the case the
/// culture determined by the configured <see cref="IRequestCultureProvider"/>s is not in the /// culture determined by the configured <see cref="IRequestCultureProvider"/>s is not in the
/// <see cref="SupportedCultures"/> list but an ancestor culture is. /// <see cref="SupportedCultures"/> list but a parent culture is.
/// Defaults to <c>true</c>; /// Defaults to <c>true</c>;
/// </summary> /// </summary>
/// <remarks>
/// Note that the parent culture check is done using only the culture name.
/// </remarks>
/// <example> /// <example>
/// If this property is <c>true</c> and the application is configured to support the culture "fr", but not the /// If this property is <c>true</c> and the application is configured to support the culture "fr", but not the
/// culture "fr-FR", and a configured <see cref="IRequestCultureProvider"/> determines a request's culture is /// culture "fr-FR", and a configured <see cref="IRequestCultureProvider"/> determines a request's culture is
/// "fr-FR", then the request's culture will be set to the culture "fr", as it is an ancestor of "fr-FR". /// "fr-FR", then the request's culture will be set to the culture "fr", as it is a parent of "fr-FR".
/// </example> /// </example>
public bool FallBackToParentCultures { get; set; } = true; public bool FallBackToParentCultures { get; set; } = true;
/// <summary> /// <summary>
/// Gets or sets a value indicating whether to set a request UI culture to an ancestor culture in the case the /// Gets or sets a value indicating whether to set a request UI culture to a parent culture in the case the
/// UI culture determined by the configured <see cref="IRequestCultureProvider"/>s is not in the /// UI culture determined by the configured <see cref="IRequestCultureProvider"/>s is not in the
/// <see cref="SupportedUICultures"/> list but an ancestor culture is. /// <see cref="SupportedUICultures"/> list but a parent culture is.
/// Defaults to <c>true</c>; /// Defaults to <c>true</c>;
/// </summary> /// </summary>
/// <remarks>
/// Note that the parent culture check is done using ony the culture name.
/// </remarks>
/// <example> /// <example>
/// If this property is <c>true</c> and the application is configured to support the UI culture "fr", but not /// If this property is <c>true</c> and the application is configured to support the UI culture "fr", but not
/// the UI culture "fr-FR", and a configured <see cref="IRequestCultureProvider"/> determines a request's UI /// the UI culture "fr-FR", and a configured <see cref="IRequestCultureProvider"/> determines a request's UI
/// culture is "fr-FR", then the request's UI culture will be set to the culture "fr", as it is an ancestor of /// culture is "fr-FR", then the request's UI culture will be set to the culture "fr", as it is a parent of
/// "fr-FR". /// "fr-FR".
/// </example> /// </example>
public bool FallBackToParentUICultures { get; set; } = true; public bool FallBackToParentUICultures { get; set; } = true;