edge
더 많은 정보: rubyonrails.org에서 확인하세요: 더 많은 Ruby on Rails

Rails Internationalization (I18n) API

루비 I18n(국제화를 의미하는 약어) 젬은 루비 온 레일즈와 함께 제공되며(레일즈 2.2부터 시작), 영어 이외의 사용자 정의 언어로 애플리케이션을 번역하거나 애플리케이션에서 다국어 지원을 제공하기 위한 쉽고 확장 가능한 프레임워크를 제공합니다.

"국제화" 프로세스는 일반적으로 애플리케이션의 모든 문자열 및 다른 로케일별 비트(날짜 또는 통화 형식과 같은)를 추상화하는 것을 의미합니다. "로컬라이제이션" 프로세스는 이러한 비트에 대한 번역 및 로컬라이즈된 형식을 제공하는 것을 의미합니다.1

따라서 레일즈 애플리케이션을 국제화하는 과정에서 다음을 수행해야 합니다:

애플리케이션을 로컬라이즈하는 과정에서 다음 세 가지를 수행하고자 할 것입니다:

이 가이드에서는 I18n API를 안내하며, 레일즈 애플리케이션을 처음부터 국제화하는 방법에 대한 튜토리얼을 포함하고 있습니다.

이 가이드를 읽은 후에는 다음을 알게 될 것입니다:

참고: 루비 I18n 프레임워크는 레일즈 애플리케이션의 국제화/로컬라이제이션에 필요한 모든 수단을 제공합니다. 또한 추가 기능이나 기능을 추가하기 위해 사용할 수 있는 다양한 젬을 사용할 수도 있습니다. 자세한 내용은 rails-i18n 젬을 참조하십시오.

1 루비 온 레일즈에서 I18n이 작동하는 방식

국제화는 복잡한 문제입니다. 자연 언어는 다양한 방식으로 다릅니다(예: 복수화 규칙). 이러한 모든 문제를 해결하기 위한 도구를 제공하는 것은 어렵습니다. 이러한 이유로 레일즈 I18n API는 다음에 중점을 두고 있습니다:

  • 기본적으로 영어 및 유사한 언어를 지원하는 기능 제공
  • 다른 언어를 위해 모든 것을 사용자 정의하고 확장하기 쉽게 만들기

이 솔루션의 일부로 레일즈 프레임워크의 모든 정적 문자열 - 예: 액티브 레코드 유효성 검사 메시지, 시간 및 날짜 형식 - 국제화되었습니다. 레일즈 애플리케이션의 로컬라이제이션은 이러한 문자열에 대한 번역된 값을 원하는 언어로 정의하는 것을 의미합니다.

애플리케이션의 콘텐츠를 로컬라이즈하고 저장하고 업데이트하려면(예: 블로그 게시물 번역), 모델 콘텐츠 번역 섹션을 참조하십시오.

1.1 라이브러리의 전체 아키텍처

따라서 루비 I18n 젬은 두 부분으로 나뉩니다:

  • I18n 프레임워크의 공개 API - 라이브러리가 작동하는 방식을 정의하는 공개 메서드가 있는 루비 모듈
  • 이러한 메서드를 구현하는 기본 백엔드(의도적으로 Simple 백엔드라고 함)

사용자는 항상 I18n 모듈의 공개 메서드에만 액세스해야 하지만 백엔드의 기능을 알고 있는 것이 유용합니다.

참고: 출하된 Simple 백엔드를 관계형 데이터베이스, GetText 사전 또는 유사한 곳에 번역 데이터를 저장하는 더 강력한 백엔드로 교체할 수 있습니다. 아래의 다른 백엔드 사용 섹션을 참조하십시오.

1.2 공개 I18n API

I18n API의 가장 중요한 메서드는 다음과 같습니다:

translate # 텍스트 번역 조회
localize  # 로컬 형식으로 날짜 및 시간 객체 로컬라이즈

이들은 #t 및 #l의 별칭을 가지고 있으므로 다음과 같이 사용할 수 있습니다:

I18n.t 'store.title'
I18n.l Time.now

다음 속성에 대한 속성 리더 및 라이터도 있습니다:

load_path                 # 사용자 정의 번역 파일을 알립니다.
locale                    # 현재 로케일을 가져오고 설정합니다.
default_locale            # 기본 로케일을 가져오고 설정합니다.
available_locales         # 애플리케이션에서 사용 가능한 허용된 로케일
enforce_available_locales # 로케일 권한 강제 적용 (true 또는 false)
exception_handler         # 다른 exception_handler 사용
backend                   # 다른 백엔드 사용

그러면 다음 장에서 기본부터 간단한 레일즈 애플리케이션을 국제화해 보겠습니다!

2 국제화를 위해 레일즈 애플리케이션 설정하기

레일즈 애플리케이션에서 I18n 지원을 사용하려면 몇 가지 단계가 필요합니다.

2.1 I18n 모듈 구성

convention over configuration 철학을 따라, Rails I18n은 합리적인 기본 번역 문자열을 제공합니다. 다른 번역 문자열이 필요한 경우, 이를 재정의할 수 있습니다.

Rails는 config/locales 디렉토리의 모든 .rb.yml 파일을 번역 로드 경로에 자동으로 추가합니다.

이 디렉토리의 기본 en.yml 로케일에는 샘플 번역 문자열 쌍이 포함되어 있습니다:

en:
  hello: "Hello world"

즉, :en 로케일에서 hello 키는 Hello world 문자열에 매핑됩니다. Rails 내의 모든 문자열은 이와 같이 국제화됩니다. 예를 들어 activemodel/lib/active_model/locale/en.yml 파일의 Active Model 유효성 검사 메시지나 activesupport/lib/active_support/locale/en.yml 파일의 시간 및 날짜 형식과 같은 것을 참조하십시오. 기본 (간단한) 백엔드에서 번역을 저장하기 위해 YAML 또는 표준 Ruby 해시를 사용할 수 있습니다.

I18n 라이브러리는 영어기본 로케일로 사용합니다. 즉, 다른 로케일이 설정되지 않은 경우, 번역을 찾기 위해 :en이 사용됩니다.

참고: i18n 라이브러리는 로케일 키에 대해 실용적인 접근 방식을 취합니다 (일부 토론을 거친 후), "언어" 부분인 :en, :pl과 같은 로케일만 포함하고, "언어"와 "지역 설정" 또는 "방언"을 구분하는 데 전통적으로 사용되는 지역 부분인 :"en-US" 또는 :"en-GB"는 포함하지 않습니다. 많은 국제 애플리케이션은 체코어, 태국어 및 스페인어에 대한 :cs, :th, :es와 같은 로케일의 "언어" 요소만 사용합니다. 그러나 중요한 경우에는 다른 언어 그룹 내에서 지역적인 차이가 있을 수 있습니다. 예를 들어, :"en-US" 로케일에서 통화 기호로 $를 사용하고, :"en-GB"에서는 £를 사용합니다. 이와 같은 방식으로 지역 및 기타 설정을 분리하는 데는 아무런 제약이 없습니다. 단지 :"en-GB" 사전에서 "영어 - 영국" 로케일을 제공해야 합니다.

번역 로드 경로 (I18n.load_path)는 자동으로 로드되는 파일 경로의 배열입니다. 이 경로를 구성하면 번역 디렉토리 구조와 파일 이름 지정 체계를 사용자 정의할 수 있습니다.

