Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
- Ollama: replace the bundled provider icon with the cleaner official mark while preserving native template tinting. Thanks @mattab178!
- Menu bar: avoid a one-time visible menu rebuild after first-open background data arrives.
- Settings: use high-contrast selected-content colors for provider sidebar text and icons.
- Localization: add Italian as a selectable app language (#1248). Thanks @Yuxin-Qiao!
- Localization: add Indonesian as a selectable app language (#1513). Thanks @StevanusPangau!

### Changed
- Antigravity: prefer app and `agy` quota summaries, group usage into Gemini and Claude + GPT session/weekly pools, and preserve IDE and OAuth fallbacks. Thanks @Zihao-Qi!
Expand Down Expand Up @@ -59,7 +61,6 @@
- Menu bar: add an optional reset-time display for the selected quota metric, with percent fallback when reset metadata is unavailable (#1223, fixes #1185). Thanks @Yuxin-Qiao!
- Cursor: include application data, extensions, settings, and caches in optional local storage tracking (fixes #1403). Thanks @dhruv-anand-aintech!
- Menu bar: move the highlighted Overview provider with trackpad or mouse-wheel scrolling while preserving native submenu and keyboard behavior (#1436). Thanks @joshuavial!
- Localization: add Italian as a selectable app language (#1248). Thanks @Yuxin-Qiao!

### Fixed
- CLI: keep Ollama API credentials scoped to Ollama when deciding whether another provider requires macOS web support (#1466). Thanks @WadydX!
Expand Down
2 changes: 2 additions & 0 deletions Sources/CodexBar/PreferencesGeneralPane.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ enum AppLanguage: String, CaseIterable, Identifiable {
case japanese = "ja"
case korean = "ko"
case turkish = "tr"
case indonesian = "id"

var id: String {
self.rawValue
Expand All @@ -44,6 +45,7 @@ enum AppLanguage: String, CaseIterable, Identifiable {
case .japanese: L("language_japanese")
case .korean: L("language_korean")
case .turkish: L("language_turkish")
case .indonesian: L("language_indonesian")
}
}
}
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/ca.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -934,3 +934,4 @@

"language_vietnamese" = "Vietnamita";
"language_turkish" = "Türkçe";
"language_indonesian" = "Indonesi";
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/de.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@
"language_korean" = "Koreanisch";
"language_turkish" = "Türkçe";
"language_italian" = "Italiano";
"language_indonesian" = "Indonesisch";
"start_at_login_title" = "Beim Login starten";
"start_at_login_subtitle" = "Startet CodexBar automatisch, wenn dein Mac hochfährt.";
"show_cost_summary" = "Kostenübersicht anzeigen";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -1077,5 +1077,6 @@
"Search providers" = "Search providers";

"language_vietnamese" = "Vietnamese";
"language_indonesian" = "Bahasa Indonesia";

"Request quota: %@ / %@" = "Request quota: %@ / %@";
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/es.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -934,3 +934,4 @@

"language_vietnamese" = "Vietnamita";
"language_turkish" = "Türkçe";
"language_indonesian" = "Indonesio";
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/fr.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@
"language_italian" = "Italiano";
"language_vietnamese" = "Vietnamien";
"language_turkish" = "Türkçe";
"language_indonesian" = "Indonésien";
"start_at_login_title" = "Lancer à l'ouverture de session";
"start_at_login_subtitle" = "Ouvre automatiquement CodexBar au démarrage de votre Mac.";
"show_cost_summary" = "Afficher le récapitulatif des coûts";
Expand Down
1,081 changes: 1,081 additions & 0 deletions Sources/CodexBar/Resources/id.lproj/Localizable.strings

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/it.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@
"language_dutch" = "Olandese";
"language_ukrainian" = "Ucraino";
"language_vietnamese" = "Vietnamita";
"language_indonesian" = "Indonesiano";
"start_at_login_title" = "Avvia all'accesso";
"start_at_login_subtitle" = "Apre automaticamente CodexBar quando avvii il Mac.";
"show_cost_summary" = "Mostra riepilogo costi";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/ja.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -1075,3 +1075,4 @@

"language_vietnamese" = "ベトナム語";
"language_turkish" = "Türkçe";
"language_indonesian" = "インドネシア語";
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/ko.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -1044,4 +1044,5 @@
"Search providers" = "공급자 검색";
"language_vietnamese" = "베트남어";
"language_turkish" = "Türkçe";
"language_indonesian" = "인도네시아어";
"Request quota: %@ / %@" = "요청 할당량: %@ / %@";
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/nl.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@
"language_swedish" = "Zweeds";
"language_vietnamese" = "Vietnamees";
"language_turkish" = "Türkçe";
"language_indonesian" = "Indonesisch";
"start_at_login_title" = "Begin bij Inloggen";
"start_at_login_subtitle" = "Opent automatisch CodexBar wanneer u uw Mac start.";
"show_cost_summary" = "Kostenoverzicht weergeven";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/pt-BR.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -1075,3 +1075,4 @@

"language_vietnamese" = "Vietnamita";
"language_turkish" = "Türkçe";
"language_indonesian" = "Indonésio";
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/sv.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@
"language_korean" = "Koreanska";
"language_turkish" = "Türkçe";
"language_italian" = "Italiano";
"language_indonesian" = "Indonesiska";
"start_at_login_title" = "Starta vid inloggning";
"start_at_login_subtitle" = "Öppnar CodexBar automatiskt när du startar din Mac.";
"show_cost_summary" = "Visa kostnadssammanfattning";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/tr.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@
"language_korean" = "한국어";
"language_turkish" = "Türkçe";
"language_italian" = "Italiano";
"language_indonesian" = "Endonezce";
"start_at_login_title" = "Girişte Başlat";
"start_at_login_subtitle" = "Mac'inizi başlattığınızda CodexBar'ı otomatik olarak açar.";
"show_cost_summary" = "Maliyet özetini göster";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/uk.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@
"language_italian" = "Italiano";
"language_vietnamese" = "В'єтнамська";
"language_turkish" = "Türkçe";
"language_indonesian" = "Індонезійська";
"start_at_login_title" = "Почніть із входу";
"start_at_login_subtitle" = "Автоматично відкриває CodexBar під час запуску Mac.";
"show_cost_summary" = "Показати підсумок витрат";
Expand Down
1 change: 1 addition & 0 deletions Sources/CodexBar/Resources/vi.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -1075,3 +1075,4 @@

"language_vietnamese" = "Tiếng Việt";
"language_turkish" = "Türkçe";
"language_indonesian" = "Tiếng Indonesia";
Original file line number Diff line number Diff line change
Expand Up @@ -1051,3 +1051,4 @@

"Request quota: %@ / %@" = "请求额度:%@ / %@";
"language_turkish" = "Türkçe";
"language_indonesian" = "印度尼西亚语";
Original file line number Diff line number Diff line change
Expand Up @@ -947,3 +947,4 @@

"Request quota: %@ / %@" = "請求額度:%@ / %@";
"language_turkish" = "Türkçe";
"language_indonesian" = "印尼語";
52 changes: 51 additions & 1 deletion Tests/CodexBarTests/LocalizationLanguageCatalogTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct LocalizationLanguageCatalogTests {
"language_japanese",
"language_korean",
"language_turkish",
"language_indonesian",
]

@Test
Expand All @@ -47,6 +48,12 @@ struct LocalizationLanguageCatalogTests {
#expect(AppLanguage.italian.rawValue == "it")
}

@Test
func `app language catalog includes Indonesian`() {
#expect(AppLanguage.allCases.contains(.indonesian))
#expect(AppLanguage.indonesian.rawValue == "id")
}

@Test
func `localized catalogs include every app language label`() throws {
#expect(self.languageKeys.count == AppLanguage.allCases.count)
Expand Down Expand Up @@ -194,7 +201,7 @@ struct LocalizationLanguageCatalogTests {
#expect(italian["ory_session_…=…; csrftoken=…"] == "ory_session_…=…; csrftoken=…")
#expect(italian["quota_warning_notifications_subtitle"]?.contains("scende sotto") == true)

let intentionallyUnchanged: Set<String> = [
let intentionallyUnchanged: Set = [
"Account",
"Build",
"Chrome",
Expand Down Expand Up @@ -234,6 +241,49 @@ struct LocalizationLanguageCatalogTests {
#expect(title == "Quota settimanale di Codex quasi esaurita")
}

@Test
func `indonesian localization matches English catalog and preserves format placeholders`() throws {
let root = URL(fileURLWithPath: #filePath)
.deletingLastPathComponent()
.deletingLastPathComponent()
.deletingLastPathComponent()
let resourcesURL = root.appendingPathComponent("Sources/CodexBar/Resources")
let enURL = resourcesURL.appendingPathComponent("en.lproj/Localizable.strings")
let idURL = resourcesURL.appendingPathComponent("id.lproj/Localizable.strings")
let english = try #require(NSDictionary(contentsOf: enURL) as? [String: String])
let indonesian = try #require(NSDictionary(contentsOf: idURL) as? [String: String])

#expect(Set(indonesian.keys) == Set(english.keys))
#expect(indonesian["language_indonesian"] == "Bahasa Indonesia")
#expect(indonesian["tab_general"] == "Umum")
#expect(indonesian["quit_app"] == "Keluar CodexBar")
#expect(indonesian["30d"] == "30 hari")
#expect(indonesian["On"] == "Aktif")
#expect(indonesian["Off"] == "Nonaktif")

let warningFormat = try #require(indonesian["quota_warning_notification_body"])
let warning = String(
format: warningFormat,
locale: Locale(identifier: "id_ID"),
arguments: ["20%", 15, "sesi"])
#expect(warning.contains("15%"))
#expect(!warning.contains("%2$d"))

let historyFormat = try #require(indonesian["%@: %@%% used"])
let historyLabel = String(
format: historyFormat,
locale: Locale(identifier: "id_ID"),
arguments: ["12 Jun", "45"])
#expect(historyLabel == "12 Jun: 45% terpakai")

let daysFormat = try #require(indonesian["%dd"])
let daysLabel = String(
format: daysFormat,
locale: Locale(identifier: "id_ID"),
arguments: [30])
#expect(daysLabel == "30 hari")
}

@Test
func `japanese usage chart accessibility text preserves argument meanings`() throws {
let root = URL(fileURLWithPath: #filePath)
Expand Down
9 changes: 9 additions & 0 deletions Tests/CodexBarTests/PreferencesPaneSmokeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,15 @@ struct PreferencesPaneSmokeTests {
#expect(L("start_at_login_title") == "ログイン時に起動")
#expect(L("quit_app") == "CodexBar を終了")
}

settings.appLanguage = "id"

#expect(UserDefaults.standard.string(forKey: "appLanguage") == "id")
CodexBarLocalizationOverride.$appLanguage.withValue("id") {
#expect(L("language_title") == "Bahasa")
#expect(L("start_at_login_title") == "Mulai saat Login")
#expect(L("quit_app") == "Keluar CodexBar")
}
}

@Test
Expand Down