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. Dismiss Notice

Localisation for Input Keys

Discussion in 'Input System' started by RedHillbilly, Apr 28, 2022.

  1. RedHillbilly

    RedHillbilly

    Joined:
    Mar 24, 2014
    Posts:
    38
    I've been using the new input system's automatic human readable string
    InputControlPath.ToHumanReadableString
    .
    Really love the idea and it works super well with rebinding, thanks a lot!

    The one issue I'm having is that these are not localized. 'Space' is 'Espace' in french for instance.

    Is there already a solution present to localize this? I have not found one. It seems like something that the community could be working on together if not, as all devs wanting to use this will face the same issue.

    I've taken the liberty to start a project on GitHub if anybody wants to contribute:
    https://github.com/GieziJo/UnityInputSystemLocalisation

    Happy to scrap it if something better already exists, just didn't find anything :D
     
    karl_jones likes this.
  2. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    7,846
    I did some prototyping on how we could handle Input some time ago.
    It's still on the plan to look into this more but I cant say when we will get to it, its quite low down the list.

    This is what I had, I was planning to make a global variable so users could type {input.action-name}.


    Code (csharp):
    1. #if PACKAGE_INPUT
    2. using UnityEngine.InputSystem;
    3.  
    4. // TODO: Support localizing the input names, e.g "Right Trigger". Maybe hook into an optional StringTableCollection which would need to be preloaded.
    5.  
    6. namespace UnityEngine.Localization.SmartFormat.GlobalVariables
    7. {
    8.     struct InputActionVariable : IGlobalVariable
    9.     {
    10.         InputAction m_Action;
    11.  
    12.         public object SourceValue => this;
    13.  
    14.         public InputActionVariable(InputAction action) => m_Action = action;
    15.  
    16.         public override string ToString() => m_Action.GetBindingDisplayString();
    17.     }
    18.  
    19.     [CreateAssetMenu(menuName = "Localization/Global Variables/Input System Mapping Group")]
    20.     public class InputSystemMappingGroup : GlobalVariablesGroupAsset
    21.     {
    22.         [SerializeField]
    23.         InputActionAsset m_ActionsAsset;
    24.  
    25.         public override IGlobalVariable this[string key]
    26.         {
    27.             get
    28.             {
    29.                 var action = m_ActionsAsset.FindAction(key);
    30.                 if (action != null)
    31.                     return new InputActionVariable(action);
    32.                 return null;
    33.             }
    34.         }
    35.  
    36.         public override bool TryGetValue(string key, out IGlobalVariable value)
    37.         {
    38.             var action = m_ActionsAsset.FindAction(key);
    39.             if (action != null)
    40.             {
    41.                 value = new InputActionVariable(action);
    42.                 return true;
    43.             }
    44.  
    45.             value = default;
    46.             return false;
    47.         }
    48.     }
    49. }
    50. #endif
    This doesn't localize the actual values, just extracts them. The next step would be to do what you are doing.
     
    RedHillbilly likes this.
  3. RedHillbilly

    RedHillbilly

    Joined:
    Mar 24, 2014
    Posts:
    38
    Oh that looks cool!
    So if I understand correctly this would map the defined input actions to the strings. But would this work for rebinding of input keys for multiplayer? For that one you need the
    PlayerInput
    specific Input binding as far as I understand, right?

    For the problem of specifically translating keys to other languages I don't suppose there are any plans yet?

    Thanks a lot for your inputs!
     
  4. noio

    noio

    Joined:
    Dec 17, 2013
    Posts:
    224
    Regarding your remark:

    Would that be easier now with Nested Translations?
     
  5. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    7,846
    I'm not sure it would work with nested translations. You still need to extract the Bindings Display String from the action, once that's done then you may as well just call LocalizationSettings.StringDatabase.GetLocalizedString. Im not sure how it could work as a nested translation unless you were to update the nested translation persistent variable instead.
    E.G have a LocalizedString with:

    English -> "Press {action-name} to Jump"
    action-name is a local LocalizedString
    https://docs.unity3d.com/Packages/c...manual/Smart/Persistent-Variables-Source.html

    You change the value of action-name in script:

    Code (csharp):
    1. public LocalizedString myString = new LocalizedString("My String Table", "My Game Text")
    2. {
    3.     // These variables will be visible in the inspector Local Variables field.
    4.     { "action-name", new LocalizedString() },
    5. };
    6.  
    7. void UpdateText(string action)
    8. {
    9.     var action = m_ActionsAsset.FindAction(action);
    10.     var key = action.GetBindingDisplayString();
    11.  
    12.     var nested = myString["action-name"] as LocalizedString;
    13.     nested.SetReference("My Table", key);
    14. }
    You would have entries in the table such as

    Key: Right Trigger
    English: Right Trigger
    etc

    That should work. You still need a script to do the conversion from InputSystem action though.
    You could try returning a LocalizedString in TryGetValue instead. You would need to call GetSourceValue on the localizedString and return that result.
     
    noio likes this.
  6. noio

    noio

    Joined:
    Dec 17, 2013
    Posts:
    224
    Gotcha!


    I've made some headway with this, but currently I'm stuck on how to hook up the
    IVariableValueChanged.ValueChanged
    event. I am detecting when the input device changes and firing the event on my
    IVariable
    s, but it seems that with a custom
    ISource
    , that event is not subscribed to by default. Even though I'm adding the
    IVariable
    to the
    FormatCache.VariableTriggers
    . I guess I don't understand the localization framework good enough to know how my code ties into
    LocalizedString.UpdateVariableListeners


    Here's a gist with the essential files (essentially an elaboration of the code you posted above)

    https://gist.github.com/noio/5209550ebcb049da763f521027ec50f5


    [EDIT: I'm realizing that this is still on the 'Input System' forum, and this is squarely a Localization System question, I'll post over there: https://forum.unity.com/threads/using-valuechanged-event-with-custom-isource.1332495/]
     
    Last edited: Sep 6, 2022