区域设置相关问题

此页面包含与区域设置相关的问题和事项。在以下段落中,您将找到在为各种区域设置配置系统时可能出现的通用概述。许多(但不是全部)现有的区域设置相关问题都可以分类并归于以下标题之一。下面的严重性评级使用以下标准:

如果某个特定软件包有已知的解决方法,它将会出现在该软件包的页面上。

所需编码不是程序中的有效选项

严重性:严重

某些程序要求用户为其输入或输出数据指定字符编码,并且只提供有限的编码选择。Enscript-1.6.6-X 选项()、未打补丁的 Cdrtools-3.02a09-input-charset 选项,以及 Links-2.30 菜单中提供的显示字符集就是这种情况。如果所需的编码不在列表中,该程序通常会完全无法使用。对于非交互式程序,可以通过在提交给程序之前将文档转换为支持的输入字符集来解决此问题。

解决此类问题的方法是为缺失的编码实现必要的支持,作为原始程序的补丁,或者寻找替代品。

程序假定外部文档采用基于区域设置的编码

严重性:非文本文档为高,文本文档为低

某些程序,例如 nano-9.1JOE-4.6,假定文档始终采用当前区域设置所隐含的编码。虽然这种假设对于用户创建的文档可能成立,但对于外部文档则不安全。当这种假设不成立时,非 ASCII 字符会显示错误,文档可能变得不可读。

如果外部文档完全是基于文本的,可以使用 iconv 程序将其转换为当前区域设置的编码。

对于非基于文本的文档,这是不可能的。事实上,对于 Microsoft Windows 操作系统已设定事实标准的文档,程序中的这种假设可能完全无效。此问题的一个示例是 MP3 文件中的 ID3v1 标签。对于这些情况,唯一的解决方案是寻找没有此问题的替代程序(例如,允许您指定假定文档编码的程序)。

在 BLFS 软件包中,此问题适用于 nano-9.1JOE-4.6 以及除 Audacious-4.6.1 之外的所有媒体播放器。

此类别中的另一个问题是,当您发送给别人的文档他们无法阅读,因为他们的操作系统设置处理字符编码的方式不同。当对方使用 Microsoft Windows 时,这种情况经常发生,因为 Windows 对给定国家/地区只提供一种字符编码。例如,这会导致在 Linux 中创建的 UTF-8 编码的 TeX 文档出现问题。在 Windows 上,大多数应用程序会假定这些文档是使用默认的 Windows 8 位编码创建的。

在极端情况下,Windows 编码兼容性问题可能只能通过在 Wine 下运行 Windows 程序来解决。

程序使用或创建错误编码的文件名

严重性:严重

POSIX 标准规定文件名编码是当前 LC_CTYPE 区域设置类别所隐含的编码。此信息在指定 TarCpio 程序行为的页面上隐藏得很深。某些程序默认会弄错(或者根本没有足够的信息来正确处理)。结果是它们创建的文件名随后无法被 ls 正确显示,或者它们拒绝接受 ls 正确显示的文件名。对于 GLib-2.88.2 库,可以通过将 G_FILENAME_ENCODING 环境变量设置为特殊的 "@locale" 值来纠正此问题。不尊重该环境变量的基于 Glib2 的程序是有缺陷的。

.zip 格式存在此问题,因为它不保存存档文件中名称的编码。当 unzip(实际上是指向 libarchive-3.8.8bsdunzip 的符号链接)解压它时,默认情况下名称被假定为使用 CP850 编码,这是西欧语言的 Windows 代码页。但如果名称包含非拉丁字符(例如简体中文的 CP936),则实际编码可能不同。如果不手动指定编码,bsdunzip 会将这些非拉丁字符转换成不可读的序列。

避免此类问题的一般规则是避免安装有缺陷的程序。如果这不可能,可以使用 convmv 命令行工具来修复这些有缺陷程序创建的文件名,或者有意地修改现有文件名以满足此类程序的错误预期。

在其他情况下,类似的问题是由于使用不支持区域设置的工具(例如 OpenSSH-10.3p1)从使用不同区域设置的系统导入文件名而引起的。为了避免在将文件传输到具有不同区域设置的系统时损坏非 ASCII 字符,可以使用以下任何方法:

  • 直接传输,然后使用 convmv 修复损坏。

  • 在发送端,使用传递给 tar--format=posix 选项创建 tar 归档文件(这将在未来版本的 tar 中成为默认值)。

  • 将文件作为附件通过邮件发送。邮件客户端会指定附件文件名的编码。

  • 将文件写入格式化为 FAT 或 FAT32 文件系统的可移动磁盘。

  • 使用 Samba 传输文件。

  • 通过 FTP 使用支持 RFC2640 的服务器(目前仅指 wu-ftpd,但其安全记录不佳)和客户端(例如 lftp)传输文件。

最后四种方法之所以有效,是因为文件名会自动从发送方的区域设置转换为 UNICODE,并以这种形式存储或发送。然后它们会从 UNICODE 透明地转换为接收方区域设置的编码。

程序破坏多字节字符或不正确计算字符单元格

严重性:高或严重

许多程序是在多字节区域设置不常见的较老时代编写的。此类程序假定 C 语言的 "char" 数据类型(一个字节)可用于存储单个字符。此外,它们假定任何字符序列都是有效字符串,并且每个字符都占据单个字符单元格。这种假设在 UTF-8 区域设置中完全失效。可见的表现是程序过早地截断字符串(例如在 80 字节处而非 80 个字符处)。基于终端的程序无法将光标正确定位在屏幕上,无法通过按 "Backspace" 键删除一个字符,并且在更新屏幕时会留下垃圾字符,通常会使屏幕变得一团糟。

从程序员的角度来看,修复这类问题是一项繁琐的任务,就像其他所有将新概念改造到旧有缺陷设计中的情况一样。在这种情况下,必须重新设计所有数据结构以适应完整字符可能跨越可变数量 "char" 的事实(或者切换到 wchar_t 并按需转换)。此外,对于每次调用 "strlen" 及类似函数,需要确定真正需要的是字节数、字符数还是字符串的宽度。有时从头开始编写具有相同功能的程序会更快。

在 BLFS 软件包中,此问题适用于 xine-ui-0.99.14 以及所有 shell。