✨ ags(i18n): finally use i18n system!
This commit is contained in:
+18
-11
@@ -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<string, string|object|Binding<string| undefined>>;
|
||||
|
||||
const i18nKeys = {
|
||||
"en_US": en_US,
|
||||
"pt_BR": pt_BR
|
||||
};
|
||||
|
||||
const languages: Array<string> = 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];
|
||||
}
|
||||
|
||||
+33
-5
@@ -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;
|
||||
|
||||
+34
-5
@@ -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;
|
||||
|
||||
@@ -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<string | undefined>;
|
||||
@@ -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,
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
import { astalify, Gtk } from "astal/gtk3";
|
||||
|
||||
// TODO
|
||||
export class FlowBox extends astalify(Gtk.FlowBox) {}
|
||||
@@ -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)
|
||||
]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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<string | undefined>;
|
||||
@@ -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; }"
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user