在iOS本地化文件中实现继承





问候,亲爱的黑客们!



今天,我想分享一个有趣的经验来解决本地化问题。在iOS中,从一个目标或多个目标的角度来看,本地化的安排非常方便,其中localizable.strings中的键不是很重复。但是,当您有十二个目标时,一切都会变得更加复杂,其中重复了一半以上的键,但同时又具有不同的含义,并且还有一组特定目标唯一的键。



对于尚未遇到此问题的人,我将通过示例更详细地解释该问题。



比方说,我们有一个大的项目,其中90%的通用代码和3个目标MyApp1MyApp2MyApp3,其中有一些特定的屏幕,以及每个人都有自己的名字和文本。本质上,目标是独立的应用程序。他们每个人都必须翻译成10种语言。但是,我们不想添加诸如app1_localizable_key1app2_localizable_key1等的本地化密钥。我们希望代码中的所有内容都美观并在一处本地化



NSLocalizedString(@"localizable_key1", nil)


没有任何ififdef,因此在添加新目标时,我们不必在大型项目的整个代码中都使用NSLocalizedString查找位置,并在那里注册新键。我们还希望将某些键绑定到特定的目标屏幕,即 有键app2_screen1_keyapp3_screen2_key



现在,您可以使用标准Xcode工具执行以下操作:



  • 将公共部分localizable.strings复制到每个目标,我们将获得这些文件的3个副本。
  • 将特定于目标的键添加到相应的localizable.strings中。


我们遇到什么问题:



  • 向项目添加新的公钥非常昂贵。席位数量等于目标数量乘以语言数量。在我们的示例中,这是30个地方。
  • 当我们在1-2个我们正在积极努力的当前目标上增加一行时,可能会出错,一年后,他们决定恢复一个或多个目标。您将必须彼此手动同步本地化,或为此编写脚本。并且,如果在添加或合并分支时显示出一些草率,并且通用键与特定键混合在一起,那么将是一个真正的任务。
  • 本地化文件的数量。它们都在不断增长,这使得与它们合作变得困难,并增加了合并分支机构时发生冲突的机会。


我想要的是:



  • 这样所有公钥都存储在单独的文件中。
  • 对于每个目标,都有一个仅存储特定于其的键的文件,以及具有该目标值的通用键。


对于我们的示例,有一个带有字符串的公用文件localizable.strings



"shared_localizable_key1" = "MyApp title"
"shared_localizable_key2" = "MyApp description"
"shared_localizable_key3" = "Shared text1"
"shared_localizable_key4" = "Shared text2"


我想要一个带有按键localizable_app2.strings文件



"shared_localizable_key1" = "MyApp2 another title"
"shared_localizable_key2" = "MyApp2 another description"
"app2_screen1_key" = "Profile screen title"


那些。在本地化文件中组织继承原则



不幸的是,Xcode并不是为此而量身定制的,所以我不得不重新发明自己的“自行车”,由于Xcode到处都是辐条,所以它不想走很长时间。



我们有一个包含18个目标和12种语言的项目。这不是开玩笑,该项目确实很大,在那里需要许多目标。每次我们需要添加新的公钥进行翻译时,我们都会处理216个本地化文件。这需要很多时间。并且添加新目标会导致以下事实:您需要将12个更多localizable.strings复制到其中。总的来说,在某个时候,我们意识到再也不能过这样的生活了,我们不得不寻找解决方案。



我将不再谈论我设法在该过程中测试的所有方法,我将直接讨论可行的解决方案。



因此,首先我们需要找到所有共享密钥。这可以使用脚本来完成,我将不赘述,这是一个相当琐碎的任务。



此外,当我们收到一个通用的(基本)本地化文件,或者说是12个物理文件,以及每个目标的一组文件时,请转到Xcode,在此添加所有文件。同时,我们不会将文件附加到任何目标,即应该取消选中“目标成员身份”下的右窗格。







我们将仅在文件上放置这些标记,这是脚本用于组装文件的结果。



然后,相同的“自行车”开始:



  • Localization, build_localization.py.
  • Localizable. localizable.strings.
  • Localizable .






我们只需要它即可正确添加到项目中文件的链接,以便Xcode可以正确识别它们。否则,它将不会使用它们来查找密钥。例如,如果您创建一个具有正确的localizable.strings文件Localizable文件夹,并将其作为文件夹引用添加到项目中,那么无论Xcode为何,都不会理解我们为它提供了本地化密钥。因此,请选择Localizable文件夹,将其作为一个组拖动(创建组),然后取消选中复制项目(如果需要)复选框,以使其如下图所示。 删除可本地化的文件夹







并将其添加到gita的例外中。因为我们不需要gita中脚本的结果,所以它将针对每个目标更改并阻塞提交。



现在我们需要将脚本添加到构建阶段。为此,在“构建阶段”中,单击“新建运行脚本阶段”,然后使用参数编写我们的脚本。 




python3 ${SRCROOT}/Localization/build_localization.py -b “${SRCROOT}/BaseLocalization" -s "${SRCROOT}/Target1Localization" -d "${SRCROOT}/Localization/Localizable"


b是具有基本本地化的文件夹,s是当前目标的本地化,d是结果文件夹。



向上移动新阶段,它必须不低于“复制捆绑资源”阶段。那些。首先,脚本会生成文件,然后才将它们放入捆绑包中。







现在,重要的是要告诉Xcode,在脚本执行过程中会更改文件,否则在构建期间会抛出错误,即找不到文件。而且,错误只会出现在干净的装配上,而不会立即清除问题所在。在构建阶段,将所有本地化文件添加到输出文件







这需要针对每个目标进行。最简单的方法是使用文本编辑器打开项目,因为Xcode将无法在目标之间复制/粘贴阶段。因此,每个目标的脚本参数-s将不同。



现在,对于每次构建,脚本都将获取基本的本地化文件,将目标文件中的更改(添加,覆盖密钥)翻转并在Localizable文件夹中生成本地化,iOS将使用该文件夹来查找密钥。



总的来说,实现继承机制时我们计划了什么:



  • 共享密钥驻留在一个文件中,不会与其他文件干扰。输入新密钥的时间减少了18!时间。
  • 与特定目标有关的密钥在相应的文件中。
  • 文件大小已大大减少。我们摆脱了重复行的混乱。
  • 向项目添加新语言的过程也大大简化了。
  • 创建新目标时,无需复制带有许多不必要行的本地化内容。创建一个名为localizable.strings的新文件,并仅添加该目标所需的文件
  • 如果您决定恢复旧的目标,则根本不需要对行进行任何操作,所有内容都将从基本文件中提取。
  • 该脚本不会乱扔git,工作结果仍保留在本地,可以轻松删除。


→可以在此处使用完成的脚本



认为是一个完美的脚本,欢迎请求请求。



All Articles