3

我想有一种易于使用的方式来编写代码,例如:

#include <iostream>
int main (){
    std::cout << "hello, world!\n";
}

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

#include <libintl.h>
#include <iostream>
int main (){
    std::cout << gettext("hello, world!\n");
}

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

我想编写类似这样的代码:

#include <i18n-iostream>
int main (){
    i18n::cout << "hello, world!\n";
}

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

它存在于某个地方吗?

4

4 回答 4

3

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

您尝试将字符串转换为单个实例,但不是/

关键是,你不想要这样的东西。考虑到:

if(n=1)
    i18n::cout << "I need one apple"
else
    i18n::cout << "I need " << n << " apples" ;

那么为什么这是行不通的,因为“n = 1”或“n!= 1”仅适用于英语,许多其他语言有不止一种复数形式,还需要将“我需要X苹果”翻译为单一实例.

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

还有一点,你通常不调用 gettext 但是

#include <libintl.h>
#include <iostream>
#define _(x) gettext(x)

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

这使得代码更清晰,使用“_”作为gettext别名也是一个相当“标准”的功能。

在尝试制作“更好”的 API 之前,请先了解如何使用它。顺便提一下,gettext API 是许多语言的事实上的标准,不仅仅是 C。

于 2009-06-10T18:43:30.770 回答
1

就我个人而言,我会选择这个答案,但是当文本被写入流时,可能会使用一些 streambuf 魔法来做到这一点。如果您真的对此感兴趣,请查看 Langer 和 Kreft 的Standard C++ IOStreams and Locales,它是 iostreams 的圣经。

以下假设要翻译写入缓冲区的所有内容,并且可以完全翻译每一行:

std::string xgettext (std::string const & s)
{
  return s;
}

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

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;
};

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

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;
}    
于 2009-06-11T08:29:30.240 回答
1

最简洁的答案是不” :)

说真的,您对国际化的哪些方面感兴趣?ICU 提供了几乎所有东西,但感觉不像标准 C++。还有其他一些规模较小的库提供一些 i18n 功能,即用于处理 UTF-8 编码字符串的 UTF-CPP。

于 2009-06-10T17:52:40.000 回答
0

你的意思是你只想要另一个API?你可以写一个小包装器,不应该太难,它会让你有可能使用你能想到的最好的 API :)

于 2009-06-10T17:51:46.663 回答