summaryrefslogtreecommitdiff
path: root/Data/BuiltIn/Libraries/addons/addons/translate/translate.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Data/BuiltIn/Libraries/addons/addons/translate/translate.lua')
-rw-r--r--Data/BuiltIn/Libraries/addons/addons/translate/translate.lua398
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