mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 21:45:19 +00:00
Move to generated string resources
This commit is contained in:
parent
a836fe0442
commit
e9be17a5ee
@ -78,6 +78,79 @@ genrule(
|
|||||||
cmd = "touch $(OUTS)",
|
cmd = "touch $(OUTS)",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
genrule(
|
||||||
|
name = "GeneratedPresentationStrings",
|
||||||
|
srcs = [
|
||||||
|
"//build-system:GenerateStrings/GenerateStrings.py",
|
||||||
|
"Telegram-iOS/en.lproj/Localizable.strings",
|
||||||
|
],
|
||||||
|
cmd = '''
|
||||||
|
python3 $(location //build-system:GenerateStrings/GenerateStrings.py) \\
|
||||||
|
--source=$(location Telegram-iOS/en.lproj/Localizable.strings) \\
|
||||||
|
--outImplementation=$(location GeneratedPresentationStrings/Sources/PresentationStrings.m) \\
|
||||||
|
--outHeader=$(location GeneratedPresentationStrings/PublicHeaders/PresentationStrings/PresentationStrings.h) \\
|
||||||
|
--outData=$(location GeneratedPresentationStrings/Resources/PresentationStrings.data) \\
|
||||||
|
''',
|
||||||
|
outs = [
|
||||||
|
"GeneratedPresentationStrings/PublicHeaders/PresentationStrings/PresentationStrings.h",
|
||||||
|
"GeneratedPresentationStrings/Sources/PresentationStrings.m",
|
||||||
|
"GeneratedPresentationStrings/Resources/PresentationStrings.data",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
empty_languages = [
|
||||||
|
"ar",
|
||||||
|
"be",
|
||||||
|
"ca",
|
||||||
|
"de",
|
||||||
|
"es",
|
||||||
|
"fa",
|
||||||
|
"fr",
|
||||||
|
"id",
|
||||||
|
"it",
|
||||||
|
"ko",
|
||||||
|
"ms",
|
||||||
|
"nl",
|
||||||
|
"pl",
|
||||||
|
"pt",
|
||||||
|
"ru",
|
||||||
|
"tr",
|
||||||
|
"uk",
|
||||||
|
"uz",
|
||||||
|
]
|
||||||
|
|
||||||
|
[
|
||||||
|
genrule(
|
||||||
|
name = "Localizable_{}.strings".format(language),
|
||||||
|
outs = ["{}.lproj/Localizable.strings".format(language)],
|
||||||
|
cmd = "touch $(OUTS)",
|
||||||
|
) for language in empty_languages
|
||||||
|
]
|
||||||
|
|
||||||
|
objc_library(
|
||||||
|
name = "PresentationStrings",
|
||||||
|
enable_modules = True,
|
||||||
|
module_name = "PresentationStrings",
|
||||||
|
srcs = [
|
||||||
|
"GeneratedPresentationStrings/Sources/PresentationStrings.m",
|
||||||
|
],
|
||||||
|
hdrs = [
|
||||||
|
"GeneratedPresentationStrings/PublicHeaders/PresentationStrings/PresentationStrings.h",
|
||||||
|
],
|
||||||
|
includes = [
|
||||||
|
"GeneratedPresentationStrings/PublicHeaders",
|
||||||
|
],
|
||||||
|
sdk_frameworks = [
|
||||||
|
"Foundation",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
"//submodules/NumberPluralizationForm:NumberPluralizationForm",
|
||||||
|
],
|
||||||
|
visibility = [
|
||||||
|
"//visibility:public",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
swift_library(
|
swift_library(
|
||||||
name = "_LocalDebugOptions",
|
name = "_LocalDebugOptions",
|
||||||
srcs = [":empty"],
|
srcs = [":empty"],
|
||||||
@ -122,9 +195,11 @@ filegroup(
|
|||||||
|
|
||||||
filegroup(
|
filegroup(
|
||||||
name = "AppStringResources",
|
name = "AppStringResources",
|
||||||
srcs = glob([
|
srcs = [
|
||||||
"Telegram-iOS/*.lproj/Localizable.strings",
|
"Telegram-iOS/en.lproj/Localizable.strings",
|
||||||
], exclude = ["Telegram-iOS/*.lproj/**/.*"]),
|
] + [
|
||||||
|
"{}.lproj/Localizable.strings".format(language) for language in empty_languages
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
filegroup(
|
filegroup(
|
||||||
@ -220,7 +295,7 @@ swift_library(
|
|||||||
"//submodules/PasswordSetupUI:PasswordSetupUIAssets",
|
"//submodules/PasswordSetupUI:PasswordSetupUIAssets",
|
||||||
"//submodules/TelegramUI:TelegramUIResources",
|
"//submodules/TelegramUI:TelegramUIResources",
|
||||||
"//submodules/TelegramUI:TelegramUIAssets",
|
"//submodules/TelegramUI:TelegramUIAssets",
|
||||||
"//submodules/PresentationStrings:PresentationStringsResources",
|
":GeneratedPresentationStrings/Resources/PresentationStrings.data",
|
||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
"//submodules/TelegramUI:TelegramUI",
|
"//submodules/TelegramUI:TelegramUI",
|
||||||
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -3,3 +3,7 @@ config_setting(
|
|||||||
name = "ios_sim_arm64",
|
name = "ios_sim_arm64",
|
||||||
values = {"cpu": "ios_sim_arm64"},
|
values = {"cpu": "ios_sim_arm64"},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
exports_files([
|
||||||
|
"GenerateStrings/GenerateStrings.py",
|
||||||
|
])
|
||||||
|
@ -287,7 +287,7 @@ static _FormattedString * _Nonnull getFormatted{num_arguments}(_PresentationStri
|
|||||||
write_string(source_file, '''// Automatically-generated file, do not edit
|
write_string(source_file, '''// Automatically-generated file, do not edit
|
||||||
|
|
||||||
#import <PresentationStrings/PresentationStrings.h>
|
#import <PresentationStrings/PresentationStrings.h>
|
||||||
#import <PresentationStrings/StringPluralization.h>
|
#import <NumberPluralizationForm/NumberPluralizationForm.h>
|
||||||
|
|
||||||
@implementation _FormattedStringRange
|
@implementation _FormattedStringRange
|
||||||
|
|
||||||
@ -364,8 +364,6 @@ static NSArray<_FormattedStringRange *> * _Nonnull extractArgumentRanges(NSStrin
|
|||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//sort?
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,21 +395,21 @@ static _FormattedString * _Nonnull formatWithArgumentRanges(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static NSString * _Nonnull getPluralizationSuffix(_PresentationStrings * _Nonnull strings, int32_t value) {
|
static NSString * _Nonnull getPluralizationSuffix(_PresentationStrings * _Nonnull strings, int32_t value) {
|
||||||
StringPluralizationForm pluralizationForm = getStringPluralizationForm(strings.lc, value);
|
NumberPluralizationForm pluralizationForm = numberPluralizationForm(strings.lc, value);
|
||||||
switch (pluralizationForm) {
|
switch (pluralizationForm) {
|
||||||
case StringPluralizationFormZero: {
|
case NumberPluralizationFormZero: {
|
||||||
return @"_0";
|
return @"_0";
|
||||||
}
|
}
|
||||||
case StringPluralizationFormOne: {
|
case NumberPluralizationFormOne: {
|
||||||
return @"_1";
|
return @"_1";
|
||||||
}
|
}
|
||||||
case StringPluralizationFormTwo: {
|
case NumberPluralizationFormTwo: {
|
||||||
return @"_2";
|
return @"_2";
|
||||||
}
|
}
|
||||||
case StringPluralizationFormFew: {
|
case NumberPluralizationFormFew: {
|
||||||
return @"_3_10";
|
return @"_3_10";
|
||||||
}
|
}
|
||||||
case StringPluralizationFormMany: {
|
case NumberPluralizationFormMany: {
|
||||||
return @"_many";
|
return @"_many";
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
@ -459,7 +457,7 @@ static NSString * _Nonnull getPluralized(_PresentationStrings * _Nonnull strings
|
|||||||
int32_t value) {
|
int32_t value) {
|
||||||
NSString *parsedKey = [[NSString alloc] initWithFormat:@"%@%@", key, getPluralizationSuffix(strings, value)];
|
NSString *parsedKey = [[NSString alloc] initWithFormat:@"%@%@", key, getPluralizationSuffix(strings, value)];
|
||||||
NSString *formatString = getSingle(strings, parsedKey);
|
NSString *formatString = getSingle(strings, parsedKey);
|
||||||
NSString *stringValue = [[NSString alloc] initWithFormat:@"%d", (int)value];
|
NSString *stringValue = formatNumberWithGroupingSeparator(strings.groupingSeparator, value);
|
||||||
NSString *result = [[NSString alloc] initWithFormat:formatString, stringValue];
|
NSString *result = [[NSString alloc] initWithFormat:formatString, stringValue];
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -10,3 +10,5 @@ typedef NS_ENUM(int32_t, NumberPluralizationForm) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
NumberPluralizationForm numberPluralizationForm(unsigned int lc, int n);
|
NumberPluralizationForm numberPluralizationForm(unsigned int lc, int n);
|
||||||
|
|
||||||
|
NSString * _Nonnull formatNumberWithGroupingSeparator(NSString * _Nonnull groupingSeparator, int32_t value);
|
||||||
|
@ -353,3 +353,22 @@ NumberPluralizationForm numberPluralizationForm(unsigned int lc, int n) {
|
|||||||
|
|
||||||
return NumberPluralizationFormOther;
|
return NumberPluralizationFormOther;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NSString * _Nonnull formatNumberWithGroupingSeparator(NSString * _Nonnull groupingSeparator, int32_t value) {
|
||||||
|
NSString *string = [[NSString alloc] initWithFormat:@"%d", (int)value];
|
||||||
|
if (ABS(value) < 1000 || groupingSeparator.length == 0) {
|
||||||
|
return string;
|
||||||
|
} else {
|
||||||
|
NSMutableString *groupedString = [[NSMutableString alloc] init];
|
||||||
|
int n = (int)ceil(((double)(string.length)) / 3.0);
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
int index = ((int)string.length) - (i + 1) * 3;
|
||||||
|
if (groupedString.length != 0) {
|
||||||
|
[groupedString insertString:groupingSeparator atIndex:0];
|
||||||
|
}
|
||||||
|
NSString *section = [string substringWithRange:NSMakeRange(MAX(0, index), 3)];
|
||||||
|
[groupedString insertString:section atIndex:0];
|
||||||
|
}
|
||||||
|
return groupedString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
|
|
||||||
filegroup(
|
|
||||||
name = "PresentationStringsResources",
|
|
||||||
srcs = glob([
|
|
||||||
"Resources/**/*",
|
|
||||||
], exclude = ["Resources/**/.*"]),
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
|
|
||||||
objc_library(
|
|
||||||
name = "PresentationStrings",
|
|
||||||
enable_modules = True,
|
|
||||||
module_name = "PresentationStrings",
|
|
||||||
srcs = glob([
|
|
||||||
"Sources/*.m",
|
|
||||||
]),
|
|
||||||
hdrs = glob([
|
|
||||||
"PublicHeaders/**/*.h",
|
|
||||||
]),
|
|
||||||
includes = [
|
|
||||||
"PublicHeaders",
|
|
||||||
],
|
|
||||||
sdk_frameworks = [
|
|
||||||
"Foundation",
|
|
||||||
],
|
|
||||||
visibility = [
|
|
||||||
"//visibility:public",
|
|
||||||
],
|
|
||||||
)
|
|
File diff suppressed because it is too large
Load Diff
@ -1,12 +0,0 @@
|
|||||||
#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
@ -1,355 +0,0 @@
|
|||||||
#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;
|
|
||||||
}
|
|
@ -18,7 +18,7 @@ swift_library(
|
|||||||
"//submodules/StringPluralization:StringPluralization",
|
"//submodules/StringPluralization:StringPluralization",
|
||||||
"//submodules/Sunrise:Sunrise",
|
"//submodules/Sunrise:Sunrise",
|
||||||
"//submodules/TinyThumbnail:TinyThumbnail",
|
"//submodules/TinyThumbnail:TinyThumbnail",
|
||||||
"//submodules/PresentationStrings:PresentationStrings",
|
"//Telegram:PresentationStrings",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -239,7 +239,6 @@ swift_library(
|
|||||||
"//submodules/ImportStickerPackUI:ImportStickerPackUI",
|
"//submodules/ImportStickerPackUI:ImportStickerPackUI",
|
||||||
"//submodules/GradientBackground:GradientBackground",
|
"//submodules/GradientBackground:GradientBackground",
|
||||||
"//submodules/WallpaperBackgroundNode:WallpaperBackgroundNode",
|
"//submodules/WallpaperBackgroundNode:WallpaperBackgroundNode",
|
||||||
"//submodules/PresentationStrings:PresentationStrings",
|
|
||||||
] + select({
|
] + select({
|
||||||
"@build_bazel_rules_apple//apple:ios_armv7": [],
|
"@build_bazel_rules_apple//apple:ios_armv7": [],
|
||||||
"@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets,
|
"@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets,
|
||||||
|
Binary file not shown.
@ -1,4 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
swift -swift-version 5 tools/GenerateLocalization.swift Telegram/Telegram-iOS/en.lproj/Localizable.strings submodules/TelegramPresentationData/Sources/PresentationStrings.swift submodules/TelegramUI/Resources/PresentationStrings.mapping
|
|
||||||
|
|
@ -1,614 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
|
|
||||||
struct Entry {
|
|
||||||
let key: String
|
|
||||||
let value: String
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ArgumentType: Equatable {
|
|
||||||
case any
|
|
||||||
case integer(decimalNumbers: Int)
|
|
||||||
case float
|
|
||||||
|
|
||||||
init(_ control: String, decimalNumbers: Int) {
|
|
||||||
switch control {
|
|
||||||
case "d":
|
|
||||||
self = .integer(decimalNumbers: decimalNumbers)
|
|
||||||
case "f":
|
|
||||||
self = .float
|
|
||||||
case "@":
|
|
||||||
self = .any
|
|
||||||
default:
|
|
||||||
preconditionFailure()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Argument: Equatable {
|
|
||||||
let index: Int
|
|
||||||
let type: ArgumentType
|
|
||||||
}
|
|
||||||
|
|
||||||
func escapedIdentifier(_ value: String) -> String {
|
|
||||||
return value.replacingOccurrences(of: ".", with: "_").replacingOccurrences(of: "#", with: "_").replacingOccurrences(of: " ", with: "_").replacingOccurrences(of: "'", with: "_")
|
|
||||||
}
|
|
||||||
|
|
||||||
func functionArguments(_ arguments: [Argument]) -> String {
|
|
||||||
var result = ""
|
|
||||||
var existingIndices = Set<Int>()
|
|
||||||
for argument in arguments.sorted(by: { $0.index < $1.index }) {
|
|
||||||
if existingIndices.contains(argument.index) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
existingIndices.insert(argument.index)
|
|
||||||
if !result.isEmpty {
|
|
||||||
result += ", "
|
|
||||||
}
|
|
||||||
result += "_ _\(argument.index): "
|
|
||||||
switch argument.type {
|
|
||||||
case .any:
|
|
||||||
result += "String"
|
|
||||||
case .float:
|
|
||||||
result += "Float"
|
|
||||||
case .integer:
|
|
||||||
result += "Int"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func formatArguments(_ arguments: [Argument]) -> String {
|
|
||||||
var result = ""
|
|
||||||
for argument in arguments.sorted(by: { $0.index < $1.index }) {
|
|
||||||
if !result.isEmpty {
|
|
||||||
result += ", "
|
|
||||||
}
|
|
||||||
switch argument.type {
|
|
||||||
case .any:
|
|
||||||
result += "_\(argument.index)"
|
|
||||||
case .float:
|
|
||||||
result += "\"\\(_\(argument.index))\""
|
|
||||||
case let .integer(decimalNumbers):
|
|
||||||
if decimalNumbers == 0 {
|
|
||||||
result += "\"\\(_\(argument.index))\""
|
|
||||||
} else {
|
|
||||||
result += "String(format: \"%.\(decimalNumbers)d\", _\(argument.index))"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
let argumentRegex = try! NSRegularExpression(pattern: "%((\\.(\\d+))?)(((\\d+)\\$)?)([@df])", options: [])
|
|
||||||
|
|
||||||
func parseArguments(_ value: String) -> [Argument] {
|
|
||||||
let string = value as NSString
|
|
||||||
|
|
||||||
let matches = argumentRegex.matches(in: string as String, options: [], range: NSRange(location: 0, length: string.length))
|
|
||||||
|
|
||||||
var arguments: [Argument] = []
|
|
||||||
var index = 0
|
|
||||||
if value.range(of: ".2d") != nil {
|
|
||||||
print(value)
|
|
||||||
}
|
|
||||||
for match in matches {
|
|
||||||
var currentIndex = index
|
|
||||||
var decimalNumbers = 0
|
|
||||||
if match.range(at: 3).location != NSNotFound {
|
|
||||||
decimalNumbers = Int(string.substring(with: match.range(at: 3)))!
|
|
||||||
}
|
|
||||||
if match.range(at: 6).location != NSNotFound {
|
|
||||||
currentIndex = Int(string.substring(with: match.range(at: 6)))!
|
|
||||||
}
|
|
||||||
arguments.append(Argument(index: currentIndex, type: ArgumentType(string.substring(with: match.range(at: 7)), decimalNumbers: decimalNumbers)))
|
|
||||||
index += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
return arguments
|
|
||||||
}
|
|
||||||
|
|
||||||
func addCode(_ lines: [String]) -> String {
|
|
||||||
var result: String = ""
|
|
||||||
for line in lines {
|
|
||||||
result += line
|
|
||||||
result += "\n"
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
enum PluralizationForm: Int32 {
|
|
||||||
case zero = 0
|
|
||||||
case one = 1
|
|
||||||
case two = 2
|
|
||||||
case few = 3
|
|
||||||
case many = 4
|
|
||||||
case other = 5
|
|
||||||
|
|
||||||
static var formCount = Int(PluralizationForm.other.rawValue + 1)
|
|
||||||
static var all: [PluralizationForm] = [.zero, .one, .two, .few, .many, .other]
|
|
||||||
|
|
||||||
var name: String {
|
|
||||||
switch self {
|
|
||||||
case .zero:
|
|
||||||
return "zero"
|
|
||||||
case .one:
|
|
||||||
return "one"
|
|
||||||
case .two:
|
|
||||||
return "two"
|
|
||||||
case .few:
|
|
||||||
return "few"
|
|
||||||
case .many:
|
|
||||||
return "many"
|
|
||||||
case .other:
|
|
||||||
return "other"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let pluralizationFormRegex = try! NSRegularExpression(pattern: "(.*?)_(0|zero|1|one|2|two|3_10|few|many|any|other)$", options: [])
|
|
||||||
|
|
||||||
func pluralizationForm(_ key: String) -> (String, PluralizationForm)? {
|
|
||||||
let string = key as NSString
|
|
||||||
let matches = pluralizationFormRegex.matches(in: string as String, options: [], range: NSRange(location: 0, length: string.length))
|
|
||||||
|
|
||||||
for match in matches {
|
|
||||||
if match.range(at: 1).location != NSNotFound && match.range(at: 2).location != NSNotFound {
|
|
||||||
let base = string.substring(with: match.range(at: 1))
|
|
||||||
let value = string.substring(with: match.range(at: 2))
|
|
||||||
let form: PluralizationForm
|
|
||||||
switch value {
|
|
||||||
case "0", "zero":
|
|
||||||
form = .zero
|
|
||||||
case "1", "one":
|
|
||||||
form = .one
|
|
||||||
case "2", "two":
|
|
||||||
form = .two
|
|
||||||
case "3_10", "few":
|
|
||||||
form = .few
|
|
||||||
case "many":
|
|
||||||
form = .many
|
|
||||||
case "any", "other":
|
|
||||||
form = .other
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return (base, form)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
final class WriteBuffer {
|
|
||||||
var data = Data()
|
|
||||||
|
|
||||||
init() {
|
|
||||||
}
|
|
||||||
|
|
||||||
func append(_ value: Int32) {
|
|
||||||
var value = value
|
|
||||||
withUnsafePointer(to: &value, { (pointer: UnsafePointer<Int32>) -> Void in
|
|
||||||
self.data.append(UnsafeRawPointer(pointer).assumingMemoryBound(to: UInt8.self), count: 4)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func append(_ string: String) {
|
|
||||||
let bytes = string.data(using: .utf8)!
|
|
||||||
self.append(Int32(bytes.count))
|
|
||||||
self.data.append(bytes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if CommandLine.arguments.count < 4 {
|
|
||||||
print("Usage: swift GenerateLocalization.swift Localizable.strings Strings.swift Strings.mapping [prefix]")
|
|
||||||
} else {
|
|
||||||
var filterPrefix: String?
|
|
||||||
if CommandLine.arguments.count > 4 {
|
|
||||||
filterPrefix = CommandLine.arguments[4]
|
|
||||||
}
|
|
||||||
|
|
||||||
let mappingFileUrl = URL(fileURLWithPath: CommandLine.arguments[3])
|
|
||||||
let mappingFileName = mappingFileUrl.lastPathComponent
|
|
||||||
let mappingFileBaseName = String(mappingFileName[mappingFileName.startIndex ..< mappingFileName.index(mappingFileName.endIndex, offsetBy: -1 - mappingFileUrl.pathExtension.count)])
|
|
||||||
let snakeCaseMappingFileBaseName = mappingFileBaseName.prefix(1).lowercased() + mappingFileBaseName.dropFirst()
|
|
||||||
|
|
||||||
if let rawDict = NSDictionary(contentsOfFile: CommandLine.arguments[1]) {
|
|
||||||
var result = "import Foundation\nimport AppBundle\nimport StringPluralization\n\n"
|
|
||||||
|
|
||||||
result +=
|
|
||||||
"""
|
|
||||||
private let fallbackDict: [String: String] = {
|
|
||||||
guard let mainPath = getAppBundle().path(forResource: \"en\", ofType: \"lproj\"), let bundle = Bundle(path: mainPath) else {
|
|
||||||
return [:]
|
|
||||||
}
|
|
||||||
guard let path = bundle.path(forResource: \"Localizable\", ofType: \"strings\") else {
|
|
||||||
return [:]
|
|
||||||
}
|
|
||||||
guard let dict = NSDictionary(contentsOf: URL(fileURLWithPath: path)) as? [String: String] else {
|
|
||||||
return [:]
|
|
||||||
}
|
|
||||||
return dict
|
|
||||||
}()
|
|
||||||
|
|
||||||
private extension PluralizationForm {
|
|
||||||
var canonicalSuffix: String {
|
|
||||||
switch self {
|
|
||||||
case .zero:
|
|
||||||
return \"_0\"
|
|
||||||
case .one:
|
|
||||||
return \"_1\"
|
|
||||||
case .two:
|
|
||||||
return \"_2\"
|
|
||||||
case .few:
|
|
||||||
return \"_3_10\"
|
|
||||||
case .many:
|
|
||||||
return \"_many\"
|
|
||||||
case .other:
|
|
||||||
return \"_any\"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final class \(mappingFileBaseName)Component {
|
|
||||||
public let languageCode: String
|
|
||||||
public let localizedName: String
|
|
||||||
public let pluralizationRulesCode: String?
|
|
||||||
public let dict: [String: String]
|
|
||||||
|
|
||||||
public init(languageCode: String, localizedName: String, pluralizationRulesCode: String?, dict: [String: String]) {
|
|
||||||
self.languageCode = languageCode
|
|
||||||
self.localizedName = localizedName
|
|
||||||
self.pluralizationRulesCode = pluralizationRulesCode
|
|
||||||
self.dict = dict
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func getValue(_ primaryComponent: \(mappingFileBaseName)Component, _ secondaryComponent: \(mappingFileBaseName)Component?, _ key: String) -> String {
|
|
||||||
if let value = primaryComponent.dict[key] {
|
|
||||||
return value
|
|
||||||
} else if let secondaryComponent = secondaryComponent, let value = secondaryComponent.dict[key] {
|
|
||||||
return value
|
|
||||||
} else if let value = fallbackDict[key] {
|
|
||||||
return value
|
|
||||||
} else {
|
|
||||||
return key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func getValueWithForm(_ primaryComponent: \(mappingFileBaseName)Component, _ secondaryComponent: \(mappingFileBaseName)Component?, _ key: String, _ form: PluralizationForm) -> String {
|
|
||||||
let builtKey = key + form.canonicalSuffix
|
|
||||||
if let value = primaryComponent.dict[builtKey] {
|
|
||||||
return value
|
|
||||||
} else if let secondaryComponent = secondaryComponent, let value = secondaryComponent.dict[builtKey] {
|
|
||||||
return value
|
|
||||||
} else if let value = fallbackDict[builtKey] {
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
return key
|
|
||||||
}
|
|
||||||
|
|
||||||
private let argumentRegex = try! NSRegularExpression(pattern: \"%(((\\\\d+)\\\\$)?)([@df])\", options: [])
|
|
||||||
private func extractArgumentRanges(_ value: String) -> [(Int, NSRange)] {
|
|
||||||
var result: [(Int, NSRange)] = []
|
|
||||||
let string = value as NSString
|
|
||||||
let matches = argumentRegex.matches(in: string as String, options: [], range: NSRange(location: 0, length: string.length))
|
|
||||||
var index = 0
|
|
||||||
for match in matches {
|
|
||||||
var currentIndex = index
|
|
||||||
if match.range(at: 3).location != NSNotFound {
|
|
||||||
currentIndex = Int(string.substring(with: match.range(at: 3)))! - 1
|
|
||||||
}
|
|
||||||
result.append((currentIndex, match.range(at: 0)))
|
|
||||||
index += 1
|
|
||||||
}
|
|
||||||
result.sort(by: { $0.1.location < $1.1.location })
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
public func formatWithArgumentRanges(_ value: String, _ ranges: [(Int, NSRange)], _ arguments: [String]) -> (String, [(Int, NSRange)]) {
|
|
||||||
let string = value as NSString
|
|
||||||
|
|
||||||
var resultingRanges: [(Int, NSRange)] = []
|
|
||||||
|
|
||||||
var currentLocation = 0
|
|
||||||
|
|
||||||
let result = NSMutableString()
|
|
||||||
for (index, range) in ranges {
|
|
||||||
if currentLocation < range.location {
|
|
||||||
result.append(string.substring(with: NSRange(location: currentLocation, length: range.location - currentLocation)))
|
|
||||||
}
|
|
||||||
resultingRanges.append((index, NSRange(location: result.length, length: (arguments[index] as NSString).length)))
|
|
||||||
result.append(arguments[index])
|
|
||||||
currentLocation = range.location + range.length
|
|
||||||
}
|
|
||||||
if currentLocation != string.length {
|
|
||||||
result.append(string.substring(with: NSRange(location: currentLocation, length: string.length - currentLocation)))
|
|
||||||
}
|
|
||||||
return (result as String, resultingRanges)
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class DataReader {
|
|
||||||
private let data: Data
|
|
||||||
private var ptr: Int = 0
|
|
||||||
|
|
||||||
init(_ data: Data) {
|
|
||||||
self.data = data
|
|
||||||
}
|
|
||||||
|
|
||||||
func readInt32() -> Int32 {
|
|
||||||
assert(self.ptr + 4 <= self.data.count)
|
|
||||||
let result = self.data.withUnsafeBytes { (bytes: UnsafePointer<Int8>) -> Int32 in
|
|
||||||
var value: Int32 = 0
|
|
||||||
memcpy(&value, bytes.advanced(by: self.ptr), 4)
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
self.ptr += 4
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func readString() -> String {
|
|
||||||
let length = Int(self.readInt32())
|
|
||||||
assert(self.ptr + length <= self.data.count)
|
|
||||||
let value = String(data: self.data.subdata(in: self.ptr ..< self.ptr + length), encoding: .utf8)!
|
|
||||||
self.ptr += length
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func loadMapping() -> ([Int], [String], [Int], [Int], [String]) {
|
|
||||||
guard let filePath = getAppBundle().path(forResource: "\(mappingFileBaseName)", ofType: "mapping") else {
|
|
||||||
fatalError()
|
|
||||||
}
|
|
||||||
guard let data = try? Data(contentsOf: URL(fileURLWithPath: filePath)) else {
|
|
||||||
fatalError()
|
|
||||||
}
|
|
||||||
|
|
||||||
let reader = DataReader(data)
|
|
||||||
|
|
||||||
let idCount = Int(reader.readInt32())
|
|
||||||
var sIdList: [Int] = []
|
|
||||||
var sKeyList: [String] = []
|
|
||||||
var sArgIdList: [Int] = []
|
|
||||||
for _ in 0 ..< idCount {
|
|
||||||
let id = Int(reader.readInt32())
|
|
||||||
sIdList.append(id)
|
|
||||||
sKeyList.append(reader.readString())
|
|
||||||
if reader.readInt32() != 0 {
|
|
||||||
sArgIdList.append(id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let pCount = Int(reader.readInt32())
|
|
||||||
var pIdList: [Int] = []
|
|
||||||
var pKeyList: [String] = []
|
|
||||||
for _ in 0 ..< Int(pCount) {
|
|
||||||
pIdList.append(Int(reader.readInt32()))
|
|
||||||
pKeyList.append(reader.readString())
|
|
||||||
}
|
|
||||||
|
|
||||||
return (sIdList, sKeyList, sArgIdList, pIdList, pKeyList)
|
|
||||||
}
|
|
||||||
|
|
||||||
private let keyMapping: ([Int], [String], [Int], [Int], [String]) = loadMapping()
|
|
||||||
|
|
||||||
public final class \(mappingFileBaseName): Equatable {
|
|
||||||
public let lc: UInt32
|
|
||||||
|
|
||||||
public let primaryComponent: \(mappingFileBaseName)Component
|
|
||||||
public let secondaryComponent: \(mappingFileBaseName)Component?
|
|
||||||
public let baseLanguageCode: String
|
|
||||||
public let groupingSeparator: String
|
|
||||||
|
|
||||||
private let _s: [Int: String]
|
|
||||||
private let _r: [Int: [(Int, NSRange)]]
|
|
||||||
private let _ps: [Int: String]
|
|
||||||
|
|
||||||
"""
|
|
||||||
var rawKeyPairs = rawDict.map({ ($0 as! String, $1 as! String) })
|
|
||||||
if let filterPrefix = filterPrefix {
|
|
||||||
rawKeyPairs = rawKeyPairs.filter {
|
|
||||||
$0.0.hasPrefix(filterPrefix)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let idKeyPairs = zip(rawKeyPairs, 0 ..< rawKeyPairs.count).map({ pair, index in (pair.0, pair.1, index) })
|
|
||||||
|
|
||||||
var pluralizationKeys = Set<String>()
|
|
||||||
var pluralizationBaseKeys = Set<String>()
|
|
||||||
for (key, _, _) in idKeyPairs {
|
|
||||||
if let (base, _) = pluralizationForm(key) {
|
|
||||||
pluralizationKeys.insert(key)
|
|
||||||
pluralizationBaseKeys.insert(base)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let pluralizationKeyPairs = zip(pluralizationBaseKeys, 0 ..< pluralizationBaseKeys.count).map({ ($0, $1) })
|
|
||||||
|
|
||||||
for (key, value, id) in idKeyPairs {
|
|
||||||
if pluralizationKeys.contains(key) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
let arguments = parseArguments(value)
|
|
||||||
if !arguments.isEmpty {
|
|
||||||
result += " public func \(escapedIdentifier(key))(\(functionArguments(arguments))) -> (String, [(Int, NSRange)]) {\n"
|
|
||||||
result += " return formatWithArgumentRanges(self._s[\(id)]!, self._r[\(id)]!, [\(formatArguments(arguments))])\n"
|
|
||||||
result += " }\n"
|
|
||||||
} else {
|
|
||||||
result += " public var \(escapedIdentifier(key)): String { return self._s[\(id)]! }\n"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (key, id) in pluralizationKeyPairs {
|
|
||||||
var arguments: [Argument]?
|
|
||||||
for (otherKey, value, _) in idKeyPairs {
|
|
||||||
if let (base, _) = pluralizationForm(otherKey), base == key {
|
|
||||||
let localArguments = parseArguments(value)
|
|
||||||
if !localArguments.isEmpty {
|
|
||||||
let numericCount = localArguments.filter({
|
|
||||||
switch $0.type {
|
|
||||||
case .integer:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}).count
|
|
||||||
if numericCount > 1 {
|
|
||||||
preconditionFailure("value for \(key) contains more than 1 numeric argument")
|
|
||||||
}
|
|
||||||
if let argumentsValue = arguments {
|
|
||||||
for i in 0 ..< min(argumentsValue.count, localArguments.count) {
|
|
||||||
if argumentsValue[i] != localArguments[i] {
|
|
||||||
preconditionFailure("value for \(key) contains incompatible argument lists")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if argumentsValue.count < localArguments.count {
|
|
||||||
arguments = localArguments
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
arguments = localArguments
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let arguments = arguments, !arguments.isEmpty {
|
|
||||||
if arguments.count > 1 {
|
|
||||||
var argList = ""
|
|
||||||
var argListAccessor = ""
|
|
||||||
for argument in arguments {
|
|
||||||
if !argList.isEmpty {
|
|
||||||
argList.append(", ")
|
|
||||||
}
|
|
||||||
if !argListAccessor.isEmpty {
|
|
||||||
argListAccessor.append(", ")
|
|
||||||
}
|
|
||||||
argList.append("_ _\(argument.index): ")
|
|
||||||
argListAccessor.append("_\(argument.index)")
|
|
||||||
switch argument.type {
|
|
||||||
case .any:
|
|
||||||
argList.append("String")
|
|
||||||
case .integer:
|
|
||||||
argList.append("Int32")
|
|
||||||
case .float:
|
|
||||||
argList.append("Float")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result +=
|
|
||||||
"""
|
|
||||||
public func \(escapedIdentifier(key))(_ selector: Int32, \(argList)) -> String {
|
|
||||||
let form = getPluralizationForm(self.lc, selector)
|
|
||||||
return String(format: self._ps[\(id) * \(PluralizationForm.formCount) + Int(form.rawValue)]!, \(argListAccessor))
|
|
||||||
}
|
|
||||||
|
|
||||||
"""
|
|
||||||
} else {
|
|
||||||
result +=
|
|
||||||
"""
|
|
||||||
public func \(escapedIdentifier(key))(_ value: Int32) -> String {
|
|
||||||
let form = getPluralizationForm(self.lc, value)
|
|
||||||
let stringValue = \(snakeCaseMappingFileBaseName)FormattedNumber(value, self.groupingSeparator)
|
|
||||||
return String(format: self._ps[\(id) * \(PluralizationForm.formCount) + Int(form.rawValue)]!, stringValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
preconditionFailure("arguments for \(key) is nil")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result +=
|
|
||||||
"""
|
|
||||||
|
|
||||||
public init(primaryComponent: \(mappingFileBaseName)Component, secondaryComponent: \(mappingFileBaseName)Component?, groupingSeparator: String) {
|
|
||||||
self.primaryComponent = primaryComponent
|
|
||||||
self.secondaryComponent = secondaryComponent
|
|
||||||
self.groupingSeparator = groupingSeparator
|
|
||||||
|
|
||||||
self.baseLanguageCode = secondaryComponent?.languageCode ?? primaryComponent.languageCode
|
|
||||||
|
|
||||||
let languageCode = primaryComponent.pluralizationRulesCode ?? primaryComponent.languageCode
|
|
||||||
var rawCode = languageCode as NSString
|
|
||||||
var range = rawCode.range(of: \"_\")
|
|
||||||
if range.location != NSNotFound {
|
|
||||||
rawCode = rawCode.substring(to: range.location) as NSString
|
|
||||||
}
|
|
||||||
range = rawCode.range(of: \"-\")
|
|
||||||
if range.location != NSNotFound {
|
|
||||||
rawCode = rawCode.substring(to: range.location) as NSString
|
|
||||||
}
|
|
||||||
rawCode = rawCode.lowercased as NSString
|
|
||||||
var lc: UInt32 = 0
|
|
||||||
for i in 0 ..< rawCode.length {
|
|
||||||
lc = (lc << 8) + UInt32(rawCode.character(at: i))
|
|
||||||
}
|
|
||||||
self.lc = lc
|
|
||||||
|
|
||||||
var _s: [Int: String] = [:]
|
|
||||||
var _r: [Int: [(Int, NSRange)]] = [:]
|
|
||||||
|
|
||||||
let loadedKeyMapping = keyMapping
|
|
||||||
|
|
||||||
let sIdList: [Int] = loadedKeyMapping.0
|
|
||||||
let sKeyList: [String] = loadedKeyMapping.1
|
|
||||||
let sArgIdList: [Int] = loadedKeyMapping.2
|
|
||||||
|
|
||||||
"""
|
|
||||||
let mappingResult = WriteBuffer()
|
|
||||||
let mappingKeyPairs = idKeyPairs.filter({ !pluralizationKeys.contains($0.0) })
|
|
||||||
mappingResult.append(Int32(mappingKeyPairs.count))
|
|
||||||
for (key, value, id) in mappingKeyPairs {
|
|
||||||
mappingResult.append(Int32(id))
|
|
||||||
mappingResult.append(key)
|
|
||||||
let arguments = parseArguments(value)
|
|
||||||
mappingResult.append(arguments.isEmpty ? 0 : 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
result +=
|
|
||||||
"""
|
|
||||||
for i in 0 ..< sIdList.count {
|
|
||||||
_s[sIdList[i]] = getValue(primaryComponent, secondaryComponent, sKeyList[i])
|
|
||||||
}
|
|
||||||
for i in 0 ..< sArgIdList.count {
|
|
||||||
_r[sArgIdList[i]] = extractArgumentRanges(_s[sArgIdList[i]]!)
|
|
||||||
}
|
|
||||||
self._s = _s
|
|
||||||
self._r = _r
|
|
||||||
|
|
||||||
var _ps: [Int: String] = [:]
|
|
||||||
let pIdList: [Int] = loadedKeyMapping.3
|
|
||||||
let pKeyList: [String] = loadedKeyMapping.4
|
|
||||||
|
|
||||||
"""
|
|
||||||
mappingResult.append(Int32(pluralizationKeyPairs.count))
|
|
||||||
for (key, id) in pluralizationKeyPairs {
|
|
||||||
mappingResult.append(Int32(id))
|
|
||||||
mappingResult.append(key)
|
|
||||||
}
|
|
||||||
result +=
|
|
||||||
"""
|
|
||||||
for i in 0 ..< pIdList.count {
|
|
||||||
for form in 0 ..< \(PluralizationForm.formCount) {
|
|
||||||
_ps[pIdList[i] * \(PluralizationForm.formCount) + form] = getValueWithForm(primaryComponent, secondaryComponent, pKeyList[i], PluralizationForm(rawValue: Int32(form))!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self._ps = _ps
|
|
||||||
|
|
||||||
"""
|
|
||||||
result += " }\n"
|
|
||||||
result +=
|
|
||||||
"""
|
|
||||||
|
|
||||||
public static func ==(lhs: \(mappingFileBaseName), rhs: \(mappingFileBaseName)) -> Bool {
|
|
||||||
return lhs === rhs
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
result += "\n}\n\n"
|
|
||||||
let _ = try? FileManager.default.removeItem(atPath: CommandLine.arguments[2])
|
|
||||||
let _ = try? FileManager.default.removeItem(atPath: CommandLine.arguments[3])
|
|
||||||
let _ = try? result.write(toFile: CommandLine.arguments[2], atomically: true, encoding: .utf8)
|
|
||||||
let _ = try? mappingResult.data.write(to: URL(fileURLWithPath: CommandLine.arguments[3]))
|
|
||||||
} else {
|
|
||||||
print("Couldn't read file")
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user