Search Unity

Injecting custom IStartupLocaleSelector

Discussion in 'Localization Tools' started by james7132, Nov 5, 2019.

  1. james7132

    james7132

    Joined:
    Mar 6, 2015
    Posts:
    166
    How does one inject a custom IStartupLocaleProvider? I have my own game options implementation and would like to read from it at startup.
     
  2. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,288
    You would inherit from ILocalesProvider and implement the interface, also mark your class Serializable.
    This should work fine in playmode however the editor does not currently support Custom Locale Providers and expects Addressable assets so you won't see your locales in the Editor unless they are also addressable.
    Ill make a note to support them in the editor in the future.

    Heres an example https://github.cds.internal.unity3d.com/gist/karl/c0a4a77c65ae1997f497b027f4810ae8

    Also worth noting that there is a bug with SerializeReference that causes classes that do not have any serializable data to not be deserialized. So if your custom locales provider contains no serializable fields then it will be lost after saving. A workaround is to just add some dummy data, this is what we do now. A fix is one the way in 2019.3.

    Code (csharp):
    1.  // There is a bug with SerializeField that causes empty instances to not deserialize. This is a workaround while we wait for the fix (case 1183543)
    2. [SerializeField, HideInInspector]
    3. int dummyObject;      
     
    Last edited: Nov 5, 2019
  3. james7132

    james7132

    Joined:
    Mar 6, 2015
    Posts:
    166
    Sorry, I think I made a typo. I meant IStartupLocaleSelector. I have a stored reference to a language code in my own game options storage, and I want to use that to select an available locale.

    That said, what's the canonical way to provide a new external provider (say, reading and caching dynamic localization assets via web service)? ILocaleProvider is not asynchronous.
     
  4. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,288
    Oh sorry, I think I misread.
    You would do the same thing really but inherit from IStartupLocaleSelector.
    Unity will detect any classes that implement IStartupLocaleSelector and they will appear in the list when you press the + button. You can then add it and set its priority in the list, top is the highest, and bottom is the lowest.
    For example, the EditorPrefs one does this:

    Code (csharp):
    1.  
    2. using System;
    3.  
    4. namespace UnityEngine.Localization.Settings
    5. {
    6.     [Serializable]
    7.     public class PlayerPrefLocaleSelector : IStartupLocaleSelector, IInitialize
    8.     {
    9.         [SerializeField]
    10.         string m_PlayerPreferenceKey = "selected-locale";
    11.  
    12.         public string PlayerPreferenceKey
    13.         {
    14.             get => m_PlayerPreferenceKey;
    15.             set => m_PlayerPreferenceKey = value;
    16.         }
    17.  
    18.         public void PostInitialization(LocalizationSettings settings)
    19.         {
    20.             if (Application.isPlaying)
    21.             {
    22.                 // Record the new selected locale so it can persist between runs
    23.                 var selectedLocale = settings.GetSelectedLocale();
    24.                 if (selectedLocale != null)
    25.                     PlayerPrefs.SetString(PlayerPreferenceKey, selectedLocale.Identifier.Code);
    26.             }
    27.         }
    28.  
    29.         public Locale GetStartupLocale(ILocalesProvider availableLocales)
    30.         {
    31.             if (PlayerPrefs.HasKey(PlayerPreferenceKey))
    32.             {
    33.                 var code = PlayerPrefs.GetString(PlayerPreferenceKey);
    34.                 if (!string.IsNullOrEmpty(code))
    35.                 {
    36.                     return availableLocales.GetLocale(code);
    37.                 }
    38.             }
    39.  
    40.             // No locale could be found.
    41.             return null;
    42.         }
    43.     }
    44. }
    If you add the IPreloadRequired interface to your ILocalesProvider then it will let you do asynchronous initialization during the LocalizationSettings initialization operation.
     
  5. james7132

    james7132

    Joined:
    Mar 6, 2015
    Posts:
    166
    Excellent. It's amazing to see how thoroughly was package was thought out. Definitely would like to see some of this added to the documentation, since I don't think I'm the only one with workflows like this.
     
  6. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,288
    Thanks :)
    The documentation is quite light at the moment, we will add lots to it before we go out of preview.