首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用C++的特性来更清晰地使用i18n库,而不是通过C++直接使用gettext

如何使用C++的特性来更清晰地使用i18n库,而不是通过C++直接使用gettext
EN

Stack Overflow用户
提问于 2009-06-10 17:47:14
回答 4查看 2.9K关注 0票数 3

我希望有一种简单易用的方式来编写代码,比如:

代码语言:javascript
运行
复制
#include <iostream>
int main (){
    std::cout << "hello, world!\n";
}

但这支持i18n。下面是一个使用gettext()的示例

代码语言:javascript
运行
复制
#include <libintl.h>
#include <iostream>
int main (){
    std::cout << gettext("hello, world!\n");
}

然后,xgettext可以对其进行处理,以生成一个消息目录文件,翻译器可以使用该文件来创建各种版本。这些额外的文件可以在目标系统上处理,以允许用户以首选语言进行交互。

我想写类似下面这样的代码:

代码语言:javascript
运行
复制
#include <i18n-iostream>
int main (){
    i18n::cout << "hello, world!\n";
}

在构建时,xgettext之类的程序将检查引用的字符串,以生成基本消息目录文件。带有参数i18n::cout<<操作符将接受字符串文字作为键,以便从消息目录中查找要使用的运行时文本。

它是否存在于某个地方?

EN

回答 4

Stack Overflow用户

发布于 2009-06-10 18:43:31

在构建时,诸如xgettext之类的程序将检查带引号的字符串,以生成基本消息目录文件。带有参数i18n::cout的<<操作符将字符串文字作为键,以便从消息目录中查找要使用的运行时文本。

您尝试像转换单个实例一样转换字符串,但它不是/

重点是,你不想要这样的东西。想一想:

代码语言:javascript
运行
复制
if(n=1)
    i18n::cout << "I need one apple"
else
    i18n::cout << "I need " << n << " apples" ;

所以为什么这是行不通的,因为"n=1“或"n!=1”只适用于英语,许多其他语言都有不止一个复数形式,而且它还需要翻译"I need X apples“作为符号实例。

我建议你只是学习处理gettext,它非常简单和强大,很多人都想过它。

另外一点,你通常不会调用gettext,而是

代码语言:javascript
运行
复制
#include <libintl.h>
#include <iostream>
#define _(x) gettext(x)

int main (){
    std::cout << _("hello, world!\n");
}

这使得代码更加清晰,而且使用"_“作为gettext别名也是一个相当”标准“的特性。

在你尝试制作“更好”的API之前,先学习如何使用它。值得一提的是,gettext API是许多语言的事实上的标准,而不仅仅是C语言。

票数 3
EN

Stack Overflow用户

发布于 2009-06-10 17:52:40

简短的回答是“不”:)

说真的,你对国际化的哪些方面感兴趣?重症监护室提供了几乎所有的东西,但感觉不像标准的C++。还有其他一些范围较小的库,它们提供了一些i18n功能,例如,用于处理UTF-8编码字符串的UTF-CPP。

票数 1
EN

Stack Overflow用户

发布于 2009-06-11 08:29:30

就我个人而言,我会使用这个answer,但它可能会使用一些streambuf魔法来实现这一点,因为文本被写入到流中。如果你真的有兴趣这样做,请看看兰格和克雷夫特的Standard C++ IOStreams and Locales,它是iostreams的圣经。

下面假设写入缓冲区的所有内容都要转换,并且每一整行都可以完全转换:

代码语言:javascript
运行
复制
std::string xgettext (std::string const & s)
{
  return s;
}

下面的transbuf类覆盖了"overflow“函数,并在每次看到换行符时转换缓冲区。

代码语言:javascript
运行
复制
class transbuf : public std::streambuf {
public:
  transbuf (std::streambuf * realsb) : std::streambuf (), m_realsb (realsb)
    , m_buf () {}

  ~transbuf () {
    // ... flush  m_buf if necessary
  }

  virtual std::streambuf::int_type overflow (std::streambuf::int_type c) {
    m_buf.push_back (c);
    if (c == '\n') {
      // We have a complete line, translate it and write it to our stream:
      std::string transtext = xgettext (m_buf);
      for (std::string::const_iterator i = transtext.begin ()
        ; i != transtext.end ()
        ; ++i) {
        m_realsb->sputc (*i);
        // ... check that overflow returned the correct value...
      }
      m_buf = "";
    }
    return c;
  }    

  std::streambuf * get () { return m_realsb; }

  // data
private:
  std::streambuf * m_realsb;
  std::string m_buf;
};

下面是一个如何使用它的示例:

代码语言:javascript
运行
复制
int main ()
{
  transbuf * buf = new transbuf (std::cout.rdbuf ());
  std::ostream trans (buf);

  trans << "Hello";  // Added to m_buf
  trans << " World"; // Added to m_buf
  trans << "\n";     // Causes m_buf to be written

  trans << "Added to buffer\neach new line causes\n"
           "the string to be translated\nand written" << std::endl;

  delete buf;
}    
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/977146

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档