Почему NSPredicateEditor автоматически локализует некоторые строки выражений? Как отключить?

Я обнаружил, что некоторые NSPredicateEditor / NSPredicateEditorRowTemplate значения локализуются автоматически OS X.

Это легко заметить при отображении операторов: .equalTo в строку is,

Но я только что заметил, что строки UTI отображаются в читаемую человеком версию этого UTI.

Ниже я установил "public.image" но затем отображается как "image",

Операторы UTI в 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)
}

Только определенные действительные UTI отображаются таким образом. Я не знаю, имеют ли другие форматы, кроме операторов и UTI, автоматические локализованные строки.

Это проблема, потому что я хочу локализовать свои шаблоны NSPredicateEditor и Row.

Процесс локализации предиката включает сопоставление ключа с локализованным значением.

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

Проблема в том, что значения в ключе должны соответствовать строкам, отображаемым в пользовательском интерфейсе. Не те строки, которые изначально установлены для левого и правого выражений шаблона строки.

Итак, я не могу локализовать с помощью "public.image" в ключе. Пользовательский интерфейс по какой-то причине уже локализует это "image", Если я хочу локализовать шаблон строки, я должен использовать строку "image" вместо. И я не знаю, как и почему это "image" Строка выбирается.

Я мог бы определить эти строки с помощью тестирования, а затем написать таблицу, которая отображает выражение в локализованную строку. Но я бы предпочел иметь решение, которое отключает эту автоматическую локализацию, чтобы мне не приходилось беспокоиться о строках, которые я не тестировал.

Почему ИМП локализуются автоматически? Другие ценности получают то же самое лечение?

Есть ли способ отключить автоматическую локализацию строк UTI и / или всего редактора предикатов?

1 ответ

Решение

Не ответ, а некоторая информация: NSPredicateEditorRowTemplate переводит строки в _displayValueForConstantValue:, Он использует словарь:

{
    "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;
}

Ы:

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

Редактировать:

_displayValueForKeyPath: использует этот словарь:

{
    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: а также _displayValueForCompoundPredicateType: перевести перечисления в строки.

Это должно быть задокументировано, но это не так. Я ставлю точку останова на _displayValueForConstantValue: и я смотрел что случилось. Словари жестко запрограммированы и могут отличаться в других версиях macOS.

Вы можете вызвать частные методы API напрямую, чтобы использовать отображение системы.

В Swift для этого требуется заголовок моста:

#import <AppKit/AppKit.h>

@interface NSPredicateEditorRowTemplate ()

- (NSString *)_displayValueForKeyPath:(CFStringRef)keyPath;
- (NSString *)_displayValueForConstantValue:(CFStringRef)constantValue;
- (NSString *)_displayValueForCompoundPredicateType:(NSCompoundPredicateType)compoundPredicateType;
- (NSString *)_displayValueForPredicateOperator:(NSPredicateOperatorType)predicateOperator;

@end

Эти частные методы затем можно вызывать так:

let keyPath = rowTemplate._displayValue(forKeyPath: kMDItemFSSize) // "File size"
let constantValue = rowTemplate._displayValue(forConstantValue: "com.apple.application" as CFString) // "application"
let compoundPredicateType = rowTemplate._displayValue(for: .or) // "Any"

Три перечисленных выше работают, но в настоящее время у меня проблемы с _displayValueForPredicateOperator: сбой с EXC_BAD_ACCESS или возврат неправильного перевода строки.

Расширяя отличный ответ Виллеке:

Добавьте символические точки останова к следующим частным методам, чтобы увидеть сопоставления.

  • _displayValueForKeyPath:
  • _displayValueForConstantValue:
  • _displayValueForCompoundPredicateType:
  • _displayValueForPredicateOperator:

Когда вы прерываете, ставьте точку останова на строку, содержащую objc_msgSend и снова сломайся там.

Затем введите po $rax для печати таблицы сопоставления.

В двух нижних случаях он не использует словарь, но строки можно увидеть при достижении точек останова.

_displayValueForKeyPath:

{
    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";
}

_displayValueForConstantValue:

{
    "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;
}

_displayValueForCompoundPredicateType:

0x7fff32a7342c <+20>: leaq   0x5ca25255(%rip), %rax    ; @"Any"
0x7fff32a73434 <+28>: leaq   0x5c9c8dad(%rip), %rax    ; @"None"
0x7fff32a7343c <+36>: leaq   0x5ca00ac5(%rip), %rax    ; @"All"
0x7fff32a73456 <+62>: leaq   0x5ca2524b(%rip), %rdx    ; @"(unknown compound type %ld)"

_displayValueForPredicateOperator:

0x7fff32a7331b <+42>:  leaq   0x5ca251c6(%rip), %rax    ; @"is less than"
0x7fff32a73332 <+65>:  leaq   0x5ca251cf(%rip), %rax    ; @"is less than or equal to"
0x7fff32a7334a <+89>:  leaq   0x5ca252f7(%rip), %rax    ; @"between"
0x7fff32a73356 <+101>: leaq   0x5ca251cb(%rip), %rax    ; @"is greater than"
0x7fff32a73362 <+113>: leaq   0x5ca251df(%rip), %rax    ; @"is greater than or equal to"
0x7fff32a7336b <+122>: leaq   0x5ca251f6(%rip), %rax    ; @"is"
0x7fff32a73374 <+131>: leaq   0x5ca2520d(%rip), %rax    ; @"is not"
0x7fff32a7337d <+140>: leaq   0x5ca25224(%rip), %rax    ; @"matches"
0x7fff32a73386 <+149>: leaq   0x5ca2523b(%rip), %rax    ; @"is like"
0x7fff32a7338f <+158>: leaq   0x5ca25252(%rip), %rax    ; @"begins with"
0x7fff32a73398 <+167>: leaq   0x5ca25269(%rip), %rax    ; @"ends with"
0x7fff32a733a1 <+176>: leaq   0x5ca01300(%rip), %rax    ; @"in"
0x7fff32a733aa <+185>: leaq   0x5ca25277(%rip), %rax    ; @"contains"
0x7fff32a733d4 <+227>: leaq   0x5ca2528d(%rip), %rdx    ; @"(unknown predicate operator %ld)"
Другие вопросы по тегам