wip - working on U4-5966
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
using System.Globalization;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
@@ -16,11 +18,14 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="culture"></param>
|
||||
/// <param name="variables">This can be null</param>
|
||||
/// <param name="tokens">This can be null</param>
|
||||
/// <returns></returns>
|
||||
string Localize(string key, CultureInfo culture,
|
||||
|
||||
//TODO: Potentially this should be a dictionary to simplify things a little?
|
||||
object variables);
|
||||
string Localize(string key, CultureInfo culture, IDictionary<string, string> tokens);
|
||||
|
||||
/// <summary>
|
||||
/// Returns all key/values in storage for the given culture
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IDictionary<string, string> GetAllStoredValues(CultureInfo culture);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace Umbraco.Core.Services
|
||||
_dictionarySource = source;
|
||||
}
|
||||
|
||||
public string Localize(string key, CultureInfo culture, object variables)
|
||||
public string Localize(string key, CultureInfo culture, IDictionary<string, string> tokens)
|
||||
{
|
||||
Mandate.ParameterNotNull(culture, "culture");
|
||||
|
||||
@@ -102,15 +102,63 @@ namespace Umbraco.Core.Services
|
||||
|
||||
if (_xmlSource != null)
|
||||
{
|
||||
return GetFromXmlSource(culture, area, alias);
|
||||
return GetFromXmlSource(culture, area, alias, tokens);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetFromDictionarySource(culture, area, alias);
|
||||
return GetFromDictionarySource(culture, area, alias, tokens);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetFromDictionarySource(CultureInfo culture, string area, string key)
|
||||
/// <summary>
|
||||
/// Returns all key/values in storage for the given culture
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IDictionary<string, string> GetAllStoredValues(CultureInfo culture)
|
||||
{
|
||||
if (culture == null) throw new ArgumentNullException("culture");
|
||||
|
||||
var result = new Dictionary<string, string>();
|
||||
|
||||
if (_xmlSource != null)
|
||||
{
|
||||
if (_xmlSource.ContainsKey(culture) == false)
|
||||
{
|
||||
throw new NullReferenceException("The culture specified " + culture + " was not found in any configured sources for this service");
|
||||
}
|
||||
|
||||
//convert all areas + keys to a single key with a '/'
|
||||
var areas = _xmlSource[culture].Value.XPathSelectElements("//area");
|
||||
foreach (var area in areas)
|
||||
{
|
||||
var keys = area.XPathSelectElements("./key");
|
||||
foreach (var key in keys)
|
||||
{
|
||||
result.Add(string.Format("{0}/{1}", (string) area.Attribute("alias"), (string) key.Attribute("alias")), key.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_dictionarySource.ContainsKey(culture) == false)
|
||||
{
|
||||
throw new NullReferenceException("The culture specified " + culture + " was not found in any configured sources for this service");
|
||||
}
|
||||
|
||||
//convert all areas + keys to a single key with a '/'
|
||||
foreach (var area in _dictionarySource[culture])
|
||||
{
|
||||
foreach (var key in area.Value)
|
||||
{
|
||||
result.Add(string.Format("{0}/{1}", area.Key, key.Key), key.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private string GetFromDictionarySource(CultureInfo culture, string area, string key, IDictionary<string, string> tokens)
|
||||
{
|
||||
if (_dictionarySource.ContainsKey(culture) == false)
|
||||
{
|
||||
@@ -138,11 +186,16 @@ namespace Umbraco.Core.Services
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
if (found != null)
|
||||
{
|
||||
return ParseTokens(found, tokens);
|
||||
}
|
||||
|
||||
//NOTE: Based on how legacy works, the default text does not contain the area, just the key
|
||||
return found ?? "[" + key + "]";
|
||||
return "[" + key + "]";
|
||||
}
|
||||
|
||||
private string GetFromXmlSource(CultureInfo culture, string area, string key)
|
||||
private string GetFromXmlSource(CultureInfo culture, string area, string key, IDictionary<string, string> tokens)
|
||||
{
|
||||
if (_xmlSource.ContainsKey(culture) == false)
|
||||
{
|
||||
@@ -157,13 +210,43 @@ namespace Umbraco.Core.Services
|
||||
|
||||
var found = cultureSource.XPathSelectElement(xpath);
|
||||
|
||||
return found == null
|
||||
//NOTE: Based on how legacy works, the default text does not contain the area, just the key
|
||||
? "[" + key + "]"
|
||||
: found.Value;
|
||||
if (found != null)
|
||||
{
|
||||
return ParseTokens(found.Value, tokens);
|
||||
}
|
||||
|
||||
//NOTE: Based on how legacy works, the default text does not contain the area, just the key
|
||||
return "[" + key + "]";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the tokens in the value
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="tokens"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This is based on how the legacy ui localized text worked, each token was just a sequential value delimited with a % symbol.
|
||||
/// For example: hello %0%, you are %1% !
|
||||
///
|
||||
/// Since we're going to continue using the same language files for now, the token system needs to remain the same. With our new service
|
||||
/// we support a dictionary which means in the future we can really have any sort of token system.
|
||||
/// Currently though, the token key's will need to be an integer and sequential - though we aren't going to throw exceptions if that is not the case.
|
||||
/// </remarks>
|
||||
internal string ParseTokens(string value, IDictionary<string, string> tokens)
|
||||
{
|
||||
if (tokens == null || tokens.Any() == false)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
foreach (var token in tokens)
|
||||
{
|
||||
value = value.Replace(string.Format("{0}{1}{0}", "%", token.Key), token.Value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,81 @@ namespace Umbraco.Tests.Services
|
||||
[TestFixture]
|
||||
public class LocalizedTextServiceTests
|
||||
{
|
||||
[Test]
|
||||
public void Using_Dictionary_Gets_All_Stored_Values()
|
||||
{
|
||||
var culture = CultureInfo.GetCultureInfo("en-US");
|
||||
var txtService = new LocalizedTextService(
|
||||
new Dictionary<CultureInfo, IDictionary<string, IDictionary<string, string>>>
|
||||
{
|
||||
{
|
||||
culture, new Dictionary<string, IDictionary<string, string>>
|
||||
{
|
||||
{
|
||||
"testArea1", new Dictionary<string, string>
|
||||
{
|
||||
{"testKey1", "testValue1"},
|
||||
{"testKey2", "testValue2"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"testArea2", new Dictionary<string, string>
|
||||
{
|
||||
{"blah1", "blahValue1"},
|
||||
{"blah2", "blahValue2"}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var result = txtService.GetAllStoredValues(culture);
|
||||
|
||||
Assert.AreEqual(4, result.Count());
|
||||
Assert.AreEqual("testArea1/testKey1", result.ElementAt(0).Key);
|
||||
Assert.AreEqual("testArea1/testKey2", result.ElementAt(1).Key);
|
||||
Assert.AreEqual("testArea2/blah1", result.ElementAt(2).Key);
|
||||
Assert.AreEqual("testArea2/blah2", result.ElementAt(3).Key);
|
||||
Assert.AreEqual("testValue1", result["testArea1/testKey1"]);
|
||||
Assert.AreEqual("testValue2", result["testArea1/testKey2"]);
|
||||
Assert.AreEqual("blahValue1", result["testArea2/blah1"]);
|
||||
Assert.AreEqual("blahValue2", result["testArea2/blah2"]);
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Using_XDocument_Gets_All_Stored_Values()
|
||||
{
|
||||
var culture = CultureInfo.GetCultureInfo("en-US");
|
||||
var txtService = new LocalizedTextService(
|
||||
new Dictionary<CultureInfo, Lazy<XDocument>>
|
||||
{
|
||||
{
|
||||
culture, new Lazy<XDocument>(() => new XDocument(
|
||||
new XElement("language",
|
||||
new XElement("area", new XAttribute("alias", "testArea1"),
|
||||
new XElement("key", new XAttribute("alias", "testKey1"), "testValue1"),
|
||||
new XElement("key", new XAttribute("alias", "testKey2"), "testValue2")),
|
||||
new XElement("area", new XAttribute("alias", "testArea2"),
|
||||
new XElement("key", new XAttribute("alias", "blah1"), "blahValue1"),
|
||||
new XElement("key", new XAttribute("alias", "blah2"), "blahValue2")))))
|
||||
}
|
||||
});
|
||||
|
||||
var result = txtService.GetAllStoredValues(culture);
|
||||
|
||||
Assert.AreEqual(4, result.Count());
|
||||
Assert.AreEqual("testArea1/testKey1", result.ElementAt(0).Key);
|
||||
Assert.AreEqual("testArea1/testKey2", result.ElementAt(1).Key);
|
||||
Assert.AreEqual("testArea2/blah1", result.ElementAt(2).Key);
|
||||
Assert.AreEqual("testArea2/blah2", result.ElementAt(3).Key);
|
||||
Assert.AreEqual("testValue1", result["testArea1/testKey1"]);
|
||||
Assert.AreEqual("testValue2", result["testArea1/testKey2"]);
|
||||
Assert.AreEqual("blahValue1", result["testArea2/blah1"]);
|
||||
Assert.AreEqual("blahValue2", result["testArea2/blah2"]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void Using_Dictionary_Returns_Text_With_Area()
|
||||
@@ -115,6 +190,32 @@ namespace Umbraco.Tests.Services
|
||||
Assert.AreEqual("[doNotFind]", result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Using_Dictionary_Returns_Tokenized_Text()
|
||||
{
|
||||
var culture = CultureInfo.GetCultureInfo("en-US");
|
||||
var txtService = new LocalizedTextService(
|
||||
new Dictionary<CultureInfo, IDictionary<string, IDictionary<string, string>>>
|
||||
{
|
||||
{
|
||||
culture, new Dictionary<string, IDictionary<string, string>>
|
||||
{
|
||||
{
|
||||
"testArea", new Dictionary<string, string>
|
||||
{
|
||||
{"testKey", "Hello %0%, you are such a %1% %2%"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var result = txtService.Localize("testKey", culture,
|
||||
new Dictionary<string, string> { { "0", "world" }, { "1", "great" }, { "2", "planet" } });
|
||||
|
||||
Assert.AreEqual("Hello world, you are such a great planet", result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Using_XDocument_Returns_Text_With_Area()
|
||||
{
|
||||
@@ -196,6 +297,27 @@ namespace Umbraco.Tests.Services
|
||||
Assert.AreEqual("[doNotFind]", result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Using_XDocument_Returns_Tokenized_Text()
|
||||
{
|
||||
var culture = CultureInfo.GetCultureInfo("en-US");
|
||||
var txtService = new LocalizedTextService(
|
||||
new Dictionary<CultureInfo, Lazy<XDocument>>
|
||||
{
|
||||
{
|
||||
culture, new Lazy<XDocument>(() => new XDocument(
|
||||
new XElement("area", new XAttribute("alias", "testArea"),
|
||||
new XElement("key", new XAttribute("alias", "testKey"),
|
||||
"Hello %0%, you are such a %1% %2%"))))
|
||||
}
|
||||
});
|
||||
|
||||
var result = txtService.Localize("testKey", culture,
|
||||
new Dictionary<string, string> { { "0", "world" }, { "1", "great" }, { "2", "planet" } });
|
||||
|
||||
Assert.AreEqual("Hello world, you are such a great planet", result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Using_Dictionary_Throws_When_No_Culture_Found()
|
||||
{
|
||||
@@ -216,7 +338,7 @@ namespace Umbraco.Tests.Services
|
||||
}
|
||||
});
|
||||
|
||||
Assert.Throws<NullReferenceException>(() => txtService.Localize("testArea/testKey", CultureInfo.GetCultureInfo("en-AU")));
|
||||
Assert.Throws<NullReferenceException>(() => txtService.Localize("testArea/testKey", CultureInfo.GetCultureInfo("en-AU")));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
@@ -360,24 +363,25 @@ namespace umbraco
|
||||
//return "[" + key + "]";
|
||||
}
|
||||
|
||||
private static string GetStringWithVars(string stringWithVars, string[] variables)
|
||||
{
|
||||
var vars = Regex.Matches(stringWithVars, @"\%(\d)\%",
|
||||
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
|
||||
foreach (Match var in vars)
|
||||
{
|
||||
stringWithVars = stringWithVars.Replace(
|
||||
var.Value,
|
||||
variables[Convert.ToInt32(var.Groups[0].Value.Replace("%", ""))]);
|
||||
}
|
||||
return stringWithVars;
|
||||
}
|
||||
//private static string GetStringWithVars(string stringWithVars, string[] variables)
|
||||
//{
|
||||
// var vars = Regex.Matches(stringWithVars, @"\%(\d)\%",
|
||||
// RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
|
||||
// foreach (Match var in vars)
|
||||
// {
|
||||
// stringWithVars = stringWithVars.Replace(
|
||||
// var.Value,
|
||||
// variables[Convert.ToInt32(var.Groups[0].Value.Replace("%", ""))]);
|
||||
// }
|
||||
// return stringWithVars;
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the language file as a xml document.
|
||||
/// </summary>
|
||||
/// <param name="language">The language.</param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in future versions")]
|
||||
public static XmlDocument getLanguageFile(string language)
|
||||
{
|
||||
var cacheKey = "uitext_" + language;
|
||||
@@ -414,10 +418,15 @@ namespace umbraco
|
||||
|
||||
}
|
||||
|
||||
|
||||
internal static object ConvertToObjectVars(string[] variables)
|
||||
/// <summary>
|
||||
/// Convert an array of strings to a dictionary of indicies -> values
|
||||
/// </summary>
|
||||
/// <param name="variables"></param>
|
||||
/// <returns></returns>
|
||||
internal static IDictionary<string, string> ConvertToObjectVars(string[] variables)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return variables.Select((s, i) => new {index = i.ToString(CultureInfo.InvariantCulture), value = s})
|
||||
.ToDictionary(keyvals => keyvals.index, keyvals => keyvals.value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user