Pull to refresh

Comments 23

Мне больше всего нравится ttag. Особенно тот факт, что ключами в нём являются сами строки на дефолтном языке, и не нужно придумывать миллиард этих ключей

Когда те самые "строки на дефолтном языке" меняется — достоинство становится недостатком. К примеру, на ru.SO от подобного каждую неделю куски перевода "слетают".

  1. Одна и та же фраза может использоваться в нескольких местах и требовать, внезапно, разного перевода в зависимости от контекста использования. Так как смыслы слов в языках не связаны отношением 1 к 1. И уж тем более в разных языках разные устойчивые выражения для разных ситуаций.

  2. "Фраза на естественном языке" может измениться в ходе разработки приложения и будет неудобно менять все места использования и все переводы.

Все приведённые примеры про статический текст, что решается совсем просто. Мой интерес, как решают проблемы типа той, что приведена ниже, не удовлетворён:

Поле ${field} заполнено неверно: ${error_description}

Вообще тут проблема в дизайне самого JS: шаблоны строк мы завезли, а явных методов форматирования нет

UPD: ммм, статья обновлена. Спасибо!

Не вижу здесь нормальной поддержки плюрализации в самих строках переводов. Вижу какую-то хрень наколеночную. Вы извините, конечно, но ваш велик сравнивать с i18next можно с оооочень большой натяжкой.

Приведите пример, который невозможно решить с помощью i18nano. Все что вы пока написали не является аргументом, плюрализация решается спокойно через переменные как было расписано в статье.

Что мне вам приводить? Вам уже внизу всё написали. В продакшен нужна поддержка переводов для разных языков, а не хардкод, как у вас. Посмотрите, как это сделано в i18next, зачем мне приводить какие-то примеры? Впрочем, приведу:

"У Васи было три яблока, пять груш, из которых две червивые". Как это поддержать с помощью вашего велосипеда на нескольких языках, да еще и так, чтобы можно было фразу отдать транслятору? Да еще и на арабском? i18next это умеет. А ваш велосипед? А если не умеет, зачем он такой нужен?

Общепринятой практикой является написание фразы на одном из языков (русский/английский) и перевод на нужный, то бишь с токенизацией у вас будет: "У {{user_name}} было {{count_apple}} {{apple}}, {{count_pear}} {{pear}}, из которых {{count_with_worm}} червивые", для английского аналогично "{{user_name}} had {{count_apple}} {{apple}}, {{count_pear}} {{pear}}, {{count_with_worm}} of which were wormy"

Хотите сказать, что с i18next у вас будет по-другому? В чем вообще претензия? Склонение существительных (и их окончания) на различных языках явно не задача i18next и подобных библиотек.

Именно так и хочу сказать, что будет по-другому. Будет примерно так:

"labelGradeResult_one": "Результат {{score}} из {{count}} балла",

"labelGradeResult_few": "Результат {{score}} из {{count}} баллов",

"labelGradeResult_many": "Результат {{score}} из {{count}} баллов"

Это для русского языка. Для английского будут one и other. Для арабского свои ключи и так далее. После чего в коде вам остается написать что-то вида t("labelGradeResult", {score, count}). Заметьте, без всяких магических слов и констант с массивами в коде, только ключ и значения. Остальное всё сделает i18next в соответствии с выбранным языком по нужной формуле. И еще, вроде как, есть плагины, которые это позволяют скомпилировать, дабы не напрягать рантайм лишним парсингом.

Вам бы неплохо сначала изучить тему подробнее, прежде чем полемизировать. А еще на сайте того же i18next можно найти транслятора, который умеет в такой формат. А еще значения ключей поддерживают вложенные функции трансляции, дабы эти самые ключи переиспользовать. Впрочем, это уже удобства, которые реализовывать необязательно.

Поддержка плюрализации это именно задача таких библиотек. Потому что иначе ваша библиотека улетит в помойку сразу как только клиент попросит что-то подобное на нескольких языках. А он попросит, ибо мультиязычное приложение, которое не умеет в плюрализацию, по определению говно. А вот форматировать даты и время, как ни странно, не является их задачей, и это правильно.

Что же вы свой же пример упростили, да и ещё добавили уйму дополнительных ключей с магическими постфиксами.

Реализация дополнительных функций для обработки числительных спокойно решается теми же плагинами, которые, к слову, появились у i18next не сразу.

Я вам привел лишь образец, взятый из реального проекта. Не вижу смысла тратить на вас свое время и расписывать свой пример подробно - любой здравомыслящий инженер прочитает документацию i18next и поймет как решить задачу, которую я привел, в доке всё расписано. У вас, к слову, кроме странной строки с плейсхолдерами ничего тоже нет, так о каком решении вы говорите? Про магические постфиксы спасибо - насмешили. Сразу видно человека, который даже не удосужился ознакомиться с уже существующими решениями подробней, а начал писать свой велик с квадратными колесами. NIH, все дела, ага.

Если это решается плагинами, так решите, у вас же всё "просто". А раз просто, то и плагин написать плёвое дело, правда?

Продолжать обсуждение более не вижу смысла, всего хорошего.

про плюрализацию как-то очень примитивно затронуто:

count: ['zero', 'one', 'two']

...и так для всех натуральных чисел?

Вот как примерно эта задача решается обычно. Выделены несколько категорий (zero/one/two/few/many/other), достаточных для дифференциации во всех языках. И в разных языках этим категориям могут соответствовать разные наборы чисел - это определяется правилами для каждой категории в рамках каждого языка.

см. https://unicode-org.github.io/cldr-staging/charts/latest/supplemental/language_plural_rules.html

Вы можете реализовать функцию, которая по переданному параметру будет отдавать нужный индекс. Не поймите меня превратно, но поддержка для всевозможных языков слишком громозкая, да и покрыть все кейсы задача почти невозможная, даже из вашего примера few, many и other не являются в чистом виде числительными, то бишь требуют дополнительной логики, которую просто не решить с помощью key-value переводов.

А смысл? Одно дело, когда подвозят типизацию в URL template на бэке типа такого:

Route('/users/{user_id:int}', user)
Route('/floating-point/{number:float}', floating_point)
Route('/uploaded/{rest_of_path:path}', uploaded)

На этапе парсинга да, типизация ключей важна. А тут задача обратная -- просто в строку кастануть. Какой смысл типизировать ключи?

Скорее не в чем смысл, а как себе это вообще можно представить? Допустим, есть микросервис переводов, который динамически отдает нужные, на этапе компиляции приложения мы можем сгенерировать типы typescript, но в runtime мы не получим никакой пользы. Да и к тому же, если, например, значение ключа изменится, то что вы предлагаете делать?

"i18nano: локализация"
i18n и l10n вроде бы это разные задачи

Пользуясь моментом: я до сих пор не понимаю, в чём разница между l10n и i18n. Определение/расшифровка не интересуют. Интересует суть -- чем одно отличается от другого

Здесь вопрос весь заключается в том, что пользователи habr или сторонние люди пришедшие из поисковика будут искать? Интернализация или локализация? Все же локализация более распространенный термин.

Это ответ на что угодно, но не мой вопрос

Sign up to leave a comment.

Articles