참고: 이 백엔드는 번역이 처음으로 조회될 때 번역을 지연로드합니다. 이 백엔드는 이미 번역이 발표된 후에도 다른 것으로 교체될 수 있습니다.

기본 로케일을 변경하고 번역 로드 경로를 config/application.rb에서 다음과 같이 구성할 수 있습니다:

config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')]
config.i18n.default_locale = :de

로드 경로는 번역이 조회되기 전에 지정해야 합니다. config/application.rb 대신 초기화 파일에서 기본 로케일을 변경하려면 다음과 같이 할 수 있습니다:

# config/initializers/locale.rb

# I18n 라이브러리가 번역 파일을 검색해야 하는 위치
I18n.load_path += Dir[Rails.root.join('lib', 'locale', '*.{rb,yml}')]

# 응용 프로그램에서 사용 가능한 허용된 로케일
I18n.available_locales = [:en, :pt]

# 기본 로케일을 :en이 아닌 다른 값으로 설정
I18n.default_locale = :pt

외부 젬의 번역을 덮어쓰지 않기 위해 응용 프로그램의 구성된 I18n 대신 I18n.load_path에 직접 추가하는 것에 주의하십시오.

2.2 요청 간 로케일 관리

로케일화된 애플리케이션은 여러 로케일을 지원해야 할 수 있습니다. 이를 위해 로케일은 각 요청의 시작 부분에서 설정되어 해당 요청의 수명 동안 원하는 로케일을 사용하여 모든 문자열이 번역되도록 설정되어야 합니다.

I18n.locale= 또는 I18n.with_locale이 사용되지 않는 한, 모든 번역에는 기본 로케일이 사용됩니다.

I18n.locale은 동일한 스레드/프로세스에서 서비스되는 후속 요청에 누출될 수 있습니다. 예를 들어, 한 POST 요청에서 I18n.locale = :es를 실행하면 로케일이 설정되지 않은 컨트롤러로의 모든 후속 요청에 영향을 미칠 수 있지만, 해당 특정 스레드/프로세스에서만 해당됩니다. 이러한 이유로 I18n.locale = 대신 누출 문제가 없는 I18n.with_locale를 사용할 수 있습니다.

로케일은 ApplicationControlleraround_action에서 설정할 수 있습니다:

around_action :switch_locale

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

