Using ".stringsdict" file with 'localizedStringWithFormat' --> Are NUMERALS localized for you? - localization

I am trying to produce the following localized string:
"In ___ day(s)" --> (ex: In 5 days)
To accomplish this, I've gone down the .stringsdict route:
<key>In %d Days</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%##Days#</string>
<key>Days</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>zero</key>
<string>Today</string>
<key>one</key>
<string>In %d Day</string>
<key>other</key>
<string>In %d Days</string>
</dict>
</dict>
I then use the following, to obtain a localized string:
NSInteger days = ...;
localizedDueDateString = [NSString localizedStringWithFormat:NSLocalizedString(#"In %d Days", #"Indicates days"),ABS(days)];
This correctly outputs a string that accounts for plurality. For example:
In 1 day
In 4 days
I am wondering if the "1" and the "4" here will be localized correct. Other languages, like Arabic for example, have different symbols for their numerals. I would expect the above string to use the symbol "٤" instead of "4", for arabic.
I know this can be accomplished using an NSNumberFormatter, but how can I accomplish numeral localization while ALSO respecting plurality visa vi a .stringsdict file?

YES
Numerals do appear to be correctly swapped when using a .stringsdict file in coordination with "localizedStringWithFormat" method!
I switched my iPad language to Arabic, and the output for
In 1 day
was...
١ day In
I don't have an arabic localization done yet, so "In" and "day" are english, but the numeral appears to be correctly localized. No need for NSNumberFormatter

Related

Password validation with regex Arabic and English characters in swift

I want to validate the password to include at least 1 Arabic or English letter and at least 1 Arabic or English number and at leats 8 length password, my old code that was made for English only was like :
let passwordRegex = "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,}$"
if (!NSPredicate(format:"SELF MATCHES %#",passwordRegex).evaluate(with: password)){
return false
}
and then i found this answer for Arabic characters and digits, then i tried to merge both like this :
let passwordRegex = "^(?=.*[A-Za-zء-ي])(?=.*٠-٩\\d)[A-Za-zء-ي٠-٩\\d]{8,}$"
if (!NSPredicate(format:"SELF MATCHES %#",passwordRegex).evaluate(with: password)){
return false
}
please advise what's wrong, thanks in advance
Since an English or Arabic letter regex (as described in this answer you linked to, also, see this answer, too) is [a-zA-Za-z\u0621-\u064A] and an English or Arabic digit regex is [0-9\u0660-\u0669] you may use
let passwordRegex = "^(?=.*[a-zA-Z\\u0621-\\u064A])(?=.*[0-9\\u0660-\\u0669])[a-zA-Za-z\\u0621-\\u064A0-9\\u0660-\\u0669]{8,}$"
NOTE: you do not need the outer ^ and $ anchors because MATCHES requires the pattern to match the whole string input.
Another way to match an Arabic letter with ICU regex used in Swift is to use [\p{L}&&[\p{script=Arabic}]] (it is an intersection inside a character class, it matches any letter but from the Arabic character set). Same with a digit: [\p{N}&&[\p{script=Arabic}]]. Then, the regex will look like
let passwordRegex = "^(?=.*[\\p{L}&&[\\p{script=Arabic}A-Za-z]])(?=.*[\\p{N}&&[\\p{script=Arabic}0-9]])[\\p{L}\\p{N}&&[\\p{script=Arabic}a-zA-Z0-9]]{8,}$"
So, here
[\\p{L}&&[\\p{script=Arabic}A-Za-z]] - any letter but it should belong to either ASCII letters or Arabic script
[\\p{N}&&[\\p{script=Arabic}0-9]] - any digit but either from 0-9 range or Arabic script
[\\p{L}\\p{N}&&[\\p{script=Arabic}a-zA-Z0-9]] - any letter or digit but only from the ASCII 0-9, A-Z, a-z and Arabic script.
Note also, that in order to match any letters, you may use\p{L} and to match any digits you may use \d (they are Unicode aware in ICU library). So, *in case t does not matter if the letters or digits are Arabic, English, Greek or whatever, you may use
let passwordRegex = "^(?=.*\\p{L})(?=.*\\d)[\\p{L}\\d]{8,}$"

String pluralizer with NSNumberFormatter

I want to display a nicely formatted integer value via the usual pluralization technology .stringsdict file. (Apple docs here.)
So if I have one thing, I want my output to read
1 thing
But if I have two thousand, three hundred sixty-four things, I want those commas:
2,364 things
but alas the string pluralization technology doesn't give them to me:
2364 things
I can achieve commas with an NSNumberFormatter. I can achieve pluralization with .stringsdict localization technology.
Can I easily achieve both?
Since you already have .stringsdict files setup with the properly plural strings, you don't actually need a number formatter. Simply use the localizedStringWithFormat method of String or NSString.
Assuming you have setup the localized key "%d things" in your Localizable.strings files and your .stringsdict files, your code would look something like:
Swift:
let things = 2364
let localizedString = String.localizedStringWithFormat(NSLocalizedString(#"%d things", #"Your comment"), things)
Objective-C:
int things = 2364;
NSString *localizedString = [NSString localizedStringWithFormat:NSLocalizedString(#"%d things", #"Your comment"), things];
Depending on your locale, the result will be something like:
2,364 things
2.364 things
2 364 things

Localizable.stringsdict: getting English to use the "two" key [duplicate]

I'm trying to use the .stringsdict functionality in iOS programming to display the proper ordinal suffix (st, nd, rd, etc...) for numbers. I've created the .stringsdict file for english, but it's only using the 'one' and 'other' keys. It's ignoring the 'two' and 'few' options. Anybody see what i've done wrong here?
The file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>TEAM_RANK_ORDINAL</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%##ordinal_string#</string>
<key>ordinal_string</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>lu</string>
<key>one</key>
<string>%lust</string>
<key>two</key>
<string>%lund</string>
<key>few</key>
<string>%lurd</string>
<key>other</key>
<string>%luth</string>
</dict>
</dict>
</dict>
</plist>
I then access it like so, from Swift. For the value 1 it appends st, but every other number appends th:
let fmt = NSLocalizedString("TEAM_RANK_ORDINAL", comment: "")
for i in 0...30 {
println(String(format: fmt, i))
}
The english locale ignores the "two" and "few" rules and uses
only "one" and "other".
See Plural Rule Properties in the "Internationalization and Localization Guide":
The meaning of the categories is language-dependent, and not all
languages have the same categories.
For example, English only uses the one, and other categories to
represent plural forms. Arabic has different plural forms for the
zero, one, two, few, many, and other categories. ...
There is (as far as I know) no way to use a .stringsdict file
for producing ordinal numbers.
While Martin answered your stringsdict question, for users who stumble across the "ordinal" issue, one should just use NumberFormatter for localized ordinal numbers. E.g.
let formatter = NumberFormatter()
formatter.numberStyle = .ordinal
for i in 1..<30 {
print(formatter.string(for: i) ?? i)
}
Producing (for English users):
1st
2nd
3rd
4th
5th
6th
7th
8th
9th
10th
11th
12th
13th
14th
15th
16th
17th
18th
19th
20th
21st
22nd
23rd
24th
25th
26th
27th
28th
29th
And, FWIW, even if the stringsdict approach worked for two, etc., doesn't have a prayer of differentiating between large numbers that use a different ordinality syntax, e.g. between 122nd and 124th. You really need to use NumberFormatter for this.

iOS .stringsdict not working

I'm trying to use the .stringsdict functionality in iOS programming to display the proper ordinal suffix (st, nd, rd, etc...) for numbers. I've created the .stringsdict file for english, but it's only using the 'one' and 'other' keys. It's ignoring the 'two' and 'few' options. Anybody see what i've done wrong here?
The file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>TEAM_RANK_ORDINAL</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%##ordinal_string#</string>
<key>ordinal_string</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>lu</string>
<key>one</key>
<string>%lust</string>
<key>two</key>
<string>%lund</string>
<key>few</key>
<string>%lurd</string>
<key>other</key>
<string>%luth</string>
</dict>
</dict>
</dict>
</plist>
I then access it like so, from Swift. For the value 1 it appends st, but every other number appends th:
let fmt = NSLocalizedString("TEAM_RANK_ORDINAL", comment: "")
for i in 0...30 {
println(String(format: fmt, i))
}
The english locale ignores the "two" and "few" rules and uses
only "one" and "other".
See Plural Rule Properties in the "Internationalization and Localization Guide":
The meaning of the categories is language-dependent, and not all
languages have the same categories.
For example, English only uses the one, and other categories to
represent plural forms. Arabic has different plural forms for the
zero, one, two, few, many, and other categories. ...
There is (as far as I know) no way to use a .stringsdict file
for producing ordinal numbers.
While Martin answered your stringsdict question, for users who stumble across the "ordinal" issue, one should just use NumberFormatter for localized ordinal numbers. E.g.
let formatter = NumberFormatter()
formatter.numberStyle = .ordinal
for i in 1..<30 {
print(formatter.string(for: i) ?? i)
}
Producing (for English users):
1st
2nd
3rd
4th
5th
6th
7th
8th
9th
10th
11th
12th
13th
14th
15th
16th
17th
18th
19th
20th
21st
22nd
23rd
24th
25th
26th
27th
28th
29th
And, FWIW, even if the stringsdict approach worked for two, etc., doesn't have a prayer of differentiating between large numbers that use a different ordinality syntax, e.g. between 122nd and 124th. You really need to use NumberFormatter for this.

CSV to Plist Conversion IOS

I need help turning my large spreadsheet into a plist. I want the key names to be Letters of the alphabet and the names to be values:
<plist version="1.0">
<dict>
<key>A</key>
<array>
<string>Amstel Light</string>
<string>Anchor Porter</string>
<string>Anchor Steam Beer</string>
<string>Anheuser Busch Natural Light</string>
<string>Asahi Draft Beer</string>
</array>
<key>B</key>
<array>
<string>Ballentine India Pale Ale</string>
<string>Ballentine Premium Lager</string>
<string>Ballentine Private Stock Malt Liquor</string>
<string>Ballentine XXX Ale </string>
<string>Bass Bale Ale</string>
<string>Beamish Irish Cream Stout</string>
<string>Beamish Red Ale</string>
<string>Beck Beer</string>
<string>Big Barrell Australian Lager</string>
<string>Black Horse Premium Draft Beer</string>
<string>Blatz Beer</string>
<string>Blatz Milwaukee 1851 Beer</string>
<string>Boulder Porter</string>
<string>Bud Light Beer</string>
<string>Budweiser King of Beers</string>
<string>Busch Beer</string>
I unfortunately had to enter these manually before, but my dataset is now enormous and contains about 1000 values. How can I automatically do this. I tried writing a Concatonate function in excel which gave me keys in the proper syntax but i still cannot copy and paste them easily due to formatting issues, basically It turns whole value into one line vs having it in four with the key, then array… The herokuapp method also does not create the keys in the way I need. Any help would be greatly appreciated.

Resources