自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

iOS文本的多語言適配和實踐

移動開發(fā)
產品被多個國家使用,產品方希望產品擁有更好的多語言使用體驗,所以設計師提供多種字體來適配指定的語言?;谝陨媳尘?,客戶端需要快速給出解決方案并且上線。

背景

產品被多個國家使用,產品方希望產品擁有更好的多語言使用體驗,所以設計師提供多種字體來適配指定的語言?;谝陨媳尘?,客戶端需要快速給出解決方案并且上線。

[[422312]]

字體包的多語言適配和實踐

需求分析

首先,在了解產品需求和設計方案之后,結合業(yè)務研發(fā)人員的痛點,整理出以下需求。

產品和設計的需求

  • 不同語言,對應字體包不相同。
  • 全局字體默認使用設計師指定的字體包。
  • 某些語言的字體包缺少某些字重版本,要求降級使用下一個字重版本。
  • 存在某些特殊文案不使用全局字體包(例如:中文,它有專屬的字體包,和語言環(huán)境無關)。
  • 產品迭代需要快速支持擴展,盡量減少研發(fā)投入成本。

設計師要求的字體包資源

研發(fā)的痛點和需求

  • 存在公用組件(其他業(yè)務線都在使用,伴魚公共業(yè)務組件目前有50+),不能修改通用組件。
  • 僅殼工程支持且依賴字體包。
  • 字體包資源來源方式要靈活。

總結一下,產品和設計的需求強調字體適配的全局性、多樣性、可擴展性,研發(fā)關心的是解耦、職責單一、靈活性。

技術設計

分析過后,先確定技術框架的分層。

垂直分層和水平模塊

如圖所示分3層,1.基礎組件提供核心實現,并支持需求擴展 2.業(yè)務組件(無相關修改)3.殼工程提供資源包和代理者。

FontPackage組件要負責什么?

  • FontPackageManager,負責綁定代理來獲取資源包,控制流程邏輯。
  • FontPackageExtension,負責AOP,增加文本屬性來滿足特殊場景的多樣性。
  • FontPackageModel,映射字體包資源的配置信息,明確了使用協議。上層業(yè)務可以增加和調整參數來配置字體包資源。

殼工程的資源包配置

  • env:國際編碼, default 表示設計師指定的默認字體。注意有些國際編碼代表一種語言,例如英語存在 en-US、en-GB 等多種編碼,需要統(tǒng)一為 en。
  • font:字重類型,0:light、1:medium、2:bold。斜體默認替換為medium
  • name:字體源文件的名稱。例如:GothamRndSSm-Medium

備注:因為設計師只要求3種字重,默認light字重,這個和系統(tǒng)提供的 UIFontWeight 不太一致。

  1. //殼工程中的配置文件,反序列化傳回FontPackage層 
  2. //appfont.json 
  3.     "list": [{ 
  4.         "env" : "vi"
  5.         "note" : "越南語,按照國際編碼:vi、vi-VN。FontPackageManager 判斷國際編碼來對應"
  6.         "data" : [{ 
  7.                 "font" : 0, 
  8.                 "name" : "genjyuu_light(越南細)" 
  9.             },{ 
  10.                 "font" : 1, 
  11.                 "name" : "genjyuu_medium(越南中)" 
  12.             },{ 
  13.                 "font" : 2, 
  14.                 "name" : "genjyuu_bold(越南粗)" 
  15.             } 
  16.         ] 
  17.     }, { 
  18.         "env" : "default"
  19.         "note" : "其他語種默認使用字體,但優(yōu)先判斷設備的國際編碼來匹配字體包"
  20.         "data" : [{ 
  21.                 "font" : 0, 
  22.                 "name" : "GothamRndSSm-Light" 
  23.             },{ 
  24.                 "font" : 1, 
  25.                 "name" : "GothamRndSSm-Medium" 
  26.             },{ 
  27.                 "font" : 2, 
  28.                 "name" : "GothamRndSSm-Bold" 
  29.             } 
  30.         ] 
  31.     } 
  32. ]} 

添加字體包和配置文件,還有冷啟動流程:

冷啟動流程圖

技術開發(fā)

FontPackage 功能組件共3個Class,200+行代碼。

首先,在冷啟動時候 FontPackage 根據 json 配置緩存語言編碼匹配到的字體包資源 Model。

