出于某种需要,我开发的软件的语言环境设置为“C”或“en_US”。使用不同的语言环境很困难,因为我只会说一种语言甚至远远接近流利程度。
因此,我经常忽略通过使用不同的区域设置可以引入的行为差异。不出所料,忽略这些差异有时会导致错误,这些错误只能由一些使用不同语言环境的不幸用户发现。在特别糟糕的情况下,该用户甚至可能不会与我共享语言,使得错误报告过程变得具有挑战性。并且,重要,我的很多软件都是图书馆的形式;虽然它几乎没有设置语言环境,但它可能与另一个库结合,或者在确实设置语言环境的应用程序中使用 - 生成我从未体验过的行为。
更具体一点,我想到的错误种类并不缺少使用这些本地化的代码中的文本本地化或错误。相反,我指的是当使用该API的代码没有预料到这种变化的可能性时(例如,在土耳其语语言环境中,语言环境改变某些语言环境感知API的结果(例如,toupper(3)
)的错误) toupper
不会将“i”更改为“I” - 对于尝试将特定网络协议讲到其他主机的网络服务器而言可能是个问题。
我维护的软件中有一些这样的错误的例子:
过去,我采用的一种处理方法是编写回归测试,明确地将语言环境更改为已知代码不起作用的语言环境,运行代码,验证正确的行为,然后恢复原始语言环境语言环境。这种方法效果很好,但只有在有人报告了错误之后,它才会覆盖代码库的一小块区域。
另一种可能的方法是建立一个持续集成系统(CIS),以便在具有不同语言环境集的环境中运行全套测试。通过在测试套件通常给出的一个备用区域设置中提供尽可能多的覆盖,这在一定程度上改善了这种情况。另一个缺点是存在许多很多很多区域设置,并且每个区域设置都可能导致不同的问题。在实践中,区域设置可能只有十几种不同的方式可以破坏程序,但是有几十种额外的测试配置会对资源造成负担(特别是对于已经通过在不同平台上测试,针对不同库来扩展其资源限制的项目版本等。)
我遇到的另一种方法是使用(可能首先创建)一个新的语言环境,它在各种方式上与“C”语言环境完全不同 - 具有不同的大小写映射,使用不同的千位分隔符,格式日期不同等等。这个语言环境可以与一个额外的CIS配置一起使用,并希望能够捕获代码中可能由任何语言环境触发的任何错误。
这样的测试区域是否已经存在?这个想法是否存在缺陷以测试区域设置兼容性?
人们采取了哪些其他的语言环境测试方法?
我主要对POSIX语言环境感兴趣,因为那些是我所知道的。但是,我知道Windows也有一些类似的功能,因此额外的信息(可能包含有关这些功能如何工作的更多背景信息)也可能有用。
答案 0 :(得分:3)
我会审核您的代码是否错误地使用toupper
等函数。在C语言环境模型下,此类函数应被视为仅在语言环境语言的自然语言文本上运行。对于任何处理潜在多语言文本的应用程序,这意味着不应该使用tolower
等函数。
如果您的目标是POSIX,那么由于uselocale
函数可以更灵活一点,这使得可以在一个线程中暂时覆盖区域设置(即不会弄乱程序的全局状态) 。然后,您可以全局保留C语言环境,并在使用自然语言文本时使用tolower
等用于ASCII /面向机器的文本(如配置文件等),并仅使用uselocale
到用户选定的语言环境来自所说的地区。
否则(如果你需要的话甚至可能更高级),我认为最好的解决方案是完全抛弃像tolower
这样的函数,并为配置文本等编写自己的ASCII版本,并使用用于自然语言文本的强大的Unicode感知库。
我尚未涉及的一个棘手问题是与snprintf
和strtod
等函数相关的小数点分隔符。在某些区域设置中将其更改为,
而不是.
会破坏您使用C库解析文件的能力。我首选的解决方案是永远不要设置LC_NUMERIC
语言环境。 (我是一名数学家,因此我倾向于认为数字应该是通用的,不受文化习俗的约束。)根据您的应用,真正需要的唯一区域设置类别可能只是LC_CTYPE
,LC_COLLATE
,和LC_MESSAGES
。通常有用的还有LC_MONETARY
和LC_TIME
。
答案 1 :(得分:2)
您需要解决两个不同的问题才能回答您的问题:测试代码并处理其他人代码的问题。
测试你自己的代码 - 我通过在CI环境中使用2或3个基于英语的语言环境设置来解决这个问题:en_GB(整理),en_ZW(几乎所有内容都会更改但你仍然可以读取错误)然后是en_AU(日期,整理)
如果您想确保您的代码适用于多字节文件名,那么您还需要使用ja_JP进行测试
处理其他人的代码在很多方面都是最困难的,我的解决方案是将日期值(几乎总是日期:)存储在原始日期/时间值中,总是保留它们作为GMT。然后,当您越过应用程序的边界时,您将转换为适当的格式。
PyTZ和PyICU非常有帮助。