成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

處理i18n國際電話區號的代碼實踐

移動開發
上周在忙產品的國際化(i18n)的問題 其中一個很重要的地方就是電話號碼的國際化(我們以電話號碼為主賬號) 電話號碼有個很重要的部分就是區號


 

前言

上周在忙產品的國際化(i18n)的問題 其中一個很重要的地方就是電話號碼的國際化(我們以電話號碼為主賬號) 電話號碼有個很重要的部分就是區號

??

上圖是我們產品的登錄界面 除了常規的電話號碼之外 前面還有一個區號 代表這個電話號碼所屬的是哪個國家和地區 關于區號的概念 可以看一下??維基百科??

 看到這里 可能有人奇怪 這有什么難的? 不就是按照列表來展示嗎? 這樣有幾個問題

  • 由于是支持多語言 那么不同的語言環境的系統 顯示出來的國家名稱是不一樣的 比如“中國” 簡體中文是“中國” 英文是“China” 韓文是“???????” 其在各個語言中的顯示排序都是不一樣的
  • 如果根據不同國家和語言來維護一張這樣的表 工作量太大 一般的公司估計做不來

所以這個工作我們就會放到本地來做 不過iOS已經幫我們做了一部分工作了 我們可以根據??國家代碼??來獲取某個國家或在當前區域中的本地化名稱

 

 

//獲取當前locale
NSLocale *locale = [NSLocale currentLocale];

//獲取所有國家的代碼
NSArray *countryArray = [NSLocale ISOCountryCodes];

for (NSString *countryCode in countryArray)
{
//根據當前locale和國家短碼 獲取指定國家的本地化名稱
NSString *localName = [locale displayNameForKey:NSLocaleCountryCode value:countryCode];
}

我們簡單測試一下

NSArray *countryArray  = [NSLocale ISOCountryCodes];
NSArray *languageArray = @[@"zh_CN",@"en_US",@"ja_JP"];

for ( NSString *languege in languageArray)
{
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:languege];

for ( int i = 0 ; i < 5 ; ++i )
{
NSString *countryCode = countryArray[i];

NSString *displayName = [locale displayNameForKey:NSLocaleCountryCode value:countryCode];

NSLog(@"%@\t%@\t%@",languege,countryCode,displayName);
}
}

結果

 

 

zh_CN   AD  安道爾
zh_CN AE 阿拉伯聯合酋長國
zh_CN AF 阿富汗
zh_CN AG 安提瓜和巴布達
zh_CN AI 安圭拉

en_US AD Andorra
en_US AE United Arab Emirates
en_US AF Afghanistan
en_US AG Antigua and Barbuda
en_US AI Anguilla

ja_JP AD アンドラ
ja_JP AE アラブ首長國連邦
ja_JP AF アフガニスタン
ja_JP AG アンティグア?バーブーダ
ja_JP AI アンギラ

已經介紹完iOS幫我們做的一部分工作了 那么另一部分就得我們自己來了
我們需要有一張 地區->區號 的列表 不過這個也簡單 網上一抓一大把 我也是網上找的 文件內容如下(diallingcode.json)

[
{
"name": "Afghanistan",
"dial_code": "+93",
"code": "AF"
},
{
"name": "Albania",
"dial_code": "+355",
"code": "AL"
},

...
...
//中間省略
...
...

{
"name": "Virgin Islands, British",
"dial_code": "+1 284",
"code": "VG"
},
{
"name": "Virgin Islands, U.S.",
"dial_code": "+1 340",
"code": "VI"
}
]

維護這樣一張表就很簡單了我們可以存在本地 也可以放在服務器(“name”字段其實是不必須的 只是為了好看)

研究

我們暫時先把代碼放一放 來看一看其他產品是怎么做的

這個是微信的

??

微信的問題還是挺多的

  • 左邊是中文環境 按拼音分組是分對了 但是文字排序卻粗錯了 “阿”開頭的國家并沒有排列在一起
  • 右邊是法語環境 這些??衍生拉丁字母?? 并沒有正確的歸類

這個是Twitter的

??

Twitter在中文環境下還是挺奇怪的 但是卻沒有犯微信第二個錯誤

Facebook的呢? 人家的工程師比較聰明(懶) 壓根就不支持索引

接下來我們會解決出現的這幾個問題

代碼

先簡歷一個Modal 用來表示國家相關的信息

@interface MMCountry : NSObject

@property (nonatomic, strong) NSString *name; //國家名(本地化后的版本)
@property (nonatomic, strong) NSString *code; //國家代號
@property (nonatomic, strong) NSString *latin; //國家名的拉丁文(只包含基本拉丁字母)
@property (nonatomic, strong) NSString *dial_code; //區號

@end

然后我們要把區號從配置文件中讀取出來 并以區號為key 建立索引

NSData *data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"diallingcode" ofType:@"json"]];
NSError *error = nil;

NSArray *arrayCode = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];

if ( error ) {

return;
}

//讀取文件
NSMutableDictionary *dicCode = [@{} mutableCopy];

for ( NSDictionary *item in arrayCode )
{
MMCountry *c = [MMCountry new];

c.code = item[@"code"];
c.dial_code = item[@"dial_code"];

[dicCode setObject:c forKey:c.code];
}

接著獲取這些國家的本地話名稱

NSLocale *locale = [NSLocale currentLocale];
NSArray *countryArray = [NSLocale ISOCountryCodes];

NSMutableDictionary *dicCountry = [@{} mutableCopy];

for (NSString *countryCode in countryArray) {

if ( dicCode[countryCode] )
{
MMCountry *c = dicCode[countryCode];

//這里 你懂的
c.name = [locale displayNameForKey:NSLocaleCountryCode value:countryCode];
if ( [c.name isEqualToString:@"臺灣"] )
{
c.name = @"中國臺灣";
}

//把名稱拉丁字母化
c.latin = [self latinize:c.name];

[dicCountry setObject:c forKey:c.code];
}
else
{
//找不到則說明配置文件不全 可以補全
NSLog(@"missed %@ %@",[locale displayNameForKey:NSLocaleCountryCode value:countryCode],countryCode);
}
}

這里要注意的是 把字母拉丁文化 解決了微信的第二個問題 使非基本拉丁字母也可以按照基本拉丁字母來排序 其函數如下

 

 

- (NSString*)latinize:(NSString*)str
{
NSMutableString *source = [str mutableCopy];

CFStringTransform((__bridge CFMutableStringRef)source, NULL, kCFStringTransformToLatin, NO);

//微信是這樣做的
//CFStringTransform((__bridge CFMutableStringRef)source, NULL, kCFStringTransformMandarinLatin, NO);

CFStringTransform((__bridge CFMutableStringRef)source, NULL, kCFStringTransformStripDiacritics, NO);

return source;
}

這里有兩步

  1. 先將文字 轉成拉丁字母(kCFStringTransformToLatin)
  2. 再將拉丁字母去掉變音符(kCFStringTransformStripDiacritics)


這里是微信犯的***個錯誤 也就是沒有正確歸類的錯誤 因為微信在***步的時候只針對漢字進行了處理 其他字符則沒有處理 導致第二步沒有得到正確的基本拉丁字符(kCFStringTransformMandarinLatin 參見注釋掉的代碼)


我們來測試一下這兩步會造成得到效果 還是之前的例子

 

 

NSArray *countryArray  = [NSLocale ISOCountryCodes];
NSArray *languageArray = @[@"zh_CN",@"en_US",@"ja_JP"];

for ( NSString *languege in languageArray)
{
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:languege];

for ( int i = 0 ; i < 5 ; ++i )
{
NSString *countryCode = countryArray[i];

NSString *displayName = [locale displayNameForKey:NSLocaleCountryCode value:countryCode];

NSLog(@"%@\t%@\t%@\t@",languege,countryCode,displayName,[self latinize:displayName]);
}
}

結果

 

 

zh_CN   AD  安道爾 |   an dao er
zh_CN AE 阿拉伯聯合酋長國 | a la bo lian he qiu zhang guo
zh_CN AF 阿富汗 | a fu han
zh_CN AG 安提瓜和巴布達 | an ti gua he ba bu da
zh_CN AI 安圭拉 | an gui la
en_US AD Andorra | Andorra
en_US AE United Arab Emirates | United Arab Emirates
en_US AF Afghanistan | Afghanistan
en_US AG Antigua & Barbuda | Antigua & Barbuda
en_US AI Anguilla | Anguilla
ja_JP AD アンドラ | andora
ja_JP AE アラブ首長國連邦 | arabu shou zhang guo lian ban
ja_JP AF アフガニスタン | afuganisutan
ja_JP AG アンティグア?バーブーダ | antigua?babuda
ja_JP AI アンギラ | angira

可以到看 系統會根據不同國家和不同語言的特點 將同一個國家的不同表達形式轉化成不同的拉丁字母

接下來 我們把獲取過的數據根據’A’-‘Z’進行歸類

NSMutableDictionary *dicSort = [@{} mutableCopy];

