DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (6b93a83735ed)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode:nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_intl_MozLocale_h__
#define mozilla_intl_MozLocale_h__

#include "nsString.h"
#include "nsTArray.h"

namespace mozilla {
namespace intl {

/**
 * Locale class is a core representation of a single locale.
 *
 * A locale is a data object representing a combination of language, script,
 * region, variant and a set of regional extension preferences that may further
 * specify particular user choices like calendar, numbering system, etc.
 *
 * A locale can be expressed as a language tag string, like a simple "fr" for
 * French, or a more specific "sr-Cyrl-RS-u-hc-h12" for Serbian in Russia with a
 * Cyrylic script, and hour cycle selected to be `h12`.
 *
 * The format of the language tag follows BCP47 standard and implements a subset
 * of it. In the future we expect to extend this class to cover more subtags and
 * extensions.
 *
 * BCP47: https://tools.ietf.org/html/bcp47
 *
 * The aim of this class it aid in validation, parsing and canonicalization of
 * the string.
 *
 * It allows the user to input any well-formed BCP47 language tag and operate
 * on its subtags in a canonicalized form.
 *
 * It should be used for all operations on language tags, and together with
 * LocaleService::NegotiateLanguages for language negotiation.
 *
 * Example:
 *
 *     Locale loc = Locale("de-at");
 *
 *     ASSERT_TRUE(loc.GetLanguage().Equals("de"));
 *     ASSERT_TRUE(loc.GetScript().IsEmpty());
 *     ASSERT_TRUE(loc.GetRegion().Equals("AT")); // canonicalized to upper case
 *
 *
 * Note: The file name is `MozLocale` to avoid compilation problems on
 * case-insensitive Windows. The class name is `Locale`.
 */
class Locale {
 public:
  /**
   * The constructor expects the input to be a well-formed BCP47-style locale
   * string.
   *
   * Two operations are performed on the well-formed language tags:
   *
   *  * Case normalization to conform with BCP47 (e.g. "eN-uS" -> "en-US")
   *  * Underscore delimiters replaced with dashed (e.g. "en_US" -> "en-US")
   *
   * If the input language tag string is not well-formed, the Locale will be
   * created with its flag `mWellFormed` set to false which will make the Locale
   * never match.
   */
  explicit Locale(const nsACString& aLocale);
  explicit Locale(const char* aLocale) : Locale(nsDependentCString(aLocale)){};

  const nsCString& GetLanguage() const;
  const nsCString& GetScript() const;
  const nsCString& GetRegion() const;
  const nsTArray<nsCString>& GetVariants() const;

  /**
   * Returns a `true` if the locale is well-formed, such that the
   * Locale object can validly be matched against others.
   */
  bool IsWellFormed() const { return mIsWellFormed; }

  /**
   * Returns a canonicalized language tag string of the locale.
   */
  const nsCString AsString() const;

  /**
   * Compares two locales optionally treating one or both of
   * the locales as a range.
   *
   * In case one of the locales is treated as a range, its
   * empty fields are considered to match all possible
   * values of the same field on the other locale.
   *
   * Example:
   *
   * Locale("en").Matches(Locale("en-US"), false, false) // false
   * Locale("en").Matches(Locale("en-US"), true, false)  // true
   *
   * The latter returns true because the region field on the "en"
   * locale is being treated as a range and matches any region field
   * value including "US" of the other locale.
   */
  bool Matches(const Locale& aOther, bool aThisRange, bool aOtherRange) const;

  /**
   * This operation uses CLDR data to build a more specific version
   * of a generic locale.
   *
   * Example:
   *
   * Locale("en").AddLikelySubtags().AsString(); // "en-Latn-US"
   */
  bool AddLikelySubtags();

  /**
   * Clears the variants field of the Locale object.
   */
  void ClearVariants();

  /**
   * Clears the region field of the Locale object.
   */
  void ClearRegion();

  /**
   * Marks the locale as invalid which in turns makes
   * it to be skipped by most LocaleService operations.
   */
  void Invalidate() { mIsWellFormed = false; }

  /**
   * Compares two locales expecting all fields to match each other.
   */
  bool operator==(const Locale& aOther) {
    // Note: non-well-formed Locale objects are never
    // treated as equal to anything
    // (even other non-well-formed ones).
    return IsWellFormed() && aOther.IsWellFormed() &&
           mLanguage.Equals(aOther.mLanguage) &&
           mScript.Equals(aOther.mScript) && mRegion.Equals(aOther.mRegion) &&
           mVariants == aOther.mVariants && mPrivateUse == aOther.mPrivateUse;
  }

 private:
  nsAutoCStringN<3> mLanguage;
  nsAutoCStringN<4> mScript;
  nsAutoCStringN<2> mRegion;
  nsTArray<nsCString> mVariants;
  nsTArray<nsCString> mPrivateUse;
  bool mIsWellFormed = true;
};

}  // namespace intl
}  // namespace mozilla

DECLARE_USE_COPY_CONSTRUCTORS(mozilla::intl::Locale)

#endif /* mozilla_intl_MozLocale_h__ */