The project is in a healthy, maintained state
Parse BCP 47 language tags, negotiate content language from Accept-Language headers, and match locales with fallback chains. Zero dependencies.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies
 Project Readme

philiprehberger-locale_kit

Tests Gem Version Last updated

BCP 47 locale parsing, matching, and content negotiation

Requirements

  • Ruby >= 3.1

Installation

Add to your Gemfile:

gem "philiprehberger-locale_kit"

Or install directly:

gem install philiprehberger-locale_kit

Usage

require "philiprehberger/locale_kit"

locale = Philiprehberger::LocaleKit.parse("en-US")
locale.language #=> "en"
locale.region   #=> "US"
locale.to_s     #=> "en-US"

Parsing BCP 47 Tags

require "philiprehberger/locale_kit"

# Language + region
en_us = Philiprehberger::LocaleKit.parse("en-US")

# Language + script + region
zh_hant_tw = Philiprehberger::LocaleKit.parse("zh-Hant-TW")
zh_hant_tw.script #=> "Hant"

# Variant subtags
locale = Philiprehberger::LocaleKit.parse("en-US-valencia")
locale.variant #=> "valencia"

# Unicode extensions
locale = Philiprehberger::LocaleKit.parse("en-u-ca-buddhist")
locale.extensions #=> { "u" => "ca-buddhist" }

Display Names

require "philiprehberger/locale_kit"

Philiprehberger::LocaleKit.parse("en-US").display_name  #=> "English (United States)"
Philiprehberger::LocaleKit.parse("ja-JP").display_name   #=> "Japanese (Japan)"
Philiprehberger::LocaleKit.parse("zh-CN").display_name   #=> "Chinese (China)"
Philiprehberger::LocaleKit.parse("fr").display_name       #=> "French"

Language Families

require "philiprehberger/locale_kit"

Philiprehberger::LocaleKit.parse("en").language_family  #=> :germanic
Philiprehberger::LocaleKit.parse("fr").language_family  #=> :romance
Philiprehberger::LocaleKit.parse("ru").language_family  #=> :slavic
Philiprehberger::LocaleKit.parse("zh").language_family  #=> :sino_tibetan
Philiprehberger::LocaleKit.parse("ja").language_family  #=> :japonic
Philiprehberger::LocaleKit.parse("ko").language_family  #=> :koreanic
Philiprehberger::LocaleKit.parse("ar").language_family  #=> :semitic

Language and Region Lookups

require "philiprehberger/locale_kit"

Philiprehberger::LocaleKit.languages["en"]  #=> "English"
Philiprehberger::LocaleKit.languages["ja"]  #=> "Japanese"

Philiprehberger::LocaleKit.regions["US"]  #=> "United States"
Philiprehberger::LocaleKit.regions["JP"]  #=> "Japan"

Content Negotiation

require "philiprehberger/locale_kit"

result = Philiprehberger::LocaleKit.negotiate(
  ["en-US", "fr"],          # requested by client
  ["en", "fr", "de"],       # available on server
  default: "en"
)
result.to_s #=> "en"

Accept-Language Header Parsing

require "philiprehberger/locale_kit"

entries = Philiprehberger::LocaleKit.parse_accept_language(
  "en-US,en;q=0.9,zh-Hant;q=0.8,*;q=0.1"
)
entries[0][:locale].to_s #=> "en-US"
entries[0][:quality]     #=> 1.0

API

Philiprehberger::LocaleKit

Method Description
.parse(tag) Parse a BCP 47 tag string into a Locale object
.negotiate(requested, available, default: nil) Find the best matching locale with fallback chains
.parse_accept_language(header) Parse an Accept-Language header into [{locale:, quality:}]
.languages Hash of ISO 639-1 language codes to English names
.regions Hash of ISO 3166-1 alpha-2 region codes to English names

Philiprehberger::LocaleKit::Locale

Method Description
#language Language subtag (e.g., "en")
#script Script subtag (e.g., "Hant") or nil
#region Region subtag (e.g., "US") or nil
#variant Variant subtag (e.g., "valencia") or nil
#extensions Extension subtags hash (e.g., { "u" => "ca-buddhist" })
#to_s Canonical BCP 47 string (e.g., "en-US")
#parent Parent locale (en-US -> en -> nil)
#match?(other) True if other is a prefix match
#display_name(in_locale: nil) Human-readable name (e.g., "English (United States)")
#language_family Language family symbol (e.g., :germanic)
#==(other) Equality based on all subtags
#<=>(other) Comparison for sorting

Development

bundle install
bundle exec rspec
bundle exec rubocop

Support

If you find this project useful:

Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT