feat(ui): translate="no", and a title of several lines translated whole or line by line
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
7605a0253c
commit
6bd3228990
9 changed files with 76 additions and 1 deletions
|
|
@ -529,6 +529,9 @@ applies to both:
|
|||
|
||||
`ui_translator(fn)`, `ui_sounds(fn)` and `ui_clock(fn)` hand the runtime the program's
|
||||
language, sounds and time. `import "ludic.ui/screen.ludic"` is the 2D screen's renderer.
|
||||
Every text a template shows is translated, except inside `translate="no"` (and `translate="yes"`
|
||||
inside that translates again). A `title` of several lines is translated whole when the translator
|
||||
knows it whole, else line by line.
|
||||
- **The look is CSS.**
|
||||
- Colours: `#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`, `rgb()`, `rgba()` and the basic names,
|
||||
usually through `var(--...)` from a theme.
|
||||
|
|
|
|||
|
|
@ -100,6 +100,8 @@ What a game's screens found missing, now in `ludic.ui`:
|
|||
`ui_scroll_set(id, px)` moves one once;
|
||||
- `linear-gradient(...)` backgrounds; `aspect-ratio`; `object-fit` for pictures (the renderer's
|
||||
`image_w` / `image_h`) and `ui_object_fit` for natives;
|
||||
- `translate="no"` keeps an element's text as written; a title of several lines is translated whole,
|
||||
else line by line;
|
||||
- a transition lands exactly on its end value (it had stopped a rounding error short of it, at every
|
||||
frame rate).
|
||||
|
||||
|
|
|
|||
44
examples/library/ui_translate.ludic
Normal file
44
examples/library/ui_translate.ludic
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# ui_translate.ludic — translation: translate="no" keeps an element's text (and everything inside it)
|
||||
# as written, translate="yes" inside it translates again; a title of several lines is translated whole
|
||||
# when the translator knows it whole, else line by line, and not inside translate="no".
|
||||
import "ludic.ui"
|
||||
program UiTranslate {
|
||||
numbers float
|
||||
var said: []string = new []string
|
||||
var now: float = 0.0
|
||||
const PAGE: string = "<ui><screen name='t'><p>Hello</p><p translate='no'>Hello</p><div translate='no'><p>Hello</p><p translate='yes'>Hello</p></div><p class='a' title='Save\\nQuit'>a</p><p class='b' title='Line one\\nLine two'>b</p><div translate='no'><p class='c' title='Line one\\nLine two'>c</p></div></screen></ui>"
|
||||
function tr(s: string) -> string {
|
||||
if s == "Hello" { return "Merhaba" }
|
||||
if s == "Save\\nQuit" { return "Kaydet ve cik" }
|
||||
if s == "Line one" { return "Satir bir" }
|
||||
if s == "Line two" { return "Satir iki" }
|
||||
return s
|
||||
}
|
||||
function rec_text(x: float, y: float, s: string, size: float, c: int, a: float) -> void { push(said, s) }
|
||||
function clock() -> float { return now }
|
||||
function tip(root: UiNode, k: int) -> string {
|
||||
let n = root.children[k]
|
||||
let i = new UiInput
|
||||
i.x = n.x + 1.0
|
||||
i.y = n.y + 1.0
|
||||
ui_input(i)
|
||||
ui_show("t", null, 0.0, 0.0, 400.0, 400.0)
|
||||
now = now + 1.0
|
||||
said = new []string
|
||||
ui_input(i)
|
||||
ui_show("t", null, 0.0, 0.0, 400.0, 400.0)
|
||||
return `{said[len(said) - 2]}/{said[len(said) - 1]}`
|
||||
}
|
||||
entry {
|
||||
let b = new UiBackend
|
||||
b.text = fn rec_text
|
||||
ui_backend(b)
|
||||
ui_translator(fn tr)
|
||||
ui_clock(fn clock)
|
||||
ui_load_text(PAGE, "t.xml")
|
||||
let root: UiNode = ui_nodes("t", null)
|
||||
ui_place(root, 0.0, 0.0, 400.0, 400.0)
|
||||
let texts = `{root.children[0].text} {root.children[1].text} {root.children[2].children[0].text} {root.children[2].children[1].text}`
|
||||
print(`{texts} | {tip(root, 3)} | {tip(root, 4)} | {tip(root, 5)}`)
|
||||
}
|
||||
}
|
||||
|
|
@ -26,7 +26,9 @@ function ui_px(v: float) -> float {
|
|||
if ui_be != null and ui_be.scale != null { return v * ui_be.scale() }
|
||||
return v
|
||||
}
|
||||
var tr_no: bool = false # inside translate="no" while a frame is built
|
||||
function ui_tr(s: string) -> string {
|
||||
if tr_no { return s }
|
||||
if ui_be != null and ui_be.translate != null { return ui_be.translate(s) }
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,10 +24,14 @@ function bd_elem(k: UiTpl, e: UiEnv, key: string) -> UiNode {
|
|||
if k.on_keys[i] == "press" { n.act = k.on_acts[i] }
|
||||
}
|
||||
lc_note(key, k.on_keys, k.on_acts, e)
|
||||
let was_no = tr_no
|
||||
let say = ui_attr_text(n, "translate")
|
||||
if say == "no" { tr_no = true } else if say == "yes" { tr_no = false }
|
||||
bd_kids(k.kids, e, key, n.children)
|
||||
if k.text != null { el_text(n, ui_tr(ui_eval_text(k.text, e))) }
|
||||
el_inline(n)
|
||||
if k.tag == "input" or k.tag == "select" or k.tag == "progress" or k.tag == "meter" { ct_build(n) }
|
||||
tr_no = was_no
|
||||
return n
|
||||
}
|
||||
function el_kind(n: UiNode, tag: string) -> void {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import "popover.ludic"
|
|||
import "popover_anchor.ludic"
|
||||
import "popover_within.ludic"
|
||||
import "tooltip.ludic"
|
||||
import "tooltip_text.ludic"
|
||||
import "life.ludic"
|
||||
import "tpl.ludic"
|
||||
import "tpl_lines.ludic"
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ function tt_track(scope: UiNode, x: float, y: float) -> void {
|
|||
tt_key = n.key
|
||||
tt_since = an_now()
|
||||
}
|
||||
tt_text = ui_tr(ui_attr_text(n, "title"))
|
||||
tt_text = tt_translate(n, ui_attr_text(n, "title"))
|
||||
tt_x = x
|
||||
tt_y = y
|
||||
}
|
||||
|
|
|
|||
18
packages/ludic.ui/tooltip_text.ludic
Normal file
18
packages/ludic.ui/tooltip_text.ludic
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# tooltip_text.ludic - a title in the program's language: the whole of it when the translator knows
|
||||
# it, else line by line; and not at all inside translate="no" (the nearest translate= out from it)
|
||||
function tt_translate(n: UiNode, s: string) -> string {
|
||||
var at = n
|
||||
while at != null {
|
||||
let say = ui_attr_text(at, "translate")
|
||||
if say == "no" { return s }
|
||||
if say == "yes" { break }
|
||||
at = at.parent
|
||||
}
|
||||
let whole = ui_tr(s)
|
||||
if whole != s { return whole }
|
||||
let lines = tt_lines(s)
|
||||
if len(lines) < 2 { return whole }
|
||||
var out = ui_tr(lines[0])
|
||||
for i in 1 .. len(lines) { out = out + "\n" + ui_tr(lines[i]) }
|
||||
return out
|
||||
}
|
||||
|
|
@ -771,6 +771,7 @@ function cmd_dev_test() -> int {
|
|||
controller_case("library/ui_nine", "", "cap 0 12 18 30/ 0 8 8 16 | wide 0 12 88 100/ 0 12 28 40 | odd 10 21 21 31/ 4 8 8 13", "ui_nine.ludic (L11: a nine-slice's corners clamped to half the box each way, on whole pixels)")
|
||||
controller_case("library/ui_scroll_hold", "", "120 50 0 top 120 | 80 50 0 top 80 | 80 50 0 top 80 | 80 50 70 top 80 | 80 50 30 top 80", "ui_scroll_hold.ludic (L11: scroll-top holds a box at an offset, on-scroll follows the wheel, ui_scroll_set moves one once)")
|
||||
controller_case("library/ui_fill", "", "0,0 2x20 #030303 .. 98,0 2x20 #fcfcfc | 0,20 50x2 #f2000d .. 0,38 50x2 #0d00f2 .. 0,58 50x2 #0000ff of 70 | 0,85 100x50 | -50,160 200x100 clipped 1 | ratio 90 knob 60", "ui_fill.ludic (L11: linear-gradient backgrounds, object-fit contain and cover, aspect-ratio for boxes and natives)")
|
||||
controller_case("library/ui_translate", "", "Merhaba Hello Hello Merhaba | c/Kaydet ve cik | Satir bir/Satir iki | Line one/Line two", "ui_translate.ludic (L11: translate=no and yes, a title of several lines translated whole or line by line)")
|
||||
controller_case("library/ui_inputs", "", "count 12 12 32 0.5 0 | 20 32 0.5 0 | 19 32 0.5 0 | How many to carry | Space bar listening 1 19 9 0.5 0 | 19 9 0.5 0 | 19 0 0.5 0 | 60% 0.50 s | 19 0 0.6 9 | 7!", "ui_inputs.ludic (L11: number fields, key capture with Esc and Backspace, notes, range formats, an event named set, a string prop given a number)")
|
||||
controller_case("library/ui_boxes", "", "list 120 of 200 | text at 32 152 wide, 3 lines, row 60 | zero 0x0 | half 140x36 pad 4 2 | order abc at 16 | fill 98x8 of 200x12", "ui_boxes.ludic (L11: flex-shrink to the leftover room, text wrapping beside its siblings, zero sizes, calc(), order, the range track as a row)")
|
||||
controller_case("library/ui_look", "", "root div.in.i.m pad 5 margin 9 color #ff0000 text Hi 2,53 #102030 | text Hi 0,50 #eeeeee | opacity 0.25 | nine 40 #ffffff nine 40 #ff0000 of 2 image photo.png #ffffff | image icon:tent #00ff00 | text first line 29,205 #eeeeee | text second line 29,223 #eeeeee by id at 84,50 | flipped at 246,268 100x32", "ui_look.ludic (L11: nested components styled by specificity, text-shadow, ui_opacity, border-image tints, pictures, tooltip lines, anchored popovers)")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue