feat: internationalize the app interface
This commit is contained in:
		| @@ -4,11 +4,17 @@ use dioxus::dioxus_core::Element; | ||||
| use dioxus::prelude::*; | ||||
| use dioxus_query::prelude::{use_init_query_client}; | ||||
| use crate::query::{QueryErrors, QueryKey, QueryValue}; | ||||
| use dioxus_sdk::i18n::{use_init_i18n}; | ||||
| use crate::internationalization::get_languages; | ||||
| use crate::server::internationalization::get_language_identifier; | ||||
|  | ||||
| #[component] | ||||
| pub(crate) fn App() -> Element { | ||||
|     use_init_query_client::<QueryValue, QueryErrors, QueryKey>(); | ||||
|      | ||||
|     let language_identifier = use_server_future(get_language_identifier)?.unwrap().unwrap(); | ||||
|     use_init_i18n(language_identifier.clone(), language_identifier, get_languages); | ||||
|      | ||||
|     rsx! { | ||||
|         div { | ||||
|             class: "min-h-screen text-zinc-200 bg-zinc-800 pt-4 pb-36", | ||||
|   | ||||
| @@ -1,13 +1,16 @@ | ||||
| use crate::components::task_list::TaskList; | ||||
| use crate::internationalization::LocaleFromLanguageIdentifier; | ||||
| use crate::models::category::Category; | ||||
| use chrono::{Datelike, Local, Locale}; | ||||
| use crate::models::task::TaskWithSubtasks; | ||||
| use crate::query::tasks::use_tasks_with_subtasks_in_category_query; | ||||
| use crate::query::QueryValue; | ||||
| use chrono::{Datelike, Local}; | ||||
| use dioxus::core_macro::rsx; | ||||
| use dioxus::dioxus_core::Element; | ||||
| use dioxus::prelude::*; | ||||
| use dioxus_query::prelude::QueryResult; | ||||
| use crate::components::task_list::TaskList; | ||||
| use crate::query::QueryValue; | ||||
| use crate::query::tasks::use_tasks_with_subtasks_in_category_query; | ||||
| use crate::models::task::{TaskWithSubtasks}; | ||||
| use dioxus_sdk::i18n::use_i18; | ||||
| use dioxus_sdk::translate; | ||||
|  | ||||
| const CALENDAR_LENGTH_DAYS: usize = 366 * 3; | ||||
|  | ||||
| @@ -20,6 +23,8 @@ pub(crate) fn CategoryCalendarPage() -> Element { | ||||
|     }); | ||||
|     let tasks_query_result = tasks.result(); | ||||
|  | ||||
|     let i18 = use_i18(); | ||||
|  | ||||
|     rsx! { | ||||
|         match tasks_query_result.value() { | ||||
|             QueryResult::Ok(QueryValue::TasksWithSubtasks(tasks)) | ||||
| @@ -37,14 +42,17 @@ pub(crate) fn CategoryCalendarPage() -> Element { | ||||
|                                     div { | ||||
|                                         class: "pt-1", | ||||
|                                         { | ||||
|                                             date_current | ||||
|                                             .format_localized( | ||||
|                                                 format!( | ||||
|                                                     "%A %-d. %B{}",  | ||||
|                                                     if date_current.year() != today_date.year() | ||||
|                                                     {" %Y"} else {""} | ||||
|                                             date_current.format_localized(translate!( | ||||
|                                                     i18, | ||||
|                                                     if date_current.year() == Local::now().year() { | ||||
|                                                         "formats.date_weekday_format" | ||||
|                                                     } else { | ||||
|                                                         "formats.date_weekday_year_format" | ||||
|                                                     } | ||||
|                                                 ).as_str(), | ||||
|                                                 Locale::en_US | ||||
|                                                 LocaleFromLanguageIdentifier::from( | ||||
|                                                     &(i18.selected_language)() | ||||
|                                                 ).into() | ||||
|                                             ) | ||||
|                                             .to_string() | ||||
|                                         } | ||||
|   | ||||
| @@ -1,12 +1,16 @@ | ||||
| use crate::components::task_list::TaskList; | ||||
| use crate::components::task_list_item::TaskListItem; | ||||
| use crate::internationalization::LocaleFromLanguageIdentifier; | ||||
| use crate::models::category::Category; | ||||
| use crate::models::task::TaskWithSubtasks; | ||||
| use crate::query::tasks::{use_tasks_with_subtasks_in_category_query}; | ||||
| use crate::query::tasks::use_tasks_with_subtasks_in_category_query; | ||||
| use crate::query::QueryValue; | ||||
| use chrono::{Local, Locale}; | ||||
| use chrono::Local; | ||||
| use dioxus::prelude::*; | ||||
| use dioxus_query::prelude::QueryResult; | ||||
| use crate::components::task_list_item::TaskListItem; | ||||
| use dioxus_sdk::i18n::use_i18; | ||||
| use dioxus_sdk::translate; | ||||
| use voca_rs::Voca; | ||||
|  | ||||
| #[component] | ||||
| pub(crate) fn CategoryTodayPage() -> Element { | ||||
| @@ -22,6 +26,8 @@ pub(crate) fn CategoryTodayPage() -> Element { | ||||
|     let long_term_tasks_query = use_tasks_with_subtasks_in_category_query(Category::LongTerm); | ||||
|     let long_term_tasks_query_result = long_term_tasks_query.result(); | ||||
|  | ||||
|     let i18 = use_i18(); | ||||
|  | ||||
|     rsx! { | ||||
|         div { | ||||
|             class: "pt-4 flex flex-col gap-8", | ||||
| @@ -40,7 +46,7 @@ pub(crate) fn CategoryTodayPage() -> Element { | ||||
|                                 } | ||||
|                                 div { | ||||
|                                     class: "mt-1", | ||||
|                                     "Long-term" | ||||
|                                     {translate!(i18, "long_term")._upper_first()} | ||||
|                                 } | ||||
|                             } | ||||
|                             div { | ||||
| @@ -103,7 +109,7 @@ pub(crate) fn CategoryTodayPage() -> Element { | ||||
|                                     } | ||||
|                                     div { | ||||
|                                         class: "mt-1", | ||||
|                                         "Overdue" | ||||
|                                         {translate!(i18, "overdue")._upper_first()} | ||||
|                                     } | ||||
|                                 } | ||||
|                                 TaskList { | ||||
| @@ -122,9 +128,23 @@ pub(crate) fn CategoryTodayPage() -> Element { | ||||
|                                 div { | ||||
|                                     class: "mt-1", | ||||
|                                     { | ||||
|                                         today_date | ||||
|                                         .format_localized("Today, %A %-d. %B", Locale::en_US) | ||||
|                                         .to_string() | ||||
|                                         let format = translate!(i18, "formats.date_weekday_format"); | ||||
|                                         let today_date = today_date.format_localized( | ||||
|                                             format.as_str(), | ||||
|                                             LocaleFromLanguageIdentifier::from( | ||||
|                                                 &(i18.selected_language)() | ||||
|                                             ).into() | ||||
|                                         ).to_string(); | ||||
|                                         format!( | ||||
|                                             "{} – {}", | ||||
|                                             translate!(i18, "today")._upper_first(), | ||||
|                                             if translate!(i18, "formats.weekday_lowercase_first") | ||||
|                                                 .parse().unwrap() { | ||||
|                                                 today_date._lower_first() | ||||
|                                             } else { | ||||
|                                                 today_date | ||||
|                                             } | ||||
|                                         ) | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| use crate::components::category_input::CategoryInput; | ||||
| use crate::components::reoccurrence_input::ReoccurrenceIntervalInput; | ||||
| use crate::components::subtasks_form::SubtasksForm; | ||||
| use crate::models::category::{CalendarTime, Category, Reoccurrence}; | ||||
| use crate::models::task::NewTask; | ||||
| use crate::models::task::Task; | ||||
| @@ -7,12 +8,14 @@ use crate::query::{QueryErrors, QueryKey, QueryValue}; | ||||
| use crate::route::Route; | ||||
| use crate::server::projects::get_projects; | ||||
| use crate::server::tasks::{create_task, delete_task, edit_task}; | ||||
| use chrono::{Duration}; | ||||
| use chrono::Duration; | ||||
| use dioxus::core_macro::{component, rsx}; | ||||
| use dioxus::dioxus_core::Element; | ||||
| use dioxus::prelude::*; | ||||
| use dioxus_query::prelude::use_query_client; | ||||
| use crate::components::subtasks_form::SubtasksForm; | ||||
| use dioxus_sdk::i18n::use_i18; | ||||
| use dioxus_sdk::translate; | ||||
| use voca_rs::Voca; | ||||
|  | ||||
| const REMINDER_OFFSETS: [Option<Duration>; 17] = [ | ||||
|     None, | ||||
| @@ -79,6 +82,8 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<() | ||||
|     let query_client = use_query_client::<QueryValue, QueryErrors, QueryKey>(); | ||||
|     let task_for_submit = task.clone(); | ||||
|  | ||||
|     let i18 = use_i18(); | ||||
|  | ||||
|     rsx! { | ||||
|         div { | ||||
|             class: "p-4 flex flex-col gap-4", | ||||
| @@ -172,7 +177,7 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<() | ||||
|                         id: "input_project", | ||||
|                         option { | ||||
|                             value: 0, | ||||
|                             "None" | ||||
|                             {translate!(i18, "none")} | ||||
|                         }, | ||||
|                         for project in projects { | ||||
|                             option { | ||||
| @@ -330,13 +335,14 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<() | ||||
|                                 label { | ||||
|                                     r#for: "category_calendar_reminder_offset_index", | ||||
|                                     class: "pr-3 min-w-16 text-right", | ||||
|                                     {REMINDER_OFFSETS[category_calendar_reminder_offset_index()].map( | ||||
|                                         |offset| if offset.num_hours() < 1 { | ||||
|                                             format!("{} min", offset.num_minutes()) | ||||
|                                         } else { | ||||
|                                             format!("{} h", offset.num_hours()) | ||||
|                                         } | ||||
|                                     ).unwrap_or_else(|| "none".to_string())} | ||||
|                                     {REMINDER_OFFSETS[category_calendar_reminder_offset_index()] | ||||
|                                         .map( | ||||
|                                             |offset| if offset.num_hours() < 1 { | ||||
|                                                 format!("{} min", offset.num_minutes()) | ||||
|                                             } else { | ||||
|                                                 format!("{} h", offset.num_hours()) | ||||
|                                             } | ||||
|                                         ).unwrap_or_else(|| translate!(i18, "none"))} | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|   | ||||
| @@ -1,12 +1,18 @@ | ||||
| use chrono::{Datelike, Local}; | ||||
| use crate::internationalization::LocaleFromLanguageIdentifier; | ||||
| use crate::models::category::Category; | ||||
| use crate::models::task::TaskWithSubtasks; | ||||
| use chrono::{Datelike, Local}; | ||||
| use dioxus::core_macro::rsx; | ||||
| use dioxus::dioxus_core::Element; | ||||
| use dioxus::prelude::*; | ||||
| use dioxus_sdk::i18n::use_i18; | ||||
| use dioxus_sdk::translate; | ||||
| use voca_rs::Voca; | ||||
|  | ||||
| #[component] | ||||
| pub(crate) fn TaskListItem(task: TaskWithSubtasks) -> Element { | ||||
|     let i18 = use_i18(); | ||||
|  | ||||
|     rsx! { | ||||
|         div { | ||||
|             class: "flex flex-col", | ||||
| @@ -22,11 +28,47 @@ pub(crate) fn TaskListItem(task: TaskWithSubtasks) -> Element { | ||||
|                         i { | ||||
|                             class: "fa-solid fa-bomb" | ||||
|                         }, | ||||
|                         {deadline.format(if deadline.year() == Local::now().year() { | ||||
|                             " %m. %-d." | ||||
|                         } else { | ||||
|                             " %m. %-d. %Y" | ||||
|                         }).to_string()} | ||||
|                         { | ||||
|                             let today_date = Local::now().date_naive(); | ||||
|                             format!( | ||||
|                                 " {}", | ||||
|                                 if deadline == today_date - chrono::Days::new(1) { | ||||
|                                     translate!(i18, "yesterday") | ||||
|                                 } else if deadline == today_date { | ||||
|                                     translate!(i18, "today") | ||||
|                                 } else if deadline == today_date + chrono::Days::new(1) { | ||||
|                                     translate!(i18, "tomorrow") | ||||
|                                 } else if deadline > today_date | ||||
|                                     && deadline <= today_date + chrono::Days::new(7) { | ||||
|                                     let deadline = deadline.format_localized( | ||||
|                                         "%A", | ||||
|                                         LocaleFromLanguageIdentifier::from( | ||||
|                                             &(i18.selected_language)() | ||||
|                                         ).into() | ||||
|                                     ).to_string(); | ||||
|                                     if translate!(i18, "formats.weekday_lowercase_first") | ||||
|                                         .parse().unwrap() { | ||||
|                                         deadline._lower_first() | ||||
|                                     } else { | ||||
|                                         deadline | ||||
|                                     } | ||||
|                                 } else { | ||||
|                                     let format = translate!(i18, | ||||
|                                         if deadline.year() == today_date.year() { | ||||
|                                             "formats.date_format" | ||||
|                                         } else { | ||||
|                                             "formats.date_year_format" | ||||
|                                         } | ||||
|                                     ); | ||||
|                                     deadline.format_localized( | ||||
|                                         format.as_str(), | ||||
|                                         LocaleFromLanguageIdentifier::from( | ||||
|                                             &(i18.selected_language)() | ||||
|                                         ).into() | ||||
|                                     ).to_string() | ||||
|                                 } | ||||
|                             ) | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 if let Category::Calendar { time, .. } = task.task().category() { | ||||
| @@ -36,7 +78,10 @@ pub(crate) fn TaskListItem(task: TaskWithSubtasks) -> Element { | ||||
|                             i { | ||||
|                                 class: "fa-solid fa-clock" | ||||
|                             }, | ||||
|                             {calendar_time.time().format(" %k:%M").to_string()} | ||||
|                             { | ||||
|                                 let format = translate!(i18, "formats.time_format"); | ||||
|                                 format!(" {}",calendar_time.time().format(format.as_str())) | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Matouš Volf
					Matouš Volf