dchuk/rails_ai_agents · Archived

i18n-patterns

Implements internationalization with Rails I18n for multi-language support. Use when adding translations, managing locales, localizing dates/currencies, pluralization, or when user mentions i18n, translations, locales, or multi-language.

First seen Feb 13, 2026

Installation

$ npx skills add dchuk/rails_ai_agents --skill i18n-patterns

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from dchuk/rails_ai_agents · top by installs.

npx skills add dchuk/rails_ai_agents

Browse all from dchuk/rails_ai_agents

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

License LICENSE
Default branch main
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Allowed toolsRead, Write, Edit, Bash, Glob, Grep

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 6,953 B
  • docs SUMMARY.md 258 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 2 installs

SKILL.md

I18n Patterns for Rails 8

Overview

Rails I18n provides internationalization support:

  • Translation lookups
  • Locale management
  • Date/time/currency formatting
  • Pluralization rules
  • Lazy lookups in views

Quick Start

# config/application.rb
config.i18n.default_locale = :en
config.i18n.available_locales = [:en, :fr, :de]
config.i18n.fallbacks = true

Project Structure

config/locales/
├── en.yml                    # English defaults
├── fr.yml                    # French defaults
├── models/
│   ├── en.yml               # Model translations
│   └── fr.yml
├── views/
│   ├── en.yml               # View translations
│   └── fr.yml
├── mailers/
│   ├── en.yml
│   └── fr.yml
└── components/
    ├── en.yml
    └── fr.yml

Locale File Organization

Models

# config/locales/models/en.yml
en:
  activerecord:
    models:
      event: Event
    attributes:
      event:
        name: Name
        event_date: Event Date
        status: Status
      event/statuses:
        draft: Draft
        confirmed: Confirmed
        cancelled: Cancelled
    errors:
      models:
        event:
          attributes:
            name:
              blank: "can't be blank"

Views

# config/locales/views/en.yml
en:
  events:
    index:
      title: Events
      new_event: New Event
      no_events: No events found
    show:
      edit: Edit
      delete: Delete
      confirm_delete: Are you sure?
    create:
      success: Event was successfully created.
    destroy:
      success: Event was successfully deleted.

Common/Shared

# config/locales/en.yml
en:
  common:
    actions:
      save: Save
      cancel: Cancel
      delete: Delete
      edit: Edit
      back: Back
      search: Search
    messages:
      loading: Loading...
      no_results: No results found
      not_specified: Not specified

Usage Patterns

In Views (Lazy Lookup)

<%# t(".title") resolves to "events.index.title" %>
<h1><%= t(".title") %></h1>

<%# With interpolation %>
<p><%= t(".welcome", name: current_user.name) %></p>

<%# With HTML (use _html suffix) %>
<p><%= t(".intro_html", link: link_to("here", help_path)) %></p>

In Controllers

class EventsController < ApplicationController
  def create
    @event = current_account.events.build(event_params)
    if @event.save
      redirect_to @event, notice: t(".success")
    else
      render :new, status: :unprocessable_entity
    end
  end
end

In Models

class Event < ApplicationRecord
  def status_text
    I18n.t("activerecord.attributes.event/statuses.#{status}")
  end
end

In Presenters

class EventPresenter < BasePresenter
  def formatted_date
    return not_specified if event_date.nil?
    I18n.l(event_date, format: :long)
  end

  private

  def not_specified
    tag.span(I18n.t("common.messages.not_specified"), class: "text-slate-400 italic")
  end
end

Date/Time/Number Formatting

I18n.l(Date.current)                    # "January 15, 2024"
I18n.l(Date.current, format: :short)    # "Jan 15"
I18n.l(Date.current, format: :long)     # "Wednesday, January 15, 2024"

number_to_currency(1234.50)             # "$1,234.50"
number_to_currency(1234.50, locale: :fr) # "1 234,50 EUR"

Pluralization

en:
  events:
    count:
      zero: No events
      one: 1 event
      other: "%{count} events"
t("events.count", count: 0)   # "No events"
t("events.count", count: 1)   # "1 event"
t("events.count", count: 5)   # "5 events"

Locale Switching

URL-Based

# config/routes.rb
scope "(:locale)", locale: /en|fr|de/ do
  resources :events
end

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  around_action :switch_locale

  private

  def switch_locale(&action)
    locale = params[:locale] || I18n.default_locale
    I18n.with_locale(locale, &action)
  end

  def default_url_options
    { locale: I18n.locale }
  end
end

User Preference

def switch_locale(&action)
  locale = current_user&.locale || extract_locale_from_header || I18n.default_locale
  I18n.with_locale(locale, &action)
end

Testing I18n

Missing Translation Detection

# test/i18n_test.rb
require "test_helper"

class I18nTest < ActiveSupport::TestCase
  test "no missing translations for English" do
    # Use i18n-tasks gem for comprehensive checks
    # Or manually verify critical paths
    assert I18n.t("events.index.title", locale: :en).present?
    assert I18n.t("events.create.success", locale: :en).present?
  end

  test "all available locales have required keys" do
    required_keys = %w[
      events.index.title
      events.create.success
      common.actions.save
      common.actions.cancel
    ]

    I18n.available_locales.each do |locale|
      required_keys.each do |key|
        translation = I18n.t(key, locale: locale, raise: true)
        assert translation.present?, "Missing #{locale}.#{key}"
      end
    end
  end
end

View Translation Test

# test/controllers/events_controller_test.rb
require "test_helper"

class EventsI18nTest < ActionDispatch::IntegrationTest
  setup do
    sign_in users(:one)
  end

  test "index page uses translations" do
    get events_path
    assert_response :success
    assert_includes response.body, I18n.t("events.index.title")
  end

  test "index page works in French" do
    get events_path(locale: :fr)
    assert_response :success
    assert_includes response.body, I18n.t("events.index.title", locale: :fr)
  end
end

i18n-tasks Gem

bundle exec i18n-tasks missing     # Find missing translations
bundle exec i18n-tasks unused      # Find unused translations
bundle exec i18n-tasks normalize   # Normalize locale files
bundle exec i18n-tasks health      # Health check

Best Practices

  • Use lazy lookups in views: t(".title") not t("events.index.title")
  • Use _html suffix for HTML content
  • Use interpolation for dynamic content: t(".greeting", name: name)
  • Organize locale files by domain (models, views, mailers)
  • Never hardcode user-facing strings in views
  • Never concatenate translations

Checklist

  • Locale files organized by domain
  • All user-facing text uses I18n
  • Lazy lookups in views
  • Pluralization for countable items
  • Date/currency formatting localized
  • Locale switching implemented
  • Missing translation detection in tests
  • All tests GREEN