从shell的gettext .po文件中提取单个翻译

时间:2019-02-11 20:25:50

标签: bash shell cmake gettext po

作为C ++应用程序的构建步骤(使用CMake作为构建系统),我需要创建一些模板文件,其中应包含本地化的字符串。

字符串已经可以通过gettext .po文件的形式从翻译器中获得(与用于翻译应用程序本身的字符串相同)。

因此,我需要一种从.po文件中提取翻译成给定英语源字符串的方法(通过Bash / shell或通过CMake)

到目前为止,我想到的是以下内容

translated_string=$(
    msggrep --msgid -e "^${untranslated_string}$" ${po_file} \
        | msgattrib --no-fuzzy \
        | grep -A 1 'msgid "${untranslated_string}$"' \
        | sed -n 's/msgstr "\(.*\)"/\1/p'
)

显然,这些都是对“简单”函数的大量调用:

  • msggrep输出的.po文件只有我想要的字符串
  • msgattrib确保翻译不“模糊”(即需要更新),因为我不能使用这些翻译
  • 然后我使用grepsed手动提取翻译

我想必须有更好的方法吗?毕竟gettext确实使在运行时转换我的应用程序变得容易,但是在构建时似乎有点不灵活...

2 个答案:

答案 0 :(得分:1)

.po文件供翻译人员使用。软件应使用已编译的.mo文件来检索翻译。

GNU gettext附带了一个二进制gettext,用于对shell脚本进行国际化。您可以按以下目的使用它:

$ mkdir -p de/LC_MESSAGES 2>/dev/null
$ msgfmt --verbose --statistics de.po -o de/LC_MESSAGES/package.mo
$ TEXTDOMAINDIR=. LANGUAGE=de LANG=de_DE.UTF-8 LC_MESSAGES=de_DE.UTF-8 gettext package 'Hello, world!'

用您的文本域“ Hello,world!”替换“ package”。使用您的消息ID和de使用您选择的语言。请注意,这要求在构建系统上安装选定的语言环境-在这种情况下为de语言环境。

有关更多信息,请参见gettext(1)msgfmt(1)

答案 1 :(得分:-1)

按照Guido Flohr在https://stackoverflow.com/a/54707280/2514664中的建议,使用二进制.mo文件并从那里提取字符串是一种可行的解决方案。

但是,按照原始答案中的建议,使用本地gettext可执行文件最终提取字符串的结果却具有太多含义(毕竟,它旨在在最适合的语言环境中提取用户可见的字符串)为用户从现有消息目录中提供,而不是作为“仅”必须从特定文件中以特定语言提取单个字符串的构建工具)。对于要在多个平台上运行的构建系统而言,它最终太脆弱了。

我原来使用Python,它的自定义gettext module效果更好,并且可以节省很多工作(特别是如果您对Python感到满意的话)。

按照链接的答案中的建议,可以从.po文件生成.mo文件:

mkdir -p locale/de/LC_MESSAGES
msgfmt de.po -o locale/de/LC_MESSAGES/package.mo

用Python进行翻译并不像

那样简单。
import gettext

translation = gettext.translation('package', localedir='locale', languages=['de'])
translated_string = translation.gettext('unstranslated_string')

顺便说一句。解决我自己的问题后,我发现我的Python发行版的“ / Tools / i18n”文件夹中还有一个msgfmt.pypygettext.py,它们应该提供与msgfmt相同的功能,并且gettext自己。两者都可能很有趣,可以直接使用,也可以查看它们的实现来创建新的东西(例如,msgfmt.py包括一个简单的.po文件解析器)。