181 lines
6.0 KiB
Julia
181 lines
6.0 KiB
Julia
function translation_file(translations; interpolation = false)
|
|
interpolate = "String fill(List<Object> params) => localizeFill(this, params);"
|
|
"""import 'package:i18n_extension/i18n_extension.dart';
|
|
|
|
extension Localization on String {
|
|
|
|
static var _t = Translations.byLocale("en_us") +
|
|
{
|
|
$(translations)
|
|
};
|
|
$(interpolation ? interpolate : "")
|
|
String get i18n => localize(this, _t);
|
|
}
|
|
"""
|
|
end
|
|
|
|
placeholder(n; place = "STRING") = string(place, "#", string(n, pad=20))
|
|
function extract(regex, content)
|
|
placeholders = Dict()
|
|
for (idx, interp) in enumerate(eachmatch(regex, content))
|
|
holder = placeholder(idx, place = "INTERPOLATION")
|
|
placeholders[holder] = interp.match
|
|
end
|
|
placeholders
|
|
end
|
|
|
|
function replace_extracted(content, placeholders)
|
|
inv = Dict(map((p) -> p[2] => p[1], collect(placeholders)))
|
|
# for placeholder in keys(placeholder)
|
|
for key in keys(inv)
|
|
content = replace(content, key => inv[key])
|
|
end
|
|
content
|
|
end
|
|
|
|
function find_all_strings(basepath, filepath)
|
|
content = read(joinpath(basepath, filepath), String)
|
|
# String interpolation ${} can contain anything (including unescaped strings)
|
|
# So it's better to extract it before doing anything
|
|
# Replace them with identifiers
|
|
placeholders = extract(r"(\$\{.*?\}|\$[A-Za-z][A-Za-z0-9]*)", content)
|
|
content = replace_extracted(content, placeholders)
|
|
# interpolations = replace(content, r"${.*}" => )
|
|
matches =
|
|
eachmatch(r"""(?P<quote>'''|'|")(?P<string>.+?)(?<!\\)\k<quote>(?P<i18n>\.i18n)?"""s, content)
|
|
# long_lines = [
|
|
# placeholder(i, place = "LONGDESCRIPTION") => a for (i, a) in
|
|
# filter(m -> occursin("\n", m.match), collect(matches)) |> enumerate
|
|
# ] |> Dict
|
|
# Now we need to find the lines of the matches.
|
|
(placeholders = placeholders,
|
|
matches = collect(matches),
|
|
content = content)
|
|
end
|
|
|
|
# function find_all_strings(basepath, filepath; i18n = true)
|
|
# content = read(joinpath(basepath, filepath), String)
|
|
# # Remove comments
|
|
# content = replace(content, r"""///?.*"""m => "")
|
|
# content = replace(content, r"""/\*.*?\*/"""s => "")
|
|
# # Remove imports/export
|
|
# content = replace(content, r"""(import|export|part) .*"""m => "")
|
|
# # Mark new lines to extract string positions
|
|
# lines = findall(x -> x == '\n', collect(content))
|
|
# # Find all types of strings
|
|
# # ? EXCLUDE PRINT?
|
|
# strings = eachmatch(r"""(['"])(.*?)\1(\.i18n)?""", content)
|
|
# out = []
|
|
# for string in strings
|
|
# (i18n && isnothing(string[3])) && continue
|
|
# # TODO: Interactively modify the source code to:
|
|
# # 1. Add the .i18n
|
|
# # 2. Include the file
|
|
# # Get the line of the match
|
|
# line = findfirst(line -> line >= string.offset, lines)
|
|
# push!(out, (file = filepath, line = line, strid = string[2]))
|
|
# end
|
|
# out
|
|
# end
|
|
|
|
dartfiles(files) = filter(f -> endswith(f, ".dart"), files)
|
|
function find_dart_files(path)
|
|
out = []
|
|
for (root, dirs, files) in walkdir(path)
|
|
for file in dartfiles(files)
|
|
push!(out, joinpath(root, file))
|
|
end
|
|
end
|
|
out
|
|
end
|
|
|
|
function find_all_strings(path)
|
|
no_i18n(files) = filter(f -> !endswith(f, "i18n.dart"), files)
|
|
excluded(files) = filter(f -> !(f in exclude), files)
|
|
path = realpath(path)
|
|
files = find_dart_files(path) |> no_i18n
|
|
find_all_strings.(Ref(path), files)
|
|
end
|
|
|
|
read_dart_project(path; exclude = []) = find_all_strings(path, exclude = exclude, i18n = true)
|
|
|
|
function i18n_project(path)
|
|
exc = ".i18n-excluded"
|
|
ign = ".i18n-ignored"
|
|
splitter = "\0¤\0"
|
|
ignored = isfile(ign) ? map(l -> split(l, splitter), readlines(ign)) : []
|
|
new_excludes = []
|
|
edits = []
|
|
adds = []
|
|
cd(path) do
|
|
exclude = isfile(exc) ? readlines(exc) : []
|
|
strings = vcat(find_all_strings(path; exclude = exclude, i18n = false)...)
|
|
files = map(s -> s.file, strings) |> unique
|
|
@info "You have a total of $(length(strings)) strings in $(length(files)) files"
|
|
@warn "!!!Remember to git commit before running this!!!"
|
|
for file in files
|
|
content = readlines(file)
|
|
@info "Inspecting file $(file)?"
|
|
for str in filter(s -> s.file == file, strings)
|
|
if !isnothing(findfirst(i -> i[1] == str.file &&
|
|
i[2] == string(str.line) &&
|
|
i[3] == str.strid, ignored))
|
|
continue
|
|
end
|
|
println("Line $(str.line): >$(str.strid)< ")
|
|
println(content[str.line])
|
|
println("[e]xclude, [a]dd, [c]hange, [i]gnore")
|
|
resp = ' '
|
|
while !(resp in ["e", "a", "c", "i"])
|
|
resp = readline(stdin)
|
|
end
|
|
if resp == "e"
|
|
push!(new_excludes, file)
|
|
break
|
|
elseif resp == "a"
|
|
push!(adds, str)
|
|
continue
|
|
elseif resp == "c"
|
|
push!(edits, str => readline(stdin))
|
|
elseif resp == "i"
|
|
open(ign, "a+") do f
|
|
println(f, join([str.file, str.line, str.strid], splitter))
|
|
end
|
|
continue
|
|
else
|
|
@error "Unknown problem"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
## Process changes
|
|
@warn "Applying changes in 3s... last chance to interrupt (Ctrl-C)"
|
|
sleep(3)
|
|
open(exc, "a+") do f
|
|
write(f, join(new_excludes, "\n"))
|
|
end
|
|
edits, adds
|
|
end
|
|
|
|
struct Translation
|
|
lang::String
|
|
msgstr::String
|
|
end
|
|
|
|
struct Translatable
|
|
msgid::String
|
|
translations::Array{Translation}
|
|
file::Union{String,Nothing}
|
|
line::Union{UInt,Nothing}
|
|
end
|
|
|
|
function dart_to_pot(path)
|
|
files = find_all_strings(path)
|
|
for file in files
|
|
i18n_s = filter(!isnothing, map(m -> m["i18n"], file.matches))
|
|
length(i18n_s) == 0 && continue
|
|
@show i18n_s
|
|
end
|
|
end
|
|
|