I wanted to be sure I am not missing something here :
I am trying to set the StringReference of a LocalizeStringEvent in script, with multiple Arguments.
My table entry with “Smart” option enabled looks like this: “{FullName} : {Value}”
_myLocalizeStringEvent.StringReference = new LocalizedString("my_table_key", "my_entry_key")
{
Arguments = new List<object> { user, message }
};
Where the “user” variable contains a “FullName” properry, ans the “message” variable contains a “Value” property.
I am getting the exception :
Exception
Exception [UnityEngine.Localization.SmartFormat.Core.Formatting.FormattingException: Error parsing format string: Could not evaluate the selector “Value” at 14
{FullName} : {Value}
--------------^
If I invert the arguments like so :
_myLocalizeStringEvent.StringReference = new LocalizedString("my_table_key", "my_entry_key")
{
Arguments = new List<object> { message, user }
};
I am getting the exception :
Exception
Exception [UnityEngine.Localization.SmartFormat.Core.Formatting.FormattingException: Error parsing format string: Could not evaluate the selector “FullName” at 1
{FullName} : {Value}
-^
So it looks like only the first Argument in the list is used for interpolation.
I looked a bit in the code and it looks like this is exactly what is done in SmartFormatter.cs :
public string FormatWithCache(ref FormatCache cache, string format, IFormatProvider formatProvider, IList<object> args)
{
args = args ?? k_Empty;
using (StringOutputPool.Get(format.Length + args.Count * 8, out var output))
{
if (cache == null)
cache = FormatCachePool.Get(Parser.ParseFormat(format, GetNotEmptyFormatterExtensionNames()));
var current = args.Count > 0 ? args[0] : args; // The first item is the default.
var formatDetails = FormatDetailsPool.Get(this, cache.Format, args, cache, formatProvider, output);
Format(formatDetails, cache.Format, current);
FormatDetailsPool.Release(formatDetails);
return output.ToString();
}
}
In this line:
var current = args.Count > 0 ? args[0] : args; // The first item is the default.
So I am wondering what is the point of passing a List for the LocalizedString Arguments when only the first element should contain the values for Interpolation ?
Please tell me if I missed anything here.
Here is the workaround I found :
- Change my table entry to : “{Values[0].FullName} : {Values[1].Value}”
- Create a class containing a list of values :
public class LocalizationInterpolationValueList
{
public IList<object> Values { get; }
public LocalizationInterpolationValueList(IList<object> values)
{
Values = values;
}
}
- Create the LocalizedString like so :
var values = new List<object> { user, message };
_localizedMessageText.StringReference = new LocalizedString(LocalizationUtils.UI, notification.Message)
{
Arguments = new List<object> { new LocalizationInterpolationValueList(values) }
};
And now the 2 values in my string are correcly interpolated and localized, but it is still a bit weird that you must have only one item in the list of Arguments, and I have found no documentation stating this.
Best Regards