用Go语言快速搭建CMS和电子商务的库,多语言化之

作者:澳门新葡京平台游戏

本文首发在我的个人博客:

参考资料

Internationalization and Localization Guide

Go语言,兼具语法简单、高并发、高性能的特点,在网络编程领域受到欢迎。
(Go语言的介绍很多,就不再赘述,还不了解Go语言的的朋友可以访问官方网站golang.org 了解详细信息 , 记得先翻墙哦)

国际化开发的两种情况

  1. 在对 iOS APP 开发时,不可避免需要对 APP 进行多语言化,特别是做 ODM 的开发,更需要实现 APP 国际化。
  2. 当订单不断的来时,意味着需要不断地适配多语言化;此时就需要先把工程代码里面已有的 Localizable.strings 导出到 xls 文档,然后再给相应的翻译部门或者外包翻译公司进行翻译。遗憾的是 Xcode 没有提供便捷地把 Localizable.strings 导出到 xlscsv 的功能(或者有而我并没有发现。)最后,这一简单而又非常繁琐的工作就落在了 Comm CComm V 身上了;如果是一百几十个还好,但如果是成千上万的,那是得多大的工作量啊,宝贵的时间就这样白白浪费了,而且还不能保证复制、粘贴过程中不会出错。
  3. 接了几次多语言化适配的我,已经疲惫不堪,下定决心做个简单的解释器出来,来缓解工作量,同时节省时间成本。于是乎,SYStringsParser 就诞生了,欢迎大家下载体验。

简介

国际化(internationalisation,i18n):一个程序或软件可给特定的人群使用而无须修改或重新编译源代码。对于 iOS 来说就是,使App能够适用于不同的语言,地区,文化的过程。

本地化 (localisation,l10n):一个程序或软件在支持国际化的基础上,给定程序特定区域的语言信息使其在信息的输入输出等处理上适应特定区域人群的使用。对于 iOS 来说就是,将App的内容翻译为多种语言的过程。

总的来说,国际化是开发者的任务,是一个一般化的过程;而本地化则是翻译者所做的事情,是一个具体的过程。国际化的运作为本地化工作提供了可能。一个软件的国际化实现需要本地化的支持。

现在已经有许多大家熟知的开源项目使用Go语言开发,例如

1.在App开发之初,就已经有了国际化开发的打算,这种情况下进行国际化是很容易的,只要在开发过程中把需要国际化的字符串进行简单的处理即可。

图片 1strings 文件解析演示图片 2CSV 文件解析演示

用户设置对于国际化的影响

在 iOS 设置应用中的通用->语言与地区中可以分别设置语言,地区和日历。一个支持国际化的应用会根据语言的设置选择相应的本地化包,语言的改变会导致系统重新启动,以便所有应用重新应用新的语言设置。地区主要影响日期,时间,数字,货币等数据的格式。用户可以通过日历选择不同的历法。地区和日历的设置都是即时的,不需要重新启动系统。另外,在语言与地区中还可以设置首选语言顺序列表,应用会以此为依据选择本地化语言包(按顺序找第一个应用支持的本地化语言包)。

  • Docker,不用多说。
  • Lantern,一个翻墙软件
  • Beego和Revel,Go语言写的Web框架
  • InfluxDB,一个开源分布式的时序、事件和指标数据库
  • Gogs,搭建自己的Git服务
    (以上项目都可以在Github上找到)

2.已经开发完毕,开发之初并没有进行国际化适配,突然来需求说需要进行国际化,此时面对项目中成百上千的字符串,内心一定是崩溃的。

  1. 便捷地把多个 Localizable.strings 文件合并转为一个 csv文件。

    图片 3strings 文件解析

  2. 同时支持把 csv 转化为多个 Localizable.strings 文件。

    图片 4csv 文件解析1

使应用支持国际化

作为一个长年参与项目工作的程序员,在使用每一种语言工作的过程中都会寻找一些能让重复工作变简单的东西(也可以说就是懒),对于Go语言也不例外。

接下来,我会主要介绍第二种情况,第一种情况随便都可以搜的到

图片 5CSV 文件解析2

使用Base Internationalization国际化界面文本

从Xcode5之后,工程默认支持Base Internationalization。
Base Internationalization将界面文本与.storyboard和.xib文件分离,使得项目只需要一套.storyboard和.xib文件。在.storyboard和.xib文件中使用你设置的开发语言填写界面文本,这套.storyboard和.xib文件就叫做Base Internationalization。之后在本地化时,将以开发语言为资源翻译成多种语言,这些语言以.strings格式的文本文件对应相应的.storyboard和.xib文件。

