├── .github
├── funding.yml
└── workflows
│ ├── build.yml
│ ├── publish-release.yml
│ └── publish-snapshot.yml
├── multiplatform-locale-all
├── api
│ └── current.txt
├── gradle.properties
├── src
│ └── commonMain
│ │ └── kotlin
│ │ └── com
│ │ └── vanniktech
│ │ └── locale
│ │ └── all
│ │ └── iosworkaround.kt
├── build.gradle.kts
└── MultiplatformLocaleAll.podspec
├── MultiplatformLocale.podspec
├── MultiplatformLocaleAll.podspec
├── MultiplatformLocaleGeo.podspec
├── sample-ios.png
├── sample-jvm.png
├── multiplatform-locale
├── gradle.properties
├── src
│ ├── commonMain
│ │ └── kotlin
│ │ │ └── com
│ │ │ └── vanniktech
│ │ │ └── locale
│ │ │ ├── Continent.kt
│ │ │ ├── capitalize.kt
│ │ │ ├── Languages.kt
│ │ │ ├── Countries.kt
│ │ │ ├── Locales.kt
│ │ │ ├── Territory.kt
│ │ │ ├── Region.kt
│ │ │ ├── Locale.kt
│ │ │ └── Language.kt
│ ├── jvmMain
│ │ └── kotlin
│ │ │ └── com
│ │ │ └── vanniktech
│ │ │ └── locale
│ │ │ ├── Countries.kt
│ │ │ ├── Languages.kt
│ │ │ ├── Locales.kt
│ │ │ └── Multiplatform.jvm.kt
│ ├── androidMain
│ │ └── kotlin
│ │ │ └── com
│ │ │ └── vanniktech
│ │ │ └── locale
│ │ │ ├── Countries.kt
│ │ │ ├── Languages.kt
│ │ │ ├── Multiplatform.android.kt
│ │ │ └── Locales.kt
│ ├── commonTest
│ │ └── kotlin
│ │ │ └── com
│ │ │ └── vanniktech
│ │ │ └── locale
│ │ │ ├── CountriesTest.kt
│ │ │ ├── LanguagesTest.kt
│ │ │ ├── LocalesTest.kt
│ │ │ ├── LanguageTest.kt
│ │ │ ├── RegionTest.kt
│ │ │ ├── LocaleTest.kt
│ │ │ └── CountryTest.kt
│ └── iosMain
│ │ └── kotlin
│ │ └── com
│ │ └── vanniktech
│ │ └── locale
│ │ ├── Languages.kt
│ │ ├── Countries.kt
│ │ ├── Locales.kt
│ │ └── Multiplatform.ios.kt
├── build.gradle.kts
└── MultiplatformLocale.podspec
├── sample-android.png
├── multiplatform-locale-geo
├── gradle.properties
├── src
│ └── commonMain
│ │ └── kotlin
│ │ └── com
│ │ └── vanniktech
│ │ └── locale
│ │ └── geo
│ │ └── Geo.kt
├── api
│ └── current.txt
├── build.gradle.kts
└── MultiplatformLocaleGeo.podspec
├── renovate.json
├── MultiplatformLocaleGooglePlayStore.podspec
├── gradle
├── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
└── libs.versions.toml
├── sample-ios
├── ios
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Preview Content
│ │ └── Preview Assets.xcassets
│ │ │ └── Contents.json
│ └── App.swift
├── ios.xcodeproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── project.pbxproj
├── ios.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── Podfile
├── Podfile.lock
└── LICENSE
├── multiplatform-locale-apple-app-store
├── gradle.properties
├── src
│ ├── commonMain
│ │ └── kotlin
│ │ │ └── com
│ │ │ └── vanniktech
│ │ │ └── locale
│ │ │ └── apple
│ │ │ └── app
│ │ │ └── store
│ │ │ └── AppleAppStoreLocale.kt
│ └── commonTest
│ │ └── kotlin
│ │ └── com
│ │ └── vanniktech
│ │ └── locale
│ │ └── apple
│ │ └── app
│ │ └── store
│ │ └── AppleAppStoreLocaleTest.kt
├── build.gradle.kts
├── MultiplatformLocaleAppleAppStore.podspec
└── api
│ └── current.txt
├── multiplatform-locale-google-play-store
├── gradle.properties
├── build.gradle.kts
├── src
│ ├── commonMain
│ │ └── kotlin
│ │ │ └── com
│ │ │ └── vanniktech
│ │ │ └── locale
│ │ │ └── google
│ │ │ └── play
│ │ │ └── store
│ │ │ └── GooglePlayStoreLocale.kt
│ └── commonTest
│ │ └── kotlin
│ │ └── com
│ │ └── vanniktech
│ │ └── locale
│ │ └── google
│ │ └── play
│ │ └── store
│ │ └── GooglePlayStoreLocaleTest.kt
├── MultiplatformLocaleGooglePlayStore.podspec
└── api
│ └── current.txt
├── sample-android
├── src
│ └── main
│ │ ├── res
│ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ ├── values
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ ├── values-v23
│ │ │ └── themes.xml
│ │ ├── values-v27
│ │ │ └── themes.xml
│ │ └── layout
│ │ │ └── activity_main.xml
│ │ ├── kotlin
│ │ └── com
│ │ │ └── vanniktech
│ │ │ └── locale
│ │ │ └── sample
│ │ │ └── android
│ │ │ ├── LocaleApplication.kt
│ │ │ └── LocaleMainActivity.kt
│ │ └── AndroidManifest.xml
└── build.gradle.kts
├── generator
├── build.gradle.kts
└── src
│ └── main
│ └── kotlin
│ └── com
│ └── vanniktech
│ └── locale
│ └── generator
│ └── main.kt
├── sample-jvm
├── build.gradle.kts
└── src
│ └── main
│ └── java
│ └── com
│ └── vanniktech
│ └── locale
│ └── sample
│ └── jvm
│ └── LocaleJvm.kt
├── settings.gradle.kts
├── lint.xml
├── .editorconfig
├── .gitignore
├── gradle.properties
├── README.md
├── gradlew.bat
├── gradlew
├── LICENSE
└── CHANGELOG.md
/.github/funding.yml:
--------------------------------------------------------------------------------
1 | github: [vanniktech]
--------------------------------------------------------------------------------
/multiplatform-locale-all/api/current.txt:
--------------------------------------------------------------------------------
1 | // Signature format: 4.0
2 |
--------------------------------------------------------------------------------
/MultiplatformLocale.podspec:
--------------------------------------------------------------------------------
1 | multiplatform-locale/MultiplatformLocale.podspec
--------------------------------------------------------------------------------
/MultiplatformLocaleAll.podspec:
--------------------------------------------------------------------------------
1 | multiplatform-locale-all/MultiplatformLocaleAll.podspec
--------------------------------------------------------------------------------
/MultiplatformLocaleGeo.podspec:
--------------------------------------------------------------------------------
1 | multiplatform-locale-geo/MultiplatformLocaleGeo.podspec
--------------------------------------------------------------------------------
/sample-ios.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vanniktech/multiplatform-locale/HEAD/sample-ios.png
--------------------------------------------------------------------------------
/sample-jvm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vanniktech/multiplatform-locale/HEAD/sample-jvm.png
--------------------------------------------------------------------------------
/multiplatform-locale/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=Locale
2 | POM_ARTIFACT_ID=multiplatform-locale
3 |
--------------------------------------------------------------------------------
/sample-android.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vanniktech/multiplatform-locale/HEAD/sample-android.png
--------------------------------------------------------------------------------
/multiplatform-locale-all/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=Locale All
2 | POM_ARTIFACT_ID=multiplatform-locale-all
3 |
--------------------------------------------------------------------------------
/multiplatform-locale-geo/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=Locale Geo
2 | POM_ARTIFACT_ID=multiplatform-locale-geo
3 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:base",
4 | ":disableDependencyDashboard"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/MultiplatformLocaleGooglePlayStore.podspec:
--------------------------------------------------------------------------------
1 | multiplatform-locale-google-play-store/MultiplatformLocaleGooglePlayStore.podspec
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vanniktech/multiplatform-locale/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/sample-ios/ios/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/multiplatform-locale-apple-app-store/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=Locale Apple App Store
2 | POM_ARTIFACT_ID=multiplatform-locale-apple-app-store
3 |
--------------------------------------------------------------------------------
/multiplatform-locale-google-play-store/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=Locale Google Play Store
2 | POM_ARTIFACT_ID=multiplatform-locale-google-play-store
3 |
--------------------------------------------------------------------------------
/sample-ios/ios/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/sample-android/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vanniktech/multiplatform-locale/HEAD/sample-android/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample-android/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vanniktech/multiplatform-locale/HEAD/sample-android/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample-android/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vanniktech/multiplatform-locale/HEAD/sample-android/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample-android/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vanniktech/multiplatform-locale/HEAD/sample-android/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample-android/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vanniktech/multiplatform-locale/HEAD/sample-android/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample-ios/ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/multiplatform-locale-all/src/commonMain/kotlin/com/vanniktech/locale/all/iosworkaround.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("standard:no-empty-file")
2 |
3 | package com.vanniktech.locale.all
4 |
5 | // Empty file is required for iOS, otherwise it fails.
6 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/commonMain/kotlin/com/vanniktech/locale/Continent.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | enum class Continent {
4 | ASIA,
5 | AFRICA,
6 | NORTH_AMERICA,
7 | SOUTH_AMERICA,
8 | ANTARCTICA,
9 | EUROPE,
10 | OCEANIA,
11 | }
12 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/commonMain/kotlin/com/vanniktech/locale/capitalize.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | internal fun String.capitalized() = replaceFirstChar {
4 | when {
5 | it.isLowerCase() -> it.titlecase()
6 | else -> it.toString()
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/sample-android/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Locale
4 | false
5 |
6 |
--------------------------------------------------------------------------------
/sample-android/src/main/res/values-v23/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-all.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/jvmMain/kotlin/com/vanniktech/locale/Countries.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | import java.util.Locale
4 |
5 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
6 | actual object Countries {
7 | actual fun currentCountryCode(): String? = Locale.getDefault().country
8 | }
9 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/jvmMain/kotlin/com/vanniktech/locale/Languages.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | import java.util.Locale
4 |
5 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
6 | actual object Languages {
7 | actual fun currentLanguageCode(): String = Locale.getDefault().language
8 | }
9 |
--------------------------------------------------------------------------------
/sample-ios/ios.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/androidMain/kotlin/com/vanniktech/locale/Countries.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | import java.util.Locale
4 |
5 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
6 | actual object Countries {
7 | actual fun currentCountryCode(): String? = Locale.getDefault().country
8 | }
9 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/androidMain/kotlin/com/vanniktech/locale/Languages.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | import java.util.Locale
4 |
5 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
6 | actual object Languages {
7 | actual fun currentLanguageCode(): String = Locale.getDefault().language
8 | }
9 |
--------------------------------------------------------------------------------
/sample-ios/ios.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/sample-ios/ios.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/commonTest/kotlin/com/vanniktech/locale/CountriesTest.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | import kotlin.test.Test
4 | import kotlin.test.assertEquals
5 |
6 | class CountriesTest {
7 | @Test fun currentCountryCode() {
8 | assertEquals(expected = "US", actual = Countries.currentCountryCode())
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/commonTest/kotlin/com/vanniktech/locale/LanguagesTest.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | import kotlin.test.Test
4 | import kotlin.test.assertEquals
5 |
6 | class LanguagesTest {
7 | @Test fun currentLanguageCode() {
8 | assertEquals(expected = "en", actual = Languages.currentLanguageCode())
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/sample-ios/Podfile:
--------------------------------------------------------------------------------
1 | source "https://cdn.cocoapods.org/"
2 | platform :ios, '14.0'
3 | workspace "ios"
4 |
5 | # Comment this line if you're not using Swift and don't want to use dynamic frameworks.
6 | use_frameworks!
7 |
8 | target 'ios' do
9 | project 'ios'
10 |
11 | pod "MultiplatformLocaleAll", :path => "../multiplatform-locale-all"
12 | end
13 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/commonMain/kotlin/com/vanniktech/locale/Languages.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
4 | expect object Languages {
5 | /** Returns the current ISO 639-1 [Language.code] - https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes. */
6 | fun currentLanguageCode(): String
7 | }
8 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/commonMain/kotlin/com/vanniktech/locale/Countries.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
4 | expect object Countries {
5 | /** Returns the current optional ISO 3166-1 alpha-2 [Country.code] - https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 */
6 | fun currentCountryCode(): String?
7 | }
8 |
--------------------------------------------------------------------------------
/sample-android/src/main/kotlin/com/vanniktech/locale/sample/android/LocaleApplication.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale.sample.android
2 |
3 | import android.app.Application
4 | import timber.log.Timber
5 |
6 | class LocaleApplication : Application() {
7 | override fun onCreate() {
8 | super.onCreate()
9 | Timber.plant(Timber.DebugTree())
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/multiplatform-locale-geo/src/commonMain/kotlin/com/vanniktech/locale/geo/Geo.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale.geo
2 |
3 | @ConsistentCopyVisibility data class Geo internal constructor(
4 | val latitude: Double,
5 | val longitude: Double,
6 | val maxLatitude: Double,
7 | val maxLongitude: Double,
8 | val minLatitude: Double,
9 | val minLongitude: Double,
10 | )
11 |
--------------------------------------------------------------------------------
/generator/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.jetbrains.kotlin.jvm")
3 | application
4 | alias(libs.plugins.kotlinSerialization)
5 | }
6 |
7 | kotlin {
8 | jvmToolchain(11)
9 | }
10 |
11 | application {
12 | mainClass.set("com.vanniktech.locale.generator.MainKt")
13 | }
14 |
15 | dependencies {
16 | implementation(libs.okio)
17 | implementation(libs.kaml)
18 | }
19 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/jvmMain/kotlin/com/vanniktech/locale/Locales.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | import java.util.Locale
4 |
5 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
6 | actual object Locales {
7 | actual fun currentLocaleString(): String = Locale.getDefault().toString()
8 |
9 | actual fun currentLocaleStrings() = listOf(currentLocaleString())
10 | }
11 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/iosMain/kotlin/com/vanniktech/locale/Languages.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | import platform.Foundation.NSLocale
4 | import platform.Foundation.currentLocale
5 | import platform.Foundation.languageCode
6 |
7 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
8 | actual object Languages {
9 | actual fun currentLanguageCode() = NSLocale.currentLocale.languageCode
10 | }
11 |
--------------------------------------------------------------------------------
/sample-jvm/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | application
3 | id("org.jetbrains.kotlin.jvm")
4 | }
5 |
6 | kotlin {
7 | jvmToolchain(11)
8 | }
9 |
10 | dependencies {
11 | implementation(project(":multiplatform-locale-all"))
12 | }
13 |
14 | dependencies {
15 | testImplementation(libs.kotlin.test.junit)
16 | }
17 |
18 | application {
19 | mainClass.set("com.vanniktech.locale.sample.jvm.LocaleJvmKt")
20 | }
21 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/iosMain/kotlin/com/vanniktech/locale/Countries.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | import platform.Foundation.NSLocale
4 | import platform.Foundation.countryCode
5 | import platform.Foundation.currentLocale
6 |
7 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
8 | actual object Countries {
9 | actual fun currentCountryCode(): String? = NSLocale.currentLocale.countryCode
10 | }
11 |
--------------------------------------------------------------------------------
/sample-android/src/main/res/values-v27/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
--------------------------------------------------------------------------------
/sample-ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - MultiplatformLocaleAll (0.10.0-SNAPSHOT)
3 |
4 | DEPENDENCIES:
5 | - MultiplatformLocaleAll (from `../multiplatform-locale-all`)
6 |
7 | EXTERNAL SOURCES:
8 | MultiplatformLocaleAll:
9 | :path: "../multiplatform-locale-all"
10 |
11 | SPEC CHECKSUMS:
12 | MultiplatformLocaleAll: 7a8aa6addcfc6e2bcd5dc38d97dcade45fc67a54
13 |
14 | PODFILE CHECKSUM: 9ed168d98ea160d8c0c0865fb29f7c761bf8bdfe
15 |
16 | COCOAPODS: 1.16.2
17 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/commonMain/kotlin/com/vanniktech/locale/Locales.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
4 | expect object Locales {
5 | /** Returns the current locale. */
6 | fun currentLocaleString(): String
7 |
8 | /**
9 | * On Android / JVM, it returns the supported locales.
10 | * On iOS, it returns the preferred languages.
11 | */
12 | fun currentLocaleStrings(): List
13 | }
14 |
--------------------------------------------------------------------------------
/sample-android/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
11 |
12 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | rootProject.name = "MultiplatformLocale"
2 |
3 | pluginManagement {
4 | repositories {
5 | mavenCentral()
6 | google()
7 | gradlePluginPortal()
8 | }
9 | }
10 |
11 | include(":generator")
12 | include(":multiplatform-locale")
13 | include(":multiplatform-locale-all")
14 | include(":multiplatform-locale-apple-app-store")
15 | include(":multiplatform-locale-geo")
16 | include(":multiplatform-locale-google-play-store")
17 | include(":sample-android")
18 | include(":sample-jvm")
19 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/iosMain/kotlin/com/vanniktech/locale/Locales.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | import platform.Foundation.NSLocale
4 | import platform.Foundation.currentLocale
5 | import platform.Foundation.localeIdentifier
6 | import platform.Foundation.preferredLanguages
7 |
8 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
9 | actual object Locales {
10 | actual fun currentLocaleString() = NSLocale.currentLocale.localeIdentifier
11 |
12 | actual fun currentLocaleStrings() = NSLocale.preferredLanguages.mapNotNull { it.toString() }
13 | }
14 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/commonMain/kotlin/com/vanniktech/locale/Territory.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | sealed interface Territory {
4 | /** ISO 3166-1 alpha-2 code - https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 */
5 | val code: String
6 |
7 | /** ISO 3166-1 alpha-3 code - https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3 */
8 | val code3: String
9 |
10 | /** Optional emoji. */
11 | val emoji: String?
12 |
13 | fun displayName() = commonDisplayName()
14 | }
15 |
16 | /** Returns the display name of [Territory] in the current language. */
17 | internal expect fun Territory.commonDisplayName(): String
18 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/jvmMain/kotlin/com/vanniktech/locale/Multiplatform.jvm.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | internal actual fun Language.commonDisplayName() = java.util.Locale(
4 | code,
5 | "",
6 | ).displayLanguage.capitalized()
7 |
8 | internal actual fun Territory.commonDisplayName() = when (this) {
9 | Region.INTERNATIONAL_WATERS -> "International Waters"
10 | else -> java.util.Locale(
11 | java.util.Locale.getDefault().language,
12 | code,
13 | ).displayCountry.capitalized()
14 | }
15 |
16 | fun Locale.toJavaLocale() = java.util.Locale(
17 | language.code,
18 | territory?.code.orEmpty(),
19 | )
20 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/androidMain/kotlin/com/vanniktech/locale/Multiplatform.android.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | internal actual fun Language.commonDisplayName() = java.util.Locale(
4 | code,
5 | "",
6 | ).displayLanguage.capitalized()
7 |
8 | internal actual fun Territory.commonDisplayName() = when (this) {
9 | Region.INTERNATIONAL_WATERS -> "International Waters"
10 | else -> java.util.Locale(
11 | java.util.Locale.getDefault().language,
12 | code,
13 | ).displayCountry.capitalized()
14 | }
15 |
16 | fun Locale.toJavaLocale() = java.util.Locale(
17 | language.code,
18 | territory?.code.orEmpty(),
19 | )
20 |
--------------------------------------------------------------------------------
/lint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.{kt,kts}]
2 | ktlint_code_style=intellij_idea
3 | indent_size=2
4 | continuation_indent_size=2
5 | ij_kotlin_allow_trailing_comma=true
6 | ij_kotlin_allow_trailing_comma_on_call_site=true
7 | insert_final_newline=true
8 | ktlint_standard_annotation=disabled
9 | ktlint_standard_max-line-length=disabled
10 | ktlint_standard_filename=disabled
11 | ktlint_standard_spacing-between-declarations-with-annotations=disabled
12 | ktlint_standard_blank-line-between-when-conditions=disabled
13 | ktlint_standard_backing-property-naming=disabled
14 | ktlint_standard_kdoc=disabled
15 | ktlint_standard_condition-wrapping=disabled
16 | ktlint_experimental=enabled
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 |
15 | # Gradle files
16 | .gradle/
17 | build/
18 |
19 | # Local configuration file (sdk path, etc)
20 | local.properties
21 |
22 | # Proguard folder generated by Eclipse
23 | proguard/
24 |
25 | # Android Studio
26 | .idea
27 | .gradle
28 | build/
29 | *.iml
30 |
31 | # iOS
32 | xcuserdata/
33 | *.ipa
34 | Pods/
35 |
36 | ios/fastlane/report.xml
37 | ios/fastlane/README.md
38 | *.dSYM.zip
39 |
40 | # Windows thumbnail db
41 | Thumbs.db
42 |
43 | # OSX files
44 | .DS_Store
45 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/androidMain/kotlin/com/vanniktech/locale/Locales.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | import android.os.Build.VERSION.SDK_INT
4 | import android.os.LocaleList
5 | import java.util.Locale
6 |
7 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
8 | actual object Locales {
9 | actual fun currentLocaleString(): String = Locale.getDefault().toString()
10 |
11 | actual fun currentLocaleStrings() = when {
12 | SDK_INT >= 24 -> {
13 | val locales = LocaleList.getDefault()
14 | (0 until locales.size()).map { locales[it] }
15 | }
16 | else -> {
17 | listOf(Locale.getDefault())
18 | }
19 | }.map { it.toString() }
20 | }
21 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/iosMain/kotlin/com/vanniktech/locale/Multiplatform.ios.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | import platform.Foundation.NSLocale
4 | import platform.Foundation.currentLocale
5 | import platform.Foundation.localizedStringForCountryCode
6 | import platform.Foundation.localizedStringForLanguageCode
7 |
8 | internal actual fun Language.commonDisplayName(): String = NSLocale.currentLocale.localizedStringForLanguageCode(code).orEmpty().capitalized()
9 |
10 | internal actual fun Territory.commonDisplayName() = when (this) {
11 | Region.INTERNATIONAL_WATERS -> "International Waters"
12 | else -> NSLocale.currentLocale.localizedStringForCountryCode(code).orEmpty().capitalized()
13 | }
14 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/commonTest/kotlin/com/vanniktech/locale/LocalesTest.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | import kotlin.test.Test
4 | import kotlin.test.assertEquals
5 |
6 | class LocalesTest {
7 | @Test fun currentLocaleString() {
8 | assertEquals(expected = "en_US", actual = Locales.currentLocaleString())
9 | }
10 |
11 | @Test fun currentLocaleStrings() {
12 | val currentLocaleStrings = Locales.currentLocaleStrings()
13 |
14 | assertEquals(
15 | message = currentLocaleStrings.joinToString(),
16 | expected = true,
17 | actual = currentLocaleStrings.contains("en_US") || currentLocaleStrings.contains("en-US"),
18 | )
19 |
20 | assertEquals(
21 | message = currentLocaleStrings.joinToString(),
22 | expected = true,
23 | actual = currentLocaleStrings.size >= 1,
24 | )
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on: [push, pull_request, merge_group]
4 |
5 | jobs:
6 | build:
7 | name: JDK ${{ matrix.java_version }}
8 | runs-on: macOS-latest
9 |
10 | strategy:
11 | matrix:
12 | java_version: [17]
13 |
14 | steps:
15 | - name: Checkout
16 | uses: actions/checkout@v6
17 |
18 | - name: Gradle Wrapper Validation
19 | uses: gradle/actions/wrapper-validation@v5
20 |
21 | - name: Setup gradle
22 | uses: gradle/gradle-build-action@v3
23 |
24 | - name: Install JDK ${{ matrix.java_version }}
25 | uses: actions/setup-java@v5
26 | with:
27 | distribution: 'zulu'
28 | java-version: ${{ matrix.java_version }}
29 |
30 | - name: Build with Gradle
31 | run: ./gradlew licensee jvmTest ktlint testDebug build --stacktrace
32 |
--------------------------------------------------------------------------------
/sample-android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
15 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/sample-jvm/src/main/java/com/vanniktech/locale/sample/jvm/LocaleJvm.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale.sample.jvm
2 |
3 | import com.vanniktech.locale.Country
4 | import com.vanniktech.locale.Language
5 | import com.vanniktech.locale.Locale
6 | import com.vanniktech.locale.Locales
7 | import com.vanniktech.locale.google.play.store.googlePlayStoreLocale
8 |
9 | fun main() {
10 | val currentLocaleString = Locales.currentLocaleString()
11 | println("Current Locale: $currentLocaleString")
12 | println("Google Play Store Locale: ${Locale.fromOrNull(currentLocaleString)?.googlePlayStoreLocale()?.toString() ?: "/"}")
13 | println("Apple App Store Locale: ${Locale.fromOrNull(currentLocaleString)?.googlePlayStoreLocale()?.toString() ?: "/"}")
14 | println()
15 | println("Current Locale Strings: ${Locales.currentLocaleStrings().joinToString(separator = ", ")}")
16 | println()
17 | println("All countries: ${Country.entries.joinToString { it.displayName() } }")
18 | println()
19 | println("All languages: ${Language.entries.joinToString { it.displayName() } }")
20 | }
21 |
--------------------------------------------------------------------------------
/.github/workflows/publish-release.yml:
--------------------------------------------------------------------------------
1 | name: Publish Release
2 |
3 | on:
4 | push:
5 | tags:
6 | - '*'
7 |
8 | jobs:
9 | publish:
10 |
11 | runs-on: macOS-latest
12 | if: github.repository == 'vanniktech/multiplatform-locale'
13 |
14 | steps:
15 | - name: Checkout
16 | uses: actions/checkout@v6
17 |
18 | - name: Install JDK 17
19 | uses: actions/setup-java@v5
20 | with:
21 | distribution: 'zulu'
22 | java-version: 17
23 |
24 | - name: Setup gradle
25 | uses: gradle/gradle-build-action@v3.5.0
26 |
27 | - name: Publish release
28 | run: ./gradlew publishAllPublicationsToMavenCentralRepository
29 | env:
30 | ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_NEXUS_USERNAME }}
31 | ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_NEXUS_PASSWORD }}
32 | ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.SIGNING_PRIVATE_KEY }}
33 | ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_PASSWORD }}
34 |
--------------------------------------------------------------------------------
/.github/workflows/publish-snapshot.yml:
--------------------------------------------------------------------------------
1 | name: Publish Snapshot
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 |
8 | jobs:
9 | publish:
10 |
11 | runs-on: macOS-latest
12 | if: github.repository == 'vanniktech/multiplatform-locale'
13 |
14 | steps:
15 | - name: Checkout
16 | uses: actions/checkout@v6
17 |
18 | - name: Install JDK 17
19 | uses: actions/setup-java@v5
20 | with:
21 | distribution: 'zulu'
22 | java-version: 17
23 |
24 | - name: Setup gradle
25 | uses: gradle/gradle-build-action@v3.5.0
26 |
27 | - name: Retrieve version
28 | run: |
29 | echo "VERSION_NAME=$(cat gradle.properties | grep -w "VERSION_NAME" | cut -d'=' -f2)" >> $GITHUB_ENV
30 |
31 | - name: Publish snapshot
32 | run: ./gradlew publishAllPublicationsToMavenCentralRepository
33 | if: endsWith(env.VERSION_NAME, '-SNAPSHOT')
34 | env:
35 | ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_NEXUS_USERNAME }}
36 | ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_NEXUS_PASSWORD }}
37 |
--------------------------------------------------------------------------------
/multiplatform-locale-geo/api/current.txt:
--------------------------------------------------------------------------------
1 | // Signature format: 4.0
2 | package com.vanniktech.locale.geo {
3 |
4 | public final class CountryGeoKt {
5 | method public static com.vanniktech.locale.geo.Geo getGeo(com.vanniktech.locale.Country);
6 | }
7 |
8 | public final class Geo {
9 | method public double component1();
10 | method public double component2();
11 | method public double component3();
12 | method public double component4();
13 | method public double component5();
14 | method public double component6();
15 | method public com.vanniktech.locale.geo.Geo copy(double latitude, double longitude, double maxLatitude, double maxLongitude, double minLatitude, double minLongitude);
16 | method public double getLatitude();
17 | method public double getLongitude();
18 | method public double getMaxLatitude();
19 | method public double getMaxLongitude();
20 | method public double getMinLatitude();
21 | method public double getMinLongitude();
22 | property public final double latitude;
23 | property public final double longitude;
24 | property public final double maxLatitude;
25 | property public final double maxLongitude;
26 | property public final double minLatitude;
27 | property public final double minLongitude;
28 | }
29 |
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/sample-android/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.android.application")
3 | id("org.jetbrains.kotlin.android")
4 | }
5 |
6 | kotlin {
7 | jvmToolchain(11)
8 | }
9 |
10 | android {
11 | namespace = "com.vanniktech.locale.sample.android"
12 |
13 | compileSdk = libs.versions.compileSdk.get().toInt()
14 |
15 | defaultConfig {
16 | applicationId = "com.vanniktech.locale.sample.android"
17 | vectorDrawables.useSupportLibrary = true
18 | minSdk = libs.versions.minSdk.get().toInt()
19 | targetSdk = libs.versions.targetSdk.get().toInt()
20 | versionCode = 1
21 | versionName = project.property("VERSION_NAME").toString()
22 |
23 | vectorDrawables.useSupportLibrary = true
24 |
25 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
26 | }
27 |
28 | compileOptions {
29 | sourceCompatibility = JavaVersion.VERSION_11
30 | targetCompatibility = JavaVersion.VERSION_11
31 | }
32 |
33 | buildFeatures {
34 | viewBinding = true
35 | }
36 |
37 | buildTypes {
38 | release {
39 | isMinifyEnabled = false
40 | isShrinkResources = false
41 | proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"))
42 | }
43 | }
44 | }
45 |
46 | dependencies {
47 | implementation(project(":multiplatform-locale-all"))
48 | implementation(libs.timber)
49 | implementation(libs.material)
50 | }
51 |
52 | dependencies {
53 | debugImplementation(libs.leakcanary.android)
54 | }
55 |
--------------------------------------------------------------------------------
/sample-ios/ios/App.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 | import multiplatform_locale_all
3 |
4 | @main
5 | struct LocaleApp : App {
6 | var body: some Scene {
7 | WindowGroup {
8 | ContentView()
9 | }
10 | }
11 | }
12 |
13 | struct ContentView: View {
14 | var body: some View {
15 | VStack {
16 | let currentLocaleString = Locales.shared.currentLocaleString()
17 | Text("Current Locale: \(currentLocaleString)")
18 |
19 | if let locale = multiplatform_locale_all.Locale.Companion.shared.fromOrNull(locale: currentLocaleString) {
20 | Text("Google Play Store Locale: \(locale.googlePlayStoreLocale()?.description() ?? "/")")
21 | Text("Apple App Store Locale: \(locale.appleAppStoreLocale()?.description() ?? "/")")
22 | }
23 |
24 | Text("Current Locale Strings: \(Locales.shared.currentLocaleStrings().joined(separator: ", "))")
25 | .padding()
26 |
27 | let countries = Country.values()
28 |
29 | Text("All countries: \((0.. {
12 | Language.from("asdfa")
13 | }
14 | }
15 |
16 | @Test fun fromOrNull() {
17 | assertEquals(expected = Language.UKRAINIAN, actual = Language.fromOrNull("uk"))
18 |
19 | assertEquals(expected = null, actual = Language.fromOrNull("asdfa"))
20 | }
21 |
22 | @Test fun fromLocale() {
23 | assertEquals(expected = Language.UKRAINIAN, actual = Language.fromLocale("uk"))
24 |
25 | assertFailsWith {
26 | Language.fromLocale("asdfa")
27 | }
28 | }
29 |
30 | @Test fun fromLocaleOrNull() {
31 | assertEquals(expected = Language.UKRAINIAN, actual = Language.fromLocaleOrNull("uk-UA"))
32 |
33 | assertEquals(expected = null, actual = Language.fromLocaleOrNull("asdfa"))
34 | }
35 |
36 | @Test fun legacyIdentifier() {
37 | assertEquals(expected = Language.HEBREW, actual = Language.from("he"))
38 | assertEquals(expected = Language.HEBREW, actual = Language.from("iw"))
39 |
40 | assertEquals(expected = Language.INDONESIAN, actual = Language.from("id"))
41 | assertEquals(expected = Language.INDONESIAN, actual = Language.from("in"))
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/commonMain/kotlin/com/vanniktech/locale/Region.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | enum class Region(
4 | /** ISO 3166-1 alpha-2 code - https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 */
5 | override val code: String,
6 | /** ISO 3166-1 alpha-3 code - https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3 */
7 | override val code3: String,
8 | ) : Territory {
9 | EUROPEAN_UNION(code = "EU", code3 = "EUE"),
10 | LATIN_AMERICA(code = "419", code3 = "419"),
11 | CANARY_ISLANDS(code = "IC", code3 = ""),
12 | INTERNATIONAL_WATERS(code = "XZ", code3 = "XZZ"), // https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#User-assigned_code_elemen
13 | ;
14 |
15 | override val emoji: String? get() =
16 | when (this) {
17 | EUROPEAN_UNION -> """🇪🇺"""
18 | LATIN_AMERICA -> null
19 | CANARY_ISLANDS -> """🇮🇨"""
20 | INTERNATIONAL_WATERS -> """🌊"""
21 | }
22 |
23 | companion object {
24 | fun fromOrNull(identifier: String?) = when {
25 | identifier.isNullOrBlank() -> null
26 | else -> entries.firstOrNull { it.code.equals(identifier, ignoreCase = true) || it.code3.equals(identifier, ignoreCase = true) }
27 | }
28 |
29 | fun fromLocaleOrNull(locale: String?): Region? = fromOrNull(localeComponents(locale)?.country)
30 |
31 | /** Tries every possible combination that I know to somehow get a meaningful country. */
32 | fun fromLenientOrNull(string: String?) = entries.firstOrNull { it.name.equals(string, ignoreCase = true) }
33 | ?: fromOrNull(string)
34 | ?: fromLocaleOrNull(string)
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Multiplatform Locale
2 | ====================
3 |
4 | A Type Safe Kotlin Multiplatform Locale implementation for your Android App, iOS / Mac App & JVM Backend.
5 |
6 | | `Android` | `iOS` | `JVM` |
7 | |:--------------------------------------|:------------------------------|:------------------------------|
8 | |  |  |  |
9 |
10 | # Usage
11 |
12 | From Kotlin Multiplatform:
13 |
14 | ```groovy
15 | kotlin {
16 | sourceSets {
17 | val commonMain by getting {
18 | dependencies {
19 | implementation("com.vanniktech:multiplatform-locale:0.9.0")
20 | }
21 | }
22 | }
23 | }
24 | ```
25 |
26 | From Android / JVM Multiplatform:
27 |
28 | ```groovy
29 | dependencies {
30 | implementation("com.vanniktech:multiplatform-locale:0.9.0")
31 | }
32 | ```
33 |
34 | From iOS:
35 |
36 | ```ruby
37 | pod 'MultiplatformLocale', :git => 'https://github.com/vanniktech/multiplatform-locale', :tag => "0.9.0"
38 | ```
39 |
40 | # API
41 |
42 | Use `com.vanniktech.locale.Locales`, `com.vanniktech.locale.Country`, `com.vanniktech.locale.Language` & `com.vanniktech.locale.Locale` directly in your platform specific code:
43 |
44 | - [sample-android](./sample-android/src/main/kotlin/com/vanniktech/locale/sample/android/LocaleMainActivity.kt)
45 | - [sample-ios](./sample-ios/ios/App.swift)
46 | - [sample-jvm](sample-jvm/src/main/java/com/vanniktech/locale/sample/jvm/LocaleJvm.kt)
47 |
48 | # License
49 |
50 | Copyright (C) 2022 - Niklas Baudy
51 |
52 | Licensed under the Apache License, Version 2.0
53 |
--------------------------------------------------------------------------------
/gradle/libs.versions.toml:
--------------------------------------------------------------------------------
1 | [versions]
2 | minSdk = "21"
3 | compileSdk = "34"
4 | targetSdk = "34"
5 |
6 | androidgradleplugin = "8.13.2"
7 | kotlin = "2.2.21"
8 | ktlint = "1.7.1"
9 |
10 | [libraries]
11 | kaml = "com.charleskorn.kaml:kaml:0.104.0"
12 | kotlin-test-annotations-common = { module = "org.jetbrains.kotlin:kotlin-test-annotations-common", version.ref = "kotlin" }
13 | kotlin-test-common = { module = "org.jetbrains.kotlin:kotlin-test-common", version.ref = "kotlin" }
14 | kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" }
15 | leakcanary-android = "com.squareup.leakcanary:leakcanary-android:2.14"
16 | material = "com.google.android.material:material:1.13.0"
17 | okio = "com.squareup.okio:okio:3.16.4"
18 | plugin-android-cache-fix = "org.gradle.android.cache-fix:org.gradle.android.cache-fix.gradle.plugin:3.0.3"
19 | plugin-androidgradleplugin = { module = "com.android.tools.build:gradle", version.ref = "androidgradleplugin" }
20 | plugin-dokka = "org.jetbrains.dokka:dokka-gradle-plugin:2.1.0"
21 | plugin-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
22 | plugin-licensee = "app.cash.licensee:licensee-gradle-plugin:1.14.1"
23 | plugin-metalava = "me.tylerbwong.gradle.metalava:plugin:0.4.0-alpha03"
24 | plugin-publish = "com.vanniktech:gradle-maven-publish-plugin:0.35.0"
25 | timber = "com.jakewharton.timber:timber:5.0.1"
26 |
27 | [plugins]
28 | codequalitytools = { id = "com.vanniktech.code.quality.tools", version = "0.24.0" }
29 | dependencygraphgenerator = { id = "com.vanniktech.dependency.graph.generator", version = "0.8.0" }
30 | kotlinSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
31 |
--------------------------------------------------------------------------------
/sample-android/src/main/kotlin/com/vanniktech/locale/sample/android/LocaleMainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale.sample.android
2 |
3 | import android.annotation.SuppressLint
4 | import android.os.Bundle
5 | import androidx.appcompat.app.AppCompatActivity
6 | import com.vanniktech.locale.Country
7 | import com.vanniktech.locale.Language
8 | import com.vanniktech.locale.Locale
9 | import com.vanniktech.locale.Locales
10 | import com.vanniktech.locale.apple.app.store.appleAppStoreLocale
11 | import com.vanniktech.locale.google.play.store.googlePlayStoreLocale
12 | import com.vanniktech.locale.sample.android.databinding.ActivityMainBinding
13 |
14 | class LocaleMainActivity : AppCompatActivity() {
15 | @SuppressLint("SetTextI18n")
16 | override fun onCreate(savedInstanceState: Bundle?) {
17 | super.onCreate(savedInstanceState)
18 |
19 | val binding = ActivityMainBinding.inflate(layoutInflater)
20 | setContentView(binding.root)
21 |
22 | val currentLocaleString = Locales.currentLocaleString()
23 | binding.currentLocaleString.text = "Current Locale: $currentLocaleString"
24 | binding.googlePlayStoreLocale.text = "Google Play Store Locale: ${Locale.fromOrNull(currentLocaleString)?.googlePlayStoreLocale()?.toString() ?: "/"}"
25 | binding.appleAppStoreLocale.text = "Apple App Store Locale: ${Locale.fromOrNull(currentLocaleString)?.appleAppStoreLocale()?.toString() ?: "/"}"
26 | binding.currentLocaleStrings.text = "Current Locale Strings: ${Locales.currentLocaleStrings().joinToString(separator = ", ")}"
27 | binding.allCountries.text = "All countries: ${Country.entries.joinToString { it.displayName() }}"
28 | binding.allLanguages.text = "All languages: ${Language.entries.joinToString { it.displayName() }}"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/multiplatform-locale-apple-app-store/src/commonMain/kotlin/com/vanniktech/locale/apple/app/store/AppleAppStoreLocale.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale.apple.app.store
2 |
3 | import com.vanniktech.locale.Country
4 | import com.vanniktech.locale.Language
5 | import com.vanniktech.locale.Locale
6 | import com.vanniktech.locale.Locale.Companion.fromOrNull
7 |
8 | /** All the locales supported by the Apple App Store. */
9 | @Suppress("ktlint:standard:enum-entry-name-case") enum class AppleAppStoreLocale {
10 | ar_SA,
11 | ca,
12 | cs,
13 | da,
14 | de_DE,
15 | el,
16 | en_AU,
17 | en_CA,
18 | en_GB,
19 | en_US,
20 | es_ES,
21 | es_MX,
22 | fi,
23 | fr_CA,
24 | fr_FR,
25 | he,
26 | hi,
27 | hr,
28 | hu,
29 | id,
30 | it,
31 | ja,
32 | ko,
33 | ms,
34 | nl_NL,
35 | no,
36 | pl,
37 | pt_BR,
38 | pt_PT,
39 | ro,
40 | ru,
41 | sk,
42 | sv,
43 | th,
44 | tr,
45 | uk,
46 | vi,
47 | zh_Hans,
48 | zh_Hant,
49 | ;
50 |
51 | override fun toString() = name.replace("_", "-")
52 | }
53 |
54 | /** Returns the optional [AppleAppStoreLocale] that can be used for localizing the Apple App Store. */
55 | fun Locale.appleAppStoreLocale(): AppleAppStoreLocale? {
56 | val optimized = Locale(
57 | language = language,
58 | territory = territory ?: language.defaultCountry,
59 | )
60 | return AppleAppStoreLocale.entries
61 | .groupBy { Language.fromLocaleOrNull(it.toString()) }
62 | .firstNotNullOfOrNull { (key, locales) ->
63 | locales.firstNotNullOfOrNull { locale ->
64 | locale.takeIf {
65 | optimized == when (it) {
66 | AppleAppStoreLocale.zh_Hant -> Locale(Language.CHINESE, Country.TAIWAN)
67 | AppleAppStoreLocale.zh_Hans -> Locale(Language.CHINESE, Country.CHINA)
68 | else -> fromOrNull(it.name)
69 | }
70 | }
71 | } ?: locales.firstNotNullOfOrNull { locale -> locale.takeIf { language == key } }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/sample-android/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
18 |
25 |
32 |
40 |
48 |
56 |
57 |
--------------------------------------------------------------------------------
/sample-ios/ios/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "scale" : "1x",
46 | "size" : "20x20"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "scale" : "2x",
51 | "size" : "20x20"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "scale" : "1x",
56 | "size" : "29x29"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "scale" : "2x",
61 | "size" : "29x29"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "scale" : "1x",
66 | "size" : "40x40"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "scale" : "2x",
71 | "size" : "40x40"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "scale" : "1x",
76 | "size" : "76x76"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "scale" : "2x",
81 | "size" : "76x76"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "scale" : "2x",
86 | "size" : "83.5x83.5"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "scale" : "1x",
91 | "size" : "1024x1024"
92 | }
93 | ],
94 | "info" : {
95 | "author" : "xcode",
96 | "version" : 1
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/multiplatform-locale-all/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.jetbrains.dokka")
3 | id("org.jetbrains.kotlin.multiplatform")
4 | id("org.jetbrains.kotlin.native.cocoapods")
5 | id("com.android.library")
6 | id("me.tylerbwong.gradle.metalava")
7 | id("com.vanniktech.maven.publish")
8 | id("app.cash.licensee")
9 | }
10 |
11 | licensee {
12 | allow("Apache-2.0")
13 | }
14 |
15 | metalava {
16 | filename.set("api/current.txt")
17 | }
18 |
19 | kotlin {
20 | applyDefaultHierarchyTemplate()
21 |
22 | androidTarget {
23 | publishLibraryVariants("release")
24 | }
25 | jvm()
26 | jvmToolchain(11)
27 | iosX64()
28 | iosArm64()
29 | iosSimulatorArm64()
30 |
31 | sourceSets {
32 | val commonMain by getting {
33 | dependencies {
34 | api(project(":multiplatform-locale"))
35 | api(project(":multiplatform-locale-apple-app-store"))
36 | api(project(":multiplatform-locale-geo"))
37 | api(project(":multiplatform-locale-google-play-store"))
38 | }
39 | }
40 | }
41 |
42 | cocoapods {
43 | summary = "Multiplatform Locale All for iOS, Android and JVM via Kotlin Multiplatform"
44 | homepage = "https://github.com/vanniktech/multiplatform-locale"
45 | license = "MIT"
46 | name = "MultiplatformLocaleAll"
47 | authors = "Niklas Baudy"
48 | version = project.property("VERSION_NAME").toString()
49 |
50 | framework {
51 | isStatic = true
52 | export(project(":multiplatform-locale"))
53 | export(project(":multiplatform-locale-apple-app-store"))
54 | export(project(":multiplatform-locale-geo"))
55 | export(project(":multiplatform-locale-google-play-store"))
56 | }
57 | }
58 | }
59 |
60 | android {
61 | namespace = "com.vanniktech.locale.all"
62 |
63 | compileSdk = libs.versions.compileSdk.get().toInt()
64 |
65 | defaultConfig {
66 | minSdk = libs.versions.minSdk.get().toInt()
67 | }
68 |
69 | compileOptions {
70 | sourceCompatibility = JavaVersion.VERSION_11
71 | targetCompatibility = JavaVersion.VERSION_11
72 | }
73 |
74 | resourcePrefix = "locale_all_"
75 | }
76 |
--------------------------------------------------------------------------------
/multiplatform-locale/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.jetbrains.dokka")
3 | id("org.jetbrains.kotlin.multiplatform")
4 | id("org.jetbrains.kotlin.native.cocoapods")
5 | id("com.android.library")
6 | id("me.tylerbwong.gradle.metalava")
7 | id("com.vanniktech.maven.publish")
8 | id("app.cash.licensee")
9 | }
10 |
11 | licensee {
12 | allow("Apache-2.0")
13 | }
14 |
15 | metalava {
16 | filename.set("api/current.txt")
17 | }
18 |
19 | kotlin {
20 | applyDefaultHierarchyTemplate()
21 |
22 | androidTarget {
23 | publishLibraryVariants("release")
24 | }
25 | jvm()
26 | jvmToolchain(11)
27 | iosX64()
28 | iosArm64()
29 | iosSimulatorArm64()
30 |
31 | targets.withType {
32 | compilations["main"].kotlinOptions.freeCompilerArgs += "-Xexport-kdoc"
33 | }
34 |
35 | sourceSets {
36 | val commonTest by getting {
37 | dependencies {
38 | implementation(libs.kotlin.test.common)
39 | implementation(libs.kotlin.test.annotations.common)
40 | }
41 | }
42 |
43 | val androidUnitTest by getting {
44 | dependencies {
45 | implementation(libs.kotlin.test.junit)
46 | }
47 | }
48 |
49 | val jvmTest by getting {
50 | dependencies {
51 | implementation(libs.kotlin.test.junit)
52 | }
53 | }
54 | }
55 |
56 | cocoapods {
57 | summary = "Multiplatform Locale for iOS, Android and JVM via Kotlin Multiplatform"
58 | homepage = "https://github.com/vanniktech/multiplatform-locale"
59 | license = "MIT"
60 | name = "MultiplatformLocale"
61 | authors = "Niklas Baudy"
62 | version = project.property("VERSION_NAME").toString()
63 |
64 | framework {
65 | isStatic = true
66 | }
67 | }
68 | }
69 |
70 | android {
71 | namespace = "com.vanniktech.locale"
72 |
73 | compileSdk = libs.versions.compileSdk.get().toInt()
74 |
75 | defaultConfig {
76 | minSdk = libs.versions.minSdk.get().toInt()
77 | }
78 |
79 | compileOptions {
80 | sourceCompatibility = JavaVersion.VERSION_11
81 | targetCompatibility = JavaVersion.VERSION_11
82 | }
83 |
84 | resourcePrefix = "locale_"
85 | }
86 |
--------------------------------------------------------------------------------
/multiplatform-locale-geo/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.jetbrains.dokka")
3 | id("org.jetbrains.kotlin.multiplatform")
4 | id("org.jetbrains.kotlin.native.cocoapods")
5 | id("com.android.library")
6 | id("me.tylerbwong.gradle.metalava")
7 | id("com.vanniktech.maven.publish")
8 | id("app.cash.licensee")
9 | }
10 |
11 | licensee {
12 | allow("Apache-2.0")
13 | }
14 |
15 | metalava {
16 | filename.set("api/current.txt")
17 | }
18 |
19 | kotlin {
20 | applyDefaultHierarchyTemplate()
21 |
22 | androidTarget {
23 | publishLibraryVariants("release")
24 | }
25 | jvm()
26 | jvmToolchain(11)
27 | iosX64()
28 | iosArm64()
29 | iosSimulatorArm64()
30 |
31 | targets.withType {
32 | compilations["main"].kotlinOptions.freeCompilerArgs += "-Xexport-kdoc"
33 | }
34 |
35 | sourceSets {
36 | val commonMain by getting {
37 | dependencies {
38 | api(project(":multiplatform-locale"))
39 | }
40 | }
41 |
42 | val commonTest by getting {
43 | dependencies {
44 | implementation(libs.kotlin.test.common)
45 | implementation(libs.kotlin.test.annotations.common)
46 | }
47 | }
48 |
49 | val androidUnitTest by getting {
50 | dependencies {
51 | implementation(libs.kotlin.test.junit)
52 | }
53 | }
54 |
55 | val jvmTest by getting {
56 | dependencies {
57 | implementation(libs.kotlin.test.junit)
58 | }
59 | }
60 | }
61 |
62 | cocoapods {
63 | summary = "Multiplatform Locale Geo for iOS, Android and JVM via Kotlin Multiplatform"
64 | homepage = "https://github.com/vanniktech/multiplatform-locale"
65 | license = "MIT"
66 | name = "MultiplatformLocaleGeo"
67 | authors = "Niklas Baudy"
68 | version = project.property("VERSION_NAME").toString()
69 |
70 | framework {
71 | isStatic = true
72 | export(project(":multiplatform-locale"))
73 | }
74 | }
75 | }
76 |
77 | android {
78 | namespace = "com.vanniktech.locale.geo"
79 |
80 | compileSdk = libs.versions.compileSdk.get().toInt()
81 |
82 | defaultConfig {
83 | minSdk = libs.versions.minSdk.get().toInt()
84 | }
85 |
86 | compileOptions {
87 | sourceCompatibility = JavaVersion.VERSION_11
88 | targetCompatibility = JavaVersion.VERSION_11
89 | }
90 |
91 | resourcePrefix = "locale_geo"
92 | }
93 |
--------------------------------------------------------------------------------
/multiplatform-locale-apple-app-store/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.jetbrains.dokka")
3 | id("org.jetbrains.kotlin.multiplatform")
4 | id("org.jetbrains.kotlin.native.cocoapods")
5 | id("com.android.library")
6 | id("me.tylerbwong.gradle.metalava")
7 | id("com.vanniktech.maven.publish")
8 | id("app.cash.licensee")
9 | }
10 |
11 | licensee {
12 | allow("Apache-2.0")
13 | }
14 |
15 | metalava {
16 | filename.set("api/current.txt")
17 | }
18 |
19 | kotlin {
20 | applyDefaultHierarchyTemplate()
21 |
22 | androidTarget {
23 | publishLibraryVariants("release")
24 | }
25 | jvm()
26 | jvmToolchain(11)
27 | iosX64()
28 | iosArm64()
29 | iosSimulatorArm64()
30 |
31 | targets.withType {
32 | compilations["main"].kotlinOptions.freeCompilerArgs += "-Xexport-kdoc"
33 | }
34 |
35 | sourceSets {
36 | val commonMain by getting {
37 | dependencies {
38 | api(project(":multiplatform-locale"))
39 | }
40 | }
41 |
42 | val commonTest by getting {
43 | dependencies {
44 | implementation(libs.kotlin.test.common)
45 | implementation(libs.kotlin.test.annotations.common)
46 | }
47 | }
48 |
49 | val androidUnitTest by getting {
50 | dependencies {
51 | implementation(libs.kotlin.test.junit)
52 | }
53 | }
54 |
55 | val jvmTest by getting {
56 | dependencies {
57 | implementation(libs.kotlin.test.junit)
58 | }
59 | }
60 | }
61 |
62 | cocoapods {
63 | summary = "Multiplatform Locale Apple App Store for iOS, Android and JVM via Kotlin Multiplatform"
64 | homepage = "https://github.com/vanniktech/multiplatform-locale"
65 | license = "MIT"
66 | name = "MultiplatformLocaleAppleAppStore"
67 | authors = "Niklas Baudy"
68 | version = project.property("VERSION_NAME").toString()
69 |
70 | framework {
71 | isStatic = true
72 | export(project(":multiplatform-locale"))
73 | }
74 | }
75 | }
76 |
77 | android {
78 | namespace = "com.vanniktech.locale.apple.app.store"
79 |
80 | compileSdk = libs.versions.compileSdk.get().toInt()
81 |
82 | defaultConfig {
83 | minSdk = libs.versions.minSdk.get().toInt()
84 | }
85 |
86 | compileOptions {
87 | sourceCompatibility = JavaVersion.VERSION_11
88 | targetCompatibility = JavaVersion.VERSION_11
89 | }
90 |
91 | resourcePrefix = "locale_apple_app_store_"
92 | }
93 |
--------------------------------------------------------------------------------
/multiplatform-locale-google-play-store/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("org.jetbrains.dokka")
3 | id("org.jetbrains.kotlin.multiplatform")
4 | id("org.jetbrains.kotlin.native.cocoapods")
5 | id("com.android.library")
6 | id("me.tylerbwong.gradle.metalava")
7 | id("com.vanniktech.maven.publish")
8 | id("app.cash.licensee")
9 | }
10 |
11 | licensee {
12 | allow("Apache-2.0")
13 | }
14 |
15 | metalava {
16 | filename.set("api/current.txt")
17 | }
18 |
19 | kotlin {
20 | applyDefaultHierarchyTemplate()
21 |
22 | androidTarget {
23 | publishLibraryVariants("release")
24 | }
25 | jvm()
26 | jvmToolchain(11)
27 | iosX64()
28 | iosArm64()
29 | iosSimulatorArm64()
30 |
31 | targets.withType {
32 | compilations["main"].kotlinOptions.freeCompilerArgs += "-Xexport-kdoc"
33 | }
34 |
35 | sourceSets {
36 | val commonMain by getting {
37 | dependencies {
38 | api(project(":multiplatform-locale"))
39 | }
40 | }
41 |
42 | val commonTest by getting {
43 | dependencies {
44 | implementation(libs.kotlin.test.common)
45 | implementation(libs.kotlin.test.annotations.common)
46 | }
47 | }
48 |
49 | val androidUnitTest by getting {
50 | dependencies {
51 | implementation(libs.kotlin.test.junit)
52 | }
53 | }
54 |
55 | val jvmTest by getting {
56 | dependencies {
57 | implementation(libs.kotlin.test.junit)
58 | }
59 | }
60 | }
61 |
62 | cocoapods {
63 | summary = "Multiplatform Locale Google Play Store for iOS, Android and JVM via Kotlin Multiplatform"
64 | homepage = "https://github.com/vanniktech/multiplatform-locale"
65 | license = "MIT"
66 | name = "MultiplatformLocaleGooglePlayStore"
67 | authors = "Niklas Baudy"
68 | version = project.property("VERSION_NAME").toString()
69 |
70 | framework {
71 | isStatic = true
72 | export(project(":multiplatform-locale"))
73 | }
74 | }
75 | }
76 |
77 | android {
78 | namespace = "com.vanniktech.locale.google.play.store"
79 |
80 | compileSdk = libs.versions.compileSdk.get().toInt()
81 |
82 | defaultConfig {
83 | minSdk = libs.versions.minSdk.get().toInt()
84 | }
85 |
86 | compileOptions {
87 | sourceCompatibility = JavaVersion.VERSION_11
88 | targetCompatibility = JavaVersion.VERSION_11
89 | }
90 |
91 | resourcePrefix = "locale_google_play_store_"
92 | }
93 |
--------------------------------------------------------------------------------
/multiplatform-locale-google-play-store/src/commonMain/kotlin/com/vanniktech/locale/google/play/store/GooglePlayStoreLocale.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale.google.play.store
2 |
3 | import com.vanniktech.locale.Language
4 | import com.vanniktech.locale.Locale
5 | import com.vanniktech.locale.Locale.Companion.fromOrNull
6 |
7 | /** All the locales supported by the Google Play Store. */
8 | @Suppress("ktlint:standard:enum-entry-name-case") enum class GooglePlayStoreLocale {
9 | af,
10 | sq,
11 | am,
12 | ar,
13 | hy_AM,
14 | az_AZ,
15 | bn_BD,
16 | eu_ES,
17 | be,
18 | bg,
19 | my_MM,
20 | ca,
21 | zh_HK,
22 | zh_CN,
23 | zh_TW,
24 | hr,
25 | cs_CZ,
26 | da_DK,
27 | nl_NL,
28 | en_AU,
29 | en_US,
30 | en_CA,
31 | en_GB,
32 | en_IN,
33 | en_SG,
34 | en_ZA,
35 | et,
36 | fil,
37 | fi_FI,
38 | fr_CA,
39 | fr_FR,
40 | gl_ES,
41 | ka_GE,
42 | de_DE,
43 | el_GR,
44 | gu,
45 | iw_IL,
46 | hi_IN,
47 | hu_HU,
48 | is_IS,
49 | id,
50 | it_IT,
51 | ja_JP,
52 | kn_IN,
53 | kk,
54 | km_KH,
55 | ko_KR,
56 | ky_KG,
57 | lo_LA,
58 | lv,
59 | lt,
60 | mk_MK,
61 | ms_MY,
62 | ms,
63 | ml_IN,
64 | mr_IN,
65 | mn_MN,
66 | ne_NP,
67 | no_NO,
68 | fa,
69 | fa_AE,
70 | fa_AF,
71 | fa_IR,
72 | pl_PL,
73 | pt_BR,
74 | pt_PT,
75 | pa,
76 | ro,
77 | rm,
78 | ru_RU,
79 | sr,
80 | si_LK,
81 | sk,
82 | sl,
83 | es_ES,
84 | es_US,
85 | es_419,
86 | sw,
87 | sv_SE,
88 | ta_IN,
89 | te_IN,
90 | th,
91 | tr_TR,
92 | uk,
93 | ur,
94 | vi,
95 | zu,
96 | ;
97 |
98 | override fun toString() = name.replace("_", "-")
99 | }
100 |
101 | /** Returns the optional [GooglePlayStoreLocale] that can be used for localizing the Google Play Store. */
102 | fun Locale.googlePlayStoreLocale(): GooglePlayStoreLocale? {
103 | val optimized = Locale(
104 | language = language,
105 | territory = territory ?: language.defaultCountry,
106 | )
107 | return GooglePlayStoreLocale.entries
108 | .groupBy { Language.fromLocaleOrNull(it.toString()) }
109 | .firstNotNullOfOrNull { (key, locales) ->
110 | locales.firstNotNullOfOrNull { locale ->
111 | locale.takeIf {
112 | fromOrNull(it.name) == optimized
113 | }
114 | } ?: locales.firstNotNullOfOrNull { locale -> locale.takeIf { language == key } }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/multiplatform-locale/MultiplatformLocale.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |spec|
2 | spec.name = 'MultiplatformLocale'
3 | spec.version = '0.10.0-SNAPSHOT'
4 | spec.homepage = 'https://github.com/vanniktech/multiplatform-locale'
5 | spec.source = { :http=> ''}
6 | spec.authors = 'Niklas Baudy'
7 | spec.license = 'MIT'
8 | spec.summary = 'Multiplatform Locale for iOS, Android and JVM via Kotlin Multiplatform'
9 | spec.vendored_frameworks = 'build/cocoapods/framework/multiplatform_locale.framework'
10 | spec.libraries = 'c++'
11 |
12 |
13 |
14 | if !Dir.exist?('build/cocoapods/framework/multiplatform_locale.framework') || Dir.empty?('build/cocoapods/framework/multiplatform_locale.framework')
15 | raise "
16 |
17 | Kotlin framework 'multiplatform_locale' doesn't exist yet, so a proper Xcode project can't be generated.
18 | 'pod install' should be executed after running ':generateDummyFramework' Gradle task:
19 |
20 | ./gradlew :multiplatform-locale:generateDummyFramework
21 |
22 | Alternatively, proper pod installation is performed during Gradle sync in the IDE (if Podfile location is set)"
23 | end
24 |
25 | spec.xcconfig = {
26 | 'ENABLE_USER_SCRIPT_SANDBOXING' => 'NO',
27 | }
28 |
29 | spec.pod_target_xcconfig = {
30 | 'KOTLIN_PROJECT_PATH' => ':multiplatform-locale',
31 | 'PRODUCT_MODULE_NAME' => 'multiplatform_locale',
32 | }
33 |
34 | spec.script_phases = [
35 | {
36 | :name => 'Build MultiplatformLocale',
37 | :execution_position => :before_compile,
38 | :shell_path => '/bin/sh',
39 | :script => <<-SCRIPT
40 | if [ "YES" = "$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED" ]; then
41 | echo "Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \"YES\""
42 | exit 0
43 | fi
44 | set -ev
45 | REPO_ROOT="$PODS_TARGET_SRCROOT"
46 | "$REPO_ROOT/../gradlew" -p "$REPO_ROOT" $KOTLIN_PROJECT_PATH:syncFramework \
47 | -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME \
48 | -Pkotlin.native.cocoapods.archs="$ARCHS" \
49 | -Pkotlin.native.cocoapods.configuration="$CONFIGURATION"
50 | SCRIPT
51 | }
52 | ]
53 |
54 | end
--------------------------------------------------------------------------------
/multiplatform-locale-all/MultiplatformLocaleAll.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |spec|
2 | spec.name = 'MultiplatformLocaleAll'
3 | spec.version = '0.10.0-SNAPSHOT'
4 | spec.homepage = 'https://github.com/vanniktech/multiplatform-locale'
5 | spec.source = { :http=> ''}
6 | spec.authors = 'Niklas Baudy'
7 | spec.license = 'MIT'
8 | spec.summary = 'Multiplatform Locale All for iOS, Android and JVM via Kotlin Multiplatform'
9 | spec.vendored_frameworks = 'build/cocoapods/framework/multiplatform_locale_all.framework'
10 | spec.libraries = 'c++'
11 |
12 |
13 |
14 | if !Dir.exist?('build/cocoapods/framework/multiplatform_locale_all.framework') || Dir.empty?('build/cocoapods/framework/multiplatform_locale_all.framework')
15 | raise "
16 |
17 | Kotlin framework 'multiplatform_locale_all' doesn't exist yet, so a proper Xcode project can't be generated.
18 | 'pod install' should be executed after running ':generateDummyFramework' Gradle task:
19 |
20 | ./gradlew :multiplatform-locale-all:generateDummyFramework
21 |
22 | Alternatively, proper pod installation is performed during Gradle sync in the IDE (if Podfile location is set)"
23 | end
24 |
25 | spec.xcconfig = {
26 | 'ENABLE_USER_SCRIPT_SANDBOXING' => 'NO',
27 | }
28 |
29 | spec.pod_target_xcconfig = {
30 | 'KOTLIN_PROJECT_PATH' => ':multiplatform-locale-all',
31 | 'PRODUCT_MODULE_NAME' => 'multiplatform_locale_all',
32 | }
33 |
34 | spec.script_phases = [
35 | {
36 | :name => 'Build MultiplatformLocaleAll',
37 | :execution_position => :before_compile,
38 | :shell_path => '/bin/sh',
39 | :script => <<-SCRIPT
40 | if [ "YES" = "$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED" ]; then
41 | echo "Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \"YES\""
42 | exit 0
43 | fi
44 | set -ev
45 | REPO_ROOT="$PODS_TARGET_SRCROOT"
46 | "$REPO_ROOT/../gradlew" -p "$REPO_ROOT" $KOTLIN_PROJECT_PATH:syncFramework \
47 | -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME \
48 | -Pkotlin.native.cocoapods.archs="$ARCHS" \
49 | -Pkotlin.native.cocoapods.configuration="$CONFIGURATION"
50 | SCRIPT
51 | }
52 | ]
53 |
54 | end
--------------------------------------------------------------------------------
/multiplatform-locale-geo/MultiplatformLocaleGeo.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |spec|
2 | spec.name = 'MultiplatformLocaleGeo'
3 | spec.version = '0.10.0-SNAPSHOT'
4 | spec.homepage = 'https://github.com/vanniktech/multiplatform-locale'
5 | spec.source = { :http=> ''}
6 | spec.authors = 'Niklas Baudy'
7 | spec.license = 'MIT'
8 | spec.summary = 'Multiplatform Locale Geo for iOS, Android and JVM via Kotlin Multiplatform'
9 | spec.vendored_frameworks = 'build/cocoapods/framework/multiplatform_locale_geo.framework'
10 | spec.libraries = 'c++'
11 |
12 |
13 |
14 | if !Dir.exist?('build/cocoapods/framework/multiplatform_locale_geo.framework') || Dir.empty?('build/cocoapods/framework/multiplatform_locale_geo.framework')
15 | raise "
16 |
17 | Kotlin framework 'multiplatform_locale_geo' doesn't exist yet, so a proper Xcode project can't be generated.
18 | 'pod install' should be executed after running ':generateDummyFramework' Gradle task:
19 |
20 | ./gradlew :multiplatform-locale-geo:generateDummyFramework
21 |
22 | Alternatively, proper pod installation is performed during Gradle sync in the IDE (if Podfile location is set)"
23 | end
24 |
25 | spec.xcconfig = {
26 | 'ENABLE_USER_SCRIPT_SANDBOXING' => 'NO',
27 | }
28 |
29 | spec.pod_target_xcconfig = {
30 | 'KOTLIN_PROJECT_PATH' => ':multiplatform-locale-geo',
31 | 'PRODUCT_MODULE_NAME' => 'multiplatform_locale_geo',
32 | }
33 |
34 | spec.script_phases = [
35 | {
36 | :name => 'Build MultiplatformLocaleGeo',
37 | :execution_position => :before_compile,
38 | :shell_path => '/bin/sh',
39 | :script => <<-SCRIPT
40 | if [ "YES" = "$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED" ]; then
41 | echo "Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \"YES\""
42 | exit 0
43 | fi
44 | set -ev
45 | REPO_ROOT="$PODS_TARGET_SRCROOT"
46 | "$REPO_ROOT/../gradlew" -p "$REPO_ROOT" $KOTLIN_PROJECT_PATH:syncFramework \
47 | -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME \
48 | -Pkotlin.native.cocoapods.archs="$ARCHS" \
49 | -Pkotlin.native.cocoapods.configuration="$CONFIGURATION"
50 | SCRIPT
51 | }
52 | ]
53 |
54 | end
--------------------------------------------------------------------------------
/multiplatform-locale-apple-app-store/MultiplatformLocaleAppleAppStore.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |spec|
2 | spec.name = 'MultiplatformLocaleAppleAppStore'
3 | spec.version = '0.10.0-SNAPSHOT'
4 | spec.homepage = 'https://github.com/vanniktech/multiplatform-locale'
5 | spec.source = { :http=> ''}
6 | spec.authors = 'Niklas Baudy'
7 | spec.license = 'MIT'
8 | spec.summary = 'Multiplatform Locale Apple App Store for iOS, Android and JVM via Kotlin Multiplatform'
9 | spec.vendored_frameworks = 'build/cocoapods/framework/multiplatform_locale_apple_app_store.framework'
10 | spec.libraries = 'c++'
11 |
12 |
13 |
14 | if !Dir.exist?('build/cocoapods/framework/multiplatform_locale_apple_app_store.framework') || Dir.empty?('build/cocoapods/framework/multiplatform_locale_apple_app_store.framework')
15 | raise "
16 |
17 | Kotlin framework 'multiplatform_locale_apple_app_store' doesn't exist yet, so a proper Xcode project can't be generated.
18 | 'pod install' should be executed after running ':generateDummyFramework' Gradle task:
19 |
20 | ./gradlew :multiplatform-locale-apple-app-store:generateDummyFramework
21 |
22 | Alternatively, proper pod installation is performed during Gradle sync in the IDE (if Podfile location is set)"
23 | end
24 |
25 | spec.xcconfig = {
26 | 'ENABLE_USER_SCRIPT_SANDBOXING' => 'NO',
27 | }
28 |
29 | spec.pod_target_xcconfig = {
30 | 'KOTLIN_PROJECT_PATH' => ':multiplatform-locale-apple-app-store',
31 | 'PRODUCT_MODULE_NAME' => 'multiplatform_locale_apple_app_store',
32 | }
33 |
34 | spec.script_phases = [
35 | {
36 | :name => 'Build MultiplatformLocaleAppleAppStore',
37 | :execution_position => :before_compile,
38 | :shell_path => '/bin/sh',
39 | :script => <<-SCRIPT
40 | if [ "YES" = "$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED" ]; then
41 | echo "Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \"YES\""
42 | exit 0
43 | fi
44 | set -ev
45 | REPO_ROOT="$PODS_TARGET_SRCROOT"
46 | "$REPO_ROOT/../gradlew" -p "$REPO_ROOT" $KOTLIN_PROJECT_PATH:syncFramework \
47 | -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME \
48 | -Pkotlin.native.cocoapods.archs="$ARCHS" \
49 | -Pkotlin.native.cocoapods.configuration="$CONFIGURATION"
50 | SCRIPT
51 | }
52 | ]
53 |
54 | end
--------------------------------------------------------------------------------
/multiplatform-locale-google-play-store/MultiplatformLocaleGooglePlayStore.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |spec|
2 | spec.name = 'MultiplatformLocaleGooglePlayStore'
3 | spec.version = '0.10.0-SNAPSHOT'
4 | spec.homepage = 'https://github.com/vanniktech/multiplatform-locale'
5 | spec.source = { :http=> ''}
6 | spec.authors = 'Niklas Baudy'
7 | spec.license = 'MIT'
8 | spec.summary = 'Multiplatform Locale Google Play Store for iOS, Android and JVM via Kotlin Multiplatform'
9 | spec.vendored_frameworks = 'build/cocoapods/framework/multiplatform_locale_google_play_store.framework'
10 | spec.libraries = 'c++'
11 |
12 |
13 |
14 | if !Dir.exist?('build/cocoapods/framework/multiplatform_locale_google_play_store.framework') || Dir.empty?('build/cocoapods/framework/multiplatform_locale_google_play_store.framework')
15 | raise "
16 |
17 | Kotlin framework 'multiplatform_locale_google_play_store' doesn't exist yet, so a proper Xcode project can't be generated.
18 | 'pod install' should be executed after running ':generateDummyFramework' Gradle task:
19 |
20 | ./gradlew :multiplatform-locale-google-play-store:generateDummyFramework
21 |
22 | Alternatively, proper pod installation is performed during Gradle sync in the IDE (if Podfile location is set)"
23 | end
24 |
25 | spec.xcconfig = {
26 | 'ENABLE_USER_SCRIPT_SANDBOXING' => 'NO',
27 | }
28 |
29 | spec.pod_target_xcconfig = {
30 | 'KOTLIN_PROJECT_PATH' => ':multiplatform-locale-google-play-store',
31 | 'PRODUCT_MODULE_NAME' => 'multiplatform_locale_google_play_store',
32 | }
33 |
34 | spec.script_phases = [
35 | {
36 | :name => 'Build MultiplatformLocaleGooglePlayStore',
37 | :execution_position => :before_compile,
38 | :shell_path => '/bin/sh',
39 | :script => <<-SCRIPT
40 | if [ "YES" = "$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED" ]; then
41 | echo "Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \"YES\""
42 | exit 0
43 | fi
44 | set -ev
45 | REPO_ROOT="$PODS_TARGET_SRCROOT"
46 | "$REPO_ROOT/../gradlew" -p "$REPO_ROOT" $KOTLIN_PROJECT_PATH:syncFramework \
47 | -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME \
48 | -Pkotlin.native.cocoapods.archs="$ARCHS" \
49 | -Pkotlin.native.cocoapods.configuration="$CONFIGURATION"
50 | SCRIPT
51 | }
52 | ]
53 |
54 | end
--------------------------------------------------------------------------------
/multiplatform-locale/src/commonMain/kotlin/com/vanniktech/locale/Locale.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | data class Locale(
4 | val language: Language,
5 | val territory: Territory?,
6 | ) : Comparable {
7 | override fun toString() = listOfNotNull(
8 | language.code,
9 | territory?.code,
10 | ).joinToString(separator = "-")
11 |
12 | override fun compareTo(other: Locale): Int = compareValuesBy(this, other, { it.language }, { it.territory as Comparable<*> })
13 |
14 | companion object {
15 | fun from(locale: String) = requireNotNull(fromOrNull(locale)) { "Can't get locale for $locale" }
16 |
17 | fun fromOrNull(locale: String?): Locale? {
18 | val language = Language.fromLocaleOrNull(locale)
19 |
20 | return if (language != null) {
21 | Locale(
22 | language = language,
23 | territory = Country.fromLocaleOrNull(locale) ?: Region.fromLocaleOrNull(locale),
24 | )
25 | } else {
26 | null
27 | }
28 | }
29 |
30 | fun fromAndroidValuesDirectoryName(androidValuesDirectoryName: String) = requireNotNull(fromAndroidValuesDirectoryNameOrNull(androidValuesDirectoryName)) { "Can't get locale for $androidValuesDirectoryName" }
31 |
32 | fun fromAndroidValuesDirectoryNameOrNull(androidValuesDirectoryName: String): Locale? {
33 | val name = androidValuesDirectoryName
34 | .removePrefix("values")
35 | .removePrefix("-")
36 |
37 | return when (androidValuesDirectoryName) {
38 | "values" -> Locale(Language.ENGLISH, null)
39 | else -> fromOrNull(name.replace("-r", "-"))
40 | }
41 | }
42 | }
43 | }
44 |
45 | internal fun localeComponents(localeString: String?): LocaleComponents? {
46 | val parts = localeString?.split("-", "_")?.filter { it.isNotBlank() }.orEmpty()
47 | val language = parts.getOrNull(0)
48 |
49 | if (language != null && isValidLanguage(language)) {
50 | when (parts.size) {
51 | 0 -> Unit
52 | 1 -> return LocaleComponents(language = language, country = null)
53 | 2 -> return LocaleComponents(language = language, country = parts[1].takeIf(::isValidCountryOrRegion))
54 | else -> return when {
55 | isValidScript(parts[1]) && isValidCountryOrRegion(parts[2]) -> LocaleComponents(language = language, country = parts[2])
56 | else -> LocaleComponents(language = language, country = parts[1].takeIf(::isValidCountryOrRegion))
57 | }
58 | }
59 | }
60 |
61 | return null
62 | }
63 |
64 | private fun isValidLanguage(lang: String) = lang.matches(VALID_LANGUAGE_REGEX)
65 | private val VALID_LANGUAGE_REGEX = Regex("^[a-z]{2,3}$")
66 |
67 | private fun isValidScript(script: String) = script.matches(VALID_SCRIPT_REGEX)
68 | private val VALID_SCRIPT_REGEX = Regex("^[A-Z][a-z]{3}$")
69 |
70 | private fun isValidCountryOrRegion(country: String) = country.matches(VALID_COUNTRY_OR_REGION_REGEX)
71 | private val VALID_COUNTRY_OR_REGION_REGEX = Regex("^[A-Z]{2}$|^[0-9]{3}$|^XZZ$")
72 |
73 | internal data class LocaleComponents(
74 | val language: String,
75 | val country: String?,
76 | )
77 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 |
74 |
75 | @rem Execute Gradle
76 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
77 |
78 | :end
79 | @rem End local scope for the variables with windows NT shell
80 | if %ERRORLEVEL% equ 0 goto mainEnd
81 |
82 | :fail
83 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
84 | rem the _cmd.exe /c_ return code!
85 | set EXIT_CODE=%ERRORLEVEL%
86 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
87 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
88 | exit /b %EXIT_CODE%
89 |
90 | :mainEnd
91 | if "%OS%"=="Windows_NT" endlocal
92 |
93 | :omega
94 |
--------------------------------------------------------------------------------
/multiplatform-locale-apple-app-store/src/commonTest/kotlin/com/vanniktech/locale/apple/app/store/AppleAppStoreLocaleTest.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale.apple.app.store
2 |
3 | import com.vanniktech.locale.Country
4 | import com.vanniktech.locale.Language
5 | import com.vanniktech.locale.Locale
6 | import kotlin.test.Test
7 | import kotlin.test.assertEquals
8 |
9 | class AppleAppStoreLocaleTest {
10 | @Test fun appleAppStoreLocaleStringAllPossibilities() {
11 | assertEquals(
12 | expected = listOf(
13 | AppleAppStoreLocale.ar_SA,
14 | AppleAppStoreLocale.zh_Hans,
15 | AppleAppStoreLocale.zh_Hant,
16 | AppleAppStoreLocale.ca,
17 | AppleAppStoreLocale.cs,
18 | AppleAppStoreLocale.hr,
19 | AppleAppStoreLocale.da,
20 | AppleAppStoreLocale.nl_NL,
21 | AppleAppStoreLocale.en_US,
22 | AppleAppStoreLocale.en_CA,
23 | AppleAppStoreLocale.en_AU,
24 | AppleAppStoreLocale.en_GB,
25 | AppleAppStoreLocale.fi,
26 | AppleAppStoreLocale.fr_FR,
27 | AppleAppStoreLocale.fr_CA,
28 | AppleAppStoreLocale.de_DE,
29 | AppleAppStoreLocale.el,
30 | AppleAppStoreLocale.he,
31 | AppleAppStoreLocale.hi,
32 | AppleAppStoreLocale.hu,
33 | AppleAppStoreLocale.id,
34 | AppleAppStoreLocale.it,
35 | AppleAppStoreLocale.ja,
36 | AppleAppStoreLocale.ko,
37 | AppleAppStoreLocale.ms,
38 | AppleAppStoreLocale.no,
39 | AppleAppStoreLocale.pl,
40 | AppleAppStoreLocale.pt_PT,
41 | AppleAppStoreLocale.pt_BR,
42 | AppleAppStoreLocale.ro,
43 | AppleAppStoreLocale.ru,
44 | AppleAppStoreLocale.sk,
45 | AppleAppStoreLocale.es_ES,
46 | AppleAppStoreLocale.es_MX,
47 | AppleAppStoreLocale.sv,
48 | AppleAppStoreLocale.th,
49 | AppleAppStoreLocale.tr,
50 | AppleAppStoreLocale.uk,
51 | AppleAppStoreLocale.vi,
52 | ),
53 | actual = Language.entries.flatMap { language -> (language.officialTerritories + language.otherTerritories).mapNotNull { Locale(language, it).appleAppStoreLocale() } }.distinct(),
54 | )
55 | }
56 |
57 | @Test fun appleAppStoreLocaleStringLenient() {
58 | // Swedish only has one GooglePlayStoreLocale, so we'll match regardless of Country.
59 | assertEquals(
60 | expected = AppleAppStoreLocale.it,
61 | actual = Locale(Language.ITALIAN, null).appleAppStoreLocale(),
62 | )
63 |
64 | assertEquals(
65 | expected = AppleAppStoreLocale.it,
66 | actual = Locale(Language.ITALIAN, Country.AUSTRIA).appleAppStoreLocale(),
67 | )
68 |
69 | assertEquals(
70 | expected = AppleAppStoreLocale.fr_FR,
71 | actual = Locale(Language.FRENCH, null).appleAppStoreLocale(),
72 | )
73 |
74 | // English has many, so we'll try to be as close as possible.
75 | assertEquals(
76 | expected = AppleAppStoreLocale.en_AU,
77 | actual = Locale(Language.ENGLISH, Country.AUSTRIA).appleAppStoreLocale(),
78 | )
79 |
80 | assertEquals(
81 | expected = AppleAppStoreLocale.en_US,
82 | actual = Locale(Language.ENGLISH, Country.USA).appleAppStoreLocale(),
83 | )
84 |
85 | assertEquals(
86 | expected = AppleAppStoreLocale.en_CA,
87 | actual = Locale(Language.ENGLISH, Country.CANADA).appleAppStoreLocale(),
88 | )
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/commonTest/kotlin/com/vanniktech/locale/RegionTest.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | import kotlin.test.Test
4 | import kotlin.test.assertEquals
5 |
6 | class RegionTest {
7 | @Test fun uniqueEmojis() {
8 | val emojis = Region.entries.groupBy { it.emoji }
9 | emojis.forEach { (emoji, countries) ->
10 | assertEquals(message = "Emoji $emoji found multiple times: ${countries.joinToString { it.displayName() }}", expected = 1, actual = countries.size)
11 | }
12 | }
13 |
14 | @Test fun displayName() {
15 | assertEquals(expected = "European Union", actual = Region.EUROPEAN_UNION.displayName())
16 | assertEquals(expected = "Latin America", actual = Region.LATIN_AMERICA.displayName())
17 | assertEquals(expected = "Canary Islands", actual = Region.CANARY_ISLANDS.displayName())
18 | assertEquals(expected = "International Waters", actual = Region.INTERNATIONAL_WATERS.displayName())
19 | }
20 |
21 | @Test fun fromOrNull() {
22 | assertEquals(expected = null, actual = Region.fromOrNull(null))
23 | assertEquals(expected = null, actual = Region.fromOrNull(""))
24 | assertEquals(expected = null, actual = Region.fromOrNull("xxx"))
25 | assertEquals(expected = Region.EUROPEAN_UNION, actual = Region.fromOrNull("EU"))
26 | assertEquals(expected = Region.EUROPEAN_UNION, actual = Region.fromOrNull("eu"))
27 | assertEquals(expected = Region.INTERNATIONAL_WATERS, actual = Region.fromOrNull("XZZ"))
28 | assertEquals(expected = Region.INTERNATIONAL_WATERS, actual = Region.fromOrNull("xzz"))
29 | }
30 |
31 | @Test fun fromLocaleOrNull() {
32 | assertEquals(expected = Region.EUROPEAN_UNION, actual = Region.fromLocaleOrNull("de-EU"))
33 | assertEquals(expected = Region.LATIN_AMERICA, actual = Region.fromLocaleOrNull("es-419"))
34 | assertEquals(expected = Region.INTERNATIONAL_WATERS, actual = Region.fromLocaleOrNull("es-XZZ"))
35 | assertEquals(expected = null, actual = Region.fromLocaleOrNull("en"))
36 | assertEquals(expected = null, actual = Region.fromLocaleOrNull("de"))
37 | assertEquals(expected = null, actual = Region.fromLocaleOrNull(""))
38 | assertEquals(expected = null, actual = Region.fromLocaleOrNull(null))
39 | }
40 |
41 | @Test fun fromLenientOrNull() {
42 | assertEquals(expected = null, actual = Region.fromLenientOrNull("xxx"))
43 | assertEquals(expected = null, actual = Region.fromLenientOrNull(null))
44 | assertEquals(expected = Region.EUROPEAN_UNION, actual = Region.fromLenientOrNull("EU"))
45 | assertEquals(expected = Region.EUROPEAN_UNION, actual = Region.fromLenientOrNull("eu"))
46 | assertEquals(expected = Region.EUROPEAN_UNION, actual = Region.fromLenientOrNull("de-EU"))
47 | assertEquals(expected = Region.LATIN_AMERICA, actual = Region.fromLenientOrNull("es-419"))
48 | assertEquals(expected = Region.INTERNATIONAL_WATERS, actual = Region.fromLenientOrNull("es-XZZ"))
49 | }
50 |
51 | @Test fun region() {
52 | assertEquals(
53 | expected = """
54 | 419-LATIN_AMERICA-null
55 | EU-EUROPEAN_UNION-🇪🇺
56 | IC-CANARY_ISLANDS-🇮🇨
57 | XZ-INTERNATIONAL_WATERS-🌊
58 | """.trimIndent(),
59 | actual = Region.entries.sortedBy { it.code }.joinToString(separator = "\n") { "${it.code}-${it.name}-${it.emoji}" },
60 | )
61 | }
62 |
63 | @Test fun noDuplicates() {
64 | val unique = Region.entries.map { it.code }.toSet()
65 | assertEquals(expected = Region.entries.size, actual = unique.size)
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/multiplatform-locale-apple-app-store/api/current.txt:
--------------------------------------------------------------------------------
1 | // Signature format: 4.0
2 | package com.vanniktech.locale.apple.app.store {
3 |
4 | public enum AppleAppStoreLocale {
5 | method public error.NonExistentClass toString();
6 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale ar_SA;
7 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale ca;
8 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale cs;
9 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale da;
10 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale de_DE;
11 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale el;
12 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale en_AU;
13 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale en_CA;
14 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale en_GB;
15 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale en_US;
16 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale es_ES;
17 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale es_MX;
18 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale fi;
19 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale fr_CA;
20 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale fr_FR;
21 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale he;
22 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale hi;
23 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale hr;
24 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale hu;
25 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale id;
26 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale it;
27 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale ja;
28 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale ko;
29 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale ms;
30 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale nl_NL;
31 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale no;
32 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale pl;
33 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale pt_BR;
34 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale pt_PT;
35 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale ro;
36 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale ru;
37 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale sk;
38 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale sv;
39 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale th;
40 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale tr;
41 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale uk;
42 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale vi;
43 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale zh_Hans;
44 | enum_constant public static final com.vanniktech.locale.apple.app.store.AppleAppStoreLocale zh_Hant;
45 | }
46 |
47 | public final class AppleAppStoreLocaleKt {
48 | method public static com.vanniktech.locale.apple.app.store.AppleAppStoreLocale? appleAppStoreLocale(com.vanniktech.locale.Locale);
49 | }
50 |
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/multiplatform-locale-google-play-store/src/commonTest/kotlin/com/vanniktech/locale/google/play/store/GooglePlayStoreLocaleTest.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale.google.play.store
2 |
3 | import com.vanniktech.locale.Country
4 | import com.vanniktech.locale.Language
5 | import com.vanniktech.locale.Locale
6 | import kotlin.test.Test
7 | import kotlin.test.assertEquals
8 |
9 | class GooglePlayStoreLocaleTest {
10 | @Test fun googlePlayStoreLocaleAllPossibilities() {
11 | assertEquals(
12 | expected = listOf(
13 | GooglePlayStoreLocale.ar,
14 | GooglePlayStoreLocale.af,
15 | GooglePlayStoreLocale.sq,
16 | GooglePlayStoreLocale.am,
17 | GooglePlayStoreLocale.hy_AM,
18 | GooglePlayStoreLocale.az_AZ,
19 | GooglePlayStoreLocale.be,
20 | GooglePlayStoreLocale.bn_BD,
21 | GooglePlayStoreLocale.bg,
22 | GooglePlayStoreLocale.my_MM,
23 | GooglePlayStoreLocale.km_KH,
24 | GooglePlayStoreLocale.zh_CN,
25 | GooglePlayStoreLocale.zh_TW,
26 | GooglePlayStoreLocale.zh_HK,
27 | GooglePlayStoreLocale.ca,
28 | GooglePlayStoreLocale.cs_CZ,
29 | GooglePlayStoreLocale.hr,
30 | GooglePlayStoreLocale.da_DK,
31 | GooglePlayStoreLocale.nl_NL,
32 | GooglePlayStoreLocale.en_US,
33 | GooglePlayStoreLocale.en_CA,
34 | GooglePlayStoreLocale.en_AU,
35 | GooglePlayStoreLocale.en_GB,
36 | GooglePlayStoreLocale.et,
37 | GooglePlayStoreLocale.fa_IR,
38 | GooglePlayStoreLocale.fa_AF,
39 | GooglePlayStoreLocale.fa,
40 | GooglePlayStoreLocale.fa_AE,
41 | GooglePlayStoreLocale.fil,
42 | GooglePlayStoreLocale.fi_FI,
43 | GooglePlayStoreLocale.fr_FR,
44 | GooglePlayStoreLocale.fr_CA,
45 | GooglePlayStoreLocale.ka_GE,
46 | GooglePlayStoreLocale.de_DE,
47 | GooglePlayStoreLocale.el_GR,
48 | GooglePlayStoreLocale.gu,
49 | GooglePlayStoreLocale.iw_IL,
50 | GooglePlayStoreLocale.is_IS,
51 | GooglePlayStoreLocale.hi_IN,
52 | GooglePlayStoreLocale.hu_HU,
53 | GooglePlayStoreLocale.id,
54 | GooglePlayStoreLocale.it_IT,
55 | GooglePlayStoreLocale.ja_JP,
56 | GooglePlayStoreLocale.kn_IN,
57 | GooglePlayStoreLocale.ko_KR,
58 | GooglePlayStoreLocale.lo_LA,
59 | GooglePlayStoreLocale.lv,
60 | GooglePlayStoreLocale.lt,
61 | GooglePlayStoreLocale.mk_MK,
62 | GooglePlayStoreLocale.ms_MY,
63 | GooglePlayStoreLocale.ml_IN,
64 | GooglePlayStoreLocale.mr_IN,
65 | GooglePlayStoreLocale.no_NO,
66 | GooglePlayStoreLocale.pl_PL,
67 | GooglePlayStoreLocale.pt_PT,
68 | GooglePlayStoreLocale.pt_BR,
69 | GooglePlayStoreLocale.ro,
70 | GooglePlayStoreLocale.ru_RU,
71 | GooglePlayStoreLocale.sr,
72 | GooglePlayStoreLocale.sk,
73 | GooglePlayStoreLocale.sl,
74 | GooglePlayStoreLocale.es_ES,
75 | GooglePlayStoreLocale.es_419,
76 | GooglePlayStoreLocale.es_US,
77 | GooglePlayStoreLocale.sw,
78 | GooglePlayStoreLocale.sv_SE,
79 | GooglePlayStoreLocale.ta_IN,
80 | GooglePlayStoreLocale.te_IN,
81 | GooglePlayStoreLocale.th,
82 | GooglePlayStoreLocale.tr_TR,
83 | GooglePlayStoreLocale.uk,
84 | GooglePlayStoreLocale.ur,
85 | GooglePlayStoreLocale.vi,
86 | ),
87 | actual = Language.entries.flatMap { language -> (language.officialTerritories + language.otherTerritories).mapNotNull { Locale(language, it).googlePlayStoreLocale() } }.distinct(),
88 | )
89 | }
90 |
91 | @Test fun googlePlayStoreLocaleLenient() {
92 | // Italian only has one GooglePlayStoreLocale, so we'll match regardless of Country.
93 | assertEquals(
94 | expected = GooglePlayStoreLocale.it_IT,
95 | actual = Locale(Language.ITALIAN, null).googlePlayStoreLocale(),
96 | )
97 |
98 | assertEquals(
99 | expected = GooglePlayStoreLocale.it_IT,
100 | actual = Locale(Language.ITALIAN, Country.AUSTRIA).googlePlayStoreLocale(),
101 | )
102 |
103 | assertEquals(
104 | expected = GooglePlayStoreLocale.fr_FR,
105 | actual = Locale(Language.FRENCH, null).googlePlayStoreLocale(),
106 | )
107 |
108 | // English has many, so we'll try to be as close as possible.
109 | assertEquals(
110 | expected = GooglePlayStoreLocale.en_AU,
111 | actual = Locale(Language.ENGLISH, Country.AUSTRIA).googlePlayStoreLocale(),
112 | )
113 |
114 | assertEquals(
115 | expected = GooglePlayStoreLocale.en_US,
116 | actual = Locale(Language.ENGLISH, Country.USA).googlePlayStoreLocale(),
117 | )
118 |
119 | assertEquals(
120 | expected = GooglePlayStoreLocale.en_CA,
121 | actual = Locale(Language.ENGLISH, Country.CANADA).googlePlayStoreLocale(),
122 | )
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/commonTest/kotlin/com/vanniktech/locale/LocaleTest.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | import kotlin.test.Test
4 | import kotlin.test.assertEquals
5 |
6 | class LocaleTest {
7 | @Test fun sorted() {
8 | assertEquals(
9 | expected = listOf(
10 | Locale(Language.ENGLISH, territory = Country.USA),
11 | Locale(Language.GERMAN, territory = Country.GERMANY),
12 | ),
13 | actual = listOf(
14 | Locale(Language.GERMAN, territory = Country.GERMANY),
15 | Locale(Language.ENGLISH, territory = Country.USA),
16 | ).sorted(),
17 | )
18 | }
19 |
20 | @Test fun fromOrNull() {
21 | listOf(
22 | Pair(Locale(Language.ENGLISH, territory = null), "en"),
23 | Pair(Locale(Language.GERMAN, territory = null), "de"),
24 | Pair(Locale(Language.ENGLISH, Country.ENGLAND), "en-GB"),
25 | Pair(Locale(Language.ENGLISH, Country.USA), "en-US"),
26 | Pair(Locale(Language.ENGLISH, Country.USA), "en_US"),
27 | Pair(Locale(Language.DUTCH, Country.NETHERLANDS), "nl-NL"),
28 | Pair(Locale(Language.DUTCH, Country.NETHERLANDS), "nl_NL"),
29 | Pair(Locale(Language.ITALIAN, Country.ITALY), "it-IT"),
30 | Pair(Locale(Language.ITALIAN, Country.ITALY), "it_IT"),
31 | Pair(Locale(Language.GERMAN, Country.USA), "de-US"),
32 | Pair(Locale(Language.GERMAN, Country.USA), "de_US"),
33 | Pair(Locale(Language.DANISH, Country.DENMARK), "da-DK"),
34 | Pair(Locale(Language.DANISH, Country.DENMARK), "da_DK"),
35 | Pair(Locale(Language.KOREAN, Country.SOUTH_KOREA), "ko_KR"),
36 | Pair(Locale(Language.KOREAN, Country.SOUTH_KOREA), "ko-KR"),
37 | Pair(Locale(Language.KOREAN, Country.NORTH_KOREA), "ko_KP"),
38 | Pair(Locale(Language.KOREAN, Country.NORTH_KOREA), "ko-KP"),
39 | Pair(Locale(Language.JAPANESE, Country.JAPAN), "ja-JP"),
40 | Pair(Locale(Language.JAPANESE, Country.JAPAN), "ja_JP"),
41 | Pair(Locale(Language.PORTUGUESE, Country.PORTUGAL), "pt-PT"),
42 | Pair(Locale(Language.PORTUGUESE, Country.PORTUGAL), "pt_PT"),
43 | Pair(Locale(Language.PORTUGUESE, Country.BRAZIL), "pt-BR"),
44 | Pair(Locale(Language.PORTUGUESE, Country.BRAZIL), "pt_BR"),
45 | Pair(Locale(Language.CHINESE, Country.CHINA), "zh-CN"),
46 | Pair(Locale(Language.CHINESE, Country.CHINA), "zh_CN_#Hans"),
47 | Pair(Locale(Language.SERBIAN, Country.SERBIA), "sr-RS"),
48 | Pair(Locale(Language.SERBIAN, Country.SERBIA), "sr_RS_#Latn"),
49 | Pair(Locale(Language.SLOVAK, Country.SLOVAKIA), "sk-SK"),
50 | Pair(Locale(Language.SLOVAK, Country.SLOVAKIA), "sk_SK"),
51 | Pair(Locale(Language.THAI, Country.THAILAND), "th-TH"),
52 | Pair(Locale(Language.ARABIC, Country.EGYPT), "ar_EG_#u-nu-latn"),
53 | Pair(Locale(Language.HINDI, Country.INDIA), "hi-IN"),
54 | Pair(Locale(Language.GUJARATI, Country.INDIA), "gu-IN"),
55 | Pair(Locale(Language.MALAY, Country.MALAYSIA), "ms_MY"),
56 | Pair(Locale(Language.FARSI, Country.IRAN), "fa-IR"),
57 | Pair(Locale(Language.ARMENIAN, Country.ARMENIA), "hy-AM"),
58 | Pair(Locale(Language.CROATIAN, Country.CROATIA), "hr-HR"),
59 | Pair(Locale(Language.AZERBAIJANI, Country.AZERBAIJAN), "az-AZ"),
60 | Pair(Locale(Language.BURMESE, Country.MYANMAR), "my-MM"),
61 | Pair(Locale(Language.IRISH, Country.IRELAND), "ga-IE"),
62 | Pair(Locale(Language.UZBEK, Country.UZBEKISTAN), "uz_UZ"),
63 | Pair(Locale(Language.CATALAN, Country.SPAIN), "ca_ES"),
64 | Pair(Locale(Language.BOKMAL, Country.NORWAY), "nb_NO"),
65 | Pair(Locale(Language.MALAYALAM, Country.INDIA), "ml-IN"),
66 | Pair(Locale(Language.URDU, Country.PAKISTAN), "ur_PK"),
67 | Pair(Locale(Language.CENTRAL_KMHER, Country.ENGLAND), "km-GB"),
68 | Pair(Locale(Language.AMHARIC, Country.ETHIOPIA), "am-ET"),
69 | Pair(Locale(Language.FILIPINO, Country.PHILIPPINES), "fil-PH"),
70 | Pair(Locale(Language.ICELANDIC, Country.ICELAND), "is_IS"),
71 | Pair(Locale(Language.SPANISH, Region.LATIN_AMERICA), "es-419"),
72 | Pair(Locale(Language.SPANISH, Region.CANARY_ISLANDS), "es-IC"),
73 | Pair(Locale(Language.BOSNIAN, Country.BOSNIA_AND_HERZEGOVINA), "bs-BA"),
74 | Pair(Locale(Language.LAO, Country.LAOS), "lo-LA"),
75 | Pair(Locale(Language.SOMALI, Country.SOMALIA), "so-SO"),
76 | Pair(Locale(Language.CHINESE, Country.NEW_ZEALAND), "zh-Hans_NZ"),
77 | Pair(Locale(Language.OROMO, Country.ETHIOPIA), "om-ET"),
78 | ).forEach { (locale, localeString) ->
79 | assertEquals(
80 | message = localeString,
81 | expected = locale,
82 | actual = Locale.fromOrNull(localeString),
83 | )
84 | }
85 | }
86 |
87 | @Test fun fromAndroidValuesDirectoryName() {
88 | assertEquals(expected = Locale(Language.ENGLISH, null), actual = Locale.fromAndroidValuesDirectoryName("values"))
89 | }
90 |
91 | @Test fun fromAndroidValuesDirectoryNameOrNull() {
92 | listOf(
93 | Pair(null, ""),
94 | Pair(null, "values-foo"),
95 | Pair(Locale(Language.ENGLISH, null), "values"),
96 | Pair(Locale(Language.ARABIC, null), "values-ar"),
97 | Pair(Locale(Language.BULGARIAN, null), "values-bg"),
98 | Pair(Locale(Language.CZECH, null), "values-cs"),
99 | Pair(Locale(Language.GERMAN, null), "values-de"),
100 | Pair(Locale(Language.GREEK, null), "values-el"),
101 | Pair(Locale(Language.SPANISH, null), "values-es"),
102 | Pair(Locale(Language.FINNISH, null), "values-fi"),
103 | Pair(Locale(Language.FRENCH, null), "values-fr"),
104 | Pair(Locale(Language.HUNGARIAN, null), "values-hu"),
105 | Pair(Locale(Language.INDONESIAN, null), "values-in"),
106 | Pair(Locale(Language.ITALIAN, null), "values-it"),
107 | Pair(Locale(Language.HEBREW, null), "values-iw"),
108 | Pair(Locale(Language.DUTCH, null), "values-nl"),
109 | Pair(Locale(Language.NORWEGIAN, null), "values-no"),
110 | Pair(Locale(Language.POLISH, null), "values-pl"),
111 | Pair(Locale(Language.PORTUGUESE, null), "values-pt"),
112 | Pair(Locale(Language.PORTUGUESE, Country.BRAZIL), "values-pt-rBR"),
113 | Pair(Locale(Language.ROMANIAN, null), "values-ro"),
114 | Pair(Locale(Language.RUSSIAN, null), "values-ru"),
115 | Pair(Locale(Language.SWEDISH, null), "values-sv"),
116 | Pair(Locale(Language.TURKISH, null), "values-tr"),
117 | Pair(Locale(Language.UKRAINIAN, null), "values-uk"),
118 | Pair(Locale(Language.VIETNAMESE, null), "values-vi"),
119 | Pair(Locale(Language.CHINESE, Country.CHINA), "values-zh-rCN"),
120 | Pair(Locale(Language.CHINESE, Country.TAIWAN), "values-zh-rTW"),
121 | Pair(Locale(Language.CHINESE, Country.TAIWAN), "zh-rTW"),
122 | Pair(Locale(Language.AZERBAIJANI, Country.AZERBAIJAN), "az_AZ_#Latn"),
123 | Pair(Locale(Language.BELARUSIAN, Country.BELARUS), "be-BY"),
124 | Pair(Locale(Language.TAMIL, Country.INDIA), "ta-IN"),
125 | Pair(Locale(Language.MARATHI, Country.INDIA), "mr-IN"),
126 | ).forEach { (locale, androidValuesDirectoryName) ->
127 | assertEquals(message = androidValuesDirectoryName, expected = locale, actual = Locale.fromAndroidValuesDirectoryNameOrNull(androidValuesDirectoryName))
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/generator/src/main/kotlin/com/vanniktech/locale/generator/main.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale.generator
2 |
3 | import com.charleskorn.kaml.Yaml
4 | import com.charleskorn.kaml.YamlConfiguration
5 | import kotlinx.serialization.SerialName
6 | import kotlinx.serialization.Serializable
7 | import kotlinx.serialization.builtins.MapSerializer
8 | import kotlinx.serialization.builtins.serializer
9 | import okio.FileSystem
10 | import okio.Path.Companion.toPath
11 |
12 | fun main() {
13 | // Adjust the path of the https://github.com/countries/countries repository as needed.
14 | val githubDirectory = "/Users/niklas/dev/GitHub/".toPath()
15 | val countriesPath = githubDirectory / "countries/lib/countries/data/countries".toPath()
16 | val fileSystem = FileSystem.SYSTEM
17 |
18 | val overwrittenNames = mutableMapOf(
19 | // Names that we want to keep.
20 | "BOLIVIA_PLURINATIONAL_STATE_OF" to "BOLIVIA",
21 | "BONAIRE_SINT_EUSTATIUS_AND_SABA" to "BONAIRE",
22 | "BRUNEI_DARUSSALAM" to "BRUNEI",
23 | "CURAÇAO" to "CURACAO",
24 | "CÔTE_DIVOIRE" to "COTE_DIVOIRE",
25 | "HOLY_SEE" to "VATICAN_CITY",
26 | "IRAN_ISLAMIC_REPUBLIC_OF" to "IRAN",
27 | "KOREA_DEMOCRATIC_PEOPLES_REPUBLIC_OF" to "NORTH_KOREA",
28 | "KOREA_REPUBLIC_OF" to "SOUTH_KOREA",
29 | "LAO_PEOPLES_DEMOCRATIC_REPUBLIC" to "LAOS",
30 | "MICRONESIA_FEDERATED_STATES_OF" to "MICRONESIA",
31 | "MOLDOVA_REPUBLIC_OF" to "MOLDOVA",
32 | "PALESTINE_STATE_OF" to "PALESTINE",
33 | "RUSSIAN_FEDERATION" to "RUSSIA",
34 | "RÉUNION" to "REUNION",
35 | "SAINT_MARTIN_FRENCH_PART" to "SAINT_MARTIN",
36 | "SINT_MAARTEN_DUTCH_PART" to "SINT_MAARTEN",
37 | "SYRIAN_ARAB_REPUBLIC" to "SYRIA",
38 | "TAIWAN_PROVINCE_OF_CHINA" to "TAIWAN",
39 | "TANZANIA_UNITED_REPUBLIC_OF" to "TANZANIA",
40 | "TÜRKIYE" to "TURKEY",
41 | "UNITED_KINGDOM_OF_GREAT_BRITAIN_AND_NORTHERN_IRELAND" to "ENGLAND",
42 | "UNITED_STATES_OF_AMERICA" to "USA",
43 | "VENEZUELA_BOLIVARIAN_REPUBLIC_OF" to "VENEZUELA",
44 | "VIET_NAM" to "VIETNAM",
45 | "ÅLAND_ISLANDS" to "ALAND_ISLANDS",
46 |
47 | // Congo.
48 | "CONGO" to "REPUBLIC_OF_THE_CONGO", // This might be fine.
49 | "CONGO_DEMOCRATIC_REPUBLIC_OF_THE" to "DEMOCRATIC_REPUBLIC_OF_CONGO", // Should be DEMOCRATIC_REPUBLIC_OF_THE_CONGO.
50 |
51 | // Names that we might align at some point.
52 | "CABO_VERDE" to "CAPE_VERDE",
53 | "COCOS_KEELING_ISLANDS" to "COCOS_ISLANDS",
54 | "FALKLAND_ISLANDS_MALVINAS" to "FALKLAND_ISLANDS",
55 | "FRENCH_SOUTHERN_TERRITORIES" to "FRENCH_SOUTHERN_AND_ANTARCTIC_LANDS",
56 | "MARSHALL_ISLANDS" to "MARSHALL_ISLAND",
57 | "PITCAIRN" to "PITCAIRN_ISLANDS",
58 | "SAINT_BARTHÉLEMY" to "SAINT_BARTS", // Should be SAINT_BARTHELEMY.
59 | "SAO_TOME_AND_PRINCIPE" to "SAO_TOME_AND_PRINCE",
60 | "TURKS_AND_CAICOS_ISLANDS" to "TURKS_AND_CAICOS",
61 | "VIRGIN_ISLANDS_BRITISH" to "BRITISH_VIRGIN_ISLANDS",
62 | "VIRGIN_ISLANDS_US" to "US_VIRGIN_ISLANDS",
63 | "WESTERN_SAHARA" to "SAHRAWI_ARAB_DEMOCRATIC_REPUBLIC",
64 | )
65 |
66 | val yaml = Yaml(configuration = YamlConfiguration(strictMode = false))
67 | val serializer = MapSerializer(String.serializer(), CountryDto.serializer())
68 | val parsedCountries = fileSystem.list(countriesPath)
69 | .flatMap { yaml.decodeFromSource(serializer, fileSystem.source(countriesPath / it)).values }
70 | .map {
71 | val fallback = it.isoShortName.uppercase()
72 | .replace(" ", "_")
73 | .replace(",", "")
74 | .replace("-", "_")
75 | .replace(".", "")
76 | .replace("'", "")
77 | .replace("(", "")
78 | .replace(")", "")
79 |
80 | it.copy(
81 | isoShortName = overwrittenNames.remove(fallback) ?: fallback,
82 | )
83 | }
84 |
85 | val otherCountries = listOf(
86 | // https://github.com/countries/countries/issues/793#issuecomment-2027531814
87 | CountryDto(
88 | alpha2 = "XK",
89 | alpha3 = "XKX",
90 | countryCode = "383",
91 | isoShortName = "KOSOVO",
92 | continent = "EUROPE",
93 | geo = Geo(
94 | latitude = 42.5833,
95 | longitude = 21.0001,
96 | maxLatitude = 43.139,
97 | maxLongitude = 21.835,
98 | minLatitude = 41.877,
99 | minLongitude = 19.949,
100 | ),
101 | ),
102 | )
103 |
104 | val countries = (parsedCountries + otherCountries).sortedBy { it.isoShortName }
105 | val enumOutput = countries
106 | .map {
107 | val callingCode = it.nanpPrefix ?: it.countryCode
108 | val continent = it.continent.uppercase()
109 | .replace(" ", "_")
110 | .replace("AUSTRALIA", "OCEANIA")
111 |
112 | "${it.isoShortName}(code = \"${it.alpha2}\", code3 = \"${it.alpha3}\", callingCodes = listOf(\"+$callingCode\"), continent = Continent.$continent),"
113 | }
114 |
115 | require(overwrittenNames.isEmpty()) { "Unmatched overwritten names: $overwrittenNames" }
116 | println(enumOutput.joinToString(separator = "\n"))
117 |
118 | fileSystem.write(githubDirectory / "multiplatform-locale/multiplatform-locale-geo/src/commonMain/kotlin/com/vanniktech/locale/geo/CountryGeo.kt") {
119 | writeUtf8(
120 | """
121 | |package com.vanniktech.locale.geo
122 | |
123 | |import com.vanniktech.locale.Country
124 | |
125 | |
126 | """.trimMargin(),
127 | )
128 |
129 | countries.forEach {
130 | writeUtf8(
131 | """
132 | |private val GEO_${it.isoShortName} = Geo(
133 | | latitude = ${it.geo.latitude},
134 | | longitude = ${it.geo.longitude},
135 | | maxLatitude = ${it.geo.maxLatitude},
136 | | maxLongitude = ${it.geo.maxLongitude},
137 | | minLatitude = ${it.geo.minLatitude},
138 | | minLongitude = ${it.geo.minLongitude},
139 | |)
140 | |
141 | |
142 | """.trimMargin(),
143 | )
144 | }
145 |
146 | writeUtf8(
147 | """
148 | |val Country.geo get() = when (this) {
149 | |
150 | """.trimMargin(),
151 | )
152 |
153 | countries.forEach {
154 | writeUtf8(
155 | """
156 | | Country.${it.isoShortName} -> GEO_${it.isoShortName}
157 | |
158 | """.trimMargin(),
159 | )
160 | }
161 |
162 | writeUtf8(
163 | """
164 | |}
165 | |
166 | """.trimMargin(),
167 | )
168 | }
169 | }
170 |
171 | // https://github.com/countries/countries/blob/master/lib/countries/data/countries/TL.yaml
172 | @Serializable data class CountryDto(
173 | @SerialName("alpha2") val alpha2: String,
174 | @SerialName("alpha3") val alpha3: String,
175 | @SerialName("country_code") val countryCode: String,
176 | @SerialName("nanp_prefix") val nanpPrefix: String? = null,
177 | @SerialName("iso_short_name") val isoShortName: String,
178 | @SerialName("continent") val continent: String,
179 | @SerialName("geo") val geo: Geo,
180 | )
181 |
182 | @Serializable data class Geo(
183 | @SerialName("latitude") val latitude: Double,
184 | @SerialName("longitude") val longitude: Double,
185 | @SerialName("max_latitude") val maxLatitude: Double,
186 | @SerialName("max_longitude") val maxLongitude: Double,
187 | @SerialName("min_latitude") val minLatitude: Double,
188 | @SerialName("min_longitude") val minLongitude: Double,
189 | )
190 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/commonTest/kotlin/com/vanniktech/locale/CountryTest.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | import kotlin.test.Test
4 | import kotlin.test.assertEquals
5 |
6 | class CountryTest {
7 | @Test fun uniqueEmojis() {
8 | val emojis = Country.entries.groupBy { it.emoji }
9 | emojis.forEach { (emoji, countries) ->
10 | assertEquals(message = "Emoji $emoji found multiple times: ${countries.joinToString { it.displayName() }}", expected = 1, actual = countries.size)
11 | }
12 | }
13 |
14 | @Test fun callingCodesAreSorted() {
15 | Country.entries
16 | .forEach {
17 | assertEquals(expected = it.callingCodes.sorted(), actual = it.callingCodes, message = "Dial codes not sorted for $it")
18 | }
19 | }
20 |
21 | @Test fun displayName() {
22 | assertEquals(expected = "United Kingdom", actual = Country.ENGLAND.displayName())
23 | assertEquals(expected = "Germany", actual = Country.GERMANY.displayName())
24 | }
25 |
26 | @Test fun fromOrNull() {
27 | assertEquals(expected = null, actual = Country.fromOrNull(null))
28 | assertEquals(expected = null, actual = Country.fromOrNull(""))
29 | assertEquals(expected = null, actual = Country.fromOrNull("xxx"))
30 | assertEquals(expected = Country.ARMENIA, actual = Country.fromOrNull("AM"))
31 | assertEquals(expected = Country.ARMENIA, actual = Country.fromOrNull("am"))
32 | assertEquals(expected = Country.USA, actual = Country.fromOrNull("US"))
33 | assertEquals(expected = Country.USA, actual = Country.fromOrNull("USA"))
34 | }
35 |
36 | @Test fun fromLocaleOrNull() {
37 | assertEquals(expected = Country.USA, actual = Country.fromLocaleOrNull("de-US"))
38 | assertEquals(expected = Country.USA, actual = Country.fromLocaleOrNull("en-US"))
39 | assertEquals(expected = Country.USA, actual = Country.fromLocaleOrNull("de_US"))
40 | assertEquals(expected = Country.USA, actual = Country.fromLocaleOrNull("en_US"))
41 | assertEquals(expected = null, actual = Country.fromLocaleOrNull("en"))
42 | assertEquals(expected = null, actual = Country.fromLocaleOrNull("de"))
43 | assertEquals(expected = null, actual = Country.fromLocaleOrNull(""))
44 | assertEquals(expected = null, actual = Country.fromLocaleOrNull(null))
45 | }
46 |
47 | @Test fun fromLenientOrNull() {
48 | assertEquals(expected = null, actual = Country.fromLenientOrNull("xxx"))
49 | assertEquals(expected = null, actual = Country.fromLenientOrNull(null))
50 | assertEquals(expected = Country.USA, actual = Country.fromLenientOrNull("US"))
51 | assertEquals(expected = Country.USA, actual = Country.fromLenientOrNull("us"))
52 | assertEquals(expected = Country.USA, actual = Country.fromLenientOrNull("USA"))
53 | assertEquals(expected = Country.USA, actual = Country.fromLenientOrNull("usa"))
54 | assertEquals(expected = Country.USA, actual = Country.fromLenientOrNull("en-US"))
55 | assertEquals(expected = Country.GERMANY, actual = Country.fromLenientOrNull("en-DE"))
56 | assertEquals(expected = Country.VIETNAM, actual = Country.fromLenientOrNull("VIETNAM"))
57 | assertEquals(expected = Country.ZAMBIA, actual = Country.fromLenientOrNull("zambia"))
58 | }
59 |
60 | @Test fun country() {
61 | assertEquals(
62 | expected = """
63 | AD-ANDORRA 🇦🇩
64 | AE-UNITED_ARAB_EMIRATES 🇦🇪
65 | AF-AFGHANISTAN 🇦🇫
66 | AG-ANTIGUA_AND_BARBUDA 🇦🇬
67 | AI-ANGUILLA 🇦🇮
68 | AL-ALBANIA 🇦🇱
69 | AM-ARMENIA 🇦🇲
70 | AO-ANGOLA 🇦🇴
71 | AQ-ANTARCTICA 🇦🇶
72 | AR-ARGENTINA 🇦🇷
73 | AS-AMERICAN_SAMOA 🇦🇸
74 | AT-AUSTRIA 🇦🇹
75 | AU-AUSTRALIA 🇦🇺
76 | AW-ARUBA 🇦🇼
77 | AX-ALAND_ISLANDS 🇦🇽
78 | AZ-AZERBAIJAN 🇦🇿
79 | BA-BOSNIA_AND_HERZEGOVINA 🇧🇦
80 | BB-BARBADOS 🇧🇧
81 | BD-BANGLADESH 🇧🇩
82 | BE-BELGIUM 🇧🇪
83 | BF-BURKINA_FASO 🇧🇫
84 | BG-BULGARIA 🇧🇬
85 | BH-BAHRAIN 🇧🇭
86 | BI-BURUNDI 🇧🇮
87 | BJ-BENIN 🇧🇯
88 | BL-SAINT_BARTS 🇧🇱
89 | BM-BERMUDA 🇧🇲
90 | BN-BRUNEI 🇧🇳
91 | BO-BOLIVIA 🇧🇴
92 | BQ-BONAIRE 🇧🇶
93 | BR-BRAZIL 🇧🇷
94 | BS-BAHAMAS 🇧🇸
95 | BT-BHUTAN 🇧🇹
96 | BV-BOUVET_ISLAND 🇧🇻
97 | BW-BOTSWANA 🇧🇼
98 | BY-BELARUS 🇧🇾
99 | BZ-BELIZE 🇧🇿
100 | CA-CANADA 🇨🇦
101 | CC-COCOS_ISLANDS 🇨🇨
102 | CD-DEMOCRATIC_REPUBLIC_OF_CONGO 🇨🇩
103 | CF-CENTRAL_AFRICAN_REPUBLIC 🇨🇫
104 | CG-REPUBLIC_OF_THE_CONGO 🇨🇬
105 | CH-SWITZERLAND 🇨🇭
106 | CI-COTE_DIVOIRE 🇨🇮
107 | CK-COOK_ISLANDS 🇨🇰
108 | CL-CHILE 🇨🇱
109 | CM-CAMEROON 🇨🇲
110 | CN-CHINA 🇨🇳
111 | CO-COLOMBIA 🇨🇴
112 | CR-COSTA_RICA 🇨🇷
113 | CU-CUBA 🇨🇺
114 | CV-CAPE_VERDE 🇨🇻
115 | CW-CURACAO 🇨🇼
116 | CX-CHRISTMAS_ISLAND 🇨🇽
117 | CY-CYPRUS 🇨🇾
118 | CZ-CZECHIA 🇨🇿
119 | DE-GERMANY 🇩🇪
120 | DJ-DJIBOUTI 🇩🇯
121 | DK-DENMARK 🇩🇰
122 | DM-DOMINICA 🇩🇲
123 | DO-DOMINICAN_REPUBLIC 🇩🇴
124 | DZ-ALGERIA 🇩🇿
125 | EC-ECUADOR 🇪🇨
126 | EE-ESTONIA 🇪🇪
127 | EG-EGYPT 🇪🇬
128 | EH-SAHRAWI_ARAB_DEMOCRATIC_REPUBLIC 🇪🇭
129 | ER-ERITREA 🇪🇷
130 | ES-SPAIN 🇪🇸
131 | ET-ETHIOPIA 🇪🇹
132 | FI-FINLAND 🇫🇮
133 | FJ-FIJI 🇫🇯
134 | FK-FALKLAND_ISLANDS 🇫🇰
135 | FM-MICRONESIA 🇫🇲
136 | FO-FAROE_ISLANDS 🇫🇴
137 | FR-FRANCE 🇫🇷
138 | GA-GABON 🇬🇦
139 | GB-ENGLAND 🇬🇧
140 | GD-GRENADA 🇬🇩
141 | GE-GEORGIA 🇬🇪
142 | GF-FRENCH_GUIANA 🇬🇫
143 | GG-GUERNSEY 🇬🇬
144 | GH-GHANA 🇬🇭
145 | GI-GIBRALTAR 🇬🇮
146 | GL-GREENLAND 🇬🇱
147 | GM-GAMBIA 🇬🇲
148 | GN-GUINEA 🇬🇳
149 | GP-GUADELOUPE 🇬🇵
150 | GQ-EQUATORIAL_GUINEA 🇬🇶
151 | GR-GREECE 🇬🇷
152 | GS-SOUTH_GEORGIA_AND_THE_SOUTH_SANDWICH_ISLANDS 🇬🇸
153 | GT-GUATEMALA 🇬🇹
154 | GU-GUAM 🇬🇺
155 | GW-GUINEA_BISSAU 🇬🇼
156 | GY-GUYANA 🇬🇾
157 | HK-HONG_KONG 🇭🇰
158 | HM-HEARD_ISLAND_AND_MCDONALD_ISLANDS 🇭🇲
159 | HN-HONDURAS 🇭🇳
160 | HR-CROATIA 🇭🇷
161 | HT-HAITI 🇭🇹
162 | HU-HUNGARY 🇭🇺
163 | ID-INDONESIA 🇮🇩
164 | IE-IRELAND 🇮🇪
165 | IL-ISRAEL 🇮🇱
166 | IM-ISLE_OF_MAN 🇮🇲
167 | IN-INDIA 🇮🇳
168 | IO-BRITISH_INDIAN_OCEAN_TERRITORY 🇮🇴
169 | IQ-IRAQ 🇮🇶
170 | IR-IRAN 🇮🇷
171 | IS-ICELAND 🇮🇸
172 | IT-ITALY 🇮🇹
173 | JE-JERSEY 🇯🇪
174 | JM-JAMAICA 🇯🇲
175 | JO-JORDAN 🇯🇴
176 | JP-JAPAN 🇯🇵
177 | KE-KENYA 🇰🇪
178 | KG-KYRGYZSTAN 🇰🇬
179 | KH-CAMBODIA 🇰🇭
180 | KI-KIRIBATI 🇰🇮
181 | KM-COMOROS 🇰🇲
182 | KN-SAINT_KITTS_AND_NEVIS 🇰🇳
183 | KP-NORTH_KOREA 🇰🇵
184 | KR-SOUTH_KOREA 🇰🇷
185 | KW-KUWAIT 🇰🇼
186 | KY-CAYMAN_ISLANDS 🇰🇾
187 | KZ-KAZAKHSTAN 🇰🇿
188 | LA-LAOS 🇱🇦
189 | LB-LEBANON 🇱🇧
190 | LC-SAINT_LUCIA 🇱🇨
191 | LI-LIECHTENSTEIN 🇱🇮
192 | LK-SRI_LANKA 🇱🇰
193 | LR-LIBERIA 🇱🇷
194 | LS-LESOTHO 🇱🇸
195 | LT-LITHUANIA 🇱🇹
196 | LU-LUXEMBOURG 🇱🇺
197 | LV-LATVIA 🇱🇻
198 | LY-LIBYA 🇱🇾
199 | MA-MOROCCO 🇲🇦
200 | MC-MONACO 🇲🇨
201 | MD-MOLDOVA 🇲🇩
202 | ME-MONTENEGRO 🇲🇪
203 | MF-SAINT_MARTIN 🇲🇫
204 | MG-MADAGASCAR 🇲🇬
205 | MH-MARSHALL_ISLAND 🇲🇭
206 | MK-NORTH_MACEDONIA 🇲🇰
207 | ML-MALI 🇲🇱
208 | MM-MYANMAR 🇲🇲
209 | MN-MONGOLIA 🇲🇳
210 | MO-MACAO 🇲🇴
211 | MP-NORTHERN_MARIANA_ISLANDS 🇲🇵
212 | MQ-MARTINIQUE 🇲🇶
213 | MR-MAURITANIA 🇲🇷
214 | MS-MONTSERRAT 🇲🇸
215 | MT-MALTA 🇲🇹
216 | MU-MAURITIUS 🇲🇺
217 | MV-MALDIVES 🇲🇻
218 | MW-MALAWI 🇲🇼
219 | MX-MEXICO 🇲🇽
220 | MY-MALAYSIA 🇲🇾
221 | MZ-MOZAMBIQUE 🇲🇿
222 | NA-NAMIBIA 🇳🇦
223 | NC-NEW_CALEDONIA 🇳🇨
224 | NE-NIGER 🇳🇪
225 | NF-NORFOLK_ISLAND 🇳🇫
226 | NG-NIGERIA 🇳🇬
227 | NI-NICARAGUA 🇳🇮
228 | NL-NETHERLANDS 🇳🇱
229 | NO-NORWAY 🇳🇴
230 | NP-NEPAL 🇳🇵
231 | NR-NAURU 🇳🇷
232 | NU-NIUE 🇳🇺
233 | NZ-NEW_ZEALAND 🇳🇿
234 | OM-OMAN 🇴🇲
235 | PA-PANAMA 🇵🇦
236 | PE-PERU 🇵🇪
237 | PF-FRENCH_POLYNESIA 🇵🇫
238 | PG-PAPUA_NEW_GUINEA 🇵🇬
239 | PH-PHILIPPINES 🇵🇭
240 | PK-PAKISTAN 🇵🇰
241 | PL-POLAND 🇵🇱
242 | PM-SAINT_PIERRE_AND_MIQUELON 🇵🇲
243 | PN-PITCAIRN_ISLANDS 🇵🇳
244 | PR-PUERTO_RICO 🇵🇷
245 | PS-PALESTINE 🇵🇸
246 | PT-PORTUGAL 🇵🇹
247 | PW-PALAU 🇵🇼
248 | PY-PARAGUAY 🇵🇾
249 | QA-QATAR 🇶🇦
250 | RE-REUNION 🇷🇪
251 | RO-ROMANIA 🇷🇴
252 | RS-SERBIA 🇷🇸
253 | RU-RUSSIA 🇷🇺
254 | RW-RWANDA 🇷🇼
255 | SA-SAUDI_ARABIA 🇸🇦
256 | SB-SOLOMON_ISLANDS 🇸🇧
257 | SC-SEYCHELLES 🇸🇨
258 | SD-SUDAN 🇸🇩
259 | SE-SWEDEN 🇸🇪
260 | SG-SINGAPORE 🇸🇬
261 | SH-SAINT_HELENA_ASCENSION_AND_TRISTAN_DA_CUNHA 🇸🇭
262 | SI-SLOVENIA 🇸🇮
263 | SJ-SVALBARD_AND_JAN_MAYEN 🇸🇯
264 | SK-SLOVAKIA 🇸🇰
265 | SL-SIERRA_LEONE 🇸🇱
266 | SM-SAN_MARINO 🇸🇲
267 | SN-SENEGAL 🇸🇳
268 | SO-SOMALIA 🇸🇴
269 | SR-SURINAME 🇸🇷
270 | SS-SOUTH_SUDAN 🇸🇸
271 | ST-SAO_TOME_AND_PRINCE 🇸🇹
272 | SV-EL_SALVADOR 🇸🇻
273 | SX-SINT_MAARTEN 🇸🇽
274 | SY-SYRIA 🇸🇾
275 | SZ-ESWATINI 🇸🇿
276 | TC-TURKS_AND_CAICOS 🇹🇨
277 | TD-CHAD 🇹🇩
278 | TF-FRENCH_SOUTHERN_AND_ANTARCTIC_LANDS 🇹🇫
279 | TG-TOGO 🇹🇬
280 | TH-THAILAND 🇹🇭
281 | TJ-TAJIKISTAN 🇹🇯
282 | TK-TOKELAU 🇹🇰
283 | TL-TIMOR_LESTE 🇹🇱
284 | TM-TURKMENISTAN 🇹🇲
285 | TN-TUNISIA 🇹🇳
286 | TO-TONGA 🇹🇴
287 | TR-TURKEY 🇹🇷
288 | TT-TRINIDAD_AND_TOBAGO 🇹🇹
289 | TV-TUVALU 🇹🇻
290 | TW-TAIWAN 🇹🇼
291 | TZ-TANZANIA 🇹🇿
292 | UA-UKRAINE 🇺🇦
293 | UG-UGANDA 🇺🇬
294 | UM-UNITED_STATES_MINOR_OUTLYING_ISLANDS 🇺🇲
295 | US-USA 🇺🇸
296 | UY-URUGUAY 🇺🇾
297 | UZ-UZBEKISTAN 🇺🇿
298 | VA-VATICAN_CITY 🇻🇦
299 | VC-SAINT_VINCENT_AND_THE_GRENADINES 🇻🇨
300 | VE-VENEZUELA 🇻🇪
301 | VG-BRITISH_VIRGIN_ISLANDS 🇻🇬
302 | VI-US_VIRGIN_ISLANDS 🇻🇮
303 | VN-VIETNAM 🇻🇳
304 | VU-VANUATU 🇻🇺
305 | WF-WALLIS_AND_FUTUNA 🇼🇫
306 | WS-SAMOA 🇼🇸
307 | XK-KOSOVO 🇽🇰
308 | YE-YEMEN 🇾🇪
309 | YT-MAYOTTE 🇾🇹
310 | ZA-SOUTH_AFRICA 🇿🇦
311 | ZM-ZAMBIA 🇿🇲
312 | ZW-ZIMBABWE 🇿🇼
313 | """.trimIndent(),
314 | actual = Country.entries.sortedBy { it.code }.joinToString(separator = "\n") { "${it.code}-${it.name} ${it.emoji}" },
315 | )
316 | }
317 |
318 | @Test fun noDuplicates() {
319 | val unique = Country.entries.map { it.code }.toSet()
320 | assertEquals(expected = Country.entries.size, actual = unique.size)
321 | }
322 | }
323 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 | # SPDX-License-Identifier: Apache-2.0
19 | #
20 |
21 | ##############################################################################
22 | #
23 | # Gradle start up script for POSIX generated by Gradle.
24 | #
25 | # Important for running:
26 | #
27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
28 | # noncompliant, but you have some other compliant shell such as ksh or
29 | # bash, then to run this script, type that shell name before the whole
30 | # command line, like:
31 | #
32 | # ksh Gradle
33 | #
34 | # Busybox and similar reduced shells will NOT work, because this script
35 | # requires all of these POSIX shell features:
36 | # * functions;
37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
39 | # * compound commands having a testable exit status, especially «case»;
40 | # * various built-in commands including «command», «set», and «ulimit».
41 | #
42 | # Important for patching:
43 | #
44 | # (2) This script targets any POSIX shell, so it avoids extensions provided
45 | # by Bash, Ksh, etc; in particular arrays are avoided.
46 | #
47 | # The "traditional" practice of packing multiple parameters into a
48 | # space-separated string is a well documented source of bugs and security
49 | # problems, so this is (mostly) avoided, by progressively accumulating
50 | # options in "$@", and eventually passing that to Java.
51 | #
52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
54 | # see the in-line comments for details.
55 | #
56 | # There are tweaks for specific operating systems such as AIX, CygWin,
57 | # Darwin, MinGW, and NonStop.
58 | #
59 | # (3) This script is generated from the Groovy template
60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
61 | # within the Gradle project.
62 | #
63 | # You can find Gradle at https://github.com/gradle/gradle/.
64 | #
65 | ##############################################################################
66 |
67 | # Attempt to set APP_HOME
68 |
69 | # Resolve links: $0 may be a link
70 | app_path=$0
71 |
72 | # Need this for daisy-chained symlinks.
73 | while
74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
75 | [ -h "$app_path" ]
76 | do
77 | ls=$( ls -ld "$app_path" )
78 | link=${ls#*' -> '}
79 | case $link in #(
80 | /*) app_path=$link ;; #(
81 | *) app_path=$APP_HOME$link ;;
82 | esac
83 | done
84 |
85 | # This is normally unused
86 | # shellcheck disable=SC2034
87 | APP_BASE_NAME=${0##*/}
88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 |
118 |
119 | # Determine the Java command to use to start the JVM.
120 | if [ -n "$JAVA_HOME" ] ; then
121 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
122 | # IBM's JDK on AIX uses strange locations for the executables
123 | JAVACMD=$JAVA_HOME/jre/sh/java
124 | else
125 | JAVACMD=$JAVA_HOME/bin/java
126 | fi
127 | if [ ! -x "$JAVACMD" ] ; then
128 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
129 |
130 | Please set the JAVA_HOME variable in your environment to match the
131 | location of your Java installation."
132 | fi
133 | else
134 | JAVACMD=java
135 | if ! command -v java >/dev/null 2>&1
136 | then
137 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
138 |
139 | Please set the JAVA_HOME variable in your environment to match the
140 | location of your Java installation."
141 | fi
142 | fi
143 |
144 | # Increase the maximum file descriptors if we can.
145 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
146 | case $MAX_FD in #(
147 | max*)
148 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
149 | # shellcheck disable=SC2039,SC3045
150 | MAX_FD=$( ulimit -H -n ) ||
151 | warn "Could not query maximum file descriptor limit"
152 | esac
153 | case $MAX_FD in #(
154 | '' | soft) :;; #(
155 | *)
156 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
157 | # shellcheck disable=SC2039,SC3045
158 | ulimit -n "$MAX_FD" ||
159 | warn "Could not set maximum file descriptor limit to $MAX_FD"
160 | esac
161 | fi
162 |
163 | # Collect all arguments for the java command, stacking in reverse order:
164 | # * args from the command line
165 | # * the main class name
166 | # * -classpath
167 | # * -D...appname settings
168 | # * --module-path (only if needed)
169 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
170 |
171 | # For Cygwin or MSYS, switch paths to Windows format before running java
172 | if "$cygwin" || "$msys" ; then
173 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
174 |
175 | JAVACMD=$( cygpath --unix "$JAVACMD" )
176 |
177 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
178 | for arg do
179 | if
180 | case $arg in #(
181 | -*) false ;; # don't mess with options #(
182 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
183 | [ -e "$t" ] ;; #(
184 | *) false ;;
185 | esac
186 | then
187 | arg=$( cygpath --path --ignore --mixed "$arg" )
188 | fi
189 | # Roll the args list around exactly as many times as the number of
190 | # args, so each arg winds up back in the position where it started, but
191 | # possibly modified.
192 | #
193 | # NB: a `for` loop captures its iteration list before it begins, so
194 | # changing the positional parameters here affects neither the number of
195 | # iterations, nor the values presented in `arg`.
196 | shift # remove old arg
197 | set -- "$@" "$arg" # push replacement arg
198 | done
199 | fi
200 |
201 |
202 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
203 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
204 |
205 | # Collect all arguments for the java command:
206 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
207 | # and any embedded shellness will be escaped.
208 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
209 | # treated as '${Hostname}' itself on the command line.
210 |
211 | set -- \
212 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
213 | -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
214 | "$@"
215 |
216 | # Stop when "xargs" is not available.
217 | if ! command -v xargs >/dev/null 2>&1
218 | then
219 | die "xargs is not available"
220 | fi
221 |
222 | # Use "xargs" to parse quoted args.
223 | #
224 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
225 | #
226 | # In Bash we could simply go:
227 | #
228 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
229 | # set -- "${ARGS[@]}" "$@"
230 | #
231 | # but POSIX shell has neither arrays nor command substitution, so instead we
232 | # post-process each arg (as a line of input to sed) to backslash-escape any
233 | # character that might be a shell metacharacter, then use eval to reverse
234 | # that process (while maintaining the separation between arguments), and wrap
235 | # the whole thing up as a single "set" statement.
236 | #
237 | # This will of course break if any of these variables contains a newline or
238 | # an unmatched quote.
239 | #
240 |
241 | eval "set -- $(
242 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
243 | xargs -n1 |
244 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
245 | tr '\n' ' '
246 | )" '"$@"'
247 |
248 | exec "$JAVACMD" "$@"
249 |
--------------------------------------------------------------------------------
/multiplatform-locale-google-play-store/api/current.txt:
--------------------------------------------------------------------------------
1 | // Signature format: 4.0
2 | package com.vanniktech.locale.google.play.store {
3 |
4 | public enum GooglePlayStoreLocale {
5 | method public error.NonExistentClass toString();
6 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale af;
7 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale am;
8 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale ar;
9 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale az_AZ;
10 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale be;
11 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale bg;
12 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale bn_BD;
13 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale ca;
14 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale cs_CZ;
15 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale da_DK;
16 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale de_DE;
17 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale el_GR;
18 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale en_AU;
19 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale en_CA;
20 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale en_GB;
21 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale en_IN;
22 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale en_SG;
23 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale en_US;
24 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale en_ZA;
25 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale es_419;
26 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale es_ES;
27 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale es_US;
28 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale et;
29 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale eu_ES;
30 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale fa;
31 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale fa_AE;
32 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale fa_AF;
33 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale fa_IR;
34 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale fi_FI;
35 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale fil;
36 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale fr_CA;
37 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale fr_FR;
38 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale gl_ES;
39 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale gu;
40 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale hi_IN;
41 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale hr;
42 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale hu_HU;
43 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale hy_AM;
44 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale id;
45 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale is_IS;
46 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale it_IT;
47 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale iw_IL;
48 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale ja_JP;
49 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale ka_GE;
50 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale kk;
51 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale km_KH;
52 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale kn_IN;
53 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale ko_KR;
54 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale ky_KG;
55 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale lo_LA;
56 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale lt;
57 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale lv;
58 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale mk_MK;
59 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale ml_IN;
60 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale mn_MN;
61 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale mr_IN;
62 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale ms;
63 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale ms_MY;
64 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale my_MM;
65 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale ne_NP;
66 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale nl_NL;
67 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale no_NO;
68 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale pa;
69 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale pl_PL;
70 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale pt_BR;
71 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale pt_PT;
72 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale rm;
73 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale ro;
74 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale ru_RU;
75 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale si_LK;
76 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale sk;
77 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale sl;
78 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale sq;
79 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale sr;
80 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale sv_SE;
81 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale sw;
82 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale ta_IN;
83 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale te_IN;
84 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale th;
85 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale tr_TR;
86 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale uk;
87 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale ur;
88 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale vi;
89 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale zh_CN;
90 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale zh_HK;
91 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale zh_TW;
92 | enum_constant public static final com.vanniktech.locale.google.play.store.GooglePlayStoreLocale zu;
93 | }
94 |
95 | public final class GooglePlayStoreLocaleKt {
96 | method public static com.vanniktech.locale.google.play.store.GooglePlayStoreLocale? googlePlayStoreLocale(com.vanniktech.locale.Locale);
97 | }
98 |
99 | }
100 |
101 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/sample-ios/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/multiplatform-locale/src/commonMain/kotlin/com/vanniktech/locale/Language.kt:
--------------------------------------------------------------------------------
1 | package com.vanniktech.locale
2 |
3 | enum class Language(
4 | /** ISO 639-1 code - https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes */
5 | val code: String,
6 | /** [HEBREW] & [INDONESIAN] changed their identifier. We are backwards compatible and support both. */
7 | val legacyCode: String? = null,
8 | /** Territories, where this [Language] is officially spoken in. */
9 | val officialTerritories: List,
10 | /** Territories, where this [Language] is spoken in. */
11 | val otherTerritories: List,
12 | ) {
13 | ARABIC(
14 | code = "ar",
15 | officialTerritories = listOf(Country.SAUDI_ARABIA, Country.ALGERIA, Country.BAHRAIN, Country.MALI, Country.NIGER, Country.SENEGAL, Country.CHAD, Country.COMOROS, Country.DJIBOUTI, Country.EGYPT, Country.IRAQ, Country.JORDAN, Country.KUWAIT, Country.LEBANON, Country.LIBYA, Country.MAURITANIA, Country.MOROCCO, Country.OMAN, Country.QATAR, Country.SOMALIA, Country.SUDAN, Country.SYRIA, Country.TUNISIA, Country.UNITED_ARAB_EMIRATES, Country.YEMEN),
16 | otherTerritories = listOf(Country.PALESTINE, Country.SOMALIA, Country.SAHRAWI_ARAB_DEMOCRATIC_REPUBLIC, Country.TANZANIA),
17 | ),
18 | AFRIKAANS(
19 | code = "af",
20 | officialTerritories = listOf(Country.SOUTH_AFRICA),
21 | otherTerritories = listOf(Country.NAMIBIA),
22 | ),
23 | ALBANIAN(
24 | code = "sq",
25 | officialTerritories = listOf(Country.ALBANIA, Country.KOSOVO),
26 | otherTerritories = listOf(Country.NORTH_MACEDONIA, Country.MONTENEGRO),
27 | ),
28 | AMHARIC(
29 | code = "am",
30 | officialTerritories = listOf(Country.ETHIOPIA),
31 | otherTerritories = emptyList(),
32 | ),
33 | ARMENIAN(
34 | code = "hy",
35 | officialTerritories = listOf(Country.ARMENIA),
36 | otherTerritories = emptyList(),
37 | ),
38 | AZERBAIJANI(
39 | code = "az",
40 | officialTerritories = listOf(Country.AZERBAIJAN),
41 | otherTerritories = emptyList(),
42 | ),
43 | BELARUSIAN(
44 | code = "be",
45 | officialTerritories = listOf(Country.BELARUS),
46 | otherTerritories = listOf(Country.RUSSIA, Country.LITHUANIA, Country.LATVIA, Country.POLAND, Country.UKRAINE),
47 | ),
48 | BENGALI(
49 | code = "bn",
50 | officialTerritories = listOf(Country.BANGLADESH),
51 | otherTerritories = listOf(Country.INDIA),
52 | ),
53 | BOKMAL(
54 | code = "nb",
55 | officialTerritories = listOf(Country.NORWAY),
56 | otherTerritories = listOf(),
57 | ),
58 | BOSNIAN(
59 | code = "bs",
60 | officialTerritories = listOf(Country.BOSNIA_AND_HERZEGOVINA),
61 | otherTerritories = listOf(),
62 | ),
63 | BULGARIAN(
64 | code = "bg",
65 | officialTerritories = listOf(Country.BULGARIA),
66 | otherTerritories = listOf(Country.GREECE, Country.ROMANIA, Country.MOLDOVA, Country.UKRAINE),
67 | ),
68 | BURMESE(
69 | code = "my",
70 | officialTerritories = listOf(Country.MYANMAR),
71 | otherTerritories = listOf(),
72 | ),
73 | CENTRAL_KMHER(
74 | code = "km",
75 | officialTerritories = listOf(Country.CAMBODIA),
76 | otherTerritories = emptyList(),
77 | ),
78 | CHINESE(
79 | code = "zh",
80 | officialTerritories = listOf(Country.CHINA, Country.TAIWAN, Country.HONG_KONG, Country.SINGAPORE, Country.MACAO),
81 | otherTerritories = emptyList(),
82 | ),
83 | CATALAN(
84 | code = "ca",
85 | officialTerritories = listOf(Country.SPAIN),
86 | otherTerritories = listOf(Country.ANDORRA),
87 | ),
88 | CZECH(
89 | code = "cs",
90 | officialTerritories = listOf(Country.CZECHIA),
91 | otherTerritories = listOf(Country.POLAND, Country.SERBIA, Country.UKRAINE, Country.SLOVAKIA, Country.BULGARIA, Country.AUSTRIA),
92 | ),
93 | CROATIAN(
94 | code = "hr",
95 | officialTerritories = listOf(Country.CROATIA),
96 | otherTerritories = listOf(Country.AUSTRIA, Country.ITALY, Country.SERBIA),
97 | ),
98 | DANISH(
99 | code = "da",
100 | officialTerritories = listOf(Country.DENMARK, Country.GREENLAND, Country.FAROE_ISLANDS),
101 | otherTerritories = emptyList(),
102 | ),
103 | DUTCH(
104 | code = "nl",
105 | officialTerritories = listOf(Country.NETHERLANDS, Country.BELGIUM, Country.SURINAME, Country.ARUBA, Country.CURACAO, Country.SINT_MAARTEN),
106 | otherTerritories = emptyList(),
107 | ),
108 | ENGLISH(
109 | code = "en",
110 | officialTerritories = listOf(Country.USA, Country.CANADA, Country.AUSTRALIA, Country.ENGLAND, Country.NEW_ZEALAND, Country.CHRISTMAS_ISLAND, Country.COCOS_ISLANDS, Country.TOKELAU, Country.BRITISH_INDIAN_OCEAN_TERRITORY, Country.GUERNSEY, Country.MONTSERRAT),
111 | otherTerritories = listOf(Country.BAHRAIN, Country.BANGLADESH, Country.BRUNEI, Country.CYPRUS, Country.ERITREA, Country.ETHIOPIA, Country.GREENLAND, Country.ICELAND, Country.ISRAEL, Country.JORDAN, Country.KUWAIT, Country.MALAYSIA, Country.MALDIVES, Country.MYANMAR, Country.QATAR, Country.SRI_LANKA, Country.UNITED_ARAB_EMIRATES),
112 | ),
113 | ESTONIAN(
114 | code = "et",
115 | officialTerritories = listOf(Country.ESTONIA),
116 | otherTerritories = emptyList(),
117 | ),
118 | FARSI(
119 | code = "fa",
120 | officialTerritories = listOf(Country.IRAN),
121 | otherTerritories = listOf(Country.AFGHANISTAN, Country.BAHRAIN, Country.IRAQ, Country.OMAN, Country.YEMEN, Country.UNITED_ARAB_EMIRATES),
122 | ),
123 | FILIPINO(
124 | code = "fil",
125 | officialTerritories = listOf(Country.PHILIPPINES),
126 | otherTerritories = emptyList(),
127 | ),
128 | FINNISH(
129 | code = "fi",
130 | officialTerritories = listOf(Country.FINLAND, Country.SWEDEN),
131 | otherTerritories = emptyList(),
132 | ),
133 | FRENCH(
134 | code = "fr",
135 | officialTerritories = listOf(Country.FRANCE, Country.CANADA, Country.BELGIUM, Country.BENIN, Country.BURKINA_FASO, Country.BURUNDI, Country.CAMEROON, Country.CHAD, Country.COTE_DIVOIRE, Country.DEMOCRATIC_REPUBLIC_OF_CONGO, Country.DJIBOUTI, Country.EQUATORIAL_GUINEA, Country.HAITI, Country.LUXEMBOURG, Country.MADAGASCAR, Country.MALI, Country.MONACO, Country.NIGER, Country.RWANDA, Country.SENEGAL, Country.SEYCHELLES, Country.SWITZERLAND, Country.TOGO, Country.VANUATU),
136 | otherTerritories = emptyList(),
137 | ),
138 | GEORGIAN(
139 | code = "ka",
140 | officialTerritories = listOf(Country.GEORGIA),
141 | otherTerritories = listOf(Country.TURKEY, Country.IRAN, Country.RUSSIA),
142 | ),
143 | GERMAN(
144 | code = "de",
145 | officialTerritories = listOf(Country.GERMANY, Country.AUSTRIA, Country.BELGIUM, Country.LUXEMBOURG, Country.SWITZERLAND, Country.LIECHTENSTEIN),
146 | otherTerritories = emptyList(),
147 | ),
148 | GREEK(
149 | code = "el",
150 | officialTerritories = listOf(Country.GREECE, Country.CYPRUS),
151 | otherTerritories = emptyList(),
152 | ),
153 | GUJARATI(
154 | code = "gu",
155 | officialTerritories = listOf(Country.INDIA, Country.SRI_LANKA, Country.SINGAPORE),
156 | otherTerritories = listOf(Country.MALAYSIA, Country.MAURITIUS, Country.FIJI, Country.SOUTH_AFRICA),
157 | ),
158 | HEBREW(
159 | code = "he",
160 | legacyCode = "iw",
161 | officialTerritories = listOf(Country.ISRAEL),
162 | otherTerritories = emptyList(),
163 | ),
164 | ICELANDIC(
165 | code = "is",
166 | officialTerritories = listOf(Country.ICELAND),
167 | otherTerritories = emptyList(),
168 | ),
169 | HINDI(
170 | code = "hi",
171 | officialTerritories = listOf(Country.INDIA),
172 | otherTerritories = listOf(Country.MAURITIUS, Country.FIJI, Country.SURINAME, Country.GUYANA, Country.TRINIDAD_AND_TOBAGO, Country.NEPAL),
173 | ),
174 | HUNGARIAN(
175 | code = "hu",
176 | officialTerritories = listOf(Country.HUNGARY),
177 | otherTerritories = listOf(Country.ROMANIA, Country.SLOVAKIA, Country.SERBIA, Country.AUSTRIA, Country.SLOVENIA),
178 | ),
179 | INDONESIAN(
180 | code = "id",
181 | legacyCode = "in",
182 | officialTerritories = listOf(Country.INDONESIA),
183 | otherTerritories = emptyList(),
184 | ),
185 | IRISH(
186 | code = "ga",
187 | officialTerritories = listOf(Country.IRELAND),
188 | otherTerritories = listOf(),
189 | ),
190 | ITALIAN(
191 | code = "it",
192 | officialTerritories = listOf(Country.ITALY, Country.SAN_MARINO, Country.SWITZERLAND, Country.VATICAN_CITY),
193 | otherTerritories = listOf(Country.CROATIA, Country.SLOVENIA, Country.AUSTRIA),
194 | ),
195 | JAPANESE(
196 | code = "ja",
197 | officialTerritories = listOf(Country.JAPAN),
198 | otherTerritories = emptyList(),
199 | ),
200 | KANNADA(
201 | code = "kn",
202 | officialTerritories = listOf(Country.INDIA),
203 | otherTerritories = emptyList(),
204 | ),
205 | KOREAN(
206 | code = "ko",
207 | officialTerritories = listOf(Country.SOUTH_KOREA, Country.NORTH_KOREA),
208 | otherTerritories = emptyList(),
209 | ),
210 | LAO(
211 | code = "lo",
212 | officialTerritories = listOf(Country.LAOS),
213 | otherTerritories = listOf(Country.THAILAND),
214 | ),
215 | LATVIAN(
216 | code = "lv",
217 | officialTerritories = listOf(Country.LATVIA),
218 | otherTerritories = emptyList(),
219 | ),
220 | LITHUANIAN(
221 | code = "lt",
222 | officialTerritories = listOf(Country.LITHUANIA),
223 | otherTerritories = emptyList(),
224 | ),
225 | MACEDONIAN(
226 | code = "mk",
227 | officialTerritories = listOf(Country.NORTH_MACEDONIA),
228 | otherTerritories = emptyList(),
229 | ),
230 | MALAY(
231 | code = "ms",
232 | officialTerritories = listOf(Country.MALAYSIA, Country.BRUNEI, Country.INDONESIA, Country.SINGAPORE),
233 | otherTerritories = emptyList(),
234 | ),
235 | MALAYALAM(
236 | code = "ml",
237 | officialTerritories = listOf(Country.INDIA),
238 | otherTerritories = emptyList(),
239 | ),
240 | MARATHI(
241 | code = "mr",
242 | officialTerritories = listOf(Country.INDIA),
243 | otherTerritories = emptyList(),
244 | ),
245 | NORWEGIAN(
246 | code = "no",
247 | officialTerritories = listOf(Country.NORWAY),
248 | otherTerritories = emptyList(),
249 | ),
250 | OROMO(
251 | code = "om",
252 | officialTerritories = listOf(Country.ETHIOPIA),
253 | otherTerritories = listOf(Country.KENYA, Country.SOMALIA),
254 | ),
255 | POLISH(
256 | code = "pl",
257 | officialTerritories = listOf(Country.POLAND),
258 | otherTerritories = emptyList(),
259 | ),
260 | PORTUGUESE(
261 | code = "pt",
262 | officialTerritories = listOf(Country.PORTUGAL, Country.BRAZIL, Country.ANGOLA, Country.MOZAMBIQUE),
263 | otherTerritories = listOf(Country.GUINEA_BISSAU, Country.CAPE_VERDE, Country.SAO_TOME_AND_PRINCE, Country.MACAO),
264 | ),
265 | ROMANIAN(
266 | code = "ro",
267 | officialTerritories = listOf(Country.ROMANIA, Country.MOLDOVA),
268 | otherTerritories = emptyList(),
269 | ),
270 | RUSSIAN(
271 | code = "ru",
272 | officialTerritories = listOf(Country.RUSSIA, Country.BELARUS, Country.KAZAKHSTAN, Country.KYRGYZSTAN),
273 | otherTerritories = listOf(Country.AZERBAIJAN, Country.ESTONIA, Country.GEORGIA, Country.LATVIA, Country.UKRAINE, Country.LITHUANIA, Country.MOLDOVA, Country.TAJIKISTAN, Country.TURKMENISTAN, Country.UZBEKISTAN, Country.ISRAEL),
274 | ),
275 | SERBIAN(
276 | code = "sr",
277 | officialTerritories = listOf(Country.SERBIA),
278 | otherTerritories = listOf(Country.CROATIA, Country.BOSNIA_AND_HERZEGOVINA, Country.MONTENEGRO),
279 | ),
280 | SLOVAK(
281 | code = "sk",
282 | officialTerritories = listOf(Country.SLOVAKIA),
283 | otherTerritories = listOf(Country.SERBIA, Country.CZECHIA, Country.HUNGARY, Country.POLAND, Country.ROMANIA, Country.UKRAINE),
284 | ),
285 | SLOVENIAN(
286 | code = "sl",
287 | officialTerritories = listOf(Country.SLOVENIA),
288 | otherTerritories = listOf(Country.AUSTRIA, Country.ITALY),
289 | ),
290 | SOMALI(
291 | code = "so",
292 | officialTerritories = listOf(Country.SOMALIA),
293 | otherTerritories = listOf(Country.DJIBOUTI, Country.ETHIOPIA, Country.KENYA),
294 | ),
295 | SPANISH(
296 | code = "es",
297 | officialTerritories = listOf(Country.SPAIN, Country.MEXICO, Country.COLOMBIA, Country.ARGENTINA, Country.CHILE, Country.NICARAGUA, Country.URUGUAY, Country.EQUATORIAL_GUINEA, Country.PANAMA, Country.COSTA_RICA, Country.EL_SALVADOR, Country.PARAGUAY, Country.HONDURAS, Country.DOMINICAN_REPUBLIC, Country.CUBA, Country.BOLIVIA, Country.ECUADOR, Country.GUATEMALA, Country.VENEZUELA, Country.PERU, Country.PARAGUAY, Country.BOLIVIA, Region.CANARY_ISLANDS, Region.LATIN_AMERICA),
298 | otherTerritories = listOf(Country.USA, Country.BELIZE, Country.ANDORRA, Country.GIBRALTAR),
299 | ),
300 | SWAHILI(
301 | code = "sw",
302 | officialTerritories = listOf(Country.TANZANIA, Country.KENYA, Country.UGANDA, Country.DEMOCRATIC_REPUBLIC_OF_CONGO),
303 | otherTerritories = listOf(Country.RWANDA, Country.BURUNDI, Country.SOMALIA, Country.MOZAMBIQUE, Country.MALAWI, Country.ZAMBIA, Country.COMOROS, Country.SOUTH_SUDAN),
304 | ),
305 | SWEDISH(
306 | code = "sv",
307 | officialTerritories = listOf(Country.SWEDEN, Country.FINLAND),
308 | otherTerritories = listOf(Country.ESTONIA, Country.LATVIA),
309 | ),
310 | TAMIL(
311 | code = "ta",
312 | officialTerritories = listOf(Country.INDIA),
313 | otherTerritories = emptyList(),
314 | ),
315 | TAGALOG(
316 | code = "tl",
317 | officialTerritories = listOf(Country.PHILIPPINES),
318 | otherTerritories = emptyList(),
319 | ),
320 | TELUGU(
321 | code = "te",
322 | officialTerritories = listOf(Country.INDIA),
323 | otherTerritories = emptyList(),
324 | ),
325 | THAI(
326 | code = "th",
327 | officialTerritories = listOf(Country.THAILAND),
328 | otherTerritories = emptyList(),
329 | ),
330 | TURKISH(
331 | code = "tr",
332 | officialTerritories = listOf(Country.TURKEY),
333 | otherTerritories = emptyList(),
334 | ),
335 | UKRAINIAN(
336 | code = "uk",
337 | officialTerritories = listOf(Country.UKRAINE),
338 | otherTerritories = listOf(Country.KAZAKHSTAN, Country.MOLDOVA, Country.POLAND, Country.ROMANIA, Country.LITHUANIA, Country.SLOVAKIA),
339 | ),
340 | URDU(
341 | code = "ur",
342 | officialTerritories = listOf(Country.PAKISTAN),
343 | otherTerritories = listOf(),
344 | ),
345 | UZBEK(
346 | code = "uz",
347 | officialTerritories = listOf(Country.UZBEKISTAN),
348 | otherTerritories = listOf(Country.KAZAKHSTAN, Country.KYRGYZSTAN, Country.TAJIKISTAN, Country.TURKMENISTAN),
349 | ),
350 | VIETNAMESE(
351 | code = "vi",
352 | officialTerritories = listOf(Country.VIETNAM),
353 | otherTerritories = emptyList(),
354 | ),
355 | ;
356 |
357 | val defaultCountry = officialTerritories.first()
358 |
359 | fun displayName() = commonDisplayName()
360 |
361 | companion object {
362 | fun from(identifier: String): Language = requireNotNull(fromOrNull(identifier)) { "Can't get language from $identifier" }
363 |
364 | fun fromOrNull(identifier: String?): Language? = entries.firstOrNull { it.code.equals(identifier, ignoreCase = true) || it.legacyCode?.equals(identifier, ignoreCase = true) == true }
365 |
366 | fun fromLocale(locale: String): Language = requireNotNull(fromLocaleOrNull(locale)) { "Can't get language from $locale" }
367 |
368 | fun fromLocaleOrNull(locale: String?): Language? = fromOrNull(localeComponents(locale)?.language)
369 | }
370 | }
371 |
372 | /** Returns the display name of [Language] in the current language. */
373 | internal expect fun Language.commonDisplayName(): String
374 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | Version 0.10.0 *(In development)*
4 | ---------------------------------
5 |
6 | Version 0.9.0 *(2025-01-19)*
7 | ----------------------------
8 |
9 | - API: Country Add BOUVET_ISLAND [\#243](https://github.com/vanniktech/multiplatform-locale/pull/243) ([vanniktech](https://github.com/vanniktech))
10 | - API: Country Add UNITED_STATES_MINOR_OUTLYING_ISLANDS [\#244](https://github.com/vanniktech/multiplatform-locale/pull/244) ([vanniktech](https://github.com/vanniktech))
11 | - API: Country.ARUBA Change Continent from SOUTH_AMERICA to NORTH_AMERICA [\#225](https://github.com/vanniktech/multiplatform-locale/pull/225) ([vanniktech](https://github.com/vanniktech))
12 | - API: Country.AZERBAIJAN remove EUROPE continent. [\#226](https://github.com/vanniktech/multiplatform-locale/pull/226) ([vanniktech](https://github.com/vanniktech))
13 | - API: Country.BONAIRE Change Continent from SOUTH_AMERICA to NORTH_AMERICA [\#227](https://github.com/vanniktech/multiplatform-locale/pull/227) ([vanniktech](https://github.com/vanniktech))
14 | - API: Country.CAYMAN_ISLANDS fix Calling Code. [\#228](https://github.com/vanniktech/multiplatform-locale/pull/228) ([vanniktech](https://github.com/vanniktech))
15 | - API: Country.CURACAO Change Continent from SOUTH_AMERICA to NORTH_AMERICA [\#232](https://github.com/vanniktech/multiplatform-locale/pull/232) ([vanniktech](https://github.com/vanniktech))
16 | - API: Country.CYPRUS remove EUROPE continent. [\#242](https://github.com/vanniktech/multiplatform-locale/pull/242) ([vanniktech](https://github.com/vanniktech))
17 | - API: Country.DOMINICAN_REPUBLIC fix Calling Code. [\#229](https://github.com/vanniktech/multiplatform-locale/pull/229) ([vanniktech](https://github.com/vanniktech))
18 | - API: Country.FRENCH_SOUTHERN_AND_ANTARCTIC_LANDS fix Calling Code. [\#241](https://github.com/vanniktech/multiplatform-locale/pull/241) ([vanniktech](https://github.com/vanniktech))
19 | - API: Country.FRENCH_SOUTHERN_AND_ANTARCTIC_LANDS remove ANTARCTICA continent. [\#246](https://github.com/vanniktech/multiplatform-locale/pull/246) ([vanniktech](https://github.com/vanniktech))
20 | - API: Country.GEORGIA remove EUROPE continent. [\#230](https://github.com/vanniktech/multiplatform-locale/pull/230) ([vanniktech](https://github.com/vanniktech))
21 | - API: Country.JAMAICA fix Calling Code. [\#231](https://github.com/vanniktech/multiplatform-locale/pull/231) ([vanniktech](https://github.com/vanniktech))
22 | - API: Country.KAZAKHSTAN fix Calling Code. [\#240](https://github.com/vanniktech/multiplatform-locale/pull/240) ([vanniktech](https://github.com/vanniktech))
23 | - API: Country.KAZAKHSTAN remove EUROPE continent. [\#245](https://github.com/vanniktech/multiplatform-locale/pull/245) ([vanniktech](https://github.com/vanniktech))
24 | - API: Country.KOSOVO fix code3. [\#248](https://github.com/vanniktech/multiplatform-locale/pull/248) ([vanniktech](https://github.com/vanniktech))
25 | - API: Country.MAYOTTE Change Continent from ASIA to AFRICA. [\#233](https://github.com/vanniktech/multiplatform-locale/pull/233) ([vanniktech](https://github.com/vanniktech))
26 | - API: Country.PITCAIRN_ISLANDS fix Calling Code. [\#234](https://github.com/vanniktech/multiplatform-locale/pull/234) ([vanniktech](https://github.com/vanniktech))
27 | - API: Country.PUERTO_RICO fix Calling Code. [\#235](https://github.com/vanniktech/multiplatform-locale/pull/235) ([vanniktech](https://github.com/vanniktech))
28 | - API: Country.RUSSIA remove ASIA continent. [\#236](https://github.com/vanniktech/multiplatform-locale/pull/236) ([vanniktech](https://github.com/vanniktech))
29 | - API: Country.SINT_MAARTEN fix Calling Code. [\#237](https://github.com/vanniktech/multiplatform-locale/pull/237) ([vanniktech](https://github.com/vanniktech))
30 | - API: Country.TRINIDAD_AND_TOBAGO Change Continent from SOUTH_AMERICA to NORTH_AMERICA [\#239](https://github.com/vanniktech/multiplatform-locale/pull/239) ([vanniktech](https://github.com/vanniktech))
31 | - API: Country.TURKEY remove ASIA continent. [\#238](https://github.com/vanniktech/multiplatform-locale/pull/238) ([vanniktech](https://github.com/vanniktech))
32 | - Breaking: Continent is only available on Country and limited to one. [\#256](https://github.com/vanniktech/multiplatform-locale/pull/256) ([vanniktech](https://github.com/vanniktech))
33 | - Breaking: Extract AppleAppStoreLocale into its own multiplatform-locale-apple-app-store module. [\#220](https://github.com/vanniktech/multiplatform-locale/pull/220) ([vanniktech](https://github.com/vanniktech))
34 | - Breaking: Extract GooglePlayStoreLocale into its own multiplatform-locale-google-play-store module. [\#218](https://github.com/vanniktech/multiplatform-locale/pull/218) ([vanniktech](https://github.com/vanniktech))
35 | - Breaking: Move displayName() extension function to Language/Territory type. [\#217](https://github.com/vanniktech/multiplatform-locale/pull/217) ([vanniktech](https://github.com/vanniktech))
36 | - Feature: New multiplatform-locale-all module that has all the modules bundled. [\#219](https://github.com/vanniktech/multiplatform-locale/pull/219) ([vanniktech](https://github.com/vanniktech))
37 | - Technical: Generate Country Enum entries based on https://github.com/countries/countries [\#249](https://github.com/vanniktech/multiplatform-locale/pull/249) ([vanniktech](https://github.com/vanniktech))
38 | - Technical: Kotlin remove deprecated Binary MemoryModel flags. [\#250](https://github.com/vanniktech/multiplatform-locale/pull/250) ([vanniktech](https://github.com/vanniktech))
39 | - Technical: Remove deprecated embedBitcode option. [\#247](https://github.com/vanniktech/multiplatform-locale/pull/247) ([vanniktech](https://github.com/vanniktech))
40 | - Technical: Update Kotlin to 2.1.0 [\#222](https://github.com/vanniktech/multiplatform-locale/pull/222) ([vanniktech](https://github.com/vanniktech))
41 |
42 | Version 0.8.0 *(2024-08-02)*
43 | ----------------------------
44 |
45 | - API: Language add Filipino. [\#178](https://github.com/vanniktech/multiplatform-locale/pull/178) ([vanniktech](https://github.com/vanniktech))
46 | - API: Language add Icelandic. [\#191](https://github.com/vanniktech/multiplatform-locale/pull/191) ([vanniktech](https://github.com/vanniktech))
47 | - Breaking: Sealed Territory interface with a Country and Region implementation to support for instance European Union and have a better separation. [\#197](https://github.com/vanniktech/multiplatform-locale/pull/197) ([vanniktech](https://github.com/vanniktech))
48 | - Bug fix: In Macao Chinese is also spoken. [\#174](https://github.com/vanniktech/multiplatform-locale/pull/174) ([vanniktech](https://github.com/vanniktech))
49 | - Technical: Automatically generate Country\#emoji based on the country code. [\#193](https://github.com/vanniktech/multiplatform-locale/pull/193) ([vanniktech](https://github.com/vanniktech))
50 | - Technical: Use Kotlin's entries property on Enums. [\#192](https://github.com/vanniktech/multiplatform-locale/pull/192) ([vanniktech](https://github.com/vanniktech))
51 | - Update kotlin monorepo to v2 \(major\) [\#179](https://github.com/vanniktech/multiplatform-locale/pull/179) ([renovate[bot]](https://github.com/apps/renovate))
52 |
53 | Version 0.7.0 *(2024-03-29)*
54 | ----------------------------
55 |
56 | - API: Language add Telugu. [\#145](https://github.com/vanniktech/multiplatform-locale/pull/145) ([vanniktech](https://github.com/vanniktech))
57 | - Fix Emoji flag for Country.COTE\_DIVOIRE. [\#142](https://github.com/vanniktech/multiplatform-locale/pull/142) ([vanniktech](https://github.com/vanniktech))
58 | - Fix Emoji flag for Country.PERU [\#159](https://github.com/vanniktech/multiplatform-locale/pull/159) ([vanniktech](https://github.com/vanniktech))
59 | - Update kotlin monorepo to v1.9.23 [\#155](https://github.com/vanniktech/multiplatform-locale/pull/155) ([renovate[bot]](https://github.com/apps/renovate))
60 |
61 | Version 0.6.0 *(2023-12-11)*
62 | ----------------------------
63 |
64 | - API: Add list of Continent\(s\) to each Country. [\#134](https://github.com/vanniktech/multiplatform-locale/pull/134) ([vanniktech](https://github.com/vanniktech))
65 | - API: Language add Amharic. [\#129](https://github.com/vanniktech/multiplatform-locale/pull/129) ([vanniktech](https://github.com/vanniktech))
66 | - API: Language add Central Kmher. [\#128](https://github.com/vanniktech/multiplatform-locale/pull/128) ([vanniktech](https://github.com/vanniktech))
67 | - API: Language add Marathi. [\#116](https://github.com/vanniktech/multiplatform-locale/pull/116) ([vanniktech](https://github.com/vanniktech))
68 | - API: Language add Tamil. [\#112](https://github.com/vanniktech/multiplatform-locale/pull/112) ([vanniktech](https://github.com/vanniktech))
69 | - API: Language add Urdu. [\#110](https://github.com/vanniktech/multiplatform-locale/pull/110) ([vanniktech](https://github.com/vanniktech))
70 | - Technical: Target Android 34. [\#133](https://github.com/vanniktech/multiplatform-locale/pull/133) ([vanniktech](https://github.com/vanniktech))
71 | - Technical: Update Kotlin to 1.9.20 & ktlint to 0.50.0 [\#103](https://github.com/vanniktech/multiplatform-locale/pull/103) ([vanniktech](https://github.com/vanniktech))
72 |
73 | Version 0.5.0 *(2023-08-28)*
74 | ----------------------------
75 |
76 | - API: Country add French Southern and Antartic Islands. [\#100](https://github.com/vanniktech/multiplatform-locale/pull/100) ([vanniktech](https://github.com/vanniktech))
77 | - API: Country add Heard Island and McDonald Islands. [\#101](https://github.com/vanniktech/multiplatform-locale/pull/101) ([vanniktech](https://github.com/vanniktech))
78 | - API: Country gets code3 property \(ISO 3166-1 alpha-3 code\) [\#99](https://github.com/vanniktech/multiplatform-locale/pull/99) ([vanniktech](https://github.com/vanniktech))
79 | - API: Language add Belarusian. [\#76](https://github.com/vanniktech/multiplatform-locale/pull/76) ([vanniktech](https://github.com/vanniktech))
80 | - API: Language add Malayalam. [\#79](https://github.com/vanniktech/multiplatform-locale/pull/79) ([vanniktech](https://github.com/vanniktech))
81 | - API: Language add Tagalog. [\#102](https://github.com/vanniktech/multiplatform-locale/pull/102) ([vanniktech](https://github.com/vanniktech))
82 |
83 | Version 0.4.0 *(2022-05-14)*
84 | ----------------------------
85 |
86 | - API: Add missing countries \(SH, MF, PM, GS & SJ\) [\#71](https://github.com/vanniktech/multiplatform-locale/pull/71) ([vanniktech](https://github.com/vanniktech))
87 | - API: Country - add calling codes list. [\#72](https://github.com/vanniktech/multiplatform-locale/pull/72) ([vanniktech](https://github.com/vanniktech))
88 | - Kotlin: Use Android Source Set Layout Version 2. [\#63](https://github.com/vanniktech/multiplatform-locale/pull/63) ([vanniktech](https://github.com/vanniktech))
89 | - Language: Add Armenian. [\#30](https://github.com/vanniktech/multiplatform-locale/pull/30) ([vanniktech](https://github.com/vanniktech))
90 | - Language: Add Azerbaijani. [\#39](https://github.com/vanniktech/multiplatform-locale/pull/39) ([vanniktech](https://github.com/vanniktech))
91 | - Language: Add Bokmal. [\#68](https://github.com/vanniktech/multiplatform-locale/pull/68) ([vanniktech](https://github.com/vanniktech))
92 | - Language: Add Burmese. [\#49](https://github.com/vanniktech/multiplatform-locale/pull/49) ([vanniktech](https://github.com/vanniktech))
93 | - Language: Add Catalan. [\#62](https://github.com/vanniktech/multiplatform-locale/pull/62) ([vanniktech](https://github.com/vanniktech))
94 | - Language: Add Croatian. [\#32](https://github.com/vanniktech/multiplatform-locale/pull/32) ([vanniktech](https://github.com/vanniktech))
95 | - Language: Add Irish. [\#53](https://github.com/vanniktech/multiplatform-locale/pull/53) ([vanniktech](https://github.com/vanniktech))
96 | - Language: Add Uzbek. [\#58](https://github.com/vanniktech/multiplatform-locale/pull/58) ([vanniktech](https://github.com/vanniktech))
97 |
98 | Version 0.3.0 *(2022-12-20)*
99 | ----------------------------
100 |
101 | - Language: Add Farsi. [\#29](https://github.com/vanniktech/multiplatform-locale/pull/29) ([vanniktech](https://github.com/vanniktech))
102 | - Gradle: Fix POM License. [\#28](https://github.com/vanniktech/multiplatform-locale/pull/28) ([vanniktech](https://github.com/vanniktech))
103 | - Fix broken Podspec symlink. [\#27](https://github.com/vanniktech/multiplatform-locale/pull/27) ([vanniktech](https://github.com/vanniktech))
104 | - Language: Add Malay. [\#26](https://github.com/vanniktech/multiplatform-locale/pull/26) ([vanniktech](https://github.com/vanniktech))
105 | - Language: Add Thai. [\#25](https://github.com/vanniktech/multiplatform-locale/pull/25) ([vanniktech](https://github.com/vanniktech))
106 | - Language: Add Hindi & Gujarati. [\#22](https://github.com/vanniktech/multiplatform-locale/pull/22) ([vanniktech](https://github.com/vanniktech))
107 | - Gradle: Set Jvm Toolchain to 11. [\#21](https://github.com/vanniktech/multiplatform-locale/pull/21) ([vanniktech](https://github.com/vanniktech))
108 | - API: Languages\#currentLanguageCode which returns the current ISO 639-1 language code. [\#19](https://github.com/vanniktech/multiplatform-locale/pull/19) ([vanniktech](https://github.com/vanniktech))
109 | - API: Countries\#currentCountryCode which returns the current optional ISO 3166-1 alpha-2 country code. [\#18](https://github.com/vanniktech/multiplatform-locale/pull/18) ([vanniktech](https://github.com/vanniktech))
110 | - Locale: Fix parsing of strings like 'ar\_EG\_\#u-nu-latn' [\#14](https://github.com/vanniktech/multiplatform-locale/pull/14) ([vanniktech](https://github.com/vanniktech))
111 | - Behavior Change: Locale\#fromAndroidValuesDirectoryNameOrNull don't require values prefix. [\#12](https://github.com/vanniktech/multiplatform-locale/pull/12) ([vanniktech](https://github.com/vanniktech))
112 |
113 | Version 0.2.0 *(2022-11-08)*
114 | ----------------------------
115 |
116 | - API: Rename Country\#identifier to Country\#code. [\#11](https://github.com/vanniktech/multiplatform-locale/pull/11) ([vanniktech](https://github.com/vanniktech))
117 | - API: Rename Language\#identifier to Language\#code. [\#10](https://github.com/vanniktech/multiplatform-locale/pull/10) ([vanniktech](https://github.com/vanniktech))
118 | - API: Remove inferDefaultCountry overload in Locale from methods. [\#9](https://github.com/vanniktech/multiplatform-locale/pull/9) ([vanniktech](https://github.com/vanniktech))
119 | - API: Locale\#fromAndroidValuesDirectoryName function. [\#8](https://github.com/vanniktech/multiplatform-locale/pull/8) ([vanniktech](https://github.com/vanniktech))
120 | - API: Language rename FINISH to FINNISH \(fixing a typo\) [\#7](https://github.com/vanniktech/multiplatform-locale/pull/7) ([vanniktech](https://github.com/vanniktech))
121 | - Behavior Change: Language uses ISO 639-1 code with backwards compatible support for Hebrew & Indonesian. [\#6](https://github.com/vanniktech/multiplatform-locale/pull/6) ([vanniktech](https://github.com/vanniktech))
122 | - API: Language\#from & Language\#fromLocale. [\#5](https://github.com/vanniktech/multiplatform-locale/pull/5) ([vanniktech](https://github.com/vanniktech))
123 | - Behavior Change: Locale\#googlePlayStoreLocale & Locale\#appleAppStoreLocale prefer Locale from Language\#defaultCountry in case there are multiple options. [\#4](https://github.com/vanniktech/multiplatform-locale/pull/4) ([vanniktech](https://github.com/vanniktech))
124 | - Behavior Change: Locale\#googlePlayStoreLocale & Locale\#appleAppStoreLocale will return a Locale if countries mismatch but language is the same. [\#3](https://github.com/vanniktech/multiplatform-locale/pull/3) ([vanniktech](https://github.com/vanniktech))
125 | - API: Locale is now Comparable. [\#2](https://github.com/vanniktech/multiplatform-locale/pull/2) ([vanniktech](https://github.com/vanniktech))
126 | - API: Locale.fromAndroidValuesDirectoryNameOrNull [\#1](https://github.com/vanniktech/multiplatform-locale/pull/1) ([vanniktech](https://github.com/vanniktech))
127 |
128 | Version 0.1.0 *(2022-11-07)*
129 | ----------------------------
130 |
131 | - Initial release
132 |
--------------------------------------------------------------------------------
/sample-ios/ios.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 55;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 850D4FB228CCEBA100714308 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 850D4FB128CCEBA100714308 /* App.swift */; };
11 | 850D4FB628CCEBA100714308 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 850D4FB528CCEBA100714308 /* Assets.xcassets */; };
12 | 850D4FB928CCEBA100714308 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 850D4FB828CCEBA100714308 /* Preview Assets.xcassets */; };
13 | D65BB7D28364C04EC850180D /* Pods_ios.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93C0936F297D4B91B3ABA725 /* Pods_ios.framework */; };
14 | /* End PBXBuildFile section */
15 |
16 | /* Begin PBXFileReference section */
17 | 208331B5D6E6A7716D6C289D /* Pods-BlurHash.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BlurHash.release.xcconfig"; path = "Target Support Files/Pods-BlurHash/Pods-BlurHash.release.xcconfig"; sourceTree = ""; };
18 | 6AFCE7532F78DBD821C8E78D /* Pods-BlurHash.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BlurHash.debug.xcconfig"; path = "Target Support Files/Pods-BlurHash/Pods-BlurHash.debug.xcconfig"; sourceTree = ""; };
19 | 850D4FAE28CCEBA100714308 /* ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ios.app; sourceTree = BUILT_PRODUCTS_DIR; };
20 | 850D4FB128CCEBA100714308 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = ""; };
21 | 850D4FB528CCEBA100714308 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
22 | 850D4FB828CCEBA100714308 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; };
23 | 8F886CA92368476133371299 /* Pods-ios.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios.debug.xcconfig"; path = "Target Support Files/Pods-ios/Pods-ios.debug.xcconfig"; sourceTree = ""; };
24 | 93C0936F297D4B91B3ABA725 /* Pods_ios.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ios.framework; sourceTree = BUILT_PRODUCTS_DIR; };
25 | E8CBC299A962EF4A7EF2E9D2 /* Pods-ios.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios.release.xcconfig"; path = "Target Support Files/Pods-ios/Pods-ios.release.xcconfig"; sourceTree = ""; };
26 | /* End PBXFileReference section */
27 |
28 | /* Begin PBXFrameworksBuildPhase section */
29 | 850D4FAB28CCEBA100714308 /* Frameworks */ = {
30 | isa = PBXFrameworksBuildPhase;
31 | buildActionMask = 2147483647;
32 | files = (
33 | D65BB7D28364C04EC850180D /* Pods_ios.framework in Frameworks */,
34 | );
35 | runOnlyForDeploymentPostprocessing = 0;
36 | };
37 | /* End PBXFrameworksBuildPhase section */
38 |
39 | /* Begin PBXGroup section */
40 | 2D6FE175FA70558B6EE8AE2B /* Frameworks */ = {
41 | isa = PBXGroup;
42 | children = (
43 | 93C0936F297D4B91B3ABA725 /* Pods_ios.framework */,
44 | );
45 | name = Frameworks;
46 | sourceTree = "";
47 | };
48 | 850D4FA528CCEBA100714308 = {
49 | isa = PBXGroup;
50 | children = (
51 | 850D4FB028CCEBA100714308 /* ios */,
52 | 850D4FAF28CCEBA100714308 /* Products */,
53 | 9BDC6B73A6A1A714F2D6297C /* Pods */,
54 | 2D6FE175FA70558B6EE8AE2B /* Frameworks */,
55 | );
56 | sourceTree = "";
57 | };
58 | 850D4FAF28CCEBA100714308 /* Products */ = {
59 | isa = PBXGroup;
60 | children = (
61 | 850D4FAE28CCEBA100714308 /* ios.app */,
62 | );
63 | name = Products;
64 | sourceTree = "";
65 | };
66 | 850D4FB028CCEBA100714308 /* ios */ = {
67 | isa = PBXGroup;
68 | children = (
69 | 850D4FB128CCEBA100714308 /* App.swift */,
70 | 850D4FB528CCEBA100714308 /* Assets.xcassets */,
71 | 850D4FB728CCEBA100714308 /* Preview Content */,
72 | );
73 | path = ios;
74 | sourceTree = "";
75 | };
76 | 850D4FB728CCEBA100714308 /* Preview Content */ = {
77 | isa = PBXGroup;
78 | children = (
79 | 850D4FB828CCEBA100714308 /* Preview Assets.xcassets */,
80 | );
81 | path = "Preview Content";
82 | sourceTree = "";
83 | };
84 | 9BDC6B73A6A1A714F2D6297C /* Pods */ = {
85 | isa = PBXGroup;
86 | children = (
87 | 6AFCE7532F78DBD821C8E78D /* Pods-BlurHash.debug.xcconfig */,
88 | 208331B5D6E6A7716D6C289D /* Pods-BlurHash.release.xcconfig */,
89 | 8F886CA92368476133371299 /* Pods-ios.debug.xcconfig */,
90 | E8CBC299A962EF4A7EF2E9D2 /* Pods-ios.release.xcconfig */,
91 | );
92 | path = Pods;
93 | sourceTree = "";
94 | };
95 | /* End PBXGroup section */
96 |
97 | /* Begin PBXNativeTarget section */
98 | 850D4FAD28CCEBA100714308 /* ios */ = {
99 | isa = PBXNativeTarget;
100 | buildConfigurationList = 850D4FBC28CCEBA100714308 /* Build configuration list for PBXNativeTarget "ios" */;
101 | buildPhases = (
102 | 7BF1B2F561E1594EC096416E /* [CP] Check Pods Manifest.lock */,
103 | 850D4FAA28CCEBA100714308 /* Sources */,
104 | 850D4FAB28CCEBA100714308 /* Frameworks */,
105 | 850D4FAC28CCEBA100714308 /* Resources */,
106 | );
107 | buildRules = (
108 | );
109 | dependencies = (
110 | );
111 | name = ios;
112 | productName = Locale;
113 | productReference = 850D4FAE28CCEBA100714308 /* ios.app */;
114 | productType = "com.apple.product-type.application";
115 | };
116 | /* End PBXNativeTarget section */
117 |
118 | /* Begin PBXProject section */
119 | 850D4FA628CCEBA100714308 /* Project object */ = {
120 | isa = PBXProject;
121 | attributes = {
122 | BuildIndependentTargetsInParallel = 1;
123 | LastSwiftUpdateCheck = 1340;
124 | LastUpgradeCheck = 1340;
125 | TargetAttributes = {
126 | 850D4FAD28CCEBA100714308 = {
127 | CreatedOnToolsVersion = 13.4.1;
128 | };
129 | };
130 | };
131 | buildConfigurationList = 850D4FA928CCEBA100714308 /* Build configuration list for PBXProject "ios" */;
132 | compatibilityVersion = "Xcode 13.0";
133 | developmentRegion = en;
134 | hasScannedForEncodings = 0;
135 | knownRegions = (
136 | en,
137 | Base,
138 | );
139 | mainGroup = 850D4FA528CCEBA100714308;
140 | productRefGroup = 850D4FAF28CCEBA100714308 /* Products */;
141 | projectDirPath = "";
142 | projectRoot = "";
143 | targets = (
144 | 850D4FAD28CCEBA100714308 /* ios */,
145 | );
146 | };
147 | /* End PBXProject section */
148 |
149 | /* Begin PBXResourcesBuildPhase section */
150 | 850D4FAC28CCEBA100714308 /* Resources */ = {
151 | isa = PBXResourcesBuildPhase;
152 | buildActionMask = 2147483647;
153 | files = (
154 | 850D4FB928CCEBA100714308 /* Preview Assets.xcassets in Resources */,
155 | 850D4FB628CCEBA100714308 /* Assets.xcassets in Resources */,
156 | );
157 | runOnlyForDeploymentPostprocessing = 0;
158 | };
159 | /* End PBXResourcesBuildPhase section */
160 |
161 | /* Begin PBXShellScriptBuildPhase section */
162 | 7BF1B2F561E1594EC096416E /* [CP] Check Pods Manifest.lock */ = {
163 | isa = PBXShellScriptBuildPhase;
164 | buildActionMask = 2147483647;
165 | files = (
166 | );
167 | inputFileListPaths = (
168 | );
169 | inputPaths = (
170 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
171 | "${PODS_ROOT}/Manifest.lock",
172 | );
173 | name = "[CP] Check Pods Manifest.lock";
174 | outputFileListPaths = (
175 | );
176 | outputPaths = (
177 | "$(DERIVED_FILE_DIR)/Pods-ios-checkManifestLockResult.txt",
178 | );
179 | runOnlyForDeploymentPostprocessing = 0;
180 | shellPath = /bin/sh;
181 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
182 | showEnvVarsInLog = 0;
183 | };
184 | /* End PBXShellScriptBuildPhase section */
185 |
186 | /* Begin PBXSourcesBuildPhase section */
187 | 850D4FAA28CCEBA100714308 /* Sources */ = {
188 | isa = PBXSourcesBuildPhase;
189 | buildActionMask = 2147483647;
190 | files = (
191 | 850D4FB228CCEBA100714308 /* App.swift in Sources */,
192 | );
193 | runOnlyForDeploymentPostprocessing = 0;
194 | };
195 | /* End PBXSourcesBuildPhase section */
196 |
197 | /* Begin XCBuildConfiguration section */
198 | 850D4FBA28CCEBA100714308 /* Debug */ = {
199 | isa = XCBuildConfiguration;
200 | buildSettings = {
201 | ALWAYS_SEARCH_USER_PATHS = NO;
202 | CLANG_ANALYZER_NONNULL = YES;
203 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
204 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
205 | CLANG_ENABLE_MODULES = YES;
206 | CLANG_ENABLE_OBJC_ARC = YES;
207 | CLANG_ENABLE_OBJC_WEAK = YES;
208 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
209 | CLANG_WARN_BOOL_CONVERSION = YES;
210 | CLANG_WARN_COMMA = YES;
211 | CLANG_WARN_CONSTANT_CONVERSION = YES;
212 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
213 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
214 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
215 | CLANG_WARN_EMPTY_BODY = YES;
216 | CLANG_WARN_ENUM_CONVERSION = YES;
217 | CLANG_WARN_INFINITE_RECURSION = YES;
218 | CLANG_WARN_INT_CONVERSION = YES;
219 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
220 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
221 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
222 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
223 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
224 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
225 | CLANG_WARN_STRICT_PROTOTYPES = YES;
226 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
227 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
228 | CLANG_WARN_UNREACHABLE_CODE = YES;
229 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
230 | COPY_PHASE_STRIP = NO;
231 | DEBUG_INFORMATION_FORMAT = dwarf;
232 | ENABLE_STRICT_OBJC_MSGSEND = YES;
233 | ENABLE_TESTABILITY = YES;
234 | GCC_C_LANGUAGE_STANDARD = gnu11;
235 | GCC_DYNAMIC_NO_PIC = NO;
236 | GCC_NO_COMMON_BLOCKS = YES;
237 | GCC_OPTIMIZATION_LEVEL = 0;
238 | GCC_PREPROCESSOR_DEFINITIONS = (
239 | "DEBUG=1",
240 | "$(inherited)",
241 | );
242 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
243 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
244 | GCC_WARN_UNDECLARED_SELECTOR = YES;
245 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
246 | GCC_WARN_UNUSED_FUNCTION = YES;
247 | GCC_WARN_UNUSED_VARIABLE = YES;
248 | IPHONEOS_DEPLOYMENT_TARGET = 15.5;
249 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
250 | MTL_FAST_MATH = YES;
251 | ONLY_ACTIVE_ARCH = YES;
252 | SDKROOT = iphoneos;
253 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
254 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
255 | };
256 | name = Debug;
257 | };
258 | 850D4FBB28CCEBA100714308 /* Release */ = {
259 | isa = XCBuildConfiguration;
260 | buildSettings = {
261 | ALWAYS_SEARCH_USER_PATHS = NO;
262 | CLANG_ANALYZER_NONNULL = YES;
263 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
264 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
265 | CLANG_ENABLE_MODULES = YES;
266 | CLANG_ENABLE_OBJC_ARC = YES;
267 | CLANG_ENABLE_OBJC_WEAK = YES;
268 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
269 | CLANG_WARN_BOOL_CONVERSION = YES;
270 | CLANG_WARN_COMMA = YES;
271 | CLANG_WARN_CONSTANT_CONVERSION = YES;
272 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
273 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
274 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
275 | CLANG_WARN_EMPTY_BODY = YES;
276 | CLANG_WARN_ENUM_CONVERSION = YES;
277 | CLANG_WARN_INFINITE_RECURSION = YES;
278 | CLANG_WARN_INT_CONVERSION = YES;
279 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
280 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
281 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
282 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
283 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
284 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
285 | CLANG_WARN_STRICT_PROTOTYPES = YES;
286 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
287 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
288 | CLANG_WARN_UNREACHABLE_CODE = YES;
289 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
290 | COPY_PHASE_STRIP = NO;
291 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
292 | ENABLE_NS_ASSERTIONS = NO;
293 | ENABLE_STRICT_OBJC_MSGSEND = YES;
294 | GCC_C_LANGUAGE_STANDARD = gnu11;
295 | GCC_NO_COMMON_BLOCKS = YES;
296 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
297 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
298 | GCC_WARN_UNDECLARED_SELECTOR = YES;
299 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
300 | GCC_WARN_UNUSED_FUNCTION = YES;
301 | GCC_WARN_UNUSED_VARIABLE = YES;
302 | IPHONEOS_DEPLOYMENT_TARGET = 15.5;
303 | MTL_ENABLE_DEBUG_INFO = NO;
304 | MTL_FAST_MATH = YES;
305 | SDKROOT = iphoneos;
306 | SWIFT_COMPILATION_MODE = wholemodule;
307 | SWIFT_OPTIMIZATION_LEVEL = "-O";
308 | VALIDATE_PRODUCT = YES;
309 | };
310 | name = Release;
311 | };
312 | 850D4FBD28CCEBA100714308 /* Debug */ = {
313 | isa = XCBuildConfiguration;
314 | baseConfigurationReference = 8F886CA92368476133371299 /* Pods-ios.debug.xcconfig */;
315 | buildSettings = {
316 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
317 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
318 | CODE_SIGN_STYLE = Automatic;
319 | CURRENT_PROJECT_VERSION = 1;
320 | DEVELOPMENT_ASSET_PATHS = "\"ios/Preview Content\"";
321 | DEVELOPMENT_TEAM = 779A4D7K9R;
322 | ENABLE_PREVIEWS = YES;
323 | GENERATE_INFOPLIST_FILE = YES;
324 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
325 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
326 | INFOPLIST_KEY_UILaunchScreen_Generation = YES;
327 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
328 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
329 | LD_RUNPATH_SEARCH_PATHS = (
330 | "$(inherited)",
331 | "@executable_path/Frameworks",
332 | );
333 | MARKETING_VERSION = 1.0;
334 | PRODUCT_BUNDLE_IDENTIFIER = com.vanniktech.locale.sample.ios;
335 | PRODUCT_NAME = "$(TARGET_NAME)";
336 | SWIFT_EMIT_LOC_STRINGS = YES;
337 | SWIFT_VERSION = 5.0;
338 | TARGETED_DEVICE_FAMILY = "1,2";
339 | };
340 | name = Debug;
341 | };
342 | 850D4FBE28CCEBA100714308 /* Release */ = {
343 | isa = XCBuildConfiguration;
344 | baseConfigurationReference = E8CBC299A962EF4A7EF2E9D2 /* Pods-ios.release.xcconfig */;
345 | buildSettings = {
346 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
347 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
348 | CODE_SIGN_STYLE = Automatic;
349 | CURRENT_PROJECT_VERSION = 1;
350 | DEVELOPMENT_ASSET_PATHS = "\"ios/Preview Content\"";
351 | DEVELOPMENT_TEAM = 779A4D7K9R;
352 | ENABLE_PREVIEWS = YES;
353 | GENERATE_INFOPLIST_FILE = YES;
354 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
355 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
356 | INFOPLIST_KEY_UILaunchScreen_Generation = YES;
357 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
358 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
359 | LD_RUNPATH_SEARCH_PATHS = (
360 | "$(inherited)",
361 | "@executable_path/Frameworks",
362 | );
363 | MARKETING_VERSION = 1.0;
364 | PRODUCT_BUNDLE_IDENTIFIER = com.vanniktech.locale.sample.ios;
365 | PRODUCT_NAME = "$(TARGET_NAME)";
366 | SWIFT_EMIT_LOC_STRINGS = YES;
367 | SWIFT_VERSION = 5.0;
368 | TARGETED_DEVICE_FAMILY = "1,2";
369 | };
370 | name = Release;
371 | };
372 | /* End XCBuildConfiguration section */
373 |
374 | /* Begin XCConfigurationList section */
375 | 850D4FA928CCEBA100714308 /* Build configuration list for PBXProject "ios" */ = {
376 | isa = XCConfigurationList;
377 | buildConfigurations = (
378 | 850D4FBA28CCEBA100714308 /* Debug */,
379 | 850D4FBB28CCEBA100714308 /* Release */,
380 | );
381 | defaultConfigurationIsVisible = 0;
382 | defaultConfigurationName = Release;
383 | };
384 | 850D4FBC28CCEBA100714308 /* Build configuration list for PBXNativeTarget "ios" */ = {
385 | isa = XCConfigurationList;
386 | buildConfigurations = (
387 | 850D4FBD28CCEBA100714308 /* Debug */,
388 | 850D4FBE28CCEBA100714308 /* Release */,
389 | );
390 | defaultConfigurationIsVisible = 0;
391 | defaultConfigurationName = Release;
392 | };
393 | /* End XCConfigurationList section */
394 | };
395 | rootObject = 850D4FA628CCEBA100714308 /* Project object */;
396 | }
397 |
--------------------------------------------------------------------------------