Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Auto-create string table entries when Localize text components

Discussion in 'Localization Tools' started by MUGIK, Nov 19, 2020.

  1. MUGIK

    MUGIK

    Joined:
    Jul 2, 2015
    Posts:
    446
    UPD 01.11.2021
    Thanks to @Misha_Kh and @karl_jones we know the right (and quite simple) way to add new entries to the table:
    Code (CSharp):
    1.  
    2. string key = "key";
    3. string text = "text";
    4. StringTable table = reference_to_table;
    5.  
    6. // actual code
    7. table.AddEntry(key, text);
    8. EditorUtility.SetDirty(table);
    9. EditorUtility.SetDirty(table.SharedData);
    10.  
    Original post:
    There is a pretty handy context menu option for setting up LocalizedStringEvent component:
    upload_2020-11-19_20-49-19.png

    But I would like to go further and somehow create entries based on the existing content of the component.

    For now, I need to:
    - click on Localize
    - unfold localized string property
    - select desired table (in most cases it's the same table again and again)
    - click on "Add new entry"
    - copy content from text component
    - unfold desired locale
    - paste text into locale

    For small games it's ok, but I have something like a narrative novel so I have a lot of text and text components. And the past half of an hour I was doing these steps again and again (I already have a lot of content in the game). And I'm really tired of doing this :) It would be really really cool if the newly created entry would have text from text component for default language.

    Text components are only one part of the issue. I also have custom dialog nodes that also need to be localized. And there are tons of nodes and text. I really want to automize this process. Hope this makes sense.

    So I'm wondering is there a way to add entries to tables from code?
    I can't find anything related in the documentation and this forum.
     
    Last edited: Nov 1, 2021
  2. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    7,787
    Yes we have lots of automation support.
    Here is an example that adds the text from TextMeshPro

    Code (csharp):
    1. using TMPro;
    2. using UnityEditor;
    3. using UnityEditor.Localization;
    4. using UnityEngine.Events;
    5. using UnityEngine.Localization.Components;
    6. using UnityEngine.Localization.Tables;
    7.  
    8. static class LocalizeMenuItem
    9. {
    10.     [MenuItem("CONTEXT/TextMeshProUGUI/Localize - Add Entry")]
    11.     static void LocalizeTMProText(MenuCommand command)
    12.     {
    13.         var target = command.context as TextMeshProUGUI;
    14.         SetupForLocalization(target);
    15.     }
    16.  
    17.     public static void SetupForLocalization(TextMeshProUGUI target)
    18.     {
    19.         var comp = Undo.AddComponent(target.gameObject, typeof(LocalizeStringEvent)) as LocalizeStringEvent;
    20.         var setStringMethod = target.GetType().GetProperty("text").GetSetMethod();
    21.         var methodDelegate = System.Delegate.CreateDelegate(typeof(UnityAction<string>), target, setStringMethod) as UnityAction<string>;
    22.         UnityEditor.Events.UnityEventTools.AddPersistentListener(comp.OnUpdateString, methodDelegate);
    23.  
    24.         var table = LocalizationEditorSettings.GetStringTableCollection("My Table");
    25.         var stringTable = table.GetTable("en") as StringTable;
    26.  
    27.         var newKey = stringTable.SharedData.AddKey();
    28.         stringTable.AddEntry(newKey.Id, target.text);
    29.  
    30.         EditorUtility.SetDirty(stringTable);
    31.         EditorUtility.SetDirty(stringTable.SharedData);
    32.     }
    33. }
     
    ggzerosum, Trisibo and MUGIK like this.
  3. MUGIK

    MUGIK

    Joined:
    Jul 2, 2015
    Posts:
    446
    Thanks a lot! You don't wanna see what I wrote trying to figure it out by myself XD

    That's working, but how can I force StringTable editor window and LocalizedString property drawer to update their editor representation?
    For now, I need to switch to another table then go back, and only after that I can see changes in StringTable editor window.
    Same for LocalizedString: I need to select another object and then select the desired object back, only after that changes are applied to the editor.
     
  4. MUGIK

    MUGIK

    Joined:
    Jul 2, 2015
    Posts:
    446
    I figured it out!
    After adding entry you need to raise some events to update editors:
    Code (CSharp):
    1.  
    2. LocalizationEditorSettings.EditorEvents.RaiseTableEntryAdded(stringTable, newKey);
    3. LocalizationEditorSettings.EditorEvents.RaiseCollectionModified(null, stringTable);
    4.  
     
    karl_jones likes this.
  5. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    7,787
    Oh yes. Nice :)
     
  6. Misha_Kh

    Misha_Kh

    Joined:
    Apr 26, 2021
    Posts:
    5
    Hi! Trying to add entries manually now, looks like I can't invoke those events, because they are now became internal. Actually, what I'm trying to do, is to fill localisation table with entries from dictionary in memory. I'm using
    Code (CSharp):
    1. SharedTableData.SharedTableEntry entry = _currentStringTable.SharedData.AddKey(key);
    2.  
    3.         var newEntry = _currentStringTable.AddEntry(entry.Id, text);
    ...where "text" is my text, and "key" is my key from dictionary. Then I'm testing the new value - have it returned correctly, like this:
    Code (CSharp):
    1. return _currentStringTable[key].LocalizedValue;
    But when I open the table editor, I see all entries generated - and empty :( Am I missing something?
     
  7. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    7,787
    Did you mark the collection dirty? Changes wont be saved if you dont.

    Code (csharp):
    1. EditorUtility.SetDirty(_currentStringTable);
    2. EditorUtility.SetDirty(_currentStringTable.SharedData);
    Also you can just call AddEntry, it will add the key if it does not already exist.
     
    Misha_Kh likes this.
  8. Misha_Kh

    Misha_Kh

    Joined:
    Apr 26, 2021
    Posts:
    5
    Thanks for replay! Yeah, I did after reading this thread - no luck for now...
     
  9. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    7,787
    So the values you add to the tables never show up in the editor?
    What does your full code look like?
     
  10. Misha_Kh

    Misha_Kh

    Joined:
    Apr 26, 2021
    Posts:
    5
    UPDATE

    Sorry, it was my bad - just had to remove
    Code (CSharp):
    1. CurrentStringTable.OnAfterDeserialize();
    - turns out, it breaks the things. I have read about adding it for correct work somewhere on forums. After removing all works fine!
    Thanks for help!


    I think, there is no problem with serialisation - I see newly added key in the table. But it's empty - that's the question. Here is my full code (have made this simplified version - with same result):
    Code (CSharp):
    1.  
    2. [CreateAssetMenu]
    3. public class DebugLocalization : ScriptableObject
    4. {
    5.     [SerializeField]
    6.     public StringTable CurrentStringTable;
    7.  
    8.     public void Add(string key, string text)
    9.     {
    10.         CurrentStringTable.AddEntry(key, text);
    11.         Debug.Log("------------ Test: Key " + key + " Value " + CurrentStringTable[key].Value);
    12.  
    13.         //LocalizationEditorSettings.EditorEvents.RaiseTableEntryAdded(_currentStringTable, newEntry);
    14.         //LocalizationEditorSettings.EditorEvents.RaiseCollectionModified(null, _currentStringTable);
    15.  
    16.         CurrentStringTable.OnAfterDeserialize();
    17.     }
    18. }
    And custom editor for it:
    Code (CSharp):
    1.  
    2. [CustomEditor(typeof(DebugLocalization))]
    3. public class DebugLocalizationEditor : Editor
    4. {
    5.     private DebugLocalization _target;
    6.  
    7.     private void OnEnable()
    8.     {
    9.         _target = target as DebugLocalization;
    10.     }
    11.  
    12.     public override void OnInspectorGUI()
    13.     {
    14.         DrawDefaultInspector();
    15.         if (GUILayout.Button("Add"))
    16.         {
    17.             _target.Add("DebugKey3", "Debug value3");
    18.  
    19.             EditorUtility.SetDirty(_target.CurrentStringTable);
    20.             EditorUtility.SetDirty(_target.CurrentStringTable.SharedData);
    21.         }
    22.     }
    23. }
    24.  
    The result of pressing "Add" button:
    1. Choose assigned table in inspector -> hit "edit table" -> see key aded, but both languages values are empty
    2. See correct console output "Test: Key DebugKey3 Value Debug value3"
     
    Last edited: Oct 26, 2021
    karl_jones likes this.