Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Struggling with smart string

Discussion in 'Localization Tools' started by Jamryl, Mar 27, 2022.

  1. Jamryl

    Jamryl

    Joined:
    Mar 9, 2020
    Posts:
    25
    As the title says, I'm struggling to understand how the smart string system work.

    To be more specific, I have a class named Student, containing several variables :
    Code (CSharp):
    1. [Serializable]
    2. public class Student
    3. {
    4. int age;
    5. DateTime dob;
    6. bool gender;
    7. string firstName;
    8. string lastName;
    9. }

    I'm creating a table with several replies such as for exemple:
    "Hi, nice to meet you, my name is {student_firstName}, {student_firstName} {student_lastName}. A pleasure to meet you."
    I have a localization table where all the names are stored, but I'm struggling with using one table result into another.

    Does someone have a concrete example to explain this please that would be very awesome.

    Thanks and have a good Sunday.
     
  2. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,226
    Values should be separated with a dot (.), Not underscore.

    There's also sample scenes with smart strings. You can add them via the package manager

    Have you looked at the docs? https://docs.unity3d.com/Packages/com.unity.localization@1.2/manual/Smart/SmartStrings.html
     
  3. Jamryl

    Jamryl

    Joined:
    Mar 9, 2020
    Posts:
    25
    Wow, thanks for the quick answer.

    Yeah, I've been looking at the docs and successfully connected my tables to Google Sheets, but I still don't really got the smart string stuff, I'm a beginner here sorry :(

    student_firstName was a variable name not the class.string but actually your comments helps me.
    How should I access the class variable and set the result into the smart string...

    Will take a look at the sample scenes see if it helps.
     
  4. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,226
    The samples should help. Looks like you need to pass an instance of Student into the string and then access its parts
    like so:

    E.G

    Code (csharp):
    1.  
    2. var student = new Student()
    3. var localizedString = new LocalizedString("My Table", "My Entry");
    4. localizedString.Arguments = new object[] { student};
    5. Debug.Log(localizedString.GetLocalizedString());
    6.  
    Your string should access the variables like so: "My age is {age}".

    Also, the getting started guide shows smart string usage https://docs.unity3d.com/Packages/c...tGuideWithVariants.html#localize-dynamic-text

    https://docs.unity3d.com/Packages/c...-string-localization-use-string-table-entries
     
    Jamryl likes this.
  5. Jamryl

    Jamryl

    Joined:
    Mar 9, 2020
    Posts:
    25
    Thank you very much! Will do that.
    Much obliged
     
    karl_jones likes this.
  6. Jamryl

    Jamryl

    Joined:
    Mar 9, 2020
    Posts:
    25
    I was thinking, would it works if I create a "Student" Global Variables empty and fill the field I need at runtime with the variable of the Student class?
     
  7. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,226
    Yes, you can do that. You will need to define the Student as a persistent variable
    https://docs.unity3d.com/Packages/c...martFormat.PersistentVariables.IVariable.html

    Will this Student need to be accessed from multiple places or just 1 string?
     
  8. Jamryl

    Jamryl

    Joined:
    Mar 9, 2020
    Posts:
    25
  9. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,226
    Ok global variable makes sense then.
    You could do this without code if you were to create a Variables Group asset and treat that as your student.
    upload_2022-3-27_21-14-59.png

    You can even have multiple assets for each student.
    Then drag them into the global variables group like so:
    upload_2022-3-27_21-15-41.png

    Now you can access it:
    "Hello {student.firstName}"

    You could even create another group called Class and have it reference multiple different student assets like so:

    upload_2022-3-27_21-21-51.png

    upload_2022-3-27_21-20-33.png
    Then we do "Hello {class.john.firstName}"
     

    Attached Files:

    Last edited: Mar 27, 2022
    Jamryl likes this.
  10. Jamryl

    Jamryl

    Joined:
    Mar 9, 2020
    Posts:
    25
    That's brilliant thanks! I should be able to make it work with your help!
     
    karl_jones likes this.
  11. Jamryl

    Jamryl

    Joined:
    Mar 9, 2020
    Posts:
    25
    I added a VariablesGroupAsset named "studentVariablesGroupAsset" into my script handling the dialogue. At Start() I would like to pass my Student Class variables into my studentVariablesGroupAsset.

    I'm looking at : Class VariablesGroupAsset

    I found Add(String, IVariable) to add a new variable and assign to it a value but is there a method to set a specific value to an existing variable found by it's name?
     
  12. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,226
    Jamryl likes this.
  13. Jamryl

    Jamryl

    Joined:
    Mar 9, 2020
    Posts:
    25
    Thanks!
     
    karl_jones likes this.
  14. Jamryl

    Jamryl

    Joined:
    Mar 9, 2020
    Posts:
    25
    karl_jones likes this.
  15. maikkanerva

    maikkanerva

    Joined:
    Dec 14, 2018
    Posts:
    27
    Hey,

    I'm trying to figure how to implement the following with smart strings.
    I have buffs on characters that have type and duration, let's say for example "DMG BUFF ({0} rounds)".
    The "DMG BUFF" part inside TMP color tags that i've defined as global variables, like "{bc.dmg}DMG BUFF{bc.end}...".

    I'd like to have plurals working correctly for the {0} rounds part, and I was wondering how this should be implemented.
    My initial thought was to have it as a global variable, as a nested localized string entry, for example "{bc.dmg}DMG BUFF{bc.end} ({bc.duration}).
    However, I was unsure how I would pass the argument ({0} currently) to that nested localized string?

    My second option would be to get this "rounds" localized entry in some script and set that as the first argument.
     
  16. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,226
    Hi,

    Can you add the plural into the main string, does it need to be nested?
    E.G
    Code (csharp):
    1. {bc.dmg}DMG BUFF{bc.end} ({bc.duration:plural:{} round|{} rounds})
     
  17. maikkanerva

    maikkanerva

    Joined:
    Dec 14, 2018
    Posts:
    27
    Hey, thanks for the suggestion.
    The issue is that I'm not sure how the bc.duration would actually know the value?
    I already implemented it so that I have a separate localization {0:plural:1 round|{} rounds} that is added as an argument to the other localization like this "{bc.dmg}DMG BUFF{bc.end} ({0}).

    My solution works just fine but was just curious on how I would pass arguments to a global variable that is a localized string that needs arguments.
     
  18. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,226
    What does your global variable look like? Can you show a screenshot?
     
  19. maikkanerva

    maikkanerva

    Joined:
    Dec 14, 2018
    Posts:
    27
    Hey, sure!

    upload_2023-5-3_14-13-42.png

    I don't use the rounds variable now in the localization, instead it looks like this:
    upload_2023-5-3_14-14-40.png

    In code I have a reference to this localized string entry, and I set the arguments like:

    localizedString.Arguments = new[] { GetDurationInRoundsLocalized() };


    Code (CSharp):
    1. public virtual string GetDurationInRoundsLocalized()
    2.         {
    3.             LocalizedString localizedString = new();
    4.  
    5.             localizedString.TableReference = TABLE_REF;
    6.             localizedString.TableEntryReference = $"Buffs/Duration/Rounds";
    7.  
    8.             IntVariable intVariable = new();
    9.             intVariable.Value = Duration;
    10.  
    11.             localizedString.Add("0", intVariable);
    12.  
    13.             return localizedString.GetLocalizedString();
    14.         }
     
  20. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,226
    What does Buffs/Duration/Rounds look like? Could you add the plurals in there?
    If you want to pass arguments to a global localized string variable you would first need to get the localized string, something like:

    https://docs.unity3d.com/Packages/c...tent-Variables-Source.html#triggering-updates

    Code (csharp):
    1. var source = LocalizationSettings.StringDatabase.SmartFormatter.GetSourceExtension<PersistentVariablesSource>();
    2. var myString = source["global"]["my-string"] as LocalizedString;
     
  21. maikkanerva

    maikkanerva

    Joined:
    Dec 14, 2018
    Posts:
    27
    Hey it's this last variable I had, so it's using the plural formatting. I guess I'm kind of doing what you're suggesting but just getting the rounds localized string directly from the table instead of through the global variables.

    upload_2023-5-3_14-59-30.png
     
    Last edited: May 3, 2023
  22. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,226
    A
    I see. Could you make the rounds value a global variable instead of using {0}? Then you could access it anywhere including your main string. That may help keep things simpler and easier on the translators.
     
  23. maikkanerva

    maikkanerva

    Joined:
    Dec 14, 2018
    Posts:
    27
    Unfortunately in my case these are buff-specific variables, basically for how many rounds a buff lasts / has remaining, so I can't make it global really. Or do you mean that I have one global localization variable that is a number, that is set to a specific buffs duration whenever this main localization is used?