diff --git a/Library/Homebrew/cask/spec/locale_spec.rb b/Library/Homebrew/cask/spec/locale_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..98a2de91394690711f3d372c5c3e3a803963b0af
--- /dev/null
+++ b/Library/Homebrew/cask/spec/locale_spec.rb
@@ -0,0 +1,72 @@
+require "spec_helper"
+require "locale"
+
+describe Locale do
+  describe "::parse" do
+    it "parses a string in the correct format" do
+      expect(described_class.parse("zh")).to eql(described_class.new("zh", nil, nil))
+      expect(described_class.parse("zh-CN")).to eql(described_class.new("zh", "CN", nil))
+      expect(described_class.parse("zh-Hans")).to eql(described_class.new("zh", nil, "Hans"))
+      expect(described_class.parse("zh-CN-Hans")).to eql(described_class.new("zh", "CN", "Hans"))
+    end
+
+    context "raises a ParserError when given" do
+      it "an empty string" do
+        expect{ described_class.parse("") }.to raise_error(Locale::ParserError)
+      end
+
+      it "a string in a wrong format" do
+        expect { described_class.parse("zh_CN_Hans") }.to raise_error(Locale::ParserError)
+        expect { described_class.parse("zhCNHans") }.to raise_error(Locale::ParserError)
+        expect { described_class.parse("zh-CN_Hans") }.to raise_error(Locale::ParserError)
+        expect { described_class.parse("zhCN") }.to raise_error(Locale::ParserError)
+        expect { described_class.parse("zh_Hans") }.to raise_error(Locale::ParserError)
+      end
+    end
+  end
+
+  describe "::new" do
+    it "raises an ArgumentError when all arguments are nil" do
+      expect { described_class.new(nil, nil, nil) }.to raise_error(ArgumentError)
+    end
+
+    it "raises a ParserError when one of the arguments does not match the locale format" do
+      expect { described_class.new("ZH", nil, nil) }.to raise_error(Locale::ParserError)
+      expect { described_class.new(nil, "cn", nil) }.to raise_error(Locale::ParserError)
+      expect { described_class.new(nil, nil, "hans") }.to raise_error(Locale::ParserError)
+    end
+  end
+
+  subject { described_class.new("zh", "CN", "Hans") }
+
+  describe "#include?" do
+    it { is_expected.to include("zh") }
+    it { is_expected.to include("zh-CN") }
+    it { is_expected.to include("CN") }
+    it { is_expected.to include("CN-Hans") }
+    it { is_expected.to include("Hans") }
+    it { is_expected.to include("zh-CN-Hans") }
+  end
+
+  describe "#eql?" do
+    subject { described_class.new("zh", "CN", "Hans") }
+
+    context "all parts match" do
+      it { is_expected.to eql("zh-CN-Hans") }
+      it { is_expected.to eql(subject) }
+    end
+
+    context "only some parts match" do
+      it { is_expected.to_not eql("zh") }
+      it { is_expected.to_not eql("zh-CN") }
+      it { is_expected.to_not eql("CN") }
+      it { is_expected.to_not eql("CN-Hans") }
+      it { is_expected.to_not eql("Hans") }
+    end
+
+    it "does not raise if 'other' cannot be parsed" do
+      expect { subject.eql?("zh_CN_Hans") }.not_to raise_error
+      expect(subject.eql?("zh_CN_Hans")).to be false
+    end
+  end
+end
diff --git a/Library/Homebrew/locale.rb b/Library/Homebrew/locale.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1aff33dae6c8b4894fc41e0ab614ea58fd1c5301
--- /dev/null
+++ b/Library/Homebrew/locale.rb
@@ -0,0 +1,68 @@
+class Locale
+  class ParserError < ::RuntimeError
+  end
+
+  LANGUAGE_REGEX = /(?:[a-z]{2})/
+  REGION_REGEX = /(?:[A-Z]{2})/
+  SCRIPT_REGEX = /(?:[A-Z][a-z]{3})/
+
+  LOCALE_REGEX = /^(#{LANGUAGE_REGEX})?(?:(?:^|-)(#{REGION_REGEX}))?(?:(?:^|-)(#{SCRIPT_REGEX}))?$/
+
+  def self.parse(string)
+    language, region, script = string.to_s.scan(LOCALE_REGEX)[0]
+
+    if language.nil? && region.nil? && script.nil?
+      raise ParserError, "'#{string}' cannot be parsed to a #{self.class}"
+    end
+
+    new(language, region, script)
+  end
+
+  attr_reader :language, :region, :script
+
+  def initialize(language, region, script)
+    if language.nil? && region.nil? && script.nil?
+      raise ArgumentError, "#{self.class} cannot be empty"
+    end
+
+    {
+      language: language,
+      region:   region,
+      script:   script,
+    }.each do |key, value|
+      next if value.nil?
+
+      regex = self.class.const_get("#{key.upcase}_REGEX")
+      raise ParserError, "'#{value}' does not match #{regex}" unless value =~ regex
+      instance_variable_set(:"@#{key}", value)
+    end
+
+    self
+  end
+
+  def include?(other)
+    other = self.class.parse(other) unless other.is_a?(self.class)
+
+    [:language, :region, :script].all? { |var|
+      if other.public_send(var).nil?
+        true
+      else
+        public_send(var) == other.public_send(var)
+      end
+    }
+  end
+
+  def eql?(other)
+    other = self.class.parse(other) unless other.is_a?(self.class)
+    [:language, :region, :script].all? { |var|
+      public_send(var) == other.public_send(var)
+    }
+  rescue ParserError
+    false
+  end
+  alias == eql?
+
+  def to_s
+    [@language, @region, @script].compact.join("-")
+  end
+end