NSLocalizedString 多语言本地化

1,494 阅读4分钟
NSLocalizedString 多语言本地化

swift 发布于 2017年08月01日
iOS 中处理多语言

NSLocalizedString 是 iOS 中处理多语言显示的标准方法,相信大家都已经不陌生,无论你开发的 APP 是否真的需要多语言,使用 NSLocalizedString 而不是直接把字符串写到代码里面都是一个相对好一些的实践。

NSLocalizedString 最基本的用法如下:

NSLocalizedString("title", comment: "")  //输出内容 "主页"

要正常使用 NSLocalizedString,还需要一个 Localizable.strings 文件。 这个文件中存放的就是字符串键值对:

"title"="主页";

title 对应我们上面的调用的第一个参数。 在运行时 NSLocalizedString 会在这个文件中查找和一个参数匹配的键值,然后读出真正要显示的字符串。

这就是 NSLocalizedString 的基本运作流程了,先准备一个 Localizable.strings 文件,然后调用 NSLocalizedString 方法读取里面的内容,基本内容就说这么多,下面再一起再和大家说说怎么能把它用的更好一些。

键命名建议

随着项目逐渐变大, Localizable.strings 中的字符串键值一定会越来越多。 这就涉及到每个键的命名,如果随意命名,就难免造成混乱,比如:

"home"="主页";
"myhome"="我的主页";
"rate"="给个评价";
"newshome"="新闻主页";
"loadnews"="加载新闻";
//...

一个相对好一些的名称组织方式是使用命名空间:

"main.home"="主页";
"my.home"="我的主页";
"my.rate"="给个评价";
"news.home"="新闻主页";
"news.load"="加载新闻";

这里的命名空间不会有编译层面的检测,只是我们在逻辑上的组织,通过对名称简单的合理组织,对项目的可维护性会有很大的提高。

几个附加参数

NSLocalizedString 除了我们开始介绍的传入键名和注释的这个调用方式外:

NSLocalizedString("title", comment: "")

还提供了传入更多参数的版本:

NSLocalizedString(_ key: String, tableName: String?, bundle: Bundle, value: String, comment: String)

可以指定 tableName 参数,用来确定 .strings 的文件名。 默认情况下,系统会从 Main Bundle 中加载名称为 Localizable.strings 的文件。 如果这样调用:

NSLocalizedString("test", tableName: "back.strings", bundle: Bundle.main, value: "", comment: "")

就会在 back.strings 文件中查询,而不是默认的 Localizable.strings 了。

那么 tableName 这个参数有什么实际用处呢? 如果项目规模开始变得比较大,就可以把不同模块的字符串资源分开存放,然后通过 tableName 参数分别加载。

另外除了 tableName 之外,NSLocalizedString 还可以指定 bundle

if let bundleURL = Bundle.main.url(forResource: "external", withExtension: "bundle") {

        if let extBundle = Bundle(url: bundleURL) {

                let str = NSLocalizedString("test", tableName: "table", bundle: extBundle, value: "", comment: "")
                print(str)

        }

}

上面这段代码,首先加载 external.bundle, 然后从这个 bundle 里面的 table.strings 文件中查找对应的字符串键值。

这样,除了用文件把字符串分开,还可以把这些文件分散在不同的 Bundle 中。又多了一个维度,对于依赖模块非常多的大项目中,这个机制还是比较有用的。比如不同模块的团队都用同一个键值命名字符串,通过文件和 Bundle 的分离,就可以避免重名冲突。

合适的注释

还记得我们最开始例子中的 comment 参数吧,用作对这个键值的注释,大多数键值名称其实已经基本表示清除含义了,比如:

"news.home"="新闻主页";
"news.load"="加载新闻";

对于这些键值,是否写注释都不妨碍理解。 注释更适合的场景是格式化输出,比如这样:

"%i views"="%i views";

上面这个字符串资源本身又是一个格式化输出模板, 那么我们就可以这样调用:

let format = NSLocalizedString("%i views", comment: "{总浏览量} views")
print(String(format: format, 20))

这里 comment 给每个格式化参数的含义做了注释,这样其他人就能更快的看懂这段代码的含义。

结束

这次介绍了 NSLocalizedString 的基本用法,以及它的几个重载参数的应用场景。这几个重载方法对于规模稍大的项目,以及模块化思路都有很好的帮助。还给大家分享了关于注释和键值命名的一些建议。

当然,这一切都不是必须的, 即使你用硬编码的方法把字符串直接写在代码里也不一定就不行。但好的设计思路肯定会让你的开发效率越来越高。同时还推荐给大家一篇 objc.io 的文章,里面有对本地化更详细的介绍 www.objc.io/issues/9-st…


如果你觉得这篇文章有帮助,还可以关注微信公众号 swift-cafe,会有更多我的原创内容分享给你~

本站文章均为原创内容,如需转载请注明出处,谢谢。