PTC

בינאום (i18n) ב־Rails: המדריך המלא

הגדירו את Rails I18n, ארגנו את config/locales/*.yml, בצעו אוטומציה לתרגומי YAML בעזרת בינה מלאכותית, ואפשרו ל־PTC (Private Translation Cloud) לסקור את אפליקציית ה־Rails הפעילה שלכם בכל גרסה. בסיום המדריך תהיה לכם אפליקציית Rails שמגיבה לכתובות /es/..., מציגה תצוגות (views) מתורגמות ליותר מ־40 שפות, ומאומתת באמצעות סקירה חזותית.

מדריך זה מניח שיש לכם אפליקציית Rails 7+ קיימת. המושגים תקפים גם לגרסאות Rails ישנות יותר עם הבדלי API מינוריים. ה־gem של I18n עצמו יציב כבר שנים. לסיפור המלא של לוקליזציה בצינורות CI/CD על פני סביבות פיתוח שונות, ראו לוקליזציית תוכנה מבוססת בינה מלאכותית המיועדת לצינורות CI/CD.

הגדרת Rails לטעינת שפות, זיהוי כתובות URL והחלפת שפה בכל בקשה

בינאום ב־Rails דורש שלושה שלבי הגדרה: הצהרה על השפות הזמינות, הוספת השפה לכתובות ה־URL שלכם, והגדרת Rails לטעינת השפה הנכונה עבור כל בקשה. בנוסף, התקינו את ה־gem‏ rails-i18n עבור נתוני השפות.

הצהרה על השפות הזמינות ב־config/application.rb

בתוך config/application.rb, הגדירו ב־Rails באילו שפות האפליקציה תומכת וקבעו שפת ברירת מחדל:

module MyApp
  class Application < Rails::Application
    config.i18n.available_locales = [:en, :es, :fr, :de, :ja]
    config.i18n.default_locale = :en
    config.i18n.fallbacks = true
    config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
  end
end

השורה load_path += Dir[...] היא שורת המפתח. כברירת מחדל, Rails טוענת רק את config/locales/*.yml (ברמה אחת בלבד). הוספת ה־glob הרקורסיבי מאפשרת לכם לארגן תרגומים לפי namespace, מודל או פיצ'ר בתוך תיקיות משנה.

הוספת :locale לטווח הכתובות (URL scope)

הוסיפו scope של :locale כדי שלכל שפה יהיה נתיב משלה, כמו /en/time או /es/time:

# config/routes.rb
scope "/:locale" do
  get '/time', to: 'home#index', as: :time_display
end

החלפת שפה בכל בקשה בעזרת I18n.with_locale

ב־ApplicationController, טענו את השפה הנכונה מהכתובת וכללו אותה בכל הקישורים שנוצרים:

class ApplicationController < ActionController::Base
  around_action :switch_locale

  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

השימוש ב־I18n.with_locale הוא הדרך האידיומטית להגדיר שפה עבור בקשה מסוימת. הפקודה מגדירה את השפה, מריצה את הבלוק, מחזירה את השפה הקודמת, והיא בטוחה לשימוש בריבוי תהליכונים (thread-safe). הפונקציה default_url_options מבטיחה שכל כתובת URL ש־Rails מייצרת תישא את השפה הנוכחית, כך שהמשתמשים יישארו בשפה שבחרו בזמן הניווט.

התקנת rails-i18n עבור שמות חודשים מתורגמים וכללי ריבוי

ה־gem‏ rails-i18n מספק נתוני שפה עבור עשרות שפות. הוא כולל שמות חודשים מתורגמים, כללי ריבוי והודעות שגיאה מובנות של Rails. כך לא תצטרכו לתרגם את הטקסטים הקבועים האלה בעצמכם.

# Gemfile
gem 'rails-i18n'
bundle install

אפליקציית ה־Rails שלכם מוגדרת כעת באופן מלא לבינאום.

הוספת בורר שפות בעזרת url_for(locale: :code)

מכיוון ש־default_url_options כולל אוטומטית את השפה בכל כתובת URL שנוצרת, בורר השפות שלכם רק צריך לעדכן את הפרמטר :locale תוך השארת המשתמש באותו דף.

<%# app/views/layouts/application.html.erb %>
<nav class="language-switcher">
  <%= link_to "English", url_for(locale: :en) %> |
  <%= link_to "Español", url_for(locale: :es) %> |
  <%= link_to "Deutsch", url_for(locale: :de) %>
</nav>

כל קישור משתמש ב־url_for(locale: :code) כדי ליצור כתובת URL עם השפה המבוקשת. כאשר משתמשים לוחצים על הקישור, הפונקציה switch_locale ב־ApplicationController מזהה את השינוי ו־Rails מרנדרת את הדף בשפה החדשה.

החלפת טקסט קשיח בתצוגות בעזרת t(:key)

טקסט קשיח (hardcoded) לא יופיע בקובצי ה־YAML שלכם, מה שאומר שלא ניתן יהיה לתרגם אותו. השתמשו תמיד במפתחות תרגום עבור כל טקסט שמוצג למשתמש.

<%# Correct - uses translation keys %>
<h1><%= t(:hello) %></h1>
<p><%= t(:current_time, time: @time) %></p>
<button id="click-me"><%= t(:refresh) %></button>

<%# Incorrect - hardcoded text %>
<h1>Hello</h1>
<p>Current time: <%= @time %></p>
<button>Refresh</button>

בבקרים (עבור הודעות flash):

def create
  if @post.save
    redirect_to @post, notice: t('flash.post.created')
  else
    flash.now[:alert] = t('flash.post.error')
    render :new, status: :unprocessable_entity
  end
end

במודלים (עבור הודעות ולידציה, השתמשו במוסכמות של Active Model):

# config/locales/en.yml
en:
  activerecord:
    attributes:
      post:
        title: "Title"
    errors:
      models:
        post:
          attributes:
            title:
              blank: "is required"

שיבוץ משתנים בעזרת %{name}

הביטוי %{name} בתוך ה־YAML יוחלף בערך שתעבירו לפונקציה t():

current_time: "Current time: %{time}"
<%= t(:current_time, time: @time) %>

שימוש בחיפוש עצל (.key) עבור תרגומים בטווח התצוגה

כאשר מפתחות התרגום שלכם מאורגנים בהתאם למבנה תיקיות התצוגה, השתמשו בנקודה בתחילת המפתח. Rails ישלים את הקידומת מהתצוגה הנוכחית:

<%# Instead of this: %>
<%= t('home.index.hello') %>

<%# Use this: %>
<%= t('.hello') %>

Rails מזהה שאתם נמצאים ב־home/index.html.erb ומוסיפה את הקידומת home.index. באופן אוטומטי. אם תשנו שם או מיקום של תצוגה, נתיבי החיפוש העצל יתעדכנו מעצמם.

ארגון config/locales/ לפי פיצ'רים במקום קובץ en.yml ענק אחד

באפליקציה אמיתית, קובץ en.yml ענק הופך לבלתי ניתן לתחזוקה. ארגנו את הקבצים לפי פיצ'רים:

config/locales/
  en.yml                       # global / shared keys
  models/
    post.en.yml
  views/
    posts.en.yml
    home.en.yml
  flash.en.yml

דוגמה לקובץ config/locales/views/posts.en.yml:

en:
  posts:
    index:
      title: "All Posts"
      empty: "No posts yet"
    new:
      title: "Create a New Post"
    show:
      published_at: "Published %{date}"
      comments_count:
        zero: "No comments yet"
        one: "1 comment"
        other: "%{count} comments"

מוסכמות:

  • מפתחות מקוננים מקבצים מחרוזות קשורות ומאפשרים חיפוש עצל.
  • שיבוץ %{name} עבור משתנים בתוך השורה.
  • מפתחות ריבוי zero / one / other עבור שמות עצם ספירים. Rails מפנה למפתח הנכון בהתבסס על count:: t('posts.show.comments_count', count: 5).

הוספת מחרוזות JavaScript גם ל־YAML

Rails אינה מחלצת אוטומטית טקסט מקובצי JavaScript. כל טקסט בצד הלקוח (התראות, חלוניות עזרה, הודעות אישור) צריך להימצא בתוך קובצי ה־YAML שלכם כדי שיעבור תרגום יחד עם כל השאר:

en:
  confirm: "Are you sure?"

כאשר תתרגמו בעזרת PTC בסעיף הבא, המחרוזות הללו יעברו יחד עם שאר הטקסטים.

תרגום config/locales/*.en.yml עם PTC ב־4 שלבים

לאחר שקובצי התרגום שלכם מוכנים, אתם זקוקים לגרסאות עבור כל שפת יעד. PTC מטפלת בזה:

  1. פתחו פרויקט PTC ובחרו באנגלית כשפת המקור. תקופת הניסיון בחינם מכסה 20,000 מילים ל־2 שפות, ללא צורך בכרטיס אשראי.
  2. העלו את קובצי ה־config/locales/*.en.yml שלכם. PTC מנתחת את ה־YAML, מזהה את מפתחות הריבוי של Rails (כמו zero, one, other, few, many), ושומרת על שיבוצי ה־%{name}.
  3. הוסיפו תיאור קצר של אפליקציית ה־Rails וקהל היעד שלכם. PTC משתמשת בהקשר זה כדי לתרגם בטון ובמונחים הנכונים.
  4. בחרו שפות יעד ואשרו. PTC מייצרת קבצים כמו posts.es.yml, posts.fr.yml ו־posts.de.yml, הזהים מבנית למקור עם ערכים מתורגמים. צורות הריבוי נוצרות בהתאם לכל שפה. פולנית תקבל one / few / many / other. יפנית תקבל רק other.

מקמו את הקבצים בתיקיית config/locales/views/, הפעילו מחדש את שרת ה־Rails, והאפליקציה תציג את השפות החדשות.

עבור פרויקטים מבוססי Git, חברו את PTC למאגר שלכם. מחרוזות חדשות בכל קובץ *.en.yml יפעילו תרגום אוטומטי. PTC תפתח PR עם קובצי שפות היעד המעודכנים. ראו את רפרנס ה־API של PTC עבור תהליך הסנכרון.

שימוש ב־I18n.with_locale בתהליכי רקע, מיילים ומשימות cron

התבנית I18n.with_locale(locale, &block) קריטית עבור כל קוד שרץ מחוץ לבקשה רגילה. זה כולל תהליכי רקע (background jobs), משימות cron ושליחת מיילים (mailers).

# Background job: send an email in the user's preferred locale
class WelcomeEmailJob < ApplicationJob
  def perform(user_id)
    user = User.find(user_id)
    I18n.with_locale(user.preferred_locale) do
      UserMailer.welcome(user).deliver_now
    end
  end
end

ללא with_locale, התהליך ירוץ בשפה שהייתה פעילה בזמן שה־worker הופעל. בדרך כלל :en, ללא קשר להעדפת המשתמש. בעזרתה, המייל ירונדר בשפת המשתמש והשפה תתאפס בסיום הבלוק.

ייצוא תרגומי Rails ל־JSON בעזרת i18n-js לשימוש בצד הלקוח

דפים המרונדרים ב־Rails מקבלים תרגומים דרך t() ב־ERB. קוד JavaScript שרץ בדפדפן לא רואה את ה־I18n של Rails ישירות. התבנית הנקייה ביותר משתמשת ב־gem‏ i18n-js כדי לייצא תרגומים כ־JSON ולטעון אותם בצד הלקוח.

# Gemfile
gem 'i18n-js'
bundle install
i18n init

עדכנו את ההגדרה שנוצרה כדי לייצא תרגומים ל־public/locales.json:

# config/i18n.rb
require "i18n-js"

I18n::JS.config do |config|
  config.export_i18n_js = false
  config.translations_path = "public/locales.json"
end

צרו את קובץ ה־JSON:

i18n export

פעולה זו קוראת את כל קובצי ה־YAML שלכם (en.yml, es.yml, de.yml) וכותבת את public/locales.json עם כל התרגומים בפורמט קריא ל־JS.

בצעו pin ל־i18n-js בעזרת Importmap ב־Rails 7+:

# config/importmap.rb
pin "i18n-js", to: "https://esm.sh/i18n-js@latest/dist/import/index.js"
pin "load_locale", to: "load_locale.js"

צרו טוען (loader):

// app/javascript/load_locale.js
export async function loadLocale() {
  const response = await fetch('/locales.json');
  return await response.json();
}

העבירו את השפה הנוכחית ל־JavaScript דרך תגית ה־<body>:

<%# app/views/layouts/application.html.erb %>
<body data-locale="<%= I18n.locale %>">

לאחר מכן השתמשו בתרגומים בתוך ה־JavaScript שלכם:

// app/javascript/application.js
import { I18n } from "i18n-js";
import { loadLocale } from "./load_locale";

document.addEventListener('turbo:load', async () => {
  const translations = await loadLocale();
  const i18n = new I18n(translations);
  i18n.locale = document.body.dataset['locale'];

  if (confirm(i18n.t('confirm'))) {
    // User clicked OK
  }
});

הפונקציה i18n.t() עובדת בדומה ל־helper‏ t של Rails. כאשר משתמשים מחליפים שפה, ה־JavaScript משתמש בתרגומים הנכונים מתוך המאפיין data-locale.

תרגום תוכן ActiveRecord בעזרת ה־API של PTC

התבנית שלעיל מתרגמת מחרוזות סטטיות בקובצי ה־YAML שלכם. תוכן ActiveRecord (פוסטים של משתמשים, תגובות, תיאורי מוצרים שנשמרים כקלט משתמש) אינו מופיע ב־YAML ודורש גישה שונה. ה־REST API של PTC מתרגם תוכן זה לפי דרישה עם אימות Bearer-token, תוך שימוש באותו מילון מונחים ובאותו טון מותג כמו קובצי ה־config/locales/*.yml שלכם. שלחו את התוכן שלכם בבקשת POST ל־PTC, ולאחר מכן קבלו callback כשהתרגומים מוכנים או בדקו את הסטטוס מתוך תהליך רקע.

לוקליזציה של תאריכים, מספרים ומטבעות בעזרת ה־helpers של Rails

תאריכים וזמנים. השתמשו ב־helper‏ l (קיצור של localize):

<%= l Time.now, format: :long %>

ה־gem‏ rails-i18n מספק פורמטים של תאריך/זמן כברירת מחדל עבור שפות רבות, כולל שמות חודשים מתורגמים ועיצוב מותאם לשפה. ניתן להגדיר פורמטים מותאמים אישית בקובצי ה־YAML שלכם.

מספרים ומטבעות. Rails כוללת helpers המותאמים לשפה:

<%= number_to_currency(100, locale: :es) %>   <!-- 100,00 € -->
<%= number_with_delimiter(1000000) %>          <!-- 1,000,000 -->

אלו מכבדים את מוסכמות השפה עבור מפרידים עשרוניים, מפרידי אלפים וסימני מטבע.

תצוגות מותאמות לפי שפה. עבור דפים עם תוכן שונה משמעותית בכל שפה, צרו קובצי תצוגה נפרדים. Rails תרנדר את התצוגה המתאימה בהתבסס על השפה הנוכחית:

app/views/pages/
  about.html.erb       <!-- Default -->
  about.es.html.erb    <!-- Spanish version -->
  about.de.html.erb    <!-- German version -->

סקירת תרגום חזותית של אפליקציית ה־Rails הפעילה – הפצה ללא QA ידני בכל גרסה

לאחר ש־PTC מתרגמת את קובצי ה־config/locales/*.yml שלכם, עדיין יש צורך לאמת את אפליקציית ה־Rails המרונדרת. תווית מתורגמת עלולה לחרוג מגבולות הכפתור בגרמנית. הודעת אימות בצרפתית עלולה להשתמש בצורה דקדוקית שגויה. מחרוזת אנגלית קשיחה בתבנית ERB (ללא קריאה ל־t()) תוצג ללא תרגום ללא קשר למספר השפות שאתם מפיצים.

ה־AI Visual QA של PTC מחליף את שלב ה־QA הידני. עבור אפליקציות Rails (מבוססות דפדפן), התקינו את ה־browser extension של PTC והקליטו מעבר מוקלט (walkthrough) של המסכים הקריטיים באפליקציה (כניסה, תהליכים מרכזיים, דפי ניהול). מאותו רגע, PTC מריצה מחדש את ההקלטה בכל שפת יעד לאחר כל עדכון תרגום, מצלמת כל מסך ומדווחת בחזרה:

  • תיקונים בקובצי ה־YAML כאשר הם בשליטת PTC. PTC מתרגמת מחדש משמעות שגויה, בוחרת מילה נרדפת קצרה יותר או מייצרת מחדש צורת ריבוי.
  • הנחיות ל־Cursor / Claude Code כאשר הבעיה נמצאת בקוד ה־Ruby או ה־ERB שלכם. מחרוזת אנגלית קשיחה מחוץ ל־t(), הודעת flash שנבנתה על ידי שרשור במקום שיבוץ, או helper שצריך להשתמש ב־I18n.l עבור עיצוב תאריך.

התוצאה: אפליקציית Rails רב־לשונית מאומתת בכל גרסה. לא רק קובצי YAML מתורגמים.

תרגום הערות גרסה, מיילים של Devise ודפי שיווק

הערות הגרסה שלכם, מיילים ללקוחות שנשלחים דרך Devise או Action Mailer ודפי שיווק נמצאים מחוץ ל־config/locales. הכלי Paste to Translate של PTC מטפל בטקסטים האלה באותו פרויקט. הדביקו את טקסט המקור בלוח הבקרה של PTC, בחרו שפות יעד וקבלו בחזרה תרגומים המשתמשים באותו מילון מונחים ובאותו טון מותג כמו תרגומי ה־YAML שלכם.

תרגמו את קובצי ה־config/locales/*.yml שלכם עם PTC

התחילו תקופת ניסיון של 30 יום בחינם – 20,000 מילים ל־2 שפות, ללא צורך בכרטיס אשראי. העלו את קובצי ה־YAML שלכם, קבלו גרסאות מתורגמות תוך דקות, ולאחר מכן התקינו את תוסף הדפדפן כדי לאמת את אפליקציית ה־Rails הפעילה שלכם.

נושאים קשורים: