Подтвердить что ты не робот

Рефакторинг Ruby on Rails i18n Файлы YAML с использованием словарей

This Вопрос StackOverflow дал мне пищу для размышлений о том, что является хорошей структурой для файлов Rails i18n, поэтому я решил поделиться другой структурой для реорганизации Rails i18n yml файлы для вашего рассмотрения/критики.

Учитывая, что я хотел бы

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

для файла config/locales/en.yml, который выглядит примерно так:

activerecord:
  attributes:
    user:
      email: Email
      name: Name
      password: Password
      password_confirmation: Confirmation
  models:
    user: User
users:
  fields:
    email: Email
    name: Name
    password: Password
    confirmation: Confirmation
sessions:
  new:
    email: Email
    password: Password

Я вижу, что есть значительное повторение, и что контекст таких слов, как "Электронная почта" и "Пароль", недвусмыслен и имеет то же значение в их соответствующих представлениях. Было бы немного досадно, что нужно пойти и изменить их все, если я решит изменить "Email" на "e-mail", поэтому я бы хотел реорганизовать строки для ссылки на какой-то словарь. Итак, как насчет добавления хеш-словаря в верхнюю часть файла с помощью некоторых привязанных &:

dictionary:
  email: &email Email
  name: &name Name
  password: &password Password
  confirmation: &confirmation Confirmation

activerecord:
  attributes:
    user:
      email: *email
      name: *name
      password: *password
      password_confirmation: *confirmation
  models:
    user: User
users:
  fields:  
    email: *email
    name: *name
    password: *password
    confirmation: *confirmation
sessions:
  new:
    email: *email
    password: *password

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

Этот способ структурирования файлов i18n yaml, похоже, хорошо работает с некоторыми локальными тестовыми приложениями, в которых я его пробовал. Я надеюсь, что замечательный Localeapp обеспечит поддержку такого рода привязки/ссылки в будущем. Но, в любом случае, все эти словарные разговоры не могут быть оригинальной идеей, так же есть ли другие проблемы с привязкой привязки в YAML или, может быть, просто с общей концепцией "словаря" вообще? Или просто лучше просто полностью удалить бэкэнд по умолчанию и заменить его Redis или что-то, если у вас есть потребности за пределами Rails по умолчанию i18n конвенции?

Edit

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

Точка 1: у вас есть общий атрибут "name" для моделей ActiveRecord, и все они просто указывают на общий словарь для имени:

dictionary:
  name: &name Name

activerecord:
  attributes:
    name: *name
    user:
      name: *name
    product:
      name: *name

Точка 2: нужно изменить имя для модели пользователя. Другие имена остаются прежними.

Вариант 1. Сохраните имена полей модели одинаково на бэкэнд и просто измените перевод на передний конец, на который он указывает.

dictionary:
  name: &name Name
  full_name: &full_name Full Name

activerecord:
  attributes:
    name: *name
    user:
      name: *full_name
    product:
      name: *name

Вариант 2. Измените имя поля модели пользователя. Это потребует изменения любых ссылок на этот ключ в коде и миграции change_table/rename_column.

dictionary:
  name: &name Name
  full_name: &full_name Full Name

activerecord:
  attributes:
    name: *name
    user:
      full_name: *full_name
    product:
      name: *name

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

dictionary:
  name: &name Name
  name_prefix: &name_prefix Prefix
  first_name: &first_name First
  middle_name: &middle_name Middle
  last_name: &last_name Last
  name_suffix: &name_suffix Suffix

activerecord:
  attributes:
    name: *name
    user:
      name_prefix: *name_prefix
      first_name: *first_name
      middle_name: *middle_name
      last_name: *last_name
      name_suffix: *name_suffix
    product:
      name: *name

Точка 3. Любой человек по какой-либо причине нуждается в изменении перевода, в этом случае маркетинге. Я последую примеру 2 Вариант 1

Вариант 1: имена полей модели одинаковы, просто измените трансляцию переднего конца.

dictionary:
  name: &name Name
  full_name: &full_name Full Name
  funky_name: &funky_name Ur Phunky Phresh Naym

activerecord:
  attributes:
    name: *name
    user:
      name: *full_name
    product:
      name: *name
sessions: # Sign up page keys
  new:
    name: *funky_name

Вариант 2: "Funky name" отчаянно необходимо также сохранить в базе данных по какой-либо причине. Позвольте называть его username, если никто не указывает (или funky_name, если по какой-то причине настаивает маркетинг).

dictionary:
  name: &name Name
  full_name: &full_name Full Name
  funky_name: &funky_name Ur Phunky Phresh Naym

activerecord:
  attributes:
    name: *name
    user:
      name: *full_name
      username: *funky_name
    product:
      name: *name
sessions: # Sign up page keys
  new:
    name: *name
    funky_name: *funky_name

