---
title: "How do I use variables in Rails i18n YAML files?"
description: "Put `%{name}` in the YAML value and pass `name` as a keyword argument to `t`. A `count` argument selects the `one`/`other` plural form and is interpolated as well. A missing variable raises `I18n::MissingInterpolationArgument`."
category: localization-files
date: 2026-10-09
canonical: https://localizely.com/i18n-questions/localization-files/how-do-i-use-variables-in-rails-i18n-yaml-files/
---

# How do I use variables in Rails i18n YAML files?

Write the placeholder as `%{name}` in the translation and pass `name:` to `t`. The value is substituted at lookup time, so the YAML file never contains Ruby code or string concatenation.

```yaml
en:
  greeting: "Hello, %{name}!"
  inbox:
    one: "You have %{count} message"
    other: "You have %{count} messages"
```

```erb
<%= t("greeting", name: current_user.first_name) %>
<%= t("inbox", count: @messages.size) %>
```

Rules worth knowing, all from the [Rails i18n guide](https://guides.rubyonrails.org/i18n.html#passing-variables-to-translations):

- Every placeholder in the string must be passed, otherwise `I18n::MissingInterpolationArgument` is raised.
- The option names of `translate` are reserved and cannot be placeholder names: `scope`, `default`, `separator`, `format`, `object`, `resolve`, `cascade`, `fallback`, `raise`, `throw`, `exception_handler`, `deep_interpolation` and `skip_interpolation` (the i18n gem also reserves its internal `fallback_in_progress` and `fallback_original_locale`). A translation containing `%{scope}` raises `I18n::ReservedInterpolationKey`.
- `count` is not reserved but special. When the key resolves to a hash, `count` picks the plural form and is still available as `%{count}`. The built-in rule for `:en` is `zero` if the hash has that key and the count is 0, `one` for 1, `other` for everything else; if the key does not resolve to a hash, `I18n::InvalidPluralizationData` is raised. For languages with more forms (`few`, `many`) add the `rails-i18n` gem, which supplies the locale-specific rules; the forms each language needs are listed at [language plural rules](/language-plural-rules/).
- Placeholders are not reordered by the code, so translators can move `%{name}` anywhere in the sentence, and `%{name}` can appear more than once.

A percent sign on its own is not special, so `"50% off"` needs no escaping. Only `%{...}` and `%<...>` are placeholders (the second form takes a `format` spec, for example `%<price>.2f`). To print the text `%{name}` literally, write `%%{name}`: the interpolation pattern of the i18n gem turns `%%` into a single `%` and leaves `{name}` as plain text.

Keys that end in `_html` (or are named `html`) return an HTML-safe string, and interpolated values are escaped unless they are already HTML-safe:

```yaml
en:
  welcome_html: "<b>Welcome, %{username}!</b>"
```

With `t("welcome_html", username: "<script>")` the tag in the username is escaped while the `<b>` from the translation is kept.

One YAML detail trips people up: a value that starts with `%` has to be quoted (`"%{count} items"`), because `%` is an indicator character in YAML. The other characters that need quoting are covered in [How do I write line breaks and special characters in YAML localization files?](/i18n-questions/localization-files/how-do-i-write-line-breaks-and-special-characters-in-yaml-localization-files/), and the file layout at [Rails YAML file](/rails-yaml-file/).

Source: https://localizely.com/i18n-questions/localization-files/how-do-i-use-variables-in-rails-i18n-yaml-files/
