From 64ddaa1239ce5f6606b5fa266bb07dee884016e6 Mon Sep 17 00:00:00 2001 From: Andrii Kurdiumov Date: Sun, 17 Sep 2023 01:57:56 +0600 Subject: [PATCH] Add infrastructure to be able translate REPL This is based on suggestions from #185 I have translation for Ukrainian and Russian, but want to gather feedback on the approach. I think that's it, and no additional strings needed, or that amount would be very small. I have to add dependency on Fable.Browser.Navigator since tha allow account for user preferences. --- paket.dependencies | 11 ++-- paket.lock | 19 ++++++ src/App/ConsolePanel.fs | 4 +- src/App/Helpers.fs | 130 +++++++++++++++++++++++++++++++++++++ src/App/Loader.fs | 8 +-- src/App/Main.fs | 32 ++++----- src/App/Mouse.fs | 5 +- src/App/Sidebar.fs | 14 ++-- src/App/Widgets/About.fs | 2 +- src/App/Widgets/General.fs | 32 ++++----- src/App/Widgets/Options.fs | 28 ++++---- src/App/Widgets/Samples.fs | 2 +- src/App/Widgets/Stats.fs | 4 +- src/App/paket.references | 3 +- 14 files changed, 224 insertions(+), 70 deletions(-) diff --git a/paket.dependencies b/paket.dependencies index eb66114d..5daee55f 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -17,9 +17,10 @@ nuget Feliz prerelease nuget Feliz.Bulma nuget Feliz.Bulma.Tooltip nuget Fable.Browser.Css -nuget Fable.Browser.Dom -nuget Fable.Browser.Event +nuget Fable.Browser.Dom == 2.4.4 +nuget Fable.Browser.Event == 1.4.5 nuget Fable.Browser.MediaQueryList +nuget Fable.Browser.Navigator == 2.0.0 # REPL Lib @@ -32,11 +33,11 @@ nuget Fable.Browser.MediaQueryList #github fulma/Fulma:1e763d852112307370675a0cf692415a53d1993f# github elmish/elmish:v3.x -github fable-compiler/fable-promise:master +github fable-compiler/fable-promise:14eca483d664dce5aebbe50fb92a536a7c1ffe53 github alfonsogarciacaro/Feliz.Engine:main github alfonsogarciacaro/Feliz.Snabbdom:main -github davedawkins/Feliz.Engine.Bulma:main -github davedawkins/Sutil:main +github davedawkins/Feliz.Engine.Bulma:0df54855ac3464a432cd207412ab66e650a87d77 +github davedawkins/Sutil:343bc31867127638a79afede0dcaa97ca56fa264 group netcorebuild source https://www.nuget.org/api/v2 diff --git a/paket.lock b/paket.lock index d9a06a09..f2397e80 100644 --- a/paket.lock +++ b/paket.lock @@ -24,11 +24,26 @@ NUGET Fable.Browser.Gamepad (1.0.3) Fable.Core (>= 3.0) FSharp.Core (>= 4.7.2) + Fable.Browser.Geolocation (1.2) + Fable.Core (>= 3.0) + FSharp.Core (>= 4.7.2) Fable.Browser.MediaQueryList (1.1.5) Fable.Browser.Dom (>= 2.4.4) Fable.Browser.Event (>= 1.4.4) Fable.Core (>= 3.0) FSharp.Core (>= 4.7.2) + Fable.Browser.MediaStream (3.3) + Fable.Browser.Dom (>= 2.11) + Fable.Browser.Event (>= 1.5) + Fable.Core (>= 3.0) + FSharp.Core (>= 4.7.2) + Fable.Browser.Navigator (2.0) + Fable.Browser.Gamepad (>= 1.0.3) + Fable.Browser.Geolocation (>= 1.0.4) + Fable.Browser.MediaStream (>= 3.0.4) + Fable.Browser.Worker (>= 1.0.5) + Fable.Core (>= 3.1.5) + FSharp.Core (>= 4.7.2) Fable.Browser.Svg (2.0.4) Fable.Browser.Dom (>= 2.4.4) Fable.Core (>= 3.0) @@ -37,6 +52,10 @@ NUGET Fable.Browser.Event (>= 1.4.4) Fable.Core (>= 3.0) FSharp.Core (>= 4.7.2) + Fable.Browser.Worker (1.2) + Fable.Browser.Event (>= 1.5) + Fable.Core (>= 3.0) + FSharp.Core (>= 4.7.2) Fable.Core (3.2.8) FSharp.Core (>= 4.7.2) Fable.Elmish (3.1) diff --git a/src/App/ConsolePanel.fs b/src/App/ConsolePanel.fs index 6b160f46..a27961f6 100644 --- a/src/App/ConsolePanel.fs +++ b/src/App/ConsolePanel.fs @@ -52,7 +52,7 @@ let renderShowSeparator = prop.style [ style.justifyContent.center ] - prop.text "Iframe loaded" + prop.text Translations.msg_iframe_loaded ] let renderBody (isExpanded : bool) (logs : Log list) (setConsoleEnd : HTMLElement -> unit) onContainerScroll = @@ -134,7 +134,7 @@ let consolePanel = Html.div [ prop.className "scrollable-panel-header-title" - prop.text "Console" + prop.text Translations.win_header_console ] Html.div [ diff --git a/src/App/Helpers.fs b/src/App/Helpers.fs index df15c663..fa7954a8 100644 --- a/src/App/Helpers.fs +++ b/src/App/Helpers.fs @@ -98,3 +98,133 @@ module Tooltip = |> List.fold (fun (res: string) (oldValue, newValue) -> res.Replace(oldValue, newValue) ) res + +[] +module Translations = + let enTranslations = dict["msg_iframe_loaded", "Iframe loaded"; + "win_header_console", "Console"; + "msg_initializing", "Initializing"; + "msg_repl_name", "Fable REPL"; + "msg_desktop_experience", "For best experience we recommend running the REPL on a desktop"; + "btn_continue", "Continue"; + "msg_gist_description", "Created with Fable REPL"; + "msg_compilation_failed", "Failed to compile"; + "msg_assemblies_load_failed", "Assemblies couldn't be loaded. Some firewalls prevent download of binary files, please check."; + "msg_gist_token_invalid", "An error occured when creating the gist. Is the token valid?"; + "msg_gist_token_missing", "You need to register your GitHub API token before sharing to Gist"; + "msg_compilation_successful", "Compiled successfuly"; + "msg_shareable_url_ready_text", "Copy it from the address bar"; + "msg_shareable_url_ready_title", "Shareable link is ready"; + "msg_load_gist_error", "An error occured when loading the gist"; + "msg_update_url_failed", "An error occured when updating the URL"; + "msg_fatal_error", "Should not happen"; + "msg_live_sample_text", "Live sample"; + "msg_code_text", "Code"; + "msg_problems", "Problems"; + "msg_problems_info", "Problems: "; + "msg_invalid_iframe_error", "`%A` is not a known value for an iframe message"; + "msg_collapse_sidebar", "Collapse sidebar"; + "msg_widget_general", "General"; + "msg_widget_samples", "Samples"; + "msg_widget_options", "Options"; + "msg_widget_statistics", "Statistics"; + "msg_widget_about", "About"; + "msg_found_a_bug", "Found a bug ?"; + "msg_general_compile_run_tooltip", "Compile and run (Alt+Enter)"; + "msg_general_compile_run_text", "Compile and run"; + "msg_general_refresh_sample_tooltip", "Refresh the live sample (without compiling)"; + "msg_general_refresh_sample_text", "Refresh the live sample"; + "msg_general_reset_repl_tooltip", "Reset the REPL, you will lose your current work"; + "msg_general_reset_repl_text", "Click here to reset"; + "msg_general_share_url_tooltip", "Share using the URL"; + "msg_general_share_url_text", "Share using the URL"; + "msg_general_share_gist_tooltip", "Share to Gist"; + "msg_general_share_gist_text", "Share to Gist"; + "msg_reset_confirmation_text", "Please, confirm to reset"; + "btn_confirm", "Confirm"; + "btn_cancel", "Cancel"; + "btn_save", "Save"; + "msg_options_editor_font_size", "Editors font size"; + "msg_options_editor_font_family", "Editors font family"; + "msg_options_size_small", "Small"; + "msg_options_size_medium", "Medium"; + "msg_options_size_large", "Large"; + "msg_options_programming_language", "Language"; + "msg_options_settings_optimize", "Optimize (experimental)"; + "msg_options_settings_debug", "Define DEBUG"; + "msg_options_settings_typed_arrays", "Typed Arrays"; + "msg_options_gist_token_delete", "Delete gist token"; + "msg_options_gist_token_githubtoken", "Github token"; + "msg_options_gist_token_githubtoken_create", " (Create)"; + "msg_options_gist_token_gist_scope", "Token with gist scope"; + "msg_samples_refresh_samples", "Refresh samples"; + "msg_stats_steps", "Steps"; + "msg_stats_milliseconds_short", "ms"; + "msg_options_size_small", "Small"; + "msg_options_size_small", "Small"] + + let translations = dict["en", enTranslations] + let []defaultLanguage = "en" + let selectedLanguage = Browser.Navigator.navigator.language |> Option.defaultValue defaultLanguage + let languageCode = selectedLanguage.Substring(0, 2) + let translation = if translations.ContainsKey languageCode then translations[languageCode] else translations[defaultLanguage] + + let msg_iframe_loaded = translation["msg_iframe_loaded"] + let win_header_console = translation["win_header_console"] + let msg_initializing = translation["msg_initializing"] + let msg_repl_name = translation["msg_repl_name"] + let msg_desktop_experience = translation["msg_desktop_experience"] + let btn_continue = translation["btn_continue"] + let msg_gist_description = translation["msg_gist_description"] + let msg_compilation_failed = translation["msg_compilation_failed"] + let msg_assemblies_load_failed = translation["msg_assemblies_load_failed"] + let msg_gist_token_invalid = translation["msg_gist_token_invalid"] + let msg_gist_token_missing = translation["msg_gist_token_missing"] + let msg_compilation_successful = translation["msg_compilation_successful"] + let msg_shareable_url_ready_text = translation["msg_shareable_url_ready_text"] + let msg_shareable_url_ready_title = translation["msg_shareable_url_ready_title"] + let msg_load_gist_error = translation["msg_load_gist_error"] + let msg_update_url_failed = translation["msg_update_url_failed"] + let msg_fatal_error = translation["msg_fatal_error"] + let msg_live_sample_text = translation["msg_live_sample_text"] + let msg_code_text = translation["msg_code_text"] + let msg_problems = translation["msg_problems"] + let msg_problems_info = translation["msg_problems_info"] + let msg_invalid_iframe_error = translation["msg_invalid_iframe_error"] + let msg_collapse_sidebar = translation["msg_collapse_sidebar"] + let msg_widget_general = translation["msg_widget_general"] + let msg_widget_samples = translation["msg_widget_samples"] + let msg_widget_options = translation["msg_widget_options"] + let msg_widget_statistics = translation["msg_widget_statistics"] + let msg_widget_about = translation["msg_widget_about"] + let msg_found_a_bug = translation["msg_found_a_bug"] + let msg_general_compile_run_tooltip = translation["msg_general_compile_run_tooltip"] + let msg_general_compile_run_text = translation["msg_general_compile_run_text"] + let msg_general_refresh_sample_tooltip = translation["msg_general_refresh_sample_tooltip"] + let msg_general_refresh_sample_text = translation["msg_general_refresh_sample_text"] + let msg_general_reset_repl_tooltip = translation["msg_general_reset_repl_tooltip"] + let msg_general_reset_repl_text = translation["msg_general_reset_repl_text"] + let msg_general_share_url_tooltip = translation["msg_general_share_url_tooltip"] + let msg_general_share_url_text = translation["msg_general_share_url_text"] + let msg_general_share_gist_tooltip = translation["msg_general_share_gist_tooltip"] + let msg_general_share_gist_text = translation["msg_general_share_gist_text"] + let msg_reset_confirmation_text = translation["msg_reset_confirmation_text"] + let btn_confirm = translation["btn_confirm"] + let btn_cancel = translation["btn_cancel"] + let btn_save = translation["btn_save"] + let msg_options_editor_font_size = translation["msg_options_editor_font_size"] + let msg_options_size_small = translation["msg_options_size_small"] + let msg_options_size_medium = translation["msg_options_size_medium"] + let msg_options_size_large = translation["msg_options_size_large"] + let msg_options_editor_font_family = translation["msg_options_editor_font_family"] + let msg_options_programming_language = translation["msg_options_programming_language"] + let msg_options_settings_optimize = translation["msg_options_settings_optimize"] + let msg_options_settings_debug = translation["msg_options_settings_debug"] + let msg_options_settings_typed_arrays = translation["msg_options_settings_typed_arrays"] + let msg_options_gist_token_delete = translation["msg_options_gist_token_delete"] + let msg_options_gist_token_githubtoken = translation["msg_options_gist_token_githubtoken"] + let msg_options_gist_token_githubtoken_create = translation["msg_options_gist_token_githubtoken_create"] + let msg_options_gist_token_gist_scope = translation["msg_options_gist_token_gist_scope"] + let msg_samples_refresh_samples = translation["msg_samples_refresh_samples"] + let msg_stats_steps = translation["msg_stats_steps"] + let msg_stats_milliseconds_short = translation["msg_stats_milliseconds_short"] diff --git a/src/App/Loader.fs b/src/App/Loader.fs index 4d2b099e..c44cb466 100644 --- a/src/App/Loader.fs +++ b/src/App/Loader.fs @@ -66,7 +66,7 @@ let init (result: Option) = let private view (model: Model) dispatch = match model with | Initializing -> - Html.text "Initializing" + Html.text Translations.msg_initializing | Running model -> Main.view model (MainMsg >> dispatch) @@ -91,19 +91,19 @@ let private view (model: Model) dispatch = Bulma.title.h3 [ text.hasTextCentered - prop.text "Fable REPL" + prop.text Translations.msg_repl_name ] Bulma.subtitle.h5 [ text.hasTextCentered - prop.text "For best experience we recommend running the REPL on a desktop" + prop.text Translations.msg_desktop_experience ] Bulma.level [ Bulma.levelItem [ Bulma.button.a [ prop.onClick (fun _ -> Initialize p |> dispatch) - prop.text "Continue" + prop.text Translations.btn_continue ] ] ] diff --git a/src/App/Main.fs b/src/App/Main.fs index fc1432f7..f0b4733a 100644 --- a/src/App/Main.fs +++ b/src/App/Main.fs @@ -169,7 +169,7 @@ let private postToGist = let data = Encode.object [ "public", Encode.bool true - "description", Encode.string "Created with Fable REPL" + "description", Encode.string Translations.msg_gist_description "files", Encode.object [ yield "fable-repl.fs", toContent code yield "fable-repl.html", toContent html @@ -216,7 +216,7 @@ let private loadGist = let private showGlobalErrorToast msg = Toast.message msg - |> Toast.title "Failed to compile" + |> Toast.title Translations.msg_compilation_failed |> Toast.position Toast.BottomRight |> Toast.icon Fa.Solid.Exclamation |> Toast.noTimeout @@ -269,7 +269,7 @@ let update msg (model : Model) = ] | LoadFail -> - let msg = "Assemblies couldn't be loaded. Some firewalls prevent download of binary files, please check." + let msg = Translations.msg_assemblies_load_failed { model with State = Idle } @@ -335,14 +335,14 @@ let update msg (model : Model) = JS.console.error exn model - , Toast.message "An error occured when creating the gist. Is the token valid?" + , Toast.message Translations.msg_gist_token_invalid |> Toast.icon Fa.Solid.ExclamationTriangle |> Toast.position Toast.BottomRight |> Toast.warning | NoToken -> model - , Toast.message "You need to register your GitHub API token before sharing to Gist" + , Toast.message Translations.msg_gist_token_missing |> Toast.icon Fa.Solid.ExclamationTriangle |> Toast.position Toast.BottomRight |> Toast.warning @@ -388,7 +388,7 @@ let update msg (model : Model) = let hasCriticalErrors = errors |> Array.exists (fun e -> not e.IsWarning) if hasCriticalErrors then let toastCmd = - Toast.message "Failed to compile" + Toast.message Translations.msg_compilation_failed |> Toast.position Toast.BottomRight |> Toast.icon Fa.Solid.Exclamation |> Toast.dismissOnClick @@ -408,7 +408,7 @@ let update msg (model : Model) = | _ -> [fun _ -> saveModel model] let cmd2 = - Toast.message "Compiled successfuly" + Toast.message Translations.msg_compilation_successful |> Toast.position Toast.BottomRight |> Toast.icon Fa.Solid.Check |> Toast.dismissOnClick @@ -563,8 +563,8 @@ let update msg (model : Model) = | ShareableUrlReady () -> model - , Toast.message "Copy it from the address bar" - |> Toast.title "Shareable link is ready" + , Toast.message Translations.msg_shareable_url_ready_text + |> Toast.title Translations.msg_shareable_url_ready_title |> Toast.position Toast.BottomRight |> Toast.icon Fa.Solid.InfoCircle |> Toast.timeout (System.TimeSpan.FromSeconds 5.) @@ -573,7 +573,7 @@ let update msg (model : Model) = | LoadGistError exn -> JS.console.error exn model - , Toast.message "An error occured when loading the gist" + , Toast.message Translations.msg_load_gist_error |> Toast.icon Fa.Solid.ExclamationTriangle |> Toast.position Toast.BottomRight |> Toast.warning @@ -581,7 +581,7 @@ let update msg (model : Model) = | UpdateQueryFailed exn -> JS.console.error exn model - , Toast.message "An error occured when updating the URL" + , Toast.message Translations.msg_update_url_failed |> Toast.icon Fa.Solid.ExclamationTriangle |> Toast.position Toast.BottomRight |> Toast.warning @@ -781,12 +781,12 @@ let private problemsPanel (isExpanded : bool) (errors : Monaco.Editor.IMarkerDat let title = if errors.Length = 0 then Html.span [ - prop.text "Problems" + prop.text Translations.msg_problems ] else Html.span [ prop.children [ - Html.text "Problems: " + Html.text Translations.msg_problems_info Html.span [ prop.style [ style.marginLeft (length.em 0.5) @@ -839,7 +839,7 @@ let private problemsPanel (isExpanded : bool) (errors : Monaco.Editor.IMarkerDat match error.severity with | Monaco.MarkerSeverity.Error -> Fa.Solid.TimesCircle, color.isDanger, "is-danger" | Monaco.MarkerSeverity.Warning -> Fa.Solid.ExclamationTriangle, color.isWarning, "is-warning" - | _ -> failwith "Should not happen", color.isDanger, "" + | _ -> failwith Translations.msg_fatal_error, color.isDanger, "" Html.div [ prop.className ("scrollable-panel-body-row " + colorClass) @@ -1005,7 +1005,7 @@ let private outputTabs (activeTab : OutputTab) dispatch = ) prop.children [ Html.a [ - prop.text "Live sample" + prop.text Translations.msg_live_sample_text ] ] ] @@ -1018,7 +1018,7 @@ let private outputTabs (activeTab : OutputTab) dispatch = ) prop.children [ Html.a [ - prop.text "Code" + prop.text Translations.msg_code_text ] ] ] diff --git a/src/App/Mouse.fs b/src/App/Mouse.fs index 0ac959d7..cd0f08a1 100644 --- a/src/App/Mouse.fs +++ b/src/App/Mouse.fs @@ -63,7 +63,10 @@ module Cmd = |> Decode.map args.ConsoleErrorCor | x -> // Discard messages we don't know how to handle it - sprintf "`%A` is not a known value for an iframe message" x + let formatMessage = + PrintfFormat string,unit,string,string>(Translations.msg_invalid_iframe_error) + + sprintf formatMessage x |> Decode.fail ) Decode.fromValue "$" iframeMessageDecoder ev?data diff --git a/src/App/Sidebar.fs b/src/App/Sidebar.fs index 6a634683..645c25aa 100644 --- a/src/App/Sidebar.fs +++ b/src/App/Sidebar.fs @@ -222,7 +222,7 @@ let private collapseButton dispatch = prop.onClick (fun _ -> dispatch ToggleState) prop.children [ Bulma.cardHeader [ - Bulma.cardHeaderTitle.div "Collapse sidebar" + Bulma.cardHeaderTitle.div Translations.msg_collapse_sidebar Bulma.cardHeaderIcon.span [ Bulma.icon [ Fa.i [ Fa.Solid.AngleDoubleLeft; Fa.Size Fa.FaLarge ] [ ] @@ -242,7 +242,7 @@ let private sidebarContainer dispatch (sections : ReactElement list) = Html.img [ prop.src "img/fable-ionide.png" ] - Bulma.title.h4 "Fable REPL" + Bulma.title.h4 Translations.msg_repl_name ] ] @@ -274,11 +274,11 @@ let view (isCompiling : bool) (model: Model) dispatch = let widgets = [ if model.IsExpanded then - "General", Fa.Solid.Th, Widgets.General.viewExpanded isCompiling model.Options.GistToken model.General (GeneralMsg >> dispatch), None - "Samples", Fa.Solid.Book, Widgets.Samples.view model.Samples (SamplesMsg >> dispatch), Some 500 - "Options", Fa.Solid.Cog, Widgets.Options.view model.Options (OptionsMsg >> dispatch), None - "Statistics", Fa.Regular.Clock, Widgets.Stats.view model.Statistics, None - "About", Fa.Solid.Info, Widgets.About.view model.FableVersion, None + Translations.msg_widget_general, Fa.Solid.Th, Widgets.General.viewExpanded isCompiling model.Options.GistToken model.General (GeneralMsg >> dispatch), None + Translations.msg_widget_samples, Fa.Solid.Book, Widgets.Samples.view model.Samples (SamplesMsg >> dispatch), Some 500 + Translations.msg_widget_options, Fa.Solid.Cog, Widgets.Options.view model.Options (OptionsMsg >> dispatch), None + Translations.msg_widget_statistics, Fa.Regular.Clock, Widgets.Stats.view model.Statistics, None + Translations.msg_widget_about, Fa.Solid.Info, Widgets.About.view model.FableVersion, None ] |> List.map (renderWidgets model dispatch) diff --git a/src/App/Widgets/About.fs b/src/App/Widgets/About.fs index 50e52ef7..f667425f 100644 --- a/src/App/Widgets/About.fs +++ b/src/App/Widgets/About.fs @@ -17,7 +17,7 @@ let view fableVersion = prop.style [ style.textDecoration.underline ] - prop.text "Found a bug ?" + prop.text Translations.msg_found_a_bug ] ] ] diff --git a/src/App/Widgets/General.fs b/src/App/Widgets/General.fs index f3edae47..1f082d9c 100644 --- a/src/App/Widgets/General.fs +++ b/src/App/Widgets/General.fs @@ -99,13 +99,13 @@ let viewCollapsed (isCompiling : bool) (gistToken : string option) (model: Model prop.className "actions-area" prop.children [ - actionButton "Compile and run (Alt+Enter)" StartCompile compileIcon - actionButton "Refresh the live sample (without compiling)" RefreshIframe [ Fa.i [ Fa.Solid.Redo ] [ ] ] - actionButton "Reset the REPL, you will lose your current work" AskReset [ Fa.i [ Fa.Solid.TrashAlt ] [ ] ] - actionButton "Share using the URL" Share [ Fa.i [ Fa.Solid.Share ] [ ] ] + actionButton Translations.msg_general_compile_run_tooltip StartCompile compileIcon + actionButton Translations.msg_general_refresh_sample_tooltip RefreshIframe [ Fa.i [ Fa.Solid.Redo ] [ ] ] + actionButton Translations.msg_general_reset_repl_tooltip AskReset [ Fa.i [ Fa.Solid.TrashAlt ] [ ] ] + actionButton Translations.msg_general_share_url_tooltip Share [ Fa.i [ Fa.Solid.Share ] [ ] ] match gistToken with | Some _ -> - actionButton "Share to Gist" ShareToGist [ Fa.i [ Fa.Brand.Github ] [ ] ] + actionButton Translations.msg_general_share_gist_tooltip ShareToGist [ Fa.i [ Fa.Brand.Github ] [ ] ] | None -> Html.none ] @@ -150,13 +150,13 @@ let viewExpanded (isCompiling : bool) (gistToken : string option) (model: Model) match model.ResetState with | Default -> Html.div [ - renderItem "Compile and run" isCompiling StartCompile Fa.Solid.Play - renderItem "Refresh the live sample" isCompiling RefreshIframe Fa.Solid.Redo - renderItem "Click here to reset" false AskReset Fa.Solid.TrashAlt - renderItem "Share using the URL" false Share Fa.Solid.Share + renderItem Translations.msg_general_compile_run_text isCompiling StartCompile Fa.Solid.Play + renderItem Translations.msg_general_refresh_sample_text isCompiling RefreshIframe Fa.Solid.Redo + renderItem Translations.msg_general_reset_repl_text false AskReset Fa.Solid.TrashAlt + renderItem Translations.msg_general_share_url_text false Share Fa.Solid.Share match gistToken with | Some _ -> - renderItem "Share to Gist" false ShareToGist Fa.Brand.Github + renderItem Translations.msg_general_share_gist_text false ShareToGist Fa.Brand.Github | None -> Html.none ] @@ -165,7 +165,7 @@ let viewExpanded (isCompiling : bool) (gistToken : string option) (model: Model) Bulma.field.div [ Bulma.help [ color.isWarning - prop.text "Please, confirm to reset" + prop.text Translations.msg_reset_confirmation_text ] Bulma.field.div [ @@ -179,7 +179,7 @@ let viewExpanded (isCompiling : bool) (gistToken : string option) (model: Model) Bulma.icon [ Fa.i [ Fa.Solid.Check ] [ ] ] - Html.span "Confirm" + Html.span Translations.btn_confirm ] ] ] @@ -192,7 +192,7 @@ let viewExpanded (isCompiling : bool) (gistToken : string option) (model: Model) Bulma.icon [ Fa.i [ Fa.Solid.Times ] [ ] ] - Html.span "Cancel" + Html.span Translations.btn_cancel ] ] ] @@ -223,7 +223,7 @@ let viewModalResetConfirmation (model: Model) dispatch = prop.children [ Html.span [ prop.className "reset-confirmation-modal-content-text" - prop.text "Please, confirm to reset" + prop.text Translations.msg_reset_confirmation_text ] Html.div [ @@ -243,7 +243,7 @@ let viewModalResetConfirmation (model: Model) dispatch = Fa.i [ Fa.Solid.Check ] [ ] ] - Html.span "Confirm" + Html.span Translations.btn_confirm ] ] ] @@ -257,7 +257,7 @@ let viewModalResetConfirmation (model: Model) dispatch = Fa.i [ Fa.Solid.Times ] [ ] ] - Html.span "Cancel" + Html.span Translations.btn_cancel ] ] ] diff --git a/src/App/Widgets/Options.fs b/src/App/Widgets/Options.fs index 4587581d..de320440 100644 --- a/src/App/Widgets/Options.fs +++ b/src/App/Widgets/Options.fs @@ -147,7 +147,7 @@ let private fontSizeOption (label : string) (fontSize : float) = let inline private fontSizeSetting (fontSize : float) dispatch = Bulma.field.div [ - Bulma.label "Editors font size" + Bulma.label Translations.msg_options_editor_font_size Bulma.control.div [ Bulma.select [ @@ -157,9 +157,9 @@ let inline private fontSizeSetting (fontSize : float) dispatch = ev.Value |> float |> ChangeFontSize |> dispatch ) prop.children [ - fontSizeOption "Small" 12. - fontSizeOption "Medium" 14. - fontSizeOption "Large" 16. + fontSizeOption Translations.msg_options_size_small 12. + fontSizeOption Translations.msg_options_size_medium 14. + fontSizeOption Translations.msg_options_size_large 16. ] ] ] @@ -173,7 +173,7 @@ let private fontFamilyOption (label : string) (fontFamily : string) = let inline private fontFamilySetting (fontFamily : string) dispatch = Bulma.field.div [ - Bulma.label "Editors font family" + Bulma.label Translations.msg_options_editor_font_family Bulma.control.div [ Bulma.select [ @@ -198,7 +198,7 @@ let private languageSetting (language : string) dispatch = ] Bulma.field.div [ - Bulma.label "Language" + Bulma.label Translations.msg_options_programming_language Bulma.control.div [ Bulma.select [ @@ -240,13 +240,13 @@ let private switchOption (label : string) isActive dispatch msg = ] let inline private optimizeSetting (model: Model) dispatch = - switchOption "Optimize (experimental)" model.Optimize dispatch ToggleOptimize + switchOption Translations.msg_options_settings_optimize model.Optimize dispatch ToggleOptimize let private defineDebugSetting (model: Model) dispatch = - switchOption "Define DEBUG" model.DefineDebug dispatch ToggleDefineDebug + switchOption Translations.msg_options_settings_debug model.DefineDebug dispatch ToggleDefineDebug let private typedArraysSetting (model: Model) dispatch = - switchOption "Typed Arrays" model.TypedArrays dispatch ToggleTypedArrays + switchOption Translations.msg_options_settings_typed_arrays model.TypedArrays dispatch ToggleTypedArrays let inline private gistTokenSetting (token : string option) (tokenField : string) dispatch = match token with @@ -255,7 +255,7 @@ let inline private gistTokenSetting (token : string option) (tokenField : string Bulma.button.a [ prop.onClick (fun _ -> dispatch DeleteToken) button.isFullWidth - prop.text "Delete gist token" + prop.text Translations.msg_options_gist_token_delete ] ] @@ -263,11 +263,11 @@ let inline private gistTokenSetting (token : string option) (tokenField : string Bulma.field.div [ Bulma.label [ prop.children [ - Html.text "Github token" + Html.text Translations.msg_options_gist_token_githubtoken Html.a [ prop.target "_blank" prop.href "https://github.com/settings/tokens/new?description=fable-repl&scopes=gist" - prop.text " (Create)" + prop.text Translations.msg_options_gist_token_githubtoken_create ] ] ] @@ -277,13 +277,13 @@ let inline private gistTokenSetting (token : string option) (tokenField : string prop.children [ Bulma.input.password [ prop.onChange (fun (ev : Types.Event) -> ev.Value |> ChangeGistToken |> dispatch) - prop.placeholder "Token with gist scope" + prop.placeholder Translations.msg_options_gist_token_gist_scope ] if tokenField.Length = 40 then Bulma.button.a [ prop.onClick (fun _ -> dispatch SaveToken) - prop.text "Save" + prop.text Translations.btn_save ] ] ] diff --git a/src/App/Widgets/Samples.fs b/src/App/Widgets/Samples.fs index 6679e729..1335cf8a 100644 --- a/src/App/Widgets/Samples.fs +++ b/src/App/Widgets/Samples.fs @@ -301,7 +301,7 @@ let view model dispatch = prop.onClick fetchSamplesMsg prop.children [ - Html.span "Refresh samples" + Html.span Translations.msg_samples_refresh_samples ] ] ] diff --git a/src/App/Widgets/Stats.fs b/src/App/Widgets/Stats.fs index 264a8efd..9395b034 100644 --- a/src/App/Widgets/Stats.fs +++ b/src/App/Widgets/Stats.fs @@ -26,10 +26,10 @@ let view (model : Model) = Bulma.table [ Html.thead [ Html.tr [ - Html.th "Steps" + Html.th Translations.msg_stats_steps Html.th [ prop.className "has-text-right" - prop.text "ms" + prop.text Translations.msg_stats_milliseconds_short ] ] ] diff --git a/src/App/paket.references b/src/App/paket.references index f3bf4f70..02c8b5f2 100644 --- a/src/App/paket.references +++ b/src/App/paket.references @@ -9,4 +9,5 @@ Fable.Fetch Fable.FontAwesome.Free Feliz Feliz.Bulma -Feliz.Bulma.Tooltip \ No newline at end of file +Feliz.Bulma.Tooltip +Fable.Browser.Navigator \ No newline at end of file