Swifternalization, 用JSON文件更聪明的方式,本地化iOS应用 Swift 框架

分享于 

22分钟阅读

GitHub

  繁體 雙語
Localize iOS apps in smarter way. Swift framework.
  • 源代码名称:Swifternalization
  • 源代码网址:http://www.github.com/tomkowz/Swifternalization
  • Swifternalization源代码文档
  • Swifternalization源代码下载
  • Git URL:
    git://www.github.com/tomkowz/Swifternalization.git
    Git Clone代码到本地:
    git clone http://www.github.com/tomkowz/Swifternalization
    Subversion代码到本地:
    $ svn co --depth empty http://www.github.com/tomkowz/Swifternalization
    Checked out revision 1.
    $ cd repo
    $ svn up trunk
    

    Swifternalization: localize apps smarter

    CocoaPods Status

    Swifternalization

    Swift 库,它可以帮助在不同。更好。更简单。更强大的方式下定位应用程序。 它使用json文件而不是字符串文件。

    Swift 3

    Swift 3兼容版本可以在 swift3 分支上使用。 目前还没有可用的吊舱。 验证podspec时遇到代码标志和 xcode 8问题。 将尝试解决它。

    特性
    • 多元化支持- 不使用 stringdict 文件
    • 自 iOS 8.0 ( 而不是像系统那样的iOS 9.0 ) 支持的长度变化支持,避免使用 stringsdict 文件
    • 表达式- 不等式和 正规表达式
    • 共享表达式
    • 内置表达式
    • NSLocalizedString ( ) 类似的工作方式
    • 使用JSON文件来最小化样板代码
    • 全面的单元测试 覆盖
    • 完整文档
    目录

    简介

    Swifternalization有助于以更聪明的方式本地化应用程序。 它是由于解决波兰语内部化问题的必要性而创造的,但是它是通用的。

    它使用JSON文件和表达式,避免编写代码来处理某些情况,在不使用这里框架时必须编写。 它使得本地化过程更简单。

    实用用法示例

    实际使用例子将使用文档后面所介绍的事物,以便继续阅读并读取这里的详细信息/特性。

    问题

    让我们假定应用支持英语和波兰语语言。 自然应用包含两个 Localizable.strings 文件。 一种是基于英语的基础语言,包括英语,英语,翻译,翻译,翻译,语言,法语,法语,法语,法语。

    应用显示标签,表示后端的对象已经更新后,比如" 2分钟前"," 3小时前"," 1分钟前"等等。

    分析

    标签以单数或者复数形式显示数字和 hour/minute/second 单词,带有"前情"后缀。 不同的语言以稍微不同的方式处理复数/基数。 这里我们需要支持英语和波兰语语言。

    在英语中,每个 hour/minute/second 单词只包含两种情况:

    • 1 -"前"
    • 0,2,3。 %d秒之前"
    • 同样的分钟和小时。

    因为基数数字更复杂,所以它更加复杂:

    • 0,( 5 - 21 ) -"%d sekund temu""
    • ( 2 - 4 ),( 22 -24 ),( 32 -34 ),( 42,44 ),。 ,( 162 -164 )。- %d sekundy temu"
    • 几分钟和小时的相同逻辑。

    以下章节将介绍没有Swifternalization框架的解决方案。 每个解决方案描述基本( 简体中文) 和波兰本地化。

    这里有一个带有复数规则 covers许多语言中数字的基数形式- 许多语言的handle。

    不带Swifternalization的解决方案

    
    Localizable.strings (Base)
    
    
    --------------------------
    
    
    "one-second" ="1 second ago";
    
    
    "many-seconds" ="%d seconds ago";
    
    
    
    "one-minute" ="1 minute ago"; 
    
    
    "many-minutes" ="%d minutes ago";
    
    
    
    "one-hour" ="1 hour ago";
    
    
    "many-hours" ="%d hours ago";
    
    
    
    Localizable.strings (Polish)
    
    
    ------------------------- 
    
    
    "one-second" ="1 sekundę temu"
    
    
    "few-seconds" ="%d sekundy temu"
    
    
    "many-seconds" ="%d sekund temu"" 
    
    
    
    "one-minute" ="1 minutę temu"
    
    
    "few-minutes" ="%d minuty temu"
    
    
    "many-minutes" ="%d minut temu" 
    
    
    
    "one-hours" ="1 godzinę temu"
    
    
    "few-hours" ="%d godziny temu"
    
    
    "many-hours" ="%d godzin temu";
    
    
    
    

    英语中有 6例案例,波兰语案例为 9. 注意,如果没有额外的逻辑,我们无法检测到应用程序的字符串的哪个版本应该显示。 不同语言之间的逻辑不同。 我们需要添加一些代码来处理我们在应用程序中使用的所有语言的逻辑。 如果有超过 2种语言的情况? do think - 这可能不是那么容易。

    然而,逻辑已经在框架中实现了,它适合每一种语言。

    带Swifternalization的解决方案

    这就是可以本地化文件的外观:

    
    base.json
    
    
    ---------
    
    
    "time-seconds": {
    
    
    "one":"%d second ago"
    
    
    "other":"%d seconds ago"
    
    
    },
    
    
    
    "time-minutes": {
    
    
    "one":"%d minute ago"
    
    
    "other":"%d minutes ago"
    
    
    },
    
    
    
    "time-hours": {
    
    
    "one":"%d hours ago"
    
    
    "other":"%d hours ago"
    
    
    }
    
    
    
    pl.json
    
    
    -------
    
    
    "time-seconds": {
    
    
    "one":"1 sekundę temu",
    
    
    "few":"%d sekundy temu",
    
    
    "many":"%d sekund temu"
    
    
    },
    
    
    
    "time-minutes": {
    
    
    "one":"1 minutę temu",
    
    
    "few":"%d minuty temu",
    
    
    "many":"%d minut temu"
    
    
    },
    
    
    
    "time-hours": {
    
    
    "one":"1 godzinę temu",
    
    
    "few":"%d godziny temu",
    
    
    "many":"%d godzin temu"
    
    
    }
    
    
    
    
    • "一个","数多个其他"那些已经被构建在Swifternalization中的共享表达式- - 下面已经覆盖了。
    • 你可以添加自己的表达式来处理特定的案例- covered。

    如前所述,逻辑实现为框架,因此如果想要获得本地化字符串之一,你必须进行简单的调用。

    
    Swifternalization.localizedString("time-seconds", intValue: 10)
    
    
    
    

    或者使用 I18n typealias ( I-18-letters-n,内部化 ):

    
    I18n.localizedString("time-seconds", intValue: 10)
    
    
    
    

    下面的代码通过加载的表达式验证了 key和 intValue 参数,并返回了字符串的正确版本。

    特性

    复数

    Swifternalization降低了使用 stringdicts 文件的必要性,比如跟随一个来支持本地化字符串中的复数。 你可以简单地定义包含这些情况的表达式。

    
    <plist version="1.0">
    
    
     <dict>
    
    
     <key>%d file(s) remaining</key>
    
    
     <dict>
    
    
     <key>NSStringLocalizedFormatKey</key>
    
    
     <string>%#@files@</string>
    
    
     <key>files</key>
    
    
     <dict>
    
    
     <key>NSStringFormatSpecTypeKey</key>
    
    
     <string>NSStringPluralRuleType</string>
    
    
     <key>NSStringFormatValueTypeKey</key>
    
    
     <string>d</string>
    
    
     <key>one</key>
    
    
     <string>%d file remaining</string>
    
    
     <key>other</key>
    
    
     <string>%d files remaining</string>
    
    
     </dict>
    
    
     </dict>
    
    
     </dict>
    
    
    </plist>
    
    
    
    

    不再需要 stringsdict 文件 !

    长度变化

    iOS 9提供了根据屏幕宽度选择正确的本地化字符串变化的新方法。 它使用 stringsdict的文件,带有NSStringVariableWidthRuleType密钥。

    Swifternalization降低了使用这种文件的必要性,不需要使用这个新的键来使用这个特性。

    使用英镑这个长度变化特性是因为 iOS 8.0有它自己的长度变化实现的框架。

    要使用长度变化功能,你的翻译文件应该具有如下条目:

    
    base.json
    
    
    ---------
    
    
    "forgot-password": {
    
    
    "@200":"Forgot Password? Help.",
    
    
    "@300":"Forgot Your Password? Use Help.",
    
    
    "@400":"Do not remember Your Password?" Use Help.""
    
    
    }
    
    
    
    

    @ 符号后的数字是一个字符串的最大宽度或者一个字符串符合的界限。 如果通过拟合宽度大于 200,小于或者等于 300,则将返回第二个字符串( 如果传递的拟合宽度为零)。

    要获取第二个本地化字符串,调用如下所示:

    
    I18n.localizedString("forgot-password", fittingWidth: 300)//201 - 300
    
    
    
    

    可以将表达式与长度变化混合。 下面的示例显示了它:

    
    base.json
    
    
    ---------
    
    
    "car": {
    
    
    "ie:x=1": {
    
    
     @100:"One car",
    
    
     @200:"You've got one car"
    
    
     },
    
    
    
    "more":"You've got few cars"
    
    
    }
    
    
    
    

    表达式

    表达式类型很少。 每个表达式类型都有自己的解析器和匹配器但是它们内部工作,因此不必担心它们。

    有 3种表达式类型:

    • 不等式 - 处理简单不等式,例如: x <,x x,x=5 x x =3 <,等。 使用整数和浮点数。
    • 不等式扩展 - - - extended不等式的扩展版本,带有这样的语法: 2 <x <10,4 <=x <6. 使用整数和浮点数。
    • 正规表达式 - 使用正则表达式。 这是最强大的;)

    不等表达式

    它由几个元素组成:

    • IE: - - 不等式的前缀- expression表达式
    • 你必须总是传递它,这意味着这里是一个数字,将匹配。 使用int和浮点数运算。
    • <,<=,=,> =,> - 使用一个不等式符号
    • 1,3,5,6,。 - MATCH的值是这里表达式中的最后一个

    例如:

    
    "cars": {
    
    
    "ie:x=1":"1 car",
    
    
    "ie:x=0":"no cars",
    
    
    "ie:x>1":"%d cars"
    
    
    }
    
    
    
    

    不等式扩展表达式

    这是不等式的扩展版本。 它由 2个值。一个值"标记"和两个不等式。

    • iex: - - extended不等式的前缀- - extended
    • x - 将匹配的编号位置。 使用int和浮点数运算。
    • 只接受 <和 <。

    Expample:

    
    "tomatos": {
    
    
    "iex:2<x<10":"%d tomatos is between 2 and 10"
    
    
    }
    
    
    
    

    正规表达式 表达式

    这是最强大的表达形式。 它需要正则表达式;)

    • :- - expression的前缀- - - - - - 表达式的前缀
    • 字符串 - 它接受带有正则表达式的字符串

    示例:( 波兰语语言的警车)

    
    "police-cars": {
    
    
    "exp:^1$":"1 samochód policyjny",
    
    
    "exp:(((?!1).[2-4]{1})$)|(^[2-4]$)":"%d samochody policyjne",
    
    
    "exp:(.*(?=1).[0-9]$)|(^[05-9]$)|(.*(?!1).[0156789])":"%d samochodów policyjnych"
    
    
    }
    
    
    
    

    强大的东西,不是>?

    PS中内置了波兰语语言解决方案,因此你可以将它的用于以下操作:

    
    "police-cars": {
    
    
    "one":"1 samochód policyjny",
    
    
    "few":"%d samochody policyjne",
    
    
    "many":"%d samochodów policyjnych"
    
    
    }
    
    
    
    

    这称为 "共享的表达式",并被覆盖。

    共享表达式

    共享表达式是所有本地化文件中可用的表达式。 它们在 expressions.json 文件中被声明为 by,你可以在本地化文件中使用它们。

    功能允许开发人员遵守干燥原则,并避免由于reapeating的代码在许多地方存在错误。

    通常情况下,声明如下表达式:

    
    ...
    
    
    "ie:x>1":"Localized String"
    
    
    ...
    
    
    
    

    如果要在多个文件中使用相同的表达式,则不必在其他位置重复表达式。 当你决定改进/更改表达式以处理另一种情况时,甚至会出现问题- 你必须在多个地方更改表达式。 因为有共享的表达式。 这些特性允许你在一个地方创建表达式,并在多个地方使用它的标识符,通常应该将这个表达式放在。

    你需要做的是创建具有以下结构的expressions.json 文件:

    
    {
    
    
    "base": {
    
    
    "one":"ie:x>1"
    
    
     },
    
    
    
    "pl": {
    
    
    //... other than"one" because"one" is available here too.
    
    
     }
    
    
    }
    
    
    
    

    现在,你必须使用下面的命令:pl.json en.json:

    
    ...
    
    
    "one":"Localized String"
    
    
    ...
    
    
    
    

    在决定创建自己的表达式之前,看看是否有相同的NAME,或者是否有这样的表达式。 也许你根本不需要这么做,只需使用它。

    内置表达式

    构建在表达式中的NAME 建议是构建在框架中的共享表达式,并可以用于零配置。 它们被国家分开,而不是所有国家都有自己的表达式。 现在,在表达式中构建了 比如 基,并构建了。 基本表达式在每个国家都可以用,有非常普遍的MATCH 所有国家的多维/基数编码逻辑。

    支持的内置共享表达式的列表:

    
    Base (English fits to this completely)
    
    
    - one - detects if number is equal 1
    
    
    -> one - detects if number is greater than 1
    
    
    - two - detects if number is equal 2
    
    
    - other - detects if number is not 1, so 0, 2, 3 and so on.
    
    
    
    Polish
    
    
    - few - matches (2-4), (22-24), (32-4),.. ., (..>22,..> 23,..> 24)
    
    
    - many - matches 0, (5-9), (10-21), (25-31),.. ., (..0,.. 1,.. 5-9)
    
    
    
    

    就像你看到的,波兰语没有"一个","> 一个",等等,因为它在默认情况下继承自 Base。

    正在启动

    本章介绍如何开始使用 Swifternalization,以及如何使用代码对它的进行完整化。

    文档

    文档涵盖了 100%个代码, 有两种类型的文档。 首先只覆盖那些只想使用框架而不需要内部查看的public API。 第二种方法涵盖所有的API - public,内部和 private。

    你可以在文档目录中找到 public API和完整的docset文档。

    它还托管在我的博客:

    Docsets:

    安装

    它适用于 iOS 8.0和更新版本。

    使用 CocoaPods:

    
    pod 'Swifternalization', '~> 1.3.1'
    
    
    
    

    如果你不使用 CocoaPods,只需将文件从 swifternalization/swifternalization 目录导入你的项目。

    Swifternalization还支持 Carthage。

    配置- 可选

    在获得第一个本地化字符串之前,必须通过传递给本地化的json文件的包来配置 Swifternalization。 如果不调用 configure(),它将在默认情况下使用 NSBundle.mainBundle()

    它将从bundle中获取用于配置它的语言。 因这里,如果不转换字符串,请确保在项目> 信息> 内部部分中添加了 for。

    
    I18n.configure(bundle)//if files are in another bundle
    
    
    
    

    使用共享表达式创建文件

    共享表达式必须放在 expressions.json 中。 文件的语法如下所示:

    
    {
    
    
    "base": {
    
    
    "ten":"ie:x=10",
    
    
    ">20":"ie:x>20",
    
    
    "custom-pl-few":"exp:(.*(?=1).[0-9]$)|(^[05-9]$)|(.*(?!1).[0156789])"
    
    
     },
    
    
    
    "pl": {
    
    
    "few":"exp:(((?!1).[2-4]{1})$)|(^[2-4]$)",
    
    
    "two":"ie:x=2",
    
    
    "three":"ie:x=3"
    
    
     }
    
    
    }
    
    
    
    

    在伪语言中:

    
    {
    
    
    "language-1": {
    
    
    "shared-expression-key-1":"expression-1",
    
    
    "shared-expression-key-2":"expression-2"
    
    
     },
    
    
    
    "language-2": {
    
    
    "shared-expression-key-1":"expression-1"
    
    
     }
    
    
    }
    
    
    
    

    文件中的表达式可以在可以本地化的文件中使用。 不同语言的所有共享表达式都放在同一文件中,因为每种语言的表达式都很少。 大多数情况下,表达式将在基中定义,因为如果表达式位于,则也可以在其他语言中使用。 因此,"十"在"pl"中可用,但"三"在"基"中不可用。

    创建每个国家的本地化文件

    可以本地化文件包含特定语言的翻译。 这些文件可能如下所示:

    
    {
    
    
    "welcome-key":"welcome",
    
    
    
    "cars": {
    
    
    "one":"one car",
    
    
    "ie:x>=2":"%d cars",
    
    
    "ie:x<=-2":"minus %d cars"
    
    
     }
    
    
    }
    
    
    
    

    文件的名称应与国家代码相同。 对于英语来说,它是 en.json,用于波兰语,用于 Polish,用于基础本地化,例如 base.json。

    你可以在这些文件中放置一些东西。 更复杂的文件如下所示:

    
    {
    
    
    "welcome":"welcome",
    
    
    
    "cars": {
    
    
    "one": {
    
    
    "@100":"one car",
    
    
    "@200":"You have one car",
    
    
    "@400":"You have got one car"
    
    
     },
    
    
    
    "other":"%d cars"
    
    
     }
    
    
    }
    
    
    
    

    在伪语言中:

    
    {
    
    
    "key":"value",
    
    
    
    "key": {
    
    
    "expression-1": {
    
    
    "length-variation-1":"value-1",
    
    
    "length-variation-2":"value-2",
    
    
    "length-variation-3":"value-3"
    
    
     },
    
    
    
    "expression-2":"value"
    
    
     }
    
    
    }
    
    
    
    

    正在获取本地化字符串

    Swifternalization允许你使用它的一个类方法,它公开了本地化应用程序所需的所有方法。

    这些方法有许多可选的paramters,如果需要,可以省略它们。 很少有常用参数:

    • key - 本地化字符串的键。
    • fittingWidth - 要放置本地化字符串的屏幕或者位置的宽度。 是整数。
    • defaultValue - 如果传递给方法的键没有本地化字符串,则返回一个值。 如果未指定这里选项,则返回 key
    • comment - 开发人员仅用于了解翻译上下文的注释。

    第一个方法称为 localizedString(_:fittingWidth:defaultValue:comment:) 允许你获取不带表达式的简单键的值。

    例如:

    
    I18n.localizedString("welcome")
    
    
    I18n.localizedString("welcome", fittingWidth: 200)
    
    
    I18n.localizedString("welcome", defaultValue:"Welcome", comment:"Displayed on app start")
    
    
    
    

    下一方法 localizedString(_:stringValue:fittingWidth:defaultValue:comment:) 用于获取 MATCH 表达式的字符串值的本地化字符串。 实际上,在大多数情况下,字符串值将包含数字,或者包含你希望匹配的其他字符串。

    
    I18n.localizedString("cars", stringValue:"5")
    
    
    //Other cases similar to 上面 example
    
    
    
    

    最后一个方法 localizedString(_:intValue:fittingWidth:defaultValue:comment:) 用于获取int值的本地化字符串。 这里方法调用上面的方法,只是将int值转换为字符串,因为所有框架都在字符串上操作。

    
    I18n.localizedString("cars", intValue: 5)
    
    
    
    

    捐赠

    Swifternalization是开源的,所以如果希望。 如果你想开发它只是 fork的repo,做你的工作并创建拉请求。 如果你有一些想法或者问题可以自由创建问题并为它的添加适当的标签。

    如果你添加了新功能,那么你必须编写单元测试来为贡献者提供指南。

    未来版本中需要做的事情

    • 为其他国家添加更多的表达式。
    • 在使用 正规表达式的表达式中添加对浮点数的支持。

    许可证

    Swifternalization是在MIT许可证下发布的。


    文件    framework  files  LOC  Swift  
    相关文章