Международная интернационализация позже очень дороже? [закрыто

StackOverflow https://stackoverflow.com/questions/2333990

Вопрос

Большинство людей согласятся с тем, что интернационализация существующего приложения стоит дороже, чем развитие интернационализированного приложения с нуля.

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

Вы можете даже утверждать, что у зрелого приложения есть много и много LOC, которые удаляются во время истории проекта, и что им не нужно быть I18. от очень начального.

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

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

Это было полезно?

Решение

«Когда вы пишете интернационализованное приложение с нуля, стоимость выполнения i18n ... амортизируется»

Однако это не вся история.

Задним числом отслеживание каждого сообщения для пользователей является - в некоторых случаях - невозможно.

Не трудно. Невозможно.

Учти это.

theMessage = "Some initial part" + some_function() + "some following part";

У вас будет ужасное время на поиске всех подобных ситуаций. После всего, some_function Просто возвращает строку. Вы не знаете, является ли это ключом базы данных (никогда не отображается человеку) или сообщение, которое должно быть переведено. И когда он переведен, правила грамматики могут показать, что конкатенация строки из 3 частей была тупой идеей.

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

Ясно, когда some_function Вообще имеет какую -либо сложность, вы озадачены тем, почему одна часть вашего применения все еще находится в шведском языке, а остальное было успешно в других языках. (В частности, не выбирать шведов, замените это любым языком, используемым для разработки, отличного от окончательного развертывания.)

Хуже того, конечно, если вы работаете в C или C ++, у вас может быть часть этого разделения между допроцессорными макросами и правильным синтаксисом C-языка.

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

Другие советы

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

  • Большую часть времени i18n не требуется, пока приложение не станет «большим». Когда вы станете большим, у вас, скорее всего, будет команда разработчиков, чтобы посвятить I18N, так что это будет меньше бремени.
  • Возможно, вам на самом деле это не нужно. Многие небольшие команды прилагают большие усилия для поддержки интернационализации, когда у вас нет клиентов, которые этого требуют.
  • После того, как вы интернационализировали, это делает постепенные изменения больше времени. Это не займет много дополнительного времени, но каждый раз, когда вам нужно добавлять в продукт строку, сначала нужно добавить ее в пакет, а затем добавлять ссылку. Нет, это не так много работы, но это усилия, и это займет немного времени.

Я предпочитаю «пересечь этот мост, когда мы приходим к нему» и интернационализуем только тогда, когда у вас есть платный клиент, который ищет его.

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

Например

Message = "Do you want to load the " & fileType() & " file?"

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

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

Итак, как вы думаете, проект, начинающийся сегодня, должен быть интернационализирован, или может ли это решение быть отложено на будущее, основываясь на успехе (или нет), которое пользуется программным обеспечением и географическим распределением спроса?

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

Я не могу сказать, что дорого, но я могу сказать вам, что чистый API позволяет интернационализировать ваше применение по очень низкой цене.

Это не похоже, что вы устанавливаете основные значения ключей для объектов Mietzins. Вам необходимо либо установить значения первичных ключей, прежде чем пытаться сохранить в базе данных, либо сообщить EF, что основные ключи будут сгенерированы в базе данных.

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

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

public class Mietzins
{
    public int Id { get; set; }
    public int LiegenschaftId { get; set; }
    public int MieterId { get; set; }
    public int ObjektId { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }

    public Liegenschaft Liegenschaft { get; set; }
    public Mieter Mieter { get; set; }
    public Objekt Objekt { get; set; }
}

public class Mieter
{
    public int Id { get; set; }
    public int LiegenschaftId { get; set; }
    public int ObjektId { get; set; }
    public string Name { get; set; }

    public Liegenschaft Liegenschaft { get; set; }
    public ICollection<Mietzins> MietzinsMenge { get; set; }
    public Objekt Objekt { get; set; }
}

public class Objekt
{
    public int Id { get; set; }
    public int LiegenschaftId { get; set; }
    public int HausId { get; set; }
    public int Zimmer { get; set; }

    public Haus Haus { get; set; }
    public Liegenschaft Liegenschaft { get; set; }
    public ICollection<Mietzins> MietzinsMenge { get; set; }
    public ICollection<Mieter> MieterMenge { get; set; }
}

public class Liegenschaft
{
    public int Id { get; set; }
    public string Strasse { get; set; }
    public int UserId { get; set; }

    public ICollection<Haus> HausMenge { get; set; }
    public ICollection<Mieter> MieterMenge { get; set; }
    public ICollection<Mietzins> MietzinsMenge { get; set; }
    public ICollection<Objekt> ObjektMenge { get; set; }
}

public class Haus
{
    public int Id { get; set; }
    public int LiegenschaftId { get; set; }
    public int Nummer { get; set; }

    public ICollection<Objekt> ObjektMenge { get; set; }
    public Liegenschaft Liegenschaft { get; set; }
}
.

Контекст:

public class ImmoReportsEntities : DbContext
{
    public DbSet<Liegenschaft> Liegenschaft { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Liegenschaft>()
            .HasMany(e => e.HausMenge)
            .WithRequired(e => e.Liegenschaft)
            .HasForeignKey(e => e.LiegenschaftId)
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<Liegenschaft>()
            .HasMany(e => e.MieterMenge)
            .WithRequired(e => e.Liegenschaft)
            .HasForeignKey(e => e.LiegenschaftId)
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<Liegenschaft>()
            .HasMany(e => e.MietzinsMenge)
            .WithRequired(e => e.Liegenschaft)
            .HasForeignKey(e => e.LiegenschaftId)
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<Liegenschaft>()
            .HasMany(e => e.ObjektMenge)
            .WithRequired(e => e.Liegenschaft)
            .HasForeignKey(e => e.LiegenschaftId)
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<Haus>()
            .HasMany(e => e.ObjektMenge)
            .WithRequired(e => e.Haus)
            .HasForeignKey(e => e.HausId)
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<Objekt>()
            .HasMany(e => e.MietzinsMenge)
            .WithRequired(e => e.Objekt)
            .HasForeignKey(e => e.ObjektId)
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<Objekt>()
            .HasMany(e => e.MieterMenge)
            .WithRequired(e => e.Objekt)
            .HasForeignKey(e => e.ObjektId)
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<Mieter>()
            .HasMany(e => e.MietzinsMenge)
            .WithRequired(e => e.Mieter)
            .HasForeignKey(e => e.MieterId)
            .WillCascadeOnDelete(false);
    }
}
.

Я тогда запустил ваш код именно так, как в вопросе, и он работал нормально.

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

public class Mietzins
{
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }
    public int LiegenschaftId { get; set; }
    public int MieterId { get; set; }
    public int ObjektId { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }

    public Liegenschaft Liegenschaft { get; set; }
    public Mieter Mieter { get; set; }
    public Objekt Objekt { get; set; }
}
.

Я снова провел код и получил следующее исключение:

Необработанное исключение: system.data.entity.infrastructure.dbupdateException: Произошла ошибка при обновлении записей. Смотрите внутреннее исключение для деталей. ---> System.data.updateException: Произошла ошибка при обновлении записей. Смотрите внутреннее исключение для деталей. ---> System.data.sqlclient.sqlexception: нарушение первичного ключа ограничения «pk_mietzins». Не удается вставить дубликатную клавишу в объекте «dbo.mietzins». Заявление было прекращено.

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

Концепция I18N и L10N шире, чем просто перевод строк на некоторые языки.

Пример: рассмотрим ввод даты и времени пользователями. Если у вас нет интернационализации, когда вы проектируете

а) Интерфейс для пользователя и

б) механизм хранения, поиска и отображения

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

Согласован, в большинстве случаев I18N не является необходимым в первую очередь. Но, и это моя точка зрения, если вы не подумаете немного Области, которые должны быть затронуты для i18n, вы обнаружите, что в конечном итоге переписываете большие части исходного кода. А потом, добавив i18n является Гораздо дороже, чем потратить немного заранее.

Одна вещь, которая, кажется, может быть большой проблемой, - это различное количество персонажей для сообщения на разных языках. Я делаю некоторую работу над приложениями iPhone и особенно на небольшом экране, если вы разработаете пользовательский интерфейс для сообщения, в котором есть 10 символов, а затем вы пытаетесь интернационализировать позже и обнаружите, что вам нужно 20 символов, чтобы отобразить то же самое, что вам теперь нужно переделать свой пользовательский интерфейс разместить. Даже с настольными приложениями это все еще может быть большой лаваш.

Это зависит от вашего проекта и от того, как организована ваша команда.

Я был вовлечен в интернационализацию веб-сайта, и это был один разработчик на полный рабочий день, вероятно, около 6-8 месяцев для меня, чтобы обрабатывать воздействие установки при необходимости (реорганизация файлов и т. Д.) И другие Разработчики время от времени участвуют, когда их проекты нуждались в тяжелом рефакторинге. Это было в приложении, которое было в V3.

Так что это определенно дорого. Что вы должны спросить, так это то, насколько дорого есть система локализации с самого начала, и как это повлияет на проект на ранних стадиях. Ваш проект на V1, возможно, не сможет выжить задержки и неудачи, вызванные проблемами, посвященной спешительно разработанной структуре интернационализации, в то время как стабильный проект V3 с широкой клиентской базой может иметь капитал, чтобы инвестировать в это правильно.

Это также зависит от того, хотите ли вы интернационализировать все, включая сообщения журнала, или только струны пользовательского интерфейса, и сколько из тех строк пользовательского интерфейса, и кто у вас есть для локализации и качества, который идет с ним, и даже какие языки Вы хотите поддержать - например, необходимо ли ваша система поддерживать строки Unicode (что является требованием для азиатских языков).

И не забывайте, что изменение бэкэнда базы данных для поддержки интернационализированных данных также может быть дорогостоящим. Просто попробуйте изменить это поле Varchar на Nvarchar, когда у вас уже есть 20 000 000 записей.

я думаю это зависит от языка. Анкет Каждое приложение J2EE (Java Web) I18N, потому что оно очень просто (даже IDE может извлечь струны для вас, и вы просто назовите их).

В J2EE это дешевле добавить его позже, Однако культура должна добавить их как можно скорее. Я думаю, что это потому, что J2EE использует много открытых источников, и почти все либеральные лица с открытым исходным кодом I18N. Это отличная идея для них, но не для большинства приложений J2EE. Большинство корпоративных приложений предназначены только для одной компании, которая говорит на одном языке.

Плюс, если у вас есть плохие тестеры Помещение слишком рано заставляет их дать вам Отчеты об ошибках о лейблах и переводах(Я только однажды видел, как переводы не были сделаны разработчиками). После того, как тестеры закончились с этим, у вас есть приложение Buggy с отличной поддержкой i18N. Однако пользователям было бы весело переключать язык и посмотреть, смогут ли они его использовать. Однако использование вашего приложения это просто скучная работа для них, поэтому они даже не сделают этого. Единственные пользователи i18n - тестеры.

Странное соединение строки не в культуре J2EE, так как вы знаете, что однажды кто -то может захотеть сделать это I18N. Единственной проблемой является извлечение меток из шаблонов HTML.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top