Как использовать возможности C ++ для более чистого использования библиотеки i18n по сравнению с прямым использованием gettext () с C - PullRequest
3 голосов
/ 10 июня 2009

Я хотел бы иметь простой в использовании способ написания кода, например:

#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 ]

3 голосов
/ 10 июня 2009

Во время сборки строки в кавычках будут проверяться программой, такой как xgettext, для создания файла каталога базовых сообщений. Оператор << с аргументом i18n :: cout будет принимать строковый литерал в качестве ключа для поиска текста времени выполнения, который будет использоваться из каталога сообщений. </p>

Вы пытаетесь преобразовать строку как отдельный экземпляр, но это не /

Дело в том, что тебе не нужно что-то подобное. Подумайте о:

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

Так почему это не сработает, потому что «n = 1» или «n! = 1» работает только для английского языка, многие другие языки имеют более одной формы множественного числа, также требуется перевод «Мне нужны X яблок» как экземпляр signle.

Я предлагаю вам просто научиться разбираться с gettext, он довольно простой и мощный, многие думали об этом.

Еще один момент, вы обычно не вызываете gettext, а

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

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

Это делает код намного чище, также это довольно "стандартная" возможность использовать "_" в качестве псевдонима gettext.

Просто узнайте, как его использовать, прежде чем пытаться сделать «более приятный» API. Отметим, что gettext API является стандартом де-факто для многих языков, не только для C.

1 голос
/ 11 июня 2009

Лично я бы пошел с этим ответом , но, возможно, можно использовать немного магии streambuf, чтобы сделать это, когда текст записывается в поток. Если вы действительно заинтересованы в этом, пожалуйста, взгляните на Стандартные C ++ IOStreams и Locales от Langer и Kreft, это библия iostreams.

Далее предполагается, что все, что записано в буфер, должно быть переведено, и что каждая полная строка может быть переведена полностью:

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

Следующий класс transbuf переопределяет функцию "overflow" и переводит буфер каждый раз, когда видит новую строку.

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;
}    
1 голос
/ 10 июня 2009

Краткий ответ "Нет":)

Серьезно, какие аспекты интернационализации вас интересуют? ICU предоставляет почти все, но не похоже на стандартный C ++. Существуют и другие библиотеки меньшего размера, которые предоставляют некоторые функции i18n, то есть UTF-CPP для обработки строк в кодировке UTF-8.

0 голосов
/ 10 июня 2009

Вы имеете в виду, что вы просто хотите другой API? Вы можете написать небольшую оболочку, которая не должна быть слишком трудной, и она даст вам возможность использовать лучший API, какой только можно придумать

...