בינאום (i18n) ב־Rails: המדריך המלא
הגדירו את ה־I18n של Rails, ארגנו את config/locales/*.yml, הפכו את תרגומי ה־YAML לאוטומטיים בעזרת בינה מלאכותית, ותנו ל־PTC (Private Translation Cloud) לסקור את אפליקציית ה־Rails שלכם כשהיא רצה בכל שחרור גרסה. בסוף התהליך תהיה לכם אפליקציית Rails שמגיבה לכתובות URL מסוג /es/..., מגישה קובצי תצוגה מתורגמים ביותר מ־40 שפות, ומאומתת על ידי סקירה חזותית.
מדריך זה יוצא מנקודת הנחה שיש לכם אפליקציית Rails מגרסה 7 ומעלה קיימת. העקרונות תקפים גם לגרסאות ישנות יותר של Rails עם הבדלי API קלים. ה־gem של I18n עצמו יציב כבר שנים. לקריאה על התמונה המלאה של לוקליזציה ב־CI/CD על פני סטאקים שונים, ראו לוקליזציית תוכנה מבוססת בינה מלאכותית שנבנתה עבור צינורות CI/CD.
הגדירו את Rails לטעון locales, לזהות כתובות URL, ולהחליף שפה בכל בקשה
בינאום ב־Rails דורש שלושה שלבי הגדרה. הגדרת ה־locales הזמינים, הוספת ה־locale לכתובות ה־URL שלכם, וגרימה לכך ש־Rails תטען את ה־locale הנכון בכל בקשה. בנוסף, תתקינו את ה־gem rails-i18n עבור נתוני ה־locale.
הצהירו על ה־locales הזמינים ב־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 ל־scope של כתובת ה־URL שלכם
הוסיפו scope של :locale כך שלכל שפה יהיה נתיב משלה, כמו /en/time או /es/time:
# config/routes.rb
scope "/:locale" do
get '/time', to: 'home#index', as: :time_display
end
החליפו locale בכל בקשה בעזרת I18n.with_locale
ב־ApplicationController, טענו את ה־locale הנכון מכתובת ה־URL וכללו אותו בכל הקישורים המיוצרים:
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 היא הדרך המקובלת להגביל locale לבקשה ספציפית. היא מגדירה את ה־locale, מריצה את הבלוק, משחזרת את ה־locale הקודם, והיא thread-safe. השיטה default_url_options מבטיחה שכל כתובת URL ש־Rails מייצרת תישא את ה־locale הנוכחי, כך שהמשתמשים יישארו בשפה שבחרו בזמן שהם מנווטים באתר.
התקינו את rails-i18n עבור שמות חודשים מתורגמים וכללי צורות רבים
ה־gem rails-i18n מספק נתוני locale עבור עשרות שפות. gem זה כולל שמות חודשים מתורגמים, כללי צורות רבים והודעות שגיאה של Rails המוגדרות כברירות מחדל. כך שלא תצטרכו לתרגם את ה־boilerplate הזה בעצמכם.
# Gemfile
gem 'rails-i18n'
bundle install
אפליקציית ה־Rails שלכם מוגדרת כעת במלואה לבינאום.
הוסיפו בורר שפה בעזרת url_for(locale: :code)
מכיוון ש־default_url_options כולל אוטומטית את ה־locale בכל כתובת 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 עם ה־locale שצוין. כאשר משתמשים לוחצים, switch_locale ב־ApplicationController מזהה את השינוי ו־Rails מרנדרת את העמוד בשפה החדשה.
החליפו מחרוזות מוטמעות בקוד בקובצי תצוגה ב־t(:key)
מחרוזות מוטמעות בקוד לא יופיעו בקובצי ה־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>
ב־controllers (עבור הודעות 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) %>
השתמשו ב־lazy lookup (.key) עבור תרגומים ברמת קובץ התצוגה
כאשר מפתחות התרגום שלכם מאורגנים כך שיתאימו למבנה תיקיות קובצי התצוגה שלכם, השתמשו בנקודה מובילה. Rails תשבץ את הקידומת מקובץ התצוגה הנוכחי:
<%# Instead of this: %>
<%= t('home.index.hello') %>
<%# Use this: %>
<%= t('.hello') %>
Rails מזהה שאתם נמצאים ב־home/index.html.erb ומוסיפה את הקידומת home.index.. אם תשנו את השם או המיקום של קובץ תצוגה, נתיבי ה־lazy lookup יתעדכנו אוטומטית.
ארגנו את 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"
מוסכמות:
- מפתחות מקוננים מקבצים יחד מחרוזות קשורות ומאפשרים lazy lookup.
- אינטרפולציה של
%{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 מטפלת בזה:
- התחילו פרויקט PTC ובחרו באנגלית כשפת המקור. תקופת הניסיון מכסה 20,000 מילים ל־2 שפות, ללא כרטיס אשראי.
- העלו את קובצי ה־
config/locales/*.en.ymlשלכם. PTC מנתחת את ה־YAML, מזהה את מפתחות צורות הרבים של Rails (zero,one,other,few,many), ומשמרת את האינטרפולציות של%{name}. - הוסיפו תיאור קצר של אפליקציית ה־Rails וקהל היעד שלכם. PTC משתמשת בהקשר הזה כדי לתרגם בטון ובטרמינולוגיה הנכונים.
- בחרו שפות יעד ואשרו. PTC מפיקה את
posts.es.yml,posts.fr.yml,posts.de.yml, הזהים מבנית למקור עם ערכים מתורגמים. צורות רבים מיוצרות לכל שפה. פולנית מקבלתone/few/many/other. יפנית מקבלת רקother.
הכניסו את הקבצים בחזרה לתוך config/locales/views/, הפעילו מחדש את שרת ה־Rails שלכם, והאפליקציה תגיש את השפות החדשות.
עבור פרויקטים מבוססי Git, חברו את PTC למאגר שלכם. מחרוזות חדשות בכל *.en.yml יפעילו תרגום אוטומטי. PTC פותחת merge request עם קובצי שפות היעד המעודכנים. ראו את מדריך ה־API של PTC עבור ה־endpoints העומדים בבסיס התהליך.
השתמשו ב־I18n.with_locale ב־background jobs, ב־mailers ובמשימות cron
התבנית I18n.with_locale(locale, &block) קריטית עבור כל קוד שרץ מחוץ לבקשה רגילה. זה כולל משימות רקע, משימות 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, המשימה רצה ב־locale שהיה פעיל כשה־worker התחיל. בדרך כלל :en, ללא קשר להעדפת המשתמש. כאשר משתמשים בה, המייל מרונדר בשפת המשתמש וה־locale מתאפס כשהבלוק מסתיים.
ייצאו תרגומי 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();
}
העבירו את ה־locale הנוכחי ל־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() עובדת כמו פונקציית העזר t של Rails. כאשר משתמשים מחליפים שפה, JavaScript משתמשת בתרגומים הנכונים מתכונת ה־data-locale.
תרגמו תוכן של ActiveRecord בעזרת ה־API של PTC
התבנית שלמעלה מתרגמת מחרוזות סטטיות בקובצי ה־YAML שלכם. תוכן של ActiveRecord (פוסטים של משתמשים, תגובות, תיאורי מוצר שנשמרים כקלט משתמש) אינו מופיע ב־YAML ודורש גישה שונה. ה־REST API של PTC מתרגם את התוכן הזה לפי דרישה בעזרת אימות טוקן Bearer, תוך שימוש באותו מילון מונחים וטון מותג כמו קובצי ה־config/locales/*.yml שלכם. שלחו את התוכן שלכם ל־PTC בבקשת POST, ולאחר מכן קבלו callback כשהתרגומים מוכנים או בדקו סטטוס (polling) מתוך משימת רקע.
בצעו לוקליזציה לתאריכים, מספרים ומטבעות בעזרת פונקציות העזר של Rails
תאריכים וזמנים. השתמשו בפונקציית העזר l (קיצור של localize):
<%= l Time.now, format: :long %>
ה־gem rails-i18n מספק פורמטים של תאריך/שעה המוגדרים כברירת מחדל עבור שפות רבות, כולל שמות חודשים מתורגמים ועיצוב ספציפי ל־locale. אתם יכולים להגדיר פורמטים מותאמים אישית בקובצי ה־YAML שלכם.
מספרים ומטבעות. Rails כוללת פונקציות עזר מודעות ל־locale:
<%= number_to_currency(100, locale: :es) %> <!-- 100,00 € -->
<%= number_with_delimiter(1000000) %> <!-- 1,000,000 -->
פונקציות אלו מכבדות את מוסכמות ה־locale עבור מפרידים עשרוניים, מפרידי אלפים וסמלי מטבע.
קובצי תצוגה מותאמים לכל שפה. עבור עמודים עם תוכן שונה משמעותית בכל locale, צרו קובצי תצוגה נפרדים. Rails מציגה את קובץ התצוגה המתאים על בסיס ה־locale הנוכחי:
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 (מבוססות דפדפן), התקינו את תוסף הדפדפן של PTC והקליטו מעבר (walkthrough) על המסכים הקריטיים של האפליקציה שלכם (התחברות, תהליכים מרכזיים, עמודי ניהול). מאותו רגע ואילך, PTC מריצה מחדש את ההקלטה בכל שפת יעד לאחר כל עדכון תרגום, מצלמת כל מסך, ומדווחת בחזרה:
- תיקונים בקובצי ה־YAML כאשר PTC שולטת בהם. PTC מתרגמת מחדש משמעות שגויה, בוחרת מילה נרדפת קצרה יותר, ומייצרת מחדש צורת רבים.
- פרומפטים ל־Cursor / Claude Code כאשר הבעיה נמצאת בקוד ה־Ruby או ה־ERB שלכם. מחרוזת אנגלית המוטמעת בקוד מחוץ ל־
t(), הודעת flash שנבנתה על ידי שרשור במקום אינטרפולציה, או פונקציית עזר שצריכה להשתמש ב־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 הרצה שלכם.
נושאים קשורים:
- מדריך ה־API של PTC - endpoints של REST עבור אינטגרציית CI.
- לוקליזציית תוכנה מבוססת בינה מלאכותית שנבנתה עבור צינורות CI/CD - סקירת השירות עבור צוותי פיתוח.
- המדריך הרשמי ל־i18n ב־Rails - מקור המידע המוסמך.