Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save moto2002/100e20b53a50955d41dba0dad4a014b4 to your computer and use it in GitHub Desktop.

Select an option

Save moto2002/100e20b53a50955d41dba0dad4a014b4 to your computer and use it in GitHub Desktop.

Revisions

  1. @andrew-raphael-lukasik andrew-raphael-lukasik renamed this gist Sep 28, 2023. 1 changed file with 7 additions and 0 deletions.
    7 changes: 7 additions & 0 deletions .readme.md → .UIDocumentLocalization.cs.md
    Original file line number Diff line number Diff line change
    @@ -2,6 +2,13 @@
    > // NOTE: this class assumes that you designate StringTable keys in label fields (as seen in Label, Button, etc)
    > // and start them all with '#' char (so other labels will be left be)







    # Programming workflow:

    Binding `UIDocument`, normally, happened at `OnEnable` but since `StringTable` can be (re)loaded at any time then we need to switch to using events.
  2. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Aug 28, 2023. 1 changed file with 100 additions and 100 deletions.
    200 changes: 100 additions & 100 deletions UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -32,120 +32,120 @@
    public class UIDocumentLocalization : MonoBehaviour
    {

    [SerializeField] LocalizedStringTable _table = null;
    UIDocument _uiDocument;
    [SerializeField] LocalizedStringTable _table = null;
    UIDocument _uiDocument;

    /// <summary> Executed after hierarchy is cloned fresh and translated. </summary>
    public event System.Action<VisualElement> onCompleted = ( VisualElement root ) =>
    {
    /// <summary> Executed after hierarchy is cloned fresh and translated. </summary>
    public event System.Action<VisualElement> onCompleted = ( VisualElement root ) =>
    {
    #if DEBUG
    Debug.Log($"{nameof(UIDocumentLocalization)}: {nameof(UIDocument)} translated");
    Debug.Log($"{nameof(UIDocumentLocalization)}: {nameof(UIDocument)} translated");
    #endif
    };
    };


    void OnEnable ()
    {
    if( _uiDocument == null )
    _uiDocument = GetComponent<UIDocument>();
    _table.TableChanged += OnTableChanged;
    }
    void OnEnable ()
    {
    if( _uiDocument == null )
    _uiDocument = GetComponent<UIDocument>();
    _table.TableChanged += OnTableChanged;
    }

    void OnDisable ()
    {
    _table.TableChanged -= OnTableChanged;
    }
    void OnDisable ()
    {
    _table.TableChanged -= OnTableChanged;
    }


    void OnTableChanged ( StringTable table )
    {
    _uiDocument.rootVisualElement.Clear();
    _uiDocument.visualTreeAsset.CloneTree(_uiDocument.rootVisualElement);
    void OnTableChanged ( StringTable table )
    {
    _uiDocument.rootVisualElement.Clear();
    _uiDocument.visualTreeAsset.CloneTree(_uiDocument.rootVisualElement);

    #if DEBUG
    Debug.Log($"{nameof(UIDocumentLocalization)}: {nameof(StringTable)} changed, {nameof(VisualTreeAsset)} has been cloned anew" , _uiDocument);
    Debug.Log($"{nameof(UIDocumentLocalization)}: {nameof(StringTable)} changed, {nameof(VisualTreeAsset)} has been cloned anew" , _uiDocument);
    #endif

    var op = _table.GetTableAsync();
    if( op.IsDone )
    {
    OnTableLoaded(op);
    }
    else
    {
    op.Completed -= OnTableLoaded;
    op.Completed += OnTableLoaded;
    }
    }

    void OnTableLoaded ( AsyncOperationHandle<StringTable> op )
    {
    StringTable table = op.Result;
    LocalizeChildrenRecursively(_uiDocument.rootVisualElement , table);
    _uiDocument.rootVisualElement.MarkDirtyRepaint();
    onCompleted(_uiDocument.rootVisualElement);
    }

    void LocalizeChildrenRecursively ( VisualElement element , StringTable table )
    {
    VisualElement.Hierarchy elementHierarchy = element.hierarchy;
    int numChildren = elementHierarchy.childCount;
    for( int i = 0 ; i < numChildren ; i++ )
    {
    VisualElement child = elementHierarchy.ElementAt(i);
    Localize(child , table);
    }
    for( int i = 0 ; i < numChildren ; i++ )
    {
    VisualElement child = elementHierarchy.ElementAt(i);
    VisualElement.Hierarchy childHierarchy = child.hierarchy;
    int numGrandChildren = childHierarchy.childCount;
    if( numGrandChildren != 0 )
    LocalizeChildrenRecursively(child , table);
    }
    }

    void Localize ( VisualElement next , StringTable table )
    {
    if( typeof(TextElement).IsInstanceOfType(next) )
    {
    TextElement textElement = (TextElement)next;
    string key = textElement.text;
    if( !string.IsNullOrEmpty(key) && key[0] == '#' )
    {
    key = key.TrimStart('#');
    StringTableEntry entry = table[key];
    if( entry != null )
    textElement.text = entry.LocalizedValue;
    else
    Debug.LogWarning($"No {table.LocaleIdentifier.Code} translation for key: '{key}'");
    }
    }
    }
    var op = _table.GetTableAsync();
    if( op.IsDone )
    {
    OnTableLoaded(op);
    }
    else
    {
    op.Completed -= OnTableLoaded;
    op.Completed += OnTableLoaded;
    }
    }

    void OnTableLoaded ( AsyncOperationHandle<StringTable> op )
    {
    StringTable table = op.Result;
    LocalizeChildrenRecursively(_uiDocument.rootVisualElement , table);
    _uiDocument.rootVisualElement.MarkDirtyRepaint();
    onCompleted(_uiDocument.rootVisualElement);
    }

    void LocalizeChildrenRecursively ( VisualElement element , StringTable table )
    {
    VisualElement.Hierarchy elementHierarchy = element.hierarchy;
    int numChildren = elementHierarchy.childCount;
    for( int i = 0 ; i < numChildren ; i++ )
    {
    VisualElement child = elementHierarchy.ElementAt(i);
    Localize(child , table);
    }
    for( int i = 0 ; i < numChildren ; i++ )
    {
    VisualElement child = elementHierarchy.ElementAt(i);
    VisualElement.Hierarchy childHierarchy = child.hierarchy;
    int numGrandChildren = childHierarchy.childCount;
    if( numGrandChildren != 0 )
    LocalizeChildrenRecursively(child , table);
    }
    }

    void Localize ( VisualElement next , StringTable table )
    {
    if( typeof(TextElement).IsInstanceOfType(next) )
    {
    TextElement textElement = (TextElement)next;
    string key = textElement.text;
    if( !string.IsNullOrEmpty(key) && key[0] == '#' )
    {
    key = key.TrimStart('#');
    StringTableEntry entry = table[key];
    if( entry != null )
    textElement.text = entry.LocalizedValue;
    else
    Debug.LogWarning($"No {table.LocaleIdentifier.Code} translation for key: '{key}'");
    }
    }
    }

    #if UNITY_EDITOR
    [CustomEditor(typeof(UIDocumentLocalization))]
    public class MyEditor : Editor
    {
    public override VisualElement CreateInspectorGUI ()
    {
    var ROOT = new VisualElement();

    var LABEL = new Label($"- Remember -<br> Use <color=\"yellow\">{nameof(onCompleted)}</color> event instead of <color=\"yellow\">OnEnable()</color><br>to localize and bind this document correctly.");
    {
    var style = LABEL.style;
    style.minHeight = EditorGUIUtility.singleLineHeight * 3;
    style.backgroundColor = new Color(1f , 0.121f , 0 , 0.2f);
    style.borderBottomLeftRadius = style.borderBottomRightRadius = style.borderTopLeftRadius = style.borderTopRightRadius = 6;
    style.unityTextAlign = TextAnchor.MiddleCenter;
    }
    ROOT.Add(LABEL);

    InspectorElement.FillDefaultInspector(ROOT , this.serializedObject , this);

    return ROOT;
    }
    }
    [CustomEditor(typeof(UIDocumentLocalization))]
    public class MyEditor : Editor
    {
    public override VisualElement CreateInspectorGUI ()
    {
    var ROOT = new VisualElement();

    var LABEL = new Label($"- Remember -<br> Use <color=\"yellow\">{nameof(onCompleted)}</color> event instead of <color=\"yellow\">OnEnable()</color><br>to localize and bind this document correctly.");
    {
    var style = LABEL.style;
    style.minHeight = EditorGUIUtility.singleLineHeight * 3;
    style.backgroundColor = new Color(1f , 0.121f , 0 , 0.2f);
    style.borderBottomLeftRadius = style.borderBottomRightRadius = style.borderTopLeftRadius = style.borderTopRightRadius = 6;
    style.unityTextAlign = TextAnchor.MiddleCenter;
    }
    ROOT.Add(LABEL);

    InspectorElement.FillDefaultInspector(ROOT , this.serializedObject , this);

    return ROOT;
    }
    }
    #endif

    }
  3. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Aug 28, 2023. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion .readme.md
    Original file line number Diff line number Diff line change
    @@ -30,4 +30,4 @@ public class MainMenuController : MonoBehaviour
    ```

    ### Works well with:
    LocaleList (https://gist.github.com/andrew-raphael-lukasik/e4ae9b45a2c24672c0d1218f77235948)
    - [LocaleList](https://gist.github.com/andrew-raphael-lukasik/e4ae9b45a2c24672c0d1218f77235948)
  4. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Aug 28, 2023. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion .readme.md
    Original file line number Diff line number Diff line change
    @@ -2,7 +2,7 @@
    > // NOTE: this class assumes that you designate StringTable keys in label fields (as seen in Label, Button, etc)
    > // and start them all with '#' char (so other labels will be left be)
    ## Programming workflow change:
    # Programming workflow:

    Binding `UIDocument`, normally, happened at `OnEnable` but since `StringTable` can be (re)loaded at any time then we need to switch to using events.
    ```cs
  5. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Aug 27, 2023. 1 changed file with 6 additions and 2 deletions.
    8 changes: 6 additions & 2 deletions .readme.md
    Original file line number Diff line number Diff line change
    @@ -2,9 +2,13 @@
    > // NOTE: this class assumes that you designate StringTable keys in label fields (as seen in Label, Button, etc)
    > // and start them all with '#' char (so other labels will be left be)
    ### Programming workflow change:
    ## Programming workflow change:

    Binding `UIDocument`, normally, happened at `OnEnable` but since `StringTable` can be (re)loaded at any time then we need to switch to using events. `GetComponent<UIDocumentLocalization>().onCompleted += (root) => Debug.Log("let's bind a freshly localized UI!");` precisely.
    Binding `UIDocument`, normally, happened at `OnEnable` but since `StringTable` can be (re)loaded at any time then we need to switch to using events.
    ```cs
    GetComponent<UIDocumentLocalization>().onCompleted += (root) => Debug.Log("let's bind a freshly localized UI!");
    ```
    I added a big remainder so ppl not miss this:

    ![Screenshot 2023-08-28 001053](https://user-images.githubusercontent.com/3066539/263556330-5e8b7ca1-21fe-493a-9a2a-4e14202f1a5d.png)

  6. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Aug 27, 2023. 1 changed file with 23 additions and 0 deletions.
    23 changes: 23 additions & 0 deletions .readme.md
    Original file line number Diff line number Diff line change
    @@ -2,5 +2,28 @@
    > // NOTE: this class assumes that you designate StringTable keys in label fields (as seen in Label, Button, etc)
    > // and start them all with '#' char (so other labels will be left be)
    ### Programming workflow change:

    Binding `UIDocument`, normally, happened at `OnEnable` but since `StringTable` can be (re)loaded at any time then we need to switch to using events. `GetComponent<UIDocumentLocalization>().onCompleted += (root) => Debug.Log("let's bind a freshly localized UI!");` precisely.

    ![Screenshot 2023-08-28 001053](https://user-images.githubusercontent.com/3066539/263556330-5e8b7ca1-21fe-493a-9a2a-4e14202f1a5d.png)

    ```cs
    using UnityEngine;
    using UnityEngine.UIElements;

    [DisallowMultipleComponent]
    [RequireComponent( typeof(UIDocumentLocalization) )]
    public class MainMenuController : MonoBehaviour
    {
    void OnEnable () => GetComponent<UIDocumentLocalization>().onCompleted += Bind;
    void OnDisable () => GetComponent<UIDocumentLocalization>().onCompleted -= Bind;
    void Bind ( VisualElement root )
    {
    /* bind here */
    }
    }
    ```

    ### Works well with:
    LocaleList (https://gist.github.com/andrew-raphael-lukasik/e4ae9b45a2c24672c0d1218f77235948)
  7. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Aug 27, 2023. 1 changed file with 51 additions and 20 deletions.
    71 changes: 51 additions & 20 deletions UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -17,10 +17,16 @@
    using UnityEngine.Localization.Tables;
    using UnityEngine.ResourceManagement.AsyncOperations;

    #if UNITY_EDITOR
    using UnityEditor;
    using UnityEditor.UIElements;
    #endif

    // NOTE: this class assumes that you designate StringTable keys in label fields (as seen in Label, Button, etc)
    // and start them all with '#' char (so other labels will be left be)
    // example: https://i.imgur.com/H5RUIej.gif

    [HelpURL("https://gist.github.com/andrew-raphael-lukasik/72a4d3d14dd547a1d61ae9dc4c4513da")]
    [DisallowMultipleComponent]
    [RequireComponent(typeof(UIDocument))]
    public class UIDocumentLocalization : MonoBehaviour
    @@ -30,38 +36,38 @@ public class UIDocumentLocalization : MonoBehaviour
    UIDocument _uiDocument;

    /// <summary> Executed after hierarchy is cloned fresh and translated. </summary>
    public event System.Action onCompleted = () =>
    public event System.Action<VisualElement> onCompleted = ( VisualElement root ) =>
    {
    #if DEBUG
    Debug.Log($"{nameof(UIDocumentLocalization)}: {nameof(UIDocument)} translated");
    #endif
    };


    void OnEnable()
    void OnEnable ()
    {
    if (_uiDocument == null)
    if( _uiDocument == null )
    _uiDocument = GetComponent<UIDocument>();
    _table.TableChanged += OnTableChanged;
    }

    void OnDisable()
    void OnDisable ()
    {
    _table.TableChanged -= OnTableChanged;
    }


    void OnTableChanged(StringTable table)
    void OnTableChanged ( StringTable table )
    {
    _uiDocument.rootVisualElement.Clear();
    _uiDocument.visualTreeAsset.CloneTree(_uiDocument.rootVisualElement);

    #if DEBUG
    Debug.Log($"{nameof(UIDocumentLocalization)}: {nameof(StringTable)} changed, {nameof(VisualTreeAsset)} has been cloned anew", _uiDocument);
    Debug.Log($"{nameof(UIDocumentLocalization)}: {nameof(StringTable)} changed, {nameof(VisualTreeAsset)} has been cloned anew" , _uiDocument);
    #endif

    var op = _table.GetTableAsync();
    if (op.IsDone)
    if( op.IsDone )
    {
    OnTableLoaded(op);
    }
    @@ -72,49 +78,74 @@ void OnTableChanged(StringTable table)
    }
    }

    void OnTableLoaded(AsyncOperationHandle<StringTable> op)
    void OnTableLoaded ( AsyncOperationHandle<StringTable> op )
    {
    StringTable table = op.Result;
    LocalizeChildrenRecursively(_uiDocument.rootVisualElement, table);
    LocalizeChildrenRecursively(_uiDocument.rootVisualElement , table);
    _uiDocument.rootVisualElement.MarkDirtyRepaint();
    onCompleted();
    onCompleted(_uiDocument.rootVisualElement);
    }

    void LocalizeChildrenRecursively(VisualElement element, StringTable table)
    void LocalizeChildrenRecursively ( VisualElement element , StringTable table )
    {
    VisualElement.Hierarchy elementHierarchy = element.hierarchy;
    int numChildren = elementHierarchy.childCount;
    for (int i = 0; i < numChildren; i++)
    for( int i = 0 ; i < numChildren ; i++ )
    {
    VisualElement child = elementHierarchy.ElementAt(i);
    Localize(child, table);
    Localize(child , table);
    }
    for (int i = 0; i < numChildren; i++)
    for( int i = 0 ; i < numChildren ; i++ )
    {
    VisualElement child = elementHierarchy.ElementAt(i);
    VisualElement.Hierarchy childHierarchy = child.hierarchy;
    int numGrandChildren = childHierarchy.childCount;
    if (numGrandChildren != 0)
    LocalizeChildrenRecursively(child, table);
    if( numGrandChildren != 0 )
    LocalizeChildrenRecursively(child , table);
    }
    }

    void Localize(VisualElement next, StringTable table)
    void Localize ( VisualElement next , StringTable table )
    {
    if (typeof(TextElement).IsInstanceOfType(next))
    if( typeof(TextElement).IsInstanceOfType(next) )
    {
    TextElement textElement = (TextElement)next;
    string key = textElement.text;
    if (!string.IsNullOrEmpty(key) && key[0] == '#')
    if( !string.IsNullOrEmpty(key) && key[0] == '#' )
    {
    key = key.TrimStart('#');
    StringTableEntry entry = table[key];
    if (entry != null)
    if( entry != null )
    textElement.text = entry.LocalizedValue;
    else
    Debug.LogWarning($"No {table.LocaleIdentifier.Code} translation for key: '{key}'");
    }
    }
    }

    #if UNITY_EDITOR
    [CustomEditor(typeof(UIDocumentLocalization))]
    public class MyEditor : Editor
    {
    public override VisualElement CreateInspectorGUI ()
    {
    var ROOT = new VisualElement();

    var LABEL = new Label($"- Remember -<br> Use <color=\"yellow\">{nameof(onCompleted)}</color> event instead of <color=\"yellow\">OnEnable()</color><br>to localize and bind this document correctly.");
    {
    var style = LABEL.style;
    style.minHeight = EditorGUIUtility.singleLineHeight * 3;
    style.backgroundColor = new Color(1f , 0.121f , 0 , 0.2f);
    style.borderBottomLeftRadius = style.borderBottomRightRadius = style.borderTopLeftRadius = style.borderTopRightRadius = 6;
    style.unityTextAlign = TextAnchor.MiddleCenter;
    }
    ROOT.Add(LABEL);

    InspectorElement.FillDefaultInspector(ROOT , this.serializedObject , this);

    return ROOT;
    }
    }
    #endif

    }
  8. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Mar 21, 2023. 1 changed file with 10 additions and 1 deletion.
    11 changes: 10 additions & 1 deletion UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -30,7 +30,12 @@ public class UIDocumentLocalization : MonoBehaviour
    UIDocument _uiDocument;

    /// <summary> Executed after hierarchy is cloned fresh and translated. </summary>
    public event System.Action onCompleted = () => { };
    public event System.Action onCompleted = () =>
    {
    #if DEBUG
    Debug.Log($"{nameof(UIDocumentLocalization)}: {nameof(UIDocument)} translated");
    #endif
    };


    void OnEnable()
    @@ -51,6 +56,10 @@ void OnTableChanged(StringTable table)
    _uiDocument.rootVisualElement.Clear();
    _uiDocument.visualTreeAsset.CloneTree(_uiDocument.rootVisualElement);

    #if DEBUG
    Debug.Log($"{nameof(UIDocumentLocalization)}: {nameof(StringTable)} changed, {nameof(VisualTreeAsset)} has been cloned anew", _uiDocument);
    #endif

    var op = _table.GetTableAsync();
    if (op.IsDone)
    {
  9. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Jan 4, 2023. 1 changed file with 7 additions and 15 deletions.
    22 changes: 7 additions & 15 deletions UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -27,21 +27,19 @@ public class UIDocumentLocalization : MonoBehaviour
    {

    [SerializeField] LocalizedStringTable _table = null;
    UIDocument[] _uiDocuments = null;
    UIDocument _uiDocument;

    /// <summary> Executed after hierarchy is cloned fresh and translated. </summary>
    public event System.Action onCompleted = () => { };


    void OnEnable()
    {
    if (_uiDocuments == null)
    _uiDocuments = GetComponents<UIDocument>();

    if (_uiDocument == null)
    _uiDocument = GetComponent<UIDocument>();
    _table.TableChanged += OnTableChanged;
    }


    void OnDisable()
    {
    _table.TableChanged -= OnTableChanged;
    @@ -50,11 +48,8 @@ void OnDisable()

    void OnTableChanged(StringTable table)
    {
    foreach (var uidocument in _uiDocuments)
    {
    uidocument.rootVisualElement.Clear();
    uidocument.visualTreeAsset.CloneTree(uidocument.rootVisualElement);
    }
    _uiDocument.rootVisualElement.Clear();
    _uiDocument.visualTreeAsset.CloneTree(_uiDocument.rootVisualElement);

    var op = _table.GetTableAsync();
    if (op.IsDone)
    @@ -71,11 +66,8 @@ void OnTableChanged(StringTable table)
    void OnTableLoaded(AsyncOperationHandle<StringTable> op)
    {
    StringTable table = op.Result;
    foreach (var uidocument in _uiDocuments)
    {
    LocalizeChildrenRecursively(uidocument.rootVisualElement, table);
    uidocument.rootVisualElement.MarkDirtyRepaint();
    }
    LocalizeChildrenRecursively(_uiDocument.rootVisualElement, table);
    _uiDocument.rootVisualElement.MarkDirtyRepaint();
    onCompleted();
    }

  10. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Jan 2, 2023. 1 changed file with 9 additions and 3 deletions.
    12 changes: 9 additions & 3 deletions UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -57,9 +57,15 @@ void OnTableChanged(StringTable table)
    }

    var op = _table.GetTableAsync();
    if (op.IsDone) OnTableLoaded(op);
    op.Completed -= OnTableLoaded;
    op.Completed += OnTableLoaded;
    if (op.IsDone)
    {
    OnTableLoaded(op);
    }
    else
    {
    op.Completed -= OnTableLoaded;
    op.Completed += OnTableLoaded;
    }
    }

    void OnTableLoaded(AsyncOperationHandle<StringTable> op)
  11. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Jan 2, 2023. 1 changed file with 3 additions and 9 deletions.
    12 changes: 3 additions & 9 deletions UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -57,15 +57,9 @@ void OnTableChanged(StringTable table)
    }

    var op = _table.GetTableAsync();
    if (op.IsDone)
    {
    OnTableLoaded(op);
    }
    else
    {
    op.Completed -= OnTableLoaded;
    op.Completed += OnTableLoaded;
    }
    if (op.IsDone) OnTableLoaded(op);
    op.Completed -= OnTableLoaded;
    op.Completed += OnTableLoaded;
    }

    void OnTableLoaded(AsyncOperationHandle<StringTable> op)
  12. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Dec 29, 2022. 1 changed file with 55 additions and 46 deletions.
    101 changes: 55 additions & 46 deletions UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -22,89 +22,98 @@
    // example: https://i.imgur.com/H5RUIej.gif

    [DisallowMultipleComponent]
    [RequireComponent( typeof(UIDocument) )]
    [RequireComponent(typeof(UIDocument))]
    public class UIDocumentLocalization : MonoBehaviour
    {

    [SerializeField] LocalizedStringTable _table = null;
    UIDocument _document;
    UIDocument[] _uiDocuments = null;

    /// <summary> Executed after hierarchy is cloned fresh and translated. </summary>
    public event System.Action onCompleted = ()=>{};
    void OnEnable ()
    public event System.Action onCompleted = () => { };


    void OnEnable()
    {
    if( _document==null )
    _document = this.gameObject.GetComponent<UIDocument>();
    if (_uiDocuments == null)
    _uiDocuments = GetComponents<UIDocument>();

    _table.TableChanged += OnTableChanged;
    }


    void OnDisable ()
    void OnDisable()
    {
    _table.TableChanged -= OnTableChanged;
    }


    void OnTableChanged ( StringTable table )
    void OnTableChanged(StringTable table)
    {
    var root = _document.rootVisualElement;
    root.Clear();
    _document.visualTreeAsset.CloneTree( root );
    foreach (var uidocument in _uiDocuments)
    {
    uidocument.rootVisualElement.Clear();
    uidocument.visualTreeAsset.CloneTree(uidocument.rootVisualElement);
    }

    var op = _table.GetTableAsync();
    op.Completed -= OnTableLoaded;
    op.Completed += OnTableLoaded;
    if (op.IsDone)
    {
    OnTableLoaded(op);
    }
    else
    {
    op.Completed -= OnTableLoaded;
    op.Completed += OnTableLoaded;
    }
    }
    void OnTableLoaded ( AsyncOperationHandle<StringTable> op )

    void OnTableLoaded(AsyncOperationHandle<StringTable> op)
    {
    StringTable table = op.Result;
    var root = _document.rootVisualElement;

    LocalizeChildrenRecursively( root , table );
    foreach (var uidocument in _uiDocuments)
    {
    LocalizeChildrenRecursively(uidocument.rootVisualElement, table);
    uidocument.rootVisualElement.MarkDirtyRepaint();
    }
    onCompleted();
    }

    root.MarkDirtyRepaint();
    void LocalizeChildrenRecursively(VisualElement element, StringTable table)
    {
    VisualElement.Hierarchy elementHierarchy = element.hierarchy;
    int numChildren = elementHierarchy.childCount;
    for (int i = 0; i < numChildren; i++)
    {
    VisualElement child = elementHierarchy.ElementAt(i);
    Localize(child, table);
    }
    for (int i = 0; i < numChildren; i++)
    {
    VisualElement child = elementHierarchy.ElementAt(i);
    VisualElement.Hierarchy childHierarchy = child.hierarchy;
    int numGrandChildren = childHierarchy.childCount;
    if (numGrandChildren != 0)
    LocalizeChildrenRecursively(child, table);
    }
    }

    void Localize ( VisualElement next , StringTable table )
    void Localize(VisualElement next, StringTable table)
    {
    if( typeof(TextElement).IsInstanceOfType(next) )
    if (typeof(TextElement).IsInstanceOfType(next))
    {
    TextElement textElement = (TextElement) next;
    TextElement textElement = (TextElement)next;
    string key = textElement.text;
    if( !string.IsNullOrEmpty(key) && key[0]=='#' )
    if (!string.IsNullOrEmpty(key) && key[0] == '#')
    {
    key = key.TrimStart('#');
    StringTableEntry entry = table[ key ];
    if( entry!=null )
    StringTableEntry entry = table[key];
    if (entry != null)
    textElement.text = entry.LocalizedValue;
    else
    Debug.LogWarning($"No {table.LocaleIdentifier.Code} translation for key: '{key}'");
    }
    }
    }

    void LocalizeChildrenRecursively ( VisualElement element , StringTable table )
    {
    VisualElement.Hierarchy elementHierarchy = element.hierarchy;
    int numChildren = elementHierarchy.childCount;
    for( int i=0 ; i<numChildren ; i++ )
    {
    VisualElement child = elementHierarchy.ElementAt( i );
    Localize( child , table );
    }
    for( int i=0 ; i<numChildren ; i++ )
    {
    VisualElement child = elementHierarchy.ElementAt( i );
    VisualElement.Hierarchy childHierarchy = child.hierarchy;
    int numGrandChildren = childHierarchy.childCount;
    if( numGrandChildren!=0 )
    LocalizeChildrenRecursively( child , table );
    }
    }

    }
  13. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Dec 28, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -36,7 +36,7 @@ public class UIDocumentLocalization : MonoBehaviour
    void OnEnable ()
    {
    if( _document==null )
    _document = gameObject.GetComponentInParent<UIDocument>( includeInactive:true );
    _document = this.gameObject.GetComponent<UIDocument>();

    _table.TableChanged += OnTableChanged;
    }
  14. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Dec 28, 2022. 1 changed file with 1 addition and 6 deletions.
    7 changes: 1 addition & 6 deletions .readme.md
    Original file line number Diff line number Diff line change
    @@ -1,11 +1,6 @@
    ![pattern to follow](https://user-images.githubusercontent.com/3066539/209739512-0e6428a0-1324-4bd3-9cf1-71f05cf33c78.png)
    > // NOTE: this class assumes that you designate StringTable keys in label fields (as seen in Label, Button, etc)
    > // and start them all with '#' char (so other labels will be left be)
    ![pattern to follow](https://user-images.githubusercontent.com/3066539/209739512-0e6428a0-1324-4bd3-9cf1-71f05cf33c78.png)

    ---

    ### Works well with:
    LocaleList (https://gist.github.com/andrew-raphael-lukasik/e4ae9b45a2c24672c0d1218f77235948)

    ---
  15. @andrew-raphael-lukasik andrew-raphael-lukasik renamed this gist Dec 28, 2022. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  16. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Dec 28, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion readme.md
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    > // NOTE: this class assumes that you designate StringTable keys in label fields (as seen in Label, Button, etc)
    > // and start them all with '#' char (so other labels will be left be)
    ![pattern to follow](https://i.imgur.com/H5RUIej.gif)
    ![pattern to follow](https://user-images.githubusercontent.com/3066539/209739512-0e6428a0-1324-4bd3-9cf1-71f05cf33c78.png)

    ---

  17. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Dec 28, 2022. 1 changed file with 11 additions and 0 deletions.
    11 changes: 11 additions & 0 deletions readme.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,11 @@
    > // NOTE: this class assumes that you designate StringTable keys in label fields (as seen in Label, Button, etc)
    > // and start them all with '#' char (so other labels will be left be)
    ![pattern to follow](https://i.imgur.com/H5RUIej.gif)

    ---

    ### Works well with:
    LocaleList (https://gist.github.com/andrew-raphael-lukasik/e4ae9b45a2c24672c0d1218f77235948)

    ---
  18. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Feb 5, 2022. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,5 @@
    // void* src = https://gist.github.com/andrew-raphael-lukasik/72a4d3d14dd547a1d61ae9dc4c4513da
    /// void* src = https://gist.github.com/andrew-raphael-lukasik/72a4d3d14dd547a1d61ae9dc4c4513da
    ///
    /// Copyright (C) 2022 Andrzej Rafał Łukasik (also known as: Andrew Raphael Lukasik)
    ///
    /// This program is free software: you can redistribute it and/or modify
    @@ -9,6 +10,7 @@
    /// but WITHOUT ANY WARRANTY; without even the implied warranty of
    /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    /// See the GNU General Public License for details https://www.gnu.org/licenses/
    ///
    using UnityEngine;
    using UnityEngine.UIElements;
    using UnityEngine.Localization;
  19. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Feb 5, 2022. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,4 @@
    // void* src = https://gist.github.com/andrew-raphael-lukasik/72a4d3d14dd547a1d61ae9dc4c4513da

    /// Copyright (C) 2022 Andrzej Rafał Łukasik (also known as: Andrew Raphael Lukasik)
    ///
    /// This program is free software: you can redistribute it and/or modify
  20. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Feb 4, 2022. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,5 @@
    // void* src = https://gist.github.com/andrew-raphael-lukasik/72a4d3d14dd547a1d61ae9dc4c4513da

    /// Copyright (C) 2022 Andrzej Rafał Łukasik (also known as: Andrew Raphael Lukasik)
    ///
    /// This program is free software: you can redistribute it and/or modify
    @@ -8,8 +10,6 @@
    /// but WITHOUT ANY WARRANTY; without even the implied warranty of
    /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    /// See the GNU General Public License for details https://www.gnu.org/licenses/

    // void* src = https://gist.github.com/andrew-raphael-lukasik/72a4d3d14dd547a1d61ae9dc4c4513da
    using UnityEngine;
    using UnityEngine.UIElements;
    using UnityEngine.Localization;
  21. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Feb 4, 2022. 1 changed file with 11 additions and 0 deletions.
    11 changes: 11 additions & 0 deletions UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,14 @@
    /// Copyright (C) 2022 Andrzej Rafał Łukasik (also known as: Andrew Raphael Lukasik)
    ///
    /// This program is free software: you can redistribute it and/or modify
    /// it under the terms of the GNU General Public License as published by
    /// the Free Software Foundation, version 3 of the License.
    ///
    /// This program is distributed in the hope that it will be useful,
    /// but WITHOUT ANY WARRANTY; without even the implied warranty of
    /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    /// See the GNU General Public License for details https://www.gnu.org/licenses/

    // void* src = https://gist.github.com/andrew-raphael-lukasik/72a4d3d14dd547a1d61ae9dc4c4513da
    using UnityEngine;
    using UnityEngine.UIElements;
  22. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist May 30, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -42,7 +42,7 @@ void OnTableChanged ( StringTable table )
    root.Clear();
    _document.visualTreeAsset.CloneTree( root );

    var op = _table.GetTable();
    var op = _table.GetTableAsync();
    op.Completed -= OnTableLoaded;
    op.Completed += OnTableLoaded;
    }
  23. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Nov 4, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -62,11 +62,11 @@ void Localize ( VisualElement next , StringTable table )
    {
    if( typeof(TextElement).IsInstanceOfType(next) )
    {
    key = key.TrimStart('#');
    TextElement textElement = (TextElement) next;
    string key = textElement.text;
    if( !string.IsNullOrEmpty(key) && key[0]=='#' )
    {
    key = key.TrimStart('#');
    StringTableEntry entry = table[ key ];
    if( entry!=null )
    textElement.text = entry.LocalizedValue;
  24. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Nov 4, 2020. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -7,7 +7,7 @@

    // NOTE: this class assumes that you designate StringTable keys in label fields (as seen in Label, Button, etc)
    // and start them all with '#' char (so other labels will be left be)
    // example: https://i.imgur.com/h495sju.jpg
    // example: https://i.imgur.com/H5RUIej.gif

    [DisallowMultipleComponent]
    [RequireComponent( typeof(UIDocument) )]
    @@ -62,6 +62,7 @@ void Localize ( VisualElement next , StringTable table )
    {
    if( typeof(TextElement).IsInstanceOfType(next) )
    {
    key = key.TrimStart('#');
    TextElement textElement = (TextElement) next;
    string key = textElement.text;
    if( !string.IsNullOrEmpty(key) && key[0]=='#' )
  25. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Sep 29, 2020. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -17,8 +17,8 @@ public class UIDocumentLocalization : MonoBehaviour
    [SerializeField] LocalizedStringTable _table = null;
    UIDocument _document;

    /// <summary> Executed just after hierarchy got cloned fresh and translated. </summary>
    public event System.Action onBind = ()=>{};
    /// <summary> Executed after hierarchy is cloned fresh and translated. </summary>
    public event System.Action onCompleted = ()=>{};


    void OnEnable ()
    @@ -53,7 +53,7 @@ void OnTableLoaded ( AsyncOperationHandle<StringTable> op )
    var root = _document.rootVisualElement;

    LocalizeChildrenRecursively( root , table );
    onBind();
    onCompleted();

    root.MarkDirtyRepaint();
    }
  26. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Sep 25, 2020. 1 changed file with 17 additions and 9 deletions.
    26 changes: 17 additions & 9 deletions UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -16,6 +16,10 @@ public class UIDocumentLocalization : MonoBehaviour

    [SerializeField] LocalizedStringTable _table = null;
    UIDocument _document;

    /// <summary> Executed just after hierarchy got cloned fresh and translated. </summary>
    public event System.Action onBind = ()=>{};


    void OnEnable ()
    {
    @@ -25,21 +29,14 @@ void OnEnable ()
    _table.TableChanged += OnTableChanged;
    }


    void OnDisable ()
    {
    _table.TableChanged -= OnTableChanged;
    }

    void OnTableLoaded ( AsyncOperationHandle<StringTable> op )
    {
    StringTable table = op.Result;
    var root = _document.rootVisualElement;

    LocalizeChildrenRecursively( root , table );
    root.MarkDirtyRepaint();
    }

    void OnTableChanged ( StringTable value )
    void OnTableChanged ( StringTable table )
    {
    var root = _document.rootVisualElement;
    root.Clear();
    @@ -49,6 +46,17 @@ void OnTableChanged ( StringTable value )
    op.Completed -= OnTableLoaded;
    op.Completed += OnTableLoaded;
    }

    void OnTableLoaded ( AsyncOperationHandle<StringTable> op )
    {
    StringTable table = op.Result;
    var root = _document.rootVisualElement;

    LocalizeChildrenRecursively( root , table );
    onBind();

    root.MarkDirtyRepaint();
    }

    void Localize ( VisualElement next , StringTable table )
    {
  27. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Sep 24, 2020. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,4 @@
    // void* src = https://gist.github.com/andrew-raphael-lukasik/72a4d3d14dd547a1d61ae9dc4c4513da
    using UnityEngine;
    using UnityEngine.UIElements;
    using UnityEngine.Localization;
  28. @andrew-raphael-lukasik andrew-raphael-lukasik revised this gist Sep 24, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -5,7 +5,7 @@
    using UnityEngine.ResourceManagement.AsyncOperations;

    // NOTE: this class assumes that you designate StringTable keys in label fields (as seen in Label, Button, etc)
    // and start them all with '#' char (so undesignated labels will be left be)
    // and start them all with '#' char (so other labels will be left be)
    // example: https://i.imgur.com/h495sju.jpg

    [DisallowMultipleComponent]
  29. @andrew-raphael-lukasik andrew-raphael-lukasik created this gist Sep 24, 2020.
    88 changes: 88 additions & 0 deletions UIDocumentLocalization.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,88 @@
    using UnityEngine;
    using UnityEngine.UIElements;
    using UnityEngine.Localization;
    using UnityEngine.Localization.Tables;
    using UnityEngine.ResourceManagement.AsyncOperations;

    // NOTE: this class assumes that you designate StringTable keys in label fields (as seen in Label, Button, etc)
    // and start them all with '#' char (so undesignated labels will be left be)
    // example: https://i.imgur.com/h495sju.jpg

    [DisallowMultipleComponent]
    [RequireComponent( typeof(UIDocument) )]
    public class UIDocumentLocalization : MonoBehaviour
    {

    [SerializeField] LocalizedStringTable _table = null;
    UIDocument _document;

    void OnEnable ()
    {
    if( _document==null )
    _document = gameObject.GetComponentInParent<UIDocument>( includeInactive:true );

    _table.TableChanged += OnTableChanged;
    }

    void OnDisable ()
    {
    _table.TableChanged -= OnTableChanged;
    }

    void OnTableLoaded ( AsyncOperationHandle<StringTable> op )
    {
    StringTable table = op.Result;
    var root = _document.rootVisualElement;

    LocalizeChildrenRecursively( root , table );
    root.MarkDirtyRepaint();
    }

    void OnTableChanged ( StringTable value )
    {
    var root = _document.rootVisualElement;
    root.Clear();
    _document.visualTreeAsset.CloneTree( root );

    var op = _table.GetTable();
    op.Completed -= OnTableLoaded;
    op.Completed += OnTableLoaded;
    }

    void Localize ( VisualElement next , StringTable table )
    {
    if( typeof(TextElement).IsInstanceOfType(next) )
    {
    TextElement textElement = (TextElement) next;
    string key = textElement.text;
    if( !string.IsNullOrEmpty(key) && key[0]=='#' )
    {
    StringTableEntry entry = table[ key ];
    if( entry!=null )
    textElement.text = entry.LocalizedValue;
    else
    Debug.LogWarning($"No {table.LocaleIdentifier.Code} translation for key: '{key}'");
    }
    }
    }

    void LocalizeChildrenRecursively ( VisualElement element , StringTable table )
    {
    VisualElement.Hierarchy elementHierarchy = element.hierarchy;
    int numChildren = elementHierarchy.childCount;
    for( int i=0 ; i<numChildren ; i++ )
    {
    VisualElement child = elementHierarchy.ElementAt( i );
    Localize( child , table );
    }
    for( int i=0 ; i<numChildren ; i++ )
    {
    VisualElement child = elementHierarchy.ElementAt( i );
    VisualElement.Hierarchy childHierarchy = child.hierarchy;
    int numGrandChildren = childHierarchy.childCount;
    if( numGrandChildren!=0 )
    LocalizeChildrenRecursively( child , table );
    }
    }

    }