Search code examples
macoscocoanspredicateeditornspredicateeditorrownsruleeditor

Why is NSPredicateEditor automatically localizing some Expression strings? How to disable?


I'm finding that some NSPredicateEditor / NSPredicateEditorRowTemplate values are being localized automatically by OS X.

This is easily observable in the mapping of operators: .equalTo to the string is.

But I just noticed that UTI strings are being mapped to a human-readable version of that UTI.

Below, I set "public.image" but it is then displayed as "image".

UTI operators in NSPredicateEditor

func setupPredicateEditor() {
    let left = [NSExpression(forKeyPath: "Type")]

    let operators = [NSComparisonPredicate.Operator.equalTo.rawValue as NSNumber]

    let right = [
        NSExpression(forConstantValue: "public.image"),
        NSExpression(forConstantValue: "public.text"),
        NSExpression(forConstantValue: "public.fakeUTI"),
        ];

    let rowTemplate = NSPredicateEditorRowTemplate.init(leftExpressions: left, rightExpressions: right, modifier: .all, operators: operators, options: 0)
    predicateEditor.rowTemplates = [rowTemplate]

    predicateEditor.addRow(self)
}

Only certain valid UTIs are mapped in this manner. I do not know if other formats beyond Operators and UTIs are given automatic localized strings.

This is an issue because I want to localize my NSPredicateEditor and Row Templates.

The process for localizing the predicate involves matching a key to a localized value.

KEY: "%[left]@ %[is]@ %[right]@"
VAL: "%1$[left_display_string]@ %2$[is]@ %3$[right_display_string]@"

The problem is that the values in the key must match the strings shown in the UI. Not the strings originally set to the Row Template's left and right expressions.

So, I cannot localize using "public.image" in the key. The UI is for some reason already localizing this to "image". If I want to localize the Row Template, I must use the string "image" instead. And I don't know how or why this "image" string is being picked.

I could determine these strings via testing, then write a table that maps the expression to the localized string. But I'd prefer to have a solution that disables this automatic localization so that I don't have to worry about strings I have not tested.

Why are UTIs being localized automatically? Do other values receive the same treatment?

Is there a way to disable the automatic localization of the UTI strings and/or the entire predicate editor?


Solution

  • Not an answer but some info: NSPredicateEditorRowTemplate translates the strings in _displayValueForConstantValue:. It uses a dictionary:

    {
        "com.apple.application" = application;
        "com.apple.pict" = PICT;
        "com.apple.protected-mpeg-4-audio" = "purchased music";
        "com.apple.rtfd" = RTFD;
        "com.compuserve.gif" = GIF;
        "com.microsoft.bmp" = BMP;
        "public.audio" = music;
        "public.folder" = folder;
        "public.html" = HTML;
        "public.image" = image;
        "public.jpeg" = JPEG;
        "public.jpeg-2000" = "JPEG 2000";
        "public.mp3" = MP3;
        "public.mpeg-4-audio" = "MPEG4 audio";
        "public.png" = PNG;
        "public.rtf" = RTF;
        "public.source-code" = "source code";
        "public.text" = text;
        "public.tiff" = TIFF;
        "public.xml" = XML;
    }
    

    bt:

    AppKit`-[NSPredicateEditorRowTemplate _displayValueForConstantValue:] + 913
    AppKit`-[NSPredicateEditorRowTemplate _viewFromExpressions:] + 589
    AppKit`-[NSPredicateEditorRowTemplate initWithLeftExpressions:rightExpressions:modifier:operators:options:] + 205
    

    Edit:

    _displayValueForKeyPath: uses this dictionary:

    {
        kMDItemContentCreationDate = Created;
        kMDItemContentModificationDate = "Last modified";
        kMDItemContentTypeTree = "File type";
        kMDItemDisplayName = "File display name";
        kMDItemFSContentChangeDate = "Change date";
        kMDItemFSCreationDate = "Creation date";
        kMDItemFSName = "File name";
        kMDItemFSOwnerGroupID = "Owner group id";
        kMDItemFSOwnerUserID = "Owner user ID";
        kMDItemFSSize = "File size";
        kMDItemLastUsedDate = "Last opened";
        kMDItemPath = "File path";
    }
    

    _displayValueForPredicateOperator: and _displayValueForCompoundPredicateType: translate the enums to strings.

    This should be documented but it isn't. I put a breakpoint on _displayValueForConstantValue: and I watched what happened. The dictionaries are hard coded and can be different in others versions of macOS.