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
2 changes: 1 addition & 1 deletion apps/desktop-tauri/src/components/MenuCardDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ export interface MenuCardPresence {
hasCostHistory: boolean;
hasCreditsHistory: boolean;
hasUsageBreakdown: boolean;
localUsage: ProviderUsageSnapshot["localUsage"] | null;
localUsage: ProviderChartData["localUsage"] | null;
wayfinderUsage: ProviderUsageSnapshot["wayfinderUsage"] | null;
hasDetails: boolean;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function provider(id: string): ProviderUsageSnapshot {
reserveWillLastToReset: false,
reserveEtaSeconds: null,
},
primaryLabel: null,
primaryLabel: undefined,
secondary: null,
secondaryLabel: undefined,
modelSpecific: null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ vi.mock("@tauri-apps/api/core", () => ({
{ value: "japanese", display: "日本語" },
{ value: "korean", display: "한국어" },
{ value: "spanish", display: "Español" },
{ value: "russian", display: "Русский" },
]),
}));

Expand Down Expand Up @@ -74,14 +75,14 @@ const settings: SettingsSnapshot = {
};

describe("GeneralTab language picker", () => {
it("renders 6 language options when Traditional Chinese is wired", () => {
it("renders all supported language options", () => {
render(<GeneralTab settings={settings} set={vi.fn()} saving={false} />);

const select = screen.getByDisplayValue("English");
expect(select).toBeInTheDocument();

const options = select.querySelectorAll("option");
expect(options).toHaveLength(6);
expect(options.length).toBeGreaterThanOrEqual(7);
});

it("includes spanish as a selectable option", () => {
Expand All @@ -92,6 +93,12 @@ describe("GeneralTab language picker", () => {
).toBeInTheDocument();
});

it("includes russian as a selectable option", () => {
render(<GeneralTab settings={settings} set={vi.fn()} saving={false} />);

expect(screen.getByText("Русский")).toBeInTheDocument();
});

it("includes korean as a selectable option", () => {
render(<GeneralTab settings={settings} set={vi.fn()} saving={false} />);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const FALLBACK_LANGUAGE_OPTIONS: LanguageOption[] = [
{ value: "japanese", display: "日本語" },
{ value: "korean", display: "한국어" },
{ value: "spanish", display: "Español" },
{ value: "russian", display: "Русский" },
];

const REFRESH_CADENCE_OPTIONS: { value: string; labelKey: LocaleKey }[] = [
Expand Down
15 changes: 15 additions & 0 deletions apps/desktop-tauri/src/types/bridge.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ describe("Language type", () => {
expect(langKo).toBe("korean");
const langZhTw: Language = "chinesetraditional";
expect(langZhTw).toBe("chinesetraditional");
const langRu: Language = "russian";
expect(langRu).toBe("russian");
});

it("allows 'spanish' in LocaleStrings payload", () => {
Expand All @@ -35,6 +37,13 @@ describe("Language type", () => {
};
expect(payloadZhTw.language).toBe("chinesetraditional");
expect(payloadZhTw.entries.TabGeneral).toBe("一般");

const payloadRu: LocaleStrings = {
language: "russian",
entries: { TabGeneral: "Общие" },
};
expect(payloadRu.language).toBe("russian");
expect(payloadRu.entries.TabGeneral).toBe("Общие");
});

it("allows 'spanish' in SettingsSnapshot.uiLanguage", () => {
Expand Down Expand Up @@ -103,5 +112,11 @@ describe("Language type", () => {
uiLanguage: "chinesetraditional",
};
expect(snapZhTw.uiLanguage).toBe("chinesetraditional");

const snapRu: SettingsSnapshot = {
...snap,
uiLanguage: "russian",
};
expect(snapRu.uiLanguage).toBe("russian");
});
});
3 changes: 2 additions & 1 deletion apps/desktop-tauri/src/types/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ export type Language =
| "chinesetraditional"
| "japanese"
| "korean"
| "spanish";
| "spanish"
| "russian";

/** Language catalog entry from the Rust backend. */
export type LanguageOption = {
Expand Down
2 changes: 2 additions & 0 deletions rust/src/locale.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ fn language_id(lang: Language) -> &'static LanguageIdentifier {
static JA_JP: LazyLock<LanguageIdentifier> = LazyLock::new(|| "ja-JP".parse().unwrap());
static KO_KR: LazyLock<LanguageIdentifier> = LazyLock::new(|| "ko-KR".parse().unwrap());
static ES_MX: LazyLock<LanguageIdentifier> = LazyLock::new(|| "es-MX".parse().unwrap());
static RU_RU: LazyLock<LanguageIdentifier> = LazyLock::new(|| "ru-RU".parse().unwrap());

match lang {
Language::English => &EN_US,
Expand All @@ -58,6 +59,7 @@ fn language_id(lang: Language) -> &'static LanguageIdentifier {
Language::Japanese => &JA_JP,
Language::Korean => &KO_KR,
Language::Spanish => &ES_MX,
Language::Russian => &RU_RU,
}
}

Expand Down
713 changes: 713 additions & 0 deletions rust/src/locale/ru-RU.ftl

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions rust/src/locale/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,19 @@ fn test_locale_key_spanish() {
);
}

#[test]
fn test_locale_key_russian() {
assert_eq!(get_text(Language::Russian, LocaleKey::TabGeneral), "Общие");
assert_eq!(
get_text(Language::Russian, LocaleKey::InterfaceLanguage),
"Язык интерфейса"
);
assert_eq!(
get_text(Language::Russian, LocaleKey::StartAtLogin),
"Запускать при входе в систему"
);
}

#[test]
fn test_locale_key_korean() {
assert_eq!(get_text(Language::Korean, LocaleKey::TabGeneral), "일반");
Expand Down Expand Up @@ -343,6 +356,10 @@ fn test_locale_respects_language_setting() {
// Test that Spanish language returns Spanish strings
let lang = Language::Spanish;
assert_eq!(get_text(lang, LocaleKey::TabAbout), "Acerca de");

// Test that Russian language returns Russian strings
let lang = Language::Russian;
assert_eq!(get_text(lang, LocaleKey::TabAbout), "О программе");
}

#[test]
Expand All @@ -354,6 +371,7 @@ fn test_english_is_complete_and_other_languages_can_fallback() {
("ja-JP", include_str!("ja-JP.ftl")),
("ko-KR", include_str!("ko-KR.ftl")),
("es-MX", include_str!("es-MX.ftl")),
("ru-RU", include_str!("ru-RU.ftl")),
];

let resource_keys: Vec<(&str, HashSet<&str>)> = resources
Expand Down
11 changes: 10 additions & 1 deletion rust/src/settings/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,13 +547,14 @@ fn test_language_defaults_to_english() {
#[test]
fn test_language_all_variants_available() {
let languages = Language::all();
assert_eq!(languages.len(), 6);
assert_eq!(languages.len(), 7);
assert!(languages.contains(&Language::English));
assert!(languages.contains(&Language::Chinese));
assert!(languages.contains(&Language::ChineseTraditional));
assert!(languages.contains(&Language::Japanese));
assert!(languages.contains(&Language::Korean));
assert!(languages.contains(&Language::Spanish));
assert!(languages.contains(&Language::Russian));
}

#[test]
Expand All @@ -562,6 +563,14 @@ fn test_language_display_names() {
assert_eq!(Language::Chinese.display_name(), "中文");
assert_eq!(Language::ChineseTraditional.display_name(), "繁體中文");
assert_eq!(Language::Japanese.display_name(), "日本語");
assert_eq!(Language::Russian.display_name(), "Русский");
}

#[test]
fn test_language_resolves_russian_aliases() {
assert_eq!(Language::resolve("russian"), Some(Language::Russian));
assert_eq!(Language::resolve("ru-RU"), Some(Language::Russian));
assert_eq!(Language::resolve("Русский"), Some(Language::Russian));
}

#[test]
Expand Down
6 changes: 6 additions & 0 deletions rust/src/settings/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ pub enum Language {
Korean,
/// Spanish (Mexican)
Spanish,
/// Russian
Russian,
}

impl Language {
Expand All @@ -84,6 +86,7 @@ impl Language {
Language::Japanese => "日本語",
Language::Korean => "한국어",
Language::Spanish => "Español",
Language::Russian => "Русский",
}
}

Expand All @@ -96,6 +99,7 @@ impl Language {
Language::Japanese,
Language::Korean,
Language::Spanish,
Language::Russian,
]
}

Expand All @@ -109,6 +113,7 @@ impl Language {
Language::Japanese => "japanese",
Language::Korean => "korean",
Language::Spanish => "spanish",
Language::Russian => "russian",
}
}

Expand All @@ -122,6 +127,7 @@ impl Language {
Language::Japanese => &["ja", "ja-jp", "日本語"],
Language::Korean => &["ko", "ko-kr", "한국어"],
Language::Spanish => &["es", "es-mx", "español"],
Language::Russian => &["ru", "ru-ru", "русский"],
}
}

Expand Down