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:
string key = "key";
string text = "text";
StringTable table = reference_to_table;
// actual code
table.AddEntry(key, text);
EditorUtility.SetDirty(table);
EditorUtility.SetDirty(table.SharedData);
Original post:
There is a pretty handy context menu option for setting up LocalizedStringEvent component:
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.
Yes we have lots of automation support.
Here is an example that adds the text from TextMeshPro
using TMPro;
using UnityEditor;
using UnityEditor.Localization;
using UnityEngine.Events;
using UnityEngine.Localization.Components;
using UnityEngine.Localization.Tables;
static class LocalizeMenuItem
{
[MenuItem("CONTEXT/TextMeshProUGUI/Localize - Add Entry")]
static void LocalizeTMProText(MenuCommand command)
{
var target = command.context as TextMeshProUGUI;
SetupForLocalization(target);
}
public static void SetupForLocalization(TextMeshProUGUI target)
{
var comp = Undo.AddComponent(target.gameObject, typeof(LocalizeStringEvent)) as LocalizeStringEvent;
var setStringMethod = target.GetType().GetProperty("text").GetSetMethod();
var methodDelegate = System.Delegate.CreateDelegate(typeof(UnityAction<string>), target, setStringMethod) as UnityAction<string>;
UnityEditor.Events.UnityEventTools.AddPersistentListener(comp.OnUpdateString, methodDelegate);
var table = LocalizationEditorSettings.GetStringTableCollection("My Table");
var stringTable = table.GetTable("en") as StringTable;
var newKey = stringTable.SharedData.AddKey();
stringTable.AddEntry(newKey.Id, target.text);
EditorUtility.SetDirty(stringTable);
EditorUtility.SetDirty(stringTable.SharedData);
}
}
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.
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
SharedTableData.SharedTableEntry entry = _currentStringTable.SharedData.AddKey(key);
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:
return _currentStringTable[key].LocalizedValue;
But when I open the table editor, I see all entries generated - and empty Am I missing something?
Sorry, it was my bad - just had to remove 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):
[CreateAssetMenu]
public class DebugLocalization : ScriptableObject
{
[SerializeField]
public StringTable CurrentStringTable;
public void Add(string key, string text)
{
CurrentStringTable.AddEntry(key, text);
Debug.Log("------------ Test: Key " + key + " Value " + CurrentStringTable[key].Value);
//LocalizationEditorSettings.EditorEvents.RaiseTableEntryAdded(_currentStringTable, newEntry);
//LocalizationEditorSettings.EditorEvents.RaiseCollectionModified(null, _currentStringTable);
CurrentStringTable.OnAfterDeserialize();
}
}
And custom editor for it:
[CustomEditor(typeof(DebugLocalization))]
public class DebugLocalizationEditor : Editor
{
private DebugLocalization _target;
private void OnEnable()
{
_target = target as DebugLocalization;
}
public override void OnInspectorGUI()
{
DrawDefaultInspector();
if (GUILayout.Button("Add"))
{
_target.Add("DebugKey3", "Debug value3");
EditorUtility.SetDirty(_target.CurrentStringTable);
EditorUtility.SetDirty(_target.CurrentStringTable.SharedData);
}
}
}
The result of pressing “Add” button:
Choose assigned table in inspector → hit “edit table” → see key aded, but both languages values are empty
See correct console output “Test: Key DebugKey3 Value Debug value3”