iOS-International

原文链接

随着项目越来越成熟,逐渐拓展到海外市场,我们就需要适配多种国际化和地区、需要对自己的产品进行国际化,让更多的用户可以使用我们的APP,这就需要对我们的产品进行国际化了。在这里就介绍一下自己在国际化项目里面踩过的一些坑。

Project配置


  • 打开你的工程 , 在左侧栏选中project
  • 在打开的面板中选中project下的蓝色图标
  • 找到Localizations选项 , 添加你需要国家化的语言
  • 在主工程下command + N 新建Localizable.string文件
  • 选中你创建的string文件 , 打开右侧面板
  • 点击Localization组下的Localize按钮
  • 把你刚才配置在工程内的选项添加进去就好。

调用方式


在以前调用的地方我们需要替换为本地化调用方式
比如以前我们是这么调用的:

NSString *tips = @"wait";


现在要换成

NSString *tips = NSLocalizedString(@"wait", nil);

(ps 第二个是为了方便翻译人员理解上下文语境使用的 。)

然后在stirng文件内添加对应的字符串:

"wait" = "别着急";

你可以在不同的文件添加对应不同语言的翻译 。

让我们看下这个宏的定义 :

#define NSLocalizedString(key, comment) \
    [NSBundle.mainBundle localizedStringForKey:(key) value:@"" table:nil]
#define NSLocalizedStringFromTable(key, tbl, comment) \
    [NSBundle.mainBundle localizedStringForKey:(key) value:@"" table:(tbl)]
#define NSLocalizedStringFromTableInBundle(key, tbl, bundle, comment) \
    [bundle localizedStringForKey:(key) value:@"" table:(tbl)]
#define NSLocalizedStringWithDefaultValue(key, tbl, bundle, val, comment) \
    [bundle localizedStringForKey:(key) value:(val) table:(tbl)]


可以看到实际上就是从mainBundle中取出了指定的String文件 , 然后根据我们在代码中定义的 ‘key’ 值取出value

有的时候我们要指定我们的string文件名字而不使用上面的那个默认名字 。

NSString *tips = NSLocalizedStringFromTableInBundle(@"wait", @"TDFOSLocalizable", [NSBundle bundleForClass:[self class]], @"some tips to tell user wait");

这里面多出来两个参数,第一个是我们要指定的string文件名字,第二个就是要从哪个bundle中取,这个bundle的问题我们下面就会讲到。

使用脚本替换工程内部调用方式


那么在我们工程很大的情况下我们要把全部的字符串都替换为前缀为NSLocalizedString的形式人工手动替换肯定是不行的,又慢又不安全,没准复制粘贴的时候还把原来的key改错了,这里贴一段python的实例代码,可以稍加改动运行替换工程中的string前缀 。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import re
import sys
import datetime

folderPath = '/Users/felix/Documents/2dfire/TDFOpenShop/TDFOpenShop/Classes'
stringToReplace = 'NSLocalizedString'
stringReplaceTo = 'TDFOSLocalizedString'

def scan_files(rootdir):
    files = []
    for  parent, dirnames, filenames  in  os.walk(rootdir):
        for  filename  in  filenames:
            if len(filename.split('.',1))>1:
                if filename.split('.',1)[1] == 'm':
                    files.append(os.path.join(parent, filename))
    return files

def replaceStringIn(file):
    code = open(file,'r+')
    text = code.read()
    code.seek(0,0)
    code.write(text.replace(stringToReplace,stringReplaceTo))
    code.close()


def main():
    files = scan_files(folderPath)
    for filePath in files:
        replaceStringIn(filePath)

if __name__ == '__main__':
    main()

这里面我是把以前的NS开头的宏替换为自定义的宏 , 大同小异 , 可以参照这个修改下即可 。

编译运行测试


当我们全部修改好以后肯定是要测试下显示对不对的、有两种方法可以快速切换App语言

  • 打开模拟器或真机 general -> setting -> lang ,不过这样比较繁琐。
  • 点击导航栏上的模拟器图标左边的schema选项,选择editSchema -> Run -> Options ->Application Language 直接改为你需要验证的语言运行就可以啦 。

如何在模块内单独配置国际化文件


很多时候我们的工程体量大到一定程度的时候都会模块化掉,几个人或者一个人负责一个模块,而有的模块是要作为SDK提供外部interface使用的 。当你把SDK提供出去的时候,我们期望的效果是在其他人(其他工程)内部运行的、我们的SDK也能够国际化显示 。但是在我们整个工程的string文件包含几千上万条的时候显然不需要全部移动到模块内 。

所以在这里面我们要做的就是把需要的使用到的字符串和翻译好的value从主工程迁移到模块内部 。

  • 解决方案:使用cocoapods集成的模块化内部进行国际化

我们先把主工程的国际化文件的文件夹复制到我们的模块路径下面,在模块内部有一个配置文件 x.podspec 里面添加这样一段配置

s.resources  = 'xxx/*.{xib,jpg,png,xcassets}','xxx/*.lproj'

主要注意后面 , 这里就把我们刚复制来的国际化问价加入了模块的资源中 ,这时 ,如果我们不想用跟主工程一样的名字 ,Localizable.strings ,可以把这个名字也给改掉 , 比如 abc.strings

  • 调用

这里为了有别于主工程的国际化 , 我们把strings文件改名为 abc.strings 然后在模块内新建一个头文件

#ifndef TDFOSLocalizeMacro_h
#define TDFOSLocalizeMacro_h

#define TDFOSLocalizedString(key, comment) \
NSLocalizedStringFromTableInBundle(key, @"abc", [NSBundle bundleForClass:[self class]], comment)

#endif /* TDFOSLocalizeMacro_h */

这里可以使用上面的脚本再次替换字符串前缀,然后运行下看看是否替换成功。
这里注意要重新pod install下,否则cocoapods不会帮我们把资源引入包内 。
ps: 别忘了删掉主工程中移除来的字符串 !!!

总结

基本用法暂时介绍到这里 , 关于模块化和国际化的东西要多了解一下NSbundle这个类 。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,094评论 1 32
  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom阅读 2,695评论 0 3
  • 最近一朋友正准备跳槽,就从各处搜索整理一些基础,便于朋友复习,也便于自己复习查看. 1. 回答person的ret...
    smile丽语阅读 1,738评论 0 7
  • 一 日更20天,我也变成了一个日更达人了。 这段时间,因为生活上的变故,加上看到简书上的一些写作变现的文章,我心动...
    空白方阅读 2,474评论 25 58
  • 生活本身就充满各种变化而跳动的思维跟让其充满惊喜一成不变的轨迹多么的无趣享受变化带来的种种可能就好像童年的酒心巧克...
    哈哈同学阅读 255评论 0 0