From abd290eba115fca0520ad3b1f1331a9594631f79 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 16 Jul 2026 12:35:19 +0200 Subject: [PATCH] improved options --- backend/src/app/rpc/commands/profile.clj | 1 + .../test/backend_tests/rpc_profile_test.clj | 15 ++ common/src/app/common/features.cljc | 3 - common/src/app/common/files/changes.cljc | 11 +- .../src/app/common/files/changes_builder.cljc | 12 ++ common/src/app/common/types/file.cljc | 16 +- .../common/types/text/japanese_layout.cljc | 1 + .../test/common_tests/files_changes_test.cljc | 20 ++ frontend/src/app/main/data/workspace.cljs | 11 ++ .../src/app/main/data/workspace/texts.cljs | 3 +- .../src/app/main/ui/settings/options.cljs | 30 ++- .../src/app/main/ui/settings/options.scss | 10 +- .../src/app/main/ui/shapes/text/fo_text.cljs | 4 +- .../app/main/ui/shapes/text/html_text.cljs | 4 +- .../src/app/main/ui/shapes/text/styles.cljs | 3 +- .../src/app/main/ui/workspace/main_menu.cljs | 37 +++- .../workspace/sidebar/options/menus/text.cljs | 183 ++++++++++-------- .../options/menus/text_japanese_layout.cljs | 85 +++++--- .../options/menus/text_japanese_layout.scss | 7 +- frontend/src/app/render_wasm/api.cljs | 20 +- frontend/src/app/render_wasm/api/texts.cljs | 10 +- frontend/src/app/render_wasm/text_editor.cljs | 1 + .../src/app/util/text/content/styles.cljs | 6 + .../render_wasm/texts_test.cljs | 26 +++ .../frontend_tests/ui/text_options_test.cljs | 57 +++++- frontend/translations/en.po | 30 ++- frontend/translations/jpn_JP.po | 28 +++ 27 files changed, 490 insertions(+), 144 deletions(-) diff --git a/backend/src/app/rpc/commands/profile.clj b/backend/src/app/rpc/commands/profile.clj index 79af070c6a..b415071621 100644 --- a/backend/src/app/rpc/commands/profile.clj +++ b/backend/src/app/rpc/commands/profile.clj @@ -49,6 +49,7 @@ [:map {:title "ProfileProps"} [:plugins {:optional true} schema:plugin-registry] [:renderer {:optional true} [::sm/one-of #{:svg :wasm}]] + [:japanese-layout-all-files {:optional true} ::sm/boolean] [:mcp-enabled {:optional true} ::sm/boolean] [:newsletter-updates {:optional true} ::sm/boolean] [:newsletter-news {:optional true} ::sm/boolean] diff --git a/backend/test/backend_tests/rpc_profile_test.clj b/backend/test/backend_tests/rpc_profile_test.clj index 7adc12d68e..376a3549fb 100644 --- a/backend/test/backend_tests/rpc_profile_test.clj +++ b/backend/test/backend_tests/rpc_profile_test.clj @@ -150,6 +150,21 @@ (t/is (nil? (:error out))) (t/is (nil? (:photo-id (:result out)))))))) +(t/deftest update-profile-japanese-layout-setting + (let [profile (th/create-profile* 1) + params {::th/type :update-profile-props + ::rpc/profile-id (:id profile) + :props {:japanese-layout-all-files true}} + out (th/command! params)] + (t/is (nil? (:error out))) + (t/is (true? (get-in out [:result :japanese-layout-all-files]))) + + (let [params {::th/type :get-profile + ::rpc/profile-id (:id profile)} + out (th/command! params)] + (t/is (nil? (:error out))) + (t/is (true? (get-in out [:result :props :japanese-layout-all-files])))))) + (t/deftest profile-deletion-1 (let [prof (th/create-profile* 1) file (th/create-file* 1 {:profile-id (:id prof) diff --git a/common/src/app/common/features.cljc b/common/src/app/common/features.cljc index 2b908a0bdd..a5097a29a7 100644 --- a/common/src/app/common/features.cljc +++ b/common/src/app/common/features.cljc @@ -56,7 +56,6 @@ "text-editor/v2-html-paste" "text-editor/v2" "text-editor-wasm/v1" - "japanese-layout/v1" "render-wasm/v1" "variants/v1"}) @@ -82,7 +81,6 @@ "text-editor/v2-html-paste" "text-editor/v2" "text-editor-wasm/v1" - "japanese-layout/v1" "tokens/numeric-input" "render-wasm/v1"}) @@ -133,7 +131,6 @@ :feature-text-editor-v2 "text-editor/v2" :feature-text-editor-v2-html-paste "text-editor/v2-html-paste" :feature-text-editor-wasm "text-editor-wasm/v1" - :feature-japanese-layout "japanese-layout/v1" :feature-render-wasm "render-wasm/v1" :feature-variants "variants/v1" :feature-token-input "tokens/numeric-input" diff --git a/common/src/app/common/files/changes.cljc b/common/src/app/common/files/changes.cljc index 8747099167..ac3fdd6452 100644 --- a/common/src/app/common/files/changes.cljc +++ b/common/src/app/common/files/changes.cljc @@ -427,7 +427,12 @@ [:set-base-font-size [:map {:title "ModBaseFontSize"} [:type [:= :set-base-font-size]] - [:base-font-size :string]]]]) + [:base-font-size :string]]] + + [:set-japanese-layout + [:map {:title "SetJapaneseLayout"} + [:type [:= :set-japanese-layout]] + [:enabled ::sm/boolean]]]]) (def schema:changes [:sequential {:gen/max 5 :gen/min 1} schema:change]) @@ -1065,6 +1070,10 @@ [data {:keys [base-font-size]}] (ctf/set-base-font-size data base-font-size)) +(defmethod process-change :set-japanese-layout + [data {:keys [enabled]}] + (ctf/set-japanese-layout-enabled data enabled)) + ;; === Operations diff --git a/common/src/app/common/files/changes_builder.cljc b/common/src/app/common/files/changes_builder.cljc index eb7593e992..1f0c98851d 100644 --- a/common/src/app/common/files/changes_builder.cljc +++ b/common/src/app/common/files/changes_builder.cljc @@ -1084,6 +1084,18 @@ :base-font-size previous-font-size}) (apply-changes-local)))) +(defn set-japanese-layout + [changes enabled?] + (assert-file-data! changes) + (let [file-data (::file-data (meta changes)) + previous-enabled (ctf/japanese-layout-enabled? file-data)] + (-> changes + (update :redo-changes conj {:type :set-japanese-layout + :enabled enabled?}) + (update :undo-changes conj {:type :set-japanese-layout + :enabled previous-enabled}) + (apply-changes-local)))) + ;; Misc changes (defn reorder-children diff --git a/common/src/app/common/types/file.cljc b/common/src/app/common/types/file.cljc index accda94bc5..efbfe95737 100644 --- a/common/src/app/common/types/file.cljc +++ b/common/src/app/common/types/file.cljc @@ -75,7 +75,8 @@ (def schema:options [:map {:title "FileOptions"} [:components-v2 {:optional true} ::sm/boolean] - [:base-font-size {:optional true} :string]]) + [:base-font-size {:optional true} :string] + [:japanese-layout {:optional true} ::sm/boolean]]) (def schema:data [:map {:title "FileData"} @@ -1225,6 +1226,19 @@ (assoc-in file-data [:options :base-font-size] base-font-size)) +;; Japanese text layout + +(defn japanese-layout-enabled? + [file-data] + (true? (get-in file-data [:options :japanese-layout]))) + +(defn set-japanese-layout-enabled + [file-data enabled?] + (if enabled? + (assoc-in file-data [:options :japanese-layout] true) + (d/update-in-when file-data [:options] dissoc :japanese-layout))) + + ;; Ref Chains (defn get-ref-chain-until-target-ref "Returns a vector with the shape ref chain until target-ref, including itself" diff --git a/common/src/app/common/types/text/japanese_layout.cljc b/common/src/app/common/types/text/japanese_layout.cljc index bdd9e4707f..adb461d42b 100644 --- a/common/src/app/common/types/text/japanese_layout.cljc +++ b/common/src/app/common/types/text/japanese_layout.cljc @@ -26,6 +26,7 @@ ;; Ruby (furigana) annotation text and customization carried per span. (def text-ruby-attrs [:ruby + :ruby-hidden :ruby-size :ruby-align :ruby-overhang diff --git a/common/test/common_tests/files_changes_test.cljc b/common/test/common_tests/files_changes_test.cljc index 3cbc475000..938ed4a192 100644 --- a/common/test/common_tests/files_changes_test.cljc +++ b/common/test/common_tests/files_changes_test.cljc @@ -24,6 +24,26 @@ (binding [ffeat/*current* #{"components/v2"}] (ctf/make-file-data file-id page-id))) +(t/deftest set-japanese-layout-file-option + (let [file-id (uuid/custom 2 2) + page-id (uuid/custom 1 1) + data (make-file-data file-id page-id) + enabled (ch/process-changes data [{:type :set-japanese-layout + :enabled true}]) + disabled (ch/process-changes enabled [{:type :set-japanese-layout + :enabled false}]) + changes (-> (pcb/empty-changes) + (pcb/with-file-data data) + (pcb/set-japanese-layout true))] + (t/is (false? (ctf/japanese-layout-enabled? data))) + (t/is (true? (ctf/japanese-layout-enabled? enabled))) + (t/is (false? (ctf/japanese-layout-enabled? disabled))) + (t/is (not (contains? (:options disabled) :japanese-layout))) + (t/is (= [{:type :set-japanese-layout :enabled true}] + (:redo-changes changes))) + (t/is (= '({:type :set-japanese-layout :enabled false}) + (:undo-changes changes))))) + (t/deftest add-obj (let [file-id (uuid/custom 2 2) page-id (uuid/custom 1 1) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index fb6245c31c..11c5c6fa08 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -604,6 +604,17 @@ (dm/export layout/toggle-layout-flag) (dm/export layout/remove-layout-flag) +(defn set-japanese-layout + [enabled?] + (ptk/reify ::set-japanese-layout + ptk/WatchEvent + (watch [it state _] + (let [file-data (dsh/lookup-file-data state) + changes (-> (pcb/empty-changes it) + (pcb/with-file-data file-data) + (pcb/set-japanese-layout enabled?))] + (rx/of (dch/commit-changes changes)))))) + ;; --- Profile (defn update-nudge diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index f101553f5c..035be21315 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -61,7 +61,7 @@ (declare v2-sync-wasm-text-layout) (def ruby-presentation-attrs - [:ruby-size :ruby-align :ruby-overhang :ruby-side]) + [:ruby-hidden :ruby-size :ruby-align :ruby-overhang :ruby-side]) ;; -- Content helpers @@ -340,7 +340,6 @@ (count (:text node))))) - (defn decorate-range-info "Adds information about ranges inside the metadata of the text nodes" [content] diff --git a/frontend/src/app/main/ui/settings/options.cljs b/frontend/src/app/main/ui/settings/options.cljs index aca2ef130c..18c81bfd8a 100644 --- a/frontend/src/app/main/ui/settings/options.cljs +++ b/frontend/src/app/main/ui/settings/options.cljs @@ -115,10 +115,37 @@ :on-change handle-render-change}]] [:> text* {:typography t/body-medium :class (stl/css :feedback)} [:a {:href "#" :on-click go-settings-feedback :class (stl/css :link)} (tr "dashboard.webgl-switch.feedback") [:> icon* {:icon-id "arrow-up-right" :size "s"}]]]])) +(mf/defc japanese-layout-settings* + [{:keys [enabled]}] + (let [handle-change + (mf/use-fn + (fn [enabled?] + (st/emit! (ev/event {::ev/name (if enabled? + "enable-japanese-layout-all-files" + "disable-japanese-layout-all-files") + ::ev/origin "settings"}) + (du/update-profile-props + {:japanese-layout-all-files enabled?}) + (ntf/success (tr "notifications.profile-saved")))))] + [:section {:class (stl/css :japanese-layout-container)} + [:> heading* {:class (stl/css :title) + :level 2 + :typography t/title-large} + (tr "dashboard.japanese-layout.title")] + [:> text* {:class (stl/css :description) :typography t/body-medium} + (tr "dashboard.japanese-layout.description")] + [:form {:class (stl/css :japanese-layout-form)} + [:> switch* {:label (tr "dashboard.japanese-layout.enable-all-files") + :default-checked enabled + :on-change handle-change}]]])) + (mf/defc options-page* [] (let [profile (mf/deref refs/profile) - renderer (or (-> profile :props :renderer) :svg)] + renderer (or (-> profile :props :renderer) :svg) + japanese-layout-enabled (true? (-> profile + :props + :japanese-layout-all-files))] (mf/use-effect #(dom/set-html-title (tr "title.settings.options"))) @@ -127,5 +154,6 @@ [:div {:class (stl/css :form-container) :data-testid "settings-form"} [:h2 (tr "labels.settings")] [:> options-form*]] + [:> japanese-layout-settings* {:enabled japanese-layout-enabled}] (when (contains? cf/flags :render-switch) [:> webgl-settings* {:renderer renderer}])]])) diff --git a/frontend/src/app/main/ui/settings/options.scss b/frontend/src/app/main/ui/settings/options.scss index d5755e6062..6ce9dd6dca 100644 --- a/frontend/src/app/main/ui/settings/options.scss +++ b/frontend/src/app/main/ui/settings/options.scss @@ -21,9 +21,9 @@ } } -/* Copied from profile.scss .form-container, but without included nested - rules, since we want custom styles for it */ -.webgl-container { +/* Settings sections with standalone controls. */ +.webgl-container, +.japanese-layout-container { display: grid; grid-auto-rows: auto; gap: var(--sp-s); @@ -34,6 +34,10 @@ color: var(--color-foreground-primary); } +.japanese-layout-form { + padding-block-start: var(--sp-xs); +} + .webgl-header { display: flex; flex-direction: row; diff --git a/frontend/src/app/main/ui/shapes/text/fo_text.cljs b/frontend/src/app/main/ui/shapes/text/fo_text.cljs index 6caa72de4f..3eb5d2fd44 100644 --- a/frontend/src/app/main/ui/shapes/text/fo_text.cljs +++ b/frontend/src/app/main/ui/shapes/text/fo_text.cljs @@ -22,7 +22,9 @@ (sts/generate-text-styles shape parent) (sts/generate-text-styles shape node)) ruby (:ruby node) - ruby? (and (string? ruby) (not (str/blank? ruby)))] + ruby? (and (not (true? (:ruby-hidden node))) + (string? ruby) + (not (str/blank? ruby)))] (if ruby? [:ruby.ruby-node {:style (sts/generate-ruby-container-styles node)} [:span.text-node {:style style} text] diff --git a/frontend/src/app/main/ui/shapes/text/html_text.cljs b/frontend/src/app/main/ui/shapes/text/html_text.cljs index 5e6c3a39f6..91d0ed2752 100644 --- a/frontend/src/app/main/ui/shapes/text/html_text.cljs +++ b/frontend/src/app/main/ui/shapes/text/html_text.cljs @@ -22,7 +22,9 @@ (sts/generate-text-styles shape node)) class (when is-code (:$id node)) ruby (:ruby node) - ruby? (and (string? ruby) (not (str/blank? ruby)))] + ruby? (and (not (true? (:ruby-hidden node))) + (string? ruby) + (not (str/blank? ruby)))] (if ruby? [:ruby.ruby-node {:style (sts/generate-ruby-container-styles node)} [:span.text-node {:style style :class class} text] diff --git a/frontend/src/app/main/ui/shapes/text/styles.cljs b/frontend/src/app/main/ui/shapes/text/styles.cljs index c7b374dcf3..f167da277c 100644 --- a/frontend/src/app/main/ui/shapes/text/styles.cljs +++ b/frontend/src/app/main/ui/shapes/text/styles.cljs @@ -97,7 +97,8 @@ font-features (:font-features data) annotation-clearance (:annotation-clearance data) annotation-layers (if (= "auto" annotation-clearance) - (+ (if (and (string? (:ruby data)) + (+ (if (and (not (true? (:ruby-hidden data))) + (string? (:ruby data)) (seq (:ruby data))) 1 0) (if (and (string? text-emphasis) (not= "none" text-emphasis)) 1 0)) diff --git a/frontend/src/app/main/ui/workspace/main_menu.cljs b/frontend/src/app/main/ui/workspace/main_menu.cljs index 394864c22a..7583d7a8ec 100644 --- a/frontend/src/app/main/ui/workspace/main_menu.cljs +++ b/frontend/src/app/main/ui/workspace/main_menu.cljs @@ -10,6 +10,7 @@ [app.common.data :as d] [app.common.data.macros :as dm] [app.common.files.helpers :as cfh] + [app.common.types.file :as ctf] [app.common.uuid :as uuid] [app.config :as cf] [app.main.data.common :as dcm] @@ -228,8 +229,13 @@ (mf/defc preferences-menu* {::mf/private true ::mf/wrap [mf/memo]} - [{:keys [layout profile toggle-flag on-close toggle-theme toggle-render]}] - (let [renderer (or (-> profile :props :renderer) :svg) + [{:keys [japanese-layout-enabled layout profile toggle-flag on-close + toggle-theme toggle-render toggle-japanese-layout]}] + (let [renderer (or (-> profile :props :renderer) :svg) + japanese-layout-all-files? (true? (-> profile + :props + :japanese-layout-all-files)) + read-only? (mf/use-ctx ctx/workspace-read-only?) show-nudge-options (mf/use-fn @@ -312,6 +318,19 @@ :id "file-menu-nudge"} [:span {:class (stl/css :item-name)} (tr "modals.nudge-title")]] + (when-not (or read-only? japanese-layout-all-files?) + [:> dropdown-menu-item* {:on-click toggle-japanese-layout + :class (stl/css :base-menu-item :submenu-item) + :on-key-down (fn [event] + (when (kbd/enter? event) + (toggle-japanese-layout event))) + :data-testid "japanese-layout" + :id "file-menu-japanese-layout"} + [:span {:class (stl/css :item-name)} + (if japanese-layout-enabled + (tr "workspace.header.menu.disable-japanese-layout") + (tr "workspace.header.menu.enable-japanese-layout"))]]) + [:> dropdown-menu-item* {:on-click toggle-theme :class (stl/css :base-menu-item :submenu-item) :on-key-down (fn [event] @@ -881,6 +900,9 @@ (mf/defc menu* [{:keys [layout file]}] (let [profile (mf/deref refs/profile) + file-data (mf/deref refs/workspace-data) + japanese-layout-enabled + (ctf/japanese-layout-enabled? file-data) show-menu* (mf/use-state false) show-menu? (deref show-menu*) @@ -949,6 +971,15 @@ (dom/stop-propagation event) (st/emit! (du/toggle-theme)))) + toggle-japanese-layout + (mf/use-fn + (mf/deps japanese-layout-enabled) + (fn [event] + (dom/stop-propagation event) + (st/emit! (dw/set-japanese-layout (not japanese-layout-enabled))) + (reset! show-menu* false) + (reset! selected-sub-menu* nil))) + toggle-render (mf/use-fn (mf/deps profile) @@ -1145,9 +1176,11 @@ :preferences [:> preferences-menu* {:layout layout :profile profile + :japanese-layout-enabled japanese-layout-enabled :toggle-flag toggle-flag :toggle-theme toggle-theme :toggle-render toggle-render + :toggle-japanese-layout toggle-japanese-layout :on-close close-sub-menu}] :plugins diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs index f451fcffbd..66d6a4e7b7 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs @@ -314,6 +314,8 @@ (get n-values :text-emphasis)) (identical? (get o-values :ruby) (get n-values :ruby)) + (identical? (get o-values :ruby-hidden) + (get n-values :ruby-hidden)) (identical? (get o-values :ruby-size) (get n-values :ruby-size)) (identical? (get o-values :ruby-align) @@ -342,10 +344,17 @@ (let [;; --- UI state menu-state* (mf/use-state {:main-menu true - :more-options false}) + :more-options false + :japanese-layout true}) menu-state (deref menu-state*) main-menu-open? (:main-menu menu-state) more-options-open? (:more-options menu-state) + japanese-layout-open? (:japanese-layout menu-state) + + profile (mf/deref refs/profile) + file-data (mf/deref refs/workspace-data) + japanese-layout-config-enabled? + (tjl/japanese-layout-config-enabled? file-data profile) token-dropdown-open* (mf/use-state false) token-dropdown-open? (deref token-dropdown-open*) @@ -431,6 +440,10 @@ (mf/use-fn #(swap! menu-state* update :more-options not)) + toggle-japanese-layout + (mf/use-fn + #(swap! menu-state* update :japanese-layout not)) + toggle-token-dropdown (mf/use-fn #(swap! token-dropdown-open* not)) @@ -555,94 +568,104 @@ (when token-dropdown-open? (ts/schedule 0 #(some-> (mf/ref-val dropdown-ref) dom/focus!)))) - [:section {:class (stl/css :element-set) - :aria-label (tr "workspace.options.text-options.text-section")} - [:div {:class (stl/css :element-title)} - [:> title-bar* {:collapsable true - :collapsed (not main-menu-open?) - :on-collapsed toggle-main-menu - :title label - :class (stl/css :title-spacing-text)} - [:* - (when (and token-typography-row-enabled? (some? (resolve-delay typography-tokens)) (not typography)) - [:> icon-button* {:variant "ghost" - :aria-label (tr "ds.inputs.numeric-input.open-token-list-dropdown") - :on-click toggle-token-dropdown - :tooltip-placement "top-left" - :icon i/tokens}]) - (when (and (not typography) (not multiple?) (not applied-token-name)) - [:> icon-button* {:variant "ghost" - :aria-label (tr "workspace.options.convert-to-typography") - :on-click on-convert-to-typography - :tooltip-placement "top-left" - :icon i/add}])]] - (when (and token-typography-row-enabled? token-dropdown-open?) - [:> searchable-options-dropdown* {:on-click on-option-click - :id listbox-id - :options (resolve-delay dropdown-options) - :selected selected-token-id - :align "right" - :placeholder (tr "workspace.tokens.search-by-token") - :ref set-option-ref}])] - - (when main-menu-open? - [:div {:class (stl/css :element-content)} - (cond - (and token-typography-row-enabled? (= :multiple current-token-name) (= typography-id :multiple)) - [:div {:class (stl/css :multiple-typography)} - [:span {:class (stl/css :multiple-text)} - (tr "workspace.libraries.text.mixed-tokens-and-assets")]] - - (and token-typography-row-enabled? (= :multiple current-token-name)) - [:div {:class (stl/css :multiple-typography)} - [:span {:class (stl/css :multiple-text)} - (tr "workspace.libraries.text.mixed-tokens")] - [:> icon-button* {:variant "ghost" - :aria-label (tr "workspace.libraries.text.multiple-token-tooltip") + [:* + [:section {:class (stl/css :element-set) + :aria-label (tr "workspace.options.text-options.text-section")} + [:div {:class (stl/css :element-title)} + [:> title-bar* {:collapsable true + :collapsed (not main-menu-open?) + :on-collapsed toggle-main-menu + :title label + :class (stl/css :title-spacing-text)} + [:* + (when (and token-typography-row-enabled? (some? (resolve-delay typography-tokens)) (not typography)) + [:> icon-button* {:variant "ghost" + :aria-label (tr "ds.inputs.numeric-input.open-token-list-dropdown") + :on-click toggle-token-dropdown :tooltip-placement "top-left" - :on-click handle-detach-all-tokens - :icon i/detach}]] - - (and token-typography-row-enabled? current-token-name) - [:> token-typography-row* {:token-name current-token-name - :detach-token detach-token - :active-tokens (resolve-delay typography-tokens)}] - - (= typography-id :multiple) - [:div {:class (stl/css :multiple-typography)} - [:span {:class (stl/css :multiple-text)} - (tr "workspace.libraries.text.mixed-typography")] - [:> icon-button* {:variant "ghost" - :aria-label (tr "workspace.libraries.text.multiple-assets-tooltip") - :on-click handle-detach-typography + :icon i/tokens}]) + (when (and (not typography) (not multiple?) (not applied-token-name)) + [:> icon-button* {:variant "ghost" + :aria-label (tr "workspace.options.convert-to-typography") + :on-click on-convert-to-typography :tooltip-placement "top-left" - :icon i/detach}]] + :icon i/add}])]] + (when (and token-typography-row-enabled? token-dropdown-open?) + [:> searchable-options-dropdown* {:on-click on-option-click + :id listbox-id + :options (resolve-delay dropdown-options) + :selected selected-token-id + :align "right" + :placeholder (tr "workspace.tokens.search-by-token") + :ref set-option-ref}])] - typography - [:> typography-entry* {:file-id typography-file-id - :typography typography - :is-local (= typography-file-id file-id) - :on-detach handle-detach-typography - :on-change handle-change-typography}] + (when main-menu-open? + [:div {:class (stl/css :element-content)} + (cond + (and token-typography-row-enabled? (= :multiple current-token-name) (= typography-id :multiple)) + [:div {:class (stl/css :multiple-typography)} + [:span {:class (stl/css :multiple-text)} + (tr "workspace.libraries.text.mixed-tokens-and-assets")]] + (and token-typography-row-enabled? (= :multiple current-token-name)) + [:div {:class (stl/css :multiple-typography)} + [:span {:class (stl/css :multiple-text)} + (tr "workspace.libraries.text.mixed-tokens")] + [:> icon-button* {:variant "ghost" + :aria-label (tr "workspace.libraries.text.multiple-token-tooltip") + :tooltip-placement "top-left" + :on-click handle-detach-all-tokens + :icon i/detach}]] + (and token-typography-row-enabled? current-token-name) + [:> token-typography-row* {:token-name current-token-name + :detach-token detach-token + :active-tokens (resolve-delay typography-tokens)}] - :else - [:> text-options* common-props]) + (= typography-id :multiple) + [:div {:class (stl/css :multiple-typography)} + [:span {:class (stl/css :multiple-text)} + (tr "workspace.libraries.text.mixed-typography")] + [:> icon-button* {:variant "ghost" + :aria-label (tr "workspace.libraries.text.multiple-assets-tooltip") + :on-click handle-detach-typography + :tooltip-placement "top-left" + :icon i/detach}]] - [:div {:class (stl/css :text-align-options)} - [:> text-align-options* common-props] - [:> grow-options* common-props] - [:> icon-button* {:variant "ghost" - :aria-label (tr "labels.options") - :data-testid "text-align-options-button" - :on-click toggle-more-options - :icon i/menu}]] + typography + [:> typography-entry* {:file-id typography-file-id + :typography typography + :is-local (= typography-file-id file-id) + :on-detach handle-detach-typography + :on-change handle-change-typography}] - (when more-options-open? - [:* + :else + [:> text-options* common-props]) + + [:div {:class (stl/css :text-align-options)} + [:> text-align-options* common-props] + [:> grow-options* common-props] + [:> icon-button* {:variant "ghost" + :aria-label (tr "labels.options") + :data-testid "text-align-options-button" + :on-click toggle-more-options + :icon i/menu}]] + + (when more-options-open? [:div {:class (stl/css :text-decoration-options)} [:> vertical-align* common-props] [:> text-decoration-options* (mf/spread-props common-props {:token-applied current-token-name})] - [:> text-direction-options* common-props]] + [:> text-direction-options* common-props]])])] + + (when japanese-layout-config-enabled? + [:section {:class (stl/css :element-set) + :aria-label (tr "workspace.options.text-options.japanese-layout")} + [:div {:class (stl/css :element-title)} + [:> title-bar* {:collapsable true + :collapsed (not japanese-layout-open?) + :on-collapsed toggle-japanese-layout + :title (tr "workspace.options.text-options.japanese-layout") + :class (stl/css :title-spacing-text)}]] + (when japanese-layout-open? + [:div {:class (stl/css :element-content)} [:> tjl/japanese-layout-options* japanese-layout-props]])])])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text_japanese_layout.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text_japanese_layout.cljs index b2c19e28f5..fe3779156f 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text_japanese_layout.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text_japanese_layout.cljs @@ -8,7 +8,7 @@ (:require-macros [app.main.style :as stl]) (:require [app.common.data :as d] - [app.main.features :as features] + [app.common.types.file :as ctf] [app.main.ui.components.title-bar :refer [title-bar*]] [app.main.ui.ds.buttons.icon-button :refer [icon-button*]] [app.main.ui.ds.controls.input :refer [input*]] @@ -71,6 +71,13 @@ (#{"horizontal-tb" "vertical-rl"} writing-mode) true :else false))) +(defn japanese-layout-config-enabled? + "Japanese layout controls are available when enabled for the current file or + globally in the user's profile." + [file-data profile] + (or (ctf/japanese-layout-enabled? file-data) + (true? (get-in profile [:props :japanese-layout-all-files])))) + (defn japanese-layout-toggle-attrs "Attrs emitted by the Japanese layout switch. A nil writing mode removes the persisted paragraph attribute, restoring the normal horizontal default." @@ -136,7 +143,7 @@ [:div {:class (stl/css :japanese-layout-toggle)} [:> switch* {:default-checked enabled - :label (tr "workspace.options.text-options.japanese-layout") + :label (tr "workspace.options.text-options.japanese-layout-enable-for-text") :on-change handle-change}]])) (mf/defc writing-mode-options* @@ -330,6 +337,26 @@ :on-change on-change :on-blur on-blur})) +(mf/defc ruby-hidden-option* + [{:keys [values on-change on-blur]}] + (let [value (:ruby-hidden values) + enabled? (cond + (mixed-span-value? value) nil + (true? value) true + :else false) + label (tr "workspace.options.text-options.ruby-hidden") + handle-change + (mf/use-fn + (mf/deps on-change on-blur) + (fn [checked?] + (on-change {:ruby-hidden checked?}) + (when (some? on-blur) (on-blur))))] + [:div {:class (stl/css :ruby-hidden-option :japanese-select-option)} + [:span {:class (stl/css :japanese-option-label)} label] + [:> switch* {:default-checked enabled? + :aria-label label + :on-change handle-change}]])) + (mf/defc ruby-customization-options* [{:keys [values on-change on-blur]}] (let [common-props (ruby-common-props values on-change on-blur) @@ -345,6 +372,7 @@ side-options [{:id "over" :label (tr "workspace.options.text-options.ruby-side-over")} {:id "under" :label (tr "workspace.options.text-options.ruby-side-under")}]] [:div {:class (stl/css :japanese-layout-controls)} + [:> ruby-hidden-option* common-props] [:> ruby-select-option* (mf/spread-props common-props {:attr :ruby-size :default-value "half" @@ -530,13 +558,10 @@ :options options :on-change handle-change}]])) - - (mf/defc japanese-layout-options* [{:keys [ids values ruby-values text-selection-active on-change on-ruby-presentation-change on-blur]}] - (let [enabled? (features/use-feature "japanese-layout/v1") - selection-key (hash ids) + (let [selection-key (hash ids) previous-selection-key-ref (mf/use-ref selection-key) active* (mf/use-state #(japanese-layout-enabled? values)) active? (deref active*) @@ -564,28 +589,26 @@ selection-changed?)) (mf/set-ref-val! previous-selection-key-ref selection-key))) - (when ^boolean enabled? - [:div {:class (stl/css :japanese-layout-options)} - [:> japanese-layout-toggle* toggle-props] - (when ^boolean active? - [:div {:class (stl/css :japanese-layout-controls)} - [:div {:class (stl/css :japanese-icon-options)} - [:> writing-mode-options* common-props] - (when ^boolean vertical? - [:* - [:> text-orientation-options* common-props] - [:> text-combine-upright-options* - (mf/spread-props common-props - {:text-selection-active text-selection-active})]]) - (when ^boolean text-selection-active - [:> warichu-options* common-props])] - (when ^boolean vertical? - [:> text-combine-upright-count-options* common-props]) - [:> font-features-options* common-props] - (when ^boolean text-selection-active - [:> text-emphasis-options* common-props]) - [:> annotation-clearance-options* common-props] - (if text-selection-active - [:> ruby-advanced-options* common-props] - [:> ruby-presentation-options* ruby-presentation-props])])]))) - + [:div {:class (stl/css :japanese-layout-options)} + [:> japanese-layout-toggle* toggle-props] + (when ^boolean active? + [:div {:class (stl/css :japanese-layout-controls)} + [:div {:class (stl/css :japanese-icon-options)} + [:> writing-mode-options* common-props] + (when ^boolean vertical? + [:* + [:> text-orientation-options* common-props] + [:> text-combine-upright-options* + (mf/spread-props common-props + {:text-selection-active text-selection-active})]]) + (when ^boolean text-selection-active + [:> warichu-options* common-props])] + (when ^boolean vertical? + [:> text-combine-upright-count-options* common-props]) + [:> font-features-options* common-props] + (when ^boolean text-selection-active + [:> text-emphasis-options* common-props]) + [:> annotation-clearance-options* common-props] + (if text-selection-active + [:> ruby-advanced-options* common-props] + [:> ruby-presentation-options* ruby-presentation-props])])])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text_japanese_layout.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text_japanese_layout.scss index ce77246a82..1211c32e68 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text_japanese_layout.scss +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text_japanese_layout.scss @@ -55,8 +55,7 @@ } .japanese-layout-options { - padding-block-start: var(--sp-xs); - border-block-start: $b-1 solid var(--color-background-quaternary); + padding-block: var(--sp-xs); } .japanese-layout-toggle { @@ -65,6 +64,10 @@ min-block-size: $sz-32; } +.ruby-hidden-option { + min-block-size: $sz-32; +} + .japanese-icon-options { display: flex; flex-wrap: wrap; diff --git a/frontend/src/app/render_wasm/api.cljs b/frontend/src/app/render_wasm/api.cljs index 215e852f05..6b394bcb5e 100644 --- a/frontend/src/app/render_wasm/api.cljs +++ b/frontend/src/app/render_wasm/api.cljs @@ -91,7 +91,6 @@ (def ^:private snapshot-capture-debounce-ms 250) - (defn initialized? "True when the WASM render context is ready to receive design-state operations. Use it to skip WASM work during transient states (e.g. while @@ -99,7 +98,6 @@ [] (and wasm/context-initialized? (not @wasm/context-lost?))) - (defn set-transition-image-from-background! "Sets `transition-image*` to a data URL representing a solid background color." [background] @@ -511,7 +509,6 @@ (when (initialized?) (h/call wasm/internal-module "_render_preview"))) - (defonce pending-render (atom false)) (defonce shapes-loading? (atom false)) (defonce deferred-render? (atom false)) @@ -735,7 +732,6 @@ [string] (+ (count string) 1)) - (defn- get-texture-id-for-gl-object "Registers a WebGL texture with Emscripten's GL object system and returns its ID" [texture] @@ -1666,7 +1662,6 @@ noop-fn)))))))] (process-next-chunk 0 [] [] [])))))) - ;; This is a version of process-pending that doesn't have sideffects ;; with like request render or update layout. (defn- process-pending-no-sideffects @@ -1859,7 +1854,6 @@ heapu32 (mem/get-heap-u32) heapf32 (mem/get-heap-f32)] - (reduce (fn [offset {:keys [type parent id index value]}] (-> offset (mem.h32/write-u32 heapu32 (sr/translate-structure-modifier-type type)) @@ -2537,7 +2531,11 @@ [element _start-pos _end-pos] (let [text (:text element) ruby (:ruby element)] - (when (and (string? text) (seq text) (string? ruby) (seq ruby)) + (when (and (not (true? (:ruby-hidden element))) + (string? text) + (seq text) + (string? ruby) + (seq ruby)) ruby))) (defn- ruby-strip-entry @@ -2546,7 +2544,8 @@ gutter placement the canvas paints." [element {:keys [start-pos end-pos x y width height]}] (let [ruby (get element :ruby)] - (when (string? ruby) + (when (and (not (true? (:ruby-hidden element))) + (string? ruby)) (let [text (subs ruby (min start-pos (count ruby)) (min end-pos (count ruby))) @@ -2655,7 +2654,10 @@ (when (= "auto" clearance) clearance)) :annotation-has-ruby (let [ruby (get element :ruby)] - (when (and (string? ruby) (seq ruby)) true)) + (when (and (not (true? (:ruby-hidden element))) + (string? ruby) + (seq ruby)) + true)) ;; Horizontal position data has no separate ruby ;; strip, so carry the annotation on the base entry ;; for static SVG export. Vertical ruby has its own diff --git a/frontend/src/app/render_wasm/api/texts.cljs b/frontend/src/app/render_wasm/api/texts.cljs index 5780e26640..36945ae13b 100644 --- a/frontend/src/app/render_wasm/api/texts.cljs +++ b/frontend/src/app/render_wasm/api/texts.cljs @@ -50,7 +50,6 @@ padding-fills (max 0 (- MAX-TEXT-FILLS (count fills)))] (+ new-ofset (* padding-fills types.fills.impl/FILL-U8-SIZE)))) - (defn- write-paragraph [offset dview paragraph] (let [text-align (sr/translate-text-align (get paragraph :text-align)) @@ -100,7 +99,9 @@ text-buffer (encode-text (get span :text "")) text-length (mem/size text-buffer) - ruby-buffer (encode-text (get span :ruby "")) + ruby-buffer (encode-text (if (true? (:ruby-hidden span)) + "" + (get span :ruby ""))) ruby-length (mem/size ruby-buffer) fills (take MAX-TEXT-FILLS (get span :fills [])) @@ -206,7 +207,10 @@ text-buffer (encode-text text) text-size (mem/size text-buffer) - ruby-text (apply str (map #(get % :ruby "") normalized-spans)) + ruby-text (apply str (map #(if (true? (:ruby-hidden %)) + "" + (get % :ruby "")) + normalized-spans)) ruby-buffer (encode-text ruby-text) ruby-size (mem/size ruby-buffer) diff --git a/frontend/src/app/render_wasm/text_editor.cljs b/frontend/src/app/render_wasm/text_editor.cljs index caf3db6cf2..3f99769390 100644 --- a/frontend/src/app/render_wasm/text_editor.cljs +++ b/frontend/src/app/render_wasm/text_editor.cljs @@ -648,6 +648,7 @@ {:text-combine-upright "none" :text-emphasis "none" :ruby "" + :ruby-hidden false :ruby-size "half" :ruby-align "space-around" :ruby-overhang "auto" diff --git a/frontend/src/app/util/text/content/styles.cljs b/frontend/src/app/util/text/content/styles.cljs index a832c009cd..bd7f4b5550 100644 --- a/frontend/src/app/util/text/content/styles.cljs +++ b/frontend/src/app/util/text/content/styles.cljs @@ -23,6 +23,12 @@ (def mapping {:fills [encode decode] :ruby [identity #(when-not (= "" %) %)] + :ruby-hidden [(fn [value] (when (some? value) (str value))) + (fn [value] + (case value + "true" true + "false" false + nil))] :ruby-size [identity #(when-not (= "" %) %)] :ruby-align [identity #(when-not (= "" %) %)] :ruby-overhang [identity #(when-not (= "" %) %)] diff --git a/frontend/test/frontend_tests/render_wasm/texts_test.cljs b/frontend/test/frontend_tests/render_wasm/texts_test.cljs index 7d9c008b56..91127b70a9 100644 --- a/frontend/test/frontend_tests/render_wasm/texts_test.cljs +++ b/frontend/test/frontend_tests/render_wasm/texts_test.cljs @@ -46,6 +46,7 @@ (t/is (= {:text-combine-upright "none" :text-emphasis "filled-dot" :ruby "にち" + :ruby-hidden false :ruby-size "half" :ruby-align "space-around" :ruby-overhang "auto" @@ -58,6 +59,7 @@ (t/is (= {:text-combine-upright "none" :text-emphasis "none" :ruby "" + :ruby-hidden false :ruby-size "half" :ruby-align "space-around" :ruby-overhang "auto" @@ -74,17 +76,20 @@ :text-combine-upright "digits2" :text-emphasis "filled-dot" :ruby "へいせい" + :ruby-hidden true :ruby-size "third" :ruby-align "center" :ruby-overhang "none" :ruby-side "under" :annotation-clearance "auto"} {:text "年" + :ruby-hidden false :warichu "warichu" :font-features "vpal"}])] (t/is (= {:text-combine-upright :multiple :text-emphasis :multiple :ruby :multiple + :ruby-hidden :multiple :ruby-size :multiple :ruby-align :multiple :ruby-overhang :multiple @@ -181,6 +186,27 @@ (t/is (= [2 3 1 1 0 0] (mapv #(.getUint8 dview %) (range 10 16)))))) +(t/deftest write-spans-omits-hidden-ruby-bytes + (let [buffer (js/ArrayBuffer. 256) + dview (js/DataView. buffer) + paragraph {:font-size "16" + :font-weight "400" + :line-height "1"}] + (write-spans 0 dview [{:text "日" + :ruby "にち" + :ruby-hidden true + :font-size "16" + :font-weight "400"}] + paragraph) + (t/is (= 0 (.getInt32 dview 72 true))) + (write-spans 0 dview [{:text "日" + :ruby "にち" + :ruby-hidden false + :font-size "16" + :font-weight "400"}] + paragraph) + (t/is (pos? (.getInt32 dview 72 true))))) + (t/deftest write-spans-serializes-counted-digits-tcy (let [sentinel (js-obj) previous (if (.hasOwnProperty wasm/serializers "text-combine-upright") diff --git a/frontend/test/frontend_tests/ui/text_options_test.cljs b/frontend/test/frontend_tests/ui/text_options_test.cljs index ca4c830b7c..4cfb230e6a 100644 --- a/frontend/test/frontend_tests/ui/text_options_test.cljs +++ b/frontend/test/frontend_tests/ui/text_options_test.cljs @@ -9,6 +9,7 @@ ["react-dom/server" :as rds] [app.main.data.workspace.texts :as dwt] [app.main.ui.ds.controls.select :as select] + [app.main.ui.shapes.text.html-text :as html-text] [app.main.ui.shapes.text.styles :as text-styles] [app.main.ui.workspace.sidebar.options.menus.text-japanese-layout :as tjl] [app.util.text.content.styles :as content-styles] @@ -20,6 +21,7 @@ [:text-combine-upright :text-emphasis :ruby + :ruby-hidden :ruby-size :ruby-align :ruby-overhang @@ -34,6 +36,18 @@ (def ^:private with-mixed-span-option @#'tjl/with-mixed-span-option) (def ^:private ruby-common-props @#'tjl/ruby-common-props) +(t/deftest japanese-layout-controls-follow-file-or-profile-configuration + (t/is (false? (tjl/japanese-layout-config-enabled? {} {}))) + (t/is (true? (tjl/japanese-layout-config-enabled? + {:options {:japanese-layout true}} + {}))) + (t/is (true? (tjl/japanese-layout-config-enabled? + {} + {:props {:japanese-layout-all-files true}}))) + (t/is (true? (tjl/japanese-layout-config-enabled? + {:options {:japanese-layout true}} + {:props {:japanese-layout-all-files false}})))) + (t/deftest text-emphasis-select-reports-and-restores-canonical-values (let [options (tjl/text-emphasis-options identity) reported-id (:id (select/get-option options "filled-dot"))] @@ -71,6 +85,27 @@ (t/is (str/includes? markup "aria-expanded=\"false\"")) (t/is (str/includes? markup "workspace.options.text-options.ruby-advanced-options")))) +(t/deftest advanced-furigana-options-include-hide-toggle + (let [markup (rds/renderToStaticMarkup + (mf/element tjl/ruby-customization-options* + #js {:values {:ruby-hidden true} + :on-change identity + :on-blur identity}))] + (t/is (str/includes? markup "workspace.options.text-options.ruby-hidden")) + (t/is (str/includes? markup "role=\"switch\"")) + (t/is (str/includes? markup "aria-checked=\"true\"")))) + +(t/deftest hidden-furigana-renders-base-text-without-ruby-layout + (let [markup (rds/renderToStaticMarkup + (mf/element html-text/render-text* + #js {:node {:text "日" + :ruby "にち" + :ruby-hidden true} + :parent {} + :shape {}}))] + (t/is (str/includes? markup ">日")) + (t/is (not (str/includes? markup "attrs {"text-combine-upright" "digits 3"})))) +(t/deftest hidden-furigana-round-trips-through-editor-styles + (t/is (= "true" + (unchecked-get + (content-styles/attrs->styles {:ruby-hidden true}) + "--ruby-hidden"))) + (t/is (= {:ruby-hidden false} + (content-styles/styles->attrs {"--ruby-hidden" "false"}))) + (t/is (= {:ruby-hidden nil} + (content-styles/styles->attrs {"--ruby-hidden" ""})))) + (t/deftest japanese-layout-is-explicitly-enabled-by-writing-mode (t/is (false? (tjl/japanese-layout-enabled? {}))) (t/is (false? (tjl/japanese-layout-enabled? {:writing-mode nil}))) diff --git a/frontend/translations/en.po b/frontend/translations/en.po index d9500c9e74..463df36f3f 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -1320,6 +1320,18 @@ msgstr "Unpublish Library" msgid "dashboard.update-settings" msgstr "Update settings" +#: src/app/main/ui/settings/options.cljs +msgid "dashboard.japanese-layout.description" +msgstr "Makes Japanese text layout controls available in every file." + +#: src/app/main/ui/settings/options.cljs +msgid "dashboard.japanese-layout.enable-all-files" +msgstr "Enable Japanese text layout for all files" + +#: src/app/main/ui/settings/options.cljs +msgid "dashboard.japanese-layout.title" +msgstr "Japanese text layout" + #: src/app/main/ui/dashboard/sidebar.cljs:1328 msgid "dashboard.upgrade-plan.no-limits" msgstr "No limits on creativity" @@ -6724,6 +6736,10 @@ msgstr "Disable snap to pixel" msgid "workspace.header.menu.disable-snap-ruler-guides" msgstr "Disable snap to ruler guides" +#: src/app/main/ui/workspace/main_menu.cljs +msgid "workspace.header.menu.disable-japanese-layout" +msgstr "Disable Japanese text layout" + #: src/app/main/ui/workspace/main_menu.cljs:336 msgid "workspace.header.menu.disable-webgl" msgstr "Disable WebGL rendering (beta)" @@ -6732,6 +6748,10 @@ msgstr "Disable WebGL rendering (beta)" msgid "workspace.header.menu.enable-dynamic-alignment" msgstr "Enable dynamic alignment" +#: src/app/main/ui/workspace/main_menu.cljs +msgid "workspace.header.menu.enable-japanese-layout" +msgstr "Enable Japanese text layout" + #: src/app/main/ui/workspace/main_menu.cljs:250 msgid "workspace.header.menu.enable-scale-content" msgstr "Enable proportional scale" @@ -8522,6 +8542,10 @@ msgstr "Normal" msgid "workspace.options.text-options.japanese-layout" msgstr "Japanese text layout" +#: src/app/main/ui/workspace/sidebar/options/menus/text_japanese_layout.cljs +msgid "workspace.options.text-options.japanese-layout-enable-for-text" +msgstr "Enable for this text" + #: src/app/main/ui/workspace/sidebar/options/menus/text.cljs msgid "workspace.options.text-options.text-combine-upright-all" msgstr "Tate-chu-yoko" @@ -8626,6 +8650,10 @@ msgstr "Furigana" msgid "workspace.options.text-options.ruby-advanced-options" msgstr "Advanced furigana options" +#: src/app/main/ui/workspace/sidebar/options/menus/text_japanese_layout.cljs +msgid "workspace.options.text-options.ruby-hidden" +msgstr "Hide furigana" + #: src/app/main/ui/workspace/sidebar/options/menus/text.cljs msgid "workspace.options.text-options.ruby-size" msgstr "Ruby size" @@ -10301,4 +10329,4 @@ msgid "workspace.viewport.click-to-close-path" msgstr "Click to close the path" msgid "notifications.invitation-canceled" -msgstr "This invitation is no longer available." \ No newline at end of file +msgstr "This invitation is no longer available." diff --git a/frontend/translations/jpn_JP.po b/frontend/translations/jpn_JP.po index 9a312ab4bf..c75ffc9b9c 100644 --- a/frontend/translations/jpn_JP.po +++ b/frontend/translations/jpn_JP.po @@ -992,6 +992,10 @@ msgstr "通常" msgid "workspace.options.text-options.japanese-layout" msgstr "日本語組版" +#: src/app/main/ui/workspace/sidebar/options/menus/text_japanese_layout.cljs +msgid "workspace.options.text-options.japanese-layout-enable-for-text" +msgstr "このテキストで有効にする" + #: src/app/main/ui/workspace/sidebar/options/menus/text.cljs msgid "workspace.options.text-options.text-combine-upright-all" msgstr "縦中横" @@ -1096,6 +1100,10 @@ msgstr "ふりがな" msgid "workspace.options.text-options.ruby-advanced-options" msgstr "ふりがなの詳細設定" +#: src/app/main/ui/workspace/sidebar/options/menus/text_japanese_layout.cljs +msgid "workspace.options.text-options.ruby-hidden" +msgstr "ふりがなを非表示" + #: src/app/main/ui/workspace/sidebar/options/menus/text.cljs msgid "workspace.options.text-options.ruby-size" msgstr "ルビの大きさ" @@ -1171,3 +1179,23 @@ msgstr "横書き" #: src/app/main/ui/workspace/sidebar/options/menus/text.cljs msgid "workspace.options.text-options.writing-mode-vertical" msgstr "縦書き(右から左)" + +#: src/app/main/ui/settings/options.cljs +msgid "dashboard.japanese-layout.description" +msgstr "すべてのファイルで日本語組版コントロールを利用できるようにします。" + +#: src/app/main/ui/settings/options.cljs +msgid "dashboard.japanese-layout.enable-all-files" +msgstr "すべてのファイルで日本語組版を有効にする" + +#: src/app/main/ui/settings/options.cljs +msgid "dashboard.japanese-layout.title" +msgstr "日本語組版" + +#: src/app/main/ui/workspace/main_menu.cljs +msgid "workspace.header.menu.disable-japanese-layout" +msgstr "日本語組版を無効にする" + +#: src/app/main/ui/workspace/main_menu.cljs +msgid "workspace.header.menu.enable-japanese-layout" +msgstr "日本語組版を有効にする"