All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.dev.teogor.xenoglot.locale.XenoglotLocale.kt Maven / Gradle / Ivy

/*
 * Copyright 2024 teogor (Teodor Grigor)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package dev.teogor.xenoglot.locale

import dev.teogor.xenoglot.Country
import dev.teogor.xenoglot.Language
import dev.teogor.xenoglot.atlas.extended.ExtendedCountryLanguageRegistry

/**
 * Represents a locale with a specific language and optional country.
 *
 * This class provides methods to retrieve locale-specific information such as display names
 * and language tags. It also allows setting and getting default locales for different categories.
 *
 * @param language The [Language] associated with this locale.
 * @param country The optional [Country] associated with this locale.
 *
 * @see Language
 * @see Country
 */
class XenoglotLocale(
  val language: Language,
  val country: Country?,
) {
  /**
   * Constructs a [XenoglotLocale] with a language and no country.
   *
   * @param language The [Language] associated with this locale.
   */
  constructor(language: Language) : this(language, null)

  /**
   * Retrieves the display name of the language in the default display locale.
   *
   * @return The display name of the language.
   */
  fun getDisplayLanguage(): String {
    return getDisplayLanguage(getDefault(LocaleCategory.DISPLAY))
  }

  /**
   * Retrieves the display name of the language in the specified locale.
   *
   * @param inLocale The [XenoglotLocale] to use for localization.
   * @return The display name of the language in the specified locale.
   */
  fun getDisplayLanguage(inLocale: XenoglotLocale): String {
    val localizations = ExtendedCountryLanguageRegistry.getLocalizations(inLocale.language.code)
    return localizations.first { it.code == language.code }.language
  }

  /**
   * Retrieves the display name of the country in the default display locale.
   *
   * @return The display name of the country, or `null` if no country is specified.
   */
  fun getDisplayCountry(): String? {
    return getDisplayCountry(getDefault(LocaleCategory.DISPLAY))
  }

  /**
   * Retrieves the display name of the country in the specified locale.
   *
   * @param inLocale The [XenoglotLocale] to use for localization.
   * @return The display name of the country in the specified locale, or `null` if no country is specified.
   */
  fun getDisplayCountry(inLocale: XenoglotLocale): String? {
    if (country == null) return null

    val localizations = ExtendedCountryLanguageRegistry.getLocalizations(inLocale.language.code)
    return localizations.first { it.code == language.code }.country
  }

  /**
   * Retrieves the display name of the locale in the default display locale.
   *
   * @return The display name of the locale.
   */
  fun getDisplayName(): String {
    return getDisplayName(getDefault(LocaleCategory.DISPLAY))
  }

  /**
   * Retrieves the display name of the locale in the specified locale.
   *
   * @param inLocale The [XenoglotLocale] to use for localization.
   * @return The display name of the locale in the specified locale.
   */
  fun getDisplayName(inLocale: XenoglotLocale): String {
    val languageName = getDisplayLanguage(inLocale)
    val countryName = getDisplayCountry(inLocale)

    return buildString {
      append(languageName)
      if (countryName != null) {
        append(" ($countryName)")
      }
    }
  }

  /**
   * Returns a well-formed IETF BCP 47 language tag representing the locale.
   *
   * @return The language tag for the locale.
   */
  fun toLanguageTag(): String {
    return buildString {
      append(language.languageTag)
      if (country != null) {
        append("_${country.code.uppercase()}")
      }
    }
  }

  /**
   * Compares this locale to another object for equality.
   *
   * @param other The other object to compare with.
   * @return `true` if the locales are equal, `false` otherwise.
   */
  override fun equals(other: Any?): Boolean {
    if (this === other) return true
    if (other !is XenoglotLocale) return false
    return this.language == other.language && this.country == other.country
  }

  /**
   * Returns a hash code for the locale.
   *
   * @return The hash code of the locale.
   */
  override fun hashCode(): Int {
    var result = language.hashCode()
    result = 31 * result + (country?.hashCode() ?: 0)
    return result
  }

  /**
   * Returns a string representation of the locale.
   *
   * @return A string describing the locale.
   */
  override fun toString(): String {
    return buildString {
      append(language.code)
      if (country != null) {
        append("_${country.code.uppercase()}")
      }
    }
  }

  companion object {
    private var defaultLocale: XenoglotLocale = XenoglotLocale(
      Language.English,
      Country.UnitedStates,
    )

    private val categoryDefaults: MutableMap = mutableMapOf(
      LocaleCategory.DISPLAY to defaultLocale,
      LocaleCategory.FORMAT to defaultLocale,
    )

    /**
     * Returns the default locale for the general case.
     *
     * @return The default locale.
     */
    fun getDefault(): XenoglotLocale {
      return defaultLocale
    }

    /**
     * Sets the default locale for the general case.
     *
     * @param newLocale The new default locale.
     */
    fun setDefault(newLocale: XenoglotLocale) {
      defaultLocale = newLocale
      categoryDefaults[LocaleCategory.DISPLAY] = newLocale
      categoryDefaults[LocaleCategory.FORMAT] = newLocale
    }

    /**
     * Gets the default locale for the specified category.
     *
     * @param category The [LocaleCategory] to get the default locale for.
     * @return The default locale for the specified category.
     */
    fun getDefault(category: LocaleCategory): XenoglotLocale {
      return categoryDefaults[category] ?: defaultLocale
    }

    /**
     * Sets the default locale for the specified category.
     *
     * @param category The [LocaleCategory] to set the default locale for.
     * @param newLocale The new default locale for the specified category.
     */
    fun setDefault(category: LocaleCategory, newLocale: XenoglotLocale) {
      categoryDefaults[category] = newLocale
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy