Как стать автором
Обновить

Комментарии 20

В принципе проблема давно решена (gnu.gettext.GettextResource API), но если вам хочется изобретать велосипед, то да — кто ж вам запретит…
Я в упор не вижу решения там проблемы склонения существительных. Я так понял, что эта фиговина предназначена для интернационализации? В Struts есть fmt для этого. Я решаю совсем другую проблему.
Да, я уже согласился, что она тоже решает проблему и кому-то gettext пригодится. Я, естественно, сначала искал готовое решение, но не нашел. Зато нашел кучу вопросов, поэтому и опубликовал свое решение.
Однако, интересная библиотека. Мне нравится их способ задания ключей.
Впрочем, пардон, решает. Вот тут указано, как. Хотя я, если честно, так и не понял, как.
Тем более, что все остальные строки properties уже заточены под MessageFormat и Struts fmt.

Ну подходит вам решение или нет — это другой вопрос. А решение там следующее: в ngettext передаётся три аргумента, но реально используется два. Первая — число и вторая — ключ. В .po файле указывается сколько вариантов теста может быть в языке (в арабском, например, шесть), как они выбираются и, собственно, эти варианты. Третий аргумент функции ngettext используется только для английского языка.

Да — по сути всё упирается в примерно те же формулы, что и у вас (русский язык-то для всех один), но оно работает для всех языков, а не только для русского.
В английском языке все просто: 1 year, 2 years ,… N years

А также criterion —> criteria, stigma —> stigmata, ox —> oxen, все по тому же шаблону ;)
Или что выбрать — appendices или appendixes? Или опять s просто добавить? :)
Это уже проблема согласования с числительными неизвестных слов. Она во всех языках с трудом решается. Речь идёт про бесконечные строки типа

if ($mailnum==1)
  print $t['mail received'];
else
  printf $mailnum+$t['mails received'];

Объяснить американцам что вариантов может быть больше двух и выбираться они могут загадочным способом и даже текст может меняться не только после числительного, но и до — довольно сложно…
В принципе согласен, просто сама фраза заставила меня улыбнуться. Вставлена так, для красного словца, и не имеет ничего общего с реальностью.
Это в любом случае решается обычным ChoiceFormat. И, таки да, для красного словца :)
Приведённый код, по моему вкусу, не так уж и хорош.
Предлагаю вам заглянуть сюда и ознакомится с достаточно универсальными формулами для целой кучи языков. При многоязыковой разработке эти формулы сильно сэкономят время. Не знаю как в Java, но в PHP эти формулы в чистом виде не применимы из-за несколько другой интерпретации оператора ?:, но в умелых руках всё работает.
Я все жду, что кто-нибудь внятно напишет, как это хозяйство к готовому Java-коду прикрутить с минимумом переделок. Особенно интересует, как этот gettext использовать в JSP.
Видите ли, из-за частного решения, пусть даже красивого и правильного, не разносят всю систему.
Вообще я не о геттексте говорил, а об универсальных формулах для числительных.

Но про геттекст тоже отвечу для Си ибо Яву уже не помню. Главный принцип gettext — минимум телодвижений. Если забыть о числительных, то для перевода на gettext программы с английскими строками требуются следующие действия:
1 Дописать инициализацию локали в начале программы.
2 Обернуть все строки «text» в _(«text»)
3 Запустить poedit и поковыряться в настройках
4 Перевести с английского на нужный.
Для строк с параметрами и с числительными придётся немного переписать код, но, как правило, эти участки после переписывания упростятся.
Не знаю как это реализовано в Яве, но не думаю, что есть большие отличия.
В Яве это реализовано на «ура». Есть класс Format и куча его наследников для разных нужд, есть класс Locale, ResourceBundle и т.п. Т.е. в Java с l10n и i18n все в порядке, за исключением проблемы множественного числа в русском языке, потому что с помощью ChoiceFormat его не опишешь. В английском, немецком, французском — запросто.
Я не спорю с тем, что библиотека gettext — штука интересная и задачу выполняет, но во-первых, в Java все (почти все, как оказалось) уже придумано до нас, описано в книгах и т.п., во-вторых, наша система изначально делалать с интернационализацией и локализацией, т.е. проблема выдирания строк изначально не стояла.
Решил добавить кратенький пример взятый из своего кода. Поддержка языков кроме русского пока отсутствует, но мы уже готовы к ней. Думаю, что этот код может отказаться полезным. (В пхп можно использовать русские юникодовые строки для геттекста, сем успешно и пользуюсь).

function plural ($n){
    return plural_russian($n);
}

function plural_russian($n){
    return $n%10==1 && $n%100!=11 ? 0 : ($n%10>=2 && $n%10<=4 && ($n%100<10 or $n%100>=20) ? 1 : 2);
}

$strings= array(
    0 => "через %d месяц",
    1 => "через %d месяца",
    2 => "через %d месяцев",
    3 => "через %d месяцев форма 3",
    4 => "через %d месяцев форма 4",
    5 => "через %d месяцев форма 5",
);

return  sprintf($strings[plural($mn)], $mn);

Для русского языка нужно добавить еще одно условие. Для числительного 1 и заканчивающихся на 1 (21, 31 и т.д.) нужна первая форма. Как-то так:

private Integer plurals(Long n){
if (n==0) return 0;
n = Math.abs(n) % 100;
Long n1 = n % 10;
if (n == 11) return 1;
if (n > 11 && n < 20) return 5;
if (n1 > 1 && n1 < 5) return 2;
if (n1 == 1) return 1;
return 5;
}
Там же есть для этого условия
Точно. мои извинения.
Да, я согласен с автором о сложности русского языка. Но когда точно известны ограничения, например только от 1 до 59 минут или от 1 часа до 24, то силы MessageFormat вполне достаточно. Всё зависит от ситуации
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории