Назад

gt-next@6.8.0

Ernest McCarter avatarErnest McCarter
gt-reactgt-nextgtx-cliv6.8.0statictranslationi18n

Обзор

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

function getSubject(gender) { 
  return gender === "male" ? "boy" : "girl" 
}
function getObject(toy, gender) { 
  return toy === "ball" ? "ball" : getSubject(gender)
}

function Component({ gender, toy }) {
  return (
    <>
      <p>
        The beautiful {getSubject(gender)} plays with the {getObject(toy, gender)}.
      </p>
    </>
  )
}

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

В gt-next 6.8.0 мы ещё увереннее придерживаемся идеи, что мощная библиотека i18n должна адаптироваться к кодовой базе, а не наоборот. Хотя gt-next уже переводит контент inline, ей по-прежнему не хватает двух ключевых возможностей такой библиотеки: (1) поддержки фрагментации предложений и (2) повторного использования контента с сохранением согласования, спряжения и изменений порядка слов.

Мы представляем компонент <Static>, который позволяет использовать статические вызовы функций прямо внутри переводов.

function getSubject(gender) { 
  return gender === "male" ? "boy" : "girl" 
}
function getObject(type, gender) { 
  return type === "ball" ? "ball" : getSubject(gender)
}

function Component({ gender, toy }) {
  return (
    <T>
      <p>
        The beautiful <Static>{getSubject(gender)}</Static> plays with the <Static>{getObject(toy, gender)}</Static>.
      </p>
    </T>
  )
}

Важные замечания

Тем не менее мы настоятельно рекомендуем использовать компонент <Static> осторожно и только там, где это действительно оправданно. Компонент <Static>, хотя и очень мощный, может значительно увеличить количество записей перевода. При неправильном использовании это может негативно повлиять на время загрузки приложения.

Как использовать <Static>

Как и компоненты <T> и <Var>, компонент <Static> служит маркером, который указывает CLI-инструменту, где искать переводимый контент, а где — нет. Он сообщает CLI-инструменту, что нужно разыменовать вызов функции внутри тегов <Static> и занести в каталог все возможные значения, которые возвращает эта функция. Рассматривайте каждый оператор return так, как если бы он был обёрнут в компонент <T>.

Когда CLI-инструмент находит все возможные результаты вызова функции, он создаёт отдельную запись перевода для каждого из них. Например, следующий код создаёт две отдельные записи перевода: "Мальчик красивый" и "Девочка красивая". Поскольку для каждого возможного результата создаётся отдельная запись перевода, можно поддерживать согласование, спряжение и порядок слов во фрагментированном предложении: "El niño es hermoso" и "La niña es hermosa".

function getSubject(gender) { 
  return gender === "male" ? "boy" : "girl" 
}
function Component({ gender }) {
  return (
    <T>
      The <Static>{getSubject(gender)}</Static> is beautiful.
    </T>
  )
}

Ограничения и планы по улучшению

Умножение

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

function getSubject(gender) { 
  return gender === "male" ? "boy" : "girl" 
}
function getObject(toy) { 
  return toy === "ball" ? "ball" : "crayon"
}
function Component({ gender, toy }) {
  return (
    <T>
      <Static>{getSubject(gender)}</Static> plays with the <Static>{getObject(toy)}</Static>.
    </T>
  )
}

Синтаксис

Важно рассматривать каждый оператор return так, как будто он обёрнут в компонент <T>. Любые переменные или вызовы функций с динамическими значениями по-прежнему должны быть обёрнуты в компоненты <Var>.

Сейчас <Static> поддерживает в качестве дочерних элементов только вызовы функций, но в будущем сможет поддерживать и более сложные выражения. Начиная с gt-next 6.8.0, для статических функций поддерживается следующий синтаксис:

function getExamples(key) {
  switch (key) {
    case "string, number, and boolean literals":
      if (condition1) {
        return "The boy"
      } else if (condition2) {
        return 22
      } else {
        return true
      }
    case "jsx expressions":
      return (
        <>
          Hello, <Static>{getTitle(title)}</Static>. How are you, <Var>{name}</Var>?
        </>
      );
    case "ternary operators":
      return condition ? "The boy" : "The girl"      
    case "function calls":
      return otherStaticFunction();
  }
}

Заключение

gt-next 6.8.0 представляет компонент <Static> как решение проблемы фрагментации предложений без ущерба для полноты перевода и корректного грамматического согласования.