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
12 changes: 6 additions & 6 deletions Sources/VoidBar/Services/Translator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Translation
/// holding the result. `TranslatePane` supplies the session.
@MainActor
final class Translator: ObservableObject {
static let russian = Locale.Language(identifier: "ru")
static let ukrainian = Locale.Language(identifier: "uk")
static let english = Locale.Language(identifier: "en")

/// Both ends are always named. Leaving the source to the framework looks
Expand Down Expand Up @@ -40,16 +40,16 @@ final class Translator: ObservableObject {
var trimmed: String { input.trimmingCharacters(in: .whitespacesAndNewlines) }
var route: Route { Self.route(for: trimmed) }

/// Russian goes out to English, everything else comes in to Russian.
/// Ukrainian goes out to English, everything else comes in to Ukrainian.
///
/// Decided by script rather than by language detection: a single word is
/// far too short to identify reliably, and "привет" comes back as Bulgarian
/// often enough to matter.
static func route(for text: String) -> Route {
let cyrillic = text.unicodeScalars.contains { (0x0400...0x04FF).contains($0.value) }
return cyrillic
? Route(source: russian, target: english)
: Route(source: english, target: russian)
? Route(source: ukrainian, target: english)
: Route(source: english, target: ukrainian)
}

func retry() {
Expand Down Expand Up @@ -108,7 +108,7 @@ final class Translator: ObservableObject {
pasteboard.setString(output, forType: .string)
}

/// "Русский", "English" — for the column headers. Named in the language the
/// "Українська", "English" — for the column headers. Named in the language the
/// panel itself is in, not in the system's: those two can differ, and a
/// column headed in one language above a button worded in another reads as
/// a mistake.
Expand All @@ -120,7 +120,7 @@ final class Translator: ObservableObject {
return name.prefix(1).uppercased() + name.dropFirst()
}

/// Short code for the header badge — "EN → RU" reads at a glance where a
/// Short code for the header badge — "EN → UK" reads at a glance where a
/// spelled-out name would not fit in the strip.
static func code(_ language: Locale.Language) -> String {
language.languageCode?.identifier.uppercased() ?? "?"
Expand Down
19 changes: 19 additions & 0 deletions Tests/VoidBarTests/TranslatorTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import XCTest
@testable import VoidBar

@MainActor
final class TranslatorTests: XCTestCase {
func testEnglishRoutesToUkrainian() {
let route = Translator.route(for: "Hello, world")

XCTAssertEqual(route.source.languageCode?.identifier, "en")
XCTAssertEqual(route.target.languageCode?.identifier, "uk")
}

func testUkrainianRoutesToEnglish() {
let route = Translator.route(for: "Привіт, світе")

XCTAssertEqual(route.source.languageCode?.identifier, "uk")
XCTAssertEqual(route.target.languageCode?.identifier, "en")
}
}
Binary file modified docs/assets/hover-demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.