然后使用 runtime hook UIFont 類的幾個構造函數,更換構造函數的 fontName 參數。目前確定5個構造函數:

  1. //已處理 
  2. + (UIFont *)systemFontOfSize:(CGFloat)fontSize; 
  3. + (UIFont *)systemFontOfSize:(CGFloat)fontSize weight:(UIFontWeight)weight; 
  4. + (UIFont *)boldSystemFontOfSize:(CGFloat)fontSize; 
  5. + (UIFont *)italicSystemFontOfSize:(CGFloat)fontSize; 
  6. + (UIFont *)fontWithName:(NSString *)fontName size:(CGFloat)fontSize; 

最后統(tǒng)一使用 +fontWithName:size: 函數初始化,fontName 為自定義字體包。

函數 -fontpackage_name: 根據原 fontName 更換為對應的自定義字體包。

 

  1. //FontPackageExtension.m  
  2. //UIFont+FontPackage.m  
  3.  

    #pragma mark - Hook

  4.  
  5. + (UIFont *)xxxFontPackage_systemFontOfSize:(CGFloat)fontSize weight:(UIFontWeight)weight { 
  6.     NSString *fontName = @""
  7.     if (weight == UIFontWeightMedium) { 
  8.         fontName = @"medium"
  9.     } else if (weight > UIFontWeightMedium) { 
  10.         fontName = @"bold"
  11.     } 
  12.     return [self fontWithName:fontName size:fontSize]; 
  13.  
  14. + (UIFont *)xxxFontPackage_italicSystemFontOfSize:(CGFloat)fontSize { 
  15.     //斜體默認是medium 
  16.     return [self fontWithName:@"medium" size:fontSize]; 
  17.  
  18. + (UIFont *)xxxFontPackage_boldSystemFontOfSize:(CGFloat)fontSize { 
  19.     return [self fontWithName:@"bold" size:fontSize]; 
  20.  
  21. + (UIFont *)xxxFontPackage_systemFontOfSize:(CGFloat)fontSize { 
  22.     return [self fontWithName:@"" size:fontSize]; 
  23.  
  24. + (UIFont *)xxxFontPackage_fontWithName:(NSString *)fontName size:(CGFloat)fontSize { 
  25.     fontName = [self fontpackage_name:fontName]; 
  26.     return [self xxxFontPackage_fontWithName:fontName size:fontSize]; 
  27.  
  28.  
  29.  
  30. + (NSString *)fontpackage_name:(NSString *)fontName { 
  31.     fontName = [fontName lowercaseString]; 
  32.     FontPackageFont replaceFont = FontPackageFontLight; //默認light 
  33.     if ([fontName containsString:@"medium"]) { 
  34.         replaceFont = FontPackageFontMedium; 
  35.     } else if ([fontName containsString:@"bold"]) { 
  36.         replaceFont = FontPackageFontBold; 
  37.     } 
  38.     //匹配替換的字體 
  39.     NSString *replaceFontName = [[FontPackageManager shareInstance].fontPackageInfo.dataMap objectForKey:@(replaceFont)]; 
  40.     return replaceFontName; 

文本信息的多語言適配和實踐

針對海外用戶做語言本地化也是一項重要的產品功能,但很多組件在開發(fā)之初并未預留本地化拓展的接口,客戶端需要提供一套優(yōu)雅的解決方案來應對此問題。

需求分析

1、產品和設計的需求

  • 語言本地化
  • 未提供本地化的語言,默認使用產品指定的語言
  • 快速支持新語言本地化

2、技術要求

  • 接入成本低,不需要對成熟組件做改動
  • 解耦,其他組件無需依賴本功能

技術設計

垂直分層和水平模塊

如圖所示分3層:1、基礎組件提供需求擴展 2、業(yè)務組件(基本不需要修改,如有特殊屬性需求可以依賴基礎組件)3、殼工程提供資源包和以及資源包的更新

LocalizedString 組件要負責什么?

  • LocalizedString,負責文字本地化適配。
  • LocalizedTool,負責語言包的配置、讀取、更換功能。
  • LocalizedExtension,負責AOP,補充某些屬性。

語言包目錄如下:

語言包目錄

可以看到,語言包是按照語言碼進行命名的,方便在使用中及時定位到對應文件并讀取(存在多種編碼的語言,統(tǒng)一使用其基礎類)。同時,在殼工程中會對本地語言包進行刷新,App啟動后會檢查是否有新的語言包可用,如果有會保證數據同步。

配置好語言包后,接下來需要冷啟動時初始化LocalizedString 組件。啟動時組件任務流程圖如下:

冷啟動流程圖

技術開發(fā)

考慮到字符串最終都會依托于 UILabel 進行展示,[UILabel setText:]會作為設置展示文本的唯一收口。所以我們對[UILabel setText:]進行了 hook 和拓展,其內部操作流程圖如下:

AOP流程圖

LocalizedString 組件有 NSString、UILabel 分類分別做了屬性拓展。具體代碼如下:

  1. @interface UILabel (Localized) 
  2. @property (nonatomic, assign) BOOL isAutoLocalized; ///< 設置的文字是否要自動轉換成本地化的語言,默認YES 
  3. @end 
  4.  
  5. @interface NSString (Localized) 
  6. @property (nonatomic, copy) NSString *oriStr; ///< 上次本地化的字符串原始值 
  7. @property (nonatomic, copy) NSString *localizedStr; ///< oriStr 本地化后的字符串 
  8. @end 

對 UILabel 的分類拓展可以判斷 Label 是否需要被本地化;對 NSString 的分類拓展會對本地化后的結果進行緩存,當同一個 string 對象再次本地化時,可以快速從緩存拿到結果減少在 map 中的檢索次數、提高效率。類拓展的方式也保證了本組件的侵入性極低。

整個工程使用了 pod 進行集成,基礎組件無需聲明依賴,對本組件有依賴要求的只在特定業(yè)務中出現。hook + pod 的方式保證了本組件的靈活使用和充分解耦。

與NSLocalizedString的兼容

從上面的流程介紹可以看到,本地化替換發(fā)生在對 Label 設置文本的時候,不同于 NSLocalizedString 需要先顯式本地化再設置文本的方式。所以,當使用方提前對文本進行了本地化,本組件的自動本地化不生效??紤]到本組件主要應用于新語言地區(qū),NSLocalizedString 尚未配置對應的結果,故目前仍然可以使用本組件兜底。我們也會后續(xù)優(yōu)化本組件,完成與 NSLocalizedString 的兼容,更加方便本組的使用。

拓展

由于上述方法只適用于[UILabel setText:]這種形式的無侵入調整,對于字符串拼接的情況,仍需要開發(fā)人員使用 LocalizedString 類對子串進行逐一本地化。同時,為了支持以后可能的應用內變更語言,LocalizedString 也提供了動態(tài)變更語言包功能。LocalizedString 主要 API 如下:

  1. /** 
  2.  @brief 直接返回指定 key 對應的 本地化文字 
  3.  @param key 轉譯文件表中的key 
  4.  */ 
  5. + (NSString *)forKey:(NSString *)key
  6.  
  7.  /** 
  8.  @brief 根據指定的 language code,返回key 對應的 本地化文字 
  9.  @param key 轉譯文件表中的key 
  10.  @param langCode語言編碼 
  11.  */ 
  12. + (NSString *)forKey:(NSString *)key langCode:(NSString *)langCode; 
  13.  
  14. /** 
  15.  @brief 設置當前默認的語言編碼 
  16.  @param langCode語言編碼 
  17.  */ 
  18. + (void)setCurrentLangCode:(NSString *)langCode; 

總結

在多個產品同時的迭代情況下,使用組件化已經變得非常普遍,不斷地重構優(yōu)化組件來保證低耦合。當面對國際化場景時,需要沉淀打磨國際化適配框架來支撐業(yè)務高效迭代,并且不能給其他業(yè)務造成負擔。

目前以上功能都已上線,滿足了產品的需求,解決了研發(fā)的痛點。

作者介紹

呂洪陽,伴魚 iOS 工程師,伴魚繪本iOS端負責人

趙杰,伴魚 iOS 工程師,負責伴魚繪本客戶端研發(fā),功能降級框架等工作

 

責任編輯:未麗燕 來源: 伴魚技術團隊
相關推薦

2014-04-16 14:50:20

Spark

2014-07-09 09:20:06

WPFWPF應用

2012-04-19 11:40:21

Titanium

2011-08-05 17:54:33

Cocoa Touch 多語言

2009-08-25 10:44:50

C#實現多語言

2021-06-29 21:48:32

開源語言架構

2024-05-09 08:14:09

系統(tǒng)設計語言多語言

2023-08-09 09:36:04

Azure AI微軟

2022-08-09 07:22:15

語言數據庫程序

2013-10-16 15:50:01

iOS優(yōu)化本地化

2009-07-17 10:02:29

WPF程序多語言支持

2023-08-04 10:18:15

2024-12-19 07:58:53

2020-04-14 09:50:02

2023-06-29 07:27:26

知識圖譜Shopee

2019-12-05 16:00:15

Vim插件編程文本編輯器

2009-08-31 17:13:09

2009-08-03 17:33:01

ASP.NET多語言支

2021-07-24 11:41:42

前端開發(fā)技術

2009-06-15 15:33:13

ScalaTwitter
點贊
收藏

51CTO技術棧公眾號