Merge branch 'main' into jacob/zg

This commit is contained in:
Jacob Sandlund
2025-07-09 19:18:19 -04:00
69 changed files with 4858 additions and 1017 deletions

View File

@ -147,14 +147,16 @@ jobs:
- name: "Notarize app bundle" - name: "Notarize app bundle"
env: env:
PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }} APPLE_NOTARIZATION_ISSUER: ${{ secrets.APPLE_NOTARIZATION_ISSUER }}
PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }} APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }} APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }}
run: | run: |
# Store the notarization credentials so that we can prevent a UI password dialog # Store the notarization credentials so that we can prevent a UI password dialog
# from blocking the CI # from blocking the CI
echo "Create keychain profile" echo "Create keychain profile"
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD" echo "$APPLE_NOTARIZATION_KEY" > notarization_key.p8
xcrun notarytool store-credentials "notarytool-profile" --key notarization_key.p8 --key-id "$APPLE_NOTARIZATION_KEY_ID" --issuer "$APPLE_NOTARIZATION_ISSUER"
rm notarization_key.p8
# We can't notarize an app bundle directly, but we need to compress it as an archive. # We can't notarize an app bundle directly, but we need to compress it as an archive.
# Therefore, we create a zip file containing our app bundle, so that we can send it to the # Therefore, we create a zip file containing our app bundle, so that we can send it to the
@ -299,14 +301,16 @@ jobs:
- name: "Notarize app bundle" - name: "Notarize app bundle"
env: env:
PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }} APPLE_NOTARIZATION_ISSUER: ${{ secrets.APPLE_NOTARIZATION_ISSUER }}
PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }} APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }} APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }}
run: | run: |
# Store the notarization credentials so that we can prevent a UI password dialog # Store the notarization credentials so that we can prevent a UI password dialog
# from blocking the CI # from blocking the CI
echo "Create keychain profile" echo "Create keychain profile"
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD" echo "$APPLE_NOTARIZATION_KEY" > notarization_key.p8
xcrun notarytool store-credentials "notarytool-profile" --key notarization_key.p8 --key-id "$APPLE_NOTARIZATION_KEY_ID" --issuer "$APPLE_NOTARIZATION_ISSUER"
rm notarization_key.p8
# We can't notarize an app bundle directly, but we need to compress it as an archive. # We can't notarize an app bundle directly, but we need to compress it as an archive.
# Therefore, we create a zip file containing our app bundle, so that we can send it to the # Therefore, we create a zip file containing our app bundle, so that we can send it to the

View File

@ -229,14 +229,16 @@ jobs:
- name: "Notarize DMG" - name: "Notarize DMG"
env: env:
PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }} APPLE_NOTARIZATION_ISSUER: ${{ secrets.APPLE_NOTARIZATION_ISSUER }}
PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }} APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }} APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }}
run: | run: |
# Store the notarization credentials so that we can prevent a UI password dialog # Store the notarization credentials so that we can prevent a UI password dialog
# from blocking the CI # from blocking the CI
echo "Create keychain profile" echo "Create keychain profile"
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD" echo "$APPLE_NOTARIZATION_KEY" > notarization_key.p8
xcrun notarytool store-credentials "notarytool-profile" --key notarization_key.p8 --key-id "$APPLE_NOTARIZATION_KEY_ID" --issuer "$APPLE_NOTARIZATION_ISSUER"
rm notarization_key.p8
# Here we send the notarization request to the Apple's Notarization service, waiting for the result. # Here we send the notarization request to the Apple's Notarization service, waiting for the result.
# This typically takes a few seconds inside a CI environment, but it might take more depending on the App # This typically takes a few seconds inside a CI environment, but it might take more depending on the App

View File

@ -267,14 +267,16 @@ jobs:
- name: "Notarize DMG" - name: "Notarize DMG"
env: env:
PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }} APPLE_NOTARIZATION_ISSUER: ${{ secrets.APPLE_NOTARIZATION_ISSUER }}
PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }} APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }} APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }}
run: | run: |
# Store the notarization credentials so that we can prevent a UI password dialog # Store the notarization credentials so that we can prevent a UI password dialog
# from blocking the CI # from blocking the CI
echo "Create keychain profile" echo "Create keychain profile"
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD" echo "$APPLE_NOTARIZATION_KEY" > notarization_key.p8
xcrun notarytool store-credentials "notarytool-profile" --key notarization_key.p8 --key-id "$APPLE_NOTARIZATION_KEY_ID" --issuer "$APPLE_NOTARIZATION_ISSUER"
rm notarization_key.p8
# Here we send the notarization request to the Apple's Notarization service, waiting for the result. # Here we send the notarization request to the Apple's Notarization service, waiting for the result.
# This typically takes a few seconds inside a CI environment, but it might take more depending on the App # This typically takes a few seconds inside a CI environment, but it might take more depending on the App
@ -471,14 +473,16 @@ jobs:
- name: "Notarize app bundle" - name: "Notarize app bundle"
env: env:
PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }} APPLE_NOTARIZATION_ISSUER: ${{ secrets.APPLE_NOTARIZATION_ISSUER }}
PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }} APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }} APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }}
run: | run: |
# Store the notarization credentials so that we can prevent a UI password dialog # Store the notarization credentials so that we can prevent a UI password dialog
# from blocking the CI # from blocking the CI
echo "Create keychain profile" echo "Create keychain profile"
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD" echo "$APPLE_NOTARIZATION_KEY" > notarization_key.p8
xcrun notarytool store-credentials "notarytool-profile" --key notarization_key.p8 --key-id "$APPLE_NOTARIZATION_KEY_ID" --issuer "$APPLE_NOTARIZATION_ISSUER"
rm notarization_key.p8
# We can't notarize an app bundle directly, but we need to compress it as an archive. # We can't notarize an app bundle directly, but we need to compress it as an archive.
# Therefore, we create a zip file containing our app bundle, so that we can send it to the # Therefore, we create a zip file containing our app bundle, so that we can send it to the
@ -646,14 +650,16 @@ jobs:
- name: "Notarize app bundle" - name: "Notarize app bundle"
env: env:
PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }} APPLE_NOTARIZATION_ISSUER: ${{ secrets.APPLE_NOTARIZATION_ISSUER }}
PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }} APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }} APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }}
run: | run: |
# Store the notarization credentials so that we can prevent a UI password dialog # Store the notarization credentials so that we can prevent a UI password dialog
# from blocking the CI # from blocking the CI
echo "Create keychain profile" echo "Create keychain profile"
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD" echo "$APPLE_NOTARIZATION_KEY" > notarization_key.p8
xcrun notarytool store-credentials "notarytool-profile" --key notarization_key.p8 --key-id "$APPLE_NOTARIZATION_KEY_ID" --issuer "$APPLE_NOTARIZATION_ISSUER"
rm notarization_key.p8
# We can't notarize an app bundle directly, but we need to compress it as an archive. # We can't notarize an app bundle directly, but we need to compress it as an archive.
# Therefore, we create a zip file containing our app bundle, so that we can send it to the # Therefore, we create a zip file containing our app bundle, so that we can send it to the

View File

@ -561,7 +561,16 @@ jobs:
name: ghostty name: ghostty
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
- name: Test GTK Build - name: Test
run: |
nix develop -c \
zig build \
-Dapp-runtime=gtk \
-Dgtk-x11=${{ matrix.x11 }} \
-Dgtk-wayland=${{ matrix.wayland }} \
test
- name: Build
run: | run: |
nix develop -c \ nix develop -c \
zig build \ zig build \

View File

@ -181,6 +181,7 @@
/po/zh_CN.UTF-8.po @ghostty-org/zh_CN /po/zh_CN.UTF-8.po @ghostty-org/zh_CN
/po/ga_IE.UTF-8.po @ghostty-org/ga_IE /po/ga_IE.UTF-8.po @ghostty-org/ga_IE
/po/ko_KR.UTF-8.po @ghostty-org/ko_KR /po/ko_KR.UTF-8.po @ghostty-org/ko_KR
/po/he_IL.UTF-8.po @ghostty-org/he_IL
# Packaging - Snap # Packaging - Snap
/snap/ @ghostty-org/snap /snap/ @ghostty-org/snap

View File

@ -1,9 +1,12 @@
[Unit] [Unit]
Description=@NAME@ Description=@NAME@
After=graphical-session.target After=graphical-session.target
After=dbus.socket
Requires=dbus.socket
[Service] [Service]
Type=dbus Type=notify-reload
ReloadSignal=SIGUSR2
BusName=@APPID@ BusName=@APPID@
ExecStart=@GHOSTTY@ --launched-from=systemd ExecStart=@GHOSTTY@ --launched-from=systemd

View File

@ -350,6 +350,11 @@ typedef struct {
const char* message; const char* message;
} ghostty_diagnostic_s; } ghostty_diagnostic_s;
typedef struct {
const char* ptr;
uintptr_t len;
} ghostty_string_s;
typedef struct { typedef struct {
double tl_px_x; double tl_px_x;
double tl_px_y; double tl_px_y;
@ -797,6 +802,7 @@ int ghostty_init(uintptr_t, char**);
void ghostty_cli_try_action(void); void ghostty_cli_try_action(void);
ghostty_info_s ghostty_info(void); ghostty_info_s ghostty_info(void);
const char* ghostty_translate(const char*); const char* ghostty_translate(const char*);
void ghostty_string_free(ghostty_string_s);
ghostty_config_t ghostty_config_new(); ghostty_config_t ghostty_config_new();
void ghostty_config_free(ghostty_config_t); void ghostty_config_free(ghostty_config_t);
@ -811,7 +817,7 @@ ghostty_input_trigger_s ghostty_config_trigger(ghostty_config_t,
uintptr_t); uintptr_t);
uint32_t ghostty_config_diagnostics_count(ghostty_config_t); uint32_t ghostty_config_diagnostics_count(ghostty_config_t);
ghostty_diagnostic_s ghostty_config_get_diagnostic(ghostty_config_t, uint32_t); ghostty_diagnostic_s ghostty_config_get_diagnostic(ghostty_config_t, uint32_t);
void ghostty_config_open(); ghostty_string_s ghostty_config_open_path(void);
ghostty_app_t ghostty_app_new(const ghostty_runtime_config_s*, ghostty_app_t ghostty_app_new(const ghostty_runtime_config_s*,
ghostty_config_t); ghostty_config_t);

View File

@ -14,6 +14,7 @@
9351BE8E3D22937F003B3499 /* nvim in Resources */ = {isa = PBXBuildFile; fileRef = 9351BE8E2D22937F003B3499 /* nvim */; }; 9351BE8E3D22937F003B3499 /* nvim in Resources */ = {isa = PBXBuildFile; fileRef = 9351BE8E2D22937F003B3499 /* nvim */; };
A50297352DFA0F3400B4E924 /* Double+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A50297342DFA0F3300B4E924 /* Double+Extension.swift */; }; A50297352DFA0F3400B4E924 /* Double+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A50297342DFA0F3300B4E924 /* Double+Extension.swift */; };
A505D21D2E1A2FA20018808F /* FileHandle+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A505D21C2E1A2F9E0018808F /* FileHandle+Extension.swift */; }; A505D21D2E1A2FA20018808F /* FileHandle+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A505D21C2E1A2F9E0018808F /* FileHandle+Extension.swift */; };
A505D21F2E1B6DE00018808F /* NSWorkspace+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A505D21E2E1B6DDC0018808F /* NSWorkspace+Extension.swift */; };
A511940F2E050595007258CC /* CloseTerminalIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A511940E2E050590007258CC /* CloseTerminalIntent.swift */; }; A511940F2E050595007258CC /* CloseTerminalIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A511940E2E050590007258CC /* CloseTerminalIntent.swift */; };
A51194112E05A483007258CC /* QuickTerminalIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51194102E05A480007258CC /* QuickTerminalIntent.swift */; }; A51194112E05A483007258CC /* QuickTerminalIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51194102E05A480007258CC /* QuickTerminalIntent.swift */; };
A51194132E05D006007258CC /* Optional+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51194122E05D003007258CC /* Optional+Extension.swift */; }; A51194132E05D006007258CC /* Optional+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51194122E05D003007258CC /* Optional+Extension.swift */; };
@ -160,6 +161,7 @@
9351BE8E2D22937F003B3499 /* nvim */ = {isa = PBXFileReference; lastKnownFileType = folder; name = nvim; path = "../zig-out/share/nvim"; sourceTree = "<group>"; }; 9351BE8E2D22937F003B3499 /* nvim */ = {isa = PBXFileReference; lastKnownFileType = folder; name = nvim; path = "../zig-out/share/nvim"; sourceTree = "<group>"; };
A50297342DFA0F3300B4E924 /* Double+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Double+Extension.swift"; sourceTree = "<group>"; }; A50297342DFA0F3300B4E924 /* Double+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Double+Extension.swift"; sourceTree = "<group>"; };
A505D21C2E1A2F9E0018808F /* FileHandle+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileHandle+Extension.swift"; sourceTree = "<group>"; }; A505D21C2E1A2F9E0018808F /* FileHandle+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileHandle+Extension.swift"; sourceTree = "<group>"; };
A505D21E2E1B6DDC0018808F /* NSWorkspace+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSWorkspace+Extension.swift"; sourceTree = "<group>"; };
A511940E2E050590007258CC /* CloseTerminalIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloseTerminalIntent.swift; sourceTree = "<group>"; }; A511940E2E050590007258CC /* CloseTerminalIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloseTerminalIntent.swift; sourceTree = "<group>"; };
A51194102E05A480007258CC /* QuickTerminalIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickTerminalIntent.swift; sourceTree = "<group>"; }; A51194102E05A480007258CC /* QuickTerminalIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickTerminalIntent.swift; sourceTree = "<group>"; };
A51194122E05D003007258CC /* Optional+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optional+Extension.swift"; sourceTree = "<group>"; }; A51194122E05D003007258CC /* Optional+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optional+Extension.swift"; sourceTree = "<group>"; };
@ -531,6 +533,7 @@
AEE8B3442B9AA39600260C5E /* NSPasteboard+Extension.swift */, AEE8B3442B9AA39600260C5E /* NSPasteboard+Extension.swift */,
C1F26EA62B738B9900404083 /* NSView+Extension.swift */, C1F26EA62B738B9900404083 /* NSView+Extension.swift */,
A5874D9C2DAD785F00E83852 /* NSWindow+Extension.swift */, A5874D9C2DAD785F00E83852 /* NSWindow+Extension.swift */,
A505D21E2E1B6DDC0018808F /* NSWorkspace+Extension.swift */,
A5985CD62C320C4500C57AD3 /* String+Extension.swift */, A5985CD62C320C4500C57AD3 /* String+Extension.swift */,
A58636722DF4813000E04A10 /* UndoManager+Extension.swift */, A58636722DF4813000E04A10 /* UndoManager+Extension.swift */,
A5CC36142C9CDA03004D6760 /* View+Extension.swift */, A5CC36142C9CDA03004D6760 /* View+Extension.swift */,
@ -819,6 +822,7 @@
A5CC36152C9CDA06004D6760 /* View+Extension.swift in Sources */, A5CC36152C9CDA06004D6760 /* View+Extension.swift in Sources */,
A56D58892ACDE6CA00508D2C /* ServiceProvider.swift in Sources */, A56D58892ACDE6CA00508D2C /* ServiceProvider.swift in Sources */,
A5CBD0602CA0C90A0017A1AE /* QuickTerminalWindow.swift in Sources */, A5CBD0602CA0C90A0017A1AE /* QuickTerminalWindow.swift in Sources */,
A505D21F2E1B6DE00018808F /* NSWorkspace+Extension.swift in Sources */,
A5CBD05E2CA0C5EC0017A1AE /* QuickTerminalController.swift in Sources */, A5CBD05E2CA0C5EC0017A1AE /* QuickTerminalController.swift in Sources */,
A5CF66D72D29DDB500139794 /* Ghostty.Event.swift in Sources */, A5CF66D72D29DDB500139794 /* Ghostty.Event.swift in Sources */,
A511940F2E050595007258CC /* CloseTerminalIntent.swift in Sources */, A511940F2E050595007258CC /* CloseTerminalIntent.swift in Sources */,

View File

@ -932,7 +932,7 @@ class AppDelegate: NSObject,
//MARK: - IB Actions //MARK: - IB Actions
@IBAction func openConfig(_ sender: Any?) { @IBAction func openConfig(_ sender: Any?) {
ghostty.openConfig() Ghostty.App.openConfig()
} }
@IBAction func reloadConfig(_ sender: Any?) { @IBAction func reloadConfig(_ sender: Any?) {

View File

@ -40,4 +40,34 @@ extension Ghostty.Action {
self.amount = c.amount self.amount = c.amount
} }
} }
struct OpenURL {
enum Kind {
case unknown
case text
init(_ c: ghostty_action_open_url_kind_e) {
switch c {
case GHOSTTY_ACTION_OPEN_URL_KIND_TEXT:
self = .text
default:
self = .unknown
}
}
}
let kind: Kind
let url: String
init(c: ghostty_action_open_url_s) {
self.kind = Kind(c.kind)
if let urlCString = c.url {
let data = Data(bytes: urlCString, count: Int(c.len))
self.url = String(data: data, encoding: .utf8) ?? ""
} else {
self.url = ""
}
}
}
} }

View File