Правильно, поэтому я признаю, что у меня мало идеи, что я делаю, однако я готов публично сфотографироваться, чтобы понять, почему этот способ работы с i18n в Haml - плохая идея в Rails приложение. Трудно читать? Кошмар для обслуживания? Действительно ли это считается "взломать формат файла", если я использую (как мне кажется) особенность языка?

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

4b9b3361

Ответ 1

TLDNR; Не взламывайте свой формат файла, не улучшайте помощники рельсов и не создавайте стандартную структуру ключей!

TL;DR;

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

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

Во-первых, якорь действительно гарантированно работает для YAML, поэтому это решение не может применяться в общем случае к I18n. Этот метод, вероятно, невозможен, если вы используете другой бэкэнд. Будь то SQL, Redis или Json, я не знаю, кто из них обладает какой-либо символической функциональностью. И это, не задумываясь о том, что под капотом переводы фактически дублируются.

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

Несомненно, по мере роста вашего приложения или добавления дополнительных языков вы обнаружите, что атрибут "имя" Person должен отличаться от атрибута "Имя" книги, который на английском языке мы будем называть "заголовком", - Хорошо, этот пример действительно запутан;), но по мере того, как вы смешиваете все больше и больше языков, эта ситуация происходит часто и в идеале, нам нужен общий способ борьбы с ней.

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

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

Позвольте мне привести пример рабочего процесса, который является очень частым:

  • В этой ситуации вы создаете форму с полем "Имя" пользователя, вы хотите использовать общие атрибуты атрибутов "name" (label_tag должен использовать что-то вроде: "attributes.name" ). Это самый простой, DRYest случай, который поможет вам быстро и быстро выполнить массовый перевод простых атрибутов.
  • Позже вы решите, что имя пользователя "имя" должно быть переведено как "полное имя" для этой модели только для того, чтобы вы создали новый перевод, который имеет более высокий приоритет в вызове look_tag label (скажем: "activerecord.attributes.users.name '))
  • Позже, у маркетолога есть блестящая идея отобразить этот полевой ярлык как "введите свое фанковое свежее имя" на этой странице (и только на этой странице). Мы больше не описываем атрибут name, мы описываем конкретный вид этой формы; это - то, где ярлык точки приходит в преобразовании: '. form.name' к чему-то вроде:: users.new.form.name.

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

С положительной стороны, мы можем получить более четкое представление о том, какой контент мы описываем и отражаем, что в наших ключевых структурах и в наших инструментах - это для меня путь вперед!:)

Ответ 2

Я только что выпустил драгоценный камень под названием i18n-recursive-lookup, который позволяет определению содержать встроенные ссылки на другие определения, введя специальный встроенный маркер ${}

https://github.com/annkissam/i18n-recursive-lookup

Используя его, вы можете реорганизовать свой пример:

dictionary:
  email: Email
  name: Name
  password: Password
  confirmation: Confirmation

activerecord:
  attributes:
    user:
      email: ${dictionary.email}
      name: ${dictionary.name}
      password: ${dictionary.password}
      password_confirmation: ${dictionary.confirmation}
  models:
    user: User
users:
  fields:  
    email: ${dictionary.email}
    name: ${dictionary.name}
    password: ${dictionary.password}
    confirmation: ${dictionary.confirmation}
sessions:
  new:
    email: ${dictionary.email}
    password: ${dictionary.password}

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

Я знаю, что это может не отвечать на более философские вопросы о том, что означает "правильный" способ СУХОЙ ПЕРЕВОДЫ, но я подумал, что это лучшая альтернатива использованию хэша YML и ссылки на ярлыки.

Ответ 3

Улучшение рефакторинга файлов YAML, особенно для тех, у кого много моделей:

ru:
  dictionary:
    name: &name "Имя"
    title_ru: &title_ru "Заголовок (ru)"
    title_en: &title_en "Заголовок (en)"
    content_ru: &content_ru "Содержание (ru)"
    content_en: &content_en "Содержание (en)"
    role: &role "Роль"
    created_at: &created_at "Создано в"
    updated_at: &updated_at "Обновлено в"
    published: &published "Опубликовано"

    nomination: &nomination
      name: *name
      title_ru: *title_ru
      title_en: *title_en

    post: &post
      content_ru: *content_ru
      content_en: *content_en
      published: *published

    dates: &dates
      created_at: *created_at
      updated_at: *updated_at

  activerecord:
    attributes:
      article:
        <<: *nomination
        <<: *post
        <<: *dates

      user:
        <<: *dates
        role: *role
        email: "Электропочта"

Userful ссылка

Ответ 4

Я только что выпустил драгоценный камень под названием dry_i18n: https://rubygems.org/gems/dry_i18n

Я создал этот камень, чтобы решить вопрос, который вы просите. С этим камнем вы сможете даже повторно использовать клавиши с интерполяциями и вставлять их.

Надеюсь, это полезно.