Search Unity

Passing returned strings to formatter

Discussion in 'Localization Tools' started by sniffle63, Jan 23, 2021.

  1. sniffle63

    sniffle63

    Joined:
    Aug 31, 2013
    Posts:
    365
    Hello,

    I was trying to have a string in my string table that looks like
    Code (CSharp):
    1. Starts In: {0:00}:{1:00}
    But I didn't want to use the smart string because it seemed easier to just return that string directly and then pass that to a formatter with my strings in it like so

    Code (CSharp):
    1.  
    2.             warmUpMessage += string.Format(message, startTimeDiffMinutes, startTimeDiffSeconds);
    But it seems like if you use parse characters in a string that isn't using smart format it returns an error instead of the string, so curious if this is a bug or intended behavior and what the best workaround for handling this would be.

    I know I could make them all public variables on the file and pass the file in as an argument to the localizedString, but I mean... that's kinda janky tbh and you can only use the variable for a single string instead of reusing it while changing its value.

    For example, I had 2 proceed buttons on the same Ui that proceeded with different arguments, normally you'd just change the argument and pass it in or create a local variable in that function or something, but I actually had to create 2 db entries saying proceed {arg1} and proceed {arg2} so I could show the same translation 2 times on the same Ui. I tried just updating arg1 to the value that arg2 required, but then it showed arg2 in both buttons.


    I changed the string to
    Code (CSharp):
    1. Starts In: {0}:{1}
    but now it turns smart string on automatically and returns system.object[] :D
     
    Last edited: Jan 23, 2021
  2. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,292
    What's the error you are getting?
    If you pass arguments in and it's not set to a smart string then it will use String.Format instead.
    It does sound like there may be some bug. We should have 0.10.0 out next week. See if that fixes the issue, it has lots of related bug fixes. If you still have a problem then please file a bug report.
     
  3. sniffle63

    sniffle63

    Joined:
    Aug 31, 2013
    Posts:
    365
    Even if you default to using string.format that makes my use case impossible because its not returning the string i want to use and instead is attempting to format it before i give the values to it, im still stuck ina scenario where I HAVE to use public variables for my arguments, correct?

    (id love to show you the error but it keeps auto turning smart format on now, was something about unable to format)
     
  4. sniffle63

    sniffle63

    Joined:
    Aug 31, 2013
    Posts:
    365
    Ah, turns out when you turn smart format on it adds the metadata to your string but when you turn it off it doesn't remove the smart format metadata, and its read-only so I cant remove it and there's like 10 of them

    heres the error

    Code (CSharp):
    1. FormatException: Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
    2. System.Text.StringBuilder.AppendFormatHelper (System.IFormatProvider provider, System.String format, System.ParamsArray args) (at <9577ac7a62ef43179789031239ba8798>:0)
    3. System.String.FormatHelper (System.IFormatProvider provider, System.String format, System.ParamsArray args) (at <9577ac7a62ef43179789031239ba8798>:0)
    4. System.String.Format (System.String format, System.Object[] args) (at <9577ac7a62ef43179789031239ba8798>:0)
    5. UnityEngine.Localization.Tables.StringTableEntry.GetLocalizedString (System.Object[] args) (at Library/PackageCache/com.unity.localization@0.9.0-preview/Runtime/Tables/StringTable.cs:98)
    6. UnityEngine.Localization.Settings.LocalizedStringDatabase.GetLocalizedStringProcessTableEntry (UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle`1[TObject] entryOp, UnityEngine.Localization.Tables.TableEntryReference tableEntryReference, UnityEngine.Localization.Locale locale, System.Object[] arguments) (at Library/PackageCache/com.unity.localization@0.9.0-preview/Runtime/Settings/Database/LocalizedStringDatabase.cs:197)
    7. UnityEngine.Localization.Settings.LocalizedStringDatabase.GetLocalizedStringAsyncInternal (UnityEngine.Localization.Tables.TableReference tableReference, UnityEngine.Localization.Tables.TableEntryReference tableEntryReference, UnityEngine.Localization.Locale locale, System.Object[] arguments) (at Library/PackageCache/com.unity.localization@0.9.0-preview/Runtime/Settings/Database/LocalizedStringDatabase.cs:175)
    8. UnityEngine.Localization.Settings.LocalizedStringDatabase.GetLocalizedStringAsync (UnityEngine.Localization.Tables.TableReference tableReference, UnityEngine.Localization.Tables.TableEntryReference tableEntryReference, UnityEngine.Localization.Locale locale, System.Object[] arguments) (at Library/PackageCache/com.unity.localization@0.9.0-preview/Runtime/Settings/Database/LocalizedStringDatabase.cs:166)
    9. UnityEngine.Localization.Settings.LocalizedStringDatabase.GetLocalizedStringAsync (UnityEngine.Localization.Tables.TableReference tableReference, UnityEngine.Localization.Tables.TableEntryReference tableEntryReference, System.Object[] arguments) (at Library/PackageCache/com.unity.localization@0.9.0-preview/Runtime/Settings/Database/LocalizedStringDatabase.cs:144)
    10. UnityEngine.Localization.LocalizedString.GetLocalizedString () (at Library/PackageCache/com.unity.localization@0.9.0-preview/Runtime/Localized Reference/LocalizedString.cs:180)
    11. Cade.Core.Services.LocalizationService+<GetLocalizedString>d__5.MoveNext () (at Assets/Cade/Core/Services/LocalizationService.cs:44)
    12. --- End of stack trace from previous location where exception was thrown ---
    13. System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () (at <9577ac7a62ef43179789031239ba8798>:0)
    14. System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) (at <9577ac7a62ef43179789031239ba8798>:0)
    15. System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) (at <9577ac7a62ef43179789031239ba8798>:0)
    16. System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) (at <9577ac7a62ef43179789031239ba8798>:0)
    17. System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult () (at <9577ac7a62ef43179789031239ba8798>:0)
    18. ActivityStatusManager+<CreateWarmUpMessage>d__29.MoveNext () (at Assets/Cade/Core/Client/UI/Widgets/WorkoutSummary/Scripts/ActivityStatusManager.cs:158)
    19. --- End of stack trace from previous location where exception was thrown ---
    20. System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () (at <9577ac7a62ef43179789031239ba8798>:0)
    21. System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__6_0 (System.Object state) (at <9577ac7a62ef43179789031239ba8798>:0)
    22. UnityEngine.UnitySynchronizationContext+WorkRequest.Invoke () (at <a4546799a4ab426788e4204c69507924>:0)
    23. UnityEngine.UnitySynchronizationContext:ExecuteTasks()
    24.  
     
  5. sniffle63

    sniffle63

    Joined:
    Aug 31, 2013
    Posts:
    365
    Hate to spam but I gave up on that approach and used the intended approach but that's not working either unfortunately.

    I have this function

    Code (CSharp):
    1. public static async Task<string> GetLocalizedString(string table, string key, params object[] args)
    2. {
    3.     var localizedString = new LocalizedString
    4.     {TableReference = table, TableEntryReference = key, Arguments = new[] {args}};
    5.     var handle = localizedString.GetLocalizedString();
    6.     while (handle.IsDone == false)
    7.         await Task.Yield();
    8.  
    9.     return handle.Result;
    10. }
    And i tried passing this into it
    Code (CSharp):
    1. await LocalizationService.GetLocalizedString("In-Game Ui", "warmUp", this);
    But it's returning an empty string for my variables that i used as the arguments on that class.

    Seems to work fine if I do use the LocalizedStringEvent, but I don't really want a wall of variables on my inspector, at this point i need a variable for each string and a variable for each argument for something that is being used for 1 frame and its just kinda messy.

    Fixed it.. doesnt work with params for some reason, even after adding ToArray
    Code (CSharp):
    1.         public static async Task<string> GetLocalizedString(string table, string key, Object[] args = null)
    2.         {
    3.             var localizedString = new LocalizedString
    4.             {TableReference = table, TableEntryReference = key};
    5.             if (args?.Length > 0)
    6.                 localizedString.Arguments = args;
    7.                  
    8.             var handle = localizedString.GetLocalizedString();
    9.             while (handle.IsDone == false)
    10.                 await Task.Yield();
    11.          
    12.             return handle.Result;
    13.         }
    14.     }
     
    Last edited: Jan 23, 2021
  6. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,292
    Sorry I was ill Saturday and lost track of the messages.

    This is fixed in 0.10.0

    Are you having better luck with the new version 0.10.0?
     
  7. sniffle63

    sniffle63

    Joined:
    Aug 31, 2013
    Posts:
    365
    First and foremost, I hope you are feeling better sorry to hear you were ill!

    I will be updating and trying it out soon! Super excited to try it out.
     
    karl_jones likes this.