mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
Add script to extract translation strings
This commit is contained in:
parent
692ccd2e20
commit
c378ea403e
@ -436,7 +436,7 @@ process(_Handlers,
|
|||||||
?INPUT(<<"hidden">>, <<"scope">>, Scope),
|
?INPUT(<<"hidden">>, <<"scope">>, Scope),
|
||||||
?INPUT(<<"hidden">>, <<"state">>, State),
|
?INPUT(<<"hidden">>, <<"state">>, State),
|
||||||
?BR,
|
?BR,
|
||||||
?LABEL(<<"ttl">>, [?CT(<<"Token TTL">>), ?CT(<<": ">>)]),
|
?LABEL(<<"ttl">>, [?CT(<<"Token TTL">>), ?C(<<": ">>)]),
|
||||||
?XAE(<<"select">>, [{<<"name">>, <<"ttl">>}],
|
?XAE(<<"select">>, [{<<"name">>, <<"ttl">>}],
|
||||||
[
|
[
|
||||||
?XAC(<<"option">>, [{<<"value">>, <<"3600">>}],<<"1 Hour">>),
|
?XAC(<<"option">>, [{<<"value">>, <<"3600">>}],<<"1 Hour">>),
|
||||||
|
@ -974,10 +974,9 @@ roomconfig_to_string(Options, Lang, FileFormat) ->
|
|||||||
Os2 = lists:sort(Os1),
|
Os2 = lists:sort(Os1),
|
||||||
Options2 = Title ++ Os2,
|
Options2 = Title ++ Os2,
|
||||||
lists:foldl(fun ({Opt, Val}, R) ->
|
lists:foldl(fun ({Opt, Val}, R) ->
|
||||||
case get_roomconfig_text(Opt) of
|
case get_roomconfig_text(Opt, Lang) of
|
||||||
undefined -> R;
|
undefined -> R;
|
||||||
OptT ->
|
OptText ->
|
||||||
OptText = (?T(OptT)),
|
|
||||||
R2 = case Val of
|
R2 = case Val of
|
||||||
false ->
|
false ->
|
||||||
<<"<div class=\"rcod\">",
|
<<"<div class=\"rcod\">",
|
||||||
@ -1025,49 +1024,49 @@ roomconfig_to_string(Options, Lang, FileFormat) ->
|
|||||||
end,
|
end,
|
||||||
<<"">>, Options2).
|
<<"">>, Options2).
|
||||||
|
|
||||||
get_roomconfig_text(title) -> <<"Room title">>;
|
get_roomconfig_text(title, Lang) -> ?T(<<"Room title">>);
|
||||||
get_roomconfig_text(persistent) ->
|
get_roomconfig_text(persistent, Lang) ->
|
||||||
<<"Make room persistent">>;
|
?T(<<"Make room persistent">>);
|
||||||
get_roomconfig_text(public) ->
|
get_roomconfig_text(public, Lang) ->
|
||||||
<<"Make room public searchable">>;
|
?T(<<"Make room public searchable">>);
|
||||||
get_roomconfig_text(public_list) ->
|
get_roomconfig_text(public_list, Lang) ->
|
||||||
<<"Make participants list public">>;
|
?T(<<"Make participants list public">>);
|
||||||
get_roomconfig_text(password_protected) ->
|
get_roomconfig_text(password_protected, Lang) ->
|
||||||
<<"Make room password protected">>;
|
?T(<<"Make room password protected">>);
|
||||||
get_roomconfig_text(password) -> <<"Password">>;
|
get_roomconfig_text(password, Lang) -> ?T(<<"Password">>);
|
||||||
get_roomconfig_text(anonymous) ->
|
get_roomconfig_text(anonymous, Lang) ->
|
||||||
<<"This room is not anonymous">>;
|
?T(<<"This room is not anonymous">>);
|
||||||
get_roomconfig_text(members_only) ->
|
get_roomconfig_text(members_only, Lang) ->
|
||||||
<<"Make room members-only">>;
|
?T(<<"Make room members-only">>);
|
||||||
get_roomconfig_text(moderated) ->
|
get_roomconfig_text(moderated, Lang) ->
|
||||||
<<"Make room moderated">>;
|
?T(<<"Make room moderated">>);
|
||||||
get_roomconfig_text(members_by_default) ->
|
get_roomconfig_text(members_by_default, Lang) ->
|
||||||
<<"Default users as participants">>;
|
?T(<<"Default users as participants">>);
|
||||||
get_roomconfig_text(allow_change_subj) ->
|
get_roomconfig_text(allow_change_subj, Lang) ->
|
||||||
<<"Allow users to change the subject">>;
|
?T(<<"Allow users to change the subject">>);
|
||||||
get_roomconfig_text(allow_private_messages) ->
|
get_roomconfig_text(allow_private_messages, Lang) ->
|
||||||
<<"Allow users to send private messages">>;
|
?T(<<"Allow users to send private messages">>);
|
||||||
get_roomconfig_text(allow_private_messages_from_visitors) ->
|
get_roomconfig_text(allow_private_messages_from_visitors, Lang) ->
|
||||||
<<"Allow visitors to send private messages to">>;
|
?T(<<"Allow visitors to send private messages to">>);
|
||||||
get_roomconfig_text(allow_query_users) ->
|
get_roomconfig_text(allow_query_users, Lang) ->
|
||||||
<<"Allow users to query other users">>;
|
?T(<<"Allow users to query other users">>);
|
||||||
get_roomconfig_text(allow_user_invites) ->
|
get_roomconfig_text(allow_user_invites, Lang) ->
|
||||||
<<"Allow users to send invites">>;
|
?T(<<"Allow users to send invites">>);
|
||||||
get_roomconfig_text(logging) -> <<"Enable logging">>;
|
get_roomconfig_text(logging, Lang) -> ?T(<<"Enable logging">>);
|
||||||
get_roomconfig_text(allow_visitor_nickchange) ->
|
get_roomconfig_text(allow_visitor_nickchange, Lang) ->
|
||||||
<<"Allow visitors to change nickname">>;
|
?T(<<"Allow visitors to change nickname">>);
|
||||||
get_roomconfig_text(allow_visitor_status) ->
|
get_roomconfig_text(allow_visitor_status, Lang) ->
|
||||||
<<"Allow visitors to send status text in "
|
?T(<<"Allow visitors to send status text in "
|
||||||
"presence updates">>;
|
"presence updates">>);
|
||||||
get_roomconfig_text(captcha_protected) ->
|
get_roomconfig_text(captcha_protected, Lang) ->
|
||||||
<<"Make room captcha protected">>;
|
?T(<<"Make room captcha protected">>);
|
||||||
get_roomconfig_text(description) ->
|
get_roomconfig_text(description, Lang) ->
|
||||||
<<"Room description">>;
|
?T(<<"Room description">>);
|
||||||
%% get_roomconfig_text(subject) -> "Subject";
|
%% get_roomconfig_text(subject, Lang) -> "Subject";
|
||||||
%% get_roomconfig_text(subject_author) -> "Subject author";
|
%% get_roomconfig_text(subject_author, Lang) -> "Subject author";
|
||||||
get_roomconfig_text(max_users) ->
|
get_roomconfig_text(max_users, Lang) ->
|
||||||
<<"Maximum Number of Occupants">>;
|
?T(<<"Maximum Number of Occupants">>);
|
||||||
get_roomconfig_text(_) -> undefined.
|
get_roomconfig_text(_, _) -> undefined.
|
||||||
|
|
||||||
%% Users = [{JID, Nick, Role}]
|
%% Users = [{JID, Nick, Role}]
|
||||||
roomoccupants_to_string(Users, _FileFormat) ->
|
roomoccupants_to_string(Users, _FileFormat) ->
|
||||||
|
@ -2697,8 +2697,8 @@ find_changed_items(UJID, UAffiliation, URole,
|
|||||||
Nick /= <<"">> ->
|
Nick /= <<"">> ->
|
||||||
case find_jids_by_nick(Nick, StateData) of
|
case find_jids_by_nick(Nick, StateData) of
|
||||||
[] ->
|
[] ->
|
||||||
ErrText = str:format(<<"Nickname ~s does not exist in the room">>,
|
ErrText = {<<"Nickname ~s does not exist in the room">>,
|
||||||
[Nick]),
|
[Nick]},
|
||||||
throw({error, xmpp:err_not_acceptable(ErrText, Lang)});
|
throw({error, xmpp:err_not_acceptable(ErrText, Lang)});
|
||||||
JIDList ->
|
JIDList ->
|
||||||
JIDList
|
JIDList
|
||||||
|
@ -324,31 +324,31 @@ default_vcard_map() ->
|
|||||||
{<<"PHOTO">>, <<"%s">>, [<<"jpegPhoto">>]}].
|
{<<"PHOTO">>, <<"%s">>, [<<"jpegPhoto">>]}].
|
||||||
|
|
||||||
default_search_fields() ->
|
default_search_fields() ->
|
||||||
[{<<"User">>, <<"%u">>},
|
[{translate:mark(<<"User">>), <<"%u">>},
|
||||||
{<<"Full Name">>, <<"displayName">>},
|
{translate:mark(<<"Full Name">>), <<"displayName">>},
|
||||||
{<<"Given Name">>, <<"givenName">>},
|
{translate:mark(<<"Given Name">>), <<"givenName">>},
|
||||||
{<<"Middle Name">>, <<"initials">>},
|
{translate:mark(<<"Middle Name">>), <<"initials">>},
|
||||||
{<<"Family Name">>, <<"sn">>},
|
{translate:mark(<<"Family Name">>), <<"sn">>},
|
||||||
{<<"Nickname">>, <<"%u">>},
|
{translate:mark(<<"Nickname">>), <<"%u">>},
|
||||||
{<<"Birthday">>, <<"birthDay">>},
|
{translate:mark(<<"Birthday">>), <<"birthDay">>},
|
||||||
{<<"Country">>, <<"c">>},
|
{translate:mark(<<"Country">>), <<"c">>},
|
||||||
{<<"City">>, <<"l">>},
|
{translate:mark(<<"City">>), <<"l">>},
|
||||||
{<<"Email">>, <<"mail">>},
|
{translate:mark(<<"Email">>), <<"mail">>},
|
||||||
{<<"Organization Name">>, <<"o">>},
|
{translate:mark(<<"Organization Name">>), <<"o">>},
|
||||||
{<<"Organization Unit">>, <<"ou">>}].
|
{translate:mark(<<"Organization Unit">>), <<"ou">>}].
|
||||||
|
|
||||||
default_search_reported() ->
|
default_search_reported() ->
|
||||||
[{<<"Full Name">>, <<"FN">>},
|
[{translate:mark(<<"Full Name">>), <<"FN">>},
|
||||||
{<<"Given Name">>, <<"FIRST">>},
|
{translate:mark(<<"Given Name">>), <<"FIRST">>},
|
||||||
{<<"Middle Name">>, <<"MIDDLE">>},
|
{translate:mark(<<"Middle Name">>), <<"MIDDLE">>},
|
||||||
{<<"Family Name">>, <<"LAST">>},
|
{translate:mark(<<"Family Name">>), <<"LAST">>},
|
||||||
{<<"Nickname">>, <<"NICK">>},
|
{translate:mark(<<"Nickname">>), <<"NICK">>},
|
||||||
{<<"Birthday">>, <<"BDAY">>},
|
{translate:mark(<<"Birthday">>), <<"BDAY">>},
|
||||||
{<<"Country">>, <<"CTRY">>},
|
{translate:mark(<<"Country">>), <<"CTRY">>},
|
||||||
{<<"City">>, <<"LOCALITY">>},
|
{translate:mark(<<"City">>), <<"LOCALITY">>},
|
||||||
{<<"Email">>, <<"EMAIL">>},
|
{translate:mark(<<"Email">>), <<"EMAIL">>},
|
||||||
{<<"Organization Name">>, <<"ORGNAME">>},
|
{translate:mark(<<"Organization Name">>), <<"ORGNAME">>},
|
||||||
{<<"Organization Unit">>, <<"ORGUNIT">>}].
|
{translate:mark(<<"Organization Unit">>), <<"ORGUNIT">>}].
|
||||||
|
|
||||||
parse_options(Host, Opts) ->
|
parse_options(Host, Opts) ->
|
||||||
MyHosts = gen_mod:get_opt_hosts(Host, Opts, <<"vjud.@HOST@">>),
|
MyHosts = gen_mod:get_opt_hosts(Host, Opts, <<"vjud.@HOST@">>),
|
||||||
|
@ -95,32 +95,32 @@ search(LServer, Data, AllowReturnAll, MaxMatch) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
search_fields(_LServer) ->
|
search_fields(_LServer) ->
|
||||||
[{<<"User">>, <<"user">>},
|
[{translate:mark(<<"User">>), <<"user">>},
|
||||||
{<<"Full Name">>, <<"fn">>},
|
{translate:mark(<<"Full Name">>), <<"fn">>},
|
||||||
{<<"Name">>, <<"first">>},
|
{translate:mark(<<"Name">>), <<"first">>},
|
||||||
{<<"Middle Name">>, <<"middle">>},
|
{translate:mark(<<"Middle Name">>), <<"middle">>},
|
||||||
{<<"Family Name">>, <<"last">>},
|
{translate:mark(<<"Family Name">>), <<"last">>},
|
||||||
{<<"Nickname">>, <<"nick">>},
|
{translate:mark(<<"Nickname">>), <<"nick">>},
|
||||||
{<<"Birthday">>, <<"bday">>},
|
{translate:mark(<<"Birthday">>), <<"bday">>},
|
||||||
{<<"Country">>, <<"ctry">>},
|
{translate:mark(<<"Country">>), <<"ctry">>},
|
||||||
{<<"City">>, <<"locality">>},
|
{translate:mark(<<"City">>), <<"locality">>},
|
||||||
{<<"Email">>, <<"email">>},
|
{translate:mark(<<"Email">>), <<"email">>},
|
||||||
{<<"Organization Name">>, <<"orgname">>},
|
{translate:mark(<<"Organization Name">>), <<"orgname">>},
|
||||||
{<<"Organization Unit">>, <<"orgunit">>}].
|
{translate:mark(<<"Organization Unit">>), <<"orgunit">>}].
|
||||||
|
|
||||||
search_reported(_LServer) ->
|
search_reported(_LServer) ->
|
||||||
[{<<"Jabber ID">>, <<"jid">>},
|
[{translate:mark(<<"Jabber ID">>), <<"jid">>},
|
||||||
{<<"Full Name">>, <<"fn">>},
|
{translate:mark(<<"Full Name">>), <<"fn">>},
|
||||||
{<<"Name">>, <<"first">>},
|
{translate:mark(<<"Name">>), <<"first">>},
|
||||||
{<<"Middle Name">>, <<"middle">>},
|
{translate:mark(<<"Middle Name">>), <<"middle">>},
|
||||||
{<<"Family Name">>, <<"last">>},
|
{translate:mark(<<"Family Name">>), <<"last">>},
|
||||||
{<<"Nickname">>, <<"nick">>},
|
{translate:mark(<<"Nickname">>), <<"nick">>},
|
||||||
{<<"Birthday">>, <<"bday">>},
|
{translate:mark(<<"Birthday">>), <<"bday">>},
|
||||||
{<<"Country">>, <<"ctry">>},
|
{translate:mark(<<"Country">>), <<"ctry">>},
|
||||||
{<<"City">>, <<"locality">>},
|
{translate:mark(<<"City">>), <<"locality">>},
|
||||||
{<<"Email">>, <<"email">>},
|
{translate:mark(<<"Email">>), <<"email">>},
|
||||||
{<<"Organization Name">>, <<"orgname">>},
|
{translate:mark(<<"Organization Name">>), <<"orgname">>},
|
||||||
{<<"Organization Unit">>, <<"orgunit">>}].
|
{translate:mark(<<"Organization Unit">>), <<"orgunit">>}].
|
||||||
|
|
||||||
remove_user(LUser, LServer) ->
|
remove_user(LUser, LServer) ->
|
||||||
US = {LUser, LServer},
|
US = {LUser, LServer},
|
||||||
|
@ -150,32 +150,32 @@ search(LServer, Data, AllowReturnAll, MaxMatch) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
search_fields(_LServer) ->
|
search_fields(_LServer) ->
|
||||||
[{<<"User">>, <<"user">>},
|
[{translate:mark(<<"User">>), <<"user">>},
|
||||||
{<<"Full Name">>, <<"fn">>},
|
{translate:mark(<<"Full Name">>), <<"fn">>},
|
||||||
{<<"Name">>, <<"first">>},
|
{translate:mark(<<"Name">>), <<"first">>},
|
||||||
{<<"Middle Name">>, <<"middle">>},
|
{translate:mark(<<"Middle Name">>), <<"middle">>},
|
||||||
{<<"Family Name">>, <<"last">>},
|
{translate:mark(<<"Family Name">>), <<"last">>},
|
||||||
{<<"Nickname">>, <<"nick">>},
|
{translate:mark(<<"Nickname">>), <<"nick">>},
|
||||||
{<<"Birthday">>, <<"bday">>},
|
{translate:mark(<<"Birthday">>), <<"bday">>},
|
||||||
{<<"Country">>, <<"ctry">>},
|
{translate:mark(<<"Country">>), <<"ctry">>},
|
||||||
{<<"City">>, <<"locality">>},
|
{translate:mark(<<"City">>), <<"locality">>},
|
||||||
{<<"Email">>, <<"email">>},
|
{translate:mark(<<"Email">>), <<"email">>},
|
||||||
{<<"Organization Name">>, <<"orgname">>},
|
{translate:mark(<<"Organization Name">>), <<"orgname">>},
|
||||||
{<<"Organization Unit">>, <<"orgunit">>}].
|
{translate:mark(<<"Organization Unit">>), <<"orgunit">>}].
|
||||||
|
|
||||||
search_reported(_LServer) ->
|
search_reported(_LServer) ->
|
||||||
[{<<"Jabber ID">>, <<"jid">>},
|
[{translate:mark(<<"Jabber ID">>), <<"jid">>},
|
||||||
{<<"Full Name">>, <<"fn">>},
|
{translate:mark(<<"Full Name">>), <<"fn">>},
|
||||||
{<<"Name">>, <<"first">>},
|
{translate:mark(<<"Name">>), <<"first">>},
|
||||||
{<<"Middle Name">>, <<"middle">>},
|
{translate:mark(<<"Middle Name">>), <<"middle">>},
|
||||||
{<<"Family Name">>, <<"last">>},
|
{translate:mark(<<"Family Name">>), <<"last">>},
|
||||||
{<<"Nickname">>, <<"nick">>},
|
{translate:mark(<<"Nickname">>), <<"nick">>},
|
||||||
{<<"Birthday">>, <<"bday">>},
|
{translate:mark(<<"Birthday">>), <<"bday">>},
|
||||||
{<<"Country">>, <<"ctry">>},
|
{translate:mark(<<"Country">>), <<"ctry">>},
|
||||||
{<<"City">>, <<"locality">>},
|
{translate:mark(<<"City">>), <<"locality">>},
|
||||||
{<<"Email">>, <<"email">>},
|
{translate:mark(<<"Email">>), <<"email">>},
|
||||||
{<<"Organization Name">>, <<"orgname">>},
|
{translate:mark(<<"Organization Name">>), <<"orgname">>},
|
||||||
{<<"Organization Unit">>, <<"orgunit">>}].
|
{translate:mark(<<"Organization Unit">>), <<"orgunit">>}].
|
||||||
|
|
||||||
remove_user(LUser, LServer) ->
|
remove_user(LUser, LServer) ->
|
||||||
ejabberd_sql:sql_transaction(
|
ejabberd_sql:sql_transaction(
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
-behaviour(gen_server).
|
-behaviour(gen_server).
|
||||||
|
|
||||||
-export([start_link/0, reload/0, translate/2]).
|
-export([start_link/0, reload/0, translate/2, mark/1]).
|
||||||
%% gen_server callbacks
|
%% gen_server callbacks
|
||||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||||
terminate/2, code_change/3]).
|
terminate/2, code_change/3]).
|
||||||
@ -219,6 +219,10 @@ translate(Msg) ->
|
|||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
-spec mark(binary()) -> binary().
|
||||||
|
mark(Msg) ->
|
||||||
|
Msg.
|
||||||
|
|
||||||
ascii_tolower(B) ->
|
ascii_tolower(B) ->
|
||||||
iolist_to_binary(ascii_tolower_s(binary_to_list(B))).
|
iolist_to_binary(ascii_tolower_s(binary_to_list(B))).
|
||||||
|
|
||||||
|
232
tools/extract-tr.sh
Executable file
232
tools/extract-tr.sh
Executable file
@ -0,0 +1,232 @@
|
|||||||
|
#!/usr/bin/env escript
|
||||||
|
%% -*- erlang -*-
|
||||||
|
%%! -pa ebin
|
||||||
|
|
||||||
|
main([Dir]) ->
|
||||||
|
Txts =
|
||||||
|
filelib:fold_files(
|
||||||
|
Dir, ".+\.beam\$", false,
|
||||||
|
fun(FileIn, Res) ->
|
||||||
|
case get_forms(FileIn) of
|
||||||
|
{ok, Forms} ->
|
||||||
|
Tree = erl_syntax:form_list(Forms),
|
||||||
|
Mod = mod(FileIn),
|
||||||
|
erl_syntax_lib:fold_subtrees(
|
||||||
|
fun(Form, Acc) ->
|
||||||
|
case erl_syntax:type(Form) of
|
||||||
|
function ->
|
||||||
|
case map(Form, Mod) of
|
||||||
|
[] ->
|
||||||
|
Acc;
|
||||||
|
Vars ->
|
||||||
|
Vars ++ Acc
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
Acc
|
||||||
|
end
|
||||||
|
end, [], Tree) ++ Res;
|
||||||
|
_Err ->
|
||||||
|
Res
|
||||||
|
end
|
||||||
|
end, []),
|
||||||
|
Dict = lists:foldl(
|
||||||
|
fun({B, Meta}, Acc) ->
|
||||||
|
dict:update(
|
||||||
|
binary_to_list(B),
|
||||||
|
fun(OldMeta) ->
|
||||||
|
lists:usort([Meta|OldMeta])
|
||||||
|
end,
|
||||||
|
[Meta], Acc)
|
||||||
|
end, dict:new(), Txts),
|
||||||
|
generate_pot(Dict).
|
||||||
|
|
||||||
|
map(Tree, Mod) ->
|
||||||
|
Vars = erl_syntax_lib:fold(
|
||||||
|
fun(Form, Acc) ->
|
||||||
|
case erl_syntax:type(Form) of
|
||||||
|
application ->
|
||||||
|
analyze_app(Form, Mod) ++ Acc;
|
||||||
|
_ ->
|
||||||
|
Acc
|
||||||
|
end
|
||||||
|
end, [], Tree),
|
||||||
|
Bins = lists:flatmap(
|
||||||
|
fun({Var, Pos}) when is_atom(Var) ->
|
||||||
|
Res = erl_syntax_lib:fold(
|
||||||
|
fun(Form, Acc) ->
|
||||||
|
case process_match_expr(
|
||||||
|
Form, Var, Mod) of
|
||||||
|
{ok, Binary, NewPos} ->
|
||||||
|
[{Binary, NewPos}|Acc];
|
||||||
|
error ->
|
||||||
|
Acc
|
||||||
|
end
|
||||||
|
end, [], Tree),
|
||||||
|
case Res of
|
||||||
|
[] ->
|
||||||
|
log("~s:~p: unresolved variable: ~s~n",
|
||||||
|
[Mod, Pos, Var]);
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
end,
|
||||||
|
Res;
|
||||||
|
({Var, Pos}) when is_binary(Var) ->
|
||||||
|
[{Var, Pos}]
|
||||||
|
end, lists:usort(Vars)),
|
||||||
|
[{B, {Mod, Pos}} || {B, Pos} <- Bins, B /= <<"">>].
|
||||||
|
|
||||||
|
process_match_expr(Form, Var, Mod) ->
|
||||||
|
case erl_syntax:type(Form) of
|
||||||
|
match_expr ->
|
||||||
|
Pattern = erl_syntax:match_expr_pattern(Form),
|
||||||
|
Body = erl_syntax:match_expr_body(Form),
|
||||||
|
{V, Expr} =
|
||||||
|
case {erl_syntax:type(Pattern), erl_syntax:type(Body)} of
|
||||||
|
{variable, _} ->
|
||||||
|
{erl_syntax:variable_name(Pattern), Body};
|
||||||
|
{_, variable} ->
|
||||||
|
{erl_syntax:variable_name(Body), Pattern};
|
||||||
|
_ ->
|
||||||
|
{'', none}
|
||||||
|
end,
|
||||||
|
Text = maybe_extract_tuple(Expr),
|
||||||
|
if V == Var ->
|
||||||
|
Pos = erl_syntax:get_pos(Text),
|
||||||
|
try {ok, erl_syntax:concrete(Text), Pos}
|
||||||
|
catch _:_ ->
|
||||||
|
case catch erl_syntax_lib:analyze_application(Text) of
|
||||||
|
{_M, {Fn, 1}} when Fn == format_error;
|
||||||
|
Fn == io_format_error ->
|
||||||
|
error;
|
||||||
|
_ ->
|
||||||
|
log("~s:~p: not a binary: ~s~n",
|
||||||
|
[Mod, Pos, erl_prettypr:format(Text)]),
|
||||||
|
{ok, <<>>, Pos}
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
true ->
|
||||||
|
error
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
error
|
||||||
|
end.
|
||||||
|
|
||||||
|
maybe_extract_tuple(none) ->
|
||||||
|
none;
|
||||||
|
maybe_extract_tuple(Form) ->
|
||||||
|
try
|
||||||
|
tuple = erl_syntax:type(Form),
|
||||||
|
[Text, _] = erl_syntax:tuple_elements(Form),
|
||||||
|
Text
|
||||||
|
catch _:{badmatch, _} ->
|
||||||
|
Form
|
||||||
|
end.
|
||||||
|
|
||||||
|
analyze_app(Form, Mod) ->
|
||||||
|
try
|
||||||
|
{M, {F, A}} = erl_syntax_lib:analyze_application(Form),
|
||||||
|
Args = erl_syntax:application_arguments(Form),
|
||||||
|
Txt = case {M, atom_to_list(F), A, Args} of
|
||||||
|
{xmpp, "err_" ++ _, 2, [T|_]} -> T;
|
||||||
|
{xmpp, "serr_" ++ _, 2, [T|_]} -> T;
|
||||||
|
{xmpp, "mk_text", 2, [T|_]} -> T;
|
||||||
|
{translate, "translate", 2, [_,T|_]} -> T;
|
||||||
|
{translate, "mark", 1, [T]} -> T
|
||||||
|
end,
|
||||||
|
Pos = erl_syntax:get_pos(Txt),
|
||||||
|
case erl_syntax:type(Txt) of
|
||||||
|
binary ->
|
||||||
|
try [{erl_syntax:concrete(Txt), Pos}]
|
||||||
|
catch _:_ ->
|
||||||
|
Pos = erl_syntax:get_pos(Txt),
|
||||||
|
log("~s:~p: not a binary: ~s~n",
|
||||||
|
[Mod, Pos, erl_prettypr:format(Txt)]),
|
||||||
|
[]
|
||||||
|
end;
|
||||||
|
variable ->
|
||||||
|
[{erl_syntax:variable_name(Txt), Pos}];
|
||||||
|
application ->
|
||||||
|
Vars = sets:to_list(erl_syntax_lib:variables(Txt)),
|
||||||
|
case Vars of
|
||||||
|
[Var] ->
|
||||||
|
[{Var, Pos}];
|
||||||
|
[_|_] ->
|
||||||
|
log("Too many variables: ~p~n", [Vars]),
|
||||||
|
[];
|
||||||
|
[] ->
|
||||||
|
[]
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
catch _:{badmatch, _} ->
|
||||||
|
[];
|
||||||
|
_:{case_clause, _} ->
|
||||||
|
[]
|
||||||
|
end.
|
||||||
|
|
||||||
|
generate_pot(Dict) ->
|
||||||
|
io:format("~s~n~n", [pot_header()]),
|
||||||
|
lists:foreach(
|
||||||
|
fun({Msg, Location}) ->
|
||||||
|
S1 = format_location(Location),
|
||||||
|
S2 = format_msg(Msg),
|
||||||
|
io:format("~smsgstr \"\"~n~n", [S1 ++ S2])
|
||||||
|
end, lists:keysort(1, dict:to_list(Dict))).
|
||||||
|
|
||||||
|
format_location([A, B, C|T]) ->
|
||||||
|
format_location_list([A,B,C]) ++ format_location(T);
|
||||||
|
format_location([A, B|T]) ->
|
||||||
|
format_location_list([A,B]) ++ format_location(T);
|
||||||
|
format_location([A|T]) ->
|
||||||
|
format_location_list([A]) ++ format_location(T);
|
||||||
|
format_location([]) ->
|
||||||
|
"".
|
||||||
|
|
||||||
|
format_location_list(L) ->
|
||||||
|
"#: " ++ string:join(
|
||||||
|
lists:map(
|
||||||
|
fun({File, Pos}) ->
|
||||||
|
io_lib:format("~s:~B", [File, Pos])
|
||||||
|
end, L),
|
||||||
|
" ") ++ io_lib:nl().
|
||||||
|
|
||||||
|
format_msg(Bin) ->
|
||||||
|
io_lib:format("msgid \"~s\"~n", [escape(Bin)]).
|
||||||
|
|
||||||
|
escape(Bin) ->
|
||||||
|
lists:map(
|
||||||
|
fun($") -> "\\\"";
|
||||||
|
(C) -> C
|
||||||
|
end, binary_to_list(iolist_to_binary(Bin))).
|
||||||
|
|
||||||
|
pot_header() ->
|
||||||
|
string:join(
|
||||||
|
["msgid \"\"",
|
||||||
|
"msgstr \"\"",
|
||||||
|
"\"Project-Id-Version: 15.11.127\\n\"",
|
||||||
|
"\"X-Language: Language Name\\n\"",
|
||||||
|
"\"Last-Translator: Translator name and contact method\\n\"",
|
||||||
|
"\"MIME-Version: 1.0\\n\"",
|
||||||
|
"\"Content-Type: text/plain; charset=UTF-8\\n\"",
|
||||||
|
"\"Content-Transfer-Encoding: 8bit\\n\""],
|
||||||
|
io_lib:nl()).
|
||||||
|
|
||||||
|
mod(Path) ->
|
||||||
|
filename:rootname(filename:basename(Path)) ++ ".erl".
|
||||||
|
|
||||||
|
log(Format, Args) ->
|
||||||
|
io:format(standard_error, Format, Args).
|
||||||
|
|
||||||
|
get_forms(File) ->
|
||||||
|
case beam_lib:chunks(File, [abstract_code]) of
|
||||||
|
{ok, {_, List}} ->
|
||||||
|
case lists:keyfind(abstract_code, 1, List) of
|
||||||
|
{abstract_code, {raw_abstract_v1, Abstr}} ->
|
||||||
|
{ok, Abstr};
|
||||||
|
_ ->
|
||||||
|
error
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
error
|
||||||
|
end.
|
Loading…
Reference in New Issue
Block a user