@ -114,9 +114,21 @@ extension Ghostty {
ghostty_app_tick(app) ghostty_app_tick(app)
} }
func openConfig() { static func openConfig() {
guard let app = self.app else { return } let str = Ghostty.AllocatedString(ghostty_config_open_path()).string
ghostty_app_open_config(app) guard !str.isEmpty else { return }
#if os(macOS)
let fileURL = URL(fileURLWithPath: str).absoluteString
var action = ghostty_action_open_url_s()
action.kind = GHOSTTY_ACTION_OPEN_URL_KIND_TEXT
fileURL.withCString { cStr in
action.url = cStr
action.len = UInt(fileURL.count)
_ = openURL(action)
}
#else
fatalError("Unsupported platform for opening config file")
#endif
} }
/// Reload the configuration. /// Reload the configuration.
@ -488,7 +500,7 @@ extension Ghostty {
pwdChanged(app, target: target, v: action.action.pwd) pwdChanged(app, target: target, v: action.action.pwd)
case GHOSTTY_ACTION_OPEN_CONFIG: case GHOSTTY_ACTION_OPEN_CONFIG:
ghostty_config_open() openConfig()
case GHOSTTY_ACTION_FLOAT_WINDOW: case GHOSTTY_ACTION_FLOAT_WINDOW:
toggleFloatWindow(app, target: target, mode: action.action.float_window) toggleFloatWindow(app, target: target, mode: action.action.float_window)
@ -547,6 +559,9 @@ extension Ghostty {
case GHOSTTY_ACTION_CHECK_FOR_UPDATES: case GHOSTTY_ACTION_CHECK_FOR_UPDATES:
checkForUpdates(app) checkForUpdates(app)
case GHOSTTY_ACTION_OPEN_URL:
return openURL(action.action.open_url)
case GHOSTTY_ACTION_UNDO: case GHOSTTY_ACTION_UNDO:
return undo(app, target: target) return undo(app, target: target)
@ -599,6 +614,34 @@ extension Ghostty {
} }
} }
private static func openURL(
_ v: ghostty_action_open_url_s
) -> Bool {
let action = Ghostty.Action.OpenURL(c: v)
// Convert the URL string to a URL object
guard let url = URL(string: action.url) else {
Ghostty.logger.warning("invalid URL for open URL action: \(action.url)")
return false
}
switch action.kind {
case .text:
// Open with the default text editor
if let textEditor = NSWorkspace.shared.defaultTextEditor {
NSWorkspace.shared.open([url], withApplicationAt: textEditor, configuration: NSWorkspace.OpenConfiguration())
return true
}
case .unknown:
break
}
// Open with the default application for the URL
NSWorkspace.shared.open(url)
return true
}
private static func undo(_ app: ghostty_app_t, target: ghostty_target_s) -> Bool { private static func undo(_ app: ghostty_app_t, target: ghostty_target_s) -> Bool {
let undoManager: UndoManager? let undoManager: UndoManager?
switch (target.tag) { switch (target.tag) {

View File

@ -73,6 +73,26 @@ extension Ghostty {
// MARK: Swift Types for C Types // MARK: Swift Types for C Types
extension Ghostty {
class AllocatedString {
private let cString: ghostty_string_s
init(_ c: ghostty_string_s) {
self.cString = c
}
var string: String {
guard let ptr = cString.ptr else { return "" }
let data = Data(bytes: ptr, count: Int(cString.len))
return String(data: data, encoding: .utf8) ?? ""
}
deinit {
ghostty_string_free(cString)
}
}
}
extension Ghostty { extension Ghostty {
enum SetFloatWIndow { enum SetFloatWIndow {
case on case on

View File

@ -0,0 +1,29 @@
import AppKit
import UniformTypeIdentifiers
extension NSWorkspace {
/// Returns the URL of the default text editor application.
/// - Returns: The URL of the default text editor, or nil if no default text editor is found.
var defaultTextEditor: URL? {
defaultApplicationURL(forContentType: UTType.plainText.identifier)
}
/// Returns the URL of the default application for opening files with the specified content type.
/// - Parameter contentType: The content type identifier (UTI) to find the default application for.
/// - Returns: The URL of the default application, or nil if no default application is found.
func defaultApplicationURL(forContentType contentType: String) -> URL? {
return LSCopyDefaultApplicationURLForContentType(
contentType as CFString,
.all,
nil
)?.takeRetainedValue() as? URL
}
/// Returns the URL of the default application for opening files with the specified file extension.
/// - Parameter ext: The file extension to find the default application for.
/// - Returns: The URL of the default application, or nil if no default application is found.
func defaultApplicationURL(forExtension ext: String) -> URL? {
guard let uti = UTType(filenameExtension: ext) else { return nil}
return defaultApplicationURL(forContentType: uti.identifier)
}
}

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-04-23 16:58+0800\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-05-19 11:34+0300\n" "PO-Revision-Date: 2025-05-19 11:34+0300\n"
"Last-Translator: Damyan Bogoev <damyan.bogoev@gmail.com>\n" "Last-Translator: Damyan Bogoev <damyan.bogoev@gmail.com>\n"
"Language-Team: Bulgarian <dict@ludost.net>\n" "Language-Team: Bulgarian <dict@ludost.net>\n"
@ -26,7 +26,8 @@ msgid "Leave blank to restore the default title."
msgstr "Оставете празно за възстановяване на заглавието по подразбиране." msgstr "Оставете празно за възстановяване на заглавието по подразбиране."
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9 #: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
#: src/apprt/gtk/CloseDialog.zig:44
msgid "Cancel" msgid "Cancel"
msgstr "Отказ" msgstr "Отказ"
@ -35,22 +36,28 @@ msgid "OK"
msgstr "ОК" msgstr "ОК"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
msgid "Configuration Errors" msgid "Configuration Errors"
msgstr "Грешки в конфигурацията" msgstr "Грешки в конфигурацията"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors " "One or more configuration errors were found. Please review the errors below, "
"below, and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
msgstr "Открити са една или повече грешки в конфигурацията. Моля, прегледайте грешките по-долу и или презаредете конфигурацията си, или ги игнорирайте." msgstr ""
"Открити са една или повече грешки в конфигурацията. Моля, прегледайте "
"грешките по-долу и или презаредете конфигурацията си, или ги игнорирайте."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
msgstr "Игнорирай" msgstr "Игнорирай"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Презареди конфигурацията" msgstr "Презареди конфигурацията"
@ -89,7 +96,7 @@ msgstr "Копирай"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
msgid "Paste" msgid "Paste"
msgstr "Постави" msgstr "Постави"
@ -119,7 +126,7 @@ msgstr "Раздел"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:255 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "Нов раздел" msgstr "Нов раздел"
@ -160,7 +167,7 @@ msgid "Terminal Inspector"
msgstr "Инспектор на терминала" msgstr "Инспектор на терминала"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1024 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "За Ghostty" msgstr "За Ghostty"
@ -170,69 +177,64 @@ msgstr "Изход"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
msgid "Authorize Clipboard Access" msgid "Authorize Clipboard Access"
msgstr "Разрешаване на достъп до клипборда" msgstr "Разрешаване на достъп до клипборда"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
msgstr "Приложение се опитва да чете от клипборда. Текущото съдържание на клипборда е показано по-долу." msgstr ""
"Приложение се опитва да чете от клипборда. Текущото съдържание на клипборда "
"е показано по-долу."
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
msgid "Deny" msgid "Deny"
msgstr "Откажи" msgstr "Откажи"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
msgid "Allow" msgid "Allow"
msgstr "Позволи" msgstr "Позволи"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
msgstr "Приложение се опитва да запише в клипборда. Текущото съдържание на клипборда е показано по-долу." msgstr ""
"Приложение се опитва да запише в клипборда. Текущото съдържание на клипборда "
"е показано по-долу."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
msgstr "Предупреждение: Потенциално опасно поставяне" msgstr "Предупреждение: Потенциално опасно поставяне"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
msgstr "Поставянето на този текст в терминала може да е опасно, тъй като изглежда, че може да бъдат изпълнени някои команди." msgstr ""
"Поставянето на този текст в терминала може да е опасно, тъй като изглежда, "
#: src/apprt/gtk/Window.zig:208 "че може да бъдат изпълнени някои команди."
msgid "Main Menu"
msgstr "Главно меню"
#: src/apprt/gtk/Window.zig:229
msgid "View Open Tabs"
msgstr "Преглед на отворените раздели"
#: src/apprt/gtk/Window.zig:256
msgid "New Split"
msgstr "Ново разделяне"
#: src/apprt/gtk/Window.zig:319
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "⚠️ Използвате дебъг версия на Ghostty! Производителността ще бъде намалена."
#: src/apprt/gtk/Window.zig:765
msgid "Reloaded the configuration"
msgstr "Конфигурацията е презаредена"
#: src/apprt/gtk/Window.zig:1005
msgid "Ghostty Developers"
msgstr "Разработчици на Ghostty"
#: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: Инспектор на терминала"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
@ -270,6 +272,36 @@ msgstr "Всички терминални сесии в този раздел щ
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "Текущият процес в това разделяне ще бъде прекратен." msgstr "Текущият процес в това разделяне ще бъде прекратен."
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "Копирано в клипборда" msgstr "Копирано в клипборда"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "Главно меню"
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr "Преглед на отворените раздели"
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr "Ново разделяне"
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Използвате дебъг версия на Ghostty! Производителността ще бъде намалена."
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr "Конфигурацията е презаредена"
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr "Разработчици на Ghostty"
#: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: Инспектор на терминала"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-04-22 08:57-0700\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-03-20 08:07+0100\n" "PO-Revision-Date: 2025-03-20 08:07+0100\n"
"Last-Translator: Francesc Arpi <francesc.arpi@gmail.com>\n" "Last-Translator: Francesc Arpi <francesc.arpi@gmail.com>\n"
"Language-Team: \n" "Language-Team: \n"
@ -26,7 +26,8 @@ msgid "Leave blank to restore the default title."
msgstr "Deixa en blanc per restaurar el títol per defecte." msgstr "Deixa en blanc per restaurar el títol per defecte."
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9 #: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
#: src/apprt/gtk/CloseDialog.zig:44
msgid "Cancel" msgid "Cancel"
msgstr "Cancel·la" msgstr "Cancel·la"
@ -35,10 +36,12 @@ msgid "OK"
msgstr "D'acord" msgstr "D'acord"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
msgid "Configuration Errors" msgid "Configuration Errors"
msgstr "Errors de configuració" msgstr "Errors de configuració"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
@ -47,12 +50,14 @@ msgstr ""
"a continuació i torna a carregar la configuració o ignora aquests errors." "a continuació i torna a carregar la configuració o ignora aquests errors."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
msgstr "Ignora" msgstr "Ignora"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Carrega la configuració" msgstr "Carrega la configuració"
@ -80,6 +85,10 @@ msgstr "Divideix a l'esquerra"
msgid "Split Right" msgid "Split Right"
msgstr "Divideix a la dreta" msgstr "Divideix a la dreta"
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
msgid "Execute a command…"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -87,7 +96,7 @@ msgstr "Copia"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
msgid "Paste" msgid "Paste"
msgstr "Enganxa" msgstr "Enganxa"
@ -117,7 +126,7 @@ msgstr "Pestanya"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:248 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "Nova pestanya" msgstr "Nova pestanya"
@ -145,29 +154,36 @@ msgid "Config"
msgstr "Configuració" msgstr "Configuració"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
msgid "Open Configuration" msgid "Open Configuration"
msgstr "Obre la configuració" msgstr "Obre la configuració"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
msgid "Command Palette"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
msgid "Terminal Inspector" msgid "Terminal Inspector"
msgstr "Inspector de terminal" msgstr "Inspector de terminal"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1003 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Sobre Ghostty" msgstr "Sobre Ghostty"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
msgid "Quit" msgid "Quit"
msgstr "Surt" msgstr "Surt"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
msgid "Authorize Clipboard Access" msgid "Authorize Clipboard Access"
msgstr "Autoritza l'accés al porta-retalls" msgstr "Autoritza l'accés al porta-retalls"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -177,15 +193,30 @@ msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
msgid "Deny" msgid "Deny"
msgstr "Denegar" msgstr "Denegar"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
msgid "Allow" msgid "Allow"
msgstr "Permet" msgstr "Permet"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -193,11 +224,11 @@ msgstr ""
"Una aplicació està intentant escriure al porta-retalls. El contingut actual " "Una aplicació està intentant escriure al porta-retalls. El contingut actual "
"del porta-retalls es mostra a continuació." "del porta-retalls es mostra a continuació."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
msgstr "Avís: Enganxament potencialment insegur" msgstr "Avís: Enganxament potencialment insegur"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
@ -205,33 +236,6 @@ msgstr ""
"Enganxar aquest text al terminal pot ser perillós, ja que sembla que es " "Enganxar aquest text al terminal pot ser perillós, ja que sembla que es "
"podrien executar algunes ordres." "podrien executar algunes ordres."
#: src/apprt/gtk/Window.zig:201
msgid "Main Menu"
msgstr "Menú principal"
#: src/apprt/gtk/Window.zig:222
msgid "View Open Tabs"
msgstr "Mostra les pestanyes obertes"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Estàs executant una versió de depuració de Ghostty! El rendiment es veurà "
"afectat."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "S'ha tornat a carregar la configuració"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Desenvolupadors de Ghostty"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
msgstr "Tanca" msgstr "Tanca"
@ -268,10 +272,37 @@ msgstr "Totes les sessions del terminal en aquesta pestanya es tancaran."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "El procés actualment en execució en aquesta divisió es tancarà." msgstr "El procés actualment en execució en aquesta divisió es tancarà."
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "Copiat al porta-retalls" msgstr "Copiat al porta-retalls"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "Menú principal"
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr "Mostra les pestanyes obertes"
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Estàs executant una versió de depuració de Ghostty! El rendiment es veurà "
"afectat."
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr "S'ha tornat a carregar la configuració"
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr "Desenvolupadors de Ghostty"
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector" msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: Inspector de terminal" msgstr "Ghostty: Inspector de terminal"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-06-28 17:01+0200\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -124,7 +124,7 @@ msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:263 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "" msgstr ""
@ -165,7 +165,7 @@ msgid "Terminal Inspector"
msgstr "" msgstr ""
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1036 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "" msgstr ""
@ -228,35 +228,6 @@ msgid ""
"commands may be executed." "commands may be executed."
msgstr "" msgstr ""
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr ""
#: src/apprt/gtk/Window.zig:238
msgid "View Open Tabs"
msgstr ""
#: src/apprt/gtk/Window.zig:264
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:327
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
#: src/apprt/gtk/Window.zig:773
msgid "Reloaded the configuration"
msgstr ""
#: src/apprt/gtk/Window.zig:1017
msgid "Ghostty Developers"
msgstr ""
#: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector"
msgstr ""
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
msgstr "" msgstr ""
@ -296,3 +267,32 @@ msgstr ""
#: src/apprt/gtk/Surface.zig:1257 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "" msgstr ""
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr ""
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr ""
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr ""
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr ""
#: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector"
msgstr ""

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-04-22 08:57-0700\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-03-06 14:57+0100\n" "PO-Revision-Date: 2025-03-06 14:57+0100\n"
"Last-Translator: Robin <r@rpfaeffle.com>\n" "Last-Translator: Robin <r@rpfaeffle.com>\n"
"Language-Team: German <translation-team-de@lists.sourceforge.net>\n" "Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
@ -27,7 +27,8 @@ msgid "Leave blank to restore the default title."
msgstr "Leer lassen, um den Standardtitel wiederherzustellen." msgstr "Leer lassen, um den Standardtitel wiederherzustellen."
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9 #: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
#: src/apprt/gtk/CloseDialog.zig:44
msgid "Cancel" msgid "Cancel"
msgstr "Abbrechen" msgstr "Abbrechen"
@ -36,22 +37,26 @@ msgid "OK"
msgstr "OK" msgstr "OK"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
msgid "Configuration Errors" msgid "Configuration Errors"
msgstr "" msgstr ""
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
msgstr "" msgstr ""
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
msgstr "" msgstr ""
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Konfiguration neu laden" msgstr "Konfiguration neu laden"
@ -79,6 +84,10 @@ msgstr "Fenter nach links teilen"
msgid "Split Right" msgid "Split Right"
msgstr "Fenster nach rechts teilen" msgstr "Fenster nach rechts teilen"
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
msgid "Execute a command…"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -86,7 +95,7 @@ msgstr "Kopieren"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
msgid "Paste" msgid "Paste"
msgstr "Einfügen" msgstr "Einfügen"
@ -116,7 +125,7 @@ msgstr "Tab"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:248 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "Neuer Tab" msgstr "Neuer Tab"
@ -144,29 +153,36 @@ msgid "Config"
msgstr "Konfiguration" msgstr "Konfiguration"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
msgid "Open Configuration" msgid "Open Configuration"
msgstr "Konfiguration öffnen" msgstr "Konfiguration öffnen"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
msgid "Command Palette"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
msgid "Terminal Inspector" msgid "Terminal Inspector"
msgstr "Terminalinspektor" msgstr "Terminalinspektor"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1003 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Über Ghostty" msgstr "Über Ghostty"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
msgid "Quit" msgid "Quit"
msgstr "Beenden" msgstr "Beenden"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
msgid "Authorize Clipboard Access" msgid "Authorize Clipboard Access"
msgstr "Zugriff auf die Zwischenablage gewähren" msgstr "Zugriff auf die Zwischenablage gewähren"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -176,15 +192,30 @@ msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
msgid "Deny" msgid "Deny"
msgstr "Nicht erlauben" msgstr "Nicht erlauben"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
msgid "Allow" msgid "Allow"
msgstr "Erlauben" msgstr "Erlauben"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -192,11 +223,11 @@ msgstr ""
"Eine Anwendung versucht in die Zwischenablage zu schreiben. Der aktuelle " "Eine Anwendung versucht in die Zwischenablage zu schreiben. Der aktuelle "
"Inhalt der Zwischenablage wird unten angezeigt." "Inhalt der Zwischenablage wird unten angezeigt."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
msgstr "Achtung: Möglicherweise unsicheres Einfügen" msgstr "Achtung: Möglicherweise unsicheres Einfügen"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
@ -204,33 +235,6 @@ msgstr ""
"Diesen Text in das Terminal einzufügen könnte möglicherweise gefährlich " "Diesen Text in das Terminal einzufügen könnte möglicherweise gefährlich "
"sein. Es scheint, dass Anweisungen ausgeführt werden könnten." "sein. Es scheint, dass Anweisungen ausgeführt werden könnten."
#: src/apprt/gtk/Window.zig:201
msgid "Main Menu"
msgstr "Hauptmenü"
#: src/apprt/gtk/Window.zig:222
msgid "View Open Tabs"
msgstr "Offene Tabs einblenden"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Du verwendest einen Debug Build von Ghostty! Die Leistung wird reduziert "
"sein."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Konfiguration wurde neu geladen"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Ghostty-Entwickler"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
msgstr "Schließen" msgstr "Schließen"
@ -267,10 +271,37 @@ msgstr "Alle Terminalsitzungen in diesem Tab werden beendet."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "Der aktuell laufende Prozess in diesem geteilten Fenster wird beendet." msgstr "Der aktuell laufende Prozess in diesem geteilten Fenster wird beendet."
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "In die Zwischenablage kopiert" msgstr "In die Zwischenablage kopiert"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "Hauptmenü"
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr "Offene Tabs einblenden"
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Du verwendest einen Debug Build von Ghostty! Die Leistung wird reduziert "
"sein."
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr "Konfiguration wurde neu geladen"
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr "Ghostty-Entwickler"
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector" msgid "Ghostty: Terminal Inspector"
msgstr "" msgstr ""

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-04-23 16:58+0800\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-05-19 20:17-0300\n" "PO-Revision-Date: 2025-05-19 20:17-0300\n"
"Last-Translator: Alan Moyano <alanmoyano203@gmail.com>\n" "Last-Translator: Alan Moyano <alanmoyano203@gmail.com>\n"
"Language-Team: Argentinian <es@tp.org.es>\n" "Language-Team: Argentinian <es@tp.org.es>\n"
@ -26,7 +26,8 @@ msgid "Leave blank to restore the default title."
msgstr "Dejar en blanco para restaurar el título predeterminado." msgstr "Dejar en blanco para restaurar el título predeterminado."
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9 #: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
#: src/apprt/gtk/CloseDialog.zig:44
msgid "Cancel" msgid "Cancel"
msgstr "Cancelar" msgstr "Cancelar"
@ -35,10 +36,12 @@ msgid "OK"
msgstr "Aceptar" msgstr "Aceptar"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
msgid "Configuration Errors" msgid "Configuration Errors"
msgstr "Errores de configuración" msgstr "Errores de configuración"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
@ -47,12 +50,14 @@ msgstr ""
"errores a continuación, y recargá tu configuración o ignorá estos errores." "errores a continuación, y recargá tu configuración o ignorá estos errores."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
msgstr "Ignorar" msgstr "Ignorar"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Recargar configuración" msgstr "Recargar configuración"
@ -91,7 +96,7 @@ msgstr "Copiar"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
msgid "Paste" msgid "Paste"
msgstr "Pegar" msgstr "Pegar"
@ -121,7 +126,7 @@ msgstr "Pestaña"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:255 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "Nueva pestaña" msgstr "Nueva pestaña"
@ -162,7 +167,7 @@ msgid "Terminal Inspector"
msgstr "Inspector de la terminal" msgstr "Inspector de la terminal"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1024 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Acerca de Ghostty" msgstr "Acerca de Ghostty"
@ -172,10 +177,13 @@ msgstr "Salir"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
msgid "Authorize Clipboard Access" msgid "Authorize Clipboard Access"
msgstr "Autorizar acceso al portapapeles" msgstr "Autorizar acceso al portapapeles"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -185,15 +193,30 @@ msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
msgid "Deny" msgid "Deny"
msgstr "Denegar" msgstr "Denegar"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
msgid "Allow" msgid "Allow"
msgstr "Permitir" msgstr "Permitir"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -201,11 +224,11 @@ msgstr ""
"Una aplicación está intentando escribir en el portapapeles. El contenido " "Una aplicación está intentando escribir en el portapapeles. El contenido "
"actual del portapapeles se muestra a continuación." "actual del portapapeles se muestra a continuación."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
msgstr "Advertencia: Pegado potencialmente inseguro" msgstr "Advertencia: Pegado potencialmente inseguro"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
@ -213,37 +236,6 @@ msgstr ""
"Pegar este texto en la terminal puede ser peligroso ya que parece que " "Pegar este texto en la terminal puede ser peligroso ya que parece que "
"algunos comandos podrían ejecutarse." "algunos comandos podrían ejecutarse."
#: src/apprt/gtk/Window.zig:208
msgid "Main Menu"
msgstr "Menú principal"
#: src/apprt/gtk/Window.zig:229
msgid "View Open Tabs"
msgstr "Ver pestañas abiertas"
#: src/apprt/gtk/Window.zig:256
msgid "New Split"
msgstr "Nueva división"
#: src/apprt/gtk/Window.zig:319
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Estás ejecutando una versión de depuración de Ghostty. El rendimiento no "
"será óptimo."
#: src/apprt/gtk/Window.zig:765
msgid "Reloaded the configuration"
msgstr "Configuración recargada"
#: src/apprt/gtk/Window.zig:1005
msgid "Ghostty Developers"
msgstr "Desarrolladores de Ghostty"
#: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: Inspector de la terminal"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
msgstr "Cerrar" msgstr "Cerrar"
@ -280,6 +272,37 @@ msgstr "Todas las sesiones de terminal en esta pestaña serán terminadas."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "El proceso actualmente en ejecución en esta división será terminado." msgstr "El proceso actualmente en ejecución en esta división será terminado."
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "Copiado al portapapeles" msgstr "Copiado al portapapeles"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "Menú principal"
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr "Ver pestañas abiertas"
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr "Nueva división"
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Estás ejecutando una versión de depuración de Ghostty. El rendimiento no "
"será óptimo."
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr "Configuración recargada"
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr "Desarrolladores de Ghostty"
#: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: Inspector de la terminal"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-04-22 08:57-0700\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-03-28 17:46+0200\n" "PO-Revision-Date: 2025-03-28 17:46+0200\n"
"Last-Translator: Miguel Peredo <miguelp@quientienemail.com>\n" "Last-Translator: Miguel Peredo <miguelp@quientienemail.com>\n"
"Language-Team: Spanish <es@tp.org.es>\n" "Language-Team: Spanish <es@tp.org.es>\n"
@ -26,7 +26,8 @@ msgid "Leave blank to restore the default title."
msgstr "Dejar en blanco para restaurar el título predeterminado." msgstr "Dejar en blanco para restaurar el título predeterminado."
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9 #: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
#: src/apprt/gtk/CloseDialog.zig:44
msgid "Cancel" msgid "Cancel"
msgstr "Cancelar" msgstr "Cancelar"
@ -35,10 +36,12 @@ msgid "OK"
msgstr "Aceptar" msgstr "Aceptar"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
msgid "Configuration Errors" msgid "Configuration Errors"
msgstr "Errores de configuración" msgstr "Errores de configuración"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
@ -47,12 +50,14 @@ msgstr ""
"errores a continuación, y recargue su configuración o ignore estos errores." "errores a continuación, y recargue su configuración o ignore estos errores."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
msgstr "Ignorar" msgstr "Ignorar"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Recargar configuración" msgstr "Recargar configuración"
@ -80,6 +85,10 @@ msgstr "Dividir a la izquierda"
msgid "Split Right" msgid "Split Right"
msgstr "Dividir a la derecha" msgstr "Dividir a la derecha"
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
msgid "Execute a command…"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -87,7 +96,7 @@ msgstr "Copiar"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
msgid "Paste" msgid "Paste"
msgstr "Pegar" msgstr "Pegar"
@ -117,7 +126,7 @@ msgstr "Pestaña"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:248 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "Nueva pestaña" msgstr "Nueva pestaña"
@ -145,29 +154,36 @@ msgid "Config"
msgstr "Configuración" msgstr "Configuración"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
msgid "Open Configuration" msgid "Open Configuration"
msgstr "Abrir configuración" msgstr "Abrir configuración"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
msgid "Command Palette"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
msgid "Terminal Inspector" msgid "Terminal Inspector"
msgstr "Inspector de la terminal" msgstr "Inspector de la terminal"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1003 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Acerca de Ghostty" msgstr "Acerca de Ghostty"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
msgid "Quit" msgid "Quit"
msgstr "Salir" msgstr "Salir"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
msgid "Authorize Clipboard Access" msgid "Authorize Clipboard Access"
msgstr "Autorizar acceso al portapapeles" msgstr "Autorizar acceso al portapapeles"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -177,15 +193,30 @@ msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
msgid "Deny" msgid "Deny"
msgstr "Denegar" msgstr "Denegar"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
msgid "Allow" msgid "Allow"
msgstr "Permitir" msgstr "Permitir"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -193,11 +224,11 @@ msgstr ""
"Una aplicación está intentando escribir en el portapapeles. El contenido " "Una aplicación está intentando escribir en el portapapeles. El contenido "
"actual del portapapeles se muestra a continuación." "actual del portapapeles se muestra a continuación."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
msgstr "Advertencia: Pegado potencialmente inseguro" msgstr "Advertencia: Pegado potencialmente inseguro"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
@ -205,33 +236,6 @@ msgstr ""
"Pegar este texto en la terminal puede ser peligroso ya que parece que " "Pegar este texto en la terminal puede ser peligroso ya que parece que "
"algunos comandos podrían ejecutarse." "algunos comandos podrían ejecutarse."
#: src/apprt/gtk/Window.zig:201
msgid "Main Menu"
msgstr "Menú principal"
#: src/apprt/gtk/Window.zig:222
msgid "View Open Tabs"
msgstr "Ver pestañas abiertas"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Está ejecutando una versión de depuración de Ghostty. El rendimiento no "
"será óptimo."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Configuración recargada"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Desarrolladores de Ghostty"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
msgstr "Cerrar" msgstr "Cerrar"
@ -268,10 +272,37 @@ msgstr "Todas las sesiones de terminal en esta pestaña serán terminadas."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "El proceso actualmente en ejecución en esta división será terminado." msgstr "El proceso actualmente en ejecución en esta división será terminado."
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "Copiado al portapapeles" msgstr "Copiado al portapapeles"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "Menú principal"
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr "Ver pestañas abiertas"
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Está ejecutando una versión de depuración de Ghostty. El rendimiento no "
"será óptimo."
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr "Configuración recargada"
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr "Desarrolladores de Ghostty"
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector" msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: Inspector de la terminal" msgstr "Ghostty: Inspector de la terminal"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-04-22 08:57-0700\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-03-22 09:31+0100\n" "PO-Revision-Date: 2025-03-22 09:31+0100\n"
"Last-Translator: Kirwiisp <swiip__@hotmail.com>\n" "Last-Translator: Kirwiisp <swiip__@hotmail.com>\n"
"Language-Team: French <traduc@traduc.org>\n" "Language-Team: French <traduc@traduc.org>\n"
@ -26,7 +26,8 @@ msgid "Leave blank to restore the default title."
msgstr "Laisser vide pour restaurer le titre par défaut." msgstr "Laisser vide pour restaurer le titre par défaut."
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9 #: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
#: src/apprt/gtk/CloseDialog.zig:44
msgid "Cancel" msgid "Cancel"
msgstr "Annuler" msgstr "Annuler"
@ -35,10 +36,12 @@ msgid "OK"
msgstr "OK" msgstr "OK"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
msgid "Configuration Errors" msgid "Configuration Errors"
msgstr "Erreurs de configuration" msgstr "Erreurs de configuration"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
@ -48,12 +51,14 @@ msgstr ""
"erreurs." "erreurs."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
msgstr "Ignorer" msgstr "Ignorer"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Recharger la configuration" msgstr "Recharger la configuration"
@ -81,6 +86,10 @@ msgstr "Panneau à gauche"
msgid "Split Right" msgid "Split Right"
msgstr "Panneau à droite" msgstr "Panneau à droite"
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
msgid "Execute a command…"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -88,7 +97,7 @@ msgstr "Copier"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
msgid "Paste" msgid "Paste"
msgstr "Coller" msgstr "Coller"
@ -118,7 +127,7 @@ msgstr "Onglet"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:248 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "Nouvel onglet" msgstr "Nouvel onglet"
@ -146,29 +155,36 @@ msgid "Config"
msgstr "Config" msgstr "Config"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
msgid "Open Configuration" msgid "Open Configuration"
msgstr "Ouvrir la configuration" msgstr "Ouvrir la configuration"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
msgid "Command Palette"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
msgid "Terminal Inspector" msgid "Terminal Inspector"
msgstr "Inspecteur de terminal" msgstr "Inspecteur de terminal"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1003 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "À propos de Ghostty" msgstr "À propos de Ghostty"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
msgid "Quit" msgid "Quit"
msgstr "Quitter" msgstr "Quitter"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
msgid "Authorize Clipboard Access" msgid "Authorize Clipboard Access"
msgstr "Autoriser l'accès au presse-papiers" msgstr "Autoriser l'accès au presse-papiers"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -178,15 +194,30 @@ msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
msgid "Deny" msgid "Deny"
msgstr "Refuser" msgstr "Refuser"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
msgid "Allow" msgid "Allow"
msgstr "Autoriser" msgstr "Autoriser"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -194,11 +225,11 @@ msgstr ""
"Une application essaie d'écrire dans le presse-papiers.Le contenu actuel du " "Une application essaie d'écrire dans le presse-papiers.Le contenu actuel du "
"presse-papiers est affiché ci-dessous." "presse-papiers est affiché ci-dessous."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
msgstr "Attention: Collage potentiellement dangereux" msgstr "Attention: Collage potentiellement dangereux"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
@ -206,33 +237,6 @@ msgstr ""
"Coller ce texte dans le terminal pourrait être dangereux, il semblerait que " "Coller ce texte dans le terminal pourrait être dangereux, il semblerait que "
"certaines commandes pourraient être exécutées." "certaines commandes pourraient être exécutées."
#: src/apprt/gtk/Window.zig:201
msgid "Main Menu"
msgstr "Menu principal"
#: src/apprt/gtk/Window.zig:222
msgid "View Open Tabs"
msgstr "Voir les onglets ouverts"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Vous utilisez une version de débogage de Ghostty ! Les performances seront "
"dégradées."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Recharger la configuration"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Les développeurs de Ghostty"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
msgstr "Fermer" msgstr "Fermer"
@ -269,10 +273,37 @@ msgstr "Toutes les sessions de cet onglet vont être arrêtées."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "Le processus en cours dans ce panneau va être arrêté." msgstr "Le processus en cours dans ce panneau va être arrêté."
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "Copié dans le presse-papiers" msgstr "Copié dans le presse-papiers"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "Menu principal"
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr "Voir les onglets ouverts"
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Vous utilisez une version de débogage de Ghostty ! Les performances seront "
"dégradées."
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr "Recharger la configuration"
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr "Les développeurs de Ghostty"
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector" msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: Inspecteur" msgstr "Ghostty: Inspecteur"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-04-23 16:58+0800\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-06-29 21:15+0100\n" "PO-Revision-Date: 2025-06-29 21:15+0100\n"
"Last-Translator: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>\n" "Last-Translator: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>\n"
"Language-Team: Irish <gaeilge-gnulinux@lists.sourceforge.net>\n" "Language-Team: Irish <gaeilge-gnulinux@lists.sourceforge.net>\n"
@ -27,7 +27,8 @@ msgid "Leave blank to restore the default title."
msgstr "Fág bán chun an teideal réamhshocraithe a athbhunú." msgstr "Fág bán chun an teideal réamhshocraithe a athbhunú."
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9 #: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
#: src/apprt/gtk/CloseDialog.zig:44
msgid "Cancel" msgid "Cancel"
msgstr "Cealaigh" msgstr "Cealaigh"
@ -36,10 +37,12 @@ msgid "OK"
msgstr "Ceart go leor" msgstr "Ceart go leor"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
msgid "Configuration Errors" msgid "Configuration Errors"
msgstr "Earráidí cumraíochta" msgstr "Earráidí cumraíochta"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
@ -48,12 +51,14 @@ msgstr ""
"thíos, agus athlódáil do chumraíocht nó déan neamhaird de na hearráidí seo." "thíos, agus athlódáil do chumraíocht nó déan neamhaird de na hearráidí seo."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
msgstr "Déan neamhaird de" msgstr "Déan neamhaird de"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Athlódáil cumraíocht" msgstr "Athlódáil cumraíocht"
@ -92,7 +97,7 @@ msgstr "Cóipeáil"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
msgid "Paste" msgid "Paste"
msgstr "Greamaigh" msgstr "Greamaigh"
@ -122,7 +127,7 @@ msgstr "Táb"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:255 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "Táb nua" msgstr "Táb nua"
@ -163,7 +168,7 @@ msgid "Terminal Inspector"
msgstr "Cigire teirminéil" msgstr "Cigire teirminéil"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1024 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Maidir le Ghostty" msgstr "Maidir le Ghostty"
@ -173,10 +178,13 @@ msgstr "Scoir"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
msgid "Authorize Clipboard Access" msgid "Authorize Clipboard Access"
msgstr "Údarú rochtain ar an ngearrthaisce" msgstr "Údarú rochtain ar an ngearrthaisce"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -186,15 +194,30 @@ msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
msgid "Deny" msgid "Deny"
msgstr "Diúltaigh" msgstr "Diúltaigh"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
msgid "Allow" msgid "Allow"
msgstr "Ceadaigh" msgstr "Ceadaigh"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -202,11 +225,11 @@ msgstr ""
"Tá feidhmchlár ag iarraidh scríobh chuig an ngearrthaisce. Taispeántar ábhar " "Tá feidhmchlár ag iarraidh scríobh chuig an ngearrthaisce. Taispeántar ábhar "
"reatha an ghearrthaisce thíos." "reatha an ghearrthaisce thíos."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
msgstr "Rabhadh: Greamaigh a d'fhéadfadh a bheith neamhshábháilte" msgstr "Rabhadh: Greamaigh a d'fhéadfadh a bheith neamhshábháilte"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
@ -214,36 +237,6 @@ msgstr ""
"Dfhéadfadh sé a bheith contúirteach an téacs seo a ghreamú isteach sa " "Dfhéadfadh sé a bheith contúirteach an téacs seo a ghreamú isteach sa "
"teirminéal, toisc go d'fhéadfadh roinnt orduithe a fhorghníomhú." "teirminéal, toisc go d'fhéadfadh roinnt orduithe a fhorghníomhú."
#: src/apprt/gtk/Window.zig:208
msgid "Main Menu"
msgstr "Príomh-Roghchlár"
#: src/apprt/gtk/Window.zig:229
msgid "View Open Tabs"
msgstr "Féach ar na táib oscailte"
#: src/apprt/gtk/Window.zig:256
msgid "New Split"
msgstr "Scoilt nua"
#: src/apprt/gtk/Window.zig:319
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Tá leagan dífhabhtaithe de Ghostty á rith agat! Laghdófar an fheidhmíocht."
#: src/apprt/gtk/Window.zig:765
msgid "Reloaded the configuration"
msgstr "Tá an chumraíocht athlódáilte"
#: src/apprt/gtk/Window.zig:1005
msgid "Ghostty Developers"
msgstr "Forbróirí Ghostty"
#: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: Cigire teirminéil"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
msgstr "Dún" msgstr "Dún"
@ -281,6 +274,36 @@ msgid "The currently running process in this split will be terminated."
msgstr "" msgstr ""
"Cuirfear deireadh leis an bpróiseas atá ar siúl faoi láthair sa scoilt seo." "Cuirfear deireadh leis an bpróiseas atá ar siúl faoi láthair sa scoilt seo."
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "Cóipeáilte chuig an ghearrthaisce" msgstr "Cóipeáilte chuig an ghearrthaisce"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "Príomh-Roghchlár"
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr "Féach ar na táib oscailte"
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr "Scoilt nua"
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Tá leagan dífhabhtaithe de Ghostty á rith agat! Laghdófar an fheidhmíocht."
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr "Tá an chumraíocht athlódáilte"
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr "Forbróirí Ghostty"
#: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: Cigire teirminéil"

304
po/he_IL.UTF-8.po Normal file
View File

@ -0,0 +1,304 @@
# Hebrew translations for com.mitchellh.ghostty.
# Copyright (C) 2025 Mitchell Hashimoto
# This file is distributed under the same license as the com.mitchellh.ghostty package.
# Sl (Shahaf Levi), Sl's Repository Ltd <ghostty@slsrepo.com>, 2025.
#
msgid ""
msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-03-13 00:00+0000\n"
"Last-Translator: Sl (Shahaf Levi), Sl's Repository Ltd <ghostty@slsrepo."
"com>\n"
"Language-Team: Hebrew <he_IL@lists.sourceforge.net>\n"
"Language: he\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:5
msgid "Change Terminal Title"
msgstr "שינוי כותרת המסוף"
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:6
msgid "Leave blank to restore the default title."
msgstr "השאר/י ריק כדי לשחזר את כותרת ברירת המחדל."
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
#: src/apprt/gtk/CloseDialog.zig:44
msgid "Cancel"
msgstr "ביטול"
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:10
msgid "OK"
msgstr "אישור"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
msgid "Configuration Errors"
msgstr "שגיאות בהגדרות"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
msgid ""
"One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors."
msgstr ""
"נמצאו אחת או יותר שגיאות בהגדרות. אנא בדוק/י את השגיאות המופיעות מטה ולאחר "
"מכן טען/י את ההגדרות מחדש או התעלם/י מהשגיאות."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
msgid "Ignore"
msgstr "התעלמות"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
msgid "Reload Configuration"
msgstr "טעינה מחדש של ההגדרות"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "פיצול למעלה"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "פיצול למטה"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "פיצול שמאלה"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "פיצול ימינה"
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
msgid "Execute a command…"
msgstr "הרץ/י פקודה…"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy"
msgstr "העתקה"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
msgid "Paste"
msgstr "הדבקה"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:18
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:73
msgid "Clear"
msgstr "ניקוי"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:23
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:78
msgid "Reset"
msgstr "איפוס"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:30
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:42
msgid "Split"
msgstr "פיצול"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:33
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:45
msgid "Change Title…"
msgstr "שינוי כותרת…"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
msgid "Tab"
msgstr "כרטיסייה"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:265
msgid "New Tab"
msgstr "כרטיסייה חדשה"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:67
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:35
msgid "Close Tab"
msgstr "סגור/י כרטיסייה"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:73
msgid "Window"
msgstr "חלון"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:76
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:18
msgid "New Window"
msgstr "חלון חדש"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:81
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:23
msgid "Close Window"
msgstr "סגור/י חלון"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:89
msgid "Config"
msgstr "הגדרות"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
msgid "Open Configuration"
msgstr "פתיחת ההגדרות"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
msgid "Command Palette"
msgstr "לוח פקודות"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
msgid "Terminal Inspector"
msgstr "בודק המסוף"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty"
msgstr "אודות Ghostty"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
msgid "Quit"
msgstr "יציאה"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
msgid "Authorize Clipboard Access"
msgstr "אשר/י גישה ללוח ההעתקה"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
msgid ""
"An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below."
msgstr "יש אפליקציה שמנסה לקרוא מלוח ההעתקה. התוכן הנוכחי של הלוח מופיע למטה."
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
msgid "Deny"
msgstr "דחייה"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
msgid "Allow"
msgstr "אישור"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
msgstr "זכור/י את הבחירה עבור פיצול זה"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
msgstr "טען/י את ההגדרות מחדש כדי להציג את הבקשה הזו שוב"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
msgid ""
"An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below."
msgstr ""
"יש אפליקציה שמנסה לכתוב לתוך לוח ההעתקה. התוכן הנוכחי של הלוח מופיע למטה."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste"
msgstr "אזהרה: ההדבקה עלולה להיות מסוכנת"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed."
msgstr ""
"הדבקת טקסט זה במסוף עלולה להיות מסוכנת, מכיוון שככל הנראה היא תוביל להרצה של "
"פקודות מסוימות."
#: src/apprt/gtk/CloseDialog.zig:47
msgid "Close"
msgstr "סגירה"
#: src/apprt/gtk/CloseDialog.zig:87
msgid "Quit Ghostty?"
msgstr "לצאת מGhostty?"
#: src/apprt/gtk/CloseDialog.zig:88
msgid "Close Window?"
msgstr "לסגור את החלון?"
#: src/apprt/gtk/CloseDialog.zig:89
msgid "Close Tab?"
msgstr "לסגור את הכרטיסייה?"
#: src/apprt/gtk/CloseDialog.zig:90
msgid "Close Split?"
msgstr "לסגור את הפיצול?"
#: src/apprt/gtk/CloseDialog.zig:96
msgid "All terminal sessions will be terminated."
msgstr "כל הפעלות המסוף יסתיימו."
#: src/apprt/gtk/CloseDialog.zig:97
msgid "All terminal sessions in this window will be terminated."
msgstr "כל הפעלות המסוף בחלון זה יסתיימו."
#: src/apprt/gtk/CloseDialog.zig:98
msgid "All terminal sessions in this tab will be terminated."
msgstr "כל הפעלות המסוף בכרטיסייה זו יסתיימו."
#: src/apprt/gtk/CloseDialog.zig:99
msgid "The currently running process in this split will be terminated."
msgstr "התהליך שרץ כרגע בפיצול זה יסתיים."
#: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard"
msgstr "הועתק ללוח ההעתקה"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "תפריט ראשי"
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr "הצג/י כרטיסיות פתוחות"
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr "פיצול חדש"
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "⚠️ את/ה מריץ/ה גרסת ניפוי שגיאות של Ghostty! הביצועים יהיו ירודים."
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr "ההגדרות הוטענו מחדש"
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr "המפתחים של Ghostty"
#: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: בודק המסוף"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-04-22 08:57-0700\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-03-20 15:19+0700\n" "PO-Revision-Date: 2025-03-20 15:19+0700\n"
"Last-Translator: Satrio Bayu Aji <halosatrio@gmail.com>\n" "Last-Translator: Satrio Bayu Aji <halosatrio@gmail.com>\n"
"Language-Team: Indonesian <translation-team-id@lists.sourceforge.net>\n" "Language-Team: Indonesian <translation-team-id@lists.sourceforge.net>\n"
@ -25,7 +25,8 @@ msgid "Leave blank to restore the default title."
msgstr "Biarkan kosong untuk mengembalikan judul bawaan." msgstr "Biarkan kosong untuk mengembalikan judul bawaan."
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9 #: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
#: src/apprt/gtk/CloseDialog.zig:44
msgid "Cancel" msgid "Cancel"
msgstr "Batal" msgstr "Batal"
@ -34,10 +35,12 @@ msgid "OK"
msgstr "OK" msgstr "OK"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
msgid "Configuration Errors" msgid "Configuration Errors"
msgstr "Kesalahan konfigurasi" msgstr "Kesalahan konfigurasi"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
@ -46,12 +49,14 @@ msgstr ""
"bawah ini, dan muat ulang konfigurasi anda atau abaikan kesalahan ini." "bawah ini, dan muat ulang konfigurasi anda atau abaikan kesalahan ini."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
msgstr "Abaikan" msgstr "Abaikan"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Muat ulang konfigurasi" msgstr "Muat ulang konfigurasi"
@ -79,6 +84,10 @@ msgstr "Belah kiri"
msgid "Split Right" msgid "Split Right"
msgstr "Belah kanan" msgstr "Belah kanan"
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
msgid "Execute a command…"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -86,7 +95,7 @@ msgstr "Salin"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
msgid "Paste" msgid "Paste"
msgstr "Tempel" msgstr "Tempel"
@ -116,7 +125,7 @@ msgstr "Tab"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:248 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "Tab baru" msgstr "Tab baru"
@ -144,29 +153,36 @@ msgid "Config"
msgstr "Konfigurasi" msgstr "Konfigurasi"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
msgid "Open Configuration" msgid "Open Configuration"
msgstr "Buka konfigurasi" msgstr "Buka konfigurasi"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
msgid "Command Palette"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
msgid "Terminal Inspector" msgid "Terminal Inspector"
msgstr "Inspektur terminal" msgstr "Inspektur terminal"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1003 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Tentang Ghostty" msgstr "Tentang Ghostty"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
msgid "Quit" msgid "Quit"
msgstr "Keluar" msgstr "Keluar"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
msgid "Authorize Clipboard Access" msgid "Authorize Clipboard Access"
msgstr "Mengesahkan akses papan klip" msgstr "Mengesahkan akses papan klip"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -176,15 +192,30 @@ msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
msgid "Deny" msgid "Deny"
msgstr "Menyangkal" msgstr "Menyangkal"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
msgid "Allow" msgid "Allow"
msgstr "Izinkan" msgstr "Izinkan"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -192,11 +223,11 @@ msgstr ""
"Aplikasi sedang mencoba menulis ke papan klip. Isi papan klip saat ini " "Aplikasi sedang mencoba menulis ke papan klip. Isi papan klip saat ini "
"ditampilkan di bawah ini." "ditampilkan di bawah ini."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
msgstr "Peringatan: Tempelan yang berpotensi tidak aman" msgstr "Peringatan: Tempelan yang berpotensi tidak aman"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
@ -204,32 +235,6 @@ msgstr ""
"Menempelkan teks ini ke terminal mungkin berbahaya karena sepertinya " "Menempelkan teks ini ke terminal mungkin berbahaya karena sepertinya "
"beberapa perintah mungkin dijalankan." "beberapa perintah mungkin dijalankan."
#: src/apprt/gtk/Window.zig:201
msgid "Main Menu"
msgstr "Menu utama"
#: src/apprt/gtk/Window.zig:222
msgid "View Open Tabs"
msgstr "Lihat tab terbuka"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Anda sedang menjalankan versi debug dari Ghostty! Performa akan menurun."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Memuat ulang konfigurasi"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Pengembang Ghostty"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
msgstr "Tutup" msgstr "Tutup"
@ -266,10 +271,36 @@ msgstr "Semua sesi terminal di tab ini akan diakhiri."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "Proses yang sedang berjalan dalam belahan ini akan diakhiri." msgstr "Proses yang sedang berjalan dalam belahan ini akan diakhiri."
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "Disalin ke papan klip" msgstr "Disalin ke papan klip"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "Menu utama"
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr "Lihat tab terbuka"
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Anda sedang menjalankan versi debug dari Ghostty! Performa akan menurun."
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr "Memuat ulang konfigurasi"
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr "Pengembang Ghostty"
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector" msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: Inspektur terminal" msgstr "Ghostty: Inspektur terminal"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-04-22 08:57-0700\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-03-21 00:08+0900\n" "PO-Revision-Date: 2025-03-21 00:08+0900\n"
"Last-Translator: Lon Sagisawa <lon@sagisawa.me>\n" "Last-Translator: Lon Sagisawa <lon@sagisawa.me>\n"
"Language-Team: Japanese\n" "Language-Team: Japanese\n"
@ -27,7 +27,8 @@ msgid "Leave blank to restore the default title."
msgstr "空白にした場合、デフォルトのタイトルを使用します。" msgstr "空白にした場合、デフォルトのタイトルを使用します。"
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9 #: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
#: src/apprt/gtk/CloseDialog.zig:44
msgid "Cancel" msgid "Cancel"
msgstr "キャンセル" msgstr "キャンセル"
@ -36,10 +37,12 @@ msgid "OK"
msgstr "OK" msgstr "OK"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
msgid "Configuration Errors" msgid "Configuration Errors"
msgstr "設定ファイルにエラーがあります" msgstr "設定ファイルにエラーがあります"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
@ -48,12 +51,14 @@ msgstr ""
"みをするか、無視してください。" "みをするか、無視してください。"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
msgstr "無視" msgstr "無視"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "設定ファイルの再読み込み" msgstr "設定ファイルの再読み込み"
@ -81,6 +86,10 @@ msgstr "左に分割"
msgid "Split Right" msgid "Split Right"
msgstr "右に分割" msgstr "右に分割"
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
msgid "Execute a command…"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -88,7 +97,7 @@ msgstr "コピー"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
msgid "Paste" msgid "Paste"
msgstr "貼り付け" msgstr "貼り付け"
@ -118,7 +127,7 @@ msgstr "タブ"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:248 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "新しいタブ" msgstr "新しいタブ"
@ -146,29 +155,36 @@ msgid "Config"
msgstr "設定" msgstr "設定"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
msgid "Open Configuration" msgid "Open Configuration"
msgstr "設定ファイルを開く" msgstr "設定ファイルを開く"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
msgid "Command Palette"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
msgid "Terminal Inspector" msgid "Terminal Inspector"
msgstr "端末インスペクター" msgstr "端末インスペクター"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1003 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Ghostty について" msgstr "Ghostty について"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
msgid "Quit" msgid "Quit"
msgstr "終了" msgstr "終了"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
msgid "Authorize Clipboard Access" msgid "Authorize Clipboard Access"
msgstr "クリップボードへのアクセスを承認" msgstr "クリップボードへのアクセスを承認"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -178,15 +194,30 @@ msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
msgid "Deny" msgid "Deny"
msgstr "拒否" msgstr "拒否"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
msgid "Allow" msgid "Allow"
msgstr "許可" msgstr "許可"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -194,11 +225,11 @@ msgstr ""
"アプリケーションがクリップボードに書き込もうとしています。現在のクリップボー" "アプリケーションがクリップボードに書き込もうとしています。現在のクリップボー"
"ドの内容は以下の通りです。" "ドの内容は以下の通りです。"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
msgstr "警告: 危険な可能性のある貼り付け" msgstr "警告: 危険な可能性のある貼り付け"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
@ -206,32 +237,6 @@ msgstr ""
"このテキストには実行可能なコマンドが含まれており、ターミナルに貼り付けるのは" "このテキストには実行可能なコマンドが含まれており、ターミナルに貼り付けるのは"
"危険な可能性があります。" "危険な可能性があります。"
#: src/apprt/gtk/Window.zig:201
msgid "Main Menu"
msgstr "メインメニュー"
#: src/apprt/gtk/Window.zig:222
msgid "View Open Tabs"
msgstr "開いているすべてのタブを表示"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Ghostty のデバッグビルドを実行しています! パフォーマンスが低下しています。"
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "設定を再読み込みしました"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Ghostty 開発者"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
msgstr "閉じる" msgstr "閉じる"
@ -268,10 +273,36 @@ msgstr "タブ内のすべてのターミナルセッションが終了します
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "分割ウィンドウ内のすべてのプロセスが終了します。" msgstr "分割ウィンドウ内のすべてのプロセスが終了します。"
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "クリップボードにコピーしました" msgstr "クリップボードにコピーしました"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "メインメニュー"
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr "開いているすべてのタブを表示"
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Ghostty のデバッグビルドを実行しています! パフォーマンスが低下しています。"
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr "設定を再読み込みしました"
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr "Ghostty 開発者"
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector" msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: 端末インスペクター" msgstr "Ghostty: 端末インスペクター"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-03-19 08:54-0700\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-03-31 03:08+0200\n" "PO-Revision-Date: 2025-03-31 03:08+0200\n"
"Last-Translator: Ruben Engelbrecht <hey@rme.gg>\n" "Last-Translator: Ruben Engelbrecht <hey@rme.gg>\n"
"Language-Team: Korean <translation-team-ko@googlegroups.com>\n" "Language-Team: Korean <translation-team-ko@googlegroups.com>\n"
@ -26,7 +26,8 @@ msgid "Leave blank to restore the default title."
msgstr "제목란을 비워 두면 기본값으로 복원됩니다." msgstr "제목란을 비워 두면 기본값으로 복원됩니다."
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9 #: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
#: src/apprt/gtk/CloseDialog.zig:44
msgid "Cancel" msgid "Cancel"
msgstr "취소" msgstr "취소"
@ -35,25 +36,59 @@ msgid "OK"
msgstr "확인" msgstr "확인"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
msgid "Configuration Errors" msgid "Configuration Errors"
msgstr "설정 오류" msgstr "설정 오류"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
msgstr "설정에 하나 이상의 문제가 발견되었습니다. 아래 오류(를)들을 확인한 후 설정을 다시 불러오거나 무시하세요." msgstr ""
"설정에 하나 이상의 문제가 발견되었습니다. 아래 오류(를)들을 확인한 후 설정을 "
"다시 불러오거나 무시하세요."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
msgstr "무시" msgstr "무시"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "설정 값 다시 불러오기" msgstr "설정 값 다시 불러오기"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "위로 창 나누기"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "아래로 창 나누기"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "왼쪽으로 창 나누기"
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "오른쪽으로 창 나누기"
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
msgid "Execute a command…"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -61,7 +96,7 @@ msgstr "복사"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
msgid "Paste" msgid "Paste"
msgstr "붙여넣기" msgstr "붙여넣기"
@ -85,33 +120,13 @@ msgstr "나누기"
msgid "Change Title…" msgid "Change Title…"
msgstr "제목 변경…" msgstr "제목 변경…"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
msgid "Split Up"
msgstr "위로 창 나누기"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
msgid "Split Down"
msgstr "아래로 창 나누기"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
msgid "Split Left"
msgstr "왼쪽으로 창 나누기"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
msgid "Split Right"
msgstr "오른쪽으로 창 나누기"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
msgid "Tab" msgid "Tab"
msgstr "탭" msgstr "탭"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:246 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "새 탭" msgstr "새 탭"
@ -139,67 +154,87 @@ msgid "Config"
msgstr "설정" msgstr "설정"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
msgid "Open Configuration" msgid "Open Configuration"
msgstr "설정 열기" msgstr "설정 열기"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
msgid "Command Palette"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
msgid "Terminal Inspector" msgid "Terminal Inspector"
msgstr "터미널 인스펙터" msgstr "터미널 인스펙터"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:960 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Ghostty 정보" msgstr "Ghostty 정보"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
msgid "Quit" msgid "Quit"
msgstr "종료" msgstr "종료"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
msgid "Authorize Clipboard Access" msgid "Authorize Clipboard Access"
msgstr "클립보드 액세스 권한 부여" msgstr "클립보드 액세스 권한 부여"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
msgstr "응용 프로그램이 클립보드에서 읽기를 시도하고 있습니다. 현재 클립보드 내용은 아래와 같습니다." msgstr ""
"응용 프로그램이 클립보드에서 읽기를 시도하고 있습니다. 현재 클립보드 내용은 "
"아래와 같습니다."
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
msgid "Deny" msgid "Deny"
msgstr "거부" msgstr "거부"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
msgid "Allow" msgid "Allow"
msgstr "허용" msgstr "허용"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
msgstr "응용 프로그램이 클립보드에 쓰기를 시도하고 있습니다. 현재 클립보드 내용은 아래와 같습니다." msgstr ""
"응용 프로그램이 클립보드에 쓰기를 시도하고 있습니다. 현재 클립보드 내용은 아"
"래와 같습니다."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
msgstr "경고: 잠재적으로 안전하지 않은 붙여넣기" msgstr "경고: 잠재적으로 안전하지 않은 붙여넣기"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
msgstr "이 텍스트를 터미널에 붙여넣는 것은 위험할 수 있습니다. 일부 명령이 실행될 수 있는 것으로 보입니다." msgstr ""
"이 텍스트를 터미널에 붙여넣는 것은 위험할 수 있습니다. 일부 명령이 실행될 수 "
#: src/apprt/gtk/inspector.zig:144 "있는 것으로 보입니다."
msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: 터미널 인스펙터"
#: src/apprt/gtk/Surface.zig:1243
msgid "Copied to clipboard"
msgstr "클립보드에 복사됨"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
@ -237,23 +272,36 @@ msgstr "이 탭의 모든 터미널 세션이 종료됩니다."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "이 분할에서 현재 실행 중인 프로세스가 종료됩니다." msgstr "이 분할에서 현재 실행 중인 프로세스가 종료됩니다."
#: src/apprt/gtk/Window.zig:200 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard"
msgstr "클립보드에 복사됨"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu" msgid "Main Menu"
msgstr "메인 메뉴" msgstr "메인 메뉴"
#: src/apprt/gtk/Window.zig:221 #: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs" msgid "View Open Tabs"
msgstr "열린 탭 보기" msgstr "열린 탭 보기"
#: src/apprt/gtk/Window.zig:295 #: src/apprt/gtk/Window.zig:266
#, fuzzy
msgid "New Split"
msgstr "나누기"
#: src/apprt/gtk/Window.zig:329
msgid "" msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded." "⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "⚠️ Ghostty 디버그 빌드로 실행 중입니다! 성능이 저하됩니다." msgstr "⚠️ Ghostty 디버그 빌드로 실행 중입니다! 성능이 저하됩니다."
#: src/apprt/gtk/Window.zig:725 #: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration" msgid "Reloaded the configuration"
msgstr "설정값을 다시 불러왔습니다" msgstr "설정값을 다시 불러왔습니다"
#: src/apprt/gtk/Window.zig:941 #: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers" msgid "Ghostty Developers"
msgstr "Ghostty 개발자들" msgstr "Ghostty 개발자들"
#: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: 터미널 인스펙터"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-04-22 08:57-0700\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-03-23 14:17+0100\n" "PO-Revision-Date: 2025-03-23 14:17+0100\n"
"Last-Translator: Andrej Daskalov <andrej.daskalov@gmail.com>\n" "Last-Translator: Andrej Daskalov <andrej.daskalov@gmail.com>\n"
"Language-Team: Macedonian\n" "Language-Team: Macedonian\n"
@ -25,7 +25,8 @@ msgid "Leave blank to restore the default title."
msgstr "Оставете празно за враќање на стандарсниот наслов." msgstr "Оставете празно за враќање на стандарсниот наслов."
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9 #: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
#: src/apprt/gtk/CloseDialog.zig:44
msgid "Cancel" msgid "Cancel"
msgstr "Откажи" msgstr "Откажи"
@ -34,10 +35,12 @@ msgid "OK"
msgstr "Во ред" msgstr "Во ред"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
msgid "Configuration Errors" msgid "Configuration Errors"
msgstr "Грешки во конфигурацијата" msgstr "Грешки во конфигурацијата"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
@ -47,12 +50,14 @@ msgstr ""
"овие грешки." "овие грешки."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
msgstr "Игнорирај" msgstr "Игнорирај"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Одново вчитај конфигурација" msgstr "Одново вчитај конфигурација"
@ -80,6 +85,10 @@ msgstr "Подели налево"
msgid "Split Right" msgid "Split Right"
msgstr "Подели надесно" msgstr "Подели надесно"
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
msgid "Execute a command…"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -87,7 +96,7 @@ msgstr "Копирај"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
msgid "Paste" msgid "Paste"
msgstr "Вметни" msgstr "Вметни"
@ -117,7 +126,7 @@ msgstr "Јазиче"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:248 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "Ново јазиче" msgstr "Ново јазиче"
@ -145,29 +154,36 @@ msgid "Config"
msgstr "Конфигурација" msgstr "Конфигурација"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
msgid "Open Configuration" msgid "Open Configuration"
msgstr "Отвори конфигурација" msgstr "Отвори конфигурација"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
msgid "Command Palette"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
msgid "Terminal Inspector" msgid "Terminal Inspector"
msgstr "Инспектор на терминал" msgstr "Инспектор на терминал"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1003 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "За Ghostty" msgstr "За Ghostty"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
msgid "Quit" msgid "Quit"
msgstr "Излез" msgstr "Излез"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
msgid "Authorize Clipboard Access" msgid "Authorize Clipboard Access"
msgstr "Авторизирај пристап до привремена меморија" msgstr "Авторизирај пристап до привремена меморија"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -177,15 +193,30 @@ msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
msgid "Deny" msgid "Deny"
msgstr "Одбиј" msgstr "Одбиј"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
msgid "Allow" msgid "Allow"
msgstr "Дозволи" msgstr "Дозволи"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -193,11 +224,11 @@ msgstr ""
"Апликација се обидува да запише во привремената меморија. Содржината е " "Апликација се обидува да запише во привремената меморија. Содржината е "
"прикажана подолу." "прикажана подолу."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
msgstr "Предупредување: Потенцијално небезбедно вметнување" msgstr "Предупредување: Потенцијално небезбедно вметнување"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
@ -205,32 +236,6 @@ msgstr ""
"Вметнувањето на овој текст во терминалот може да биде опасно, бидејќи " "Вметнувањето на овој текст во терминалот може да биде опасно, бидејќи "
"изгледа како да ќе се извршат одредени команди." "изгледа како да ќе се извршат одредени команди."
#: src/apprt/gtk/Window.zig:201
msgid "Main Menu"
msgstr "Главно мени"
#: src/apprt/gtk/Window.zig:222
msgid "View Open Tabs"
msgstr "Прегледај отворени јазичиња"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Извршувате дебаг верзија на Ghostty! Перформансите ќе бидат намалени."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Конфигурацијата е одново вчитана"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Развивачи на Ghostty"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
msgstr "Затвори" msgstr "Затвори"
@ -267,10 +272,36 @@ msgstr "Сите сесии во ова јазиче ќе бидат преки
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "Процесот кој моментално се извршува во оваа поделба ќе биде прекинат." msgstr "Процесот кој моментално се извршува во оваа поделба ќе биде прекинат."
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "Копирано во привремена меморија" msgstr "Копирано во привремена меморија"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "Главно мени"
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr "Прегледај отворени јазичиња"
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Извршувате дебаг верзија на Ghostty! Перформансите ќе бидат намалени."
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr "Конфигурацијата е одново вчитана"
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr "Развивачи на Ghostty"
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector" msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: Инспектор на терминал" msgstr "Ghostty: Инспектор на терминал"

View File

@ -10,7 +10,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-04-22 08:57-0700\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-04-14 16:25+0200\n" "PO-Revision-Date: 2025-04-14 16:25+0200\n"
"Last-Translator: cryptocode <cryptocode@zolo.io>\n" "Last-Translator: cryptocode <cryptocode@zolo.io>\n"
"Language-Team: Norwegian Bokmal <l10n-no@lister.huftis.org>\n" "Language-Team: Norwegian Bokmal <l10n-no@lister.huftis.org>\n"
@ -29,7 +29,8 @@ msgid "Leave blank to restore the default title."
msgstr "Blank verdi gjenoppretter standardtittelen." msgstr "Blank verdi gjenoppretter standardtittelen."
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9 #: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
#: src/apprt/gtk/CloseDialog.zig:44
msgid "Cancel" msgid "Cancel"
msgstr "Avbryt" msgstr "Avbryt"
@ -38,10 +39,12 @@ msgid "OK"
msgstr "OK" msgstr "OK"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
msgid "Configuration Errors" msgid "Configuration Errors"
msgstr "Konfigurasjonsfeil" msgstr "Konfigurasjonsfeil"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
@ -50,12 +53,14 @@ msgstr ""
"under, og enten last konfigurasjonen din på nytt eller ignorer disse feilene." "under, og enten last konfigurasjonen din på nytt eller ignorer disse feilene."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
msgstr "Ignorer" msgstr "Ignorer"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Last konfigurasjon på nytt" msgstr "Last konfigurasjon på nytt"
@ -83,6 +88,10 @@ msgstr "Del til venstre"
msgid "Split Right" msgid "Split Right"
msgstr "Del til høyre" msgstr "Del til høyre"
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
msgid "Execute a command…"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -90,7 +99,7 @@ msgstr "Kopier"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
msgid "Paste" msgid "Paste"
msgstr "Lim inn" msgstr "Lim inn"
@ -120,7 +129,7 @@ msgstr "Fane"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:248 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "Ny fane" msgstr "Ny fane"
@ -148,29 +157,36 @@ msgid "Config"
msgstr "Konfigurasjon" msgstr "Konfigurasjon"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
msgid "Open Configuration" msgid "Open Configuration"
msgstr "Åpne konfigurasjon" msgstr "Åpne konfigurasjon"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
msgid "Command Palette"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
msgid "Terminal Inspector" msgid "Terminal Inspector"
msgstr "Terminalinspektør" msgstr "Terminalinspektør"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1003 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Om Ghostty" msgstr "Om Ghostty"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
msgid "Quit" msgid "Quit"
msgstr "Avslutt" msgstr "Avslutt"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
msgid "Authorize Clipboard Access" msgid "Authorize Clipboard Access"
msgstr "Gi tilgang til utklippstavlen" msgstr "Gi tilgang til utklippstavlen"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -180,15 +196,30 @@ msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
msgid "Deny" msgid "Deny"
msgstr "Avslå" msgstr "Avslå"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
msgid "Allow" msgid "Allow"
msgstr "Tillat" msgstr "Tillat"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -196,11 +227,11 @@ msgstr ""
"En applikasjon forsøker å skrive til utklippstavlen. Gjeldende " "En applikasjon forsøker å skrive til utklippstavlen. Gjeldende "
"utklippstavleinnhold er vist nedenfor." "utklippstavleinnhold er vist nedenfor."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
msgstr "Adarsel: Lim inn kan være utrygt" msgstr "Adarsel: Lim inn kan være utrygt"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
@ -208,31 +239,6 @@ msgstr ""
"Det ser ut som at kommandoer vil bli kjørt hvis du limer inn dette, vurder " "Det ser ut som at kommandoer vil bli kjørt hvis du limer inn dette, vurder "
"om du mener det er trygt." "om du mener det er trygt."
#: src/apprt/gtk/Window.zig:201
msgid "Main Menu"
msgstr "Hovedmeny"
#: src/apprt/gtk/Window.zig:222
msgid "View Open Tabs"
msgstr "Se åpne faner"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr "Del opp vindu"
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "⚠️ Du kjører et debug-bygg av Ghostty. Debug-bygg har redusert ytelse."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Konfigurasjonen ble lastet på nytt"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Ghostty-utviklere"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
msgstr "Lukk" msgstr "Lukk"
@ -269,10 +275,35 @@ msgstr "Alle terminaløkter i denne fanen vil bli avsluttet."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "Den kjørende prosessen for denne splitten vil bli avsluttet." msgstr "Den kjørende prosessen for denne splitten vil bli avsluttet."
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "Kopiert til utklippstavlen" msgstr "Kopiert til utklippstavlen"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "Hovedmeny"
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr "Se åpne faner"
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr "Del opp vindu"
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "⚠️ Du kjører et debug-bygg av Ghostty. Debug-bygg har redusert ytelse."
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr "Konfigurasjonen ble lastet på nytt"
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr "Ghostty-utviklere"
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector" msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: Terminalinspektør" msgstr "Ghostty: Terminalinspektør"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-04-22 08:57-0700\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-03-24 15:00+0100\n" "PO-Revision-Date: 2025-03-24 15:00+0100\n"
"Last-Translator: Nico Geesink <geesinknico@gmail.com>\n" "Last-Translator: Nico Geesink <geesinknico@gmail.com>\n"
"Language-Team: Dutch <vertaling@vrijschrift.org>\n" "Language-Team: Dutch <vertaling@vrijschrift.org>\n"
@ -26,7 +26,8 @@ msgid "Leave blank to restore the default title."
msgstr "Laat leeg om de standaard titel te herstellen." msgstr "Laat leeg om de standaard titel te herstellen."
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9 #: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
#: src/apprt/gtk/CloseDialog.zig:44
msgid "Cancel" msgid "Cancel"
msgstr "Annuleren" msgstr "Annuleren"
@ -35,10 +36,12 @@ msgid "OK"
msgstr "OK" msgstr "OK"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
msgid "Configuration Errors" msgid "Configuration Errors"
msgstr "Configuratiefouten" msgstr "Configuratiefouten"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
@ -47,12 +50,14 @@ msgstr ""
"fouten en herlaad je configuratie of negeer deze fouten." "fouten en herlaad je configuratie of negeer deze fouten."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
msgstr "Negeer" msgstr "Negeer"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Herlaad configuratie" msgstr "Herlaad configuratie"
@ -80,6 +85,10 @@ msgstr "Splits naar links"
msgid "Split Right" msgid "Split Right"
msgstr "Splits naar rechts" msgstr "Splits naar rechts"
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
msgid "Execute a command…"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -87,7 +96,7 @@ msgstr "Kopiëren"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
msgid "Paste" msgid "Paste"
msgstr "Plakken" msgstr "Plakken"
@ -117,7 +126,7 @@ msgstr "Tabblad"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:248 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "Nieuw tabblad" msgstr "Nieuw tabblad"
@ -145,29 +154,36 @@ msgid "Config"
msgstr "Configuratie" msgstr "Configuratie"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
msgid "Open Configuration" msgid "Open Configuration"
msgstr "Open configuratie" msgstr "Open configuratie"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
msgid "Command Palette"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
msgid "Terminal Inspector" msgid "Terminal Inspector"
msgstr "Terminal inspecteur" msgstr "Terminal inspecteur"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1003 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Over Ghostty" msgstr "Over Ghostty"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
msgid "Quit" msgid "Quit"
msgstr "Afsluiten" msgstr "Afsluiten"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
msgid "Authorize Clipboard Access" msgid "Authorize Clipboard Access"
msgstr "Verleen toegang tot klembord" msgstr "Verleen toegang tot klembord"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -177,15 +193,30 @@ msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
msgid "Deny" msgid "Deny"
msgstr "Weigeren" msgstr "Weigeren"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
msgid "Allow" msgid "Allow"
msgstr "Toestaan" msgstr "Toestaan"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -193,11 +224,11 @@ msgstr ""
"Een applicatie probeert de inhoud van het klembord te wijzigen. De huidige " "Een applicatie probeert de inhoud van het klembord te wijzigen. De huidige "
"inhoud van het klembord wordt hieronder weergegeven." "inhoud van het klembord wordt hieronder weergegeven."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
msgstr "Waarschuwing: mogelijk onveilige plakactie" msgstr "Waarschuwing: mogelijk onveilige plakactie"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
@ -205,33 +236,6 @@ msgstr ""
"Het plakken van deze tekst in de terminal is mogelijk gevaarlijk, omdat het " "Het plakken van deze tekst in de terminal is mogelijk gevaarlijk, omdat het "
"lijkt op een commando dat uitgevoerd kan worden." "lijkt op een commando dat uitgevoerd kan worden."
#: src/apprt/gtk/Window.zig:201
msgid "Main Menu"
msgstr "Hoofdmenu"
#: src/apprt/gtk/Window.zig:222
msgid "View Open Tabs"
msgstr "Open tabbladen bekijken"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Je draait een debug versie van Ghostty! Prestaties zullen minder zijn dan "
"normaal."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "De configuratie is herladen"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Ghostty ontwikkelaars"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
msgstr "Afsluiten" msgstr "Afsluiten"
@ -269,10 +273,37 @@ msgid "The currently running process in this split will be terminated."
msgstr "" msgstr ""
"Alle processen die nu draaien in deze splitsing zullen worden beëindigd." "Alle processen die nu draaien in deze splitsing zullen worden beëindigd."
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "Gekopieerd naar klembord" msgstr "Gekopieerd naar klembord"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "Hoofdmenu"
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr "Open tabbladen bekijken"
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Je draait een debug versie van Ghostty! Prestaties zullen minder zijn dan "
"normaal."
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr "De configuratie is herladen"
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr "Ghostty ontwikkelaars"
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector" msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: terminal inspecteur" msgstr "Ghostty: terminal inspecteur"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-04-22 08:57-0700\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-03-17 12:15+0100\n" "PO-Revision-Date: 2025-03-17 12:15+0100\n"
"Last-Translator: Bartosz Sokorski <b.sokorski@gmail.com>\n" "Last-Translator: Bartosz Sokorski <b.sokorski@gmail.com>\n"
"Language-Team: Polish <translation-team-pl@lists.sourceforge.net>\n" "Language-Team: Polish <translation-team-pl@lists.sourceforge.net>\n"
@ -28,7 +28,8 @@ msgid "Leave blank to restore the default title."
msgstr "Pozostaw puste by przywrócić domyślny tytuł." msgstr "Pozostaw puste by przywrócić domyślny tytuł."
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9 #: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
#: src/apprt/gtk/CloseDialog.zig:44
msgid "Cancel" msgid "Cancel"
msgstr "Anuluj" msgstr "Anuluj"
@ -37,10 +38,12 @@ msgid "OK"
msgstr "OK" msgstr "OK"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
msgid "Configuration Errors" msgid "Configuration Errors"
msgstr "Błędy konfiguracji" msgstr "Błędy konfiguracji"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
@ -49,12 +52,14 @@ msgstr ""
"poniżej i przeładuj konfigurację lub zignoruj je." "poniżej i przeładuj konfigurację lub zignoruj je."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
msgstr "Zignoruj" msgstr "Zignoruj"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Przeładuj konfigurację" msgstr "Przeładuj konfigurację"
@ -82,6 +87,10 @@ msgstr "Podziel w lewo"
msgid "Split Right" msgid "Split Right"
msgstr "Podziel w prawo" msgstr "Podziel w prawo"
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
msgid "Execute a command…"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -89,7 +98,7 @@ msgstr "Kopiuj"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
msgid "Paste" msgid "Paste"
msgstr "Wklej" msgstr "Wklej"
@ -119,7 +128,7 @@ msgstr "Karta"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:248 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "Nowa karta" msgstr "Nowa karta"
@ -147,29 +156,36 @@ msgid "Config"
msgstr "Konfiguracja" msgstr "Konfiguracja"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
msgid "Open Configuration" msgid "Open Configuration"
msgstr "Otwórz konfigurację" msgstr "Otwórz konfigurację"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
msgid "Command Palette"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
msgid "Terminal Inspector" msgid "Terminal Inspector"
msgstr "Inspektor terminala" msgstr "Inspektor terminala"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1003 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "O Ghostty" msgstr "O Ghostty"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
msgid "Quit" msgid "Quit"
msgstr "Zamknij" msgstr "Zamknij"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
msgid "Authorize Clipboard Access" msgid "Authorize Clipboard Access"
msgstr "Udziel dostępu do schowka" msgstr "Udziel dostępu do schowka"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -179,15 +195,30 @@ msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
msgid "Deny" msgid "Deny"
msgstr "Odmów" msgstr "Odmów"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
msgid "Allow" msgid "Allow"
msgstr "Zezwól" msgstr "Zezwól"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -195,11 +226,11 @@ msgstr ""
"Aplikacja próbuje zapisać do schowka. Obecna zawartość schowka pokazana " "Aplikacja próbuje zapisać do schowka. Obecna zawartość schowka pokazana "
"poniżej." "poniżej."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
msgstr "Uwaga: potencjalnie niebezpieczne wklejenie ze schowka" msgstr "Uwaga: potencjalnie niebezpieczne wklejenie ze schowka"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
@ -207,31 +238,6 @@ msgstr ""
"Wklejenie tego tekstu do terminala może być niebezpieczne, ponieważ może " "Wklejenie tego tekstu do terminala może być niebezpieczne, ponieważ może "
"spowodować wykonanie komend." "spowodować wykonanie komend."
#: src/apprt/gtk/Window.zig:201
msgid "Main Menu"
msgstr "Menu główne"
#: src/apprt/gtk/Window.zig:222
msgid "View Open Tabs"
msgstr "Zobacz otwarte karty"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "⚠️ Używasz wersji Ghostty do debugowania! Wydajność będzie obniżona."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Przeładowano konfigurację"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Twórcy Ghostty"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
msgstr "Zamknij" msgstr "Zamknij"
@ -268,10 +274,35 @@ msgstr "Wszystkie sesje terminala w obecnej karcie zostaną zakończone."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "Wszyskie trwające procesy w obecnym podziale zostaną zakończone." msgstr "Wszyskie trwające procesy w obecnym podziale zostaną zakończone."
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "Skopiowano do schowka" msgstr "Skopiowano do schowka"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "Menu główne"
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr "Zobacz otwarte karty"
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "⚠️ Używasz wersji Ghostty do debugowania! Wydajność będzie obniżona."
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr "Przeładowano konfigurację"
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr "Twórcy Ghostty"
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector" msgid "Ghostty: Terminal Inspector"
msgstr "Inspektor terminala Ghostty" msgstr "Inspektor terminala Ghostty"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-04-22 08:57-0700\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-06-20 10:19-0300\n" "PO-Revision-Date: 2025-06-20 10:19-0300\n"
"Last-Translator: Mário Victor Ribeiro Silva <mariovictorrs@gmail.com>\n" "Last-Translator: Mário Victor Ribeiro Silva <mariovictorrs@gmail.com>\n"
"Language-Team: Brazilian Portuguese <ldpbr-translation@lists.sourceforge." "Language-Team: Brazilian Portuguese <ldpbr-translation@lists.sourceforge."
@ -28,7 +28,8 @@ msgid "Leave blank to restore the default title."
msgstr "Deixe em branco para restaurar o título original." msgstr "Deixe em branco para restaurar o título original."
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9 #: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
#: src/apprt/gtk/CloseDialog.zig:44
msgid "Cancel" msgid "Cancel"
msgstr "Cancelar" msgstr "Cancelar"
@ -37,10 +38,12 @@ msgid "OK"
msgstr "OK" msgstr "OK"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
msgid "Configuration Errors" msgid "Configuration Errors"
msgstr "Erros de configuração" msgstr "Erros de configuração"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
@ -49,12 +52,14 @@ msgstr ""
"abaixo, e ou recarregue sua configuração, ou ignore esses erros." "abaixo, e ou recarregue sua configuração, ou ignore esses erros."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
msgstr "Ignorar" msgstr "Ignorar"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Recarregar configuração" msgstr "Recarregar configuração"
@ -82,6 +87,10 @@ msgstr "Dividir à esquerda"
msgid "Split Right" msgid "Split Right"
msgstr "Dividir à direita" msgstr "Dividir à direita"
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
msgid "Execute a command…"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -89,7 +98,7 @@ msgstr "Copiar"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
msgid "Paste" msgid "Paste"
msgstr "Colar" msgstr "Colar"
@ -119,7 +128,7 @@ msgstr "Aba"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:248 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "Nova aba" msgstr "Nova aba"
@ -147,29 +156,36 @@ msgid "Config"
msgstr "Configurar" msgstr "Configurar"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
msgid "Open Configuration" msgid "Open Configuration"
msgstr "Abrir configuração" msgstr "Abrir configuração"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
msgid "Command Palette"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
msgid "Terminal Inspector" msgid "Terminal Inspector"
msgstr "Inspetor de terminal" msgstr "Inspetor de terminal"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1003 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Sobre o Ghostty" msgstr "Sobre o Ghostty"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
msgid "Quit" msgid "Quit"
msgstr "Sair" msgstr "Sair"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
msgid "Authorize Clipboard Access" msgid "Authorize Clipboard Access"
msgstr "Autorizar acesso à área de transferência" msgstr "Autorizar acesso à área de transferência"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -179,15 +195,30 @@ msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
msgid "Deny" msgid "Deny"
msgstr "Negar" msgstr "Negar"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
msgid "Allow" msgid "Allow"
msgstr "Permitir" msgstr "Permitir"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -195,11 +226,11 @@ msgstr ""
"Uma aplicação está tentando escrever na área de transferência. O conteúdo " "Uma aplicação está tentando escrever na área de transferência. O conteúdo "
"atual da área de transferência está aparecendo abaixo." "atual da área de transferência está aparecendo abaixo."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
msgstr "Aviso: Conteúdo potencialmente inseguro" msgstr "Aviso: Conteúdo potencialmente inseguro"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
@ -207,32 +238,6 @@ msgstr ""
"Colar esse texto em um terminal pode ser perigoso, pois parece que alguns " "Colar esse texto em um terminal pode ser perigoso, pois parece que alguns "
"comandos podem ser executados." "comandos podem ser executados."
#: src/apprt/gtk/Window.zig:201
msgid "Main Menu"
msgstr "Menu Principal"
#: src/apprt/gtk/Window.zig:222
msgid "View Open Tabs"
msgstr "Visualizar abas abertas"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr "Nova divisão"
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Você está rodando uma build de debug do Ghostty! O desempenho será afetado."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Configuração recarregada"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Desenvolvedores Ghostty"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
msgstr "Fechar" msgstr "Fechar"
@ -269,10 +274,36 @@ msgstr "Todas as sessões de terminal nessa aba serão finalizadas."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "O processo atual rodando nessa divisão será finalizado." msgstr "O processo atual rodando nessa divisão será finalizado."
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "Copiado para a área de transferência" msgstr "Copiado para a área de transferência"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "Menu Principal"
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr "Visualizar abas abertas"
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr "Nova divisão"
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Você está rodando uma build de debug do Ghostty! O desempenho será afetado."
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr "Configuração recarregada"
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr "Desenvolvedores Ghostty"
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector" msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: Inspetor de terminal" msgstr "Ghostty: Inspetor de terminal"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-04-22 08:57-0700\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-03-24 00:01+0500\n" "PO-Revision-Date: 2025-03-24 00:01+0500\n"
"Last-Translator: blackzeshi <sergey_zhuzhgov@mail.ru>\n" "Last-Translator: blackzeshi <sergey_zhuzhgov@mail.ru>\n"
"Language-Team: Russian <gnu@d07.ru>\n" "Language-Team: Russian <gnu@d07.ru>\n"
@ -28,7 +28,8 @@ msgid "Leave blank to restore the default title."
msgstr "Оставьте пустым, чтобы восстановить исходный заголовок." msgstr "Оставьте пустым, чтобы восстановить исходный заголовок."
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9 #: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
#: src/apprt/gtk/CloseDialog.zig:44
msgid "Cancel" msgid "Cancel"
msgstr "Отмена" msgstr "Отмена"
@ -37,10 +38,12 @@ msgid "OK"
msgstr "ОК" msgstr "ОК"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
msgid "Configuration Errors" msgid "Configuration Errors"
msgstr "Ошибки конфигурации" msgstr "Ошибки конфигурации"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
@ -49,12 +52,14 @@ msgstr ""
"конфигурацию, либо проигнорируйте ошибки." "конфигурацию, либо проигнорируйте ошибки."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
msgstr "Игнорировать" msgstr "Игнорировать"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Обновить конфигурацию" msgstr "Обновить конфигурацию"
@ -82,6 +87,10 @@ msgstr "Сплит влево"
msgid "Split Right" msgid "Split Right"
msgstr "Сплит вправо" msgstr "Сплит вправо"
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
msgid "Execute a command…"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -89,7 +98,7 @@ msgstr "Копировать"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
msgid "Paste" msgid "Paste"
msgstr "Вставить" msgstr "Вставить"
@ -119,7 +128,7 @@ msgstr "Вкладка"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:248 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "Новая вкладка" msgstr "Новая вкладка"
@ -147,29 +156,36 @@ msgid "Config"
msgstr "Конфигурация" msgstr "Конфигурация"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
msgid "Open Configuration" msgid "Open Configuration"
msgstr "Открыть конфигурационный файл" msgstr "Открыть конфигурационный файл"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
msgid "Command Palette"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
msgid "Terminal Inspector" msgid "Terminal Inspector"
msgstr "Инспектор терминала" msgstr "Инспектор терминала"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1003 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "О Ghostty" msgstr "О Ghostty"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
msgid "Quit" msgid "Quit"
msgstr "Выход" msgstr "Выход"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
msgid "Authorize Clipboard Access" msgid "Authorize Clipboard Access"
msgstr "Разрешить доступ к буферу обмена" msgstr "Разрешить доступ к буферу обмена"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -179,26 +195,41 @@ msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
msgid "Deny" msgid "Deny"
msgstr "Отклонить" msgstr "Отклонить"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
msgid "Allow" msgid "Allow"
msgstr "Разрешить" msgstr "Разрешить"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
msgstr "" msgstr ""
"Приложение пытается записать данные в буфер обмена. Эти данные показаны ниже." "Приложение пытается записать данные в буфер обмена. Эти данные показаны ниже."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
msgstr "Внимание! Вставляемые данные могут нанести вред вашей системе" msgstr "Внимание! Вставляемые данные могут нанести вред вашей системе"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
@ -206,33 +237,6 @@ msgstr ""
"Вставка этого текста в терминал может быть опасной. Это выглядит как " "Вставка этого текста в терминал может быть опасной. Это выглядит как "
"команды, которые могут быть исполнены." "команды, которые могут быть исполнены."
#: src/apprt/gtk/Window.zig:201
msgid "Main Menu"
msgstr "Главное меню"
#: src/apprt/gtk/Window.zig:222
msgid "View Open Tabs"
msgstr "Просмотреть открытые вкладки"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Вы запустили отладочную сборку Ghostty! Это может влиять на "
"производительность."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Конфигурация была обновлена"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Разработчики Ghostty"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
msgstr "Закрыть" msgstr "Закрыть"
@ -269,10 +273,37 @@ msgstr "Все сессии терминала в этой вкладке буд
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "Процесс, работающий в этой сплит-области, будет остановлен." msgstr "Процесс, работающий в этой сплит-области, будет остановлен."
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "Скопировано в буфер обмена" msgstr "Скопировано в буфер обмена"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "Главное меню"
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr "Просмотреть открытые вкладки"
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Вы запустили отладочную сборку Ghostty! Это может влиять на "
"производительность."
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr "Конфигурация была обновлена"
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr "Разработчики Ghostty"
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector" msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: инспектор терминала" msgstr "Ghostty: инспектор терминала"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-04-22 08:57-0700\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-03-24 22:01+0300\n" "PO-Revision-Date: 2025-03-24 22:01+0300\n"
"Last-Translator: Emir SARI <emir_sari@icloud.com>\n" "Last-Translator: Emir SARI <emir_sari@icloud.com>\n"
"Language-Team: Turkish\n" "Language-Team: Turkish\n"
@ -26,7 +26,8 @@ msgid "Leave blank to restore the default title."
msgstr "Öntanımlı başlığı geri yüklemek için boş bırakın." msgstr "Öntanımlı başlığı geri yüklemek için boş bırakın."
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9 #: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
#: src/apprt/gtk/CloseDialog.zig:44
msgid "Cancel" msgid "Cancel"
msgstr "İptal" msgstr "İptal"
@ -35,10 +36,12 @@ msgid "OK"
msgstr "Tamam" msgstr "Tamam"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
msgid "Configuration Errors" msgid "Configuration Errors"
msgstr "Yapılandırma Hataları" msgstr "Yapılandırma Hataları"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
@ -48,12 +51,14 @@ msgstr ""
"hataları yok sayın." "hataları yok sayın."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
msgstr "Yok Say" msgstr "Yok Say"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Yapılandırmayı Yeniden Yükle" msgstr "Yapılandırmayı Yeniden Yükle"
@ -81,6 +86,10 @@ msgstr "Sola Doğru Böl"
msgid "Split Right" msgid "Split Right"
msgstr "Sağa Doğru Böl" msgstr "Sağa Doğru Böl"
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
msgid "Execute a command…"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -88,7 +97,7 @@ msgstr "Kopyala"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
msgid "Paste" msgid "Paste"
msgstr "Yapıştır" msgstr "Yapıştır"
@ -118,7 +127,7 @@ msgstr "Sekme"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:248 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "Yeni Sekme" msgstr "Yeni Sekme"
@ -146,29 +155,36 @@ msgid "Config"
msgstr "Yapılandırma" msgstr "Yapılandırma"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
msgid "Open Configuration" msgid "Open Configuration"
msgstr "Yapılandırmayı Aç" msgstr "Yapılandırmayı Aç"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
msgid "Command Palette"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
msgid "Terminal Inspector" msgid "Terminal Inspector"
msgstr "Uçbirim Denetçisi" msgstr "Uçbirim Denetçisi"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1003 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Ghostty Hakkında" msgstr "Ghostty Hakkında"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
msgid "Quit" msgid "Quit"
msgstr "Çık" msgstr "Çık"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
msgid "Authorize Clipboard Access" msgid "Authorize Clipboard Access"
msgstr "Pano Erişimine İzin Ver" msgstr "Pano Erişimine İzin Ver"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -178,15 +194,30 @@ msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
msgid "Deny" msgid "Deny"
msgstr "Reddet" msgstr "Reddet"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
msgid "Allow" msgid "Allow"
msgstr "İzin Ver" msgstr "İzin Ver"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -194,11 +225,11 @@ msgstr ""
"Bir uygulama panoya yazmaya çalışıyor. Geçerli pano içeriği aşağıda " "Bir uygulama panoya yazmaya çalışıyor. Geçerli pano içeriği aşağıda "
"gösterilmektedir." "gösterilmektedir."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
msgstr "Uyarı: Tehlikeli Olabilecek Yapıştırma" msgstr "Uyarı: Tehlikeli Olabilecek Yapıştırma"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
@ -206,33 +237,6 @@ msgstr ""
"Bu metni uçbirime yapıştırmak tehlikeli olabilir; çünkü bir komut " "Bu metni uçbirime yapıştırmak tehlikeli olabilir; çünkü bir komut "
"yürütülebilecekmiş gibi duruyor." "yürütülebilecekmiş gibi duruyor."
#: src/apprt/gtk/Window.zig:201
msgid "Main Menu"
msgstr "Ana Menü"
#: src/apprt/gtk/Window.zig:222
msgid "View Open Tabs"
msgstr "Açık Sekmeleri Görüntüle"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr "Yeni Bölme"
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Ghosttynin hata ayıklama amaçlı yapılmış bir sürümünü kullanıyorsunuz! "
"Başarım normale göre daha düşük olacaktır."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Yapılandırma yeniden yüklendi"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Ghostty Geliştiricileri"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
msgstr "Kapat" msgstr "Kapat"
@ -269,10 +273,37 @@ msgstr "Bu sekmedeki tüm uçbirim oturumları sonlandırılacaktır."
msgid "The currently running process in this split will be terminated." msgid "The currently running process in this split will be terminated."
msgstr "Bu bölmedeki şu anda çalışan süreç sonlandırılacaktır." msgstr "Bu bölmedeki şu anda çalışan süreç sonlandırılacaktır."
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "Panoya kopyalandı" msgstr "Panoya kopyalandı"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "Ana Menü"
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr "Açık Sekmeleri Görüntüle"
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr "Yeni Bölme"
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Ghosttynin hata ayıklama amaçlı yapılmış bir sürümünü kullanıyorsunuz! "
"Başarım normale göre daha düşük olacaktır."
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr "Yapılandırma yeniden yüklendi"
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr "Ghostty Geliştiricileri"
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector" msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: Uçbirim Denetçisi" msgstr "Ghostty: Uçbirim Denetçisi"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-04-22 08:57-0700\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-03-16 20:16+0200\n" "PO-Revision-Date: 2025-03-16 20:16+0200\n"
"Last-Translator: Danylo Zalizchuk <danilmail0110@gmail.com>\n" "Last-Translator: Danylo Zalizchuk <danilmail0110@gmail.com>\n"
"Language-Team: Ukrainian <trans-uk@lists.fedoraproject.org>\n" "Language-Team: Ukrainian <trans-uk@lists.fedoraproject.org>\n"
@ -27,7 +27,8 @@ msgid "Leave blank to restore the default title."
msgstr "Залиште порожнім, щоб відновити назву за замовчуванням." msgstr "Залиште порожнім, щоб відновити назву за замовчуванням."
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9 #: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
#: src/apprt/gtk/CloseDialog.zig:44
msgid "Cancel" msgid "Cancel"
msgstr "Відмінити" msgstr "Відмінити"
@ -36,10 +37,12 @@ msgid "OK"
msgstr "ОК" msgstr "ОК"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
msgid "Configuration Errors" msgid "Configuration Errors"
msgstr "Помилки конфігурації" msgstr "Помилки конфігурації"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
msgid "" msgid ""
"One or more configuration errors were found. Please review the errors below, " "One or more configuration errors were found. Please review the errors below, "
"and either reload your configuration or ignore these errors." "and either reload your configuration or ignore these errors."
@ -49,12 +52,14 @@ msgstr ""
"ці помилки." "ці помилки."
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
msgid "Ignore" msgid "Ignore"
msgstr "Ігнорувати" msgstr "Ігнорувати"
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10 #: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
msgid "Reload Configuration" msgid "Reload Configuration"
msgstr "Перезавантажити конфігурацію" msgstr "Перезавантажити конфігурацію"
@ -82,6 +87,10 @@ msgstr "Розділити панель ліворуч"
msgid "Split Right" msgid "Split Right"
msgstr "Розділити панель праворуч" msgstr "Розділити панель праворуч"
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
msgid "Execute a command…"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
msgid "Copy" msgid "Copy"
@ -89,7 +98,7 @@ msgstr "Скопіювати"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
msgid "Paste" msgid "Paste"
msgstr "Вставити" msgstr "Вставити"
@ -119,7 +128,7 @@ msgstr "Вкладка"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:248 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "Нова вкладка" msgstr "Нова вкладка"
@ -147,29 +156,36 @@ msgid "Config"
msgstr "Конфігурація" msgstr "Конфігурація"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
msgid "Open Configuration" msgid "Open Configuration"
msgstr "Відкрити конфігурацію" msgstr "Відкрити конфігурацію"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
msgid "Command Palette"
msgstr ""
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
msgid "Terminal Inspector" msgid "Terminal Inspector"
msgstr "Інспектор терміналу" msgstr "Інспектор терміналу"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1003 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "Про Ghostty" msgstr "Про Ghostty"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
msgid "Quit" msgid "Quit"
msgstr "Завершити" msgstr "Завершити"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
msgid "Authorize Clipboard Access" msgid "Authorize Clipboard Access"
msgstr "Дозволити доступ до буфера обміну" msgstr "Дозволити доступ до буфера обміну"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
msgid "" msgid ""
"An application is attempting to read from the clipboard. The current " "An application is attempting to read from the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -179,15 +195,30 @@ msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
msgid "Deny" msgid "Deny"
msgstr "Відхилити" msgstr "Відхилити"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
msgid "Allow" msgid "Allow"
msgstr "Дозволити" msgstr "Дозволити"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
msgstr ""
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7 #: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
msgid "" msgid ""
"An application is attempting to write to the clipboard. The current " "An application is attempting to write to the clipboard. The current "
"clipboard contents are shown below." "clipboard contents are shown below."
@ -195,11 +226,11 @@ msgstr ""
"Програма намагається записати дані до буфера обміну. Нижче показано поточний " "Програма намагається записати дані до буфера обміну. Нижче показано поточний "
"вміст буфера обміну." "вміст буфера обміну."
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
msgid "Warning: Potentially Unsafe Paste" msgid "Warning: Potentially Unsafe Paste"
msgstr "Увага: потенційно небезпечна вставка" msgstr "Увага: потенційно небезпечна вставка"
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 #: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
msgid "" msgid ""
"Pasting this text into the terminal may be dangerous as it looks like some " "Pasting this text into the terminal may be dangerous as it looks like some "
"commands may be executed." "commands may be executed."
@ -207,32 +238,6 @@ msgstr ""
"Вставка цього тексту в термінал може бути небезпечною, оскільки виглядає " "Вставка цього тексту в термінал може бути небезпечною, оскільки виглядає "
"так, ніби деякі команди можуть бути виконані." "так, ніби деякі команди можуть бути виконані."
#: src/apprt/gtk/Window.zig:201
msgid "Main Menu"
msgstr "Головне меню"
#: src/apprt/gtk/Window.zig:222
msgid "View Open Tabs"
msgstr "Переглянути відкриті вкладки"
#: src/apprt/gtk/Window.zig:249
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:312
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Ви використовуєте відладочну збірку Ghostty! Продуктивність буде погіршено."
#: src/apprt/gtk/Window.zig:744
msgid "Reloaded the configuration"
msgstr "Конфігурацію перезавантажено"
#: src/apprt/gtk/Window.zig:984
msgid "Ghostty Developers"
msgstr "Розробники Ghostty"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
msgstr "Закрити" msgstr "Закрити"
@ -270,10 +275,36 @@ msgid "The currently running process in this split will be terminated."
msgstr "" msgstr ""
"Поточний процес, що виконується в цій розділеній панелі, буде завершено." "Поточний процес, що виконується в цій розділеній панелі, буде завершено."
#: src/apprt/gtk/Surface.zig:1243 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "Скопійовано в буфер обміну" msgstr "Скопійовано в буфер обміну"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "Головне меню"
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr "Переглянути відкриті вкладки"
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr ""
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr ""
"⚠️ Ви використовуєте відладочну збірку Ghostty! Продуктивність буде погіршено."
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr "Конфігурацію перезавантажено"
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr "Розробники Ghostty"
#: src/apprt/gtk/inspector.zig:144 #: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector" msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty: Інспектор терміналу" msgstr "Ghostty: Інспектор терміналу"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n" "Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-06-28 17:01+0200\n" "POT-Creation-Date: 2025-07-08 15:13-0500\n"
"PO-Revision-Date: 2025-02-27 09:16+0100\n" "PO-Revision-Date: 2025-02-27 09:16+0100\n"
"Last-Translator: Leah <hi@pluie.me>\n" "Last-Translator: Leah <hi@pluie.me>\n"
"Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n" "Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n"
@ -125,7 +125,7 @@ msgstr "标签页"
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62 #: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
#: src/apprt/gtk/Window.zig:263 #: src/apprt/gtk/Window.zig:265
msgid "New Tab" msgid "New Tab"
msgstr "新建标签页" msgstr "新建标签页"
@ -166,7 +166,7 @@ msgid "Terminal Inspector"
msgstr "终端调试器" msgstr "终端调试器"
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107 #: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
#: src/apprt/gtk/Window.zig:1036 #: src/apprt/gtk/Window.zig:1038
msgid "About Ghostty" msgid "About Ghostty"
msgstr "关于 Ghostty" msgstr "关于 Ghostty"
@ -229,35 +229,6 @@ msgid ""
"commands may be executed." "commands may be executed."
msgstr "将以下内容粘贴至终端内将可能执行有害命令。" msgstr "将以下内容粘贴至终端内将可能执行有害命令。"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "主菜单"
#: src/apprt/gtk/Window.zig:238
msgid "View Open Tabs"
msgstr "浏览标签页"
#: src/apprt/gtk/Window.zig:264
msgid "New Split"
msgstr "新建分屏"
#: src/apprt/gtk/Window.zig:327
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "⚠️ Ghostty 正在以调试模式运行!性能将大打折扣。"
#: src/apprt/gtk/Window.zig:773
msgid "Reloaded the configuration"
msgstr "已重新加载配置"
#: src/apprt/gtk/Window.zig:1017
msgid "Ghostty Developers"
msgstr "Ghostty 开发团队"
#: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty 终端调试器"
#: src/apprt/gtk/CloseDialog.zig:47 #: src/apprt/gtk/CloseDialog.zig:47
msgid "Close" msgid "Close"
msgstr "关闭" msgstr "关闭"
@ -297,3 +268,32 @@ msgstr "分屏内正在运行中的进程将被终止。"
#: src/apprt/gtk/Surface.zig:1257 #: src/apprt/gtk/Surface.zig:1257
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "已复制至剪贴板" msgstr "已复制至剪贴板"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
msgstr "主菜单"
#: src/apprt/gtk/Window.zig:239
msgid "View Open Tabs"
msgstr "浏览标签页"
#: src/apprt/gtk/Window.zig:266
msgid "New Split"
msgstr "新建分屏"
#: src/apprt/gtk/Window.zig:329
msgid ""
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
msgstr "⚠️ Ghostty 正在以调试模式运行!性能将大打折扣。"
#: src/apprt/gtk/Window.zig:775
msgid "Reloaded the configuration"
msgstr "已重新加载配置"
#: src/apprt/gtk/Window.zig:1019
msgid "Ghostty Developers"
msgstr "Ghostty 开发团队"
#: src/apprt/gtk/inspector.zig:144
msgid "Ghostty: Terminal Inspector"
msgstr "Ghostty 终端调试器"

View File

@ -29,6 +29,7 @@ const apprt = @import("../../apprt.zig");
const configpkg = @import("../../config.zig"); const configpkg = @import("../../config.zig");
const input = @import("../../input.zig"); const input = @import("../../input.zig");
const internal_os = @import("../../os/main.zig"); const internal_os = @import("../../os/main.zig");
const systemd = @import("../../os/systemd.zig");
const terminal = @import("../../terminal/main.zig"); const terminal = @import("../../terminal/main.zig");
const Config = configpkg.Config; const Config = configpkg.Config;
const CoreApp = @import("../../App.zig"); const CoreApp = @import("../../App.zig");
@ -496,7 +497,7 @@ pub fn performAction(
.resize_split => self.resizeSplit(target, value), .resize_split => self.resizeSplit(target, value),
.equalize_splits => self.equalizeSplits(target), .equalize_splits => self.equalizeSplits(target),
.goto_split => return self.gotoSplit(target, value), .goto_split => return self.gotoSplit(target, value),
.open_config => try configpkg.edit.open(self.core_app.alloc), .open_config => return self.openConfig(),
.config_change => self.configChange(target, value.config), .config_change => self.configChange(target, value.config),
.reload_config => try self.reloadConfig(target, value), .reload_config => try self.reloadConfig(target, value),
.inspector => self.controlInspector(target, value), .inspector => self.controlInspector(target, value),
@ -1035,6 +1036,12 @@ pub fn reloadConfig(
target: apprt.action.Target, target: apprt.action.Target,
opts: apprt.action.ReloadConfig, opts: apprt.action.ReloadConfig,
) !void { ) !void {
// Tell systemd that reloading has started.
systemd.notify.reloading();
// When we exit this function tell systemd that reloading has finished.
defer systemd.notify.ready();
if (opts.soft) { if (opts.soft) {
switch (target) { switch (target) {
.app => try self.core_app.updateConfig(self, &self.config), .app => try self.core_app.updateConfig(self, &self.config),
@ -1367,6 +1374,9 @@ pub fn run(self: *App) !void {
log.warn("error handling configuration changes err={}", .{err}); log.warn("error handling configuration changes err={}", .{err});
}; };
// Tell systemd that we are ready.
systemd.notify.ready();
while (self.running) { while (self.running) {
_ = glib.MainContext.iteration(self.ctx, 1); _ = glib.MainContext.iteration(self.ctx, 1);
@ -1759,7 +1769,22 @@ fn initActions(self: *App) void {
} }
} }
pub fn openUrl( fn openConfig(self: *App) !bool {
// Get the config file path
const alloc = self.core_app.alloc;
const path = configpkg.edit.openPath(alloc) catch |err| {
log.warn("error getting config file path: {}", .{err});
return false;
};
defer alloc.free(path);
// Open it using openURL. "path" isn't actually a URL but
// at the time of writing that works just fine for GTK.
self.openUrl(.{ .kind = .text, .url = path });
return true;
}
fn openUrl(
app: *App, app: *App,
value: apprt.action.OpenUrl, value: apprt.action.OpenUrl,
) void { ) void {

View File

@ -2333,6 +2333,7 @@ pub fn defaultTermioEnv(self: *Surface) !std.process.EnvMap {
env.remove("DBUS_STARTER_BUS_TYPE"); env.remove("DBUS_STARTER_BUS_TYPE");
env.remove("INVOCATION_ID"); env.remove("INVOCATION_ID");
env.remove("JOURNAL_STREAM"); env.remove("JOURNAL_STREAM");
env.remove("NOTIFY_SOCKET");
// Unset environment varies set by snaps if we're running in a snap. // Unset environment varies set by snaps if we're running in a snap.
// This allows Ghostty to further launch additional snaps. // This allows Ghostty to further launch additional snaps.

View File

@ -103,7 +103,7 @@ pub inline fn runtimeUntil(
test "atLeast" { test "atLeast" {
const testing = std.testing; const testing = std.testing;
const funs = &.{ atLeast, runtimeAtLeast, runtimeUntil }; const funs = &.{ atLeast, runtimeAtLeast };
inline for (funs) |fun| { inline for (funs) |fun| {
try testing.expect(fun(c.GTK_MAJOR_VERSION, c.GTK_MINOR_VERSION, c.GTK_MICRO_VERSION)); try testing.expect(fun(c.GTK_MAJOR_VERSION, c.GTK_MINOR_VERSION, c.GTK_MICRO_VERSION));
@ -118,3 +118,23 @@ test "atLeast" {
try testing.expect(fun(c.GTK_MAJOR_VERSION, c.GTK_MINOR_VERSION - 1, c.GTK_MICRO_VERSION + 1)); try testing.expect(fun(c.GTK_MAJOR_VERSION, c.GTK_MINOR_VERSION - 1, c.GTK_MICRO_VERSION + 1));
} }
} }
test "runtimeUntil" {
const testing = std.testing;
// This is an array in case we add a comptime variant.
const funs = &.{runtimeUntil};
inline for (funs) |fun| {
try testing.expect(!fun(c.GTK_MAJOR_VERSION, c.GTK_MINOR_VERSION, c.GTK_MICRO_VERSION));
try testing.expect(fun(c.GTK_MAJOR_VERSION, c.GTK_MINOR_VERSION, c.GTK_MICRO_VERSION + 1));
try testing.expect(fun(c.GTK_MAJOR_VERSION, c.GTK_MINOR_VERSION + 1, c.GTK_MICRO_VERSION));
try testing.expect(fun(c.GTK_MAJOR_VERSION + 1, c.GTK_MINOR_VERSION, c.GTK_MICRO_VERSION));
try testing.expect(!fun(c.GTK_MAJOR_VERSION - 1, c.GTK_MINOR_VERSION, c.GTK_MICRO_VERSION));
try testing.expect(!fun(c.GTK_MAJOR_VERSION - 1, c.GTK_MINOR_VERSION + 1, c.GTK_MICRO_VERSION));
try testing.expect(!fun(c.GTK_MAJOR_VERSION - 1, c.GTK_MINOR_VERSION, c.GTK_MICRO_VERSION + 1));
try testing.expect(!fun(c.GTK_MAJOR_VERSION, c.GTK_MINOR_VERSION - 1, c.GTK_MICRO_VERSION + 1));
}
}

View File

@ -115,7 +115,8 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyDist {
// Capture stderr so it doesn't spew into the parent build. // Capture stderr so it doesn't spew into the parent build.
// On the flip side, if the test fails we won't know why so // On the flip side, if the test fails we won't know why so
// that sucks but we should have already ran tests at this point. // that sucks but we should have already ran tests at this point.
_ = step.captureStdErr(); // NOTE(mitchellh): temporarily disabled to diagnose heisenbug
//_ = step.captureStdErr();
break :step step; break :step step;
}; };

View File

@ -79,24 +79,38 @@ fn createUpdateStep(b: *std.Build) !*std.Build.Step {
xgettext.has_side_effects = true; xgettext.has_side_effects = true;
inline for (gresource.blueprint_files) |blp| { inline for (gresource.blueprint_files) |blp| {
// We avoid using addFileArg here since the full, absolute file path const path = std.fmt.comptimePrint(
// would be added to the file as its location, which differs for
// everyone's checkout of the repository.
// This comes at a cost of losing per-file caching, of course.
xgettext.addArg(std.fmt.comptimePrint(
"src/apprt/gtk/ui/{[major]}.{[minor]}/{[name]s}.blp", "src/apprt/gtk/ui/{[major]}.{[minor]}/{[name]s}.blp",
blp, blp,
)); );
// The arguments to xgettext must be the relative path in the build root
// or the resulting files will contain the absolute path. This will cause
// a lot of churn because not everyone has the Ghostty code checked out in
// exactly the same location.
xgettext.addArg(path);
// Mark the file as an input so that the Zig build system caching will work.
xgettext.addFileInput(b.path(path));
} }
{ {
var gtk_files = try b.build_root.handle.openDir( // Iterate over all of the files underneath `src/apprt/gtk`. We store
// them in an array so that they can be sorted into a determininistic
// order. That will minimize code churn as directory walking is not
// guaranteed to happen in any particular order.
var gtk_files: std.ArrayListUnmanaged([]const u8) = .empty;
defer {
for (gtk_files.items) |item| b.allocator.free(item);
gtk_files.deinit(b.allocator);
}
var gtk_dir = try b.build_root.handle.openDir(
"src/apprt/gtk", "src/apprt/gtk",
.{ .iterate = true }, .{ .iterate = true },
); );
defer gtk_files.close(); defer gtk_dir.close();
var walk = try gtk_files.walk(b.allocator); var walk = try gtk_dir.walk(b.allocator);
defer walk.deinit(); defer walk.deinit();
while (try walk.next()) |src| { while (try walk.next()) |src| {
switch (src.kind) { switch (src.kind) {
@ -109,7 +123,29 @@ fn createUpdateStep(b: *std.Build) !*std.Build.Step {
else => continue, else => continue,
} }
xgettext.addArg((b.pathJoin(&.{ "src/apprt/gtk", src.path }))); try gtk_files.append(b.allocator, try b.allocator.dupe(u8, src.path));
}
std.mem.sort(
[]const u8,
gtk_files.items,
{},
struct {
fn lt(_: void, lhs: []const u8, rhs: []const u8) bool {
return std.mem.order(u8, lhs, rhs) == .lt;
}
}.lt,
);
for (gtk_files.items) |item| {
const path = b.pathJoin(&.{ "src/apprt/gtk", item });
// The arguments to xgettext must be the relative path in the build root
// or the resulting files will contain the absolute path. This will
// cause a lot of churn because not everyone has the Ghostty code
// checked out in exactly the same location.
xgettext.addArg(path);
// Mark the file as an input so that the Zig build system caching will work.
xgettext.addFileInput(b.path(path));
} }
} }
@ -120,7 +156,7 @@ fn createUpdateStep(b: *std.Build) !*std.Build.Step {
); );
inline for (internal_os.i18n.locales) |locale| { inline for (internal_os.i18n.locales) |locale| {
const msgmerge = b.addSystemCommand(&.{ "msgmerge", "-q" }); const msgmerge = b.addSystemCommand(&.{ "msgmerge", "--quiet", "--no-fuzzy-matching" });
msgmerge.addFileArg(b.path("po/" ++ locale ++ ".po")); msgmerge.addFileArg(b.path("po/" ++ locale ++ ".po"));
msgmerge.addFileArg(xgettext.captureStdOut()); msgmerge.addFileArg(xgettext.captureStdOut());
usf.addCopyFileToSource(msgmerge.captureStdOut(), "po/" ++ locale ++ ".po"); usf.addCopyFileToSource(msgmerge.captureStdOut(), "po/" ++ locale ++ ".po");

View File

@ -767,6 +767,9 @@ pub fn gtkDistResources(
}); });
const resources_c = generate_c.addOutputFileArg("ghostty_resources.c"); const resources_c = generate_c.addOutputFileArg("ghostty_resources.c");
generate_c.addFileArg(gresource_xml); generate_c.addFileArg(gresource_xml);
for (gresource.dependencies) |file| {
generate_c.addFileInput(b.path(file));
}
const generate_h = b.addSystemCommand(&.{ const generate_h = b.addSystemCommand(&.{
"glib-compile-resources", "glib-compile-resources",
@ -777,6 +780,9 @@ pub fn gtkDistResources(
}); });
const resources_h = generate_h.addOutputFileArg("ghostty_resources.h"); const resources_h = generate_h.addOutputFileArg("ghostty_resources.h");
generate_h.addFileArg(gresource_xml); generate_h.addFileArg(gresource_xml);
for (gresource.dependencies) |file| {
generate_h.addFileInput(b.path(file));
}
return .{ return .{
.resources_c = .{ .resources_c = .{

View File

@ -9,6 +9,7 @@ const list_keybinds = @import("list_keybinds.zig");
const list_themes = @import("list_themes.zig"); const list_themes = @import("list_themes.zig");
const list_colors = @import("list_colors.zig"); const list_colors = @import("list_colors.zig");
const list_actions = @import("list_actions.zig"); const list_actions = @import("list_actions.zig");
const ssh_cache = @import("ssh_cache.zig");
const edit_config = @import("edit_config.zig"); const edit_config = @import("edit_config.zig");
const show_config = @import("show_config.zig"); const show_config = @import("show_config.zig");
const validate_config = @import("validate_config.zig"); const validate_config = @import("validate_config.zig");
@ -41,6 +42,9 @@ pub const Action = enum {
/// List keybind actions /// List keybind actions
@"list-actions", @"list-actions",
/// Manage SSH terminfo cache for automatic remote host setup
@"ssh-cache",
/// Edit the config file in the configured terminal editor. /// Edit the config file in the configured terminal editor.
@"edit-config", @"edit-config",
@ -155,6 +159,7 @@ pub const Action = enum {
.@"list-themes" => try list_themes.run(alloc), .@"list-themes" => try list_themes.run(alloc),
.@"list-colors" => try list_colors.run(alloc), .@"list-colors" => try list_colors.run(alloc),
.@"list-actions" => try list_actions.run(alloc), .@"list-actions" => try list_actions.run(alloc),
.@"ssh-cache" => try ssh_cache.run(alloc),
.@"edit-config" => try edit_config.run(alloc), .@"edit-config" => try edit_config.run(alloc),
.@"show-config" => try show_config.run(alloc), .@"show-config" => try show_config.run(alloc),
.@"validate-config" => try validate_config.run(alloc), .@"validate-config" => try validate_config.run(alloc),
@ -192,6 +197,7 @@ pub const Action = enum {
.@"list-themes" => list_themes.Options, .@"list-themes" => list_themes.Options,
.@"list-colors" => list_colors.Options, .@"list-colors" => list_colors.Options,
.@"list-actions" => list_actions.Options, .@"list-actions" => list_actions.Options,
.@"ssh-cache" => ssh_cache.Options,
.@"edit-config" => edit_config.Options, .@"edit-config" => edit_config.Options,
.@"show-config" => show_config.Options, .@"show-config" => show_config.Options,
.@"validate-config" => validate_config.Options, .@"validate-config" => validate_config.Options,

View File

@ -0,0 +1,549 @@
/// An SSH terminfo entry cache that stores its cache data on
/// disk. The cache only stores metadata (hostname, terminfo value,
/// etc.) and does not store any sensitive data.
const DiskCache = @This();
const std = @import("std");
const assert = std.debug.assert;
const Allocator = std.mem.Allocator;
const xdg = @import("../../os/main.zig").xdg;
const TempDir = @import("../../os/main.zig").TempDir;
const Entry = @import("Entry.zig");
// 512KB - sufficient for approximately 10k entries
const MAX_CACHE_SIZE = 512 * 1024;
/// Path to a file where the cache is stored.
path: []const u8,
pub const DefaultPathError = Allocator.Error || error{
/// The general error that is returned for any filesystem error
/// that may have resulted in the XDG lookup failing.
XdgLookupFailed,
};
pub const Error = error{ CacheIsLocked, HostnameIsInvalid };
/// Returns the default path for the cache for a given program.
///
/// On all platforms, this is `${XDG_STATE_HOME}/ghostty/ssh_cache`.
///
/// The returned value is allocated and must be freed by the caller.
pub fn defaultPath(
alloc: Allocator,
program: []const u8,
) DefaultPathError![]const u8 {
const state_dir: []const u8 = xdg.state(
alloc,
.{ .subdir = program },
) catch |err| return switch (err) {
error.OutOfMemory => error.OutOfMemory,
else => error.XdgLookupFailed,
};
defer alloc.free(state_dir);
return try std.fs.path.join(alloc, &.{ state_dir, "ssh_cache" });
}
/// Clear all cache data stored in the disk cache.
/// This removes the cache file from disk, effectively clearing all cached
/// SSH terminfo entries.
pub fn clear(self: DiskCache) !void {
std.fs.cwd().deleteFile(self.path) catch |err| switch (err) {
error.FileNotFound => {},
else => return err,
};
}
pub const AddResult = enum { added, updated };
/// Add or update a hostname entry in the cache.
/// Returns AddResult.added for new entries or AddResult.updated for existing ones.
/// The cache file is created if it doesn't exist with secure permissions (0600).
pub fn add(
self: DiskCache,
alloc: Allocator,
hostname: []const u8,
) !AddResult {
if (!isValidCacheKey(hostname)) return error.HostnameIsInvalid;
// Create cache directory if needed
if (std.fs.path.dirname(self.path)) |dir| {
std.fs.makeDirAbsolute(dir) catch |err| switch (err) {
error.PathAlreadyExists => {},
else => return err,
};
}
// Open or create cache file with secure permissions
const file = std.fs.createFileAbsolute(self.path, .{
.read = true,
.truncate = false,
.mode = 0o600,
}) catch |err| switch (err) {
error.PathAlreadyExists => blk: {
const existing_file = try std.fs.openFileAbsolute(
self.path,
.{ .mode = .read_write },
);
errdefer existing_file.close();
try fixupPermissions(existing_file);
break :blk existing_file;
},
else => return err,
};
defer file.close();
// Lock
_ = file.tryLock(.exclusive) catch return error.CacheIsLocked;
defer file.unlock();
var entries = try readEntries(alloc, file);
defer deinitEntries(alloc, &entries);
// Add or update entry
const gop = try entries.getOrPut(hostname);
const result: AddResult = if (!gop.found_existing) add: {
const hostname_copy = try alloc.dupe(u8, hostname);
errdefer alloc.free(hostname_copy);
const terminfo_copy = try alloc.dupe(u8, "xterm-ghostty");
errdefer alloc.free(terminfo_copy);
gop.key_ptr.* = hostname_copy;
gop.value_ptr.* = .{
.hostname = gop.key_ptr.*,
.timestamp = std.time.timestamp(),
.terminfo_version = terminfo_copy,
};
break :add .added;
} else update: {
// Update timestamp for existing entry
gop.value_ptr.timestamp = std.time.timestamp();
break :update .updated;
};
try self.writeCacheFile(alloc, entries, null);
return result;
}
/// Remove a hostname entry from the cache.
/// No error is returned if the hostname doesn't exist or the cache file is missing.
pub fn remove(
self: DiskCache,
alloc: Allocator,
hostname: []const u8,
) !void {
if (!isValidCacheKey(hostname)) return error.HostnameIsInvalid;
// Open our file
const file = std.fs.openFileAbsolute(
self.path,
.{ .mode = .read_write },
) catch |err| switch (err) {
error.FileNotFound => return,
else => return err,
};
defer file.close();
try fixupPermissions(file);
// Acquire exclusive lock
_ = file.tryLock(.exclusive) catch return error.CacheIsLocked;
defer file.unlock();
// Read existing entries
var entries = try readEntries(alloc, file);
defer deinitEntries(alloc, &entries);
// Remove the entry if it exists and ensure we free the memory
if (entries.fetchRemove(hostname)) |kv| {
assert(kv.key.ptr == kv.value.hostname.ptr);
alloc.free(kv.value.hostname);
alloc.free(kv.value.terminfo_version);
}
try self.writeCacheFile(alloc, entries, null);
}
/// Check if a hostname exists in the cache.
/// Returns false if the cache file doesn't exist.
pub fn contains(
self: DiskCache,
alloc: Allocator,
hostname: []const u8,
) !bool {
if (!isValidCacheKey(hostname)) return error.HostnameIsInvalid;
// Open our file
const file = std.fs.openFileAbsolute(
self.path,
.{ .mode = .read_write },
) catch |err| switch (err) {
error.FileNotFound => return false,
else => return err,
};
defer file.close();
try fixupPermissions(file);
// Read existing entries
var entries = try readEntries(alloc, file);
defer deinitEntries(alloc, &entries);
return entries.contains(hostname);
}
fn fixupPermissions(file: std.fs.File) !void {
// Ensure file has correct permissions (readable/writable by
// owner only)
const stat = try file.stat();
if (stat.mode & 0o777 != 0o600) {
try file.chmod(0o600);
}
}
fn writeCacheFile(
self: DiskCache,
alloc: Allocator,
entries: std.StringHashMap(Entry),
expire_days: ?u32,
) !void {
var td: TempDir = try .init();
defer td.deinit();
const tmp_file = try td.dir.createFile("ssh-cache", .{ .mode = 0o600 });
defer tmp_file.close();
const tmp_path = try td.dir.realpathAlloc(alloc, "ssh-cache");
defer alloc.free(tmp_path);
const writer = tmp_file.writer();
var iter = entries.iterator();
while (iter.next()) |kv| {
// Only write non-expired entries
if (kv.value_ptr.isExpired(expire_days)) continue;
try kv.value_ptr.format(writer);
}
// Atomic replace
try std.fs.renameAbsolute(tmp_path, self.path);
}
/// List all entries in the cache.
/// The returned HashMap must be freed using `deinitEntries`.
/// Returns an empty map if the cache file doesn't exist.
pub fn list(
self: DiskCache,
alloc: Allocator,
) !std.StringHashMap(Entry) {
// Open our file
const file = std.fs.openFileAbsolute(
self.path,
.{},
) catch |err| switch (err) {
error.FileNotFound => return .init(alloc),
else => return err,
};
defer file.close();
return readEntries(alloc, file);
}
/// Free memory allocated by the `list` function.
/// This must be called to properly deallocate all entry data.
pub fn deinitEntries(
alloc: Allocator,
entries: *std.StringHashMap(Entry),
) void {
// All our entries we dupe the memory owned by the hostname and the
// terminfo, and we always match the hostname key and value.
var it = entries.iterator();
while (it.next()) |entry| {
assert(entry.key_ptr.*.ptr == entry.value_ptr.hostname.ptr);
alloc.free(entry.value_ptr.hostname);
alloc.free(entry.value_ptr.terminfo_version);
}
entries.deinit();
}
fn readEntries(
alloc: Allocator,
file: std.fs.File,
) !std.StringHashMap(Entry) {
const content = try file.readToEndAlloc(alloc, MAX_CACHE_SIZE);
defer alloc.free(content);
var entries = std.StringHashMap(Entry).init(alloc);
var lines = std.mem.tokenizeScalar(u8, content, '\n');
while (lines.next()) |line| {
const trimmed = std.mem.trim(u8, line, " \t\r");
const entry = Entry.parse(trimmed) orelse continue;
// Always allocate hostname first to avoid key pointer confusion
const hostname = try alloc.dupe(u8, entry.hostname);
errdefer alloc.free(hostname);
const gop = try entries.getOrPut(hostname);
if (!gop.found_existing) {
const terminfo_copy = try alloc.dupe(u8, entry.terminfo_version);
gop.value_ptr.* = .{
.hostname = hostname,
.timestamp = entry.timestamp,
.terminfo_version = terminfo_copy,
};
} else {
// Don't need the copy since entry already exists
alloc.free(hostname);
// Handle duplicate entries - keep newer timestamp
if (entry.timestamp > gop.value_ptr.timestamp) {
gop.value_ptr.timestamp = entry.timestamp;
if (!std.mem.eql(
u8,
gop.value_ptr.terminfo_version,
entry.terminfo_version,
)) {
alloc.free(gop.value_ptr.terminfo_version);
const terminfo_copy = try alloc.dupe(u8, entry.terminfo_version);
gop.value_ptr.terminfo_version = terminfo_copy;
}
}
}
}
return entries;
}
// Supports both standalone hostnames and user@hostname format
fn isValidCacheKey(key: []const u8) bool {
// 253 + 1 + 64 for user@hostname
if (key.len == 0 or key.len > 320) return false;
// Check for user@hostname format
if (std.mem.indexOf(u8, key, "@")) |at_pos| {
const user = key[0..at_pos];
const hostname = key[at_pos + 1 ..];
return isValidUser(user) and isValidHostname(hostname);
}
return isValidHostname(key);
}
// Basic hostname validation - accepts domains and IPs
// (including IPv6 in brackets)
fn isValidHostname(host: []const u8) bool {
if (host.len == 0 or host.len > 253) return false;
// Handle IPv6 addresses in brackets
if (host.len >= 4 and host[0] == '[' and host[host.len - 1] == ']') {
const ipv6_part = host[1 .. host.len - 1];
if (ipv6_part.len == 0) return false;
var has_colon = false;
for (ipv6_part) |c| {
switch (c) {
'a'...'f', 'A'...'F', '0'...'9' => {},
':' => has_colon = true,
else => return false,
}
}
return has_colon;
}
// Standard hostname/domain validation
for (host) |c| {
switch (c) {
'a'...'z', 'A'...'Z', '0'...'9', '.', '-' => {},
else => return false,
}
}
// No leading/trailing dots or hyphens, no consecutive dots
if (host[0] == '.' or host[0] == '-' or
host[host.len - 1] == '.' or host[host.len - 1] == '-')
{
return false;
}
return std.mem.indexOf(u8, host, "..") == null;
}
fn isValidUser(user: []const u8) bool {
if (user.len == 0 or user.len > 64) return false;
for (user) |c| {
switch (c) {
'a'...'z', 'A'...'Z', '0'...'9', '_', '-', '.' => {},
else => return false,
}
}
return true;
}
test "disk cache default path" {
const testing = std.testing;
const alloc = std.testing.allocator;
const path = try DiskCache.defaultPath(alloc, "ghostty");
defer alloc.free(path);
try testing.expect(path.len > 0);
}
test "disk cache clear" {
const testing = std.testing;
const alloc = testing.allocator;
// Create our path
var td: TempDir = try .init();
defer td.deinit();
{
var file = try td.dir.createFile("cache", .{});
defer file.close();
try file.writer().writeAll("HELLO!");
}
const path = try td.dir.realpathAlloc(alloc, "cache");
defer alloc.free(path);
// Setup our cache
const cache: DiskCache = .{ .path = path };
try cache.clear();
// Verify the file is gone
try testing.expectError(
error.FileNotFound,
td.dir.openFile("cache", .{}),
);
}
test "disk cache operations" {
const testing = std.testing;
const alloc = testing.allocator;
// Create our path
var td: TempDir = try .init();
defer td.deinit();
{
var file = try td.dir.createFile("cache", .{});
defer file.close();
try file.writer().writeAll("HELLO!");
}
const path = try td.dir.realpathAlloc(alloc, "cache");
defer alloc.free(path);
// Setup our cache
const cache: DiskCache = .{ .path = path };
try testing.expectEqual(
AddResult.added,
try cache.add(alloc, "example.com"),
);
try testing.expectEqual(
AddResult.updated,
try cache.add(alloc, "example.com"),
);
try testing.expect(
try cache.contains(alloc, "example.com"),
);
// List
var entries = try cache.list(alloc);
deinitEntries(alloc, &entries);
// Remove
try cache.remove(alloc, "example.com");
try testing.expect(
!(try cache.contains(alloc, "example.com")),
);
try testing.expectEqual(
AddResult.added,
try cache.add(alloc, "example.com"),
);
}
// Tests
test "hostname validation - valid cases" {
const testing = std.testing;
try testing.expect(isValidHostname("example.com"));
try testing.expect(isValidHostname("sub.example.com"));
try testing.expect(isValidHostname("host-name.domain.org"));
try testing.expect(isValidHostname("192.168.1.1"));
try testing.expect(isValidHostname("a"));
try testing.expect(isValidHostname("1"));
}
test "hostname validation - IPv6 addresses" {
const testing = std.testing;
try testing.expect(isValidHostname("[::1]"));
try testing.expect(isValidHostname("[2001:db8::1]"));
try testing.expect(!isValidHostname("[fe80::1%eth0]")); // Interface notation not supported
try testing.expect(!isValidHostname("[]")); // Empty IPv6
try testing.expect(!isValidHostname("[invalid]")); // No colons
}
test "hostname validation - invalid cases" {
const testing = std.testing;
try testing.expect(!isValidHostname(""));
try testing.expect(!isValidHostname("host\nname"));
try testing.expect(!isValidHostname(".example.com"));
try testing.expect(!isValidHostname("example.com."));
try testing.expect(!isValidHostname("host..domain"));
try testing.expect(!isValidHostname("-hostname"));
try testing.expect(!isValidHostname("hostname-"));
try testing.expect(!isValidHostname("host name"));
try testing.expect(!isValidHostname("host_name"));
try testing.expect(!isValidHostname("host@domain"));
try testing.expect(!isValidHostname("host:port"));
// Too long
const long_host = "a" ** 254;
try testing.expect(!isValidHostname(long_host));
}
test "user validation - valid cases" {
const testing = std.testing;
try testing.expect(isValidUser("user"));
try testing.expect(isValidUser("deploy"));
try testing.expect(isValidUser("test-user"));
try testing.expect(isValidUser("user_name"));
try testing.expect(isValidUser("user.name"));
try testing.expect(isValidUser("user123"));
try testing.expect(isValidUser("a"));
}
test "user validation - complex realistic cases" {
const testing = std.testing;
try testing.expect(isValidUser("git"));
try testing.expect(isValidUser("ubuntu"));
try testing.expect(isValidUser("root"));
try testing.expect(isValidUser("service.account"));
try testing.expect(isValidUser("user-with-dashes"));
}
test "user validation - invalid cases" {
const testing = std.testing;
try testing.expect(!isValidUser(""));
try testing.expect(!isValidUser("user name"));
try testing.expect(!isValidUser("user@domain"));
try testing.expect(!isValidUser("user:group"));
try testing.expect(!isValidUser("user\nname"));
// Too long
const long_user = "a" ** 65;
try testing.expect(!isValidUser(long_user));
}
test "cache key validation - hostname format" {
const testing = std.testing;
try testing.expect(isValidCacheKey("example.com"));
try testing.expect(isValidCacheKey("sub.example.com"));
try testing.expect(isValidCacheKey("192.168.1.1"));
try testing.expect(isValidCacheKey("[::1]"));
try testing.expect(!isValidCacheKey(""));
try testing.expect(!isValidCacheKey(".invalid.com"));
}
test "cache key validation - user@hostname format" {
const testing = std.testing;
try testing.expect(isValidCacheKey("user@example.com"));
try testing.expect(isValidCacheKey("deploy@prod.server.com"));
try testing.expect(isValidCacheKey("test-user@192.168.1.1"));
try testing.expect(isValidCacheKey("user_name@host.domain.org"));
try testing.expect(isValidCacheKey("git@github.com"));
try testing.expect(isValidCacheKey("ubuntu@[::1]"));
try testing.expect(!isValidCacheKey("@example.com"));
try testing.expect(!isValidCacheKey("user@"));
try testing.expect(!isValidCacheKey("user@@host"));
try testing.expect(!isValidCacheKey("user@.invalid.com"));
}

154
src/cli/ssh-cache/Entry.zig Normal file
View File

@ -0,0 +1,154 @@
/// A single entry within our SSH entry cache. Our SSH entry cache
/// stores which hosts we've sent our terminfo to so that we don't have
/// to send it again. It doesn't store any sensitive information.
const Entry = @This();
const std = @import("std");
hostname: []const u8,
timestamp: i64,
terminfo_version: []const u8,
pub fn parse(line: []const u8) ?Entry {
const trimmed = std.mem.trim(u8, line, " \t\r\n");
if (trimmed.len == 0) return null;
// Parse format: hostname|timestamp|terminfo_version
var iter = std.mem.tokenizeScalar(u8, trimmed, '|');
const hostname = iter.next() orelse return null;
const timestamp_str = iter.next() orelse return null;
const terminfo_version = iter.next() orelse "xterm-ghostty";
const timestamp = std.fmt.parseInt(i64, timestamp_str, 10) catch |err| {
std.log.warn(
"Invalid timestamp in cache entry: {s} err={}",
.{ timestamp_str, err },
);
return null;
};
return .{
.hostname = hostname,
.timestamp = timestamp,
.terminfo_version = terminfo_version,
};
}
pub fn format(self: Entry, writer: anytype) !void {
try writer.print(
"{s}|{d}|{s}\n",
.{ self.hostname, self.timestamp, self.terminfo_version },
);
}
pub fn isExpired(self: Entry, expire_days_: ?u32) bool {
const expire_days = expire_days_ orelse return false;
const now = std.time.timestamp();
const age_days = @divTrunc(now -| self.timestamp, std.time.s_per_day);
return age_days > expire_days;
}
test "cache entry expiration" {
const testing = std.testing;
const now = std.time.timestamp();
const fresh_entry: Entry = .{
.hostname = "test.com",
.timestamp = now - std.time.s_per_day, // 1 day old
.terminfo_version = "xterm-ghostty",
};
try testing.expect(!fresh_entry.isExpired(90));
const old_entry: Entry = .{
.hostname = "old.com",
.timestamp = now - (std.time.s_per_day * 100), // 100 days old
.terminfo_version = "xterm-ghostty",
};
try testing.expect(old_entry.isExpired(90));
// Test never-expire case
try testing.expect(!old_entry.isExpired(null));
}
test "cache entry expiration exact boundary" {
const testing = std.testing;
const now = std.time.timestamp();
// Exactly at expiration boundary
const boundary_entry: Entry = .{
.hostname = "example.com",
.timestamp = now - (std.time.s_per_day * 30),
.terminfo_version = "xterm-ghostty",
};
try testing.expect(!boundary_entry.isExpired(30));
try testing.expect(boundary_entry.isExpired(29));
}
test "cache entry expiration large timestamp" {
const testing = std.testing;
const now = std.time.timestamp();
const boundary_entry: Entry = .{
.hostname = "example.com",
.timestamp = now + (std.time.s_per_day * 30),
.terminfo_version = "xterm-ghostty",
};
try testing.expect(!boundary_entry.isExpired(30));
}
test "cache entry parsing valid formats" {
const testing = std.testing;
const entry = Entry.parse("example.com|1640995200|xterm-ghostty").?;
try testing.expectEqualStrings("example.com", entry.hostname);
try testing.expectEqual(@as(i64, 1640995200), entry.timestamp);
try testing.expectEqualStrings("xterm-ghostty", entry.terminfo_version);
// Test default terminfo version
const entry_no_version = Entry.parse("test.com|1640995200").?;
try testing.expectEqualStrings(
"xterm-ghostty",
entry_no_version.terminfo_version,
);
// Test complex hostnames
const complex_entry = Entry.parse("user@server.example.com|1640995200|xterm-ghostty").?;
try testing.expectEqualStrings(
"user@server.example.com",
complex_entry.hostname,
);
}
test "cache entry parsing invalid formats" {
const testing = std.testing;
try testing.expect(Entry.parse("") == null);
// Invalid format (no pipe)
try testing.expect(Entry.parse("v1") == null);
// Missing timestamp
try testing.expect(Entry.parse("example.com") == null);
// Invalid timestamp
try testing.expect(Entry.parse("example.com|invalid") == null);
// Empty terminfo should default
try testing.expect(Entry.parse("example.com|1640995200|") != null);
}
test "cache entry parsing malformed data resilience" {
const testing = std.testing;
// Extra pipes should not break parsing
try testing.expect(Entry.parse("host|123|term|extra") != null);
// Whitespace handling
try testing.expect(Entry.parse(" host|123|term ") != null);
try testing.expect(Entry.parse("\n") == null);
try testing.expect(Entry.parse(" \t \n") == null);
// Extremely large timestamp
try testing.expect(
Entry.parse("host|999999999999999999999999999999999999999999999999|xterm-ghostty") == null,
);
}

208
src/cli/ssh_cache.zig Normal file
View File

@ -0,0 +1,208 @@
const std = @import("std");
const fs = std.fs;
const Allocator = std.mem.Allocator;
const xdg = @import("../os/xdg.zig");
const args = @import("args.zig");
const Action = @import("action.zig").Action;
pub const Entry = @import("ssh-cache/Entry.zig");
pub const DiskCache = @import("ssh-cache/DiskCache.zig");
pub const Options = struct {
clear: bool = false,
add: ?[]const u8 = null,
remove: ?[]const u8 = null,
host: ?[]const u8 = null,
@"expire-days": ?u32 = null,
pub fn deinit(self: *Options) void {
_ = self;
}
pub fn help(self: Options) !void {
_ = self;
return Action.help_error;
}
};
/// Manage the SSH terminfo cache for automatic remote host setup.
///
/// When SSH integration is enabled with `shell-integration-features = ssh-terminfo`,
/// Ghostty automatically installs its terminfo on remote hosts. This command
/// manages the cache of successful installations to avoid redundant uploads.
///
/// The cache stores hostnames (or user@hostname combinations) along with timestamps.
/// Entries older than the expiration period are automatically removed during cache
/// operations. By default, entries never expire.
///
/// Only one of `--clear`, `--add`, `--remove`, or `--host` can be specified.
/// If multiple are specified, one of the actions will be executed but
/// it isn't guaranteed which one. This is entirely unsafe so you should split
/// multiple actions into separate commands.
///
/// Examples:
/// ghostty +ssh-cache # List all cached hosts
/// ghostty +ssh-cache --host=example.com # Check if host is cached
/// ghostty +ssh-cache --add=example.com # Manually add host to cache
/// ghostty +ssh-cache --add=user@example.com # Add user@host combination
/// ghostty +ssh-cache --remove=example.com # Remove host from cache
/// ghostty +ssh-cache --clear # Clear entire cache
/// ghostty +ssh-cache --expire-days=30 # Set custom expiration period
pub fn run(alloc_gpa: Allocator) !u8 {
var arena = std.heap.ArenaAllocator.init(alloc_gpa);
defer arena.deinit();
const alloc = arena.allocator();
var opts: Options = .{};
defer opts.deinit();
{
var iter = try args.argsIterator(alloc_gpa);
defer iter.deinit();
try args.parse(Options, alloc_gpa, &opts, &iter);
}
const stdout = std.io.getStdOut().writer();
const stderr = std.io.getStdErr().writer();
// Setup our disk cache to the standard location
const cache_path = try DiskCache.defaultPath(alloc, "ghostty");
const cache: DiskCache = .{ .path = cache_path };
if (opts.clear) {
try cache.clear();
try stdout.print("Cache cleared.\n", .{});
return 0;
}
if (opts.add) |host| {
const result = cache.add(alloc, host) catch |err| switch (err) {
DiskCache.Error.HostnameIsInvalid => {
try stderr.print("Error: Invalid hostname format '{s}'\n", .{host});
try stderr.print("Expected format: hostname or user@hostname\n", .{});
return 1;
},
DiskCache.Error.CacheIsLocked => {
try stderr.print("Error: Cache is busy, try again\n", .{});
return 1;
},
else => {
try stderr.print(
"Error: Unable to add '{s}' to cache. Error: {}\n",
.{ host, err },
);
return 1;
},
};
switch (result) {
.added => try stdout.print("Added '{s}' to cache.\n", .{host}),
.updated => try stdout.print("Updated '{s}' cache entry.\n", .{host}),
}
return 0;
}
if (opts.remove) |host| {
cache.remove(alloc, host) catch |err| switch (err) {
DiskCache.Error.HostnameIsInvalid => {
try stderr.print("Error: Invalid hostname format '{s}'\n", .{host});
try stderr.print("Expected format: hostname or user@hostname\n", .{});
return 1;
},
DiskCache.Error.CacheIsLocked => {
try stderr.print("Error: Cache is busy, try again\n", .{});
return 1;
},
else => {
try stderr.print(
"Error: Unable to remove '{s}' from cache. Error: {}\n",
.{ host, err },
);
return 1;
},
};
try stdout.print("Removed '{s}' from cache.\n", .{host});
return 0;
}
if (opts.host) |host| {
const cached = cache.contains(alloc, host) catch |err| switch (err) {
error.HostnameIsInvalid => {
try stderr.print("Error: Invalid hostname format '{s}'\n", .{host});
try stderr.print("Expected format: hostname or user@hostname\n", .{});
return 1;
},
else => {
try stderr.print(
"Error: Unable to check host '{s}' in cache. Error: {}\n",
.{ host, err },
);
return 1;
},
};
if (cached) {
try stdout.print(
"'{s}' has Ghostty terminfo installed.\n",
.{host},
);
return 0;
} else {
try stdout.print(
"'{s}' does not have Ghostty terminfo installed.\n",
.{host},
);
return 1;
}
}
// Default action: list all hosts
var entries = try cache.list(alloc);
defer DiskCache.deinitEntries(alloc, &entries);
try listEntries(alloc, &entries, stdout);
return 0;
}
fn listEntries(
alloc: Allocator,
entries: *const std.StringHashMap(Entry),
writer: anytype,
) !void {
if (entries.count() == 0) {
try writer.print("No hosts in cache.\n", .{});
return;
}
// Sort entries by hostname for consistent output
var items = std.ArrayList(Entry).init(alloc);
defer items.deinit();
var iter = entries.iterator();
while (iter.next()) |kv| {
try items.append(kv.value_ptr.*);
}
std.mem.sort(Entry, items.items, {}, struct {
fn lessThan(_: void, a: Entry, b: Entry) bool {
return std.mem.lessThan(u8, a.hostname, b.hostname);
}
}.lessThan);
try writer.print("Cached hosts ({d}):\n", .{items.items.len});
const now = std.time.timestamp();
for (items.items) |entry| {
const age_days = @divTrunc(now - entry.timestamp, std.time.s_per_day);
if (age_days == 0) {
try writer.print(" {s} (today)\n", .{entry.hostname});
} else if (age_days == 1) {
try writer.print(" {s} (yesterday)\n", .{entry.hostname});
} else {
try writer.print(" {s} ({d} days ago)\n", .{ entry.hostname, age_days });
}
}
}
test {
_ = DiskCache;
_ = Entry;
}

View File

@ -1,7 +1,9 @@
const std = @import("std"); const std = @import("std");
const assert = std.debug.assert;
const cli = @import("../cli.zig"); const cli = @import("../cli.zig");
const inputpkg = @import("../input.zig"); const inputpkg = @import("../input.zig");
const global = &@import("../global.zig").state; const state = &@import("../global.zig").state;
const c = @import("../main_c.zig");
const Config = @import("Config.zig"); const Config = @import("Config.zig");
const c_get = @import("c_get.zig"); const c_get = @import("c_get.zig");
@ -12,14 +14,14 @@ const log = std.log.scoped(.config);
/// Create a new configuration filled with the initial default values. /// Create a new configuration filled with the initial default values.
export fn ghostty_config_new() ?*Config { export fn ghostty_config_new() ?*Config {
const result = global.alloc.create(Config) catch |err| { const result = state.alloc.create(Config) catch |err| {
log.err("error allocating config err={}", .{err}); log.err("error allocating config err={}", .{err});
return null; return null;
}; };
result.* = Config.default(global.alloc) catch |err| { result.* = Config.default(state.alloc) catch |err| {
log.err("error creating config err={}", .{err}); log.err("error creating config err={}", .{err});
global.alloc.destroy(result); state.alloc.destroy(result);
return null; return null;
}; };
@ -29,20 +31,20 @@ export fn ghostty_config_new() ?*Config {
export fn ghostty_config_free(ptr: ?*Config) void { export fn ghostty_config_free(ptr: ?*Config) void {
if (ptr) |v| { if (ptr) |v| {
v.deinit(); v.deinit();
global.alloc.destroy(v); state.alloc.destroy(v);
} }
} }
/// Deep clone the configuration. /// Deep clone the configuration.
export fn ghostty_config_clone(self: *Config) ?*Config { export fn ghostty_config_clone(self: *Config) ?*Config {
const result = global.alloc.create(Config) catch |err| { const result = state.alloc.create(Config) catch |err| {
log.err("error allocating config err={}", .{err}); log.err("error allocating config err={}", .{err});
return null; return null;
}; };
result.* = self.clone(global.alloc) catch |err| { result.* = self.clone(state.alloc) catch |err| {
log.err("error cloning config err={}", .{err}); log.err("error cloning config err={}", .{err});
global.alloc.destroy(result); state.alloc.destroy(result);
return null; return null;
}; };
@ -51,7 +53,7 @@ export fn ghostty_config_clone(self: *Config) ?*Config {
/// Load the configuration from the CLI args. /// Load the configuration from the CLI args.
export fn ghostty_config_load_cli_args(self: *Config) void { export fn ghostty_config_load_cli_args(self: *Config) void {
self.loadCliArgs(global.alloc) catch |err| { self.loadCliArgs(state.alloc) catch |err| {
log.err("error loading config err={}", .{err}); log.err("error loading config err={}", .{err});
}; };
} }
@ -60,7 +62,7 @@ export fn ghostty_config_load_cli_args(self: *Config) void {
/// is usually done first. The default file locations are locations /// is usually done first. The default file locations are locations
/// such as the home directory. /// such as the home directory.
export fn ghostty_config_load_default_files(self: *Config) void { export fn ghostty_config_load_default_files(self: *Config) void {
self.loadDefaultFiles(global.alloc) catch |err| { self.loadDefaultFiles(state.alloc) catch |err| {
log.err("error loading config err={}", .{err}); log.err("error loading config err={}", .{err});
}; };
} }
@ -69,7 +71,7 @@ export fn ghostty_config_load_default_files(self: *Config) void {
/// file locations in the previously loaded configuration. This will /// file locations in the previously loaded configuration. This will
/// recursively continue to load up to a built-in limit. /// recursively continue to load up to a built-in limit.
export fn ghostty_config_load_recursive_files(self: *Config) void { export fn ghostty_config_load_recursive_files(self: *Config) void {
self.loadRecursiveFiles(global.alloc) catch |err| { self.loadRecursiveFiles(state.alloc) catch |err| {
log.err("error loading config err={}", .{err}); log.err("error loading config err={}", .{err});
}; };
} }
@ -122,10 +124,13 @@ export fn ghostty_config_get_diagnostic(self: *Config, idx: u32) Diagnostic {
return .{ .message = message.ptr }; return .{ .message = message.ptr };
} }
export fn ghostty_config_open() void { export fn ghostty_config_open_path() c.String {
edit.open(global.alloc) catch |err| { const path = edit.openPath(state.alloc) catch |err| {
log.err("error opening config in editor err={}", .{err}); log.err("error opening config in editor err={}", .{err});
return .empty;
}; };
return .fromSlice(path);
} }
/// Sync with ghostty_diagnostic_s /// Sync with ghostty_diagnostic_s

View File

@ -305,6 +305,7 @@ pub const compatibility = std.StaticStringMap(
/// ///
/// * `cursor` - Break runs under the cursor. /// * `cursor` - Break runs under the cursor.
/// ///
/// Available since: 1.2.0
@"font-shaping-break": FontShapingBreak = .{}, @"font-shaping-break": FontShapingBreak = .{},
/// What color space to use when performing alpha blending. /// What color space to use when performing alpha blending.
@ -329,6 +330,8 @@ pub const compatibility = std.StaticStringMap(
/// * `linear-corrected` - Same as `linear`, but with a correction step applied /// * `linear-corrected` - Same as `linear`, but with a correction step applied
/// for text that makes it look nearly or completely identical to `native`, /// for text that makes it look nearly or completely identical to `native`,
/// but without any of the darkening artifacts. /// but without any of the darkening artifacts.
///
/// Available since: 1.1.0
@"alpha-blending": AlphaBlending = @"alpha-blending": AlphaBlending =
if (builtin.os.tag == .macos) if (builtin.os.tag == .macos)
.native .native
@ -396,6 +399,20 @@ pub const compatibility = std.StaticStringMap(
/// Thickness in pixels or percentage adjustment of box drawing characters. /// Thickness in pixels or percentage adjustment of box drawing characters.
/// See the notes about adjustments in `adjust-cell-width`. /// See the notes about adjustments in `adjust-cell-width`.
@"adjust-box-thickness": ?MetricModifier = null, @"adjust-box-thickness": ?MetricModifier = null,
/// Height in pixels or percentage adjustment of maximum height for nerd font icons.
///
/// Increasing this value will allow nerd font icons to be larger, but won't
/// necessarily force them to be. Decreasing this value will make nerd font
/// icons smaller.
///
/// The default value for the icon height is 1.2 times the height of capital
/// letters in your primary font, so something like -16.6% would make icons
/// roughly the same height as capital letters.
///
/// See the notes about adjustments in `adjust-cell-width`.
///
/// Available in: 1.2.0
@"adjust-icon-height": ?MetricModifier = null,
/// The method to use for calculating the cell width of a grapheme cluster. /// The method to use for calculating the cell width of a grapheme cluster.
/// The default value is `unicode` which uses the Unicode standard to determine /// The default value is `unicode` which uses the Unicode standard to determine
@ -503,7 +520,6 @@ pub const compatibility = std.StaticStringMap(
/// be fixed in a future update: /// be fixed in a future update:
/// ///
/// - macOS: titlebar tabs style is not updated when switching themes. /// - macOS: titlebar tabs style is not updated when switching themes.
///
theme: ?Theme = null, theme: ?Theme = null,
/// Background color for the window. /// Background color for the window.
@ -527,6 +543,8 @@ foreground: Color = .{ .r = 0xFF, .g = 0xFF, .b = 0xFF },
/// For sufficiently large images, this could lead to a large increase in /// For sufficiently large images, this could lead to a large increase in
/// memory usage (specifically VRAM usage). A future Ghostty improvement /// memory usage (specifically VRAM usage). A future Ghostty improvement
/// will resolve this by sharing image textures across terminals. /// will resolve this by sharing image textures across terminals.
///
/// Available since: 1.2.0
@"background-image": ?Path = null, @"background-image": ?Path = null,
/// Background image opacity. /// Background image opacity.
@ -546,6 +564,8 @@ foreground: Color = .{ .r = 0xFF, .g = 0xFF, .b = 0xFF },
/// configured `background-opacity` is `0.5` and `background-image-opacity` /// configured `background-opacity` is `0.5` and `background-image-opacity`
/// is set to `1.5`, then the final opacity of the background image will be /// is set to `1.5`, then the final opacity of the background image will be
/// `0.5 * 1.5 = 0.75`. /// `0.5 * 1.5 = 0.75`.
///
/// Available since: 1.2.0
@"background-image-opacity": f32 = 1.0, @"background-image-opacity": f32 = 1.0,
/// Background image position. /// Background image position.
@ -562,6 +582,8 @@ foreground: Color = .{ .r = 0xFF, .g = 0xFF, .b = 0xFF },
/// * `bottom-right` /// * `bottom-right`
/// ///
/// The default value is `center`. /// The default value is `center`.
///
/// Available since: 1.2.0
@"background-image-position": BackgroundImagePosition = .center, @"background-image-position": BackgroundImagePosition = .center,
/// Background image fit. /// Background image fit.
@ -590,6 +612,8 @@ foreground: Color = .{ .r = 0xFF, .g = 0xFF, .b = 0xFF },
/// Don't scale the background image. /// Don't scale the background image.
/// ///
/// The default value is `contain`. /// The default value is `contain`.
///
/// Available since: 1.2.0
@"background-image-fit": BackgroundImageFit = .contain, @"background-image-fit": BackgroundImageFit = .contain,
/// Whether to repeat the background image or not. /// Whether to repeat the background image or not.
@ -599,6 +623,8 @@ foreground: Color = .{ .r = 0xFF, .g = 0xFF, .b = 0xFF },
/// fill the terminal area. /// fill the terminal area.
/// ///
/// The default value is `false`. /// The default value is `false`.
///
/// Available since: 1.2.0
@"background-image-repeat": bool = false, @"background-image-repeat": bool = false,
/// The foreground and background color for selection. If this is not set, then /// The foreground and background color for selection. If this is not set, then
@ -624,6 +650,8 @@ foreground: Color = .{ .r = 0xFF, .g = 0xFF, .b = 0xFF },
/// ///
/// If this is `false`, then the selection can still be manually /// If this is `false`, then the selection can still be manually
/// cleared by clicking once or by pressing `escape`. /// cleared by clicking once or by pressing `escape`.
///
/// Available since: 1.2.0
@"selection-clear-on-typing": bool = true, @"selection-clear-on-typing": bool = true,
/// The minimum contrast ratio between the foreground and background colors. /// The minimum contrast ratio between the foreground and background colors.
@ -661,11 +689,10 @@ palette: Palette = .{},
/// other colors at runtime: /// other colors at runtime:
/// ///
/// * `cell-foreground` - Match the cell foreground color. /// * `cell-foreground` - Match the cell foreground color.
/// (Available since version 1.2.0) /// (Available since: 1.2.0)
/// ///
/// * `cell-background` - Match the cell background color. /// * `cell-background` - Match the cell background color.
/// (Available since version 1.2.0) /// (Available since: 1.2.0)
///
@"cursor-color": ?TerminalColor = null, @"cursor-color": ?TerminalColor = null,
/// The opacity level (opposite of transparency) of the cursor. A value of 1 /// The opacity level (opposite of transparency) of the cursor. A value of 1
@ -690,7 +717,6 @@ palette: Palette = .{},
/// * `bar` /// * `bar`
/// * `underline` /// * `underline`
/// * `block_hollow` /// * `block_hollow`
///
@"cursor-style": terminal.CursorStyle = .block, @"cursor-style": terminal.CursorStyle = .block,
/// Sets the default blinking state of the cursor. This is just the default /// Sets the default blinking state of the cursor. This is just the default
@ -710,7 +736,6 @@ palette: Palette = .{},
/// * ` ` (blank) /// * ` ` (blank)
/// * `true` /// * `true`
/// * `false` /// * `false`
///
@"cursor-style-blink": ?bool = null, @"cursor-style-blink": ?bool = null,
/// The color of the text under the cursor. If this is not set, a default will /// The color of the text under the cursor. If this is not set, a default will
@ -767,7 +792,6 @@ palette: Palette = .{},
/// * `false` /// * `false`
/// * `always` /// * `always`
/// * `never` /// * `never`
///
@"mouse-shift-capture": MouseShiftCapture = .false, @"mouse-shift-capture": MouseShiftCapture = .false,
/// Multiplier for scrolling distance with the mouse wheel. Any value less /// Multiplier for scrolling distance with the mouse wheel. Any value less
@ -775,6 +799,8 @@ palette: Palette = .{},
/// value. /// value.
/// ///
/// A value of "3" (default) scrolls 3 lines per tick. /// A value of "3" (default) scrolls 3 lines per tick.
///
/// Available since: 1.2.0
@"mouse-scroll-multiplier": f64 = 3.0, @"mouse-scroll-multiplier": f64 = 3.0,
/// The opacity level (opposite of transparency) of the background. A value of /// The opacity level (opposite of transparency) of the background. A value of
@ -843,6 +869,8 @@ palette: Palette = .{},
/// The color of the split divider. If this is not set, a default will be chosen. /// The color of the split divider. If this is not set, a default will be chosen.
/// Specified as either hex (`#RRGGBB` or `RRGGBB`) or a named X11 color. /// Specified as either hex (`#RRGGBB` or `RRGGBB`) or a named X11 color.
///
/// Available since: 1.1.0
@"split-divider-color": ?Color = null, @"split-divider-color": ?Color = null,
/// The command to run, usually a shell. If this is not an absolute path, it'll /// The command to run, usually a shell. If this is not an absolute path, it'll
@ -857,14 +885,14 @@ palette: Palette = .{},
/// arguments are provided, the command will be executed using `/bin/sh -c` /// arguments are provided, the command will be executed using `/bin/sh -c`
/// to offload shell argument expansion. /// to offload shell argument expansion.
/// ///
/// To avoid shell expansion altogether, prefix the command with `direct:`, /// To avoid shell expansion altogether, prefix the command with `direct:`, e.g.
/// e.g. `direct:nvim foo`. This will avoid the roundtrip to `/bin/sh` but will /// `direct:nvim foo`. This will avoid the roundtrip to `/bin/sh` but will also
/// also not support any shell parsing such as arguments with spaces, filepaths /// not support any shell parsing such as arguments with spaces, filepaths with
/// with `~`, globs, etc. /// `~`, globs, etc. (Available since: 1.2.0)
/// ///
/// You can also explicitly prefix the command with `shell:` to always /// You can also explicitly prefix the command with `shell:` to always wrap the
/// wrap the command in a shell. This can be used to ensure our heuristics /// command in a shell. This can be used to ensure our heuristics to choose the
/// to choose the right mode are not used in case they are wrong. /// right mode are not used in case they are wrong. (Available since: 1.2.0)
/// ///
/// This command will be used for all new terminal surfaces, i.e. new windows, /// This command will be used for all new terminal surfaces, i.e. new windows,
/// tabs, etc. If you want to run a command only for the first terminal surface /// tabs, etc. If you want to run a command only for the first terminal surface
@ -910,7 +938,6 @@ command: ?Command = null,
/// shell integration with a `-e`-executed command, you must either /// shell integration with a `-e`-executed command, you must either
/// name your binary appropriately or source the shell integration script /// name your binary appropriately or source the shell integration script
/// manually. /// manually.
///
@"initial-command": ?Command = null, @"initial-command": ?Command = null,
/// Extra environment variables to pass to commands launched in a terminal /// Extra environment variables to pass to commands launched in a terminal
@ -947,6 +974,8 @@ command: ?Command = null,
/// These environment variables _will not_ be passed to commands run by Ghostty /// These environment variables _will not_ be passed to commands run by Ghostty
/// for other purposes, like `open` or `xdg-open` used to open URLs in your /// for other purposes, like `open` or `xdg-open` used to open URLs in your
/// browser. /// browser.
///
/// Available since: 1.2.0
env: RepeatableStringMap = .{}, env: RepeatableStringMap = .{},
/// Data to send as input to the command on startup. /// Data to send as input to the command on startup.
@ -988,6 +1017,8 @@ env: RepeatableStringMap = .{},
/// ///
/// Changing this configuration at runtime will only affect new /// Changing this configuration at runtime will only affect new
/// terminals. /// terminals.
///
/// Available since: 1.2.0
input: RepeatableReadableIO = .{}, input: RepeatableReadableIO = .{},
/// If true, keep the terminal open after the command exits. Normally, the /// If true, keep the terminal open after the command exits. Normally, the
@ -1056,11 +1087,15 @@ link: RepeatableLink = .{},
/// previews are never shown. When set to "osc8", link previews are only shown /// previews are never shown. When set to "osc8", link previews are only shown
/// for hyperlinks created with the OSC 8 sequence (in this case, the link text /// for hyperlinks created with the OSC 8 sequence (in this case, the link text
/// can differ from the link destination). /// can differ from the link destination).
///
/// Available since: 1.2.0
@"link-previews": LinkPreviews = .true, @"link-previews": LinkPreviews = .true,
/// Whether to start the window in a maximized state. This setting applies /// Whether to start the window in a maximized state. This setting applies
/// to new windows and does not apply to tabs, splits, etc. However, this setting /// to new windows and does not apply to tabs, splits, etc. However, this setting
/// will apply to all new windows, not just the first one. /// will apply to all new windows, not just the first one.
///
/// Available since: 1.1.0
maximize: bool = false, maximize: bool = false,
/// Start new windows in fullscreen. This setting applies to new windows and /// Start new windows in fullscreen. This setting applies to new windows and
@ -1285,6 +1320,8 @@ class: ?[:0]const u8 = null,
/// applies to actions that are surface-specific. For actions that /// applies to actions that are surface-specific. For actions that
/// are already global (e.g. `quit`), this prefix has no effect. /// are already global (e.g. `quit`), this prefix has no effect.
/// ///
/// Available since: 1.0.0
///
/// * `global:` - Make the keybind global. By default, keybinds only work /// * `global:` - Make the keybind global. By default, keybinds only work
/// within Ghostty and under the right conditions (application focused, /// within Ghostty and under the right conditions (application focused,
/// sometimes terminal focused, etc.). If you want a keybind to work /// sometimes terminal focused, etc.). If you want a keybind to work
@ -1293,6 +1330,9 @@ class: ?[:0]const u8 = null,
/// work in all environments; see the additional notes below for more /// work in all environments; see the additional notes below for more
/// information. /// information.
/// ///
/// Available since: 1.0.0 (on macOS)
/// Available since: 1.2.0 (on GTK)
///
/// * `unconsumed:` - Do not consume the input. By default, a keybind /// * `unconsumed:` - Do not consume the input. By default, a keybind
/// will consume the input, meaning that the associated encoding (if /// will consume the input, meaning that the associated encoding (if
/// any) will not be sent to the running program in the terminal. If /// any) will not be sent to the running program in the terminal. If
@ -1303,6 +1343,8 @@ class: ?[:0]const u8 = null,
/// Since they are not associated with a specific terminal surface, /// Since they are not associated with a specific terminal surface,
/// they're never encoded. /// they're never encoded.
/// ///
/// Available since: 1.0.0
///
/// * `performable:` - Only consume the input if the action is able to be /// * `performable:` - Only consume the input if the action is able to be
/// performed. For example, the `copy_to_clipboard` action will only /// performed. For example, the `copy_to_clipboard` action will only
/// consume the input if there is a selection to copy. If there is no /// consume the input if there is a selection to copy. If there is no
@ -1318,6 +1360,8 @@ class: ?[:0]const u8 = null,
/// Performable keybinds will still work, they just won't appear as /// Performable keybinds will still work, they just won't appear as
/// a shortcut label in the menu. /// a shortcut label in the menu.
/// ///
/// Available since: 1.1.0
///
/// Keybind triggers are not unique per prefix combination. For example, /// Keybind triggers are not unique per prefix combination. For example,
/// `ctrl+a` and `global:ctrl+a` are not two separate keybinds. The keybind /// `ctrl+a` and `global:ctrl+a` are not two separate keybinds. The keybind
/// set later will overwrite the keybind set earlier. In this case, the /// set later will overwrite the keybind set earlier. In this case, the
@ -1427,7 +1471,6 @@ keybind: Keybinds = .{},
/// do not look good extended. /// do not look good extended.
/// * The nearest row contains a perfect fit powerline character. These /// * The nearest row contains a perfect fit powerline character. These
/// don't look good extended. /// don't look good extended.
///
@"window-padding-color": WindowPaddingColor = .background, @"window-padding-color": WindowPaddingColor = .background,
/// Synchronize rendering with the screen refresh rate. If true, this will /// Synchronize rendering with the screen refresh rate. If true, this will
@ -1474,6 +1517,8 @@ keybind: Keybinds = .{},
/// ///
/// * `client` - Prefer client-side decorations. /// * `client` - Prefer client-side decorations.
/// ///
/// Available since: 1.1.0
///
/// * `server` - Prefer server-side decorations. This is only relevant /// * `server` - Prefer server-side decorations. This is only relevant
/// on Linux with GTK, either on X11, or Wayland on a compositor that /// on Linux with GTK, either on X11, or Wayland on a compositor that
/// supports the `org_kde_kwin_server_decoration` protocol (e.g. KDE Plasma, /// supports the `org_kde_kwin_server_decoration` protocol (e.g. KDE Plasma,
@ -1482,6 +1527,8 @@ keybind: Keybinds = .{},
/// If `server` is set but the environment doesn't support server-side /// If `server` is set but the environment doesn't support server-side
/// decorations, client-side decorations will be used instead. /// decorations, client-side decorations will be used instead.
/// ///
/// Available since: 1.1.0
///
/// The default value is `auto`. /// The default value is `auto`.
/// ///
/// For the sake of backwards compatibility and convenience, this setting also /// For the sake of backwards compatibility and convenience, this setting also
@ -1504,6 +1551,8 @@ keybind: Keybinds = .{},
/// ///
/// Note: any font available on the system may be used, this font is not /// Note: any font available on the system may be used, this font is not
/// required to be a fixed-width font. /// required to be a fixed-width font.
///
/// Available since: 1.1.0 (on GTK)
@"window-title-font-family": ?[:0]const u8 = null, @"window-title-font-family": ?[:0]const u8 = null,
/// The text that will be displayed in the subtitle of the window. Valid values: /// The text that will be displayed in the subtitle of the window. Valid values:
@ -1513,6 +1562,8 @@ keybind: Keybinds = .{},
/// surface. /// surface.
/// ///
/// This feature is only supported on GTK. /// This feature is only supported on GTK.
///
/// Available since: 1.1.0
@"window-subtitle": WindowSubtitle = .false, @"window-subtitle": WindowSubtitle = .false,
/// The theme to use for the windows. Valid values: /// The theme to use for the windows. Valid values:
@ -1656,6 +1707,8 @@ keybind: Keybinds = .{},
/// ///
/// Always display the tab bar, even when there's only one tab. /// Always display the tab bar, even when there's only one tab.
/// ///
/// Available since: 1.2.0
///
/// - `auto` *(default)* /// - `auto` *(default)*
/// ///
/// Automatically show and hide the tab bar. The tab bar is only /// Automatically show and hide the tab bar. The tab bar is only
@ -1740,6 +1793,8 @@ keybind: Keybinds = .{},
/// ///
/// The maximum value is `584y 49w 23h 34m 33s 709ms 551µs 615ns`. Any /// The maximum value is `584y 49w 23h 34m 33s 709ms 551µs 615ns`. Any
/// value larger than this will be clamped to the maximum value. /// value larger than this will be clamped to the maximum value.
///
/// Available since 1.0.0
@"resize-overlay-duration": Duration = .{ .duration = 750 * std.time.ns_per_ms }, @"resize-overlay-duration": Duration = .{ .duration = 750 * std.time.ns_per_ms },
/// If true, when there are multiple split panes, the mouse selects the pane /// If true, when there are multiple split panes, the mouse selects the pane
@ -1785,6 +1840,8 @@ keybind: Keybinds = .{},
/// Warning: This can expose sensitive information at best and enable /// Warning: This can expose sensitive information at best and enable
/// arbitrary code execution at worst (with a maliciously crafted title /// arbitrary code execution at worst (with a maliciously crafted title
/// and a minor amount of user interaction). /// and a minor amount of user interaction).
///
/// Available since: 1.0.1
@"title-report": bool = false, @"title-report": bool = false,
/// The total amount of bytes that can be used for image data (e.g. the Kitty /// The total amount of bytes that can be used for image data (e.g. the Kitty
@ -1972,6 +2029,8 @@ keybind: Keybinds = .{},
/// This configuration is only supported on macOS. Linux doesn't /// This configuration is only supported on macOS. Linux doesn't
/// support undo operations at all so this configuration has no /// support undo operations at all so this configuration has no
/// effect. /// effect.
///
/// Available since: 1.2.0
@"undo-timeout": Duration = .{ .duration = 5 * std.time.ns_per_s }, @"undo-timeout": Duration = .{ .duration = 5 * std.time.ns_per_s },
/// The position of the "quick" terminal window. To learn more about the /// The position of the "quick" terminal window. To learn more about the
@ -2075,6 +2134,8 @@ keybind: Keybinds = .{},
/// ///
/// Only implemented on macOS. /// Only implemented on macOS.
/// On Linux the behavior is always equivalent to `move`. /// On Linux the behavior is always equivalent to `move`.
///
/// Available since: 1.1.0
@"quick-terminal-space-behavior": QuickTerminalSpaceBehavior = .move, @"quick-terminal-space-behavior": QuickTerminalSpaceBehavior = .move,
/// Determines under which circumstances that the quick terminal should receive /// Determines under which circumstances that the quick terminal should receive
@ -2103,6 +2164,8 @@ keybind: Keybinds = .{},
/// ///
/// Only has an effect on Linux Wayland. /// Only has an effect on Linux Wayland.
/// On macOS the behavior is always equivalent to `on-demand`. /// On macOS the behavior is always equivalent to `on-demand`.
///
/// Available since: 1.2.0
@"quick-terminal-keyboard-interactivity": QuickTerminalKeyboardInteractivity = .@"on-demand", @"quick-terminal-keyboard-interactivity": QuickTerminalKeyboardInteractivity = .@"on-demand",
/// Whether to enable shell integration auto-injection or not. Shell integration /// Whether to enable shell integration auto-injection or not. Shell integration
@ -2139,6 +2202,8 @@ keybind: Keybinds = .{},
/// its default value is used, so you must explicitly disable features you don't /// its default value is used, so you must explicitly disable features you don't
/// want. You can also use `true` or `false` to turn all features on or off. /// want. You can also use `true` or `false` to turn all features on or off.
/// ///
/// Example: `cursor`, `no-cursor`, `sudo`, `no-sudo`, `title`, `no-title`
///
/// Available features: /// Available features:
/// ///
/// * `cursor` - Set the cursor to a blinking bar at the prompt. /// * `cursor` - Set the cursor to a blinking bar at the prompt.
@ -2147,7 +2212,26 @@ keybind: Keybinds = .{},
/// ///
/// * `title` - Set the window title via shell integration. /// * `title` - Set the window title via shell integration.
/// ///
/// Example: `cursor`, `no-cursor`, `sudo`, `no-sudo`, `title`, `no-title` /// * `ssh-env` - Enable SSH environment variable compatibility. Automatically
/// converts TERM from `xterm-ghostty` to `xterm-256color` when connecting to
/// remote hosts and propagates COLORTERM, TERM_PROGRAM, and TERM_PROGRAM_VERSION.
/// Whether or not these variables will be accepted by the remote host(s) will
/// depend on whether or not the variables are allowed in their sshd_config.
/// (Available since: 1.2.0)
///
/// * `ssh-terminfo` - Enable automatic terminfo installation on remote hosts.
/// Attempts to install Ghostty's terminfo entry using `infocmp` and `tic` when
/// connecting to hosts that lack it. Requires `infocmp` to be available locally
/// and `tic` to be available on remote hosts. Once terminfo is installed on a
/// remote host, it will be automatically "cached" to avoid repeat installations.
/// If desired, the `+ssh-cache` CLI action can be used to manage the installation
/// cache manually using various arguments.
/// (Available since: 1.2.0)
///
/// SSH features work independently and can be combined for optimal experience:
/// when both `ssh-env` and `ssh-terminfo` are enabled, Ghostty will install its
/// terminfo on remote hosts and use `xterm-ghostty` as TERM, falling back to
/// `xterm-256color` with environment variables if terminfo installation fails.
@"shell-integration-features": ShellIntegrationFeatures = .{}, @"shell-integration-features": ShellIntegrationFeatures = .{},
/// Custom entries into the command palette. /// Custom entries into the command palette.
@ -2170,6 +2254,8 @@ keybind: Keybinds = .{},
/// ```ini /// ```ini
/// command-palette-entry = /// command-palette-entry =
/// ``` /// ```
///
/// Available since: 1.2.0
@"command-palette-entry": RepeatableCommand = .{}, @"command-palette-entry": RepeatableCommand = .{},
/// Sets the reporting format for OSC sequences that request color information. /// Sets the reporting format for OSC sequences that request color information.
@ -2334,6 +2420,8 @@ keybind: Keybinds = .{},
/// Only implemented on macOS. /// Only implemented on macOS.
/// ///
/// Example: `audio`, `no-audio`, `system`, `no-system` /// Example: `audio`, `no-audio`, `system`, `no-system`
///
/// Available since: 1.2.0
@"bell-features": BellFeatures = .{}, @"bell-features": BellFeatures = .{},
/// If `audio` is an enabled bell feature, this is a path to an audio file. If /// If `audio` is an enabled bell feature, this is a path to an audio file. If
@ -2341,12 +2429,16 @@ keybind: Keybinds = .{},
/// configuration file that it is referenced from, or from the current working /// configuration file that it is referenced from, or from the current working
/// directory if this is used as a CLI flag. The path may be prefixed with `~/` /// directory if this is used as a CLI flag. The path may be prefixed with `~/`
/// to reference the user's home directory. (GTK only) /// to reference the user's home directory. (GTK only)
///
/// Available since: 1.2.0
@"bell-audio-path": ?Path = null, @"bell-audio-path": ?Path = null,
/// If `audio` is an enabled bell feature, this is the volume to play the audio /// If `audio` is an enabled bell feature, this is the volume to play the audio
/// file at (relative to the system volume). This is a floating point number /// file at (relative to the system volume). This is a floating point number
/// ranging from 0.0 (silence) to 1.0 (as loud as possible). The default is 0.5. /// ranging from 0.0 (silence) to 1.0 (as loud as possible). The default is 0.5.
/// (GTK only) /// (GTK only)
///
/// Available since: 1.2.0
@"bell-audio-volume": f64 = 0.5, @"bell-audio-volume": f64 = 0.5,
/// Control the in-app notifications that Ghostty shows. /// Control the in-app notifications that Ghostty shows.
@ -2372,6 +2464,8 @@ keybind: Keybinds = .{},
/// enable all notifications. /// enable all notifications.
/// ///
/// This configuration only applies to GTK. /// This configuration only applies to GTK.
///
/// Available since: 1.1.0
@"app-notifications": AppNotifications = .{}, @"app-notifications": AppNotifications = .{},
/// If anything other than false, fullscreen mode on macOS will not use the /// If anything other than false, fullscreen mode on macOS will not use the
@ -2422,6 +2516,8 @@ keybind: Keybinds = .{},
/// The default value is `visible`. /// The default value is `visible`.
/// ///
/// Changing this option at runtime only applies to new windows. /// Changing this option at runtime only applies to new windows.
///
/// Available since: 1.2.0
@"macos-window-buttons": MacWindowButtons = .visible, @"macos-window-buttons": MacWindowButtons = .visible,
/// The style of the macOS titlebar. Available values are: "native", /// The style of the macOS titlebar. Available values are: "native",
@ -2544,6 +2640,8 @@ keybind: Keybinds = .{},
/// ///
/// Note: When the macOS application is hidden, keyboard layout changes /// Note: When the macOS application is hidden, keyboard layout changes
/// will no longer be automatic. This is a limitation of macOS. /// will no longer be automatic. This is a limitation of macOS.
///
/// Available since: 1.2.0
@"macos-hidden": MacHidden = .never, @"macos-hidden": MacHidden = .never,
/// If true, Ghostty on macOS will automatically enable the "Secure Input" /// If true, Ghostty on macOS will automatically enable the "Secure Input"
@ -2605,7 +2703,6 @@ keybind: Keybinds = .{},
/// This is because the update dialog is managed through a /// This is because the update dialog is managed through a
/// separate framework and cannot be customized without significant /// separate framework and cannot be customized without significant
/// effort. /// effort.
///
@"macos-icon": MacAppIcon = .official, @"macos-icon": MacAppIcon = .official,
/// The material to use for the frame of the macOS app icon. /// The material to use for the frame of the macOS app icon.
@ -2619,7 +2716,6 @@ keybind: Keybinds = .{},
/// ///
/// Note: This configuration is required when `macos-icon` is set to /// Note: This configuration is required when `macos-icon` is set to
/// `custom-style`. /// `custom-style`.
///
@"macos-icon-frame": MacAppIconFrame = .aluminum, @"macos-icon-frame": MacAppIconFrame = .aluminum,
/// The color of the ghost in the macOS app icon. /// The color of the ghost in the macOS app icon.
@ -2640,7 +2736,6 @@ keybind: Keybinds = .{},
/// ///
/// Note: This configuration is required when `macos-icon` is set to /// Note: This configuration is required when `macos-icon` is set to
/// `custom-style`. /// `custom-style`.
///
@"macos-icon-screen-color": ?ColorList = null, @"macos-icon-screen-color": ?ColorList = null,
/// Whether macOS Shortcuts are allowed to control Ghostty. /// Whether macOS Shortcuts are allowed to control Ghostty.
@ -2664,6 +2759,7 @@ keybind: Keybinds = .{},
/// ///
/// * `deny` - Deny Shortcuts from controlling Ghostty. /// * `deny` - Deny Shortcuts from controlling Ghostty.
/// ///
/// Available since: 1.2.0
@"macos-shortcuts": MacShortcuts = .ask, @"macos-shortcuts": MacShortcuts = .ask,
/// Put every surface (tab, split, window) into a dedicated Linux cgroup. /// Put every surface (tab, split, window) into a dedicated Linux cgroup.
@ -2691,7 +2787,6 @@ keybind: Keybinds = .{},
/// * `always` - Always use cgroups. /// * `always` - Always use cgroups.
/// * `single-instance` - Enable cgroups only for Ghostty instances launched /// * `single-instance` - Enable cgroups only for Ghostty instances launched
/// as single-instance applications (see gtk-single-instance). /// as single-instance applications (see gtk-single-instance).
///
@"linux-cgroup": LinuxCgroup = if (builtin.os.tag == .linux) @"linux-cgroup": LinuxCgroup = if (builtin.os.tag == .linux)
.@"single-instance" .@"single-instance"
else else
@ -2728,6 +2823,8 @@ else
/// Enable or disable GTK's OpenGL debugging logs. The default is `true` for /// Enable or disable GTK's OpenGL debugging logs. The default is `true` for
/// debug builds, `false` for all others. /// debug builds, `false` for all others.
///
/// Available since: 1.1.0
@"gtk-opengl-debug": bool = builtin.mode == .Debug, @"gtk-opengl-debug": bool = builtin.mode == .Debug,
/// If `true`, the Ghostty GTK application will run in single-instance mode: /// If `true`, the Ghostty GTK application will run in single-instance mode:
@ -2765,6 +2862,8 @@ else
/// If this is `true`, the titlebar will be hidden when the window is maximized, /// If this is `true`, the titlebar will be hidden when the window is maximized,
/// and shown when the titlebar is unmaximized. GTK only. /// and shown when the titlebar is unmaximized. GTK only.
///
/// Available since: 1.1.0
@"gtk-titlebar-hide-when-maximized": bool = false, @"gtk-titlebar-hide-when-maximized": bool = false,
/// Determines the appearance of the top and bottom bars tab bar. /// Determines the appearance of the top and bottom bars tab bar.
@ -2802,6 +2901,8 @@ else
/// not exist. If you want to include a file that begins with a literal ? /// not exist. If you want to include a file that begins with a literal ?
/// character, surround the file path in double quotes ("). /// character, surround the file path in double quotes (").
/// The file size limit for a single stylesheet is 5MiB. /// The file size limit for a single stylesheet is 5MiB.
///
/// Available since: 1.1.0
@"gtk-custom-css": RepeatablePath = .{}, @"gtk-custom-css": RepeatablePath = .{},
/// If `true` (default), applications running in the terminal can show desktop /// If `true` (default), applications running in the terminal can show desktop
@ -2813,8 +2914,8 @@ else
/// This can be set to a specific color, using the same format as /// This can be set to a specific color, using the same format as
/// `background` or `foreground` (e.g. `#RRGGBB` but other formats /// `background` or `foreground` (e.g. `#RRGGBB` but other formats
/// are also supported; see the aforementioned documentation). If a /// are also supported; see the aforementioned documentation). If a
/// specific color is set, this color will always be used for all /// specific color is set, this color will always be used for the default
/// bold text regardless of the terminal's color scheme. /// bold text color. It will set the rest of the bold colors to `bright`.
/// ///
/// This can also be set to `bright`, which uses the bright color palette /// This can also be set to `bright`, which uses the bright color palette
/// for bold text. For example, if the text is red, then the bold will /// for bold text. For example, if the text is red, then the bold will
@ -2854,6 +2955,8 @@ term: []const u8 = "xterm-ghostty",
/// this isn't intended to be modified by users, the documentation is /// this isn't intended to be modified by users, the documentation is
/// lighter than the other configurations and users are expected to /// lighter than the other configurations and users are expected to
/// refer to the code for details. /// refer to the code for details.
///
/// Available since: 1.2.0
@"launched-from": ?LaunchSource = null, @"launched-from": ?LaunchSource = null,
/// Configures the low-level API to use for async IO, eventing, etc. /// Configures the low-level API to use for async IO, eventing, etc.
@ -2882,6 +2985,8 @@ term: []const u8 = "xterm-ghostty",
/// ///
/// This is only supported on Linux, since this is the only platform /// This is only supported on Linux, since this is the only platform
/// where we have multiple options. On macOS, we always use `kqueue`. /// where we have multiple options. On macOS, we always use `kqueue`.
///
/// Available since: 1.2.0
@"async-backend": AsyncBackend = .auto, @"async-backend": AsyncBackend = .auto,
/// Control the auto-update functionality of Ghostty. This is only supported /// Control the auto-update functionality of Ghostty. This is only supported
@ -6552,6 +6657,8 @@ pub const ShellIntegrationFeatures = packed struct {
cursor: bool = true, cursor: bool = true,
sudo: bool = false, sudo: bool = false,
title: bool = true, title: bool = true,
@"ssh-env": bool = false,
@"ssh-terminfo": bool = false,
}; };
pub const RepeatableCommand = struct { pub const RepeatableCommand = struct {

View File

@ -5,18 +5,19 @@ const Allocator = std.mem.Allocator;
const ArenaAllocator = std.heap.ArenaAllocator; const ArenaAllocator = std.heap.ArenaAllocator;
const internal_os = @import("../os/main.zig"); const internal_os = @import("../os/main.zig");
/// Open the configuration in the OS default editor according to the default /// The path to the configuration that should be opened for editing.
/// paths the main config file could be in.
/// ///
/// On Linux, this will open the file at the XDG config path. This is the /// On Linux, this will use the file at the XDG config path. This is the
/// only valid path for Linux so we don't need to check for other paths. /// only valid path for Linux so we don't need to check for other paths.
/// ///
/// On macOS, both XDG and AppSupport paths are valid. Because Ghostty /// On macOS, both XDG and AppSupport paths are valid. Because Ghostty
/// prioritizes AppSupport over XDG, we will open AppSupport if it exists, /// prioritizes AppSupport over XDG, we will use AppSupport if it exists,
/// followed by XDG if it exists, and finally AppSupport if neither exist. /// followed by XDG if it exists, and finally AppSupport if neither exist.
/// For the existence check, we also prefer non-empty files over empty /// For the existence check, we also prefer non-empty files over empty
/// files. /// files.
pub fn open(alloc_gpa: Allocator) !void { ///
/// The returned value is allocated using the provided allocator.
pub fn openPath(alloc_gpa: Allocator) ![:0]const u8 {
// Use an arena to make memory management easier in here. // Use an arena to make memory management easier in here.
var arena = ArenaAllocator.init(alloc_gpa); var arena = ArenaAllocator.init(alloc_gpa);
defer arena.deinit(); defer arena.deinit();
@ -41,7 +42,7 @@ pub fn open(alloc_gpa: Allocator) !void {
} }
}; };
try internal_os.open(alloc_gpa, .text, config_path); return try alloc_gpa.dupeZ(u8, config_path);
} }
/// Returns the config path to use for open for the current OS. /// Returns the config path to use for open for the current OS.

View File

@ -69,9 +69,13 @@ pub fn deinit(self: *Collection, alloc: Allocator) void {
if (self.load_options) |*v| v.deinit(alloc); if (self.load_options) |*v| v.deinit(alloc);
} }
pub const AddError = Allocator.Error || error{ pub const AddError =
Allocator.Error ||
AdjustSizeError ||
error{
CollectionFull, CollectionFull,
DeferredLoadingUnavailable, DeferredLoadingUnavailable,
SetSizeFailed,
}; };
/// Add a face to the collection for the given style. This face will be added /// Add a face to the collection for the given style. This face will be added
@ -81,10 +85,9 @@ pub const AddError = Allocator.Error || error{
/// If no error is encountered then the collection takes ownership of the face, /// If no error is encountered then the collection takes ownership of the face,
/// in which case face will be deallocated when the collection is deallocated. /// in which case face will be deallocated when the collection is deallocated.
/// ///
/// If a loaded face is added to the collection, it should be the same /// If a loaded face is added to the collection, its size will be changed to
/// size as all the other faces in the collection. This function will not /// match the size specified in load_options, adjusted for harmonization with
/// verify or modify the size until the size of the entire collection is /// the primary face.
/// changed.
pub fn add( pub fn add(
self: *Collection, self: *Collection,
alloc: Allocator, alloc: Allocator,
@ -103,9 +106,107 @@ pub fn add(
return error.DeferredLoadingUnavailable; return error.DeferredLoadingUnavailable;
try list.append(alloc, face); try list.append(alloc, face);
var owned: *Entry = list.at(idx);
// If the face is already loaded, apply font size adjustment
// now, otherwise we'll apply it whenever we do load it.
if (owned.getLoaded()) |loaded| {
if (try self.adjustedSize(loaded)) |opts| {
loaded.setSize(opts.faceOptions()) catch return error.SetSizeFailed;
}
}
return .{ .style = style, .idx = @intCast(idx) }; return .{ .style = style, .idx = @intCast(idx) };
} }
pub const AdjustSizeError = font.Face.GetMetricsError;
// Calculate a size for the provided face that will match it with the primary
// font, metrically, to improve consistency with fallback fonts. Right now we
// match the font based on the ex height, or the ideograph width if the font
// has ideographs in it.
//
// This returns null if load options is null or if self.load_options is null.
//
// This is very much like the `font-size-adjust` CSS property in how it works.
// ref: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size-adjust
//
// TODO: In the future, provide config options that allow the user to select
// which metric should be matched for fallback fonts, instead of hard
// coding it as ex height.
pub fn adjustedSize(
self: *Collection,
face: *Face,
) AdjustSizeError!?LoadOptions {
const load_options = self.load_options orelse return null;
// We silently do nothing if we can't get the primary
// face, because this might be the primary face itself.
const primary_face = self.getFace(.{ .idx = 0 }) catch return null;
// We do nothing if the primary face and this face are the same.
if (@intFromPtr(primary_face) == @intFromPtr(face)) return null;
const primary_metrics = try primary_face.getMetrics();
const face_metrics = try face.getMetrics();
// We use the ex height to match our font sizes, so that the height of
// lower-case letters matches between all fonts in the fallback chain.
//
// We estimate ex height as 0.75 * cap height if it's not specifically
// provided, and we estimate cap height as 0.75 * ascent in the same case.
//
// If the fallback font has an ic_width we prefer that, for normalization
// of CJK font sizes when mixed with latin fonts.
//
// We estimate the ic_width as twice the cell width if it isn't provided.
var primary_cap = primary_metrics.cap_height orelse 0.0;
if (primary_cap <= 0) primary_cap = primary_metrics.ascent * 0.75;
var primary_ex = primary_metrics.ex_height orelse 0.0;
if (primary_ex <= 0) primary_ex = primary_cap * 0.75;
var primary_ic = primary_metrics.ic_width orelse 0.0;
if (primary_ic <= 0) primary_ic = primary_metrics.cell_width * 2;
var face_cap = face_metrics.cap_height orelse 0.0;
if (face_cap <= 0) face_cap = face_metrics.ascent * 0.75;
var face_ex = face_metrics.ex_height orelse 0.0;
if (face_ex <= 0) face_ex = face_cap * 0.75;
var face_ic = face_metrics.ic_width orelse 0.0;
if (face_ic <= 0) face_ic = face_metrics.cell_width * 2;
// If the line height of the scaled font would be larger than
// the line height of the primary font, we don't want that, so
// we take the minimum between matching the ic/ex and the line
// height.
//
// NOTE: We actually allow the line height to be up to 1.2
// times the primary line height because empirically
// this is usually fine and is better for CJK.
//
// TODO: We should probably provide a config option that lets
// the user pick what metric to use for size adjustment.
const scale = @min(
1.2 * primary_metrics.lineHeight() / face_metrics.lineHeight(),
if (face_metrics.ic_width != null)
primary_ic / face_ic
else
primary_ex / face_ex,
);
// Make a copy of our load options, set the size to the size of
// the provided face, and then multiply that by our scaling factor.
var opts = load_options;
opts.size = face.size;
opts.size.points *= @as(f32, @floatCast(scale));
return opts;
}
/// Return the Face represented by a given Index. The returned pointer /// Return the Face represented by a given Index. The returned pointer
/// is only valid as long as this collection is not modified. /// is only valid as long as this collection is not modified.
/// ///
@ -129,21 +230,38 @@ pub fn getFace(self: *Collection, index: Index) !*Face {
break :item item; break :item item;
}; };
return try self.getFaceFromEntry(item); const face = try self.getFaceFromEntry(
item,
// We only want to adjust the size if this isn't the primary face.
index.style != .regular or index.idx > 0,
);
return face;
} }
/// Get the face from an entry. /// Get the face from an entry.
/// ///
/// This entry must not be an alias. /// This entry must not be an alias.
fn getFaceFromEntry(self: *Collection, entry: *Entry) !*Face { fn getFaceFromEntry(
self: *Collection,
entry: *Entry,
/// Whether to adjust the font size to match the primary face after loading.
adjust: bool,
) !*Face {
assert(entry.* != .alias); assert(entry.* != .alias);
return switch (entry.*) { return switch (entry.*) {
inline .deferred, .fallback_deferred => |*d, tag| deferred: { inline .deferred, .fallback_deferred => |*d, tag| deferred: {
const opts = self.load_options orelse const opts = self.load_options orelse
return error.DeferredLoadingUnavailable; return error.DeferredLoadingUnavailable;
const face = try d.load(opts.library, opts.faceOptions()); var face = try d.load(opts.library, opts.faceOptions());
d.deinit(); d.deinit();
// If we need to adjust the size, do so.
if (adjust) if (try self.adjustedSize(&face)) |new_opts| {
try face.setSize(new_opts.faceOptions());
};
entry.* = switch (tag) { entry.* = switch (tag) {
.deferred => .{ .loaded = face }, .deferred => .{ .loaded = face },
.fallback_deferred => .{ .fallback_loaded = face }, .fallback_deferred => .{ .fallback_loaded = face },
@ -247,7 +365,7 @@ pub fn completeStyles(
while (it.next()) |entry| { while (it.next()) |entry| {
// Load our face. If we fail to load it, we just skip it and // Load our face. If we fail to load it, we just skip it and
// continue on to try the next one. // continue on to try the next one.
const face = self.getFaceFromEntry(entry) catch |err| { const face = self.getFaceFromEntry(entry, false) catch |err| {
log.warn("error loading regular entry={d} err={}", .{ log.warn("error loading regular entry={d} err={}", .{
it.index - 1, it.index - 1,
err, err,
@ -371,7 +489,7 @@ fn syntheticBold(self: *Collection, entry: *Entry) !Face {
const opts = self.load_options orelse return error.DeferredLoadingUnavailable; const opts = self.load_options orelse return error.DeferredLoadingUnavailable;
// Try to bold it. // Try to bold it.
const regular = try self.getFaceFromEntry(entry); const regular = try self.getFaceFromEntry(entry, false);
const face = try regular.syntheticBold(opts.faceOptions()); const face = try regular.syntheticBold(opts.faceOptions());
var buf: [256]u8 = undefined; var buf: [256]u8 = undefined;
@ -391,7 +509,7 @@ fn syntheticItalic(self: *Collection, entry: *Entry) !Face {
const opts = self.load_options orelse return error.DeferredLoadingUnavailable; const opts = self.load_options orelse return error.DeferredLoadingUnavailable;
// Try to italicize it. // Try to italicize it.
const regular = try self.getFaceFromEntry(entry); const regular = try self.getFaceFromEntry(entry, false);
const face = try regular.syntheticItalic(opts.faceOptions()); const face = try regular.syntheticItalic(opts.faceOptions());
var buf: [256]u8 = undefined; var buf: [256]u8 = undefined;
@ -420,9 +538,12 @@ pub fn setSize(self: *Collection, size: DesiredSize) !void {
while (it.next()) |array| { while (it.next()) |array| {
var entry_it = array.value.iterator(0); var entry_it = array.value.iterator(0);
while (entry_it.next()) |entry| switch (entry.*) { while (entry_it.next()) |entry| switch (entry.*) {
.loaded, .fallback_loaded => |*f| try f.setSize( .loaded,
opts.faceOptions(), .fallback_loaded,
), => |*f| {
const new_opts = try self.adjustedSize(f) orelse opts.*;
try f.setSize(new_opts.faceOptions());
},
// Deferred aren't loaded so we don't need to set their size. // Deferred aren't loaded so we don't need to set their size.
// The size for when they're loaded is set since `opts` changed. // The size for when they're loaded is set since `opts` changed.
@ -549,6 +670,16 @@ pub const Entry = union(enum) {
} }
} }
/// If this face is loaded, or is an alias to a loaded face,
/// then this returns the `Face`, otherwise returns null.
pub fn getLoaded(self: *Entry) ?*Face {
return switch (self.*) {
.deferred, .fallback_deferred => null,
.loaded, .fallback_loaded => |*face| face,
.alias => |v| v.getLoaded(),
};
}
/// True if the entry is deferred. /// True if the entry is deferred.
fn isDeferred(self: Entry) bool { fn isDeferred(self: Entry) bool {
return switch (self) { return switch (self) {
@ -906,12 +1037,13 @@ test "metrics" {
var c = init(); var c = init();
defer c.deinit(alloc); defer c.deinit(alloc);
c.load_options = .{ .library = lib }; const size: DesiredSize = .{ .points = 12, .xdpi = 96, .ydpi = 96 };
c.load_options = .{ .library = lib, .size = size };
_ = try c.add(alloc, .regular, .{ .loaded = try .init( _ = try c.add(alloc, .regular, .{ .loaded = try .init(
lib, lib,
testFont, testFont,
.{ .size = .{ .points = 12, .xdpi = 96, .ydpi = 96 } }, .{ .size = size },
) }); ) });
try c.updateMetrics(); try c.updateMetrics();
@ -940,6 +1072,7 @@ test "metrics" {
.overline_thickness = 1, .overline_thickness = 1,
.box_thickness = 1, .box_thickness = 1,
.cursor_height = 17, .cursor_height = 17,
.icon_height = 11,
}, c.metrics); }, c.metrics);
// Resize should change metrics // Resize should change metrics
@ -956,5 +1089,65 @@ test "metrics" {
.overline_thickness = 2, .overline_thickness = 2,
.box_thickness = 2, .box_thickness = 2,
.cursor_height = 34, .cursor_height = 34,
.icon_height = 23,
}, c.metrics); }, c.metrics);
} }
// TODO: Also test CJK fallback sizing, we don't currently have a CJK test font.
test "adjusted sizes" {
const testing = std.testing;
const alloc = testing.allocator;
const testFont = font.embedded.inconsolata;
const fallback = font.embedded.monaspace_neon;
var lib = try Library.init(alloc);
defer lib.deinit();
var c = init();
defer c.deinit(alloc);
const size: DesiredSize = .{ .points = 12, .xdpi = 96, .ydpi = 96 };
c.load_options = .{ .library = lib, .size = size };
// Add our primary face.
_ = try c.add(alloc, .regular, .{ .loaded = try .init(
lib,
testFont,
.{ .size = size },
) });
try c.updateMetrics();
// Add the fallback face.
const fallback_idx = try c.add(alloc, .regular, .{ .loaded = try .init(
lib,
fallback,
.{ .size = size },
) });
// The ex heights should match.
{
const primary_metrics = try (try c.getFace(.{ .idx = 0 })).getMetrics();
const fallback_metrics = try (try c.getFace(fallback_idx)).getMetrics();
try std.testing.expectApproxEqAbs(
primary_metrics.ex_height.?,
fallback_metrics.ex_height.?,
// We accept anything within half a pixel.
0.5,
);
}
// Resize should keep that relationship.
try c.setSize(.{ .points = 37, .xdpi = 96, .ydpi = 96 });
{
const primary_metrics = try (try c.getFace(.{ .idx = 0 })).getMetrics();
const fallback_metrics = try (try c.getFace(fallback_idx)).getMetrics();
try std.testing.expectApproxEqAbs(
primary_metrics.ex_height.?,
fallback_metrics.ex_height.?,
// We accept anything within half a pixel.
0.5,
);
}
}

View File

@ -17,9 +17,3 @@ offset_y: i32,
/// be normalized to be between 0 and 1 prior to use in shaders. /// be normalized to be between 0 and 1 prior to use in shaders.
atlas_x: u32, atlas_x: u32,
atlas_y: u32, atlas_y: u32,
/// horizontal position to increase drawing position for strings
advance_x: f32,
/// Whether we drew this glyph ourselves with the sprite font.
sprite: bool = false,

View File

@ -35,9 +35,8 @@ cursor_thickness: u32 = 1,
/// The height in pixels of the cursor sprite. /// The height in pixels of the cursor sprite.
cursor_height: u32, cursor_height: u32,
/// Original cell width in pixels. This is used to keep /// The constraint height for nerd fonts icons.
/// glyphs centered if the cell width is adjusted wider. icon_height: u32,
original_cell_width: ?u32 = null,
/// Minimum acceptable values for some fields to prevent modifiers /// Minimum acceptable values for some fields to prevent modifiers
/// from being able to, for example, cause 0-thickness underlines. /// from being able to, for example, cause 0-thickness underlines.
@ -50,6 +49,7 @@ const Minimums = struct {
const box_thickness = 1; const box_thickness = 1;
const cursor_thickness = 1; const cursor_thickness = 1;
const cursor_height = 1; const cursor_height = 1;
const icon_height = 1;
}; };
/// Metrics extracted from a font face, based on /// Metrics extracted from a font face, based on
@ -107,6 +107,19 @@ pub const FaceMetrics = struct {
/// a provided ex height metric or measured from the height of the /// a provided ex height metric or measured from the height of the
/// lowercase x glyph. /// lowercase x glyph.
ex_height: ?f64 = null, ex_height: ?f64 = null,
/// The width of the character "" (CJK water ideograph, U+6C34),
/// if present. This is used for font size adjustment, to normalize
/// the width of CJK fonts mixed with latin fonts.
///
/// NOTE: IC = Ideograph Character
ic_width: ?f64 = null,
/// Convenience function for getting the line height
/// (ascent - descent + line_gap).
pub inline fn lineHeight(self: FaceMetrics) f64 {
return self.ascent - self.descent + self.line_gap;
}
}; };
/// Calculate our metrics based on values extracted from a font. /// Calculate our metrics based on values extracted from a font.
@ -120,7 +133,7 @@ pub fn calc(face: FaceMetrics) Metrics {
// that the cell is large enough for the provided size, since we cast // that the cell is large enough for the provided size, since we cast
// it to an integer later. // it to an integer later.
const cell_width = @ceil(face.cell_width); const cell_width = @ceil(face.cell_width);
const cell_height = @ceil(face.ascent - face.descent + face.line_gap); const cell_height = @ceil(face.lineHeight());
// We split our line gap in two parts, and put half of it on the top // We split our line gap in two parts, and put half of it on the top
// of the cell and the other half on the bottom, so that our text never // of the cell and the other half on the bottom, so that our text never
@ -164,6 +177,17 @@ pub fn calc(face: FaceMetrics) Metrics {
(face.strikethrough_position orelse (face.strikethrough_position orelse
ex_height * 0.5 + strikethrough_thickness * 0.5)); ex_height * 0.5 + strikethrough_thickness * 0.5));
// The calculation for icon height in the nerd fonts patcher
// is two thirds cap height to one third line height, but we
// use an opinionated default of 1.2 * cap height instead.
//
// Doing this prevents fonts with very large line heights
// from having excessively oversized icons, and allows fonts
// with very small line heights to still have roomy icons.
//
// We do cap it at `cell_height` though for obvious reasons.
const icon_height = @min(cell_height, cap_height * 1.2);
var result: Metrics = .{ var result: Metrics = .{
.cell_width = @intFromFloat(cell_width), .cell_width = @intFromFloat(cell_width),
.cell_height = @intFromFloat(cell_height), .cell_height = @intFromFloat(cell_height),
@ -176,6 +200,7 @@ pub fn calc(face: FaceMetrics) Metrics {
.overline_thickness = @intFromFloat(underline_thickness), .overline_thickness = @intFromFloat(underline_thickness),
.box_thickness = @intFromFloat(underline_thickness), .box_thickness = @intFromFloat(underline_thickness),
.cursor_height = @intFromFloat(cell_height), .cursor_height = @intFromFloat(cell_height),
.icon_height = @intFromFloat(icon_height),
}; };
// Ensure all metrics are within their allowable range. // Ensure all metrics are within their allowable range.
@ -201,11 +226,6 @@ pub fn apply(self: *Metrics, mods: ModifierSet) void {
const new = @max(entry.value_ptr.apply(original), 1); const new = @max(entry.value_ptr.apply(original), 1);
if (new == original) continue; if (new == original) continue;
// Preserve the original cell width if not set.
if (self.original_cell_width == null) {
self.original_cell_width = self.cell_width;
}
// Set the new value // Set the new value
@field(self, @tagName(tag)) = new; @field(self, @tagName(tag)) = new;
@ -419,6 +439,7 @@ fn init() Metrics {
.overline_thickness = 0, .overline_thickness = 0,
.box_thickness = 0, .box_thickness = 0,
.cursor_height = 0, .cursor_height = 0,
.icon_height = 0,
}; };
} }

View File

@ -449,6 +449,7 @@ pub const DerivedConfig = struct {
@"adjust-cursor-thickness": ?Metrics.Modifier, @"adjust-cursor-thickness": ?Metrics.Modifier,
@"adjust-cursor-height": ?Metrics.Modifier, @"adjust-cursor-height": ?Metrics.Modifier,
@"adjust-box-thickness": ?Metrics.Modifier, @"adjust-box-thickness": ?Metrics.Modifier,
@"adjust-icon-height": ?Metrics.Modifier,
@"freetype-load-flags": font.face.FreetypeLoadFlags, @"freetype-load-flags": font.face.FreetypeLoadFlags,
/// Initialize a DerivedConfig. The config should be either a /// Initialize a DerivedConfig. The config should be either a
@ -488,6 +489,7 @@ pub const DerivedConfig = struct {
.@"adjust-cursor-thickness" = config.@"adjust-cursor-thickness", .@"adjust-cursor-thickness" = config.@"adjust-cursor-thickness",
.@"adjust-cursor-height" = config.@"adjust-cursor-height", .@"adjust-cursor-height" = config.@"adjust-cursor-height",
.@"adjust-box-thickness" = config.@"adjust-box-thickness", .@"adjust-box-thickness" = config.@"adjust-box-thickness",
.@"adjust-icon-height" = config.@"adjust-icon-height",
.@"freetype-load-flags" = if (font.face.FreetypeLoadFlags != void) config.@"freetype-load-flags" else {}, .@"freetype-load-flags" = if (font.face.FreetypeLoadFlags != void) config.@"freetype-load-flags" else {},
// This must be last so the arena contains all our allocations // This must be last so the arena contains all our allocations
@ -634,6 +636,7 @@ pub const Key = struct {
if (config.@"adjust-cursor-thickness") |m| try set.put(alloc, .cursor_thickness, m); if (config.@"adjust-cursor-thickness") |m| try set.put(alloc, .cursor_thickness, m);
if (config.@"adjust-cursor-height") |m| try set.put(alloc, .cursor_height, m); if (config.@"adjust-cursor-height") |m| try set.put(alloc, .cursor_height, m);
if (config.@"adjust-box-thickness") |m| try set.put(alloc, .box_thickness, m); if (config.@"adjust-box-thickness") |m| try set.put(alloc, .box_thickness, m);
if (config.@"adjust-icon-height") |m| try set.put(alloc, .icon_height, m);
break :set set; break :set set;
}; };

View File

@ -144,12 +144,32 @@ pub const RenderOptions = struct {
/// Bottom padding when resizing. /// Bottom padding when resizing.
pad_bottom: f64 = 0.0, pad_bottom: f64 = 0.0,
// This acts as a multiple of the provided width when applying
// constraints, so if this is 1.6 for example, then a width of
// 10 would be treated as though it were 16.
group_width: f64 = 1.0,
// This acts as a multiple of the provided height when applying
// constraints, so if this is 1.6 for example, then a height of
// 10 would be treated as though it were 16.
group_height: f64 = 1.0,
// This is an x offset for the actual width within the group width.
// If this is 0.5 then the glyph will be offset so that its left
// edge sits at the halfway point of the group width.
group_x: f64 = 0.0,
// This is a y offset for the actual height within the group height.
// If this is 0.5 then the glyph will be offset so that its bottom
// edge sits at the halfway point of the group height.
group_y: f64 = 0.0,
/// Maximum ratio of width to height when resizing. /// Maximum ratio of width to height when resizing.
max_xy_ratio: ?f64 = null, max_xy_ratio: ?f64 = null,
/// Maximum number of cells horizontally to use. /// Maximum number of cells horizontally to use.
max_constraint_width: u2 = 2, max_constraint_width: u2 = 2,
/// What to use as the height metric when constraining the glyph.
height: Height = .cell,
pub const Size = enum { pub const Size = enum {
/// Don't change the size of this glyph. /// Don't change the size of this glyph.
none, none,
@ -176,6 +196,13 @@ pub const RenderOptions = struct {
center, center,
}; };
pub const Height = enum {
/// Use the full height of the cell for constraining this glyph.
cell,
/// Use the "icon height" from the grid metrics as the height.
icon,
};
/// The size and position of a glyph. /// The size and position of a glyph.
pub const GlyphSize = struct { pub const GlyphSize = struct {
width: f64, width: f64,
@ -189,35 +216,55 @@ pub const RenderOptions = struct {
pub fn constrain( pub fn constrain(
self: Constraint, self: Constraint,
glyph: GlyphSize, glyph: GlyphSize,
/// Width of one cell. metrics: Metrics,
cell_width: f64,
/// Height of one cell.
cell_height: f64,
/// Number of cells horizontally available for this glyph. /// Number of cells horizontally available for this glyph.
constraint_width: u2, constraint_width: u2,
) GlyphSize { ) GlyphSize {
var g = glyph; var g = glyph;
const available_width = var available_width: f64 = @floatFromInt(
cell_width * @as(f64, @floatFromInt( metrics.cell_width * @min(
@min(
self.max_constraint_width, self.max_constraint_width,
constraint_width, constraint_width,
), ),
)); );
const available_height: f64 = @floatFromInt(switch (self.height) {
.cell => metrics.cell_height,
.icon => metrics.icon_height,
});
// We make the opinionated choice here to reduce the width
// of icon-height symbols by the same amount horizontally,
// since otherwise wide aspect ratio icons like folders end
// up far too wide.
//
// But we *only* do this if the constraint width is 2, since
// otherwise it would make them way too small when sized for
// a single cell.
const is_icon_width = self.height == .icon and @min(self.max_constraint_width, constraint_width) > 1;
const orig_avail_width = available_width;
if (is_icon_width) {
const cell_height: f64 = @floatFromInt(metrics.cell_height);
const ratio = available_height / cell_height;
available_width *= ratio;
}
const w = available_width - const w = available_width -
self.pad_left * available_width - self.pad_left * available_width -
self.pad_right * available_width; self.pad_right * available_width;
const h = cell_height - const h = available_height -
self.pad_top * cell_height - self.pad_top * available_height -
self.pad_bottom * cell_height; self.pad_bottom * available_height;
// Subtract padding from the bearings so that our // Subtract padding from the bearings so that our
// alignment and sizing code works correctly. We // alignment and sizing code works correctly. We
// re-add before returning. // re-add before returning.
g.x -= self.pad_left * available_width; g.x -= self.pad_left * available_width;
g.y -= self.pad_bottom * cell_height; g.y -= self.pad_bottom * available_height;
// Multiply by group width and height for better sizing.
g.width *= self.group_width;
g.height *= self.group_height;
switch (self.size_horizontal) { switch (self.size_horizontal) {
.none => {}, .none => {},
@ -297,6 +344,14 @@ pub const RenderOptions = struct {
}, },
} }
// Add group-relative position
g.x += self.group_x * g.width;
g.y += self.group_y * g.height;
// Divide group width and height back out before we align.
g.width /= self.group_width;
g.height /= self.group_height;
if (self.max_xy_ratio) |ratio| if (g.width > g.height * ratio) { if (self.max_xy_ratio) |ratio| if (g.width > g.height * ratio) {
const orig_width = g.width; const orig_width = g.width;
g.width = g.height * ratio; g.width = g.height * ratio;
@ -317,9 +372,23 @@ pub const RenderOptions = struct {
.center => g.y = (h - g.height) / 2, .center => g.y = (h - g.height) / 2,
} }
// Add offset for icon width restriction, to keep it centered.
if (is_icon_width) {
g.x += (orig_avail_width - available_width) / 2;
}
// Re-add our padding before returning. // Re-add our padding before returning.
g.x += self.pad_left * available_width; g.x += self.pad_left * available_width;
g.y += self.pad_bottom * cell_height; g.y += self.pad_bottom * available_height;
// If the available height is less than the cell height, we
// add half of the difference to center it in the full height.
//
// If necessary, in the future, we can adjust this to account
// for alignment, but that isn't necessary with any of the nf
// icons afaict.
const cell_height: f64 = @floatFromInt(metrics.cell_height);
g.y += (cell_height - available_height) / 2;
return g; return g;
} }

View File

@ -31,6 +31,9 @@ pub const Face = struct {
/// tables). /// tables).
color: ?ColorState = null, color: ?ColorState = null,
/// The current size this font is set to.
size: font.face.DesiredSize,
/// True if our build is using Harfbuzz. If we're not, we can avoid /// True if our build is using Harfbuzz. If we're not, we can avoid
/// some Harfbuzz-specific code paths. /// some Harfbuzz-specific code paths.
const harfbuzz_shaper = font.options.backend.hasHarfbuzz(); const harfbuzz_shaper = font.options.backend.hasHarfbuzz();
@ -106,6 +109,7 @@ pub const Face = struct {
.font = ct_font, .font = ct_font,
.hb_font = hb_font, .hb_font = hb_font,
.color = color, .color = color,
.size = opts.size,
}; };
result.quirks_disable_default_font_features = quirks.disableDefaultFontFeatures(&result); result.quirks_disable_default_font_features = quirks.disableDefaultFontFeatures(&result);
@ -333,38 +337,99 @@ pub const Face = struct {
.offset_y = 0, .offset_y = 0,
.atlas_x = 0, .atlas_x = 0,
.atlas_y = 0, .atlas_y = 0,
.advance_x = 0,
}; };
const metrics = opts.grid_metrics; const metrics = opts.grid_metrics;
const cell_width: f64 = @floatFromInt(metrics.cell_width); const cell_width: f64 = @floatFromInt(metrics.cell_width);
const cell_height: f64 = @floatFromInt(metrics.cell_height); // const cell_height: f64 = @floatFromInt(metrics.cell_height);
const glyph_size = opts.constraint.constrain( // We eliminate any negative vertical padding since these overlap
// values aren't needed under CoreText with how precisely we apply
// constraints, and they can lead to extra height that looks bad
// for things like powerline glyphs.
var constraint = opts.constraint;
constraint.pad_top = @max(0.0, constraint.pad_top);
constraint.pad_bottom = @max(0.0, constraint.pad_bottom);
const glyph_size = constraint.constrain(
.{ .{
.width = rect.size.width, .width = rect.size.width,
.height = rect.size.height, .height = rect.size.height,
.x = rect.origin.x, .x = rect.origin.x,
.y = rect.origin.y + @as(f64, @floatFromInt(metrics.cell_baseline)), .y = rect.origin.y + @as(f64, @floatFromInt(metrics.cell_baseline)),
}, },
cell_width, metrics,
cell_height,
opts.constraint_width, opts.constraint_width,
); );
const width = glyph_size.width; // These calculations are an attempt to mostly imitate the effect of
const height = glyph_size.height; // `shouldSubpixelQuantizeFonts`[^1], which helps maximize legibility
const x = glyph_size.x; // at small pixel sizes (low DPI). We do this math ourselves instead
const y = glyph_size.y; // of letting CoreText do it because it's not entirely clear how the
// math in CoreText works and we've run in to edge cases where glyphs
// have their bottom or left row cut off due to bad rounding.
//
// This math seems to have a mostly comparable result to whatever it
// is that CoreText does, and is even (in my opinion) better in some
// cases.
//
// I'm not entirely certain but I suspect that when you enable the
// CoreText option it also does some sort of rudimentary hinting,
// but it doesn't seem to make that big of a difference in terms
// of legibility in the end.
//
// [^1]: https://developer.apple.com/documentation/coregraphics/cgcontext/setshouldsubpixelquantizefonts(_:)?language=objc
// We have to include the fractional pixels that we won't be offsetting // We only want to apply quantization if we don't have any
// in our width and height calculations, that is, we offset by the floor // constraints and this isn't a bitmap glyph, since CoreText
// of the bearings when we render the glyph, meaning there's still a bit // doesn't seem to apply its quantization to bitmap glyphs.
// of extra width to the area that's drawn in beyond just the width of //
// the glyph itself, so we include that extra fraction of a pixel when // TODO: Maybe gate this so it only applies at small font sizes,
// calculating the width and height here. // or else offer a user config option that can disable it.
const px_width: u32 = @intFromFloat(@ceil(width + rect.origin.x - @floor(rect.origin.x))); const should_quantize = !sbix and std.meta.eql(opts.constraint, .none);
const px_height: u32 = @intFromFloat(@ceil(height + rect.origin.y - @floor(rect.origin.y)));
// We offset our glyph by its bearings when we draw it, using `@floor`
// here rounds it *up* since we negate it right outside. Moving it by
// whole pixels ensures that we don't disturb the pixel alignment of
// the glyph, fractional pixels will still be drawn on all sides as
// necessary.
const draw_x = -@floor(rect.origin.x);
const draw_y = -@floor(rect.origin.y);
// We use `x` and `y` for our full pixel bearings post-raster.
// We need to subtract the fractional pixel of difference from
// the edge of the draw area to the edge of the actual glyph.
const frac_x = rect.origin.x + draw_x;
const frac_y = rect.origin.y + draw_y;
const x = glyph_size.x - frac_x;
const y = glyph_size.y - frac_y;
// We never modify the width.
//
// When using the CoreText option the widths do seem to be
// modified extremely subtly, but even at very small font
// sizes it's hardly a noticeable difference.
const width = glyph_size.width;
// If the top of the glyph (taking in to account the y position)
// is within half a pixel of an exact pixel edge, we round up the
// height, otherwise leave it alone.
//
// This seems to match what CoreText does.
const frac_top = (glyph_size.height + frac_y) - @floor(glyph_size.height + frac_y);
const height =
if (should_quantize)
if (frac_top >= 0.5)
glyph_size.height + 1 - frac_top
else
glyph_size.height
else
glyph_size.height;
// Add the fractional pixel to the width and height and take
// the ceiling to get a canvas size that will definitely fit
// our drawn glyph.
const px_width: u32 = @intFromFloat(@ceil(width + frac_x));
const px_height: u32 = @intFromFloat(@ceil(height + frac_y));
// Settings that are specific to if we are rendering text or emoji. // Settings that are specific to if we are rendering text or emoji.
const color: struct { const color: struct {
@ -429,12 +494,23 @@ pub const Face = struct {
}, },
}); });
// "Font smoothing" is what we call "thickening", it's an attempt
// to compensate for optical thinning of fonts, but at this point
// it's just something that makes the text look closer to system
// applications if users want that.
context.setAllowsFontSmoothing(ctx, true); context.setAllowsFontSmoothing(ctx, true);
context.setShouldSmoothFonts(ctx, opts.thicken); // The amadeus "enthicken" context.setShouldSmoothFonts(ctx, opts.thicken);
context.setAllowsFontSubpixelQuantization(ctx, true);
context.setShouldSubpixelQuantizeFonts(ctx, true); // Subpixel positioning allows glyphs to be placed at non-integer
// coordinates. We need this for our alignment.
context.setAllowsFontSubpixelPositioning(ctx, true); context.setAllowsFontSubpixelPositioning(ctx, true);
context.setShouldSubpixelPositionFonts(ctx, true); context.setShouldSubpixelPositionFonts(ctx, true);
// See comments about quantization earlier in the function.
context.setAllowsFontSubpixelQuantization(ctx, false);
context.setShouldSubpixelQuantizeFonts(ctx, false);
// Anti-aliasing is self explanatory.
context.setAllowsAntialiasing(ctx, true); context.setAllowsAntialiasing(ctx, true);
context.setShouldAntialias(ctx, true); context.setShouldAntialias(ctx, true);
@ -455,19 +531,16 @@ pub const Face = struct {
context.setLineWidth(ctx, line_width); context.setLineWidth(ctx, line_width);
} }
// Scale the drawing context so that when we draw
// our glyph it's stretched to the constrained size.
context.scaleCTM( context.scaleCTM(
ctx, ctx,
width / rect.size.width, width / rect.size.width,
height / rect.size.height, height / rect.size.height,
); );
// We want to render the glyphs at (0,0), but the glyphs themselves // Draw our glyph.
// are offset by bearings, so we have to undo those bearings in order self.font.drawGlyphs(&glyphs, &.{.{ .x = draw_x, .y = draw_y }}, ctx);
// to get them to 0,0.
self.font.drawGlyphs(&glyphs, &.{.{
.x = -@floor(rect.origin.x),
.y = -@floor(rect.origin.y),
}}, ctx);
// Write our rasterized glyph to the atlas. // Write our rasterized glyph to the atlas.
const region = try atlas.reserve(alloc, px_width, px_height); const region = try atlas.reserve(alloc, px_width, px_height);
@ -475,33 +548,47 @@ pub const Face = struct {
// This should be the distance from the bottom of // This should be the distance from the bottom of
// the cell to the top of the glyph's bounding box. // the cell to the top of the glyph's bounding box.
const offset_y: i32 = const offset_y: i32 = @as(i32, @intFromFloat(@round(y))) + @as(i32, @intCast(px_height));
@as(i32, @intFromFloat(@floor(y))) +
@as(i32, @intCast(px_height));
// This should be the distance from the left of // This should be the distance from the left of
// the cell to the left of the glyph's bounding box. // the cell to the left of the glyph's bounding box.
const offset_x: i32 = offset_x: { const offset_x: i32 = offset_x: {
var result: i32 = @intFromFloat(@round(x)); // If the glyph's advance is narrower than the cell width then we
// center the advance of the glyph within the cell width. At first
// If our cell was resized then we adjust our glyph's // I implemented this to proportionally scale the center position
// position relative to the new center. This keeps glyphs // of the glyph but that messes up glyphs that are meant to align
// centered in the cell whether it was made wider or narrower. // vertically with others, so this is a compromise.
if (metrics.original_cell_width) |original_width| { //
const before: i32 = @intCast(original_width); // This makes it so that when the `adjust-cell-width` config is
const after: i32 = @intCast(metrics.cell_width); // used, or when a fallback font with a different advance width
// Increase the offset by half of the difference // is used, we don't get weirdly aligned glyphs.
// between the widths to keep things centered. //
result += @divTrunc(after - before, 2); // We don't do this if the constraint has a horizontal alignment,
// since in that case the position was already calculated with the
// new cell width in mind.
if (opts.constraint.align_horizontal == .none) {
const advance = self.font.getAdvancesForGlyphs(.horizontal, &glyphs, null);
const new_advance =
cell_width * @as(f64, @floatFromInt(opts.cell_width orelse 1));
// If the original advance is greater than the cell width then
// it's possible that this is a ligature or other glyph that is
// intended to overflow the cell to one side or the other, and
// adjusting the bearings could mess that up, so we just leave
// it alone if that's the case.
//
// We also don't want to do anything if the advance is zero or
// less, since this is used for stuff like combining characters.
if (advance > new_advance or advance <= 0.0) {
break :offset_x @intFromFloat(@round(x));
}
break :offset_x @intFromFloat(
@round(x + (new_advance - advance) / 2),
);
} else {
break :offset_x @intFromFloat(@round(x));
} }
break :offset_x result;
}; };
// Get our advance
var advances: [glyphs.len]macos.graphics.Size = undefined;
_ = self.font.getAdvancesForGlyphs(.horizontal, &glyphs, &advances);
return .{ return .{
.width = px_width, .width = px_width,
.height = px_height, .height = px_height,
@ -509,7 +596,6 @@ pub const Face = struct {
.offset_y = offset_y, .offset_y = offset_y,
.atlas_x = region.x, .atlas_x = region.x,
.atlas_y = region.y, .atlas_y = region.y,
.advance_x = @floatCast(advances[0].width),
}; };
} }
@ -741,6 +827,20 @@ pub const Face = struct {
break :cell_width max; break :cell_width max;
}; };
// Measure "" (CJK water ideograph, U+6C34) for our ic width.
const ic_width: ?f64 = ic_width: {
const glyph = self.glyphIndex('水') orelse break :ic_width null;
var advances: [1]macos.graphics.Size = undefined;
_ = ct_font.getAdvancesForGlyphs(
.horizontal,
&.{@intCast(glyph)},
&advances,
);
break :ic_width advances[0].width;
};
return .{ return .{
.cell_width = cell_width, .cell_width = cell_width,
.ascent = ascent, .ascent = ascent,
@ -752,6 +852,7 @@ pub const Face = struct {
.strikethrough_thickness = strikethrough_thickness, .strikethrough_thickness = strikethrough_thickness,
.cap_height = cap_height, .cap_height = cap_height,
.ex_height = ex_height, .ex_height = ex_height,
.ic_width = ic_width,
}; };
} }

View File

@ -59,6 +59,9 @@ pub const Face = struct {
bold: bool = false, bold: bool = false,
} = .{}, } = .{},
/// The current size this font is set to.
size: font.face.DesiredSize,
/// Initialize a new font face with the given source in-memory. /// Initialize a new font face with the given source in-memory.
pub fn initFile( pub fn initFile(
lib: Library, lib: Library,
@ -107,6 +110,7 @@ pub const Face = struct {
.hb_font = hb_font, .hb_font = hb_font,
.ft_mutex = ft_mutex, .ft_mutex = ft_mutex,
.load_flags = opts.freetype_load_flags, .load_flags = opts.freetype_load_flags,
.size = opts.size,
}; };
result.quirks_disable_default_font_features = quirks.disableDefaultFontFeatures(&result); result.quirks_disable_default_font_features = quirks.disableDefaultFontFeatures(&result);
@ -203,6 +207,7 @@ pub const Face = struct {
/// for clearing any glyph caches, font atlas data, etc. /// for clearing any glyph caches, font atlas data, etc.
pub fn setSize(self: *Face, opts: font.face.Options) !void { pub fn setSize(self: *Face, opts: font.face.Options) !void {
try setSize_(self.face, opts.size); try setSize_(self.face, opts.size);
self.size = opts.size;
} }
fn setSize_(face: freetype.Face, size: font.face.DesiredSize) !void { fn setSize_(face: freetype.Face, size: font.face.DesiredSize) !void {
@ -373,7 +378,6 @@ pub const Face = struct {
.offset_y = 0, .offset_y = 0,
.atlas_x = 0, .atlas_x = 0,
.atlas_y = 0, .atlas_y = 0,
.advance_x = 0,
}; };
// For synthetic bold, we embolden the glyph. // For synthetic bold, we embolden the glyph.
@ -391,7 +395,7 @@ pub const Face = struct {
const metrics = opts.grid_metrics; const metrics = opts.grid_metrics;
const cell_width: f64 = @floatFromInt(metrics.cell_width); const cell_width: f64 = @floatFromInt(metrics.cell_width);
const cell_height: f64 = @floatFromInt(metrics.cell_height); // const cell_height: f64 = @floatFromInt(metrics.cell_height);
const glyph_x: f64 = f26dot6ToF64(glyph.*.metrics.horiBearingX); const glyph_x: f64 = f26dot6ToF64(glyph.*.metrics.horiBearingX);
const glyph_y: f64 = f26dot6ToF64(glyph.*.metrics.horiBearingY) - glyph_height; const glyph_y: f64 = f26dot6ToF64(glyph.*.metrics.horiBearingY) - glyph_height;
@ -403,8 +407,7 @@ pub const Face = struct {
.x = glyph_x, .x = glyph_x,
.y = glyph_y + @as(f64, @floatFromInt(metrics.cell_baseline)), .y = glyph_y + @as(f64, @floatFromInt(metrics.cell_baseline)),
}, },
cell_width, metrics,
cell_height,
opts.constraint_width, opts.constraint_width,
); );
@ -639,20 +642,40 @@ pub const Face = struct {
// This should be the distance from the left of // This should be the distance from the left of
// the cell to the left of the glyph's bounding box. // the cell to the left of the glyph's bounding box.
const offset_x: i32 = offset_x: { const offset_x: i32 = offset_x: {
var result: i32 = @intFromFloat(@floor(x)); // If the glyph's advance is narrower than the cell width then we
// center the advance of the glyph within the cell width. At first
// If our cell was resized then we adjust our glyph's // I implemented this to proportionally scale the center position
// position relative to the new center. This keeps glyphs // of the glyph but that messes up glyphs that are meant to align
// centered in the cell whether it was made wider or narrower. // vertically with others, so this is a compromise.
if (metrics.original_cell_width) |original_width| { //
const before: i32 = @intCast(original_width); // This makes it so that when the `adjust-cell-width` config is
const after: i32 = @intCast(metrics.cell_width); // used, or when a fallback font with a different advance width
// Increase the offset by half of the difference // is used, we don't get weirdly aligned glyphs.
// between the widths to keep things centered. //
result += @divTrunc(after - before, 2); // We don't do this if the constraint has a horizontal alignment,
// since in that case the position was already calculated with the
// new cell width in mind.
if (opts.constraint.align_horizontal == .none) {
const advance = f26dot6ToFloat(glyph.*.advance.x);
const new_advance =
cell_width * @as(f64, @floatFromInt(opts.cell_width orelse 1));
// If the original advance is greater than the cell width then
// it's possible that this is a ligature or other glyph that is
// intended to overflow the cell to one side or the other, and
// adjusting the bearings could mess that up, so we just leave
// it alone if that's the case.
//
// We also don't want to do anything if the advance is zero or
// less, since this is used for stuff like combining characters.
if (advance > new_advance or advance <= 0.0) {
break :offset_x @intFromFloat(@floor(x));
}
break :offset_x @intFromFloat(
@floor(x + (new_advance - advance) / 2),
);
} else {
break :offset_x @intFromFloat(@floor(x));
} }
break :offset_x result;
}; };
return Glyph{ return Glyph{
@ -662,7 +685,6 @@ pub const Face = struct {
.offset_y = offset_y, .offset_y = offset_y,
.atlas_x = region.x, .atlas_x = region.x,
.atlas_y = region.y, .atlas_y = region.y,
.advance_x = f26dot6ToFloat(glyph.*.advance.x),
}; };
} }
@ -833,7 +855,7 @@ pub const Face = struct {
while (c < 127) : (c += 1) { while (c < 127) : (c += 1) {
if (face.getCharIndex(c)) |glyph_index| { if (face.getCharIndex(c)) |glyph_index| {
if (face.loadGlyph(glyph_index, .{ if (face.loadGlyph(glyph_index, .{
.render = true, .render = false,
.no_svg = true, .no_svg = true,
})) { })) {
max = @max( max = @max(
@ -871,7 +893,7 @@ pub const Face = struct {
defer self.ft_mutex.unlock(); defer self.ft_mutex.unlock();
if (face.getCharIndex('H')) |glyph_index| { if (face.getCharIndex('H')) |glyph_index| {
if (face.loadGlyph(glyph_index, .{ if (face.loadGlyph(glyph_index, .{
.render = true, .render = false,
.no_svg = true, .no_svg = true,
})) { })) {
break :cap f26dot6ToF64(face.handle.*.glyph.*.metrics.height); break :cap f26dot6ToF64(face.handle.*.glyph.*.metrics.height);
@ -884,7 +906,7 @@ pub const Face = struct {
defer self.ft_mutex.unlock(); defer self.ft_mutex.unlock();
if (face.getCharIndex('x')) |glyph_index| { if (face.getCharIndex('x')) |glyph_index| {
if (face.loadGlyph(glyph_index, .{ if (face.loadGlyph(glyph_index, .{
.render = true, .render = false,
.no_svg = true, .no_svg = true,
})) { })) {
break :ex f26dot6ToF64(face.handle.*.glyph.*.metrics.height); break :ex f26dot6ToF64(face.handle.*.glyph.*.metrics.height);
@ -895,6 +917,21 @@ pub const Face = struct {
}; };
}; };
// Measure "" (CJK water ideograph, U+6C34) for our ic width.
const ic_width: ?f64 = ic_width: {
self.ft_mutex.lock();
defer self.ft_mutex.unlock();
const glyph = face.getCharIndex('水') orelse break :ic_width null;
face.loadGlyph(glyph, .{
.render = false,
.no_svg = true,
}) catch break :ic_width null;
break :ic_width f26dot6ToF64(face.handle.*.glyph.*.advance.x);
};
return .{ return .{
.cell_width = cell_width, .cell_width = cell_width,
@ -910,6 +947,7 @@ pub const Face = struct {
.cap_height = cap_height, .cap_height = cap_height,
.ex_height = ex_height, .ex_height = ex_height,
.ic_width = ic_width,
}; };
} }
@ -1019,6 +1057,7 @@ test "color emoji" {
.overline_thickness = 0, .overline_thickness = 0,
.box_thickness = 0, .box_thickness = 0,
.cursor_height = 0, .cursor_height = 0,
.icon_height = 0,
}, .constraint_width = 2, .constraint = .{ }, .constraint_width = 2, .constraint = .{
.size_horizontal = .cover, .size_horizontal = .cover,
.size_vertical = .cover, .size_vertical = .cover,

View File

@ -235,7 +235,6 @@ pub const Face = struct {
.offset_y = 0, .offset_y = 0,
.atlas_x = region.x, .atlas_x = region.x,
.atlas_y = region.y, .atlas_y = region.y,
.advance_x = 0,
}; };
} }

View File

@ -25,6 +25,7 @@ pub fn getConstraint(cp: u21) Constraint {
=> .{ => .{
.size_horizontal = .cover, .size_horizontal = .cover,
.size_vertical = .fit, .size_vertical = .fit,
.height = .icon,
.max_constraint_width = 1, .max_constraint_width = 1,
.align_horizontal = .center, .align_horizontal = .center,
.align_vertical = .center, .align_vertical = .center,
@ -33,7 +34,35 @@ pub fn getConstraint(cp: u21) Constraint {
.pad_top = 0.1, .pad_top = 0.1,
.pad_bottom = 0.1, .pad_bottom = 0.1,
}, },
0x276c...0x2771, 0x276c...0x276d,
=> .{
.size_horizontal = .cover,
.size_vertical = .fit,
.max_constraint_width = 1,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.4028056112224450,
.group_height = 1.1222570532915361,
.group_x = 0.1428571428571428,
.group_y = 0.0349162011173184,
.pad_top = 0.15,
.pad_bottom = 0.15,
},
0x276e...0x276f,
=> .{
.size_horizontal = .cover,
.size_vertical = .fit,
.max_constraint_width = 1,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0115606936416186,
.group_height = 1.1222570532915361,
.group_x = 0.0057142857142857,
.group_y = 0.0125698324022346,
.pad_top = 0.15,
.pad_bottom = 0.15,
},
0x2770...0x2771,
=> .{ => .{
.size_horizontal = .cover, .size_horizontal = .cover,
.size_vertical = .fit, .size_vertical = .fit,
@ -285,7 +314,7 @@ pub fn getConstraint(cp: u21) Constraint {
0xe0d0...0xe0d1, 0xe0d0...0xe0d1,
=> .{ => .{
.size_horizontal = .cover, .size_horizontal = .cover,
.size_vertical = .cover, .size_vertical = .fit,
.align_horizontal = .start, .align_horizontal = .start,
.align_vertical = .center, .align_vertical = .center,
}, },
@ -294,7 +323,7 @@ pub fn getConstraint(cp: u21) Constraint {
0xe0d5, 0xe0d5,
=> .{ => .{
.size_horizontal = .cover, .size_horizontal = .cover,
.size_vertical = .cover, .size_vertical = .fit,
.align_horizontal = .center, .align_horizontal = .center,
.align_vertical = .center, .align_vertical = .center,
}, },
@ -356,15 +385,689 @@ pub fn getConstraint(cp: u21) Constraint {
0x2b58, 0x2b58,
0xe000...0xe0a9, 0xe000...0xe0a9,
0xe4fa...0xe7ef, 0xe4fa...0xe7ef,
0xea60...0xec1e, 0xea60,
0xed00...0xf847, 0xea62...0xea7c,
0xea7e...0xea98,
0xeaa3...0xeab3,
0xeab8...0xead3,
0xead7...0xeb42,
0xeb44...0xeb6d,
0xeb72...0xeb89,
0xeb8b...0xeb99,
0xeb9b...0xebd4,
0xebd6,
0xebd8...0xec06,
0xec08...0xec0a,
0xec0d...0xec1e,
0xed00...0xf018,
0xf01a...0xf02f,
0xf031...0xf03c,
0xf041...0xf043,
0xf045...0xf049,
0xf04b...0xf050,
0xf054...0xf059,
0xf05c...0xf070,
0xf072...0xf077,
0xf079...0xf07a,
0xf07c...0xf080,
0xf082...0xf08b,
0xf08d...0xf091,
0xf093...0xf09b,
0xf09d...0xf09e,
0xf0a0,
0xf0a5...0xf0a9,
0xf0ab...0xf0c9,
0xf0cb...0xf0d5,
0xf0d7...0xf0dd,
0xf0df...0xf0e6,
0xf0e8...0xf295,
0xf297...0xf2c1,
0xf2c6...0xf2ef,
0xf2f1...0xf305,
0xf307...0xf847,
0xf0001...0xf1af0, 0xf0001...0xf1af0,
=> .{ => .{
.size_horizontal = .fit, .size_horizontal = .fit,
.size_vertical = .fit, .size_vertical = .fit,
.height = .icon,
.align_horizontal = .center, .align_horizontal = .center,
.align_vertical = .center, .align_vertical = .center,
}, },
0xea61,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.3315669947009841,
.group_height = 1.0763840224246670,
.group_x = 0.0847072200113701,
.group_y = 0.0709635416666667,
},
0xea7d,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.1913145539906103,
.group_height = 1.1428571428571428,
.group_x = 0.0916256157635468,
.group_y = 0.0415039062500000,
},
0xea99,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0639412997903563,
.group_height = 2.0940695296523519,
.group_x = 0.0295566502463054,
.group_y = 0.2270507812500000,
},
0xea9a,
0xeaa1,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.3029525032092426,
.group_height = 1.1729667812142039,
.group_x = 0.1527093596059113,
.group_y = 0.0751953125000000,
},
0xea9b,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.1639908256880733,
.group_height = 1.3128205128205128,
.group_x = 0.0719211822660099,
.group_y = 0.0869140625000000,
},
0xea9c,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.1639908256880733,
.group_height = 1.3195876288659794,
.group_x = 0.0719211822660099,
.group_y = 0.0830078125000000,
},
0xea9d,
0xeaa0,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 2.4457831325301207,
.group_height = 1.9692307692307693,
.group_x = 0.2857142857142857,
.group_y = 0.2763671875000000,
},
0xea9e...0xea9f,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.9556840077071291,
.group_height = 2.4674698795180725,
.group_x = 0.2137931034482759,
.group_y = 0.3066406250000000,
},
0xeaa2,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.2412121212121212,
.group_height = 1.0591799039527152,
.group_x = 0.0683593750000000,
.group_y = 0.0146484375000000,
},
0xeab4,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0049115913555993,
.group_height = 1.8998144712430427,
.group_y = 0.2026367187500000,
},
0xeab5,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.8979591836734695,
.group_height = 1.0054000981836033,
.group_x = 0.2023460410557185,
.group_y = 0.0053710937500000,
},
0xeab6,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.8979591836734695,
.group_height = 1.0054000981836033,
.group_x = 0.2707722385141740,
},
0xeab7,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0049115913555993,
.group_height = 1.8980537534754403,
.group_x = 0.0048875855327468,
.group_y = 0.2709960937500000,
},
0xead4...0xead5,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.4152542372881356,
.group_x = 0.1486118671747414,
},
0xead6,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_height = 1.1390433815350389,
.group_y = 0.0688476562500000,
},
0xeb43,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.3635153129161119,
.group_height = 1.0002360944082516,
.group_x = 0.1992187500000000,
.group_y = 0.0002360386808388,
},
0xeb6e,
0xeb71,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_height = 2.0197238658777121,
.group_y = 0.2524414062500000,
},
0xeb6f,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 2.0098619329388558,
.group_x = 0.2492639842983317,
},
0xeb70,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 2.0098619329388558,
.group_height = 1.0039215686274510,
.group_x = 0.2492639842983317,
.group_y = 0.0039062500000000,
},
0xeb8a,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 2.8826979472140764,
.group_height = 2.9804097167804766,
.group_x = 0.2634791454730417,
.group_y = 0.3314678485576923,
},
0xeb9a,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.1441340782122904,
.group_height = 1.0591799039527152,
.group_x = 0.0683593750000000,
.group_y = 0.0146484375000000,
},
0xebd5,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0723270440251573,
.group_height = 1.0728129910948141,
.group_y = 0.0678710937500000,
},
0xebd7,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_height = 1.0000418544302916,
.group_y = 0.0000418526785714,
},
0xec07,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 2.8615369874243446,
.group_height = 2.9789458113505249,
.group_x = 0.2609446802539727,
.group_y = 0.3313029661016949,
},
0xec0b,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0722513089005237,
.group_height = 1.0002360944082516,
.group_y = 0.0002360386808388,
},
0xec0c,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.2487804878048780,
.group_x = 0.1992187500000000,
},
0xf019,
0xf08c,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0004882812500000,
},
0xf030,
0xf03e,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0004882812500000,
.group_height = 1.1428571428571428,
.group_y = 0.0625000000000000,
},
0xf03d,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0004882812500000,
.group_height = 1.5014662756598240,
.group_y = 0.1669921875000000,
},
0xf03f,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.6018762826150690,
.group_x = 0.1876220107369448,
},
0xf040,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0006976906439684,
.group_height = 1.0001808776182035,
.group_x = 0.0006972042111134,
.group_y = 0.0001808449074074,
},
0xf044,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.1029147024980515,
.group_height = 1.1024142703367676,
.group_x = 0.0463592039005675,
.group_y = 0.0430325010461710,
},
0xf04a,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0004882812500000,
.group_height = 1.3312975252838291,
.group_y = 0.1245571402616279,
},
0xf051,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.6007812500000000,
.group_height = 1.3312170271945341,
.group_x = 0.1874084919472914,
.group_y = 0.1245117187500000,
},
0xf052,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.1436671384194865,
.group_height = 1.1430165816326530,
.group_x = 0.0624629273607646,
.group_y = 0.0625610266424885,
},
0xf053,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.8765709864847797,
.group_height = 1.0707191397207079,
.group_x = 0.2332599943628554,
.group_y = 0.0332682382480123,
},
0xf05a...0xf05b,
0xf081,
0xf092,
0xf0aa,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0005935142780173,
.group_height = 1.0001395089285714,
.group_y = 0.0000697447342726,
},
0xf071,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0014662756598240,
.group_height = 1.1428571428571428,
.group_x = 0.0004880429477794,
.group_y = 0.0625000000000000,
},
0xf078,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0717654378877508,
.group_height = 1.8757195185766613,
.group_x = 0.0331834301604062,
.group_y = 0.1670386385827870,
},
0xf07b,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_height = 1.1428571428571428,
.group_y = 0.0625000000000000,
},
0xf09c,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_height = 1.0810546875000000,
},
0xf09f,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.7506617925122907,
.group_height = 1.0810546875000000,
.group_x = 0.2143937211981567,
},
0xf0a1,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0009775171065494,
.group_x = 0.0004882812500000,
},
0xf0a2,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.1433271023627367,
.group_height = 1.0001395089285714,
.group_x = 0.0624235731978609,
.group_y = 0.0000697447342726,
},
0xf0a3,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0005760656161586,
.group_height = 1.0001220681837999,
.group_x = 0.0004792774839344,
.group_y = 0.0000610266424885,
},
0xf0a4,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0005935142780173,
.group_height = 1.3335193452380951,
.group_y = 0.1250523085507044,
},
0xf0ca,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0005935142780173,
.group_height = 1.1922501247297521,
.group_y = 0.0806249128190822,
},
0xf0d6,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_height = 1.5014662756598240,
.group_y = 0.1669921875000000,
},
0xf0de,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.2253421114919656,
.group_height = 2.5216400911161729,
.group_x = 0.0918898809523810,
.group_y = 0.6034327009936766,
},
0xf0e7,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.3336843856081169,
.group_x = 0.1247597299147187,
},
0xf296,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0005148743038617,
.group_height = 1.0385966606705219,
.group_x = 0.0005146093447336,
.group_y = 0.0186218440507742,
},
0xf2c2...0xf2c3,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0000770970394737,
.group_height = 1.2864321608040201,
.group_y = 0.1113281250000000,
},
0xf2c4,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0344231791600214,
.group_x = 0.0166002826673519,
},
0xf2c5,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0004538836055876,
.group_height = 1.4840579710144928,
.group_x = 0.0004536776887225,
.group_y = 0.1630859375000000,
},
0xf2f0,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.0005935142780173,
.group_height = 1.0334438518091393,
.group_y = 0.0161807783512345,
},
0xf306,
=> .{
.size_horizontal = .fit,
.size_vertical = .fit,
.height = .icon,
.align_horizontal = .center,
.align_vertical = .center,
.group_width = 1.2427184466019416,
.group_x = 0.0976562500000000,
},
else => .none, else => .none,
}; };
} }

View File

@ -7,11 +7,16 @@ attributes and scaling rules.
This does include an `eval` call! This is spooky, but we trust the nerd fonts code to This does include an `eval` call! This is spooky, but we trust the nerd fonts code to
be safe and not malicious or anything. be safe and not malicious or anything.
This script requires Python 3.12 or greater. This script requires Python 3.12 or greater, requires that the `fontTools`
python module is installed, and requires that the path to a copy of the
SymbolsNerdFontMono font is passed as the first argument to the script.
""" """
import ast import ast
import sys
import math import math
from fontTools.ttLib import TTFont
from fontTools.pens.boundsPen import BoundsPen
from collections import defaultdict from collections import defaultdict
from contextlib import suppress from contextlib import suppress
from pathlib import Path from pathlib import Path
@ -19,7 +24,18 @@ from types import SimpleNamespace
from typing import Literal, TypedDict, cast from typing import Literal, TypedDict, cast
type PatchSetAttributes = dict[Literal["default"] | int, PatchSetAttributeEntry] type PatchSetAttributes = dict[Literal["default"] | int, PatchSetAttributeEntry]
type AttributeHash = tuple[str | None, str | None, str, float, float, float] type AttributeHash = tuple[
str | None,
str | None,
str,
float,
float,
float,
float,
float,
float,
float,
]
type ResolvedSymbol = PatchSetAttributes | PatchSetScaleRules | int | None type ResolvedSymbol = PatchSetAttributes | PatchSetScaleRules | int | None
@ -34,6 +50,11 @@ class PatchSetAttributeEntry(TypedDict):
stretch: str stretch: str
params: dict[str, float | bool] params: dict[str, float | bool]
group_x: float
group_y: float
group_width: float
group_height: float
class PatchSet(TypedDict): class PatchSet(TypedDict):
SymStart: int SymStart: int
@ -137,6 +158,10 @@ def attr_key(attr: PatchSetAttributeEntry) -> AttributeHash:
float(params.get("overlap", 0.0)), float(params.get("overlap", 0.0)),
float(params.get("xy-ratio", -1.0)), float(params.get("xy-ratio", -1.0)),
float(params.get("ypadding", 0.0)), float(params.get("ypadding", 0.0)),
float(attr.get("group_x", 0.0)),
float(attr.get("group_y", 0.0)),
float(attr.get("group_width", 1.0)),
float(attr.get("group_height", 1.0)),
) )
@ -162,6 +187,11 @@ def emit_zig_entry_multikey(codepoints: list[int], attr: PatchSetAttributeEntry)
stretch = attr.get("stretch", "") stretch = attr.get("stretch", "")
params = attr.get("params", {}) params = attr.get("params", {})
group_x = attr.get("group_x", 0.0)
group_y = attr.get("group_y", 0.0)
group_width = attr.get("group_width", 1.0)
group_height = attr.get("group_height", 1.0)
overlap = params.get("overlap", 0.0) overlap = params.get("overlap", 0.0)
xy_ratio = params.get("xy-ratio", -1.0) xy_ratio = params.get("xy-ratio", -1.0)
y_padding = params.get("ypadding", 0.0) y_padding = params.get("ypadding", 0.0)
@ -180,16 +210,18 @@ def emit_zig_entry_multikey(codepoints: list[int], attr: PatchSetAttributeEntry)
if "xy" in stretch: if "xy" in stretch:
s += " .size_horizontal = .stretch,\n" s += " .size_horizontal = .stretch,\n"
s += " .size_vertical = .stretch,\n" s += " .size_vertical = .stretch,\n"
elif "!" in stretch: elif "!" in stretch or "^" in stretch:
s += " .size_horizontal = .cover,\n" s += " .size_horizontal = .cover,\n"
s += " .size_vertical = .fit,\n" s += " .size_vertical = .fit,\n"
elif "^" in stretch:
s += " .size_horizontal = .cover,\n"
s += " .size_vertical = .cover,\n"
else: else:
s += " .size_horizontal = .fit,\n" s += " .size_horizontal = .fit,\n"
s += " .size_vertical = .fit,\n" s += " .size_vertical = .fit,\n"
# `^` indicates that scaling should fill
# the whole cell, not just the icon height.
if "^" not in stretch:
s += " .height = .icon,\n"
# There are two cases where we want to limit the constraint width to 1: # There are two cases where we want to limit the constraint width to 1:
# - If there's a `1` in the stretch mode string. # - If there's a `1` in the stretch mode string.
# - If the stretch mode is `xy` and there's not an explicit `2`. # - If the stretch mode is `xy` and there's not an explicit `2`.
@ -201,6 +233,15 @@ def emit_zig_entry_multikey(codepoints: list[int], attr: PatchSetAttributeEntry)
if valign is not None: if valign is not None:
s += f" .align_vertical = {valign},\n" s += f" .align_vertical = {valign},\n"
if group_width != 1.0:
s += f" .group_width = {group_width:.16f},\n"
if group_height != 1.0:
s += f" .group_height = {group_height:.16f},\n"
if group_x != 0.0:
s += f" .group_x = {group_x:.16f},\n"
if group_y != 0.0:
s += f" .group_y = {group_y:.16f},\n"
# `overlap` and `ypadding` are mutually exclusive, # `overlap` and `ypadding` are mutually exclusive,
# this is asserted in the nerd fonts patcher itself. # this is asserted in the nerd fonts patcher itself.
if overlap: if overlap:
@ -223,16 +264,53 @@ def emit_zig_entry_multikey(codepoints: list[int], attr: PatchSetAttributeEntry)
return s return s
def generate_zig_switch_arms(patch_sets: list[PatchSet]) -> str: def generate_zig_switch_arms(
patch_sets: list[PatchSet],
nerd_font: TTFont,
) -> str:
cmap = nerd_font.getBestCmap()
glyphs = nerd_font.getGlyphSet()
entries: dict[int, PatchSetAttributeEntry] = {} entries: dict[int, PatchSetAttributeEntry] = {}
for entry in patch_sets: for entry in patch_sets:
attributes = entry["Attributes"] attributes = entry["Attributes"]
for cp in range(entry["SymStart"], entry["SymEnd"] + 1): for cp in range(entry["SymStart"], entry["SymEnd"] + 1):
entries[cp] = attributes["default"] entries[cp] = attributes["default"].copy()
entries |= {k: v for k, v in attributes.items() if isinstance(k, int)} entries |= {k: v for k, v in attributes.items() if isinstance(k, int)}
if entry["ScaleRules"] is not None and "ScaleGroups" in entry["ScaleRules"]:
for group in entry["ScaleRules"]["ScaleGroups"]:
xMin = math.inf
yMin = math.inf
xMax = -math.inf
yMax = -math.inf
individual_bounds: dict[int, tuple[int, int, int ,int]] = {}
for cp in group:
if cp not in cmap:
continue
glyph = glyphs[cmap[cp]]
bounds = BoundsPen(glyphSet=glyphs)
glyph.draw(bounds)
individual_bounds[cp] = bounds.bounds
xMin = min(bounds.bounds[0], xMin)
yMin = min(bounds.bounds[1], yMin)
xMax = max(bounds.bounds[2], xMax)
yMax = max(bounds.bounds[3], yMax)
group_width = xMax - xMin
group_height = yMax - yMin
for cp in group:
if cp not in cmap or cp not in entries:
continue
this_bounds = individual_bounds[cp]
this_width = this_bounds[2] - this_bounds[0]
this_height = this_bounds[3] - this_bounds[1]
entries[cp]["group_width"] = group_width / this_width
entries[cp]["group_height"] = group_height / this_height
entries[cp]["group_x"] = (this_bounds[0] - xMin) / group_width
entries[cp]["group_y"] = (this_bounds[1] - yMin) / group_height
del entries[0] del entries[0]
# Group codepoints by attribute key # Group codepoints by attribute key
@ -253,6 +331,10 @@ def generate_zig_switch_arms(patch_sets: list[PatchSet]) -> str:
if __name__ == "__main__": if __name__ == "__main__":
project_root = Path(__file__).resolve().parents[2] project_root = Path(__file__).resolve().parents[2]
nf_path = sys.argv[1]
nerd_font = TTFont(nf_path)
patcher_path = project_root / "vendor" / "nerd-fonts" / "font-patcher.py" patcher_path = project_root / "vendor" / "nerd-fonts" / "font-patcher.py"
source = patcher_path.read_text(encoding="utf-8") source = patcher_path.read_text(encoding="utf-8")
patch_set = extract_patch_set_values(source) patch_set = extract_patch_set_values(source)
@ -272,5 +354,5 @@ const Constraint = @import("face.zig").RenderOptions.Constraint;
pub fn getConstraint(cp: u21) Constraint { pub fn getConstraint(cp: u21) Constraint {
return switch (cp) { return switch (cp) {
""") """)
f.write(generate_zig_switch_arms(patch_set)) f.write(generate_zig_switch_arms(patch_set, nerd_font))
f.write("\n else => .none,\n };\n}\n") f.write("\n else => .none,\n };\n}\n")

View File

@ -195,7 +195,6 @@ pub fn renderGlyph(
.offset_y = 0, .offset_y = 0,
.atlas_x = 0, .atlas_x = 0,
.atlas_y = 0, .atlas_y = 0,
.advance_x = 0,
}; };
const metrics = self.metrics; const metrics = self.metrics;
@ -227,8 +226,6 @@ pub fn renderGlyph(
.offset_y = @as(i32, @intCast(region.height +| canvas.clip_bottom)) - @as(i32, @intCast(padding_y)), .offset_y = @as(i32, @intCast(region.height +| canvas.clip_bottom)) - @as(i32, @intCast(padding_y)),
.atlas_x = region.x, .atlas_x = region.x,
.atlas_y = region.y, .atlas_y = region.y,
.advance_x = @floatFromInt(width),
.sprite = true,
}; };
} }

View File

@ -19,8 +19,13 @@ const internal_os = @import("os/main.zig");
// Some comptime assertions that our C API depends on. // Some comptime assertions that our C API depends on.
comptime { comptime {
// We allow tests to reference this file because we unit test
// some of the C API. At runtime though we should never get these
// functions unless we are building libghostty.
if (!builtin.is_test) {
assert(apprt.runtime == apprt.embedded); assert(apprt.runtime == apprt.embedded);
} }
}
/// Global options so we can log. This is identical to main. /// Global options so we can log. This is identical to main.
pub const std_options = main.std_options; pub const std_options = main.std_options;
@ -29,8 +34,10 @@ comptime {
// These structs need to be referenced so the `export` functions // These structs need to be referenced so the `export` functions
// are truly exported by the C API lib. // are truly exported by the C API lib.
_ = @import("config.zig").CAPI; _ = @import("config.zig").CAPI;
if (@hasDecl(apprt.runtime, "CAPI")) {
_ = apprt.runtime.CAPI; _ = apprt.runtime.CAPI;
} }
}
/// ghostty_info_s /// ghostty_info_s
const Info = extern struct { const Info = extern struct {
@ -46,6 +53,24 @@ const Info = extern struct {
}; };
}; };
/// ghostty_string_s
pub const String = extern struct {
ptr: ?[*]const u8,
len: usize,
pub const empty: String = .{
.ptr = null,
.len = 0,
};
pub fn fromSlice(slice: []const u8) String {
return .{
.ptr = slice.ptr,
.len = slice.len,
};
}
};
/// Initialize ghostty global state. /// Initialize ghostty global state.
export fn ghostty_init(argc: usize, argv: [*][*:0]u8) c_int { export fn ghostty_init(argc: usize, argv: [*][*:0]u8) c_int {
assert(builtin.link_libc); assert(builtin.link_libc);
@ -95,3 +120,8 @@ export fn ghostty_info() Info {
export fn ghostty_translate(msgid: [*:0]const u8) [*:0]const u8 { export fn ghostty_translate(msgid: [*:0]const u8) [*:0]const u8 {
return internal_os.i18n._(msgid); return internal_os.i18n._(msgid);
} }
/// Free a string allocated by Ghostty.
export fn ghostty_string_free(str: String) void {
state.alloc.free(str.ptr.?[0..str.len]);
}

View File

@ -49,6 +49,7 @@ pub const locales = [_][:0]const u8{
"ca_ES.UTF-8", "ca_ES.UTF-8",
"bg_BG.UTF-8", "bg_BG.UTF-8",
"ga_IE.UTF-8", "ga_IE.UTF-8",
"he_IL.UTF-8",
}; };
/// Set for faster membership lookup of locales. /// Set for faster membership lookup of locales.

View File

@ -17,7 +17,7 @@ test "read /proc/sys/kernel/osrelease" {
if (comptime builtin.os.tag != .linux) return null; if (comptime builtin.os.tag != .linux) return null;
const allocator = std.testing.allocator; const allocator = std.testing.allocator;
const kernel_info = try getKernelInfo(allocator); const kernel_info = getKernelInfo(allocator).?;
defer allocator.free(kernel_info); defer allocator.free(kernel_info);
// Since we can't hardcode the info in tests, just check // Since we can't hardcode the info in tests, just check

View File

@ -2,6 +2,8 @@
//! system. These aren't restricted to syscalls or low-level operations, but //! system. These aren't restricted to syscalls or low-level operations, but
//! also OS-specific features and conventions. //! also OS-specific features and conventions.
const builtin = @import("builtin");
const dbus = @import("dbus.zig"); const dbus = @import("dbus.zig");
const desktop = @import("desktop.zig"); const desktop = @import("desktop.zig");
const env = @import("env.zig"); const env = @import("env.zig");
@ -14,7 +16,7 @@ const openpkg = @import("open.zig");
const pipepkg = @import("pipe.zig"); const pipepkg = @import("pipe.zig");
const resourcesdir = @import("resourcesdir.zig"); const resourcesdir = @import("resourcesdir.zig");
const systemd = @import("systemd.zig"); const systemd = @import("systemd.zig");
const kernelInfo = @import("kernel_info.zig"); const kernel_info = @import("kernel_info.zig");
// Namespaces // Namespaces
pub const args = @import("args.zig"); pub const args = @import("args.zig");
@ -59,8 +61,12 @@ pub const pipe = pipepkg.pipe;
pub const resourcesDir = resourcesdir.resourcesDir; pub const resourcesDir = resourcesdir.resourcesDir;
pub const ResourcesDir = resourcesdir.ResourcesDir; pub const ResourcesDir = resourcesdir.ResourcesDir;
pub const ShellEscapeWriter = shell.ShellEscapeWriter; pub const ShellEscapeWriter = shell.ShellEscapeWriter;
pub const getKernelInfo = kernelInfo.getKernelInfo; pub const getKernelInfo = kernel_info.getKernelInfo;
test { test {
_ = i18n; _ = i18n;
if (comptime builtin.os.tag == .linux) {
_ = kernel_info;
}
} }

View File

@ -63,3 +63,136 @@ pub fn launchedBySystemd() bool {
else => false, else => false,
}; };
} }
/// systemd notifications. Used by Ghostty to inform systemd of the state of the
/// process. Currently only used to notify systemd that we are ready and that
/// configuration reloading has started.
///
/// See: https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html
///
/// These functions were re-implemented in Zig instead of using the `libsystemd`
/// library to avoid the complexity of another external dependency, as well as
/// to take advantage of Zig features like `comptime` to ensure minimal impact
/// on non-Linux systems (like FreeBSD) that will never support `systemd`.
///
/// Linux systems that do not use `systemd` should not be impacted as they
/// should never start Ghostty with the `NOTIFY_SOCKET` environment variable set
/// and these functions essentially become a no-op.
///
/// See `systemd`'s [Interface Portability and Stability Promise](https://systemd.io/PORTABILITY_AND_STABILITY/)
/// for assurances that the interfaces used here will be supported and stable for
/// the long term.
pub const notify = struct {
/// Send the given message to the UNIX socket specified in the NOTIFY_SOCKET
/// environment variable. If there NOTIFY_SOCKET environment variable does
/// not exist then no message is sent.
fn send(message: []const u8) void {
// systemd is Linux-only so this is a no-op anywhere else
if (comptime builtin.os.tag != .linux) return;
// Get the socket address that should receive notifications.
const socket_path = std.posix.getenv("NOTIFY_SOCKET") orelse return;
// If the socket address is an empty string return.
if (socket_path.len == 0) return;
// The socket address must be a path or an abstract socket.
if (socket_path[0] != '/' and socket_path[0] != '@') {
log.warn("only AF_UNIX sockets with path or abstract namespace addresses are supported!", .{});
return;
}
var socket_address: std.os.linux.sockaddr.un = undefined;
// Error out if the supplied socket path is too long.
if (socket_address.path.len < socket_path.len) {
log.warn("NOTIFY_SOCKET path is too long!", .{});
return;
}
socket_address.family = std.os.linux.AF.UNIX;
@memcpy(socket_address.path[0..socket_path.len], socket_path);
socket_address.path[socket_path.len] = 0;
const socket: std.os.linux.socket_t = socket: {
const rc = std.os.linux.socket(
std.os.linux.AF.UNIX,
std.os.linux.SOCK.DGRAM | std.os.linux.SOCK.CLOEXEC,
0,
);
switch (std.os.linux.E.init(rc)) {
.SUCCESS => break :socket @intCast(rc),
else => |e| {
log.warn("creating socket failed: {s}", .{@tagName(e)});
return;
},
}
};
defer _ = std.os.linux.close(socket);
connect: {
const rc = std.os.linux.connect(
socket,
&socket_address,
@offsetOf(std.os.linux.sockaddr.un, "path") + socket_address.path.len,
);
switch (std.os.linux.E.init(rc)) {
.SUCCESS => break :connect,
else => |e| {
log.warn("unable to connect to notify socket: {s}", .{@tagName(e)});
return;
},
}
}
write: {
const rc = std.os.linux.write(socket, message.ptr, message.len);
switch (std.os.linux.E.init(rc)) {
.SUCCESS => {
const written = rc;
if (written < message.len) {
log.warn("short write to notify socket: {d} < {d}", .{ rc, message.len });
return;
}
break :write;
},
else => |e| {
log.warn("unable to write to notify socket: {s}", .{@tagName(e)});
return;
},
}
}
}
/// Tell systemd that we are ready or that we are finished reloading.
/// See: https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html#READY=1
pub fn ready() void {
if (comptime builtin.os.tag != .linux) return;
send("READY=1");
}
/// Tell systemd that we have started reloading our configuration.
/// See: https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html#RELOADING=1
/// and: https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html#MONOTONIC_USEC=%E2%80%A6
pub fn reloading() void {
if (comptime builtin.os.tag != .linux) return;
const ts = std.posix.clock_gettime(.MONOTONIC) catch |err| {
log.err("unable to get MONOTONIC clock: {}", .{err});
return;
};
const now = ts.sec * std.time.us_per_s + @divFloor(ts.nsec, std.time.ns_per_us);
var buffer: [64]u8 = undefined;
const message = std.fmt.bufPrint(&buffer, "RELOADING=1\nMONOTONIC_USEC={d}", .{now}) catch |err| {
log.err("unable to format reloading message: {}", .{err});
return;
};
send(message);
}
};

View File

@ -95,6 +95,76 @@ if [[ "$GHOSTTY_SHELL_FEATURES" == *"sudo"* && -n "$TERMINFO" ]]; then
} }
fi fi
# SSH Integration
if [[ "$GHOSTTY_SHELL_FEATURES" == *ssh-* ]]; then
ssh() {
builtin local ssh_term ssh_opts
ssh_term="xterm-256color"
ssh_opts=()
# Configure environment variables for remote session
if [[ "$GHOSTTY_SHELL_FEATURES" == *ssh-env* ]]; then
ssh_opts+=(-o "SetEnv COLORTERM=truecolor")
ssh_opts+=(-o "SendEnv TERM_PROGRAM TERM_PROGRAM_VERSION")
fi
# Install terminfo on remote host if needed
if [[ "$GHOSTTY_SHELL_FEATURES" == *ssh-terminfo* ]]; then
builtin local ssh_user ssh_hostname
while IFS=' ' read -r ssh_key ssh_value; do
case "$ssh_key" in
user) ssh_user="$ssh_value" ;;
hostname) ssh_hostname="$ssh_value" ;;
esac
[[ -n "$ssh_user" && -n "$ssh_hostname" ]] && break
done < <(builtin command ssh -G "$@" 2>/dev/null)
if [[ -n "$ssh_hostname" ]]; then
builtin local ssh_target="${ssh_user}@${ssh_hostname}"
# Check if terminfo is already cached
if "$GHOSTTY_BIN_DIR/ghostty" +ssh-cache --host="$ssh_target" >/dev/null 2>&1; then
ssh_term="xterm-ghostty"
elif builtin command -v infocmp >/dev/null 2>&1; then
builtin local ssh_terminfo ssh_cpath_dir ssh_cpath
ssh_terminfo=$(infocmp -0 -x xterm-ghostty 2>/dev/null)
if [[ -n "$ssh_terminfo" ]]; then
builtin echo "Setting up xterm-ghostty terminfo on $ssh_hostname..." >&2
ssh_cpath_dir=$(mktemp -d "/tmp/ghostty-ssh-$ssh_user.XXXXXX" 2>/dev/null) || ssh_cpath_dir="/tmp/ghostty-ssh-$ssh_user.$$"
ssh_cpath="$ssh_cpath_dir/socket"
if builtin echo "$ssh_terminfo" | builtin command ssh -o ControlMaster=yes -o ControlPath="$ssh_cpath" -o ControlPersist=60s "$@" '
infocmp xterm-ghostty >/dev/null 2>&1 && exit 0
command -v tic >/dev/null 2>&1 || exit 1
mkdir -p ~/.terminfo 2>/dev/null && tic -x - 2>/dev/null && exit 0
exit 1
' 2>/dev/null; then
ssh_term="xterm-ghostty"
ssh_opts+=(-o "ControlPath=$ssh_cpath")
# Cache successful installation
"$GHOSTTY_BIN_DIR/ghostty" +ssh-cache --add="$ssh_target" >/dev/null 2>&1 || true
else
builtin echo "Warning: Failed to install terminfo." >&2
fi
else
builtin echo "Warning: Could not generate terminfo data." >&2
fi
else
builtin echo "Warning: ghostty command not available for cache management." >&2
fi
fi
fi
# Execute SSH with TERM environment variable
TERM="$ssh_term" builtin command ssh "${ssh_opts[@]}" "$@"
}
fi
# Import bash-preexec, safe to do multiple times # Import bash-preexec, safe to do multiple times
builtin source "$(dirname -- "${BASH_SOURCE[0]}")/bash-preexec.sh" builtin source "$(dirname -- "${BASH_SOURCE[0]}")/bash-preexec.sh"

