mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
Refactor string generation
This commit is contained in:
parent
bbd096d88b
commit
7bed1728bb
205 changed files with 15848 additions and 33988 deletions
|
|
@ -220,6 +220,7 @@ swift_library(
|
|||
"//submodules/PasswordSetupUI:PasswordSetupUIAssets",
|
||||
"//submodules/TelegramUI:TelegramUIResources",
|
||||
"//submodules/TelegramUI:TelegramUIAssets",
|
||||
"//submodules/PresentationStrings:PresentationStringsResources",
|
||||
],
|
||||
deps = [
|
||||
"//submodules/TelegramUI:TelegramUI",
|
||||
|
|
|
|||
|
|
@ -91,22 +91,31 @@
|
|||
"PUSH_MESSAGE_FWD" = "%1$@|forwarded you a message";
|
||||
"PUSH_MESSAGE_FWDS_1" = "%1$@|forwarded you a message";
|
||||
"PUSH_MESSAGE_FWDS_any" = "%1$@|forwarded you %2$d messages";
|
||||
"PUSH_MESSAGE_FWDS_TEXT_1" = "forwarded you a message";
|
||||
"PUSH_MESSAGE_FWDS_TEXT_any" = "forwarded you %d messages";
|
||||
"PUSH_MESSAGE_PHOTO" = "%1$@|sent you a photo";
|
||||
"PUSH_MESSAGE_PHOTOS_1" = "%1$@|sent you a photo";
|
||||
"PUSH_MESSAGE_PHOTOS_any" = "%1$@|sent you %2$d photos";
|
||||
"PUSH_MESSAGE_PHOTOS_TEXT_1" = "sent you a photo";
|
||||
"PUSH_MESSAGE_PHOTOS_TEXT_any" = "sent you %d photos";
|
||||
"PUSH_MESSAGE_VIDEO" = "%1$@|sent you a video";
|
||||
"PUSH_MESSAGE_VIDEOS_1" = "%1$@|sent you a video";
|
||||
"PUSH_MESSAGE_VIDEOS_any" = "%1$@|sent you %2$d videos";
|
||||
"PUSH_MESSAGE_VIDEOS_TEXT_1" = "sent you a video";
|
||||
"PUSH_MESSAGE_VIDEOS_TEXT_any" = "sent you %d videos";
|
||||
"PUSH_MESSAGE_ROUND" = "%1$@|sent you a video message";
|
||||
"PUSH_MESSAGE_ROUNDS_1" = "%1$@|sent you a video message";
|
||||
"PUSH_MESSAGE_ROUNDS_any" = "%1$@|sent you %2$d video messages";
|
||||
"PUSH_MESSAGE" = "%1$@|sent you a message";
|
||||
"PUSH_MESSAGES_1" = "%1$@|sent you a message";
|
||||
"PUSH_MESSAGES_any" = "%1$@|sent you %2$d messages";
|
||||
"PUSH_MESSAGES_TEXT_1" = "sent you a message";
|
||||
"PUSH_MESSAGES_TEXT_any" = "sent you %2$d messages";
|
||||
"PUSH_ALBUM" = "%1$@|sent you an album";
|
||||
"PUSH_MESSAGE_FILES_1" = "%1$@|sent you a file";
|
||||
"PUSH_MESSAGE_FILES_any" = "%1$@|sent you %2$d files";
|
||||
|
||||
"PUSH_MESSAGE_FILES_TEXT_1" = "sent you a file";
|
||||
"PUSH_MESSAGE_FILES_TEXT_any" = "sent you %d files";
|
||||
|
||||
"PUSH_CHANNEL_MESSAGE_TEXT" = "%1$@|%2$@";
|
||||
"PUSH_CHANNEL_MESSAGE_NOTEXT" = "%1$@|posted a message";
|
||||
|
|
@ -129,19 +138,26 @@
|
|||
"PUSH_CHANNEL_MESSAGE_PHOTO" = "%1$@|posted a photo";
|
||||
"PUSH_CHANNEL_MESSAGE_PHOTOS_1" = "%1$@|posted a photo";
|
||||
"PUSH_CHANNEL_MESSAGE_PHOTOS_any" = "%1$@|posted %2$d photos";
|
||||
"PUSH_CHANNEL_MESSAGE_PHOTOS_TEXT_1" = "posted a photo";
|
||||
"PUSH_CHANNEL_MESSAGE_PHOTOS_TEXT_any" = "posted %d photos";
|
||||
"PUSH_CHANNEL_MESSAGE_VIDEO" = "%1$@|posted a video";
|
||||
"PUSH_CHANNEL_MESSAGE_VIDEOS_1" = "%1$@|posted a video";
|
||||
"PUSH_CHANNEL_MESSAGE_VIDEOS_any" = "%1$@|posted %2$d videos";
|
||||
"PUSH_CHANNEL_MESSAGE_VIDEOS_TEXT_1" = "posted a video";
|
||||
"PUSH_CHANNEL_MESSAGE_VIDEOS_TEXT_any" = "posted %d videos";
|
||||
"PUSH_CHANNEL_MESSAGE_ROUND" = "%1$@|posted a video message";
|
||||
"PUSH_CHANNEL_MESSAGE_ROUNDS_1" = "%1$@|posted a video message";
|
||||
"PUSH_CHANNEL_MESSAGE_ROUNDS_any" = "%1$@|posted %2$d video messages";
|
||||
"PUSH_CHANNEL_MESSAGE" = "%1$@|posted a message";
|
||||
"PUSH_CHANNEL_MESSAGES_1" = "%1$@|posted a message";
|
||||
"PUSH_CHANNEL_MESSAGES_any" = "%1$@|posted %2$d messages";
|
||||
"PUSH_CHANNEL_MESSAGES_TEXT_1" = "posted a message";
|
||||
"PUSH_CHANNEL_MESSAGES_TEXT_any" = "posted %d messages";
|
||||
"PUSH_CHANNEL_ALBUM" = "%1$@|posted an album";
|
||||
"PUSH_CHANNEL_MESSAGE_DOCS" = "%1$@|posted %2$d files";
|
||||
"PUSH_CHANNEL_MESSAGE_DOCS_1" = "%1$@|posted a file";
|
||||
"PUSH_CHANNEL_MESSAGE_DOCS_any" = "%1$@|posted %2$d files";
|
||||
"PUSH_CHANNEL_MESSAGE_DOCS_TEXT_1" = "posted a file";
|
||||
"PUSH_CHANNEL_MESSAGE_DOCS_TEXT_any" = "posted %d files";
|
||||
|
||||
"PUSH_CHAT_MESSAGE_TEXT" = "%2$@|%1$@:%3$@";
|
||||
"PUSH_CHAT_MESSAGE_NOTEXT" = "%2$@|%1$@ sent a message to the group";
|
||||
|
|
@ -171,21 +187,31 @@
|
|||
"PUSH_CHAT_MESSAGE_FWD" = "%2$@|%1$@ forwarded a message";
|
||||
"PUSH_CHAT_MESSAGE_FWDS_1" = "%2$@|%1$@ forwarded a message";
|
||||
"PUSH_CHAT_MESSAGE_FWDS_any" = "%2$@|%1$@ forwarded %3$d messages";
|
||||
"PUSH_CHAT_MESSAGE_FWDS_TEXT_1" = "{author} forwarded a message";
|
||||
"PUSH_CHAT_MESSAGE_FWDS_TEXT_any" = "{author} forwarded %d messages";
|
||||
"PUSH_CHAT_MESSAGE_PHOTO" = "%2$@|%1$@ sent a photo";
|
||||
"PUSH_CHAT_MESSAGE_PHOTOS_1" = "%2$@|%1$@ sent a photo";
|
||||
"PUSH_CHAT_MESSAGE_PHOTOS_any" = "%2$@|%1$@ sent %3$d photos";
|
||||
"PUSH_CHAT_MESSAGE_PHOTOS_TEXT_1" = "{author} sent a photo";
|
||||
"PUSH_CHAT_MESSAGE_PHOTOS_TEXT_any" = "{author} sent %d photos";
|
||||
"PUSH_CHAT_MESSAGE_VIDEO" = "%2$@|%1$@ sent a video";
|
||||
"PUSH_CHAT_MESSAGE_VIDEOS_1" = "%2$@|%1$@ sent a video";
|
||||
"PUSH_CHAT_MESSAGE_VIDEOS_any" = "%2$@|%1$@ sent %3$d videos";
|
||||
"PUSH_CHAT_MESSAGE_VIDEOS_TEXT_1" = "{author} sent a video";
|
||||
"PUSH_CHAT_MESSAGE_VIDEOS_TEXT_any" = "{text} sent %d videos";
|
||||
"PUSH_CHAT_MESSAGE_ROUND" = "%2$@|%1$@ sent a video message";
|
||||
"PUSH_CHAT_MESSAGE_ROUNDS_1" = "%2$@|%1$@ sent a video message";
|
||||
"PUSH_CHAT_MESSAGE_ROUNDS_any" = "%2$@|%1$@ sent %3$d video messages";
|
||||
"PUSH_CHAT_MESSAGE" = "%2$@|%1$@ sent a message";
|
||||
"PUSH_CHAT_MESSAGES_1" = "%2$@|%1$@ sent a message";
|
||||
"PUSH_CHAT_MESSAGES_any" = "%2$@|%1$@ sent %3$d messages";
|
||||
"PUSH_CHAT_MESSAGES_TEXT_1" = "{author} sent a message";
|
||||
"PUSH_CHAT_MESSAGES_TEXT_any" = "{author} sent %d messages";
|
||||
"PUSH_CHAT_ALBUM" = "%2$@|%1$@ sent an album";
|
||||
"PUSH_CHAT_MESSAGE_DOCS_FIX1_1" = "%2$@|%1$@ sent a file";
|
||||
"PUSH_CHAT_MESSAGE_DOCS_FIX1_any" = "%2$@|%1$@ sent %3$d files";
|
||||
"PUSH_CHAT_MESSAGE_DOCS_TEXT_1" = "{author} sent a file";
|
||||
"PUSH_CHAT_MESSAGE_DOCS_TEXT_any" = "{author} sent %d files";
|
||||
|
||||
"PUSH_PINNED_TEXT" = "%1$@|pinned \"%2$@\" ";
|
||||
"PUSH_PINNED_NOTEXT" = "%1$@|pinned a message";
|
||||
|
|
@ -3298,7 +3324,7 @@ Unused sets are archived when you add more.";
|
|||
"Passport.DeleteDocument" = "Delete Document";
|
||||
"Passport.DeleteDocumentConfirmation" = "Are you sure you want to delete this document? All details will be lost.";
|
||||
|
||||
"Passport.Scans" = "SCANS";
|
||||
"Passport.ScansHeader" = "SCANS";
|
||||
"Passport.Scans.Upload" = "Upload Scan";
|
||||
"Passport.Scans.UploadNew" = "Upload Additional Scan";
|
||||
"Passport.Scans.ScanIndex" = "Scan %@";
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
import argparse
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import codecs
|
||||
import struct
|
||||
|
||||
|
||||
def _unescape_key(s):
|
||||
|
|
@ -142,6 +142,18 @@ def write_string(file, string: str):
|
|||
file.write((string + '\n').encode('utf-8'))
|
||||
|
||||
|
||||
def write_bin_uint32(file, value: int):
|
||||
file.write(struct.pack('I', value))
|
||||
|
||||
|
||||
def write_bin_uint8(file, value: int):
|
||||
file.write(struct.pack('B', value))
|
||||
|
||||
|
||||
def write_bin_string(file, value: str):
|
||||
file.write(value.encode('utf-8'))
|
||||
|
||||
|
||||
class IndexCounter:
|
||||
def __init__(self):
|
||||
self.dictionary = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
|
|
@ -188,71 +200,426 @@ def sanitize_entry_identifer(string: str) -> str:
|
|||
return string.replace('.', '_')
|
||||
|
||||
|
||||
def generate(header_path: str, implementation_path: str, entries: [Entry]):
|
||||
test_path = '/Users/ali/build/telegram/telegram-ios/submodules/PresentationStrings/main.m'
|
||||
def generate(header_path: str, implementation_path: str, data_path: str, entries: [Entry]):
|
||||
print('Generating strings into:\n{}\n{}'.format(header_path, implementation_path))
|
||||
with open(header_path, 'wb') as header_file, open(implementation_path, 'wb') as source_file, open(test_path, 'wb') as test_file:
|
||||
write_string(test_file, '#import <Foundation/Foundation.h>')
|
||||
write_string(test_file, '#import <PresentationStrings/PresentationStrings.h>')
|
||||
write_string(test_file, '')
|
||||
write_string(test_file, 'int main(int argc, const char **argv) {')
|
||||
write_string(test_file, 'PresentationStrings *strings = [[PresentationStrings alloc] init];')
|
||||
with open(header_path, 'wb') as header_file, open(implementation_path, 'wb') as source_file,\
|
||||
open(data_path, 'wb') as data_file:
|
||||
|
||||
write_string(header_file, '#import <Foundation/Foundation.h>')
|
||||
write_string(header_file, '')
|
||||
write_string(header_file, '@interface PresentationStrings : NSObject')
|
||||
write_string(header_file, '')
|
||||
write_string(header_file, '@end')
|
||||
formatted_accessors = ''
|
||||
max_format_argument_count = 0
|
||||
for entry in entries:
|
||||
num_arguments = len(entry.positional_arguments)
|
||||
if num_arguments > max_format_argument_count:
|
||||
max_format_argument_count = num_arguments
|
||||
if max_format_argument_count != 0:
|
||||
for num_arguments in range(1, max_format_argument_count + 1):
|
||||
arguments_string = ''
|
||||
arguments_array = ''
|
||||
for i in range(0, num_arguments):
|
||||
arguments_string += ', id arg{}'.format(i)
|
||||
if i != 0:
|
||||
arguments_array += ', '
|
||||
arguments_array += 'arg{}'.format(i)
|
||||
formatted_accessors += '''
|
||||
static _FormattedString * _Nonnull getFormatted{num_arguments}(_PresentationStrings * _Nonnull strings,
|
||||
uint32_t keyId{arguments_string}) {{
|
||||
NSString *formatString = getSingle(strings, strings->_idToKey[@(keyId)]);
|
||||
NSArray<_FormattedStringRange *> *argumentRanges = extractArgumentRanges(formatString);
|
||||
return formatWithArgumentRanges(formatString, argumentRanges, @[{arguments_array}]);
|
||||
}}
|
||||
'''.format(num_arguments=num_arguments, arguments_string=arguments_string, arguments_array=arguments_array)
|
||||
|
||||
write_string(source_file, '#import <PresentationStrings/PresentationStrings.h>')
|
||||
write_string(source_file, '')
|
||||
write_string(source_file, '@implementation PresentationStrings')
|
||||
write_string(source_file, '@end')
|
||||
write_string(source_file, '')
|
||||
write_string(header_file, '''// Automatically-generated file, do not edit
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface _FormattedStringRange : NSObject
|
||||
|
||||
@property (nonatomic, readonly) NSInteger index;
|
||||
@property (nonatomic, readonly) NSRange range;
|
||||
|
||||
- (instancetype _Nonnull)initWithIndex:(NSInteger)index range:(NSRange)range;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface _FormattedString : NSObject
|
||||
|
||||
@property (nonatomic, strong, readonly) NSString * _Nonnull string;
|
||||
@property (nonatomic, strong, readonly) NSArray<_FormattedStringRange *> * _Nonnull ranges;
|
||||
|
||||
- (instancetype _Nonnull)initWithString:(NSString * _Nonnull)string
|
||||
ranges:(NSArray<_FormattedStringRange *> * _Nonnull)ranges;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface _PresentationStringsComponent : NSObject
|
||||
|
||||
@property (nonatomic, strong, readonly) NSString * _Nonnull languageCode;
|
||||
@property (nonatomic, strong, readonly) NSString * _Nonnull localizedName;
|
||||
@property (nonatomic, strong, readonly) NSString * _Nullable pluralizationRulesCode;
|
||||
@property (nonatomic, strong, readonly) NSDictionary<NSString *, NSString *> * _Nonnull dict;
|
||||
|
||||
- (instancetype _Nonnull)initWithLanguageCode:(NSString * _Nonnull)languageCode
|
||||
localizedName:(NSString * _Nonnull)localizedName
|
||||
pluralizationRulesCode:(NSString * _Nullable)pluralizationRulesCode
|
||||
dict:(NSDictionary<NSString *, NSString *> * _Nonnull)dict;
|
||||
|
||||
@end
|
||||
|
||||
@interface _PresentationStrings : NSObject
|
||||
|
||||
@property (nonatomic, readonly) uint32_t lc;
|
||||
@property (nonatomic, strong, readonly) _PresentationStringsComponent * _Nonnull primaryComponent;
|
||||
@property (nonatomic, strong, readonly) _PresentationStringsComponent * _Nullable secondaryComponent;
|
||||
@property (nonatomic, strong, readonly) NSString * _Nonnull baseLanguageCode;
|
||||
@property (nonatomic, strong, readonly) NSString * _Nonnull groupingSeparator;
|
||||
|
||||
- (instancetype _Nonnull)initWithPrimaryComponent:(_PresentationStringsComponent * _Nonnull)primaryComponent
|
||||
secondaryComponent:(_PresentationStringsComponent * _Nullable)secondaryComponent
|
||||
groupingSeparator:(NSString * _Nullable)groupingSeparator;
|
||||
|
||||
@end
|
||||
|
||||
''')
|
||||
|
||||
write_string(source_file, '''// Automatically-generated file, do not edit
|
||||
|
||||
#import <PresentationStrings/PresentationStrings.h>
|
||||
#import <PresentationStrings/StringPluralization.h>
|
||||
|
||||
@implementation _FormattedStringRange
|
||||
|
||||
- (instancetype _Nonnull)initWithIndex:(NSInteger)index range:(NSRange)range {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_index = index;
|
||||
_range = range;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation _FormattedString
|
||||
|
||||
- (instancetype _Nonnull)initWithString:(NSString * _Nonnull)string
|
||||
ranges:(NSArray<_FormattedStringRange *> * _Nonnull)ranges {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_string = string;
|
||||
_ranges = ranges;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _PresentationStringsComponent
|
||||
|
||||
- (instancetype _Nonnull)initWithLanguageCode:(NSString * _Nonnull)languageCode
|
||||
localizedName:(NSString * _Nonnull)localizedName
|
||||
pluralizationRulesCode:(NSString * _Nullable)pluralizationRulesCode
|
||||
dict:(NSDictionary<NSString *, NSString *> * _Nonnull)dict {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_languageCode = languageCode;
|
||||
_localizedName = localizedName;
|
||||
_pluralizationRulesCode = pluralizationRulesCode;
|
||||
_dict = dict;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface _PresentationStrings () {
|
||||
@public
|
||||
NSDictionary<NSNumber *, NSString *> *_idToKey;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static NSArray<_FormattedStringRange *> * _Nonnull extractArgumentRanges(NSString * _Nonnull string) {
|
||||
static NSRegularExpression *argumentRegex = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
argumentRegex = [NSRegularExpression regularExpressionWithPattern:@"%(((\\\\d+)\\\\$)?)([@df])"
|
||||
options:0 error:nil];
|
||||
});
|
||||
|
||||
NSMutableArray<_FormattedStringRange *> *result = [[NSMutableArray alloc] init];
|
||||
NSArray<NSTextCheckingResult *> *matches = [argumentRegex matchesInString:string
|
||||
options:0 range:NSMakeRange(0, string.length)];
|
||||
int index = 0;
|
||||
for (NSTextCheckingResult *match in matches) {
|
||||
int currentIndex = index;
|
||||
NSRange matchRange = [match rangeAtIndex:3];
|
||||
if (matchRange.location != NSNotFound) {
|
||||
currentIndex = [[string substringWithRange:matchRange] intValue] - 1;
|
||||
}
|
||||
[result addObject:[[_FormattedStringRange alloc] initWithIndex:currentIndex range:[match rangeAtIndex:0]]];
|
||||
index += 1;
|
||||
}
|
||||
|
||||
//sort?
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static _FormattedString * _Nonnull formatWithArgumentRanges(
|
||||
NSString * _Nonnull string,
|
||||
NSArray<_FormattedStringRange *> * _Nonnull ranges,
|
||||
NSArray<NSString *> * _Nonnull arguments
|
||||
) {
|
||||
NSMutableArray<_FormattedStringRange *> *resultingRanges = [[NSMutableArray alloc] init];
|
||||
NSMutableString *result = [[NSMutableString alloc] init];
|
||||
NSUInteger currentLocation = 0;
|
||||
|
||||
for (_FormattedStringRange *range in ranges) {
|
||||
if (currentLocation < range.range.location) {
|
||||
[result appendString:[string substringWithRange:
|
||||
NSMakeRange(currentLocation, range.range.location - currentLocation)]];
|
||||
}
|
||||
[resultingRanges addObject:[[_FormattedStringRange alloc] initWithIndex:range.index
|
||||
range:NSMakeRange(result.length, arguments[range.index].length)]];
|
||||
[result appendString:arguments[range.index]];
|
||||
currentLocation = range.range.location + range.range.length;
|
||||
}
|
||||
|
||||
if (currentLocation != string.length) {
|
||||
[result appendString:[string substringWithRange:NSMakeRange(currentLocation, string.length - currentLocation)]];
|
||||
}
|
||||
|
||||
return [[_FormattedString alloc] initWithString:result ranges:resultingRanges];
|
||||
}
|
||||
|
||||
static NSString * _Nonnull getPluralizationSuffix(_PresentationStrings * _Nonnull strings, int32_t value) {
|
||||
StringPluralizationForm pluralizationForm = getStringPluralizationForm(strings.lc, value);
|
||||
switch (pluralizationForm) {
|
||||
case StringPluralizationFormZero: {
|
||||
return @"_0";
|
||||
}
|
||||
case StringPluralizationFormOne: {
|
||||
return @"_1";
|
||||
}
|
||||
case StringPluralizationFormTwo: {
|
||||
return @"_2";
|
||||
}
|
||||
case StringPluralizationFormFew: {
|
||||
return @"_3_10";
|
||||
}
|
||||
case StringPluralizationFormMany: {
|
||||
return @"_many";
|
||||
}
|
||||
default: {
|
||||
return @"_any";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static NSString * _Nonnull getSingle(_PresentationStrings * _Nonnull strings, NSString * _Nonnull key) {
|
||||
NSString *result = strings.primaryComponent.dict[key];
|
||||
if (!result) {
|
||||
result = strings.secondaryComponent.dict[key];
|
||||
}
|
||||
if (!result) {
|
||||
static NSDictionary<NSString *, NSString *> *fallbackDict = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSString *lprojPath = [[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj"];
|
||||
if (!lprojPath) {
|
||||
return;
|
||||
}
|
||||
NSBundle *bundle = [NSBundle bundleWithPath:lprojPath];
|
||||
if (!bundle) {
|
||||
return;
|
||||
}
|
||||
NSString *stringsPath = [bundle pathForResource:@"Localizable" ofType:@"strings"];
|
||||
if (!stringsPath) {
|
||||
return;
|
||||
}
|
||||
fallbackDict = [NSDictionary dictionaryWithContentsOfURL:[NSURL fileURLWithPath:stringsPath]];
|
||||
});
|
||||
result = fallbackDict[key];
|
||||
}
|
||||
if (!result) {
|
||||
result = key;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static NSString * _Nonnull getSingleIndirect(_PresentationStrings * _Nonnull strings, uint32_t keyId) {
|
||||
return getSingle(strings, strings->_idToKey[@(keyId)]);
|
||||
}
|
||||
|
||||
static NSString * _Nonnull getPluralized(_PresentationStrings * _Nonnull strings, NSString * _Nonnull key,
|
||||
int32_t value) {
|
||||
NSString *parsedKey = [[NSString alloc] initWithFormat:@"%@%@", key, getPluralizationSuffix(strings, value)];
|
||||
NSString *formatString = getSingle(strings, parsedKey);
|
||||
NSString *stringValue = [[NSString alloc] initWithFormat:@"%d", (int)value];
|
||||
NSString *result = [[NSString alloc] initWithFormat:formatString, stringValue];
|
||||
return result;
|
||||
}
|
||||
|
||||
static NSString * _Nonnull getPluralizedIndirect(_PresentationStrings * _Nonnull strings, uint32_t keyId,
|
||||
int32_t value) {
|
||||
return getPluralized(strings, strings->_idToKey[@(keyId)], value);
|
||||
}''' + formatted_accessors + '''
|
||||
@implementation _PresentationStrings
|
||||
|
||||
- (instancetype _Nonnull)initWithPrimaryComponent:(_PresentationStringsComponent * _Nonnull)primaryComponent
|
||||
secondaryComponent:(_PresentationStringsComponent * _Nullable)secondaryComponent
|
||||
groupingSeparator:(NSString * _Nullable)groupingSeparator {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
static NSDictionary<NSNumber *, NSString *> *idToKey = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSString *dataPath = [[NSBundle mainBundle] pathForResource:@"PresentationStrings" ofType:@"data"];
|
||||
if (!dataPath) {
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
NSData *data = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:dataPath]];
|
||||
if (!data) {
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
if (data.length < 4) {
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableDictionary<NSNumber *, NSString *> *result = [[NSMutableDictionary alloc] init];
|
||||
|
||||
uint32_t entryCount = 0;
|
||||
[data getBytes:&entryCount range:NSMakeRange(0, 4)];
|
||||
|
||||
NSInteger offset = 4;
|
||||
for (uint32_t i = 0; i < entryCount; i++) {
|
||||
uint8_t stringLength = 0;
|
||||
[data getBytes:&stringLength range:NSMakeRange(offset, 1)];
|
||||
offset += 1;
|
||||
|
||||
NSData *stringData = [data subdataWithRange:NSMakeRange(offset, stringLength)];
|
||||
offset += stringLength;
|
||||
|
||||
result[@(i)] = [[NSString alloc] initWithData:stringData encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
idToKey = result;
|
||||
});
|
||||
_idToKey = idToKey;
|
||||
|
||||
_primaryComponent = primaryComponent;
|
||||
_secondaryComponent = secondaryComponent;
|
||||
_groupingSeparator = groupingSeparator;
|
||||
|
||||
if (secondaryComponent) {
|
||||
_baseLanguageCode = secondaryComponent.languageCode;
|
||||
} else {
|
||||
_baseLanguageCode = primaryComponent.languageCode;
|
||||
}
|
||||
|
||||
NSString *languageCode = nil;
|
||||
if (primaryComponent.pluralizationRulesCode) {
|
||||
languageCode = primaryComponent.pluralizationRulesCode;
|
||||
} else {
|
||||
languageCode = primaryComponent.languageCode;
|
||||
}
|
||||
|
||||
NSString *rawCode = languageCode;
|
||||
|
||||
NSRange range = [languageCode rangeOfString:@"_"];
|
||||
if (range.location != NSNotFound) {
|
||||
rawCode = [rawCode substringWithRange:NSMakeRange(0, range.location)];
|
||||
}
|
||||
range = [languageCode rangeOfString:@"-"];
|
||||
if (range.location != NSNotFound) {
|
||||
rawCode = [rawCode substringWithRange:NSMakeRange(0, range.location)];
|
||||
}
|
||||
|
||||
rawCode = [rawCode lowercaseString];
|
||||
|
||||
uint32_t lc = 0;
|
||||
for (NSInteger i = 0; i < rawCode.length; i++) {
|
||||
lc = (lc << 8) + (uint32_t)[rawCode characterAtIndex:i];
|
||||
}
|
||||
_lc = lc;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
''')
|
||||
|
||||
counter = IndexCounter()
|
||||
|
||||
entry_keys = []
|
||||
|
||||
for entry in entries:
|
||||
entry_id = '_L' + counter.get_next_valid_id()
|
||||
write_string(header_file, '// {}'.format(entry.name))
|
||||
|
||||
entry_key_id = len(entry_keys)
|
||||
entry_keys.append(entry.name)
|
||||
|
||||
write_string(source_file, '// {}'.format(entry.name))
|
||||
|
||||
function_arguments = ''
|
||||
format_arguments_array = ''
|
||||
if entry.is_pluralized:
|
||||
swift_spec = 'PresentationStrings.{}(self:_:)'.format(sanitize_entry_identifer(entry.name))
|
||||
function_return_spec = 'NSString * _Nonnull'
|
||||
swift_spec = '_PresentationStrings.{}(self:_:)'.format(sanitize_entry_identifer(entry.name))
|
||||
function_arguments = ', int32_t value'
|
||||
elif len(entry.positional_arguments) != 0:
|
||||
function_return_spec = '_FormattedString * _Nonnull'
|
||||
positional_arguments_spec = ''
|
||||
argument_index = -1
|
||||
for argument in entry.positional_arguments:
|
||||
argument_index += 1
|
||||
format_arguments_array += ', '
|
||||
if argument.kind == 'd':
|
||||
function_arguments += ', int32_t _{}'.format(argument_index)
|
||||
function_arguments += ', NSInteger _{}'.format(argument_index)
|
||||
format_arguments_array += '@(_{})'\
|
||||
.format(argument_index)
|
||||
elif argument.kind == '@':
|
||||
function_arguments += ', NSString * _Nonnull _{}'.format(argument_index)
|
||||
format_arguments_array += '_{}'.format(argument_index)
|
||||
else:
|
||||
raise Exception('Unsupported argument type {}'.format(argument.kind))
|
||||
positional_arguments_spec += '_:'
|
||||
swift_spec = 'PresentationStrings.{}(self:{})'.format(
|
||||
swift_spec = '_PresentationStrings.{}(self:{})'.format(
|
||||
sanitize_entry_identifer(entry.name), positional_arguments_spec)
|
||||
else:
|
||||
swift_spec = 'getter:PresentationStrings.{}(self:)'.format(sanitize_entry_identifer(entry.name))
|
||||
# write_string(header_file, '__attribute__((swift_name("{}")))'
|
||||
# .format(swift_spec))
|
||||
write_string(header_file, 'NSString * _Nonnull {}(PresentationStrings * _Nonnull _self);'.format(
|
||||
entry_id, function_arguments))
|
||||
function_return_spec = 'NSString * _Nonnull'
|
||||
swift_spec = 'getter:_PresentationStrings.{}(self:)'.format(sanitize_entry_identifer(entry.name))
|
||||
|
||||
write_string(test_file, '{}(strings);'.format(entry_id))
|
||||
write_string(test_file, '{}(strings);'.format(entry_id))
|
||||
write_string(test_file, '{}(strings);'.format(entry_id))
|
||||
function_spec = '{} {}'.format(function_return_spec, entry_id)
|
||||
function_spec += '(_PresentationStrings * _Nonnull _self{})'.format(function_arguments)
|
||||
|
||||
write_string(source_file, 'NSString * _Nonnull {}(PresentationStrings * _Nonnull _self) {{'.format(
|
||||
entry_id, function_arguments))
|
||||
write_string(source_file, ' return @"";'.format(entry_id))
|
||||
write_string(source_file, '}')
|
||||
write_string(source_file, ''.format(entry_id))
|
||||
write_string(test_file, ' return 0;')
|
||||
write_string(test_file, '}')
|
||||
write_string(test_file, '')
|
||||
write_string(header_file, '{function_spec} __attribute__((__swift_name__("{swift_spec}")));'.format(
|
||||
function_spec=function_spec, swift_spec=swift_spec))
|
||||
|
||||
if entry.is_pluralized:
|
||||
write_string(source_file, function_spec + ''' {{
|
||||
return getPluralizedIndirect(_self, {entry_key_id}, value);
|
||||
}}'''.format(key=entry.name, entry_key_id=entry_key_id))
|
||||
elif len(entry.positional_arguments) != 0:
|
||||
write_string(source_file, function_spec + ''' {{
|
||||
return getFormatted{argument_count}(_self, {key_id}{arguments_array});
|
||||
}}'''.format(key_id=entry_key_id, argument_count=len(entry.positional_arguments), arguments_array=format_arguments_array))
|
||||
else:
|
||||
write_string(source_file, function_spec + ''' {{
|
||||
return getSingleIndirect(_self, {entry_key_id});
|
||||
}}'''.format(key=entry.name, entry_key_id=entry_key_id))
|
||||
|
||||
write_bin_uint32(data_file, len(entry_keys))
|
||||
for entry_key in entry_keys:
|
||||
write_bin_uint8(data_file, len(entry_key))
|
||||
write_bin_string(data_file, entry_key)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
@ -276,6 +643,12 @@ if __name__ == '__main__':
|
|||
help='Path to PresentationStrings.h',
|
||||
metavar='path'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--outData',
|
||||
required=True,
|
||||
help='Path to PresentationStrings.data',
|
||||
metavar='path'
|
||||
)
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
parser.print_help()
|
||||
|
|
@ -285,4 +658,5 @@ if __name__ == '__main__':
|
|||
|
||||
parsed_strings = parse_strings(args.source)
|
||||
all_entries = parse_entries(parsed_strings)
|
||||
generate(header_path=args.outHeader, implementation_path=args.outImplementation, entries=all_entries)
|
||||
generate(header_path=args.outHeader, implementation_path=args.outImplementation, data_path=args.outData,
|
||||
entries=all_entries)
|
||||
|
|
|
|||
|
|
@ -30,13 +30,13 @@ public func authorizationNextOptionText(currentType: SentAuthorizationCodeType,
|
|||
return (NSAttributedString(string: strings.Login_CodeSentSms, font: Font.regular(16.0), textColor: primaryColor, paragraphAlignment: .center), false)
|
||||
} else {
|
||||
let timeString = NSString(format: "%d:%.02d", Int(minutes), Int(seconds))
|
||||
return (NSAttributedString(string: strings.Login_WillSendSms(timeString as String).0, font: Font.regular(16.0), textColor: primaryColor, paragraphAlignment: .center), false)
|
||||
return (NSAttributedString(string: strings.Login_WillSendSms(timeString as String).string, font: Font.regular(16.0), textColor: primaryColor, paragraphAlignment: .center), false)
|
||||
}
|
||||
case .call, .flashCall:
|
||||
if timeout <= 0 {
|
||||
return (NSAttributedString(string: strings.ChangePhoneNumberCode_Called, font: Font.regular(16.0), textColor: primaryColor, paragraphAlignment: .center), false)
|
||||
} else {
|
||||
return (NSAttributedString(string: String(format: strings.ChangePhoneNumberCode_CallTimer(String(format: "%d:%.2d", minutes, seconds)).0, minutes, seconds), font: Font.regular(16.0), textColor: primaryColor, paragraphAlignment: .center), false)
|
||||
return (NSAttributedString(string: String(format: strings.ChangePhoneNumberCode_CallTimer(String(format: "%d:%.2d", minutes, seconds)).string, minutes, seconds), font: Font.regular(16.0), textColor: primaryColor, paragraphAlignment: .center), false)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -971,7 +971,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
|
|||
let totalAmount = currentTotalPrice(paymentForm: self.paymentFormValue, validatedFormInfo: self.currentValidatedFormInfo, currentShippingOptionId: self.currentShippingOptionId, currentTip: self.currentTipAmount)
|
||||
let payString: String
|
||||
if let paymentForm = self.paymentFormValue, totalAmount > 0 {
|
||||
payString = self.presentationData.strings.Checkout_PayPrice(formatCurrencyAmount(totalAmount, currency: paymentForm.invoice.currency)).0
|
||||
payString = self.presentationData.strings.Checkout_PayPrice(formatCurrencyAmount(totalAmount, currency: paymentForm.invoice.currency)).string
|
||||
} else {
|
||||
payString = self.presentationData.strings.CheckoutInfo_Pay
|
||||
}
|
||||
|
|
@ -1324,12 +1324,12 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
|
|||
let alertText: String
|
||||
if requiresBiometrics {
|
||||
if let biometricAuthentication = LocalAuth.biometricAuthentication, case .faceId = biometricAuthentication {
|
||||
alertText = strongSelf.presentationData.strings.Checkout_SavePasswordTimeoutAndFaceId(durationString).0
|
||||
alertText = strongSelf.presentationData.strings.Checkout_SavePasswordTimeoutAndFaceId(durationString).string
|
||||
} else {
|
||||
alertText = strongSelf.presentationData.strings.Checkout_SavePasswordTimeoutAndTouchId(durationString).0
|
||||
alertText = strongSelf.presentationData.strings.Checkout_SavePasswordTimeoutAndTouchId(durationString).string
|
||||
}
|
||||
} else {
|
||||
alertText = strongSelf.presentationData.strings.Checkout_SavePasswordTimeout(durationString).0
|
||||
alertText = strongSelf.presentationData.strings.Checkout_SavePasswordTimeout(durationString).string
|
||||
}
|
||||
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: alertText, actions: [
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ private final class BotCheckoutPasswordAlertContentNode: AlertContentNode {
|
|||
self.titleNode = titleNode
|
||||
|
||||
self.textNode = ASTextNode()
|
||||
self.textNode.attributedText = NSAttributedString(string: strings.Checkout_PasswordEntry_Text(cardTitle).0, font: Font.regular(13.0), textColor: theme.actionSheet.primaryTextColor, paragraphAlignment: .center)
|
||||
self.textNode.attributedText = NSAttributedString(string: strings.Checkout_PasswordEntry_Text(cardTitle).string, font: Font.regular(13.0), textColor: theme.actionSheet.primaryTextColor, paragraphAlignment: .center)
|
||||
self.textNode.displaysAsynchronously = false
|
||||
self.textNode.isUserInteractionEnabled = false
|
||||
|
||||
|
|
|
|||
|
|
@ -438,8 +438,8 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
|||
statusAccessibilityString = isVideo ? (item.presentationData.strings.Call_VoiceOver_VideoCallOutgoing + ", " + item.presentationData.strings.Call_VoiceOver_VideoCallIncoming) : (item.presentationData.strings.Call_VoiceOver_VoiceCallOutgoing + ", " + item.presentationData.strings.Call_VoiceOver_VoiceCallIncoming)
|
||||
} else if hasIncoming {
|
||||
if let callDuration = callDuration, callDuration != 0 {
|
||||
statusAttributedString = NSAttributedString(string: item.presentationData.strings.Notification_CallTimeFormat(item.presentationData.strings.Notification_CallIncomingShort, callDurationString(strings: item.presentationData.strings, duration: callDuration)).0, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
statusAccessibilityString = item.presentationData.strings.Notification_CallTimeFormat(isVideo ? item.presentationData.strings.Call_VoiceOver_VideoCallIncoming : item.presentationData.strings.Call_VoiceOver_VoiceCallIncoming, callDurationString(strings: item.presentationData.strings, duration: callDuration)).0
|
||||
statusAttributedString = NSAttributedString(string: item.presentationData.strings.Notification_CallTimeFormat(item.presentationData.strings.Notification_CallIncomingShort, callDurationString(strings: item.presentationData.strings, duration: callDuration)).string, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
statusAccessibilityString = item.presentationData.strings.Notification_CallTimeFormat(isVideo ? item.presentationData.strings.Call_VoiceOver_VideoCallIncoming : item.presentationData.strings.Call_VoiceOver_VoiceCallIncoming, callDurationString(strings: item.presentationData.strings, duration: callDuration)).string
|
||||
|
||||
} else {
|
||||
statusAttributedString = NSAttributedString(string: item.presentationData.strings.Notification_CallIncomingShort, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
|
|
@ -447,8 +447,8 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
|||
}
|
||||
} else {
|
||||
if let callDuration = callDuration, callDuration != 0 {
|
||||
statusAttributedString = NSAttributedString(string: item.presentationData.strings.Notification_CallTimeFormat(item.presentationData.strings.Notification_CallOutgoingShort, callDurationString(strings: item.presentationData.strings, duration: callDuration)).0, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
statusAccessibilityString = item.presentationData.strings.Notification_CallTimeFormat(isVideo ? item.presentationData.strings.Call_VoiceOver_VideoCallOutgoing : item.presentationData.strings.Call_VoiceOver_VoiceCallOutgoing, callDurationString(strings: item.presentationData.strings, duration: callDuration)).0
|
||||
statusAttributedString = NSAttributedString(string: item.presentationData.strings.Notification_CallTimeFormat(item.presentationData.strings.Notification_CallOutgoingShort, callDurationString(strings: item.presentationData.strings, duration: callDuration)).string, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
statusAccessibilityString = item.presentationData.strings.Notification_CallTimeFormat(isVideo ? item.presentationData.strings.Call_VoiceOver_VideoCallOutgoing : item.presentationData.strings.Call_VoiceOver_VoiceCallOutgoing, callDurationString(strings: item.presentationData.strings, duration: callDuration)).string
|
||||
} else {
|
||||
statusAttributedString = NSAttributedString(string: item.presentationData.strings.Notification_CallOutgoingShort, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
statusAccessibilityString = isVideo ? item.presentationData.strings.Call_VoiceOver_VideoCallOutgoing : item.presentationData.strings.Call_VoiceOver_VoiceCallOutgoing
|
||||
|
|
|
|||
|
|
@ -449,7 +449,7 @@ public final class CallListController: TelegramBaseController {
|
|||
if let cachedUserData = view.cachedData as? CachedUserData, cachedUserData.callsPrivate {
|
||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, title: presentationData.strings.Call_ConnectionErrorTitle, text: presentationData.strings.Call_PrivacyErrorMessage(peer.compactDisplayTitle).0, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, title: presentationData.strings.Call_ConnectionErrorTitle, text: presentationData.strings.Call_PrivacyErrorMessage(peer.compactDisplayTitle).string, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ final class CallListControllerNode: ASDisplayNode {
|
|||
self.listNode = ListView()
|
||||
self.listNode.verticalScrollIndicatorColor = self.presentationData.theme.list.scrollIndicatorColor
|
||||
self.listNode.accessibilityPageScrolledString = { row, count in
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
self.leftOverlayNode = ASDisplayNode()
|
||||
|
|
@ -338,7 +338,7 @@ final class CallListControllerNode: ASDisplayNode {
|
|||
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
|
||||
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_DeleteMessagesFor(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).0, color: .destructive, action: { [weak actionSheet] in
|
||||
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_DeleteMessagesFor(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string, color: .destructive, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ public final class ChatListSearchRecentPeersNode: ASDisplayNode {
|
|||
self.listView = ListView()
|
||||
self.listView.transform = CATransform3DMakeRotation(-CGFloat.pi / 2.0, 0.0, 0.0, 1.0)
|
||||
self.listView.accessibilityPageScrolledString = { row, count in
|
||||
return strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
super.init()
|
||||
|
|
|
|||
|
|
@ -2340,7 +2340,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||
beginClear(.forLocalPeer)
|
||||
actionSheet?.dismissAnimated()
|
||||
}))
|
||||
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.ChatList_DeleteForEveryone(mainPeer.compactDisplayTitle).0, color: .destructive, action: { [weak actionSheet] in
|
||||
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.ChatList_DeleteForEveryone(mainPeer.compactDisplayTitle).string, color: .destructive, action: { [weak actionSheet] in
|
||||
beginClear(.forEveryone)
|
||||
actionSheet?.dismissAnimated()
|
||||
}))
|
||||
|
|
@ -2369,7 +2369,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||
}
|
||||
|
||||
if chatPeer is TelegramSecretChat {
|
||||
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.ChatList_DeleteForEveryone(mainPeer.compactDisplayTitle).0, color: .destructive, action: { [weak actionSheet] in
|
||||
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.ChatList_DeleteForEveryone(mainPeer.compactDisplayTitle).string, color: .destructive, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
|
|
@ -2511,7 +2511,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||
})
|
||||
completion(true)
|
||||
}))
|
||||
items.append(ActionSheetButtonItem(title: self.presentationData.strings.ChatList_DeleteForEveryone(mainPeer.compactDisplayTitle).0, color: .destructive, action: { [weak self, weak actionSheet] in
|
||||
items.append(ActionSheetButtonItem(title: self.presentationData.strings.ChatList_DeleteForEveryone(mainPeer.compactDisplayTitle).string, color: .destructive, action: { [weak self, weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -369,7 +369,7 @@ private final class ChatListContainerItemNode: ASDisplayNode {
|
|||
self.presentationData = presentationData
|
||||
|
||||
self.listNode.accessibilityPageScrolledString = { row, count in
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
self.listNode.updateThemeAndStrings(theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: true)
|
||||
|
|
|
|||
|
|
@ -841,7 +841,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
|||
if isChannel {
|
||||
globalTitle = strongSelf.presentationData.strings.Conversation_DeleteMessagesForMe
|
||||
} else if let personalPeerName = personalPeerName {
|
||||
globalTitle = strongSelf.presentationData.strings.Conversation_DeleteMessagesFor(personalPeerName).0
|
||||
globalTitle = strongSelf.presentationData.strings.Conversation_DeleteMessagesFor(personalPeerName).string
|
||||
} else {
|
||||
globalTitle = strongSelf.presentationData.strings.Conversation_DeleteMessagesForEveryone
|
||||
}
|
||||
|
|
@ -967,14 +967,14 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
|||
} else {
|
||||
if peers.count == 1, let peer = peers.first {
|
||||
let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).0 : presentationData.strings.Conversation_ForwardTooltip_Chat_Many(peerName).0
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).string : presentationData.strings.Conversation_ForwardTooltip_Chat_Many(peerName).string
|
||||
} else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last {
|
||||
let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).0 : presentationData.strings.Conversation_ForwardTooltip_TwoChats_Many(firstPeerName, secondPeerName).0
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string : presentationData.strings.Conversation_ForwardTooltip_TwoChats_Many(firstPeerName, secondPeerName).string
|
||||
} else if let peer = peers.first {
|
||||
let peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").0 : presentationData.strings.Conversation_ForwardTooltip_ManyChats_Many(peerName, "\(peers.count - 1)").0
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").string : presentationData.strings.Conversation_ForwardTooltip_ManyChats_Many(peerName, "\(peers.count - 1)").string
|
||||
} else {
|
||||
text = ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -746,7 +746,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||
self.recentListNode = ListView()
|
||||
self.recentListNode.verticalScrollIndicatorColor = self.presentationData.theme.list.scrollIndicatorColor
|
||||
self.recentListNode.accessibilityPageScrolledString = { row, count in
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
self.shimmerNode = ChatListSearchShimmerNode(key: key)
|
||||
|
|
@ -756,7 +756,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||
self.listNode = ListView()
|
||||
self.listNode.verticalScrollIndicatorColor = self.presentationData.theme.list.scrollIndicatorColor
|
||||
self.listNode.accessibilityPageScrolledString = { row, count in
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
var openMediaMessageImpl: ((Message, ChatControllerInteractionOpenMessageMode) -> Void)?
|
||||
|
|
@ -2077,7 +2077,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||
let emptyResultsText: String
|
||||
if let query = transition.query, !query.isEmpty {
|
||||
emptyResultsTitle = strongSelf.presentationData.strings.ChatList_Search_NoResults
|
||||
emptyResultsText = strongSelf.presentationData.strings.ChatList_Search_NoResultsQueryDescription(query).0
|
||||
emptyResultsText = strongSelf.presentationData.strings.ChatList_Search_NoResultsQueryDescription(query).string
|
||||
} else {
|
||||
if let searchOptions = searchOptions, searchOptions.date == nil && searchOptions.peer == nil {
|
||||
emptyResultsTitle = strongSelf.presentationData.strings.ChatList_Search_NoResultsFilter
|
||||
|
|
|
|||
|
|
@ -520,7 +520,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||
}
|
||||
let (_, initialHideAuthor, messageText) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: messages, chatPeer: peer, accountPeerId: item.context.account.peerId, isPeerGroup: false)
|
||||
if message.flags.contains(.Incoming), !initialHideAuthor, let author = message.author, author is TelegramUser {
|
||||
result += "\n\(item.presentationData.strings.VoiceOver_ChatList_MessageFrom(author.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)).0)"
|
||||
result += "\n\(item.presentationData.strings.VoiceOver_ChatList_MessageFrom(author.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)).string)"
|
||||
}
|
||||
result += "\n\(messageText)"
|
||||
return result
|
||||
|
|
@ -554,7 +554,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||
}
|
||||
let (_, initialHideAuthor, messageText) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: messages, chatPeer: peer, accountPeerId: item.context.account.peerId, isPeerGroup: false)
|
||||
if message.flags.contains(.Incoming), !initialHideAuthor, let author = message.author, author is TelegramUser {
|
||||
result += "\n\(item.presentationData.strings.VoiceOver_ChatList_MessageFrom(author.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)).0)"
|
||||
result += "\n\(item.presentationData.strings.VoiceOver_ChatList_MessageFrom(author.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)).string)"
|
||||
}
|
||||
if !message.flags.contains(.Incoming), let combinedReadState = combinedReadState, combinedReadState.isOutgoingMessageIndexRead(message.index) {
|
||||
result += "\n\(item.presentationData.strings.VoiceOver_ChatList_MessageRead)"
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder:
|
|||
processed = true
|
||||
break inner
|
||||
} else {
|
||||
messageText = strings.Message_StickerText(displayText).0
|
||||
messageText = strings.Message_StickerText(displayText).string
|
||||
processed = true
|
||||
break inner
|
||||
}
|
||||
|
|
@ -288,16 +288,16 @@ public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder:
|
|||
case .active:
|
||||
switch secretChat.role {
|
||||
case .creator:
|
||||
messageText = strings.DialogList_EncryptedChatStartedOutgoing(peer?.compactDisplayTitle ?? "").0
|
||||
messageText = strings.DialogList_EncryptedChatStartedOutgoing(peer?.compactDisplayTitle ?? "").string
|
||||
case .participant:
|
||||
messageText = strings.DialogList_EncryptedChatStartedIncoming(peer?.compactDisplayTitle ?? "").0
|
||||
messageText = strings.DialogList_EncryptedChatStartedIncoming(peer?.compactDisplayTitle ?? "").string
|
||||
}
|
||||
case .terminated:
|
||||
messageText = strings.DialogList_EncryptionRejected
|
||||
case .handshake:
|
||||
switch secretChat.role {
|
||||
case .creator:
|
||||
messageText = strings.DialogList_AwaitingEncryption(peer?.compactDisplayTitle ?? "").0
|
||||
messageText = strings.DialogList_AwaitingEncryption(peer?.compactDisplayTitle ?? "").string
|
||||
case .participant:
|
||||
messageText = strings.DialogList_EncryptionProcessing
|
||||
}
|
||||
|
|
|
|||
|
|
@ -714,7 +714,7 @@ public final class ChatListNode: ListView {
|
|||
if chatListFilter != nil {
|
||||
text = strongSelf.currentState.presentationData.strings.DialogList_UnknownPinLimitError
|
||||
} else {
|
||||
text = strongSelf.currentState.presentationData.strings.DialogList_PinLimitError("\(maxCount)").0
|
||||
text = strongSelf.currentState.presentationData.strings.DialogList_PinLimitError("\(maxCount)").string
|
||||
}
|
||||
strongSelf.presentAlert?(text)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,21 +85,21 @@ final class ChatListInputActivitiesNode: ASDisplayNode {
|
|||
let peerTitle = activities[0].0.compactDisplayTitle
|
||||
switch activities[0].1 {
|
||||
case .uploadingVideo:
|
||||
text = strings.DialogList_SingleUploadingVideoSuffix(peerTitle).0
|
||||
text = strings.DialogList_SingleUploadingVideoSuffix(peerTitle).string
|
||||
case .uploadingInstantVideo:
|
||||
text = strings.DialogList_SingleUploadingVideoSuffix(peerTitle).0
|
||||
text = strings.DialogList_SingleUploadingVideoSuffix(peerTitle).string
|
||||
case .uploadingPhoto:
|
||||
text = strings.DialogList_SingleUploadingPhotoSuffix(peerTitle).0
|
||||
text = strings.DialogList_SingleUploadingPhotoSuffix(peerTitle).string
|
||||
case .uploadingFile:
|
||||
text = strings.DialogList_SingleUploadingFileSuffix(peerTitle).0
|
||||
text = strings.DialogList_SingleUploadingFileSuffix(peerTitle).string
|
||||
case .recordingVoice:
|
||||
text = strings.DialogList_SingleRecordingAudioSuffix(peerTitle).0
|
||||
text = strings.DialogList_SingleRecordingAudioSuffix(peerTitle).string
|
||||
case .recordingInstantVideo:
|
||||
text = strings.DialogList_SingleRecordingVideoMessageSuffix(peerTitle).0
|
||||
text = strings.DialogList_SingleRecordingVideoMessageSuffix(peerTitle).string
|
||||
case .playingGame:
|
||||
text = strings.DialogList_SinglePlayingGameSuffix(peerTitle).0
|
||||
text = strings.DialogList_SinglePlayingGameSuffix(peerTitle).string
|
||||
case .typingText:
|
||||
text = strings.DialogList_SingleTypingSuffix(peerTitle).0
|
||||
text = strings.DialogList_SingleTypingSuffix(peerTitle).string
|
||||
case .speakingInGroupCall:
|
||||
text = ""
|
||||
}
|
||||
|
|
@ -129,12 +129,12 @@ final class ChatListInputActivitiesNode: ASDisplayNode {
|
|||
let peerTitle = activities[0].0.compactDisplayTitle
|
||||
if activities.count == 2 {
|
||||
let secondPeerTitle = activities[1].0.compactDisplayTitle
|
||||
string = NSAttributedString(string: strings.DialogList_MultipleTypingPair(peerTitle, secondPeerTitle).0, font: textFont, textColor: color)
|
||||
string = NSAttributedString(string: strings.DialogList_MultipleTypingPair(peerTitle, secondPeerTitle).string, font: textFont, textColor: color)
|
||||
} else {
|
||||
string = NSAttributedString(string: strings.DialogList_MultipleTyping(peerTitle, strings.DialogList_MultipleTypingSuffix(activities.count - 1).0).0, font: textFont, textColor: color)
|
||||
string = NSAttributedString(string: strings.DialogList_MultipleTyping(peerTitle, strings.DialogList_MultipleTypingSuffix(activities.count - 1).string).string, font: textFont, textColor: color)
|
||||
}
|
||||
} else {
|
||||
string = NSAttributedString(string: strings.DialogList_MultipleTypingSuffix(activities.count).0, font: textFont, textColor: color)
|
||||
string = NSAttributedString(string: strings.DialogList_MultipleTypingSuffix(activities.count).string, font: textFont, textColor: color)
|
||||
}
|
||||
state = .typingText(string, lightColor)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ class ContactsAddItemNode: ListViewItemNode {
|
|||
let leftInset: CGFloat = 65.0 + params.leftInset
|
||||
let rightInset: CGFloat = 10.0 + params.rightInset
|
||||
|
||||
let titleAttributedString = NSAttributedString(string: item.strings.Contacts_AddPhoneNumber(formatPhoneNumber(item.phoneNumber)).0, font: titleFont, textColor: item.theme.list.itemAccentColor)
|
||||
let titleAttributedString = NSAttributedString(string: item.strings.Contacts_AddPhoneNumber(formatPhoneNumber(item.phoneNumber)).string, font: titleFont, textColor: item.theme.list.itemAccentColor)
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: max(0.0, params.width - leftInset - rightInset), height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
|
|
|
|||
|
|
@ -889,7 +889,7 @@ public final class ContactListNode: ASDisplayNode {
|
|||
self.listNode = ListView()
|
||||
self.listNode.dynamicBounceEnabled = false
|
||||
self.listNode.accessibilityPageScrolledString = { row, count in
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
self.indexNode = CollectionIndexNode()
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo
|
|||
self.listNode.backgroundColor = self.presentationData.theme.list.plainBackgroundColor
|
||||
self.listNode.isHidden = true
|
||||
self.listNode.accessibilityPageScrolledString = { row, count in
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
super.init()
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ public class InviteContactsController: ViewController, MFMessageComposeViewContr
|
|||
self.contactsNode.requestShareTelegram = { [weak self] in
|
||||
if let strongSelf = self {
|
||||
let url = strongSelf.presentationData.strings.InviteText_URL
|
||||
let body = strongSelf.presentationData.strings.InviteText_SingleContact(url).0
|
||||
let body = strongSelf.presentationData.strings.InviteText_SingleContact(url).string
|
||||
presentExternalShare(context: strongSelf.context, text: body, parentController: strongSelf)
|
||||
|
||||
strongSelf.contactsNode.listNode.clearHighlightAnimated(true)
|
||||
|
|
@ -149,7 +149,7 @@ public class InviteContactsController: ViewController, MFMessageComposeViewContr
|
|||
composer.messageComposeDelegate = strongSelf
|
||||
composer.recipients = Array(Set(recipients))
|
||||
let url = strongSelf.presentationData.strings.InviteText_URL
|
||||
var body = strongSelf.presentationData.strings.InviteText_SingleContact(url).0
|
||||
var body = strongSelf.presentationData.strings.InviteText_SingleContact(url).string
|
||||
if numbers.count == 1, numbers[0].1 > 0 {
|
||||
body = strongSelf.presentationData.strings.InviteText_ContactsCountText(numbers[0].1)
|
||||
body = body.replacingOccurrences(of: "{url}", with: url)
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ final class InviteContactsControllerNode: ASDisplayNode {
|
|||
|
||||
self.listNode = ListView()
|
||||
self.listNode.accessibilityPageScrolledString = { row, count in
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
var shareImpl: (() -> Void)?
|
||||
|
|
|
|||
|
|
@ -103,11 +103,11 @@ private final class DeleteChatPeerActionSheetItemNode: ActionSheetItemNode {
|
|||
break
|
||||
}
|
||||
default:
|
||||
var text: (String, [(Int, NSRange)])?
|
||||
var text: PresentationStrings.FormattedString?
|
||||
switch action {
|
||||
case .delete:
|
||||
if chatPeer.id == context.account.peerId {
|
||||
text = (strings.ChatList_DeleteSavedMessagesConfirmation, [])
|
||||
text = PresentationStrings.FormattedString(string: strings.ChatList_DeleteSavedMessagesConfirmation, ranges: [])
|
||||
} else if let chatPeer = chatPeer as? TelegramGroup {
|
||||
text = strings.ChatList_LeaveGroupConfirmation(chatPeer.title)
|
||||
} else if let chatPeer = chatPeer as? TelegramChannel {
|
||||
|
|
@ -119,7 +119,7 @@ private final class DeleteChatPeerActionSheetItemNode: ActionSheetItemNode {
|
|||
}
|
||||
case .deleteAndLeave:
|
||||
if chatPeer.id == context.account.peerId {
|
||||
text = (strings.ChatList_DeleteSavedMessagesConfirmation, [])
|
||||
text = PresentationStrings.FormattedString(string: strings.ChatList_DeleteSavedMessagesConfirmation, ranges: [])
|
||||
} else if let chatPeer = chatPeer as? TelegramGroup {
|
||||
text = strings.ChatList_DeleteAndLeaveGroupConfirmation(chatPeer.title)
|
||||
} else if let chatPeer = chatPeer as? TelegramChannel {
|
||||
|
|
@ -131,7 +131,7 @@ private final class DeleteChatPeerActionSheetItemNode: ActionSheetItemNode {
|
|||
}
|
||||
case let .clearHistory(canClearCache):
|
||||
if peer.id == context.account.peerId {
|
||||
text = (strings.ChatList_DeleteSavedMessagesConfirmation, [])
|
||||
text = PresentationStrings.FormattedString(string: strings.ChatList_DeleteSavedMessagesConfirmation, ranges: [])
|
||||
} else if peer is TelegramUser {
|
||||
text = strings.ChatList_ClearChatConfirmation(peer.displayTitle(strings: strings, displayOrder: nameOrder))
|
||||
} else {
|
||||
|
|
@ -139,7 +139,9 @@ private final class DeleteChatPeerActionSheetItemNode: ActionSheetItemNode {
|
|||
}
|
||||
|
||||
if canClearCache {
|
||||
text?.0 += "\n\n\(strings.Conversation_AlsoClearCacheTitle)"
|
||||
if let textValue = text {
|
||||
text = PresentationStrings.FormattedString(string: textValue.string + "\n\n\(strings.Conversation_AlsoClearCacheTitle)", ranges: textValue.ranges)
|
||||
}
|
||||
}
|
||||
case .removeFromGroup:
|
||||
text = strings.VoiceChat_RemoveAndBanPeerConfirmation(peer.displayTitle(strings: strings, displayOrder: nameOrder), chatPeer.displayTitle(strings: strings, displayOrder: nameOrder))
|
||||
|
|
@ -149,9 +151,9 @@ private final class DeleteChatPeerActionSheetItemNode: ActionSheetItemNode {
|
|||
break
|
||||
}
|
||||
if let text = text {
|
||||
let formattedAttributedText = NSMutableAttributedString(attributedString: NSAttributedString(string: text.0, font: textFont, textColor: theme.primaryTextColor))
|
||||
for (_, range) in text.1 {
|
||||
formattedAttributedText.addAttribute(.font, value: boldFont, range: range)
|
||||
let formattedAttributedText = NSMutableAttributedString(attributedString: NSAttributedString(string: text.string, font: textFont, textColor: theme.primaryTextColor))
|
||||
for range in text.ranges {
|
||||
formattedAttributedText.addAttribute(.font, value: boldFont, range: range.range)
|
||||
}
|
||||
attributedText = formattedAttributedText
|
||||
}
|
||||
|
|
|
|||
|
|
@ -527,7 +527,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
|||
|
||||
func setup(origin: GalleryItemOriginData?, caption: NSAttributedString) {
|
||||
let titleText = origin?.title
|
||||
let dateText = origin?.timestamp.flatMap { humanReadableStringForTimestamp(strings: self.strings, dateTimeFormat: self.dateTimeFormat, timestamp: $0).0 }
|
||||
let dateText = origin?.timestamp.flatMap { humanReadableStringForTimestamp(strings: self.strings, dateTimeFormat: self.dateTimeFormat, timestamp: $0).string }
|
||||
|
||||
if self.currentMessageText != caption || self.currentAuthorNameText != titleText || self.currentDateText != dateText {
|
||||
self.currentMessageText = caption
|
||||
|
|
@ -610,7 +610,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
|||
authorNameText = peer.displayTitle(strings: self.strings, displayOrder: self.nameOrder)
|
||||
}
|
||||
|
||||
var dateText = humanReadableStringForTimestamp(strings: self.strings, dateTimeFormat: self.dateTimeFormat, timestamp: message.timestamp).0
|
||||
var dateText = humanReadableStringForTimestamp(strings: self.strings, dateTimeFormat: self.dateTimeFormat, timestamp: message.timestamp).string
|
||||
if !displayInfo {
|
||||
authorNameText = ""
|
||||
dateText = ""
|
||||
|
|
@ -991,7 +991,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
|||
if isChannel {
|
||||
globalTitle = strongSelf.strings.Common_Delete
|
||||
} else if let personalPeerName = personalPeerName {
|
||||
globalTitle = strongSelf.strings.Conversation_DeleteMessagesFor(personalPeerName).0
|
||||
globalTitle = strongSelf.strings.Conversation_DeleteMessagesFor(personalPeerName).string
|
||||
} else {
|
||||
globalTitle = strongSelf.strings.Conversation_DeleteMessagesForEveryone
|
||||
}
|
||||
|
|
@ -1153,14 +1153,14 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
|||
} else {
|
||||
if peers.count == 1, let peer = peers.first {
|
||||
let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).0 : presentationData.strings.Conversation_ForwardTooltip_Chat_Many(peerName).0
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).string : presentationData.strings.Conversation_ForwardTooltip_Chat_Many(peerName).string
|
||||
} else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last {
|
||||
let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).0 : presentationData.strings.Conversation_ForwardTooltip_TwoChats_Many(firstPeerName, secondPeerName).0
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string : presentationData.strings.Conversation_ForwardTooltip_TwoChats_Many(firstPeerName, secondPeerName).string
|
||||
} else if let peer = peers.first {
|
||||
let peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").0 : presentationData.strings.Conversation_ForwardTooltip_ManyChats_Many(peerName, "\(peers.count - 1)").0
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").string : presentationData.strings.Conversation_ForwardTooltip_ManyChats_Many(peerName, "\(peers.count - 1)").string
|
||||
} else {
|
||||
text = ""
|
||||
}
|
||||
|
|
@ -1217,14 +1217,14 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
|||
} else {
|
||||
if peers.count == 1, let peer = peers.first {
|
||||
let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).0 : presentationData.strings.Conversation_ForwardTooltip_Chat_Many(peerName).0
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).string : presentationData.strings.Conversation_ForwardTooltip_Chat_Many(peerName).string
|
||||
} else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last {
|
||||
let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).0 : presentationData.strings.Conversation_ForwardTooltip_TwoChats_Many(firstPeerName, secondPeerName).0
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string : presentationData.strings.Conversation_ForwardTooltip_TwoChats_Many(firstPeerName, secondPeerName).string
|
||||
} else if let peer = peers.first {
|
||||
let peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").0 : presentationData.strings.Conversation_ForwardTooltip_ManyChats_Many(peerName, "\(peers.count - 1)").0
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").string : presentationData.strings.Conversation_ForwardTooltip_ManyChats_Many(peerName, "\(peers.count - 1)").string
|
||||
} else {
|
||||
text = ""
|
||||
}
|
||||
|
|
@ -1342,14 +1342,14 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
|||
} else {
|
||||
if peers.count == 1, let peer = peers.first {
|
||||
let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
text = presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).0
|
||||
text = presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).string
|
||||
} else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last {
|
||||
let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
text = presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).0
|
||||
text = presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string
|
||||
} else if let peer = peers.first {
|
||||
let peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
text = presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").0
|
||||
text = presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").string
|
||||
} else {
|
||||
text = ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ final class ChatVideoGalleryItemScrubberView: UIView {
|
|||
case .Remote:
|
||||
text = dataSizeString(fileSize, forceDecimal: true, formatting: formatting)
|
||||
case let .Fetching(_, progress):
|
||||
text = strings.DownloadingStatus(dataSizeString(Int64(Float(fileSize) * progress), forceDecimal: true, formatting: formatting), dataSizeString(fileSize, forceDecimal: true, formatting: formatting)).0
|
||||
text = strings.DownloadingStatus(dataSizeString(Int64(Float(fileSize) * progress), forceDecimal: true, formatting: formatting), dataSizeString(fileSize, forceDecimal: true, formatting: formatting)).string
|
||||
default:
|
||||
text = ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ final class GalleryTitleView: UIView, NavigationBarTitleView {
|
|||
|
||||
func setMessage(_ message: Message, presentationData: PresentationData, accountPeerId: PeerId) {
|
||||
let authorNameText = stringForFullAuthorName(message: message, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, accountPeerId: accountPeerId)
|
||||
let dateText = humanReadableStringForTimestamp(strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, timestamp: message.timestamp).0
|
||||
let dateText = humanReadableStringForTimestamp(strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, timestamp: message.timestamp).string
|
||||
|
||||
self.authorNameNode.attributedText = NSAttributedString(string: authorNameText, font: titleFont, textColor: .white)
|
||||
self.dateNode.attributedText = NSAttributedString(string: dateText, font: dateFont, textColor: .white)
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class ChatDocumentGalleryItem: GalleryItem {
|
|||
}
|
||||
|
||||
if let location = self.location {
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(location.index + 1)", "\(location.count)").0))
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(location.index + 1)", "\(location.count)").string))
|
||||
}
|
||||
node.setMessage(self.message)
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ class ChatDocumentGalleryItem: GalleryItem {
|
|||
|
||||
func updateNode(node: GalleryItemNode, synchronous: Bool) {
|
||||
if let node = node as? ChatDocumentGalleryItemNode, let location = self.location {
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(location.index + 1)", "\(location.count)").0))
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(location.index + 1)", "\(location.count)").string))
|
||||
node.setMessage(self.message)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ class ChatExternalFileGalleryItem: GalleryItem {
|
|||
}
|
||||
|
||||
if let location = self.location {
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(location.index + 1)", "\(location.count)").0))
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(location.index + 1)", "\(location.count)").string))
|
||||
}
|
||||
node.setMessage(self.message)
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ class ChatExternalFileGalleryItem: GalleryItem {
|
|||
|
||||
func updateNode(node: GalleryItemNode, synchronous: Bool) {
|
||||
if let node = node as? ChatExternalFileGalleryItemNode, let location = self.location {
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(location.index + 1)", "\(location.count)").0))
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(location.index + 1)", "\(location.count)").string))
|
||||
node.setMessage(self.message)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ class ChatImageGalleryItem: GalleryItem {
|
|||
}
|
||||
|
||||
if let location = self.location {
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(location.index + 1)", "\(location.count)").0))
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(location.index + 1)", "\(location.count)").string))
|
||||
}
|
||||
|
||||
if self.displayInfoOnTop {
|
||||
|
|
@ -155,7 +155,7 @@ class ChatImageGalleryItem: GalleryItem {
|
|||
|
||||
func updateNode(node: GalleryItemNode, synchronous: Bool) {
|
||||
if let node = node as? ChatImageGalleryItemNode, let location = self.location {
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(location.index + 1)", "\(location.count)").0))
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(location.index + 1)", "\(location.count)").string))
|
||||
|
||||
if self.displayInfoOnTop {
|
||||
node.titleContentView?.setMessage(self.message, presentationData: self.presentationData, accountPeerId: self.context.account.peerId)
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ public class UniversalVideoGalleryItem: GalleryItem {
|
|||
let node = UniversalVideoGalleryItemNode(context: self.context, presentationData: self.presentationData, performAction: self.performAction, openActionOptions: self.openActionOptions, present: self.present)
|
||||
|
||||
if let indexData = self.indexData {
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(indexData.position + 1)", "\(indexData.totalCount)").0))
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(indexData.position + 1)", "\(indexData.totalCount)").string))
|
||||
}
|
||||
|
||||
node.setupItem(self)
|
||||
|
|
@ -87,7 +87,7 @@ public class UniversalVideoGalleryItem: GalleryItem {
|
|||
public func updateNode(node: GalleryItemNode, synchronous: Bool) {
|
||||
if let node = node as? UniversalVideoGalleryItemNode {
|
||||
if let indexData = self.indexData {
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(indexData.position + 1)", "\(indexData.totalCount)").0))
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(indexData.position + 1)", "\(indexData.totalCount)").string))
|
||||
}
|
||||
|
||||
node.setupItem(self)
|
||||
|
|
|
|||
|
|
@ -314,12 +314,12 @@ public final class SecretMediaPreviewController: ViewController {
|
|||
let text: String
|
||||
if let file = media as? TelegramMediaFile {
|
||||
if file.isAnimated {
|
||||
text = strongSelf.presentationData.strings.SecretGIF_NotViewedYet(peerTitle).0
|
||||
text = strongSelf.presentationData.strings.SecretGIF_NotViewedYet(peerTitle).string
|
||||
} else {
|
||||
text = strongSelf.presentationData.strings.SecretVideo_NotViewedYet(peerTitle).0
|
||||
text = strongSelf.presentationData.strings.SecretVideo_NotViewedYet(peerTitle).string
|
||||
}
|
||||
} else {
|
||||
text = strongSelf.presentationData.strings.SecretImage_NotViewedYet(peerTitle).0
|
||||
text = strongSelf.presentationData.strings.SecretImage_NotViewedYet(peerTitle).string
|
||||
}
|
||||
contentNode.setText(text)
|
||||
strongSelf.controllerNode.updatePresentationState({
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ final class HashtagSearchControllerNode: ASDisplayNode {
|
|||
self.query = query
|
||||
self.listNode = ListView()
|
||||
self.listNode.accessibilityPageScrolledString = { row, count in
|
||||
return strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
self.toolbarBackgroundNode = NavigationBackgroundNode(color: theme.rootController.navigationBar.blurredBackgroundColor)
|
||||
|
|
|
|||
|
|
@ -513,7 +513,7 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
|
|||
self.radialStatusText.attributedText = NSAttributedString(string: "\(Int(effectiveProgress * 100.0))%", font: Font.with(size: floor(36.0 * maxK), design: .round, weight: .semibold), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
|
||||
let radialStatusTextSize = self.radialStatusText.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude))
|
||||
|
||||
self.progressText.attributedText = NSAttributedString(string: self.presentationData.strings.ImportStickerPack_Of(String(count), String(total)).0, font: Font.semibold(17.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
|
||||
self.progressText.attributedText = NSAttributedString(string: self.presentationData.strings.ImportStickerPack_Of(String(count), String(total)).string, font: Font.semibold(17.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
|
||||
let progressTextSize = self.progressText.updateLayout(CGSize(width: layout.size.width - 16.0 * 2.0, height: .greatestFiniteMagnitude))
|
||||
|
||||
self.infoText.attributedText = NSAttributedString(string: self.presentationData.strings.ImportStickerPack_InProgress, font: Font.regular(17.0), textColor: self.presentationData.theme.list.itemSecondaryTextColor)
|
||||
|
|
@ -678,7 +678,7 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
|
|||
if let firstStickerItem = firstStickerItem, let resource = firstStickerItem.resource as? TelegramMediaResource {
|
||||
firstItem = StickerPackItem(index: ItemCollectionItemIndex(index: 0, id: 0), file: TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: stickerPack.isAnimated ? "application/x-tgsticker": "image/png", size: nil, attributes: [.FileName(fileName: stickerPack.isAnimated ? "sticker.tgs" : "sticker.png"), .ImageSize(size: firstStickerItem.dimensions)]), indexKeys: [])
|
||||
}
|
||||
strongSelf.presentInGlobalOverlay?(UndoOverlayController(presentationData: strongSelf.presentationData, content: .stickersModified(title: strongSelf.presentationData.strings.StickerPackActionInfo_AddedTitle, text: strongSelf.presentationData.strings.StickerPackActionInfo_AddedText(info.title).0, undo: false, info: info, topItem: firstItem ?? items.first, context: strongSelf.context), elevatedLayout: false, action: { action in
|
||||
strongSelf.presentInGlobalOverlay?(UndoOverlayController(presentationData: strongSelf.presentationData, content: .stickersModified(title: strongSelf.presentationData.strings.StickerPackActionInfo_AddedTitle, text: strongSelf.presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: firstItem ?? items.first, context: strongSelf.context), elevatedLayout: false, action: { action in
|
||||
if case .info = action {
|
||||
(navigationController?.viewControllers.last as? ViewController)?.present(StickerPackScreen(context: context, mode: .settings, mainStickerPack: .id(id: info.id.id, accessHash: info.accessHash), stickerPacks: [], parentNavigationController: navigationController, actionPerformed: { _, _, _ in
|
||||
}), in: .window(.root))
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class InstantImageGalleryItem: GalleryItem {
|
|||
node.setImage(imageReference: self.imageReference)
|
||||
|
||||
if let location = self.location {
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(location.position + 1)", "\(location.totalCount)").0))
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(location.position + 1)", "\(location.totalCount)").string))
|
||||
}
|
||||
|
||||
node.setCaption(self.caption, credit: self.credit)
|
||||
|
|
@ -79,7 +79,7 @@ class InstantImageGalleryItem: GalleryItem {
|
|||
func updateNode(node: GalleryItemNode, synchronous: Bool) {
|
||||
if let node = node as? InstantImageGalleryItemNode {
|
||||
if let location = self.location {
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(location.position + 1)", "\(location.totalCount)").0))
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(location.position + 1)", "\(location.totalCount)").string))
|
||||
}
|
||||
|
||||
node.setCaption(self.caption, credit: self.credit)
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ func layoutInstantPageBlock(webpage: TelegramMediaWebpage, rtl: Bool, block: Ins
|
|||
} else {
|
||||
if date != 0 {
|
||||
let dateText = RichText.plain(stringForDate(date))
|
||||
let formatString = strings.InstantPage_AuthorAndDateTitle("%1$@", "%2$@").0
|
||||
let formatString = strings.InstantPage_AuthorAndDateTitle("%1$@", "%2$@").string
|
||||
let authorRange = formatString.range(of: "%1$@")!
|
||||
let dateRange = formatString.range(of: "%2$@")!
|
||||
|
||||
|
|
@ -780,7 +780,7 @@ func layoutInstantPageBlock(webpage: TelegramMediaWebpage, rtl: Bool, block: Ins
|
|||
if article.author != nil || article.date != nil {
|
||||
if let author = article.author {
|
||||
if let date = article.date {
|
||||
subtext = strings.InstantPage_RelatedArticleAuthorAndDateTitle(author, stringForDate(date)).0
|
||||
subtext = strings.InstantPage_RelatedArticleAuthorAndDateTitle(author, stringForDate(date)).string
|
||||
} else {
|
||||
subtext = author
|
||||
}
|
||||
|
|
|
|||
|
|
@ -320,7 +320,7 @@ public final class InviteLinkInviteController: ViewController {
|
|||
self.listNode.verticalScrollIndicatorColor = UIColor(white: 0.0, alpha: 0.3)
|
||||
self.listNode.verticalScrollIndicatorFollowsOverscroll = true
|
||||
self.listNode.accessibilityPageScrolledString = { row, count in
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
super.init()
|
||||
|
|
|
|||
|
|
@ -311,7 +311,7 @@ private func inviteLinkListControllerEntries(presentationData: PresentationData,
|
|||
entries.append(.mainLink(presentationData.theme, mainInvite, importers?.importers.prefix(3).compactMap { $0.peer.peer } ?? [], importersCount, isPublic))
|
||||
if let adminPeer = admin?.peer.peer, let peer = peerViewMainPeer(view) {
|
||||
let string = presentationData.strings.InviteLink_OtherPermanentLinkInfo(adminPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder))
|
||||
entries.append(.mainLinkOtherInfo(presentationData.theme, string.0))
|
||||
entries.append(.mainLinkOtherInfo(presentationData.theme, string.string))
|
||||
}
|
||||
|
||||
var additionalInvites: [ExportedInvitation]?
|
||||
|
|
|
|||
|
|
@ -417,7 +417,7 @@ public final class InviteLinkViewController: ViewController {
|
|||
self.listNode.verticalScrollIndicatorColor = UIColor(white: 0.0, alpha: 0.3)
|
||||
self.listNode.verticalScrollIndicatorFollowsOverscroll = true
|
||||
self.listNode.accessibilityPageScrolledString = { row, count in
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
super.init()
|
||||
|
|
@ -839,9 +839,9 @@ public final class InviteLinkViewController: ViewController {
|
|||
} else {
|
||||
let elapsedTime = expireDate - currentTime
|
||||
if elapsedTime >= 86400 {
|
||||
subtitleText = self.presentationData.strings.InviteLink_ExpiresIn(scheduledTimeIntervalString(strings: self.presentationData.strings, value: elapsedTime)).0
|
||||
subtitleText = self.presentationData.strings.InviteLink_ExpiresIn(scheduledTimeIntervalString(strings: self.presentationData.strings, value: elapsedTime)).string
|
||||
} else {
|
||||
subtitleText = self.presentationData.strings.InviteLink_ExpiresIn(textForTimeout(value: elapsedTime)).0
|
||||
subtitleText = self.presentationData.strings.InviteLink_ExpiresIn(textForTimeout(value: elapsedTime)).string
|
||||
if self.countdownTimer == nil {
|
||||
let countdownTimer = SwiftSignalKit.Timer(timeout: 1.0, repeat: true, completion: { [weak self] in
|
||||
if let strongSelf = self, let layout = strongSelf.validLayout {
|
||||
|
|
|
|||
|
|
@ -392,9 +392,9 @@ public class ItemListInviteLinkItemNode: ListViewItemNode, ItemListItemNode {
|
|||
}
|
||||
let elapsedTime = expireDate - currentTime
|
||||
if elapsedTime >= 86400 {
|
||||
subtitleText += item.presentationData.strings.InviteLink_ExpiresIn(scheduledTimeIntervalString(strings: item.presentationData.strings, value: elapsedTime)).0
|
||||
subtitleText += item.presentationData.strings.InviteLink_ExpiresIn(scheduledTimeIntervalString(strings: item.presentationData.strings, value: elapsedTime)).string
|
||||
} else {
|
||||
subtitleText += item.presentationData.strings.InviteLink_ExpiresIn(textForTimeout(value: elapsedTime)).0
|
||||
subtitleText += item.presentationData.strings.InviteLink_ExpiresIn(textForTimeout(value: elapsedTime)).string
|
||||
}
|
||||
if timerValue == nil {
|
||||
timerValue = .timestamp(creation: invite.startDate ?? invite.date, deadline: expireDate)
|
||||
|
|
|
|||
|
|
@ -705,7 +705,7 @@ open class ItemListControllerNode: ASDisplayNode {
|
|||
}
|
||||
|
||||
self.listNode.accessibilityPageScrolledString = { row, count in
|
||||
return transition.strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return transition.strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
var updateToolbarItem = false
|
||||
|
|
|
|||
|
|
@ -36,13 +36,13 @@ final class LanguageLinkPreviewContentNode: ASDisplayNode, ShareContentContainer
|
|||
let text: String
|
||||
if localizationInfo.totalStringCount == 0 {
|
||||
self.titleNode.attributedText = NSAttributedString(string: strings.ApplyLanguage_UnsufficientDataTitle, font: Font.medium(18.0), textColor: theme.actionSheet.primaryTextColor, paragraphAlignment: .center)
|
||||
text = strings.ApplyLanguage_UnsufficientDataText(localizationInfo.title).0
|
||||
text = strings.ApplyLanguage_UnsufficientDataText(localizationInfo.title).string
|
||||
} else {
|
||||
self.titleNode.attributedText = NSAttributedString(string: strings.ApplyLanguage_ChangeLanguageTitle, font: Font.medium(18.0), textColor: theme.actionSheet.primaryTextColor, paragraphAlignment: .center)
|
||||
if !localizationInfo.isOfficial {
|
||||
text = strings.ApplyLanguage_ChangeLanguageUnofficialText(localizationInfo.title, "\(completionScore)").0
|
||||
text = strings.ApplyLanguage_ChangeLanguageUnofficialText(localizationInfo.title, "\(completionScore)").string
|
||||
} else {
|
||||
text = strings.ApplyLanguage_ChangeLanguageOfficialText(localizationInfo.title).0
|
||||
text = strings.ApplyLanguage_ChangeLanguageOfficialText(localizationInfo.title).string
|
||||
}
|
||||
}
|
||||
let body = MarkdownAttributeSet(font: Font.regular(15.0), textColor: theme.actionSheet.primaryTextColor)
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ public final class LanguageLinkPreviewController: ViewController {
|
|||
return
|
||||
}
|
||||
if result.languageCode == strongSelf.presentationData.strings.primaryComponent.languageCode {
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.ApplyLanguage_ChangeLanguageAlreadyActive(result.localizedTitle).0, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.ApplyLanguage_ChangeLanguageAlreadyActive(result.localizedTitle).string, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
strongSelf.dismiss()
|
||||
} else {
|
||||
strongSelf.localizationInfo = result
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ public final class ChatMessageLiveLocationTimerNode: ASDisplayNode {
|
|||
let string: String
|
||||
if intRemaining > 60 * 60 {
|
||||
let hours = Int32(round(remaining / (60.0 * 60.0)))
|
||||
string = strings.Map_LiveLocationShortHour("\(hours)").0
|
||||
string = strings.Map_LiveLocationShortHour("\(hours)").string
|
||||
} else {
|
||||
let minutes = Int32(round(remaining / (60.0)))
|
||||
string = "\(minutes)"
|
||||
|
|
|
|||
|
|
@ -394,10 +394,10 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||
}
|
||||
let distance = self.usesMetricSystem ? "\(formattedValue) \(self.presentationData.strings.Location_ProximityNotification_DistanceKM)" : "\(formattedValue) \(self.presentationData.strings.Location_ProximityNotification_DistanceMI)"
|
||||
|
||||
let shortTitle = self.presentationData.strings.Location_ProximityNotification_Notify(distance).0
|
||||
let shortTitle = self.presentationData.strings.Location_ProximityNotification_Notify(distance).string
|
||||
var longTitle: String?
|
||||
if let displayTitle = self.compactDisplayTitle, let (layout, _) = self.containerLayout {
|
||||
let title = self.presentationData.strings.Location_ProximityNotification_NotifyLong(displayTitle, distance).0
|
||||
let title = self.presentationData.strings.Location_ProximityNotification_NotifyLong(displayTitle, distance).string
|
||||
let width = horizontalContainerFillingSizeForLayout(layout: layout, sideInset: layout.safeInsets.left)
|
||||
|
||||
self.measureButtonTitleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(17.0), textColor: .black)
|
||||
|
|
@ -408,7 +408,7 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||
}
|
||||
self.doneButton.title = longTitle ?? shortTitle
|
||||
|
||||
self.textNode.attributedText = NSAttributedString(string: self.presentationData.strings.Location_ProximityNotification_AlreadyClose(distance).0, font: Font.regular(14.0), textColor: self.presentationData.theme.actionSheet.secondaryTextColor)
|
||||
self.textNode.attributedText = NSAttributedString(string: self.presentationData.strings.Location_ProximityNotification_AlreadyClose(distance).string, font: Font.regular(14.0), textColor: self.presentationData.theme.actionSheet.secondaryTextColor)
|
||||
if let (layout, navigationBarHeight) = self.containerLayout {
|
||||
self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ final class LocationLiveListItemNode: ListViewItemNode {
|
|||
|
||||
var subtitle = timeString
|
||||
if let distance = item.distance {
|
||||
let distanceString = item.presentationData.strings.Map_DistanceAway(shortStringForDistance(strings: item.presentationData.strings, distance: Int32(distance))).0
|
||||
let distanceString = item.presentationData.strings.Map_DistanceAway(shortStringForDistance(strings: item.presentationData.strings, distance: Int32(distance))).string
|
||||
subtitle = "\(timeString) • \(distanceString)"
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ public final class LocationPickerController: ViewController {
|
|||
let controller = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
var title = strongSelf.presentationData.strings.Map_LiveLocationGroupDescription
|
||||
if case let .share(peer, _, _) = strongSelf.mode, let receiver = peer as? TelegramUser {
|
||||
title = strongSelf.presentationData.strings.Map_LiveLocationPrivateDescription(receiver.compactDisplayTitle).0
|
||||
title = strongSelf.presentationData.strings.Map_LiveLocationPrivateDescription(receiver.compactDisplayTitle).string
|
||||
}
|
||||
controller.setItemGroups([
|
||||
ActionSheetItemGroup(items: [
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
|
|||
self.listNode.verticalScrollIndicatorColor = UIColor(white: 0.0, alpha: 0.3)
|
||||
self.listNode.verticalScrollIndicatorFollowsOverscroll = true
|
||||
self.listNode.accessibilityPageScrolledString = { row, count in
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
self.emptyResultsTextNode = ImmediateTextNode()
|
||||
|
|
@ -489,7 +489,7 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
|
|||
case .pick:
|
||||
title = presentationData.strings.Map_SetThisLocation
|
||||
}
|
||||
entries.append(.location(presentationData.theme, title, (userLocation?.horizontalAccuracy).flatMap { presentationData.strings.Map_AccurateTo(stringForDistance(strings: presentationData.strings, distance: $0)).0 } ?? presentationData.strings.Map_Locating, nil, userLocation?.coordinate))
|
||||
entries.append(.location(presentationData.theme, title, (userLocation?.horizontalAccuracy).flatMap { presentationData.strings.Map_AccurateTo(stringForDistance(strings: presentationData.strings, distance: $0)).string } ?? presentationData.strings.Map_Locating, nil, userLocation?.coordinate))
|
||||
}
|
||||
|
||||
if case .share(_, _, true) = mode {
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ private struct LocationSearchEntry: Identifiable, Comparable {
|
|||
subtitle = nil
|
||||
} else {
|
||||
header = ChatListSearchItemHeader(type: .mapAddress, theme: presentationData.theme, strings: presentationData.strings)
|
||||
subtitle = presentationData.strings.Map_DistanceAway(stringForDistance(strings: presentationData.strings, distance: self.distance)).0
|
||||
subtitle = presentationData.strings.Map_DistanceAway(stringForDistance(strings: presentationData.strings, distance: self.distance)).string
|
||||
}
|
||||
return ItemListVenueItem(presentationData: ItemListPresentationData(presentationData), account: account, venue: self.location, title: self.title, subtitle: subtitle, style: .plain, action: {
|
||||
sendVenue(venue)
|
||||
|
|
@ -124,7 +124,7 @@ final class LocationSearchContainerNode: ASDisplayNode {
|
|||
self.listNode.backgroundColor = self.presentationData.theme.list.plainBackgroundColor
|
||||
self.listNode.isHidden = true
|
||||
self.listNode.accessibilityPageScrolledString = { row, count in
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
self.emptyResultsTitleNode = ImmediateTextNode()
|
||||
|
|
@ -313,7 +313,7 @@ final class LocationSearchContainerNode: ASDisplayNode {
|
|||
strongSelf.listNode.isHidden = !transition.isSearching
|
||||
strongSelf.dimNode.isHidden = transition.isSearching
|
||||
|
||||
strongSelf.emptyResultsTextNode.attributedText = NSAttributedString(string: strongSelf.presentationData.strings.Map_SearchNoResultsDescription(transition.query).0, font: Font.regular(15.0), textColor: strongSelf.presentationData.theme.list.freeTextColor)
|
||||
strongSelf.emptyResultsTextNode.attributedText = NSAttributedString(string: strongSelf.presentationData.strings.Map_SearchNoResultsDescription(transition.query).string, font: Font.regular(15.0), textColor: strongSelf.presentationData.theme.list.freeTextColor)
|
||||
|
||||
let emptyResults = transition.isSearching && transition.isEmpty
|
||||
strongSelf.emptyResultsTitleNode.isHidden = !emptyResults
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ func stringForEstimatedDuration(strings: PresentationStrings, eta: Double) -> St
|
|||
} else {
|
||||
string = strings.Map_ETAMinutes(minutes)
|
||||
}
|
||||
return strings.Map_DirectionsDriveEta(string).0
|
||||
return strings.Map_DirectionsDriveEta(string).string
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -277,9 +277,9 @@ public final class LocationViewController: ViewController {
|
|||
var text: String
|
||||
let distanceString = shortStringForDistance(strings: strongSelf.presentationData.strings, distance: distance)
|
||||
if let compactDisplayTitle = compactDisplayTitle {
|
||||
text = strongSelf.presentationData.strings.Location_ProximityAlertSetText(compactDisplayTitle, distanceString).0
|
||||
text = strongSelf.presentationData.strings.Location_ProximityAlertSetText(compactDisplayTitle, distanceString).string
|
||||
} else {
|
||||
text = strongSelf.presentationData.strings.Location_ProximityAlertSetTextGroup(distanceString).0
|
||||
text = strongSelf.presentationData.strings.Location_ProximityAlertSetTextGroup(distanceString).string
|
||||
}
|
||||
|
||||
strongSelf.dismissAllTooltips()
|
||||
|
|
@ -352,9 +352,9 @@ public final class LocationViewController: ViewController {
|
|||
var text: String
|
||||
let distanceString = shortStringForDistance(strings: strongSelf.presentationData.strings, distance: distance)
|
||||
if let compactDisplayTitle = compactDisplayTitle {
|
||||
text = strongSelf.presentationData.strings.Location_ProximityAlertSetText(compactDisplayTitle, distanceString).0
|
||||
text = strongSelf.presentationData.strings.Location_ProximityAlertSetText(compactDisplayTitle, distanceString).string
|
||||
} else {
|
||||
text = strongSelf.presentationData.strings.Location_ProximityAlertSetTextGroup(distanceString).0
|
||||
text = strongSelf.presentationData.strings.Location_ProximityAlertSetTextGroup(distanceString).string
|
||||
}
|
||||
|
||||
strongSelf.dismissAllTooltips()
|
||||
|
|
@ -380,7 +380,7 @@ public final class LocationViewController: ViewController {
|
|||
let controller = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
var title = strongSelf.presentationData.strings.Map_LiveLocationGroupDescription
|
||||
if let user = peer as? TelegramUser {
|
||||
title = strongSelf.presentationData.strings.Map_LiveLocationPrivateDescription(user.compactDisplayTitle).0
|
||||
title = strongSelf.presentationData.strings.Map_LiveLocationPrivateDescription(user.compactDisplayTitle).string
|
||||
}
|
||||
|
||||
let sendLiveLocationImpl: (Int32) -> Void = { [weak controller] period in
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ private enum LocationViewEntry: Comparable, Identifiable {
|
|||
}
|
||||
let distanceString: String?
|
||||
if let distance = distance {
|
||||
distanceString = distance < 10 ? presentationData.strings.Map_YouAreHere : presentationData.strings.Map_DistanceAway(stringForDistance(strings: presentationData.strings, distance: distance)).0
|
||||
distanceString = distance < 10 ? presentationData.strings.Map_YouAreHere : presentationData.strings.Map_DistanceAway(stringForDistance(strings: presentationData.strings, distance: distance)).string
|
||||
} else {
|
||||
distanceString = nil
|
||||
}
|
||||
|
|
@ -235,7 +235,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
|||
self.listNode.verticalScrollIndicatorColor = UIColor(white: 0.0, alpha: 0.3)
|
||||
self.listNode.verticalScrollIndicatorFollowsOverscroll = true
|
||||
self.listNode.accessibilityPageScrolledString = { row, count in
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
var setupProximityNotificationImpl: ((Bool) -> Void)?
|
||||
|
|
@ -721,7 +721,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
|||
|
||||
var text: String = strongSelf.presentationData.strings.Location_ProximityGroupTip
|
||||
if peer.id.namespace == Namespaces.Peer.CloudUser {
|
||||
text = strongSelf.presentationData.strings.Location_ProximityTip(peer.compactDisplayTitle).0
|
||||
text = strongSelf.presentationData.strings.Location_ProximityTip(peer.compactDisplayTitle).string
|
||||
}
|
||||
|
||||
strongSelf.interaction.present(TooltipScreen(text: text, icon: nil, location: .point(location.offsetBy(dx: -9.0, dy: 0.0), .right), displayDuration: .custom(3.0), shouldDismissOnTouch: { _ in
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ public func notificationMuteSettingsController(presentationData: PresentationDat
|
|||
items.append(item)
|
||||
}
|
||||
if let soundSettings = soundSettings {
|
||||
items.append(ActionSheetButtonItem(title: soundSettings.value.flatMap({ presentationData.strings.Notification_Exceptions_Sound(localizedPeerNotificationSoundString(strings: presentationData.strings, sound: $0)).0 }) ?? presentationData.strings.GroupInfo_SetSound, action: {
|
||||
items.append(ActionSheetButtonItem(title: soundSettings.value.flatMap({ presentationData.strings.Notification_Exceptions_Sound(localizedPeerNotificationSoundString(strings: presentationData.strings, sound: $0)).string }) ?? presentationData.strings.GroupInfo_SetSound, action: {
|
||||
dismissAction()
|
||||
openSoundSettings()
|
||||
}))
|
||||
|
|
|
|||
|
|
@ -58,13 +58,13 @@ final class SecureIdAuthFormContentNode: ASDisplayNode, SecureIdAuthContentNode,
|
|||
let privacyPolicyAttributes = MarkdownAttributeSet(font: infoFont, textColor: theme.list.freeTextColor)
|
||||
let privacyPolicyLinkAttributes = MarkdownAttributeSet(font: infoFont, textColor: theme.list.itemAccentColor, additionalAttributes: [NSAttributedString.Key.underlineStyle.rawValue: NSUnderlineStyle.single.rawValue as NSNumber, TelegramTextAttributes.URL: privacyPolicyUrl])
|
||||
|
||||
text = parseMarkdownIntoAttributedString(strings.Passport_PrivacyPolicy(peer.displayTitle(strings: strings, displayOrder: nameDisplayOrder), (peer.addressName ?? "")).0.replacingOccurrences(of: "]", with: "]()"), attributes: MarkdownAttributes(body: privacyPolicyAttributes, bold: privacyPolicyAttributes, link: privacyPolicyLinkAttributes, linkAttribute: { _ in
|
||||
text = parseMarkdownIntoAttributedString(strings.Passport_PrivacyPolicy(peer.displayTitle(strings: strings, displayOrder: nameDisplayOrder), (peer.addressName ?? "")).string.replacingOccurrences(of: "]", with: "]()"), attributes: MarkdownAttributes(body: privacyPolicyAttributes, bold: privacyPolicyAttributes, link: privacyPolicyLinkAttributes, linkAttribute: { _ in
|
||||
return nil
|
||||
}), textAlignment: .center)
|
||||
|
||||
|
||||
} else {
|
||||
text = NSAttributedString(string: strings.Passport_AcceptHelp(peer.displayTitle(strings: strings, displayOrder: nameDisplayOrder), (peer.addressName ?? "")).0, font: infoFont, textColor: theme.list.freeTextColor, paragraphAlignment: .left)
|
||||
text = NSAttributedString(string: strings.Passport_AcceptHelp(peer.displayTitle(strings: strings, displayOrder: nameDisplayOrder), (peer.addressName ?? "")).string, font: infoFont, textColor: theme.list.freeTextColor, paragraphAlignment: .left)
|
||||
}
|
||||
self.textNode.attributedText = text
|
||||
|
||||
|
|
|
|||
|
|
@ -491,7 +491,7 @@ private func placeholderForDocumentTypes(_ types: [SecureIdRequestedIdentityDocu
|
|||
}
|
||||
}
|
||||
|
||||
return strings.Passport_Identity_UploadOneOfScan(string).0
|
||||
return strings.Passport_Identity_UploadOneOfScan(string).string
|
||||
}
|
||||
|
||||
private func placeholderForDocumentTypes(_ types: [SecureIdRequestedAddressDocumentWithAttributes], strings: PresentationStrings) -> String {
|
||||
|
|
@ -521,7 +521,7 @@ private func placeholderForDocumentTypes(_ types: [SecureIdRequestedAddressDocum
|
|||
}
|
||||
}
|
||||
|
||||
return strings.Passport_Address_UploadOneOfScan(string).0
|
||||
return strings.Passport_Address_UploadOneOfScan(string).string
|
||||
}
|
||||
|
||||
private func stringForDocumentValue(_ value: SecureIdValue, strings: PresentationStrings) -> String? {
|
||||
|
|
@ -587,7 +587,7 @@ private func fieldTitleAndText(field: SecureIdParsedRequestedFormField, strings:
|
|||
isOneOf = true
|
||||
let typesArray = Array(types)
|
||||
if typesArray.count == 2 {
|
||||
title = strings.Passport_FieldOneOf_Or(stringForDocumentType(typesArray[0].document, strings: strings), stringForDocumentType(typesArray[1].document, strings: strings)).0
|
||||
title = strings.Passport_FieldOneOf_Or(stringForDocumentType(typesArray[0].document, strings: strings), stringForDocumentType(typesArray[1].document, strings: strings)).string
|
||||
}
|
||||
placeholder = placeholderForDocumentTypes(typesArray, strings: strings)
|
||||
for type in types.sorted(by: { $0.document.valueKey.rawValue < $1.document.valueKey.rawValue }) {
|
||||
|
|
@ -638,7 +638,7 @@ private func fieldTitleAndText(field: SecureIdParsedRequestedFormField, strings:
|
|||
isOneOf = true
|
||||
let typesArray = Array(types)
|
||||
if typesArray.count == 2 {
|
||||
title = strings.Passport_FieldOneOf_Or(stringForDocumentType(typesArray[0].document, strings: strings), stringForDocumentType(typesArray[1].document, strings: strings)).0
|
||||
title = strings.Passport_FieldOneOf_Or(stringForDocumentType(typesArray[0].document, strings: strings), stringForDocumentType(typesArray[1].document, strings: strings)).string
|
||||
}
|
||||
placeholder = placeholderForDocumentTypes(typesArray, strings: strings)
|
||||
for type in types.sorted(by: { $0.document.valueKey.rawValue < $1.document.valueKey.rawValue }) {
|
||||
|
|
|
|||
|
|
@ -58,9 +58,9 @@ final class SecureIdAuthHeaderNode: ASDisplayNode {
|
|||
let titleData = self.strings.Passport_RequestHeader(formData.servicePeer.displayTitle(strings: self.strings, displayOrder: self.nameDisplayOrder))
|
||||
|
||||
let titleString = NSMutableAttributedString()
|
||||
titleString.append(NSAttributedString(string: titleData.0, font: textFont, textColor: self.theme.list.freeTextColor))
|
||||
for (_, range) in titleData.1 {
|
||||
titleString.addAttribute(.font, value: titleFont, range: range)
|
||||
titleString.append(NSAttributedString(string: titleData.string, font: textFont, textColor: self.theme.list.freeTextColor))
|
||||
for range in titleData.ranges {
|
||||
titleString.addAttribute(.font, value: titleFont, range: range.range)
|
||||
}
|
||||
self.titleNode.attributedText = titleString
|
||||
self.iconNode.isHidden = true
|
||||
|
|
|
|||
|
|
@ -1809,9 +1809,9 @@ enum SecureIdDocumentFormEntry: FormControllerEntry {
|
|||
case .scanYourPassportInfo:
|
||||
return FormControllerTextItem(text: strings.Passport_ScanPassportHelp)
|
||||
case .scansHeader:
|
||||
return FormControllerHeaderItem(text: strings.Passport_Scans)
|
||||
return FormControllerHeaderItem(text: strings.Passport_ScansHeader)
|
||||
case let .scan(index, document, error):
|
||||
return SecureIdValueFormFileItem(account: params.account, context: params.context, document: document, placeholder: nil, title: strings.Passport_Scans_ScanIndex("\(index + 1)").0, label: error.flatMap(SecureIdValueFormFileItemLabel.error) ?? .timestamp, activated: {
|
||||
return SecureIdValueFormFileItem(account: params.account, context: params.context, document: document, placeholder: nil, title: strings.Passport_Scans_ScanIndex("\(index + 1)").string, label: error.flatMap(SecureIdValueFormFileItemLabel.error) ?? .timestamp, activated: {
|
||||
params.openDocument(document)
|
||||
}, deleted: {
|
||||
params.deleteDocument(document)
|
||||
|
|
@ -1876,7 +1876,7 @@ enum SecureIdDocumentFormEntry: FormControllerEntry {
|
|||
}
|
||||
|
||||
if let value = value {
|
||||
title = strings.Passport_Identity_NativeNameTitle(value).0.uppercased()
|
||||
title = strings.Passport_Identity_NativeNameTitle(value).string.uppercased()
|
||||
} else {
|
||||
title = strings.Passport_Identity_NativeNameGenericTitle
|
||||
}
|
||||
|
|
@ -1916,7 +1916,7 @@ enum SecureIdDocumentFormEntry: FormControllerEntry {
|
|||
text = strings.Passport_Identity_NativeNameHelp
|
||||
} else {
|
||||
let countryName = AuthorizationSequenceCountrySelectionController.lookupCountryNameById(countryCode.uppercased(), strings: strings) ?? ""
|
||||
text = strings.Passport_Identity_NativeNameGenericHelp(countryName).0
|
||||
text = strings.Passport_Identity_NativeNameGenericHelp(countryName).string
|
||||
}
|
||||
return FormControllerTextItem(text: text)
|
||||
case let .gender(value, error):
|
||||
|
|
@ -2115,7 +2115,7 @@ enum SecureIdDocumentFormEntry: FormControllerEntry {
|
|||
case .translationsHeader:
|
||||
return FormControllerHeaderItem(text: strings.Passport_Identity_Translations)
|
||||
case let .translation(index, document, error):
|
||||
return SecureIdValueFormFileItem(account: params.account, context: params.context, document: document, placeholder: nil, title: strings.Passport_Scans_ScanIndex("\(index + 1)").0, label: error.flatMap(SecureIdValueFormFileItemLabel.error) ?? .timestamp, activated: {
|
||||
return SecureIdValueFormFileItem(account: params.account, context: params.context, document: document, placeholder: nil, title: strings.Passport_Scans_ScanIndex("\(index + 1)").string, label: error.flatMap(SecureIdValueFormFileItemLabel.error) ?? .timestamp, activated: {
|
||||
params.openDocument(document)
|
||||
}, deleted: {
|
||||
params.deleteDocument(document)
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class SecureIdDocumentGalleryItem: GalleryItem {
|
|||
|
||||
node.setResource(secureIdContext: self.secureIdContext, resource: self.resource)
|
||||
|
||||
node._title.set(.single(self.strings.Items_NOfM("\(self.location.position + 1)", "\(self.location.totalCount)").0))
|
||||
node._title.set(.single(self.strings.Items_NOfM("\(self.location.position + 1)", "\(self.location.totalCount)").string))
|
||||
|
||||
node.setCaption(self.caption)
|
||||
node.delete = self.delete
|
||||
|
|
@ -54,7 +54,7 @@ class SecureIdDocumentGalleryItem: GalleryItem {
|
|||
|
||||
func updateNode(node: GalleryItemNode, synchronous: Bool) {
|
||||
if let node = node as? SecureIdDocumentGalleryItemNode {
|
||||
node._title.set(.single(self.strings.Items_NOfM("\(self.location.position + 1)", "\(self.location.totalCount)").0))
|
||||
node._title.set(.single(self.strings.Items_NOfM("\(self.location.position + 1)", "\(self.location.totalCount)").string))
|
||||
|
||||
node.setCaption(self.caption)
|
||||
node.delete = self.delete
|
||||
|
|
|
|||
|
|
@ -570,7 +570,7 @@ public enum SecureIdPlaintextFormEntry: FormControllerEntry {
|
|||
public func item(params: SecureIdPlaintextFormParams, strings: PresentationStrings) -> FormControllerItem {
|
||||
switch self {
|
||||
case let .immediatelyAvailablePhone(value):
|
||||
return FormControllerActionItem(type: .accent, title: strings.Passport_Phone_UseTelegramNumber(formatPhoneNumber(value)).0, activated: {
|
||||
return FormControllerActionItem(type: .accent, title: strings.Passport_Phone_UseTelegramNumber(formatPhoneNumber(value)).string, activated: {
|
||||
params.usePhone(value)
|
||||
})
|
||||
case .immediatelyAvailablePhoneInfo:
|
||||
|
|
@ -603,7 +603,7 @@ public enum SecureIdPlaintextFormEntry: FormControllerEntry {
|
|||
case .numberVerifyInfo:
|
||||
return FormControllerTextItem(text: strings.ChangePhoneNumberCode_Help)
|
||||
case let .immediatelyAvailableEmail(value):
|
||||
return FormControllerActionItem(type: .accent, title: strings.Passport_Email_UseTelegramEmail(value).0, activated: {
|
||||
return FormControllerActionItem(type: .accent, title: strings.Passport_Email_UseTelegramEmail(value).string, activated: {
|
||||
params.useEmailAddress(value)
|
||||
})
|
||||
case .immediatelyAvailableEmailInfo:
|
||||
|
|
@ -625,7 +625,7 @@ public enum SecureIdPlaintextFormEntry: FormControllerEntry {
|
|||
|
||||
})
|
||||
case let .emailVerifyInfo(address):
|
||||
return FormControllerTextItem(text: strings.Passport_Email_CodeHelp(address).0)
|
||||
return FormControllerTextItem(text: strings.Passport_Email_CodeHelp(address).string)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,14 +71,14 @@ private enum ResetPasswordEntry: ItemListNodeEntry, Equatable {
|
|||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! ResetPasswordControllerArguments
|
||||
switch self {
|
||||
case let .code(theme, strings, text, value):
|
||||
case let .code(theme, _, text, value):
|
||||
return ItemListSingleLineInputItem(presentationData: presentationData, title: NSAttributedString(string: text, textColor: theme.list.itemPrimaryTextColor), text: value, placeholder: "", type: .number, spacing: 10.0, tag: ResetPasswordEntryTag.code, sectionId: self.section, textUpdated: { updatedText in
|
||||
arguments.updateCodeText(updatedText)
|
||||
}, action: {
|
||||
})
|
||||
case let .codeInfo(theme, text):
|
||||
case let .codeInfo(_, text):
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .helpInfo(theme, text):
|
||||
case let .helpInfo(_, text):
|
||||
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section, linkAction: { action in
|
||||
if case .tap = action {
|
||||
arguments.openHelp()
|
||||
|
|
@ -100,10 +100,10 @@ private func resetPasswordControllerEntries(presentationData: PresentationData,
|
|||
entries.append(.codeInfo(presentationData.theme, presentationData.strings.TwoStepAuth_RecoveryCodeHelp))
|
||||
|
||||
let stringData = presentationData.strings.TwoStepAuth_RecoveryEmailUnavailable(pattern)
|
||||
var string = stringData.0
|
||||
if let (_, range) = stringData.1.first {
|
||||
string.insert(contentsOf: "]()", at: string.index(string.startIndex, offsetBy: range.upperBound))
|
||||
string.insert(contentsOf: "[", at: string.index(string.startIndex, offsetBy: range.lowerBound))
|
||||
var string = stringData.string
|
||||
if let range = stringData.ranges.first {
|
||||
string.insert(contentsOf: "]()", at: string.index(string.startIndex, offsetBy: range.range.upperBound))
|
||||
string.insert(contentsOf: "[", at: string.index(string.startIndex, offsetBy: range.range.lowerBound))
|
||||
}
|
||||
entries.append(.helpInfo(presentationData.theme, string))
|
||||
|
||||
|
|
|
|||
|
|
@ -380,7 +380,7 @@ final class SetupTwoStepVerificationControllerNode: ViewControllerTracingNode {
|
|||
case let .confirm(_, _, pattern, _):
|
||||
emailPattern = pattern
|
||||
}
|
||||
subtitle = self.presentationData.strings.TwoStepAuth_ConfirmEmailDescription(emailPattern).0
|
||||
subtitle = self.presentationData.strings.TwoStepAuth_ConfirmEmailDescription(emailPattern).string
|
||||
inputType = .code
|
||||
inputPlaceholder = self.presentationData.strings.TwoStepAuth_ConfirmEmailCodePlaceholder
|
||||
inputText = code
|
||||
|
|
|
|||
|
|
@ -639,7 +639,7 @@ public final class TwoFactorDataInputScreen: ViewController {
|
|||
case let .limitExceeded(retryAtTimestamp):
|
||||
if let retryAtTimestamp = retryAtTimestamp {
|
||||
let remainingSeconds = retryAtTimestamp - Int32(Date().timeIntervalSince1970)
|
||||
text = presentationData.strings.TwoFactorSetup_ResetFloodWait(timeIntervalString(strings: presentationData.strings, value: remainingSeconds)).0
|
||||
text = presentationData.strings.TwoFactorSetup_ResetFloodWait(timeIntervalString(strings: presentationData.strings, value: remainingSeconds)).string
|
||||
} else {
|
||||
text = presentationData.strings.TwoStepAuth_FloodError
|
||||
}
|
||||
|
|
@ -679,7 +679,7 @@ public final class TwoFactorDataInputScreen: ViewController {
|
|||
case let .limitExceeded(retryAtTimestamp):
|
||||
if let retryAtTimestamp = retryAtTimestamp {
|
||||
let remainingSeconds = retryAtTimestamp - Int32(Date().timeIntervalSince1970)
|
||||
text = presentationData.strings.TwoFactorSetup_ResetFloodWait(timeIntervalString(strings: presentationData.strings, value: remainingSeconds)).0
|
||||
text = presentationData.strings.TwoFactorSetup_ResetFloodWait(timeIntervalString(strings: presentationData.strings, value: remainingSeconds)).string
|
||||
} else {
|
||||
text = presentationData.strings.TwoStepAuth_FloodError
|
||||
}
|
||||
|
|
@ -743,7 +743,7 @@ public final class TwoFactorDataInputScreen: ViewController {
|
|||
case let .limitExceeded(retryAtTimestamp):
|
||||
if let retryAtTimestamp = retryAtTimestamp {
|
||||
let remainingSeconds = retryAtTimestamp - Int32(Date().timeIntervalSince1970)
|
||||
text = strongSelf.presentationData.strings.TwoFactorSetup_ResetFloodWait(timeIntervalString(strings: strongSelf.presentationData.strings, value: remainingSeconds)).0
|
||||
text = strongSelf.presentationData.strings.TwoFactorSetup_ResetFloodWait(timeIntervalString(strings: strongSelf.presentationData.strings, value: remainingSeconds)).string
|
||||
} else {
|
||||
text = strongSelf.presentationData.strings.TwoStepAuth_FloodError
|
||||
}
|
||||
|
|
@ -1378,12 +1378,12 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||
]
|
||||
case let .passwordRecoveryEmail(emailPattern, _):
|
||||
title = presentationData.strings.TwoFactorSetup_EmailVerification_Title
|
||||
let (rawText, ranges) = presentationData.strings.TwoFactorSetup_EmailVerification_Text(emailPattern)
|
||||
let formattedString = presentationData.strings.TwoFactorSetup_EmailVerification_Text(emailPattern)
|
||||
|
||||
let string = NSMutableAttributedString()
|
||||
string.append(NSAttributedString(string: rawText, font: Font.regular(16.0), textColor: presentationData.theme.list.itemPrimaryTextColor))
|
||||
for (_, range) in ranges {
|
||||
string.addAttribute(.font, value: Font.semibold(16.0), range: range)
|
||||
string.append(NSAttributedString(string: formattedString.string, font: Font.regular(16.0), textColor: presentationData.theme.list.itemPrimaryTextColor))
|
||||
for range in formattedString.ranges {
|
||||
string.addAttribute(.font, value: Font.semibold(16.0), range: range.range)
|
||||
}
|
||||
|
||||
text = string
|
||||
|
|
@ -1405,12 +1405,12 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||
]
|
||||
case let .emailConfirmation(_, emailPattern, _):
|
||||
title = presentationData.strings.TwoFactorSetup_EmailVerification_Title
|
||||
let (rawText, ranges) = presentationData.strings.TwoFactorSetup_EmailVerification_Text(emailPattern)
|
||||
let formattedString = presentationData.strings.TwoFactorSetup_EmailVerification_Text(emailPattern)
|
||||
|
||||
let string = NSMutableAttributedString()
|
||||
string.append(NSAttributedString(string: rawText, font: Font.regular(16.0), textColor: presentationData.theme.list.itemPrimaryTextColor))
|
||||
for (_, range) in ranges {
|
||||
string.addAttribute(.font, value: Font.semibold(16.0), range: range)
|
||||
string.append(NSAttributedString(string: formattedString.string, font: Font.regular(16.0), textColor: presentationData.theme.list.itemPrimaryTextColor))
|
||||
for range in formattedString.ranges {
|
||||
string.addAttribute(.font, value: Font.semibold(16.0), range: range.range)
|
||||
}
|
||||
|
||||
text = string
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ final class AvatarGalleryItemFooterContentNode: GalleryFooterContentNode {
|
|||
case let .image(_, _, _, videoRepresentations, peer, date, _, _, _, _):
|
||||
nameText = peer?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? ""
|
||||
if let date = date {
|
||||
dateText = humanReadableStringForTimestamp(strings: self.strings, dateTimeFormat: self.dateTimeFormat, timestamp: date).0
|
||||
dateText = humanReadableStringForTimestamp(strings: self.strings, dateTimeFormat: self.dateTimeFormat, timestamp: date).string
|
||||
}
|
||||
|
||||
if (!videoRepresentations.isEmpty) {
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ class PeerAvatarImageGalleryItem: GalleryItem {
|
|||
let node = PeerAvatarImageGalleryItemNode(context: self.context, presentationData: self.presentationData, peer: self.peer, sourceCorners: self.sourceCorners)
|
||||
|
||||
if let indexData = self.entry.indexData {
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(indexData.position + 1)", "\(indexData.totalCount)").0))
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(indexData.position + 1)", "\(indexData.totalCount)").string))
|
||||
}
|
||||
|
||||
node.setEntry(self.entry, synchronous: synchronous)
|
||||
|
|
@ -85,7 +85,7 @@ class PeerAvatarImageGalleryItem: GalleryItem {
|
|||
func updateNode(node: GalleryItemNode, synchronous: Bool) {
|
||||
if let node = node as? PeerAvatarImageGalleryItemNode {
|
||||
if let indexData = self.entry.indexData {
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(indexData.position + 1)", "\(indexData.totalCount)").0))
|
||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(indexData.position + 1)", "\(indexData.totalCount)").string))
|
||||
}
|
||||
let previousContentAnimations = node.imageNode.contentAnimations
|
||||
if synchronous {
|
||||
|
|
|
|||
|
|
@ -736,7 +736,7 @@ private func channelAdminControllerEntries(presentationData: PresentationData, s
|
|||
let rankEnabled = !state.updating && canEdit
|
||||
entries.append(.rankTitle(presentationData.theme, presentationData.strings.Group_EditAdmin_RankTitle.uppercased(), rankEnabled && state.focusedOnRank ? Int32(currentRank?.count ?? 0) : nil, rankMaxLength))
|
||||
entries.append(.rank(presentationData.theme, presentationData.strings, isCreator ? presentationData.strings.Group_EditAdmin_RankOwnerPlaceholder : presentationData.strings.Group_EditAdmin_RankAdminPlaceholder, currentRank ?? "", rankEnabled))
|
||||
entries.append(.rankInfo(presentationData.theme, presentationData.strings.Group_EditAdmin_RankInfo(placeholder).0))
|
||||
entries.append(.rankInfo(presentationData.theme, presentationData.strings.Group_EditAdmin_RankInfo(placeholder).string))
|
||||
}
|
||||
|
||||
if canDismiss {
|
||||
|
|
@ -1059,9 +1059,9 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
|||
if let admin = adminView.peers[adminView.peerId] {
|
||||
switch channel.info {
|
||||
case .broadcast:
|
||||
text = presentationData.strings.Privacy_GroupsAndChannels_InviteToChannelError(admin.compactDisplayTitle, admin.compactDisplayTitle).0
|
||||
text = presentationData.strings.Privacy_GroupsAndChannels_InviteToChannelError(admin.compactDisplayTitle, admin.compactDisplayTitle).string
|
||||
case .group:
|
||||
text = presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(admin.compactDisplayTitle, admin.compactDisplayTitle).0
|
||||
text = presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(admin.compactDisplayTitle, admin.compactDisplayTitle).string
|
||||
}
|
||||
}
|
||||
case .notMutualContact:
|
||||
|
|
@ -1143,9 +1143,9 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
|||
case .restricted:
|
||||
switch channel.info {
|
||||
case .broadcast:
|
||||
text = presentationData.strings.Privacy_GroupsAndChannels_InviteToChannelError(admin.compactDisplayTitle, admin.compactDisplayTitle).0
|
||||
text = presentationData.strings.Privacy_GroupsAndChannels_InviteToChannelError(admin.compactDisplayTitle, admin.compactDisplayTitle).string
|
||||
case .group:
|
||||
text = presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(admin.compactDisplayTitle, admin.compactDisplayTitle).0
|
||||
text = presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(admin.compactDisplayTitle, admin.compactDisplayTitle).string
|
||||
}
|
||||
case .notMutualContact:
|
||||
if case .broadcast = channel.info {
|
||||
|
|
@ -1204,7 +1204,7 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
|||
updateRightsDisposable.set((context.engine.peers.addGroupAdmin(peerId: peerId, adminId: adminId)
|
||||
|> deliverOnMainQueue).start(error: { error in
|
||||
if case let .addMemberError(error) = error, case .privacy = error, let admin = adminView.peers[adminView.peerId] {
|
||||
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(admin.compactDisplayTitle, admin.compactDisplayTitle).0, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
|
||||
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(admin.compactDisplayTitle, admin.compactDisplayTitle).string, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
|
||||
} else if case .adminsTooMuch = error {
|
||||
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Group_ErrorAdminsTooMuch, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
|
||||
}
|
||||
|
|
@ -1264,7 +1264,7 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
|||
if case let .addMemberError(error) = error {
|
||||
var text = presentationData.strings.Login_UnknownError
|
||||
if case .restricted = error, let admin = adminView.peers[adminView.peerId] {
|
||||
text = presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(admin.compactDisplayTitle, admin.compactDisplayTitle).0
|
||||
text = presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(admin.compactDisplayTitle, admin.compactDisplayTitle).string
|
||||
} else if case .tooMuchJoined = error {
|
||||
text = presentationData.strings.Invite_ChannelsTooMuch
|
||||
}
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ private enum ChannelAdminsEntry: ItemListNodeEntry {
|
|||
if peer.id == participant.peer.id {
|
||||
peerText = strings.Channel_Management_LabelAdministrator
|
||||
} else {
|
||||
peerText = strings.Channel_Management_PromotedBy(peer.displayTitle(strings: strings, displayOrder: nameDisplayOrder)).0
|
||||
peerText = strings.Channel_Management_PromotedBy(peer.displayTitle(strings: strings, displayOrder: nameDisplayOrder)).string
|
||||
}
|
||||
} else {
|
||||
peerText = ""
|
||||
|
|
@ -545,7 +545,7 @@ public func channelAdminsController(context: AccountContext, peerId initialPeerI
|
|||
guard let peer = peer, let user = user else {
|
||||
return
|
||||
}
|
||||
presentControllerImpl?(UndoOverlayController(presentationData: context.sharedContext.currentPresentationData.with { $0 }, content: .succeed(text: presentationData.strings.Channel_OwnershipTransfer_TransferCompleted(user.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0), elevatedLayout: false, action: { _ in return false }), nil)
|
||||
presentControllerImpl?(UndoOverlayController(presentationData: context.sharedContext.currentPresentationData.with { $0 }, content: .succeed(text: presentationData.strings.Channel_OwnershipTransfer_TransferCompleted(user.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string), elevatedLayout: false, action: { _ in return false }), nil)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -318,7 +318,7 @@ private func channelBannedMemberControllerEntries(presentationData: Presentation
|
|||
entries.append(.timeout(presentationData.theme, presentationData.strings.GroupPermission_Duration, currentTimeoutString))
|
||||
|
||||
if let initialParticipant = initialParticipant, case let .member(member) = initialParticipant, let banInfo = member.banInfo, let initialBannedBy = initialBannedBy {
|
||||
entries.append(.exceptionInfo(presentationData.theme, presentationData.strings.GroupPermission_AddedInfo(initialBannedBy.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), stringForRelativeSymbolicTimestamp(strings: presentationData.strings, relativeTimestamp: banInfo.timestamp, relativeTo: state.referenceTimestamp, dateTimeFormat: presentationData.dateTimeFormat)).0))
|
||||
entries.append(.exceptionInfo(presentationData.theme, presentationData.strings.GroupPermission_AddedInfo(initialBannedBy.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), stringForRelativeSymbolicTimestamp(strings: presentationData.strings, relativeTimestamp: banInfo.timestamp, relativeTo: state.referenceTimestamp, dateTimeFormat: presentationData.dateTimeFormat)).string))
|
||||
entries.append(.delete(presentationData.theme, presentationData.strings.GroupPermission_Delete))
|
||||
}
|
||||
} else if let group = channelView.peers[channelView.peerId] as? TelegramGroup, let member = memberView.peers[memberView.peerId] {
|
||||
|
|
@ -364,7 +364,7 @@ private func channelBannedMemberControllerEntries(presentationData: Presentation
|
|||
entries.append(.timeout(presentationData.theme, presentationData.strings.GroupPermission_Duration, currentTimeoutString))
|
||||
|
||||
if let initialParticipant = initialParticipant, case let .member(member) = initialParticipant, let banInfo = member.banInfo, let initialBannedBy = initialBannedBy {
|
||||
entries.append(.exceptionInfo(presentationData.theme, presentationData.strings.GroupPermission_AddedInfo(initialBannedBy.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), stringForRelativeSymbolicTimestamp(strings: presentationData.strings, relativeTimestamp: banInfo.timestamp, relativeTo: state.referenceTimestamp, dateTimeFormat: presentationData.dateTimeFormat)).0))
|
||||
entries.append(.exceptionInfo(presentationData.theme, presentationData.strings.GroupPermission_AddedInfo(initialBannedBy.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), stringForRelativeSymbolicTimestamp(strings: presentationData.strings, relativeTimestamp: banInfo.timestamp, relativeTo: state.referenceTimestamp, dateTimeFormat: presentationData.dateTimeFormat)).string))
|
||||
entries.append(.delete(presentationData.theme, presentationData.strings.GroupPermission_Delete))
|
||||
}
|
||||
}
|
||||
|
|
@ -717,7 +717,7 @@ public func channelBannedMemberController(context: AccountContext, peerId: PeerI
|
|||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
items.append(ActionSheetTextItem(title: presentationData.strings.GroupPermission_ApplyAlertText(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0))
|
||||
items.append(ActionSheetTextItem(title: presentationData.strings.GroupPermission_ApplyAlertText(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string))
|
||||
items.append(ActionSheetButtonItem(title: presentationData.strings.GroupPermission_ApplyAlertAction, color: .accent, font: .default, enabled: true, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
applyRights()
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ private enum ChannelBlacklistEntry: ItemListNodeEntry {
|
|||
switch participant.participant {
|
||||
case let .member(_, _, _, banInfo, _):
|
||||
if let banInfo = banInfo, let peer = participant.peers[banInfo.restrictedBy] {
|
||||
text = .text(strings.Channel_Management_RemovedBy(peer.displayTitle(strings: strings, displayOrder: nameDisplayOrder)).0, .secondary)
|
||||
text = .text(strings.Channel_Management_RemovedBy(peer.displayTitle(strings: strings, displayOrder: nameDisplayOrder)).string, .secondary)
|
||||
}
|
||||
default:
|
||||
break
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ private final class ChannelDiscussionGroupActionSheetItemNode: ActionSheetItemNo
|
|||
self.channelAvatarNode.setPeer(context: context, theme: (context.sharedContext.currentPresentationData.with { $0 }).theme, peer: channelPeer)
|
||||
self.groupAvatarNode.setPeer(context: context, theme: (context.sharedContext.currentPresentationData.with { $0 }).theme, peer: groupPeer)
|
||||
|
||||
let text: (String, [(Int, NSRange)])
|
||||
let text: PresentationStrings.FormattedString
|
||||
if let channelPeer = channelPeer as? TelegramChannel, let addressName = channelPeer.addressName, !addressName.isEmpty {
|
||||
text = strings.Channel_DiscussionGroup_PublicChannelLink(groupPeer.displayTitle(strings: strings, displayOrder: nameDisplayOrder), channelPeer.displayTitle(strings: strings, displayOrder: nameDisplayOrder))
|
||||
} else {
|
||||
|
|
@ -79,9 +79,9 @@ private final class ChannelDiscussionGroupActionSheetItemNode: ActionSheetItemNo
|
|||
let textFont = Font.regular(floor(theme.baseFontSize * 14.0 / 17.0))
|
||||
let boldFont = Font.semibold(floor(theme.baseFontSize * 14.0 / 17.0))
|
||||
|
||||
let attributedText = NSMutableAttributedString(attributedString: NSAttributedString(string: text.0, font: textFont, textColor: theme.primaryTextColor))
|
||||
for (_, range) in text.1 {
|
||||
attributedText.addAttribute(.font, value: boldFont, range: range)
|
||||
let attributedText = NSMutableAttributedString(attributedString: NSAttributedString(string: text.string, font: textFont, textColor: theme.primaryTextColor))
|
||||
for range in text.ranges {
|
||||
attributedText.addAttribute(.font, value: boldFont, range: range.range)
|
||||
}
|
||||
|
||||
self.textNode.attributedText = attributedText
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ final class ChannelDiscussionGroupSearchContainerNode: SearchDisplayControllerCo
|
|||
self.dimNode = ASDisplayNode()
|
||||
self.listNode = ListView()
|
||||
self.listNode.accessibilityPageScrolledString = { row, count in
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
super.init()
|
||||
|
|
|
|||
|
|
@ -136,9 +136,9 @@ private enum ChannelDiscussionGroupSetupControllerEntry: ItemListNodeEntry {
|
|||
let text: String
|
||||
if let title = title {
|
||||
if isGroup {
|
||||
text = presentationData.strings.Channel_CommentsGroup_HeaderGroupSet(title).0
|
||||
text = presentationData.strings.Channel_CommentsGroup_HeaderGroupSet(title).string
|
||||
} else {
|
||||
text = presentationData.strings.Channel_CommentsGroup_HeaderSet(title).0
|
||||
text = presentationData.strings.Channel_CommentsGroup_HeaderSet(title).string
|
||||
}
|
||||
} else {
|
||||
text = presentationData.strings.Channel_CommentsGroup_Header
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ class ChannelDiscussionGroupSetupHeaderItemNode: ListViewItemNode {
|
|||
let bold = MarkdownAttributeSet(font: titleBoldFont, textColor: item.theme.list.sectionHeaderTextColor)
|
||||
let string: NSAttributedString
|
||||
if let title = item.title {
|
||||
string = addAttributesToStringWithRanges(item.isGroup ? item.strings.Channel_CommentsGroup_HeaderGroupSet(title) : item.strings.Channel_CommentsGroup_HeaderSet(title), body: body, argumentAttributes: [0: bold])
|
||||
string = addAttributesToStringWithRanges(item.isGroup ? item.strings.Channel_CommentsGroup_HeaderGroupSet(title)._tuple : item.strings.Channel_CommentsGroup_HeaderSet(title)._tuple, body: body, argumentAttributes: [0: bold])
|
||||
} else {
|
||||
string = NSAttributedString(string: item.strings.Channel_CommentsGroup_Header, font: titleFont, textColor: item.theme.list.sectionHeaderTextColor)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -337,12 +337,12 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon
|
|||
|
||||
self.emptyQueryListNode = ListView()
|
||||
self.emptyQueryListNode.accessibilityPageScrolledString = { row, count in
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
self.listNode = ListView()
|
||||
self.listNode.accessibilityPageScrolledString = { row, count in
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
self.emptyResultsTitleNode = ImmediateTextNode()
|
||||
|
|
@ -817,7 +817,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon
|
|||
if peer.id == participant.peer.id {
|
||||
label = presentationData.strings.Channel_Management_LabelAdministrator
|
||||
} else {
|
||||
label = presentationData.strings.Channel_Management_PromotedBy(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0
|
||||
label = presentationData.strings.Channel_Management_PromotedBy(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -844,7 +844,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon
|
|||
switch participant.participant {
|
||||
case let .member(_, _, _, banInfo, _):
|
||||
if let banInfo = banInfo, let peer = participant.peers[banInfo.restrictedBy] {
|
||||
label = presentationData.strings.Channel_Management_RemovedBy(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0
|
||||
label = presentationData.strings.Channel_Management_RemovedBy(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string
|
||||
}
|
||||
default:
|
||||
break
|
||||
|
|
@ -1121,7 +1121,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon
|
|||
if peer.id == participant.peer.id {
|
||||
label = presentationData.strings.Channel_Management_LabelAdministrator
|
||||
} else {
|
||||
label = presentationData.strings.Channel_Management_PromotedBy(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0
|
||||
label = presentationData.strings.Channel_Management_PromotedBy(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1148,7 +1148,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon
|
|||
switch participant.participant {
|
||||
case let .member(_, _, _, banInfo, _):
|
||||
if let banInfo = banInfo, let peer = participant.peers[banInfo.restrictedBy] {
|
||||
label = presentationData.strings.Channel_Management_RemovedBy(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0
|
||||
label = presentationData.strings.Channel_Management_RemovedBy(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string
|
||||
}
|
||||
default:
|
||||
break
|
||||
|
|
@ -1351,7 +1351,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon
|
|||
strongSelf.listNode.isHidden = !isSearching
|
||||
strongSelf.emptyQueryListNode.isHidden = isSearching
|
||||
|
||||
strongSelf.emptyResultsTextNode.attributedText = NSAttributedString(string: strongSelf.presentationData.strings.ChatList_Search_NoResultsQueryDescription(transition.query).0, font: Font.regular(15.0), textColor: strongSelf.presentationData.theme.list.freeTextColor)
|
||||
strongSelf.emptyResultsTextNode.attributedText = NSAttributedString(string: strongSelf.presentationData.strings.ChatList_Search_NoResultsQueryDescription(transition.query).string, font: Font.regular(15.0), textColor: strongSelf.presentationData.theme.list.freeTextColor)
|
||||
|
||||
let emptyResults = transition.isSearching && transition.isEmpty
|
||||
strongSelf.emptyResultsTitleNode.isHidden = !emptyResults
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ class ChannelMembersSearchControllerNode: ASDisplayNode {
|
|||
}
|
||||
|
||||
self.listNode.accessibilityPageScrolledString = { row, count in
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
super.init()
|
||||
|
|
|
|||
|
|
@ -542,10 +542,10 @@ private func confirmChannelOwnershipTransferController(context: AccountContext,
|
|||
var text: String
|
||||
if isGroup {
|
||||
title = presentationData.strings.Group_OwnershipTransfer_Title
|
||||
text = presentationData.strings.Group_OwnershipTransfer_DescriptionInfo(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), member.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0
|
||||
text = presentationData.strings.Group_OwnershipTransfer_DescriptionInfo(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), member.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string
|
||||
} else {
|
||||
title = presentationData.strings.Channel_OwnershipTransfer_Title
|
||||
text = presentationData.strings.Channel_OwnershipTransfer_DescriptionInfo(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), member.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0
|
||||
text = presentationData.strings.Channel_OwnershipTransfer_DescriptionInfo(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), member.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string
|
||||
}
|
||||
|
||||
let attributedTitle = NSAttributedString(string: title, font: Font.medium(17.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||
|
|
|
|||
|
|
@ -451,7 +451,7 @@ private func channelPermissionsControllerEntries(context: AccountContext, presen
|
|||
if channel.flags.contains(.isCreator) && !channel.flags.contains(.isGigagroup), let memberCount = cachedData.participantsSummary.memberCount, memberCount > participantsLimit - 1000 {
|
||||
entries.append(.conversionHeader(presentationData.theme, presentationData.strings.GroupInfo_Permissions_BroadcastTitle.uppercased()))
|
||||
entries.append(.conversion(presentationData.theme, presentationData.strings.GroupInfo_Permissions_BroadcastConvert))
|
||||
entries.append(.conversionInfo(presentationData.theme, presentationData.strings.GroupInfo_Permissions_BroadcastConvertInfo(presentationStringsFormattedNumber(participantsLimit, presentationData.dateTimeFormat.groupingSeparator)).0))
|
||||
entries.append(.conversionInfo(presentationData.theme, presentationData.strings.GroupInfo_Permissions_BroadcastConvertInfo(presentationStringsFormattedNumber(participantsLimit, presentationData.dateTimeFormat.groupingSeparator)).string))
|
||||
}
|
||||
|
||||
entries.append(.slowmodeHeader(presentationData.theme, presentationData.strings.GroupInfo_Permissions_SlowmodeHeader))
|
||||
|
|
@ -753,7 +753,7 @@ public func channelPermissionsController(context: AccountContext, peerId origina
|
|||
let _ = (convertGroupToGigagroup(account: context.account, peerId: originalPeerId)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
let participantsLimit = context.currentLimitsConfiguration.with { $0 }.maxSupergroupMemberCount
|
||||
presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .gigagroupConversion(text: presentationData.strings.BroadcastGroups_Success(presentationStringsFormattedNumber(participantsLimit, presentationData.dateTimeFormat.decimalSeparator)).0), elevatedLayout: true, action: { _ in return false }), nil)
|
||||
presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .gigagroupConversion(text: presentationData.strings.BroadcastGroups_Success(presentationStringsFormattedNumber(participantsLimit, presentationData.dateTimeFormat.decimalSeparator)).string), elevatedLayout: true, action: { _ in return false }), nil)
|
||||
|
||||
dismissToChatController?()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -576,7 +576,7 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa
|
|||
case let .availability(availability):
|
||||
switch availability {
|
||||
case .available:
|
||||
text = presentationData.strings.Channel_Username_UsernameIsAvailable(currentAddressName).0
|
||||
text = presentationData.strings.Channel_Username_UsernameIsAvailable(currentAddressName).string
|
||||
case .invalid:
|
||||
text = presentationData.strings.Channel_Username_InvalidCharacters
|
||||
case .taken:
|
||||
|
|
@ -708,7 +708,7 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa
|
|||
case let .availability(availability):
|
||||
switch availability {
|
||||
case .available:
|
||||
text = presentationData.strings.Channel_Username_UsernameIsAvailable(currentAddressName).0
|
||||
text = presentationData.strings.Channel_Username_UsernameIsAvailable(currentAddressName).string
|
||||
case .invalid:
|
||||
text = presentationData.strings.Channel_Username_InvalidCharacters
|
||||
case .taken:
|
||||
|
|
|
|||
|
|
@ -690,11 +690,11 @@ private func deviceContactInfoEntries(account: Account, presentationData: Presen
|
|||
}
|
||||
|
||||
if contactData.basicData.phoneNumbers.isEmpty {
|
||||
entries.append(.phoneNumberSharingInfo(entries.count, presentationData.theme, presentationData.strings.AddContact_ContactWillBeSharedAfterMutual(personCompactName).0))
|
||||
entries.append(.phoneNumberSharingInfo(entries.count, presentationData.theme, presentationData.strings.AddContact_ContactWillBeSharedAfterMutual(personCompactName).string))
|
||||
}
|
||||
if shareViaException {
|
||||
entries.append(.phoneNumberShareViaException(entries.count, presentationData.theme, presentationData.strings.AddContact_SharedContactException, state.addToPrivacyExceptions))
|
||||
entries.append(.phoneNumberShareViaExceptionInfo(entries.count, presentationData.theme, presentationData.strings.AddContact_SharedContactExceptionInfo(personCompactName).0))
|
||||
entries.append(.phoneNumberShareViaExceptionInfo(entries.count, presentationData.theme, presentationData.strings.AddContact_SharedContactExceptionInfo(personCompactName).string))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -798,7 +798,7 @@ private final class DeviceContactInfoController: ItemListController, MFMessageCo
|
|||
composer.messageComposeDelegate = self
|
||||
composer.recipients = Array(Set(numbers))
|
||||
let url = presentationData.strings.InviteText_URL
|
||||
let body = presentationData.strings.InviteText_SingleContact(url).0
|
||||
let body = presentationData.strings.InviteText_SingleContact(url).string
|
||||
composer.body = body
|
||||
self.composer = composer
|
||||
if let window = self.view.window {
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ private final class OldChannelsSearchContainerNode: SearchDisplayControllerConte
|
|||
self.listNode.backgroundColor = self.presentationData.theme.chatList.backgroundColor
|
||||
self.listNode.isHidden = true
|
||||
self.listNode.accessibilityPageScrolledString = { row, count in
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).0
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
super.init()
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ class PeerRemoveTimeoutItemNode: ListViewItemNode, ItemListItemNode {
|
|||
if item.availableValues[index] == Int32.max {
|
||||
text = item.presentationData.strings.AutoremoveSetup_TimerValueNever
|
||||
} else {
|
||||
text = item.presentationData.strings.AutoremoveSetup_TimerValueAfter(timeIntervalString(strings: item.presentationData.strings, value: item.availableValues[index])).0
|
||||
text = item.presentationData.strings.AutoremoveSetup_TimerValueAfter(timeIntervalString(strings: item.presentationData.strings, value: item.availableValues[index])).string
|
||||
}
|
||||
return makeLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: text, font: Font.regular(13.0), textColor: item.presentationData.theme.list.itemSecondaryTextColor), maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: 100.0, height: 100.0)))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,14 +119,14 @@ final class SecretChatKeyControllerNode: ViewControllerTracingNode {
|
|||
|
||||
let (keyTextLayout, keyTextApply) = makeKeyTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: text, font: Font.semiboldMonospace(15.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: layout.size.width - sideInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .left, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let (infoRaw, infoRanges) = self.presentationData.strings.EncryptionKey_Description(self.peer.compactDisplayTitle, self.peer.compactDisplayTitle)
|
||||
let infoText = NSMutableAttributedString(string: infoRaw, attributes: [.font: Font.regular(14.0), .foregroundColor: self.presentationData.theme.list.itemPrimaryTextColor])
|
||||
let infoString = self.presentationData.strings.EncryptionKey_Description(self.peer.compactDisplayTitle, self.peer.compactDisplayTitle)
|
||||
let infoText = NSMutableAttributedString(string: infoString.string, attributes: [.font: Font.regular(14.0), .foregroundColor: self.presentationData.theme.list.itemPrimaryTextColor])
|
||||
|
||||
for (_, range) in infoRanges {
|
||||
infoText.addAttributes([.font: Font.semibold(14.0)], range: range)
|
||||
for range in infoString.ranges {
|
||||
infoText.addAttributes([.font: Font.semibold(14.0)], range: range.range)
|
||||
}
|
||||
|
||||
let linkRange = (infoRaw as NSString).range(of: "telegram.org")
|
||||
let linkRange = (infoString.string as NSString).range(of: "telegram.org")
|
||||
if linkRange.location != NSNotFound {
|
||||
infoText.addAttributes([.foregroundColor: self.presentationData.theme.list.itemAccentColor, NSAttributedString.Key(rawValue: TelegramTextAttributes.URL): "https://telegram.org/faq#secret-chats"], range: linkRange)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ public func openAddPersonContactImpl(context: AccountContext, peerId: PeerId, pu
|
|||
}
|
||||
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
present(OverlayStatusController(theme: presentationData.theme, type: .genericSuccess(presentationData.strings.AddContact_StatusSuccess(peer.compactDisplayTitle).0, true)), nil)
|
||||
present(OverlayStatusController(theme: presentationData.theme, type: .genericSuccess(presentationData.strings.AddContact_StatusSuccess(peer.compactDisplayTitle).string, true)), nil)
|
||||
}
|
||||
}), completed: nil, cancelled: nil))
|
||||
})
|
||||
|
|
|
|||
|
|
@ -226,10 +226,10 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
|
|||
arguments.toggleVisibility(!stop)
|
||||
})
|
||||
case let .user(_, _, strings, dateTimeFormat, nameDisplayOrder, peer):
|
||||
var text = strings.Map_DistanceAway(shortStringForDistance(strings: strings, distance: peer.distance)).0
|
||||
var text = strings.Map_DistanceAway(shortStringForDistance(strings: strings, distance: peer.distance)).string
|
||||
let isSelfPeer = peer.peer.0.id == arguments.context.account.peerId
|
||||
if isSelfPeer {
|
||||
text = strings.PeopleNearby_VisibleUntil(humanReadableStringForTimestamp(strings: strings, dateTimeFormat: dateTimeFormat, timestamp: peer.expires).0).0
|
||||
text = strings.PeopleNearby_VisibleUntil(humanReadableStringForTimestamp(strings: strings, dateTimeFormat: dateTimeFormat, timestamp: peer.expires).string).string
|
||||
}
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, context: arguments.context, peer: peer.peer.0, aliasHandling: .standard, nameColor: .primary, nameStyle: .distinctBold, presence: nil, text: .text(text, .secondary), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: !isSelfPeer, sectionId: self.section, action: {
|
||||
if !isSelfPeer {
|
||||
|
|
@ -251,9 +251,9 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
|
|||
case let .group(_, _, strings, dateTimeFormat, nameDisplayOrder, peer, highlighted):
|
||||
var text: ItemListPeerItemText
|
||||
if let cachedData = peer.peer.1 as? CachedChannelData, let memberCount = cachedData.participantsSummary.memberCount {
|
||||
text = .text("\(strings.Map_DistanceAway(shortStringForDistance(strings: strings, distance: peer.distance)).0), \(memberCount > 0 ? strings.Conversation_StatusMembers(memberCount) : strings.PeopleNearby_NoMembers)", .secondary)
|
||||
text = .text("\(strings.Map_DistanceAway(shortStringForDistance(strings: strings, distance: peer.distance)).string), \(memberCount > 0 ? strings.Conversation_StatusMembers(memberCount) : strings.PeopleNearby_NoMembers)", .secondary)
|
||||
} else {
|
||||
text = .text(strings.Map_DistanceAway(shortStringForDistance(strings: strings, distance: peer.distance)).0, .secondary)
|
||||
text = .text(strings.Map_DistanceAway(shortStringForDistance(strings: strings, distance: peer.distance)).string, .secondary)
|
||||
}
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, context: arguments.context, peer: peer.peer.0, aliasHandling: .standard, nameColor: .primary, nameStyle: .distinctBold, presence: nil, text: text, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, highlighted: highlighted, selectable: true, sectionId: self.section, action: {
|
||||
arguments.openChat(peer.peer.0)
|
||||
|
|
@ -265,9 +265,9 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
|
|||
case let .channel(_, _, strings, dateTimeFormat, nameDisplayOrder, peer, highlighted):
|
||||
var text: ItemListPeerItemText
|
||||
if let cachedData = peer.peer.1 as? CachedChannelData, let memberCount = cachedData.participantsSummary.memberCount {
|
||||
text = .text("\(strings.Map_DistanceAway(shortStringForDistance(strings: strings, distance: peer.distance)).0), \(strings.Conversation_StatusSubscribers(memberCount))", .secondary)
|
||||
text = .text("\(strings.Map_DistanceAway(shortStringForDistance(strings: strings, distance: peer.distance)).string), \(strings.Conversation_StatusSubscribers(memberCount))", .secondary)
|
||||
} else {
|
||||
text = .text(strings.Map_DistanceAway(shortStringForDistance(strings: strings, distance: peer.distance)).0, .secondary)
|
||||
text = .text(strings.Map_DistanceAway(shortStringForDistance(strings: strings, distance: peer.distance)).string, .secondary)
|
||||
}
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, context: arguments.context, peer: peer.peer.0, aliasHandling: .standard, nameColor: .primary, nameStyle: .distinctBold, presence: nil, text: text, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, highlighted: highlighted, selectable: true, sectionId: self.section, action: {
|
||||
arguments.openChat(peer.peer.0)
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ public func openUserGeneratedUrl(context: AccountContext, peerId: PeerId?, url:
|
|||
}
|
||||
var displayUrl = rawDisplayUrl
|
||||
displayUrl = displayUrl.replacingOccurrences(of: "\u{202e}", with: "")
|
||||
present(textAlertController(context: context, title: nil, text: presentationData.strings.Generic_OpenHiddenLinkAlert(displayUrl).0, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_No, action: {}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Yes, action: {
|
||||
present(textAlertController(context: context, title: nil, text: presentationData.strings.Generic_OpenHiddenLinkAlert(displayUrl).string, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_No, action: {}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Yes, action: {
|
||||
openImpl()
|
||||
})]))
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,11 @@
|
|||
|
||||
filegroup(
|
||||
name = "PresentationStringsResources",
|
||||
srcs = glob([
|
||||
"Resources/**/*",
|
||||
], exclude = ["Resources/**/.*"]),
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
objc_library(
|
||||
name = "PresentationStrings",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,12 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
typedef NS_ENUM(int32_t, StringPluralizationForm) {
|
||||
StringPluralizationFormZero,
|
||||
StringPluralizationFormOne,
|
||||
StringPluralizationFormTwo,
|
||||
StringPluralizationFormFew,
|
||||
StringPluralizationFormMany,
|
||||
StringPluralizationFormOther
|
||||
};
|
||||
|
||||
StringPluralizationForm getStringPluralizationForm(unsigned int lc, int n);
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load diff
355
submodules/PresentationStrings/Sources/StringPluralization.m
Normal file
355
submodules/PresentationStrings/Sources/StringPluralization.m
Normal file
|
|
@ -0,0 +1,355 @@
|
|||
#import <PresentationStrings/StringPluralization.h>
|
||||
|
||||
StringPluralizationForm getStringPluralizationForm(unsigned int lc, int n) {
|
||||
switch (lc) {
|
||||
|
||||
// set1
|
||||
case 0x6c74: // lt
|
||||
if (((n % 10) == 1) && (((n % 100) < 11 || (n % 100) > 19))) // n mod 10 is 1 and n mod 100 not in 11..19
|
||||
return StringPluralizationFormOne;
|
||||
if ((((n % 10) >= 2 && (n % 10) <= 9)) && (((n % 100) < 11 || (n % 100) > 19))) // n mod 10 in 2..9 and n mod 100 not in 11..19
|
||||
return StringPluralizationFormFew;
|
||||
break;
|
||||
|
||||
// set2
|
||||
case 0x6c76: // lv
|
||||
if (n == 0) // n is 0
|
||||
return StringPluralizationFormZero;
|
||||
if (((n % 10) == 1) && ((n % 100) != 11)) // n mod 10 is 1 and n mod 100 is not 11
|
||||
return StringPluralizationFormOne;
|
||||
break;
|
||||
|
||||
// set3
|
||||
case 0x6379: // cy
|
||||
if (n == 2) // n is 2
|
||||
return StringPluralizationFormTwo;
|
||||
if (n == 3) // n is 3
|
||||
return StringPluralizationFormFew;
|
||||
if (n == 0) // n is 0
|
||||
return StringPluralizationFormZero;
|
||||
if (n == 1) // n is 1
|
||||
return StringPluralizationFormOne;
|
||||
if (n == 6) // n is 6
|
||||
return StringPluralizationFormMany;
|
||||
break;
|
||||
|
||||
// set4
|
||||
case 0x6265: // be
|
||||
case 0x7275: // ru
|
||||
case 0x756b: // uk
|
||||
if (((n % 10) == 1) && ((n % 100) != 11)) // n mod 10 is 1 and n mod 100 is not 11
|
||||
return StringPluralizationFormOne;
|
||||
if ((((n % 10) >= 2 && (n % 10) <= 4)) && (((n % 100) < 12 || (n % 100) > 14))) // n mod 10 in 2..4 and n mod 100 not in 12..14
|
||||
return StringPluralizationFormFew;
|
||||
if (((n % 10) == 0) || (((n % 10) >= 5 && (n % 10) <= 9)) || (((n % 100) >= 11 && (n % 100) <= 14))) // n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14
|
||||
return StringPluralizationFormMany;
|
||||
break;
|
||||
|
||||
// set4 - bugfix
|
||||
case 0x6273: // bs
|
||||
case 0x6872: // hr
|
||||
case 0x7368: // sh
|
||||
case 0x7372: // sr
|
||||
if (((n % 10) == 1) && ((n % 100) != 11)) // n mod 10 is 1 and n mod 100 is not 11
|
||||
return StringPluralizationFormOne;
|
||||
if ((((n % 10) >= 2 && (n % 10) <= 4)) && (((n % 100) < 12 || (n % 100) > 14))) // n mod 10 in 2..4 and n mod 100 not in 12..14
|
||||
return StringPluralizationFormFew;
|
||||
if (((n % 10) == 0) || (((n % 10) >= 5 && (n % 10) <= 9)) || (((n % 100) >= 11 && (n % 100) <= 14))) // n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14
|
||||
return StringPluralizationFormOther;
|
||||
break;
|
||||
|
||||
// set5
|
||||
case 0x6b7368: // ksh
|
||||
if (n == 0) // n is 0
|
||||
return StringPluralizationFormZero;
|
||||
if (n == 1) // n is 1
|
||||
return StringPluralizationFormOne;
|
||||
break;
|
||||
|
||||
// set6
|
||||
case 0x736869: // shi
|
||||
if ((n >= 2 && n <= 10)) // n in 2..10
|
||||
return StringPluralizationFormFew;
|
||||
if ((n >= 0 && n <= 1)) // n within 0..1
|
||||
return StringPluralizationFormOne;
|
||||
break;
|
||||
|
||||
// set7
|
||||
case 0x6865: // he
|
||||
if (n == 2) // n is 2
|
||||
return StringPluralizationFormTwo;
|
||||
if (n == 1) // n is 1
|
||||
return StringPluralizationFormOne;
|
||||
if ((n != 0) && ((n % 10) == 0)) // n is not 0 AND n mod 10 is 0
|
||||
return StringPluralizationFormMany;
|
||||
break;
|
||||
|
||||
// set8
|
||||
case 0x6373: // cs
|
||||
case 0x736b: // sk
|
||||
if (n == 1) // n is 1
|
||||
return StringPluralizationFormOne;
|
||||
if ((n >= 2 && n <= 4)) // n in 2..4
|
||||
return StringPluralizationFormFew;
|
||||
break;
|
||||
|
||||
// set9
|
||||
case 0x6272: // br
|
||||
if ((n != 0) && ((n % 1000000) == 0)) // n is not 0 and n mod 1000000 is 0
|
||||
return StringPluralizationFormMany;
|
||||
if (((n % 10) == 1) && (((n % 100) != 11) && ((n % 100) != 71) && ((n % 100) != 91))) // n mod 10 is 1 and n mod 100 not in 11,71,91
|
||||
return StringPluralizationFormOne;
|
||||
if (((n % 10) == 2) && (((n % 100) != 12) && ((n % 100) != 72) && ((n % 100) != 92))) // n mod 10 is 2 and n mod 100 not in 12,72,92
|
||||
return StringPluralizationFormTwo;
|
||||
if ((((n % 10) >= 3 && (n % 10) <= 4) || ((n % 10) == 9)) && (((n % 100) < 10 || (n % 100) > 19) && ((n % 100) < 70 || (n % 100) > 79) && ((n % 100) < 90 || (n % 100) > 99))) // n mod 10 in 3..4,9 and n mod 100 not in 10..19,70..79,90..99
|
||||
return StringPluralizationFormFew;
|
||||
break;
|
||||
|
||||
// set10
|
||||
case 0x736c: // sl
|
||||
if ((n % 100) == 2) // n mod 100 is 2
|
||||
return StringPluralizationFormTwo;
|
||||
if ((n % 100) == 1) // n mod 100 is 1
|
||||
return StringPluralizationFormOne;
|
||||
if (((n % 100) >= 3 && (n % 100) <= 4)) // n mod 100 in 3..4
|
||||
return StringPluralizationFormFew;
|
||||
break;
|
||||
|
||||
// set11
|
||||
case 0x6c6167: // lag
|
||||
if (n == 0) // n is 0
|
||||
return StringPluralizationFormZero;
|
||||
if (((n >= 0 && n <= 2)) && (n != 0) && (n != 2)) // n within 0..2 and n is not 0 and n is not 2
|
||||
return StringPluralizationFormOne;
|
||||
break;
|
||||
|
||||
// set12
|
||||
case 0x706c: // pl
|
||||
if (n == 1) // n is 1
|
||||
return StringPluralizationFormOne;
|
||||
if ((((n % 10) >= 2 && (n % 10) <= 4)) && (((n % 100) < 12 || (n % 100) > 14))) // n mod 10 in 2..4 and n mod 100 not in 12..14
|
||||
return StringPluralizationFormFew;
|
||||
if (((n != 1) && (((n % 10) >= 0 && (n % 10) <= 1))) || (((n % 10) >= 5 && (n % 10) <= 9)) || (((n % 100) >= 12 && (n % 100) <= 14))) // n is not 1 and n mod 10 in 0..1 or n mod 10 in 5..9 or n mod 100 in 12..14
|
||||
return StringPluralizationFormMany;
|
||||
break;
|
||||
|
||||
// set13
|
||||
case 0x6764: // gd
|
||||
if ((n == 2) || (n == 12)) // n in 2,12
|
||||
return StringPluralizationFormTwo;
|
||||
if ((n == 1) || (n == 11)) // n in 1,11
|
||||
return StringPluralizationFormOne;
|
||||
if ((n >= 3 && n <= 10) || (n >= 13 && n <= 19)) // n in 3..10,13..19
|
||||
return StringPluralizationFormFew;
|
||||
break;
|
||||
|
||||
// set14
|
||||
case 0x6776: // gv
|
||||
if ((((n % 10) >= 1 && (n % 10) <= 2)) || ((n % 20) == 0)) // n mod 10 in 1..2 or n mod 20 is 0
|
||||
return StringPluralizationFormOne;
|
||||
break;
|
||||
|
||||
// set15
|
||||
case 0x6d6b: // mk
|
||||
if (((n % 10) == 1) && (n != 11)) // n mod 10 is 1 and n is not 11
|
||||
return StringPluralizationFormOne;
|
||||
break;
|
||||
|
||||
// set16
|
||||
case 0x6d74: // mt
|
||||
if (n == 1) // n is 1
|
||||
return StringPluralizationFormOne;
|
||||
if (((n % 100) >= 11 && (n % 100) <= 19)) // n mod 100 in 11..19
|
||||
return StringPluralizationFormMany;
|
||||
if ((n == 0) || (((n % 100) >= 2 && (n % 100) <= 10))) // n is 0 or n mod 100 in 2..10
|
||||
return StringPluralizationFormFew;
|
||||
break;
|
||||
|
||||
// set17
|
||||
case 0x6d6f: // mo
|
||||
case 0x726f: // ro
|
||||
if (n == 1) // n is 1
|
||||
return StringPluralizationFormOne;
|
||||
if ((n == 0) || ((n != 1) && (((n % 100) >= 1 && (n % 100) <= 19)))) // n is 0 OR n is not 1 AND n mod 100 in 1..19
|
||||
return StringPluralizationFormFew;
|
||||
break;
|
||||
|
||||
// set18
|
||||
case 0x6761: // ga
|
||||
if (n == 2) // n is 2
|
||||
return StringPluralizationFormTwo;
|
||||
if (n == 1) // n is 1
|
||||
return StringPluralizationFormOne;
|
||||
if ((n >= 3 && n <= 6)) // n in 3..6
|
||||
return StringPluralizationFormFew;
|
||||
if ((n >= 7 && n <= 10)) // n in 7..10
|
||||
return StringPluralizationFormMany;
|
||||
break;
|
||||
|
||||
// set19
|
||||
case 0x6666: // ff
|
||||
case 0x6672: // fr
|
||||
case 0x6b6162: // kab
|
||||
if (((n >= 0 && n <= 2)) && (n != 2)) // n within 0..2 and n is not 2
|
||||
return StringPluralizationFormOne;
|
||||
break;
|
||||
|
||||
// set20
|
||||
case 0x6975: // iu
|
||||
case 0x6b77: // kw
|
||||
case 0x7365: // se
|
||||
case 0x6e6171: // naq
|
||||
case 0x736d61: // sma
|
||||
case 0x736d69: // smi
|
||||
case 0x736d6a: // smj
|
||||
case 0x736d6e: // smn
|
||||
case 0x736d73: // sms
|
||||
if (n == 2) // n is 2
|
||||
return StringPluralizationFormTwo;
|
||||
if (n == 1) // n is 1
|
||||
return StringPluralizationFormOne;
|
||||
break;
|
||||
|
||||
// set21
|
||||
case 0x616b: // ak
|
||||
case 0x616d: // am
|
||||
case 0x6268: // bh
|
||||
case 0x6869: // hi
|
||||
case 0x6c6e: // ln
|
||||
case 0x6d67: // mg
|
||||
case 0x7469: // ti
|
||||
case 0x746c: // tl
|
||||
case 0x7761: // wa
|
||||
case 0x66696c: // fil
|
||||
case 0x677577: // guw
|
||||
case 0x6e736f: // nso
|
||||
if ((n >= 0 && n <= 1)) // n in 0..1
|
||||
return StringPluralizationFormOne;
|
||||
break;
|
||||
|
||||
// set22
|
||||
case 0x747a6d: // tzm
|
||||
if (((n >= 0 && n <= 1)) || ((n >= 11 && n <= 99))) // n in 0..1 or n in 11..99
|
||||
return StringPluralizationFormOne;
|
||||
break;
|
||||
|
||||
// set23
|
||||
case 0x6166: // af
|
||||
case 0x6267: // bg
|
||||
case 0x626e: // bn
|
||||
case 0x6361: // ca
|
||||
case 0x6461: // da
|
||||
case 0x6465: // de
|
||||
case 0x6476: // dv
|
||||
case 0x6565: // ee
|
||||
case 0x656c: // el
|
||||
case 0x656e: // en
|
||||
case 0x656f: // eo
|
||||
case 0x6573: // es
|
||||
case 0x6574: // et
|
||||
case 0x6575: // eu
|
||||
case 0x6669: // fi
|
||||
case 0x666f: // fo
|
||||
case 0x6679: // fy
|
||||
case 0x676c: // gl
|
||||
case 0x6775: // gu
|
||||
case 0x6861: // ha
|
||||
case 0x6973: // is
|
||||
case 0x6974: // it
|
||||
case 0x6b6b: // kk
|
||||
case 0x6b6c: // kl
|
||||
case 0x6b73: // ks
|
||||
case 0x6b75: // ku
|
||||
case 0x6b79: // ky
|
||||
case 0x6c62: // lb
|
||||
case 0x6c67: // lg
|
||||
case 0x6d6c: // ml
|
||||
case 0x6d6e: // mn
|
||||
case 0x6d72: // mr
|
||||
case 0x6e62: // nb
|
||||
case 0x6e64: // nd
|
||||
case 0x6e65: // ne
|
||||
case 0x6e6c: // nl
|
||||
case 0x6e6e: // nn
|
||||
case 0x6e6f: // no
|
||||
case 0x6e72: // nr
|
||||
case 0x6e79: // ny
|
||||
case 0x6f6d: // om
|
||||
case 0x6f72: // or
|
||||
case 0x6f73: // os
|
||||
case 0x7061: // pa
|
||||
case 0x7073: // ps
|
||||
case 0x7074: // pt
|
||||
case 0x726d: // rm
|
||||
case 0x736e: // sn
|
||||
case 0x736f: // so
|
||||
case 0x7371: // sq
|
||||
case 0x7373: // ss
|
||||
case 0x7374: // st
|
||||
case 0x7376: // sv
|
||||
case 0x7377: // sw
|
||||
case 0x7461: // ta
|
||||
case 0x7465: // te
|
||||
case 0x746b: // tk
|
||||
case 0x746e: // tn
|
||||
case 0x7473: // ts
|
||||
case 0x7572: // ur
|
||||
case 0x7665: // ve
|
||||
case 0x766f: // vo
|
||||
case 0x7868: // xh
|
||||
case 0x7a75: // zu
|
||||
case 0x617361: // asa
|
||||
case 0x617374: // ast
|
||||
case 0x62656d: // bem
|
||||
case 0x62657a: // bez
|
||||
case 0x627278: // brx
|
||||
case 0x636767: // cgg
|
||||
case 0x636872: // chr
|
||||
case 0x636b62: // ckb
|
||||
case 0x667572: // fur
|
||||
case 0x677377: // gsw
|
||||
case 0x686177: // haw
|
||||
case 0x6a676f: // jgo
|
||||
case 0x6a6d63: // jmc
|
||||
case 0x6b616a: // kaj
|
||||
case 0x6b6367: // kcg
|
||||
case 0x6b6b6a: // kkj
|
||||
case 0x6b7362: // ksb
|
||||
case 0x6d6173: // mas
|
||||
case 0x6d676f: // mgo
|
||||
case 0x6e6168: // nah
|
||||
case 0x6e6e68: // nnh
|
||||
case 0x6e796e: // nyn
|
||||
case 0x706170: // pap
|
||||
case 0x726f66: // rof
|
||||
case 0x72776b: // rwk
|
||||
case 0x736171: // saq
|
||||
case 0x736568: // seh
|
||||
case 0x737379: // ssy
|
||||
case 0x737972: // syr
|
||||
case 0x74656f: // teo
|
||||
case 0x746967: // tig
|
||||
case 0x76756e: // vun
|
||||
case 0x776165: // wae
|
||||
case 0x786f67: // xog
|
||||
if (n == 1) // n is 1
|
||||
return StringPluralizationFormOne;
|
||||
break;
|
||||
|
||||
// set24
|
||||
case 0x6172: // ar
|
||||
if (n == 2) // n is 2
|
||||
return StringPluralizationFormTwo;
|
||||
if (n == 1) // n is 1
|
||||
return StringPluralizationFormOne;
|
||||
if (n == 0) // n is 0
|
||||
return StringPluralizationFormZero;
|
||||
if (((n % 100) >= 3 && (n % 100) <= 10)) // n mod 100 in 3..10
|
||||
return StringPluralizationFormFew;
|
||||
if (((n % 100) >= 11 && (n % 100) <= 99)) // n mod 100 in 11..99
|
||||
return StringPluralizationFormMany;
|
||||
break;
|
||||
}
|
||||
|
||||
return StringPluralizationFormOther;
|
||||
}
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
|
@ -144,7 +144,7 @@ final class ChangePhoneNumberController: ViewController, MFMailComposeViewContro
|
|||
text = presentationData.strings.Login_InvalidPhoneError
|
||||
actions.append(TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {}))
|
||||
case .phoneNumberOccupied:
|
||||
text = presentationData.strings.ChangePhone_ErrorOccupied(formatPhoneNumber(phoneNumber)).0
|
||||
text = presentationData.strings.ChangePhone_ErrorOccupied(formatPhoneNumber(phoneNumber)).string
|
||||
actions.append(TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {}))
|
||||
case .phoneBanned:
|
||||
text = presentationData.strings.Login_PhoneBannedError
|
||||
|
|
@ -160,7 +160,7 @@ final class ChangePhoneNumberController: ViewController, MFMailComposeViewContro
|
|||
let carrier = CTCarrier()
|
||||
let mnc = carrier.mobileNetworkCode ?? "none"
|
||||
|
||||
strongSelf.presentEmailComposeController(address: "login@stel.com", subject: presentationData.strings.Login_PhoneBannedEmailSubject(formattedNumber).0, body: presentationData.strings.Login_PhoneBannedEmailBody(formattedNumber, appVersion, systemVersion, locale, mnc).0)
|
||||
strongSelf.presentEmailComposeController(address: "login@stel.com", subject: presentationData.strings.Login_PhoneBannedEmailSubject(formattedNumber).string, body: presentationData.strings.Login_PhoneBannedEmailBody(formattedNumber, appVersion, systemVersion, locale, mnc).string)
|
||||
}))
|
||||
case .generic:
|
||||
text = presentationData.strings.Login_UnknownError
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ private func stringForAutomaticDownloadPeers(strings: PresentationStrings, decim
|
|||
|
||||
if peers.contacts && peers.otherPrivate && peers.groups && peers.channels {
|
||||
if let size = size {
|
||||
return strings.AutoDownloadSettings_UpToForAll(size).0
|
||||
return strings.AutoDownloadSettings_UpToForAll(size).string
|
||||
} else {
|
||||
return strings.AutoDownloadSettings_OnForAll
|
||||
}
|
||||
|
|
@ -238,9 +238,9 @@ private func stringForAutomaticDownloadPeers(strings: PresentationStrings, decim
|
|||
}
|
||||
|
||||
if let size = size {
|
||||
return strings.AutoDownloadSettings_UpToFor(size, string).0
|
||||
return strings.AutoDownloadSettings_UpToFor(size, string).string
|
||||
} else {
|
||||
return strings.AutoDownloadSettings_OnFor(string).0
|
||||
return strings.AutoDownloadSettings_OnFor(string).string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -276,11 +276,11 @@ private func autodownloadMediaCategoryControllerEntries(presentationData: Presen
|
|||
} else {
|
||||
sizeText = autodownloadDataSizeString(Int64(size), decimalSeparator: presentationData.dateTimeFormat.decimalSeparator)
|
||||
}
|
||||
let text = presentationData.strings.AutoDownloadSettings_UpTo(sizeText).0
|
||||
let text = presentationData.strings.AutoDownloadSettings_UpTo(sizeText).string
|
||||
entries.append(.sizeItem(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat.decimalSeparator, text, size))
|
||||
if #available(iOSApplicationExtension 10.3, *), category == .video {
|
||||
entries.append(.sizePreload(presentationData.theme, presentationData.strings.AutoDownloadSettings_PreloadVideo, predownload, size > 2 * 1024 * 1024))
|
||||
entries.append(.sizePreloadInfo(presentationData.theme, presentationData.strings.AutoDownloadSettings_PreloadVideoInfo(sizeText).0))
|
||||
entries.append(.sizePreloadInfo(presentationData.theme, presentationData.strings.AutoDownloadSettings_PreloadVideoInfo(sizeText).string))
|
||||
}
|
||||
default:
|
||||
break
|
||||
|
|
|
|||
|
|
@ -439,10 +439,10 @@ private func stringForAutoDownloadTypes(strings: PresentationStrings, decimalSep
|
|||
types.append(strings.ChatSettings_AutoDownloadSettings_TypePhoto)
|
||||
}
|
||||
if let videoSize = videoSize {
|
||||
types.append(strings.ChatSettings_AutoDownloadSettings_TypeVideo(autodownloadDataSizeString(Int64(videoSize), decimalSeparator: decimalSeparator)).0)
|
||||
types.append(strings.ChatSettings_AutoDownloadSettings_TypeVideo(autodownloadDataSizeString(Int64(videoSize), decimalSeparator: decimalSeparator)).string)
|
||||
}
|
||||
if let fileSize = fileSize {
|
||||
types.append(strings.ChatSettings_AutoDownloadSettings_TypeFile(autodownloadDataSizeString(Int64(fileSize), decimalSeparator: decimalSeparator)).0)
|
||||
types.append(strings.ChatSettings_AutoDownloadSettings_TypeFile(autodownloadDataSizeString(Int64(fileSize), decimalSeparator: decimalSeparator)).string)
|
||||
}
|
||||
|
||||
if types.isEmpty {
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ private func networkUsageStatsControllerEntries(presentationData: PresentationDa
|
|||
formatter.dateFormat = "E, d MMM yyyy HH:mm"
|
||||
let dateStringPlain = formatter.string(from: Date(timeIntervalSince1970: Double(stats.resetCellularTimestamp)))
|
||||
|
||||
entries.append(.resetTimestamp(presentationData.theme, presentationData.strings.NetworkUsageSettings_CellularUsageSince(dateStringPlain).0))
|
||||
entries.append(.resetTimestamp(presentationData.theme, presentationData.strings.NetworkUsageSettings_CellularUsageSince(dateStringPlain).string))
|
||||
}
|
||||
case .wifi:
|
||||
entries.append(.messagesHeader(presentationData.theme, presentationData.strings.NetworkUsageSettings_GeneralDataSection))
|
||||
|
|
@ -374,7 +374,7 @@ private func networkUsageStatsControllerEntries(presentationData: PresentationDa
|
|||
formatter.dateFormat = "E, d MMM yyyy HH:mm"
|
||||
let dateStringPlain = formatter.string(from: Date(timeIntervalSince1970: Double(stats.resetWifiTimestamp)))
|
||||
|
||||
entries.append(.resetTimestamp(presentationData.theme, presentationData.strings.NetworkUsageSettings_WifiUsageSince(dateStringPlain).0))
|
||||
entries.append(.resetTimestamp(presentationData.theme, presentationData.strings.NetworkUsageSettings_WifiUsageSince(dateStringPlain).string))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ private func proxySettingsControllerEntries(theme: PresentationTheme, strings: P
|
|||
var text = strings.SocksProxySetup_ProxyStatusConnected
|
||||
if case let .available(rtt) = status {
|
||||
let pingTime: Int = Int(rtt * 1000.0)
|
||||
text = text + ", \(strings.SocksProxySetup_ProxyStatusPing("\(pingTime)").0)"
|
||||
text = text + ", \(strings.SocksProxySetup_ProxyStatusPing("\(pingTime)").string)"
|
||||
}
|
||||
displayStatus = DisplayProxyServerStatus(activity: false, text: text, textActive: true)
|
||||
}
|
||||
|
|
@ -280,7 +280,7 @@ private func proxySettingsControllerEntries(theme: PresentationTheme, strings: P
|
|||
displayStatus = DisplayProxyServerStatus(activity: false, text: text, textActive: false)
|
||||
case let .available(rtt):
|
||||
let pingTime: Int = Int(rtt * 1000.0)
|
||||
text = text + ", \(strings.SocksProxySetup_ProxyStatusPing("\(pingTime)").0)"
|
||||
text = text + ", \(strings.SocksProxySetup_ProxyStatusPing("\(pingTime)").string)"
|
||||
displayStatus = DisplayProxyServerStatus(activity: false, text: text, textActive: false)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ private final class ProxyServerInfoItemNode: ActionSheetItemNode {
|
|||
statusType = .generic(strongSelf.strings.SocksProxySetup_ProxyStatusChecking)
|
||||
case let .available(rtt):
|
||||
let pingTime = Int(rtt * 1000.0)
|
||||
statusType = .generic(strongSelf.strings.SocksProxySetup_ProxyStatusPing("\(pingTime)").0)
|
||||
statusType = .generic(strongSelf.strings.SocksProxySetup_ProxyStatusPing("\(pingTime)").string)
|
||||
case .notAvailable:
|
||||
statusType = .failed(strongSelf.strings.SocksProxySetup_ProxyStatusUnavailable)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ private func storageUsageControllerEntries(presentationData: PresentationData, c
|
|||
|
||||
var addedHeader = false
|
||||
|
||||
entries.append(.storageHeader(presentationData.theme, presentationData.strings.ClearCache_StorageTitle(stringForDeviceType().uppercased()).0))
|
||||
entries.append(.storageHeader(presentationData.theme, presentationData.strings.ClearCache_StorageTitle(stringForDeviceType().uppercased()).string))
|
||||
if let cacheStats = cacheStats, case let .result(stats) = cacheStats {
|
||||
var peerSizes: Int64 = 0
|
||||
var statsByPeerId: [(PeerId, Int64)] = []
|
||||
|
|
@ -490,7 +490,7 @@ public func storageUsageController(context: AccountContext, cacheUsagePromise: P
|
|||
if filteredSize == 0 {
|
||||
title = presentationData.strings.Cache_ClearNone
|
||||
} else {
|
||||
title = presentationData.strings.Cache_Clear("\(dataSizeString(filteredSize, formatting: DataSizeStringFormatting(presentationData: presentationData)))").0
|
||||
title = presentationData.strings.Cache_Clear("\(dataSizeString(filteredSize, formatting: DataSizeStringFormatting(presentationData: presentationData)))").string
|
||||
}
|
||||
|
||||
if let item = item as? ActionSheetButtonItem {
|
||||
|
|
@ -545,7 +545,7 @@ public func storageUsageController(context: AccountContext, cacheUsagePromise: P
|
|||
selectedSize = totalSize
|
||||
|
||||
if !items.isEmpty {
|
||||
items.append(ActionSheetButtonItem(title: presentationData.strings.Cache_Clear("\(dataSizeString(totalSize, formatting: DataSizeStringFormatting(presentationData: presentationData)))").0, action: {
|
||||
items.append(ActionSheetButtonItem(title: presentationData.strings.Cache_Clear("\(dataSizeString(totalSize, formatting: DataSizeStringFormatting(presentationData: presentationData)))").string, action: {
|
||||
if let statsPromise = statsPromise {
|
||||
let clearCategories = sizeIndex.keys.filter({ sizeIndex[$0]!.0 })
|
||||
|
||||
|
|
@ -637,7 +637,7 @@ public func storageUsageController(context: AccountContext, cacheUsagePromise: P
|
|||
clearDisposable.set((signal
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
statsPromise.set(.single(.result(resultStats)))
|
||||
presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .succeed(text: presentationData.strings.ClearCache_Success("\(dataSizeString(selectedSize, formatting: DataSizeStringFormatting(presentationData: presentationData)))", stringForDeviceType()).0), elevatedLayout: false, action: { _ in return false }), .current, nil)
|
||||
presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .succeed(text: presentationData.strings.ClearCache_Success("\(dataSizeString(selectedSize, formatting: DataSizeStringFormatting(presentationData: presentationData)))", stringForDeviceType()).string), elevatedLayout: false, action: { _ in return false }), .current, nil)
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
@ -692,7 +692,7 @@ public func storageUsageController(context: AccountContext, cacheUsagePromise: P
|
|||
if filteredSize == 0 {
|
||||
title = presentationData.strings.Cache_ClearNone
|
||||
} else {
|
||||
title = presentationData.strings.Cache_Clear("\(dataSizeString(filteredSize, formatting: DataSizeStringFormatting(presentationData: presentationData)))").0
|
||||
title = presentationData.strings.Cache_Clear("\(dataSizeString(filteredSize, formatting: DataSizeStringFormatting(presentationData: presentationData)))").string
|
||||
}
|
||||
|
||||
if let item = item as? ActionSheetButtonItem {
|
||||
|
|
@ -742,7 +742,7 @@ public func storageUsageController(context: AccountContext, cacheUsagePromise: P
|
|||
selectedSize = totalSize
|
||||
|
||||
if !items.isEmpty {
|
||||
items.append(ActionSheetButtonItem(title: presentationData.strings.Cache_Clear("\(dataSizeString(totalSize, formatting: DataSizeStringFormatting(presentationData: presentationData)))").0, action: {
|
||||
items.append(ActionSheetButtonItem(title: presentationData.strings.Cache_Clear("\(dataSizeString(totalSize, formatting: DataSizeStringFormatting(presentationData: presentationData)))").string, action: {
|
||||
if let statsPromise = statsPromise {
|
||||
let clearCategories = sizeIndex.keys.filter({ sizeIndex[$0]!.0 })
|
||||
var clearMediaIds = Set<MediaId>()
|
||||
|
|
@ -818,7 +818,7 @@ public func storageUsageController(context: AccountContext, cacheUsagePromise: P
|
|||
clearDisposable.set((signal
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
statsPromise.set(.single(.result(resultStats)))
|
||||
presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .succeed(text: presentationData.strings.ClearCache_Success("\(dataSizeString(selectedSize, formatting: DataSizeStringFormatting(presentationData: presentationData)))", stringForDeviceType()).0), elevatedLayout: false, action: { _ in return false }), .current, nil)
|
||||
presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .succeed(text: presentationData.strings.ClearCache_Success("\(dataSizeString(selectedSize, formatting: DataSizeStringFormatting(presentationData: presentationData)))", stringForDeviceType()).string), elevatedLayout: false, action: { _ in return false }), .current, nil)
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
@ -945,7 +945,7 @@ public func storageUsageController(context: AccountContext, cacheUsagePromise: P
|
|||
clearDisposable.set((signal
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
statsPromise.set(.single(.result(resultStats)))
|
||||
presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .succeed(text: presentationData.strings.ClearCache_Success("\(dataSizeString(totalSize, formatting: DataSizeStringFormatting(presentationData: presentationData)))", stringForDeviceType()).0), elevatedLayout: false, action: { _ in return false }), .current, nil)
|
||||
presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .succeed(text: presentationData.strings.ClearCache_Success("\(dataSizeString(totalSize, formatting: DataSizeStringFormatting(presentationData: presentationData)))", stringForDeviceType()).string), elevatedLayout: false, action: { _ in return false }), .current, nil)
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue