wip - working on U4-5966

This commit is contained in:
Shannon
2014-12-17 16:19:42 +11:00
parent da25970f79
commit 4e33552a5c
4 changed files with 253 additions and 34 deletions

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}

View File

@@ -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]

View File

@@ -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);
}
}