Search Unity

Localization tooling - getting locale in editor

Discussion in 'Localization Tools' started by Exentro, Mar 23, 2020.

  1. Exentro

    Exentro

    Joined:
    Oct 8, 2013
    Posts:
    36
    Hello,
    Currently I am trying to create some tool on top of the localization package.
    For that, I am writing my own localization manager, but I am struggling to have a selected locale within the LocalizationSettings instance in editor mode, wich I need for editing and creating localized tables.

    None of the following callbacks seems to be triggered :/
    Is there a way to force the LocalProvider to preload in editor mode ?
    Code (CSharp):
    1. LocalizationSettings.Instance.OnSelectedLocaleChanged += OnLocalizationLocaleChange;
    2. LocalizationSettings.Instance.GetInitializationOperation().Completed += OnLocalizationSettingsInit;
    3. LocalizationSettings.InitializationOperation.Completed += OnLocalizationSettingsInit;
    4.  
    5. LocalesProvider provider = (LocalesProvider)LocalizationSettings.Instance.GetAvailableLocales();
    6. provider.PreloadOperation.Completed += OnLocalesProviderPreload;
    Event that don't seems to trigger the LocalizationSettings.Instance.OnSelectedLocaleChanged callback
    Code (CSharp):
    1. LocalizationSettings.Instance.SetSelectedLocale(LocalizationSettings.AvailableLocales.GetLocale(SystemLanguage.French));
     
  2. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    Hi,
    The concept of a selected locale does not really exist in edit mode at the moment. We do have an editor API under UnityEditor.Localization.LocalizationEditorSettings. If you are doing any editor work then this is likely whatr you need.

    For example UnityEditor.Localization.LocalizationEditorSettings.GetLocales() will return all the Locales in the project.
     
  3. Exentro

    Exentro

    Joined:
    Oct 8, 2013
    Posts:
    36
    Thanks karl_jones, I will take a look on that.

    I assume the package workflow is supposed to be like:
    1. create the collections and tables using the editor interface
    2. add the localize components and bind them to the collections
    3. at runtime, the locale will load at start, wich will update all the localize components, wich will update theirs respective targets (UI.Text, TextMeshPro, Image, ...)

    I actually feel a bit wrong, localization is not something we do while setting up the scenes, but afterwards. Our artists will setup the UI and fill the text and images for their own language and are not supposed to care about localization at that point.
    My objectives about my tool is :
    1. a localization element I can add later, that element may not be a component since I would not only need it in GameObject, but also within ScriptableObject or EditorWindow (Actually I am embedding in a propertyDrawer).
    2. I want the database to be generated from what the artists made
    3. be able to visualize any screen for any locale in editor mode and not only at runtime. It means a shortcut to change the application locale and updating the UI elements when a new locale is setted (but as I said, the API is mainly about runtime)
    4. the localization element have to works both in editor and runtime
    5. possibility to export/import all strings as/from csv
    6. a not-too-ugly editor layout (I am using Odin)
    By the way, I now have regularly GameObjects "EventCollector" and "ResourceManagerCallbacks" spawning in my scene hierachy (attached file). It seems to be related to the adressables, and since the Localization package is the only one using it, can I assume it come from the Localization package (or some issue between the package and Odin) ?
     

    Attached Files:

  4. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    Yes, thats the general workflow at the moment.

    Localization does not require components. We have LocalizedString, LocalizedTexture etc which are classes that can be used anywhere. Are you just localizing something for the player or also editor tools? Editor tools localization is supported but its not part of the localization package, its an editor feature.

    At the moment we have the `Localize` option for UI, TMP etc. This currently adds a component and maps it to a string that matches the original text. In the future, we will improve this so that if the string does not exist it will add it to the database. We will also be adding a specialized version of UI and TMP instead of an additional component. The workflow would then be to swap the UI/TMP component with a localized version, find or add the original string in the db and map it across. Then this could be automated so that a scene could be automatically localized and the assets in the scene extracted, in the way you describe.

    This is planned as part of the localized components(UI, TMP & UIElements) work.
    At the moment we are working on import and export for google sheets and a few other formats. csv will be one although we may not be able to support metadata for all formats, some may have to just be key and values.
    Yes this is addressables. Addressables does support loading in editor however this looks like a bug. Could you please file a bug report?

    Localization is still very much in development, there are gaps in the API and workflows. We are still in a position where we can make big changes so if you have feedback or suggestions we are open to them. It always helps to have a use case or solid example of what you need and why.
    Thanks for the feedback so far.
     
  5. Exentro

    Exentro

    Joined:
    Oct 8, 2013
    Posts:
    36
    Actually the project I am working for is a template to create projects faster. Projects are touristic mobile applications with some gamification elements (like geolocated points on a map, points are mini games with an inventory shared to those points).
    I am currently working on the localization and inventory tools (which rely on the localization).

    I do have a very basic InventoryItem ScriptableObject class wich holds 2 strings (name and description) and an image. I did achieve to localize it but by referencing 2 LocalizedString and one LocalizedSprite. But those implementations do not allow a designer to edit them directly, he would have to open the Localization Table Editor Windows and I want to avoid that (as said in my previous post, he should not care about localization at that point).
    That said, I will probably wreate an EditorWindow to handle my Inventory, but I still think designer will always be tempted to edit the ScriptableObject asset directly.

    As reference, here is where I am (attached file)
    "Application Current Locale" is the shorcut to change the application Locale, with the idea changing that will update the whole application as reaction.
    "Update when locale change" is a way to disable the locale update on for the element listed below.
    The "Update Database" button will override the strings for the binds listed below for their corrsponding TextMeshPro element.
    The "Read from Database" button will override the textmesh pro texts with the values from the database.
    "TextMeshPro Fields" is a list of TextMeshProUGUI references associated with a Bind.
    The Bind is actually similar to the Localization package LocalizeString, it is populated with the current tables and key in the Localization database. You can edit the path (format is tablename/key), if it does not exists in the database, the "+" button will allows to add it directly.
    I plan to add more type list (direct string, images, etc..) and an event on the class invoked when all elements references are updated(*)

    (*) In the current package implementation, the update is per-element based, but imo its actually rarely the case in real world scenario, you want to update the UI or objects only when every backing fields are ready and have a single method to update everythings. This is the idea I followed here.
     

    Attached Files:

  6. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    We do allow for editing them directly. We have custom property drawers for strings and assets

    Property Editor for LocalizedString:


    I have to run so ill finish reading your post later....
     
  7. Exentro

    Exentro

    Joined:
    Oct 8, 2013
    Posts:
    36
    I realized I am heavily relying on the
    AssetTableCollection
    definition without noticing it, which is actually part of the
    UnityEditor.Localization
    namespace , meaning I can't do that way at runtime.

    For the runtime, are the
    GetLocalizedStringAsync
    from the
    LocalizedStringDatabase
    and
    LocalizedString
    GetLocalizedString()
    method the only ways to fetch localized string ?

    Since it can only be used with
    TableReference
    and
    TableEntryReference
    or
    LocalizedString
    definitions so it is very limitating/locked for custom code.

    Could you simply provide overloads using simple strings for the table and the key for runtime context ?
     
  8. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    Can you give me an example of what you mean?
     
  9. Exentro

    Exentro

    Joined:
    Oct 8, 2013
    Posts:
    36
    Instead of having to use

    Code (CSharp):
    1. LocalizedString myLocalizedString;
    2. LocalizedStringDatabase stringDatabase = LocalizationSettings.Instance.GetStringDatabase();
    3.  
    4. TableReference table = myLocalizedString.TableReference;
    5. TableEntryReference entry = myLocalizedString.TableEntryReference;
    6.  
    7. stringDatabase.GetLocalizedStringAsync(table, entry).Completed += (AsyncOperationHandle<string> op) =>
    8. {
    9.   string localizedStringResult = op.Result;
    10. };
    ... being able to query with string like
    Code (CSharp):
    1. LocalizedStringDatabase stringDatabase = LocalizationSettings.Instance.GetStringDatabase();
    2.  
    3. string table = "myTable";
    4. string entry = "myKey";
    5.  
    6. stringDatabase.GetLocalizedStringAsync(table, entry).Completed += (AsyncOperationHandle<string> op) =>
    7. {
    8.   string localizedStringResult = op.Result;
    9. };
     
  10. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    Have you tried? This should already work as we have implicit conversions.
    TableReference can be a string or Guid and TableEntryReference string or uint.

    e.g
    Code (csharp):
    1. TableReference table = "myTable";
    2. TableEntryReference entry = "myKey";
     
  11. Exentro

    Exentro

    Joined:
    Oct 8, 2013
    Posts:
    36
    Actually... no. :oops:
    I saw theirs interface definition but assumed it had to be fully initialized to be used. The idea of creating an instance and just fill them like that didn't even crossed my mind to be honest (and if it did, I probably wouldn't even try assuming it would not be sufficient). I will try that. Thanks!

    By the way, did you finished reading my yesterday post ?
     
  12. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    Yes I read through it :)
    The window to show the bindings is an interesting concept. I have some ideas I want to try out similar to this. An overview window to show all bindings in a scene. I think I understand what you are doing, would you be able to share an example when you have something? I find it much easier to understand when I play about with an example.
    We are currently working on improving the editor side, converting AssetTableCollections into Editor only assets which should make things a little simpler. There are plans for editor support to change selected locale etc but that will come after the next release.
     
  13. Exentro

    Exentro

    Joined:
    Oct 8, 2013
    Posts:
    36
    Still messing a bit around the API.

    I have a LocalizedString set up in the editor and referencing an entry in an actual localized table, but those lines
    Code (CSharp):
    1. string tableName = _stringReference.TableReference.TableName;
    2. string key = _stringReference.TableEntryReference.Key;
    actually holds "GUID:bed3f1bfcb3f9fe459a58df7c1ff935e" and an empty string as values. The keyid and Gui holds the expected values.
    Is it the expected behavior ?
     

    Attached Files:

  14. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    Yes. You can reference a table by either its string name or its name guid and a table entry with its key name or key id. This can be determined by the ReferenceType property.
    We favour Guid and id by default as this means changes to the table name or key name will still allow us to keep the mapping(Guid and Id should never change).
    So by far the safest option is to use Guid and Id however if you dont expect to make changes to table names or key names then using strings is fine.

    For example, if you had a table named "My_Game_Assets" and you then later decide to rename this table to "Level_1_Assets" then you would need to go back into all the scenes that referenced the "My_Game_Assets" table via a string and update them to reference the "Level_1_Assets" table. However, if they referenced the table with a Guid then you would not need to change anything after the table name.

    If you are familiar with our assembly definition assets (asmdefs) then its a similiar concept. They do give you an option to use guid or string, maybe we can do the same.

    Edit:
    Showing TableName as GUID is a bug, it should be empty (""). Ill make a bug for it.
     
    Last edited: Mar 24, 2020
  15. Exentro

    Exentro

    Joined:
    Oct 8, 2013
    Posts:
    36
    The point was more I was expecting TableName to be "TestStringTable" and Key to be "Country" as the LocalizedString appears as "TestStringTable/Country" in the inspector. The field do access these info since they are displayed in the editor when expanding the LocalizedString property ("Table Collection" and "Entry Name"). Are
    TableEntryReference.Key;
    and the entry name supposed to be 2 differents things ?

    I understand the GUID and the entry keyid are more reliable, but the natural language string values could be accessible for convenience (and debug!) and filled once the bind is done.
     
  16. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    Yes being able to see the string values would be good for debugging. I'll look into how we can support this. Showing a table name from guid should be simple although showing a entry name is a little trickier as we don't have the table it belongs to in the struct.
     
    Last edited: Mar 24, 2020
  17. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    No they are the same.
     
  18. Exentro

    Exentro

    Joined:
    Oct 8, 2013
    Posts:
    36
    ow I am supposed to read/write the database in editor mode without tableName and entryKey as strings ?
    I didn't find relevant methods in
    LocalizationEditorSettings
    and I tried

    Code (CSharp):
    1. public static void GetLocalizedText(TableReference table_reference, TableEntryReference entry_reference, Action<string> callback)
    2. {
    3. LocalizationSettings.Instance.GetStringDatabase().GetLocalizedStringAsync(table_reference, entry_reference, ActiveLocale).Completed +=
    4.   (AsyncOperationHandle<string> op) =>
    5.   {
    6.     callback.Invoke(op.Result);
    7.   };
    8. }
    9.  
    10. public static void SetLocalizedText(TableReference table_reference, TableEntryReference entry_reference, string text)
    11. {
    12.   LocalizationSettings.Instance.GetStringDatabase().GetTableEntryAsync(table_reference, entry_reference, ActiveLocale).Completed +=
    13.   (AsyncOperationHandle < LocalizedDatabase<StringTable, StringTableEntry>.TableEntryResult > op) =>
    14.   {
    15.     op.Result.Entry.Value = text;
    16.   };
    17. }
    18.  
    But the Completed delegate are never invoked.


    The issue disapeared at some point and came back now. They were popping after Unity recompile and I opened my localization property in the inspector. Now this is when I click on a button.
    I modified theirs scripts to make them run in editor with
    [ExecuteInEditMode]
    to get a call stack log:

    EventCollector:
    Code (CSharp):
    1.  
    ResourceManagerCallbacks
    Code (CSharp):
    1. InvalidOperationException: The following game object is invoking the DontDestroyOnLoad method: ResourceManagerCallbacks. Notice that DontDestroyOnLoad can only be used in play mode and, as such, cannot be part of an editor script.
    2. MonoBehaviourCallbackHooks.Awake () (at Library/PackageCache/com.unity.addressables@1.5.1/Runtime/ResourceManager/Util/MonoBehaviourCallbackHooks.cs:13)
    3. UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:<.ctor>b__27_0(AsyncOperationHandle)
    4. DelegateList`1:Invoke(AsyncOperationHandle) (at Library/PackageCache/com.unity.addressables@1.5.1/Runtime/ResourceManager/Util/DelegateList.cs:69)
    5. UnityEngine.AddressableAssets.ResourceProviders.InternalOp:OnCatalogLoaded(AsyncOperationHandle`1)
    6. DelegateList`1:Invoke(AsyncOperationHandle`1) (at Library/PackageCache/com.unity.addressables@1.5.1/Runtime/ResourceManager/Util/DelegateList.cs:69)
    7. UnityEngine.AsyncOperation:InvokeCompletionEvent()
     
  19. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    I
    I have not tested the localization loading side in editor mode, I suspect we may have some guards that prevent it.

    Could you please file a bug report for the ResourceManagerCallbacks error, that will need to go to a different team.

    So if this is an editor script I would suggest avoiding the Async methods and use the Editor code. It should be much simpler and won't need to be async.

    Here is a simple example
    Code (csharp):
    1. // This will get us all table collections that are StringTables.
    2. var tableCollections = LocalizationEditorSettings.GetAssetTablesCollection<StringTable>();
    3. // Now lets find the one we care about
    4. var foundTableCollection = tableCollections.First(col => col.TableName == "My Table");
    5. // Now lets get the table for English. Calling Tables will force all the table assets to be loaded so there may be a small pause here.
    6. var englishTable = foundTableCollection.Tables.First(tbl => tbl.LocaleIdentifier == "en") as StringTable;
    7.  
    8. // We need to mark the table dirty so changes are saved. If a new key is created then the shared datas will also need to be dirty.
    9. Undo.RecordObjects(new Object[] { englishTable.SharedData, englishTable }, "Added entry");
    10.  
    11. // Now we can get or set the value
    12. var entry = englishTable.GetEntry("My Table Entry");
    13. entry.Value = "Some New Value";
    14.  
    15. // Or do it like this which will also create the entry if it does not exist
    16. englishTable.AddEntry("My Table Entry", "Some New Value");
    The editor code is going through some refactoring at the moment, it needs some improvements and may change a little but this should get you what you need. Feedback is welcome :)
     
    Last edited: Mar 25, 2020
    marudice likes this.
  20. Exentro

    Exentro

    Joined:
    Oct 8, 2013
    Posts:
    36
    Sounds like you skipped the first line of my previous post :p
    This was more or less what I was doing (but without linq nor Undo handling) but the point was I don't have the TableName and the KeyName as strings, only the guid and the entryid. Wich is frustrating since they appears in the inspector, so they are resolved somehow at somepoint.
    I can't find a guid value in LocalizedTable or a way to get a LocalizedTable from an AssetTableCollection using a guid.
    I am not familiar with the addressable API, but I guess I should not retrieve the LocalizedTable from it directly anyway.

    Not sure there is any guard to prevent loading that way (or warnings/errors should be raised), AsyncOperation probably relies on Coroutines, which relies themselves on MonoBehavior update loops, since they are not called in Editor, they can't reach their completion point.
     
  21. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    Ohhh yes sorry. Ok this is fine.
    So to get a table name from a guid you can do one of 2 things.
    Code (csharp):
    1.  
    2. // Option 1, the guid is the guid of the asset so load the asset
    3. var guidString = myTableReference.TableNameGuid.ToString("N"); // This gives us it in the Unity required format
    4. var assetPath = AssetDatabase.GUIDToAssetPath(guidString);
    5. var sharedData = AssetDatabase.LoadAssetAtPath<SharedTableData>(assetPath);
    6. Debug.Log("Table name is " + sharedData.TableName);
    7.  
    8. // Option 2. Compare the guid instead of name
    9. var tableCollections = LocalizationEditorSettings.GetAssetTablesCollection<StringTable>();
    10. var foundTableCollection = tableCollections.First(col => col.SharedData.TableNameGuid == myTableReference.TableNameGuid);
     
    Exentro likes this.
  22. Exentro

    Exentro

    Joined:
    Oct 8, 2013
    Posts:
    36
    Thanks again karl_jones, I feel like I am close to achieve my goal (at least for the TextMeshPro references, I will continue with images and raw strings)

    At some point, I will try to isolate the localization code into a different repository, at least to submit the addressable bug (ResourceManagerCallbacks and EventCollector gameobjects) and to export the solution to a production repository (the one I am working on is a prototype/proff of concept one with messy stuff other than localization), would you be able to fetch it from the bug submission ?


    Also, I just noticed that
    LocalizationEditorSettings.ActiveLocalizationSettings.SetSelectedLocale(value);
    don't seems to raise the
    LocalizationEditorSettings.ActiveLocalizationSettings.OnSelectedLocaleChanged
    event in editor mode.
     
  23. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    Thanks. Yes I can get it from a bug report, just post the bug I'd when you submit.

    I don't think we fire events in edit mode. Once we add proper edit mode support then we will. :)
    Thanks for all the feedback so far, it's very helpful to see how people are using the system.
     
  24. Exentro

    Exentro

    Joined:
    Oct 8, 2013
    Posts:
    36
    I am more or less satisfied about strings, now I am trying the same with Texture for RawImages.

    And I am stuck :/
    The only way I can find are asyncronous and don't run in editor mode.
    Can you give me any clue how how I can achieve that ?

    I am to that point :
    • For getting a texture from the database, I can get the right LocalizedTable (then cast it as AssetTable)
      Code (CSharp):
      1.  AssetTable.GetAssetAsync<Texture>(key_id).Completed += (AsyncOperationHandle<Texture> op) =>
      2. {
      3.   Texture result = op.Result;
      4. };
    • For setting a texture to the database, I do have the right LocalizedTable/AssetTable as well, and the corresponding AssetTableEntry. Then I don't know how I can use it, by using the guid to override the existing texture maybe, but how ?
     
  25. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    To find out what asset is assigned you would do something similar to strings.
    Code (csharp):
    1. // To get the asset you can do what you did with String tables, this will give you the asset GUID.
    2. var entry = assetTable.GetEntry("my entry");
    3. //entry.Guid - This is the asset guid. You can load it from the asset database like normal
    To change the value is a little different because when you change the asset that is assigned to a table entry we also need to ensure that it is added to addressables, the correct assressable group, has the correct labels and metadata etc.
    So we have an interface to add and remove:

    LocalizationEditorSettings.AddAssetToTable
    LocalizationEditorSettings.RemoveAssetFromTable
     
    Exentro likes this.
  26. Exentro

    Exentro

    Joined:
    Oct 8, 2013
    Posts:
    36
    Thanks! Pretty sure I wouldn't figure this out.
    Actually I have my own manager to handle higher level calls that use one method or another according the context (runtime or editor). Public methods are

    Code (CSharp):
    1. public static string GetLocalizedText(Guid table_guid, uint key_id, Locale locale = null)
    2.  
    3. public static void SetLocalizedText(Guid table_guid, uint key_id, string text, Locale locale = null)
    4.  
    5. public static void SetLocalizedTexture(Guid table_guid, uint key_id, Texture texture, Locale locale = null)
    6.  
    7. public static Texture GetLocalizedTexture(Guid table_guid, uint key_id, Locale locale = null)
    Maybe it could be less confusing to have something similar in the localization package api.

    It works so far for TextMeshPro texts and RawImage textures, but after some cleaning and refactoring, I want to add some security checks.

    Can I check if the asset is the same as the one in the table ? (to not replace an asset by himself)
    Can I know somehow if the asset is actually referenced somewhere else ? (to not remove the entry if its the case, especially if I can't update the content but have to delete and create)
     
  27. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    AddAssetToTable and RemoveAssetFromTable will check if the asset is used in other tables/collections. We don't have an API to get this information at the moment, ill look to add one for the future. If an asset is used by multiple locales then it goes into a Shared Addressables group, otherwise, it goes into a per locale group.

    Im not sure what you mean by this. To check if the asset is already assigned to a field? You could just check the 2 guids.
    We do have stuff to do this internally but its not public at the moment.
     
  28. Exentro

    Exentro

    Joined:
    Oct 8, 2013
    Posts:
    36
    For the first, I was not talking about being used by multiple locale. Actually I am managing list of element (so far a list of TextMesh, and a list of RawImage) and have editor buttons to save/load. When saving, I am iterating over all listed RawImage and set their texture for the current locale, but ending setting a texture the same as already in the table (since it didn't actually changed). I was wondering if I could prevent that.

    For the second, a single texture can be used by multiple UI component in multiple scene. Since I update all texture when pressing my button, I need to prevent deletion of a texture used in another UI element, since it could be in another scene, I can't scan all references to see if any guid match. I think I saw the addressable are loaded when needed and they keep a reference count to prevent unloading the asset when released but still in use somewhere else (the counter is just decreased). I am actualling looking for something similar in the Localization, a way to now from the database how many references is using that specific entry.

    Also I submitted the project for the GameObjects spawn bug (Case 1230916) if you want test my wip localization tool :D
     
  29. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    Im not sure I fully understand. You have a RawImage with a reference to TextureA, you then switch locale and it also references TextureA so don't want to update it? Its not really something we check for in the player although we would just pull a reference to the same asset(we wont load it again).

    Is this in Editor or play mode? In play mode we would just work the same way as Addressables. We won't load the asset until you ask for it(unless using preload). We do hold onto a reference once its been loaded, we could look at changing this to something like a WeakReference if its an issue. We dont have any way to know how many references there are to a particular asset in editor. We can figure out how many table entries reference the same asset although its a little brute force at the moment(hopefully we can improve it in the future). Its hard to know if an asset is referenced by other scenes, even if it was just a normal RawImage without localization. To do something like this would require loading each scene and checking them. This could be done as some sort of build step or report generator(possibly something we do in the future to generate a localization report). For your editor, in theory you could use a editor only Metadata for an entry to keep track of where it is referenced. It would just require making sure it stays in sync.

    Thanks ill take a look, hopefully, ill understand what you are doing a bit better :)
     
  30. Exentro

    Exentro

    Joined:
    Oct 8, 2013
    Posts:
    36
    Editor mode, changing the localization table in runtime would be as tricky as hacky :D

    This is why I am hoping having something like that in the package instead of a custom solution ;)
    I was more thinking about adding a readable link based on guid in the serialization so the count could be done by reading the scenes serialization using regex (at startup and/or based on some actions for example). Something like that. I might actually possible right now since the package Localized fields uses guid, but didn't look in the scene serialization yet.

    To explain the questions with an example:
    • I do have an asset table with on key : flag and 2 locale : french and english. The assets are texture of their respective flag.
    • I am keeping a list of RawImageReference, wich consist of a RawImage reference, and and LocalizedSprite.
    The first question was
    • At start, and when the Locale change, the LocalizedSprite will load the sprite referenced by its table/key reference, and update its associated RawImage texture.
    • When I press a Save button, I iterate over that list and ask the LocalizedSprite to save the current texture in use by the associated RawImage.
    • The things is, if I never change the LocalizedSprite table reference since it loaded, I will override the texture in the Localization table with the exact same thing (since this is where it came from at first).
    • Is there a way to detect they are the same texture ?
    The second question was
    • If I change the french flag with another, lets say the US flag.
    • I press Save again
    • Maybe I do have other UI element that use the french flag and for those cases I don't want them to show the US flag.
    • To avoid breaking something else, I want to detect that and prevent it, then send a message to the user
    • Is there a way to know how many element are using my french flag (and maybe which ones) ?
    Thanks again for your numerous replies!
     
  31. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    You mean reading the raw scene yaml files? This could work however it would fail if binary serialization was being used.

    Can you detect if the asset is dirty? That would indicate something has changed.

    Hmm. Some generally the idea would be for them to use different keys however I can see how this would be an issue if you want them to all share the same key but also ensure that a change does not break other scenes. Essentially changing the source asset but wanting to make sure that anything else that references it, does not need the original. At the moment Localization is all about the tables, with an intentional divide between whats actually using them. I cant see a simple solution to this issue, in a way it also exists with normal assets. The only safe solution I can really think of is to brute force check by loading the scenes, prefabs and any related assets but this could become a significant performance issue in large projects. We could try to generate some type of dependency graph although I think this may be going out of scope.
    What if each of your fields were to use their own Localization table entry instead of sharing one? We do have plans in the future to allow for entries to reference other entries via smart strings, so that may be an idea.
    e.g if you had entries:
    "My Texture" : "guid"
    "My Texture Reference" : {tableName:My Texture}