一般情况下,每种语言相对应的文件会放在相应的语言包下,比如en.lproj、zh.lproj等。但是所有的.storyboard和.xib文件会放在一个名为Base.lproj的文件夹内,这就是为了共用同一套.storyboard和.xib文件,这样,在其他语言包内就可以只存放相应的.strings格式的文本文件了。由于.storyboard和.xib文件中已经使用开发语言填写了界面文本,所以在开发语言的语言包内就不需要再有相对应的.strings文件了。
关于开发语言的设置:

  1. 在项目的.xcodeproj文件中打开project.pbxproj
  2. 搜索developmentRegion,并将该key的值改为所要设置的开发语言对应的语言ID,比如en、zh等
  3. 保存,效果如下图所示
![](https://upload-images.jianshu.io/upload_images/669609-0c93dab4f79fd5ae.png)

不像PHP、Python可以找到很多CMS项目可以快速的搭建网站,Go语言毕竟还太年轻,虽然有几个很好用的Web框架,但开源的CMS还很少,QOR就是其中之一。

情景一:刚开始适配国际化
刚接到适配国际化适配需求时,普通的程序员内心是崩溃的,并且会不断地跟上司说"雅蠛蝶,这个要花好多时间的~~".当你看到这里的时候,其实你的时间已经减少了80%了.
然后,重点来了。Command Shift F,进入全局搜索引擎,切换为Replace模式,并把匹配模式改为Regular Expression。

  1. 同时支持去重,保证对同一 key 的翻译唯一性。图片 6去重
使用Auto Layout辅助国际化界面文本

因为所支持的语言所占界面空间不同,Auto Layout可以使一套界面适配布局不同的文字。使用时注意:

  1. 显示文字的组件不使用固定宽度的约束,否则在某些语言下文字可能显示不完全,text fields和labels默认的行为都是自动适配到内容的合适的尺寸,完全可以使用这种方式。
  2. 添加水平间距约束时,使用leading和trailing,这样针对左右顺序不同的语言可互换左右间距值。
  3. 因为语言不同视图组件所占空间不同,所以约束应于相邻视图组件建立,这样当语言改变时,其他视图组件也会自动适配。

QOR,官方(getqor.com)的定义是:QOR是首个使用�Go语言开发的电商系统、CMS的SDK。它是一组用Go编写的库,用于抽象业务应用程序,内容管理系统(CMS)和电子商务系统(EC)所需的通用功能。

第一步:在搜索条件里输入(@"["]*[\u4E00-\u9FA5] ["n]*?"),在下面替换内容里输入NSLocalizedString($1, nil)。此处正则表达式两边加括号的目的是为了能够在替换时用$1获取原有字符串的值,在替换时把原有值放入宏定义内key的位置。然后,搜索,可以看到搜索结果,点击Replace All,即可完成替换。

国际化代码中的文本

在项目中,一些在界面上显示的文本是需要在代码中提供的(比如错误信息提示),而对这部分文本国际化的方式是将文本写入.strings文件中,之后使用宏NSLocalizedString去从文件中获取。在.strings文件中键值对的格式为

"key1" = "value1";
"key2" = "value2";

使用NSLocalizedString去取值的方式为

NSLocalizedString("key1", "comment");
NSLocalizedStringFromTable("key1", "tableName", "comment");

其中标准的NSLocalizedString函数会从main bundle中的Localizable.strings文件中找到相应键的值,而comment是对该键值对的解释。同理NSLocalizedStringFromTable函数的第二个参数可以指定其他.strings文件的文件名。

根据本人的使用体验,QOR可以看作是PHP中的ThinkPHP,Python中的Django。

然后!!!!!因为这里是会把整个项目的中文字符(类似于@"哈哈"这种),全部替换,如果之前项目图片素材使用中文名的话(虽然规范来说是不能中文名的,但是难免会有人用),那么你会发现imageview.image这里就会有问题了,大概类似于:self.imageView.image = [UIImage imageNamed:NSLocalizedString(@"正方形",nil)]; 这样的话最后一步导出语言文件时会把图片的加载也会导出,如果错手翻译了的话,那么debug之后,就会发现有不少地方素材丢失,那么就要进行第二步了.

国际化数据格式

不同的国家和地区有着不同的日期,时间,货币,数值等的格式,所以要在代码中根据用户设置的地区来正确的格式化这些数据。
格式化时用到NSLocale类,NSLocale类封装了某一个地区的相应的格式化信息,如果要获得用户当前设置地区的NSLocale实例可以使用[NSLocale currentLocale]或者[NSLocale autoupdatingCurrentLocale],两者的区别是,后一个类方法返回的值会根据用户设置的改变而改变,而前者不会。可以通过NSLocal查看很多这一地区的数据格式化信息,例如(其他key值请查阅相关文档):

NSNumber *metricSystem = [[NSLocale currentLocale] objectForKey:NSLocaleUsesMetricSystem];
NSString *currencySymbol = [[NSLocale currentLocale] objectForKey:NSLocaleCurrencySymbol];
// 用当前地区的语言显示语言ID
NSLocale *zhHansLocal = [NSLocale localeWithLocaleIdentifier:@"zh-Hans"];
NSString *currentLocalZH = [zhHansLocal displayNameForKey:NSLocaleIdentifier value:@"zh-Hant-TW"];
NSString *currentLocalEN = [zhHansLocal displayNameForKey:NSLocaleIdentifier value:@"en-US"];
// 获取该地区所使用的引号
NSString *bQuote = [locale objectForKey:NSLocaleQuotationBeginDelimiterKey];
NSString *eQuote = [locale objectForKey:NSLocaleQuotationEndDelimiterKey];
// 国际化大小写转换
NSString *localizedUppercaseString = [string uppercaseStringWithLocale:[NSLocale currentLocale]];
NSString *localizedlowercaseString = [string lowercaseStringWithLocale:[NSLocale currentLocale]];
NSString *localizedCapitalizedString = [string capitalizedStringWithLocale:[NSLocale currentLocale]];

当使用[NSString stringWithFormat]去拼装字符串时,如果传入的参数带有数值,日期等需要格式化的内容,最好使用以下方式(更好的方式是使用formatter进行转换):

// 使[NSLocale systemLocale]
NSString *localizedString = [NSString localizedStringWithFormat:@"%3.2f", myNumber];
NSString *localizedString = [[NSString alloc] initWithFormat:@"%@" locale:[NSLocale localeWithLocaleIdentifier:@"zh"], [NSDate date]];

使用formatter格式化日期和时间时的国际化

// 使用预设的格式
NSString *localizedDateTime = [NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterShortStyle];
// 使用自定义的格式
NSDateFormatter *dateFormatter = [NSDateFormatter new];
NSString *localeFormatString = [NSDateFormatter dateFormatFromTemplate:@"dMMM" options:0 locale:dateFormatter.locale];
dateFormatter.dateFormat = localeFormatString;
NSString *localizedString = [dateFormatter stringFromDate:[NSDate date]];

对于数值型数据的格式化主要包括小数、千位分割、货币、百分比。同样也需要支持国际化。

NSString *localizedString = [NSNumberFormatter localizedStringFromNumber:myNumber numberStyle:NSNumberFormatterDecimalStyle];

同理对于NSCalendar的使用也受NSLocale的影响。
地区和时区的设置发生变化的通知分别是NSCurrentLocaleDidChangeNotificationNSSystemTimeZoneDidChangeNotification

图片 7

第二步:在搜索条件里输入imageNamed:NSLocalizedString(, nil[)],在下面替换内容里输入imageNamed:$1。替换之后,你会发现原本的self.imageView.image = [UIImage imageNamed:NSLocalizedString(@"正方形",nil)]; 都会变为 self.imageView.image = [UIImage imageNamed:@"正方形"]; 这样在最后一步导出语言文件时就不会把图片加载的文件名也一并导出了.

国际化支持相反的语言方向

有一些语言,比如阿拉伯语等,方向是从右向左的。使用
Base Internationalization和Auto Layout在大部分情况下可以很好的支持这些语言,一些不支持的情况,可以在代码中进行如下判断:

if ([UIView userInterfaceLayoutDirectionForSemanticContentAttribute:view.semanticContentAttribute] == UIUserInterfaceLayoutDirectionRightToLeft) {
    …
}

Paste_Image.png

情景二:已经适配到一半了,才看到这篇文章
如果是这种情况的话,那么用第一步的操作,以前适配好的代码里面就会出现NSLocalizedString(NSLocalizedString(@"正方形"),nil)这种情况了,那么这个时候就需要执行第三步了

本地化应用

当我们使应用支持国际化后,就可以配合翻译人员完成应用本地化的工作了。大致的过程是,通过 Xcode 将开发语言的文本资源导出为 XLIFF (XML Localisation Interchange File Format) 文件,翻译人员在完成该文件内的相应翻译内容后,再通过 Xcode 将文件导入,这时所翻译的语言资源就会被加入到工程中了。

QOR能做什么?

首先,QOR还不算是CMS,它比起Web框架来说进行了更进一步的封装,将Web开发中常用的部分封装成用起来更简单的库。用它来创建一个基于内容管理的Web应用更加快速简单。

第三步:在搜索条件里面输入NSLocalizedString[(]NSLocalizedString(, nil[)],在下面替换内容里输入NSLocalizedString($1。替换之后你会发现原本的NSLocalizedString(NSLocalizedString(@"正方形"),nil) 都会变为NSLocalizedString(@"正方形",nil) 到了这里,如果还出现其他问题,相信有认真瞄一眼正则表达式的小伙伴都会知道规律在哪了.

导出 XLIFF
  1. 在 Xcode 中选中工程或 target。
  2. 选择 Editor > Export For Localization。

之后 Xcode 会将 .xliff 文件导出到你指定的目录中。如果你在工程的 Localizations 设置项中还没有添加过其他的语言,而只有开发语言(如 English)一种,那么导出的文件为 en.xliff。这时的 en.xliff 文件中并没有指明要翻译的目标语言,而这会导致在翻译完成后文件无法正常导入,需要在文件源码中添加target-language=""字段。更好的做法是,在创建工程时就把要从开发语言翻译的其他语言(如 Chinese)添加到 Localizations 中,这样导出的文件就为 zh.xliff,且其中已标明目标语言,可以正常的导入。另一个要注意的地方是,.strings文件支持国际化时,开始的开发语言版本不要放到Base.lproj文件夹中,Base.lproj文件夹中存放的全部是界面文件,而是应直接放入对应的开发语言的.lproj文件中。

命令行方式:

xcodebuild -exportLocalizations -localizationPath <dirpath> -project <projectname> [[-exportLanguage <targetlanguage>]]

在等待翻译资源的时候,你并不希望界面或者仅仅是界面中的文本再发生变化,这个时候可以使用 Xcode 的一项特性 Locking Views。可以只针对某一 view 修改,在该 view 的 Identity inspector 中修改 Lock 项。也可设置整个 nib 文件的该属性,选中对应 nib 文件后,修改 Editor > Localization Locking 菜单项。

QOR目前可用的有9个部分(另外有3个部分官方标记为Coming Soon,就不做介绍了):

Admin
快速为您的�应用程序生成一个漂亮、可跨平台运行、可配置的管理后台。用过Django的朋友很容易理解,它会生成一个管理ORM的Web界面,搭配Role和Transition可以将它自定义成灵活的管理后台。默认主题是基于谷歌Materials Design的设计理念;可同时兼容PC和移动设备。通常情况下,QOR的其他所有部分都是围绕Admin工作的。

Publish
分别设置预演和正式服务器,使用Publish,内容管理员就能在正式发布之前预览所更新的内容。支持在预演环境下预览,支持管理员对需要发布到正式服务器的类目进行选择。Publish可以配置成指定哪些数据类型需要先经预演服务器,再发布到正式服务器上,哪些数据允许预览或直接发布。结合Role和Transition,系统就能灵活完成内容修改和发布工作。

Transition
用Transition来体现业务流程和执行业务规则。定义状态、定义事件、定义状态变化的验证条件。

Media Library
支持上传文件至云端或其他位置;支持图像裁剪和调整尺寸。Media Library支持上传和动态调整图片尺寸,且有选项支持将其保存为多种尺寸和分辨率,以适配多种平台。Media Library可以配置成文件保存在文件系统或云存储系统,结合Worker,就能高效管理批量图像的导入和处理。

Worker
运行批处理进程,进行批量数据处理或其他耗时的计算。
Worker本质上是长进程的调度程序。Worker提供了一个界面,用于查看一个长进程的进展,中断不完整的长进程,以及查看所有长进程的运行日志。

Exchange
应用程序支持数据以CSV或者Excel文件导入和导出,是一个数据文件的出口和入口。目前支持的导入和导出文件格式包括CSV和Excel 电子表格。

Internationalization(i18n)
多语言应用程序的翻译工具。

Localization(l10n)
在多语言环境中智能管理你的业务对象。Localization用于管理多语言环境下的数据对象。请注意,这和简单的文字翻译(Internationalization包含了这个功能)是不一样的。

Roles
给不同的人分配不同角色,不同角色对应不同的权限,灵活实现细粒度的权限控制。Roles 提供了一个健壮、可配置的架构,从而保证角色和权限的粒度控制。Roles还能对特定数据字段进行访问控制。使用Roles就能使某些功能为特定的用户/用户类型生效;结合Transition,就能让您的应用程序完美体现组织的工作流程。

最后一步了.我们需要先新建所需语言的文件夹。
cd 工程目录
mkdir en.lproj
mkdir zh-Hans.lproj

导入 XLIFF
  1. 在 Xcode 中选中工程或 target。
  2. 选择 Editor > Import Localizations。

Xcode 会从 XLIFF 文件中解析出翻译内容的 .strings 文件,然后放到对应语言的 .lproj 目录中,而在工程中,nib 文件和 .strings 文件都以组的形式管理。

命令行方式:

xcodebuild -importLocalizations -localizationPath <filepath> -project <projectname>

QOR应用程序结构

图片 8

Paste_Image.png

QOR的核心是上图中的Engine,它负责管理数据访问和数据处理的接口。

QOR通过插件方式扩展Engine,例如使用worker exchange实现数据导入/导出,或使用media_library实现文件上传。

对于数据库的管理,QOR默认使用GORM,当然也可以用其他ORM库替换默认的GORM。

QOR将前端完全交给开发人员,没有对前端进行任何管理,让开发人员可以自由灵活的开发前端部分。

然后,遍历所有.m文件,根据每个文件内的需要国际化的字符串生成key和value。
find . -name *.m | xargs genstrings -o en.lproj
find . -name *.m | xargs genstrings -o zh-Hans.lproj

其他资源

除了文本资源外,其他的资源文件,比如图片、音视频文件等可能也需要针对不同地区使用不同内容。

图片 9

在国际化资源文件后,就可以将本地化版本的文件加到对应的 .lproj 目录中。

结束

QOR虽然目前Github上Star不到2000,Fork也只是接近300,但QOR的模式是挺不错的,希望能够被广泛的认可和使用。

欢迎大家简书或我的个人博客与我交流

此时,en.lproj和zh-Hans.lproj文件夹中就应该有了相应的Localizable.string文件了。

最佳实践

对于大部分的国内开发者来说,其应用主要针对使用中文的用户,而鉴于翻译资源的有限,可能针对其他地区用户仅能支持国际通用的英文。在这种情况下,最合适的流程是,在开发过程中,开发者使用中文填写界面文本,而之后由翻译人员翻译为英文,最后使应用在所有不匹配中文地区的设备上,都能使用英文资源。

要达到上述效果,首先要设置工程的开发语言为中文,如上文所述,修改工程文件中的字段 developmentRegion 为 zh,同时确保需要翻译的英文已添加在列表中。在完成国际化的工作后,就可导出 en.xliff 文件交由翻译人员翻译,并最终导入。最后一步,是要确认 Info.plist 文件中的 CFBundleDevelopmentRegion 字段设置为 en,该字段决定在用户当前地区未匹配到翻译资源时,使用应用已有的哪一套翻译资源作为界面文本显示。

需要注意的一点是,尽管文档中提到:

You can choose from more than 100 different languages and dialects designated by regions to localize your app. However, the more general you make your localized resources, the more regions you can support with a single set of resources. This can save a lot of space in your app bundle and help reduce localization costs. For example, if you don’t need to distinguish between different regions that use the English language, you can add English to support users in the United States, United Kingdom, and Australia. Even if you provide region-specific resources always provide a complete set of language-specific resources for all the languages you support.

但当用户设备的语言设置为繁体中文时,并不会匹配到中文(zh)的语言资源,所以在上述配置后,最终在繁体中文的设备上,应用会使用英文资源。如果想要所有中文设备都显示作为开发语言的简体中文,最后需要多添加一种语言 zh-Hant,但不需要进一步翻译,直接以开发语言为模板生成即可。

到此,国际化适配已经完成了.导出的语言文件该怎么处理就怎么处理吧喜欢的点个赞吧

测试

在 Xcode 中,可以使用预览功能,在不运行应用的情况下,检测国际化和本地化的结果。选择一个 .storyboard 或 .xib 文件,打开辅助编辑器,在相关文件中选择 Preview,通过右下角语言选项,可以在国际化后选择 Double-Length Pseudolocalizations 进行检测,本地化后选择对应语言进行检测。

预览过后,可以通过设置应用启动时的参数,在设备上测试国际化和本地化的结果,而不需要修改设备的设置。编辑 Scheme,选择 Run -> Options,在 Application Language 一项中,可以选择对应语言资源,Double-Length Pseudolocalizations 以及 Right to Left Pseudolocalizations。勾选 Show non-localized strings 项,可以检测未本地化的文本,其会以大写形式显示。

本文由新葡京8455发布,转载请注明来源

关键词: