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 @@
-

Theme

-

Choose your preferred colour scheme.

+

{{l("theme_label")}}

+

{{l("theme_desc")}}

- + +
+
+
+

{{l("language_label")}}

+

{{l("language_desc")}}

+
+ +
- +
- + \ No newline at end of file -- cgit v1.2.3