✨ 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 en_US from "./lang/en_US";
|
||||||
import pt_BR from "./lang/pt_BR";
|
import pt_BR from "./lang/pt_BR";
|
||||||
|
|
||||||
import { GLib } from "astal";
|
|
||||||
|
export type i18nStruct = Record<string, string|object|Binding<string| undefined>>;
|
||||||
|
|
||||||
const i18nKeys = {
|
const i18nKeys = {
|
||||||
"en_US": en_US,
|
"en_US": en_US,
|
||||||
"pt_BR": pt_BR
|
"pt_BR": pt_BR
|
||||||
};
|
};
|
||||||
|
|
||||||
const languages: Array<string> = Object.keys(i18nKeys);
|
const languages: Array<string> = Object.keys(i18nKeys);
|
||||||
|
|
||||||
const defaultLanguage: string = languages[0];
|
|
||||||
let language: string = getSystemLanguage();
|
let language: string = getSystemLanguage();
|
||||||
|
|
||||||
export function getSystemLanguage(): string {
|
export function getSystemLanguage(): string {
|
||||||
const sysLanguage: (string|null|undefined) = GLib.getenv("LANG") || GLib.getenv("LANGUAGE");
|
const sysLanguage: (string|null|undefined) = GLib.getenv("LANG") || GLib.getenv("LANGUAGE");
|
||||||
|
|
||||||
if(!sysLanguage) {
|
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");
|
console.log("[TIP] Please set the LANG or LANGUAGE environment variable");
|
||||||
|
|
||||||
return "en_US";
|
return languages[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
return sysLanguage.split('.')[0];
|
return sysLanguage.split('.')[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setLanguage(lang: keyof typeof i18nKeys): string {
|
export function setLanguage(lang: string): string {
|
||||||
languages.map((cur: string) => {
|
languages.map((cur: string) => {
|
||||||
if(cur === lang) {
|
if(cur === lang) {
|
||||||
language = lang;
|
language = lang;
|
||||||
@@ -42,12 +41,20 @@ export function setLanguage(lang: keyof typeof i18nKeys): string {
|
|||||||
|
|
||||||
export function tr(key: string): string {
|
export function tr(key: string): string {
|
||||||
let result = i18nKeys[language as keyof typeof i18nKeys],
|
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;
|
result = result[keyString as keyof typeof result] as never;
|
||||||
defResult = defResult[keyString as keyof typeof defResult] 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 {
|
export default {
|
||||||
"language": "English (United States)",
|
language: "English (United States)",
|
||||||
"bar": {
|
bar: {
|
||||||
"logo": {
|
apps: {
|
||||||
"tooltip": "Applications"
|
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 {
|
export default {
|
||||||
"language": "Português (Brasil)",
|
language: "Português (Brasil)",
|
||||||
"bar": {
|
bar: {
|
||||||
"logo": {
|
apps: {
|
||||||
"tooltip": "Aplicativos"
|
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 { PopupWindow, PopupWindowProps } from "./PopupWindow";
|
||||||
import { Astal, Gtk, Widget } from "astal/gtk3";
|
import { Astal, Gtk, Widget } from "astal/gtk3";
|
||||||
import { Separator } from "./Separator";
|
import { Separator } from "./Separator";
|
||||||
|
import { tr } from "../i18n/intl";
|
||||||
|
|
||||||
export type AskPopupProps = {
|
export type AskPopupProps = {
|
||||||
title?: string | Binding<string | undefined>;
|
title?: string | Binding<string | undefined>;
|
||||||
@@ -22,7 +23,7 @@ export function AskPopup(props: AskPopupProps) {
|
|||||||
new Widget.Button({
|
new Widget.Button({
|
||||||
className: "cancel",
|
className: "cancel",
|
||||||
hexpand: true,
|
hexpand: true,
|
||||||
label: props.cancelText || "Cancel",
|
label: props.cancelText || tr("ask_popup.options.cancel") || "Cancel",
|
||||||
onClick: (_) => {
|
onClick: (_) => {
|
||||||
window.destroy();
|
window.destroy();
|
||||||
props.onCancel && props.onCancel();
|
props.onCancel && props.onCancel();
|
||||||
@@ -31,7 +32,7 @@ export function AskPopup(props: AskPopupProps) {
|
|||||||
new Widget.Button({
|
new Widget.Button({
|
||||||
className: "accept",
|
className: "accept",
|
||||||
hexpand: true,
|
hexpand: true,
|
||||||
label: props.acceptText || "Ok",
|
label: props.acceptText || tr("ask_popup.options.accept") || "Ok",
|
||||||
onClick: (_) => {
|
onClick: (_) => {
|
||||||
window.destroy();
|
window.destroy();
|
||||||
props.onAccept && props.onAccept();
|
props.onAccept && props.onAccept();
|
||||||
@@ -57,7 +58,7 @@ export function AskPopup(props: AskPopupProps) {
|
|||||||
new Widget.Label({
|
new Widget.Label({
|
||||||
className: "title",
|
className: "title",
|
||||||
visible: Boolean(props.title),
|
visible: Boolean(props.title),
|
||||||
label: props.title || ""
|
label: props.title || tr("ask_popup.title") || "Question"
|
||||||
} as Widget.LabelProps),
|
} as Widget.LabelProps),
|
||||||
Separator({
|
Separator({
|
||||||
alpha: .2,
|
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 { Astal, Gtk, Widget } from "astal/gtk3";
|
||||||
import AstalNotifd from "gi://AstalNotifd";
|
import AstalNotifd from "gi://AstalNotifd";
|
||||||
import { Separator } from "./Separator";
|
import { Separator } from "./Separator";
|
||||||
|
import Pango from "gi://Pango";
|
||||||
|
|
||||||
export function getUrgencyString(notif: AstalNotifd.Notification) {
|
export function getUrgencyString(notif: AstalNotifd.Notification) {
|
||||||
switch(notif.urgency) {
|
switch(notif.urgency) {
|
||||||
@@ -78,6 +79,7 @@ export function NotificationWidget(notification: AstalNotifd.Notification|number
|
|||||||
new Widget.Box({
|
new Widget.Box({
|
||||||
className: "text",
|
className: "text",
|
||||||
orientation: Gtk.Orientation.VERTICAL,
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
|
expand: true,
|
||||||
children: [
|
children: [
|
||||||
new Widget.Label({
|
new Widget.Label({
|
||||||
className: "summary",
|
className: "summary",
|
||||||
@@ -89,9 +91,10 @@ export function NotificationWidget(notification: AstalNotifd.Notification|number
|
|||||||
new Widget.Label({
|
new Widget.Label({
|
||||||
className: "body",
|
className: "body",
|
||||||
useMarkup: true,
|
useMarkup: true,
|
||||||
xalign: 0,
|
halign: Gtk.Align.START,
|
||||||
expand: true,
|
truncate: false,
|
||||||
wrap: true,
|
wrap: true,
|
||||||
|
wrapMode: Pango.WrapMode.WORD,
|
||||||
label: notification.body
|
label: notification.body
|
||||||
} as Widget.LabelProps)
|
} as Widget.LabelProps)
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Gtk, Widget } from "astal/gtk3";
|
import { Gtk, Widget } from "astal/gtk3";
|
||||||
import AstalHyprland from "gi://AstalHyprland";
|
import AstalHyprland from "gi://AstalHyprland";
|
||||||
|
import { trGet } from "../../i18n/intl";
|
||||||
|
|
||||||
export function Logo(): Gtk.Widget {
|
export function Logo(): Gtk.Widget {
|
||||||
return new Widget.EventBox({
|
return new Widget.EventBox({
|
||||||
@@ -8,6 +9,7 @@ export function Logo(): Gtk.Widget {
|
|||||||
child: new Widget.Box({
|
child: new Widget.Box({
|
||||||
child: new Widget.Label({
|
child: new Widget.Label({
|
||||||
className: "nf",
|
className: "nf",
|
||||||
|
tooltipText: trGet()["bar"]["apps"]["tooltip"],
|
||||||
label: ""
|
label: ""
|
||||||
} as Widget.LabelProps)
|
} as Widget.LabelProps)
|
||||||
} as Widget.BoxProps)
|
} as Widget.BoxProps)
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ import { bind, execAsync, Variable } from "astal";
|
|||||||
import { Tile, TileProps } from "./Tile";
|
import { Tile, TileProps } from "./Tile";
|
||||||
import AstalNetwork from "gi://AstalNetwork";
|
import AstalNetwork from "gi://AstalNetwork";
|
||||||
import { Widget } from "astal/gtk3";
|
import { Widget } from "astal/gtk3";
|
||||||
import { showPages, togglePage } from "../Pages";
|
import { togglePage } from "../Pages";
|
||||||
import { PageNetwork } from "../pages/Network";
|
import { PageNetwork } from "../pages/Network";
|
||||||
|
import { tr } from "../../../i18n/intl";
|
||||||
|
|
||||||
export const TileNetwork = new Widget.Box({
|
export const TileNetwork = new Widget.Box({
|
||||||
child: Variable.derive([
|
child: Variable.derive([
|
||||||
@@ -14,18 +15,18 @@ export const TileNetwork = new Widget.Box({
|
|||||||
(primary: AstalNetwork.Primary, wired: AstalNetwork.Wired, wifi: AstalNetwork.Wifi) => {
|
(primary: AstalNetwork.Primary, wired: AstalNetwork.Wired, wifi: AstalNetwork.Wifi) => {
|
||||||
if(primary === AstalNetwork.Primary.WIFI) {
|
if(primary === AstalNetwork.Primary.WIFI) {
|
||||||
return Tile({
|
return Tile({
|
||||||
title: "Wireless",
|
title: tr("control_center.tiles.network.wireless") || "Wireless",
|
||||||
description: Variable.derive(
|
description: Variable.derive(
|
||||||
[ bind(wifi, "ssid"), bind(wifi, "internet") ],
|
[ bind(wifi, "ssid"), bind(wifi, "internet") ],
|
||||||
(ssid: string, internet: AstalNetwork.Internet) =>
|
(ssid: string, internet: AstalNetwork.Internet) =>
|
||||||
ssid ? ssid : (() => {
|
ssid ? ssid : (() => {
|
||||||
switch(internet) {
|
switch(internet) {
|
||||||
case AstalNetwork.Internet.CONNECTED:
|
case AstalNetwork.Internet.CONNECTED:
|
||||||
return "Connected";
|
return tr("control_center.tiles.network.connected") || "Connected";
|
||||||
case AstalNetwork.Internet.DISCONNECTED:
|
case AstalNetwork.Internet.DISCONNECTED:
|
||||||
return "Disconnected";
|
return tr("control_center.tiles.network.disconnected") || "Disconnected";
|
||||||
case AstalNetwork.Internet.CONNECTING:
|
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) {
|
} else if(primary === AstalNetwork.Primary.WIRED) {
|
||||||
return Tile({
|
return Tile({
|
||||||
title: "Wired",
|
title: tr("control_center.tiles.network.wired") || "Wired",
|
||||||
description: bind(wired, "internet").as((internet: AstalNetwork.Internet) => {
|
description: bind(wired, "internet").as((internet: AstalNetwork.Internet) => {
|
||||||
switch(internet) {
|
switch(internet) {
|
||||||
case AstalNetwork.Internet.CONNECTED:
|
case AstalNetwork.Internet.CONNECTED:
|
||||||
return "Connected";
|
return tr("control_center.tiles.network.connected") || "Connected";
|
||||||
case AstalNetwork.Internet.DISCONNECTED:
|
case AstalNetwork.Internet.DISCONNECTED:
|
||||||
return "Disconnected";
|
return tr("control_center.tiles.network.disconnected") || "Disconnected";
|
||||||
case AstalNetwork.Internet.CONNECTING:
|
case AstalNetwork.Internet.CONNECTING:
|
||||||
return "Connecting...";
|
return tr("control_center.tiles.network.connecting") + "..." || "Connecting...";
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
onToggledOn: () => execAsync("nmcli n on"),
|
onToggledOn: () => execAsync("nmcli n on"),
|
||||||
@@ -72,8 +73,8 @@ export const TileNetwork = new Widget.Box({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Tile({
|
return Tile({
|
||||||
title: "Network",
|
title: tr("control_center.tiles.network.network") || "Network",
|
||||||
description: "Disconnected",
|
description: tr("control_center.tiles.network.disconnected") || "Disconnected",
|
||||||
onToggledOn: () => execAsync("nmcli n on"),
|
onToggledOn: () => execAsync("nmcli n on"),
|
||||||
onToggledOff: () => execAsync("nmcli n off"),
|
onToggledOff: () => execAsync("nmcli n off"),
|
||||||
onClickMore: () => togglePage(PageNetwork),
|
onClickMore: () => togglePage(PageNetwork),
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import { Tile, TileProps } from "./Tile";
|
import { Tile, TileProps } from "./Tile";
|
||||||
import { Recording } from "../../../scripts/recording";
|
import { Recording } from "../../../scripts/recording";
|
||||||
import { bind } from "astal";
|
import { bind } from "astal";
|
||||||
|
import { tr } from "../../../i18n/intl";
|
||||||
|
|
||||||
export const TileRecording = Tile({
|
export const TileRecording = Tile({
|
||||||
title: "Screen Recording",
|
title: tr("control_center.tiles.recording.title") || "Screen Recording",
|
||||||
description: bind(Recording.getDefault(), "recording").as(
|
description: bind(Recording.getDefault(), "recording").as(
|
||||||
(isRecording: boolean) => isRecording ?
|
(isRecording: boolean) => isRecording ?
|
||||||
"Recording {time}"
|
"Recording {time}"
|
||||||
: "Start a Screen Record"
|
: tr("control_center.tiles.recording.disabled_description") || "Start recording"
|
||||||
),
|
),
|
||||||
icon: "",
|
icon: "",
|
||||||
onToggledOff: () => Recording.getDefault().stopRecording(),
|
onToggledOff: () => Recording.getDefault().stopRecording(),
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Binding, Variable } from "astal";
|
import { Binding, Variable } from "astal";
|
||||||
import { Gtk, Widget } from "astal/gtk3";
|
import { Gtk, Widget } from "astal/gtk3";
|
||||||
|
import { tr } from "../../../i18n/intl";
|
||||||
|
|
||||||
export type TileProps = {
|
export type TileProps = {
|
||||||
className?: string | Binding<string | undefined>;
|
className?: string | Binding<string | undefined>;
|
||||||
@@ -99,6 +100,7 @@ export function Tile(props: TileProps): Widget.EventBox {
|
|||||||
className: "more icon",
|
className: "more icon",
|
||||||
visible: props.onClickMore !== undefined,
|
visible: props.onClickMore !== undefined,
|
||||||
halign: Gtk.Align.END,
|
halign: Gtk.Align.END,
|
||||||
|
tooltipText: tr("control_center.tiles.more") || "More",
|
||||||
image: new Widget.Icon({
|
image: new Widget.Icon({
|
||||||
icon: "go-next-symbolic",
|
icon: "go-next-symbolic",
|
||||||
css: "icon { font-size: 16px; }"
|
css: "icon { font-size: 16px; }"
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { handleShell } from "../scripts/runner/shell";
|
|||||||
import { handleWebSearch } from "../scripts/runner/websearch";
|
import { handleWebSearch } from "../scripts/runner/websearch";
|
||||||
import { handleApplications } from "../scripts/runner/apps";
|
import { handleApplications } from "../scripts/runner/apps";
|
||||||
import { ResultWidget, ResultWidgetProps } from "../widget/runner/ResultWidget";
|
import { ResultWidget, ResultWidgetProps } from "../widget/runner/ResultWidget";
|
||||||
import Wp05 from "gi://Wp";
|
|
||||||
|
|
||||||
export let runnerInstance: (Widget.Window|null) = null;
|
export let runnerInstance: (Widget.Window|null) = null;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user