I18n questions · Localization 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.
en:
greeting: "Hello, %{name}!"
inbox:
one: "You have %{count} message"
other: "You have %{count} messages"
<%= t("greeting", name: current_user.first_name) %>
<%= t("inbox", count: @messages.size) %>
Rules worth knowing, all from the Rails i18n guide:
I18n::MissingInterpolationArgument is raised.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.%{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:
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?, and the file layout at Rails YAML file.
Published Oct 9, 2026 · Markdown version