Search Unity

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:
    481
    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:
    8,281
    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. }
     
  3. MUGIK

    MUGIK

    Joined:
    Jul 2, 2015
    Posts:
    481
    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:
    481
    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:
    8,281
    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:
    8,281
    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:
    8,281
    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.