# Синтаксис сообщений локализации

# Структура

Синтаксис сообщений локализации:

// Как определение Flowtype, синтаксис сообщений перевода аналогичен аннотации BNF
type LocaleMessages = { [key: Locale]: LocaleMessageObject }
type LocaleMessageObject = { [key: Path]: LocaleMessage }
type LocaleMessageArray = LocaleMessage[]
type MessageContext = {
  list: (index: number) => mixed,
  named: (key: string) => mixed,
  linked: (key: string) => TranslateResult,
  values: any,
  path: string,
  formatter: Formatter,
  messages: LocaleMessages,
  locale: Locale
};
type MessageFunction = (ctx: MessageContext) => string;
type LocaleMessage = string | MessageFunction | LocaleMessageObject | LocaleMessageArray;
type Locale = string
type Path = string

Используя синтаксис выше, можно создать следующую структуру сообщений локализации:

{
  // локализация 'ru'
  "ru": {
    "key1": "это сообщение 1", // обычное использование
    "nested": {
      // вложенное
      "message1": "это вложенное сообщение 1"
    },
    "errors": [
      // массив
      "это сообщение кода ошибки 0",
      {
        // объект в массиве
        "internal1": "это внутреннее сообщение кода ошибки 1"
      },
      [
        // массив в массиве
        "это вложенный массив ошибки 1"
      ]
    ]
  },
  // локализация 'en'
  "en": {
    // ...
  }
}

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

<div id="app">
  <!-- обычное использование -->
  <p>{{ $t('key1') }}</p>
  <!-- вложенное -->
  <p>{{ $t('nested.message1') }}</p>
  <!-- массив -->
  <p>{{ $t('errors[0]') }}</p>
  <!-- объект в массиве -->
  <p>{{ $t('errors[1].internal1') }}</p>
  <!-- массив в массиве -->
  <p>{{ $t('errors[2][0]') }}</p>
</div>

Результат:

<div id="app">
  <!-- обычное использование -->
  <p>это сообщение 1</p>
  <!-- вложенное -->
  <p>это вложенное сообщение 1</p>
  <!-- массив -->
  <p>это сообщение кода ошибки 0</p>
  <!-- объект в массиве -->
  <p>это внутреннее сообщение кода ошибки 1</p>
  <!-- массив в массиве -->
  <p>это вложенный массив ошибки 1</p>
</div>

# Связанные сообщения локализации

Когда есть ключ с сообщением перевода, которое в точности повторяется в сообщении по другому ключу, то вместо дублирования можно поставить ссылку на него. Для этого к его содержимому нужно добавить префикс @: после которого указать полное имя ключа к сообщению перевода, включая пространство имён, к которому делаем ссылку.

Сообщения локализации:

const messages = {
  en: {
    message: {
      the_world: 'the world',
      dio: 'DIO:',
      linked: '@:message.dio @:message.the_world !!!!'
    }
  }
}

Шаблон:

<p>{{ $t('message.linked') }}</p>

Результат:

<p>DIO: the world !!!!</p>

# Форматирование связанных сообщений локализации

Если важен регистр символов в переводе, то можно управлять регистром связанного сообщения локализации. Связанные сообщения можно отформатировать используя модификатор @.modifier:key

Доступны следующие модификаторы:

  • upper: Форматирование в верхний регистр всех символов в связанном сообщении.
  • lower: Форматирование в нижний регистр всех символов в связанном сообщении.
  • capitalize: Форматирование заглавной первой буквы в связанном сообщении.

Сообщения локализации:

const messages = {
  en: {
    message: {
      homeAddress: 'Home address',
      missingHomeAddress: 'Please provide @.lower:message.homeAddress'
    }
  },
  ru: {
    message: {
      homeAddress: 'Домашний адрес',
      missingHomeAddress: 'Пожалуйста укажите @.lower:message.homeAddress'
    }
  }
}
<label>{{ $t('message.homeAddress') }}</label>

<p class="error">{{ $t('message.missingHomeAddress') }}</p>

Результат:

<label>Домашний адрес</label>

<p class="error">Пожалуйста укажите домашний адрес</p>

При необходимости можно добавлять новые модификаторы или перезаписывать существующие через опцию modifiers в конструкторе VueI18n.

const i18n = new VueI18n({
  locale: 'ru',
  modifiers: {
    // Добавление нового модификатора
    snakeCase: str => str.split(' ').join('-')
  },
  messages: {
    // ...
  },
})

# Группировка с помощью скобок

Ключ связанного сообщения также можно указывать в виде @:(message.foo.bar.baz), где ссылка на другой ключ перевода обрамляется в скобки ().

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

Сообщения локализации:

const messages = {
  en: {
    message: {
      dio: 'DIO',
      linked: "There's a reason, you lost, @:(message.dio)."
    }
  },
  ru: {
    message: {
      dio: 'DIO',
      linked: "Есть причина по которой ты проиграл, @:(message.dio)."
    }
  }
}

Шаблон:

<p>{{ $t('message.linked') }}</p>

Результат:

<p>There's a reason, you lost, DIO.</p>

# Функция для сообщения

vue-i18n рекомендует использовать строки для формата списком или именованного формата в качестве сообщения локализации при переводе сообщений.

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

Функция ниже просто возвращает приветствие:

const messages = {
  en: {
    greeting: (ctx) => 'hello!'
  },
  ru: {
    greeting: (ctx) => 'привет!'
  }
}

Использовать функцию для сообщения очень просто! Необходимо просто указать ключ с помощью $t или t:

<p>{{ $t('greeting') }}</p>

Результат будет таким:

<p>привет!</p>

Используется возвращаемый результат из функции для сообщения.

# Именованный формат

vue-i18n поддерживает именованный формат для строковых сообщений. vue-i18n интерполирует значения с помощью $t или t и выводит их.

Тоже самое можно сделать и с функцией для сообщения, используя контекст сообщения:

Пример приветствия:

const messages = {
  en: {
    greeting: (ctx) => `hello, ${ctx.named('name')}!`
  },
  ru: {
    greeting: (ctx) => `привет, ${ctx.named('name')}!`
  }
}

Шаблон:

<p>{{ $t('greeting', { name: 'DIO' }) }}</p>

Результат:

<p>привет, DIO!</p>

Контекст сообщения предоставляет доступ к функции named. Необходимо указать ключ, указываемым для $t или t, который разрешится требуемым значением.

# Формат списков

Использование формата списков аналогично именованному формату, описанному выше.

vue-i18n поддерживает формат списков для строковых сообщений. vue-i18n интерполирует значения с помощью $t или t и выводит их.

Тоже самое можно сделать и с функцией для сообщения, используя контекст сообщения:

Пример приветствия:

const messages = {
  en: {
    greeting: (ctx) => `hello, ${ctx.list(0)}!`
  },
  ru: {
    greeting: (ctx) => `привет, ${ctx.list(0)}!`
  }
}

Шаблон:

<p>{{ $t('greeting', ['DIO']) }}</p>

Результат:

<p>привет, DIO!</p>

Контекст сообщения предоставляет доступ к функции list. Необходимо указать ключ, указываемым для $t или t, который разрешится требуемым значением.

# Ограничение

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

  • Связанные сообщения локализации
  • Плюрализация