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"

Language Compatibility

require "philiprehberger/locale_kit"

en_us = Philiprehberger::LocaleKit.parse("en-US")
en_us.compatible?("en-GB")  #=> true  (same primary language)
en_us.compatible?("en")      #=> true
en_us.compatible?("fr-FR")  #=> false
en_us.compatible?("bogus!") #=> false (invalid tag)
en_us.compatible?(nil)       #=> false

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
#compatible?(other) True if other shares the same primary language subtag (accepts Locale or tag string)
#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