Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Feature Request Contextual LocalizedString attribute

Discussion in 'Localization Tools' started by CDF, Feb 28, 2023.

  1. CDF

    CDF

    Joined:
    Sep 14, 2013
    Posts:
    1,306
    Apologies if this is something that already exists/being worked on.
    But it would be great to have the ability to define a contextual search term for a LocalizedString, so we can initially limit what values are shown to a user when picking localization.

    I've implemented something like this using the AssemblyDefinitionReference hack (so I can access internal namespace) And it works nicely:

    Code (CSharp):
    1. using System;
    2.  
    3. namespace UnityEngine.Localization {
    4.  
    5.     /// <summary>
    6.     /// Adds search term filtering to a <see cref="LocalizedString"/> in the editor.
    7.     /// </summary>
    8.     [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
    9.     public sealed class LocalizedStringContextAttribute : PropertyAttribute {
    10.        
    11.         public readonly string searchTerm;
    12.  
    13.         public LocalizedStringContextAttribute(string searchTerm) {
    14.  
    15.             this.searchTerm = searchTerm;
    16.         }
    17.     }
    18. }
    19.  
    20. using UnityEngine;
    21. using UnityEngine.Localization;
    22.  
    23. #if ENABLE_SEARCH
    24. using UnityEditor.Localization.Search;
    25. #endif
    26.  
    27. namespace UnityEditor.Localization.UI {
    28.  
    29.     /// <summary>
    30.     /// PropertyDrawer for a <see cref="LocalizedString"/> that uses the search term from a <see cref="LocalizedStringContextAttribute"/> attribute.
    31.     /// </summary>
    32.     [CustomPropertyDrawer(typeof(LocalizedStringContextAttribute), true)]
    33.     internal sealed class LocalizedStringContextAttributeDrawer : LocalizedStringPropertyDrawer {
    34.  
    35.         #region Protected Methods
    36.  
    37. #if ENABLE_SEARCH
    38.         protected override void ShowPicker(Data data, Rect dropDownPosition) {
    39.  
    40.             if (!LocalizationEditorSettings.UseLocalizedStringSearchPicker) {
    41.  
    42.                 base.ShowPicker(data, dropDownPosition);
    43.                 return;
    44.             }
    45.  
    46.             LocalizedStringContextAttribute attrib = attribute as LocalizedStringContextAttribute;
    47.  
    48.             var provider = new StringTableSearchProvider();
    49.             var searchText = $"{provider.filterId}{attrib.searchTerm}";
    50.             var context = UnityEditor.Search.SearchService.CreateContext(provider, searchText);
    51.             var picker = new LocalizedReferencePicker<StringTableCollection>(context, "string table entry", data, this);
    52.             picker.Show();
    53.         }
    54. #endif
    55.         #endregion
    56.     }
    57. }
    58.  
    59. class SomeClass {
    60.  
    61.     [SerializeField]
    62.     [LocalizedStringContext("Minigame_Results")] //Initially filter the localized string popup with this search term
    63.     private LocalizedString resultHeader = new LocalizedString();
    64. }
     
  2. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,226
    Oh interesting. I'll add the suggestion to our list. Look good

    Thanks!:)
     
    CDF likes this.
  3. Orion

    Orion

    Joined:
    Mar 31, 2008
    Posts:
    261
    This is currently our single most wanted feature of the localization toolset.

    Thanks for sharing your solution, great idea!
     
  4. Orion

    Orion

    Joined:
    Mar 31, 2008
    Posts:
    261
    @CDF Could you elaborate on how you made an internal class inheritable?
     
  5. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,226
  6. Orion

    Orion

    Joined:
    Mar 31, 2008
    Posts:
    261
    Maybe I don't quite understand. I didn't figure this to be a hack, but a necessity, when using assembly definition files and using specific Unity namespaces.

    I've added Unity.Localization.Editor, but I still get `'LocalizedStringPropertyDrawer' is inaccessible due to its protection level. Cannot access internal class 'LocalizedStringPropertyDrawer' here.`

    When I edit the code file for it, it's actually private, not even internal.

    Or do you mean that I have to add an assembly definition reference into the localization package?
     
  7. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,226
    Did you place your code into the same directory as the asmref file?
     
  8. Orion

    Orion

    Joined:
    Mar 31, 2008
    Posts:
    261
    Ah, I get it now. I see now why it's considered a hack. The asmref references the unity.localization.editor assembly.
    I noticed I have to put the attribute in there as well, in order to access it from the drawer.

    And my regular asm files now have to reference unity.localization.editor as well.

    I also had to add an extra folder with an assembly definition file that builds for all targets except Editor and includes the same attribute class again, because otherwise, all builds will fail.

    But it works. So that's pretty cool. I really hated the string search picker, because it's actively making finding stuff more work; but like this, it's useful for something after all. Nice!
     
  9. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,226
    What is it you dont like about the string picker? Are you using 1.4.3? There was a bug with it that caused it to be empty by default.
     
  10. Orion

    Orion

    Joined:
    Mar 31, 2008
    Posts:
    261
    We're using Unity 2021.3, the latest version the package manager is offering is 1.3.2.
    My main gripe is that requires too many operations to find what I'm looking for. The "non-string picker" immediately shows the string tables and from there I can pick what I need. It's not great, but at least I have an idea where I am.

    With the string picker, I have to search. But to search I have to know exactly what I'm looking for. But I also get all sorts of results that contain the word that I'm not looking for. Having to remember the correct commands for filtering is a mental strain that I'd rather avoid. I have looked into it, but to this day I can't figure out the command to get an exact string table. "st:" seems appropriate, but it just looks in everything.

    With the above solution, I've now set it up so it doesn't show the string picker by default unless there's an attribute that specifies search criteria (any of "st:", "key:", or "NOT key:"). This way I pretty much only get a list of strings that are appropriate for the field in question, without having to touch the filters (with a couple of rogue entries, because st apparently looks everywhere, not just in the string table names).
     
  11. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,226
  12. Orion

    Orion

    Joined:
    Mar 31, 2008
    Posts:
    261
    Ah, thanks. That works. I hadn't expected that to be the issue.