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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Text translation

Discussion in 'UI Toolkit' started by Deleted User, Jan 7, 2022.

  1. Deleted User

    Deleted User

    Guest

    Hi,

    I was wondering how text translation works with UI TK.

    Do we have to go through an external tool and then modify each text via code or is there a system provided for this purpose?
     
  2. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    700
    If you want to integrate with UXML then you will need to make a child class but if you are ok with C# then you can use a special function like this:

    Code (CSharp):
    1.     public static void SetLocalizedLabel(this TextField textField, string localeKey)
    2.     {
    3.         var p = localeKey.IndexOf('/');
    4.         var localizedString = new LocalizedString();
    5.  
    6.         if (p > 0 && p != (localeKey.Length - 1) && localeKey.Length > 2)
    7.         {
    8.             localizedString.TableReference = localeKey.Substring(0, p);
    9.             localizedString.TableEntryReference = localeKey.Substring(p + 1);
    10.         }
    11.         var locale = LocalizationSettings.SelectedLocale;
    12.         if (locale != null)
    13.         {
    14.             updateLabel(locale);
    15.         }
    16.  
    17.  
    18.         LocalizationSettings.SelectedLocaleChanged += updateLabel;
    19.  
    20.         void updateLabel(Locale locale)
    21.         {
    22.             if (!localizedString.IsEmpty)
    23.             {
    24.                 var localizedTextHandle = localizedString.GetLocalizedStringAsync(locale);
    25.                 localizedTextHandle.Completed += (handle) =>
    26.                 {
    27.                     textField.label = handle.Result;
    28.                 };
    29.             }
    30.         }
    31.     }
    with:

    Code (CSharp):
    1. myTextField.SetLocalizedLabel("LocalizationTableName/lbKey");
     
    karl_jones likes this.
  3. Deleted User

    Deleted User

    Guest

    Thank you for your answer.

    I don't understand how I can link this code with the UI Toolkit system. Is this valid with any translation system?

    I am using I2 Languages in my project.
     
  4. PaoloAm

    PaoloAm

    Joined:
    Jul 15, 2019
    Posts:
    28
    That could be an extention class you create on your own project, using that approach you will need to set the localized version by code at the start.

    As suggested above by @dlorre but with the added static class:
    Code (CSharp):
    1. public static class TextFieldExtention
    2. {
    3.   public static void SetLocalizedLabel(this TextField textField, string localeKey)
    4.     {
    5.         var p = localeKey.IndexOf('/');
    6.         var localizedString = new LocalizedString();
    7.         if (p > 0 && p != (localeKey.Length - 1) && localeKey.Length > 2)
    8.         {
    9.             localizedString.TableReference = localeKey.Substring(0, p);
    10.             localizedString.TableEntryReference = localeKey.Substring(p + 1);
    11.         }
    12.         var locale = LocalizationSettings.SelectedLocale;
    13.         if (locale != null)
    14.         {
    15.             updateLabel(locale);
    16.         }
    17.         LocalizationSettings.SelectedLocaleChanged += updateLabel;
    18.         void updateLabel(Locale locale)
    19.         {
    20.             if (!localizedString.IsEmpty)
    21.             {
    22.                 var localizedTextHandle = localizedString.GetLocalizedStringAsync(locale);
    23.                 localizedTextHandle.Completed += (handle) =>
    24.                 {
    25.                     textField.label = handle.Result;
    26.                 };
    27.             }
    28.         }
    29.     }
    30. }
    The other solution he mentioned is making a visual element that is a child of TextField that on Start it calls internally the I2 library passing the current text as the translation key.

    I will need to implement the same thing due and I will use a mixed approach, where the text is static I will use the child of the TextField. When instead the text is dynamic I will use the extended method at runtime.

    I hope this clarify a bit :)
     
    Deleted User likes this.
  5. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    700
    It works with the localization package: https://docs.unity3d.com/Packages/com.unity.localization@1.0/manual/index.html

    And yes, @PaoloAm has shown a good way to use it. I have made a LocalizedLabel class but I find the static method more simple.
     
    Deleted User likes this.
  6. PaoloAm

    PaoloAm

    Joined:
    Jul 15, 2019
    Posts:
    28
    @dlorre how do you extend the exposed properties of the parent in the UI Builder? In the builder I can't fill the text of the Label and this would means I need to programmatically do it for static string as well. Thanks!

    Code (CSharp):
    1. public class TranslatedLabel : Label
    2.     {
    3.         #region UXML
    4.         [Preserve]
    5.         public new class UxmlFactory : UxmlFactory<TranslatedLabel, UxmlTraits> { }
    6.  
    7.         [Preserve]
    8.         public new class UxmlTraits : VisualElement.UxmlTraits { }
    9.         #endregion
    10.  
    11.         public TranslatedLabel()
    12.         {
    13.             TranslateContent(base.text);
    14.         }
    15.  
    16.         public TranslatedLabel(string text) : base(text)
    17.         {
    18.             TranslateContent(text);
    19.         }
    20.  
    21.         public void SetText(string newContent)
    22.         {
    23.             TranslateContent(newContent);
    24.         }
    25.  
    26.         private void TranslateContent(string newContent)
    27.         {
    28.             if (!string.IsNullOrEmpty(newContent))
    29.             {
    30.                 base.text = LocalisationUtils.GetLocalization(newContent);
    31.             }
    32.         }
    33.     }
    EDIT:
    One solution I have found is to take the traits directly from the parent element but this prevent me for creating child properties (not that I need them at the moment but it's a good to know)
    Code (CSharp):
    1. public new class UxmlFactory : UxmlFactory<TranslatedLabel, Label.UxmlTraits> { }
    If I try to extend it in the UxmlTraits class directly they don't get displayed sadly
     
    Last edited: Jan 11, 2022
  7. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    700
    I did not make it inherit from Label but I rather copied the source of Label and then made the changes:

    Code (CSharp):
    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Text;
    5. using System.Threading.Tasks;
    6. using UnityEngine;
    7. using UnityEngine.Localization;
    8. using UnityEngine.Localization.Settings;
    9. using UnityEngine.Localization.Tables;
    10. using UnityEngine.UIElements;
    11.  
    12. namespace UnityEngine.UIElements
    13. {
    14.     class LocalizedLabel : TextElement
    15.     {
    16.         public new class UxmlFactory : UxmlFactory<LocalizedLabel, UxmlTraits> { }
    17.  
    18.         public new class UxmlTraits : TextElement.UxmlTraits
    19.         {
    20.             UxmlStringAttributeDescription m_LocaleKey = new UxmlStringAttributeDescription { name = "locale-key" };
    21.  
    22.             public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription
    23.             {
    24.                 get { yield break; }
    25.             }
    26.  
    27.             public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
    28.             {
    29.  
    30.                 base.Init(ve, bag, cc);
    31.                 var ll = ve as LocalizedLabel;
    32.                 ll.localeKey = m_LocaleKey.GetValueFromBag(bag, cc);
    33.                 ll.initLabel();
    34.             }
    35.         }
    36.         public string localeKey { get; set; }
    37.         private LocalizedString localizedString;
    38.  
    39.         public new static readonly string ussClassName = "localized-label";
    40.  
    41.         public LocalizedLabel() : this(String.Empty) { }
    42.  
    43.         public LocalizedLabel(string localeKey)
    44.         {
    45.             AddToClassList(ussClassName);
    46.             this.localeKey = localeKey;
    47.         }
    48.  
    49.         private void updateLabel(Locale locale)
    50.         {
    51.             if (!localizedString.IsEmpty)
    52.             {
    53.                 var localizedTextHandle = localizedString.GetLocalizedStringAsync(locale);
    54.                 localizedTextHandle.Completed += (handle) =>
    55.                 {
    56.                     text = handle.Result;
    57.                 };
    58.             }
    59.         }
    60.  
    61.         private void initLabel()
    62.         {
    63.             var p = localeKey.IndexOf('/');
    64.             localizedString = new LocalizedString();
    65.  
    66.             if (p > 0 && p != (localeKey.Length - 1) && localeKey.Length > 2)
    67.             {
    68.                 localizedString = new LocalizedString();
    69.                 localizedString.TableReference = localeKey.Substring(0, p);
    70.                 localizedString.TableEntryReference = localeKey.Substring(p + 1);
    71.             }
    72.             var locale = LocalizationSettings.SelectedLocale;
    73.             if (locale != null)
    74.             {
    75.                 updateLabel(locale);
    76.             }
    77.             LocalizationSettings.SelectedLocaleChanged += updateLabel;
    78.         }
    79.  
    80.  
    81.     }
    82. }
    83.  
     
  8. PaoloAm

    PaoloAm

    Joined:
    Jul 15, 2019
    Posts:
    28
    Thanks for the tip, it solve my issue I was having that they was changed everytime even when not running.

    So what I did is update your version to use the library I am using (I2).

    Here the working code, it can be used when you have a static string you don't change, otherwise just use a normal label and change it programmatically

    Code (CSharp):
    1. using System;
    2. using System.Collections.Generic;
    3. using I2.Loc;
    4. using UnityEngine.UIElements;
    5.  
    6. namespace ui.Generics
    7. {
    8.     class LocalizedLabel : Label
    9.     {
    10.         public new class UxmlFactory : UxmlFactory<LocalizedLabel, UxmlTraits> { }
    11.  
    12.         public new class UxmlTraits : Label.UxmlTraits
    13.         {
    14.             UxmlStringAttributeDescription _mLocaleKey = new UxmlStringAttributeDescription { name = "locale-key" };
    15.  
    16.             public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription
    17.             {
    18.                 get { yield break; }
    19.             }
    20.  
    21.             public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
    22.             {
    23.                 base.Init(ve, bag, cc);
    24.                 var ll = ve as LocalizedLabel;
    25.                 ll.LocaleKey = _mLocaleKey.GetValueFromBag(bag, cc);
    26.                 ll.InitLabel();
    27.             }
    28.         }
    29.  
    30.         public string LocaleKey { get; set; }
    31.  
    32.         private new static readonly string ussClassName = "localized-label";
    33.  
    34.         public LocalizedLabel() : this(String.Empty) { }
    35.  
    36.         public LocalizedLabel(string localeKey)
    37.         {
    38.             AddToClassList(ussClassName);
    39.             this.LocaleKey = localeKey;
    40.         }
    41.  
    42.         private void UpdateLabel()
    43.         {
    44.             if (!string.IsNullOrEmpty(LocaleKey))
    45.             {
    46.                 base.text = LocalizationManager.GetTranslation(LocaleKey);
    47.             }
    48.         }
    49.  
    50.         private void InitLabel()
    51.         {
    52.             if (!string.IsNullOrEmpty(LocaleKey))
    53.             {
    54.                 UpdateLabel();
    55.             }
    56.             LocalizationManager.OnLocalizeEvent += UpdateLabel;
    57.         }
    58.     }
    59. }
     
  9. Deleted User

    Deleted User

    Guest

    Thank you for your answers ! This will help me with my issue too!
     
    PaoloAm likes this.