Skip to content

Commit

Permalink
Merge pull request #23602 from brave/ios-primary-lang-metric
Browse files Browse the repository at this point in the history
[iOS] Add metric for primary language
  • Loading branch information
kylehickinson authored May 14, 2024
2 parents 2a79cdd + f86f8fb commit ce7a52a
Show file tree
Hide file tree
Showing 4 changed files with 257 additions and 0 deletions.
2 changes: 2 additions & 0 deletions ios/brave-ios/App/iOS/Delegates/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
)
}

LanguageMetrics.recordPrimaryLanguageP3A()

Task(priority: .low) {
await self.cleanUpLargeTemporaryDirectory()
}
Expand Down
1 change: 1 addition & 0 deletions ios/brave-ios/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ var package = Package(
name: "Growth",
dependencies: [
"BraveVPN", "Shared", "BraveShared", "Strings", "SnapKit", "CertificateUtilities",
.product(name: "OrderedCollections", package: "swift-collections"),
],
plugins: ["LoggerPlugin"]
),
Expand Down
225 changes: 225 additions & 0 deletions ios/brave-ios/Sources/Growth/LanguageMetrics.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
// Copyright (c) 2024 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

import BraveCore
import Foundation
import OrderedCollections

public class LanguageMetrics {

// This list is copied from //brave/components/misc_metrics/language_metrics.cc
static let acceptedLanguages: OrderedSet<String> = [
"aa", // Afar
"ab", // Abkhazian
"ae", // Avestan
"af", // Afrikaans
"ak", // Akan
"am", // Amharic
"an", // Aragonese
"ar", // Arabic
"as", // Assamese
"av", // Avaric
"ay", // Aymara
"az", // Azerbaijani
"ba", // Bashkir
"be", // Belarusian
"bg", // Bulgarian
"bh", // Bihari languages
"bi", // Bislama
"bm", // Bambara
"bn", // Bengali
"bo", // Tibetan
"br", // Breton
"bs", // Bosnian
"ca", // Catalan; Valencian
"ce", // Chechen
"ch", // Chamorro
"co", // Corsican
"cr", // Cree
"cs", // Czech
"cu", // Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; // Old Church Slavonic
"cv", // Chuvash
"cy", // Welsh
"da", // Danish
"de", // German
"dv", // Divehi; Dhivehi; Maldivian
"dz", // Dzongkha
"ee", // Ewe
"el", // "Greek, Modern (1453-)"
"en", // English
"eo", // Esperanto
"es", // Spanish; Castilian
"et", // Estonian
"eu", // Basque
"fa", // Persian
"ff", // Fulah
"fi", // Finnish
"fj", // Fijian
"fo", // Faroese
"fr", // French
"fy", // Western Frisian
"ga", // Irish
"gd", // Gaelic; Scottish Gaelic
"gl", // Galician
"gn", // Guarani
"gu", // Gujarati
"gv", // Manx
"ha", // Hausa
"he", // Hebrew
"hi", // Hindi
"ho", // Hiri Motu
"hr", // Croatian
"ht", // Haitian; Haitian Creole
"hu", // Hungarian
"hy", // Armenian
"hz", // Herero
"ia", // Interlingua (International Auxiliary Language Association)
"id", // Indonesian
"ie", // Interlingue; Occidental
"ig", // Igbo
"ii", // Sichuan Yi; Nuosu
"ik", // Inupiaq
"io", // Ido
"is", // Icelandic
"it", // Italian
"iu", // Inuktitut
"ja", // Japanese
"jv", // Javanese
"ka", // Georgian
"kg", // Kongo
"ki", // Kikuyu; Gikuyu
"kj", // Kuanyama; Kwanyama
"kk", // Kazakh
"kl", // Kalaallisut; Greenlandic
"km", // Central Khmer
"kn", // Kannada
"ko", // Korean
"kr", // Kanuri
"ks", // Kashmiri
"ku", // Kurdish
"kv", // Komi
"kw", // Cornish
"ky", // Kirghiz; Kyrgyz
"la", // Latin
"lb", // Luxembourgish; Letzeburgesch
"lg", // Ganda
"li", // Limburgan; Limburger; Limburgish
"ln", // Lingala
"lo", // Lao
"lt", // Lithuanian
"lu", // Luba-Katanga
"lv", // Latvian
"mg", // Malagasy
"mh", // Marshallese
"mi", // Maori
"mk", // Macedonian
"ml", // Malayalam
"mn", // Mongolian
"mr", // Marathi
"ms", // Malay
"mt", // Maltese
"my", // Burmese
"na", // Nauru
"nb", // "Bokmål, Norwegian; Norwegian Bokmål"
"nd", // "Ndebele, North; North Ndebele"
"ne", // Nepali
"ng", // Ndonga
"nl", // Dutch; Flemish
"nn", // "Norwegian Nynorsk; Nynorsk, Norwegian"
"no", // Norwegian
"nr", // "Ndebele, South; South Ndebele"
"nv", // Navajo; Navaho
"ny", // Chichewa; Chewa; Nyanja
"oc", // Occitan (post 1500)
"oj", // Ojibwa
"om", // Oromo
"or", // Oriya
"os", // Ossetian; Ossetic
"pa", // Panjabi; Punjabi
"pi", // Pali
"pl", // Polish
"ps", // Pushto; Pashto
"pt", // Portuguese
"qu", // Quechua
"rm", // Romansh
"rn", // Rundi
"ro", // Romanian; Moldavian; Moldovan
"ru", // Russian
"rw", // Kinyarwanda
"sa", // Sanskrit
"sc", // Sardinian
"sd", // Sindhi
"se", // Northern Sami
"sg", // Sango
"si", // Sinhala; Sinhalese
"sk", // Slovak
"sl", // Slovenian
"sm", // Samoan
"sn", // Shona
"so", // Somali
"sq", // Albanian
"sr", // Serbian
"ss", // Swati
"st", // "Sotho, Southern"
"su", // Sundanese
"sv", // Swedish
"sw", // Swahili
"ta", // Tamil
"te", // Telugu
"tg", // Tajik
"th", // Thai
"ti", // Tigrinya
"tk", // Turkmen
"tl", // Tagalog
"tn", // Tswana
"to", // Tonga (Tonga Islands)
"tr", // Turkish
"ts", // Tsonga
"tt", // Tatar
"tw", // Twi
"ty", // Tahitian
"ug", // Uighur; Uyghur
"uk", // Ukrainian
"ur", // Urdu
"uz", // Uzbek
"ve", // Venda
"vi", // Vietnamese
"vo", // Volapük
"wa", // Walloon
"wo", // Wolof
"xh", // Xhosa
"yi", // Yiddish
"yo", // Yoruba
"za", // Zhuang; Chuang
"zh", // Chinese
"zu", // Zulu
]

static let languageSynonyms: [String: String] = [
"in": "id",
"iw": "he",
"ji": "yi",
"jw": "jv",
"mo": "ro",
]

static func answerForLangaugeCode(_ languageCode: String?) -> Int {
let suspendedMetricValue = Int.max - 1
guard let languageCode = languageCode,
case let primaryLanguage = languageSynonyms[languageCode, default: languageCode],
let answer = acceptedLanguages.firstIndex(of: primaryLanguage)
else {
// Suspend metric if primary language not detected or language isn't accepted
return suspendedMetricValue
}
return answer
}

public static func recordPrimaryLanguageP3A() {
let primaryLanguageHistogramName = "Brave.Core.PrimaryLang"
let answer = answerForLangaugeCode(Locale.current.languageCode)
UmaHistogramExactLinear(primaryLanguageHistogramName, answer, acceptedLanguages.count)
}
}
29 changes: 29 additions & 0 deletions ios/brave-ios/Tests/GrowthTests/LangaugeMetricsTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) 2024 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

import Foundation
import XCTest

@testable import Growth

class LanguageMetricsTests: XCTestCase {
func testInvalidLanguageCodes() {
let expectedValue = Int.max - 1
XCTAssertEqual(LanguageMetrics.answerForLangaugeCode(nil), expectedValue)
XCTAssertEqual(LanguageMetrics.answerForLangaugeCode("notalangugage"), expectedValue)
}

func testValidLanguageCodes() {
for (index, languageCode) in LanguageMetrics.acceptedLanguages.enumerated() {
XCTAssertEqual(LanguageMetrics.answerForLangaugeCode(languageCode), index)
}
}

func testLanguageSynonyms() {
let (deprecated, active) = ("in", "id")
let expectedAnswer = LanguageMetrics.answerForLangaugeCode(active)
XCTAssertEqual(LanguageMetrics.answerForLangaugeCode(deprecated), expectedAnswer)
}
}

0 comments on commit ce7a52a

Please sign in to comment.