diff options
Diffstat (limited to 'Data/BuiltIn/Libraries/addons/addons/translate/translate.lua')
-rw-r--r-- | Data/BuiltIn/Libraries/addons/addons/translate/translate.lua | 398 |
1 files changed, 0 insertions, 398 deletions
diff --git a/Data/BuiltIn/Libraries/addons/addons/translate/translate.lua b/Data/BuiltIn/Libraries/addons/addons/translate/translate.lua deleted file mode 100644 index a33bbda..0000000 --- a/Data/BuiltIn/Libraries/addons/addons/translate/translate.lua +++ /dev/null @@ -1,398 +0,0 @@ ---Copyright (c) 2014~2020, Byrthnoth ---All rights reserved. - ---Redistribution and use in source and binary forms, with or without ---modification, are permitted provided that the following conditions are met: - --- * Redistributions of source code must retain the above copyright --- notice, this list of conditions and the following disclaimer. --- * Redistributions in binary form must reproduce the above copyright --- notice, this list of conditions and the following disclaimer in the --- documentation and/or other materials provided with the distribution. --- * Neither the name of <addon name> nor the --- names of its contributors may be used to endorse or promote products --- derived from this software without specific prior written permission. - ---THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ---ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ---WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ---DISCLAIMED. IN NO EVENT SHALL <your name> BE LIABLE FOR ANY ---DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ---(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ---LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ---ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ---(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ---SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -_addon.name = 'Translate' -_addon.version = '2.0.0.0' -_addon.author = 'Byrth' -_addon.commands = {'trans','translate'} - - -language = 'english' -trans_list = {} -res = require 'resources' -require 'sets' -require 'lists' -require 'pack' -require 'strings' -require 'katakana_to_romanji' -search_comment = {ts = 0, reg = L{}, translated = false} - -handled_resources = S{ - 'ability_recasts', - 'auto_translates', - 'buffs', - 'days', - 'elements', - 'items', - 'job_abilities', - 'job_traits', - 'jobs', - 'key_items', - 'monster_abilities', - 'monstrosity', - 'moon_phases', - 'races', - 'regions', - 'skills', - 'spells', - 'titles', - 'weapon_skills', - 'weather', - 'zones' - } - -green_open = string.char(0xEF,0x27) -red_close = string.char(0xEF,0x28) - -green_col = ''--string.char(0x1E,2) -rcol = ''--string.char(0x1E,1) - -local temp_str - -function to_a_code(num) - local first_byte,second_byte = math.floor(num/256),num%256 - if first_byte == 0 or second_byte == 0 then return nil end - return string.char(0xFD,2,2,first_byte,second_byte,0xFD):escape() - -- 0xFD,2,2,8,37,0xFD :: 37 = % -end - -function to_item_code(id) - local first_byte,second_byte = math.floor(id/256),id%256 - local t = 0x07 - if first_byte == 0 then - t = 0x09 - first_byte = 0xFF - elseif second_byte == 0 then - t = 0x0A - second_byte = 0xFF - end - return string.char(0xFD,t,2,first_byte,second_byte,0xFD):escape() -end - -function to_ki_code(id) - local first_byte,second_byte = math.floor(id/256),id%256 - local t = 0x13 - if first_byte == 0 then - t = 0x15 - first_byte = 0xFF - elseif second_byte == 0 then - t = 0x16 - second_byte = 0xFF - end - return string.char(0xFD,t,2,first_byte,second_byte,0xFD):escape() -end - -function sanity_check(ja) - return (ja and string.len(ja) > 0 and ja ~= '%.') -end - -function load_dict(dict) - for _,res_line in pairs(dict) do - local jp = windower.to_shift_jis(res_line.ja or ''):escape() - local jps = windower.to_shift_jis(res_line.jas or ''):escape() - if sanity_check(jp) and sanity_check(res_line.en) and jp~= res_line.en:escape() then - trans_list[jp] = green_col..res_line.en..rcol - end - if sanity_check(jps) and sanity_check(res_line.ens) and jps ~= res_line.ens:escape() then - trans_list[jps] = green_col..res_line.ens..rcol - end - end -end - -load_dict(katakana_to_romanji) - -for res_name in pairs(handled_resources) do - local resource = res[res_name] or {} - if res_name == 'auto_translates' then - for autotranslate_code,res_line in pairs(resource) do - local jp = windower.to_shift_jis(res_line.ja or ''):escape() - if sanity_check(jp) and not trans_list[jp] and jp ~= res_line.en:escape() then - trans_list[jp] = to_a_code(autotranslate_code) - end - end - elseif res_name == 'items' then - for id,res_line in pairs(resource) do - local jp = windower.to_shift_jis(res_line.ja or ''):escape() - if sanity_check(jp) and not trans_list[jp] and jp ~= res_line.en:escape() then - trans_list[jp] = to_item_code(id) - end - end - elseif res_name == 'key_items' then - for id,res_line in pairs(resource) do - local jp = windower.to_shift_jis(res_line.ja or ''):escape() - if sanity_check(jp) and not trans_list[jp] and jp ~= res_line.en:escape() then - trans_list[jp] = to_ki_code(id) - end - end - elseif res_name == 'jobs' then - for _,res_line in pairs(resource) do - local jp = windower.to_shift_jis(res_line.ja or ''):escape() - local jps = windower.to_shift_jis(res_line.jas or ''):escape() - if sanity_check(jp) and sanity_check(res_line.en) and jp ~= res_line.en:escape() then - trans_list[jp] = green_col..res_line.en..rcol:escape() - end - if sanity_check(jps) and sanity_check(res_line.ens) and jp ~= res_line.en:escape() and jps ~= res_line.ens:escape() and res_line.ens ~= 'PUP' then - trans_list[jps] = green_col..res_line.ens..rcol:escape() - end - end - else - for _,res_line in pairs(resource) do - local jp = windower.to_shift_jis(res_line.ja or ''):escape() - local jps = windower.to_shift_jis(res_line.jas or ''):escape() - if sanity_check(jp) and not trans_list[jp] and sanity_check(res_line.en) and jp ~= res_line.en:escape() then - trans_list[jp] = green_col..res_line.en..rcol:escape() - end - if sanity_check(jps) and not trans_list[jps] and sanity_check(res_line.ens) and jp ~= res_line.en:escape() and jps ~= res_line.ens:escape() then - trans_list[jps] = green_col..res_line.ens..rcol:escape() - end - end - end -end - -local custom_dict_names = S(windower.get_dir(windower.addon_path..'dicts/')):filter(string.endswith-{'.lua'}):map(string.sub-{1, -5}) -for dict_name in pairs(custom_dict_names) do - local dict = dofile(windower.addon_path..'dicts/'..dict_name..'.lua') - if dict then - load_dict(dict) - end -end - -function print_bytes(str) - local c = '' - local i = 1 - while i <= #str do - c = c..' '..str:byte(i) - i = i + 1 - end - return c -end - -trans_list[string.char(0x46)] = nil -trans_list['\.'] = nil - - -windower.register_event('incoming chunk',function(id,orgi,modi,is_injected,is_blocked) - if id == 0x17 and not is_injected and not is_blocked then - local out_text = modi:unpack('z',0x18) - - out_text = translate_phrase(out_text) - - if not out_text then return end - - if show_original then windower.add_to_chat(8,modi:sub(9,0x17):unpack('z',1)..'[Original]: '..modi:unpack('z',0x18)) end - while #out_text > 0 do - local boundary = get_boundary_length(out_text,151) - local len = math.ceil((boundary+1+23)/2) -- Make sure there is at least one nul after the string - local out_pack = string.char(0x17,len)..modi:sub(3,0x17)..out_text:sub(1,boundary) - - -- zero pad it - while #out_pack < len*2 do - out_pack = out_pack..string.char(0) - end - windower.packets.inject_incoming(0x17,out_pack) - out_text = out_text:sub(boundary+1) - end - return true - end -end) - -function translate_phrase(out_text) - local matches,match_bool = {},false - local function make_matches(catch) - -- build a table of matches indexed by their length - local esc = catch:escape() - if not sanity_check(esc) then return end - - - - if not matches[#catch] then - matches[#catch] = {} - end - matches[#catch][#matches[#catch]+1] = esc - match_bool = true - end - for jp,en in pairs(trans_list) do - out_text:gsub(jp,make_matches) - end - - if not match_bool then return end - - local order = {} - for len,_ in pairs(matches) do - local c,found = 1,false - while c <= #order do - if len > order[c] then - table.insert(order,c,len) - found = true - break - end - c = c + 1 - end - if c > #order then order[c] = len end - end - - for _,ind in ipairs(order) do - for _,option in ipairs(matches[ind]) do - out_text = sjis_gsub(out_text,unescape(option),unescape(trans_list[option])) - end - end - return out_text -end - -function get_boundary_length(str,limit) - -- If it is already short enough, return it - if #str <= limit then return #str end - - local lim = 0 - for i= 1,#str do - local c_byte = str:byte(i) - if c_byte == 0xFD then - i = i + 6 - elseif ( (c_byte > 0x7F and c_byte <= 0xA0) or c_byte >= 0xE0) then - i = i + 2 - else - i = i + 1 - end - if i > limit then - return lim - else - lim = i - end - end - - -- Otherwise, try to pick a spot to split that will not interfere with command codes and such ---[[ local boundary = limit - for i=limit-5,limit do - local c_byte = str:byte(i) - if c_byte ==0xFD then - -- 0xFD: Autotranslate code, 6 bytes - boundary = i-1 - break - elseif c_byte == 0xEF and str:byte(i+1) == 0x27 then - -- Opening green ( - boundary = i-1 - break - elseif i == limit and ( (c_byte > 0x7F and c_byte <= 0xA0) or c_byte >= 0xE0) then - -- Double-byte shift_JIS character - boundary = i-1 - break - end - end - return boundary]] -end - -windower.register_event('addon command', function(...) - local commands = {...} - if not commands[1] then return end - if commands[1]:lower() == 'show' then - if commands[2] and commands[2]:lower() == 'original' then - show_original=not show_original - if show_original then - print('Translate: Showing the original text line.') - else - print('Translate: Hiding the original text line.') - end - end - elseif commands[1]:lower() == 'eval' and commands[2] then - table.remove(commands,1) - assert(loadstring(table.concat(commands, ' ')))() - end -end) - -windower.register_event('incoming text',function(org,mod,ocol,mcol,blk) - if not blk and ocol == 204 then - local ret = translate_phrase(mod) - temp_str = ret or org - if ret then - if show_original then - windower.add_to_chat:schedule(0.3, 8,'[Original]: '..org) - end - mod = ret - if org == temp_str then - blk = true - temp_str = '' - end - return blk and blk or mod - end - end -end) - -function unescape(str) - return (str:gsub('%%([%%%%^%$%*%(%)%.%+%?%-%]%[])','%1')) -end - - --- Two problems with how I currently do this: --- 1: It is possible to have something like 0x94, (0x92, 0x8B,) 0xE1, which are two JP characters that contain a third. --- 2: It is possible to have a gsub replace something with an autotranslate code, which then causes a later dictionary --- option to match part of the replacement. --- If I solve #1, will #2 be an issue? No, it should not be. - -function sjis_gsub(str,pattern,rep) - if not (type(rep) == 'function' or type(rep) == 'string') then return str end - local str_len,pat_len,ret_str = string.len(str),string.len(pattern),str - local i = 1 - while i<=str_len-pat_len+1 do - local c_byte = str:byte(i) - if str:sub(i,i+pat_len-1) == pattern then - if type(rep) == 'function' then - ret_str = rep(pattern) or str - -- No recursion for functions at the moment, because this addon doesn't need it - return - elseif type(rep) == 'string' then - if i ~= 1 then - -- Not the beginning - ret_str = str:sub(1,i-1)..rep - else - -- The beginning - ret_str = rep - end - if i+pat_len <= str_len-pat_len+1 then - -- i == 13, pat_len == 2, str_len == 16 - -- Match is characters 13 and 14. Could conceivably match again to characters 15 and 16. - - -- Send the remainder of the string back through recursively. - return ret_str..sjis_gsub(str:sub(i+pat_len),pattern,rep) - elseif i+pat_len <= str_len then - -- i == 14, pat_len == 2, str_len == 16 - -- Match is characters 14 and 15, so 16 can't possibly be a match but needs to be stuck on there - return ret_str..str:sub(i+pat_len) - else - -- i == 15, pat_len == 2, str_len == 16 - -- Match is characters 15 and 16, so no further addition is necessary - return ret_str - end - end - elseif c_byte == 0xFD then - i = i + 6 - elseif ( (c_byte > 0x7F and c_byte <= 0xA0) or c_byte >= 0xE0) then - i = i + 2 - else - i = i + 1 - end - end - return ret_str -end |