gpt4 book ai didi

c - 与 strftime 或 printf 相比,GNU gettext 的本地化行为不稳定

转载 作者:行者123 更新时间:2023-11-30 16:55:28 24 4
gpt4 key购买 nike

我试图找出为什么 GNU gettext 的行为不像 strftimeprintf当谈到本地化时。我从头到尾阅读了整个手册,但示例相当简单。我已将问题简化为一个简单的 C 程序。

任务是通过用户输入切换应用程序中的区域设置以接收本地化文件输出。

我的区域设置:

LANG=de_DE.UTF-8
LC_CTYPE="de_DE.UTF-8"
LC_COLLATE="de_DE.UTF-8"
LC_TIME="de_DE.UTF-8"
LC_NUMERIC="de_DE.UTF-8"
LC_MONETARY="de_DE.UTF-8"
LC_MESSAGES="de_DE.UTF-8"
LC_ALL=

考虑这个 C 示例:

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <time.h>
#include <math.h>
#include "my-i18n.h"

#define PI acos(-1.0)

static char *locales[] = {
"de_DE.UTF-8",
"ru_RU.UTF-8",
"he_IL.UTF-8",
"es_ES.UTF-8",
"C",
};

void localize(char *locale, struct tm *time) {
printf("==============================================================\n");
printf("Passed locale: %s\n", locale);
char *setlocale_out = setlocale(LC_ALL, locale);
printf("Set locale: %s\n", setlocale_out);

char buffer[80];
strftime(buffer, sizeof(buffer), "%c", time);
printf("Localized time: %s\n", buffer);

printf("Get rational, π: %f\n", PI);

printf(_("Hello World!\n"));
printf(_("Goodbye!\n"));
}

int main(void) {
time_t rawtime = time(NULL);
struct tm *time;
localtime(&rawtime);
time = localtime(&rawtime);

bindtextdomain("my-i18n", LOCALEDIR);
textdomain("my-i18n");
int i;
for (i = 0; i < sizeof(locales)/sizeof(locales[0]); i++) {
localize(locales[i], time);
}

return EXIT_SUCCESS;
}

及其输出:

==============================================================
Passed locale: de_DE.UTF-8
Set locale: de_DE.UTF-8
Localized time: Fr 28 Okt 11:44:24 2016
Get rational, π: 3,141593
Setting LANG=de_DE.UTF-8
Hallo Welt!
Tschüß!
==============================================================
Passed locale: ru_RU.UTF-8
Set locale: ru_RU.UTF-8
Localized time: пятница, 28 октября 2016 г. 11:44:24
Get rational, π: 3,141593
Setting LANG=ru_RU.UTF-8
Hallo Welt!
Tschüß!
==============================================================
Passed locale: he_IL.UTF-8
Set locale: he_IL.UTF-8
Localized time: CEST 11:44:24 2016 אוק 28 ו'
Get rational, π: 3.141593
Setting LANG=he_IL.UTF-8
Hallo Welt!
Tschüß!
==============================================================
Passed locale: es_ES.UTF-8
Set locale: es_ES.UTF-8
Localized time: vie 28 oct 11:44:24 2016
Get rational, π: 3,141593
Setting LANG=es_ES.UTF-8
Hallo Welt!
Tschüß!
==============================================================
Passed locale: C
Set locale: C
Localized time: Fri Oct 28 11:44:24 2016
Get rational, π: 3.141593
Setting LANG=C
Hallo Welt!
Tschüß!

如您所见,strftimeprintf完全符合我的预期,但 gettext 仅考虑我的外部区域设置。经过 Google 和 SO 搜索后,我发现 bindtextdomain和/或 textdomain必须在每个 setlocale 之后执行。而且,我还要执行putenv("LANG=...")强制 gettext 工作。

修改后的C代码:

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <time.h>
#include <math.h>
#include "my-i18n.h"

#define PI acos(-1.0)

static char *locales[] = {
"de_DE.UTF-8",
"ru_RU.UTF-8",
"he_IL.UTF-8",
"es_ES.UTF-8",
"C",
};

void localize(char *locale, struct tm *time) {
printf("==============================================================\n");
printf("Passed locale: %s\n", locale);
char *setlocale_out = setlocale(LC_ALL, locale);
printf("Set locale: %s\n", setlocale_out);

char buffer[80];
strftime(buffer, sizeof(buffer), "%c", time);
printf("Localized time: %s\n", buffer);

printf("Get rational, π: %f\n", PI);

printf("Setting LANG=%s\n", locale);
setenv("LANG", locale, 1);

bindtextdomain("my-i18n", LOCALEDIR);
textdomain("my-i18n");
printf(_("Hello World!\n"));
printf(_("Goodbye!\n"));
}

int main(void) {
time_t rawtime = time(NULL);
struct tm *time;
localtime(&rawtime);
time = localtime(&rawtime);

int i;
for (i = 0; i < sizeof(locales)/sizeof(locales[0]); i++) {
localize(locales[i], time);
}

return EXIT_SUCCESS;
}

和输出:

==============================================================
Passed locale: de_DE.UTF-8
Set locale: de_DE.UTF-8
Localized time: Fr 28 Okt 11:50:33 2016
Get rational, π: 3,141593
Setting LANG=de_DE.UTF-8
Hallo Welt!
Tschüß!
==============================================================
Passed locale: ru_RU.UTF-8
Set locale: ru_RU.UTF-8
Localized time: пятница, 28 октября 2016 г. 11:50:33
Get rational, π: 3,141593
Setting LANG=ru_RU.UTF-8
Привет мир!
Пока!
==============================================================
Passed locale: he_IL.UTF-8
Set locale: he_IL.UTF-8
Localized time: CEST 11:50:33 2016 אוק 28 ו'
Get rational, π: 3.141593
Setting LANG=he_IL.UTF-8
Hello World!
Goodbye!
==============================================================
Passed locale: es_ES.UTF-8
Set locale: es_ES.UTF-8
Localized time: vie 28 oct 11:50:33 2016
Get rational, π: 3,141593
Setting LANG=es_ES.UTF-8
¡Hola mundo!
¡Adios!
==============================================================
Passed locale: C
Set locale: C
Localized time: Fri Oct 28 11:50:33 2016
Get rational, π: 3.141593
Setting LANG=C
Hello World!
Goodbye!

有人可以解释一下这种“奇怪”的行为吗?

编辑:我已在邮件列表中提出它:http://lists.gnu.org/archive/html/bug-gettext/2016-11/msg00002.html

最佳答案

您需要调用bindtextdomain()的主要原因在setlocale()之后调用,正在缓存

如果每个 gettext()调用来检查环境变量,这会很慢。也许对于今天的机器来说它不会引人注目,但它曾经非常重要。相反,当您发出 bindtextdomain() 调用时,就会完成(区域设置)查找,并缓存结果,以提高效率。

在实践中,存在..缺点。特别是,LANGUAGE 环境变量会影响每个 gettext() 调用。此外,gettext 支持线程特定的区域设置(通过 uselocale() GNU 扩展)——在 Linux 中,使用 glibc 2.4 或更高版本(2006 年发布)时,以及自 2013 年以来的 macOS/Mac OSX 中或左右。 (编辑:我在此之前就开始使用 gettext,只是没能跟上最新的情况;我做了一些我不应该做的假设。抱歉。)由于 gettext 的初始版本早在 1990 年就发布了,并且从那时到现在,很多东西都发生了变化,你也可以考虑这个历史包袱,甚至是一个错误。

关于c - 与 strftime 或 printf 相比,GNU gettext 的本地化行为不稳定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40302497/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com