for ( MMCountry *c in dicCountry.allValues )
{
NSString *indexKey = @"";

if ( c.latin.length > 0 )
{
indexKey = [[c.latin substringToIndex:1] uppercaseString];

char c = [indexKey characterAtIndex:0];

if ( ( c < 'A') || ( c > 'Z' ) )
{
continue;
}
}
else
{
continue;
}

NSMutableArray *array = dicSort[indexKey];

if ( !array )
{
array = [NSMutableArray array];

dicSort[indexKey] = array;
}

[array addObject:c];
}

*** 將每個歸類下面的數據 排序重新整理

for ( NSString *key in dicSort.allKeys )
{
NSArray *array = dicSort[key];

array = [array sortedArrayUsingComparator:^NSComparisonResult(MMCountry *obj1, MMCountry *obj2) {

return [obj1.name localizedStandardCompare:obj2.name];
}];

// array = [array sortedArrayUsingComparator:^NSComparisonResult(CSCountry *obj1, CSCountry *obj2) {
//
// return obj1.latin > obj2.latin;
// }];

dicSort[key] = array;
}

這樣dicSort就是我們最終得到的結果集


這里是微信犯的第二個錯誤 微信的排序是按照latin來排序的(見注釋掉的代碼) 所以導致了相同漢字的國家排不到一起的情況 正確的方式是用localizedStandardCompare來排序 這也是iOS已為我們提供好了的本地化比較函數
看看之前的圖中 挑三個國家出來 比如:阿爾巴尼亞 愛爾蘭 阿魯巴 他們的拼音是 aerbabiya aierlan aluba 如果按照拼音排序的話 這樣的排序就是正確的


我們來看看最終的效果

??

是不是比微信的更好?

討論

雖然代碼是寫完了 但是問題并沒有結果 有一個關鍵的問題就是 為什么我們要按照’A’-‘Z’來索引排序呢? 比如Twitter在日文和韓文環境下是這樣的

??

其實按照不同國家的語言特點來進行對應的索引 應該才是***的解決辦法(PS:看到Twitter在中文環境下的糟糕結果 我也不確定其在日文和韓文下的結果是否是正確的(ˉ﹃ˉ)
當然 如果真要這樣做 其實改動量也不大 只要在索引的那塊稍微修改一下就行了

小結

文中的demo可以在??這里??找到

正如討論中說的一樣 本文所討論的方案 并不是最終的解決方案 如果需要更好的體驗的話 還要深入研究各國的文化才行 所以 國際化并不單純是個技術問題 更是個社會工程啊~~~~

責任編輯:倪明 來源: 里脊串的開發隨筆
相關推薦

2023-09-05 15:23:06

開發應用鴻蒙

2016-12-19 15:35:10

Web開發者jQueryi18n

2021-04-16 16:37:23

SpringMVC源碼配置

2023-01-31 10:29:26

JavaScript國際化國際化庫

2012-02-01 09:22:33

Java

2020-11-06 07:30:36

JS文件

2015-03-30 09:32:15

XcodeiOS應用程序

2018-06-06 15:08:57

前端開發工具

2022-08-02 09:01:55

后臺管理模版

2024-04-01 11:52:46

2020-01-15 15:12:38

Java8日期處理代碼

2020-02-06 11:35:58

Java 8APIJava

2010-08-26 17:39:48

谷歌

2024-05-17 08:25:06

數據驅動React語言包

2023-07-17 15:28:03

JavaScrip開發

2021-04-08 10:01:48

Java機器學習深度學習

2014-06-23 14:55:13

浪潮I2I國際化

2024-07-25 13:04:21

2023-05-04 08:02:13

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日本大片在线播放 | 日韩在线观看网站 | 福利片在线看 | 精品九九| 久久久久久99 | 亚洲36d大奶网 | 久久久久一区二区 | 亚洲h色| 欧美美女二区 | av毛片 | 午夜成人免费视频 | 亚洲麻豆 | 日韩中文一区 | 麻豆一区二区三区精品视频 | 日韩精品一区二区三区中文字幕 | 欧美性网站 | 久草视频观看 | 尤物在线视频 | 国产精品影视 | 久久久久久看片 | 久久成人18免费网站 | 黄色片免费在线观看 | 欧美中文 | h视频亚洲 | www.一区二区三区 | 亚洲国产精品久久久 | 久久久久欧美 | 日韩一级精品视频在线观看 | 久久久久久国产精品 | 亚洲精品一区二区在线观看 | 最新中文字幕在线 | 国产一区二区三区高清 | 国产一区二区三区欧美 | 日韩三级电影一区二区 | 91综合在线视频 | 成人性生交大片免费看中文带字幕 | 日韩一区二区在线视频 | 欧美lesbianxxxxhd视频社区 | 老司机精品福利视频 | 欧美 日韩 国产 成人 | 污片在线免费观看 |