View File

@ -98,6 +98,95 @@
(external sudo) $@args (external sudo) $@args
} }
# SSH Integration
use str
if (str:contains $E:GHOSTTY_SHELL_FEATURES ssh-) {
fn ssh {|@args|
var ssh-term = "xterm-256color"
var ssh-opts = []
# Configure environment variables for remote session
if (str:contains $E:GHOSTTY_SHELL_FEATURES ssh-env) {
set ssh-opts = (conj $ssh-opts
-o "SetEnv COLORTERM=truecolor"
-o "SendEnv TERM_PROGRAM TERM_PROGRAM_VERSION"
)
}
# Install terminfo on remote host if needed
if (str:contains $E:GHOSTTY_SHELL_FEATURES ssh-terminfo) {
var ssh-user = ""
var ssh-hostname = ""
# Parse ssh config
var ssh-config = (external ssh -G $@args 2>/dev/null | slurp)
for line (str:split "\n" $ssh-config) {
var parts = (str:split " " $line)
if (> (count $parts) 1) {
var ssh-key = $parts[0]
var ssh-value = $parts[1]
if (eq $ssh-key user) {
set ssh-user = $ssh-value
} elif (eq $ssh-key hostname) {
set ssh-hostname = $ssh-value
}
if (and (not-eq $ssh-user "") (not-eq $ssh-hostname "")) {
break
}
}
}
if (not-eq $ssh-hostname "") {
var ssh-target = $ssh-user"@"$ssh-hostname
# Check if terminfo is already cached
if (and (has-external ghostty) (bool ?(external ghostty +ssh-cache --host=$ssh-target >/dev/null 2>&1))) {
set ssh-term = "xterm-ghostty"
} elif (has-external infocmp) {
var ssh-terminfo = (external infocmp -0 -x xterm-ghostty 2>/dev/null | slurp)
if (not-eq $ssh-terminfo "") {
echo "Setting up xterm-ghostty terminfo on "$ssh-hostname"..." >&2
var ssh-cpath-dir = ""
try {
set ssh-cpath-dir = (external mktemp -d "/tmp/ghostty-ssh-"$ssh-user".XXXXXX" 2>/dev/null | slurp)
} catch {
set ssh-cpath-dir = "/tmp/ghostty-ssh-"$ssh-user"."(randint 10000 99999)
}
var ssh-cpath = $ssh-cpath-dir"/socket"
if (bool ?(echo $ssh-terminfo | external ssh $@ssh-opts -o ControlMaster=yes -o ControlPath=$ssh-cpath -o ControlPersist=60s $@args '
infocmp xterm-ghostty >/dev/null 2>&1 && exit 0
command -v tic >/dev/null 2>&1 || exit 1
mkdir -p ~/.terminfo 2>/dev/null && tic -x - 2>/dev/null && exit 0
exit 1
' 2>/dev/null)) {
set ssh-term = "xterm-ghostty"
set ssh-opts = (conj $ssh-opts -o ControlPath=$ssh-cpath)
# Cache successful installation
if (has-external ghostty) {
external ghostty +ssh-cache --add=$ssh-target >/dev/null 2>&1
}
} else {
echo "Warning: Failed to install terminfo." >&2
}
} else {
echo "Warning: Could not generate terminfo data." >&2
}
} else {
echo "Warning: ghostty command not available for cache management." >&2
}
}
}
# Execute SSH with TERM environment variable
external E:TERM=$ssh-term ssh $@ssh-opts $@args
}
}
defer { defer {
mark-prompt-start mark-prompt-start
report-pwd report-pwd

View File

@ -86,6 +86,89 @@ function __ghostty_setup --on-event fish_prompt -d "Setup ghostty integration"
end end
end end
# SSH Integration
set -l features (string split ',' -- "$GHOSTTY_SHELL_FEATURES")
if contains ssh-env $features; or contains ssh-terminfo $features
function ssh --wraps=ssh --description "SSH wrapper with Ghostty integration"
set -l features (string split ',' -- "$GHOSTTY_SHELL_FEATURES")
set -l ssh_term "xterm-256color"
set -l ssh_opts
# Configure environment variables for remote session
if contains ssh-env $features
set -a ssh_opts -o "SetEnv COLORTERM=truecolor"
set -a ssh_opts -o "SendEnv TERM_PROGRAM TERM_PROGRAM_VERSION"
end
# Install terminfo on remote host if needed
if contains ssh-terminfo $features
set -l ssh_user
set -l ssh_hostname
for line in (command ssh -G $argv 2>/dev/null)
set -l parts (string split ' ' -- $line)
if test (count $parts) -ge 2
switch $parts[1]
case user
set ssh_user $parts[2]
case hostname
set ssh_hostname $parts[2]
end
if test -n "$ssh_user"; and test -n "$ssh_hostname"
break
end
end
end
if test -n "$ssh_hostname"
set -l ssh_target "$ssh_user@$ssh_hostname"
# Check if terminfo is already cached
if test -x "$GHOSTTY_BIN_DIR/ghostty"; and "$GHOSTTY_BIN_DIR/ghostty" +ssh-cache --host="$ssh_target" >/dev/null 2>&1
set ssh_term "xterm-ghostty"
else if command -q infocmp
set -l ssh_terminfo
set -l ssh_cpath_dir
set -l ssh_cpath
set ssh_terminfo (infocmp -0 -x xterm-ghostty 2>/dev/null)
if test -n "$ssh_terminfo"
echo "Setting up xterm-ghostty terminfo on $ssh_hostname..." >&2
set ssh_cpath_dir (mktemp -d "/tmp/ghostty-ssh-$ssh_user.XXXXXX" 2>/dev/null; or echo "/tmp/ghostty-ssh-$ssh_user."(random))
set ssh_cpath "$ssh_cpath_dir/socket"
if echo "$ssh_terminfo" | command ssh $ssh_opts -o ControlMaster=yes -o ControlPath="$ssh_cpath" -o ControlPersist=60s $argv '
infocmp xterm-ghostty >/dev/null 2>&1 && exit 0
command -v tic >/dev/null 2>&1 || exit 1
mkdir -p ~/.terminfo 2>/dev/null && tic -x - 2>/dev/null && exit 0
exit 1
' 2>/dev/null
set ssh_term "xterm-ghostty"
set -a ssh_opts -o "ControlPath=$ssh_cpath"
# Cache successful installation
if test -x "$GHOSTTY_BIN_DIR/ghostty"
"$GHOSTTY_BIN_DIR/ghostty" +ssh-cache --add="$ssh_target" >/dev/null 2>&1; or true
end
else
echo "Warning: Failed to install terminfo." >&2
end
else
echo "Warning: Could not generate terminfo data." >&2
end
else
echo "Warning: ghostty command not available for cache management." >&2
end
end
end
# Execute SSH with TERM environment variable
env TERM="$ssh_term" command ssh $ssh_opts $argv
end
end
# Setup prompt marking # Setup prompt marking
function __ghostty_mark_prompt_start --on-event fish_prompt --on-event fish_cancel --on-event fish_posterror function __ghostty_mark_prompt_start --on-event fish_prompt --on-event fish_cancel --on-event fish_posterror
# If we never got the output end event, then we need to send it now. # If we never got the output end event, then we need to send it now.

View File

@ -244,6 +244,79 @@ _ghostty_deferred_init() {
} }
fi fi
# SSH Integration
if [[ "$GHOSTTY_SHELL_FEATURES" == *ssh-* ]]; then
ssh() {
emulate -L zsh
setopt local_options no_glob_subst
local ssh_term ssh_opts
ssh_term="xterm-256color"
ssh_opts=()
# Configure environment variables for remote session
if [[ "$GHOSTTY_SHELL_FEATURES" == *ssh-env* ]]; then
ssh_opts+=(-o "SetEnv COLORTERM=truecolor")
ssh_opts+=(-o "SendEnv TERM_PROGRAM TERM_PROGRAM_VERSION")
fi
# Install terminfo on remote host if needed
if [[ "$GHOSTTY_SHELL_FEATURES" == *ssh-terminfo* ]]; then
local ssh_user ssh_hostname
while IFS=' ' read -r ssh_key ssh_value; do
case "$ssh_key" in
user) ssh_user="$ssh_value" ;;
hostname) ssh_hostname="$ssh_value" ;;
esac
[[ -n "$ssh_user" && -n "$ssh_hostname" ]] && break
done < <(command ssh -G "$@" 2>/dev/null)
if [[ -n "$ssh_hostname" ]]; then
local ssh_target="${ssh_user}@${ssh_hostname}"
# Check if terminfo is already cached
if "$GHOSTTY_BIN_DIR/ghostty" +ssh-cache --host="$ssh_target" >/dev/null 2>&1; then
ssh_term="xterm-ghostty"
elif (( $+commands[infocmp] )); then
local ssh_terminfo ssh_cpath_dir ssh_cpath
ssh_terminfo=$(infocmp -0 -x xterm-ghostty 2>/dev/null)
if [[ -n "$ssh_terminfo" ]]; then
print "Setting up xterm-ghostty terminfo on $ssh_hostname..." >&2
ssh_cpath_dir=$(mktemp -d "/tmp/ghostty-ssh-$ssh_user.XXXXXX" 2>/dev/null) || ssh_cpath_dir="/tmp/ghostty-ssh-$ssh_user.$$"
ssh_cpath="$ssh_cpath_dir/socket"
if print "$ssh_terminfo" | command ssh "${ssh_opts[@]}" -o ControlMaster=yes -o ControlPath="$ssh_cpath" -o ControlPersist=60s "$@" '
infocmp xterm-ghostty >/dev/null 2>&1 && exit 0
command -v tic >/dev/null 2>&1 || exit 1
mkdir -p ~/.terminfo 2>/dev/null && tic -x - 2>/dev/null && exit 0
exit 1
' 2>/dev/null; then
ssh_term="xterm-ghostty"
ssh_opts+=(-o "ControlPath=$ssh_cpath")
# Cache successful installation
"$GHOSTTY_BIN_DIR/ghostty" +ssh-cache --add="$ssh_target" >/dev/null 2>&1 || true
else
print "Warning: Failed to install terminfo." >&2
fi
else
print "Warning: Could not generate terminfo data." >&2
fi
else
print "Warning: ghostty command not available for cache management." >&2
fi
fi
fi
# Execute SSH with TERM environment variable
TERM="$ssh_term" command ssh "${ssh_opts[@]}" "$@"
}
fi
# Some zsh users manually run `source ~/.zshrc` in order to apply rc file # Some zsh users manually run `source ~/.zshrc` in order to apply rc file
# changes to the current shell. This is a terrible practice that breaks many # changes to the current shell. This is a terrible practice that breaks many
# things, including our shell integration. For example, Oh My Zsh and Prezto # things, including our shell integration. For example, Oh My Zsh and Prezto

