From c41ab84738ddfc71d6062e0d173afa33ac2c35a6 Mon Sep 17 00:00:00 2001
From: frosty
Date: Wed, 1 Apr 2026 00:37:15 +0300
Subject: feat: begin working on localisation
---
locales/ca_ca.ini | 29 ++++++++++++++
locales/en_uk.ini | 29 ++++++++++++++
locales/en_us.ini | 29 ++++++++++++++
src/Main.c | 8 ++++
src/Routes/Home.c | 4 ++
src/Routes/Images.c | 5 +++
src/Routes/Search.c | 4 ++
src/Routes/Settings.c | 24 +++++++++++-
src/Routes/SettingsSave.c | 6 +++
src/Utility/Utility.c | 9 +++++
src/Utility/Utility.h | 3 ++
static/main.css | 98 ++++++++++++++++++++++++++++++++++++-----------
templates/home.html | 10 ++---
templates/images.html | 16 ++++----
templates/results.html | 20 +++++-----
templates/settings.html | 44 +++++++++++++--------
16 files changed, 275 insertions(+), 63 deletions(-)
create mode 100644 locales/ca_ca.ini
create mode 100644 locales/en_uk.ini
create mode 100644 locales/en_us.ini
diff --git a/locales/ca_ca.ini b/locales/ca_ca.ini
new file mode 100644
index 0000000..a685037
--- /dev/null
+++ b/locales/ca_ca.ini
@@ -0,0 +1,29 @@
+[Meta]
+Id = "ca_ca"
+Name = "Cat (Demo)"
+Direction = "ltr"
+
+[Keys]
+search_placeholder = "meow"
+search_button = "meow"
+surprise_me_button = "meow"
+all_tab = "meow"
+images_tab = "meow"
+settings_tab = "meow"
+settings_title = "meow"
+theme_label = "meow"
+theme_desc = "meow"
+theme_system = "meow"
+theme_light = "meow"
+theme_dark = "meow"
+language_label = "meow"
+display_language_label = "meow"
+language_desc = "meow"
+save_settings_button = "meow"
+no_results = "meow"
+error_images = "meow"
+rate_limit = "meow"
+read_more = "meow"
+view_cached = "meow"
+view_image = "meow"
+visit_site = "meow"
diff --git a/locales/en_uk.ini b/locales/en_uk.ini
new file mode 100644
index 0000000..84a7d8b
--- /dev/null
+++ b/locales/en_uk.ini
@@ -0,0 +1,29 @@
+[Meta]
+Id = "en_uk"
+Name = "English (Traditional)"
+Direction = "ltr"
+
+[Keys]
+search_placeholder = "Search the web..."
+search_button = "Search"
+surprise_me_button = "Surprise me"
+all_tab = "All"
+images_tab = "Images"
+settings_tab = "Settings"
+settings_title = "Settings"
+theme_label = "Appearance"
+theme_desc = "Choose your preferred colour scheme."
+theme_system = "System"
+theme_light = "Light"
+theme_dark = "Dark"
+language_label = "Language"
+display_language_label = "Display Language"
+language_desc = "Choose your preferred language."
+save_settings_button = "Save Settings"
+no_results = "No results found"
+error_images = "Error fetching images"
+rate_limit = "Slow down! Too many searches from you!"
+read_more = "Read More"
+view_cached = "Cached"
+view_image = "Image"
+visit_site = "Site"
diff --git a/locales/en_us.ini b/locales/en_us.ini
new file mode 100644
index 0000000..db9b3d2
--- /dev/null
+++ b/locales/en_us.ini
@@ -0,0 +1,29 @@
+[Meta]
+Id = "en_us"
+Name = "English (Simplified)"
+Direction = "ltr"
+
+[Keys]
+search_placeholder = "Search the web..."
+search_button = "Search"
+surprise_me_button = "Surprise me"
+all_tab = "All"
+images_tab = "Images"
+settings_tab = "Settings"
+settings_title = "Settings"
+theme_label = "Appearance"
+theme_desc = "Choose your preferred color scheme."
+theme_system = "System"
+theme_light = "Light"
+theme_dark = "Dark"
+language_label = "Language"
+display_language_label = "Display Language"
+language_desc = "Choose your preferred language."
+save_settings_button = "Save Settings"
+no_results = "No results found"
+error_images = "Error fetching images"
+rate_limit = "Slow down! Too many searches from you!"
+read_more = "Read More"
+view_cached = "Cached"
+view_image = "Image"
+visit_site = "Site"
diff --git a/src/Main.c b/src/Main.c
index c3a607a..988d0b0 100644
--- a/src/Main.c
+++ b/src/Main.c
@@ -67,6 +67,13 @@ int main() {
global_config = cfg;
+ int loaded = beaker_load_locales();
+ if (loaded > 0) {
+ fprintf(stderr, "[INFO] Loaded %d locales\n", loaded);
+ } else {
+ fprintf(stderr, "[WARN] No locales loaded (make sure to run from omnisearch directory)\n");
+ }
+
apply_engines_config(cfg.engines);
if (cache_init(cfg.cache_dir) != 0) {
@@ -119,6 +126,7 @@ int main() {
curl_global_cleanup();
xmlCleanupParser();
+ beaker_free_locales();
free_proxy_list();
cache_shutdown();
return EXIT_SUCCESS;
diff --git a/src/Routes/Home.c b/src/Routes/Home.c
index c857663..48edfd9 100644
--- a/src/Routes/Home.c
+++ b/src/Routes/Home.c
@@ -1,19 +1,23 @@
#include "Home.h"
#include "../Utility/Utility.h"
+#include
#include
int home_handler(UrlParams *params) {
(void)params;
char *theme = get_theme("");
+ char *locale = get_locale("en_uk");
TemplateContext ctx = new_context();
context_set(&ctx, "theme", theme);
+ beaker_set_locale(&ctx, locale);
char *rendered_html = render_template("home.html", &ctx);
send_response(rendered_html);
free(rendered_html);
free_context(&ctx);
free(theme);
+ free(locale);
return 0;
}
diff --git a/src/Routes/Images.c b/src/Routes/Images.c
index 98fd3f4..636f071 100644
--- a/src/Routes/Images.c
+++ b/src/Routes/Images.c
@@ -5,6 +5,7 @@
#include "../Utility/Unescape.h"
#include "../Utility/Utility.h"
#include "Config.h"
+#include
static char *build_images_request_cache_key(const char *query, int page,
const char *client_key) {
@@ -46,6 +47,10 @@ int images_handler(UrlParams *params) {
context_set(&ctx, "theme", theme);
free(theme);
+ char *locale = get_locale("en_uk");
+ beaker_set_locale(&ctx, locale);
+ free(locale);
+
context_set(&ctx, "page", page_str);
context_set(&ctx, "prev_page", prev_str);
context_set(&ctx, "next_page", next_str);
diff --git a/src/Routes/Search.c b/src/Routes/Search.c
index 170b488..c5b3ec0 100644
--- a/src/Routes/Search.c
+++ b/src/Routes/Search.c
@@ -419,6 +419,10 @@ int results_handler(UrlParams *params) {
context_set(&ctx, "theme", theme);
free(theme);
+ char *locale = get_locale("en_uk");
+ beaker_set_locale(&ctx, locale);
+ free(locale);
+
char page_str[16];
snprintf(page_str, sizeof(page_str), "%d", page);
context_set(&ctx, "page", page_str);
diff --git a/src/Routes/Settings.c b/src/Routes/Settings.c
index 05edc56..cfadd09 100644
--- a/src/Routes/Settings.c
+++ b/src/Routes/Settings.c
@@ -1,5 +1,6 @@
#include "Settings.h"
#include "../Utility/Utility.h"
+#include
#include
#include
@@ -9,21 +10,42 @@ int settings_handler(UrlParams *params) {
for (int i = 0; i < params->count; i++) {
if (strcmp(params->params[i].key, "q") == 0) {
query = params->params[i].value;
- break;
}
}
}
char *theme = get_theme("system");
+ char *locale = get_locale("en_uk");
+
+ LocaleInfo locales[32];
+ int locale_count = beaker_get_all_locales(locales, 32);
+
+ char **locale_data[32];
+ int inner_counts[32];
+ for (int i = 0; i < locale_count; i++) {
+ locale_data[i] = malloc(sizeof(char *) * 2);
+ locale_data[i][0] = locales[i].meta.id;
+ locale_data[i][1] = locales[i].meta.name;
+ inner_counts[i] = 2;
+ }
TemplateContext ctx = new_context();
+ beaker_set_locale(&ctx, locale);
context_set(&ctx, "query", query);
context_set(&ctx, "theme", theme);
+ context_set(&ctx, "locale", locale);
+ context_set_array_of_arrays(&ctx, "locales", locale_data, locale_count, inner_counts);
+
+ for (int i = 0; i < locale_count; i++) {
+ free(locale_data[i]);
+ }
+
char *rendered_html = render_template("settings.html", &ctx);
send_response(rendered_html);
free(rendered_html);
free(theme);
+ free(locale);
free_context(&ctx);
return 0;
diff --git a/src/Routes/SettingsSave.c b/src/Routes/SettingsSave.c
index d286507..323fe0d 100644
--- a/src/Routes/SettingsSave.c
+++ b/src/Routes/SettingsSave.c
@@ -4,12 +4,15 @@
int settings_save_handler(UrlParams *params) {
const char *theme = "";
+ const char *locale = "";
const char *query = "";
if (params) {
for (int i = 0; i < params->count; i++) {
if (strcmp(params->params[i].key, "theme") == 0) {
theme = params->params[i].value;
+ } else if (strcmp(params->params[i].key, "locale") == 0) {
+ locale = params->params[i].value;
} else if (strcmp(params->params[i].key, "q") == 0) {
query = params->params[i].value;
}
@@ -19,6 +22,9 @@ int settings_save_handler(UrlParams *params) {
if (strlen(theme) > 0) {
set_cookie("theme", theme, "Fri, 31 Dec 2038 23:59:59 GMT", "/", false, false);
}
+ if (strlen(locale) > 0) {
+ set_cookie("locale", locale, "Fri, 31 Dec 2038 23:59:59 GMT", "/", false, false);
+ }
char redirect_url[512];
snprintf(redirect_url, sizeof(redirect_url), "/settings?q=%s", query);
diff --git a/src/Utility/Utility.c b/src/Utility/Utility.c
index b4ad91d..0d7a28e 100644
--- a/src/Utility/Utility.c
+++ b/src/Utility/Utility.c
@@ -23,3 +23,12 @@ char *get_theme(const char *default_theme) {
free(cookie);
return strdup(default_theme);
}
+
+char *get_locale(const char *default_locale) {
+ char *cookie = get_cookie("locale");
+ if (cookie && beaker_get_locale_meta(cookie) != NULL) {
+ return cookie;
+ }
+ free(cookie);
+ return strdup(default_locale);
+}
diff --git a/src/Utility/Utility.h b/src/Utility/Utility.h
index e67282f..387aae0 100644
--- a/src/Utility/Utility.h
+++ b/src/Utility/Utility.h
@@ -1,7 +1,10 @@
#ifndef UTILITY_H
#define UTILITY_H
+#include
+
int hex_to_int(char c);
char *get_theme(const char *default_theme);
+char *get_locale(const char *default_locale);
#endif
diff --git a/static/main.css b/static/main.css
index a548591..6994ade 100644
--- a/static/main.css
+++ b/static/main.css
@@ -31,7 +31,7 @@ html {
body {
background-color:var(--bg-main);
- background-image:radial-gradient(circle at top right, var(--bg-card) 0%, var(--bg-main) 100%);
+ background-image:radial-gradient(circle at top end, var(--bg-card) 0%, var(--bg-main) 100%);
background-attachment:fixed;
color:var(--text-primary);
font-family:system-ui,-apple-system,sans-serif;
@@ -124,7 +124,7 @@ img[src=""] {
.home-settings-btn {
position:fixed;
top:27px;
- right:60px;
+ inset-inline-end:60px;
width:24px;
height:24px;
background-color:var(--text-primary);
@@ -139,7 +139,7 @@ img[src=""] {
width:24px;
height:24px;
flex-shrink:0;
- margin-left:auto;
+ margin-inline-start:auto;
margin-top:3px;
background-color:var(--text-secondary);
-webkit-mask-image:url('/static/settings.svg');
@@ -154,13 +154,14 @@ img[src=""] {
}
.nav-settings-link {
display:none;
- margin-left:auto;
+ margin-inline-start:auto;
}
header {
display:flex;
align-items:center;
gap:20px;
- padding:15px 60px;
+ padding-block:15px;
+ padding-inline:60px;
border-bottom:1px solid var(--border);
background:var(--bg-main);
width:100%;
@@ -204,7 +205,7 @@ header .logo-link:hover {
box-shadow:0 0 0 4px var(--accent-glow);
}
.nav-tabs {
- padding:0 60px;
+ padding-inline:60px;
border-bottom:1px solid var(--border);
background:var(--bg-main);
width:100%;
@@ -231,7 +232,7 @@ header .logo-link:hover {
border-bottom-color:var(--accent);
}
.nav-right {
- margin-left:auto;
+ margin-inline-start:auto;
}
.image-results-container {
padding:30px 60px;
@@ -335,7 +336,8 @@ header .logo-link:hover {
display:grid;
grid-template-columns:140px minmax(0,700px) 450px;
gap:60px;
- padding:30px 60px;
+ padding-block:30px;
+ padding-inline:60px;
}
.result-header {
display: flex;
@@ -351,7 +353,7 @@ header .logo-link:hover {
background-size: cover;
background-position: center;
position: absolute;
- left: -24px;
+ inset-inline-start: -24px;
}
.url {
color: var(--text-secondary);
@@ -365,7 +367,7 @@ header .logo-link:hover {
.result-favicon {
width: 14px;
height: 14px;
- left: -20px;
+ inset-inline-start: -20px;
}
}
@@ -373,7 +375,7 @@ header .logo-link:hover {
.result-favicon {
width: 12px;
height: 12px;
- left: -16px;
+ inset-inline-start: -16px;
}
}
.results-container {
@@ -540,7 +542,8 @@ header .logo-link:hover {
@media (max-width:1200px) {
.content-layout {
grid-template-columns:1fr;
- padding:20px 30px;
+ padding-block:20px;
+ padding-inline:30px;
gap:20px;
}
header {
@@ -551,7 +554,8 @@ header .logo-link:hover {
max-width:100%;
}
.settings-layout {
- padding:20px 30px;
+ padding-block:20px;
+ padding-inline:30px;
display:flex;
justify-content:center;
}
@@ -559,10 +563,11 @@ header .logo-link:hover {
order:-1;
}
.nav-tabs,.image-results-container {
- padding:0 30px;
+ padding-inline:30px;
}
header {
- padding:15px 30px;
+ padding-block:15px;
+ padding-inline:30px;
}
}
@@ -576,7 +581,8 @@ header .logo-link:hover {
header {
flex-direction:column;
gap:12px;
- padding:12px 16px;
+ padding-block:12px;
+ padding-inline:16px;
text-align:center;
}
h1 {
@@ -592,7 +598,7 @@ header .logo-link:hover {
.nav-tabs {
overflow-x:auto;
-webkit-overflow-scrolling:touch;
- padding:0 16px;
+ padding-inline:16px;
}
.nav-container {
gap:24px;
@@ -603,7 +609,9 @@ header .logo-link:hover {
font-size:0.95rem;
}
.content-layout {
- padding:16px 16px 16px 40px;
+ padding-inline-start:40px;
+ padding-inline-end:16px;
+ padding-block:16px;
gap:16px;
}
.result {
@@ -647,7 +655,7 @@ header .logo-link:hover {
max-width:200px;
}
.image-results-container {
- padding:16px;
+ padding-inline:16px;
}
.pagination {
flex-wrap:wrap;
@@ -692,13 +700,16 @@ header .logo-link:hover {
@media (max-width:600px) {
.content-layout {
- padding:16px 16px 16px 28px;
+ padding-inline-start:28px;
+ padding-inline-end:16px;
+ padding-block:16px;
}
.settings-layout {
- padding:12px 0;
+ padding:0;
}
header {
- padding:12px 12px;
+ padding-inline:12px;
+ padding-block:12px;
}
.search-box {
font-size:0.95rem;
@@ -735,7 +746,9 @@ header .logo-link:hover {
}
.settings-layout {
- padding:30px 60px 30px 260px;
+ padding-block: 30px;
+ padding-inline-start: 260px;
+ padding-inline-end: 60px;
}
.settings-container {
@@ -875,3 +888,42 @@ header .logo-link:hover {
text-align:center;
}
}
+
+[dir="rtl"] {
+ direction: rtl;
+ unicode-bidi: embed;
+}
+
+[dir="rtl"] header {
+ flex-direction: row-reverse;
+ direction: ltr;
+}
+
+[dir="rtl"] .nav-container {
+ flex-direction: row-reverse;
+ direction: ltr;
+}
+
+[dir="rtl"] .search-box {
+ text-align: right;
+ direction: rtl;
+}
+
+[dir="rtl"] .url {
+ text-align: end;
+}
+
+[dir="rtl"] .nav-settings-icon {
+ margin-inline-start: unset;
+ margin-inline-end: auto;
+}
+
+[dir="rtl"] .settings-actions .btn-primary {
+ margin-inline-end: auto;
+}
+
+@media (max-width: 768px) {
+ [dir="rtl"] header {
+ flex-direction: column;
+ }
+}
diff --git a/templates/home.html b/templates/home.html
index ae00824..8bec45b 100644
--- a/templates/home.html
+++ b/templates/home.html
@@ -1,5 +1,5 @@
-
+
@@ -24,21 +24,21 @@
-
+
diff --git a/templates/images.html b/templates/images.html
index f2b5222..f4522aa 100644
--- a/templates/images.html
+++ b/templates/images.html
@@ -1,5 +1,5 @@
-
+
@@ -19,21 +19,21 @@
OmniSearch
-
+
@@ -46,10 +46,10 @@
diff --git a/templates/results.html b/templates/results.html
index 9dec20c..4ce7496 100644
--- a/templates/results.html
+++ b/templates/results.html
@@ -1,5 +1,5 @@
-
+
@@ -23,21 +23,21 @@
-
+
@@ -88,7 +88,7 @@
{{result[3]}}
- View Cached
+ {{l("view_cached")}}
{{endfor}}
@@ -117,9 +117,9 @@
diff --git a/templates/settings.html b/templates/settings.html
index 8b79033..9d8854b 100644
--- a/templates/settings.html
+++ b/templates/settings.html
@@ -1,11 +1,11 @@
-
+
- OmniSearch - Settings
+ OmniSearch - {{l("settings_title")}}
{{if theme == "light"}}{{endif}}
@@ -23,27 +23,27 @@
{{if query != ""}}
{{endif}}
{{if query != ""}}
-
+
{{else}}
-
+
{{endif}}
{{if query != ""}}
@@ -53,23 +53,35 @@
-
+
\ No newline at end of file
--
cgit v1.2.3