Pull to refresh

Comments 14

Много вариантов локализаций видел.
Часто не удобно работать не со строками в коде, а package[150] или Resource.Id.
Обычно пишешь со строками на одном языке, запускаешь, а потом нужны еще. И начинаешь лопатить код. А писать сразу через ресурсы, неудобно.
Как-то писал проект (но как обычно забросил).
Он ildasm переводил IL код, парсил его. Там операция инициализации строки простая.
Собирал БД адресов строк и строки.
Потом для каждой строки делал перевод.
Правил IL код. Собирал ilasm в сборку на нужном языке.
В DEBUG-версии библиотеки при попытке получения строки с несуществующим идентификатором, будет возвращено пустое значение, но сама строка при этом будет создана и при завершении работы программы эти изменения можно будет сохранить.

Но лично я вижу более удобное решение, которое уже реализовано в другом проекте, где используется эта библиотека, а именно: коды строк, их значения и краткие описания (для переводчиков) хранятся в Excel-файле, а специальная программа по требованию парсит его и генерирует для каждого листа класс-набор констант, примерно так:
public static class STR_COMMON
{
    public const int Welcome = 0x00000001;
    public const int ServerUnavailable = 0x00000002;
    public const int ConnectionRefused = 0x00000003;
    // и т.д.
}

Заодно пополняет словарь локализации, в программе остается вызывать только package[STR_COMMON.Welcome] и строка получена.
Для потенциального переводчика надо будет только перевести тексты сообщений в Excel-файле для получения локализации на другом языке.
UFO just landed and posted this here
Вариант с вызовом функции наподобие Plural(%0, "str1", "str2") имеет одну фатальную опасность, если у вас много переводчиков и они работают удаленно: переводчик может вдруг решить перевести название функции и программа будет не просто выдавать некорректную строку, а падать с необработанным исключением, и проверить это крайне сложно.

У нас в приложении тоже используется локализация — и да, проблема с корректной формой числительных актуальна как никогда. Правда, мы решили вопрос по-другому: у нас есть строки типа «plural form» в формате «user|users» или «пользователь|пользователя|пользователей», и есть одна специальная строка с кодом функции, выбирающей номер такой формы в зависимости от числа. В таком формате сложнее ошибиться.
Зачем переводчику заменять названия функций? Это нелогично, т.к. функции оформлены спец-символами, а именно %Plural(%0, "str1", "str2", "str3")%

Но если это все же произошло (например, написали %Множественный(%0, "str1", "str2", "str3")%), интерпретатор выдаст исключение о том, что функция «Множественный» не найдена.

Плюс, при желании, можно добавить свои функции или переопределить уже существующие, например так:
[Function("P", "Множественный", "ЧислФорма")]
protected override object Plural(int count, params object[] forms)
{
    int m10 = count % 10;
    int m100 = count % 100;
    if (m10 == 1 && m100 != 11)
    {
        return forms[0];
    }
    else if (m10 >= 2 && m10 <= 4 && (m100 < 10 || m100 >= 20))
    {
        return forms[1];
    }
    else
    {
        return forms[2];
    }
}

И в дальнейшем использовать наиболее удобный псевдоним.

Хотя, надо признать, сейчас не реализована полная проверка синтаксиса строк, и если допустить ошибку (забыть знак %), то в некоторых случаях программа упадет.
Согласен, что с точки зрения программиста это абсолютно нелогично, но такие случаи у нас были. Главная проблема заключалась в том, что строка компилировалась только во время запуска программы с конкретной локалью. Если в вашей системе строки компилируются предварительно (например, при подготовке релиза) и это можно отследить заблаговременно — то хорошо :)
Зачем переводчику заменять названия функций?

Халтура, когда весь или часть материала переводчик фигачит в гугл транслейт.
Я с .Net конечно не очень знаком, но разве есть какие-то препоны перед использованием gettext? Судя по тому, что Вы говорите о «многих летах» я не могу поверить, что Вы о нём не знаете.
Да, читал о нем, но его функционал не подходит для моего проекта. Там есть только поддержка множественного числа и ничего более.

А для меня важно было иметь возможность расширения функционала пакетов своими функциями, возможность подгрузки и смены пакетов «на лету», возможность, в конце концов, использовать числа в качестве идентификаторов. Последнее имеет принципиальное значение при передаче сообщений между клиентом и сервером — не будете же вы передавать по сети длинную строку идентификатора вместо компактного числа.
Чтобы не изобретать свой синтаксис для ресурсных строк у нас в проекте использовался Razor (ну и работало все через RazorEngine). Туда можно было засунуть любые пользовательские функции, иногда даже какую-то простую логику без необходимости корячить функцию.
Сами ресурсные строки хранились в xml, который элементарно преобразовывался в формат excel, для передачи переводчикам.
Возможно, я неформал, но очень не люблю таскать чужие библиотеки в своих проектах. Уж извините, такая у меня слабость.

Но вы подкинули хорошую идею. Добавлю в библиотеку возможность подстановки полей классов, если соответствующий аргумент является классом. В моем синтаксисе это будет выглядеть примерно так: %0.Name%
Что насчёт NuGet пакета и как с этим работать, например в Asp.Net MVC?
Sign up to leave a comment.

Articles