Change text with specific localization key in table

Hello,

I have a menu to select a character between 4 types.
When a character is selected, a text pannel is updated to add informations.
I want to update this pannel with localization. I know how to do it withtout the new localization package, but what I want to do is “write this specific localization key here”.
The localization key may varie for each character so I will make a “variable variable” to seperate :

I will have this on my localization database :

Character_TypeKnight_Name
Character_TypeKnight_Description
Character_TypeMagician_Name
Character_TypeMagician_Description

Here the script I tried using autocompletion :

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using UnityEngine.Localization;

public class SelectCharacterEvent : MonoBehaviour, ISelectHandler
{
    public string CharacNameIDUI;
    public Text CharacSelectionName;

    public void OnSelect(BaseEventData eventData)
    {
            Debug.Log("I'm selected" + CharacNameIDUI);
 
        CharacSelectionName.text = UnityEngine.Localization.Tables.DetailedLocalizationTable<TTable, Tentry>;
    }
}

I know how to change text with localization, but in this case it’s more complicated because the text depend on event.

https://docs.unity3d.com/Packages/com.unity.localization@0.4/manual/index.html#9-string-localization-use-string-tables

I’m not entirely sure I understand but it sounds like you want to change the Key for a LocalizedString at runtime.
This is fine. The Samples contain various ways to work with LocalizedStrings, this is a modified version that may do what you need:

public class LocalizedStringWithChangeHandlerExample : MonoBehaviour
{
    public LocalizedString stringRef = new LocalizedString() { TableReference = "My String Table", TableEntryReference = "Character_TypeKnight_Name" };

    public string CharacNameIDUI;
    public Text CharacSelectionName;

    void OnEnable()
    {
        stringRef.StringChanged += UpdateString;
    }

    void OnDisable()
    {
        stringRef.StringChanged -= UpdateString;
    }

    void UpdateString(string translatedValue)
    {
        CharacSelectionName.text = translatedValue;
    }

    public void OnSelect(BaseEventData eventData)
    {
        Debug.Log("I'm selected" + CharacNameIDUI);

        // Change the Key here. This will trigger an update which will call UpdateString with the new translated value
        stringRef.TableEntryReference = CharacNameIDUI;
    }
}

Thank you for your time.

There is 2 character playable : a Magician, a Knight. The player must do a choice.
On my UI there is 2 images that represent a Magician, and a Knight, they can be selected.
I have ONE character_nametype_ui that display the choice before confirmation, and is updated when I select Magician or Knight (i.e : “Will you play a Magicial ?”).

All I want, is that when someone click on the Magician’s Image, the character_nametype_ui update with the magician name, but I want to localize that as well. I can change the character_nametype_ui content, but how do I do it with localization ?

In my “Table Collection Name” : UI_Text I have these entries :

KEY‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎en_EN ‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎fr_FR
Character_Name_Magician ‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎Magician ‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎Sorcier
Character_Name_Knight ‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎Knight ‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎‏‏‎ ‎Chevalier

There is a lot of way to do it. Simpler for me will be :

  • Search on the “Table Collection Name” in “UI_Text”
  • Search for the entry “Character_Name_VARIABLE”
  • Go to “localisation settings”
  • Put this text into my variable.
  • Update character_nametype_ui with my variable.

I dont know if i’m clear, I just want to know how to access to a “Key” or “Key ID” in a specific table from my script that’s all ?

Something like : variable = “Entry Value” for “Key Id = XXX” && “Table Collection = YYYY” for the current localisation language selected.

You can get a StringTable and then query the Keys and Key Ids.
See the LocalizedStringTableExample in the Samples.

using UnityEngine;
using UnityEngine.Localization;
using UnityEngine.Localization.Settings;
using UnityEngine.Localization.Tables;

namespace UnityEditor.Localization.Samples
{
    /// <summary>
    /// This example shows how a <see cref="StringTable"> can be used directly in order to get translated
    /// strings for multiple entries using a <see cref="LocalizedStringTable>"/>.
    /// </summary>
    public class LocalizedStringTableExample : MonoBehaviour
    {
        public LocalizedStringTable stringTable = new LocalizedStringTable { TableReference = "My Strings" };

        // We will cache our translated strings
        string m_TranslatedStringHello;
        string m_TranslatedStringGoodbye;
        string m_TranslatedStringThisIsATest;

        void OnEnable()
        {
            stringTable.TableChanged += LoadStrings;
        }

        void OnDisable()
        {
            stringTable.TableChanged -= LoadStrings;
        }

        void LoadStrings(StringTable stringTable)
        {
            m_TranslatedStringHello = GetLocalizedString(stringTable, "Hello");
            m_TranslatedStringGoodbye = GetLocalizedString(stringTable, "Goodbye");
            m_TranslatedStringThisIsATest = GetLocalizedString(stringTable, "This is a test");
        }

        static string GetLocalizedString(StringTable table, string entryName)
        {
            // Get the table entry. The entry contains the localized string and Metadata
            var entry = table.GetEntry(entryName);
            return entry.GetLocalizedString(); // We can pass in optional arguments for Smart Format or String.Format here.
        }

        void OnGUI()
        {
            // We can check if the localization system is ready using the InitializationOperation.
            // Initialization involves loading locales and optionally preloading localized data for the current locale.
            if (!LocalizationSettings.InitializationOperation.IsDone)
            {
                GUILayout.Label("Initializing Localization");
                return;
            }

            GUILayout.Label(m_TranslatedStringThisIsATest);
            GUILayout.Label(m_TranslatedStringHello);
            GUILayout.Label(m_TranslatedStringGoodbye);
        }
    }
}

Once you have the table you can access its SharedData property which contains all the keys and ids.
You can also use LocalizationSettings.StringDatabase.GetTableAsync to get the table instead of LocalizationSettings.StringDatabase.GetTableAsync

2 Likes

If you have a table with a list of words, how would you make a textMesh text change to a random item of the table every 30 seconds ?

Something like this

public class Example : MonoBehaviour
{
    public TextMeshProUGUI tmp;
    public LocalizedStringTable myTable = new LocalizedStringTable("Random Strings Table");
    public float delay = 30;

    StringTable table;
    Coroutine coroutine;

    private void Start()
    {
        myTable.TableChanged += MyTable_TableChanged;
    }

    void MyTable_TableChanged(StringTable value)
    {
        table = value;

        if (coroutine != null)
            StopCoroutine(coroutine);

        coroutine = StartCoroutine(UpdateStrings());
    }

    IEnumerator UpdateStrings()
    {
        var wait = new WaitForSeconds(delay);

        while (Application.isPlaying)
        {
            var randomEntry = table.SharedData.Entries[Random.Range(0, table.Count)];
            tmp.text = table.GetEntry(randomEntry.Id).GetLocalizedString();

            yield return wait;
        }
    }
}
2 Likes

Thanks, that’s exactly what I was looking for :slight_smile:

1 Like

Sorry but how would you do almost the same but now with an audio clip? Get a random audio clip asset and play it

Similar but by using an AssetTable.
Instead of calling GetLocalizedString on the entry you would call LocalizationSettings.AssetDatabase
LoadAssetAsync(table name, EntryId)

Sorry But I didn’t get it, right now my code looks like this, it’s not working

using System.Collections;
using UnityEngine;
using UnityEngine.Localization;
using UnityEngine.Localization.Tables;
using UnityEngine.Localization.Settings;


public class GetRandomAudioClip : MonoBehaviour
{

    public LocalizedAssetTable myTable = new LocalizedAssetTable("Tabla");

    public AssetTable table;

    public AudioClip clip;

    private void Start()
    {
        myTable.TableChanged += MyTable_TableChanged;
    }

    private void MyTable_TableChanged(AssetTable value)
    {
        table = value;
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.F))
        {
            getAudioClip();
        }
    }

    public void getAudioClip()
    {

        StartCoroutine(getRandomAudioClipFromAssetTable());
    }

    IEnumerator getRandomAudioClipFromAssetTable()
    {
        int entryIndex = UnityEngine.Random.Range(0, table.Count);

        var randomEntry = table.SharedData.Entries[entryIndex];

        var assetLoadOperation = LocalizationSettings.AssetDatabase.GetLocalizedAssetAsync<AudioClip>(table.name, randomEntry.Id);

        yield return assetLoadOperation;

        clip = assetLoadOperation.Result;
    }



}

Try ch

Do you get any errors?
Try changing table.name to table.TableCollectionName.

You are right, that was my error, thank you :smile:

1 Like