diff --git a/ags/i18n/intl.ts b/ags/i18n/intl.ts index e9db088..f6152ef 100644 --- a/ags/i18n/intl.ts +++ b/ags/i18n/intl.ts @@ -1,33 +1,32 @@ -//TODO use I18n system >.< +import { Binding, GLib } from "astal"; + import en_US from "./lang/en_US"; import pt_BR from "./lang/pt_BR"; -import { GLib } from "astal"; + +export type i18nStruct = Record>; const i18nKeys = { "en_US": en_US, "pt_BR": pt_BR }; - const languages: Array = Object.keys(i18nKeys); - -const defaultLanguage: string = languages[0]; let language: string = getSystemLanguage(); export function getSystemLanguage(): string { const sysLanguage: (string|null|undefined) = GLib.getenv("LANG") || GLib.getenv("LANGUAGE"); if(!sysLanguage) { - console.log(`[WARNING] Couldn't get system language, fallback to default ${defaultLanguage}`); + console.log(`[WARNING] Couldn't get system language, fallback to default ${languages[0]}`); console.log("[TIP] Please set the LANG or LANGUAGE environment variable"); - return "en_US"; + return languages[0]; } return sysLanguage.split('.')[0]; } -export function setLanguage(lang: keyof typeof i18nKeys): string { +export function setLanguage(lang: string): string { languages.map((cur: string) => { if(cur === lang) { language = lang; @@ -42,12 +41,20 @@ export function setLanguage(lang: keyof typeof i18nKeys): string { export function tr(key: string): string { let result = i18nKeys[language as keyof typeof i18nKeys], - defResult = i18nKeys[defaultLanguage as keyof typeof i18nKeys]; + defResult = i18nKeys[languages[0] as keyof typeof i18nKeys]; - for(const keyString in key.split('.')) { + for(const keyString of key.split('.')) { result = result[keyString as keyof typeof result] as never; defResult = defResult[keyString as keyof typeof defResult] as never; } - return (result as never) || (defResult as never) || "couldn't find i18n key"; + return (typeof result == "string") ? + result + : ((typeof defResult == "string") ? + defResult + : "not found / is not of type \"string\""); +} + +export function trGet() { + return i18nKeys[getSystemLanguage() as keyof typeof i18nKeys]; } diff --git a/ags/i18n/lang/en_US.ts b/ags/i18n/lang/en_US.ts index 11f0433..6385654 100644 --- a/ags/i18n/lang/en_US.ts +++ b/ags/i18n/lang/en_US.ts @@ -1,8 +1,36 @@ +import { i18nStruct } from "../intl"; + export default { - "language": "English (United States)", - "bar": { - "logo": { - "tooltip": "Applications" + language: "English (United States)", + bar: { + apps: { + tooltip: "Applications" + } + }, + control_center: { + tiles: { + more: "More", + network: { + network: "Network", + connected: "Connected", + disconnected: "Disconnected", + unknown: "Unknown", + connecting: "Connecting", + wireless: "Wireless", + wired: "Wired" + }, + recording: { + title: "Screen Recording", + disabled_description: "Start recording", + enabled_description: "Stop recording", + } + } + }, + ask_popup: { + title: "Question", + options: { + cancel: "Cancel", + accept: "Ok" } } -} +} as i18nStruct; diff --git a/ags/i18n/lang/pt_BR.ts b/ags/i18n/lang/pt_BR.ts index 337496c..97e8ccd 100644 --- a/ags/i18n/lang/pt_BR.ts +++ b/ags/i18n/lang/pt_BR.ts @@ -1,8 +1,37 @@ +import { i18nStruct } from "../intl"; + export default { - "language": "Português (Brasil)", - "bar": { - "logo": { - "tooltip": "Aplicativos" + language: "Português (Brasil)", + bar: { + apps: { + tooltip: "Aplicativos" + } + }, + control_center: { + tiles: { + more: "Mais", + + network: { + network: "Rede", + connected: "Conectado", + disconnected: "Desconectado", + unknown: "Desconhecido", + connecting: "Conectando", + wireless: "Wireless", + wired: "Cabeado" + }, + recording: { + title: "Gravação de Tela", + disabled_description: "Iniciar gravação", + enabled_description: "Parar gravação", + } + } + }, + ask_popup: { + title: "Pergunta", + options: { + cancel: "Cancelar", + accept: "Ok" } } -} +} as i18nStruct; diff --git a/ags/widget/AskPopup.ts b/ags/widget/AskPopup.ts index 36793b7..9283ea4 100644 --- a/ags/widget/AskPopup.ts +++ b/ags/widget/AskPopup.ts @@ -2,6 +2,7 @@ import { Binding } from "astal"; import { PopupWindow, PopupWindowProps } from "./PopupWindow"; import { Astal, Gtk, Widget } from "astal/gtk3"; import { Separator } from "./Separator"; +import { tr } from "../i18n/intl"; export type AskPopupProps = { title?: string | Binding; @@ -22,7 +23,7 @@ export function AskPopup(props: AskPopupProps) { new Widget.Button({ className: "cancel", hexpand: true, - label: props.cancelText || "Cancel", + label: props.cancelText || tr("ask_popup.options.cancel") || "Cancel", onClick: (_) => { window.destroy(); props.onCancel && props.onCancel(); @@ -31,7 +32,7 @@ export function AskPopup(props: AskPopupProps) { new Widget.Button({ className: "accept", hexpand: true, - label: props.acceptText || "Ok", + label: props.acceptText || tr("ask_popup.options.accept") || "Ok", onClick: (_) => { window.destroy(); props.onAccept && props.onAccept(); @@ -57,7 +58,7 @@ export function AskPopup(props: AskPopupProps) { new Widget.Label({ className: "title", visible: Boolean(props.title), - label: props.title || "" + label: props.title || tr("ask_popup.title") || "Question" } as Widget.LabelProps), Separator({ alpha: .2, diff --git a/ags/widget/FlowBox.ts b/ags/widget/FlowBox.ts deleted file mode 100644 index 13d8690..0000000 --- a/ags/widget/FlowBox.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { astalify, Gtk } from "astal/gtk3"; - -// TODO -export class FlowBox extends astalify(Gtk.FlowBox) {} diff --git a/ags/widget/Notification.ts b/ags/widget/Notification.ts index d6b3166..aa7a9af 100644 --- a/ags/widget/Notification.ts +++ b/ags/widget/Notification.ts @@ -1,6 +1,7 @@ import { Astal, Gtk, Widget } from "astal/gtk3"; import AstalNotifd from "gi://AstalNotifd"; import { Separator } from "./Separator"; +import Pango from "gi://Pango"; export function getUrgencyString(notif: AstalNotifd.Notification) { switch(notif.urgency) { @@ -78,6 +79,7 @@ export function NotificationWidget(notification: AstalNotifd.Notification|number new Widget.Box({ className: "text", orientation: Gtk.Orientation.VERTICAL, + expand: true, children: [ new Widget.Label({ className: "summary", @@ -89,9 +91,10 @@ export function NotificationWidget(notification: AstalNotifd.Notification|number new Widget.Label({ className: "body", useMarkup: true, - xalign: 0, - expand: true, + halign: Gtk.Align.START, + truncate: false, wrap: true, + wrapMode: Pango.WrapMode.WORD, label: notification.body } as Widget.LabelProps) ] diff --git a/ags/widget/bar/Logo.ts b/ags/widget/bar/Logo.ts index 4f84777..7b40269 100644 --- a/ags/widget/bar/Logo.ts +++ b/ags/widget/bar/Logo.ts @@ -1,5 +1,6 @@ import { Gtk, Widget } from "astal/gtk3"; import AstalHyprland from "gi://AstalHyprland"; +import { trGet } from "../../i18n/intl"; export function Logo(): Gtk.Widget { return new Widget.EventBox({ @@ -8,6 +9,7 @@ export function Logo(): Gtk.Widget { child: new Widget.Box({ child: new Widget.Label({ className: "nf", + tooltipText: trGet()["bar"]["apps"]["tooltip"], label: "" } as Widget.LabelProps) } as Widget.BoxProps) diff --git a/ags/widget/control-center/tiles/Network.ts b/ags/widget/control-center/tiles/Network.ts index ca97cb5..58221af 100644 --- a/ags/widget/control-center/tiles/Network.ts +++ b/ags/widget/control-center/tiles/Network.ts @@ -2,8 +2,9 @@ import { bind, execAsync, Variable } from "astal"; import { Tile, TileProps } from "./Tile"; import AstalNetwork from "gi://AstalNetwork"; import { Widget } from "astal/gtk3"; -import { showPages, togglePage } from "../Pages"; +import { togglePage } from "../Pages"; import { PageNetwork } from "../pages/Network"; +import { tr } from "../../../i18n/intl"; export const TileNetwork = new Widget.Box({ child: Variable.derive([ @@ -14,18 +15,18 @@ export const TileNetwork = new Widget.Box({ (primary: AstalNetwork.Primary, wired: AstalNetwork.Wired, wifi: AstalNetwork.Wifi) => { if(primary === AstalNetwork.Primary.WIFI) { return Tile({ - title: "Wireless", + title: tr("control_center.tiles.network.wireless") || "Wireless", description: Variable.derive( [ bind(wifi, "ssid"), bind(wifi, "internet") ], (ssid: string, internet: AstalNetwork.Internet) => ssid ? ssid : (() => { switch(internet) { case AstalNetwork.Internet.CONNECTED: - return "Connected"; + return tr("control_center.tiles.network.connected") || "Connected"; case AstalNetwork.Internet.DISCONNECTED: - return "Disconnected"; + return tr("control_center.tiles.network.disconnected") || "Disconnected"; case AstalNetwork.Internet.CONNECTING: - return "Connecting..."; + return tr("control_center.tiles.network.connecting") + "..." || "Connecting..."; } })() )(), @@ -39,15 +40,15 @@ export const TileNetwork = new Widget.Box({ } else if(primary === AstalNetwork.Primary.WIRED) { return Tile({ - title: "Wired", + title: tr("control_center.tiles.network.wired") || "Wired", description: bind(wired, "internet").as((internet: AstalNetwork.Internet) => { switch(internet) { case AstalNetwork.Internet.CONNECTED: - return "Connected"; + return tr("control_center.tiles.network.connected") || "Connected"; case AstalNetwork.Internet.DISCONNECTED: - return "Disconnected"; + return tr("control_center.tiles.network.disconnected") || "Disconnected"; case AstalNetwork.Internet.CONNECTING: - return "Connecting..."; + return tr("control_center.tiles.network.connecting") + "..." || "Connecting..."; } }), onToggledOn: () => execAsync("nmcli n on"), @@ -72,8 +73,8 @@ export const TileNetwork = new Widget.Box({ } return Tile({ - title: "Network", - description: "Disconnected", + title: tr("control_center.tiles.network.network") || "Network", + description: tr("control_center.tiles.network.disconnected") || "Disconnected", onToggledOn: () => execAsync("nmcli n on"), onToggledOff: () => execAsync("nmcli n off"), onClickMore: () => togglePage(PageNetwork), diff --git a/ags/widget/control-center/tiles/Recording.ts b/ags/widget/control-center/tiles/Recording.ts index 7c29e3b..1e88387 100644 --- a/ags/widget/control-center/tiles/Recording.ts +++ b/ags/widget/control-center/tiles/Recording.ts @@ -1,13 +1,14 @@ import { Tile, TileProps } from "./Tile"; import { Recording } from "../../../scripts/recording"; import { bind } from "astal"; +import { tr } from "../../../i18n/intl"; export const TileRecording = Tile({ - title: "Screen Recording", + title: tr("control_center.tiles.recording.title") || "Screen Recording", description: bind(Recording.getDefault(), "recording").as( (isRecording: boolean) => isRecording ? "Recording {time}" - : "Start a Screen Record" + : tr("control_center.tiles.recording.disabled_description") || "Start recording" ), icon: "󰻂", onToggledOff: () => Recording.getDefault().stopRecording(), diff --git a/ags/widget/control-center/tiles/Tile.ts b/ags/widget/control-center/tiles/Tile.ts index f1650bd..2e65673 100644 --- a/ags/widget/control-center/tiles/Tile.ts +++ b/ags/widget/control-center/tiles/Tile.ts @@ -1,5 +1,6 @@ import { Binding, Variable } from "astal"; import { Gtk, Widget } from "astal/gtk3"; +import { tr } from "../../../i18n/intl"; export type TileProps = { className?: string | Binding; @@ -99,6 +100,7 @@ export function Tile(props: TileProps): Widget.EventBox { className: "more icon", visible: props.onClickMore !== undefined, halign: Gtk.Align.END, + tooltipText: tr("control_center.tiles.more") || "More", image: new Widget.Icon({ icon: "go-next-symbolic", css: "icon { font-size: 16px; }" diff --git a/ags/window/Runner.ts b/ags/window/Runner.ts index f2f88b9..1623734 100644 --- a/ags/window/Runner.ts +++ b/ags/window/Runner.ts @@ -6,7 +6,6 @@ import { handleShell } from "../scripts/runner/shell"; import { handleWebSearch } from "../scripts/runner/websearch"; import { handleApplications } from "../scripts/runner/apps"; import { ResultWidget, ResultWidgetProps } from "../widget/runner/ResultWidget"; -import Wp05 from "gi://Wp"; export let runnerInstance: (Widget.Window|null) = null;