summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/StardewModdingAPI.Tests/TranslationTests.cs15
-rw-r--r--src/StardewModdingAPI/Translation.cs51
2 files changed, 39 insertions, 27 deletions
diff --git a/src/StardewModdingAPI.Tests/TranslationTests.cs b/src/StardewModdingAPI.Tests/TranslationTests.cs
index 1778ed6a..09f0ce32 100644
--- a/src/StardewModdingAPI.Tests/TranslationTests.cs
+++ b/src/StardewModdingAPI.Tests/TranslationTests.cs
@@ -19,8 +19,11 @@ namespace StardewModdingAPI.Tests
/// <summary>A token structure type.</summary>
public enum TokenType
{
- /// <summary>The tokens are passed in a dictionary.</summary>
- Dictionary,
+ /// <summary>The tokens are passed in a string/object dictionary.</summary>
+ DictionaryStringObject,
+
+ /// <summary>The tokens are passed in a string/string dictionary.</summary>
+ DictionaryStringString,
/// <summary>The tokens are passed in an anonymous object.</summary>
AnonymousObject
@@ -190,7 +193,7 @@ namespace StardewModdingAPI.Tests
** Translation tokens
****/
[Test(Description = "Assert that multiple translation tokens are replaced correctly regardless of the token structure.")]
- public void Translation_Tokens([Values(TokenType.AnonymousObject, TokenType.Dictionary)] TokenType tokenType)
+ public void Translation_Tokens([Values(TokenType.AnonymousObject, TokenType.DictionaryStringObject, TokenType.DictionaryStringString)] TokenType tokenType)
{
// arrange
string start = Guid.NewGuid().ToString("N");
@@ -207,10 +210,14 @@ namespace StardewModdingAPI.Tests
translation = translation.Tokens(new { start, middle, end });
break;
- case TokenType.Dictionary:
+ case TokenType.DictionaryStringObject:
translation = translation.Tokens(new Dictionary<string, object> { ["start"] = start, ["middle"] = middle, ["end"] = end });
break;
+ case TokenType.DictionaryStringString:
+ translation = translation.Tokens(new Dictionary<string, string> { ["start"] = start, ["middle"] = middle, ["end"] = end });
+ break;
+
default:
throw new NotSupportedException($"Unknown token type {tokenType}.");
}
diff --git a/src/StardewModdingAPI/Translation.cs b/src/StardewModdingAPI/Translation.cs
index 868ee4fa..8dcaee0f 100644
--- a/src/StardewModdingAPI/Translation.cs
+++ b/src/StardewModdingAPI/Translation.cs
@@ -1,6 +1,7 @@
using System;
+using System.Collections;
using System.Collections.Generic;
-using System.Linq;
+using System.Reflection;
using System.Text.RegularExpressions;
namespace StardewModdingAPI
@@ -82,37 +83,41 @@ namespace StardewModdingAPI
}
/// <summary>Replace tokens in the text like <c>{{value}}</c> with the given values. Returns a new instance.</summary>
- /// <param name="tokens">An anonymous object containing token key/value pairs, like <c>new { value = 42, name = "Cranberries" }</c>.</param>
+ /// <param name="tokens">An object containing token key/value pairs. This can be an anonymous object (like <c>new { value = 42, name = "Cranberries" }</c>) or a dictionary of token values.</param>
/// <exception cref="ArgumentNullException">The <paramref name="tokens"/> argument is <c>null</c>.</exception>
public Translation Tokens(object tokens)
{
if (tokens == null)
throw new ArgumentNullException(nameof(tokens));
- IDictionary<string, object> dictionary = tokens
- .GetType()
- .GetProperties()
- .ToDictionary(
- p => p.Name,
- p => p.GetValue(tokens)
- );
- return this.Tokens(dictionary);
- }
-
- /// <summary>Replace tokens in the text like <c>{{value}}</c> with the given values. Returns a new instance.</summary>
- /// <param name="tokens">A dictionary containing token key/value pairs.</param>
- /// <exception cref="ArgumentNullException">The <paramref name="tokens"/> argument is <c>null</c>.</exception>
- public Translation Tokens(IDictionary<string, object> tokens)
- {
- if (tokens == null)
- throw new ArgumentNullException(nameof(tokens));
-
- tokens = tokens.ToDictionary(p => p.Key.Trim(), p => p.Value, StringComparer.InvariantCultureIgnoreCase);
+ // get dictionary of tokens
+ IDictionary<string, string> tokenLookup = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
+ {
+ // from dictionary
+ if (tokens is IDictionary inputLookup)
+ {
+ foreach (DictionaryEntry entry in inputLookup)
+ {
+ string key = entry.Key?.ToString().Trim();
+ if (key != null)
+ tokenLookup[key] = entry.Value?.ToString();
+ }
+ }
+
+ // from object properties
+ else
+ {
+ foreach (PropertyInfo prop in tokens.GetType().GetProperties())
+ tokenLookup[prop.Name] = prop.GetValue(tokens)?.ToString();
+ }
+ }
+
+ // format translation
string text = Regex.Replace(this.Text, @"{{([ \w\.\-]+)}}", match =>
{
string key = match.Groups[1].Value.Trim();
- return tokens.TryGetValue(key, out object value)
- ? value?.ToString()
+ return tokenLookup.TryGetValue(key, out string value)
+ ? value
: match.Value;
});
return new Translation(this.ModName, this.Locale, this.Key, text);