View File

@ -154,15 +154,12 @@ pub const Style = struct {
.palette => |idx| palette: { .palette => |idx| palette: {
if (self.flags.bold) { if (self.flags.bold) {
if (opts.bold) |bold| switch (bold) { if (opts.bold) |_| {
.color => |v| break :palette v.toTerminalRGB(),
.bright => {
const bright_offset = @intFromEnum(color.Name.bright_black); const bright_offset = @intFromEnum(color.Name.bright_black);
if (idx < bright_offset) { if (idx < bright_offset) {
break :palette opts.palette[idx + bright_offset]; break :palette opts.palette[idx + bright_offset];
} }
}, }
};
} }
break :palette opts.palette[idx]; break :palette opts.palette[idx];

View File

@ -177,10 +177,28 @@ pub fn setupFeatures(
}; };
var buffer = try std.BoundedArray(u8, capacity).init(0); var buffer = try std.BoundedArray(u8, capacity).init(0);
inline for (fields) |field| { // Sort the fields so that the output is deterministic. This is
if (@field(features, field.name)) { // done at comptime so it has no runtime cost
const fields_sorted: [fields.len][]const u8 = comptime fields: {
var fields_sorted: [fields.len][]const u8 = undefined;
for (fields, 0..) |field, i| fields_sorted[i] = field.name;
std.mem.sortUnstable(
[]const u8,
&fields_sorted,
{},
(struct {
fn lessThan(_: void, lhs: []const u8, rhs: []const u8) bool {
return std.ascii.orderIgnoreCase(lhs, rhs) == .lt;
}
}).lessThan,
);
break :fields fields_sorted;
};
inline for (fields_sorted) |name| {
if (@field(features, name)) {
if (buffer.len > 0) try buffer.append(','); if (buffer.len > 0) try buffer.append(',');
try buffer.appendSlice(field.name); try buffer.appendSlice(name);
} }
} }
@ -201,8 +219,8 @@ test "setup features" {
var env = EnvMap.init(alloc); var env = EnvMap.init(alloc);
defer env.deinit(); defer env.deinit();
try setupFeatures(&env, .{ .cursor = true, .sudo = true, .title = true }); try setupFeatures(&env, .{ .cursor = true, .sudo = true, .title = true, .@"ssh-env" = true, .@"ssh-terminfo" = true });
try testing.expectEqualStrings("cursor,sudo,title", env.get("GHOSTTY_SHELL_FEATURES").?); try testing.expectEqualStrings("cursor,ssh-env,ssh-terminfo,sudo,title", env.get("GHOSTTY_SHELL_FEATURES").?);
} }
// Test: all features disabled // Test: all features disabled
@ -210,7 +228,7 @@ test "setup features" {
var env = EnvMap.init(alloc); var env = EnvMap.init(alloc);
defer env.deinit(); defer env.deinit();
try setupFeatures(&env, .{ .cursor = false, .sudo = false, .title = false }); try setupFeatures(&env, .{ .cursor = false, .sudo = false, .title = false, .@"ssh-env" = false, .@"ssh-terminfo" = false });
try testing.expect(env.get("GHOSTTY_SHELL_FEATURES") == null); try testing.expect(env.get("GHOSTTY_SHELL_FEATURES") == null);
} }
@ -219,8 +237,8 @@ test "setup features" {
var env = EnvMap.init(alloc); var env = EnvMap.init(alloc);
defer env.deinit(); defer env.deinit();
try setupFeatures(&env, .{ .cursor = false, .sudo = true, .title = false }); try setupFeatures(&env, .{ .cursor = false, .sudo = true, .title = false, .@"ssh-env" = true, .@"ssh-terminfo" = false });
try testing.expectEqualStrings("sudo", env.get("GHOSTTY_SHELL_FEATURES").?); try testing.expectEqualStrings("ssh-env,sudo", env.get("GHOSTTY_SHELL_FEATURES").?);
} }
} }