Is it possible to use a localized string inside a a Smart String?

Hi :slight_smile: I’m trying to understand if is possible to do what is said in the title.

For example, supposing to have a smart string like this:

{vehicleType} is {vehicleStatus}

where carname and velocity can assume different values and are localized.

Carname values are {car, motorbyke, bicycle}.
Velocity values are {free, reserved}.

For example I want strings like:
“Car is free”,
"Bicycle is reserved},
etc…

Given this setup, when I go to change the language, these strings must be localized correctly.

How can I manage this kind of situations?

Thank you so much :slight_smile:

Yes, you can use nesting of localized strings but you should be careful about it.
The structure may need to change when dealing with languages such as Spanish where the gender of the object can change the other words. For example, see here Persistent Variables source | Localization | 1.3.2
The gender example is available through the Samples which can be found in the package manager.
You should be able to do something similiar. If you dont have a lot of objects and states then it may be worth just having each sentence as a separate table entry, this will be much easier for a translator to work with.

Hi, thank you for the answer :). Since I’m doing it via script, as I was doing here , can you help me with the setup?

Actually I add the LocalizeStringEvent to the interested GameObject as follows:

// Add LocalizeStringEvent component
targetGameObject.AddComponent<LocalizeStringEvent>();

// Assign text to update
TextMeshProUGUI textToUpdate = data.text;

// Setup LocalizeString.
LocalizedString localizeString = new LocalizedString("table_name", "entry_name");

// Setup smart fields
localizeString.Add("smartFieldName1", new StringVariable { Value = valueToAssign });
localizeString.Add("smartFieldName2", new StringVariable { Value = valueToAssign });

// Assign localized string and setup update
targetGameObject.GetComponent<LocalizeStringEvent>().StringReference = localizeString;
targetGameObject.GetComponent<LocalizeStringEvent>().OnUpdateString.AddListener(x => textToUpdate.text = x);
targetGameObject.GetComponent<LocalizeStringEvent>().StringReference.RefreshString();

But I can’t figure out how to add nested localization setup :(.

Thank you :slight_smile:

A nested localized string is done by adding it as a persistent variable to a LocalizedString.
https://docs.unity3d.com/Packages/com.unity.localization@1.3/manual/Smart/Persistent-Variables-Source.html#nested-translations

It can be done through script like this: Class LocalizedString | Localization | 1.3.2

public LocalizedString withNestedTranslation = new LocalizedString("My String Table", "My Game Text")
{
   { "some-text", new StringVariable { Value = "Hello World" } },
   { "nested", new LocalizedString("My String Table", "My Nested Text")
     {
         { "score", new IntVariable { Value = 100 } },
     }}
};

You can also call Add on an existing LocalizedString.

myString.Add("nested-string", new LocalizedString("My String Table", "My Nested Text");
1 Like

So, supposing I want to continue my above implementation and supposing I have the following table where ItemText is the SmartString to setup:

8436599--1117571--upload_2022-9-13_16-38-39.png

As you said, I can add persistent serialized arguments by using Add. I should to it in lines 11 and 12. What I don’t understand is the values to assign. If there are multiple values (item = {pen, backpack} - color = {red, blue, etc…}, how can I add the right value?

// Add LocalizeStringEvent component
targetGameObject.AddComponent<LocalizeStringEvent>();

// Assign text to update
TextMeshProUGUI textToUpdate = data.text;

// Setup LocalizeString.
LocalizedString localizeString = new LocalizedString("table_name", "entry_name");

// Setup smart fields
localizeString.Add("item", new StringVariable { Value = ?? });
localizeString.Add("color", new StringVariable { Value = ?? });

// Assign localized string and setup update
targetGameObject.GetComponent<LocalizeStringEvent>().StringReference = localizeString;
targetGameObject.GetComponent<LocalizeStringEvent>().OnUpdateString.AddListener(x => textToUpdate.text = x);
targetGameObject.GetComponent<LocalizeStringEvent>().StringReference.RefreshString();

If you look at the sample scene for this example you will see how we do it.

You can add the nested strings and leave them empty.

localizeString.Add("item", new LocalizedString());
localizeString.Add("color", new LocalizedString());

Then change their values at a later point when you need them.

public void SetItem(string itemName)
{
    var item = localizeString["item"] as LocalizedString;
    item.SetReference("My Table", itemName);
}

In our example when a button is pressed we update the nested value

using System;
using UnityEngine;
using UnityEngine.Localization;
using UnityEngine.Localization.Components;

public class SetLocalVariable : MonoBehaviour
{
    public LocalizeStringEvent localizedString;

    public void SetNestedStringEntry(string variableAndEntry)
    {
        var args = variableAndEntry.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
        if (args.Length != 2)
            return;

        if (localizedString.StringReference[args[0]] is LocalizedString nested)
        {
            nested.TableEntryReference = args[1];
        }
    }
}
1 Like

Ahhhh, ok. I got it! Thank you so much! :):):slight_smile:

1 Like