У меня есть сотни динамических строк, т.е. в этой строке существует одна или несколько переменных, которые динамически генерируются в коде. Например, это строка с чем-либо в ‹›, представляющая переменную, значение которой неизвестно, пока код не будет выполнен:
‹Преимущественно облачно›, до ‹25 °› от ‹2pm›
Поскольку эти строки будут локализованы, в идеале я бы использовал файл .strings для их хранения. Вот пример выше, если бы я определил его там:
/*
One condition throughout an hourly range
e.g. <Mostly cloudy> with <temperatures> <rising> to <25°> by <2pm>.
Parameters:
1- weather
2- measurement point (default=temperature)
3- measurement trajectory (upwards or downwards)
4- measurement value
5- time above value is reached
*/
"hourSeries_const" = "%@ with %@ %@ to %@ by %@.";
Благодаря https://stackoverflow.com/a/56445894/698971 я создал расширение String, которое возвращает локализованную строку с переданными аргументами:
/// Fetches a localised String Arguments
///
/// - Parameter arguments: parameters to be added in a string
/// - Returns: localized string
public func localized(with arguments: [CVarArg]) -> String {
return String(format: self.localized, locale: nil, arguments: arguments)
}
И получить последнюю строку для пользовательского интерфейса так же просто, как позвонить:
let a = "hourSeries_const".localized(with: ["Mostly cloudy","temperatures","rising","24°","2pm"])
Но это не идеально по нескольким причинам. Строка в файле .strings не удобна для чтения. Комментарии необходимы для понимания того, что представляет собой каждая переменная. А затем представьте ситуацию, в которой необходимо изменить порядок переменных, чтобы строка читалась естественным образом на языке. Это нужно как-то отслеживать, а затем мне также приходится вмешиваться в код, чтобы гарантировать, что порядок, который я передаю в аргументах, изменился соответствующим образом.
Альтернатива, о которой я подумал, может частично решить эту проблему (но имеет свои проблемы - подробнее об этом позже) - это переместить строки в код. Например, есть функция:
func hourSeries_const(weather:String, dataPoint:String, valueDirection:String, valueHighlight:String, highlightedValueTime:String) -> String {
return "\(weather) with \(dataPoint) \(valueDirection) to \(valueHighlight) by \(highlightedValueTime)."
}
Но для поддержки нескольких языков мне понадобится switch
, чтобы выбирать между разными языками. Это не идеально, так как я планировал отправлять каждому переводчику их языковые файлы для работы, то есть он должен включать только строки их языка. Я мог бы обойтись, добавив функцию выбора, которая вызывает функцию выбранного языка:
func hourSeries_const(...) -> String {
switch language {
case "en": return hourSeries_const_en(...)
case "de": return hourSeries_const_de(...)
}
}
Это не конец света, но это означает, что каждый раз, когда я добавляю новый язык, мне нужно будет добавлять новый регистр для каждой из этих функций, указывающих на соответствующую языковую функцию для строки.
Есть ли вариант, который удобен в зависимости от файлов .strings, но обеспечивает удобочитаемость описательных имен переменных в строках для работы переводчиков?
"hourSeries_const" = "%@ with %@ %@ to %@ by %@.";
, а не"\(weather) with \(dataPoint) \(valueDirection) to \(valueHighlight) by \(highlightedValueTime)."
. Возможно, вас заинтересует SwiftGen github.com/SwiftGen/SwiftGen#strings - person Larme   schedule 21.05.2021"hourSeries_const" = [[Weather]] with to [[Temperature]] by [[Time]]
и заменять их. Это может означать парсер. Обратите внимание, как работает SwiftGen, вы можете использовать для этого собственный шаблон Stencil (но это означает, что некоторые из них работают на вашей стороне). - person Larme   schedule 21.05.2021