Thư viện i18n Rails mạnh hơn vẻ ngoài. Bạn không chỉ dùng cho translation. i18n hữu ích bất cứ nơi nào bạn muốn tách text hiển thị khỏi nơi hiển thị.
Khi ở Avvo, chúng tôi dùng i18n làm điều cool. Tôi chia sẻ vài điều học được hữu ích, cùng một hack điên rồ nhưng hoạt động cực tốt.
Tự động escape HTML
Bạn có dòng kiểu:
<%= raw(t('form.required_field_header')) %>
trong view? Bạn không cần raw, vì nếu key translation kết thúc _html, bạn được escaping miễn phí:
<%= t('form.required_field_header_html') %>
Đơn giản, nhất quán với các t() khác.
Truy cập locale tiện lợi hơn
Khi build locale file, bạn có key nhóm dưới cùng parent:
en:
bugs:
index:
new_label: "File a new bug"
edit_label: "edit"
delete_label: "delete"
Để tham chiếu nhóm này, bạn có thể dùng full key:
<%= t('bugs.index.edit_label') %> | <%= t('bugs.index.delete_label') %>
Phiền và lặp. Nhưng t() hỗ trợ scope, tham chiếu key tiện hơn:
<% bugs_scope = 'bugs.index' -%>
<%= t('edit_label', scope: bugs_scope) %> | <%= t('delete_label', scope: bugs_scope) %>
Nếu đặt tên partial tốt, even không cần scope:
<%= t('.edit_label') %> | <%= t('.delete_label') %>
Tức .edit_label tham chiếu bugs.index.edit_label, vì bạn ở bugs/index.html.erb.
ActiveRecord backend
Thỉnh thoảng static translation trong yaml không work. Nếu dùng ActiveRecord i18n backend:
require 'i18n/backend/active_record'
I18n.backend = I18n::Backend::ActiveRecord.new
Bạn lookup translation trong bảng translations database. Cách này, không cần define tất cả translation upfront. Thay vào đó, thêm translation mới on the fly.
Setup bảng translations cần migration cụ thể. README repo i18n-active_record có info cần thiết.
Chia sẻ partial giữa loại object
Tại Avvo, có lawyer directory, attorney reviews, legal advice. Nhưng vài năm trước, không chỉ lawyer trên site. Còn bác sĩ và nha sĩ!
Nhiều UI giống nhau giữa nghề nghiệp. Nhưng đủ khác (ví dụ, lawyer gọi "practice areas", bác sĩ gọi "specialties"), khó share view/partial không code xấu.
Cuối cùng, nghĩ dùng i18n system cho việc này. Dù sao, tiếng Anh lawyerese khoảng là dialect của tiếng Anh, doctorese cũng vậy. Không muốn block việc dùng ngôn ngữ khác sau, tạo hai locale mới: en_jd và en_md.
Dễ setup custom i18n backend:
class AvvoI18nStore < I18n::Backend::Simple
def translate(locale, key, options = {})
begin
default = options.delete(:default)
super(locale, key, options)
rescue I18n::MissingTranslationData => e
# fallback về "en" nếu không tìm thấy dưới "en_jd", etc.
fallback_locale = locale.to_s.split("_").first
super(fallback_locale, key, options.merge(:default => default))
end
end
end
I18n.backend = AvvoI18nStore.new
Define translation cũng dễ:
en_jd:
practice_area: "practice area"
en_md:
practice_area: "specialty"
Hoạt động tuyệt cho translate cả partial (chú ý filename):
<!-- Lawyer badge HTML -->
<!-- Doctor badge HTML -->
Và fallback về en locale, cho translation chung:
en:
leaderboard:
title: "Leaderboard"
Khi ở section "Doctors", đổi default locale thành :en_md, ngược lại:
I18n.locale = :en_md
Và mọi thứ just works!
Tôi không chắc khuyên cách này. Hơi điên, nghĩ nghề nghiệp khác nhau như ngôn ngữ khác. Nhưng nó chạy cực tốt khi làm. Và nó tiết lộ công cụ đơn giản như i18n có thể mạnh đến đâu.
Bạn học những thứ này ở đâu?
Tuần trước, tôi nói về deep dive vào technology cụ thể như cách từ beginner thành expert. Đây là ví dụ khác: hầu hết i18n chúng tôi học từ Rails guides và API docs.
Vậy hãy bước thêm. Học tốt công cụ bạn phụ thuộc. Bạn sẽ tìm thấy convenience và trick không chỉ làm productive hơn, mà có thể mở category giải pháp mới bạn chưa bao giờ nghĩ tới.