您的位置:首页 > 其它

MinGW/GCC 编译器修改 gettext 初始化路径使之能在任意位置输出中文消息

2013-11-10 23:12 218 查看
GCC 编译器支持 gettext 的本地化,MinGW 也一样,只是可惜他们在内部实现时使用了绝对路径。这个绝对路径的前缀(prefix) 由编译时传递给 configure 的 --prefix 设定,这样就导致了 MinGW 只有在指定的位置上才能实现编译消息本地化。

我所做的就是让 GCC 在初始化 gettext 时使用相对路径,这样就能使 MinGW 在任何地方都能使用本地化的字符串了。包含文件搜索路径也同理。

通过查找 bindtextdomain 函数可以知道 gcc 对 gettext 的初始化在 gcc\intl.c 中完成。包含文件搜索路径定义在 incpath.c 中。

void
gcc_init_libintl (void)
{
#ifdef HAVE_LC_MESSAGES
setlocale (LC_CTYPE, "");
setlocale (LC_MESSAGES, "");
#else
setlocale (LC_ALL, "");
#endif

(void) bindtextdomain ("gcc", LOCALEDIR);
(void) textdomain ("gcc");

/* Opening quotation mark.  */
open_quote = _("`");

/* Closing quotation mark.  */
close_quote = _("'");

#if defined HAVE_LANGINFO_CODESET
locale_encoding = nl_langinfo (CODESET);
if (locale_encoding != NULL
&& (!strcasecmp (locale_encoding, "utf-8")
|| !strcasecmp (locale_encoding, "utf8")))
locale_utf8 = true;
#endif

if (!strcmp (open_quote, "`") && !strcmp (close_quote, "'"))
{
/* Untranslated quotes that it may be possible to replace with
U+2018 and U+2019; but otherwise use "'" instead of "`" as
opening quote.  */
open_quote = "'";
#if defined HAVE_LANGINFO_CODESET
if (locale_utf8)
{
open_quote = "\xe2\x80\x98";
close_quote = "\xe2\x80\x99";
}
#endif
}
}


由于我所做的是针对 Windows 下的修改,因此所有改动都要加上 #ifdef WIN32 ... #endif

首先在开头加上:

#ifdef WIN32
#include <windows.h>

BOOL DirectoryExists(LPSTR lpszPath)
{
WIN32_FIND_DATA wfd;
BOOL bResult = FALSE;
HANDLE hFind = FindFirstFile(lpszPath, &wfd);
if ((hFind != INVALID_HANDLE_VALUE) && (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
bResult = TRUE;
}
FindClose(hFind);
return bResult;
}
#endif


其中 DirectoryExists 是用来判断路径是否存在的。

然后修改 (void) bindtextdomain ("gcc", LOCALEDIR); 为:

#ifndef WIN32
(void) bindtextdomain ("gcc", LOCALEDIR);
#else
DWORD dwSize = MAX_PATH + 20;
LPSTR lpszName = (LPSTR) xmalloc(dwSize);
DWORD dwRealSize = GetModuleFileNameA(NULL, lpszName, dwSize) + 1;
if (dwRealSize > dwSize)
{
lpszName = (LPSTR) xrealloc(lpszName, dwSize + 20);
GetModuleFileNameA(NULL, lpszName, dwRealSize + 20);
}

/* 去掉文件名 */
int l = strlen(lpszName);
while (l >= 0)
{
if (lpszName[l] == '\\')
break;
l--;
}
lpszName[l] = 0;

/* 去掉一层文件夹 */
l = strlen(lpszName);
while (l > 0)
{
if (lpszName[l] == '\\')
break;
l--;
}

/* 判断是否到根路径 */
if (lpszName[l] != '\\')
(void) bindtextdomain ("gcc", LOCALEDIR);
else
{
// 连接上 share\locale
lpszName[l + 1] = 0;
strcat(lpszName, "share\\locale");
if (DirectoryExists(lpszName))
(void) bindtextdomain ("gcc", lpszName);
else
(void) bindtextdomain ("gcc", LOCALEDIR);
}

free(lpszName);
#endif


这样重新编译后,无论 MinGW 位置在哪,它都能显示翻译后的消息了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