Могут ли файлы ресурсов .strings быть добавлены во время выполнения?

#objective-c #ios #cocoa #macos #localization

#objective-c #iOS #cocoa #macos #локализация

Вопрос:

Я знаю, что в приложениях Mac можно добавлять файлы .strings в папку проекта для добавления локализаций.

Есть ли какой-либо способ добавления дополнительных локализаций в приложение (iOS или Mac OS) без загрузки их из пакета ресурсов во время компиляции. Скажем, загрузить дополнительную локализацию и сохранить ее в /Documents на iOS?

Комментарии:

1. 5 лет спустя для этого появился продукт. lokalise.co «Больше не нужно повторно отправлять ваше приложение на проверку. Используйте Lokalise iOS и Android SDK для обновления строк и переводов с помощью нескольких строк кода.»

Ответ №1:

Да, но это не то, что вы думаете.

Вы можете взять файл strings и загрузить его в NSString , а затем преобразовать его в словарь с помощью -[NSString propertyListFromStringsFileFormat] .

Это предоставит вам способ сохранить ваши переведенные пользователем строки в памяти.

Что касается фактического использования этого, вам нужно будет определить пользовательские функции перевода. Т.е. вы больше не можете использовать NSLocalizedString() и friends. К счастью, genstrings (утилита, используемая для создания файлов strings) позволяет указывать имена пользовательских функций:

 genstrings -s "JPLocalizedString" ...
  

Это означает, что в коде вы можете определить:

 NSString* JPLocalizedString(NSString *key, NSString *comment) {
  return [myLoadedStrings objectForKey:key];
}
  

А также JPLocalizedStringFromTable() , JPLocalizedStringFromTableInBundle() JPLocalizedStringWithDefaultValue() . genstrings будет собирать все это. (Другими словами, только потому, что NSLocalizedString это макрос, не означает, что ваша версия должна быть)

Если вы сделаете это и будете использовать эти JPLocalizedString варианты, то genstrings ваши файлы strings все равно будут сгенерированы для вас (при условии, что вы используете -s флаг).

После вызова этих функций вы можете использовать любой механизм поиска, который вы хотите, возвращаясь по умолчанию к NSLocalizedString версиям, если вы ничего не можете найти.

Комментарии:

1. Спасибо, это был скорее теоретический вопрос, и у меня нет планов по его реализации.

Ответ №2:

Если вы хотите внедрить альтернативную версию NSLocalizedString() внутри вашего приложения, для этого существует ряд хороших стратегий. Это позволило бы вам изменять значения, используемые внутри самого вашего приложения. Но они не будут работать, когда дело доходит до Push-уведомлений.

Однако предупреждение: для Push-уведомлений iOS, в которых используются локализованные строки, не существует законного метода выполнения измените встроенные ресурсы strings, которые используются для перевода локализованных аргументов, отправляемых с вашего сервера, на родной язык устройства.

Итак, если вы хотите использовать локализованные строки как часть Push-уведомлений, вы должны отправить их в приложение при отправке в магазин. Их нельзя изменить позже, загрузив что-либо с сервера.

Ответ №3:

Вы должны быть в состоянии достичь этого, переопределив NSBundle различные pathForResource: … методы в категории. (Я бы предположил, что все они проходят через -pathForResource:ofType:inDirectory:forLocalization: , но это не задокументировано, поэтому вы не можете полагаться на это, даже если это окажется так сейчас, поэтому вы должны переопределить их все.)

Я также предлагаю подать запрос на улучшение для чистого способа переопределения механизма поиска.

Комментарии:

1. ооо, плохая идея. единственный способ заставить это работать — использовать -[NSBundle localizedStringForKey:value:table:] метод, и это действительно очень плохая идея.

2. Что ж, я беру свои слова обратно. Вы могли бы использовать подкласс NSBundle , переопределять логику в методе и вызывать super при необходимости, но вам пришлось бы всегда использовать макросы NSLocalizedStringFromTableInBundle() или NSLocalizedStringWithDefaultValue() для указания вашего пользовательского пакета.

Ответ №4:

Мне удалось это сделать, и я создал небольшой репозиторий, чтобы показать, как я это сделал:

https://github.com/multitudes/MyLocalisationTestApp

Создайте пользовательский пакет в каталоге documents.

Просматривая документацию Apple для текста:https://developer.apple.com/documentation/swiftui/text

Инициализатор текстового представления SwiftUI принимает параметр bundle.

1 — Я создал пользовательский пакет в каталоге Documents. 2 — Я программно поместил в языковые папки файлы strings внутри него. 3 — При его использовании я передаю пользовательский пакет и tableName (имя .strings файла) в Text инициализатор вместе с key .
Как и в SwiftUI, это будет: Text(localizedStringKey, tableName: tableName, bundle: bundle)