이 예제는 URL 쿼리 매개변수를 사용하여 로케일을 설정하는 방법을 보여줍니다 (예: http://example.com/books?locale=pt). 이 접근 방식을 사용하면 http://localhost:3000?locale=pt는 포르투갈어 로컬라이제이션을 렌더링하고, http://localhost:3000?locale=de는 독일어 로컬라이제이션을 로드합니다.

로케일은 여러 가지 다른 방법을 사용하여 설정할 수 있습니다.

2.2.1 도메인 이름에서 로케일 설정하기

가능한 방법 중 하나는 애플리케이션이 실행되는 도메인 이름에서 로케일을 설정하는 것입니다. 예를 들어, www.example.com은 영어 (또는 기본) 로케일을 로드하고, www.example.es는 스페인어 로케일을 로드하도록 설정합니다. 따라서 상위 도메인 이름이 로케일 설정에 사용됩니다. 이에는 여러 가지 장점이 있습니다: * 로케일은 URL의 명백한 부분입니다. * 사람들은 어떤 언어로 콘텐츠가 표시될지 직관적으로 이해합니다. * Rails에서 구현하기 매우 간단합니다. * 검색 엔진은 서로 연결된 다른 언어의 콘텐츠를 선호하는 것 같습니다.

ApplicationController에서 다음과 같이 구현할 수 있습니다:

around_action :switch_locale

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

# 최상위 도메인에서 로케일을 가져오거나 해당 로케일을 사용할 수 없는 경우 +nil+을 반환합니다.
# 로컬에서 이를 테스트하려면 /etc/hosts 파일에 다음과 같이 추가해야 합니다:
#   127.0.0.1 application.com
#   127.0.0.1 application.it
#   127.0.0.1 application.pl
def extract_locale_from_tld
  parsed_locale = request.host.split('.').last
  I18n.available_locales.map(&:to_s).include?(parsed_locale) ? parsed_locale : nil
end

매우 유사한 방식으로 서브도메인에서 로케일을 설정할 수도 있습니다:

# 요청 서브도메인에서 로케일 코드를 가져옵니다 (예: http://it.application.local:3000)
# 로컬에서 이를 테스트하려면 /etc/hosts 파일에 다음과 같이 추가해야 합니다:
#   127.0.0.1 gr.application.local
def extract_locale_from_subdomain
  parsed_locale = request.subdomains.first
  I18n.available_locales.map(&:to_s).include?(parsed_locale) ? parsed_locale : nil
end

로케일 전환 메뉴가 애플리케이션에 포함되어 있다면 다음과 같이 사용할 수 있습니다:

link_to("Deutsch", "#{APP_CONFIG[:deutsch_website_url]}#{request.env['PATH_INFO']}")

APP_CONFIG[:deutsch_website_url]http://www.application.de와 같은 값으로 설정한다고 가정합니다.

이 솔루션은 위에서 언급한 장점을 가지고 있지만, 서로 다른 도메인에 다른 로컬화("언어 버전")를 제공할 수 없거나 원하지 않을 수도 있습니다. 가장 명백한 해결책은 URL 매개변수(또는 요청 경로)에 로케일 코드를 포함하는 것입니다.

2.2.2 URL 매개변수에서 로케일 설정

로케일을 설정하고 전달하는 가장 일반적인 방법은 URL 매개변수에 포함하는 것입니다. 첫 번째 예제에서 I18n.with_locale(params[:locale], &action) around_action에서 수행한 것과 같이 URL 매개변수에 포함하고 싶습니다. 이 경우 www.example.com/books?locale=ja 또는 www.example.com/ja/books와 같은 URL을 원합니다.

이 접근 방식은 도메인 이름에서 로케일을 설정하는 것과 거의 동일한 장점을 가지고 있습니다. 즉, RESTful하며 월드 와이드 웹의 나머지 부분과 일치합니다. 그러나 구현하는 데 약간의 추가 작업이 필요합니다.

params에서 로케일을 가져오고 해당 로케일을 설정하는 것은 어렵지 않습니다. 그러나 모든 URL에 포함하고 따라서 요청을 통과시키는 것은 조금 더 어렵습니다. 모든 URL에 명시적인 옵션을 포함하는 것은 지루하고 아마도 불가능할 것입니다.

Rails에는 ApplicationController#default_url_options에서 "URL에 대한 동적 결정을 중앙 집중화하는" 인프라가 포함되어 있습니다. 이는 정확히 이러한 시나리오에 유용합니다. url_for 및 이에 의존하는 도우미 메서드에 대한 "기본값"을 설정할 수 있도록 해줍니다 (default_url_options를 구현/재정의함으로써).

그러면 다음과 같이 ApplicationController에 포함할 수 있습니다:

# app/controllers/application_controller.rb
def default_url_options
  { locale: I18n.locale }
end

url_for에 의존하는 모든 도우미 메서드(예: root_path 또는 root_url, books_path 또는 books_url 등의 이름이 지정된 경로, 리소스 경로 등)는 이제 쿼리 문자열에 로케일을 자동으로 포함합니다. 예를 들어 http://localhost:3001/?locale=ja와 같은 URL이 생성됩니다.

이로써 만족할 수 있을 것입니다. 그러나 읽기 쉬움 측면에서는 URL의 끝에 로케일이 "매달려" 있는 것이 영향을 미칩니다. 또한 아키텍처적인 측면에서 로케일은 일반적으로 애플리케이션 도메인의 다른 부분보다 위계적인 위치에 있습니다. URL은 이를 반영해야 합니다.

URL이 다음과 같아 보이도록 원할 것입니다: http://www.example.com/en/books (영어 로케일을 로드) 및 http://www.example.com/nl/books (네덜란드어 로케일을 로드). 이는 위에서 언급한 "default_url_options" 전략을 사용하여 달성할 수 있습니다. scope를 사용하여 라우트를 설정해야 합니다:

# config/routes.rb
scope "/:locale" do
  resources :books
end

이제 books_path 메서드를 호출하면 기본 로케일인 "/en/books"를 얻어야 합니다. http://localhost:3001/nl/books와 같은 URL은 네덜란드어 로케일을 로드하고, 이후 books_path 호출은 "/nl/books"를 반환해야 합니다(로케일이 변경되었으므로).

경고. default_url_options의 반환 값은 요청당 캐시되므로 로케일 선택기의 URL을 생성할 때 반복마다 해당 I18n.locale을 설정하는 루프에서 도우미를 호출하여 URL을 생성할 수 없습니다. 대신 I18n.locale을 건드리지 말고 도우미에 명시적인 :locale 옵션을 전달하거나 request.original_fullpath를 편집하세요.

라우트에서 로케일 사용을 강제하고 싶지 않은 경우 다음과 같이 선택적 경로 스코프(괄호로 표시됨)를 사용할 수 있습니다:

# config/routes.rb
scope "(:locale)", locale: /en|nl/ do
  resources :books
end

이 접근 방식을 사용하면 로케일이 지정되지 않은 경우 http://localhost:3001/books와 같은 리소스에 액세스 할 때 Routing Error가 발생하지 않습니다. 로케일이 지정되지 않은 경우 기본 로케일을 사용하려는 경우 유용합니다.

물론 응용 프로그램의 루트 URL(일반적으로 "홈페이지" 또는 "대시보드")에 특별한 주의를 기울여야 합니다. http://localhost:3001/nl과 같은 URL은 자동으로 작동하지 않습니다. 왜냐하면 routes.rbroot to: "dashboard#index" 선언은 로케일을 고려하지 않기 때문입니다. (그리고 올바르게도: "루트" URL은 하나뿐입니다.)

아마도 다음과 같은 URL을 매핑해야 할 것입니다.

# config/routes.rb
get '/:locale' => 'dashboard#index'

라우트의 순서에 특별히 주의하여 이 라우트 선언이 다른 라우트를 "먹지" 않도록 해야 합니다. (루트 :to 선언 바로 앞에 직접 추가하는 것이 좋을 수 있습니다.)

참고: 라우트 작업을 단순화하는 다양한 젬을 살펴보세요: routing_filter, route_translator.

2.2.3 사용자 환경 설정에서 로케일 설정하기

인증된 사용자가 있는 응용 프로그램은 사용자가 응용 프로그램의 인터페이스를 통해 로케일 환경 설정을 할 수 있도록 허용할 수 있습니다. 이 접근 방식을 사용하면 사용자가 선택한 로케일 환경 설정이 데이터베이스에 유지되고 해당 사용자의 인증된 요청에 대해 로케일이 설정됩니다.

around_action :switch_locale

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

2.2.4 암시적 로케일 선택하기

요청에 명시적으로 로케일이 설정되지 않은 경우 (위의 방법 중 하나를 통해), 응용 프로그램은 원하는 로케일을 추론하려고 시도해야 합니다.

2.2.4.1 언어 헤더에서 로케일 추론하기

Accept-Language HTTP 헤더는 요청의 응답에 대한 선호하는 언어를 나타냅니다. 브라우저는 사용자의 언어 설정에 기반하여 이 헤더 값을 설정합니다, 따라서 로케일을 추론하는 첫 번째 선택으로 좋습니다.

Accept-Language 헤더를 사용하는 간단한 구현은 다음과 같습니다.

def switch_locale(&action)
  logger.debug "* Accept-Language: #{request.env['HTTP_ACCEPT_LANGUAGE']}"
  locale = extract_locale_from_accept_language_header
  logger.debug "* Locale set to '#{locale}'"
  I18n.with_locale(locale, &action)
end

private
  def extract_locale_from_accept_language_header
    request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first
  end

실제로 이를 신뢰할 수 있는 방법으로 수행하기 위해 더 견고한 코드가 필요합니다. Iain Hecker의 http_accept_language 라이브러리나 Ryan Tomayko의 locale Rack 미들웨어는 이 문제에 대한 해결책을 제공합니다.

2.2.4.2 IP 지리 위치에서 로케일 추론하기

요청을 하는 클라이언트의 IP 주소를 사용하여 클라이언트의 지역 및 로케일을 추론할 수 있습니다. GeoLite2 Country와 같은 서비스 또는 geocoder와 같은 젬을 사용하여 이 접근 방식을 구현할 수 있습니다.

일반적으로 이 접근 방식은 언어 헤더를 사용하는 것보다 신뢰성이 훨씬 낮으며 대부분의 웹 응용 프로그램에 권장되지 않습니다.

2.2.5 세션 또는 쿠키에서 로케일 저장하기

경고: 선택한 로케일을 세션이나 쿠키에 저장하려는 유혹을 느낄 수 있습니다. 그러나 이렇게 하지 마십시오. 로케일은 투명하고 URL의 일부여야 합니다. 이렇게 하면 웹 자체에 대한 사람들의 기본 가정을 깨뜨리지 않습니다. URL을 친구에게 보내면 친구도 동일한 페이지와 콘텐츠를 볼 수 있어야 합니다. 이를 RESTful하다고 할 수 있습니다. Stefan Tilkov의 기사에서 RESTful 접근 방식에 대해 자세히 알아보세요. 이 규칙에는 때로는 예외가 있을 수 있으며, 이에 대해서는 아래에서 논의됩니다.

3 국제화 및 로컬라이제이션

좋아요! 이제 Ruby on Rails 응용 프로그램에 대한 I18n 지원을 초기화하고 사용할 로케일을 지정하고 요청 간에 로케일을 유지하는 방법을 알았습니다.

다음으로는 응용 프로그램을 국제화하기 위해 모든 로케일별 요소를 추상화해야 합니다. 마지막으로, 이 추상화된 요소에 대한 필요한 번역을 제공하여 응용 프로그램을 로컬라이즈해야 합니다.

다음 예제를 고려해 보겠습니다.

# config/routes.rb
Rails.application.routes.draw do
  root to: "home#index"
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  around_action :switch_locale

  def switch_locale(&action)
    locale = params[:locale] || I18n.default_locale
    I18n.with_locale(locale, &action)
  end
end
# app/controllers/home_controller.rb
class HomeController < ApplicationController
  def index
    flash[:notice] = "Hello Flash"
  end
end
<!-- app/views/home/index.html.erb -->
<h1>Hello World</h1>
<p><%= flash[:notice] %></p>

rails i18n demo untranslated

3.1 로컬라이즈된 코드 추상화하기

우리의 코드에서 응답에 렌더링될 두 개의 영어 문자열이 있습니다 ("Hello Flash"와 "Hello World"). 이 코드를 국제화하기 위해 이러한 문자열을 각각 적절한 키와 함께 Rails의 #t 헬퍼를 호출하는 것으로 대체해야 합니다.

# app/controllers/home_controller.rb
class HomeController < ApplicationController
  def index
    flash[:notice] = t(:hello_flash)
  end
end
<!-- app/views/home/index.html.erb -->
<h1><%= t :hello_world %></h1>
<p><%= flash[:notice] %></p>

이제이보기가 렌더링 될 때 :hello_world:hello_flash 키에 대한 번역이 누락되었다는 오류 메시지가 표시됩니다.

rails i18n demo translation missing

참고 : Rails는 뷰에 I18n.t를 매번 입력할 필요가 없도록 t (translate) 도우미 메서드를 추가합니다. 또한이 도우미는 누락 된 번역을 잡아서 결과 오류 메시지를 <span class="translation_missing">로 래핑합니다.

3.2 국제화 된 문자열에 대한 번역 제공

번역 사전 파일에 누락 된 번역을 추가하십시오.

# config/locales/en.yml
en:
  hello_world: Hello world!
  hello_flash: Hello flash!
# config/locales/pirate.yml
pirate:
  hello_world: Ahoy World
  hello_flash: Ahoy Flash

default_locale이 변경되지 않았으므로 번역은 :en 로케일을 사용하고 응답은 영어 문자열을 렌더링합니다.

rails i18n demo translated to English

로케일이 URL을 통해 해적 로케일 (http://localhost:3000?locale=pirate)로 설정되면 응답은 해적 문자열을 렌더링합니다.

rails i18n demo translated to pirate

참고 : 새로운 로케일 파일을 추가 할 때 서버를 다시 시작해야합니다.

SimpleStore에 번역을 저장하기 위해 YAML (.yml) 또는 일반 Ruby (.rb) 파일을 사용할 수 있습니다. YAML은 Rails 개발자들 사이에서 선호되는 옵션입니다. 그러나 YAML은 공백과 특수 문자에 매우 민감하기 때문에 응용 프로그램이 사전을 제대로로드하지 못할 수 있습니다. Ruby 파일은 첫 번째 요청에서 응용 프로그램을 충돌시킬 수 있으므로 문제를 쉽게 찾을 수 있습니다. (YAML 사전에 "이상한 문제"가 발생하는 경우 사전의 해당 부분을 Ruby 파일에 넣어보십시오.)

번역이 YAML 파일에 저장된 경우 일부 키를 이스케이프해야합니다. 그들은 다음과 같습니다.

  • true, on, yes
  • false, off, no

예제 :

# config/locales/en.yml
en:
  success:
    'true':  'True!'
    'on':    'On!'
    'false': 'False!'
  failure:
    true:    'True!'
    off:     'Off!'
    false:   'False!'
I18n.t 'success.true'  # => 'True!'
I18n.t 'success.on'    # => 'On!'
I18n.t 'success.false' # => 'False!'
I18n.t 'failure.false' # => Translation Missing
I18n.t 'failure.off'   # => Translation Missing
I18n.t 'failure.true'  # => Translation Missing

3.3 번역에 변수 전달

응용 프로그램을 성공적으로 국제화하는 데 필요한 주요 고려 사항 중 하나는 지역화 된 코드를 추상화 할 때 문법 규칙에 대해 잘못된 가정을하지 않는 것입니다. 한 로케일에서 기본적으로 보이는 문법 규칙이 다른 로케일에서는 참이 아닐 수 있습니다.

잘못된 추상화는 다음 예에서 나타납니다. 다른 부분의 순서에 대한 가정이 이루어집니다. Rails는 다음 경우를 처리하기 위해 number_to_currency 도우미를 제공합니다.

<!-- app/views/products/show.html.erb -->
<%= "#{t('currency')}#{@product.price}" %>
# config/locales/en.yml
en:
  currency: "$"
# config/locales/es.yml
es:
  currency: "€"

제품의 가격이 10이면 스페인어의 적절한 번역은 "10 €"이며 "€10"이 아닙니다. 그러나 추상화는 이를 제공 할 수 없습니다.

올바른 추상화를 위해 I18n 젬은 변수 보간이라는 기능을 제공합니다. 이 기능을 사용하여 번역 정의에서 변수를 사용하고 이러한 변수의 값을 번역 메서드에 전달할 수 있습니다.

다음 예에서 올바른 추상화가 표시됩니다.

<!-- app/views/products/show.html.erb -->
<%= t('product_price', price: @product.price) %>
# config/locales/en.yml
en:
  product_price: "$%{price}"
# config/locales/es.yml
es:
  product_price: "%{price} €"

문법 및 구두점 결정은 정의 자체에서 이루어지므로 추상화는 적절한 번역을 제공 할 수 있습니다.

참고 : defaultscope 키워드는 예약되어 있으며 변수 이름으로 사용할 수 없습니다. 사용하면 I18n::ReservedInterpolationKey 예외가 발생합니다. 번역이 보간 변수를 예상하지만이를 #translate에 전달하지 않은 경우 I18n::MissingInterpolationArgument 예외가 발생합니다.

3.4 날짜/시간 형식 추가

좋아요! 이제 뷰에 타임 스탬프를 추가하여 날짜/시간 지역화 기능을 데모 할 수 있습니다. 시간 형식을 지역화하려면 I18n.l에 Time 개체를 전달하거나 (가능하면) Rails의 #l 도우미를 사용합니다. :format 옵션을 전달하여 형식을 선택할 수 있습니다. 기본적으로 :default 형식이 사용됩니다.

<!-- app/views/home/index.html.erb -->
<h1><%= t :hello_world %></h1>
<p><%= flash[:notice] %></p>
<p><%= l Time.now, format: :short %></p>

그리고 우리의 해적 번역 파일에 시간 형식을 추가 해 봅시다 (이미 Rails의 영어 기본값에 있습니다).

# config/locales/pirate.yml
pirate:
  time:
    formats:
      short: "arrrround %H'ish"

그러면 다음과 같이됩니다.

rails i18n demo localized time to pirate

TIP : 지금은 I18n 백엔드가 예상대로 작동하도록하기 위해 (적어도 '해적'로케일의 경우) 몇 가지 추가 날짜/시간 형식을 추가해야 할 수도 있습니다. 물론 이미 로케일을 위해 Rails의 기본값을 번역 한 사람이 모든 작업을 수행 한 가능성이 큽니다. GitHub의 rails-i18n 저장소에서 다양한 로케일 파일의 아카이브를 참조하십시오. 이러한 파일을 config/locales/ 디렉토리에 넣으면 자동으로 사용할 준비가됩니다.

3.5 다른 로케일을 위한 굴절 규칙

Rails는 영어 이외의 로케일에 대한 굴절 규칙 (단수화 및 복수화 규칙과 같은 규칙)을 정의할 수 있습니다. config/initializers/inflections.rb에서 여러 로케일에 대한 이러한 규칙을 정의할 수 있습니다. 이니셜라이저에는 영어에 대한 추가 규칙을 지정하는 기본 예제가 포함되어 있으며, 필요한 경우 다른 로케일에 대해 해당 형식을 따르면 됩니다.

3.6 로케일별 뷰

예를 들어 애플리케이션에 BooksController가 있다고 가정해 보겠습니다. index 액션은 app/views/books/index.html.erb 템플릿에서 콘텐츠를 렌더링합니다. 이 디렉토리에 localized variant 템플릿인 index.es.html.erb를 넣으면, 로케일이 :es로 설정된 경우에는 이 템플릿에서 콘텐츠를 렌더링합니다. 로케일이 기본 로케일로 설정된 경우에는 일반적인 index.html.erb 뷰가 사용됩니다. (향후 Rails 버전에서는 public 등의 자산에 대한 이 자동 로컬라이제이션 기능이 도입될 수 있습니다.)

이 기능을 활용하면 YAML이나 Ruby 사전에 넣기에는 번거로운 대량의 정적 콘텐츠를 처리할 때 유용합니다. 그러나 나중에 템플릿에 대한 변경을 수행하려면 모든 템플릿에 전파되어야 한다는 점을 염두에 두어야 합니다.

3.7 로케일 파일의 구성

i18n 라이브러리와 함께 제공되는 기본 SimpleStore를 사용하는 경우, 사전은 디스크의 일반 텍스트 파일에 저장됩니다. 한 로케일당 애플리케이션의 모든 부분에 대한 번역을 하나의 파일에 저장하는 것은 관리하기 어려울 수 있습니다. 이러한 파일을 의미 있는 계층 구조로 저장할 수 있습니다.

예를 들어, config/locales 디렉토리는 다음과 같이 구성될 수 있습니다:

|-defaults
|---es.yml
|---en.yml
|-models
|---book
|-----es.yml
|-----en.yml
|-views
|---defaults
|-----es.yml
|-----en.yml
|---books
|-----es.yml
|-----en.yml
|---users
|-----es.yml
|-----en.yml
|---navigation
|-----es.yml
|-----en.yml

이렇게 하면 모델 및 모델 속성 이름을 뷰 내의 텍스트와 분리할 수 있으며, 이 모든 것을 "기본값" (예: 날짜 및 시간 형식)과 분리할 수 있습니다. i18n 라이브러리의 다른 저장소는 이러한 분리를 위한 다른 방법을 제공할 수 있습니다.

참고: Rails의 기본 로케일 로딩 메커니즘은 여기와 같이 중첩된 사전 파일을 로드하지 않습니다. 따라서 이를 작동시키기 위해 Rails에 명시적으로 계속 찾도록 알려주어야 합니다:

# config/application.rb
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]

4 I18n API 기능 개요

지금까지 i18n 라이브러리를 사용하는 방법에 대해 잘 이해하고 기본적인 Rails 애플리케이션을 국제화하는 방법을 알게 되었습니다. 다음 장에서는 이러한 기능을 더 자세히 다룰 것입니다.

이 장에서는 I18n.translate 메소드와 translate 뷰 헬퍼 메소드를 사용한 예제를 보여줍니다 (뷰 헬퍼 메소드가 제공하는 추가 기능을 강조합니다).

다음과 같은 기능이 다루어집니다:

  • 번역 조회
  • 데이터를 번역에 보간
  • 번역 복수화
  • 안전한 HTML 번역 사용 (뷰 헬퍼 메소드만 해당)
  • 날짜, 숫자, 통화 등 로컬라이즈

4.1 번역 조회

4.1.1 기본 조회, 스코프 및 중첩 키

번역은 심볼 또는 문자열로 된 키를 사용하여 조회됩니다. 따라서 다음 호출은 동등합니다:

I18n.t :message
I18n.t 'message'

translate 메소드는 :scope 옵션도 사용할 수 있습니다. 이 옵션은 하나 이상의 추가 키를 포함할 수 있으며, 번역 키에 대한 "네임스페이스" 또는 스코프를 지정하는 데 사용됩니다:

I18n.t :record_invalid, scope: [:activerecord, :errors, :messages]

이는 Active Record 오류 메시지에서 :record_invalid 메시지를 조회합니다.

또한 키와 스코프를 점으로 구분된 키로 지정할 수도 있습니다:

I18n.translate "activerecord.errors.messages.record_invalid"

따라서 다음 호출은 동등합니다:

I18n.t 'activerecord.errors.messages.record_invalid'
I18n.t 'errors.messages.record_invalid', scope: :activerecord
I18n.t :record_invalid, scope: 'activerecord.errors.messages'
I18n.t :record_invalid, scope: [:activerecord, :errors, :messages]

4.1.2 기본값

:default 옵션이 주어지면, 번역이 없는 경우 해당 값이 반환됩니다:

I18n.t :missing, default: 'Not here'
# => 'Not here'

default 값이 심볼인 경우, 키로 사용되고 번역됩니다. 여러 개의 값을 기본값으로 제공할 수 있습니다. 값이 결과를 반환하는 첫 번째 값이 반환됩니다.

예를 들어, 다음은 먼저 키 :missing을 번역하고 그 다음 키 :also_missing을 번역합니다. 둘 다 결과를 반환하지 않으므로 문자열 "Not here"가 반환됩니다:

I18n.t :missing, default: [:also_missing, 'Not here']
# => 'Not here'

4.1.3 대량 및 네임스페이스 조회

한 번에 여러 개의 번역을 조회하려면 키의 배열을 전달할 수 있습니다: ```ruby I18n.t [:odd, :even], scope: 'errors.messages'

=> ["홀수여야 합니다", "짝수여야 합니다"]


또한, 키는 (잠재적으로 중첩된) 그룹화된 번역의 해시로 변환될 수 있습니다. 예를 들어, 다음과 같이 _모든_ Active Record 오류 메시지를 해시로 받을 수 있습니다:

```ruby
I18n.t 'errors.messages'
# => {:inclusion=>"목록에 포함되지 않았습니다", :exclusion=> ... }

여러 개의 번역 해시에 대해 보간을 수행하려면 deep_interpolation: true를 매개변수로 전달해야 합니다. 다음과 같은 사전이 있는 경우:

en:
  welcome:
    title: "환영합니다!"
    content: "%{app_name}에 오신 것을 환영합니다"

그러면 다음과 같이 중첩된 보간은 설정 없이 무시됩니다:

I18n.t 'welcome', app_name: '서점'
# => {:title=>"환영합니다!", :content=>"%{app_name}에 오신 것을 환영합니다"}

I18n.t 'welcome', deep_interpolation: true, app_name: '서점'
# => {:title=>"환영합니다!", :content=>"서점에 오신 것을 환영합니다"}

4.1.4 "게으른" 조회

Rails는 내에서 로캘을 조회하는 편리한 방법을 구현합니다. 다음과 같은 사전이 있는 경우:

es:
  books:
    index:
      title: "제목"

다음과 같이 app/views/books/index.html.erb 템플릿 내부에서 books.index.title 값을 조회할 수 있습니다 (점을 참고하세요):

<%= t '.title' %>

참고: 부분별로 자동 번역 범위를 설정하는 것은 translate 뷰 도우미 메서드에서만 사용할 수 있습니다.

"게으른" 조회는 컨트롤러에서도 사용할 수 있습니다:

en:
  books:
    create:
      success: 책이 생성되었습니다!

이는 예를 들어 플래시 메시지를 설정하는 데 유용합니다:

class BooksController < ApplicationController
  def create
    # ...
    redirect_to books_url, notice: t('.success')
  end
end

4.2 복수화

영어를 포함한 많은 언어에서는 주어진 문자열에 대해 단수와 복수 두 가지 형태만 있습니다. 예를 들어 "1개의 메시지"와 "2개의 메시지"입니다. 다른 언어 (아랍어, 일본어, 러시아어 등)는 추가적이거나 더 적은 복수 형태를 가진 다른 문법을 가지고 있습니다. 따라서 I18n API는 유연한 복수화 기능을 제공합니다.

:count 보간 변수는 번역에 대해 보간되고 복수화 백엔드에서 정의된 복수화 규칙에 따라 번역에서 복수화를 선택하는 데 사용됩니다. 기본적으로 영어 복수화 규칙만 적용됩니다.

I18n.backend.store_translations :en, inbox: {
  zero: '메시지 없음', # 선택 사항
  one: '1개의 메시지',
  other: '%{count}개의 메시지'
}
I18n.translate :inbox, count: 2
# => '2개의 메시지'

I18n.translate :inbox, count: 1
# => '1개의 메시지'

I18n.translate :inbox, count: 0
# => '메시지 없음'

:en의 복수화에 대한 알고리즘은 다음과 같습니다:

lookup_key = :zero if count == 0 && entry.has_key?(:zero)
lookup_key ||= count == 1 ? :one : :other
entry[lookup_key]

:one으로 표시된 번역은 단수로 간주되며, :other는 복수로 사용됩니다. 카운트가 0이고 :zero 항목이 있는 경우, :other 대신 사용됩니다.

키에 대한 조회 결과가 복수화에 적합한 해시를 반환하지 않으면 I18n::InvalidPluralizationData 예외가 발생합니다.

4.2.1 로캘별 규칙

I18n 젬은 로캘별 규칙을 활성화할 수 있는 복수화 백엔드를 제공합니다. 이를 위해 Simple 백엔드에 포함시키고, i18n.plural.rule로 로캘별 복수화 알고리즘을 번역 저장소에 추가합니다.

I18n::Backend::Simple.include(I18n::Backend::Pluralization)
I18n.backend.store_translations :pt, i18n: { plural: { rule: lambda { |n| [0, 1].include?(n) ? :one : :other } } }
I18n.backend.store_translations :pt, apples: { one: '하나 또는 없음', other: '하나 이상' }

I18n.t :apples, count: 0, locale: :pt
# => '하나 또는 없음'

또는 별도의 젬인 rails-i18n을 사용하여 더 많은 로캘별 복수화 규칙을 제공할 수 있습니다.

4.3 로캘 설정 및 전달

로캘은 I18n.locale에 의해 의사 전역적으로 설정될 수 있으며 (Time.zone과 같은 방식으로 Thread.current를 사용합니다), 또는 #translate#localize에 옵션으로 전달될 수 있습니다.

로캘이 전달되지 않으면 I18n.locale이 사용됩니다:

I18n.locale = :de
I18n.t :foo
I18n.l Time.now

로캘을 명시적으로 전달하는 경우:

I18n.t :foo, locale: :de
I18n.l Time.now, locale: :de

I18n.locale은 기본적으로 I18n.default_locale을 사용하며, 이는 기본적으로 :en입니다. 기본 로캘은 다음과 같이 설정할 수 있습니다:

I18n.default_locale = :de

4.4 안전한 HTML 번역 사용

'_html' 접미사를 가진 키와 'html'이라는 이름의 키는 HTML 안전으로 표시됩니다. 뷰에서 사용할 때 HTML이 이스케이프되지 않습니다.

# config/locales/en.yml
en:
  welcome: <b>환영합니다!</b>
  hello_html: <b>안녕하세요!</b>
  title:
    html: <b>제목!</b>
<!-- app/views/home/index.html.erb -->
<div><%= t('welcome') %></div>
<div><%= raw t('welcome') %></div>
<div><%= t('hello_html') %></div>
<div><%= t('title.html') %></div>

그러나 보간은 필요에 따라 이스케이프됩니다. 예를 들어 다음과 같이 주어진 경우:

en:
  welcome_html: "<b>Welcome %{username}!</b>"

사용자가 설정한대로 사용자 이름을 안전하게 전달할 수 있습니다:

<%# 이것은 안전하며 필요한 경우 이스케이프됩니다. %>
<%= t('welcome_html', username: @current_user.username) %>

안전한 문자열은 그대로 보간됩니다.

참고: HTML 안전한 번역 텍스트로의 자동 변환은 translate (또는 t) 도우미 메서드에서만 사용할 수 있습니다. 이는 뷰와 컨트롤러에서 작동합니다.

i18n demo HTML safe

4.5 Active Record 모델에 대한 번역

Model.model_name.humanModel.human_attribute_name(attribute) 메서드를 사용하여 모델 및 속성 이름에 대한 번역을 투명하게 찾을 수 있습니다.

예를 들어 다음과 같은 번역을 추가하는 경우:

en:
  activerecord:
    models:
      user: Customer
    attributes:
      user:
        login: "Handle"
      # User 속성 "login"을 "Handle"로 번역합니다.

그런 다음 User.model_name.human은 "Customer"를 반환하고 User.human_attribute_name("login")은 "Handle"을 반환합니다.

또한 모델 이름에 대한 복수형 형태를 설정할 수도 있습니다. 다음과 같이 추가하면 됩니다:

en:
  activerecord:
    models:
      user:
        one: Customer
        other: Customers

그런 다음 User.model_name.human(count: 2)는 "Customers"를 반환합니다. count: 1 또는 매개변수 없이는 "Customer"를 반환합니다.

특정 모델 내에서 중첩된 속성에 액세스해야하는 경우, 번역 파일의 모델 수준에서 model/attribute 아래에 중첩해야합니다:

en:
  activerecord:
    attributes:
      user/role:
        admin: "Admin"
        contributor: "Contributor"

그런 다음 User.human_attribute_name("role.admin")은 "Admin"을 반환합니다.

참고: ActiveRecord::Base에서 상속되지 않고 ActiveModel을 포함하는 클래스를 사용하는 경우 위의 키 경로에서 activerecordactivemodel로 대체하십시오.

4.5.1 오류 메시지 범위

Active Record 유효성 검사 오류 메시지도 쉽게 번역할 수 있습니다. Active Record는 특정 모델, 속성 및/또는 유효성에 대한 다른 메시지와 번역을 제공하기 위해 메시지 번역을 배치할 수 있는 여러 네임스페이스를 제공합니다. 또한 단일 테이블 상속을 투명하게 고려합니다.

이를 통해 애플리케이션의 요구에 유연하게 메시지를 조정할 수 있는 강력한 수단을 제공합니다.

다음과 같이 이름 속성에 대한 유효성 검사가 있는 User 모델을 고려해보십시오:

class User < ApplicationRecord
  validates :name, presence: true
end

이 경우 오류 메시지의 키는 :blank입니다. Active Record는 다음과 같은 네임스페이스에서 이 키를 찾습니다:

activerecord.errors.models.[model_name].attributes.[attribute_name]
activerecord.errors.models.[model_name]
activerecord.errors.messages
errors.attributes.[attribute_name]
errors.messages

따라서 우리의 예에서는 다음과 같은 순서로 이러한 키를 시도하고 첫 번째 결과를 반환합니다:

activerecord.errors.models.user.attributes.name.blank
activerecord.errors.models.user.blank
activerecord.errors.messages.blank
errors.attributes.name.blank
errors.messages.blank

모델이 상속을 사용하는 경우 메시지는 상속 체인에서 찾습니다.

예를 들어 User에서 상속하는 Admin 모델이 있을 수 있습니다:

class Admin < User
  validates :name, presence: true
end

그런 다음 Active Record는 다음과 같은 순서로 메시지를 찾습니다:

activerecord.errors.models.admin.attributes.name.blank
activerecord.errors.models.admin.blank
activerecord.errors.models.user.attributes.name.blank
activerecord.errors.models.user.blank
activerecord.errors.messages.blank
errors.attributes.name.blank
errors.messages.blank

이렇게 하면 모델의 상속 체인과 속성, 모델 또는 기본 범위에서 다양한 오류 메시지에 대한 특별한 번역을 제공할 수 있습니다.

4.5.2 오류 메시지 보간

번역된 모델 이름, 번역된 속성 이름 및 값은 항상 model, attributevalue로 보간할 수 있습니다.

예를 들어 기본 오류 메시지 "cannot be blank" 대신 다음과 같이 속성 이름을 사용할 수 있습니다: "Please fill in your %{attribute}".

  • 가능한 경우 count는 복수형을 위해 복수화에 사용할 수 있습니다:
유효성 검사 옵션과 함께 메시지 보간
confirmation - :confirmation attribute
acceptance - :accepted -
presence - :blank -
absence - :present -
length :within, :in :too_short count
length :within, :in :too_long count
length :is :wrong_length count
length :minimum :too_short count
length :maximum :too_long count
uniqueness - :taken -
format - :invalid -
inclusion - :inclusion -
exclusion - :exclusion -
associated - :invalid -
non-optional association - :required -
numericality - :not_a_number -
numericality :greater_than :greater_than count
numericality :greater_than_or_equal_to :greater_than_or_equal_to count
numericality :equal_to :equal_to count
numericality :less_than :less_than count
numericality :less_than_or_equal_to :less_than_or_equal_to count
numericality :other_than :other_than count
numericality :only_integer :not_an_integer -
numericality :in :in count
numericality :odd :odd -
numericality :even :even -
comparison :greater_than :greater_than count
comparison :greater_than_or_equal_to :greater_than_or_equal_to count
comparison :equal_to :equal_to count
comparison :less_than :less_than count
comparison :less_than_or_equal_to :less_than_or_equal_to count
comparison :other_than :other_than count

4.6 Action Mailer 이메일 제목에 대한 번역

mail 메서드에 subject를 전달하지 않으면 Action Mailer는 번역에서 찾으려고 시도합니다. 수행되는 조회는 <mailer_scope>.<action_name>.subject 패턴을 사용하여 키를 구성합니다.

# user_mailer.rb
class UserMailer < ActionMailer::Base
  def welcome(user)
    #...
  end
end
en:
  user_mailer:
    welcome:
      subject: "Rails 가이드에 오신 것을 환영합니다!"

메일러에서 보간에 매개변수를 전달하려면 default_i18n_subject 메서드를 사용하십시오.

# user_mailer.rb
class UserMailer < ActionMailer::Base
  def welcome(user)
    mail(to: user.email, subject: default_i18n_subject(user: user.name))
  end
end
en:
  user_mailer:
    welcome:
      subject: "%{user}, Rails 가이드에 오신 것을 환영합니다!"

4.7 I18n 지원을 제공하는 기타 내장 메서드 개요

Rails는 몇 가지 도우미에서 고정된 문자열과 형식 문자열 및 기타 형식 정보와 같은 다른 지역화를 사용합니다. 간략한 개요를 살펴보겠습니다.

4.7.1 Action View 도우미 메서드

  • distance_of_time_in_words는 결과를 번역하고 복수화하며 초, 분, 시간 등의 숫자를 보간합니다. datetime.distance_in_words 번역을 참조하십시오.

  • datetime_selectselect_month는 결과 선택 태그를 채우기 위해 번역된 월 이름을 사용합니다. 번역을 위해 date.month_names를 참조하십시오. datetime_select는 또한 date.order에서 order 옵션을 조회합니다(명시적으로 옵션을 전달하지 않는 한). 모든 날짜 선택 도우미는 적용 가능한 경우 번역에서 datetime.prompts 범위의 프롬프트를 번역합니다.

  • number_to_currency, number_with_precision, number_to_percentage, number_with_delimiter, number_to_human_size 도우미는 number 범위에 있는 숫자 형식 설정을 사용합니다.

4.7.2 Active Model 메서드

  • model_name.humanhuman_attribute_nameactiverecord.models 범위에 사용 가능한 모델 이름과 속성 이름에 대한 번역을 사용합니다. "오류 메시지 범위"에서 설명한대로 상속된 클래스 이름에 대한 번역도 지원합니다.

  • ActiveModel::Errors#generate_message(Active Model 유효성 검사에서 사용되지만 수동으로 사용될 수도 있음)는 model_name.humanhuman_attribute_name을 사용합니다(위 참조). 또한 오류 메시지를 번역하고 "오류 메시지 범위"에서 설명한대로 상속된 클래스 이름에 대한 번역도 지원합니다.

  • ActiveModel::Error#full_messageActiveModel::Errors#full_messageserrors.format에서 형식을 조회하여 속성 이름을 오류 메시지 앞에 추가합니다(기본값: "%{attribute} %{message}"). 기본 형식을 사용자 정의하려면 앱의 로캘 파일에서 재정의하십시오. 모델별 또는 속성별로 형식을 사용자 정의하려면 config.active_model.i18n_customize_full_message를 참조하십시오.

4.7.3 Active Support 메서드

  • Array#to_sentencesupport.array 범위에 지정된 형식 설정을 사용합니다.

5 사용자 정의 번역 저장 방법

Active Support와 함께 제공되는 Simple 백엔드를 사용하면 번역을 일반적인 Ruby 및 YAML 형식으로 저장할 수 있습니다.2

예를 들어, 번역을 제공하는 Ruby 해시는 다음과 같이 보일 수 있습니다.

{
  pt: {
    foo: {
      bar: "baz"
    }
  }
}

동등한 YAML 파일은 다음과 같이 보일 것입니다.

pt:
  foo:
    bar: baz

보시다시피, 두 경우 모두 최상위 키는 로캘입니다. :foo는 네임스페이스 키이고 :bar는 번역 "baz"의 키입니다.

다음은 Active Support en.yml 번역 YAML 파일에서 "실제" 예입니다.

en:
  date:
    formats:
      default: "%Y-%m-%d"
      short: "%b %d"
      long: "%B %d, %Y"

따라서 다음과 같은 동등한 조회는 :short 날짜 형식 "%b %d"을 반환합니다.

I18n.t 'date.formats.short'
I18n.t 'formats.short', scope: :date
I18n.t :short, scope: 'date.formats'
I18n.t :short, scope: [:date, :formats]

일반적으로 번역을 저장하기 위해 YAML 형식을 사용하는 것을 권장합니다. 그러나 특별한 날짜 형식과 같은 로캘 데이터의 일부로 Ruby 람다를 저장해야하는 경우도 있습니다.

6 I18n 설정 사용자 정의

6.1 다른 백엔드 사용

여러 가지 이유로 Active Support와 함께 제공되는 Simple 백엔드는 "가능한 가장 간단한 것"을 수행합니다. 즉, 영어와 영어와 매우 유사한 언어에 대해서만 작동을 보장합니다.3 또한, Simple 백엔드는 번역을 읽을 수는 있지만 동적으로 어떤 형식에도 저장할 수 없습니다.

그러나 이러한 제한으로 고생할 필요는 없습니다. Ruby I18n 젬을 사용하면 I18n.backend= 세터에 백엔드 인스턴스를 전달하여 Simple 백엔드 구현을 더 적합한 다른 것으로 교체할 수 있습니다.

예를 들어, Simple 백엔드를 Chain 백엔드로 대체하여 여러 백엔드를 연결할 수 있습니다. 이는 Simple 백엔드로 표준 번역을 사용하고 데이터베이스나 기타 백엔드에 사용자 정의 애플리케이션 번역을 저장하려는 경우에 유용합니다. Chain 백엔드를 사용하면 Active Record 백엔드를 사용하고 (기본값인) Simple 백엔드로 되돌아갈 수 있습니다:

I18n.backend = I18n::Backend::Chain.new(I18n::Backend::ActiveRecord.new, I18n.backend)

6.2 다른 예외 처리기 사용하기

I18n API는 백엔드에서 해당하는 예기치 않은 조건이 발생할 때 발생하는 다음 예외를 정의합니다:

예외 이유
I18n::MissingTranslationData 요청한 키에 대한 번역이 없음
I18n::InvalidLocale I18n.locale로 설정된 로케일이 잘못됨 (예: nil)
I18n::InvalidPluralizationData count 옵션이 전달되었지만 복수화에 적합한 번역 데이터가 아님
I18n::MissingInterpolationArgument 번역이 전달되지 않은 보간 인수를 예상함
I18n::ReservedInterpolationKey 번역에 예약된 보간 변수 이름이 포함됨 (즉, scope, default 중 하나)
I18n::UnknownFileType 백엔드가 I18n.load_path에 추가된 파일 유형을 처리할 수 없음

6.2.1 I18n::MissingTranslationData가 처리되는 방식 사용자 정의하기

config.i18n.raise_on_missing_translationstrue인 경우 I18n::MissingTranslationData 오류가 발생합니다. 누락된 번역이 요청된 위치를 확인할 수 있도록 테스트 환경에서 이를 켜는 것이 좋습니다.

config.i18n.raise_on_missing_translationsfalse인 경우 (모든 환경의 기본값), 예외의 오류 메시지가 출력됩니다. 이는 누락된 키/범위를 포함하므로 코드를 수정할 수 있습니다.

이 동작을 더욱 사용자 정의하려면 config.i18n.raise_on_missing_translations = false로 설정한 다음 I18n.exception_handler를 구현해야 합니다. 사용자 정의 예외 처리기는 proc 또는 call 메서드를 가진 클래스일 수 있습니다:

# config/initializers/i18n.rb
module I18n
  class RaiseExceptForSpecificKeyExceptionHandler
    def call(exception, locale, key, options)
      if key == "special.key"
        "translation missing!" # 반환하고 예외를 발생시키지 않음
      elsif exception.is_a?(MissingTranslation)
        raise exception.to_exception
      else
        raise exception
      end
    end
  end
end

I18n.exception_handler = I18n::RaiseExceptForSpecificKeyExceptionHandler.new

이는 I18n.t("special.key")의 경우를 제외하고 기본 처리기와 동일한 방식으로 모든 예외를 발생시킵니다.

7 모델 콘텐츠 번역

이 가이드에서 설명하는 I18n API는 주로 인터페이스 문자열을 번역하는 데 사용됩니다. 모델 콘텐츠 (예: 블로그 게시물)를 번역하려면 다른 솔루션을 사용해야 합니다.

다음과 같은 몇 가지 젬을 사용할 수 있습니다:

  • Mobility: 번역 테이블, JSON 열 (PostgreSQL) 등 다양한 형식으로 번역을 저장하는 기능 제공
  • Traco: 모델 테이블 자체에 저장된 번역 가능한 열

8 결론

이제 Ruby on Rails에서 I18n 지원이 작동하는 방식에 대해 잘 이해하고 프로젝트를 번역하기 시작할 준비가 되었습니다.

9 Rails I18n에 기여하기

Ruby on Rails의 I18n 지원은 2.2 버전에서 소개되었으며 여전히 발전 중입니다. 이 프로젝트는 먼저 젬이나 실제 애플리케이션에서 솔루션을 발전시키고, 가장 유용한 기능을 핵심에 포함시키기 위해 최고의 솔루션을 선택하는 좋은 Ruby on Rails 개발 전통을 따릅니다.

따라서 모두에게 새로운 아이디어와 기능을 실험하고 젬이나 다른 라이브러리에서 이를 커뮤니티에 제공할 것을 권장합니다. (작업 내용을 메일링 리스트에서 발표하는 것을 잊지 마세요!)

Ruby on Rails의 예제 번역 데이터 저장소에서 자체 로케일(언어)이 누락된 경우, 저장소를 fork하여 데이터를 추가하고 pull request를 보내주시기 바랍니다.

10 리소스

  • Google 그룹: rails-i18n - 프로젝트의 메일링 리스트입니다.
  • GitHub: rails-i18n - rails-i18n 프로젝트의 코드 저장소 및 이슈 트래커입니다. 가장 중요한 것은 대부분의 경우 애플리케이션에 작동할 수 있는 Rails용 예제 번역을 찾을 수 있습니다.
  • GitHub: i18n - i18n 젬의 코드 저장소 및 이슈 트래커입니다.

11 저자

12 각주

1 또는 위키백과를 인용하면 다음과 같습니다: "국제화는 소프트웨어 응용 프로그램을 공학적인 변경 없이 다양한 언어와 지역에 적응할 수 있도록 설계하는 과정입니다. 지역화는 특정 지역이나 언어에 대해 소프트웨어를 적응시키기 위해 로케일별 구성 요소를 추가하고 텍스트를 번역하는 과정입니다."

2 다른 백엔드는 다른 형식을 사용하도록 허용하거나 요구할 수 있습니다. 예를 들어 GetText 백엔드는 GetText 파일을 읽을 수 있을 수 있습니다.

3 이러한 이유 중 하나는 I18n 기능이 필요하지 않은 애플리케이션에 불필요한 부하를 암시하지 않기 위해서이며, 따라서 영어에 대해서는 가능한 한 I18n 라이브러리를 간단하게 유지해야 합니다. 또 다른 이유는 모든 기존 언어에 대한 I18n과 관련된 모든 문제에 대해 일반적인 해결책을 구현하는 것이 사실상 불가능하기 때문입니다. 따라서 전체 구현을 쉽게 교체할 수 있는 솔루션이 적절합니다. 이는 사용자 정의 기능과 확장을 실험하는 데도 훨씬 쉽게 만들어줍니다.

피드백

이 가이드의 품질을 개선하는 데 도움을 주시기를 권장합니다.

오타나 사실적인 오류를 발견하면 기여해주십시오. 시작하려면 문서 기여 섹션을 읽어보세요.

불완전한 내용이나 최신 정보가 아닌 내용을 발견할 수도 있습니다. 주요한 부분에 누락된 문서를 추가해주세요. Edge 가이드에서 이미 문제가 해결되었는지 확인하세요. 스타일과 규칙은 Ruby on Rails 가이드 지침을 확인하세요.

수정할 내용을 발견했지만 직접 수정할 수 없는 경우 이슈를 열어주세요.

마지막으로, Ruby on Rails 문서에 관한 모든 토론은 공식 Ruby on Rails 포럼에서 환영합니다.