Skip to content

Commit

Permalink
veb: translations via %translation_key
Browse files Browse the repository at this point in the history
  • Loading branch information
medvednikov committed Oct 20, 2024
1 parent 1cf38ed commit 4ed9d13
Show file tree
Hide file tree
Showing 13 changed files with 115 additions and 15 deletions.
2 changes: 1 addition & 1 deletion cmd/tools/vast/vast.v
Original file line number Diff line number Diff line change
Expand Up @@ -1028,7 +1028,7 @@ fn (t Tree) comptime_call(node ast.ComptimeCall) &Node {
obj.add_terse('method_name', t.string_node(node.method_name))
obj.add_terse('left', t.expr(node.left))
obj.add_terse('is_vweb', t.bool_node(node.is_vweb))
obj.add_terse('vweb_tmpl', t.string_node(node.vweb_tmpl.path))
obj.add_terse('veb_tmpl', t.string_node(node.vweb_tmpl.path))
obj.add_terse('args_var', t.string_node(node.args_var))
obj.add_terse('has_parens', t.bool_node(node.has_parens))
obj.add_terse('is_embed', t.bool_node(node.is_embed))
Expand Down
1 change: 1 addition & 0 deletions vlib/orm/orm_insert_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ fn test_the_result_of_insert_should_be_the_last_insert_id() {
insert address into Address
} or { panic(err) }
dump(aid1)
assert aid1 == 1
aid2 := sql db {
insert address into Address
} or { panic(err) }
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/ast/ast.v
Original file line number Diff line number Diff line change
Expand Up @@ -1989,7 +1989,7 @@ pub:
mut:
is_d_resolved bool
pub mut:
vweb_tmpl File
veb_tmpl File
left Expr
left_type Type
result_type Type
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/checker/comptime.v
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
}
mut c2 := new_checker(c.table, pref2)
c2.comptime_call_pos = node.pos.pos
c2.check(mut node.vweb_tmpl)
c2.check(mut node.veb_tmpl)
c.warnings << c2.warnings
c.errors << c2.errors
c.notices << c2.notices
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/checker/errors.v
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ fn (mut c Checker) error(message string, pos token.Pos) {
mut msg := message.replace('`Array_', '`[]')
if c.pref.is_vweb {
// Show in which veb action the error occurred (for easier debugging)
veb_action := c.table.cur_fn.name.replace('vweb_tmpl_', '')
veb_action := c.table.cur_fn.name.replace('veb_tmpl_', '')
mut j := 0
for _, ch in veb_action {
if ch.is_digit() {
Expand Down
4 changes: 2 additions & 2 deletions vlib/v/gen/c/comptime.v
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ fn (mut g Gen) comptime_call(mut node ast.ComptimeCall) {
is_x_vweb := ret_sym.cname == 'x__vweb__Result'
is_veb := ret_sym.cname == 'veb__Result'

for stmt in node.vweb_tmpl.stmts {
for stmt in node.veb_tmpl.stmts {
if stmt is ast.FnDecl {
if stmt.name.starts_with('main.vweb_tmpl') {
if stmt.name.starts_with('main.veb_tmpl') {
if is_html {
g.inside_vweb_tmpl = true
if is_veb {
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/markused/walker.v
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ fn (mut w Walker) expr(node_ ast.Expr) {
ast.ComptimeCall {
w.expr(node.left)
if node.is_vweb {
w.stmts(node.vweb_tmpl.stmts)
w.stmts(node.veb_tmpl.stmts)
}
}
ast.DumpExpr {
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/parser/comptime.v
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
scope: unsafe { nil }
is_vweb: true
is_veb: is_veb
vweb_tmpl: file
veb_tmpl: file
method_name: method_name
args_var: literal_string_param
args: [arg]
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/parser/parse_type.v
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ fn (mut p Parser) parse_map_type() ast.Type {
return 0
}
if value_type.idx() == ast.void_type_idx {
p.error_with_pos('map value type cannot be void', p.tok.pos())
p.error_with_pos('map value type is missing: use `map[KeyType]ValueType`', p.tok.pos())
return 0
}
idx := p.table.find_or_register_map(key_type, value_type)
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/parser/tests/map_init_void.out
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
vlib/v/parser/tests/map_init_void.vv:2:18: error: map value type cannot be void
vlib/v/parser/tests/map_init_void.vv:2:18: error: map value type is missing: use `map[KeyType]ValueType`
1 | fn main() {
2 | m := map[string]{}
| ^
Expand Down
11 changes: 6 additions & 5 deletions vlib/v/parser/tmpl.v
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ fn is_html_open_tag(name string, s string) bool {

fn insert_template_code(fn_name string, tmpl_str_start string, line string) string {
// HTML, may include `@var`
// escaped by cgen, unless it's a `vweb.RawHtml` string
// escaped by cgen, unless it's a `veb.RawHtml` string
trailing_bs := tmpl_str_end + 'sb_${fn_name}.write_u8(92)\n' + tmpl_str_start
replace_pairs := ['\\', '\\\\', r"'", "\\'", r'@@', r'@', r'@', r'$', r'$$', r'\@']
mut rline := line.replace_each(replace_pairs)
Expand Down Expand Up @@ -225,8 +225,9 @@ pub fn (mut p Parser) compile_template_file(template_file string, fn_name string
mut source := strings.new_builder(1000)
source.writeln('
import strings
// === vweb html template ===
fn vweb_tmpl_${fn_name}() string {
import veb
// === veb html template ===
fn veb_tmpl_${fn_name}() string {
mut sb_${fn_name} := strings.new_builder(${lstartlength})\n
')
Expand Down Expand Up @@ -438,7 +439,7 @@ fn vweb_tmpl_${fn_name}() string {
key := line[pos + 1..end]
println('GOT tr key line="${line}" key="${key}"')
// source.writeln('\${tr("${key}")}')
line_ = line.replace('%${key}', '\${tr("${key}")}')
line_ = line.replace('%${key}', '\${veb.tr(ctx.lang.str(), "${key}")}')
// i += key.len
}
// println(source.str())
Expand All @@ -454,7 +455,7 @@ fn vweb_tmpl_${fn_name}() string {
source.writeln('\t_tmpl_res_${fn_name} := sb_${fn_name}.str() ')
source.writeln('\treturn _tmpl_res_${fn_name}')
source.writeln('}')
source.writeln('// === end of vweb html template_file: ${template_file} ===')
source.writeln('// === end of veb html template_file: ${template_file} ===')

result := source.str()
$if trace_tmpl_expansion ? {
Expand Down
95 changes: 95 additions & 0 deletions vlib/veb/tr.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module veb

import os

const tr_map = load_tr_map()

pub fn raw(s string) RawHtml {
return RawHtml(s)
}

/*
struct TrData {
data
}
m map[string]TrData
*/

// This function is run once, on app startup. Setting the `tr_map` const.
// m['en']['house'] == 'House'
fn load_tr_map() map[string]map[string]string {
// Find all translation files to figure out how many languages we have and to load the translation map
files := os.walk_ext('translations/', '.tr')
mut res := map[string]map[string]string{}
for tr_path in files {
lang := fetch_lang_from_tr_path(tr_path)
text := os.read_file(tr_path) or {
eprintln('translation file "${tr_path}" failed to laod')
return {}
}
x := text.split('-----\n')
for i, s in x {
// println('val="${val}"')
nl_pos := s.index('\n') or { continue }
key := s[..nl_pos]
val := s[nl_pos..]
// v := vals[i + 1]
// println('key="${key}" => val="${v}"')
res[lang][key] = val
// println(val)
}
}
return res
}

fn fetch_lang_from_tr_path(path string) string {
return path.find_between('/', '.')
}

// Used by %key in templates
pub fn tr(lang string, key string) string {
res := tr_map[lang][key]
if res == '' {
eprintln('NO TRANSLATION FOR KEY "${key}"')
return key
}
return RawHtml(res)
}

pub fn tr_plural(lang string, key string, amount int) string {
s := tr_map[lang][key]
if s == '' {
eprintln('NO TRANSLATION FOR KEY "${key}"')
return key
}
if s.contains('|') {
//-----
// goods
// товар|а|ов
vals := s.split('|')
if vals.len != 3 {
return s
}
amount_str := amount.str()
// 1, 21, 121 товар
ending := if amount % 10 == 1 && !amount_str.ends_with('11') { // vals[0]
''
// 2, 3, 4, 22 товара
} else if amount % 10 == 2 && !amount_str.ends_with('12') {
vals[1]
} else if amount % 10 == 3 && !amount_str.ends_with('13') {
vals[1]
} else if amount % 10 == 4 && !amount_str.ends_with('14') {
vals[1]
} else {
// 5 товаров, 11 товаров etc
vals[2]
}
return vals[0] + ending
} else {
return s
}
}
3 changes: 3 additions & 0 deletions vlib/veb/veb.v
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module veb

import io
Expand Down

0 comments on commit 4ed9d13

Please sign in to comment.